From patchwork Thu Jun 9 11:52:17 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Adrian Hunter X-Patchwork-Id: 9166831 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 3EC2560467 for ; Thu, 9 Jun 2016 11:58:03 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 2F8502766D for ; Thu, 9 Jun 2016 11:58:03 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 247BC28345; Thu, 9 Jun 2016 11:58:03 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.9 required=2.0 tests=BAYES_00,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id A7BBC2766D for ; Thu, 9 Jun 2016 11:58:02 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751535AbcFIL6A (ORCPT ); Thu, 9 Jun 2016 07:58:00 -0400 Received: from mga01.intel.com ([192.55.52.88]:63235 "EHLO mga01.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751510AbcFIL56 (ORCPT ); Thu, 9 Jun 2016 07:57:58 -0400 Received: from fmsmga002.fm.intel.com ([10.253.24.26]) by fmsmga101.fm.intel.com with ESMTP; 09 Jun 2016 04:57:57 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.26,444,1459839600"; d="scan'208";a="998503726" Received: from ahunter-desktop.fi.intel.com ([10.237.72.168]) by fmsmga002.fm.intel.com with ESMTP; 09 Jun 2016 04:57:53 -0700 From: Adrian Hunter To: Ulf Hansson Cc: linux-mmc , Alex Lemberg , Mateusz Nowak , Yuliy Izrailov , Jaehoon Chung , Dong Aisheng , Das Asutosh , Zhangfei Gao , Sujit Reddy Thumma , Dorfman Konstantin , David Griego , Sahitya Tummala , Harjani Ritesh Subject: [PATCH RFC 17/46] mmc: sdhci: Allow for finishing multiple requests Date: Thu, 9 Jun 2016 14:52:17 +0300 Message-Id: <1465473166-22532-18-git-send-email-adrian.hunter@intel.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1465473166-22532-1-git-send-email-adrian.hunter@intel.com> References: <1465473166-22532-1-git-send-email-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 X-Virus-Scanned: ClamAV using ClamSMTP In order to support commands during data transfer, there will have to be up to two active requests (mrqs) at a time, instead of just one. That means recording which request is finished. Doing that obsoletes host->mrq which is therefore removed. Signed-off-by: Adrian Hunter --- drivers/mmc/host/sdhci.c | 71 +++++++++++++++++++++++++++++++++--------------- drivers/mmc/host/sdhci.h | 5 +++- 2 files changed, 53 insertions(+), 23 deletions(-) diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index f04df6f42f35..fa527a89ee4c 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -938,6 +938,29 @@ static bool sdhci_needs_reset(struct sdhci_host *host, struct mmc_request *mrq) (host->quirks & SDHCI_QUIRK_RESET_AFTER_REQUEST))); } +static void __sdhci_finish_mrq(struct sdhci_host *host, struct mmc_request *mrq) +{ + int i; + + for (i = 0; i < SDHCI_MAX_MRQS; i++) { + if (host->mrqs_done[i] == mrq) { + WARN_ON(1); + return; + } + } + + for (i = 0; i < SDHCI_MAX_MRQS; i++) { + if (!host->mrqs_done[i]) { + host->mrqs_done[i] = mrq; + break; + } + } + + WARN_ON(i >= SDHCI_MAX_MRQS); + + tasklet_schedule(&host->finish_tasklet); +} + static void sdhci_finish_mrq(struct sdhci_host *host, struct mmc_request *mrq) { if (host->cmd && host->cmd->mrq == mrq) @@ -952,7 +975,7 @@ static void sdhci_finish_mrq(struct sdhci_host *host, struct mmc_request *mrq) if (sdhci_needs_reset(host, mrq)) host->pending_reset = true; - tasklet_schedule(&host->finish_tasklet); + __sdhci_finish_mrq(host, mrq); } static void sdhci_finish_data(struct sdhci_host *host) @@ -1440,8 +1463,6 @@ static void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq) spin_lock_irqsave(&host->lock, flags); - WARN_ON(host->mrq != NULL); - sdhci_led_activate(host); /* @@ -1455,8 +1476,6 @@ static void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq) } } - host->mrq = mrq; - if (!present || host->flags & SDHCI_DEVICE_DEAD) { mrq->cmd->error = -ENOMEDIUM; sdhci_finish_mrq(host, mrq); @@ -1987,13 +2006,13 @@ static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode) cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC; cmd.retries = 0; cmd.data = NULL; + cmd.mrq = &mrq; cmd.error = 0; if (tuning_loop_counter-- == 0) break; mrq.cmd = &cmd; - host->mrq = &mrq; /* * In response to CMD19, the card sends 64 bytes of tuning @@ -2023,7 +2042,6 @@ static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode) sdhci_send_command(host, &cmd); host->cmd = NULL; - host->mrq = NULL; spin_unlock_irqrestore(&host->lock, flags); /* Wait for Buffer Read Ready interrupt */ @@ -2224,26 +2242,26 @@ static const struct mmc_host_ops sdhci_ops = { * * \*****************************************************************************/ -static void sdhci_tasklet_finish(unsigned long param) +static bool sdhci_request_done(struct sdhci_host *host) { - struct sdhci_host *host; unsigned long flags; struct mmc_request *mrq; - - host = (struct sdhci_host*)param; + int i; spin_lock_irqsave(&host->lock, flags); - /* - * If this tasklet gets rescheduled while running, it will - * be run again afterwards but without any active request. - */ - if (!host->mrq) { - spin_unlock_irqrestore(&host->lock, flags); - return; + for (i = 0; i < SDHCI_MAX_MRQS; i++) { + mrq = host->mrqs_done[i]; + if (mrq) { + host->mrqs_done[i] = NULL; + break; + } } - mrq = host->mrq; + if (!mrq) { + spin_unlock_irqrestore(&host->lock, flags); + return true; + } sdhci_del_timer(host, mrq); @@ -2281,14 +2299,23 @@ static void sdhci_tasklet_finish(unsigned long param) host->pending_reset = false; } - host->mrq = NULL; - - sdhci_led_deactivate(host); + if (!sdhci_has_requests(host)) + sdhci_led_deactivate(host); mmiowb(); spin_unlock_irqrestore(&host->lock, flags); mmc_request_done(host->mmc, mrq); + + return false; +} + +static void sdhci_tasklet_finish(unsigned long param) +{ + struct sdhci_host *host = (struct sdhci_host *)param; + + while (!sdhci_request_done(host)) + ; } static void sdhci_timeout_timer(unsigned long data) diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h index 10f835f785f7..7c1f3cf4c459 100644 --- a/drivers/mmc/host/sdhci.h +++ b/drivers/mmc/host/sdhci.h @@ -314,6 +314,9 @@ struct sdhci_adma2_64_desc { */ #define SDHCI_MAX_SEGS 128 +/* Allow for a a command request and a data request at the same time */ +#define SDHCI_MAX_MRQS 2 + enum sdhci_cookie { COOKIE_UNMAPPED, COOKIE_PRE_MAPPED, /* mapped by sdhci_pre_req() */ @@ -462,7 +465,7 @@ struct sdhci_host { bool preset_enabled; /* Preset is enabled */ bool pending_reset; /* Cmd/data reset is pending */ - struct mmc_request *mrq; /* Current request */ + 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_data *data; /* Current data request */