From 84a55b411d594cbc22e7280aa4ad3a3685571a90 Mon Sep 17 00:00:00 2001 From: Gauri Joshi Date: Thu, 11 Jun 2020 21:03:31 +0530 Subject: [PATCH 1/7] msm: mhi_dev: Clear reset while waiting for M0 On some customer platforms, resume from hibernate results in a cold boot of the end-point. The previous mhi device state gets cleared and this results in mhi host issuing a reset. Clear the reset while waiting for M0 from host to enable host to proceed with issuing M0. Change-Id: I18aa4e760d59e37842a9f3a6dba1478a98137bb8 Signed-off-by: Siva Kumar Akkireddi Signed-off-by: Gauri Joshi --- drivers/platform/msm/mhi_dev/mhi.c | 10 ++++++++++ drivers/platform/msm/mhi_dev/mhi.h | 8 +++++++- drivers/platform/msm/mhi_dev/mhi_mmio.c | 14 +++++++++++++- 3 files changed, 30 insertions(+), 2 deletions(-) diff --git a/drivers/platform/msm/mhi_dev/mhi.c b/drivers/platform/msm/mhi_dev/mhi.c index 3948391d2280..da7bc72af9f5 100644 --- a/drivers/platform/msm/mhi_dev/mhi.c +++ b/drivers/platform/msm/mhi_dev/mhi.c @@ -3349,6 +3349,11 @@ static void mhi_dev_enable(struct work_struct *work) pr_err("%s: get mhi state failed\n", __func__); return; } + if (mhi_reset) { + mhi_dev_mmio_clear_reset(mhi); + mhi_log(MHI_MSG_VERBOSE, + "Cleared reset before waiting for M0\n"); + } while (state != MHI_DEV_M0_STATE && max_cnt < MHI_SUSPEND_TIMEOUT) { /* Wait for Host to set the M0 state */ @@ -3358,6 +3363,11 @@ static void mhi_dev_enable(struct work_struct *work) pr_err("%s: get mhi state failed\n", __func__); return; } + if (mhi_reset) { + mhi_dev_mmio_clear_reset(mhi); + mhi_log(MHI_MSG_VERBOSE, + "Cleared reset while waiting for M0\n"); + } max_cnt++; } diff --git a/drivers/platform/msm/mhi_dev/mhi.h b/drivers/platform/msm/mhi_dev/mhi.h index a4abc677ed8b..47f77aab4a91 100644 --- a/drivers/platform/msm/mhi_dev/mhi.h +++ b/drivers/platform/msm/mhi_dev/mhi.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-2.0-only */ -/* Copyright (c) 2015-2020, The Linux Foundation. All rights reserved.*/ +/* Copyright (c) 2015-2021, The Linux Foundation. All rights reserved.*/ #ifndef __MHI_H #define __MHI_H @@ -966,6 +966,12 @@ int mhi_dev_mmio_get_cmd_db(struct mhi_dev_ring *ring, uint64_t *wr_offset); */ int mhi_dev_mmio_set_env(struct mhi_dev *dev, uint32_t value); +/** + * mhi_dev_mmio_clear_reset() - Clear the reset bit + * @dev: MHI device structure. + */ +int mhi_dev_mmio_clear_reset(struct mhi_dev *dev); + /** * mhi_dev_mmio_reset() - Reset the MMIO done as part of initialization. * @dev: MHI device structure. diff --git a/drivers/platform/msm/mhi_dev/mhi_mmio.c b/drivers/platform/msm/mhi_dev/mhi_mmio.c index 44030cee6c93..dad69ba0ade1 100644 --- a/drivers/platform/msm/mhi_dev/mhi_mmio.c +++ b/drivers/platform/msm/mhi_dev/mhi_mmio.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-2.0-only -/* Copyright (c) 2015,2017-2020, The Linux Foundation. All rights reserved.*/ +/* Copyright (c) 2015,2017-2021, The Linux Foundation. All rights reserved.*/ #include #include @@ -574,6 +574,18 @@ int mhi_dev_mmio_set_env(struct mhi_dev *dev, uint32_t value) } EXPORT_SYMBOL(mhi_dev_mmio_set_env); +int mhi_dev_mmio_clear_reset(struct mhi_dev *dev) +{ + if (WARN_ON(!dev)) + return -EINVAL; + + mhi_dev_mmio_masked_write(dev, MHICTRL, + MHICTRL_RESET_MASK, MHICTRL_RESET_SHIFT, 0); + + return 0; +} +EXPORT_SYMBOL(mhi_dev_mmio_clear_reset); + int mhi_dev_mmio_reset(struct mhi_dev *dev) { if (WARN_ON(!dev)) From c17f1783a6043d8a8d15592076983eadb4eae2ab Mon Sep 17 00:00:00 2001 From: Gauri Joshi Date: Fri, 17 Apr 2020 00:30:28 +0530 Subject: [PATCH 2/7] msm: mhi_dev: Add an option to not timeout waiting for M0 On certain platforms host might take a long time to send M0 to device. Only modified msm files in this commit. Change-Id: I8c5f07a7926e01afa84a983ef98721749787d2da Signed-off-by: Siva Kumar Akkireddi Signed-off-by: Gauri Joshi --- drivers/platform/msm/mhi_dev/mhi.c | 6 +++++- drivers/platform/msm/mhi_dev/mhi.h | 4 ++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/drivers/platform/msm/mhi_dev/mhi.c b/drivers/platform/msm/mhi_dev/mhi.c index da7bc72af9f5..565c9d19a108 100644 --- a/drivers/platform/msm/mhi_dev/mhi.c +++ b/drivers/platform/msm/mhi_dev/mhi.c @@ -3355,7 +3355,8 @@ static void mhi_dev_enable(struct work_struct *work) "Cleared reset before waiting for M0\n"); } - while (state != MHI_DEV_M0_STATE && max_cnt < MHI_SUSPEND_TIMEOUT) { + while (state != MHI_DEV_M0_STATE && + ((max_cnt < MHI_SUSPEND_TIMEOUT) || mhi->no_m0_timeout)) { /* Wait for Host to set the M0 state */ msleep(MHI_SUSPEND_MIN); rc = mhi_dev_mmio_get_mhi_state(mhi, &state, &mhi_reset); @@ -3624,6 +3625,9 @@ static int get_device_tree_data(struct platform_device *pdev) mhi->enable_m2 = of_property_read_bool((&pdev->dev)->of_node, "qcom,enable-m2"); + mhi->no_m0_timeout = of_property_read_bool((&pdev->dev)->of_node, + "qcom,no-m0-timeout"); + mhi_log(MHI_MSG_VERBOSE, "acquiring wakelock\n"); return 0; diff --git a/drivers/platform/msm/mhi_dev/mhi.h b/drivers/platform/msm/mhi_dev/mhi.h index 47f77aab4a91..47a3fd368082 100644 --- a/drivers/platform/msm/mhi_dev/mhi.h +++ b/drivers/platform/msm/mhi_dev/mhi.h @@ -595,9 +595,13 @@ struct mhi_dev { /*Register for interrupt*/ bool mhi_int; bool mhi_int_en; + /* Enable M2 autonomous mode from MHI */ bool enable_m2; + /* Dont timeout waiting for M0 */ + bool no_m0_timeout; + /* Registered client callback list */ struct list_head client_cb_list; /* Tx, Rx DMA channels */ From 3e7d0429392ff5b67893d9a24a6e2b152058cc93 Mon Sep 17 00:00:00 2001 From: Gauri Joshi Date: Mon, 9 Nov 2020 13:26:26 +0530 Subject: [PATCH 3/7] msm: mhi: Changes to avoid mhi_sm_wq schedule out Queue mhi_sm_wq as system_highpri_wq to avoid WQ getting scheduled out. Change-Id: I92f6442a6425dc71b64550078cfc44d85f744f41 Signed-off-by: Subramanian Ananthanarayanan Signed-off-by: Gauri Joshi --- drivers/platform/msm/mhi_dev/mhi_sm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/platform/msm/mhi_dev/mhi_sm.c b/drivers/platform/msm/mhi_dev/mhi_sm.c index 3c53ea89403d..7e3be7654729 100644 --- a/drivers/platform/msm/mhi_dev/mhi_sm.c +++ b/drivers/platform/msm/mhi_dev/mhi_sm.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-2.0-only -/* Copyright (c) 2015-2020, The Linux Foundation. All rights reserved.*/ +/* Copyright (c) 2015-2021, The Linux Foundation. All rights reserved.*/ #include #include @@ -1429,7 +1429,7 @@ void mhi_dev_sm_pcie_handler(struct ep_pcie_notify *notify) dstate_change_evt->event = event; INIT_WORK(&dstate_change_evt->work, mhi_sm_pcie_event_manager); - queue_work(mhi_sm_ctx->mhi_sm_wq, &dstate_change_evt->work); + queue_work(system_highpri_wq, &dstate_change_evt->work); atomic_inc(&mhi_sm_ctx->pending_pcie_events); exit: From b3f6abccd535fd79ff0f39e05d85a2059dedc0e3 Mon Sep 17 00:00:00 2001 From: Gauri Joshi Date: Mon, 2 Nov 2020 16:04:07 +0530 Subject: [PATCH 4/7] msm: mhi_dev: Fix to avoid double free in alloc_evt_buf_evt_req() There is a possible race condition, if the client calls MHI close and channel gets a start command then mhi_dev_alloc_evt_buf_evt_req() would be called. This can lead to tr_events and ereqs getting freed from both the contexts. Fix is to use a mutex to prevent this from happening parallelly. Change-Id: I9ac10211d5bd5cee96e69b7fc10955e24569cf64 Signed-off-by: Subramanian Ananthanarayanan Signed-off-by: Gauri Joshi --- drivers/platform/msm/mhi_dev/mhi.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/platform/msm/mhi_dev/mhi.c b/drivers/platform/msm/mhi_dev/mhi.c index 565c9d19a108..d1943a2062c7 100644 --- a/drivers/platform/msm/mhi_dev/mhi.c +++ b/drivers/platform/msm/mhi_dev/mhi.c @@ -1713,8 +1713,10 @@ static void mhi_dev_process_cmd_ring(struct mhi_dev *mhi, return; } } + mutex_lock(&mhi->ch[ch_id].ch_lock); mhi_dev_alloc_evt_buf_evt_req(mhi, &mhi->ch[ch_id], evt_ring); + mutex_unlock(&mhi->ch[ch_id].ch_lock); } if (MHI_USE_DMA(mhi)) From 9a551ddff35d4496c7b868792465d9cce5ed806a Mon Sep 17 00:00:00 2001 From: Gauri Joshi Date: Mon, 28 Dec 2020 10:31:37 +0530 Subject: [PATCH 5/7] msm: mhi: Release inbuf_list memory in channel disconnect Driver allocates in_buf_list.addr during open_client_mhi_channels, which is called for every CONNECT event for AT_CTRL channels. in_buf_list.addr is not released during DISCONNECT event. Adding a fix to release this memory during a channel DISCONNECT event. Change-Id: Idd7cac731137934d820e6a8a07335982575a913b Signed-off-by: Subramanian Ananthanarayanan Signed-off-by: Gauri Joshi --- drivers/platform/msm/mhi_dev/mhi_uci.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/platform/msm/mhi_dev/mhi_uci.c b/drivers/platform/msm/mhi_dev/mhi_uci.c index e4edf6f97730..e694f086bac8 100644 --- a/drivers/platform/msm/mhi_dev/mhi_uci.c +++ b/drivers/platform/msm/mhi_dev/mhi_uci.c @@ -1941,7 +1941,7 @@ static void mhi_uci_at_ctrl_tre_cb(struct mhi_dev_client_cb_reason *reason) static void mhi_uci_at_ctrl_client_cb(struct mhi_dev_client_cb_data *cb_data) { struct uci_client *client = cb_data->user_data; - int rc; + int rc, i; struct mhi_req *ureq; uci_log(UCI_DBG_VERBOSE, " Rcvd MHI cb for channel %d, state %d\n", @@ -1980,6 +1980,12 @@ static void mhi_uci_at_ctrl_client_cb(struct mhi_dev_client_cb_data *cb_data) /* Add to in-use list */ list_add_tail(&ureq->list, &client->req_list); } + + for (i = 0; i < (client->in_chan_attr->nr_trbs); i++) { + kfree(client->in_buf_list[i].addr); + client->in_buf_list[i].addr = NULL; + client->in_buf_list[i].buf_size = 0; + } } } From ad691d6737fb8a546185ff5c5ace9b9c00ff85cd Mon Sep 17 00:00:00 2001 From: Gauri Joshi Date: Mon, 22 Feb 2021 15:12:09 -0800 Subject: [PATCH 6/7] msm: ep-pcie: Add support to vote and scale MX rail Chipsets which have PCIe Gen4 PHY and controller on MX rail requires explicit vote for higher corners than the default. Therefore add support to vote for and scale MX rail based on the Gen speed which PCIe link operates at. Change-Id: I6aa595aa6e3955ff09d8eeae604431b47a14985a Signed-off-by: Gauri Joshi --- drivers/platform/msm/ep_pcie/ep_pcie_com.h | 2 +- drivers/platform/msm/ep_pcie/ep_pcie_core.c | 19 +++++++++++++++++-- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/drivers/platform/msm/ep_pcie/ep_pcie_com.h b/drivers/platform/msm/ep_pcie/ep_pcie_com.h index 2dc2dd0d5d49..7776b6bae902 100644 --- a/drivers/platform/msm/ep_pcie/ep_pcie_com.h +++ b/drivers/platform/msm/ep_pcie/ep_pcie_com.h @@ -176,7 +176,7 @@ #define MAX_IATU_ENTRY_NUM 2 #define EP_PCIE_LOG_PAGES 50 -#define EP_PCIE_MAX_VREG 3 +#define EP_PCIE_MAX_VREG 4 #define EP_PCIE_MAX_CLK 10 #define EP_PCIE_MAX_PIPE_CLK 1 #define EP_PCIE_MAX_RESET 2 diff --git a/drivers/platform/msm/ep_pcie/ep_pcie_core.c b/drivers/platform/msm/ep_pcie/ep_pcie_core.c index daa0abc5f5e2..3c995cb7300d 100644 --- a/drivers/platform/msm/ep_pcie/ep_pcie_core.c +++ b/drivers/platform/msm/ep_pcie/ep_pcie_core.c @@ -5,6 +5,7 @@ * MSM PCIe endpoint core driver. */ +#include #include #include #include @@ -54,7 +55,8 @@ struct ep_pcie_dev_t ep_pcie_dev = {0}; static struct ep_pcie_vreg_info_t ep_pcie_vreg_info[EP_PCIE_MAX_VREG] = { {NULL, "vreg-1p8", 1200000, 1200000, 3000, true}, {NULL, "vreg-0p9", 912000, 912000, 132000, true}, - {NULL, "vreg-cx", 0, 0, 0, false} + {NULL, "vreg-cx", 0, 0, 0, false}, + {NULL, "vreg-mx", 0, 0, 0, false} }; static struct ep_pcie_gpio_info_t ep_pcie_gpio_info[EP_PCIE_MAX_GPIO] = { @@ -311,8 +313,15 @@ static int ep_pcie_vreg_init(struct ep_pcie_dev_t *dev) while (i--) { struct regulator *hdl = dev->vreg[i].hdl; - if (hdl) + if (hdl) { regulator_disable(hdl); + if (!strcmp(dev->vreg[i].name, "vreg-mx")) { + EP_PCIE_DBG(dev, "PCIe V%d: Removing vote for %s.\n", + dev->rev, dev->vreg[i].name); + regulator_set_voltage(hdl, RPMH_REGULATOR_LEVEL_RETENTION, + RPMH_REGULATOR_LEVEL_MAX); + } + } } return rc; @@ -329,6 +338,12 @@ static void ep_pcie_vreg_deinit(struct ep_pcie_dev_t *dev) EP_PCIE_DBG(dev, "Vreg %s is being disabled\n", dev->vreg[i].name); regulator_disable(dev->vreg[i].hdl); + if (!strcmp(dev->vreg[i].name, "vreg-mx")) { + EP_PCIE_DBG(dev, "PCIe V%d: Removing vote for %s.\n", + dev->rev, dev->vreg[i].name); + regulator_set_voltage(dev->vreg[i].hdl, + RPMH_REGULATOR_LEVEL_RETENTION, RPMH_REGULATOR_LEVEL_MAX); + } } } } From 5cc155bb37bc34918cfc82824f676be5ff52fa1d Mon Sep 17 00:00:00 2001 From: Gauri Joshi Date: Wed, 3 Feb 2021 14:19:51 -0800 Subject: [PATCH 7/7] msm: ep-pcie: Update load factor for 1.2V rail on sdxlemur Change the load factor from 3000 to 30000 for sdxlemur. Change-Id: I939610150bcaddba7ff508ea130009a010cfb6c0 Signed-off-by: Gauri Joshi --- drivers/platform/msm/ep_pcie/ep_pcie_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/platform/msm/ep_pcie/ep_pcie_core.c b/drivers/platform/msm/ep_pcie/ep_pcie_core.c index 3c995cb7300d..59068faa1b77 100644 --- a/drivers/platform/msm/ep_pcie/ep_pcie_core.c +++ b/drivers/platform/msm/ep_pcie/ep_pcie_core.c @@ -53,7 +53,7 @@ static u32 clkreq_irq; struct ep_pcie_dev_t ep_pcie_dev = {0}; static struct ep_pcie_vreg_info_t ep_pcie_vreg_info[EP_PCIE_MAX_VREG] = { - {NULL, "vreg-1p8", 1200000, 1200000, 3000, true}, + {NULL, "vreg-1p8", 1200000, 1200000, 30000, true}, {NULL, "vreg-0p9", 912000, 912000, 132000, true}, {NULL, "vreg-cx", 0, 0, 0, false}, {NULL, "vreg-mx", 0, 0, 0, false}