diff options
Diffstat (limited to 'drivers/mmc')
-rw-r--r-- | drivers/mmc/card/block.c | 82 | ||||
-rw-r--r-- | drivers/mmc/core/core.c | 10 | ||||
-rw-r--r-- | drivers/mmc/core/core.h | 1 | ||||
-rw-r--r-- | drivers/mmc/core/mmc.c | 5 | ||||
-rw-r--r-- | drivers/mmc/core/sd.c | 1 | ||||
-rw-r--r-- | drivers/mmc/core/sdio.c | 1 | ||||
-rw-r--r-- | drivers/mmc/host/atmel-mci.c | 9 | ||||
-rw-r--r-- | drivers/mmc/host/mmci.c | 14 | ||||
-rw-r--r-- | drivers/mmc/host/mxcmmc.c | 1 | ||||
-rw-r--r-- | drivers/mmc/host/sdhci-esdhc-imx.c | 5 | ||||
-rw-r--r-- | drivers/mmc/host/sdhci.c | 6 | ||||
-rw-r--r-- | drivers/mmc/host/vub300.c | 2 |
12 files changed, 82 insertions, 55 deletions
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c index 625bd9e..435f1fd 100644 --- a/drivers/mmc/card/block.c +++ b/drivers/mmc/card/block.c @@ -247,6 +247,9 @@ static struct mmc_blk_ioc_data *mmc_blk_ioctl_copy_from_user( goto idata_err; } + if (!idata->buf_bytes) + return idata; + idata->buf = kzalloc(idata->buf_bytes, GFP_KERNEL); if (!idata->buf) { err = -ENOMEM; @@ -293,25 +296,6 @@ static int mmc_blk_ioctl_cmd(struct block_device *bdev, if (IS_ERR(idata)) return PTR_ERR(idata); - cmd.opcode = idata->ic.opcode; - cmd.arg = idata->ic.arg; - cmd.flags = idata->ic.flags; - - data.sg = &sg; - data.sg_len = 1; - data.blksz = idata->ic.blksz; - data.blocks = idata->ic.blocks; - - sg_init_one(data.sg, idata->buf, idata->buf_bytes); - - if (idata->ic.write_flag) - data.flags = MMC_DATA_WRITE; - else - data.flags = MMC_DATA_READ; - - mrq.cmd = &cmd; - mrq.data = &data; - md = mmc_blk_get(bdev->bd_disk); if (!md) { err = -EINVAL; @@ -324,6 +308,48 @@ static int mmc_blk_ioctl_cmd(struct block_device *bdev, goto cmd_done; } + cmd.opcode = idata->ic.opcode; + cmd.arg = idata->ic.arg; + cmd.flags = idata->ic.flags; + + if (idata->buf_bytes) { + data.sg = &sg; + data.sg_len = 1; + data.blksz = idata->ic.blksz; + data.blocks = idata->ic.blocks; + + sg_init_one(data.sg, idata->buf, idata->buf_bytes); + + if (idata->ic.write_flag) + data.flags = MMC_DATA_WRITE; + else + data.flags = MMC_DATA_READ; + + /* data.flags must already be set before doing this. */ + mmc_set_data_timeout(&data, card); + + /* Allow overriding the timeout_ns for empirical tuning. */ + if (idata->ic.data_timeout_ns) + data.timeout_ns = idata->ic.data_timeout_ns; + + if ((cmd.flags & MMC_RSP_R1B) == MMC_RSP_R1B) { + /* + * Pretend this is a data transfer and rely on the + * host driver to compute timeout. When all host + * drivers support cmd.cmd_timeout for R1B, this + * can be changed to: + * + * mrq.data = NULL; + * cmd.cmd_timeout = idata->ic.cmd_timeout_ms; + */ + data.timeout_ns = idata->ic.cmd_timeout_ms * 1000000; + } + + mrq.data = &data; + } + + mrq.cmd = &cmd; + mmc_claim_host(card->host); if (idata->ic.is_acmd) { @@ -332,24 +358,6 @@ static int mmc_blk_ioctl_cmd(struct block_device *bdev, goto cmd_rel_host; } - /* data.flags must already be set before doing this. */ - mmc_set_data_timeout(&data, card); - /* Allow overriding the timeout_ns for empirical tuning. */ - if (idata->ic.data_timeout_ns) - data.timeout_ns = idata->ic.data_timeout_ns; - - if ((cmd.flags & MMC_RSP_R1B) == MMC_RSP_R1B) { - /* - * Pretend this is a data transfer and rely on the host driver - * to compute timeout. When all host drivers support - * cmd.cmd_timeout for R1B, this can be changed to: - * - * mrq.data = NULL; - * cmd.cmd_timeout = idata->ic.cmd_timeout_ms; - */ - data.timeout_ns = idata->ic.cmd_timeout_ms * 1000000; - } - mmc_wait_for_req(card->host, &mrq); if (cmd.error) { diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index a39acb9..8536095 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -1058,7 +1058,7 @@ static void mmc_power_up(struct mmc_host *host) mmc_host_clk_release(host); } -static void mmc_power_off(struct mmc_host *host) +void mmc_power_off(struct mmc_host *host) { mmc_host_clk_hold(host); @@ -1178,8 +1178,7 @@ void mmc_attach_bus(struct mmc_host *host, const struct mmc_bus_ops *ops) } /* - * Remove the current bus handler from a host. Assumes that there are - * no interesting cards left, so the bus is powered down. + * Remove the current bus handler from a host. */ void mmc_detach_bus(struct mmc_host *host) { @@ -1196,8 +1195,6 @@ void mmc_detach_bus(struct mmc_host *host) spin_unlock_irqrestore(&host->lock, flags); - mmc_power_off(host); - mmc_bus_put(host); } @@ -1723,6 +1720,7 @@ void mmc_stop_host(struct mmc_host *host) mmc_claim_host(host); mmc_detach_bus(host); + mmc_power_off(host); mmc_release_host(host); mmc_bus_put(host); return; @@ -1848,6 +1846,7 @@ int mmc_suspend_host(struct mmc_host *host) host->bus_ops->remove(host); mmc_claim_host(host); mmc_detach_bus(host); + mmc_power_off(host); mmc_release_host(host); host->pm_flags = 0; err = 0; @@ -1946,6 +1945,7 @@ int mmc_pm_notify(struct notifier_block *notify_block, host->bus_ops->remove(host); mmc_detach_bus(host); + mmc_power_off(host); mmc_release_host(host); host->pm_flags = 0; break; diff --git a/drivers/mmc/core/core.h b/drivers/mmc/core/core.h index d9411ed..14664f1 100644 --- a/drivers/mmc/core/core.h +++ b/drivers/mmc/core/core.h @@ -43,6 +43,7 @@ int mmc_set_signal_voltage(struct mmc_host *host, int signal_voltage, bool cmd11); void mmc_set_timing(struct mmc_host *host, unsigned int timing); void mmc_set_driver_type(struct mmc_host *host, unsigned int drv_type); +void mmc_power_off(struct mmc_host *host); static inline void mmc_delay(unsigned int ms) { diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index aa7d1d7..f601180 100644 --- a/drivers/mmc/core/mmc.c +++ b/drivers/mmc/core/mmc.c @@ -359,6 +359,7 @@ static int mmc_read_ext_csd(struct mmc_card *card, u8 *ext_csd) * card has the Enhanced area enabled. If so, export enhanced * area offset and size to user by adding sysfs interface. */ + card->ext_csd.raw_partition_support = ext_csd[EXT_CSD_PARTITION_SUPPORT]; if ((ext_csd[EXT_CSD_PARTITION_SUPPORT] & 0x2) && (ext_csd[EXT_CSD_PARTITION_ATTRIBUTE] & 0x1)) { u8 hc_erase_grp_sz = @@ -405,6 +406,7 @@ static int mmc_read_ext_csd(struct mmc_card *card, u8 *ext_csd) if (card->ext_csd.rev >= 5) card->ext_csd.rel_param = ext_csd[EXT_CSD_WR_REL_PARAM]; + card->ext_csd.raw_erased_mem_count = ext_csd[EXT_CSD_ERASED_MEM_CONT]; if (ext_csd[EXT_CSD_ERASED_MEM_CONT]) card->erased_byte = 0xFF; else @@ -828,7 +830,7 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, * * WARNING: eMMC rules are NOT the same as SD DDR */ - if (ddr == EXT_CSD_CARD_TYPE_DDR_1_2V) { + if (ddr == MMC_1_2V_DDR_MODE) { err = mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_120, 0); if (err) @@ -891,6 +893,7 @@ static void mmc_detect(struct mmc_host *host) mmc_claim_host(host); mmc_detach_bus(host); + mmc_power_off(host); mmc_release_host(host); } } diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c index 5decf49..0635da5 100644 --- a/drivers/mmc/core/sd.c +++ b/drivers/mmc/core/sd.c @@ -1048,6 +1048,7 @@ static void mmc_sd_detect(struct mmc_host *host) mmc_claim_host(host); mmc_detach_bus(host); + mmc_power_off(host); mmc_release_host(host); } } diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c index 7da522e..a2c1c4d 100644 --- a/drivers/mmc/core/sdio.c +++ b/drivers/mmc/core/sdio.c @@ -617,6 +617,7 @@ out: mmc_claim_host(host); mmc_detach_bus(host); + mmc_power_off(host); mmc_release_host(host); } } diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c index aa8039f..b6cd386 100644 --- a/drivers/mmc/host/atmel-mci.c +++ b/drivers/mmc/host/atmel-mci.c @@ -468,7 +468,14 @@ err: static inline unsigned int ns_to_clocks(struct atmel_mci *host, unsigned int ns) { - return (ns * (host->bus_hz / 1000000) + 999) / 1000; + /* + * It is easier here to use us instead of ns for the timeout, + * it prevents from overflows during calculation. + */ + unsigned int us = DIV_ROUND_UP(ns, 1000); + + /* Maximum clock frequency is host->bus_hz/2 */ + return us * (DIV_ROUND_UP(host->bus_hz, 2000000)); } static void atmci_set_timeout(struct atmel_mci *host, diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c index fe14072..9394d0b 100644 --- a/drivers/mmc/host/mmci.c +++ b/drivers/mmc/host/mmci.c @@ -557,7 +557,8 @@ mmci_data_irq(struct mmci_host *host, struct mmc_data *data, unsigned int status) { /* First check for errors */ - if (status & (MCI_DATACRCFAIL|MCI_DATATIMEOUT|MCI_TXUNDERRUN|MCI_RXOVERRUN)) { + if (status & (MCI_DATACRCFAIL|MCI_DATATIMEOUT|MCI_STARTBITERR| + MCI_TXUNDERRUN|MCI_RXOVERRUN)) { u32 remain, success; /* Terminate the DMA transfer */ @@ -636,8 +637,12 @@ mmci_cmd_irq(struct mmci_host *host, struct mmc_command *cmd, } if (!cmd->data || cmd->error) { - if (host->data) + if (host->data) { + /* Terminate the DMA transfer */ + if (dma_inprogress(host)) + mmci_dma_data_error(host); mmci_stop_data(host); + } mmci_request_end(host, cmd->mrq); } else if (!(cmd->data->flags & MMC_DATA_READ)) { mmci_start_data(host, cmd->data); @@ -837,8 +842,9 @@ static irqreturn_t mmci_irq(int irq, void *dev_id) dev_dbg(mmc_dev(host->mmc), "irq0 (data+cmd) %08x\n", status); data = host->data; - if (status & (MCI_DATACRCFAIL|MCI_DATATIMEOUT|MCI_TXUNDERRUN| - MCI_RXOVERRUN|MCI_DATAEND|MCI_DATABLOCKEND) && data) + if (status & (MCI_DATACRCFAIL|MCI_DATATIMEOUT|MCI_STARTBITERR| + MCI_TXUNDERRUN|MCI_RXOVERRUN|MCI_DATAEND| + MCI_DATABLOCKEND) && data) mmci_data_irq(host, data, status); cmd = host->cmd; diff --git a/drivers/mmc/host/mxcmmc.c b/drivers/mmc/host/mxcmmc.c index cc20e02..e12fbc5 100644 --- a/drivers/mmc/host/mxcmmc.c +++ b/drivers/mmc/host/mxcmmc.c @@ -731,6 +731,7 @@ static void mxcmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) "failed to config DMA channel. Falling back to PIO\n"); dma_release_channel(host->dma); host->do_dma = 0; + host->dma = NULL; } } diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c index ba31abe..92e5437 100644 --- a/drivers/mmc/host/sdhci-esdhc-imx.c +++ b/drivers/mmc/host/sdhci-esdhc-imx.c @@ -139,8 +139,9 @@ static void esdhc_writew_le(struct sdhci_host *host, u16 val, int reg) imx_data->scratchpad = val; return; case SDHCI_COMMAND: - if ((host->cmd->opcode == MMC_STOP_TRANSMISSION) - && (imx_data->flags & ESDHC_FLAG_MULTIBLK_NO_INT)) + if ((host->cmd->opcode == MMC_STOP_TRANSMISSION || + host->cmd->opcode == MMC_SET_BLOCK_COUNT) && + (imx_data->flags & ESDHC_FLAG_MULTIBLK_NO_INT)) val |= SDHCI_CMD_ABORTCMD; writel(val << 16 | imx_data->scratchpad, host->ioaddr + SDHCI_TRANSFER_MODE); diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 1536485..862ad52 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -1384,8 +1384,7 @@ static void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) if ((ios->timing == MMC_TIMING_UHS_SDR50) || (ios->timing == MMC_TIMING_UHS_SDR104) || (ios->timing == MMC_TIMING_UHS_DDR50) || - (ios->timing == MMC_TIMING_UHS_SDR25) || - (ios->timing == MMC_TIMING_UHS_SDR12)) + (ios->timing == MMC_TIMING_UHS_SDR25)) ctrl |= SDHCI_CTRL_HISPD; ctrl_2 = sdhci_readw(host, SDHCI_HOST_CONTROL2); @@ -2323,9 +2322,8 @@ int sdhci_suspend_host(struct sdhci_host *host, pm_message_t state) /* Disable tuning since we are suspending */ if (host->version >= SDHCI_SPEC_300 && host->tuning_count && host->tuning_mode == SDHCI_TUNING_MODE_1) { + del_timer_sync(&host->tuning_timer); host->flags &= ~SDHCI_NEEDS_RETUNING; - mod_timer(&host->tuning_timer, jiffies + - host->tuning_count * HZ); } ret = mmc_suspend_host(host->mmc); diff --git a/drivers/mmc/host/vub300.c b/drivers/mmc/host/vub300.c index d4455ff..52f4b64 100644 --- a/drivers/mmc/host/vub300.c +++ b/drivers/mmc/host/vub300.c @@ -259,7 +259,7 @@ static int firmware_rom_wait_states = 0x04; static int firmware_rom_wait_states = 0x1C; #endif -module_param(firmware_rom_wait_states, bool, 0644); +module_param(firmware_rom_wait_states, int, 0644); MODULE_PARM_DESC(firmware_rom_wait_states, "ROM wait states byte=RRRIIEEE (Reserved Internal External)"); |