From b3e7aed275bf18a57ebf6b29d873805c0d851ad9 Mon Sep 17 00:00:00 2001 From: Subramanian Ananthanarayanan Date: Tue, 18 Aug 2020 18:51:24 +0530 Subject: [PATCH 1/4] msm: mhi_dev: Avoid MSI trigger during device cold boot scenario In hibernate scenario, due to recent changes on host side the BHI register value is updated before M0 is issued. This causes a mismatch with the reset value 0xfffffff expectations. As a result device ends up sending an MSI to indicate ready status. This is not expected from host side, and causes race conditions where it leads the host to process MHI initialization and MHI reset concurrently in two thread contexts. This manifest into two different signatures primarily: a) M0 is acknowledged in Thread 1 context, host keep waiting for device to Acknowledged M0 sent as part of Thread 2. Device ignores the 2nd request as its already in M0. b) MMIO event ring is initialized with a primary value x, because of Thread 2 doing a re-installation the event ring base is updated by the host to another value y. The device which is only aware of the primary value send completion event with RP value corresponding to x. This is treated as a junk RP and ends up resulting in a host crash with BSOD 0xdeaddead. Change-Id: Iae0ee996ad086ff5e6430c198f29e56d994c1ef7 Signed-off-by: Subramanian Ananthanarayanan Signed-off-by: Gauri Joshi --- drivers/platform/msm/mhi_dev/mhi.c | 20 +------------------- 1 file changed, 1 insertion(+), 19 deletions(-) diff --git a/drivers/platform/msm/mhi_dev/mhi.c b/drivers/platform/msm/mhi_dev/mhi.c index 5d5a1ebecbcf..f7dd281613a8 100644 --- a/drivers/platform/msm/mhi_dev/mhi.c +++ b/drivers/platform/msm/mhi_dev/mhi.c @@ -3265,12 +3265,11 @@ static int mhi_dev_recover(struct mhi_dev *mhi) static void mhi_dev_enable(struct work_struct *work) { int rc = 0; - struct ep_pcie_msi_config msi_cfg; struct mhi_dev *mhi = container_of(work, struct mhi_dev, ring_init_cb_work); u32 mhi_reset; enum mhi_dev_state state; - uint32_t max_cnt = 0, bhi_intvec = 0; + uint32_t max_cnt = 0; if (mhi->use_ipa) { rc = ipa_dma_init(); @@ -3292,23 +3291,6 @@ static void mhi_dev_enable(struct work_struct *work) return; } - rc = mhi_dev_mmio_read(mhi, BHI_INTVEC, &bhi_intvec); - if (rc) - return; - - if (bhi_intvec != 0xffffffff) { - /* Indicate the host that the device is ready */ - rc = ep_pcie_get_msi_config(mhi->phandle, &msi_cfg); - if (!rc) { - rc = ep_pcie_trigger_msi(mhi_ctx->phandle, bhi_intvec); - if (rc) { - pr_err("%s: error sending msi\n", __func__); - return; - } - } else { - pr_err("MHI: error geting msi configs\n"); - } - } rc = mhi_dev_mmio_get_mhi_state(mhi, &state, &mhi_reset); if (rc) { From 137bc0157e1004b157259381a96d4b2c51888e84 Mon Sep 17 00:00:00 2001 From: Subramanian Ananthanarayanan Date: Tue, 7 Jul 2020 12:42:04 +0530 Subject: [PATCH 2/4] msm: mhi_dev: Fix interrupt storm during Enable/disable mhi_dev_backup_mmio() and mhi_dev_restore_mmio() does backup/restore of INTR registers of MHI device, causing it to restore interrupts that are not valid during PCIE PM_RST_DEAST event. The fix is to skip the INTR register space. Change-Id: I2a8cde174cf4c6acd7acce13ad0195ed6a9a6f0b Signed-off-by: Subramanian Ananthanarayanan Signed-off-by: Gauri Joshi --- drivers/platform/msm/mhi_dev/mhi.h | 3 ++- drivers/platform/msm/mhi_dev/mhi_mmio.c | 12 ++++++++---- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/drivers/platform/msm/mhi_dev/mhi.h b/drivers/platform/msm/mhi_dev/mhi.h index a4abc677ed8b..f33de7d1626f 100644 --- a/drivers/platform/msm/mhi_dev/mhi.h +++ b/drivers/platform/msm/mhi_dev/mhi.h @@ -412,7 +412,8 @@ static inline void mhi_dev_ring_inc_index(struct mhi_dev_ring *ring, #define TRACE_DATA_MAX 128 #define MHI_DEV_DATA_MAX 512 -#define MHI_DEV_MMIO_RANGE 0xc80 +#define MHI_DEV_MMIO_RANGE 0xb80 +#define MHI_DEV_MMIO_OFFSET 0x100 struct ring_cache_req { struct completion *done; diff --git a/drivers/platform/msm/mhi_dev/mhi_mmio.c b/drivers/platform/msm/mhi_dev/mhi_mmio.c index 44030cee6c93..6e2ccde6c25c 100644 --- a/drivers/platform/msm/mhi_dev/mhi_mmio.c +++ b/drivers/platform/msm/mhi_dev/mhi_mmio.c @@ -598,7 +598,8 @@ int mhi_dev_restore_mmio(struct mhi_dev *dev) mhi_dev_mmio_mask_interrupts(dev); for (i = 0; i < (MHI_DEV_MMIO_RANGE/4); i++) { - reg_cntl_addr = dev->mmio_base_addr + (i * 4); + reg_cntl_addr = dev->mmio_base_addr + + MHI_DEV_MMIO_OFFSET + (i * 4); reg_cntl_value = dev->mmio_backup[i]; writel_relaxed(reg_cntl_value, reg_cntl_addr); } @@ -619,13 +620,16 @@ EXPORT_SYMBOL(mhi_dev_restore_mmio); int mhi_dev_backup_mmio(struct mhi_dev *dev) { uint32_t i = 0; + void __iomem *reg_cntl_addr; if (WARN_ON(!dev)) return -EINVAL; - for (i = 0; i < MHI_DEV_MMIO_RANGE/4; i++) - dev->mmio_backup[i] = - readl_relaxed(dev->mmio_base_addr + (i * 4)); + for (i = 0; i < MHI_DEV_MMIO_RANGE/4; i++) { + reg_cntl_addr = (void __iomem *) (dev->mmio_base_addr + + MHI_DEV_MMIO_OFFSET + (i * 4)); + dev->mmio_backup[i] = readl_relaxed(reg_cntl_addr); + } return 0; } From c0a31b28b1993f2903b9317844e4ae76451334c7 Mon Sep 17 00:00:00 2001 From: Subramanian Ananthanarayanan Date: Fri, 28 Aug 2020 11:53:56 +0530 Subject: [PATCH 3/4] msm: mhi_dev: Enable CMDB during restore mmio During mhi_dev_restore_mmio() we call mhi_dev_mmio_mask_interrupts, restore the backup registers and we enable only CTRL,CHDB interrupts. This causes the CMDB do be in disabled state, so after first D3 cold transition we don't get CMDB interrupt until it fires along with one of the already enabled interrupts. This causes delay in processing CMDB interrupts that host might have queued at a very early stage. Change is to enable CMDB interrupts post mmio restore along with the other interrupts. Change-Id: I75acbeda3f6e7c50669be4db9190b8ccd5b1dd1e Signed-off-by: Subramanian Ananthanarayanan Signed-off-by: Gauri Joshi --- drivers/platform/msm/mhi_dev/mhi_mmio.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/platform/msm/mhi_dev/mhi_mmio.c b/drivers/platform/msm/mhi_dev/mhi_mmio.c index 6e2ccde6c25c..d0c2bda62935 100644 --- a/drivers/platform/msm/mhi_dev/mhi_mmio.c +++ b/drivers/platform/msm/mhi_dev/mhi_mmio.c @@ -605,12 +605,18 @@ int mhi_dev_restore_mmio(struct mhi_dev *dev) } mhi_dev_mmio_clear_interrupts(dev); + + /* Mask and enable control interrupt */ mhi_dev_mmio_enable_ctrl_interrupt(dev); /*Enable chdb interrupt*/ mhi_dev_mmio_enable_chdb_interrupts(dev); - /* Mask and enable control interrupt */ + /*Enable cmdb interrupt*/ + mhi_dev_mmio_enable_cmdb_interrupt(dev); + + /*Enable erdb interrupt*/ + mhi_dev_mmio_enable_erdb_interrupts(dev); mb(); return 0; From e6af79bae98a2b92efeaa3f07a9ef42c166c9c73 Mon Sep 17 00:00:00 2001 From: Subramanian Ananthanarayanan Date: Thu, 3 Sep 2020 23:00:44 +0530 Subject: [PATCH 4/4] msm: mhi_dev: Change to not enable ERDB interrupts We see spurious interrupts during modem standby if ERDB is enabled. Making changes to not enable ERDB interrupts. Change-Id: I5a51101b54f67e7c8e56d46c56bddd739c8852a5 Signed-off-by: Subramanian Ananthanarayanan Signed-off-by: Gauri Joshi --- drivers/platform/msm/mhi_dev/mhi_mmio.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/platform/msm/mhi_dev/mhi_mmio.c b/drivers/platform/msm/mhi_dev/mhi_mmio.c index d0c2bda62935..b0cc8673fe03 100644 --- a/drivers/platform/msm/mhi_dev/mhi_mmio.c +++ b/drivers/platform/msm/mhi_dev/mhi_mmio.c @@ -615,8 +615,6 @@ int mhi_dev_restore_mmio(struct mhi_dev *dev) /*Enable cmdb interrupt*/ mhi_dev_mmio_enable_cmdb_interrupt(dev); - /*Enable erdb interrupt*/ - mhi_dev_mmio_enable_erdb_interrupts(dev); mb(); return 0;