From aea64b583601aa5e0d6ea51a0420e46e43710bd4 Mon Sep 17 00:00:00 2001 From: Stefan Wahren Date: Sun, 8 Sep 2019 09:45:52 +0200 Subject: Revert "mmc: bcm2835: Terminate timeout work synchronously" The commit 37fefadee8bb ("mmc: bcm2835: Terminate timeout work synchronously") causes lockups in case of hardware timeouts due the timeout work also calling cancel_delayed_work_sync() on its own. So revert it. Fixes: 37fefadee8bb ("mmc: bcm2835: Terminate timeout work synchronously") Cc: stable@vger.kernel.org Signed-off-by: Stefan Wahren Signed-off-by: Ulf Hansson --- drivers/mmc/host/bcm2835.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mmc/host/bcm2835.c b/drivers/mmc/host/bcm2835.c index 7e0d3a49c06d..bb31e13648d6 100644 --- a/drivers/mmc/host/bcm2835.c +++ b/drivers/mmc/host/bcm2835.c @@ -597,7 +597,7 @@ static void bcm2835_finish_request(struct bcm2835_host *host) struct dma_chan *terminate_chan = NULL; struct mmc_request *mrq; - cancel_delayed_work_sync(&host->timeout_work); + cancel_delayed_work(&host->timeout_work); mrq = host->mrq; -- cgit v1.2.3-58-ga151 From 49baa01c8b99ef92958e18fb58ebeb5dfdcde8af Mon Sep 17 00:00:00 2001 From: Daniel Drake Date: Thu, 5 Sep 2019 12:55:57 +0800 Subject: Revert "mmc: sdhci: Remove unneeded quirk2 flag of O2 SD host controller" This reverts commit 414126f9e5abf1973c661d24229543a9458fa8ce. This commit broke eMMC storage access on a new consumer MiniPC based on AMD SoC, which has eMMC connected to: 02:00.0 SD Host controller: O2 Micro, Inc. Device 8620 (rev 01) (prog-if 01) Subsystem: O2 Micro, Inc. Device 0002 During probe, several errors are seen including: mmc1: Got data interrupt 0x02000000 even though no data operation was in progress. mmc1: Timeout waiting for hardware interrupt. mmc1: error -110 whilst initialising MMC card Reverting this commit allows the eMMC storage to be detected & usable again. Signed-off-by: Daniel Drake Fixes: 414126f9e5ab ("mmc: sdhci: Remove unneeded quirk2 flag of O2 SD host controller") Cc: stable@vger.kernel.org # v5.1+ Signed-off-by: Ulf Hansson --- drivers/mmc/host/sdhci-pci-o2micro.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mmc/host/sdhci-pci-o2micro.c b/drivers/mmc/host/sdhci-pci-o2micro.c index 9dc4548271b4..19944b0049db 100644 --- a/drivers/mmc/host/sdhci-pci-o2micro.c +++ b/drivers/mmc/host/sdhci-pci-o2micro.c @@ -432,7 +432,6 @@ int sdhci_pci_o2_probe_slot(struct sdhci_pci_slot *slot) mmc_hostname(host->mmc)); host->flags &= ~SDHCI_SIGNALING_330; host->flags |= SDHCI_SIGNALING_180; - host->quirks2 |= SDHCI_QUIRK2_CLEAR_TRANSFERMODE_REG_BEFORE_CMD; host->mmc->caps2 |= MMC_CAP2_NO_SD; host->mmc->caps2 |= MMC_CAP2_NO_SDIO; pci_write_config_dword(chip->pdev, @@ -682,6 +681,7 @@ static const struct sdhci_ops sdhci_pci_o2_ops = { const struct sdhci_pci_fixes sdhci_o2 = { .probe = sdhci_pci_o2_probe, .quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC, + .quirks2 = SDHCI_QUIRK2_CLEAR_TRANSFERMODE_REG_BEFORE_CMD, .probe_slot = sdhci_pci_o2_probe_slot, #ifdef CONFIG_PM_SLEEP .resume = sdhci_pci_o2_resume, -- cgit v1.2.3-58-ga151 From 8861474a105c91e812d38cd65d3be795c7f32c4f Mon Sep 17 00:00:00 2001 From: Ulf Hansson Date: Fri, 13 Sep 2019 10:03:15 +0200 Subject: Revert "mmc: tmio: move runtime PM enablement to the driver implementations" This reverts commit 7ff213193310ef8d0ee5f04f79d791210787ac2c. It turns out that the above commit introduces other problems. For example, calling pm_runtime_set_active() must not be done prior calling pm_runtime_enable() as that makes it fail. This leads to additional problems, such as clock enables being wrongly balanced. Rather than fixing the problem on top, let's start over by doing a revert. Fixes: 7ff213193310 ("mmc: tmio: move runtime PM enablement to the driver implementations") Signed-off-by: Ulf Hansson Tested-by: Geert Uytterhoeven --- drivers/mmc/host/renesas_sdhi_core.c | 6 ------ drivers/mmc/host/tmio_mmc.c | 5 ----- drivers/mmc/host/tmio_mmc_core.c | 11 ++--------- drivers/mmc/host/uniphier-sd.c | 3 --- 4 files changed, 2 insertions(+), 23 deletions(-) diff --git a/drivers/mmc/host/renesas_sdhi_core.c b/drivers/mmc/host/renesas_sdhi_core.c index 64d3b5fb7fe5..4a2872f49a60 100644 --- a/drivers/mmc/host/renesas_sdhi_core.c +++ b/drivers/mmc/host/renesas_sdhi_core.c @@ -774,8 +774,6 @@ int renesas_sdhi_probe(struct platform_device *pdev, /* All SDHI have SDIO status bits which must be 1 */ mmc_data->flags |= TMIO_MMC_SDIO_STATUS_SETBITS; - pm_runtime_enable(&pdev->dev); - ret = renesas_sdhi_clk_enable(host); if (ret) goto efree; @@ -856,8 +854,6 @@ edisclk: efree: tmio_mmc_host_free(host); - pm_runtime_disable(&pdev->dev); - return ret; } EXPORT_SYMBOL_GPL(renesas_sdhi_probe); @@ -869,8 +865,6 @@ int renesas_sdhi_remove(struct platform_device *pdev) tmio_mmc_host_remove(host); renesas_sdhi_clk_disable(host); - pm_runtime_disable(&pdev->dev); - return 0; } EXPORT_SYMBOL_GPL(renesas_sdhi_remove); diff --git a/drivers/mmc/host/tmio_mmc.c b/drivers/mmc/host/tmio_mmc.c index 8539e10784b4..93e83ad25976 100644 --- a/drivers/mmc/host/tmio_mmc.c +++ b/drivers/mmc/host/tmio_mmc.c @@ -172,8 +172,6 @@ static int tmio_mmc_probe(struct platform_device *pdev) host->mmc->f_max = pdata->hclk; host->mmc->f_min = pdata->hclk / 512; - pm_runtime_enable(&pdev->dev); - ret = tmio_mmc_host_probe(host); if (ret) goto host_free; @@ -193,7 +191,6 @@ host_remove: tmio_mmc_host_remove(host); host_free: tmio_mmc_host_free(host); - pm_runtime_disable(&pdev->dev); cell_disable: if (cell->disable) cell->disable(pdev); @@ -210,8 +207,6 @@ static int tmio_mmc_remove(struct platform_device *pdev) if (cell->disable) cell->disable(pdev); - pm_runtime_disable(&pdev->dev); - return 0; } diff --git a/drivers/mmc/host/tmio_mmc_core.c b/drivers/mmc/host/tmio_mmc_core.c index 2cb3f951c3e2..8b299c1f0069 100644 --- a/drivers/mmc/host/tmio_mmc_core.c +++ b/drivers/mmc/host/tmio_mmc_core.c @@ -1153,15 +1153,6 @@ void tmio_mmc_host_free(struct tmio_mmc_host *host) } EXPORT_SYMBOL_GPL(tmio_mmc_host_free); -/** - * tmio_mmc_host_probe() - Common probe for all implementations - * @_host: Host to probe - * - * Perform tasks common to all implementations probe functions. - * - * The caller should have called pm_runtime_enable() prior to calling - * the common probe function. - */ int tmio_mmc_host_probe(struct tmio_mmc_host *_host) { struct platform_device *pdev = _host->pdev; @@ -1260,6 +1251,7 @@ int tmio_mmc_host_probe(struct tmio_mmc_host *_host) pm_runtime_set_active(&pdev->dev); pm_runtime_set_autosuspend_delay(&pdev->dev, 50); pm_runtime_use_autosuspend(&pdev->dev); + pm_runtime_enable(&pdev->dev); ret = mmc_add_host(mmc); if (ret) @@ -1295,6 +1287,7 @@ void tmio_mmc_host_remove(struct tmio_mmc_host *host) pm_runtime_dont_use_autosuspend(&pdev->dev); pm_runtime_put_sync(&pdev->dev); + pm_runtime_disable(&pdev->dev); } EXPORT_SYMBOL_GPL(tmio_mmc_host_remove); diff --git a/drivers/mmc/host/uniphier-sd.c b/drivers/mmc/host/uniphier-sd.c index 49aad9a79c18..91a2be41edf6 100644 --- a/drivers/mmc/host/uniphier-sd.c +++ b/drivers/mmc/host/uniphier-sd.c @@ -631,7 +631,6 @@ static int uniphier_sd_probe(struct platform_device *pdev) host->clk_disable = uniphier_sd_clk_disable; host->set_clock = uniphier_sd_set_clock; - pm_runtime_enable(&pdev->dev); ret = uniphier_sd_clk_enable(host); if (ret) goto free_host; @@ -653,7 +652,6 @@ static int uniphier_sd_probe(struct platform_device *pdev) free_host: tmio_mmc_host_free(host); - pm_runtime_disable(&pdev->dev); return ret; } @@ -664,7 +662,6 @@ static int uniphier_sd_remove(struct platform_device *pdev) tmio_mmc_host_remove(host); uniphier_sd_clk_disable(host); - pm_runtime_disable(&pdev->dev); return 0; } -- cgit v1.2.3-58-ga151 From aa86f1a3887523d78bfadd1c4e4df8f919336511 Mon Sep 17 00:00:00 2001 From: Ulf Hansson Date: Fri, 13 Sep 2019 11:19:26 +0200 Subject: 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: stable@vger.kernel.org Signed-off-by: Ulf Hansson Tested-by: Geert Uytterhoeven --- drivers/mmc/host/tmio_mmc.h | 1 + drivers/mmc/host/tmio_mmc_core.c | 9 ++++++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/drivers/mmc/host/tmio_mmc.h b/drivers/mmc/host/tmio_mmc.h index c5ba13fae399..2f0b092d6dcc 100644 --- a/drivers/mmc/host/tmio_mmc.h +++ b/drivers/mmc/host/tmio_mmc.h @@ -163,6 +163,7 @@ struct tmio_mmc_host { unsigned long last_req_ts; struct mutex ios_lock; /* protect set_ios() context */ bool native_hotplug; + bool runtime_synced; bool sdio_irq_enabled; /* Mandatory callback */ diff --git a/drivers/mmc/host/tmio_mmc_core.c b/drivers/mmc/host/tmio_mmc_core.c index 8b299c1f0069..32f9679ec42e 100644 --- a/drivers/mmc/host/tmio_mmc_core.c +++ b/drivers/mmc/host/tmio_mmc_core.c @@ -1248,20 +1248,22 @@ int tmio_mmc_host_probe(struct tmio_mmc_host *_host) /* See if we also get DMA */ tmio_mmc_request_dma(_host, pdata); - pm_runtime_set_active(&pdev->dev); pm_runtime_set_autosuspend_delay(&pdev->dev, 50); pm_runtime_use_autosuspend(&pdev->dev); pm_runtime_enable(&pdev->dev); + pm_runtime_get_sync(&pdev->dev); ret = mmc_add_host(mmc); if (ret) goto remove_host; dev_pm_qos_expose_latency_limit(&pdev->dev, 100); + pm_runtime_put(&pdev->dev); return 0; remove_host: + pm_runtime_put_noidle(&pdev->dev); tmio_mmc_host_remove(_host); return ret; } @@ -1330,6 +1332,11 @@ int tmio_mmc_host_runtime_resume(struct device *dev) { struct tmio_mmc_host *host = dev_get_drvdata(dev); + if (!host->runtime_synced) { + host->runtime_synced = true; + return 0; + } + tmio_mmc_clk_enable(host); tmio_mmc_hw_reset(host->mmc); -- cgit v1.2.3-58-ga151 From 87b5d602a1cc76169b8d81ec2c74c8d95d9350dc Mon Sep 17 00:00:00 2001 From: Ulf Hansson Date: Fri, 13 Sep 2019 11:20:22 +0200 Subject: mmc: tmio: Fixup runtime PM management during remove Accessing the device when it may be runtime suspended is a bug, which is the case in tmio_mmc_host_remove(). Let's fix the behaviour. Cc: stable@vger.kernel.org Signed-off-by: Ulf Hansson Tested-by: Geert Uytterhoeven --- drivers/mmc/host/tmio_mmc_core.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/mmc/host/tmio_mmc_core.c b/drivers/mmc/host/tmio_mmc_core.c index 32f9679ec42e..9b6e1001e77c 100644 --- a/drivers/mmc/host/tmio_mmc_core.c +++ b/drivers/mmc/host/tmio_mmc_core.c @@ -1274,12 +1274,11 @@ void tmio_mmc_host_remove(struct tmio_mmc_host *host) struct platform_device *pdev = host->pdev; struct mmc_host *mmc = host->mmc; + pm_runtime_get_sync(&pdev->dev); + if (host->pdata->flags & TMIO_MMC_SDIO_IRQ) sd_ctrl_write16(host, CTL_TRANSACTION_CTL, 0x0000); - if (!host->native_hotplug) - pm_runtime_get_sync(&pdev->dev); - dev_pm_qos_hide_latency_limit(&pdev->dev); mmc_remove_host(mmc); @@ -1288,6 +1287,8 @@ void tmio_mmc_host_remove(struct tmio_mmc_host *host) tmio_mmc_release_dma(host); pm_runtime_dont_use_autosuspend(&pdev->dev); + if (host->native_hotplug) + pm_runtime_put_noidle(&pdev->dev); pm_runtime_put_sync(&pdev->dev); pm_runtime_disable(&pdev->dev); } -- cgit v1.2.3-58-ga151