From 03583443072113ac80eef713c33c5513ea84fdca Mon Sep 17 00:00:00 2001 From: lintao Date: Fri, 28 Mar 2014 13:24:38 +0800 Subject: [PATCH] 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] [] (mmc_bus_suspend+0x40/0x44) from [] (dpm_run_callback.isra.5+0x28/0x60) [ 43.436168] [] (dpm_run_callback.isra.5+0x28/0x60) from [] (__device_suspend+0x1e4/0x274) mmc: core: rockchip: Tags rockchip eMMC controller's pm_caps with MMC_PM_IGNORE_PM_NOTIFY refered to commit 3549af216ba41d5bd70. 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 --- drivers/mmc/core/bus.c | 21 +++++++++++--------- drivers/mmc/host/rk_sdmmc.c | 39 +++++++++++++------------------------ 2 files changed, 26 insertions(+), 34 deletions(-) mode change 100644 => 100755 drivers/mmc/core/bus.c diff --git a/drivers/mmc/core/bus.c b/drivers/mmc/core/bus.c old mode 100644 new mode 100755 index 37b4be81e530..664a19822913 --- a/drivers/mmc/core/bus.c +++ b/drivers/mmc/core/bus.c @@ -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); diff --git a/drivers/mmc/host/rk_sdmmc.c b/drivers/mmc/host/rk_sdmmc.c index f3520b63cc00..9c101eaeef0e 100755 --- a/drivers/mmc/host/rk_sdmmc.c +++ b/drivers/mmc/host/rk_sdmmc.c @@ -2534,6 +2534,13 @@ static int dw_mci_init_slot(struct dw_mci *host, unsigned int id) 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); else{ @@ -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; + 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 */ + 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, " "%u deep fifo\n", @@ -3124,23 +3133,7 @@ EXPORT_SYMBOL(dw_mci_remove); */ 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) 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 ret; } return 0; } -- 2.34.1