[PATCH 5.4 33/47] mmc: core: Disable card detect during shutdown

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Ulf Hansson <ulf.hansson@xxxxxxxxxx>

commit 66c915d09b942fb3b2b0cb2f56562180901fba17 upstream.

It's seems prone to problems by allowing card detect and its corresponding
mmc_rescan() work to run, during platform shutdown. For example, we may end
up turning off the power while initializing a card, which potentially could
damage it.

To avoid this scenario, let's add ->shutdown_pre() callback for the mmc host
class device and then turn of the card detect from there.

Reported-by: Al Cooper <alcooperx@xxxxxxxxx>
Suggested-by: Adrian Hunter <adrian.hunter@xxxxxxxxx>
Signed-off-by: Ulf Hansson <ulf.hansson@xxxxxxxxxx>
Cc: stable@xxxxxxxxxxxxxxx
Link: https://lore.kernel.org/r/20211203141555.105351-1-ulf.hansson@xxxxxxxxxx
Signed-off-by: Greg Kroah-Hartman <gregkh@xxxxxxxxxxxxxxxxxxx>
---
 drivers/mmc/core/core.c |    7 ++++++-
 drivers/mmc/core/core.h |    1 +
 drivers/mmc/core/host.c |    9 +++++++++
 3 files changed, 16 insertions(+), 1 deletion(-)

--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -2364,7 +2364,7 @@ void mmc_start_host(struct mmc_host *hos
 	_mmc_detect_change(host, 0, false);
 }
 
-void mmc_stop_host(struct mmc_host *host)
+void __mmc_stop_host(struct mmc_host *host)
 {
 	if (host->slot.cd_irq >= 0) {
 		mmc_gpio_set_cd_wake(host, false);
@@ -2373,6 +2373,11 @@ void mmc_stop_host(struct mmc_host *host
 
 	host->rescan_disable = 1;
 	cancel_delayed_work_sync(&host->detect);
+}
+
+void mmc_stop_host(struct mmc_host *host)
+{
+	__mmc_stop_host(host);
 
 	/* clear pm flags now and let card drivers set them as needed */
 	host->pm_flags = 0;
--- a/drivers/mmc/core/core.h
+++ b/drivers/mmc/core/core.h
@@ -69,6 +69,7 @@ static inline void mmc_delay(unsigned in
 
 void mmc_rescan(struct work_struct *work);
 void mmc_start_host(struct mmc_host *host);
+void __mmc_stop_host(struct mmc_host *host);
 void mmc_stop_host(struct mmc_host *host);
 
 void _mmc_detect_change(struct mmc_host *host, unsigned long delay,
--- a/drivers/mmc/core/host.c
+++ b/drivers/mmc/core/host.c
@@ -76,9 +76,18 @@ static void mmc_host_classdev_release(st
 	kfree(host);
 }
 
+static int mmc_host_classdev_shutdown(struct device *dev)
+{
+	struct mmc_host *host = cls_dev_to_mmc_host(dev);
+
+	__mmc_stop_host(host);
+	return 0;
+}
+
 static struct class mmc_host_class = {
 	.name		= "mmc_host",
 	.dev_release	= mmc_host_classdev_release,
+	.shutdown_pre	= mmc_host_classdev_shutdown,
 	.pm		= MMC_HOST_CLASS_DEV_PM_OPS,
 };
 





[Index of Archives]     [Linux Kernel]     [Kernel Development Newbies]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite Hiking]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux