mmc: core: bus:

Fix mmc_bus_suspend and mmc_bus_resume panic kernel bug. Since pm notify call
chain fall into mmc subsystem, host controller driver may not register bus_ops indeed ,
actually it's optional for bus-level drivers to complete this hook pointer.

[   42.603423] Freezing user space processes ... (elapsed 0.008 seconds) done.
[   42.611886] Freezing remaining freezable tasks ... (elapsed 0.001 seconds) done.
[   42.614351] Unable to handle kernel NULL pointer dereference at virtual address 00000000
[   42.630102] pgd = c0004000
[   42.632816] [00000000] *pgd=00000000
[   42.636483] Internal error: Oops: 80000005 [#1] PREEMPT SMP ARM
....
[   43.426496] [<c045f788>] (mmc_bus_suspend+0x40/0x44) from [<c02e94dc>] (dpm_run_callback.isra.5+0x28/0x60)
[   43.436168] [<c02e94dc>] (dpm_run_callback.isra.5+0x28/0x60) from [<c02e9b78>] (__device_suspend+0x1e4/0x274)

mmc: core: rockchip:
     Tags rockchip eMMC controller's pm_caps with MMC_PM_IGNORE_PM_NOTIFY refered to commit 3549af216b.
eMMC controller now only ack probe/shudown and remove event by poweroff notify. Otherwise, PM freezing will be disterbed
by emergancy I/O error from file system.

[   42.710633] PM: suspend entry 2013-01-21 09:54:47.245333254 UTC
[   42.710659] PM: Syncing filesystems ... done.
[   42.728095] mmc0: card 0001 removed
[   42.828461] EXT4-fs error (device mmcblk0p12): ext4_wait_block_bitmap:466:
		comm PackageManager: Cannot read block bitmap - block_group = 1, block_bitmap = 34
[   42.828653] EXT4-fs (mmcblk0p12): delayed block allocation failed for inode 647 at logical offset 0 with
		max blocks 30 with error -5
[   42.828689] EXT4-fs (mmcblk0p12): This should not happen!! Data will be lost
[   42.829227] Aborting journal on device mmcblk0p12-8.
[   42.829322] JBD2: Error -5 detected when updating journal superblock for mmcblk0p12-8.
[   42.829409] journal commit I/O error
[   42.829942] EXT4-fs (mmcblk0p12): previous I/O error to superblock detected
......
[   43.179043] Freezing user space processes ...
[   43.179519] active wakeup source: mmc0_detect

Signed-off-by: lintao <lintao@rock-chips.com>
This commit is contained in:
lintao
2014-03-28 13:24:38 +08:00
parent 0fba1743c6
commit 0358344307
2 changed files with 27 additions and 35 deletions

21
drivers/mmc/core/bus.c Normal file → Executable file
View File

@@ -147,15 +147,16 @@ static int mmc_bus_suspend(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;
int ret = 0;
if (dev->driver && drv->suspend) {
ret = drv->suspend(card);
if (ret)
return ret;
}
ret = host->bus_ops->suspend(host);
if(host->bus_ops->suspend)
ret = host->bus_ops->suspend(host);
return ret;
}
@@ -164,13 +165,15 @@ static int mmc_bus_resume(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;
ret = host->bus_ops->resume(host);
if (ret)
pr_warn("%s: error %d during resume (card was removed?)\n",
mmc_hostname(host), ret);
int ret = 0;
if(host->bus_ops->resume){
ret = host->bus_ops->resume(host);
if (ret)
pr_warn("%s: error %d during resume (card was removed?)\n",
mmc_hostname(host), ret);
}
if (dev->driver && drv->resume)
ret = drv->resume(card);

View File

@@ -2534,6 +2534,13 @@ static int dw_mci_init_slot(struct dw_mci *host, unsigned int id)
mmc->restrict_caps |= RESTRICT_CARD_TYPE_SDIO;
if (of_find_property(host->dev->of_node, "supports-emmc", NULL))
mmc->restrict_caps |= RESTRICT_CARD_TYPE_EMMC;
//if(mmc->restrict_caps & RESTRICT_CARD_TYPE_EMMC)
// mmc->caps |= MMC_CAP_NONREMOVABLE;
/* eMMC should not sched into pm mgmt framework*/
if(mmc->restrict_caps & RESTRICT_CARD_TYPE_EMMC)
mmc->pm_flags |= MMC_PM_IGNORE_PM_NOTIFY;
if (host->pdata->get_ocr)
mmc->ocr_avail = host->pdata->get_ocr(id);
@@ -3037,12 +3044,14 @@ int dw_mci_probe(struct dw_mci *host)
*/
mci_writel(host, RINTSTS, 0xFFFFFFFF);
regs = SDMMC_INT_CMD_DONE | SDMMC_INT_DATA_OVER | SDMMC_INT_TXDR |
SDMMC_INT_RXDR | DW_MCI_ERROR_FLAGS;
if(!(host->mmc->restrict_caps & RESTRICT_CARD_TYPE_SDIO))
regs |= SDMMC_INT_CD;
mci_writel(host, INTMASK, regs);
SDMMC_INT_RXDR | DW_MCI_ERROR_FLAGS;
if(!(host->mmc->restrict_caps & RESTRICT_CARD_TYPE_SDIO)
&& !(host->mmc->restrict_caps & RESTRICT_CARD_TYPE_EMMC))
regs |= SDMMC_INT_CD;
mci_writel(host, INTMASK, regs);
mci_writel(host, CTRL, SDMMC_CTRL_INT_ENABLE); /* Enable mci interrupt */
dev_info(host->dev, "DW MMC controller at irq %d, "
"%d bit host data width, "
@@ -3124,23 +3133,7 @@ EXPORT_SYMBOL(dw_mci_remove);
* TODO: we should probably disable the clock to the card in the suspend path.
*/
int dw_mci_suspend(struct dw_mci *host)
{
/*int i, ret = 0;
for (i = 0; i < host->num_slots; i++) {
struct dw_mci_slot *slot = host->slot[i];
if (!slot)
continue;
ret = mmc_suspend_host(slot->mmc);
if (ret < 0) {
while (--i >= 0) {
slot = host->slot[i];
if (slot)
mmc_resume_host(host->slot[i]->mmc);
}
return ret;
}
}
{
if (host->vmmc)
regulator_disable(host->vmmc);
@@ -3195,10 +3188,6 @@ int dw_mci_resume(struct dw_mci *host)
if (slot->mmc->pm_flags & MMC_PM_KEEP_POWER) {
dw_mci_set_ios(slot->mmc, &slot->mmc->ios);
dw_mci_setup_bus(slot, true);
}
// ret = mmc_resume_host(host->slot[i]->mmc);
// if (ret < 0)
}
}
return 0;