From 75c8d2fc98bf09c5f068d3bc1c0669d144097129 Mon Sep 17 00:00:00 2001 From: Gauri Joshi Date: Wed, 11 Aug 2021 14:50:24 -0700 Subject: [PATCH 1/2] msm: ep-pcie: Enable global IRQ after enumeration The global irqs are being enabled before EP driver has completed successful link enumeration. This causes a race condition where the BME IRQ is processed before link up causing the link up to exit before updating the link status. Any further processing results in LINK_DISABLED error. Avoid this scenario by enabling the global interrupts after enumeration has finished. Change-Id: I983a35f461da5d8966cadc9918b5529d16182b47 Signed-off-by: Gauri Joshi --- drivers/platform/msm/ep_pcie/ep_pcie_core.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/platform/msm/ep_pcie/ep_pcie_core.c b/drivers/platform/msm/ep_pcie/ep_pcie_core.c index 710c4a647f67..219e0e97b794 100644 --- a/drivers/platform/msm/ep_pcie/ep_pcie_core.c +++ b/drivers/platform/msm/ep_pcie/ep_pcie_core.c @@ -2603,6 +2603,7 @@ int32_t ep_pcie_irq_init(struct ep_pcie_dev_t *dev) INIT_WORK(&dev->handle_d3cold_work, handle_d3cold_func); if (dev->aggregated_irq) { + irq_set_status_flags(dev->irq[EP_PCIE_INT_GLOBAL].num, IRQ_NOAUTOEN); ret = devm_request_irq(pdev, dev->irq[EP_PCIE_INT_GLOBAL].num, ep_pcie_handle_global_irq, @@ -3446,6 +3447,7 @@ static int ep_pcie_probe(struct platform_device *pdev) qcom_edma_init(&pdev->dev); + enable_irq(ep_pcie_dev.irq[EP_PCIE_INT_GLOBAL].num); return 0; irq_deinit: From 1f3617efcce4000ce57631ad35af24fea2b2752f Mon Sep 17 00:00:00 2001 From: Gauri Joshi Date: Wed, 4 Aug 2021 22:14:37 -0700 Subject: [PATCH 2/2] msm: mhi-dev: Flush ereqs from dev close to avoid OOS transfers Currently there is a race condition where during the flushing of ereqs the channel is closed from the client on the EP side, which is causing the flush function to access null memory. To avoid that call the flush from dev close which ensures all the pending ereqs are closed before closing the channel and freeing the memory. Change-Id: Id81d8cb8b326340d28f6cfe9d48dcd685a8038f9 Signed-off-by: Gauri Joshi --- drivers/platform/msm/mhi_dev/mhi.c | 26 +++++++++++++++++++------- drivers/platform/msm/mhi_dev/mhi.h | 1 + 2 files changed, 20 insertions(+), 7 deletions(-) diff --git a/drivers/platform/msm/mhi_dev/mhi.c b/drivers/platform/msm/mhi_dev/mhi.c index 94320c1377a6..2bfa406cb18c 100644 --- a/drivers/platform/msm/mhi_dev/mhi.c +++ b/drivers/platform/msm/mhi_dev/mhi.c @@ -25,6 +25,7 @@ #include #include #include +#include #include "mhi.h" #include "mhi_hwio.h" @@ -65,7 +66,7 @@ #define MHI_DEV_CH_CLOSE_TIMEOUT_MIN 5000 #define MHI_DEV_CH_CLOSE_TIMEOUT_MAX 5100 -#define MHI_DEV_CH_CLOSE_TIMEOUT_COUNT 30 +#define MHI_DEV_CH_CLOSE_TIMEOUT_COUNT 200 uint32_t bhi_imgtxdb; enum mhi_msg_level mhi_msg_lvl = MHI_MSG_ERROR; @@ -363,6 +364,12 @@ static void mhi_dev_event_msi_cb(void *req) } ch = ereq->context; + if (!ch) { + mhi_log(MHI_MSG_ERROR, "Invalid ereq context, return\n"); + return; + } + if (ch->pend_flush_cnt++ >= U32_MAX) + ch->pend_flush_cnt = 0; mhi = ch->ring->mhi_dev; mhi_log(MHI_MSG_VERBOSE, "MSI completed for flush req %d\n", @@ -641,7 +648,8 @@ static int mhi_dev_flush_transfer_completion_events(struct mhi_dev *mhi, list_del_init(&flush_ereq->list); spin_unlock_irqrestore(&mhi->lock, flags); - ch->flush_req_cnt++; + if (ch->flush_req_cnt++ >= U32_MAX) + ch->flush_req_cnt = 0; flush_ereq->flush_num = ch->flush_req_cnt; mhi_log(MHI_MSG_DBG, "Flush num %d called for ch %d\n", ch->flush_req_cnt, ch->ch_id); @@ -3214,24 +3222,28 @@ void mhi_dev_close_channel(struct mhi_dev_client *handle) { struct mhi_dev_channel *ch; int count = 0; - + int rc = 0; if (!handle) { mhi_log(MHI_MSG_ERROR, "Invalid channel access:%d\n", -ENODEV); return; } ch = handle->channel; + mutex_lock(&ch->ch_lock); + + rc = mhi_dev_flush_transfer_completion_events(mhi_ctx, ch); + if (rc) { + mhi_log(MHI_MSG_ERROR, + "Failed to flush read completions to host\n"); + } do { - if (ch->pend_wr_count && - !list_empty(&ch->event_req_buffers)) { + if (ch->flush_req_cnt != ch->pend_flush_cnt) { usleep_range(MHI_DEV_CH_CLOSE_TIMEOUT_MIN, MHI_DEV_CH_CLOSE_TIMEOUT_MAX); } else break; } while (++count < MHI_DEV_CH_CLOSE_TIMEOUT_COUNT); - mutex_lock(&ch->ch_lock); - if (ch->pend_wr_count) mhi_log(MHI_MSG_ERROR, "%d writes pending for channel %d\n", ch->pend_wr_count, ch->ch_id); diff --git a/drivers/platform/msm/mhi_dev/mhi.h b/drivers/platform/msm/mhi_dev/mhi.h index f703d2b546cf..bef742a496b2 100644 --- a/drivers/platform/msm/mhi_dev/mhi.h +++ b/drivers/platform/msm/mhi_dev/mhi.h @@ -508,6 +508,7 @@ struct mhi_dev_channel { uint32_t pend_wr_count; uint32_t msi_cnt; uint32_t flush_req_cnt; + uint32_t pend_flush_cnt; bool skip_td; bool db_pending; bool reset_pending;