Commit bd68e0838fe85794b06892054772fa013a8d1986

Authored by Ben Hutchings
Committed by Linus Torvalds
1 parent c78402e95d

mmc: add module parameter to set whether cards are assumed removable

Some people run general-purpose distribution kernels on netbooks with
a card that is physically non-removable or logically non-removable
(e.g. used for /home) and cannot be cleanly unmounted during suspend.
Add a module parameter to set whether cards are assumed removable or
non-removable, with the default set by CONFIG_MMC_UNSAFE_RESUME.

In general, it is not possible to tell whether a card present in an MMC
slot after resume is the same that was there before suspend.  So there are
two possible behaviours, each of which will cause data loss in some cases:

CONFIG_MMC_UNSAFE_RESUME=n (default): Cards are assumed to be removed
during suspend.  Any filesystem on them must be unmounted before suspend;
otherwise, buffered writes will be lost.

CONFIG_MMC_UNSAFE_RESUME=y: Cards are assumed to remain present during
suspend.  They must not be swapped during suspend; otherwise, buffered
writes will be flushed to the wrong card.

Currently the choice is made at compile time and this allows that to be
overridden at module load time.

Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
Cc: Wouter van Heyst <larstiq@larstiq.dyndns.org>
Cc: <linux-mmc@vger.kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

Showing 5 changed files with 23 additions and 43 deletions Side-by-side Diff

drivers/mmc/core/Kconfig
... ... @@ -3,7 +3,7 @@
3 3 #
4 4  
5 5 config MMC_UNSAFE_RESUME
6   - bool "Allow unsafe resume (DANGEROUS)"
  6 + bool "Assume MMC/SD cards are non-removable (DANGEROUS)"
7 7 help
8 8 If you say Y here, the MMC layer will assume that all cards
9 9 stayed in their respective slots during the suspend. The
... ... @@ -13,4 +13,7 @@
13 13  
14 14 This option is usually just for embedded systems which use
15 15 a MMC/SD card for rootfs. Most people should say N here.
  16 +
  17 + This option sets a default which can be overridden by the
  18 + module parameter "removable=0" or "removable=1".
drivers/mmc/core/core.c
... ... @@ -48,6 +48,22 @@
48 48 module_param(use_spi_crc, bool, 0);
49 49  
50 50 /*
  51 + * We normally treat cards as removed during suspend if they are not
  52 + * known to be on a non-removable bus, to avoid the risk of writing
  53 + * back data to a different card after resume. Allow this to be
  54 + * overridden if necessary.
  55 + */
  56 +#ifdef CONFIG_MMC_UNSAFE_RESUME
  57 +int mmc_assume_removable;
  58 +#else
  59 +int mmc_assume_removable = 1;
  60 +#endif
  61 +module_param_named(removable, mmc_assume_removable, bool, 0644);
  62 +MODULE_PARM_DESC(
  63 + removable,
  64 + "MMC/SD cards are removable and may be removed during suspend");
  65 +
  66 +/*
51 67 * Internal function. Schedule delayed work in the MMC work queue.
52 68 */
53 69 static int mmc_schedule_delayed_work(struct delayed_work *work,
drivers/mmc/core/core.h
... ... @@ -54,7 +54,9 @@
54 54 int mmc_attach_sd(struct mmc_host *host, u32 ocr);
55 55 int mmc_attach_sdio(struct mmc_host *host, u32 ocr);
56 56  
  57 +/* Module parameters */
57 58 extern int use_spi_crc;
  59 +extern int mmc_assume_removable;
58 60  
59 61 /* Debugfs information for hosts and cards */
60 62 void mmc_add_host_debugfs(struct mmc_host *host);
drivers/mmc/core/mmc.c
... ... @@ -602,30 +602,11 @@
602 602 return err;
603 603 }
604 604  
605   -#ifdef CONFIG_MMC_UNSAFE_RESUME
606   -
607 605 static const struct mmc_bus_ops mmc_ops = {
608 606 .awake = mmc_awake,
609 607 .sleep = mmc_sleep,
610 608 .remove = mmc_remove,
611 609 .detect = mmc_detect,
612   - .suspend = mmc_suspend,
613   - .resume = mmc_resume,
614   - .power_restore = mmc_power_restore,
615   -};
616   -
617   -static void mmc_attach_bus_ops(struct mmc_host *host)
618   -{
619   - mmc_attach_bus(host, &mmc_ops);
620   -}
621   -
622   -#else
623   -
624   -static const struct mmc_bus_ops mmc_ops = {
625   - .awake = mmc_awake,
626   - .sleep = mmc_sleep,
627   - .remove = mmc_remove,
628   - .detect = mmc_detect,
629 610 .suspend = NULL,
630 611 .resume = NULL,
631 612 .power_restore = mmc_power_restore,
632 613  
... ... @@ -645,14 +626,12 @@
645 626 {
646 627 const struct mmc_bus_ops *bus_ops;
647 628  
648   - if (host->caps & MMC_CAP_NONREMOVABLE)
  629 + if (host->caps & MMC_CAP_NONREMOVABLE || !mmc_assume_removable)
649 630 bus_ops = &mmc_ops_unsafe;
650 631 else
651 632 bus_ops = &mmc_ops;
652 633 mmc_attach_bus(host, bus_ops);
653 634 }
654   -
655   -#endif
656 635  
657 636 /*
658 637 * Starting point for MMC card init.
drivers/mmc/core/sd.c
... ... @@ -606,26 +606,9 @@
606 606 mmc_release_host(host);
607 607 }
608 608  
609   -#ifdef CONFIG_MMC_UNSAFE_RESUME
610   -
611 609 static const struct mmc_bus_ops mmc_sd_ops = {
612 610 .remove = mmc_sd_remove,
613 611 .detect = mmc_sd_detect,
614   - .suspend = mmc_sd_suspend,
615   - .resume = mmc_sd_resume,
616   - .power_restore = mmc_sd_power_restore,
617   -};
618   -
619   -static void mmc_sd_attach_bus_ops(struct mmc_host *host)
620   -{
621   - mmc_attach_bus(host, &mmc_sd_ops);
622   -}
623   -
624   -#else
625   -
626   -static const struct mmc_bus_ops mmc_sd_ops = {
627   - .remove = mmc_sd_remove,
628   - .detect = mmc_sd_detect,
629 612 .suspend = NULL,
630 613 .resume = NULL,
631 614 .power_restore = mmc_sd_power_restore,
632 615  
... ... @@ -643,14 +626,12 @@
643 626 {
644 627 const struct mmc_bus_ops *bus_ops;
645 628  
646   - if (host->caps & MMC_CAP_NONREMOVABLE)
  629 + if (host->caps & MMC_CAP_NONREMOVABLE || !mmc_assume_removable)
647 630 bus_ops = &mmc_sd_ops_unsafe;
648 631 else
649 632 bus_ops = &mmc_sd_ops;
650 633 mmc_attach_bus(host, bus_ops);
651 634 }
652   -
653   -#endif
654 635  
655 636 /*
656 637 * Starting point for SD card init.