[PATCH 0/4] mmc: sandbox: Some small fixes

Various small fixes which were found with valgrind.
Sean Anderson (4): mmc: sandbox: Initialize the status register mmc: sandbox: Initialize backing buffer mmc: Import some defines for R1 responses mmc: sandbox: Set the response
drivers/mmc/sandbox_mmc.c | 13 +++++++--- include/mmc.h | 52 +++++++++++++++++++++++++++++++++++++-- 2 files changed, 60 insertions(+), 5 deletions(-)

The send status command expects the status register to be returned as a response. Without writing data back, whatever is on the stack will be interpreted as the status register. There are a lot of fields in this register, but fortunately all zeros is interpreted as "we don't support anything."
Signed-off-by: Sean Anderson seanga2@gmail.com ---
drivers/mmc/sandbox_mmc.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/drivers/mmc/sandbox_mmc.c b/drivers/mmc/sandbox_mmc.c index 451fe4a4e5..35159451e1 100644 --- a/drivers/mmc/sandbox_mmc.c +++ b/drivers/mmc/sandbox_mmc.c @@ -57,6 +57,7 @@ static int sandbox_mmc_send_cmd(struct udevice *dev, struct mmc_cmd *cmd, break; case MMC_CMD_SEND_STATUS: cmd->response[0] = MMC_STATUS_RDY_FOR_DATA; + memset(data->dest, '\0', data->blocks * data->blocksize); break; case MMC_CMD_SELECT_CARD: break;

Hi
On 3/31/22 01:54, Sean Anderson wrote:
The send status command expects the status register to be returned as a response. Without writing data back, whatever is on the stack will be interpreted as the status register. There are a lot of fields in this register, but fortunately all zeros is interpreted as "we don't support anything."
Signed-off-by: Sean Anderson seanga2@gmail.com
Reviewed-by: Jaehoon Chung jh80.chung@samsung.com
Best Regards, Jaehoon Chung
drivers/mmc/sandbox_mmc.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/drivers/mmc/sandbox_mmc.c b/drivers/mmc/sandbox_mmc.c index 451fe4a4e5..35159451e1 100644 --- a/drivers/mmc/sandbox_mmc.c +++ b/drivers/mmc/sandbox_mmc.c @@ -57,6 +57,7 @@ static int sandbox_mmc_send_cmd(struct udevice *dev, struct mmc_cmd *cmd, break; case MMC_CMD_SEND_STATUS: cmd->response[0] = MMC_STATUS_RDY_FOR_DATA;
break; case MMC_CMD_SELECT_CARD: break;memset(data->dest, '\0', data->blocks * data->blocksize);

Dear Sean,
On 4/22/22 21:03, Jaehoon Chung wrote:
Hi
On 3/31/22 01:54, Sean Anderson wrote:
The send status command expects the status register to be returned as a response. Without writing data back, whatever is on the stack will be interpreted as the status register. There are a lot of fields in this register, but fortunately all zeros is interpreted as "we don't support anything."
Signed-off-by: Sean Anderson seanga2@gmail.com
Reviewed-by: Jaehoon Chung jh80.chung@samsung.com
After applied your patch, CI testing was failed. I have been checking what's problem. So this patch set will be applied after fixing it.
Best Regards, Jaehoon Chung
Best Regards, Jaehoon Chung
drivers/mmc/sandbox_mmc.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/drivers/mmc/sandbox_mmc.c b/drivers/mmc/sandbox_mmc.c index 451fe4a4e5..35159451e1 100644 --- a/drivers/mmc/sandbox_mmc.c +++ b/drivers/mmc/sandbox_mmc.c @@ -57,6 +57,7 @@ static int sandbox_mmc_send_cmd(struct udevice *dev, struct mmc_cmd *cmd, break; case MMC_CMD_SEND_STATUS: cmd->response[0] = MMC_STATUS_RDY_FOR_DATA;
break; case MMC_CMD_SELECT_CARD: break;memset(data->dest, '\0', data->blocks * data->blocksize);

Hi Jaehoon,
On 4/26/22 3:56 AM, Jaehoon Chung wrote:
Dear Sean,
On 4/22/22 21:03, Jaehoon Chung wrote:
Hi
On 3/31/22 01:54, Sean Anderson wrote:
The send status command expects the status register to be returned as a response. Without writing data back, whatever is on the stack will be interpreted as the status register. There are a lot of fields in this register, but fortunately all zeros is interpreted as "we don't support anything."
Signed-off-by: Sean Anderson seanga2@gmail.com
Reviewed-by: Jaehoon Chung jh80.chung@samsung.com
After applied your patch, CI testing was failed. I have been checking what's problem. So this patch set will be applied after fixing it.
Did you ever figure out what was causing CI failures? If you don't have time to look into it, could you send me the log?
--Sean

Hi,
On 8/14/22 00:26, Sean Anderson wrote:
Hi Jaehoon,
On 4/26/22 3:56 AM, Jaehoon Chung wrote:
Dear Sean,
On 4/22/22 21:03, Jaehoon Chung wrote:
Hi
On 3/31/22 01:54, Sean Anderson wrote:
The send status command expects the status register to be returned as a response. Without writing data back, whatever is on the stack will be interpreted as the status register. There are a lot of fields in this register, but fortunately all zeros is interpreted as "we don't support anything."
Signed-off-by: Sean Anderson seanga2@gmail.com
Reviewed-by: Jaehoon Chung jh80.chung@samsung.com
After applied your patch, CI testing was failed. I have been checking what's problem. So this patch set will be applied after fixing it.
Did you ever figure out what was causing CI failures? If you don't have time to look into it, could you send me the log?
I will check it with latest u-boot base. And If there is a failed, I will share a log. Sorry for too late.
Best Regards, Jaehoon Chung
--Sean

Private data is initialized to all zeros by DM. Malloc does not do this. Initialize it. This fixes partition detection logic from trying to detect partitions in uninitialized memory.
Fixes: 0bf61aced2 ("sandbox: mmc: Support a backing file") Signed-off-by: Sean Anderson seanga2@gmail.com ---
drivers/mmc/sandbox_mmc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/mmc/sandbox_mmc.c b/drivers/mmc/sandbox_mmc.c index 35159451e1..60a6be0add 100644 --- a/drivers/mmc/sandbox_mmc.c +++ b/drivers/mmc/sandbox_mmc.c @@ -178,7 +178,7 @@ static int sandbox_mmc_probe(struct udevice *dev) priv->csize = 0; priv->size = (priv->csize + 1) * SIZE_MULTIPLE; /* 1 MiB */
- priv->buf = malloc(priv->size); + priv->buf = calloc(1, priv->size); if (!priv->buf) { log_err("%s: Not enough memory (%x bytes)\n", dev->name, priv->size);

On 3/31/22 01:54, Sean Anderson wrote:
Private data is initialized to all zeros by DM. Malloc does not do this. Initialize it. This fixes partition detection logic from trying to detect partitions in uninitialized memory.
Fixes: 0bf61aced2 ("sandbox: mmc: Support a backing file") Signed-off-by: Sean Anderson seanga2@gmail.com
Reviewed-by: Jaehoon Chung jh80.chung@samsung.com
Best Regards, Jaehoon Chung
drivers/mmc/sandbox_mmc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/mmc/sandbox_mmc.c b/drivers/mmc/sandbox_mmc.c index 35159451e1..60a6be0add 100644 --- a/drivers/mmc/sandbox_mmc.c +++ b/drivers/mmc/sandbox_mmc.c @@ -178,7 +178,7 @@ static int sandbox_mmc_probe(struct udevice *dev) priv->csize = 0; priv->size = (priv->csize + 1) * SIZE_MULTIPLE; /* 1 MiB */
priv->buf = malloc(priv->size);
if (!priv->buf) { log_err("%s: Not enough memory (%x bytes)\n", dev->name, priv->size);priv->buf = calloc(1, priv->size);

This imports defines for R1 responses from include/linux/mmc/mmc.h from Linux 5.10.
Signed-off-by: Sean Anderson seanga2@gmail.com --- Yes, this is an old version, but it's what I had checked out, and I don't think there are any new fields we need to handle :)
include/mmc.h | 52 +++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 50 insertions(+), 2 deletions(-)
diff --git a/include/mmc.h b/include/mmc.h index 6bdcce881d..7304eee0d4 100644 --- a/include/mmc.h +++ b/include/mmc.h @@ -311,8 +311,56 @@ static inline bool mmc_is_tuning_cmd(uint cmdidx) #define EXT_CSD_WR_DATA_REL_USR (1 << 0) /* user data area WR_REL */ #define EXT_CSD_WR_DATA_REL_GP(x) (1 << ((x)+1)) /* GP part (x+1) WR_REL */
-#define R1_ILLEGAL_COMMAND (1 << 22) -#define R1_APP_CMD (1 << 5) +/* + MMC status in R1, for native mode (SPI bits are different) + Type + e : error bit + s : status bit + r : detected and set for the actual command response + x : detected and set during command execution. the host must poll + the card by sending status command in order to read these bits. + Clear condition + a : according to the card state + b : always related to the previous command. Reception of + a valid command will clear it (with a delay of one command) + c : clear by read + */ + +#define R1_OUT_OF_RANGE (1 << 31) /* er, c */ +#define R1_ADDRESS_ERROR (1 << 30) /* erx, c */ +#define R1_BLOCK_LEN_ERROR (1 << 29) /* er, c */ +#define R1_ERASE_SEQ_ERROR (1 << 28) /* er, c */ +#define R1_ERASE_PARAM (1 << 27) /* ex, c */ +#define R1_WP_VIOLATION (1 << 26) /* erx, c */ +#define R1_CARD_IS_LOCKED (1 << 25) /* sx, a */ +#define R1_LOCK_UNLOCK_FAILED (1 << 24) /* erx, c */ +#define R1_COM_CRC_ERROR (1 << 23) /* er, b */ +#define R1_ILLEGAL_COMMAND (1 << 22) /* er, b */ +#define R1_CARD_ECC_FAILED (1 << 21) /* ex, c */ +#define R1_CC_ERROR (1 << 20) /* erx, c */ +#define R1_ERROR (1 << 19) /* erx, c */ +#define R1_UNDERRUN (1 << 18) /* ex, c */ +#define R1_OVERRUN (1 << 17) /* ex, c */ +#define R1_CID_CSD_OVERWRITE (1 << 16) /* erx, c, CID/CSD overwrite */ +#define R1_WP_ERASE_SKIP (1 << 15) /* sx, c */ +#define R1_CARD_ECC_DISABLED (1 << 14) /* sx, a */ +#define R1_ERASE_RESET (1 << 13) /* sr, c */ +#define R1_STATUS(x) (x & 0xFFF9A000) +#define R1_CURRENT_STATE(x) ((x & 0x00001E00) >> 9) /* sx, b (4 bits) */ +#define R1_READY_FOR_DATA (1 << 8) /* sx, a */ +#define R1_SWITCH_ERROR (1 << 7) /* sx, c */ +#define R1_EXCEPTION_EVENT (1 << 6) /* sr, a */ +#define R1_APP_CMD (1 << 5) /* sr, c */ + +#define R1_STATE_IDLE 0 +#define R1_STATE_READY 1 +#define R1_STATE_IDENT 2 +#define R1_STATE_STBY 3 +#define R1_STATE_TRAN 4 +#define R1_STATE_DATA 5 +#define R1_STATE_RCV 6 +#define R1_STATE_PRG 7 +#define R1_STATE_DIS 8
#define MMC_RSP_PRESENT (1 << 0) #define MMC_RSP_136 (1 << 1) /* 136 bit response */

On 3/31/22 01:54, Sean Anderson wrote:
This imports defines for R1 responses from include/linux/mmc/mmc.h from Linux 5.10.
Signed-off-by: Sean Anderson seanga2@gmail.com
Reviewed-by: Jaehoon Chung jh80.chung@samsung.com
Best Regards, Jaehoon Chung
Yes, this is an old version, but it's what I had checked out, and I don't think there are any new fields we need to handle :)
include/mmc.h | 52 +++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 50 insertions(+), 2 deletions(-)
diff --git a/include/mmc.h b/include/mmc.h index 6bdcce881d..7304eee0d4 100644 --- a/include/mmc.h +++ b/include/mmc.h @@ -311,8 +311,56 @@ static inline bool mmc_is_tuning_cmd(uint cmdidx) #define EXT_CSD_WR_DATA_REL_USR (1 << 0) /* user data area WR_REL */ #define EXT_CSD_WR_DATA_REL_GP(x) (1 << ((x)+1)) /* GP part (x+1) WR_REL */
-#define R1_ILLEGAL_COMMAND (1 << 22) -#define R1_APP_CMD (1 << 5) +/*
- MMC status in R1, for native mode (SPI bits are different)
- Type
- e : error bit
- s : status bit
- r : detected and set for the actual command response
- x : detected and set during command execution. the host must poll
the card by sending status command in order to read these bits.
- Clear condition
- a : according to the card state
- b : always related to the previous command. Reception of
a valid command will clear it (with a delay of one command)
- c : clear by read
- */
+#define R1_OUT_OF_RANGE (1 << 31) /* er, c */ +#define R1_ADDRESS_ERROR (1 << 30) /* erx, c */ +#define R1_BLOCK_LEN_ERROR (1 << 29) /* er, c */ +#define R1_ERASE_SEQ_ERROR (1 << 28) /* er, c */ +#define R1_ERASE_PARAM (1 << 27) /* ex, c */ +#define R1_WP_VIOLATION (1 << 26) /* erx, c */ +#define R1_CARD_IS_LOCKED (1 << 25) /* sx, a */ +#define R1_LOCK_UNLOCK_FAILED (1 << 24) /* erx, c */ +#define R1_COM_CRC_ERROR (1 << 23) /* er, b */ +#define R1_ILLEGAL_COMMAND (1 << 22) /* er, b */ +#define R1_CARD_ECC_FAILED (1 << 21) /* ex, c */ +#define R1_CC_ERROR (1 << 20) /* erx, c */ +#define R1_ERROR (1 << 19) /* erx, c */ +#define R1_UNDERRUN (1 << 18) /* ex, c */ +#define R1_OVERRUN (1 << 17) /* ex, c */ +#define R1_CID_CSD_OVERWRITE (1 << 16) /* erx, c, CID/CSD overwrite */ +#define R1_WP_ERASE_SKIP (1 << 15) /* sx, c */ +#define R1_CARD_ECC_DISABLED (1 << 14) /* sx, a */ +#define R1_ERASE_RESET (1 << 13) /* sr, c */ +#define R1_STATUS(x) (x & 0xFFF9A000) +#define R1_CURRENT_STATE(x) ((x & 0x00001E00) >> 9) /* sx, b (4 bits) */ +#define R1_READY_FOR_DATA (1 << 8) /* sx, a */ +#define R1_SWITCH_ERROR (1 << 7) /* sx, c */ +#define R1_EXCEPTION_EVENT (1 << 6) /* sr, a */ +#define R1_APP_CMD (1 << 5) /* sr, c */
+#define R1_STATE_IDLE 0 +#define R1_STATE_READY 1 +#define R1_STATE_IDENT 2 +#define R1_STATE_STBY 3 +#define R1_STATE_TRAN 4 +#define R1_STATE_DATA 5 +#define R1_STATE_RCV 6 +#define R1_STATE_PRG 7 +#define R1_STATE_DIS 8
#define MMC_RSP_PRESENT (1 << 0) #define MMC_RSP_136 (1 << 1) /* 136 bit response */

The mmc subsystem checks the response, but we (almost) never set it. Add a bare-bones implementation. Technically, we are supposed to return our current state in our responses, but I don't think the subsystem checks it.
Signed-off-by: Sean Anderson seanga2@gmail.com ---
drivers/mmc/sandbox_mmc.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-)
diff --git a/drivers/mmc/sandbox_mmc.c b/drivers/mmc/sandbox_mmc.c index 60a6be0add..8922eeba2a 100644 --- a/drivers/mmc/sandbox_mmc.c +++ b/drivers/mmc/sandbox_mmc.c @@ -44,6 +44,9 @@ static int sandbox_mmc_send_cmd(struct udevice *dev, struct mmc_cmd *cmd, struct mmc *mmc = mmc_get_mmc_dev(dev); static ulong erase_start, erase_end;
+ /* Default R1 response */ + cmd->response[0] = R1_READY_FOR_DATA; + switch (cmd->cmdidx) { case MMC_CMD_ALL_SEND_CID: memset(cmd->response, '\0', sizeof(cmd->response)); @@ -55,8 +58,8 @@ static int sandbox_mmc_send_cmd(struct udevice *dev, struct mmc_cmd *cmd, case SD_CMD_SEND_IF_COND: cmd->response[0] = 0xaa; break; - case MMC_CMD_SEND_STATUS: - cmd->response[0] = MMC_STATUS_RDY_FOR_DATA; + case SD_CMD_APP_SD_STATUS: + cmd->response[0] |= R1_APP_CMD; memset(data->dest, '\0', data->blocks * data->blocksize); break; case MMC_CMD_SELECT_CARD: @@ -106,6 +109,7 @@ static int sandbox_mmc_send_cmd(struct udevice *dev, struct mmc_cmd *cmd, cmd->response[2] = 0; break; case MMC_CMD_APP_CMD: + cmd->response[0] |= R1_APP_CMD; break; case MMC_CMD_SET_BLOCKLEN: debug("block len %d\n", cmd->cmdarg); @@ -113,11 +117,13 @@ static int sandbox_mmc_send_cmd(struct udevice *dev, struct mmc_cmd *cmd, case SD_CMD_APP_SEND_SCR: { u32 *scr = (u32 *)data->dest;
+ cmd->response[0] |= R1_APP_CMD; scr[0] = cpu_to_be32(2 << 24 | 1 << 15); /* SD version 3 */ break; } default: debug("%s: Unknown command %d\n", __func__, cmd->cmdidx); + cmd->response[0] |= R1_ILLEGAL_COMMAND; break; }

On 3/31/22 01:54, Sean Anderson wrote:
The mmc subsystem checks the response, but we (almost) never set it. Add a bare-bones implementation. Technically, we are supposed to return our current state in our responses, but I don't think the subsystem checks it.
Signed-off-by: Sean Anderson seanga2@gmail.com
Reviewed-by: Jaehoon Chung jh80.chung@samsung.com
Best Regards, Jaehoon Chung
drivers/mmc/sandbox_mmc.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-)
diff --git a/drivers/mmc/sandbox_mmc.c b/drivers/mmc/sandbox_mmc.c index 60a6be0add..8922eeba2a 100644 --- a/drivers/mmc/sandbox_mmc.c +++ b/drivers/mmc/sandbox_mmc.c @@ -44,6 +44,9 @@ static int sandbox_mmc_send_cmd(struct udevice *dev, struct mmc_cmd *cmd, struct mmc *mmc = mmc_get_mmc_dev(dev); static ulong erase_start, erase_end;
- /* Default R1 response */
- cmd->response[0] = R1_READY_FOR_DATA;
- switch (cmd->cmdidx) { case MMC_CMD_ALL_SEND_CID: memset(cmd->response, '\0', sizeof(cmd->response));
@@ -55,8 +58,8 @@ static int sandbox_mmc_send_cmd(struct udevice *dev, struct mmc_cmd *cmd, case SD_CMD_SEND_IF_COND: cmd->response[0] = 0xaa; break;
- case MMC_CMD_SEND_STATUS:
cmd->response[0] = MMC_STATUS_RDY_FOR_DATA;
- case SD_CMD_APP_SD_STATUS:
memset(data->dest, '\0', data->blocks * data->blocksize); break; case MMC_CMD_SELECT_CARD:cmd->response[0] |= R1_APP_CMD;
@@ -106,6 +109,7 @@ static int sandbox_mmc_send_cmd(struct udevice *dev, struct mmc_cmd *cmd, cmd->response[2] = 0; break; case MMC_CMD_APP_CMD:
break; case MMC_CMD_SET_BLOCKLEN: debug("block len %d\n", cmd->cmdarg);cmd->response[0] |= R1_APP_CMD;
@@ -113,11 +117,13 @@ static int sandbox_mmc_send_cmd(struct udevice *dev, struct mmc_cmd *cmd, case SD_CMD_APP_SEND_SCR: { u32 *scr = (u32 *)data->dest;
scr[0] = cpu_to_be32(2 << 24 | 1 << 15); /* SD version 3 */ break; } default: debug("%s: Unknown command %d\n", __func__, cmd->cmdidx);cmd->response[0] |= R1_APP_CMD;
break; }cmd->response[0] |= R1_ILLEGAL_COMMAND;
participants (3)
-
Jaehoon Chung
-
Jaehoon Chung
-
Sean Anderson