Loading drivers/platform/msm/mhi_dev/mhi.c +59 −7 Original line number Original line Diff line number Diff line Loading @@ -63,6 +63,10 @@ #define TR_RING_ELEMENT_SZ sizeof(struct mhi_dev_transfer_ring_element) #define TR_RING_ELEMENT_SZ sizeof(struct mhi_dev_transfer_ring_element) #define RING_ELEMENT_TYPE_SZ sizeof(union mhi_dev_ring_element_type) #define RING_ELEMENT_TYPE_SZ sizeof(union mhi_dev_ring_element_type) #define MHI_DEV_CH_CLOSE_TIMEOUT_MIN 5000 #define MHI_DEV_CH_CLOSE_TIMEOUT_MAX 5100 #define MHI_DEV_CH_CLOSE_TIMEOUT_COUNT 30 uint32_t bhi_imgtxdb; uint32_t bhi_imgtxdb; enum mhi_msg_level mhi_msg_lvl = MHI_MSG_ERROR; enum mhi_msg_level mhi_msg_lvl = MHI_MSG_ERROR; enum mhi_msg_level mhi_ipc_msg_lvl = MHI_MSG_VERBOSE; enum mhi_msg_level mhi_ipc_msg_lvl = MHI_MSG_VERBOSE; Loading Loading @@ -913,7 +917,7 @@ static int mhi_dev_process_stop_cmd(struct mhi_dev_ring *ring, uint32_t ch_id, return 0; return 0; } else if (mhi->ch_ctx_cache[ch_id].ch_type == } else if (mhi->ch_ctx_cache[ch_id].ch_type == MHI_DEV_CH_TYPE_INBOUND_CHANNEL && MHI_DEV_CH_TYPE_INBOUND_CHANNEL && mhi->ch[ch_id].wr_request_active) { (mhi->ch[ch_id].pend_wr_count > 0)) { mhi_log(MHI_MSG_INFO, "Pending inbound transaction\n"); mhi_log(MHI_MSG_INFO, "Pending inbound transaction\n"); return 0; return 0; } } Loading Loading @@ -1453,9 +1457,23 @@ static void mhi_dev_transfer_completion_cb(void *mreq) rd_offset = req->rd_offset; rd_offset = req->rd_offset; ch->curr_ereq->context = ch; ch->curr_ereq->context = ch; if (mhi->ch_ctx_cache[ch->ch_id].ch_type == MHI_DEV_CH_TYPE_INBOUND_CHANNEL) ch->pend_wr_count--; dma_unmap_single(&mhi_ctx->pdev->dev, req->dma, dma_unmap_single(&mhi_ctx->pdev->dev, req->dma, req->len, DMA_FROM_DEVICE); req->len, DMA_FROM_DEVICE); /* * Channel got closed with transfers pending * Do not trigger callback or send cmpl to host */ if (ch->state == MHI_DEV_CH_CLOSED) { mhi_log(MHI_MSG_DBG, "Ch %d closed with %d writes pending\n", ch->ch_id, ch->pend_wr_count + 1); return; } /* Trigger client call back */ /* Trigger client call back */ req->client_cb(req); req->client_cb(req); Loading Loading @@ -2009,18 +2027,49 @@ int mhi_dev_channel_isempty(struct mhi_dev_client *handle) } } EXPORT_SYMBOL(mhi_dev_channel_isempty); EXPORT_SYMBOL(mhi_dev_channel_isempty); bool mhi_dev_channel_has_pending_write(struct mhi_dev_client *handle) { struct mhi_dev_channel *ch; if (!handle) { mhi_log(MHI_MSG_ERROR, "Invalid channel access\n"); return -EINVAL; } ch = handle->channel; if (!ch) return -EINVAL; return ch->pend_wr_count ? true : false; } EXPORT_SYMBOL(mhi_dev_channel_has_pending_write); int mhi_dev_close_channel(struct mhi_dev_client *handle) int mhi_dev_close_channel(struct mhi_dev_client *handle) { { struct mhi_dev_channel *ch; struct mhi_dev_channel *ch; int count = 0; int rc = 0; int rc = 0; ch = handle->channel; ch = handle->channel; do { if (ch->pend_wr_count) { 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); 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); if (ch->state != MHI_DEV_CH_PENDING_START) { if (ch->state != MHI_DEV_CH_PENDING_START) { if (ch->ch_type == MHI_DEV_CH_TYPE_OUTBOUND_CHANNEL && if ((ch->ch_type == MHI_DEV_CH_TYPE_OUTBOUND_CHANNEL && !mhi_dev_channel_isempty(handle)) { !mhi_dev_channel_isempty(handle)) || ch->tre_loc) { mhi_log(MHI_MSG_ERROR, mhi_log(MHI_MSG_DBG, "Trying to close an active channel (%d)\n", "Trying to close an active channel (%d)\n", ch->ch_id); ch->ch_id); rc = -EAGAIN; rc = -EAGAIN; Loading Loading @@ -2237,6 +2286,7 @@ int mhi_dev_write_channel(struct mhi_req *wreq) size_t bytes_to_write = 0; size_t bytes_to_write = 0; size_t bytes_written = 0; size_t bytes_written = 0; uint32_t tre_len = 0, suspend_wait_timeout = 0; uint32_t tre_len = 0, suspend_wait_timeout = 0; bool async_wr_sched = false; if (!wreq || !wreq->client || !wreq->buf) { if (!wreq || !wreq->client || !wreq->buf) { pr_err("%s: invalid parameters\n", __func__); pr_err("%s: invalid parameters\n", __func__); Loading Loading @@ -2280,12 +2330,12 @@ int mhi_dev_write_channel(struct mhi_req *wreq) handle_client = wreq->client; handle_client = wreq->client; ch = handle_client->channel; ch = handle_client->channel; ch->wr_request_active = true; ring = ch->ring; ring = ch->ring; mutex_lock(&ch->ch_lock); mutex_lock(&ch->ch_lock); ch->pend_wr_count++; if (ch->state == MHI_DEV_CH_STOPPED) { if (ch->state == MHI_DEV_CH_STOPPED) { mhi_log(MHI_MSG_ERROR, mhi_log(MHI_MSG_ERROR, "channel %d already stopped\n", wreq->chan); "channel %d already stopped\n", wreq->chan); Loading Loading @@ -2336,7 +2386,8 @@ int mhi_dev_write_channel(struct mhi_req *wreq) "Error while writing chan (%d) rc %d\n", "Error while writing chan (%d) rc %d\n", wreq->chan, rc); wreq->chan, rc); goto exit; goto exit; } } else if (wreq->mode == DMA_ASYNC) async_wr_sched = true; bytes_written += bytes_to_write; bytes_written += bytes_to_write; usr_buf_remaining -= bytes_to_write; usr_buf_remaining -= bytes_to_write; Loading Loading @@ -2376,7 +2427,8 @@ int mhi_dev_write_channel(struct mhi_req *wreq) } } } } exit: exit: ch->wr_request_active = false; if (wreq->mode == DMA_SYNC || !async_wr_sched) ch->pend_wr_count--; mutex_unlock(&ch->ch_lock); mutex_unlock(&ch->ch_lock); mutex_unlock(&mhi_ctx->mhi_write_test); mutex_unlock(&mhi_ctx->mhi_write_test); return bytes_written; return bytes_written; Loading drivers/platform/msm/mhi_dev/mhi.h +1 −1 Original line number Original line Diff line number Diff line Loading @@ -461,7 +461,7 @@ struct mhi_dev_channel { uint32_t tre_bytes_left; uint32_t tre_bytes_left; /* td size being read/written from/to so far */ /* td size being read/written from/to so far */ uint32_t td_size; uint32_t td_size; bool wr_request_active; uint32_t pend_wr_count; bool skip_td; bool skip_td; }; }; Loading drivers/platform/msm/mhi_dev/mhi_uci.c +46 −27 Original line number Original line Diff line number Diff line Loading @@ -47,6 +47,10 @@ #define MHI_UCI_AT_CTRL_READ_TIMEOUT msecs_to_jiffies(1000) #define MHI_UCI_AT_CTRL_READ_TIMEOUT msecs_to_jiffies(1000) #define MHI_UCI_WRITE_REQ_AVAIL_TIMEOUT msecs_to_jiffies(1000) #define MHI_UCI_WRITE_REQ_AVAIL_TIMEOUT msecs_to_jiffies(1000) #define MHI_UCI_RELEASE_TIMEOUT_MIN 5000 #define MHI_UCI_RELEASE_TIMEOUT_MAX 5100 #define MHI_UCI_RELEASE_TIMEOUT_COUNT 30 enum uci_dbg_level { enum uci_dbg_level { UCI_DBG_VERBOSE = 0x0, UCI_DBG_VERBOSE = 0x0, UCI_DBG_INFO = 0x1, UCI_DBG_INFO = 0x1, Loading Loading @@ -907,41 +911,56 @@ static int mhi_uci_client_release(struct inode *mhi_inode, struct file *file_handle) struct file *file_handle) { { struct uci_client *uci_handle = file_handle->private_data; struct uci_client *uci_handle = file_handle->private_data; int rc = 0; int count = 0; if (!uci_handle) if (!uci_handle) return -EINVAL; return -EINVAL; if (atomic_sub_return(1, &uci_handle->ref_count) == 0) { if (atomic_sub_return(1, &uci_handle->ref_count)) { uci_log(UCI_DBG_DBG, "Client close chan %d, ref count 0x%x\n", iminor(mhi_inode), atomic_read(&uci_handle->ref_count)); return 0; } uci_log(UCI_DBG_DBG, uci_log(UCI_DBG_DBG, "Last client left, closing channel 0x%x\n", "Last client left, closing channel 0x%x\n", iminor(mhi_inode)); iminor(mhi_inode)); do { if (mhi_dev_channel_has_pending_write(uci_handle->out_handle)) usleep_range(MHI_UCI_RELEASE_TIMEOUT_MIN, MHI_UCI_RELEASE_TIMEOUT_MAX); else break; } while (++count < MHI_UCI_RELEASE_TIMEOUT_COUNT); if (count == MHI_UCI_RELEASE_TIMEOUT_COUNT) { uci_log(UCI_DBG_DBG, "Channel %d has pending writes\n", iminor(mhi_inode)); } if (atomic_read(&uci_handle->mhi_chans_open)) { if (atomic_read(&uci_handle->mhi_chans_open)) { atomic_set(&uci_handle->mhi_chans_open, 0); atomic_set(&uci_handle->mhi_chans_open, 0); if (!(uci_handle->f_flags & O_SYNC)) if (!(uci_handle->f_flags & O_SYNC)) kfree(uci_handle->wreqs); kfree(uci_handle->wreqs); mutex_lock(&uci_handle->out_chan_lock); mutex_lock(&uci_handle->out_chan_lock); rc = mhi_dev_close_channel(uci_handle->out_handle); mhi_dev_close_channel(uci_handle->out_handle); wake_up(&uci_handle->write_wq); wake_up(&uci_handle->write_wq); mutex_unlock(&uci_handle->out_chan_lock); mutex_unlock(&uci_handle->out_chan_lock); mutex_lock(&uci_handle->in_chan_lock); mutex_lock(&uci_handle->in_chan_lock); rc = mhi_dev_close_channel(uci_handle->in_handle); mhi_dev_close_channel(uci_handle->in_handle); wake_up(&uci_handle->read_wq); wake_up(&uci_handle->read_wq); mutex_unlock(&uci_handle->in_chan_lock); mutex_unlock(&uci_handle->in_chan_lock); } } atomic_set(&uci_handle->read_data_ready, 0); atomic_set(&uci_handle->read_data_ready, 0); atomic_set(&uci_handle->write_data_ready, 0); atomic_set(&uci_handle->write_data_ready, 0); file_handle->private_data = NULL; file_handle->private_data = NULL; } else { uci_log(UCI_DBG_DBG, return 0; "Client close chan %d, ref count 0x%x\n", iminor(mhi_inode), atomic_read(&uci_handle->ref_count)); } return rc; } } static void mhi_parse_state(char *buf, int *nbytes, uint32_t info) static void mhi_parse_state(char *buf, int *nbytes, uint32_t info) Loading include/linux/msm_mhi_dev.h +15 −0 Original line number Original line Diff line number Diff line Loading @@ -18,6 +18,8 @@ #define IPA_DMA_SYNC 1 #define IPA_DMA_SYNC 1 #define IPA_DMA_ASYNC 0 #define IPA_DMA_ASYNC 0 #define DMA_SYNC 1 #define DMA_ASYNC 0 enum cb_reason { enum cb_reason { MHI_DEV_TRE_AVAILABLE = 0, MHI_DEV_TRE_AVAILABLE = 0, Loading Loading @@ -196,6 +198,13 @@ int mhi_dev_write_channel(struct mhi_req *wreq); */ */ int mhi_dev_channel_isempty(struct mhi_dev_client *handle); int mhi_dev_channel_isempty(struct mhi_dev_client *handle); /** * mhi_dev_channel_has_pending_write() - Checks if there are any pending writes * to be completed on inbound channel * @handle_client: Client Handle issued during mhi_dev_open_channel */ bool mhi_dev_channel_has_pending_write(struct mhi_dev_client *handle); /** /** * mhi_ctrl_state_info() - Provide MHI state info * mhi_ctrl_state_info() - Provide MHI state info * @idx: Channel number idx. Look at channel_state_info and * @idx: Channel number idx. Look at channel_state_info and Loading Loading @@ -246,6 +255,12 @@ static inline int mhi_dev_channel_isempty(struct mhi_dev_client *handle) return -EINVAL; return -EINVAL; }; }; static inline bool mhi_dev_channel_has_pending_write (struct mhi_dev_client *handle) { return false; } static inline int mhi_ctrl_state_info(uint32_t idx, uint32_t *info) static inline int mhi_ctrl_state_info(uint32_t idx, uint32_t *info) { { return -EINVAL; return -EINVAL; Loading Loading
drivers/platform/msm/mhi_dev/mhi.c +59 −7 Original line number Original line Diff line number Diff line Loading @@ -63,6 +63,10 @@ #define TR_RING_ELEMENT_SZ sizeof(struct mhi_dev_transfer_ring_element) #define TR_RING_ELEMENT_SZ sizeof(struct mhi_dev_transfer_ring_element) #define RING_ELEMENT_TYPE_SZ sizeof(union mhi_dev_ring_element_type) #define RING_ELEMENT_TYPE_SZ sizeof(union mhi_dev_ring_element_type) #define MHI_DEV_CH_CLOSE_TIMEOUT_MIN 5000 #define MHI_DEV_CH_CLOSE_TIMEOUT_MAX 5100 #define MHI_DEV_CH_CLOSE_TIMEOUT_COUNT 30 uint32_t bhi_imgtxdb; uint32_t bhi_imgtxdb; enum mhi_msg_level mhi_msg_lvl = MHI_MSG_ERROR; enum mhi_msg_level mhi_msg_lvl = MHI_MSG_ERROR; enum mhi_msg_level mhi_ipc_msg_lvl = MHI_MSG_VERBOSE; enum mhi_msg_level mhi_ipc_msg_lvl = MHI_MSG_VERBOSE; Loading Loading @@ -913,7 +917,7 @@ static int mhi_dev_process_stop_cmd(struct mhi_dev_ring *ring, uint32_t ch_id, return 0; return 0; } else if (mhi->ch_ctx_cache[ch_id].ch_type == } else if (mhi->ch_ctx_cache[ch_id].ch_type == MHI_DEV_CH_TYPE_INBOUND_CHANNEL && MHI_DEV_CH_TYPE_INBOUND_CHANNEL && mhi->ch[ch_id].wr_request_active) { (mhi->ch[ch_id].pend_wr_count > 0)) { mhi_log(MHI_MSG_INFO, "Pending inbound transaction\n"); mhi_log(MHI_MSG_INFO, "Pending inbound transaction\n"); return 0; return 0; } } Loading Loading @@ -1453,9 +1457,23 @@ static void mhi_dev_transfer_completion_cb(void *mreq) rd_offset = req->rd_offset; rd_offset = req->rd_offset; ch->curr_ereq->context = ch; ch->curr_ereq->context = ch; if (mhi->ch_ctx_cache[ch->ch_id].ch_type == MHI_DEV_CH_TYPE_INBOUND_CHANNEL) ch->pend_wr_count--; dma_unmap_single(&mhi_ctx->pdev->dev, req->dma, dma_unmap_single(&mhi_ctx->pdev->dev, req->dma, req->len, DMA_FROM_DEVICE); req->len, DMA_FROM_DEVICE); /* * Channel got closed with transfers pending * Do not trigger callback or send cmpl to host */ if (ch->state == MHI_DEV_CH_CLOSED) { mhi_log(MHI_MSG_DBG, "Ch %d closed with %d writes pending\n", ch->ch_id, ch->pend_wr_count + 1); return; } /* Trigger client call back */ /* Trigger client call back */ req->client_cb(req); req->client_cb(req); Loading Loading @@ -2009,18 +2027,49 @@ int mhi_dev_channel_isempty(struct mhi_dev_client *handle) } } EXPORT_SYMBOL(mhi_dev_channel_isempty); EXPORT_SYMBOL(mhi_dev_channel_isempty); bool mhi_dev_channel_has_pending_write(struct mhi_dev_client *handle) { struct mhi_dev_channel *ch; if (!handle) { mhi_log(MHI_MSG_ERROR, "Invalid channel access\n"); return -EINVAL; } ch = handle->channel; if (!ch) return -EINVAL; return ch->pend_wr_count ? true : false; } EXPORT_SYMBOL(mhi_dev_channel_has_pending_write); int mhi_dev_close_channel(struct mhi_dev_client *handle) int mhi_dev_close_channel(struct mhi_dev_client *handle) { { struct mhi_dev_channel *ch; struct mhi_dev_channel *ch; int count = 0; int rc = 0; int rc = 0; ch = handle->channel; ch = handle->channel; do { if (ch->pend_wr_count) { 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); 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); if (ch->state != MHI_DEV_CH_PENDING_START) { if (ch->state != MHI_DEV_CH_PENDING_START) { if (ch->ch_type == MHI_DEV_CH_TYPE_OUTBOUND_CHANNEL && if ((ch->ch_type == MHI_DEV_CH_TYPE_OUTBOUND_CHANNEL && !mhi_dev_channel_isempty(handle)) { !mhi_dev_channel_isempty(handle)) || ch->tre_loc) { mhi_log(MHI_MSG_ERROR, mhi_log(MHI_MSG_DBG, "Trying to close an active channel (%d)\n", "Trying to close an active channel (%d)\n", ch->ch_id); ch->ch_id); rc = -EAGAIN; rc = -EAGAIN; Loading Loading @@ -2237,6 +2286,7 @@ int mhi_dev_write_channel(struct mhi_req *wreq) size_t bytes_to_write = 0; size_t bytes_to_write = 0; size_t bytes_written = 0; size_t bytes_written = 0; uint32_t tre_len = 0, suspend_wait_timeout = 0; uint32_t tre_len = 0, suspend_wait_timeout = 0; bool async_wr_sched = false; if (!wreq || !wreq->client || !wreq->buf) { if (!wreq || !wreq->client || !wreq->buf) { pr_err("%s: invalid parameters\n", __func__); pr_err("%s: invalid parameters\n", __func__); Loading Loading @@ -2280,12 +2330,12 @@ int mhi_dev_write_channel(struct mhi_req *wreq) handle_client = wreq->client; handle_client = wreq->client; ch = handle_client->channel; ch = handle_client->channel; ch->wr_request_active = true; ring = ch->ring; ring = ch->ring; mutex_lock(&ch->ch_lock); mutex_lock(&ch->ch_lock); ch->pend_wr_count++; if (ch->state == MHI_DEV_CH_STOPPED) { if (ch->state == MHI_DEV_CH_STOPPED) { mhi_log(MHI_MSG_ERROR, mhi_log(MHI_MSG_ERROR, "channel %d already stopped\n", wreq->chan); "channel %d already stopped\n", wreq->chan); Loading Loading @@ -2336,7 +2386,8 @@ int mhi_dev_write_channel(struct mhi_req *wreq) "Error while writing chan (%d) rc %d\n", "Error while writing chan (%d) rc %d\n", wreq->chan, rc); wreq->chan, rc); goto exit; goto exit; } } else if (wreq->mode == DMA_ASYNC) async_wr_sched = true; bytes_written += bytes_to_write; bytes_written += bytes_to_write; usr_buf_remaining -= bytes_to_write; usr_buf_remaining -= bytes_to_write; Loading Loading @@ -2376,7 +2427,8 @@ int mhi_dev_write_channel(struct mhi_req *wreq) } } } } exit: exit: ch->wr_request_active = false; if (wreq->mode == DMA_SYNC || !async_wr_sched) ch->pend_wr_count--; mutex_unlock(&ch->ch_lock); mutex_unlock(&ch->ch_lock); mutex_unlock(&mhi_ctx->mhi_write_test); mutex_unlock(&mhi_ctx->mhi_write_test); return bytes_written; return bytes_written; Loading
drivers/platform/msm/mhi_dev/mhi.h +1 −1 Original line number Original line Diff line number Diff line Loading @@ -461,7 +461,7 @@ struct mhi_dev_channel { uint32_t tre_bytes_left; uint32_t tre_bytes_left; /* td size being read/written from/to so far */ /* td size being read/written from/to so far */ uint32_t td_size; uint32_t td_size; bool wr_request_active; uint32_t pend_wr_count; bool skip_td; bool skip_td; }; }; Loading
drivers/platform/msm/mhi_dev/mhi_uci.c +46 −27 Original line number Original line Diff line number Diff line Loading @@ -47,6 +47,10 @@ #define MHI_UCI_AT_CTRL_READ_TIMEOUT msecs_to_jiffies(1000) #define MHI_UCI_AT_CTRL_READ_TIMEOUT msecs_to_jiffies(1000) #define MHI_UCI_WRITE_REQ_AVAIL_TIMEOUT msecs_to_jiffies(1000) #define MHI_UCI_WRITE_REQ_AVAIL_TIMEOUT msecs_to_jiffies(1000) #define MHI_UCI_RELEASE_TIMEOUT_MIN 5000 #define MHI_UCI_RELEASE_TIMEOUT_MAX 5100 #define MHI_UCI_RELEASE_TIMEOUT_COUNT 30 enum uci_dbg_level { enum uci_dbg_level { UCI_DBG_VERBOSE = 0x0, UCI_DBG_VERBOSE = 0x0, UCI_DBG_INFO = 0x1, UCI_DBG_INFO = 0x1, Loading Loading @@ -907,41 +911,56 @@ static int mhi_uci_client_release(struct inode *mhi_inode, struct file *file_handle) struct file *file_handle) { { struct uci_client *uci_handle = file_handle->private_data; struct uci_client *uci_handle = file_handle->private_data; int rc = 0; int count = 0; if (!uci_handle) if (!uci_handle) return -EINVAL; return -EINVAL; if (atomic_sub_return(1, &uci_handle->ref_count) == 0) { if (atomic_sub_return(1, &uci_handle->ref_count)) { uci_log(UCI_DBG_DBG, "Client close chan %d, ref count 0x%x\n", iminor(mhi_inode), atomic_read(&uci_handle->ref_count)); return 0; } uci_log(UCI_DBG_DBG, uci_log(UCI_DBG_DBG, "Last client left, closing channel 0x%x\n", "Last client left, closing channel 0x%x\n", iminor(mhi_inode)); iminor(mhi_inode)); do { if (mhi_dev_channel_has_pending_write(uci_handle->out_handle)) usleep_range(MHI_UCI_RELEASE_TIMEOUT_MIN, MHI_UCI_RELEASE_TIMEOUT_MAX); else break; } while (++count < MHI_UCI_RELEASE_TIMEOUT_COUNT); if (count == MHI_UCI_RELEASE_TIMEOUT_COUNT) { uci_log(UCI_DBG_DBG, "Channel %d has pending writes\n", iminor(mhi_inode)); } if (atomic_read(&uci_handle->mhi_chans_open)) { if (atomic_read(&uci_handle->mhi_chans_open)) { atomic_set(&uci_handle->mhi_chans_open, 0); atomic_set(&uci_handle->mhi_chans_open, 0); if (!(uci_handle->f_flags & O_SYNC)) if (!(uci_handle->f_flags & O_SYNC)) kfree(uci_handle->wreqs); kfree(uci_handle->wreqs); mutex_lock(&uci_handle->out_chan_lock); mutex_lock(&uci_handle->out_chan_lock); rc = mhi_dev_close_channel(uci_handle->out_handle); mhi_dev_close_channel(uci_handle->out_handle); wake_up(&uci_handle->write_wq); wake_up(&uci_handle->write_wq); mutex_unlock(&uci_handle->out_chan_lock); mutex_unlock(&uci_handle->out_chan_lock); mutex_lock(&uci_handle->in_chan_lock); mutex_lock(&uci_handle->in_chan_lock); rc = mhi_dev_close_channel(uci_handle->in_handle); mhi_dev_close_channel(uci_handle->in_handle); wake_up(&uci_handle->read_wq); wake_up(&uci_handle->read_wq); mutex_unlock(&uci_handle->in_chan_lock); mutex_unlock(&uci_handle->in_chan_lock); } } atomic_set(&uci_handle->read_data_ready, 0); atomic_set(&uci_handle->read_data_ready, 0); atomic_set(&uci_handle->write_data_ready, 0); atomic_set(&uci_handle->write_data_ready, 0); file_handle->private_data = NULL; file_handle->private_data = NULL; } else { uci_log(UCI_DBG_DBG, return 0; "Client close chan %d, ref count 0x%x\n", iminor(mhi_inode), atomic_read(&uci_handle->ref_count)); } return rc; } } static void mhi_parse_state(char *buf, int *nbytes, uint32_t info) static void mhi_parse_state(char *buf, int *nbytes, uint32_t info) Loading
include/linux/msm_mhi_dev.h +15 −0 Original line number Original line Diff line number Diff line Loading @@ -18,6 +18,8 @@ #define IPA_DMA_SYNC 1 #define IPA_DMA_SYNC 1 #define IPA_DMA_ASYNC 0 #define IPA_DMA_ASYNC 0 #define DMA_SYNC 1 #define DMA_ASYNC 0 enum cb_reason { enum cb_reason { MHI_DEV_TRE_AVAILABLE = 0, MHI_DEV_TRE_AVAILABLE = 0, Loading Loading @@ -196,6 +198,13 @@ int mhi_dev_write_channel(struct mhi_req *wreq); */ */ int mhi_dev_channel_isempty(struct mhi_dev_client *handle); int mhi_dev_channel_isempty(struct mhi_dev_client *handle); /** * mhi_dev_channel_has_pending_write() - Checks if there are any pending writes * to be completed on inbound channel * @handle_client: Client Handle issued during mhi_dev_open_channel */ bool mhi_dev_channel_has_pending_write(struct mhi_dev_client *handle); /** /** * mhi_ctrl_state_info() - Provide MHI state info * mhi_ctrl_state_info() - Provide MHI state info * @idx: Channel number idx. Look at channel_state_info and * @idx: Channel number idx. Look at channel_state_info and Loading Loading @@ -246,6 +255,12 @@ static inline int mhi_dev_channel_isempty(struct mhi_dev_client *handle) return -EINVAL; return -EINVAL; }; }; static inline bool mhi_dev_channel_has_pending_write (struct mhi_dev_client *handle) { return false; } static inline int mhi_ctrl_state_info(uint32_t idx, uint32_t *info) static inline int mhi_ctrl_state_info(uint32_t idx, uint32_t *info) { { return -EINVAL; return -EINVAL; Loading