Thread (6 messages) 6 messages, 5 authors, 2025-02-18

RE: [PATCH] mmc: sdhci-esdhc-imx: improve imx8mq emmc/sd read performance

From: Bough Chen <haibo.chen@nxp.com>
Date: 2025-02-17 11:52:33
Also in: imx, linux-mmc, lkml

-----Original Message-----
From: Luke Wang <redacted>
Sent: 2025年2月17日 19:06
To: adrian.hunter@intel.com; ulf.hansson@linaro.org
Cc: Bough Chen <haibo.chen@nxp.com>; shawnguo@kernel.org;
s.hauer@pengutronix.de; kernel@pengutronix.de; festevam@gmail.com;
imx@lists.linux.dev; linux-mmc@vger.kernel.org; dl-S32 [off-list ref];
linux-arm-kernel@lists.infradead.org; linux-kernel@vger.kernel.org
Subject: [PATCH] mmc: sdhci-esdhc-imx: improve imx8mq emmc/sd read
performance

From: Luke Wang <redacted>

Compared with kernel 6.1, imx8mq eMMC/SD read performance drops by about
30% with kernel 6.6.

The eMMC/SD read thread will be put to sleep until the hardware completes
data transfer. Normally, the read thread will be woken up immediately when the
data transfer is completed. However, due to a known ic bug, if imx8mq is in
cpuidle, it will take a long time (about 500us) to exit cpuidle. As a result, the
read thread cannot immediately read the next data block, affecting the read
performance.

Kernel 6.6 uses EEVDF as the new scheduler, which affects cpu scheduling and
cpuidle behavior. With kernel 6.6, the cpu which the read thread resides has a
greater probability in cpuidle (about 80%), while with kernel 6.1, the probability
is only about 20-30%. For other platforms, this does not have a significant impact
on read performance because the cpuidle exit time is very short (for example,
imx93 is about 60us). But for imx8mq, this results in longer waits for the thread
to be woken up while reading eMMC/SD, which drops performance.

So for imx8mq, use the ESDHC_FLAG_PMQOS flag to request the cpu latency
QoS constraint. This can prevent entering cpuidle during data transfer.
Reviewed-by: Haibo Chen <haibo.chen@nxp.com>

Regards
Haibo Chen
quoted hunk ↗ jump to hunk
Signed-off-by: Luke Wang <redacted>
---
 drivers/mmc/host/sdhci-esdhc-imx.c | 10 ++++++++++
 1 file changed, 10 insertions(+)
diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c
b/drivers/mmc/host/sdhci-esdhc-imx.c
index ff78a7c6a04c..b3bf9c171d46 100644
--- a/drivers/mmc/host/sdhci-esdhc-imx.c
+++ b/drivers/mmc/host/sdhci-esdhc-imx.c
@@ -337,6 +337,15 @@ static struct esdhc_soc_data usdhc_imx8mm_data = {
 	.quirks = SDHCI_QUIRK_NO_LED,
 };

+static struct esdhc_soc_data usdhc_imx8mq_data = {
+	.flags = ESDHC_FLAG_USDHC | ESDHC_FLAG_STD_TUNING
+			| ESDHC_FLAG_HAVE_CAP1 | ESDHC_FLAG_HS200
+			| ESDHC_FLAG_HS400 | ESDHC_FLAG_PMQOS
+			| ESDHC_FLAG_STATE_LOST_IN_LPMODE
+			| ESDHC_FLAG_BROKEN_AUTO_CMD23,
+	.quirks = SDHCI_QUIRK_NO_LED,
+};
+
 struct pltfm_imx_data {
 	u32 scratchpad;
 	struct pinctrl *pinctrl;
@@ -381,6 +390,7 @@ static const struct of_device_id imx_esdhc_dt_ids[] = {
 	{ .compatible = "fsl,imx7ulp-usdhc", .data = &usdhc_imx7ulp_data, },
 	{ .compatible = "fsl,imx8qxp-usdhc", .data = &usdhc_imx8qxp_data, },
 	{ .compatible = "fsl,imx8mm-usdhc", .data = &usdhc_imx8mm_data, },
+	{ .compatible = "fsl,imx8mq-usdhc", .data = &usdhc_imx8mq_data, },
 	{ .compatible = "fsl,imxrt1050-usdhc", .data = &usdhc_imxrt1050_data, },
 	{ .compatible = "nxp,s32g2-usdhc", .data = &usdhc_s32g2_data, },
 	{ /* sentinel */ }
--
2.34.1
  
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help