Skip to content

Commit aa86f1a

Browse files
committed
mmc: tmio: Fixup runtime PM management during probe
The tmio_mmc_host_probe() calls pm_runtime_set_active() to update the runtime PM status of the device, as to make it reflect the current status of the HW. This works fine for most cases, but unfortunate not for all. Especially, there is a generic problem when the device has a genpd attached and that genpd have the ->start|stop() callbacks assigned. More precisely, if the driver calls pm_runtime_set_active() during ->probe(), genpd does not get to invoke the ->start() callback for it, which means the HW isn't really fully powered on. Furthermore, in the next phase, when the device becomes runtime suspended, genpd will invoke the ->stop() callback for it, potentially leading to usage count imbalance problems, depending on what's implemented behind the callbacks of course. To fix this problem, convert to call pm_runtime_get_sync() from tmio_mmc_host_probe() rather than pm_runtime_set_active(). Additionally, to avoid bumping usage counters and unnecessary re-initializing the HW the first time the tmio driver's ->runtime_resume() callback is called, introduce a state flag to keeping track of this. Cc: [email protected] Signed-off-by: Ulf Hansson <[email protected]> Tested-by: Geert Uytterhoeven <[email protected]>
1 parent 8861474 commit aa86f1a

File tree

2 files changed

+9
-1
lines changed

2 files changed

+9
-1
lines changed

drivers/mmc/host/tmio_mmc.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,7 @@ struct tmio_mmc_host {
163163
unsigned long last_req_ts;
164164
struct mutex ios_lock; /* protect set_ios() context */
165165
bool native_hotplug;
166+
bool runtime_synced;
166167
bool sdio_irq_enabled;
167168

168169
/* Mandatory callback */

drivers/mmc/host/tmio_mmc_core.c

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1248,20 +1248,22 @@ int tmio_mmc_host_probe(struct tmio_mmc_host *_host)
12481248
/* See if we also get DMA */
12491249
tmio_mmc_request_dma(_host, pdata);
12501250

1251-
pm_runtime_set_active(&pdev->dev);
12521251
pm_runtime_set_autosuspend_delay(&pdev->dev, 50);
12531252
pm_runtime_use_autosuspend(&pdev->dev);
12541253
pm_runtime_enable(&pdev->dev);
1254+
pm_runtime_get_sync(&pdev->dev);
12551255

12561256
ret = mmc_add_host(mmc);
12571257
if (ret)
12581258
goto remove_host;
12591259

12601260
dev_pm_qos_expose_latency_limit(&pdev->dev, 100);
1261+
pm_runtime_put(&pdev->dev);
12611262

12621263
return 0;
12631264

12641265
remove_host:
1266+
pm_runtime_put_noidle(&pdev->dev);
12651267
tmio_mmc_host_remove(_host);
12661268
return ret;
12671269
}
@@ -1330,6 +1332,11 @@ int tmio_mmc_host_runtime_resume(struct device *dev)
13301332
{
13311333
struct tmio_mmc_host *host = dev_get_drvdata(dev);
13321334

1335+
if (!host->runtime_synced) {
1336+
host->runtime_synced = true;
1337+
return 0;
1338+
}
1339+
13331340
tmio_mmc_clk_enable(host);
13341341
tmio_mmc_hw_reset(host->mmc);
13351342

0 commit comments

Comments
 (0)