Commit 12e8ae94 authored by Chaotian Jing's avatar Chaotian Jing Committed by Greg Kroah-Hartman

mmc: block: Add CMD13 polling for MMC IOCTLS with R1B response

commit a0d4c7eb upstream.

MMC IOCTLS with R1B responses may cause the card to enter the busy state,
which means it's not ready to receive a new request. To prevent new
requests from being sent to the card, use a CMD13 polling loop to verify
that the card returns to the transfer state, before completing the request.
Signed-off-by: default avatarChaotian Jing <chaotian.jing@mediatek.com>
Reviewed-by: default avatarAvri Altman <avri.altman@wdc.com>
Cc: stable@vger.kernel.org
Signed-off-by: default avatarUlf Hansson <ulf.hansson@linaro.org>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 848fd6b1
......@@ -409,38 +409,6 @@ static int mmc_blk_ioctl_copy_to_user(struct mmc_ioc_cmd __user *ic_ptr,
return 0;
}
static int ioctl_rpmb_card_status_poll(struct mmc_card *card, u32 *status,
u32 retries_max)
{
int err;
u32 retry_count = 0;
if (!status || !retries_max)
return -EINVAL;
do {
err = __mmc_send_status(card, status, 5);
if (err)
break;
if (!R1_STATUS(*status) &&
(R1_CURRENT_STATE(*status) != R1_STATE_PRG))
break; /* RPMB programming operation complete */
/*
* Rechedule to give the MMC device a chance to continue
* processing the previous command without being polled too
* frequently.
*/
usleep_range(1000, 5000);
} while (++retry_count < retries_max);
if (retry_count == retries_max)
err = -EPERM;
return err;
}
static int ioctl_do_sanitize(struct mmc_card *card)
{
int err;
......@@ -469,6 +437,58 @@ static int ioctl_do_sanitize(struct mmc_card *card)
return err;
}
static inline bool mmc_blk_in_tran_state(u32 status)
{
/*
* Some cards mishandle the status bits, so make sure to check both the
* busy indication and the card state.
*/
return status & R1_READY_FOR_DATA &&
(R1_CURRENT_STATE(status) == R1_STATE_TRAN);
}
static int card_busy_detect(struct mmc_card *card, unsigned int timeout_ms,
u32 *resp_errs)
{
unsigned long timeout = jiffies + msecs_to_jiffies(timeout_ms);
int err = 0;
u32 status;
do {
bool done = time_after(jiffies, timeout);
err = __mmc_send_status(card, &status, 5);
if (err) {
dev_err(mmc_dev(card->host),
"error %d requesting status\n", err);
return err;
}
/* Accumulate any response error bits seen */
if (resp_errs)
*resp_errs |= status;
/*
* Timeout if the device never becomes ready for data and never
* leaves the program state.
*/
if (done) {
dev_err(mmc_dev(card->host),
"Card stuck in wrong state! %s status: %#x\n",
__func__, status);
return -ETIMEDOUT;
}
/*
* Some cards mishandle the status bits,
* so make sure to check both the busy
* indication and the card state.
*/
} while (!mmc_blk_in_tran_state(status));
return err;
}
static int __mmc_blk_ioctl_cmd(struct mmc_card *card, struct mmc_blk_data *md,
struct mmc_blk_ioc_data *idata)
{
......@@ -478,7 +498,6 @@ static int __mmc_blk_ioctl_cmd(struct mmc_card *card, struct mmc_blk_data *md,
struct scatterlist sg;
int err;
unsigned int target_part;
u32 status = 0;
if (!card || !md || !idata)
return -EINVAL;
......@@ -612,16 +631,12 @@ static int __mmc_blk_ioctl_cmd(struct mmc_card *card, struct mmc_blk_data *md,
memcpy(&(idata->ic.response), cmd.resp, sizeof(cmd.resp));
if (idata->rpmb) {
if (idata->rpmb || (cmd.flags & MMC_RSP_R1B)) {
/*
* Ensure RPMB command has completed by polling CMD13
* Ensure RPMB/R1B command has completed by polling CMD13
* "Send Status".
*/
err = ioctl_rpmb_card_status_poll(card, &status, 5);
if (err)
dev_err(mmc_dev(card->host),
"%s: Card Status=0x%08X, error %d\n",
__func__, status, err);
err = card_busy_detect(card, MMC_BLK_TIMEOUT_MS, NULL);
}
return err;
......@@ -971,58 +986,6 @@ static unsigned int mmc_blk_data_timeout_ms(struct mmc_host *host,
return ms;
}
static inline bool mmc_blk_in_tran_state(u32 status)
{
/*
* Some cards mishandle the status bits, so make sure to check both the
* busy indication and the card state.
*/
return status & R1_READY_FOR_DATA &&
(R1_CURRENT_STATE(status) == R1_STATE_TRAN);
}
static int card_busy_detect(struct mmc_card *card, unsigned int timeout_ms,
u32 *resp_errs)
{
unsigned long timeout = jiffies + msecs_to_jiffies(timeout_ms);
int err = 0;
u32 status;
do {
bool done = time_after(jiffies, timeout);
err = __mmc_send_status(card, &status, 5);
if (err) {
dev_err(mmc_dev(card->host),
"error %d requesting status\n", err);
return err;
}
/* Accumulate any response error bits seen */
if (resp_errs)
*resp_errs |= status;
/*
* Timeout if the device never becomes ready for data and never
* leaves the program state.
*/
if (done) {
dev_err(mmc_dev(card->host),
"Card stuck in wrong state! %s status: %#x\n",
__func__, status);
return -ETIMEDOUT;
}
/*
* Some cards mishandle the status bits,
* so make sure to check both the busy
* indication and the card state.
*/
} while (!mmc_blk_in_tran_state(status));
return err;
}
static int mmc_blk_reset(struct mmc_blk_data *md, struct mmc_host *host,
int type)
{
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment