From patchwork Thu Nov 26 12:36:09 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chaotian Jing X-Patchwork-Id: 7706471 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id B527ABF90C for ; Thu, 26 Nov 2015 12:38:39 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id D4B3B2063F for ; Thu, 26 Nov 2015 12:38:38 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.9]) (using TLSv1.2 with cipher AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id DC46E20211 for ; Thu, 26 Nov 2015 12:38:37 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1a1vnA-0003eI-Cj; Thu, 26 Nov 2015 12:36:52 +0000 Received: from [210.61.82.184] (helo=mailgw02.mediatek.com) by bombadil.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1a1vn5-0003RJ-Tj; Thu, 26 Nov 2015 12:36:49 +0000 X-Listener-Flag: 11101 Received: from mtkhts09.mediatek.inc [(172.21.101.70)] by mailgw02.mediatek.com (envelope-from ) (mhqrelay.mediatek.com ESMTP with TLS) with ESMTP id 1011810125; Thu, 26 Nov 2015 20:36:22 +0800 Received: from localhost.localdomain (10.17.3.153) by mtkhts09.mediatek.inc (172.21.101.73) with Microsoft SMTP Server id 14.3.181.6; Thu, 26 Nov 2015 20:36:20 +0800 From: Chaotian Jing To: Ulf Hansson Subject: [PATCH v2] mmc: core: fix __mmc_switch timeout caused by preempt Date: Thu, 26 Nov 2015 20:36:09 +0800 Message-ID: <1448541369-23086-1-git-send-email-chaotian.jing@mediatek.com> X-Mailer: git-send-email 1.8.1.1.dirty MIME-Version: 1.0 X-MTK: N X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20151126_043648_310657_10BCE28F X-CRM114-Status: GOOD ( 15.78 ) X-Spam-Score: -1.1 (-) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: srv_heupstream@mediatek.com, Stephen Boyd , linux-mmc@vger.kernel.org, Adrian Hunter , linux-kernel@vger.kernel.org, linux-mediatek@lists.infradead.org, linux-arm-kernel@lists.infradead.org, Minda Chen , Matthias Brugger , Chaotian Jing Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Spam-Status: No, score=-5.2 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_MED, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP there is a time window between __mmc_send_status() and time_afer(), on some eMMC chip, the timeout_ms is only 10ms, if this thread was scheduled out during this period, then, even card has already changes to transfer state by the result of CMD13, this part of code also treat it to timeout error. So, need calculate timeout first, then call __mmc_send_status(), if already timeout and card still in programing state, then treat it to the real timeout error. Signed-off-by: Chaotian Jing --- drivers/mmc/core/mmc_ops.c | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c index 1f44426..eba5295 100644 --- a/drivers/mmc/core/mmc_ops.c +++ b/drivers/mmc/core/mmc_ops.c @@ -489,6 +489,7 @@ int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value, unsigned long timeout; u32 status = 0; bool use_r1b_resp = use_busy_signal; + bool expired; mmc_retune_hold(host); @@ -545,9 +546,23 @@ int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value, timeout = jiffies + msecs_to_jiffies(timeout_ms); do { if (send_status) { + /* + * Timeout if the device never leaves the program state. + * Due to the possibility of being preempted after + * sending the status command, check the expiration + * time first. + */ + expired = time_after(jiffies, timeout); err = __mmc_send_status(card, &status, ignore_crc); if (err) goto out; + if (expired && + R1_CURRENT_STATE(status) == R1_STATE_PRG) { + pr_err("%s: Card stuck in programming state! %s\n", + mmc_hostname(host), __func__); + err = -ETIMEDOUT; + goto out; + } } if ((host->caps & MMC_CAP_WAIT_WHILE_BUSY) && use_r1b_resp) break; @@ -563,14 +578,6 @@ int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value, mmc_delay(timeout_ms); goto out; } - - /* Timeout if the device never leaves the program state. */ - if (time_after(jiffies, timeout)) { - pr_err("%s: Card stuck in programming state! %s\n", - mmc_hostname(host), __func__); - err = -ETIMEDOUT; - goto out; - } } while (R1_CURRENT_STATE(status) == R1_STATE_PRG); err = mmc_switch_status_error(host, status);