summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAmandeep Singh <amansing@codeaurora.org>2019-08-06 15:24:57 +0530
committerAmandeep Singh <amansing@codeaurora.org>2019-09-03 11:35:06 +0530
commita419a64bc9bef3b7fe5c3201412e0b59ef69e5e6 (patch)
tree340404fffddd3ebd60649127fdaeae99ffa597cf
parent2ca7eb28dcac93fcf0818232e10fe51f43acfac1 (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.c64
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;