Commit a57f14ba authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'mmc-v4.2' of git://git.linaro.org/people/ulf.hansson/mmc

Pull MMC updates from Ulf Hansson:
 "Here are the changes for MMC for v4.2.

  MMC core:
   - Fix an error path in the mmc block layer
   - Fix PM domain attachment for the SDIO bus
   - Add support for driver strength selection
   - Increase a delay to let voltage stabilize
   - Add support for disabling write-protect detection
   - Add facility to support re-tuning
   - Re-tune and retry in the recovery path
   - Add reset option for SDIO
   - Consolidations and clean-ups

  MMC host:
   - Add Mediatek MMC driver
   - Constify platform_device_id for a couple of hosts
   - Fix modalias to make module auto-loading work for a couple of hosts
   - sdhci: Add support for sdhci-arasan4.9a
   - sdhci: Fix low memory corruption
   - sdhci: Restore behavior while creating OCR mask
   - sdhci: Add a callback to select drive strength
   - sdhci: Fix driver type B and D handling
   - sdhci: Add support for drive strength selection for SPT
   - sdhci: Enable HS400 for some Intel host controllers
   - sdhci: Convert to use the new re-tuning facility
   - sdhci: Various minor fixes and clean-ups
   - dw_mmc: Add support for hi6220
   - dw_mmc: Use core to handle absent write protect line
   - dw_mmc: Add support to switch voltage
   - tmio: Some fixes and modernizations
   - sh_mmcif: Improve clock rate calculation"

* tag 'mmc-v4.2' of git://git.linaro.org/people/ulf.hansson/mmc: (98 commits)
  mmc: queue: prevent soft lockups on PREEMPT=n
  mmc: mediatek: Add PM support for MMC driver
  mmc: mediatek: Add Mediatek MMC driver
  mmc: dt-bindings: add Mediatek MMC bindings
  mmc: card: Fixup request missing in mmc_blk_issue_rw_rq
  mmc: sdhci: fix low memory corruption
  mmc: sdhci-pci: Change AMD SDHCI quirk application scope
  i2c-piix4: Use Macro for AMD CZ SMBus device ID
  pci_ids: Add AMD KERNCZ device ID support
  mmc: queue: use swap() in mmc_queue_thread()
  mmc: dw_mmc: insmod followed by rmmod will hung for eMMC
  mmc: sdhci: Restore behavior while creating OCR mask
  mmc: sdhci-pxav3: fix device wakeup initialization
  mmc: core: Attach PM domain prior probing of SDIO func driver
  mmc: core: Remove redundant ->power_restore() callback for SD
  mmc: core: Remove redundant ->power_restore() callback for MMC
  mmc: sdhci-bcm2835: Actually enable the clock
  mmc: sdhci-bcm2835: Clean up platform allocations if sdhci init fails.
  mmc: sdhci-of-esdhc: enable interrupt mode to detect card
  mmc: sdhci-esdhc-imx: add quirk SDHCI_QUIRK2_BROKEN_HS200 for imx6qdl
  ...
parents 10b4b096 a8c27c0b
......@@ -8,7 +8,8 @@ Device Tree Bindings for the Arasan SDHCI Controller
[3] Documentation/devicetree/bindings/interrupt-controller/interrupts.txt
Required Properties:
- compatible: Compatibility string. Must be 'arasan,sdhci-8.9a'
- compatible: Compatibility string. Must be 'arasan,sdhci-8.9a' or
'arasan,sdhci-4.9a'
- reg: From mmc bindings: Register location and length.
- clocks: From clock bindings: Handles to clock inputs.
- clock-names: From clock bindings: Tuple including "clk_xin" and "clk_ahb"
......
......@@ -7,7 +7,14 @@ This file documents differences between the core properties described
by mmc.txt and the properties used by the sdhci-esdhc-imx driver.
Required properties:
- compatible : Should be "fsl,<chip>-esdhc"
- compatible : Should be "fsl,<chip>-esdhc", the supported chips include
"fsl,imx25-esdhc"
"fsl,imx35-esdhc"
"fsl,imx51-esdhc"
"fsl,imx53-esdhc"
"fsl,imx6q-usdhc"
"fsl,imx6sl-usdhc"
"fsl,imx6sx-usdhc"
Optional properties:
- fsl,cd-controller : Indicate to use controller internal card detection
......
......@@ -13,6 +13,10 @@ Required Properties:
* compatible: should be one of the following.
- "hisilicon,hi4511-dw-mshc": for controllers with hi4511 specific extensions.
- "hisilicon,hi6220-dw-mshc": for controllers with hi6220 specific extensions.
Optional Properties:
- hisilicon,peripheral-syscon: phandle of syscon used to control peripheral.
Example:
......@@ -42,3 +46,27 @@ Example:
cap-mmc-highspeed;
cap-sd-highspeed;
};
/* for Hi6220 */
dwmmc_1: dwmmc1@f723e000 {
compatible = "hisilicon,hi6220-dw-mshc";
num-slots = <0x1>;
bus-width = <0x4>;
disable-wp;
cap-sd-highspeed;
sd-uhs-sdr12;
sd-uhs-sdr25;
card-detect-delay = <200>;
hisilicon,peripheral-syscon = <&ao_ctrl>;
reg = <0x0 0xf723e000 0x0 0x1000>;
interrupts = <0x0 0x49 0x4>;
clocks = <&clock_sys HI6220_MMC1_CIUCLK>, <&clock_sys HI6220_MMC1_CLK>;
clock-names = "ciu", "biu";
cd-gpios = <&gpio1 0 1>;
pinctrl-names = "default", "idle";
pinctrl-0 = <&sd_pmx_func &sd_clk_cfg_func &sd_cfg_func>;
pinctrl-1 = <&sd_pmx_idle &sd_clk_cfg_idle &sd_cfg_idle>;
vqmmc-supply = <&ldo7>;
vmmc-supply = <&ldo10>;
};
......@@ -21,5 +21,7 @@ Example:
sdhci0_pwrseq {
compatible = "mmc-pwrseq-simple";
reset-gpios = <&gpio1 12 0>;
reset-gpios = <&gpio1 12 GPIO_ACTIVE_LOW>;
clocks = <&clk_32768_ck>;
clock-names = "ext_clock";
}
......@@ -21,6 +21,11 @@ Optional properties:
below for the case, when a GPIO is used for the CD line
- wp-inverted: when present, polarity on the WP line is inverted. See the note
below for the case, when a GPIO is used for the WP line
- disable-wp: When set no physical WP line is present. This property should
only be specified when the controller has a dedicated write-protect
detection logic. If a GPIO is always used for the write-protect detection
logic it is sufficient to not specify wp-gpios property in the absence of a WP
line.
- max-frequency: maximum operating clock frequency
- no-1-8-v: when present, denotes that 1.8v card voltage is not supported on
this system, even if the controller claims it is.
......
* MTK MMC controller
The MTK MSDC can act as a MMC controller
to support MMC, SD, and SDIO types of memory cards.
This file documents differences between the core properties in mmc.txt
and the properties used by the msdc driver.
Required properties:
- compatible: Should be "mediatek,mt8173-mmc","mediatek,mt8135-mmc"
- interrupts: Should contain MSDC interrupt number
- clocks: MSDC source clock, HCLK
- clock-names: "source", "hclk"
- pinctrl-names: should be "default", "state_uhs"
- pinctrl-0: should contain default/high speed pin ctrl
- pinctrl-1: should contain uhs mode pin ctrl
- vmmc-supply: power to the Core
- vqmmc-supply: power to the IO
Examples:
mmc0: mmc@11230000 {
compatible = "mediatek,mt8173-mmc", "mediatek,mt8135-mmc";
reg = <0 0x11230000 0 0x108>;
interrupts = <GIC_SPI 39 IRQ_TYPE_LEVEL_LOW>;
vmmc-supply = <&mt6397_vemc_3v3_reg>;
vqmmc-supply = <&mt6397_vio18_reg>;
clocks = <&pericfg CLK_PERI_MSDC30_0>, <&topckgen CLK_TOP_MSDC50_0_H_SEL>;
clock-names = "source", "hclk";
pinctrl-names = "default", "state_uhs";
pinctrl-0 = <&mmc0_pins_default>;
pinctrl-1 = <&mmc0_pins_uhs>;
};
......@@ -18,6 +18,8 @@ Required properties:
dma-names property.
- dma-names: must contain "tx" for the transmit DMA channel and "rx" for the
receive DMA channel.
- max-frequency: Maximum operating clock frequency, driver uses default clock
frequency if it is not set.
Example: R8A7790 (R-Car H2) MMCIF0
......@@ -29,4 +31,5 @@ Example: R8A7790 (R-Car H2) MMCIF0
clocks = <&mstp3_clks R8A7790_CLK_MMCIF0>;
dmas = <&dmac0 0xd1>, <&dmac0 0xd2>;
dma-names = "tx", "rx";
max-frequency = <97500000>;
};
......@@ -10033,7 +10033,7 @@ F: include/linux/toshiba.h
F: include/uapi/linux/toshiba.h
TMIO MMC DRIVER
M: Ian Molton <ian.molton@codethink.co.uk>
M: Ian Molton <ian@mnementh.co.uk>
L: linux-mmc@vger.kernel.org
S: Maintained
F: drivers/mmc/host/tmio_mmc*
......
......@@ -370,6 +370,7 @@
/include/ "qoriq-esdhc-0.dtsi"
sdhc@114000 {
compatible = "fsl,p2041-esdhc", "fsl,esdhc";
fsl,iommu-parent = <&pamu1>;
fsl,liodn-reg = <&guts 0x530>; /* eSDHCLIODNR */
sdhci,auto-cmd12;
......
......@@ -397,6 +397,7 @@
/include/ "qoriq-esdhc-0.dtsi"
sdhc@114000 {
compatible = "fsl,p3041-esdhc", "fsl,esdhc";
fsl,iommu-parent = <&pamu1>;
fsl,liodn-reg = <&guts 0x530>; /* eSDHCLIODNR */
sdhci,auto-cmd12;
......
......@@ -469,6 +469,7 @@
/include/ "qoriq-esdhc-0.dtsi"
sdhc@114000 {
compatible = "fsl,p4080-esdhc", "fsl,esdhc";
fsl,iommu-parent = <&pamu1>;
fsl,liodn-reg = <&guts 0x530>; /* eSDHCLIODNR */
voltage-ranges = <3300 3300>;
......
......@@ -384,6 +384,7 @@
/include/ "qoriq-esdhc-0.dtsi"
sdhc@114000 {
compatible = "fsl,p5020-esdhc", "fsl,esdhc";
fsl,iommu-parent = <&pamu1>;
fsl,liodn-reg = <&guts 0x530>; /* eSDHCLIODNR */
sdhci,auto-cmd12;
......
......@@ -362,6 +362,7 @@
/include/ "qoriq-esdhc-0.dtsi"
sdhc@114000 {
compatible = "fsl,p5040-esdhc", "fsl,esdhc";
fsl,iommu-parent = <&pamu2>;
fsl,liodn-reg = <&guts 0x530>; /* eSDHCLIODNR */
sdhci,auto-cmd12;
......
......@@ -245,7 +245,7 @@ static int piix4_setup_sb800(struct pci_dev *PIIX4_dev,
PIIX4_dev->device == PCI_DEVICE_ID_AMD_HUDSON2_SMBUS &&
PIIX4_dev->revision >= 0x41) ||
(PIIX4_dev->vendor == PCI_VENDOR_ID_AMD &&
PIIX4_dev->device == 0x790b &&
PIIX4_dev->device == PCI_DEVICE_ID_AMD_KERNCZ_SMBUS &&
PIIX4_dev->revision >= 0x49))
smb_en = 0x00;
else
......@@ -545,7 +545,7 @@ static const struct pci_device_id piix4_ids[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP400_SMBUS) },
{ PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_SBX00_SMBUS) },
{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_HUDSON2_SMBUS) },
{ PCI_DEVICE(PCI_VENDOR_ID_AMD, 0x790b) },
{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_KERNCZ_SMBUS) },
{ PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS,
PCI_DEVICE_ID_SERVERWORKS_OSB4) },
{ PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS,
......
......@@ -913,6 +913,9 @@ static int mmc_blk_cmd_recovery(struct mmc_card *card, struct request *req,
if (!err)
break;
/* Re-tune if needed */
mmc_retune_recheck(card->host);
prev_cmd_status_valid = false;
pr_err("%s: error %d sending status command, %sing\n",
req->rq_disk->disk_name, err, retry ? "retry" : "abort");
......@@ -1204,6 +1207,7 @@ static int mmc_blk_err_check(struct mmc_card *card,
mmc_active);
struct mmc_blk_request *brq = &mq_mrq->brq;
struct request *req = mq_mrq->req;
int need_retune = card->host->need_retune;
int ecc_err = 0, gen_err = 0;
/*
......@@ -1271,6 +1275,12 @@ static int mmc_blk_err_check(struct mmc_card *card,
}
if (brq->data.error) {
if (need_retune && !brq->retune_retry_done) {
pr_info("%s: retrying because a re-tune was needed\n",
req->rq_disk->disk_name);
brq->retune_retry_done = 1;
return MMC_BLK_RETRY;
}
pr_err("%s: error %d transferring data, sector %u, nr %u, cmd response %#x, card status %#x\n",
req->rq_disk->disk_name, brq->data.error,
(unsigned)blk_rq_pos(req),
......@@ -1830,7 +1840,7 @@ static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *rqc)
struct mmc_blk_data *md = mq->data;
struct mmc_card *card = md->queue.card;
struct mmc_blk_request *brq = &mq->mqrq_cur->brq;
int ret = 1, disable_multi = 0, retry = 0, type;
int ret = 1, disable_multi = 0, retry = 0, type, retune_retry_done = 0;
enum mmc_blk_status status;
struct mmc_queue_req *mq_rq;
struct request *req = rqc;
......@@ -1910,10 +1920,13 @@ static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *rqc)
break;
case MMC_BLK_CMD_ERR:
ret = mmc_blk_cmd_err(md, card, brq, req, ret);
if (!mmc_blk_reset(md, card->host, type))
break;
goto cmd_abort;
if (mmc_blk_reset(md, card->host, type))
goto cmd_abort;
if (!ret)
goto start_new_req;
break;
case MMC_BLK_RETRY:
retune_retry_done = brq->retune_retry_done;
if (retry++ < 5)
break;
/* Fall through */
......@@ -1976,6 +1989,7 @@ static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *rqc)
mmc_start_req(card->host,
&mq_rq->mmc_active, NULL);
}
mq_rq->brq.retune_retry_done = retune_retry_done;
}
} while (ret);
......@@ -2217,7 +2231,8 @@ static struct mmc_blk_data *mmc_blk_alloc(struct mmc_card *card)
* The CSD capacity field is in units of read_blkbits.
* set_capacity takes units of 512 bytes.
*/
size = card->csd.capacity << (card->csd.read_blkbits - 9);
size = (typeof(sector_t))card->csd.capacity
<< (card->csd.read_blkbits - 9);
}
return mmc_blk_alloc_req(card, &card->dev, size, false, NULL,
......
......@@ -268,8 +268,6 @@ static int mmc_test_wait_busy(struct mmc_test_card *test)
static int mmc_test_buffer_transfer(struct mmc_test_card *test,
u8 *buffer, unsigned addr, unsigned blksz, int write)
{
int ret;
struct mmc_request mrq = {0};
struct mmc_command cmd = {0};
struct mmc_command stop = {0};
......@@ -292,11 +290,7 @@ static int mmc_test_buffer_transfer(struct mmc_test_card *test,
if (data.error)
return data.error;
ret = mmc_test_wait_busy(test);
if (ret)
return ret;
return 0;
return mmc_test_wait_busy(test);
}
static void mmc_test_free_mem(struct mmc_test_mem *mem)
......@@ -826,9 +820,7 @@ static int mmc_test_nonblock_transfer(struct mmc_test_card *test,
mmc_test_nonblock_reset(&mrq1, &cmd1,
&stop1, &data1);
}
done_areq = cur_areq;
cur_areq = other_areq;
other_areq = done_areq;
swap(cur_areq, other_areq);
dev_addr += blocks;
}
......@@ -994,11 +986,7 @@ static int mmc_test_basic_write(struct mmc_test_card *test)
sg_init_one(&sg, test->buffer, 512);
ret = mmc_test_simple_transfer(test, &sg, 1, 0, 1, 512, 1);
if (ret)
return ret;
return 0;
return mmc_test_simple_transfer(test, &sg, 1, 0, 1, 512, 1);
}
static int mmc_test_basic_read(struct mmc_test_card *test)
......@@ -1012,44 +1000,29 @@ static int mmc_test_basic_read(struct mmc_test_card *test)
sg_init_one(&sg, test->buffer, 512);
ret = mmc_test_simple_transfer(test, &sg, 1, 0, 1, 512, 0);
if (ret)
return ret;
return 0;
return mmc_test_simple_transfer(test, &sg, 1, 0, 1, 512, 0);
}
static int mmc_test_verify_write(struct mmc_test_card *test)
{
int ret;
struct scatterlist sg;
sg_init_one(&sg, test->buffer, 512);
ret = mmc_test_transfer(test, &sg, 1, 0, 1, 512, 1);
if (ret)
return ret;
return 0;
return mmc_test_transfer(test, &sg, 1, 0, 1, 512, 1);
}
static int mmc_test_verify_read(struct mmc_test_card *test)
{
int ret;
struct scatterlist sg;
sg_init_one(&sg, test->buffer, 512);
ret = mmc_test_transfer(test, &sg, 1, 0, 1, 512, 0);
if (ret)
return ret;
return 0;
return mmc_test_transfer(test, &sg, 1, 0, 1, 512, 0);
}
static int mmc_test_multi_write(struct mmc_test_card *test)
{
int ret;
unsigned int size;
struct scatterlist sg;
......@@ -1066,16 +1039,11 @@ static int mmc_test_multi_write(struct mmc_test_card *test)
sg_init_one(&sg, test->buffer, size);
ret = mmc_test_transfer(test, &sg, 1, 0, size/512, 512, 1);
if (ret)
return ret;
return 0;
return mmc_test_transfer(test, &sg, 1, 0, size/512, 512, 1);
}
static int mmc_test_multi_read(struct mmc_test_card *test)
{
int ret;
unsigned int size;
struct scatterlist sg;
......@@ -1092,11 +1060,7 @@ static int mmc_test_multi_read(struct mmc_test_card *test)
sg_init_one(&sg, test->buffer, size);
ret = mmc_test_transfer(test, &sg, 1, 0, size/512, 512, 0);
if (ret)
return ret;
return 0;
return mmc_test_transfer(test, &sg, 1, 0, size/512, 512, 0);
}
static int mmc_test_pow2_write(struct mmc_test_card *test)
......@@ -1263,11 +1227,7 @@ static int mmc_test_xfersize_write(struct mmc_test_card *test)
if (ret)
return ret;
ret = mmc_test_broken_transfer(test, 1, 512, 1);
if (ret)
return ret;
return 0;
return mmc_test_broken_transfer(test, 1, 512, 1);
}
static int mmc_test_xfersize_read(struct mmc_test_card *test)
......@@ -1278,11 +1238,7 @@ static int mmc_test_xfersize_read(struct mmc_test_card *test)
if (ret)
return ret;
ret = mmc_test_broken_transfer(test, 1, 512, 0);
if (ret)
return ret;
return 0;
return mmc_test_broken_transfer(test, 1, 512, 0);
}
static int mmc_test_multi_xfersize_write(struct mmc_test_card *test)
......@@ -1296,11 +1252,7 @@ static int mmc_test_multi_xfersize_write(struct mmc_test_card *test)
if (ret)
return ret;
ret = mmc_test_broken_transfer(test, 2, 512, 1);
if (ret)
return ret;
return 0;
return mmc_test_broken_transfer(test, 2, 512, 1);
}
static int mmc_test_multi_xfersize_read(struct mmc_test_card *test)
......@@ -1314,48 +1266,33 @@ static int mmc_test_multi_xfersize_read(struct mmc_test_card *test)
if (ret)
return ret;
ret = mmc_test_broken_transfer(test, 2, 512, 0);
if (ret)
return ret;
return 0;
return mmc_test_broken_transfer(test, 2, 512, 0);
}
#ifdef CONFIG_HIGHMEM
static int mmc_test_write_high(struct mmc_test_card *test)
{
int ret;
struct scatterlist sg;
sg_init_table(&sg, 1);
sg_set_page(&sg, test->highmem, 512, 0);
ret = mmc_test_transfer(test, &sg, 1, 0, 1, 512, 1);
if (ret)
return ret;
return 0;
return mmc_test_transfer(test, &sg, 1, 0, 1, 512, 1);
}
static int mmc_test_read_high(struct mmc_test_card *test)
{
int ret;
struct scatterlist sg;
sg_init_table(&sg, 1);
sg_set_page(&sg, test->highmem, 512, 0);
ret = mmc_test_transfer(test, &sg, 1, 0, 1, 512, 0);
if (ret)
return ret;
return 0;
return mmc_test_transfer(test, &sg, 1, 0, 1, 512, 0);
}
static int mmc_test_multi_write_high(struct mmc_test_card *test)
{
int ret;
unsigned int size;
struct scatterlist sg;
......@@ -1373,16 +1310,11 @@ static int mmc_test_multi_write_high(struct mmc_test_card *test)
sg_init_table(&sg, 1);
sg_set_page(&sg, test->highmem, size, 0);
ret = mmc_test_transfer(test, &sg, 1, 0, size/512, 512, 1);
if (ret)
return ret;
return 0;
return mmc_test_transfer(test, &sg, 1, 0, size/512, 512, 1);
}
static int mmc_test_multi_read_high(struct mmc_test_card *test)
{
int ret;
unsigned int size;
struct scatterlist sg;
......@@ -1400,11 +1332,7 @@ static int mmc_test_multi_read_high(struct mmc_test_card *test)
sg_init_table(&sg, 1);
sg_set_page(&sg, test->highmem, size, 0);
ret = mmc_test_transfer(test, &sg, 1, 0, size/512, 512, 0);
if (ret)
return ret;
return 0;
return mmc_test_transfer(test, &sg, 1, 0, size/512, 512, 0);
}
#else
......
......@@ -56,7 +56,6 @@ static int mmc_queue_thread(void *d)
down(&mq->thread_sem);
do {
struct request *req = NULL;
struct mmc_queue_req *tmp;
unsigned int cmd_flags = 0;
spin_lock_irq(q->queue_lock);
......@@ -69,6 +68,7 @@ static int mmc_queue_thread(void *d)
set_current_state(TASK_RUNNING);
cmd_flags = req ? req->cmd_flags : 0;
mq->issue_fn(mq, req);
cond_resched();
if (mq->flags & MMC_QUEUE_NEW_REQUEST) {
mq->flags &= ~MMC_QUEUE_NEW_REQUEST;
continue; /* fetch again */
......@@ -86,9 +86,7 @@ static int mmc_queue_thread(void *d)
mq->mqrq_prev->brq.mrq.data = NULL;
mq->mqrq_prev->req = NULL;
tmp = mq->mqrq_prev;
mq->mqrq_prev = mq->mqrq_cur;
mq->mqrq_cur = tmp;
swap(mq->mqrq_prev, mq->mqrq_cur);
} else {
if (kthread_should_stop()) {
set_current_state(TASK_RUNNING);
......
......@@ -12,6 +12,7 @@ struct mmc_blk_request {
struct mmc_command cmd;
struct mmc_command stop;
struct mmc_data data;
int retune_retry_done;
};
enum mmc_packed_type {
......
......@@ -133,6 +133,12 @@ void mmc_request_done(struct mmc_host *host, struct mmc_request *mrq)
struct mmc_command *cmd = mrq->cmd;
int err = cmd->error;
/* Flag re-tuning needed on CRC errors */
if (err == -EILSEQ || (mrq->sbc && mrq->sbc->error == -EILSEQ) ||
(mrq->data && mrq->data->error == -EILSEQ) ||
(mrq->stop && mrq->stop->error == -EILSEQ))
mmc_retune_needed(host);
if (err && cmd->retries && mmc_host_is_spi(host)) {
if (cmd->resp[0] & R1_SPI_ILLEGAL_COMMAND)
cmd->retries = 0;
......@@ -186,12 +192,29 @@ void mmc_request_done(struct mmc_host *host, struct mmc_request *mrq)
EXPORT_SYMBOL(mmc_request_done);
static void __mmc_start_request(struct mmc_host *host, struct mmc_request *mrq)
{
int err;
/* Assumes host controller has been runtime resumed by mmc_claim_host */
err = mmc_retune(host);
if (err) {
mrq->cmd->error = err;
mmc_request_done(host, mrq);
return;
}
host->ops->request(host, mrq);
}
static int mmc_start_request(struct mmc_host *host, struct mmc_request *mrq)
{
#ifdef CONFIG_MMC_DEBUG
unsigned int i, sz;
struct scatterlist *sg;
#endif
mmc_retune_hold(host);
if (mmc_card_removed(host->card))
return -ENOMEDIUM;
......@@ -252,7 +275,7 @@ static int mmc_start_request(struct mmc_host *host, struct mmc_request *mrq)
}
mmc_host_clk_hold(host);
led_trigger_event(host->led, LED_FULL);
host->ops->request(host, mrq);
__mmc_start_request(host, mrq);
return 0;
}
......@@ -301,12 +324,15 @@ void mmc_start_bkops(struct mmc_card *card, bool from_exception)
use_busy_signal = false;
}