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))