From ad22cfa30a628635c4232c50d30dac72f2655476 Mon Sep 17 00:00:00 2001 From: Subramanian Ananthanarayanan Date: Thu, 26 Nov 2020 12:40:55 +0530 Subject: [PATCH 1/5] msm: mhi_dev: Allocate ring element during M0 Device allocates ring memory during mmio initialization, this causes 128 event ring elements to be created as MHICFG register may not be updated by the host. This causes memory to get exhausted leading to an MMIO init failure. The Change is to allocate ring memory during M0, during which MHICFG register is bound to be updated by the host. Change-Id: I04a0e0ed79a46f16f96e2be4c5c68cba9ee2c99d Signed-off-by: Subramanian Ananthanarayanan Signed-off-by: Gauri Joshi --- drivers/platform/msm/mhi_dev/mhi.c | 70 ++++++++++++++++++++++-------- 1 file changed, 52 insertions(+), 18 deletions(-) diff --git a/drivers/platform/msm/mhi_dev/mhi.c b/drivers/platform/msm/mhi_dev/mhi.c index 4e1a15dd8c72..5eca5c2d3214 100644 --- a/drivers/platform/msm/mhi_dev/mhi.c +++ b/drivers/platform/msm/mhi_dev/mhi.c @@ -91,6 +91,7 @@ static void mhi_dev_cmd_event_msi_cb(void *req); static int mhi_dev_alloc_cmd_ack_buf_req(struct mhi_dev *mhi); +static int mhi_dev_ring_init(struct mhi_dev *dev); static struct mhi_dev_uevent_info channel_state_info[MHI_MAX_CHANNELS]; static DECLARE_COMPLETION(read_from_host); @@ -2685,6 +2686,25 @@ static int mhi_dev_cache_host_cfg(struct mhi_dev *mhi) mhi->cfg.event_rings; mhi->ch_ctx_shadow.size = sizeof(struct mhi_dev_ch_ctx) * mhi->cfg.channels; + + /* Allocate ring elements, during M0 when host + * would have updated MHICFG register + */ + + if (!mhi->ring) { + mhi->ring = devm_kcalloc(&pdev->dev, + (mhi->cfg.channels + mhi->cfg.event_rings+1), + sizeof(struct mhi_dev_ring), + GFP_KERNEL); + if (!mhi->ring) { + rc = -ENOMEM; + goto exit; + } + mhi_log(MHI_MSG_INFO, + "MEM_ALLOC: size:%d RING_ALLOC\n", + (sizeof(struct mhi_dev_ring) * + (mhi->cfg.channels + mhi->cfg.event_rings + 1))); + } /* * This func mhi_dev_cache_host_cfg will be called when * processing mhi device reset as well, do not allocate @@ -2731,6 +2751,13 @@ static int mhi_dev_cache_host_cfg(struct mhi_dev *mhi) } memset(mhi->ch_ctx_cache, 0, sizeof(struct mhi_dev_ch_ctx) * mhi->cfg.channels); + + rc = mhi_dev_ring_init(mhi); + if (rc) { + mhi_log(MHI_MSG_VERBOSE, "MHI dev ring init failed\n"); + goto exit; + } + if (MHI_USE_DMA(mhi)) { data_transfer.phy_addr = mhi->cmd_ctx_cache_dma_handle; data_transfer.host_pa = mhi->cmd_ctx_shadow.host_pa; @@ -2761,21 +2788,43 @@ static int mhi_dev_cache_host_cfg(struct mhi_dev *mhi) mhi->ev_ctx_cache->rp, mhi->ev_ctx_cache->wp); - return mhi_ring_start(&mhi->ring[0], + rc = mhi_ring_start(&mhi->ring[0], (union mhi_dev_ring_ctx *)mhi->cmd_ctx_cache, mhi); + if (rc) { + pr_err("MHI ring start failed:%d\n", rc); + goto exit; + } + return 0; exit: - if (mhi->cmd_ctx_cache) + if (mhi->ring) { + devm_kfree(&pdev->dev, mhi->ring); + mhi->ring = NULL; + mhi_log(MHI_MSG_INFO, + "MEM_DEALLOC: size:%d RING_ALLOC\n", + (sizeof(struct mhi_dev_ring) * + (mhi->cfg.channels + mhi->cfg.event_rings + 1))); + } + if (mhi->cmd_ctx_cache) { dma_free_coherent(&pdev->dev, sizeof(struct mhi_dev_cmd_ctx), mhi->cmd_ctx_cache, mhi->cmd_ctx_cache_dma_handle); - if (mhi->ev_ctx_cache) + mhi_log(MHI_MSG_INFO, + "MEM_DEALLOC: size:%d CMD_CTX_CACHE\n", + sizeof(struct mhi_dev_cmd_ctx)); + } + if (mhi->ev_ctx_cache) { dma_free_coherent(&pdev->dev, sizeof(struct mhi_dev_ev_ctx) * mhi->cfg.event_rings, mhi->ev_ctx_cache, mhi->ev_ctx_cache_dma_handle); + mhi_log(MHI_MSG_INFO, + "MEM_DEALLOC: size:%d EV_CTX_CACHE\n", + sizeof(struct mhi_dev_ev_ctx) * + mhi->cfg.event_rings); + } return rc; } @@ -3675,13 +3724,6 @@ static void mhi_dev_enable(struct work_struct *work) } } - rc = mhi_dev_ring_init(mhi); - if (rc) { - pr_err("MHI dev ring init failed\n"); - return; - } - - rc = mhi_dev_mmio_get_mhi_state(mhi, &state, &mhi_reset); if (rc) { pr_err("%s: get mhi state failed\n", __func__); @@ -3995,14 +4037,6 @@ static int mhi_init(struct mhi_dev *mhi) return rc; } - if (!mhi->ring) - mhi->ring = devm_kzalloc(&pdev->dev, - (sizeof(struct mhi_dev_ring) * - (mhi->cfg.channels + mhi->cfg.event_rings + 1)), - GFP_KERNEL); - if (!mhi->ring) - return -ENOMEM; - /* * mhi_init is also called during device reset, in * which case channel mem will already be allocated. From e623db906d62a1da61a6812c68b7d57fc4283c28 Mon Sep 17 00:00:00 2001 From: Nitesh Gupta Date: Fri, 5 Mar 2021 18:11:20 +0530 Subject: [PATCH 2/5] msm: mhi: Queue channel db only if channel is open Channel interrupts are seen on device even before, channel ring is initialized. Queuing pending work without checking ring status can lead to processing of spurious interrupts. Adding proper checks in place before queuing channel doorbell. Change-Id: I3ccd7302b535d2b8ef63eada9d7a1fe553dccdaa Signed-off-by: Nitesh Gupta Signed-off-by: Gauri Joshi --- drivers/platform/msm/mhi_dev/mhi.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/drivers/platform/msm/mhi_dev/mhi.c b/drivers/platform/msm/mhi_dev/mhi.c index 5eca5c2d3214..573911877588 100644 --- a/drivers/platform/msm/mhi_dev/mhi.c +++ b/drivers/platform/msm/mhi_dev/mhi.c @@ -2236,11 +2236,12 @@ static int mhi_dev_get_event_notify(enum mhi_dev_state state, return rc; } -static void mhi_dev_queue_channel_db(struct mhi_dev *mhi, +static bool mhi_dev_queue_channel_db(struct mhi_dev *mhi, uint32_t chintr_value, uint32_t ch_num) { struct mhi_dev_ring *ring; struct mhi_dev_channel *ch; + bool work_pending = false; int rc = 0; for (; chintr_value; ch_num++, chintr_value >>= 1) { @@ -2255,14 +2256,16 @@ static void mhi_dev_queue_channel_db(struct mhi_dev *mhi, ch = &mhi->ch[ch_num]; mutex_lock(&ch->ch_lock); ch->db_pending = true; + work_pending = true; mutex_unlock(&ch->ch_lock); rc = mhi_dev_mmio_disable_chdb_a7(mhi, ch_num); if (rc) { pr_err("Error disabling chdb\n"); - return; + return work_pending; } } } + return work_pending; } /* @@ -2291,11 +2294,11 @@ static bool mhi_dev_check_channel_interrupt(struct mhi_dev *mhi) /* Process channel status whose mask is enabled */ chintr_value = (mhi->chdb[i].status & mhi->chdb[i].mask); if (chintr_value) { - pending_work = true; mhi_log(MHI_MSG_VERBOSE, "processing id: %d, ch interrupt 0x%x\n", i, chintr_value); - mhi_dev_queue_channel_db(mhi, chintr_value, ch_num); + pending_work |= mhi_dev_queue_channel_db(mhi, + chintr_value, ch_num); rc = mhi_dev_mmio_write(mhi, MHI_CHDB_INT_CLEAR_A7_n(i), mhi->chdb[i].status); if (rc) { From 45edd7ec797d479b3113f780b9867044a98c090f Mon Sep 17 00:00:00 2001 From: Nitesh Gupta Date: Mon, 8 Mar 2021 13:23:07 +0530 Subject: [PATCH 3/5] msm: mhi_dev: free allocated memory in reverse order of allocation Freeing cmd_ctx before ereqs will result into NULL ptr dereference. Freeing memory in proper order. Change-Id: Ie999017685574e940685eee3b7c205ebe1672664 Signed-off-by: Nitesh Gupta Signed-off-by: Gauri Joshi --- drivers/platform/msm/mhi_dev/mhi.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/platform/msm/mhi_dev/mhi.c b/drivers/platform/msm/mhi_dev/mhi.c index 573911877588..01d2c5dd4e7c 100644 --- a/drivers/platform/msm/mhi_dev/mhi.c +++ b/drivers/platform/msm/mhi_dev/mhi.c @@ -2978,8 +2978,8 @@ static int mhi_dev_alloc_cmd_ack_buf_req(struct mhi_dev *mhi) sizeof(*cmd_ctx->ereqs), GFP_KERNEL); if (!cmd_ctx->ereqs) { + rc = -ENOMEM; goto free_ereqs; - return -ENOMEM; } /* Allocate buffers to queue transfer completion events */ @@ -3008,9 +3008,13 @@ static int mhi_dev_alloc_cmd_ack_buf_req(struct mhi_dev *mhi) return 0; free_ereqs: - kfree(mhi->cmd_ctx); kfree(cmd_ctx->ereqs); cmd_ctx->ereqs = NULL; + + kfree(mhi->cmd_ctx); + mhi_log(MHI_MSG_INFO, + "MEM_DEALLOC: size:%d CMD_CTX\n", + sizeof(struct mhi_cmd_cmpl_ctx)); mhi->cmd_ctx = NULL; return rc; } From ec8cdae2939b1cf12acf087842ca00c1c4760900 Mon Sep 17 00:00:00 2001 From: Subramanian Ananthanarayanan Date: Tue, 9 Mar 2021 15:06:45 +0530 Subject: [PATCH 4/5] msm: mhi_dev: check for error during ring processing The change is to check for error code from cmd processing in case of db pending cases, to avoid rd_offset increment. Change-Id: If213297fe02ec1087bfab572f5af97b1e7bb5791 Signed-off-by: Subramanian Ananthanarayanan Signed-off-by: Gauri Joshi --- drivers/platform/msm/mhi_dev/mhi.c | 41 +++++++++++++++---------- drivers/platform/msm/mhi_dev/mhi.h | 4 +-- drivers/platform/msm/mhi_dev/mhi_ring.c | 4 +-- 3 files changed, 28 insertions(+), 21 deletions(-) diff --git a/drivers/platform/msm/mhi_dev/mhi.c b/drivers/platform/msm/mhi_dev/mhi.c index 01d2c5dd4e7c..b9866a4182e9 100644 --- a/drivers/platform/msm/mhi_dev/mhi.c +++ b/drivers/platform/msm/mhi_dev/mhi.c @@ -1872,7 +1872,7 @@ static void mhi_dev_process_reset_cmd(struct mhi_dev *mhi, int ch_id) ch->reset_pending = false; } -static void mhi_dev_process_cmd_ring(struct mhi_dev *mhi, +static int mhi_dev_process_cmd_ring(struct mhi_dev *mhi, union mhi_dev_ring_element_type *el, void *ctx) { int rc = 0; @@ -1901,7 +1901,7 @@ static void mhi_dev_process_cmd_ring(struct mhi_dev *mhi, if (rc) mhi_log(MHI_MSG_ERROR, "Error with compl event\n"); - return; + return rc; } goto send_start_completion_event; } @@ -1921,7 +1921,7 @@ static void mhi_dev_process_cmd_ring(struct mhi_dev *mhi, if (rc) mhi_log(MHI_MSG_ERROR, "Error with compl event\n"); - return; + return rc; } mhi->ring[mhi->ch_ring_start + ch_id].state = @@ -1943,7 +1943,7 @@ static void mhi_dev_process_cmd_ring(struct mhi_dev *mhi, if (rc) mhi_log(MHI_MSG_ERROR, "Error with compl event\n"); - return; + return rc; } if (mhi->use_edma || mhi->use_ipa) { @@ -1959,7 +1959,7 @@ static void mhi_dev_process_cmd_ring(struct mhi_dev *mhi, mhi_log(MHI_MSG_ERROR, "error starting event ring %d\n", mhi->ch_ctx_cache[ch_id].err_indx); - return; + return rc; } } mutex_lock(&mhi->ch[ch_id].ch_lock); @@ -2014,7 +2014,7 @@ send_start_completion_event: rc = mhi_dev_flush_cmd_completion_events(mhi, &event); if (rc) { pr_err("stop event send failed\n"); - return; + return rc; } } else { /* @@ -2027,7 +2027,7 @@ send_start_completion_event: ring = &mhi->ring[ch_id + mhi->ch_ring_start]; if (ring->state == RING_STATE_UINT) { pr_err("Channel not opened for %d\n", ch_id); - return; + return -EINVAL; } ch = &mhi->ch[ch_id]; @@ -2076,7 +2076,7 @@ send_start_completion_event: rc = mhi_dev_flush_cmd_completion_events(mhi, &event); if (rc) { pr_err("stop event send failed\n"); - return; + return rc; } } else { @@ -2087,7 +2087,7 @@ send_start_completion_event: ring = &mhi->ring[ch_id + mhi->ch_ring_start]; if (ring->state == RING_STATE_UINT) { pr_err("Channel not opened for %d\n", ch_id); - return; + return -EINVAL; } ch = &mhi->ch[ch_id]; mutex_lock(&ch->ch_lock); @@ -2099,7 +2099,8 @@ send_start_completion_event: ch->reset_pending = true; mutex_unlock(&ch->ring->event_lock); mutex_unlock(&ch->ch_lock); - return; + rc = -EBUSY; + return rc; } mhi_dev_process_reset_cmd(mhi, ch_id); mutex_unlock(&ch->ring->event_lock); @@ -2114,9 +2115,10 @@ send_start_completion_event: pr_err("%s: Invalid command:%d\n", __func__, el->generic.type); break; } + return rc; } -static void mhi_dev_process_tre_ring(struct mhi_dev *mhi, +static int mhi_dev_process_tre_ring(struct mhi_dev *mhi, union mhi_dev_ring_element_type *el, void *ctx) { struct mhi_dev_ring *ring = (struct mhi_dev_ring *)ctx; @@ -2127,7 +2129,7 @@ static void mhi_dev_process_tre_ring(struct mhi_dev *mhi, mhi_log(MHI_MSG_VERBOSE, "invalid channel ring id (%d), should be < %lu\n", ring->id, mhi->ch_ring_start); - return; + return -EINVAL; } ch = &mhi->ch[ring->id - mhi->ch_ring_start]; @@ -2141,6 +2143,7 @@ static void mhi_dev_process_tre_ring(struct mhi_dev *mhi, */ if (ch->active_client && ch->active_client->event_trigger != NULL) ch->active_client->event_trigger(&reason); + return 0; } static void mhi_dev_process_ring_pending(struct work_struct *work) @@ -2155,7 +2158,7 @@ static void mhi_dev_process_ring_pending(struct work_struct *work) mutex_lock(&mhi_ctx->mhi_lock); rc = mhi_dev_process_ring(&mhi->ring[mhi->cmd_ring_idx]); - if (rc) { + if (rc && rc != -EBUSY) { mhi_log(MHI_MSG_ERROR, "error processing command ring\n"); goto exit; } @@ -2181,6 +2184,7 @@ static void mhi_dev_process_ring_pending(struct work_struct *work) } mutex_lock(&ch->ch_lock); ch->db_pending = false; + mutex_unlock(&ch->ch_lock); if (ch->reset_pending) { /* @@ -2191,9 +2195,13 @@ static void mhi_dev_process_ring_pending(struct work_struct *work) ch_id = ch->ch_id; mhi_log(MHI_MSG_VERBOSE, "processing pending ch:%d reset\n", ch_id); - mutex_lock(&ch->ring->event_lock); - mhi_dev_process_reset_cmd(mhi, ch_id); - mutex_unlock(&ch->ring->event_lock); + rc = mhi_dev_process_ring( + &mhi->ring[mhi->cmd_ring_idx]); + if (rc) { + mhi_log(MHI_MSG_ERROR, + "error processing command ring\n"); + goto exit; + } } rc = mhi_dev_mmio_enable_chdb_a7(mhi, ch->ch_id); @@ -2203,7 +2211,6 @@ static void mhi_dev_process_ring_pending(struct work_struct *work) mutex_unlock(&ch->ch_lock); goto exit; } - mutex_unlock(&ch->ch_lock); } exit: diff --git a/drivers/platform/msm/mhi_dev/mhi.h b/drivers/platform/msm/mhi_dev/mhi.h index c477bfa7686b..f703d2b546cf 100644 --- a/drivers/platform/msm/mhi_dev/mhi.h +++ b/drivers/platform/msm/mhi_dev/mhi.h @@ -407,7 +407,7 @@ struct mhi_dev_ring { /* ring_ctx_shadow -> tracking ring_ctx in the host */ union mhi_dev_ring_ctx *ring_ctx_shadow; struct msi_buf_cb_data msi_buffer; - void (*ring_cb)(struct mhi_dev *dev, + int (*ring_cb)(struct mhi_dev *dev, union mhi_dev_ring_element_type *el, void *ctx); }; @@ -775,7 +775,7 @@ int mhi_dev_add_element(struct mhi_dev_ring *ring, * @ring_cb: callback function. */ void mhi_ring_set_cb(struct mhi_dev_ring *ring, - void (*ring_cb)(struct mhi_dev *dev, + int (*ring_cb)(struct mhi_dev *dev, union mhi_dev_ring_element_type *el, void *ctx)); /** diff --git a/drivers/platform/msm/mhi_dev/mhi_ring.c b/drivers/platform/msm/mhi_dev/mhi_ring.c index c06e7b36f310..e7b6fb4c389e 100644 --- a/drivers/platform/msm/mhi_dev/mhi_ring.c +++ b/drivers/platform/msm/mhi_dev/mhi_ring.c @@ -197,7 +197,7 @@ int mhi_dev_process_ring_element(struct mhi_dev_ring *ring, size_t offset) el->tre.len, offset); if (ring->ring_cb) - ring->ring_cb(ring->mhi_dev, el, (void *)ring); + return ring->ring_cb(ring->mhi_dev, el, (void *)ring); else mhi_log(MHI_MSG_ERROR, "No callback registered for ring %d\n", ring->id); @@ -557,7 +557,7 @@ void mhi_ring_init(struct mhi_dev_ring *ring, enum mhi_dev_ring_type type, EXPORT_SYMBOL(mhi_ring_init); void mhi_ring_set_cb(struct mhi_dev_ring *ring, - void (*ring_cb)(struct mhi_dev *dev, + int (*ring_cb)(struct mhi_dev *dev, union mhi_dev_ring_element_type *el, void *ctx)) { if (WARN_ON(!ring || !ring_cb)) From eac435a0a2a6df3199bb8ee7029ac92256283459 Mon Sep 17 00:00:00 2001 From: Abhinab Abhinab Date: Mon, 10 May 2021 17:13:45 +0530 Subject: [PATCH 5/5] msm: mhi_dev: Disabling Ch Db Intr during MHI INIT phase In order to tackle the spurious interrupts coming from the host on an invalid channel, the channel doorbell interrupts are disabled during initialization phase. These are enabled after receiving the start command for a particular channel. Change-Id: I12bb315bcd249383ed442ad969e84c9eef25a324 Signed-off-by: Abhinab Abhinab Signed-off-by: Gauri Joshi --- drivers/platform/msm/mhi_dev/mhi.c | 49 ++++++++++++++----------- drivers/platform/msm/mhi_dev/mhi_mmio.c | 27 ++++++++++++-- 2 files changed, 51 insertions(+), 25 deletions(-) diff --git a/drivers/platform/msm/mhi_dev/mhi.c b/drivers/platform/msm/mhi_dev/mhi.c index b9866a4182e9..b7662d475f95 100644 --- a/drivers/platform/msm/mhi_dev/mhi.c +++ b/drivers/platform/msm/mhi_dev/mhi.c @@ -1349,13 +1349,7 @@ static int mhi_enable_int(void) int rc = 0; mhi_log(MHI_MSG_VERBOSE, - "Enable chdb, ctrl and cmdb interrupts\n"); - - rc = mhi_dev_mmio_enable_chdb_interrupts(mhi_ctx); - if (rc) { - pr_err("Failed to enable channel db: %d\n", rc); - return rc; - } + "Enable ctrl and cmdb interrupts\n"); rc = mhi_dev_mmio_enable_ctrl_interrupt(mhi_ctx); if (rc) { @@ -1840,6 +1834,18 @@ static void mhi_dev_process_reset_cmd(struct mhi_dev *mhi, int ch_id) struct mhi_dev_channel *ch; struct mhi_addr host_addr; + rc = mhi_dev_mmio_disable_chdb_a7(mhi, ch_id); + if (rc) { + mhi_log(MHI_MSG_VERBOSE, + "Failed to disable chdb for ch %d\n", ch_id); + rc = mhi_dev_send_cmd_comp_event(mhi, + MHI_CMD_COMPL_CODE_UNDEFINED); + if (rc) + mhi_log(MHI_MSG_VERBOSE, + "Error with compl event\n"); + return; + } + ch = &mhi->ch[ch_id]; /* hard stop and set the channel to stop */ mhi->ch_ctx_cache[ch_id].ch_state = @@ -1889,7 +1895,7 @@ static int mhi_dev_process_cmd_ring(struct mhi_dev *mhi, switch (el->generic.type) { case MHI_DEV_RING_EL_START: - mhi_log(MHI_MSG_VERBOSE, "recived start cmd for channel %d\n", + mhi_log(MHI_MSG_VERBOSE, "received start cmd for channel %d\n", ch_id); if (ch_id >= (HW_CHANNEL_BASE)) { rc = mhi_hwc_chcmd(mhi, ch_id, el->generic.type); @@ -1897,13 +1903,26 @@ static int mhi_dev_process_cmd_ring(struct mhi_dev *mhi, mhi_log(MHI_MSG_ERROR, "Error with HW channel cmd %d\n", rc); rc = mhi_dev_send_cmd_comp_event(mhi, - MHI_CMD_COMPL_CODE_UNDEFINED); + MHI_CMD_COMPL_CODE_UNDEFINED); if (rc) mhi_log(MHI_MSG_ERROR, "Error with compl event\n"); return rc; } goto send_start_completion_event; + } else { + rc = mhi_dev_mmio_enable_chdb_a7(mhi, ch_id); + if (rc) { + mhi_log(MHI_MSG_VERBOSE, + "Failed to enable chdb for ch %d\n", + ch_id); + rc = mhi_dev_send_cmd_comp_event(mhi, + MHI_CMD_COMPL_CODE_UNDEFINED); + if (rc) + mhi_log(MHI_MSG_VERBOSE, + "Error with compl event\n"); + return rc; + } } /* fetch the channel context from host */ @@ -1934,18 +1953,6 @@ static int mhi_dev_process_cmd_ring(struct mhi_dev *mhi, mhi->ch[ch_id].ring = &mhi->ring[mhi->ch_ring_start + ch_id]; mhi->ch[ch_id].ch_type = mhi->ch_ctx_cache[ch_id].ch_type; - /* enable DB for event ring */ - rc = mhi_dev_mmio_enable_chdb_a7(mhi, ch_id); - if (rc) { - pr_err("Failed to enable channel db\n"); - rc = mhi_dev_send_cmd_comp_event(mhi, - MHI_CMD_COMPL_CODE_UNDEFINED); - if (rc) - mhi_log(MHI_MSG_ERROR, - "Error with compl event\n"); - return rc; - } - if (mhi->use_edma || mhi->use_ipa) { uint32_t evnt_ring_idx = mhi->ev_ring_start + mhi->ch_ctx_cache[ch_id].err_indx; diff --git a/drivers/platform/msm/mhi_dev/mhi_mmio.c b/drivers/platform/msm/mhi_dev/mhi_mmio.c index 71fa971dc8eb..a6aebc969a59 100644 --- a/drivers/platform/msm/mhi_dev/mhi_mmio.c +++ b/drivers/platform/msm/mhi_dev/mhi_mmio.c @@ -601,13 +601,18 @@ EXPORT_SYMBOL(mhi_dev_mmio_reset); int mhi_dev_restore_mmio(struct mhi_dev *dev) { + int rc = 0; uint32_t i, reg_cntl_value; void *reg_cntl_addr; if (WARN_ON(!dev)) return -EINVAL; - mhi_dev_mmio_mask_interrupts(dev); + mhi_dev_mmio_disable_ctrl_interrupt(dev); + + mhi_dev_mmio_disable_cmdb_interrupt(dev); + + mhi_dev_mmio_mask_erdb_interrupts(dev); for (i = 0; i < (MHI_DEV_MMIO_RANGE/4); i++) { reg_cntl_addr = dev->mmio_base_addr + @@ -618,12 +623,26 @@ int mhi_dev_restore_mmio(struct mhi_dev *dev) mhi_dev_mmio_clear_interrupts(dev); + for (i = 0; i < MHI_MASK_ROWS_CH_EV_DB; i++) { + /* Enable channel interrupt whose mask is enabled */ + if (dev->chdb[i].mask) { + mhi_log(MHI_MSG_VERBOSE, + "Enabling id: %d, chdb mask 0x%x\n", + i, dev->chdb[i].mask); + + rc = mhi_dev_mmio_write(dev, MHI_CHDB_INT_MASK_A7_n(i), + dev->chdb[i].mask); + if (rc) { + mhi_log(MHI_MSG_VERBOSE, + "Error writing enable for A7\n"); + return rc; + } + } + } + /* Mask and enable control interrupt */ mhi_dev_mmio_enable_ctrl_interrupt(dev); - /*Enable chdb interrupt*/ - mhi_dev_mmio_enable_chdb_interrupts(dev); - /*Enable cmdb interrupt*/ mhi_dev_mmio_enable_cmdb_interrupt(dev);