Loading drivers/platform/msm/mhi_dev/mhi.c +44 −10 Original line number Diff line number Diff line Loading @@ -323,6 +323,7 @@ static int mhi_dev_send_multiple_tr_events(struct mhi_dev *mhi, int evnt_ring, return -EINVAL; } mutex_lock(&ring->event_lock); mhi_log(MHI_MSG_VERBOSE, "Flushing %d cmpl events of ch %d\n", ereq->num_events, ch->ch_id); /* add the events */ Loading @@ -331,6 +332,7 @@ static int mhi_dev_send_multiple_tr_events(struct mhi_dev *mhi, int evnt_ring, rc = mhi_dev_add_element(ring, ereq->tr_events, ereq, evt_len); if (rc) { pr_err("%s(): error in adding element rc %d\n", __func__, rc); mutex_unlock(&ring->event_lock); return rc; } ring->ring_ctx_shadow->ev.rp = (ring->rd_offset * Loading Loading @@ -366,6 +368,7 @@ static int mhi_dev_send_multiple_tr_events(struct mhi_dev *mhi, int evnt_ring, ereq->client_cb = mhi_dev_event_rd_offset_completion_cb; ereq->event_ring = evnt_ring; mhi_ctx->write_to_host(mhi, &transfer_addr, ereq, MHI_DEV_DMA_ASYNC); mutex_unlock(&ring->event_lock); return rc; } Loading Loading @@ -1393,6 +1396,37 @@ int mhi_dev_send_event(struct mhi_dev *mhi, int evnt_ring, return ep_pcie_trigger_msi(mhi_ctx->phandle, ctx->ev.msivec); } static int mhi_dev_send_completion_event_async(struct mhi_dev_channel *ch, size_t rd_ofst, uint32_t len, enum mhi_dev_cmd_completion_code code, struct mhi_req *mreq) { int rc; struct mhi_dev *mhi = ch->ring->mhi_dev; mhi_log(MHI_MSG_VERBOSE, "Ch %d\n", ch->ch_id); /* Queue the completion event for the current transfer */ mreq->snd_cmpl = 1; rc = mhi_dev_queue_transfer_completion(mreq, NULL); if (rc) { mhi_log(MHI_MSG_ERROR, "Failed to queue completion for ch %d, rc %d\n", ch->ch_id, rc); return rc; } mhi_log(MHI_MSG_VERBOSE, "Calling flush for ch %d\n", ch->ch_id); rc = mhi_dev_flush_transfer_completion_events(mhi, ch); if (rc) { mhi_log(MHI_MSG_ERROR, "Failed to flush read completions to host\n"); return rc; } return 0; } static int mhi_dev_send_completion_event(struct mhi_dev_channel *ch, size_t rd_ofst, uint32_t len, enum mhi_dev_cmd_completion_code code) Loading Loading @@ -2699,7 +2733,7 @@ EXPORT_SYMBOL(mhi_dev_close_channel); static int mhi_dev_check_tre_bytes_left(struct mhi_dev_channel *ch, struct mhi_dev_ring *ring, union mhi_dev_ring_element_type *el, uint32_t *chain) struct mhi_req *mreq) { uint32_t td_done = 0; Loading @@ -2710,17 +2744,17 @@ static int mhi_dev_check_tre_bytes_left(struct mhi_dev_channel *ch, if (ch->tre_bytes_left == 0) { if (el->tre.chain) { if (el->tre.ieob) mhi_dev_send_completion_event(ch, mhi_dev_send_completion_event_async(ch, ring->rd_offset, el->tre.len, MHI_CMD_COMPL_CODE_EOB); *chain = 1; MHI_CMD_COMPL_CODE_EOB, mreq); mreq->chain = 1; } else { if (el->tre.ieot) mhi_dev_send_completion_event( mhi_dev_send_completion_event_async( ch, ring->rd_offset, el->tre.len, MHI_CMD_COMPL_CODE_EOT); MHI_CMD_COMPL_CODE_EOT, mreq); td_done = 1; *chain = 0; mreq->chain = 0; } mhi_dev_ring_inc_index(ring, ring->rd_offset); ch->tre_bytes_left = 0; Loading Loading @@ -2831,7 +2865,7 @@ int mhi_dev_read_channel(struct mhi_req *mreq) goto exit; } else { td_done = mhi_dev_check_tre_bytes_left(ch, ring, el, &mreq->chain); el, mreq); } } while (usr_buf_remaining && !td_done); if (td_done && ch->state == MHI_DEV_CH_PENDING_STOP) { Loading drivers/platform/msm/mhi_dev/mhi.h +5 −1 Original line number Diff line number Diff line Loading @@ -382,7 +382,11 @@ struct mhi_dev_ring { enum mhi_dev_ring_type type; enum mhi_dev_ring_state state; /* * Lock to prevent race in updating event ring * which is shared by multiple channels */ struct mutex event_lock; /* device virtual address location of the cached host ring ctx data */ union mhi_dev_ring_element_type *ring_cache; /* Physical address of the cached ring copy on the device side */ Loading drivers/platform/msm/mhi_dev/mhi_ring.c +2 −1 Original line number Diff line number Diff line /* Copyright (c) 2015-2019, The Linux Foundation. All rights reserved. /* Copyright (c) 2015-2020, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -453,6 +453,7 @@ void mhi_ring_init(struct mhi_dev_ring *ring, enum mhi_dev_ring_type type, ring->state = RING_STATE_UINT; ring->ring_cb = NULL; ring->type = type; mutex_init(&ring->event_lock); } EXPORT_SYMBOL(mhi_ring_init); Loading Loading
drivers/platform/msm/mhi_dev/mhi.c +44 −10 Original line number Diff line number Diff line Loading @@ -323,6 +323,7 @@ static int mhi_dev_send_multiple_tr_events(struct mhi_dev *mhi, int evnt_ring, return -EINVAL; } mutex_lock(&ring->event_lock); mhi_log(MHI_MSG_VERBOSE, "Flushing %d cmpl events of ch %d\n", ereq->num_events, ch->ch_id); /* add the events */ Loading @@ -331,6 +332,7 @@ static int mhi_dev_send_multiple_tr_events(struct mhi_dev *mhi, int evnt_ring, rc = mhi_dev_add_element(ring, ereq->tr_events, ereq, evt_len); if (rc) { pr_err("%s(): error in adding element rc %d\n", __func__, rc); mutex_unlock(&ring->event_lock); return rc; } ring->ring_ctx_shadow->ev.rp = (ring->rd_offset * Loading Loading @@ -366,6 +368,7 @@ static int mhi_dev_send_multiple_tr_events(struct mhi_dev *mhi, int evnt_ring, ereq->client_cb = mhi_dev_event_rd_offset_completion_cb; ereq->event_ring = evnt_ring; mhi_ctx->write_to_host(mhi, &transfer_addr, ereq, MHI_DEV_DMA_ASYNC); mutex_unlock(&ring->event_lock); return rc; } Loading Loading @@ -1393,6 +1396,37 @@ int mhi_dev_send_event(struct mhi_dev *mhi, int evnt_ring, return ep_pcie_trigger_msi(mhi_ctx->phandle, ctx->ev.msivec); } static int mhi_dev_send_completion_event_async(struct mhi_dev_channel *ch, size_t rd_ofst, uint32_t len, enum mhi_dev_cmd_completion_code code, struct mhi_req *mreq) { int rc; struct mhi_dev *mhi = ch->ring->mhi_dev; mhi_log(MHI_MSG_VERBOSE, "Ch %d\n", ch->ch_id); /* Queue the completion event for the current transfer */ mreq->snd_cmpl = 1; rc = mhi_dev_queue_transfer_completion(mreq, NULL); if (rc) { mhi_log(MHI_MSG_ERROR, "Failed to queue completion for ch %d, rc %d\n", ch->ch_id, rc); return rc; } mhi_log(MHI_MSG_VERBOSE, "Calling flush for ch %d\n", ch->ch_id); rc = mhi_dev_flush_transfer_completion_events(mhi, ch); if (rc) { mhi_log(MHI_MSG_ERROR, "Failed to flush read completions to host\n"); return rc; } return 0; } static int mhi_dev_send_completion_event(struct mhi_dev_channel *ch, size_t rd_ofst, uint32_t len, enum mhi_dev_cmd_completion_code code) Loading Loading @@ -2699,7 +2733,7 @@ EXPORT_SYMBOL(mhi_dev_close_channel); static int mhi_dev_check_tre_bytes_left(struct mhi_dev_channel *ch, struct mhi_dev_ring *ring, union mhi_dev_ring_element_type *el, uint32_t *chain) struct mhi_req *mreq) { uint32_t td_done = 0; Loading @@ -2710,17 +2744,17 @@ static int mhi_dev_check_tre_bytes_left(struct mhi_dev_channel *ch, if (ch->tre_bytes_left == 0) { if (el->tre.chain) { if (el->tre.ieob) mhi_dev_send_completion_event(ch, mhi_dev_send_completion_event_async(ch, ring->rd_offset, el->tre.len, MHI_CMD_COMPL_CODE_EOB); *chain = 1; MHI_CMD_COMPL_CODE_EOB, mreq); mreq->chain = 1; } else { if (el->tre.ieot) mhi_dev_send_completion_event( mhi_dev_send_completion_event_async( ch, ring->rd_offset, el->tre.len, MHI_CMD_COMPL_CODE_EOT); MHI_CMD_COMPL_CODE_EOT, mreq); td_done = 1; *chain = 0; mreq->chain = 0; } mhi_dev_ring_inc_index(ring, ring->rd_offset); ch->tre_bytes_left = 0; Loading Loading @@ -2831,7 +2865,7 @@ int mhi_dev_read_channel(struct mhi_req *mreq) goto exit; } else { td_done = mhi_dev_check_tre_bytes_left(ch, ring, el, &mreq->chain); el, mreq); } } while (usr_buf_remaining && !td_done); if (td_done && ch->state == MHI_DEV_CH_PENDING_STOP) { Loading
drivers/platform/msm/mhi_dev/mhi.h +5 −1 Original line number Diff line number Diff line Loading @@ -382,7 +382,11 @@ struct mhi_dev_ring { enum mhi_dev_ring_type type; enum mhi_dev_ring_state state; /* * Lock to prevent race in updating event ring * which is shared by multiple channels */ struct mutex event_lock; /* device virtual address location of the cached host ring ctx data */ union mhi_dev_ring_element_type *ring_cache; /* Physical address of the cached ring copy on the device side */ Loading
drivers/platform/msm/mhi_dev/mhi_ring.c +2 −1 Original line number Diff line number Diff line /* Copyright (c) 2015-2019, The Linux Foundation. All rights reserved. /* Copyright (c) 2015-2020, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -453,6 +453,7 @@ void mhi_ring_init(struct mhi_dev_ring *ring, enum mhi_dev_ring_type type, ring->state = RING_STATE_UINT; ring->ring_cb = NULL; ring->type = type; mutex_init(&ring->event_lock); } EXPORT_SYMBOL(mhi_ring_init); Loading