From patchwork Wed Jan 29 22:37:57 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ulf Hansson X-Patchwork-Id: 3554941 Return-Path: X-Original-To: patchwork-linux-mmc@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 63CA3C02DC for ; Wed, 29 Jan 2014 22:38:26 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 8219820170 for ; Wed, 29 Jan 2014 22:38:25 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 95E6E2017A for ; Wed, 29 Jan 2014 22:38:24 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751468AbaA2WiX (ORCPT ); Wed, 29 Jan 2014 17:38:23 -0500 Received: from mail-la0-f43.google.com ([209.85.215.43]:45377 "EHLO mail-la0-f43.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751398AbaA2WiX (ORCPT ); Wed, 29 Jan 2014 17:38:23 -0500 Received: by mail-la0-f43.google.com with SMTP id pv20so1973674lab.2 for ; Wed, 29 Jan 2014 14:38:21 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=z90lnWvWfNCWa5rVWpACPo4JTxwKaiBNG7untASMYcw=; b=Zp1Slb7Ey7Mw2y2bwaA+k27Xcz/Q8Aj8b8ZWPLyN8pfknr/Y7fZ1yeCCG/An3yEmCM vUHLgn/wYRof7qDF6mECJZP4leQQTTP66q1klJXMrgt/mmXpPfHIdIL2jCkAVYxrgIPn psMOD75L0QAZL90ht+jQyPRLhO4NEiX8oxtX5mC7E4CHHgvzn8c8D5HJmBRVhm6z3sSh /QOtC+jBavnW/qL6a75xWFu9XcJaEjXBj50jDwv1N8axxQmyqrFXIyr7sUyw3HUmtBG9 6L6AZlnfb8kxqvkaQqm/ocRRBCBnBJCBu8Uj6a98GOoIXUzYlPUqDblP2WWAgdgRi49B OqQA== X-Gm-Message-State: ALoCoQmO+PCHyNBdh4TZp/eTwHwfsaCYnbsH+Ztvx3q67kzigi5yetqEbdkM3YtLHTmQHGtTKV9t X-Received: by 10.112.131.100 with SMTP id ol4mr2921592lbb.38.1391035101561; Wed, 29 Jan 2014 14:38:21 -0800 (PST) Received: from linaro-ulf.lan (90-231-160-185-no158.tbcn.telia.com. [90.231.160.185]) by mx.google.com with ESMTPSA id wt2sm3998221lbb.2.2014.01.29.14.38.19 for (version=TLSv1.1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Wed, 29 Jan 2014 14:38:20 -0800 (PST) From: Ulf Hansson To: linux-mmc@vger.kernel.org, Chris Ball Cc: Dong Aisheng , Stephen Warren , Vladimir Zapolskiy , Adrian Hunter , Ulf Hansson Subject: [PATCH 05/13] mmc: core: Fixup busy detection for mmc switch operations Date: Wed, 29 Jan 2014 23:37:57 +0100 Message-Id: <1391035085-2747-6-git-send-email-ulf.hansson@linaro.org> X-Mailer: git-send-email 1.7.9.5 In-Reply-To: <1391035085-2747-1-git-send-email-ulf.hansson@linaro.org> References: <1391035085-2747-1-git-send-email-ulf.hansson@linaro.org> 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.4 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=ham 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 If the host controller supports busy detection in HW, we expect the MMC_CAP_WAIT_WHILE_BUSY to be set. Likewise the corresponding host->max_busy_timeout should reflect the maximum busy detection timeout supported by the host. Previously we expected a host that supported MMC_CAP_WAIT_WHILE_BUSY to cope with any timeout, which just isn't feasible due to HW limitations. For most switch operations, R1B responses are expected and thus we need to check for busy detection completion. To cope with cases where the requested busy detection timeout is greater than what the host are able to support, we fallback to use a R1 response instead. This will prevent the host from doing HW busy detection. In those cases, busy detection completion is handled by polling the for the card's status using CMD13. This is the same mechanism used when the host doesn't support MMC_CAP_WAIT_WHILE_BUSY. Do note, a host->max_busy_timeout set to zero, is interpreted by the mmc core as it don't know what the host supports. It will then provide the host with whatever timeout the mmc core finds suitable. For some cases the mmc core has unfurtunate no clue of what timeout to use. In these cases we provide the host with a timeout value of zero, which the host may interpret as use whatever timeout it finds suitable. Signed-off-by: Ulf Hansson --- drivers/mmc/core/mmc_ops.c | 33 ++++++++++++++++++++++++++------- 1 file changed, 26 insertions(+), 7 deletions(-) diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c index 04ecdb9..f51b5ba 100644 --- a/drivers/mmc/core/mmc_ops.c +++ b/drivers/mmc/core/mmc_ops.c @@ -418,6 +418,17 @@ int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value, struct mmc_command cmd = {0}; unsigned long timeout; u32 status = 0; + bool use_r1b_resp = use_busy_signal; + + /* + * If the cmd timeout and the max_busy_timeout of the host are both + * specified, let's validate them. A failure means we need to prevent + * the host from doing hw busy detection, which is done by converting + * to a R1 response instead of a R1B. + */ + if (timeout_ms && host->max_busy_timeout && + (timeout_ms > host->max_busy_timeout)) + use_r1b_resp = false; cmd.opcode = MMC_SWITCH; cmd.arg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) | @@ -425,13 +436,17 @@ int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value, (value << 8) | set; cmd.flags = MMC_CMD_AC; - if (use_busy_signal) + if (use_r1b_resp) { cmd.flags |= MMC_RSP_SPI_R1B | MMC_RSP_R1B; - else + /* + * A busy_timeout of zero means the host can decide to use + * whatever value it finds suitable. + */ + cmd.busy_timeout = timeout_ms; + } else { cmd.flags |= MMC_RSP_SPI_R1 | MMC_RSP_R1; + } - - cmd.busy_timeout = timeout_ms; if (index == EXT_CSD_SANITIZE_START) cmd.sanitize_busy = true; @@ -447,18 +462,22 @@ int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value, * CRC errors shall only be ignored in cases were CMD13 is used to poll * to detect busy completion. */ - if (host->caps & MMC_CAP_WAIT_WHILE_BUSY) + if ((host->caps & MMC_CAP_WAIT_WHILE_BUSY) && use_r1b_resp) ignore_crc = false; + /* We have an unspecified cmd timeout, use the fallback value. */ + if (!timeout_ms) + timeout_ms = MMC_OPS_TIMEOUT_MS; + /* Must check status to be sure of no errors. */ - timeout = jiffies + msecs_to_jiffies(MMC_OPS_TIMEOUT_MS); + timeout = jiffies + msecs_to_jiffies(timeout_ms); do { if (send_status) { err = __mmc_send_status(card, &status, ignore_crc); if (err) return err; } - if (host->caps & MMC_CAP_WAIT_WHILE_BUSY) + if ((host->caps & MMC_CAP_WAIT_WHILE_BUSY) && use_r1b_resp) break; if (mmc_host_is_spi(host)) break;