Commit a0d4c7eb authored by Chaotian Jing's avatar Chaotian Jing Committed by Ulf Hansson
Browse files

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



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>
parent 3869468e
Loading
Loading
Loading
Loading
+55 −92
Original line number Diff line number Diff line
@@ -408,38 +408,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;
@@ -468,6 +436,58 @@ out:
	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)
{
@@ -477,7 +497,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;
@@ -611,16 +630,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;
@@ -970,58 +985,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)
{