Skip to content

Commit e72a55f

Browse files
nishadkamdarstorulf
authored andcommitted
mmc: core: Return correct emmc response in case of ioctl error
When a read/write command is sent via ioctl to the kernel, and the command fails, the actual error response of the emmc is not sent to the user. IOCTL read/write tests are carried out using commands 17 (Single BLock Read), 24 (Single Block Write), 18 (Multi Block Read), 25 (Multi Block Write) The tests are carried out on a 64Gb emmc device. All of these tests try to access an "out of range" sector address (0x09B2FFFF). It is seen that without the patch the response received by the user is not OUT_OF_RANGE error (R1 response 31st bit is not set) as per JEDEC specification. After applying the patch proper response is seen. This is because the function returns without copying the response to the user in case of failure. This patch fixes the issue. Hence, this memcpy is required whether we get an error response or not. Therefor it is moved up from the current position up to immediately after we have called mmc_wait_for_req(). The test code and the output of only the CMD17 is included in the commit to limit the message length. CMD17 (Test Code Snippet): ========================== printf("Forming CMD%d\n", opt_idx); /* single block read */ cmd.blksz = 512; cmd.blocks = 1; cmd.write_flag = 0; cmd.opcode = 17; //cmd.arg = atoi(argv[3]); cmd.arg = 0x09B2FFFF; /* Expecting response R1B */ cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC; memset(data, 0, sizeof(__u8) * 512); mmc_ioc_cmd_set_data(cmd, data); printf("Sending CMD%d: ARG[0x%08x]\n", opt_idx, cmd.arg); if(ioctl(fd, MMC_IOC_CMD, &cmd)) perror("Error"); printf("\nResponse: %08x\n", cmd.response[0]); CMD17 (Output without patch): ============================= test@test-LIVA-Z:~$ sudo ./mmc cmd_test /dev/mmcblk0 17 Entering the do_mmc_commands:Device: /dev/mmcblk0 nargs:4 Entering the do_mmc_commands:Device: /dev/mmcblk0 options[17, 0x09B2FFF] Forming CMD17 Sending CMD17: ARG[0x09b2ffff] Error: Connection timed out Response: 00000000 (Incorrect response) CMD17 (Output with patch): ========================== test@test-LIVA-Z:~$ sudo ./mmc cmd_test /dev/mmcblk0 17 [sudo] password for test: Entering the do_mmc_commands:Device: /dev/mmcblk0 nargs:4 Entering the do_mmc_commands:Device: /dev/mmcblk0 options[17, 09B2FFFF] Forming CMD17 Sending CMD17: ARG[0x09b2ffff] Error: Connection timed out Response: 80000900 (Correct OUT_OF_ERROR response as per JEDEC specification) Signed-off-by: Nishad Kamdar <[email protected]> Reviewed-by: Avri Altman <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Ulf Hansson <[email protected]>
1 parent 45334ee commit e72a55f

File tree

1 file changed

+1
-2
lines changed

1 file changed

+1
-2
lines changed

drivers/mmc/core/block.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -518,6 +518,7 @@ static int __mmc_blk_ioctl_cmd(struct mmc_card *card, struct mmc_blk_data *md,
518518
return mmc_sanitize(card, idata->ic.cmd_timeout_ms);
519519

520520
mmc_wait_for_req(card->host, &mrq);
521+
memcpy(&idata->ic.response, cmd.resp, sizeof(cmd.resp));
521522

522523
if (cmd.error) {
523524
dev_err(mmc_dev(card->host), "%s: cmd error %d\n",
@@ -567,8 +568,6 @@ static int __mmc_blk_ioctl_cmd(struct mmc_card *card, struct mmc_blk_data *md,
567568
if (idata->ic.postsleep_min_us)
568569
usleep_range(idata->ic.postsleep_min_us, idata->ic.postsleep_max_us);
569570

570-
memcpy(&(idata->ic.response), cmd.resp, sizeof(cmd.resp));
571-
572571
if (idata->rpmb || (cmd.flags & MMC_RSP_R1B) == MMC_RSP_R1B) {
573572
/*
574573
* Ensure RPMB/R1B command has completed by polling CMD13

0 commit comments

Comments
 (0)