diff options
| author | Amandeep Singh <amansing@codeaurora.org> | 2019-06-24 14:51:08 +0530 |
|---|---|---|
| committer | Amandeep Singh <amansing@codeaurora.org> | 2019-09-03 11:11:32 +0530 |
| commit | 23ddb3ee2d6cf4bdbca5fcdb69c334f95e157edb (patch) | |
| tree | c586c0d618c5cd8d2440e0257424f63b28ce1288 | |
| parent | ff692c270002f0590e7a37090b3220aa0f0c6a3d (diff) | |
msm: qcn: Synchronize clients operating at different modes
Add synchronization support between clients that operate on different
modes, i.e. synchronous or asynchronous. The synchronous client will
momentarily switch to asynchronous if any asynchronous transmission is
scheduled.
Change-Id: I41aec9bff950d2816a9ce55017e118e8504be77a
Signed-off-by: Amandeep Singh <amansing@codeaurora.org>
| -rw-r--r-- | drivers/platform/msm/qcn/qcn_sdio.c | 89 |
1 files changed, 57 insertions, 32 deletions
diff --git a/drivers/platform/msm/qcn/qcn_sdio.c b/drivers/platform/msm/qcn/qcn_sdio.c index 867377f40c2c..71787acd6940 100644 --- a/drivers/platform/msm/qcn/qcn_sdio.c +++ b/drivers/platform/msm/qcn/qcn_sdio.c @@ -63,6 +63,7 @@ struct completion client_probe_complete; static struct mutex lock; static struct list_head cinfo_head; static atomic_t status; +static spinlock_t async_lock; #if (QCN_SDIO_META_VER_0) #define META_INFO(event, data) \ @@ -660,6 +661,7 @@ int qcn_sdio_probe(struct sdio_func *func, const struct sdio_device_id *id) spin_lock_init(&sdio_ctxt->lock_free_q); spin_lock_init(&sdio_ctxt->lock_wait_q); + spin_lock_init(&async_lock); INIT_WORK(&sdio_ctxt->sdio_rw_w, qcn_sdio_rw_work); INIT_LIST_HEAD(&sdio_ctxt->rw_free_q); INIT_LIST_HEAD(&sdio_ctxt->rw_wait_q); @@ -984,38 +986,6 @@ void sdio_al_deregister_channel(struct sdio_al_channel_handle *ch_handle) } EXPORT_SYMBOL(sdio_al_deregister_channel); -int sdio_al_queue_transfer(struct sdio_al_channel_handle *ch_handle, - enum sdio_al_dma_direction dir, - void *buf, size_t len, int priority) -{ - int ret = 0; - u32 cid = QCN_SDIO_CH_MAX; - - if (!ch_handle) { - pr_err("%s: SDIO: Invalid Param\n", __func__); - return -EINVAL; - } - - cid = ch_handle->channel_id; - - if (!(cid < QCN_SDIO_CH_MAX)) - return -EINVAL; - - if (dir == SDIO_AL_RX) { - ret = qcn_sdio_recv_buff(cid, buf, len); - if (rx_dump) - HEX_DUMP("SYNC_RECV: ", buf, len); - } else if (dir == SDIO_AL_TX) { - ret = qcn_sdio_send_buff(cid, buf, len); - if (tx_dump) - HEX_DUMP("SYNC_SEND: ", buf, len); - } else - ret = -EINVAL; - - return ret; -} -EXPORT_SYMBOL(sdio_al_queue_transfer); - int sdio_al_queue_transfer_async(struct sdio_al_channel_handle *handle, enum sdio_al_dma_direction dir, void *buf, size_t len, int priority, void *ctxt) @@ -1046,13 +1016,68 @@ int sdio_al_queue_transfer_async(struct sdio_al_channel_handle *handle, rw_req->buf = buf; rw_req->len = len; rw_req->ctxt = ctxt; + + if (dir == SDIO_AL_RX) + spin_lock(&async_lock); + qcn_sdio_add_rw_req(rw_req); queue_work(sdio_ctxt->qcn_sdio_wq, &sdio_ctxt->sdio_rw_w); + if (dir == SDIO_AL_RX) + spin_unlock(&async_lock); + return 0; } EXPORT_SYMBOL(sdio_al_queue_transfer_async); +int sdio_al_queue_transfer(struct sdio_al_channel_handle *ch_handle, + enum sdio_al_dma_direction dir, + void *buf, size_t len, int priority) +{ + int ret = 0; + u32 cid = QCN_SDIO_CH_MAX; + + if (!ch_handle) { + pr_err("%s: SDIO: Invalid Param\n", __func__); + return -EINVAL; + } + + if (dir == SDIO_AL_RX && !list_empty(&sdio_ctxt->rw_wait_q) && + !atomic_read(&sdio_ctxt->wait_list_count)) { + sdio_al_queue_transfer_async(ch_handle, dir, buf, len, true, + (void *)(uintptr_t)len); + pr_info("%s: switching to async\n", __func__); + ret = 1; + } else { + cid = ch_handle->channel_id; + + if (!(cid < QCN_SDIO_CH_MAX)) + return -EINVAL; + + if (dir == SDIO_AL_RX) { + if (!atomic_read(&sdio_ctxt->wait_list_count)) + ret = qcn_sdio_recv_buff(cid, buf, len); + else { + sdio_al_queue_transfer_async(ch_handle, dir, + buf, len, true, (void *)(uintptr_t)len); + pr_info("%s switching to async\n", __func__); + ret = 1; + } + + if (rx_dump) + HEX_DUMP("SYNC_RECV: ", buf, len); + } else if (dir == SDIO_AL_TX) { + ret = qcn_sdio_send_buff(cid, buf, len); + if (tx_dump) + HEX_DUMP("SYNC_SEND: ", buf, len); + } else + ret = -EINVAL; + } + + return ret; +} +EXPORT_SYMBOL(sdio_al_queue_transfer); + int sdio_al_meta_transfer(struct sdio_al_channel_handle *handle, unsigned int data, unsigned int trans) { |
