diff options
| author | Amandeep Singh <amansing@codeaurora.org> | 2019-08-06 15:24:57 +0530 |
|---|---|---|
| committer | Amandeep Singh <amansing@codeaurora.org> | 2019-09-03 11:35:06 +0530 |
| commit | a419a64bc9bef3b7fe5c3201412e0b59ef69e5e6 (patch) | |
| tree | 340404fffddd3ebd60649127fdaeae99ffa597cf | |
| parent | 2ca7eb28dcac93fcf0818232e10fe51f43acfac1 (diff) | |
msm: qcn: Detect and switch host to RDDM
Switch driver operating mode to RDDM when target device switches to RDDM.
Change-Id: I501672f4965e57e59f5a272e35534e66c63b67c1
Signed-off-by: Amandeep Singh <amansing@codeaurora.org>
| -rw-r--r-- | drivers/platform/msm/qcn/qcn_sdio.c | 64 |
1 files changed, 50 insertions, 14 deletions
diff --git a/drivers/platform/msm/qcn/qcn_sdio.c b/drivers/platform/msm/qcn/qcn_sdio.c index 18bca8b2e13c..4b4caaebac76 100644 --- a/drivers/platform/msm/qcn/qcn_sdio.c +++ b/drivers/platform/msm/qcn/qcn_sdio.c @@ -22,6 +22,7 @@ #include <linux/mmc/sd.h> #include <linux/delay.h> #include <linux/platform_device.h> +#include <linux/kthread.h> #include "qcn_sdio.h" static bool tx_dump; @@ -65,7 +66,9 @@ struct completion client_probe_complete; static struct mutex lock; static struct list_head cinfo_head; static atomic_t status; +static atomic_t xport_status; static spinlock_t async_lock; +static struct task_struct *reset_task; static int qcn_create_sysfs(struct device *dev); @@ -133,6 +136,18 @@ static void qcn_sdio_free_rw_req(struct qcn_sdio_rw_info *rw_req) spin_unlock(&sdio_ctxt->lock_free_q); } +static void qcn_sdio_purge_rw_buff(void) +{ + struct qcn_sdio_rw_info *rw_req = NULL; + + while (!list_empty(&sdio_ctxt->rw_wait_q)) { + rw_req = list_first_entry(&sdio_ctxt->rw_wait_q, + struct qcn_sdio_rw_info, list); + list_del(&rw_req->list); + qcn_sdio_free_rw_req(rw_req); + } +} + void qcn_sdio_client_probe_complete(int id) { complete(&client_probe_complete); @@ -513,13 +528,35 @@ static int qcn_read_meta_info(void) return ret; } +static int reset_thread(void *data) +{ + qcn_sdio_purge_rw_buff(); + qcn_sdio_card_state(false); + qcn_sdio_card_state(true); + kthread_stop(reset_task); + reset_task = NULL; + + return 0; +} + static void qcn_sdio_irq_handler(struct sdio_func *func) { u8 data = 0; - + int ret = 0; sdio_claim_host(sdio_ctxt->func); - data = sdio_readb(sdio_ctxt->func, SDIO_QCN_IRQ_STATUS, NULL); + data = sdio_readb(sdio_ctxt->func, SDIO_QCN_IRQ_STATUS, &ret); + if (ret) { + sdio_release_host(sdio_ctxt->func); + + pr_err("%s: IRQ status read error ret = %d\n", __func__, ret); + + reset_task = kthread_run(reset_thread, NULL, "qcn_reset"); + if (IS_ERR(reset_task)) + pr_err("Failed to run qcn_reset thread\n"); + + return; + } sdio_release_host(sdio_ctxt->func); if (data & SDIO_QCN_IRQ_CRQ_READY_MASK) { @@ -591,18 +628,6 @@ static int qcn_sdio_recv_buff(u32 cid, void *buff, size_t len) return ret; } -static void qcn_sdio_purge_rw_buff(void) -{ - struct qcn_sdio_rw_info *rw_req = NULL; - - while (!list_empty(&sdio_ctxt->rw_wait_q)) { - rw_req = list_first_entry(&sdio_ctxt->rw_wait_q, - struct qcn_sdio_rw_info, list); - list_del(&rw_req->list); - qcn_sdio_free_rw_req(rw_req); - } -} - static void qcn_sdio_rw_work(struct work_struct *work) { int ret = 0; @@ -709,6 +734,7 @@ int qcn_sdio_probe(struct sdio_func *func, const struct sdio_device_id *id) current_host = func->card->host; + atomic_set(&xport_status, 1); return 0; err: kfree(sdio_ctxt); @@ -721,6 +747,7 @@ static void qcn_sdio_remove(struct sdio_func *func) struct qcn_sdio_client_info *cinfo = NULL; struct qcn_sdio_ch_info *ch_info = NULL; + atomic_set(&xport_status, 0); sdio_claim_host(sdio_ctxt->func); qcn_enable_async_irq(false); sdio_release_host(sdio_ctxt->func); @@ -1027,6 +1054,9 @@ int sdio_al_queue_transfer_async(struct sdio_al_channel_handle *handle, struct qcn_sdio_rw_info *rw_req = NULL; u32 cid = QCN_SDIO_CH_MAX; + if (!atomic_read(&xport_status)) + return -ENODEV; + if (!handle) { pr_err("%s: Error: Invalid Param\n", __func__); return -EINVAL; @@ -1071,6 +1101,9 @@ int sdio_al_queue_transfer(struct sdio_al_channel_handle *ch_handle, int ret = 0; u32 cid = QCN_SDIO_CH_MAX; + if (!atomic_read(&xport_status)) + return -ENODEV; + if (!ch_handle) { pr_err("%s: SDIO: Invalid Param\n", __func__); return -EINVAL; @@ -1118,6 +1151,9 @@ int sdio_al_meta_transfer(struct sdio_al_channel_handle *handle, u32 cid = QCN_SDIO_CH_MAX; u8 event = 0; + if (!atomic_read(&xport_status)) + return -ENODEV; + if (!handle) return -EINVAL; |
