From patchwork Sun Apr 12 09:03:45 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Adrian Hunter X-Patchwork-Id: 11484471 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 247C815AB for ; Sun, 12 Apr 2020 09:04:41 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 0793620709 for ; Sun, 12 Apr 2020 09:04:41 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726043AbgDLJEk (ORCPT ); Sun, 12 Apr 2020 05:04:40 -0400 Received: from mga12.intel.com ([192.55.52.136]:20973 "EHLO mga12.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725832AbgDLJEj (ORCPT ); Sun, 12 Apr 2020 05:04:39 -0400 IronPort-SDR: GNcQ+urhct/6fBMxL5K0UmWy+6p6DVEhYc+Rxy0uP1WsVi6WmIce+wtHd/xFxRqA3fG6C1SbWt igP0X0aeVhiQ== X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga001.fm.intel.com ([10.253.24.23]) by fmsmga106.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 12 Apr 2020 02:04:40 -0700 IronPort-SDR: fPiwfDBBxLDCIcmP8kszKGPvzWHe2kZyicc4CcE5c4tklHUPpTIV1IvzPbAR4nQ3Gk8jBW5Pre ZcZJ/478KGFg== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.72,374,1580803200"; d="scan'208";a="362835152" Received: from ahunter-desktop.fi.intel.com ([10.237.72.87]) by fmsmga001.fm.intel.com with ESMTP; 12 Apr 2020 02:04:38 -0700 From: Adrian Hunter To: Ulf Hansson , Baolin Wang Cc: linux-mmc Subject: [PATCH 1/5] mmc: sdhci: Add helpers for the auto-CMD23 flag Date: Sun, 12 Apr 2020 12:03:45 +0300 Message-Id: <20200412090349.1607-2-adrian.hunter@intel.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200412090349.1607-1-adrian.hunter@intel.com> References: <20200412090349.1607-1-adrian.hunter@intel.com> Organization: Intel Finland Oy, Registered Address: PL 281, 00181 Helsinki, Business Identity Code: 0357606 - 4, Domiciled in Helsinki Sender: linux-mmc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-mmc@vger.kernel.org Add 2 helper functions to make the use of the auto-CMD23 flag more readable. Signed-off-by: Adrian Hunter --- drivers/mmc/host/sdhci.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 3f716466fcfd..07548e5efd1f 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -1350,13 +1350,25 @@ static inline bool sdhci_auto_cmd12(struct sdhci_host *host, !mrq->cap_cmd_during_tfr; } +static inline bool sdhci_auto_cmd23(struct sdhci_host *host, + struct mmc_request *mrq) +{ + return mrq->sbc && (host->flags & SDHCI_AUTO_CMD23); +} + +static inline bool sdhci_manual_cmd23(struct sdhci_host *host, + struct mmc_request *mrq) +{ + return mrq->sbc && !(host->flags & SDHCI_AUTO_CMD23); +} + static inline void sdhci_auto_cmd_select(struct sdhci_host *host, struct mmc_command *cmd, u16 *mode) { bool use_cmd12 = sdhci_auto_cmd12(host, cmd->mrq) && (cmd->opcode != SD_IO_RW_EXTENDED); - bool use_cmd23 = cmd->mrq->sbc && (host->flags & SDHCI_AUTO_CMD23); + bool use_cmd23 = sdhci_auto_cmd23(host, cmd->mrq); u16 ctrl2; /* @@ -1416,7 +1428,7 @@ static void sdhci_set_transfer_mode(struct sdhci_host *host, if (mmc_op_multi(cmd->opcode) || data->blocks > 1) { mode = SDHCI_TRNS_BLK_CNT_EN | SDHCI_TRNS_MULTI; sdhci_auto_cmd_select(host, cmd, &mode); - if (cmd->mrq->sbc && (host->flags & SDHCI_AUTO_CMD23)) + if (sdhci_auto_cmd23(host, cmd->mrq)) sdhci_writel(host, cmd->mrq->sbc->arg, SDHCI_ARGUMENT2); } @@ -2054,7 +2066,7 @@ void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq) mrq->cmd->error = -ENOMEDIUM; sdhci_finish_mrq(host, mrq); } else { - if (mrq->sbc && !(host->flags & SDHCI_AUTO_CMD23)) + if (sdhci_manual_cmd23(host, mrq)) sdhci_send_command(host, mrq->sbc); else sdhci_send_command(host, mrq->cmd); From patchwork Sun Apr 12 09:03:46 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Adrian Hunter X-Patchwork-Id: 11484473 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 0810E112C for ; Sun, 12 Apr 2020 09:04:43 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id DEA4C20709 for ; Sun, 12 Apr 2020 09:04:42 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726102AbgDLJEl (ORCPT ); Sun, 12 Apr 2020 05:04:41 -0400 Received: from mga12.intel.com ([192.55.52.136]:20973 "EHLO mga12.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725832AbgDLJEl (ORCPT ); Sun, 12 Apr 2020 05:04:41 -0400 IronPort-SDR: 7j1pYkWxitOyJhllMaqgVwtar4KYT9dbQb5UqVX3/xcymDzDygVroCzMPx2flwWUq4CFiUvE7t iZq3NE4M0BcQ== X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga001.fm.intel.com ([10.253.24.23]) by fmsmga106.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 12 Apr 2020 02:04:41 -0700 IronPort-SDR: 0Zj3ogToVenb45U/72QjFNW5dN1Wxk9rmWInloPQfkARyTY36oF75ZwGAUArYt6N6jICHlV8jS HsC1e7slfZYw== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.72,374,1580803200"; d="scan'208";a="362835159" Received: from ahunter-desktop.fi.intel.com ([10.237.72.87]) by fmsmga001.fm.intel.com with ESMTP; 12 Apr 2020 02:04:40 -0700 From: Adrian Hunter To: Ulf Hansson , Baolin Wang Cc: linux-mmc Subject: [PATCH 2/5] mmc: sdhci: Stop exporting sdhci_send_command() Date: Sun, 12 Apr 2020 12:03:46 +0300 Message-Id: <20200412090349.1607-3-adrian.hunter@intel.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200412090349.1607-1-adrian.hunter@intel.com> References: <20200412090349.1607-1-adrian.hunter@intel.com> Organization: Intel Finland Oy, Registered Address: PL 281, 00181 Helsinki, Business Identity Code: 0357606 - 4, Domiciled in Helsinki Sender: linux-mmc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-mmc@vger.kernel.org sdhci_send_command() has not been used outside of sdhci.c for many years. Stop exporting it. Signed-off-by: Adrian Hunter --- drivers/mmc/host/sdhci.c | 5 +++-- drivers/mmc/host/sdhci.h | 1 - 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 07548e5efd1f..429e5b80f2fb 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -52,6 +52,8 @@ static void sdhci_finish_data(struct sdhci_host *); static void sdhci_enable_preset_value(struct sdhci_host *host, bool enable); +static void sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd); + void sdhci_dumpregs(struct sdhci_host *host) { SDHCI_DUMP("============ SDHCI REGISTER DUMP ===========\n"); @@ -1558,7 +1560,7 @@ static void sdhci_finish_data(struct sdhci_host *host) } } -void sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd) +static void sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd) { int flags; u32 mask; @@ -1658,7 +1660,6 @@ void sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd) sdhci_writew(host, SDHCI_MAKE_CMD(cmd->opcode, flags), SDHCI_COMMAND); } -EXPORT_SYMBOL_GPL(sdhci_send_command); static void sdhci_read_rsp_136(struct sdhci_host *host, struct mmc_command *cmd) { diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h index 79dffbb731d3..47324feeba86 100644 --- a/drivers/mmc/host/sdhci.h +++ b/drivers/mmc/host/sdhci.h @@ -757,7 +757,6 @@ void sdhci_cleanup_host(struct sdhci_host *host); int __sdhci_add_host(struct sdhci_host *host); int sdhci_add_host(struct sdhci_host *host); void sdhci_remove_host(struct sdhci_host *host, int dead); -void sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd); static inline void sdhci_read_caps(struct sdhci_host *host) { From patchwork Sun Apr 12 09:03:47 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Adrian Hunter X-Patchwork-Id: 11484475 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 2DF8081 for ; Sun, 12 Apr 2020 09:04:44 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 0F9AE20709 for ; Sun, 12 Apr 2020 09:04:44 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726139AbgDLJEn (ORCPT ); Sun, 12 Apr 2020 05:04:43 -0400 Received: from mga12.intel.com ([192.55.52.136]:20973 "EHLO mga12.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725832AbgDLJEm (ORCPT ); Sun, 12 Apr 2020 05:04:42 -0400 IronPort-SDR: ynyXstpmW0s+NSK+cBsbAz5gEQ0+T90YUoDXZMSq8j6eXBzUGew3e4LVjWonrGKBSM3uDO44Vv qReqBOR/Ix1w== X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga001.fm.intel.com ([10.253.24.23]) by fmsmga106.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 12 Apr 2020 02:04:43 -0700 IronPort-SDR: ljuvzZBHqzw2PRbqiNqzqjAZB+NWwBa7BjkuGsyvUQFDNWu3upAi3BuCM2WBnYafPKe2WmM0j0 9iBxKscFe57A== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.72,374,1580803200"; d="scan'208";a="362835163" Received: from ahunter-desktop.fi.intel.com ([10.237.72.87]) by fmsmga001.fm.intel.com with ESMTP; 12 Apr 2020 02:04:41 -0700 From: Adrian Hunter To: Ulf Hansson , Baolin Wang Cc: linux-mmc Subject: [PATCH 3/5] mmc: sdhci: Remove unneeded forward declaration of sdhci_finish_data() Date: Sun, 12 Apr 2020 12:03:47 +0300 Message-Id: <20200412090349.1607-4-adrian.hunter@intel.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200412090349.1607-1-adrian.hunter@intel.com> References: <20200412090349.1607-1-adrian.hunter@intel.com> Organization: Intel Finland Oy, Registered Address: PL 281, 00181 Helsinki, Business Identity Code: 0357606 - 4, Domiciled in Helsinki Sender: linux-mmc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-mmc@vger.kernel.org sdhci_finish_data() is defined before it is referenced, so forward declaration is not necessary. Signed-off-by: Adrian Hunter --- drivers/mmc/host/sdhci.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 429e5b80f2fb..27be2152553f 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -48,8 +48,6 @@ static unsigned int debug_quirks = 0; static unsigned int debug_quirks2; -static void sdhci_finish_data(struct sdhci_host *); - static void sdhci_enable_preset_value(struct sdhci_host *host, bool enable); static void sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd); From patchwork Sun Apr 12 09:03:48 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Adrian Hunter X-Patchwork-Id: 11484477 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id B9ABD81 for ; Sun, 12 Apr 2020 09:04:45 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id A64B420709 for ; Sun, 12 Apr 2020 09:04:45 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726658AbgDLJEo (ORCPT ); Sun, 12 Apr 2020 05:04:44 -0400 Received: from mga12.intel.com ([192.55.52.136]:20973 "EHLO mga12.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725832AbgDLJEo (ORCPT ); Sun, 12 Apr 2020 05:04:44 -0400 IronPort-SDR: Iwy+id4MxoJ9kzoJq/nS+6AycLLfh0ICyEZhc9p57IgaC2R3/ofl34EbQDvT6qNIO4btRDd83p FL+kmjKPFADg== X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga001.fm.intel.com ([10.253.24.23]) by fmsmga106.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 12 Apr 2020 02:04:44 -0700 IronPort-SDR: gRtjE8uSOj/wdKO+cNHTX+QUcqs9/OdA8q45gLovBtG1/2PJk4fMFGwIhISVo7FZ5cV0ZEcI24 aoXUiQaJaS3A== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.72,374,1580803200"; d="scan'208";a="362835168" Received: from ahunter-desktop.fi.intel.com ([10.237.72.87]) by fmsmga001.fm.intel.com with ESMTP; 12 Apr 2020 02:04:43 -0700 From: Adrian Hunter To: Ulf Hansson , Baolin Wang Cc: linux-mmc Subject: [PATCH 4/5] mmc: sdhci: Tidy sdhci_request() a bit Date: Sun, 12 Apr 2020 12:03:48 +0300 Message-Id: <20200412090349.1607-5-adrian.hunter@intel.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200412090349.1607-1-adrian.hunter@intel.com> References: <20200412090349.1607-1-adrian.hunter@intel.com> Organization: Intel Finland Oy, Registered Address: PL 281, 00181 Helsinki, Business Identity Code: 0357606 - 4, Domiciled in Helsinki Sender: linux-mmc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-mmc@vger.kernel.org In preparation for further changes, tidy sdhci_request() a bit. Signed-off-by: Adrian Hunter --- drivers/mmc/host/sdhci.c | 39 ++++++++++++++++++++++++++------------- 1 file changed, 26 insertions(+), 13 deletions(-) diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 27be2152553f..b9ddc8edffe2 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -1659,6 +1659,17 @@ static void sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd) sdhci_writew(host, SDHCI_MAKE_CMD(cmd->opcode, flags), SDHCI_COMMAND); } +static bool sdhci_present_error(struct sdhci_host *host, + struct mmc_command *cmd, bool present) +{ + if (!present || host->flags & SDHCI_DEVICE_DEAD) { + cmd->error = -ENOMEDIUM; + return true; + } + + return false; +} + static void sdhci_read_rsp_136(struct sdhci_host *host, struct mmc_command *cmd) { int i, reg; @@ -2048,11 +2059,10 @@ EXPORT_SYMBOL_GPL(sdhci_set_power_and_bus_voltage); void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq) { - struct sdhci_host *host; - int present; + struct sdhci_host *host = mmc_priv(mmc); + struct mmc_command *cmd; unsigned long flags; - - host = mmc_priv(mmc); + bool present; /* Firstly check card presence */ present = mmc->ops->get_cd(mmc); @@ -2061,16 +2071,19 @@ void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq) sdhci_led_activate(host); - if (!present || host->flags & SDHCI_DEVICE_DEAD) { - mrq->cmd->error = -ENOMEDIUM; - sdhci_finish_mrq(host, mrq); - } else { - if (sdhci_manual_cmd23(host, mrq)) - sdhci_send_command(host, mrq->sbc); - else - sdhci_send_command(host, mrq->cmd); - } + if (sdhci_present_error(host, mrq->cmd, present)) + goto out_finish; + + cmd = sdhci_manual_cmd23(host, mrq) ? mrq->sbc : mrq->cmd; + + sdhci_send_command(host, cmd); + + spin_unlock_irqrestore(&host->lock, flags); + + return; +out_finish: + sdhci_finish_mrq(host, mrq); spin_unlock_irqrestore(&host->lock, flags); } EXPORT_SYMBOL_GPL(sdhci_request); From patchwork Sun Apr 12 09:03:49 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Adrian Hunter X-Patchwork-Id: 11484479 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 4243081 for ; Sun, 12 Apr 2020 09:04:47 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 268D520709 for ; Sun, 12 Apr 2020 09:04:47 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726689AbgDLJEq (ORCPT ); Sun, 12 Apr 2020 05:04:46 -0400 Received: from mga12.intel.com ([192.55.52.136]:20973 "EHLO mga12.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725832AbgDLJEq (ORCPT ); Sun, 12 Apr 2020 05:04:46 -0400 IronPort-SDR: TfphDBdnqYP5VnMhxFWMQGvBEGg7W220VKuGhunehdymj/tLo2lc/y4lJ2DgOztpv3CbDW08rp QS8+FT1QGXTQ== X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga001.fm.intel.com ([10.253.24.23]) by fmsmga106.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 12 Apr 2020 02:04:46 -0700 IronPort-SDR: MkXWtZHbWj2T32Vf5t5Uw3jiBXYdPoBX0eD3FCHpLnXikTGVCP9TAl2mbs7rpgh88f8Y0HUmcM zd11wnFi2EnQ== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.72,374,1580803200"; d="scan'208";a="362835175" Received: from ahunter-desktop.fi.intel.com ([10.237.72.87]) by fmsmga001.fm.intel.com with ESMTP; 12 Apr 2020 02:04:44 -0700 From: Adrian Hunter To: Ulf Hansson , Baolin Wang Cc: linux-mmc Subject: [PATCH 5/5] mmc: sdhci: Reduce maximum time under spinlock in sdhci_send_command() Date: Sun, 12 Apr 2020 12:03:49 +0300 Message-Id: <20200412090349.1607-6-adrian.hunter@intel.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200412090349.1607-1-adrian.hunter@intel.com> References: <20200412090349.1607-1-adrian.hunter@intel.com> Organization: Intel Finland Oy, Registered Address: PL 281, 00181 Helsinki, Business Identity Code: 0357606 - 4, Domiciled in Helsinki Sender: linux-mmc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-mmc@vger.kernel.org Spending time under spinlock increases IRQ latencies and also response times because preemption is disabled. sdhci_send_command() waits up to 10 ms under spinlock for inhibit bits to clear. In general inhibit bits will not be set, but there may be corner cases, especially in the face of errors, where waiting helps. There might also be dysfunctional hardware that needs the waiting. So retain the legacy behaviour but do not wait for inhibit bits while under spinlock. Instead adjust the logic to enable waiting while not under spinlock. That is mostly straight forward, but in the interrupt handler it requires deferring an "inhibited" command to the IRQ thread where sleeping is allowed. Signed-off-by: Adrian Hunter --- drivers/mmc/host/sdhci.c | 126 ++++++++++++++++++++++++++++++--------- drivers/mmc/host/sdhci.h | 1 + 2 files changed, 99 insertions(+), 28 deletions(-) diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index b9ddc8edffe2..10b9570f48aa 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -50,7 +50,7 @@ static unsigned int debug_quirks2; static void sdhci_enable_preset_value(struct sdhci_host *host, bool enable); -static void sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd); +static bool sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd); void sdhci_dumpregs(struct sdhci_host *host) { @@ -1478,6 +1478,9 @@ static void __sdhci_finish_mrq(struct sdhci_host *host, struct mmc_request *mrq) if (host->data_cmd && host->data_cmd->mrq == mrq) host->data_cmd = NULL; + if (host->deferred_cmd && host->deferred_cmd->mrq == mrq) + host->deferred_cmd = NULL; + if (host->data && host->data->mrq == mrq) host->data = NULL; @@ -1499,7 +1502,7 @@ static void sdhci_finish_mrq(struct sdhci_host *host, struct mmc_request *mrq) queue_work(host->complete_wq, &host->complete_work); } -static void sdhci_finish_data(struct sdhci_host *host) +static void __sdhci_finish_data(struct sdhci_host *host, bool sw_data_timeout) { struct mmc_command *data_cmd = host->data_cmd; struct mmc_data *data = host->data; @@ -1551,14 +1554,31 @@ static void sdhci_finish_data(struct sdhci_host *host) } else { /* Avoid triggering warning in sdhci_send_command() */ host->cmd = NULL; - sdhci_send_command(host, data->stop); + if (!sdhci_send_command(host, data->stop)) { + if (sw_data_timeout) { + /* + * This is anyway a sw data timeout, so + * give up now. + */ + data->stop->error = -EIO; + __sdhci_finish_mrq(host, data->mrq); + } else { + WARN_ON(host->deferred_cmd); + host->deferred_cmd = data->stop; + } + } } } else { __sdhci_finish_mrq(host, data->mrq); } } -static void sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd) +static void sdhci_finish_data(struct sdhci_host *host) +{ + __sdhci_finish_data(host, false); +} + +static bool sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd) { int flags; u32 mask; @@ -1573,9 +1593,6 @@ static void sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd) cmd->opcode == MMC_STOP_TRANSMISSION) cmd->flags |= MMC_RSP_BUSY; - /* Wait max 10 ms */ - timeout = 10; - mask = SDHCI_CMD_INHIBIT; if (sdhci_data_line_cmd(cmd)) mask |= SDHCI_DATA_INHIBIT; @@ -1585,18 +1602,8 @@ static void sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd) if (cmd->mrq->data && (cmd == cmd->mrq->data->stop)) mask &= ~SDHCI_DATA_INHIBIT; - while (sdhci_readl(host, SDHCI_PRESENT_STATE) & mask) { - if (timeout == 0) { - pr_err("%s: Controller never released inhibit bit(s).\n", - mmc_hostname(host->mmc)); - sdhci_dumpregs(host); - cmd->error = -EIO; - sdhci_finish_mrq(host, cmd->mrq); - return; - } - timeout--; - mdelay(1); - } + if (sdhci_readl(host, SDHCI_PRESENT_STATE) & mask) + return false; host->cmd = cmd; host->data_timeout = 0; @@ -1618,11 +1625,13 @@ static void sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd) sdhci_set_transfer_mode(host, cmd); if ((cmd->flags & MMC_RSP_136) && (cmd->flags & MMC_RSP_BUSY)) { - pr_err("%s: Unsupported response type!\n", - mmc_hostname(host->mmc)); - cmd->error = -EINVAL; - sdhci_finish_mrq(host, cmd->mrq); - return; + WARN_ONCE(1, "Unsupported response type!\n"); + /* + * This does not happen in practice because 136-bit response + * commands never have busy waiting, so rather than complicate + * the error path, just remove busy waiting and continue. + */ + cmd->flags &= ~MMC_RSP_BUSY; } if (!(cmd->flags & MMC_RSP_PRESENT)) @@ -1657,6 +1666,8 @@ static void sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd) sdhci_external_dma_pre_transfer(host, cmd); sdhci_writew(host, SDHCI_MAKE_CMD(cmd->opcode, flags), SDHCI_COMMAND); + + return true; } static bool sdhci_present_error(struct sdhci_host *host, @@ -1670,6 +1681,47 @@ static bool sdhci_present_error(struct sdhci_host *host, return false; } +static bool sdhci_send_command_retry(struct sdhci_host *host, + struct mmc_command *cmd, + unsigned long flags) + __releases(host->lock) + __acquires(host->lock) +{ + struct mmc_command *deferred_cmd = host->deferred_cmd; + int timeout = 10; /* Approx. 10 ms */ + bool present; + + while (!sdhci_send_command(host, cmd)) { + if (!timeout--) { + pr_err("%s: Controller never released inhibit bit(s).\n", + mmc_hostname(host->mmc)); + sdhci_dumpregs(host); + cmd->error = -EIO; + return false; + } + + spin_unlock_irqrestore(&host->lock, flags); + + usleep_range(1000, 1250); + + present = host->mmc->ops->get_cd(host->mmc); + + spin_lock_irqsave(&host->lock, flags); + + /* A deferred command might disappear, handle that */ + if (cmd == deferred_cmd && cmd != host->deferred_cmd) + return true; + + if (sdhci_present_error(host, cmd, present)) + return false; + } + + if (cmd == host->deferred_cmd) + host->deferred_cmd = NULL; + + return true; +} + static void sdhci_read_rsp_136(struct sdhci_host *host, struct mmc_command *cmd) { int i, reg; @@ -1729,7 +1781,10 @@ static void sdhci_finish_command(struct sdhci_host *host) /* Finished CMD23, now send actual command. */ if (cmd == cmd->mrq->sbc) { - sdhci_send_command(host, cmd->mrq->cmd); + if (!sdhci_send_command(host, cmd->mrq->cmd)) { + WARN_ON(host->deferred_cmd); + host->deferred_cmd = cmd->mrq->cmd; + } } else { /* Processed actual command. */ @@ -2076,7 +2131,8 @@ void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq) cmd = sdhci_manual_cmd23(host, mrq) ? mrq->sbc : mrq->cmd; - sdhci_send_command(host, cmd); + if (!sdhci_send_command_retry(host, cmd, flags)) + goto out_finish; spin_unlock_irqrestore(&host->lock, flags); @@ -2624,7 +2680,11 @@ void sdhci_send_tuning(struct sdhci_host *host, u32 opcode) */ sdhci_writew(host, SDHCI_TRNS_READ, SDHCI_TRANSFER_MODE); - sdhci_send_command(host, &cmd); + if (!sdhci_send_command_retry(host, &cmd, flags)) { + spin_unlock_irqrestore(&host->lock, flags); + host->tuning_done = 0; + return; + } host->cmd = NULL; @@ -3042,7 +3102,7 @@ static void sdhci_timeout_data_timer(struct timer_list *t) if (host->data) { host->data->error = -ETIMEDOUT; - sdhci_finish_data(host); + __sdhci_finish_data(host, true); queue_work(host->complete_wq, &host->complete_work); } else if (host->data_cmd) { host->data_cmd->error = -ETIMEDOUT; @@ -3414,6 +3474,9 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id) } } out: + if (host->deferred_cmd) + result = IRQ_WAKE_THREAD; + spin_unlock(&host->lock); /* Process mrqs ready for immediate completion */ @@ -3439,6 +3502,7 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id) static irqreturn_t sdhci_thread_irq(int irq, void *dev_id) { struct sdhci_host *host = dev_id; + struct mmc_command *cmd; unsigned long flags; u32 isr; @@ -3446,8 +3510,14 @@ static irqreturn_t sdhci_thread_irq(int irq, void *dev_id) ; spin_lock_irqsave(&host->lock, flags); + isr = host->thread_isr; host->thread_isr = 0; + + cmd = host->deferred_cmd; + if (cmd && !sdhci_send_command_retry(host, cmd, flags)) + sdhci_finish_mrq(host, cmd->mrq); + spin_unlock_irqrestore(&host->lock, flags); if (isr & (SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE)) { diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h index 47324feeba86..a7e469c00617 100644 --- a/drivers/mmc/host/sdhci.h +++ b/drivers/mmc/host/sdhci.h @@ -540,6 +540,7 @@ struct sdhci_host { struct mmc_request *mrqs_done[SDHCI_MAX_MRQS]; /* Requests done */ struct mmc_command *cmd; /* Current command */ struct mmc_command *data_cmd; /* Current data command */ + struct mmc_command *deferred_cmd; /* Deferred command */ struct mmc_data *data; /* Current data request */ unsigned int data_early:1; /* Data finished before cmd */