mmc: cmdq: trigger get queue status after dcmd

CMDQ spec defines periodic SEND_STATUS mechanism to poll
on READY tasks in the device. When DAT lines are in IDLE
the counter counts from its reset value to '0' and then
triggers SEND_STATUS command. When CMD13 is completed and
also the syncing of the device status to HCLK domain is done
there is a 1 cycle pulse to reload the counter with timer
reset value so that the counting can start over.

In rare cases, when the 'done' pulse for reloading the
counter happens in parallel to a BUSY state of direct
command - the IDLE counter is not reloaded and can't
trigger another CMD13. If this scenario happens when
there are pending tasks which are not 'READY' yet  - it
can lead to a deadlock, since there is no other mechainsm to
send CMD13, and CQE will never get READY on the pending tasks.

Hence, trigger a send status command after DCMD is completed
as a work-around to the above issue.

Change-Id: I4e8530e72c8bf581ffaeed7d35d8b8c61d282ffa
Signed-off-by: Asutosh Das <asutoshd@codeaurora.org>
diff --git a/drivers/mmc/host/cmdq_hci.c b/drivers/mmc/host/cmdq_hci.c
index 66979c2..cbc0e57 100644
--- a/drivers/mmc/host/cmdq_hci.c
+++ b/drivers/mmc/host/cmdq_hci.c
@@ -185,6 +185,8 @@
 	pr_err(DRV_NAME ": Resp idx 0x%08x	  | Resp arg:  0x%08x\n",
 		cmdq_readl(cq_host, CQCRI),
 		cmdq_readl(cq_host, CQCRA));
+	pr_err(DRV_NAME": Vendor cfg 0x%08x\n",
+	       cmdq_readl(cq_host, CQ_VENDOR_CFG));
 	pr_err(DRV_NAME ": ===========================================\n");
 
 	cmdq_dump_debug_ram(cq_host);
@@ -630,6 +632,9 @@
 	if (tag == cq_host->dcmd_slot)
 		mrq->cmd->resp[0] = cmdq_readl(cq_host, CQCRDCT);
 
+	if (mrq->cmdq_req->cmdq_req_flags & DCMD)
+		cmdq_writel(cq_host, cmdq_readl(cq_host, CQ_VENDOR_CFG) |
+			    CMDQ_SEND_STATUS_TRIGGER, CQCTL);
 	mrq->done(mrq);
 }
 
diff --git a/drivers/mmc/host/cmdq_hci.h b/drivers/mmc/host/cmdq_hci.h
index 9d4505c..fd52d1c 100644
--- a/drivers/mmc/host/cmdq_hci.h
+++ b/drivers/mmc/host/cmdq_hci.h
@@ -146,6 +146,9 @@
 #define DAT_ADDR_LO(x)	((x & 0xFFFFFFFF) << 32)
 #define DAT_ADDR_HI(x)	((x & 0xFFFFFFFF) << 0)
 
+#define CQ_VENDOR_CFG	0x100
+#define CMDQ_SEND_STATUS_TRIGGER (1 << 31)
+
 struct cmdq_host {
 	const struct cmdq_host_ops *ops;
 	void __iomem *mmio;