Handle command retries for commands originating at the mmc layer, and
ensure that all such commands have a non-zero retry count except for those that are expected to fail (for example, because they are used to probe for feature support). While it is possible to pass a retry count down to the hardware driver in the command request structure, no hardware driver currently implements any retry logic. The hardware doesn't know much about the context of a single request, so it makes more sense to handle retries at a layer that does. This adds retry loops to the mmc_wait_for_cmd() and mmc_wait_for_app_cmd() functions. These functions are the gateway from other code within mmc.c to the hardware. App commands are a sequence of two commands and a retry has to rerun both of them in order, so it needs its own retry loop. Retry looping is specifically NOT implemented in mmc_wait_for_request() because it is the gateway for children on the bus, and they have to implement their own retry logic depending on what makes sense for them.
This commit is contained in:
parent
5aa60b6f21
commit
a8328210d0
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=254431
@ -393,8 +393,9 @@ mmc_wait_for_req(struct mmc_softc *sc, struct mmc_request *req)
|
||||
while ((req->flags & MMC_REQ_DONE) == 0)
|
||||
msleep(req, &sc->sc_mtx, 0, "mmcreq", 0);
|
||||
MMC_UNLOCK(sc);
|
||||
if (mmc_debug > 2 || (mmc_debug > 1 && req->cmd->error))
|
||||
device_printf(sc->dev, "RESULT: %d\n", req->cmd->error);
|
||||
if (mmc_debug > 2 || (mmc_debug > 0 && req->cmd->error != MMC_ERR_NONE))
|
||||
device_printf(sc->dev, "CMD%d RESULT: %d\n",
|
||||
req->cmd->opcode, req->cmd->error);
|
||||
return (0);
|
||||
}
|
||||
|
||||
@ -410,14 +411,21 @@ static int
|
||||
mmc_wait_for_cmd(struct mmc_softc *sc, struct mmc_command *cmd, int retries)
|
||||
{
|
||||
struct mmc_request mreq;
|
||||
int err;
|
||||
|
||||
memset(&mreq, 0, sizeof(mreq));
|
||||
memset(cmd->resp, 0, sizeof(cmd->resp));
|
||||
cmd->retries = retries;
|
||||
cmd->mrq = &mreq;
|
||||
mreq.cmd = cmd;
|
||||
mmc_wait_for_req(sc, &mreq);
|
||||
return (cmd->error);
|
||||
do {
|
||||
memset(&mreq, 0, sizeof(mreq));
|
||||
memset(cmd->resp, 0, sizeof(cmd->resp));
|
||||
cmd->retries = 0; /* Retries done here, not in hardware. */
|
||||
cmd->mrq = &mreq;
|
||||
mreq.cmd = cmd;
|
||||
if (mmc_wait_for_req(sc, &mreq) != 0)
|
||||
err = MMC_ERR_FAILED;
|
||||
else
|
||||
err = cmd->error;
|
||||
} while (err != MMC_ERR_NONE && retries-- > 0);
|
||||
|
||||
return (err);
|
||||
}
|
||||
|
||||
static int
|
||||
@ -425,24 +433,27 @@ mmc_wait_for_app_cmd(struct mmc_softc *sc, uint32_t rca,
|
||||
struct mmc_command *cmd, int retries)
|
||||
{
|
||||
struct mmc_command appcmd;
|
||||
int err = MMC_ERR_NONE, i;
|
||||
int err;
|
||||
|
||||
for (i = 0; i <= retries; i++) {
|
||||
do {
|
||||
appcmd.opcode = MMC_APP_CMD;
|
||||
appcmd.arg = rca << 16;
|
||||
appcmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
|
||||
appcmd.data = NULL;
|
||||
mmc_wait_for_cmd(sc, &appcmd, 0);
|
||||
err = appcmd.error;
|
||||
if (err != MMC_ERR_NONE)
|
||||
continue;
|
||||
if (!(appcmd.resp[0] & R1_APP_CMD))
|
||||
return MMC_ERR_FAILED;
|
||||
mmc_wait_for_cmd(sc, cmd, 0);
|
||||
err = cmd->error;
|
||||
if (err == MMC_ERR_NONE)
|
||||
break;
|
||||
}
|
||||
if (mmc_wait_for_cmd(sc, &appcmd, 0) != 0)
|
||||
err = MMC_ERR_FAILED;
|
||||
else
|
||||
err = appcmd.error;
|
||||
if (err == MMC_ERR_NONE) {
|
||||
if (!(appcmd.resp[0] & R1_APP_CMD))
|
||||
return MMC_ERR_FAILED; /* Retries won't help. */
|
||||
if (mmc_wait_for_cmd(sc, cmd, 0) != 0)
|
||||
err = MMC_ERR_FAILED;
|
||||
else
|
||||
err = cmd->error;
|
||||
}
|
||||
} while (err != MMC_ERR_NONE && retries-- > 0);
|
||||
|
||||
return (err);
|
||||
}
|
||||
|
||||
@ -461,8 +472,6 @@ mmc_wait_for_command(struct mmc_softc *sc, uint32_t opcode,
|
||||
err = mmc_wait_for_cmd(sc, &cmd, retries);
|
||||
if (err)
|
||||
return (err);
|
||||
if (cmd.error)
|
||||
return (cmd.error);
|
||||
if (resp) {
|
||||
if (flags & MMC_RSP_136)
|
||||
memcpy(resp, cmd.resp, 4 * sizeof(uint32_t));
|
||||
@ -488,7 +497,7 @@ mmc_idle_cards(struct mmc_softc *sc)
|
||||
cmd.arg = 0;
|
||||
cmd.flags = MMC_RSP_NONE | MMC_CMD_BC;
|
||||
cmd.data = NULL;
|
||||
mmc_wait_for_cmd(sc, &cmd, 0);
|
||||
mmc_wait_for_cmd(sc, &cmd, CMD_RETRIES);
|
||||
mmc_ms_delay(1);
|
||||
|
||||
mmcbr_set_chip_select(dev, cs_dontcare);
|
||||
@ -625,7 +634,7 @@ mmc_switch(struct mmc_softc *sc, uint8_t set, uint8_t index, uint8_t value)
|
||||
set;
|
||||
cmd.flags = MMC_RSP_R1B | MMC_CMD_AC;
|
||||
cmd.data = NULL;
|
||||
err = mmc_wait_for_cmd(sc, &cmd, 0);
|
||||
err = mmc_wait_for_cmd(sc, &cmd, CMD_RETRIES);
|
||||
return (err);
|
||||
}
|
||||
|
||||
@ -1054,7 +1063,7 @@ mmc_all_send_cid(struct mmc_softc *sc, uint32_t *rawcid)
|
||||
cmd.arg = 0;
|
||||
cmd.flags = MMC_RSP_R2 | MMC_CMD_BCR;
|
||||
cmd.data = NULL;
|
||||
err = mmc_wait_for_cmd(sc, &cmd, 0);
|
||||
err = mmc_wait_for_cmd(sc, &cmd, CMD_RETRIES);
|
||||
memcpy(rawcid, cmd.resp, 4 * sizeof(uint32_t));
|
||||
return (err);
|
||||
}
|
||||
@ -1069,7 +1078,7 @@ mmc_send_csd(struct mmc_softc *sc, uint16_t rca, uint32_t *rawcsd)
|
||||
cmd.arg = rca << 16;
|
||||
cmd.flags = MMC_RSP_R2 | MMC_CMD_BCR;
|
||||
cmd.data = NULL;
|
||||
err = mmc_wait_for_cmd(sc, &cmd, 0);
|
||||
err = mmc_wait_for_cmd(sc, &cmd, CMD_RETRIES);
|
||||
memcpy(rawcsd, cmd.resp, 4 * sizeof(uint32_t));
|
||||
return (err);
|
||||
}
|
||||
@ -1160,7 +1169,7 @@ mmc_set_relative_addr(struct mmc_softc *sc, uint16_t resp)
|
||||
cmd.arg = resp << 16;
|
||||
cmd.flags = MMC_RSP_R6 | MMC_CMD_BCR;
|
||||
cmd.data = NULL;
|
||||
err = mmc_wait_for_cmd(sc, &cmd, 0);
|
||||
err = mmc_wait_for_cmd(sc, &cmd, CMD_RETRIES);
|
||||
return (err);
|
||||
}
|
||||
|
||||
@ -1174,7 +1183,7 @@ mmc_send_relative_addr(struct mmc_softc *sc, uint32_t *resp)
|
||||
cmd.arg = 0;
|
||||
cmd.flags = MMC_RSP_R6 | MMC_CMD_BCR;
|
||||
cmd.data = NULL;
|
||||
err = mmc_wait_for_cmd(sc, &cmd, 0);
|
||||
err = mmc_wait_for_cmd(sc, &cmd, CMD_RETRIES);
|
||||
*resp = cmd.resp[0];
|
||||
return (err);
|
||||
}
|
||||
@ -1189,7 +1198,7 @@ mmc_send_status(struct mmc_softc *sc, uint16_t rca, uint32_t *status)
|
||||
cmd.arg = rca << 16;
|
||||
cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
|
||||
cmd.data = NULL;
|
||||
err = mmc_wait_for_cmd(sc, &cmd, 0);
|
||||
err = mmc_wait_for_cmd(sc, &cmd, CMD_RETRIES);
|
||||
*status = cmd.resp[0];
|
||||
return (err);
|
||||
}
|
||||
@ -1204,7 +1213,7 @@ mmc_set_blocklen(struct mmc_softc *sc, uint32_t len)
|
||||
cmd.arg = len;
|
||||
cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
|
||||
cmd.data = NULL;
|
||||
err = mmc_wait_for_cmd(sc, &cmd, 0);
|
||||
err = mmc_wait_for_cmd(sc, &cmd, CMD_RETRIES);
|
||||
return (err);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user