aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mmc
diff options
context:
space:
mode:
authorBen Hutchings <ben@decadent.org.uk>2009-12-14 21:01:29 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2009-12-15 11:53:35 -0500
commitbd68e0838fe85794b06892054772fa013a8d1986 (patch)
treeadb0a3a1aad94f756b7d3d2f8e077877a0b982d0 /drivers/mmc
parentc78402e95dd8238ee2b0e6e62b9a0c8b2bb9bba9 (diff)
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>
Diffstat (limited to 'drivers/mmc')
-rw-r--r--drivers/mmc/core/Kconfig4
-rw-r--r--drivers/mmc/core/core.c16
-rw-r--r--drivers/mmc/core/core.h2
-rw-r--r--drivers/mmc/core/mmc.c23
-rw-r--r--drivers/mmc/core/sd.c21
5 files changed, 23 insertions, 43 deletions
diff --git a/drivers/mmc/core/Kconfig b/drivers/mmc/core/Kconfig
index ab37a6d9d32a..bb22ffd76ef8 100644
--- a/drivers/mmc/core/Kconfig
+++ b/drivers/mmc/core/Kconfig
@@ -3,7 +3,7 @@
3# 3#
4 4
5config MMC_UNSAFE_RESUME 5config MMC_UNSAFE_RESUME
6 bool "Allow unsafe resume (DANGEROUS)" 6 bool "Assume MMC/SD cards are non-removable (DANGEROUS)"
7 help 7 help
8 If you say Y here, the MMC layer will assume that all cards 8 If you say Y here, the MMC layer will assume that all cards
9 stayed in their respective slots during the suspend. The 9 stayed in their respective slots during the suspend. The
@@ -14,3 +14,5 @@ config MMC_UNSAFE_RESUME
14 This option is usually just for embedded systems which use 14 This option is usually just for embedded systems which use
15 a MMC/SD card for rootfs. Most people should say N here. 15 a MMC/SD card for rootfs. Most people should say N here.
16 16
17 This option sets a default which can be overridden by the
18 module parameter "removable=0" or "removable=1".
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index 7dab2e5f4bc9..30acd5265821 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -48,6 +48,22 @@ int use_spi_crc = 1;
48module_param(use_spi_crc, bool, 0); 48module_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
57int mmc_assume_removable;
58#else
59int mmc_assume_removable = 1;
60#endif
61module_param_named(removable, mmc_assume_removable, bool, 0644);
62MODULE_PARM_DESC(
63 removable,
64 "MMC/SD cards are removable and may be removed during suspend");
65
66/*
51 * Internal function. Schedule delayed work in the MMC work queue. 67 * Internal function. Schedule delayed work in the MMC work queue.
52 */ 68 */
53static int mmc_schedule_delayed_work(struct delayed_work *work, 69static int mmc_schedule_delayed_work(struct delayed_work *work,
diff --git a/drivers/mmc/core/core.h b/drivers/mmc/core/core.h
index 67ae6abc4230..a811c52a1659 100644
--- a/drivers/mmc/core/core.h
+++ b/drivers/mmc/core/core.h
@@ -54,7 +54,9 @@ int mmc_attach_mmc(struct mmc_host *host, u32 ocr);
54int mmc_attach_sd(struct mmc_host *host, u32 ocr); 54int mmc_attach_sd(struct mmc_host *host, u32 ocr);
55int mmc_attach_sdio(struct mmc_host *host, u32 ocr); 55int mmc_attach_sdio(struct mmc_host *host, u32 ocr);
56 56
57/* Module parameters */
57extern int use_spi_crc; 58extern int use_spi_crc;
59extern int mmc_assume_removable;
58 60
59/* Debugfs information for hosts and cards */ 61/* Debugfs information for hosts and cards */
60void mmc_add_host_debugfs(struct mmc_host *host); 62void mmc_add_host_debugfs(struct mmc_host *host);
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
index bfefce365ae7..c11189446a1f 100644
--- a/drivers/mmc/core/mmc.c
+++ b/drivers/mmc/core/mmc.c
@@ -602,25 +602,6 @@ static int mmc_awake(struct mmc_host *host)
602 return err; 602 return err;
603} 603}
604 604
605#ifdef CONFIG_MMC_UNSAFE_RESUME
606
607static const struct mmc_bus_ops mmc_ops = {
608 .awake = mmc_awake,
609 .sleep = mmc_sleep,
610 .remove = mmc_remove,
611 .detect = mmc_detect,
612 .suspend = mmc_suspend,
613 .resume = mmc_resume,
614 .power_restore = mmc_power_restore,
615};
616
617static void mmc_attach_bus_ops(struct mmc_host *host)
618{
619 mmc_attach_bus(host, &mmc_ops);
620}
621
622#else
623
624static const struct mmc_bus_ops mmc_ops = { 605static const struct mmc_bus_ops mmc_ops = {
625 .awake = mmc_awake, 606 .awake = mmc_awake,
626 .sleep = mmc_sleep, 607 .sleep = mmc_sleep,
@@ -645,15 +626,13 @@ static void mmc_attach_bus_ops(struct mmc_host *host)
645{ 626{
646 const struct mmc_bus_ops *bus_ops; 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 bus_ops = &mmc_ops_unsafe; 630 bus_ops = &mmc_ops_unsafe;
650 else 631 else
651 bus_ops = &mmc_ops; 632 bus_ops = &mmc_ops;
652 mmc_attach_bus(host, bus_ops); 633 mmc_attach_bus(host, bus_ops);
653} 634}
654 635
655#endif
656
657/* 636/*
658 * Starting point for MMC card init. 637 * Starting point for MMC card init.
659 */ 638 */
diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c
index 10b2a4d20f5a..fdd414eded09 100644
--- a/drivers/mmc/core/sd.c
+++ b/drivers/mmc/core/sd.c
@@ -606,23 +606,6 @@ static void mmc_sd_power_restore(struct mmc_host *host)
606 mmc_release_host(host); 606 mmc_release_host(host);
607} 607}
608 608
609#ifdef CONFIG_MMC_UNSAFE_RESUME
610
611static const struct mmc_bus_ops mmc_sd_ops = {
612 .remove = mmc_sd_remove,
613 .detect = mmc_sd_detect,
614 .suspend = mmc_sd_suspend,
615 .resume = mmc_sd_resume,
616 .power_restore = mmc_sd_power_restore,
617};
618
619static void mmc_sd_attach_bus_ops(struct mmc_host *host)
620{
621 mmc_attach_bus(host, &mmc_sd_ops);
622}
623
624#else
625
626static const struct mmc_bus_ops mmc_sd_ops = { 609static const struct mmc_bus_ops mmc_sd_ops = {
627 .remove = mmc_sd_remove, 610 .remove = mmc_sd_remove,
628 .detect = mmc_sd_detect, 611 .detect = mmc_sd_detect,
@@ -643,15 +626,13 @@ static void mmc_sd_attach_bus_ops(struct mmc_host *host)
643{ 626{
644 const struct mmc_bus_ops *bus_ops; 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 bus_ops = &mmc_sd_ops_unsafe; 630 bus_ops = &mmc_sd_ops_unsafe;
648 else 631 else
649 bus_ops = &mmc_sd_ops; 632 bus_ops = &mmc_sd_ops;
650 mmc_attach_bus(host, bus_ops); 633 mmc_attach_bus(host, bus_ops);
651} 634}
652 635
653#endif
654
655/* 636/*
656 * Starting point for SD card init. 637 * Starting point for SD card init.
657 */ 638 */