From patchwork Wed Feb 5 12:50:28 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Baolin Wang X-Patchwork-Id: 11366243 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 686FD1395 for ; Wed, 5 Feb 2020 12:51:24 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 27F8120702 for ; Wed, 5 Feb 2020 12:51:24 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="erF5E7kl" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727843AbgBEMvX (ORCPT ); Wed, 5 Feb 2020 07:51:23 -0500 Received: from mail-pj1-f68.google.com ([209.85.216.68]:55714 "EHLO mail-pj1-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726960AbgBEMvX (ORCPT ); Wed, 5 Feb 2020 07:51:23 -0500 Received: by mail-pj1-f68.google.com with SMTP id d5so941292pjz.5; Wed, 05 Feb 2020 04:51:22 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :in-reply-to:references; bh=7oAyWKRGwewusOfJodJV0lT1HUd5U1xNB3qu+a+b4NE=; b=erF5E7klaPnf3plaxnnKWK5pITTHaSVxTm4w30mmcsZ9e2fRawTC1Jh2uZyC61EAIP lWgEV4Tkz0yjC1nEev782X0VE788TgQUv5LLysM4IpHqwMFIA7DM5L1duqftpzdRfbQb f/UmPo8dwChk2/DEH3wx9UPPwtkb907MRMAJsPOjpFCpVH3H6Xg0LSjCgumqbMFe3FGv 83B9Vymf2xOovtMvirr4R7mU1iMQ5lWhNoLypsBRja84PVfEkEf04e3ipdwCDpytkPSp jsK7iV/rjxO7cJVCUlQ4dMTYAj/BHiNl6QTuSkO5QUJwt58ybWDs7ECYOvJ37mM6+WzX 4y5g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:in-reply-to:references; bh=7oAyWKRGwewusOfJodJV0lT1HUd5U1xNB3qu+a+b4NE=; b=Zup3l7jmoyZ/N1K5JMevNLZN0rRx36Y9oq+g02A5nFjNZoTp9PaznIi5Q1kPelVlMY Snbfygeix9Pws2cOdsCNEuMEdS1fde5+fpG4XlHdAuj1qEFh9MCExvPz3LDmyPf4FKxo KC0tfCJXQFhrmn+rbGD77R4YdAF5nzzgFBxTM8s9zsHGLRLTiFY3ykWFUuX9EaSCWJGD cau2wmIAgaYixNz+eCb+Vanq0c5Q7+qTq/gXl/ICnJky5/DAQxX01kNE/RCcD8gpL6oR M6UNfg8miEfFnI0RCJgkqlNCTvSlb8Xdf0lM68FfBbXHslpiM5gIlZFe6ARLq935/Ssi L4Hw== X-Gm-Message-State: APjAAAUTyppowz3UP7AOUo5zih64+3PVyFBgWT00TrGd6JN+YVA5yQvx Mnz6dnMp7Ls152D1bGdfbhU= X-Google-Smtp-Source: APXvYqxnrCQISn0NbywEjSgPFZx1rQ9qRyj4je9QHWq9zn+FUuDHnsnMphIF2BIZu9PS0mQFXhV/YQ== X-Received: by 2002:a17:90a:fb45:: with SMTP id iq5mr5396245pjb.93.1580907081443; Wed, 05 Feb 2020 04:51:21 -0800 (PST) Received: from baolinwangubtpc.spreadtrum.com ([117.18.48.82]) by smtp.gmail.com with ESMTPSA id y127sm22864784pfg.22.2020.02.05.04.51.18 (version=TLS1 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Wed, 05 Feb 2020 04:51:20 -0800 (PST) From: Baolin Wang To: adrian.hunter@intel.com, ulf.hansson@linaro.org, asutoshd@codeaurora.org Cc: orsonzhai@gmail.com, zhang.lyra@gmail.com, arnd@arndb.de, linus.walleij@linaro.org, baolin.wang@linaro.org, baolin.wang7@gmail.com, linux-mmc@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v8 1/5] mmc: Add MMC host software queue support Date: Wed, 5 Feb 2020 20:50:28 +0800 Message-Id: <3fd82478e82b19c72dddcc17c85313725aa13ff6.1580894083.git.baolin.wang7@gmail.com> X-Mailer: git-send-email 1.7.9.5 In-Reply-To: References: In-Reply-To: References: Sender: linux-mmc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-mmc@vger.kernel.org From: Baolin Wang Now the MMC read/write stack will always wait for previous request is completed by mmc_blk_rw_wait(), before sending a new request to hardware, or queue a work to complete request, that will bring context switching overhead, especially for high I/O per second rates, to affect the IO performance. Thus this patch introduces MMC software queue interface based on the hardware command queue engine's interfaces, which is similar with the hardware command queue engine's idea, that can remove the context switching. Moreover we set the default queue depth as 64 for software queue, which allows more requests to be prepared, merged and inserted into IO scheduler to improve performance, but we only allow 2 requests in flight, that is enough to let the irq handler always trigger the next request without a context switch, as well as avoiding a long latency. From the fio testing data in cover letter, we can see the software queue can improve some performance with 4K block size, increasing about 16% for random read, increasing about 90% for random write, though no obvious improvement for sequential read and write. Moreover we can expand the software queue interface to support MMC packed request or packed command in future. Reviewed-by: Arnd Bergmann Signed-off-by: Baolin Wang Signed-off-by: Baolin Wang --- drivers/mmc/core/block.c | 61 ++++++++ drivers/mmc/core/mmc.c | 13 +- drivers/mmc/core/queue.c | 22 ++- drivers/mmc/host/Kconfig | 7 + drivers/mmc/host/Makefile | 1 + drivers/mmc/host/cqhci.c | 3 + drivers/mmc/host/mmc_hsq.c | 343 ++++++++++++++++++++++++++++++++++++++++++++ drivers/mmc/host/mmc_hsq.h | 30 ++++ include/linux/mmc/host.h | 3 + 9 files changed, 476 insertions(+), 7 deletions(-) create mode 100644 drivers/mmc/host/mmc_hsq.c create mode 100644 drivers/mmc/host/mmc_hsq.h diff --git a/drivers/mmc/core/block.c b/drivers/mmc/core/block.c index 663d879..55d52fc 100644 --- a/drivers/mmc/core/block.c +++ b/drivers/mmc/core/block.c @@ -168,6 +168,11 @@ struct mmc_rpmb_data { static inline int mmc_blk_part_switch(struct mmc_card *card, unsigned int part_type); +static void mmc_blk_rw_rq_prep(struct mmc_queue_req *mqrq, + struct mmc_card *card, + int disable_multi, + struct mmc_queue *mq); +static void mmc_blk_hsq_req_done(struct mmc_request *mrq); static struct mmc_blk_data *mmc_blk_get(struct gendisk *disk) { @@ -1532,9 +1537,30 @@ static int mmc_blk_cqe_issue_flush(struct mmc_queue *mq, struct request *req) return mmc_blk_cqe_start_req(mq->card->host, mrq); } +static int mmc_blk_hsq_issue_rw_rq(struct mmc_queue *mq, struct request *req) +{ + struct mmc_queue_req *mqrq = req_to_mmc_queue_req(req); + struct mmc_host *host = mq->card->host; + int err; + + mmc_blk_rw_rq_prep(mqrq, mq->card, 0, mq); + mqrq->brq.mrq.done = mmc_blk_hsq_req_done; + mmc_pre_req(host, &mqrq->brq.mrq); + + err = mmc_cqe_start_req(host, &mqrq->brq.mrq); + if (err) + mmc_post_req(host, &mqrq->brq.mrq, err); + + return err; +} + static int mmc_blk_cqe_issue_rw_rq(struct mmc_queue *mq, struct request *req) { struct mmc_queue_req *mqrq = req_to_mmc_queue_req(req); + struct mmc_host *host = mq->card->host; + + if (host->hsq_enabled) + return mmc_blk_hsq_issue_rw_rq(mq, req); mmc_blk_data_prep(mq, mqrq, 0, NULL, NULL); @@ -1920,6 +1946,41 @@ static void mmc_blk_urgent_bkops(struct mmc_queue *mq, mmc_run_bkops(mq->card); } +static void mmc_blk_hsq_req_done(struct mmc_request *mrq) +{ + struct mmc_queue_req *mqrq = + container_of(mrq, struct mmc_queue_req, brq.mrq); + struct request *req = mmc_queue_req_to_req(mqrq); + struct request_queue *q = req->q; + struct mmc_queue *mq = q->queuedata; + struct mmc_host *host = mq->card->host; + unsigned long flags; + + if (mmc_blk_rq_error(&mqrq->brq) || + mmc_blk_urgent_bkops_needed(mq, mqrq)) { + spin_lock_irqsave(&mq->lock, flags); + mq->recovery_needed = true; + mq->recovery_req = req; + spin_unlock_irqrestore(&mq->lock, flags); + + host->cqe_ops->cqe_recovery_start(host); + + schedule_work(&mq->recovery_work); + return; + } + + mmc_blk_rw_reset_success(mq, req); + + /* + * Block layer timeouts race with completions which means the normal + * completion path cannot be used during recovery. + */ + if (mq->in_recovery) + mmc_blk_cqe_complete_rq(mq, req); + else + blk_mq_complete_request(req); +} + void mmc_blk_mq_complete(struct request *req) { struct mmc_queue *mq = req->q->queuedata; diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index f6912de..7a9976f 100644 --- a/drivers/mmc/core/mmc.c +++ b/drivers/mmc/core/mmc.c @@ -1851,15 +1851,22 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, */ card->reenable_cmdq = card->ext_csd.cmdq_en; - if (card->ext_csd.cmdq_en && !host->cqe_enabled) { + if (host->cqe_ops && !host->cqe_enabled) { err = host->cqe_ops->cqe_enable(host, card); if (err) { pr_err("%s: Failed to enable CQE, error %d\n", mmc_hostname(host), err); } else { host->cqe_enabled = true; - pr_info("%s: Command Queue Engine enabled\n", - mmc_hostname(host)); + + if (card->ext_csd.cmdq_en) { + pr_info("%s: Command Queue Engine enabled\n", + mmc_hostname(host)); + } else { + host->hsq_enabled = true; + pr_info("%s: Host Software Queue enabled\n", + mmc_hostname(host)); + } } } diff --git a/drivers/mmc/core/queue.c b/drivers/mmc/core/queue.c index 9edc086..25bee3d 100644 --- a/drivers/mmc/core/queue.c +++ b/drivers/mmc/core/queue.c @@ -62,7 +62,7 @@ enum mmc_issue_type mmc_issue_type(struct mmc_queue *mq, struct request *req) { struct mmc_host *host = mq->card->host; - if (mq->use_cqe) + if (mq->use_cqe && !host->hsq_enabled) return mmc_cqe_issue_type(host, req); if (req_op(req) == REQ_OP_READ || req_op(req) == REQ_OP_WRITE) @@ -124,12 +124,14 @@ static enum blk_eh_timer_return mmc_mq_timed_out(struct request *req, { struct request_queue *q = req->q; struct mmc_queue *mq = q->queuedata; + struct mmc_card *card = mq->card; + struct mmc_host *host = card->host; unsigned long flags; int ret; spin_lock_irqsave(&mq->lock, flags); - if (mq->recovery_needed || !mq->use_cqe) + if (mq->recovery_needed || !mq->use_cqe || host->hsq_enabled) ret = BLK_EH_RESET_TIMER; else ret = mmc_cqe_timed_out(req); @@ -144,12 +146,13 @@ static void mmc_mq_recovery_handler(struct work_struct *work) struct mmc_queue *mq = container_of(work, struct mmc_queue, recovery_work); struct request_queue *q = mq->queue; + struct mmc_host *host = mq->card->host; mmc_get_card(mq->card, &mq->ctx); mq->in_recovery = true; - if (mq->use_cqe) + if (mq->use_cqe && !host->hsq_enabled) mmc_blk_cqe_recovery(mq); else mmc_blk_mq_recovery(mq); @@ -160,6 +163,9 @@ static void mmc_mq_recovery_handler(struct work_struct *work) mq->recovery_needed = false; spin_unlock_irq(&mq->lock); + if (host->hsq_enabled) + host->cqe_ops->cqe_recovery_finish(host); + mmc_put_card(mq->card, &mq->ctx); blk_mq_run_hw_queues(q, true); @@ -279,6 +285,14 @@ static blk_status_t mmc_mq_queue_rq(struct blk_mq_hw_ctx *hctx, } break; case MMC_ISSUE_ASYNC: + /* + * For MMC host software queue, we only allow 2 requests in + * flight to avoid a long latency. + */ + if (host->hsq_enabled && mq->in_flight[issue_type] > 2) { + spin_unlock_irq(&mq->lock); + return BLK_STS_RESOURCE; + } break; default: /* @@ -430,7 +444,7 @@ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card) * The queue depth for CQE must match the hardware because the request * tag is used to index the hardware queue. */ - if (mq->use_cqe) + if (mq->use_cqe && !host->hsq_enabled) mq->tag_set.queue_depth = min_t(int, card->ext_csd.cmdq_depth, host->cqe_qdepth); else diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig index 3a5089f..65d3966 100644 --- a/drivers/mmc/host/Kconfig +++ b/drivers/mmc/host/Kconfig @@ -949,6 +949,13 @@ config MMC_CQHCI If unsure, say N. +config MMC_HSQ + tristate "MMC Host Software Queue support" + help + This selects the Software Queue support. + + If unsure, say N. + config MMC_TOSHIBA_PCI tristate "Toshiba Type A SD/MMC Card Interface Driver" depends on PCI diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile index 21d9089..b929ef9 100644 --- a/drivers/mmc/host/Makefile +++ b/drivers/mmc/host/Makefile @@ -100,6 +100,7 @@ obj-$(CONFIG_MMC_SDHCI_BRCMSTB) += sdhci-brcmstb.o obj-$(CONFIG_MMC_SDHCI_OMAP) += sdhci-omap.o obj-$(CONFIG_MMC_SDHCI_SPRD) += sdhci-sprd.o obj-$(CONFIG_MMC_CQHCI) += cqhci.o +obj-$(CONFIG_MMC_HSQ) += mmc_hsq.o ifeq ($(CONFIG_CB710_DEBUG),y) CFLAGS-cb710-mmc += -DDEBUG diff --git a/drivers/mmc/host/cqhci.c b/drivers/mmc/host/cqhci.c index 5047f73..4a335f7 100644 --- a/drivers/mmc/host/cqhci.c +++ b/drivers/mmc/host/cqhci.c @@ -321,6 +321,9 @@ static int cqhci_enable(struct mmc_host *mmc, struct mmc_card *card) struct cqhci_host *cq_host = mmc->cqe_private; int err; + if (!card->ext_csd.cmdq_en) + return -EINVAL; + if (cq_host->enabled) return 0; diff --git a/drivers/mmc/host/mmc_hsq.c b/drivers/mmc/host/mmc_hsq.c new file mode 100644 index 0000000..2011988 --- /dev/null +++ b/drivers/mmc/host/mmc_hsq.c @@ -0,0 +1,343 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * MMC software queue support based on command queue interfaces + * + * Copyright (C) 2019 Linaro, Inc. + * Author: Baolin Wang + */ + +#include +#include + +#include "mmc_hsq.h" + +#define HSQ_NUM_SLOTS 64 +#define HSQ_INVALID_TAG HSQ_NUM_SLOTS + +static void mmc_hsq_pump_requests(struct mmc_hsq *hsq) +{ + struct mmc_host *mmc = hsq->mmc; + struct hsq_slot *slot; + unsigned long flags; + + spin_lock_irqsave(&hsq->lock, flags); + + /* Make sure we are not already running a request now */ + if (hsq->mrq) { + spin_unlock_irqrestore(&hsq->lock, flags); + return; + } + + /* Make sure there are remain requests need to pump */ + if (!hsq->qcnt || !hsq->enabled) { + spin_unlock_irqrestore(&hsq->lock, flags); + return; + } + + slot = &hsq->slot[hsq->next_tag]; + hsq->mrq = slot->mrq; + hsq->qcnt--; + + spin_unlock_irqrestore(&hsq->lock, flags); + + mmc->ops->request(mmc, hsq->mrq); +} + +static void mmc_hsq_update_next_tag(struct mmc_hsq *hsq, int remains) +{ + struct hsq_slot *slot; + int tag; + + /* + * If there are no remain requests in software queue, then set a invalid + * tag. + */ + if (!remains) { + hsq->next_tag = HSQ_INVALID_TAG; + return; + } + + /* + * Increasing the next tag and check if the corresponding request is + * available, if yes, then we found a candidate request. + */ + if (++hsq->next_tag != HSQ_INVALID_TAG) { + slot = &hsq->slot[hsq->next_tag]; + if (slot->mrq) + return; + } + + /* Othersie we should iterate all slots to find a available tag. */ + for (tag = 0; tag < HSQ_NUM_SLOTS; tag++) { + slot = &hsq->slot[tag]; + if (slot->mrq) + break; + } + + if (tag == HSQ_NUM_SLOTS) + tag = HSQ_INVALID_TAG; + + hsq->next_tag = tag; +} + +static void mmc_hsq_post_request(struct mmc_hsq *hsq) +{ + unsigned long flags; + int remains; + + spin_lock_irqsave(&hsq->lock, flags); + + remains = hsq->qcnt; + hsq->mrq = NULL; + + /* Update the next available tag to be queued. */ + mmc_hsq_update_next_tag(hsq, remains); + + if (hsq->waiting_for_idle && !remains) { + hsq->waiting_for_idle = false; + wake_up(&hsq->wait_queue); + } + + /* Do not pump new request in recovery mode. */ + if (hsq->recovery_halt) { + spin_unlock_irqrestore(&hsq->lock, flags); + return; + } + + spin_unlock_irqrestore(&hsq->lock, flags); + + /* + * Try to pump new request to host controller as fast as possible, + * after completing previous request. + */ + if (remains > 0) + mmc_hsq_pump_requests(hsq); +} + +/** + * mmc_hsq_finalize_request - finalize one request if the request is done + * @mmc: the host controller + * @mrq: the request need to be finalized + * + * Return true if we finalized the corresponding request in software queue, + * otherwise return false. + */ +bool mmc_hsq_finalize_request(struct mmc_host *mmc, struct mmc_request *mrq) +{ + struct mmc_hsq *hsq = mmc->cqe_private; + unsigned long flags; + + spin_lock_irqsave(&hsq->lock, flags); + + if (!hsq->enabled || !hsq->mrq || hsq->mrq != mrq) { + spin_unlock_irqrestore(&hsq->lock, flags); + return false; + } + + /* + * Clear current completed slot request to make a room for new request. + */ + hsq->slot[hsq->next_tag].mrq = NULL; + + spin_unlock_irqrestore(&hsq->lock, flags); + + mmc_cqe_request_done(mmc, hsq->mrq); + + mmc_hsq_post_request(hsq); + + return true; +} +EXPORT_SYMBOL_GPL(mmc_hsq_finalize_request); + +static void mmc_hsq_recovery_start(struct mmc_host *mmc) +{ + struct mmc_hsq *hsq = mmc->cqe_private; + unsigned long flags; + + spin_lock_irqsave(&hsq->lock, flags); + + hsq->recovery_halt = true; + + spin_unlock_irqrestore(&hsq->lock, flags); +} + +static void mmc_hsq_recovery_finish(struct mmc_host *mmc) +{ + struct mmc_hsq *hsq = mmc->cqe_private; + int remains; + + spin_lock_irq(&hsq->lock); + + hsq->recovery_halt = false; + remains = hsq->qcnt; + + spin_unlock_irq(&hsq->lock); + + /* + * Try to pump new request if there are request pending in software + * queue after finishing recovery. + */ + if (remains > 0) + mmc_hsq_pump_requests(hsq); +} + +static int mmc_hsq_request(struct mmc_host *mmc, struct mmc_request *mrq) +{ + struct mmc_hsq *hsq = mmc->cqe_private; + int tag = mrq->tag; + + spin_lock_irq(&hsq->lock); + + if (!hsq->enabled) { + spin_unlock_irq(&hsq->lock); + return -ESHUTDOWN; + } + + /* Do not queue any new requests in recovery mode. */ + if (hsq->recovery_halt) { + spin_unlock_irq(&hsq->lock); + return -EBUSY; + } + + hsq->slot[tag].mrq = mrq; + + /* + * Set the next tag as current request tag if no available + * next tag. + */ + if (hsq->next_tag == HSQ_INVALID_TAG) + hsq->next_tag = tag; + + hsq->qcnt++; + + spin_unlock_irq(&hsq->lock); + + mmc_hsq_pump_requests(hsq); + + return 0; +} + +static void mmc_hsq_post_req(struct mmc_host *mmc, struct mmc_request *mrq) +{ + if (mmc->ops->post_req) + mmc->ops->post_req(mmc, mrq, 0); +} + +static bool mmc_hsq_queue_is_idle(struct mmc_hsq *hsq, int *ret) +{ + bool is_idle; + + spin_lock_irq(&hsq->lock); + + is_idle = (!hsq->mrq && !hsq->qcnt) || + hsq->recovery_halt; + + *ret = hsq->recovery_halt ? -EBUSY : 0; + hsq->waiting_for_idle = !is_idle; + + spin_unlock_irq(&hsq->lock); + + return is_idle; +} + +static int mmc_hsq_wait_for_idle(struct mmc_host *mmc) +{ + struct mmc_hsq *hsq = mmc->cqe_private; + int ret; + + wait_event(hsq->wait_queue, + mmc_hsq_queue_is_idle(hsq, &ret)); + + return ret; +} + +static void mmc_hsq_disable(struct mmc_host *mmc) +{ + struct mmc_hsq *hsq = mmc->cqe_private; + u32 timeout = 500; + int ret; + + spin_lock_irq(&hsq->lock); + + if (!hsq->enabled) { + spin_unlock_irq(&hsq->lock); + return; + } + + spin_unlock_irq(&hsq->lock); + + ret = wait_event_timeout(hsq->wait_queue, + mmc_hsq_queue_is_idle(hsq, &ret), + msecs_to_jiffies(timeout)); + if (ret == 0) { + pr_warn("could not stop mmc software queue\n"); + return; + } + + spin_lock_irq(&hsq->lock); + + hsq->enabled = false; + + spin_unlock_irq(&hsq->lock); +} + +static int mmc_hsq_enable(struct mmc_host *mmc, struct mmc_card *card) +{ + struct mmc_hsq *hsq = mmc->cqe_private; + + spin_lock_irq(&hsq->lock); + + if (hsq->enabled) { + spin_unlock_irq(&hsq->lock); + return -EBUSY; + } + + hsq->enabled = true; + + spin_unlock_irq(&hsq->lock); + + return 0; +} + +static const struct mmc_cqe_ops mmc_hsq_ops = { + .cqe_enable = mmc_hsq_enable, + .cqe_disable = mmc_hsq_disable, + .cqe_request = mmc_hsq_request, + .cqe_post_req = mmc_hsq_post_req, + .cqe_wait_for_idle = mmc_hsq_wait_for_idle, + .cqe_recovery_start = mmc_hsq_recovery_start, + .cqe_recovery_finish = mmc_hsq_recovery_finish, +}; + +int mmc_hsq_init(struct mmc_hsq *hsq, struct mmc_host *mmc) +{ + hsq->num_slots = HSQ_NUM_SLOTS; + hsq->next_tag = HSQ_INVALID_TAG; + + hsq->slot = devm_kcalloc(mmc_dev(mmc), hsq->num_slots, + sizeof(struct hsq_slot), GFP_KERNEL); + if (!hsq->slot) + return -ENOMEM; + + hsq->mmc = mmc; + hsq->mmc->cqe_private = hsq; + mmc->cqe_ops = &mmc_hsq_ops; + + spin_lock_init(&hsq->lock); + init_waitqueue_head(&hsq->wait_queue); + + return 0; +} +EXPORT_SYMBOL_GPL(mmc_hsq_init); + +void mmc_hsq_suspend(struct mmc_host *mmc) +{ + mmc_hsq_disable(mmc); +} +EXPORT_SYMBOL_GPL(mmc_hsq_suspend); + +int mmc_hsq_resume(struct mmc_host *mmc) +{ + return mmc_hsq_enable(mmc, NULL); +} +EXPORT_SYMBOL_GPL(mmc_hsq_resume); diff --git a/drivers/mmc/host/mmc_hsq.h b/drivers/mmc/host/mmc_hsq.h new file mode 100644 index 0000000..d51beb7 --- /dev/null +++ b/drivers/mmc/host/mmc_hsq.h @@ -0,0 +1,30 @@ +// SPDX-License-Identifier: GPL-2.0 +#ifndef LINUX_MMC_HSQ_H +#define LINUX_MMC_HSQ_H + +struct hsq_slot { + struct mmc_request *mrq; +}; + +struct mmc_hsq { + struct mmc_host *mmc; + struct mmc_request *mrq; + wait_queue_head_t wait_queue; + struct hsq_slot *slot; + spinlock_t lock; + + int next_tag; + int num_slots; + int qcnt; + + bool enabled; + bool waiting_for_idle; + bool recovery_halt; +}; + +int mmc_hsq_init(struct mmc_hsq *hsq, struct mmc_host *mmc); +void mmc_hsq_suspend(struct mmc_host *mmc); +int mmc_hsq_resume(struct mmc_host *mmc); +bool mmc_hsq_finalize_request(struct mmc_host *mmc, struct mmc_request *mrq); + +#endif diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h index ba70338..562ed06 100644 --- a/include/linux/mmc/host.h +++ b/include/linux/mmc/host.h @@ -462,6 +462,9 @@ struct mmc_host { bool cqe_enabled; bool cqe_on; + /* Host Software Queue support */ + bool hsq_enabled; + unsigned long private[0] ____cacheline_aligned; }; From patchwork Wed Feb 5 12:50:29 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Baolin Wang X-Patchwork-Id: 11366251 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 7337E1395 for ; Wed, 5 Feb 2020 12:51:41 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 511782072B for ; Wed, 5 Feb 2020 12:51:41 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="fbNGETkV" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728034AbgBEMvZ (ORCPT ); Wed, 5 Feb 2020 07:51:25 -0500 Received: from mail-pj1-f65.google.com ([209.85.216.65]:50859 "EHLO mail-pj1-f65.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726960AbgBEMvZ (ORCPT ); Wed, 5 Feb 2020 07:51:25 -0500 Received: by mail-pj1-f65.google.com with SMTP id r67so954234pjb.0; Wed, 05 Feb 2020 04:51:24 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :in-reply-to:references; bh=p4o6nUOGxNPuRPSrNBregTBA8bwmvTg5CUl0u2z528Q=; b=fbNGETkV3yePdfOPkkretpz/hHkJaTfR9FtEV44umuMjmWjiSP4KwUy85KHD5vWFMM k08UG0ivgazlOCXXwx0uzSviXrifB+a1cvgQSXZpLuTQTDqR2SHs19Kx6HecK1J2Dksx oCdml0BtSgbx+B5wK5EhnXCYYfFnYNhBBwnBpLFuQYMQjBnYGiw5eESm3HJBFoazO3oq 1mVsem66t2Izi8pvp9eP8o83i1aCKEx5GJn5VTy3w1yjIpdTgYz+34eOy/5fzNSKjbVC qTm3dTiHbUyYtGn/LTfYkOItlGFeS3zq0LVexbdrwKyHzDVP9JCSzW+AmaSkvtXKKz1r vH/w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:in-reply-to:references; bh=p4o6nUOGxNPuRPSrNBregTBA8bwmvTg5CUl0u2z528Q=; b=GFZGkousOn9FrT0tUqIRWL5c/cq8kiWpaili6Evb72mv8/tmFndcC4h3gMuQGcADbK ebi8AnkKkMLlAMiZHmyLryxw2Ky758WBY7eF1ClCvVyP1qGUc/dH6RV2BAVm2MI5Fz4I WZ6vLKu8Nv0g3QLqNFZRiPcVuBWcBZP6fqcFB8u5jNODDIjg6fJG9IXgfmofTeiapFmB gQgdKWUyAmL/gdcM9jgPn5ftRNlbvFILpkY5QyyJUOHI6rcOtJ1e5Mo9EnK3TJIiyUIr NheXUpwrTXE+sNb1/1kIn2uA3kAHjPCTMKqi45Flw+qc2sTiasZtjQehupUim1lS0pkZ z4hw== X-Gm-Message-State: APjAAAUH7UXTkDMBriet4paA0O1WqlwWfMlCcUoEsMvd1QNzbpFjFa0e w/SnWLMfSJKSSpXYKe+od9o= X-Google-Smtp-Source: APXvYqzTrsVY+JCK2jDAhzccvTSDjze99dIgbA83iOUDSRGNMdW2P2/zXjPYHf1DwPAwSaRbU1O64w== X-Received: by 2002:a17:90a:9285:: with SMTP id n5mr5701197pjo.58.1580907084424; Wed, 05 Feb 2020 04:51:24 -0800 (PST) Received: from baolinwangubtpc.spreadtrum.com ([117.18.48.82]) by smtp.gmail.com with ESMTPSA id y127sm22864784pfg.22.2020.02.05.04.51.21 (version=TLS1 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Wed, 05 Feb 2020 04:51:24 -0800 (PST) From: Baolin Wang To: adrian.hunter@intel.com, ulf.hansson@linaro.org, asutoshd@codeaurora.org Cc: orsonzhai@gmail.com, zhang.lyra@gmail.com, arnd@arndb.de, linus.walleij@linaro.org, baolin.wang@linaro.org, baolin.wang7@gmail.com, linux-mmc@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v8 2/5] mmc: core: Enable the MMC host software queue for the SD card Date: Wed, 5 Feb 2020 20:50:29 +0800 Message-Id: <0dc2be36722232c07ad9bd61ca285ed1553fe3c9.1580894083.git.baolin.wang7@gmail.com> X-Mailer: git-send-email 1.7.9.5 In-Reply-To: References: In-Reply-To: References: Sender: linux-mmc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-mmc@vger.kernel.org From: Baolin Wang Enable the MMC host software queue for the SD card if the host controller supports the MMC host software queue. Signed-off-by: Baolin Wang Signed-off-by: Baolin Wang --- drivers/mmc/core/sd.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c index fe914ff..76c7add 100644 --- a/drivers/mmc/core/sd.c +++ b/drivers/mmc/core/sd.c @@ -1082,6 +1082,16 @@ static int mmc_sd_init_card(struct mmc_host *host, u32 ocr, } } + if (host->cqe_ops && !host->cqe_enabled) { + err = host->cqe_ops->cqe_enable(host, card); + if (!err) { + host->cqe_enabled = true; + host->hsq_enabled = true; + pr_info("%s: Host Software Queue enabled\n", + mmc_hostname(host)); + } + } + if (host->caps2 & MMC_CAP2_AVOID_3_3V && host->ios.signal_voltage == MMC_SIGNAL_VOLTAGE_330) { pr_err("%s: Host failed to negotiate down from 3.3V\n", From patchwork Wed Feb 5 12:50:30 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Baolin Wang X-Patchwork-Id: 11366245 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 A12A4138D for ; Wed, 5 Feb 2020 12:51:29 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 8073C217F4 for ; Wed, 5 Feb 2020 12:51:29 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="hJusQJKJ" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726960AbgBEMv2 (ORCPT ); Wed, 5 Feb 2020 07:51:28 -0500 Received: from mail-pf1-f194.google.com ([209.85.210.194]:33402 "EHLO mail-pf1-f194.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726308AbgBEMv2 (ORCPT ); Wed, 5 Feb 2020 07:51:28 -0500 Received: by mail-pf1-f194.google.com with SMTP id n7so1188210pfn.0; Wed, 05 Feb 2020 04:51:27 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :in-reply-to:references; bh=6hpkny8N/XZM7wZK5JpvEfe2AHXPpO8aqNteI1qybns=; b=hJusQJKJ3dMO68YWd/RkVmXquAcSQCouv+XJYUHwrjq+Ec5w/GLEVgFg/ymRr/W07j 1dDKHA4QuTspdrU82bamvjc8HNp76lvEvEH4OuaxAurErXqtCxF4NqBu7fSTKsz2HzR8 PnGbzgi+nw4onNaIVPb/H+RF9OHbaPihw6zMjrU8Umb1ujstnxbQsCxrnHWhG+XcG0mh SodEOQOxj+fAxFGA16q1NFzWrEBEmf2Ha61Q4vSMqLq12xJ9VG1y0nxUql0MmGbILeoI je0w7F8LWcO1Q0iOi8pC8zQgY8cdy/nWB9AeQywoQzCELmcIWFkyjHU+yeXYn3Zow+tc p/Bg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:in-reply-to:references; bh=6hpkny8N/XZM7wZK5JpvEfe2AHXPpO8aqNteI1qybns=; b=h/LYMNSUQM4rVpohzjdFTGpmg+xGjp6ceB1OLL34VMjNQnVO14PtpvYq7IugH8JOsN RgDldQSK0zOqb1CA+3Y6MmRI7hGWzyVkrkdr+dUep78D5dm2uXy7IENwhu/qlckFkMi7 0Kd1OCPy5prIhwx2XoURSEaJPJX5xJT1kiZbdWdQCZwZwkCV79e/1aOlpDDtF4TSvgi6 3uH2iacXKZ4p1tjg99MOupq7PUqQrc/fI1NcUX7zqUNfFehGII13yMRTM395Gw6sy+Vz mFAbQI9pL5yiQADgHmJj/tCr+KXrAqlsKfC8mklyHiHQAITZAX7GvXu/MObr3p3Q/ZTW ToGw== X-Gm-Message-State: APjAAAX4xT/ugvaAvX4kuvj0bj1zzwJFG+aYvNA9cv8K3rMzivGlU0OV 74Vogi+MDQRZx3BXWhdAUxw= X-Google-Smtp-Source: APXvYqw9idXFBSsT2xdvOiIRwSJPnB/B0HjeQJuBKo2i8fBwcpNqyp3vAtg3WzJp921F+ZoJTl6mhQ== X-Received: by 2002:a63:c14b:: with SMTP id p11mr13707443pgi.290.1580907087478; Wed, 05 Feb 2020 04:51:27 -0800 (PST) Received: from baolinwangubtpc.spreadtrum.com ([117.18.48.82]) by smtp.gmail.com with ESMTPSA id y127sm22864784pfg.22.2020.02.05.04.51.24 (version=TLS1 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Wed, 05 Feb 2020 04:51:27 -0800 (PST) From: Baolin Wang To: adrian.hunter@intel.com, ulf.hansson@linaro.org, asutoshd@codeaurora.org Cc: orsonzhai@gmail.com, zhang.lyra@gmail.com, arnd@arndb.de, linus.walleij@linaro.org, baolin.wang@linaro.org, baolin.wang7@gmail.com, linux-mmc@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v8 3/5] mmc: host: sdhci: Add request_done ops for struct sdhci_ops Date: Wed, 5 Feb 2020 20:50:30 +0800 Message-Id: <825d6f7b69393b4bc11fc3175749d46a0a495496.1580894083.git.baolin.wang7@gmail.com> X-Mailer: git-send-email 1.7.9.5 In-Reply-To: References: In-Reply-To: References: Sender: linux-mmc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-mmc@vger.kernel.org From: Baolin Wang Add request_done ops for struct sdhci_ops as a preparation in case some host controllers have different method to complete one request, such as supporting request completion of MMC software queue. Suggested-by: Adrian Hunter Signed-off-by: Baolin Wang Signed-off-by: Baolin Wang --- drivers/mmc/host/sdhci.c | 12 ++++++++++-- drivers/mmc/host/sdhci.h | 2 ++ 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 63db844..9761981 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -2944,7 +2944,10 @@ static bool sdhci_request_done(struct sdhci_host *host) spin_unlock_irqrestore(&host->lock, flags); - mmc_request_done(host->mmc, mrq); + if (host->ops->request_done) + host->ops->request_done(host, mrq); + else + mmc_request_done(host->mmc, mrq); return false; } @@ -3372,7 +3375,12 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id) /* Process mrqs ready for immediate completion */ for (i = 0; i < SDHCI_MAX_MRQS; i++) { - if (mrqs_done[i]) + if (!mrqs_done[i]) + continue; + + if (host->ops->request_done) + host->ops->request_done(host, mrqs_done[i]); + else mmc_request_done(host->mmc, mrqs_done[i]); } diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h index a6a3ddc..3e95f74 100644 --- a/drivers/mmc/host/sdhci.h +++ b/drivers/mmc/host/sdhci.h @@ -654,6 +654,8 @@ struct sdhci_ops { void (*voltage_switch)(struct sdhci_host *host); void (*adma_write_desc)(struct sdhci_host *host, void **desc, dma_addr_t addr, int len, unsigned int cmd); + void (*request_done)(struct sdhci_host *host, + struct mmc_request *mrq); }; #ifdef CONFIG_MMC_SDHCI_IO_ACCESSORS From patchwork Wed Feb 5 12:50:31 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Baolin Wang X-Patchwork-Id: 11366247 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 CD566138D for ; Wed, 5 Feb 2020 12:51:32 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id AAC9F2082E for ; Wed, 5 Feb 2020 12:51:32 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="PqK8prlj" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728101AbgBEMvb (ORCPT ); Wed, 5 Feb 2020 07:51:31 -0500 Received: from mail-pj1-f68.google.com ([209.85.216.68]:55723 "EHLO mail-pj1-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728094AbgBEMvb (ORCPT ); Wed, 5 Feb 2020 07:51:31 -0500 Received: by mail-pj1-f68.google.com with SMTP id d5so941423pjz.5; Wed, 05 Feb 2020 04:51:30 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :in-reply-to:references; bh=qXFSOdJFY54Rwc/1S4vXiFbbifW3bH93ZRFzyBvbEM0=; b=PqK8prljZrh8Nl09N/AoAVTK4xaSUk222FtX0iOIv5d7HaHwIloY88/YO3i1r7jFcQ IRsyA1hnh8T364CkFBfs8D95p2pgdi/QjgzUepSOWpc/C1NqmzRcpsYGbyuRRYKzrpN2 F4hNclJnsWtTYSesPMcbOAPWdHGHIWBiMTdHWaxVlDsUsLSt8SDKbGkNyhSvvvcPwdh8 99gDupRFG7Tgnd6olFlUrnRQXKaCXT2UMS8S0mTG6UFHahmeQpIbj7s3dS9V30BE3gpO /nBwM0msmy3ceE6XEDvmzdLEHPUgbj0HLjD9s8I8zqyiwxiTN1JOD375+dJxtPJ1KbUn oppg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:in-reply-to:references; bh=qXFSOdJFY54Rwc/1S4vXiFbbifW3bH93ZRFzyBvbEM0=; b=QAElIwRXnJGytcVpZygqYXuAR2I6FnRxT70W/neuoizY+MRnfp0+n+MSGkj+z2+AjN 5wBZKPcEnAP1oNc1RUTeCOvYhuhUSrLeZaUttrn70ya9DGsIqAiWF2vPMT7Pd+qSeKaJ 37h2kPQRqZUhB6qUxFRaD2JN/xWtWb9ykbD9IZSWZWpTzSgubXz7MiMRyBOQfy3KEPo3 HOzuUMOoGq5Lr/txW8pArIuRM9Ex1RWnlX+Ffvw79db11yoHMfPhRXIYWip63Etl5rsb Qzh1bTk68YJBW0UMeGAHnrseGb/3Qt7aXIPHjzEymSGs7vjoLEge5X378i5Q9XaMRF2H BczQ== X-Gm-Message-State: APjAAAUnQYh19zTYowHl48Ywoq4eMYghChUaeZMsxCD4kmQyVMauLGbl ZTZtqPFB9OPpMLWOALmbWl4= X-Google-Smtp-Source: APXvYqzsQZpSNdGN//eoRR8y6Oymb4LbqAIXFeFJVpYMTWuLiWFf/HhP918199kPK7K0s8Xxr49Wtw== X-Received: by 2002:a17:902:463:: with SMTP id 90mr36624355ple.213.1580907090390; Wed, 05 Feb 2020 04:51:30 -0800 (PST) Received: from baolinwangubtpc.spreadtrum.com ([117.18.48.82]) by smtp.gmail.com with ESMTPSA id y127sm22864784pfg.22.2020.02.05.04.51.27 (version=TLS1 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Wed, 05 Feb 2020 04:51:30 -0800 (PST) From: Baolin Wang To: adrian.hunter@intel.com, ulf.hansson@linaro.org, asutoshd@codeaurora.org Cc: orsonzhai@gmail.com, zhang.lyra@gmail.com, arnd@arndb.de, linus.walleij@linaro.org, baolin.wang@linaro.org, baolin.wang7@gmail.com, linux-mmc@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v8 4/5] mmc: host: sdhci: Add a variable to defer to complete requests if needed Date: Wed, 5 Feb 2020 20:50:31 +0800 Message-Id: <99f715b4b442d196bd7127cb6264b804219036ad.1580894083.git.baolin.wang7@gmail.com> X-Mailer: git-send-email 1.7.9.5 In-Reply-To: References: In-Reply-To: References: Sender: linux-mmc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-mmc@vger.kernel.org From: Baolin Wang When using the host software queue, it will trigger the next request in irq handler without a context switch. But the sdhci_request() can not be called in interrupt context when using host software queue for some host drivers, due to the get_cd() ops can be sleepable. But for some host drivers, such as Spreadtrum host driver, the card is nonremovable, so the get_cd() ops is not sleepable, which means we can complete the data request and trigger the next request in irq handler to remove the context switch for the Spreadtrum host driver. As suggested by Adrian, we should introduce a request_atomic() API to indicate that a request can be called in interrupt context to remove the context switch when using mmc host software queue. But this should be done in another thread to convert the users of mmc host software queue. Thus we can introduce a variable in struct sdhci_host to indicate that we will always to defer to complete requests when using the host software queue. Suggested-by: Adrian Hunter Signed-off-by: Baolin Wang Signed-off-by: Baolin Wang --- drivers/mmc/host/sdhci.c | 2 +- drivers/mmc/host/sdhci.h | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 9761981..9c37451 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -3250,7 +3250,7 @@ static inline bool sdhci_defer_done(struct sdhci_host *host, { struct mmc_data *data = mrq->data; - return host->pending_reset || + return host->pending_reset || host->always_defer_done || ((host->flags & SDHCI_REQ_USE_DMA) && data && data->host_cookie == COOKIE_MAPPED); } diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h index 3e95f74..cac2d97 100644 --- a/drivers/mmc/host/sdhci.h +++ b/drivers/mmc/host/sdhci.h @@ -537,6 +537,7 @@ struct sdhci_host { bool irq_wake_enabled; /* IRQ wakeup is enabled */ bool v4_mode; /* Host Version 4 Enable */ bool use_external_dma; /* Host selects to use external DMA */ + bool always_defer_done; /* Always defer to complete requests */ struct mmc_request *mrqs_done[SDHCI_MAX_MRQS]; /* Requests done */ struct mmc_command *cmd; /* Current command */ From patchwork Wed Feb 5 12:50:32 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Baolin Wang X-Patchwork-Id: 11366249 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 DCEE5138D for ; Wed, 5 Feb 2020 12:51:40 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id BCB602192A for ; Wed, 5 Feb 2020 12:51:40 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="X931Yhml" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728122AbgBEMvg (ORCPT ); Wed, 5 Feb 2020 07:51:36 -0500 Received: from mail-pl1-f195.google.com ([209.85.214.195]:43326 "EHLO mail-pl1-f195.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728094AbgBEMvf (ORCPT ); Wed, 5 Feb 2020 07:51:35 -0500 Received: by mail-pl1-f195.google.com with SMTP id p11so843146plq.10; Wed, 05 Feb 2020 04:51:33 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :in-reply-to:references; bh=z2rCwKhMPk5QQnDbc8O1zs9yu0JRS1NKgiYNty4j9ao=; b=X931Yhmlt5lykJmxHSlQn3LYRIUeitZYLnkp5ML0fo7ckqAoWt/tL0qCCLVzoyj4R2 4AfbRO5ga4ri3gN8/w77nULBeLd0GjHz+SkMPLgllyxl8I0khXZKKzV+ym/NLnjuBU6t 4ypn3cfgezDr9aqrMkiEv08OPrn7n5la/xbqov5TMWFG8JXaxDIenETzT35qv71bQqPK 3U1ImKu1C9TOQphMuge5niN4ld5uF3v2JcQH3BUUZekyLV9xBnU3bXssE6D8FYUwiWnG 9M5YkP89Zof8L7v9srlmRqyBXpsrDj3rc2/w9oKvSh6oxJYjE8B8makLJfZUHCLyRAGe azXg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:in-reply-to:references; bh=z2rCwKhMPk5QQnDbc8O1zs9yu0JRS1NKgiYNty4j9ao=; b=t4Gl94Z/xVO8GNdUmxQusbUYZNtyMsgiD23aOXB7DL3hi1CYekGWytJAFZdkys9+8h OAQu12nKq4rCoJs0RMN22KCOqlH8NyFeq1MKH46bj0T7X2sMY6dCetOc2C94wo44avrN j6h9a5tDHZEz1FL/j5AWatvc8/jVFc6WY2HxnsM0X+elqHszyGrZk1svW95JcJ84tplS viqlVT8sv7TBIjBxdzJKWekT1n0jq+NKfjvWnXBvpQodStDGaJYQ4/UW4qlAf0EIczQN PGu7XCFsn1AfjGLeTN3wfTKB/f9TkU5GFPtNmt8tA0TxnJCIFoFr/GJgyNhnOqqolVB+ k0Hw== X-Gm-Message-State: APjAAAVIIGdKFsU27Hc5Bc4fZwtk89sBpvKvL4r5PSQyCJl5MhArHh1J GDuZYdfQX0hZviEurKvo+88= X-Google-Smtp-Source: APXvYqxZ4IRD5HLednMl/VFLWobo0wrxj9CQmKQi4CyUuhEgfruu+Gnwt2VtBAlL08UlIjC42Iotkg== X-Received: by 2002:a17:902:24:: with SMTP id 33mr34959814pla.91.1580907093379; Wed, 05 Feb 2020 04:51:33 -0800 (PST) Received: from baolinwangubtpc.spreadtrum.com ([117.18.48.82]) by smtp.gmail.com with ESMTPSA id y127sm22864784pfg.22.2020.02.05.04.51.30 (version=TLS1 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Wed, 05 Feb 2020 04:51:32 -0800 (PST) From: Baolin Wang To: adrian.hunter@intel.com, ulf.hansson@linaro.org, asutoshd@codeaurora.org Cc: orsonzhai@gmail.com, zhang.lyra@gmail.com, arnd@arndb.de, linus.walleij@linaro.org, baolin.wang@linaro.org, baolin.wang7@gmail.com, linux-mmc@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v8 5/5] mmc: host: sdhci-sprd: Add software queue support Date: Wed, 5 Feb 2020 20:50:32 +0800 Message-Id: <6e11c5faeecafc2ef817c14268577925eee0bd4e.1580894083.git.baolin.wang7@gmail.com> X-Mailer: git-send-email 1.7.9.5 In-Reply-To: References: In-Reply-To: References: Sender: linux-mmc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-mmc@vger.kernel.org From: Baolin Wang Add software queue support to improve the performance. Signed-off-by: Baolin Wang Signed-off-by: Baolin Wang --- drivers/mmc/host/Kconfig | 1 + drivers/mmc/host/sdhci-sprd.c | 28 ++++++++++++++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig index 65d3966..3ea45be 100644 --- a/drivers/mmc/host/Kconfig +++ b/drivers/mmc/host/Kconfig @@ -645,6 +645,7 @@ config MMC_SDHCI_SPRD depends on ARCH_SPRD depends on MMC_SDHCI_PLTFM select MMC_SDHCI_IO_ACCESSORS + select MMC_HSQ help This selects the SDIO Host Controller in Spreadtrum SoCs, this driver supports R11(IP version: R11P0). diff --git a/drivers/mmc/host/sdhci-sprd.c b/drivers/mmc/host/sdhci-sprd.c index d07b979..d346223 100644 --- a/drivers/mmc/host/sdhci-sprd.c +++ b/drivers/mmc/host/sdhci-sprd.c @@ -19,6 +19,7 @@ #include #include "sdhci-pltfm.h" +#include "mmc_hsq.h" /* SDHCI_ARGUMENT2 register high 16bit */ #define SDHCI_SPRD_ARG2_STUFF GENMASK(31, 16) @@ -379,6 +380,16 @@ static unsigned int sdhci_sprd_get_ro(struct sdhci_host *host) return 0; } +static void sdhci_sprd_request_done(struct sdhci_host *host, + struct mmc_request *mrq) +{ + /* Validate if the request was from software queue firstly. */ + if (mmc_hsq_finalize_request(host->mmc, mrq)) + return; + + mmc_request_done(host->mmc, mrq); +} + static struct sdhci_ops sdhci_sprd_ops = { .read_l = sdhci_sprd_readl, .write_l = sdhci_sprd_writel, @@ -392,6 +403,7 @@ static unsigned int sdhci_sprd_get_ro(struct sdhci_host *host) .hw_reset = sdhci_sprd_hw_reset, .get_max_timeout_count = sdhci_sprd_get_max_timeout_count, .get_ro = sdhci_sprd_get_ro, + .request_done = sdhci_sprd_request_done, }; static void sdhci_sprd_request(struct mmc_host *mmc, struct mmc_request *mrq) @@ -521,6 +533,7 @@ static int sdhci_sprd_probe(struct platform_device *pdev) { struct sdhci_host *host; struct sdhci_sprd_host *sprd_host; + struct mmc_hsq *hsq; struct clk *clk; int ret = 0; @@ -631,6 +644,18 @@ static int sdhci_sprd_probe(struct platform_device *pdev) sprd_host->flags = host->flags; + hsq = devm_kzalloc(&pdev->dev, sizeof(*hsq), GFP_KERNEL); + if (!hsq) { + ret = -ENOMEM; + goto err_cleanup_host; + } + + ret = mmc_hsq_init(hsq, host->mmc); + if (ret) + goto err_cleanup_host; + + host->always_defer_done = true; + ret = __sdhci_add_host(host); if (ret) goto err_cleanup_host; @@ -689,6 +714,7 @@ static int sdhci_sprd_runtime_suspend(struct device *dev) struct sdhci_host *host = dev_get_drvdata(dev); struct sdhci_sprd_host *sprd_host = TO_SPRD_HOST(host); + mmc_hsq_suspend(host->mmc); sdhci_runtime_suspend_host(host); clk_disable_unprepare(sprd_host->clk_sdio); @@ -717,6 +743,8 @@ static int sdhci_sprd_runtime_resume(struct device *dev) goto clk_disable; sdhci_runtime_resume_host(host, 1); + mmc_hsq_resume(host->mmc); + return 0; clk_disable: