diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-10-28 09:33:42 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-10-28 09:33:42 -0700 |
commit | 00ebb6382b8d9c7c15b5f8ad230670d8161d38dd (patch) | |
tree | 23591394b83776953aaf0b382d4c7b09e0ca1e34 /drivers/mmc/host/mmc_spi.c | |
parent | 11cc21f5f5575b9abd14d53a6055ccbf72b67573 (diff) | |
parent | 536ac998f6076a0ae423b1046b85d7690e8b7107 (diff) | |
download | talos-op-linux-00ebb6382b8d9c7c15b5f8ad230670d8161d38dd.tar.gz talos-op-linux-00ebb6382b8d9c7c15b5f8ad230670d8161d38dd.zip |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/cjb/mmc
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/cjb/mmc: (66 commits)
mmc: add new sdhci-pxa driver for Marvell SoCs
mmc: make number of mmcblk minors configurable
mmc_spi: Recover from CRC errors for r/w operation over SPI.
mmc: sdhci-pltfm: add -pltfm driver for imx35/51
mmc: sdhci-of-esdhc: factor out common stuff
mmc: sdhci_pltfm: pass more data on custom init call
mmc: sdhci: introduce get_ro private write-protect hook
mmc: sdhci-pltfm: move .h file into appropriate subdir
mmc: sdhci-pltfm: Add structure for host-specific data
mmc: fix cb710 kconfig dependency warning
mmc: cb710: remove debugging printk (info duplicated from mmc-core)
mmc: cb710: clear irq handler on init() error path
mmc: cb710: remove unnecessary msleep()
mmc: cb710: implement get_cd() callback
mmc: cb710: partially demystify clock selection
mmc: add a file to debugfs for changing host clock at runtime
mmc: sdhci: allow for eMMC 74 clock generation by controller
mmc: sdhci: highspeed: check for mmc as well as sd cards
mmc: sdhci: Add Moorestown device support
mmc: sdhci: Intel Medfield support
...
Diffstat (limited to 'drivers/mmc/host/mmc_spi.c')
-rw-r--r-- | drivers/mmc/host/mmc_spi.c | 24 |
1 files changed, 22 insertions, 2 deletions
diff --git a/drivers/mmc/host/mmc_spi.c b/drivers/mmc/host/mmc_spi.c index 62a35822003e..fd877f633dd2 100644 --- a/drivers/mmc/host/mmc_spi.c +++ b/drivers/mmc/host/mmc_spi.c @@ -1055,6 +1055,8 @@ static void mmc_spi_request(struct mmc_host *mmc, struct mmc_request *mrq) { struct mmc_spi_host *host = mmc_priv(mmc); int status = -EINVAL; + int crc_retry = 5; + struct mmc_command stop; #ifdef DEBUG /* MMC core and layered drivers *MUST* issue SPI-aware commands */ @@ -1087,10 +1089,29 @@ static void mmc_spi_request(struct mmc_host *mmc, struct mmc_request *mrq) /* request exclusive bus access */ spi_bus_lock(host->spi->master); +crc_recover: /* issue command; then optionally data and stop */ status = mmc_spi_command_send(host, mrq, mrq->cmd, mrq->data != NULL); if (status == 0 && mrq->data) { mmc_spi_data_do(host, mrq->cmd, mrq->data, mrq->data->blksz); + + /* + * The SPI bus is not always reliable for large data transfers. + * If an occasional crc error is reported by the SD device with + * data read/write over SPI, it may be recovered by repeating + * the last SD command again. The retry count is set to 5 to + * ensure the driver passes stress tests. + */ + if (mrq->data->error == -EILSEQ && crc_retry) { + stop.opcode = MMC_STOP_TRANSMISSION; + stop.arg = 0; + stop.flags = MMC_RSP_SPI_R1B | MMC_RSP_R1B | MMC_CMD_AC; + status = mmc_spi_command_send(host, mrq, &stop, 0); + crc_retry--; + mrq->data->error = 0; + goto crc_recover; + } + if (mrq->stop) status = mmc_spi_command_send(host, mrq, mrq->stop, 0); else @@ -1345,8 +1366,7 @@ static int mmc_spi_probe(struct spi_device *spi) mmc->ops = &mmc_spi_ops; mmc->max_blk_size = MMC_SPI_BLOCKSIZE; - mmc->max_hw_segs = MMC_SPI_BLOCKSATONCE; - mmc->max_phys_segs = MMC_SPI_BLOCKSATONCE; + mmc->max_segs = MMC_SPI_BLOCKSATONCE; mmc->max_req_size = MMC_SPI_BLOCKSATONCE * MMC_SPI_BLOCKSIZE; mmc->max_blk_count = MMC_SPI_BLOCKSATONCE; |