From e4d224046375c67226e35cc29dadb6d402a7aa9c Mon Sep 17 00:00:00 2001 From: lintao Date: Fri, 27 Jun 2014 14:56:34 +0800 Subject: [PATCH] mmc: core: rk_sdmmc: fix NULL pointer cause by edma complete If card been removed after sending read cmd to it, and before its response data sent to host, data null pointer occur. --- drivers/mmc/host/rk_sdmmc.c | 83 +++++++++++++++++++++++-------------- 1 file changed, 53 insertions(+), 30 deletions(-) diff --git a/drivers/mmc/host/rk_sdmmc.c b/drivers/mmc/host/rk_sdmmc.c index 3e0d97c5aefb..1c02aa9fa3b7 100755 --- a/drivers/mmc/host/rk_sdmmc.c +++ b/drivers/mmc/host/rk_sdmmc.c @@ -591,12 +591,11 @@ static void dw_mci_edmac_complete_dma(void *arg) dev_vdbg(host->dev, "DMA complete\n"); - if(data->flags & MMC_DATA_READ) - { - /* Invalidate cache after read */ - dma_sync_sg_for_cpu(mmc_dev(host->mmc), data->sg, - data->sg_len, DMA_FROM_DEVICE); - } + if(data) + if(data->flags & MMC_DATA_READ) + /* Invalidate cache after read */ + dma_sync_sg_for_cpu(mmc_dev(host->mmc), data->sg, + data->sg_len, DMA_FROM_DEVICE); host->dma_ops->cleanup(host); @@ -1059,7 +1058,7 @@ static void dw_mci_setup_bus(struct dw_mci_slot *slot, bool force_clkinit) MMC_DBG_BOOT_FUNC(host->mmc, "dw_mci_setup_bus: argue clk_mmc workaround out %dHz for init[%s]", clock * 2, mmc_hostname(host->mmc)); - /* RK3288 clk_mmc will change parents to 24MHz xtal*/ + /* clk_mmc will change parents to 24MHz xtal*/ clk_set_rate(host->clk_mmc, clock * 2); div = 0; @@ -1673,21 +1672,31 @@ enum{ }; static void dw_mci_do_grf_io_domain_switch(struct dw_mci *host, u32 voltage) { - if(cpu_is_rk3288()){ - if(voltage == IO_DOMAIN_33) + switch(voltage){ + case IO_DOMAIN_33: voltage = 0; - else if(voltage == IO_DOMAIN_18) + break; + case IO_DOMAIN_18: voltage = 1; - else - MMC_DBG_ERR_FUNC(host->mmc,"%s : err io domain voltage [%s]\n", - __FUNCTION__, mmc_hostname(host->mmc)); + break; + case IO_DOMAIN_12: + MMC_DBG_ERR_FUNC(host->mmc,"%s : Not support io domain voltage [%s]\n", + __FUNCTION__, mmc_hostname(host->mmc)); + break; + default: + MMC_DBG_ERR_FUNC(host->mmc,"%s : Err io domain voltage [%s]\n", + __FUNCTION__, mmc_hostname(host->mmc)); + break; + } + + if(cpu_is_rk3288()){ if(host->mmc->restrict_caps & RESTRICT_CARD_TYPE_SD) grf_writel((voltage << 7) | (1 << 23), RK3288_GRF_IO_VSEL); else return ; }else{ - MMC_DBG_ERR_FUNC(host->mmc,"%s : unknown chip [%s]\n", - __FUNCTION__, mmc_hostname(host->mmc)); + MMC_DBG_ERR_FUNC(host->mmc,"%s : unknown chip [%s]\n", + __FUNCTION__, mmc_hostname(host->mmc)); } } @@ -1823,6 +1832,13 @@ static int dw_mci_execute_tuning(struct mmc_host *mmc, u32 opcode) struct dw_mci_tuning_data tuning_data; int err = -ENOSYS; + /* Fixme: 3036/3126 doesn't support 1.8 io domain, no sense exe tuning + if(cpu_is_3036() || cpu_is_3126()) + return ENOSYS; + AND + what about audi-b? + */ + if (opcode == MMC_SEND_TUNING_BLOCK_HS200) { if (mmc->ios.bus_width == MMC_BUS_WIDTH_8) { tuning_data.blk_pattern = tuning_blk_pattern_8bit; @@ -3905,30 +3921,38 @@ int dw_mci_resume(struct dw_mci *host) /*only for sdmmc controller*/ if(host->mmc->restrict_caps & RESTRICT_CARD_TYPE_SD) { disable_irq_wake(host->mmc->slot.cd_irq); - mmc_gpio_free_cd(host->mmc); + mmc_gpio_free_cd(host->mmc); if(pinctrl_select_state(host->pinctrl, host->pins_default) < 0) MMC_DBG_ERR_FUNC(host->mmc, "Default pinctrl setting failed! [%s]", mmc_hostname(host->mmc)); host->mmc->rescan_disable = 0; - if(cpu_is_rk3288()) { - grf_writel(((1<<12)<<16)|(0<<12), RK3288_GRF_SOC_CON0);//disable jtag - } - } - if (host->vmmc) { + /* Disable jtag*/ + if(cpu_is_rk3288()) + grf_writel(((1 << 12) << 16) | (0 << 12), RK3288_GRF_SOC_CON0); + /* + else if(cpu_is_rk3036()) + grf_writel(((1 << 11) << 16) | (0 << 11), RK3036_GRF_SOC_CON0); + else if(cpu_is_rk3126()) + TODO; + else if audi-b + TODO; + */ + } + if(host->vmmc){ ret = regulator_enable(host->vmmc); - if (ret) { + if (ret){ dev_err(host->dev, "failed to enable regulator: %d\n", ret); return ret; } } - if (!dw_mci_ctrl_all_reset(host)) { + if(!dw_mci_ctrl_all_reset(host)){ ret = -ENODEV; return ret; } - if (host->use_dma && host->dma_ops->init) + if(host->use_dma && host->dma_ops->init) host->dma_ops->init(host); /* @@ -3948,21 +3972,20 @@ int dw_mci_resume(struct dw_mci *host) mci_writel(host, INTMASK, regs); mci_writel(host, CTRL, SDMMC_CTRL_INT_ENABLE); /*only for sdmmc controller*/ - if((host->mmc->restrict_caps & RESTRICT_CARD_TYPE_SD)&& (!retry_cnt)) { + if((host->mmc->restrict_caps & RESTRICT_CARD_TYPE_SD)&& (!retry_cnt)){ enable_irq(host->irq); } - - for (i = 0; i < host->num_slots; i++) { + for(i = 0; i < host->num_slots; i++){ struct dw_mci_slot *slot = host->slot[i]; - if (!slot) + if(!slot) continue; - if (slot->mmc->pm_flags & MMC_PM_KEEP_POWER) { + if(slot->mmc->pm_flags & MMC_PM_KEEP_POWER){ dw_mci_set_ios(slot->mmc, &slot->mmc->ios); dw_mci_setup_bus(slot, true); } } - + return 0; } EXPORT_SYMBOL(dw_mci_resume); -- 2.34.1