aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-07-10 11:16:00 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2013-07-10 11:16:00 -0700
commitbfffbea1aaeeb1eb6500c83ff9653416daa5b490 (patch)
tree1325ecb176b7a3d04924d6a1563b15ad6085d36a
parent34ae0a6f05aee9f51fca17001b4a90703d434ae1 (diff)
parent01ebea1b411aafc8eab440bf1d2037f01bbed99b (diff)
Merge tag 'mmc-updates-for-3.11-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/cjb/mmc
Pull MMC updates from Chris Ball: "MMC highlights for 3.11: Core: - Add support for eMMC 5.1 devices - Add MMC_CAP_AGGRESSIVE_PM capability for aggressive power management of eMMC/SD between requests, using runtime PM - Add an ioctl to perform the eMMC 4.5 Sanitize command. Sample code at: git://git.kernel.org/pub/scm/linux/kernel/git/cjb/mmc-utils.git Drivers: - dw_mmc: Add support for Rockchip's Cortex-A9 SoCs - dw_mmc: Add support for Altera SoCFPGAs - sdhci-esdhc-imx: Add support for 8-bit bus width, non-removable cards - sdhci-bcm-kona: New driver for Broadcom Kona (281xx) SoCs - sdhi/tmio: Add DT DMA support" * tag 'mmc-updates-for-3.11-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/cjb/mmc: (87 commits) mmc: bcm281xx SDHCI driver mmc: sdhci: add card_event callback to sdhci mmc: core: Fixup Oops for SDIO shutdown mmc: sdhci-pci: add another device id mmc: esdhc: Fix bug when writing to SDHCI_HOST_CONTROL register mmc: esdhc: Add support for 8-bit bus width and non-removable card mmc: core: production year for eMMC 4.41 and later mmc: omap: remove unnecessary #if 0's mmc: sdhci: fix ctrl_2 on super-speed selection mmc: dw_mmc-pltfm: add Rockchip variant mmc: dw_mmc-pltfm: move probe and remove below dt match table mmc: dw_mmc-pltfm: remove static from dw_mci_pltfm_remove mmc: sdhci-acpi: add support for eMMC hardware reset for HID 80860F14 mmc: sdhci-pci: add support for eMMC hardware reset for BYT eMMC. mmc: dw_mmc: Add support DW SD/MMC driver on SOCFPGA mmc: sdhci: fix caps2 for HS200 sdhci-pxav3: Fix runtime PM initialization mmc: core: Add DT-bindings for MMC_CAP2_FULL_PWR_CYCLE mmc: core: Invent MMC_CAP2_FULL_PWR_CYCLE mmc: core: Enable power_off_notify for eMMC shutdown sequence ...
-rw-r--r--Documentation/devicetree/bindings/mmc/mmc.txt1
-rw-r--r--Documentation/devicetree/bindings/mmc/rockchip-dw-mshc.txt23
-rw-r--r--Documentation/devicetree/bindings/mmc/synopsis-dw-mshc.txt20
-rw-r--r--arch/arm/configs/bcm_defconfig7
-rw-r--r--drivers/mmc/card/block.c130
-rw-r--r--drivers/mmc/card/mmc_test.c5
-rw-r--r--drivers/mmc/card/queue.c2
-rw-r--r--drivers/mmc/core/bus.c52
-rw-r--r--drivers/mmc/core/core.c200
-rw-r--r--drivers/mmc/core/core.h7
-rw-r--r--drivers/mmc/core/debugfs.c8
-rw-r--r--drivers/mmc/core/host.c32
-rw-r--r--drivers/mmc/core/mmc.c249
-rw-r--r--drivers/mmc/core/mmc_ops.c36
-rw-r--r--drivers/mmc/core/mmc_ops.h1
-rw-r--r--drivers/mmc/core/sd.c68
-rw-r--r--drivers/mmc/core/sdio.c76
-rw-r--r--drivers/mmc/host/Kconfig19
-rw-r--r--drivers/mmc/host/Makefile2
-rw-r--r--drivers/mmc/host/android-goldfish.c2
-rw-r--r--drivers/mmc/host/atmel-mci.c14
-rw-r--r--drivers/mmc/host/au1xmmc.c1
-rw-r--r--drivers/mmc/host/bfin_sdh.c2
-rw-r--r--drivers/mmc/host/cb710-mmc.c2
-rw-r--r--drivers/mmc/host/cb710-mmc.h2
-rw-r--r--drivers/mmc/host/davinci_mmc.c1
-rw-r--r--drivers/mmc/host/dw_mmc-exynos.c2
-rw-r--r--drivers/mmc/host/dw_mmc-pci.c58
-rw-r--r--drivers/mmc/host/dw_mmc-pltfm.c73
-rw-r--r--drivers/mmc/host/dw_mmc-socfpga.c140
-rw-r--r--drivers/mmc/host/dw_mmc.c65
-rw-r--r--drivers/mmc/host/dw_mmc.h3
-rw-r--r--drivers/mmc/host/jz4740_mmc.c180
-rw-r--r--drivers/mmc/host/mvsdio.c74
-rw-r--r--drivers/mmc/host/mxcmmc.c6
-rw-r--r--drivers/mmc/host/mxs-mmc.c11
-rw-r--r--drivers/mmc/host/omap.c18
-rw-r--r--drivers/mmc/host/omap_hsmmc.c2
-rw-r--r--drivers/mmc/host/pxamci.c2
-rw-r--r--drivers/mmc/host/rtsx_pci_sdmmc.c2
-rw-r--r--drivers/mmc/host/sdhci-acpi.c96
-rw-r--r--drivers/mmc/host/sdhci-bcm-kona.c348
-rw-r--r--drivers/mmc/host/sdhci-bcm2835.c2
-rw-r--r--drivers/mmc/host/sdhci-cns3xxx.c2
-rw-r--r--drivers/mmc/host/sdhci-dove.c2
-rw-r--r--drivers/mmc/host/sdhci-esdhc-imx.c30
-rw-r--r--drivers/mmc/host/sdhci-esdhc.h16
-rw-r--r--drivers/mmc/host/sdhci-of-esdhc.c63
-rw-r--r--drivers/mmc/host/sdhci-of-hlwd.c2
-rw-r--r--drivers/mmc/host/sdhci-pci.c43
-rw-r--r--drivers/mmc/host/sdhci-pltfm.c23
-rw-r--r--drivers/mmc/host/sdhci-pltfm.h14
-rw-r--r--drivers/mmc/host/sdhci-pxav2.c4
-rw-r--r--drivers/mmc/host/sdhci-pxav3.c18
-rw-r--r--drivers/mmc/host/sdhci-s3c.c1
-rw-r--r--drivers/mmc/host/sdhci-sirf.c59
-rw-r--r--drivers/mmc/host/sdhci-spear.c2
-rw-r--r--drivers/mmc/host/sdhci-tegra.c11
-rw-r--r--drivers/mmc/host/sdhci.c63
-rw-r--r--drivers/mmc/host/sdhci.h1
-rw-r--r--drivers/mmc/host/sh_mmcif.c12
-rw-r--r--drivers/mmc/host/sh_mobile_sdhi.c34
-rw-r--r--drivers/mmc/host/tmio_mmc.c2
-rw-r--r--drivers/mmc/host/tmio_mmc.h21
-rw-r--r--drivers/mmc/host/tmio_mmc_dma.c48
-rw-r--r--drivers/mmc/host/tmio_mmc_pio.c40
-rw-r--r--drivers/mmc/host/wmt-sdmmc.c2
-rw-r--r--include/linux/mfd/tmio.h5
-rw-r--r--include/linux/mmc/card.h11
-rw-r--r--include/linux/mmc/core.h5
-rw-r--r--include/linux/mmc/host.h12
-rw-r--r--include/linux/mmc/sdhci.h6
-rw-r--r--include/linux/platform_data/mmc-esdhc-imx.h1
73 files changed, 1807 insertions, 790 deletions
diff --git a/Documentation/devicetree/bindings/mmc/mmc.txt b/Documentation/devicetree/bindings/mmc/mmc.txt
index 85aada2263d..458b57f199a 100644
--- a/Documentation/devicetree/bindings/mmc/mmc.txt
+++ b/Documentation/devicetree/bindings/mmc/mmc.txt
@@ -28,6 +28,7 @@ Optional properties:
- cap-mmc-highspeed: MMC high-speed timing is supported
- cap-power-off-card: powering off the card is safe
- cap-sdio-irq: enable SDIO IRQ signalling on this interface
+- full-pwr-cycle: full power cycle of the card is supported
*NOTE* on CD and WP polarity. To use common for all SD/MMC host controllers line
polarity properties, we have to fix the meaning of the "normal" and "inverted"
diff --git a/Documentation/devicetree/bindings/mmc/rockchip-dw-mshc.txt b/Documentation/devicetree/bindings/mmc/rockchip-dw-mshc.txt
new file mode 100644
index 00000000000..8a3d91d47b6
--- /dev/null
+++ b/Documentation/devicetree/bindings/mmc/rockchip-dw-mshc.txt
@@ -0,0 +1,23 @@
+* Rockchip specific extensions to the Synopsis Designware Mobile
+ Storage Host Controller
+
+The Synopsis designware mobile storage host controller is used to interface
+a SoC with storage medium such as eMMC or SD/MMC cards. This file documents
+differences between the core Synopsis dw mshc controller properties described
+by synopsis-dw-mshc.txt and the properties used by the Rockchip specific
+extensions to the Synopsis Designware Mobile Storage Host Controller.
+
+Required Properties:
+
+* compatible: should be
+ - "rockchip,rk2928-dw-mshc": for Rockchip RK2928 and following
+
+Example:
+
+ rkdwmmc0@12200000 {
+ compatible = "rockchip,rk2928-dw-mshc";
+ reg = <0x12200000 0x1000>;
+ interrupts = <0 75 0>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
diff --git a/Documentation/devicetree/bindings/mmc/synopsis-dw-mshc.txt b/Documentation/devicetree/bindings/mmc/synopsis-dw-mshc.txt
index 1180d7814af..cdcebea9c6f 100644
--- a/Documentation/devicetree/bindings/mmc/synopsis-dw-mshc.txt
+++ b/Documentation/devicetree/bindings/mmc/synopsis-dw-mshc.txt
@@ -39,6 +39,19 @@ Required Properties:
Optional properties:
+* clocks: from common clock binding: handle to biu and ciu clocks for the
+ bus interface unit clock and the card interface unit clock.
+
+* clock-names: from common clock binding: Shall be "biu" and "ciu".
+ If the biu clock is missing we'll simply skip enabling it. If the
+ ciu clock is missing we'll just assume that the clock is running at
+ clock-frequency. It is an error to omit both the ciu clock and the
+ clock-frequency.
+
+* clock-frequency: should be the frequency (in Hz) of the ciu clock. If this
+ is specified and the ciu clock is specified then we'll try to set the ciu
+ clock to this at probe time.
+
* num-slots: specifies the number of slots supported by the controller.
The number of physical slots actually used could be equal or less than the
value specified by num-slots. If this property is not specified, the value
@@ -55,6 +68,9 @@ Optional properties:
* broken-cd: as documented in mmc core bindings.
+* vmmc-supply: The phandle to the regulator to use for vmmc. If this is
+ specified we'll defer probe until we can find this regulator.
+
Aliases:
- All the MSHC controller nodes should be represented in the aliases node using
@@ -67,6 +83,8 @@ board specific portions as listed below.
dwmmc0@12200000 {
compatible = "snps,dw-mshc";
+ clocks = <&clock 351>, <&clock 132>;
+ clock-names = "biu", "ciu";
reg = <0x12200000 0x1000>;
interrupts = <0 75 0>;
#address-cells = <1>;
@@ -74,11 +92,13 @@ board specific portions as listed below.
};
dwmmc0@12200000 {
+ clock-frequency = <400000000>;
num-slots = <1>;
supports-highspeed;
broken-cd;
fifo-depth = <0x80>;
card-detect-delay = <200>;
+ vmmc-supply = <&buck8>;
slot@0 {
reg = <0>;
diff --git a/arch/arm/configs/bcm_defconfig b/arch/arm/configs/bcm_defconfig
index e3bf2d65618..65edf6d4721 100644
--- a/arch/arm/configs/bcm_defconfig
+++ b/arch/arm/configs/bcm_defconfig
@@ -78,6 +78,13 @@ CONFIG_BACKLIGHT_LCD_SUPPORT=y
CONFIG_LCD_CLASS_DEVICE=y
CONFIG_BACKLIGHT_CLASS_DEVICE=y
# CONFIG_USB_SUPPORT is not set
+CONFIG_MMC=y
+CONFIG_MMC_UNSAFE_RESUME=y
+CONFIG_MMC_BLOCK_MINORS=32
+CONFIG_MMC_TEST=y
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_PLTFM=y
+CONFIG_MMC_SDHCI_BCM_KONA=y
CONFIG_NEW_LEDS=y
CONFIG_LEDS_CLASS=y
CONFIG_LEDS_TRIGGERS=y
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
index dd27b0783d5..cd0b7f4a1ff 100644
--- a/drivers/mmc/card/block.c
+++ b/drivers/mmc/card/block.c
@@ -34,6 +34,7 @@
#include <linux/delay.h>
#include <linux/capability.h>
#include <linux/compat.h>
+#include <linux/pm_runtime.h>
#include <linux/mmc/ioctl.h>
#include <linux/mmc/card.h>
@@ -58,6 +59,8 @@ MODULE_ALIAS("mmc:block");
#define INAND_CMD38_ARG_SECTRIM1 0x81
#define INAND_CMD38_ARG_SECTRIM2 0x88
#define MMC_BLK_TIMEOUT_MS (10 * 60 * 1000) /* 10 minute timeout */
+#define MMC_SANITIZE_REQ_TIMEOUT 240000
+#define MMC_EXTRACT_INDEX_FROM_ARG(x) ((x & 0x00FF0000) >> 16)
#define mmc_req_rel_wr(req) (((req->cmd_flags & REQ_FUA) || \
(req->cmd_flags & REQ_META)) && \
@@ -222,7 +225,7 @@ static ssize_t power_ro_lock_store(struct device *dev,
md = mmc_blk_get(dev_to_disk(dev));
card = md->queue.card;
- mmc_claim_host(card->host);
+ mmc_get_card(card);
ret = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BOOT_WP,
card->ext_csd.boot_ro_lock |
@@ -233,7 +236,7 @@ static ssize_t power_ro_lock_store(struct device *dev,
else
card->ext_csd.boot_ro_lock |= EXT_CSD_BOOT_WP_B_PWR_WP_EN;
- mmc_release_host(card->host);
+ mmc_put_card(card);
if (!ret) {
pr_info("%s: Locking boot partition ro until next power on\n",
@@ -408,6 +411,35 @@ static int ioctl_rpmb_card_status_poll(struct mmc_card *card, u32 *status,
return err;
}
+static int ioctl_do_sanitize(struct mmc_card *card)
+{
+ int err;
+
+ if (!(mmc_can_sanitize(card) &&
+ (card->host->caps2 & MMC_CAP2_SANITIZE))) {
+ pr_warn("%s: %s - SANITIZE is not supported\n",
+ mmc_hostname(card->host), __func__);
+ err = -EOPNOTSUPP;
+ goto out;
+ }
+
+ pr_debug("%s: %s - SANITIZE IN PROGRESS...\n",
+ mmc_hostname(card->host), __func__);
+
+ err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
+ EXT_CSD_SANITIZE_START, 1,
+ MMC_SANITIZE_REQ_TIMEOUT);
+
+ if (err)
+ pr_err("%s: %s - EXT_CSD_SANITIZE_START failed. err=%d\n",
+ mmc_hostname(card->host), __func__, err);
+
+ pr_debug("%s: %s - SANITIZE COMPLETED\n", mmc_hostname(card->host),
+ __func__);
+out:
+ return err;
+}
+
static int mmc_blk_ioctl_cmd(struct block_device *bdev,
struct mmc_ioc_cmd __user *ic_ptr)
{
@@ -491,7 +523,7 @@ static int mmc_blk_ioctl_cmd(struct block_device *bdev,
mrq.cmd = &cmd;
- mmc_claim_host(card->host);
+ mmc_get_card(card);
err = mmc_blk_part_switch(card, md);
if (err)
@@ -510,6 +542,17 @@ static int mmc_blk_ioctl_cmd(struct block_device *bdev,
goto cmd_rel_host;
}
+ if ((MMC_EXTRACT_INDEX_FROM_ARG(cmd.arg) == EXT_CSD_SANITIZE_START) &&
+ (cmd.opcode == MMC_SWITCH)) {
+ err = ioctl_do_sanitize(card);
+
+ if (err)
+ pr_err("%s: ioctl_do_sanitize() failed. err = %d",
+ __func__, err);
+
+ goto cmd_rel_host;
+ }
+
mmc_wait_for_req(card->host, &mrq);
if (cmd.error) {
@@ -558,7 +601,7 @@ static int mmc_blk_ioctl_cmd(struct block_device *bdev,
}
cmd_rel_host:
- mmc_release_host(card->host);
+ mmc_put_card(card);
cmd_done:
mmc_blk_put(md);
@@ -939,10 +982,10 @@ static int mmc_blk_issue_secdiscard_rq(struct mmc_queue *mq,
{
struct mmc_blk_data *md = mq->data;
struct mmc_card *card = md->queue.card;
- unsigned int from, nr, arg, trim_arg, erase_arg;
+ unsigned int from, nr, arg;
int err = 0, type = MMC_BLK_SECDISCARD;
- if (!(mmc_can_secure_erase_trim(card) || mmc_can_sanitize(card))) {
+ if (!(mmc_can_secure_erase_trim(card))) {
err = -EOPNOTSUPP;
goto out;
}
@@ -950,23 +993,11 @@ static int mmc_blk_issue_secdiscard_rq(struct mmc_queue *mq,
from = blk_rq_pos(req);
nr = blk_rq_sectors(req);
- /* The sanitize operation is supported at v4.5 only */
- if (mmc_can_sanitize(card)) {
- erase_arg = MMC_ERASE_ARG;
- trim_arg = MMC_TRIM_ARG;
- } else {
- erase_arg = MMC_SECURE_ERASE_ARG;
- trim_arg = MMC_SECURE_TRIM1_ARG;
- }
+ if (mmc_can_trim(card) && !mmc_erase_group_aligned(card, from, nr))
+ arg = MMC_SECURE_TRIM1_ARG;
+ else
+ arg = MMC_SECURE_ERASE_ARG;
- if (mmc_erase_group_aligned(card, from, nr))
- arg = erase_arg;
- else if (mmc_can_trim(card))
- arg = trim_arg;
- else {
- err = -EINVAL;
- goto out;
- }
retry:
if (card->quirks & MMC_QUIRK_INAND_CMD38) {
err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
@@ -1002,9 +1033,6 @@ retry:
goto out;
}
- if (mmc_can_sanitize(card))
- err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
- EXT_CSD_SANITIZE_START, 1, 0);
out_retry:
if (err && !mmc_blk_reset(md, card->host, type))
goto retry;
@@ -1895,7 +1923,7 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
if (req && !mq->mqrq_prev->req)
/* claim host only for the first request */
- mmc_claim_host(card->host);
+ mmc_get_card(card);
ret = mmc_blk_part_switch(card, md);
if (ret) {
@@ -1939,7 +1967,7 @@ out:
* In case sepecial request, there is no reentry to
* the 'mmc_blk_issue_rq' with 'mqrq_prev->req'.
*/
- mmc_release_host(card->host);
+ mmc_put_card(card);
return ret;
}
@@ -2158,6 +2186,14 @@ static void mmc_blk_remove_req(struct mmc_blk_data *md)
struct mmc_card *card;
if (md) {
+ /*
+ * Flush remaining requests and free queues. It
+ * is freeing the queue that stops new requests
+ * from being accepted.
+ */
+ mmc_cleanup_queue(&md->queue);
+ if (md->flags & MMC_BLK_PACKED_CMD)
+ mmc_packed_clean(&md->queue);
card = md->queue.card;
if (md->disk->flags & GENHD_FL_UP) {
device_remove_file(disk_to_dev(md->disk), &md->force_ro);
@@ -2166,14 +2202,8 @@ static void mmc_blk_remove_req(struct mmc_blk_data *md)
device_remove_file(disk_to_dev(md->disk),
&md->power_ro_lock);
- /* Stop new requests from getting into the queue */
del_gendisk(md->disk);
}
-
- /* Then flush out any already in there */
- mmc_cleanup_queue(&md->queue);
- if (md->flags & MMC_BLK_PACKED_CMD)
- mmc_packed_clean(&md->queue);
mmc_blk_put(md);
}
}
@@ -2336,6 +2366,19 @@ static int mmc_blk_probe(struct mmc_card *card)
if (mmc_add_disk(part_md))
goto out;
}
+
+ pm_runtime_set_autosuspend_delay(&card->dev, 3000);
+ pm_runtime_use_autosuspend(&card->dev);
+
+ /*
+ * Don't enable runtime PM for SD-combo cards here. Leave that
+ * decision to be taken during the SDIO init sequence instead.
+ */
+ if (card->type != MMC_TYPE_SD_COMBO) {
+ pm_runtime_set_active(&card->dev);
+ pm_runtime_enable(&card->dev);
+ }
+
return 0;
out:
@@ -2349,20 +2392,24 @@ static void mmc_blk_remove(struct mmc_card *card)
struct mmc_blk_data *md = mmc_get_drvdata(card);
mmc_blk_remove_parts(card, md);
+ pm_runtime_get_sync(&card->dev);
mmc_claim_host(card->host);
mmc_blk_part_switch(card, md);
mmc_release_host(card->host);
+ if (card->type != MMC_TYPE_SD_COMBO)
+ pm_runtime_disable(&card->dev);
+ pm_runtime_put_noidle(&card->dev);
mmc_blk_remove_req(md);
mmc_set_drvdata(card, NULL);
}
-#ifdef CONFIG_PM
-static int mmc_blk_suspend(struct mmc_card *card)
+static int _mmc_blk_suspend(struct mmc_card *card)
{
struct mmc_blk_data *part_md;
struct mmc_blk_data *md = mmc_get_drvdata(card);
if (md) {
+ pm_runtime_get_sync(&card->dev);
mmc_queue_suspend(&md->queue);
list_for_each_entry(part_md, &md->part, part) {
mmc_queue_suspend(&part_md->queue);
@@ -2371,6 +2418,17 @@ static int mmc_blk_suspend(struct mmc_card *card)
return 0;
}
+static void mmc_blk_shutdown(struct mmc_card *card)
+{
+ _mmc_blk_suspend(card);
+}
+
+#ifdef CONFIG_PM
+static int mmc_blk_suspend(struct mmc_card *card)
+{
+ return _mmc_blk_suspend(card);
+}
+
static int mmc_blk_resume(struct mmc_card *card)
{
struct mmc_blk_data *part_md;
@@ -2386,6 +2444,7 @@ static int mmc_blk_resume(struct mmc_card *card)
list_for_each_entry(part_md, &md->part, part) {
mmc_queue_resume(&part_md->queue);
}
+ pm_runtime_put(&card->dev);
}
return 0;
}
@@ -2402,6 +2461,7 @@ static struct mmc_driver mmc_driver = {
.remove = mmc_blk_remove,
.suspend = mmc_blk_suspend,
.resume = mmc_blk_resume,
+ .shutdown = mmc_blk_shutdown,
};
static int __init mmc_blk_init(void)
diff --git a/drivers/mmc/card/mmc_test.c b/drivers/mmc/card/mmc_test.c
index 759714ed6be..a69df521627 100644
--- a/drivers/mmc/card/mmc_test.c
+++ b/drivers/mmc/card/mmc_test.c
@@ -3025,12 +3025,17 @@ static void mmc_test_remove(struct mmc_card *card)
mmc_test_free_dbgfs_file(card);
}
+static void mmc_test_shutdown(struct mmc_card *card)
+{
+}
+
static struct mmc_driver mmc_driver = {
.drv = {
.name = "mmc_test",
},
.probe = mmc_test_probe,
.remove = mmc_test_remove,
+ .shutdown = mmc_test_shutdown,
};
static int __init mmc_test_init(void)
diff --git a/drivers/mmc/card/queue.c b/drivers/mmc/card/queue.c
index 9447a0e970d..fa9632eb63f 100644
--- a/drivers/mmc/card/queue.c
+++ b/drivers/mmc/card/queue.c
@@ -173,7 +173,7 @@ static void mmc_queue_setup_discard(struct request_queue *q,
/* granularity must not be greater than max. discard */
if (card->pref_erase > max_discard)
q->limits.discard_granularity = 0;
- if (mmc_can_secure_erase_trim(card) || mmc_can_sanitize(card))
+ if (mmc_can_secure_erase_trim(card))
queue_flag_set_unlocked(QUEUE_FLAG_SECDISCARD, q);
}
diff --git a/drivers/mmc/core/bus.c b/drivers/mmc/core/bus.c
index 9d5c7112557..704bf66f587 100644
--- a/drivers/mmc/core/bus.c
+++ b/drivers/mmc/core/bus.c
@@ -122,15 +122,39 @@ static int mmc_bus_remove(struct device *dev)
return 0;
}
+static void mmc_bus_shutdown(struct device *dev)
+{
+ struct mmc_driver *drv = to_mmc_driver(dev->driver);
+ struct mmc_card *card = mmc_dev_to_card(dev);
+ struct mmc_host *host = card->host;
+ int ret;
+
+ if (dev->driver && drv->shutdown)
+ drv->shutdown(card);
+
+ if (host->bus_ops->shutdown) {
+ ret = host->bus_ops->shutdown(host);
+ if (ret)
+ pr_warn("%s: error %d during shutdown\n",
+ mmc_hostname(host), ret);
+ }
+}