From 23ddb3ee2d6cf4bdbca5fcdb69c334f95e157edb Mon Sep 17 00:00:00 2001 From: Amandeep Singh Date: Mon, 24 Jun 2019 14:51:08 +0530 Subject: [PATCH] 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 --- drivers/platform/msm/qcn/qcn_sdio.c | 89 ++++++++++++++++++----------- 1 file 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) {