diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-10-05 11:34:53 -0700 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-10-05 11:34:53 -0700 |
| commit | 64cbd16a8751fde075aa103dc7823a8c05805104 (patch) | |
| tree | 09c6a4f46ceaaa6d949862413a064b7eb5f8c1b6 | |
| parent | edadd0e5a7f9970553423ebd08172c9e3d1fb189 (diff) | |
| parent | 0f75c404503cc49cbe92555fbab80a584c1f4ae2 (diff) | |
| download | linux-64cbd16a8751fde075aa103dc7823a8c05805104.tar.gz linux-64cbd16a8751fde075aa103dc7823a8c05805104.tar.bz2 linux-64cbd16a8751fde075aa103dc7823a8c05805104.zip | |
Merge tag 'mmc-v4.9' of git://git.linaro.org/people/ulf.hansson/mmc
Pull MMC updates from Ulf Hansson:
MMC core:
- Add support for sending commands during data transfer
- Erase/discard/trim improvements
- Improved error handling
- Extend sysfs with SD status register
- Document info about the vmmc/vmmcq regulators
- Extend pwrseq-simple to manage an optional post-power-on-delay
- Some various minor improvements and cleanups
MMC host:
- dw_mmc: Add reset support
- dw_mmc: Return -EILSEQ for EBE and SBE error
- dw_mmc: Some cleanups
- dw_mmc-k3: Add UHS-I support Hisilicon Hikey
- tmio: Add eMMC support
- sh_mobile_sdhi: Add r8a7796 support
- sunxi: Don't use sample clocks for sun4i/sun5i
- sunxi: Add support for A64 mmc controller
- sunxi: Some cleanups and improvements
- sdhci: Support for sending commands during data transfer
- sdhci: Do not allow tuning procedure to be interrupted
- sdhci-pci: Enable SD/SDIO on Merrifield
- sdhci-pci|acpi: Enable MMC_CAP_CMD_DURING_TFR
- sdhci-pci: Some cleanups
- sdhci-of-arasan: Set controller to test mode when no CD bit
- sdhci-of-arasan: Some fixes for clocks and phys
- sdhci-brcmstb: Don't use ADMA 64-bit when not supported
- sdhci-tegra: Mark 64-bit DMA broken on Tegra124
- sdhci-esdhc-imx: Fixups related to data timeouts
* tag 'mmc-v4.9' of git://git.linaro.org/people/ulf.hansson/mmc: (68 commits)
mmc: dw_mmc: remove the deprecated "supports-highspeed" property
mmc: dw_mmc: minor cleanup for dw_mci_adjust_fifoth
mmc: dw_mmc: use macro to define ring buffer size
mmc: dw_mmc: fix misleading error print if failing to do DMA transfer
mmc: dw_mmc: avoid race condition of cpu and IDMAC
mmc: dw_mmc: split out preparation of desc for IDMAC32 and IDMAC64
mmc: core: don't try to switch block size for dual rate mode
mmc: sdhci-of-arasan: Set controller to test mode when no CD bit
dt: sdhci-of-arasan: Add device tree option xlnx, fails-without-test-cd
mmc: tmio: add eMMC support
mmc: rtsx_usb: use new macro for R1 without CRC
mmc: rtsx_pci: use new macro for R1 without CRC
mmc: add define for R1 response without CRC
mmc: card: do away with indirection pointer
mmc: sdhci-acpi: Set MMC_CAP_CMD_DURING_TFR for Intel eMMC controllers
mmc: sdhci-pci: Set MMC_CAP_CMD_DURING_TFR for Intel eMMC controllers
mmc: sdhci: Support cap_cmd_during_tfr requests
mmc: mmc_test: Add tests for sending commands during transfer
mmc: core: Add support for sending commands during data transfer
mmc: sdhci-brcmstb: Fix incorrect capability
...
49 files changed, 1305 insertions, 481 deletions
diff --git a/Documentation/devicetree/bindings/mmc/arasan,sdhci.txt b/Documentation/devicetree/bindings/mmc/arasan,sdhci.txt index 3404afa9b938..49df630bd44f 100644 --- a/Documentation/devicetree/bindings/mmc/arasan,sdhci.txt +++ b/Documentation/devicetree/bindings/mmc/arasan,sdhci.txt @@ -36,6 +36,9 @@ Optional Properties: - #clock-cells: If specified this should be the value <0>. With this property in place we will export a clock representing the Card Clock. This clock is expected to be consumed by our PHY. You must also specify + - xlnx,fails-without-test-cd: when present, the controller doesn't work when + the CD line is not connected properly, and the line is not connected + properly. Test mode can be used to force the controller to function. Example: sdhci@e0100000 { diff --git a/Documentation/devicetree/bindings/mmc/brcm,bcm7425-sdhci.txt b/Documentation/devicetree/bindings/mmc/brcm,sdhci-brcmstb.txt index 82847174c37d..733b64a4d8eb 100644 --- a/Documentation/devicetree/bindings/mmc/brcm,bcm7425-sdhci.txt +++ b/Documentation/devicetree/bindings/mmc/brcm,sdhci-brcmstb.txt @@ -8,7 +8,9 @@ on Device Tree properties to enable them for SoC/Board combinations that support them. Required properties: -- compatible: "brcm,bcm7425-sdhci" +- compatible: should be one of the following + - "brcm,bcm7425-sdhci" + - "brcm,bcm7445-sdhci" Refer to clocks/clock-bindings.txt for generic clock consumer properties. diff --git a/Documentation/devicetree/bindings/mmc/mmc-pwrseq-simple.txt b/Documentation/devicetree/bindings/mmc/mmc-pwrseq-simple.txt index ce0e76749671..e25436861867 100644 --- a/Documentation/devicetree/bindings/mmc/mmc-pwrseq-simple.txt +++ b/Documentation/devicetree/bindings/mmc/mmc-pwrseq-simple.txt @@ -16,6 +16,8 @@ Optional properties: See ../clocks/clock-bindings.txt for details. - clock-names : Must include the following entry: "ext_clock" (External clock provided to the card). +- post-power-on-delay-ms : Delay in ms after powering the card and + de-asserting the reset-gpios (if any) Example: diff --git a/Documentation/devicetree/bindings/mmc/mmc.txt b/Documentation/devicetree/bindings/mmc/mmc.txt index 22d1e1f3f38b..8a377827695b 100644 --- a/Documentation/devicetree/bindings/mmc/mmc.txt +++ b/Documentation/devicetree/bindings/mmc/mmc.txt @@ -75,6 +75,17 @@ Optional SDIO properties: - wakeup-source: Enables wake up of host system on SDIO IRQ assertion (Legacy property supported: "enable-sdio-wakeup") +MMC power +--------- + +Controllers may implement power control from both the connected cards and +the IO signaling (for example to change to high-speed 1.8V signalling). If +the system supports this, then the following two properties should point +to valid regulator nodes: + +- vqmmc-supply: supply node for IO line power +- vmmc-supply: supply node for card's power + MMC power sequences: -------------------- @@ -102,11 +113,13 @@ Required host node properties when using function subnodes: - #size-cells: should be zero. Required function subnode properties: -- compatible: name of SDIO function following generic names recommended practice - reg: Must contain the SDIO function number of the function this subnode describes. A value of 0 denotes the memory SD function, values from 1 to 7 denote the SDIO functions. +Optional function subnode properties: +- compatible: name of SDIO function following generic names recommended practice + Examples -------- diff --git a/Documentation/devicetree/bindings/mmc/sunxi-mmc.txt b/Documentation/devicetree/bindings/mmc/sunxi-mmc.txt index 4bf41d833804..55cdd804cdba 100644 --- a/Documentation/devicetree/bindings/mmc/sunxi-mmc.txt +++ b/Documentation/devicetree/bindings/mmc/sunxi-mmc.txt @@ -8,7 +8,12 @@ as the speed of SD standard 3.0. Absolute maximum transfer rate is 200MB/s Required properties: - - compatible : "allwinner,sun4i-a10-mmc" or "allwinner,sun5i-a13-mmc" + - compatible : should be one of: + * "allwinner,sun4i-a10-mmc" + * "allwinner,sun5i-a13-mmc" + * "allwinner,sun7i-a20-mmc" + * "allwinner,sun9i-a80-mmc" + * "allwinner,sun50i-a64-mmc" - reg : mmc controller base registers - clocks : a list with 4 phandle + clock specifier pairs - clock-names : must contain "ahb", "mmc", "output" and "sample" diff --git a/Documentation/devicetree/bindings/mmc/synopsys-dw-mshc.txt b/Documentation/devicetree/bindings/mmc/synopsys-dw-mshc.txt index 8636f5ae97e5..4e00e859e885 100644 --- a/Documentation/devicetree/bindings/mmc/synopsys-dw-mshc.txt +++ b/Documentation/devicetree/bindings/mmc/synopsys-dw-mshc.txt @@ -39,6 +39,10 @@ Required Properties: Optional properties: +* resets: phandle + reset specifier pair, intended to represent hardware + reset signal present internally in some host controller IC designs. + See Documentation/devicetree/bindings/reset/reset.txt for details. + * clocks: from common clock binding: handle to biu and ciu clocks for the bus interface unit clock and the card interface unit clock. diff --git a/Documentation/devicetree/bindings/mmc/tmio_mmc.txt b/Documentation/devicetree/bindings/mmc/tmio_mmc.txt index 0f610d4b5b00..13df9c2399c3 100644 --- a/Documentation/devicetree/bindings/mmc/tmio_mmc.txt +++ b/Documentation/devicetree/bindings/mmc/tmio_mmc.txt @@ -23,6 +23,7 @@ Required properties: "renesas,sdhi-r8a7793" - SDHI IP on R8A7793 SoC "renesas,sdhi-r8a7794" - SDHI IP on R8A7794 SoC "renesas,sdhi-r8a7795" - SDHI IP on R8A7795 SoC + "renesas,sdhi-r8a7796" - SDHI IP on R8A7796 SoC Optional properties: - toshiba,mmc-wrprotect-disable: write-protect detection is unavailable diff --git a/arch/arm/boot/dts/sun6i-a31.dtsi b/arch/arm/boot/dts/sun6i-a31.dtsi index 1867af24ff52..0d24f107ede0 100644 --- a/arch/arm/boot/dts/sun6i-a31.dtsi +++ b/arch/arm/boot/dts/sun6i-a31.dtsi @@ -469,7 +469,7 @@ }; mmc0: mmc@01c0f000 { - compatible = "allwinner,sun5i-a13-mmc"; + compatible = "allwinner,sun7i-a20-mmc"; reg = <0x01c0f000 0x1000>; clocks = <&ahb1_gates 8>, <&mmc0_clk 0>, @@ -488,7 +488,7 @@ }; mmc1: mmc@01c10000 { - compatible = "allwinner,sun5i-a13-mmc"; + compatible = "allwinner,sun7i-a20-mmc"; reg = <0x01c10000 0x1000>; clocks = <&ahb1_gates 9>, <&mmc1_clk 0>, @@ -507,7 +507,7 @@ }; mmc2: mmc@01c11000 { - compatible = "allwinner,sun5i-a13-mmc"; + compatible = "allwinner,sun7i-a20-mmc"; reg = <0x01c11000 0x1000>; clocks = <&ahb1_gates 10>, <&mmc2_clk 0>, @@ -526,7 +526,7 @@ }; mmc3: mmc@01c12000 { - compatible = "allwinner,sun5i-a13-mmc"; + compatible = "allwinner,sun7i-a20-mmc"; reg = <0x01c12000 0x1000>; clocks = <&ahb1_gates 11>, <&mmc3_clk 0>, diff --git a/arch/arm/boot/dts/sun7i-a20.dtsi b/arch/arm/boot/dts/sun7i-a20.dtsi index bd0c47660243..94cf5a1c7172 100644 --- a/arch/arm/boot/dts/sun7i-a20.dtsi +++ b/arch/arm/boot/dts/sun7i-a20.dtsi @@ -905,7 +905,7 @@ }; mmc0: mmc@01c0f000 { - compatible = "allwinner,sun5i-a13-mmc"; + compatible = "allwinner,sun7i-a20-mmc"; reg = <0x01c0f000 0x1000>; clocks = <&ahb_gates 8>, <&mmc0_clk 0>, @@ -922,7 +922,7 @@ }; mmc1: mmc@01c10000 { - compatible = "allwinner,sun5i-a13-mmc"; + compatible = "allwinner,sun7i-a20-mmc"; reg = <0x01c10000 0x1000>; clocks = <&ahb_gates 9>, <&mmc1_clk 0>, @@ -939,7 +939,7 @@ }; mmc2: mmc@01c11000 { - compatible = "allwinner,sun5i-a13-mmc"; + compatible = "allwinner,sun7i-a20-mmc"; reg = <0x01c11000 0x1000>; clocks = <&ahb_gates 10>, <&mmc2_clk 0>, @@ -956,7 +956,7 @@ }; mmc3: mmc@01c12000 { - compatible = "allwinner,sun5i-a13-mmc"; + compatible = "allwinner,sun7i-a20-mmc"; reg = <0x01c12000 0x1000>; clocks = <&ahb_gates 11>, <&mmc3_clk 0>, diff --git a/arch/arm/boot/dts/sun8i-a23-a33.dtsi b/arch/arm/boot/dts/sun8i-a23-a33.dtsi index 7e05e09e61c7..e3b196e08ccf 100644 --- a/arch/arm/boot/dts/sun8i-a23-a33.dtsi +++ b/arch/arm/boot/dts/sun8i-a23-a33.dtsi @@ -266,7 +266,7 @@ }; mmc0: mmc@01c0f000 { - compatible = "allwinner,sun5i-a13-mmc"; + compatible = "allwinner,sun7i-a20-mmc"; reg = <0x01c0f000 0x1000>; clocks = <&ahb1_gates 8>, <&mmc0_clk 0>, @@ -285,7 +285,7 @@ }; mmc1: mmc@01c10000 { - compatible = "allwinner,sun5i-a13-mmc"; + compatible = "allwinner,sun7i-a20-mmc"; reg = <0x01c10000 0x1000>; clocks = <&ahb1_gates 9>, <&mmc1_clk 0>, @@ -304,7 +304,7 @@ }; mmc2: mmc@01c11000 { - compatible = "allwinner,sun5i-a13-mmc"; + compatible = "allwinner,sun7i-a20-mmc"; reg = <0x01c11000 0x1000>; clocks = <&ahb1_gates 10>, <&mmc2_clk 0>, diff --git a/arch/arm/boot/dts/sun8i-h3.dtsi b/arch/arm/boot/dts/sun8i-h3.dtsi index fdf9fdbda267..8a95e3613488 100644 --- a/arch/arm/boot/dts/sun8i-h3.dtsi +++ b/arch/arm/boot/dts/sun8i-h3.dtsi @@ -150,7 +150,7 @@ }; mmc0: mmc@01c0f000 { - compatible = "allwinner,sun5i-a13-mmc"; + compatible = "allwinner,sun7i-a20-mmc"; reg = <0x01c0f000 0x1000>; clocks = <&ccu CLK_BUS_MMC0>, <&ccu CLK_MMC0>, @@ -169,7 +169,7 @@ }; mmc1: mmc@01c10000 { - compatible = "allwinner,sun5i-a13-mmc"; + compatible = "allwinner,sun7i-a20-mmc"; reg = <0x01c10000 0x1000>; clocks = <&ccu CLK_BUS_MMC1>, <&ccu CLK_MMC1>, @@ -188,7 +188,7 @@ }; mmc2: mmc@01c11000 { - compatible = "allwinner,sun5i-a13-mmc"; + compatible = "allwinner,sun7i-a20-mmc"; reg = <0x01c11000 0x1000>; clocks = <&ccu CLK_BUS_MMC2>, <&ccu CLK_MMC2>, diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c index 2206d4477dbb..c3335112e68c 100644 --- a/drivers/mmc/card/block.c +++ b/drivers/mmc/card/block.c @@ -142,8 +142,6 @@ static inline void mmc_blk_clear_packed(struct mmc_queue_req *mqrq) { struct mmc_packed *packed = mqrq->packed; - BUG_ON(!packed); - mqrq->cmd_type = MMC_PACKED_NONE; packed->nr_entries = MMC_PACKED_NR_ZERO; packed->idx_failure = MMC_PACKED_NR_IDX; @@ -1443,8 +1441,6 @@ static int mmc_blk_packed_err_check(struct mmc_card *card, int err, check, status; u8 *ext_csd; - BUG_ON(!packed); - packed->retries--; check = mmc_blk_err_check(card, areq); err = get_card_status(card, &status, 0); @@ -1673,6 +1669,18 @@ static u8 mmc_blk_prep_packed_list(struct mmc_queue *mq, struct request *req) u8 max_packed_rw = 0; u8 reqs = 0; + /* + * We don't need to check packed for any further + * operation of packed stuff as we set MMC_PACKED_NONE + * and return zero for reqs if geting null packed. Also + * we clean the flag of MMC_BLK_PACKED_CMD to avoid doing + * it again when removing blk req. + */ + if (!mqrq->packed) { + md->flags &= (~MMC_BLK_PACKED_CMD); + goto no_packed; + } + if (!(md->flags & MMC_BLK_PACKED_CMD)) goto no_packed; @@ -1782,8 +1790,6 @@ static void mmc_blk_packed_hdr_wrq_prep(struct mmc_queue_req *mqrq, u8 hdr_blocks; u8 i = 1; - BUG_ON(!packed); - mqrq->cmd_type = MMC_PACKED_WRITE; packed->blocks = 0; packed->idx_failure = MMC_PACKED_NR_IDX; @@ -1887,8 +1893,6 @@ static int mmc_blk_end_packed_req(struct mmc_queue_req *mq_rq) int idx = packed->idx_failure, i = 0; int ret = 0; - BUG_ON(!packed); - while (!list_empty(&packed->list)) { prq = list_entry_rq(packed->list.next); if (idx == i) { @@ -1917,8 +1921,6 @@ static void mmc_blk_abort_packed_req(struct mmc_queue_req *mq_rq) struct request *prq; struct mmc_packed *packed = mq_rq->packed; - BUG_ON(!packed); - while (!list_empty(&packed->list)) { prq = list_entry_rq(packed->list.next); list_del_init(&prq->queuelist); @@ -1935,8 +1937,6 @@ static void mmc_blk_revert_packed_req(struct mmc_queue *mq, struct request_queue *q = mq->queue; struct mmc_packed *packed = mq_rq->packed; - BUG_ON(!packed); - while (!list_empty(&packed->list)) { prq = list_entry_rq(packed->list.prev); if (prq->queuelist.prev != &packed->list) { @@ -2144,7 +2144,7 @@ static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *rqc) return 0; } -static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req) +int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req) { int ret; struct mmc_blk_data *md = mq->data; @@ -2265,7 +2265,6 @@ again: if (ret) goto err_putdisk; - md->queue.issue_fn = mmc_blk_issue_rq; md->queue.data = md; md->disk->major = MMC_BLOCK_MAJOR; @@ -2303,7 +2302,8 @@ again: set_capacity(md->disk, size); if (mmc_host_cmd23(card->host)) { - if (mmc_card_mmc(card) || + if ((mmc_card_mmc(card) && + card->csd.mmca_vsn >= CSD_SPEC_VER_3) || (mmc_card_sd(card) && card->scr.cmds & SD_SCR_CMD23_SUPPORT)) md->flags |= MMC_BLK_CMD23; diff --git a/drivers/mmc/card/block.h b/drivers/mmc/card/block.h new file mode 100644 index 000000000000..cdabb2ee74be --- /dev/null +++ b/drivers/mmc/card/block.h @@ -0,0 +1 @@ +int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req); diff --git a/drivers/mmc/card/mmc_test.c b/drivers/mmc/card/mmc_test.c index c032eef45762..5a8dc5a76e0d 100644 --- a/drivers/mmc/card/mmc_test.c +++ b/drivers/mmc/card/mmc_test.c @@ -184,6 +184,29 @@ static int mmc_test_set_blksize(struct mmc_test_card *test, unsigned size) return mmc_set_blocklen(test->card, size); } +static bool mmc_test_card_cmd23(struct mmc_card *card) +{ + return mmc_card_mmc(card) || + (mmc_card_sd(card) && card->scr.cmds & SD_SCR_CMD23_SUPPORT); +} + +static void mmc_test_prepare_sbc(struct mmc_test_card *test, + struct mmc_request *mrq, unsigned int blocks) +{ + struct mmc_card *card = test->card; + + if (!mrq->sbc || !mmc_host_cmd23(card->host) || + !mmc_test_card_cmd23(card) || !mmc_op_multi(mrq->cmd->opcode) || + (card->quirks & MMC_QUIRK_BLK_NO_CMD23)) { + mrq->sbc = NULL; + return; + } + + mrq->sbc->opcode = MMC_SET_BLOCK_COUNT; + mrq->sbc->arg = blocks; + mrq->sbc->flags = MMC_RSP_R1 | MMC_CMD_AC; +} + /* * Fill in the mmc_request structure given a set of transfer parameters. */ @@ -221,6 +244,8 @@ static void mmc_test_prepare_mrq(struct mmc_test_card *test, mrq->data->sg = sg; mrq->data->sg_len = sg_len; + mmc_test_prepare_sbc(test, mrq, blocks); + mmc_set_data_timeout(mrq->data, test->card); } @@ -693,6 +718,8 @@ static int mmc_test_check_result(struct mmc_test_card *test, ret = 0; + if (mrq->sbc && mrq->sbc->error) + ret = mrq->sbc->error; if (!ret && mrq->cmd->error) ret = mrq->cmd->error; if (!ret && mrq->data->error) @@ -2278,6 +2305,245 @@ static int mmc_test_reset(struct mmc_test_card *test) return RESULT_FAIL; } +struct mmc_test_req { + struct mmc_request mrq; + struct mmc_command sbc; + struct mmc_command cmd; + struct mmc_command stop; + struct mmc_command status; + struct mmc_data data; +}; + +static struct mmc_test_req *mmc_test_req_alloc(void) +{ + struct mmc_test_req *rq = kzalloc(sizeof(*rq), GFP_KERNEL); + + if (rq) { + rq->mrq.cmd = &rq->cmd; + rq->mrq.data = &rq->data; + rq->mrq.stop = &rq->stop; + } + + return rq; +} + +static int mmc_test_send_status(struct mmc_test_card *test, + struct mmc_command *cmd) +{ + memset(cmd, 0, sizeof(*cmd)); + + cmd->opcode = MMC_SEND_STATUS; + if (!mmc_host_is_spi(test->card->host)) + cmd->arg = test->card->rca << 16; + cmd->flags = MMC_RSP_SPI_R2 | MMC_RSP_R1 | MMC_CMD_AC; + + return mmc_wait_for_cmd(test->card->host, cmd, 0); +} + +static int mmc_test_ongoing_transfer(struct mmc_test_card *test, + unsigned int dev_addr, int use_sbc, + int repeat_cmd, int write, int use_areq) +{ + struct mmc_test_req *rq = mmc_test_req_alloc(); + struct mmc_host *host = test->card->host; + struct mmc_test_area *t = &test->area; + struct mmc_async_req areq; + struct mmc_request *mrq; + unsigned long timeout; + bool expired = false; + int ret = 0, cmd_ret; + u32 status = 0; + int count = 0; + + if (!rq) + return -ENOMEM; + + mrq = &rq->mrq; + if (use_sbc) + mrq->sbc = &rq->sbc; + mrq->cap_cmd_during_tfr = true; + + areq.mrq = mrq; + areq.err_check = mmc_test_check_result_async; + + mmc_test_prepare_mrq(test, mrq, t->sg, t->sg_len, dev_addr, t->blocks, + 512, write); + + if (use_sbc && t->blocks > 1 && !mrq->sbc) { + ret = mmc_host_cmd23(host) ? + RESULT_UNSUP_CARD : + RESULT_UNSUP_HOST; + goto out_free; + } + + /* Start ongoing data request */ + if (use_areq) { + mmc_start_req(host, &areq, &ret); + if (ret) + goto out_free; + } else { + mmc_wait_for_req(host, mrq); + } + + timeout = jiffies + msecs_to_jiffies(3000); + do { + count += 1; + + /* Send status command while data transfer in progress */ + cmd_ret = mmc_test_send_status(test, &rq->status); + if (cmd_ret) + break; + + status = rq->status.resp[0]; + if (status & R1_ERROR) { + cmd_ret = -EIO; + break; + } + + if (mmc_is_req_done(host, mrq)) + break; + + expired = time_after(jiffies, timeout); + if (expired) { + pr_info("%s: timeout waiting for Tran state status %#x\n", + mmc_hostname(host), status); + cmd_ret = -ETIMEDOUT; + break; + } + } while (repeat_cmd && R1_CURRENT_STATE(status) != R1_STATE_TRAN); + + /* Wait for data request to complete */ + if (use_areq) + mmc_start_req(host, NULL, &ret); + else + mmc_wait_for_req_done(test->card->host, mrq); + + /* + * For cap_cmd_during_tfr request, upper layer must send stop if + * required. + */ + if (mrq->data->stop && (mrq->data->error || !mrq->sbc)) { + if (ret) + mmc_wait_for_cmd(host, mrq->data->stop, 0); + else + ret = mmc_wait_for_cmd(host, mrq->data->stop, 0); + } + + if (ret) + goto out_free; + + if (cmd_ret) { + pr_info("%s: Send Status failed: status %#x, error %d\n", + mmc_hostname(test->card->host), status, cmd_ret); + } + + ret = mmc_test_check_result(test, mrq); + if (ret) + goto out_free; + + ret = mmc_test_wait_busy(test); + if (ret) + goto out_free; + + if (repeat_cmd && (t->blocks + 1) << 9 > t->max_tfr) + pr_info("%s: %d commands completed during transfer of %u blocks\n", + mmc_hostname(test->card->host), count, t->blocks); + + if (cmd_ret) + ret = cmd_ret; +out_free: + kfree(rq); + + return ret; +} + +static int __mmc_test_cmds_during_tfr(struct mmc_test_card *test, + unsigned long sz, int use_sbc, int write, + int use_areq) |
