diff mbox series

[4/5] mmc: core: Add support for graceful host removal for eMMC

Message ID 20250320140040.162416-5-ulf.hansson@linaro.org (mailing list archive)
State New
Headers show
Series mmc: core: Add support for graceful host removal for eMMC/SD | expand

Commit Message

Ulf Hansson March 20, 2025, 2 p.m. UTC
An mmc host driver may allow to unbind from its corresponding host device.
If an eMMC card is attached to the host, the mmc core will just try to cut
the power for it, without obeying to the eMMC spec.

Potentially this may damage the card and it may also prevent us from
successfully doing a re-initialization of it, which would typically happen
if/when we try to re-bind the mmc host driver.

To fix these problems, let's implement a graceful power-down of the card at
host removal.

Reported-by: Wolfram Sang <wsa+renesas@sang-engineering.com>
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
---
 drivers/mmc/core/mmc.c | 27 +++++++++++++++++----------
 1 file changed, 17 insertions(+), 10 deletions(-)

Comments

Avri Altman March 28, 2025, 8:13 a.m. UTC | #1
> +/*
> + * Host is being removed. Free up the current card and do a graceful power-
> off.
> + */
> +static void mmc_remove(struct mmc_host *host) {
> +	get_device(&host->card->dev);
> +	mmc_remove_card(host->card);
> +
> +	_mmc_suspend(host, MMC_POWEROFF_UNBIND);
Couldn't find how _mmc_suspend handles this new power off flag?

Thanks,
Avri

> +
> +	put_device(&host->card->dev);
> +	host->card = NULL;
> +}
> +
>  /*
>   * Suspend callback
>   */
> --
> 2.43.0
>
Ulf Hansson March 28, 2025, 10:21 a.m. UTC | #2
On Fri, 28 Mar 2025 at 09:13, Avri Altman <Avri.Altman@sandisk.com> wrote:
>
> > +/*
> > + * Host is being removed. Free up the current card and do a graceful power-
> > off.
> > + */
> > +static void mmc_remove(struct mmc_host *host) {
> > +     get_device(&host->card->dev);
> > +     mmc_remove_card(host->card);
> > +
> > +     _mmc_suspend(host, MMC_POWEROFF_UNBIND);
> Couldn't find how _mmc_suspend handles this new power off flag?

Right. You need to look closer at mmc_may_poweroff_notify() as it
should return false if MMC_POWEROFF_UNBIND, unless
MMC_CAP2_FULL_PWR_CYCLE.

[...]

Kind regards
Uffe
diff mbox series

Patch

diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
index 60af88ac0213..5a62a3d3df32 100644
--- a/drivers/mmc/core/mmc.c
+++ b/drivers/mmc/core/mmc.c
@@ -36,6 +36,7 @@ 
 enum mmc_poweroff_type {
 	MMC_POWEROFF_SUSPEND,
 	MMC_POWEROFF_SHUTDOWN,
+	MMC_POWEROFF_UNBIND,
 };
 
 static const unsigned int tran_exp[] = {
@@ -2054,15 +2055,6 @@  static int mmc_poweroff_notify(struct mmc_card *card, unsigned int notify_type)
 	return err;
 }
 
-/*
- * Host is being removed. Free up the current card.
- */
-static void mmc_remove(struct mmc_host *host)
-{
-	mmc_remove_card(host->card);
-	host->card = NULL;
-}
-
 /*
  * Card detection - card is alive.
  */
@@ -2088,7 +2080,8 @@  static void mmc_detect(struct mmc_host *host)
 	mmc_put_card(host->card, NULL);
 
 	if (err) {
-		mmc_remove(host);
+		mmc_remove_card(host->card);
+		host->card = NULL;
 
 		mmc_claim_host(host);
 		mmc_detach_bus(host);
@@ -2160,6 +2153,20 @@  static int _mmc_suspend(struct mmc_host *host, enum mmc_poweroff_type pm_type)
 	return err;
 }
 
+/*
+ * Host is being removed. Free up the current card and do a graceful power-off.
+ */
+static void mmc_remove(struct mmc_host *host)
+{
+	get_device(&host->card->dev);
+	mmc_remove_card(host->card);
+
+	_mmc_suspend(host, MMC_POWEROFF_UNBIND);
+
+	put_device(&host->card->dev);
+	host->card = NULL;
+}
+
 /*
  * Suspend callback
  */