mmc: core: bus:
authorlintao <lintao@rock-chips.com>
Fri, 28 Mar 2014 05:24:38 +0000 (13:24 +0800)
committerlintao <lintao@rock-chips.com>
Fri, 28 Mar 2014 05:34:41 +0000 (13:34 +0800)
     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 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 <lintao@rock-chips.com>
drivers/mmc/core/bus.c [changed mode: 0644->0755]
drivers/mmc/host/rk_sdmmc.c

old mode 100644 (file)
new mode 100755 (executable)
index 37b4be8..664a198
@@ -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);
 
index f3520b63cc0036923a8d8eeb93bdc64f7576c727..9c101eaeef0e0cbbfe702b2e651be61c6259c586 100755 (executable)
@@ -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;
 }