From patchwork Wed Jan 22 15:00:18 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ulf Hansson X-Patchwork-Id: 23533 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-pb0-f72.google.com (mail-pb0-f72.google.com [209.85.160.72]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id 102AA218CB for ; Wed, 22 Jan 2014 15:00:38 +0000 (UTC) Received: by mail-pb0-f72.google.com with SMTP id up15sf1041703pbc.7 for ; Wed, 22 Jan 2014 07:00:38 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:delivered-to:from:to:cc:subject :date:message-id:in-reply-to:references:x-original-sender :x-original-authentication-results:precedence:mailing-list:list-id :list-post:list-help:list-archive:list-unsubscribe; bh=Uw0P4uyk4rS4E/dkDyrXP7Hr1Rc1q+2G9uWdlUT34Mo=; b=MKJh+tayoYtFL3y1WsrzOiDiNiTUE8u+OtMsLQazwUcRUAHW8NCbssMVn4vQg29MoS 5eg91Jgr8ToTj6rylXCpslAOPGvI8PJMm7G7Q4QXotpV6OvrmKgEtgKyEpU9lsgo/bNm NJwy6Wgd/YqQN1Ldd0x0PGDc/CZwHKm0bVuClposYtLKKUcDKp/JhefNbxvhgsaLJKq/ 6Z2H7C4U2qM1tqOPnSUJjxmfb1h/3RcMKqyQrSUamlVECnHAdm4MEH0z/0vpyYxCsY9V jqJ5lGj18TPBtj++lidAhFmLGnsJppx75oDO4gbelPZSq6kqHJgDQ8hDcbleCKHEhrz4 UY6Q== X-Gm-Message-State: ALoCoQknlCEteBQA6hORBACN3x13OzrwysyZyXBOBtsja/Vr2QCbJvbqFo65t5vcWfE8DzzNuF5L X-Received: by 10.66.118.37 with SMTP id kj5mr696717pab.17.1390402838282; Wed, 22 Jan 2014 07:00:38 -0800 (PST) MIME-Version: 1.0 X-BeenThere: patchwork-forward@linaro.org Received: by 10.49.106.232 with SMTP id gx8ls92805qeb.39.gmail; Wed, 22 Jan 2014 07:00:38 -0800 (PST) X-Received: by 10.220.76.201 with SMTP id d9mr1204349vck.33.1390402838117; Wed, 22 Jan 2014 07:00:38 -0800 (PST) Received: from mail-vc0-f169.google.com (mail-vc0-f169.google.com [209.85.220.169]) by mx.google.com with ESMTPS id vi9si4695487vec.18.2014.01.22.07.00.38 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Wed, 22 Jan 2014 07:00:38 -0800 (PST) Received-SPF: neutral (google.com: 209.85.220.169 is neither permitted nor denied by best guess record for domain of patch+caf_=patchwork-forward=linaro.org@linaro.org) client-ip=209.85.220.169; Received: by mail-vc0-f169.google.com with SMTP id hq11so279814vcb.28 for ; Wed, 22 Jan 2014 07:00:38 -0800 (PST) X-Received: by 10.58.211.130 with SMTP id nc2mr1175618vec.7.1390402838031; Wed, 22 Jan 2014 07:00:38 -0800 (PST) X-Forwarded-To: patchwork-forward@linaro.org X-Forwarded-For: patch@linaro.org patchwork-forward@linaro.org Delivered-To: patches@linaro.org Received: by 10.220.174.196 with SMTP id u4csp190321vcz; Wed, 22 Jan 2014 07:00:37 -0800 (PST) X-Received: by 10.180.38.11 with SMTP id c11mr20078455wik.60.1390402836902; Wed, 22 Jan 2014 07:00:36 -0800 (PST) Received: from mail-wi0-f173.google.com (mail-wi0-f173.google.com [209.85.212.173]) by mx.google.com with ESMTPS id gc5si7041915wic.46.2014.01.22.07.00.36 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Wed, 22 Jan 2014 07:00:36 -0800 (PST) Received-SPF: neutral (google.com: 209.85.212.173 is neither permitted nor denied by best guess record for domain of ulf.hansson@linaro.org) client-ip=209.85.212.173; Received: by mail-wi0-f173.google.com with SMTP id d13so5707084wiw.0 for ; Wed, 22 Jan 2014 07:00:36 -0800 (PST) X-Received: by 10.180.75.202 with SMTP id e10mr20351520wiw.50.1390402836192; Wed, 22 Jan 2014 07:00:36 -0800 (PST) Received: from localhost.localdomain ([85.235.11.236]) by mx.google.com with ESMTPSA id dd3sm15401824wjb.9.2014.01.22.07.00.34 for (version=TLSv1.1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Wed, 22 Jan 2014 07:00:35 -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 04/10] mmc: core: Fixup busy detection for mmc switch operations Date: Wed, 22 Jan 2014 16:00:18 +0100 Message-Id: <1390402824-9850-5-git-send-email-ulf.hansson@linaro.org> X-Mailer: git-send-email 1.7.9.5 In-Reply-To: <1390402824-9850-1-git-send-email-ulf.hansson@linaro.org> References: <1390402824-9850-1-git-send-email-ulf.hansson@linaro.org> X-Removed-Original-Auth: Dkim didn't pass. X-Original-Sender: ulf.hansson@linaro.org X-Original-Authentication-Results: mx.google.com; spf=neutral (google.com: 209.85.220.169 is neither permitted nor denied by best guess record for domain of patch+caf_=patchwork-forward=linaro.org@linaro.org) smtp.mail=patch+caf_=patchwork-forward=linaro.org@linaro.org Precedence: list Mailing-list: list patchwork-forward@linaro.org; contact patchwork-forward+owners@linaro.org List-ID: X-Google-Group-Id: 836684582541 List-Post: , List-Help: , List-Archive: List-Unsubscribe: , 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 shall reflect the maximum busy detection timeout supported by the host. A timeout set to zero, is interpreted as the host supports whatever timeout the mmc core provides it with. 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, which is the same mechanism used when the host doesn't support MMC_CAP_WAIT_WHILE_BUSY. Signed-off-by: Ulf Hansson --- drivers/mmc/core/mmc_ops.c | 53 ++++++++++++++++++++++++++++++-------------- 1 file changed, 36 insertions(+), 17 deletions(-) diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c index 5e1a2cb..2e0cccb 100644 --- a/drivers/mmc/core/mmc_ops.c +++ b/drivers/mmc/core/mmc_ops.c @@ -413,13 +413,31 @@ int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value, unsigned int timeout_ms, bool use_busy_signal, bool send_status, bool ignore_crc) { + struct mmc_host *host; int err; struct mmc_command cmd = {0}; unsigned long timeout; + unsigned int max_busy_timeout; u32 status = 0; + bool use_r1b_resp = true; BUG_ON(!card); BUG_ON(!card->host); + host = card->host; + + /* Once all callers provides a timeout, remove this fallback. */ + if (!timeout_ms) + timeout_ms = MMC_OPS_TIMEOUT_MS; + + /* We interpret unspecified timeouts as the host can cope with all. */ + max_busy_timeout = host->max_busy_timeout ? + host->max_busy_timeout : timeout_ms; + + if (use_busy_signal && (host->caps & MMC_CAP_WAIT_WHILE_BUSY) && + (timeout_ms > max_busy_timeout)) + use_r1b_resp = false; + else if (!use_busy_signal) + use_r1b_resp = false; cmd.opcode = MMC_SWITCH; cmd.arg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) | @@ -427,17 +445,25 @@ 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 cmd.flags |= MMC_RSP_SPI_R1 | MMC_RSP_R1; + if ((host->caps & MMC_CAP_WAIT_WHILE_BUSY) && use_r1b_resp) { + /* Tell the host what busy detection timeout to use. */ + cmd.busy_timeout = timeout_ms; + /* + * CRC errors shall only be ignored in cases were CMD13 is used + * to poll to detect busy completion. + */ + ignore_crc = false; + } - cmd.busy_timeout = timeout_ms; if (index == EXT_CSD_SANITIZE_START) cmd.sanitize_busy = true; - err = mmc_wait_for_cmd(card->host, &cmd, MMC_CMD_RETRIES); + err = mmc_wait_for_cmd(host, &cmd, MMC_CMD_RETRIES); if (err) return err; @@ -445,24 +471,17 @@ int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value, if (!use_busy_signal) return 0; - /* - * CRC errors shall only be ignored in cases were CMD13 is used to poll - * to detect busy completion. - */ - if (card->host->caps & MMC_CAP_WAIT_WHILE_BUSY) - ignore_crc = false; - /* 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 (card->host->caps & MMC_CAP_WAIT_WHILE_BUSY) + if ((host->caps & MMC_CAP_WAIT_WHILE_BUSY) && use_r1b_resp) break; - if (mmc_host_is_spi(card->host)) + if (mmc_host_is_spi(host)) break; /* @@ -478,18 +497,18 @@ int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value, /* 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(card->host), __func__); + mmc_hostname(host), __func__); return -ETIMEDOUT; } } while (R1_CURRENT_STATE(status) == R1_STATE_PRG); - if (mmc_host_is_spi(card->host)) { + if (mmc_host_is_spi(host)) { if (status & R1_SPI_ILLEGAL_COMMAND) return -EBADMSG; } else { if (status & 0xFDFFA000) - pr_warning("%s: unexpected status %#x after " - "switch", mmc_hostname(card->host), status); + pr_warn("%s: unexpected status %#x after switch\n", + mmc_hostname(host), status); if (status & R1_SWITCH_ERROR) return -EBADMSG; }