mmc: sdhci: delay the QoS vote removal

By delaying the QoS vote removal, there is some improvement
in performance in single threaded use cases.

Change-Id: I80545486057c55c697b72b56d57e2ea47cff86b9
Signed-off-by: Asutosh Das <asutoshd@codeaurora.org>
[xiaonian@codeaurora.org: fixed trivial merge conflict]
Signed-off-by: Xiaonian Wang <xiaonian@codeaurora.org>
diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
index 0a4bcce..1dba926 100644
--- a/drivers/mmc/host/sdhci-msm.c
+++ b/drivers/mmc/host/sdhci-msm.c
@@ -43,6 +43,7 @@
 #include "sdhci-msm.h"
 #include "cmdq_hci.h"
 
+#define QOS_REMOVE_DELAY_MS	10
 #define CORE_POWER		0x0
 #define CORE_SW_RST		(1 << 7)
 
@@ -3149,7 +3150,8 @@
 static void sdhci_msm_pm_qos_irq_unvote_work(struct work_struct *work)
 {
 	struct sdhci_msm_pm_qos_irq *pm_qos_irq =
-		container_of(work, struct sdhci_msm_pm_qos_irq, unvote_work);
+		container_of(work, struct sdhci_msm_pm_qos_irq,
+			     unvote_work.work);
 
 	if (atomic_read(&pm_qos_irq->counter))
 		return;
@@ -3175,7 +3177,7 @@
 		&& counter > 1)
 		return;
 
-	cancel_work_sync(&msm_host->pm_qos_irq.unvote_work);
+	cancel_delayed_work_sync(&msm_host->pm_qos_irq.unvote_work);
 	msm_host->pm_qos_irq.latency = latency->latency[host->power_policy];
 	pm_qos_update_request(&msm_host->pm_qos_irq.req,
 				msm_host->pm_qos_irq.latency);
@@ -3201,7 +3203,8 @@
 		return;
 
 	if (async) {
-		schedule_work(&msm_host->pm_qos_irq.unvote_work);
+		schedule_delayed_work(&msm_host->pm_qos_irq.unvote_work,
+				      msecs_to_jiffies(QOS_REMOVE_DELAY_MS));
 		return;
 	}
 
@@ -3256,7 +3259,7 @@
 
 	msm_host->pm_qos_irq.enabled = enable;
 	if (!enable) {
-		cancel_work_sync(&msm_host->pm_qos_irq.unvote_work);
+		cancel_delayed_work_sync(&msm_host->pm_qos_irq.unvote_work);
 		atomic_set(&msm_host->pm_qos_irq.counter, 0);
 		msm_host->pm_qos_irq.latency = PM_QOS_DEFAULT_VALUE;
 		pm_qos_update_request(&msm_host->pm_qos_irq.req,
@@ -3302,7 +3305,7 @@
 		cpumask_copy(&msm_host->pm_qos_irq.req.cpus_affine,
 			cpumask_of(msm_host->pdata->pm_qos_data.irq_cpu));
 
-	INIT_WORK(&msm_host->pm_qos_irq.unvote_work,
+	INIT_DELAYED_WORK(&msm_host->pm_qos_irq.unvote_work,
 		sdhci_msm_pm_qos_irq_unvote_work);
 	/* For initialization phase, set the performance latency */
 	irq_latency = &msm_host->pdata->pm_qos_data.irq_latency;
@@ -3396,7 +3399,8 @@
 	msm_host->pm_qos_group_enable = enable;
 	if (!enable) {
 		for (i = 0; i < nr_groups; i++) {
-			cancel_work_sync(&msm_host->pm_qos[i].unvote_work);
+			cancel_delayed_work_sync(
+				&msm_host->pm_qos[i].unvote_work);
 			atomic_set(&msm_host->pm_qos[i].counter, 0);
 			msm_host->pm_qos[i].latency = PM_QOS_DEFAULT_VALUE;
 			pm_qos_update_request(&msm_host->pm_qos[i].req,
@@ -3445,7 +3449,7 @@
 		&& counter > 1)
 		return;
 
-	cancel_work_sync(&pm_qos_group->unvote_work);
+	cancel_delayed_work_sync(&pm_qos_group->unvote_work);
 
 	pm_qos_group->latency = latency->latency[host->power_policy];
 	pm_qos_update_request(&pm_qos_group->req, pm_qos_group->latency);
@@ -3454,7 +3458,8 @@
 static void sdhci_msm_pm_qos_cpu_unvote_work(struct work_struct *work)
 {
 	struct sdhci_msm_pm_qos_group *group =
-		container_of(work, struct sdhci_msm_pm_qos_group, unvote_work);
+		container_of(work, struct sdhci_msm_pm_qos_group,
+			     unvote_work.work);
 
 	if (atomic_read(&group->counter))
 		return;
@@ -3474,7 +3479,8 @@
 		return false;
 
 	if (async) {
-		schedule_work(&msm_host->pm_qos[group].unvote_work);
+		schedule_delayed_work(&msm_host->pm_qos[group].unvote_work,
+				      msecs_to_jiffies(QOS_REMOVE_DELAY_MS));
 		return true;
 	}
 
@@ -3504,7 +3510,7 @@
 
 	for (i = 0; i < nr_groups; i++) {
 		group = &msm_host->pm_qos[i];
-		INIT_WORK(&group->unvote_work,
+		INIT_DELAYED_WORK(&group->unvote_work,
 			sdhci_msm_pm_qos_cpu_unvote_work);
 		atomic_set(&group->counter, 0);
 		group->req.type = PM_QOS_REQ_AFFINE_CORES;