mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-08 11:50:43 +09:00
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:
21
drivers/mmc/core/bus.c
Normal file → Executable file
21
drivers/mmc/core/bus.c
Normal file → Executable 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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user