Some MMC hosts implement a fine-grained runtime PM, whereby they
runtime-suspend and -resume the host interface on each transfer. This can
negatively affect performance, if the user was trying to transfer data
blocks back-to-back. This patch adds a PM QoS constraint to avoid such a
throughput reduction. This constraint prevents runtime-suspending the
device, if the expected wakeup latency is larger than 100us.

Signed-off-by: Guennadi Liakhovetski <g.liakhovet...@gmx.de>
---

This patch has been tested on SuperH and ARM sh-mobile hosts with 
sh_mobile_sdhi and sh_mmcif drivers. Would be good to also have it tested 
on other platforms, enabling PM QoS, e.g., those, using the simple QoS 
PM domain governor.

 drivers/mmc/core/core.c  |   16 +++++++++++++++-
 include/linux/mmc/host.h |    2 ++
 2 files changed, 17 insertions(+), 1 deletions(-)

diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index b27b940..40f666f 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -22,6 +22,7 @@
 #include <linux/scatterlist.h>
 #include <linux/log2.h>
 #include <linux/regulator/consumer.h>
+#include <linux/pm_domain.h>
 #include <linux/pm_runtime.h>
 #include <linux/suspend.h>
 
@@ -589,8 +590,16 @@ int __mmc_claim_host(struct mmc_host *host, atomic_t 
*abort)
                wake_up(&host->wq);
        spin_unlock_irqrestore(&host->lock, flags);
        remove_wait_queue(&host->wq, &wait);
-       if (!stop)
+       if (!stop) {
+               if (host->claim_cnt == 1) {
+                       int ret = dev_pm_qos_add_request(host->parent,
+                                                        &host->pm_qos, 100);
+                       if (ret < 0)
+                               dev_err(host->parent,
+                                       "PM QoS request failed: %d\n", ret);
+               }
                mmc_host_enable(host);
+       }
        return stop;
 }
 
@@ -615,6 +624,10 @@ int mmc_try_claim_host(struct mmc_host *host)
                claimed_host = 1;
        }
        spin_unlock_irqrestore(&host->lock, flags);
+
+       if (claimed_host && host->claim_cnt == 1)
+               dev_pm_qos_add_request(host->parent, &host->pm_qos, 100);
+
        return claimed_host;
 }
 EXPORT_SYMBOL(mmc_try_claim_host);
@@ -639,6 +652,7 @@ void mmc_do_release_host(struct mmc_host *host)
                host->claimer = NULL;
                spin_unlock_irqrestore(&host->lock, flags);
                wake_up(&host->wq);
+               dev_pm_qos_remove_request(&host->pm_qos);
        }
 }
 EXPORT_SYMBOL(mmc_do_release_host);
diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h
index 1d09562..3e9d2f3 100644
--- a/include/linux/mmc/host.h
+++ b/include/linux/mmc/host.h
@@ -11,6 +11,7 @@
 #define LINUX_MMC_HOST_H
 
 #include <linux/leds.h>
+#include <linux/pm_qos.h>
 #include <linux/sched.h>
 
 #include <linux/mmc/core.h>
@@ -175,6 +176,7 @@ struct mmc_host {
        u32                     ocr_avail_sd;   /* SD-specific OCR */
        u32                     ocr_avail_mmc;  /* MMC-specific OCR */
        struct notifier_block   pm_notify;
+       struct dev_pm_qos_request pm_qos;
 
 #define MMC_VDD_165_195                0x00000080      /* VDD voltage 1.65 - 
1.95 */
 #define MMC_VDD_20_21          0x00000100      /* VDD voltage 2.0 ~ 2.1 */
-- 
1.7.2.5

--
To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to