From patchwork Thu Nov 26 02:51:49 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chaotian Jing X-Patchwork-Id: 7704211 Return-Path: X-Original-To: patchwork-linux-mmc@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 80C2A9F1BE for ; Thu, 26 Nov 2015 02:52:52 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id AD02320826 for ; Thu, 26 Nov 2015 02:52:51 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id BECC620808 for ; Thu, 26 Nov 2015 02:52:50 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751106AbbKZCwJ (ORCPT ); Wed, 25 Nov 2015 21:52:09 -0500 Received: from mailgw02.mediatek.com ([210.61.82.184]:33309 "EHLO mailgw02.mediatek.com" rhost-flags-OK-FAIL-OK-FAIL) by vger.kernel.org with ESMTP id S1750830AbbKZCwH (ORCPT ); Wed, 25 Nov 2015 21:52:07 -0500 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 203606407; Thu, 26 Nov 2015 10:51:55 +0800 Received: from mhfsdcap03.mhfswrd (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 10:51:54 +0800 From: Chaotian Jing To: Ulf Hansson CC: Matthias Brugger , Stephen Boyd , Chaotian Jing , Adrian Hunter , Minda Chen , , , , , Subject: [PATCH] mmc: core: fix __mmc_switch timeout caused by preempt Date: Thu, 26 Nov 2015 10:51:49 +0800 Message-ID: <1448506309-18163-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 Sender: linux-mmc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-mmc@vger.kernel.org X-Spam-Status: No, score=-7.5 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, 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, 14 insertions(+), 9 deletions(-) diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c index 1f44426..0add634 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 = false; mmc_retune_hold(host); @@ -544,10 +545,22 @@ int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value, /* Must check status to be sure of no errors. */ timeout = jiffies + msecs_to_jiffies(timeout_ms); do { + /* Timeout if the device never leaves the program state. + * must check it firstly to avoid problem caused by preempt. + */ + expired = time_after(jiffies, timeout); + if (send_status) { err = __mmc_send_status(card, &status, ignore_crc); - if (err) + if (err) { goto out; + } else 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 +576,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);