Received: by 2002:a25:8b91:0:0:0:0:0 with SMTP id j17csp2286583ybl; Thu, 19 Dec 2019 11:02:14 -0800 (PST) X-Google-Smtp-Source: APXvYqwh3YmtxYE5GJhWoF5+BE/SrEcXQDuoKXemOk5OnuSlD235LsppkDEkWUtU4FHjGMudAL5U X-Received: by 2002:a9d:75da:: with SMTP id c26mr10381376otl.40.1576782133797; Thu, 19 Dec 2019 11:02:13 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1576782133; cv=none; d=google.com; s=arc-20160816; b=o8XtRM8U70WXeg/una8n5ndO/jvCnqWG4MTRUzCzTUezz6puV2vwtiRKBoJ8j6UOmq d3nwzqd+VtHed/4uxcJzcXQro1hQi6v9EdF5gtfs14WbfFxtcy+3nAI93LW9LBuRG5gr lG4W5yhwVtiL8u3NU++nKXAbfqWQFGEYmTUTJTXoIQPuakZ/ej7kA5GmH6VSNGzqBMvF pBcC3ooBSiU9Yo4974HIUtDqz2e2ZozTJB5Og+tUKRkpjdxLzVhzzKEEWZLmbF1bPk7n e3+9Cd1YJMIKLWTJkiP47ThWD6/o8Ysk7Yx02CV3i4t/zFo5rnx+MNZO6qvefJTl9ftw jI3g== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :user-agent:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=wxaChsXYFr4BlyYa0LjkqAw2sZCpCssEDvdTZUhrT2U=; b=iCLowm9yaGBNH/2WYgFpBDF/5p+Pdh02KiU52SXumnQvNbPb77pBr8ln1cxME3smpe YRmXEXpNUZU83MwlHOZel7p/cSWJPrijNTV6xwBlj1qDzrto7CSDs3NdMd6KVbd6veMo 34KL+UAXKAWgm1SsNHzd3zztLOvljdVWtUgCowWcYj2HnlsOkp/yACCcAf9hXlGqbKls V7fAIDo+Ug/IvUMNywow4GgpeBc7vjyWD8j4p8aKeGYVReiQKSnUftuYu1VgNtPGQTYB WHWbdU3TFZgw5tnCVQHwBzX1hIcJx3L5zy7K5qnbLuM4cyGFWnaz/NKFuUu2ba6NpCLt 0M9w== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=OpEjLrJm; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id l8si3879776otq.75.2019.12.19.11.01.55; Thu, 19 Dec 2019 11:02:13 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=OpEjLrJm; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729953AbfLSSwB (ORCPT + 99 others); Thu, 19 Dec 2019 13:52:01 -0500 Received: from mail.kernel.org ([198.145.29.99]:46360 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729966AbfLSSv5 (ORCPT ); Thu, 19 Dec 2019 13:51:57 -0500 Received: from localhost (83-86-89-107.cable.dynamic.v4.ziggo.nl [83.86.89.107]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id 2526C227BF; Thu, 19 Dec 2019 18:51:55 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1576781515; bh=IebOsnRruRJT2wt0+t9bs4S3ty5GthByZG1FKzkWW0Q=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=OpEjLrJmJzp9p8k1fXlJEbZhldLwoMXBo45U4uiPrm5tNg22qZtkBoClhurbtSZ5p D7j+3RdtH7SvZIUH0Hwudy6xbJRwGmZD8P6OykAJxJqwr8nEd0XRNa23VTU7Joq+bM pJfb+yxWtk6tjVj4P1SBSj7DJ2EwL3srxxEfQoC0= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Chaotian Jing , Avri Altman , Ulf Hansson Subject: [PATCH 4.19 17/47] mmc: block: Add CMD13 polling for MMC IOCTLS with R1B response Date: Thu, 19 Dec 2019 19:34:31 +0100 Message-Id: <20191219182917.716278574@linuxfoundation.org> X-Mailer: git-send-email 2.24.1 In-Reply-To: <20191219182857.659088743@linuxfoundation.org> References: <20191219182857.659088743@linuxfoundation.org> User-Agent: quilt/0.66 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Chaotian Jing commit a0d4c7eb71dd08a89ad631177bb0cbbabd598f84 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: Chaotian Jing Reviewed-by: Avri Altman Cc: stable@vger.kernel.org Signed-off-by: Ulf Hansson Signed-off-by: Greg Kroah-Hartman --- drivers/mmc/core/block.c | 147 +++++++++++++++++------------------------------ 1 file changed, 55 insertions(+), 92 deletions(-) --- a/drivers/mmc/core/block.c +++ b/drivers/mmc/core/block.c @@ -409,38 +409,6 @@ static int mmc_blk_ioctl_copy_to_user(st 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 @@ 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) { @@ -478,7 +498,6 @@ static int __mmc_blk_ioctl_cmd(struct mm 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 mm 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 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) {