From patchwork Thu May 6 14:58:28 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ulf Hansson X-Patchwork-Id: 431664 Delivered-To: patches@linaro.org Received: by 2002:a02:c901:0:0:0:0:0 with SMTP id t1csp1523333jao; Thu, 6 May 2021 07:58:38 -0700 (PDT) X-Received: by 2002:a19:ec03:: with SMTP id b3mr3314614lfa.656.1620313118746; Thu, 06 May 2021 07:58:38 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1620313118; cv=none; d=google.com; s=arc-20160816; b=wRh4nkmNMtZXFQAlir8DpdRSEdR2HQh+vk2fRcwXwGQ3ZSsenRhMDrad+IqxB15Uhz 9CWM7ZQrjv/9n9bJmfacweFwdJhbgoWE2Ewj1kik/+LOQCuJ7dGpBK8uSnQLNvhJLd9A 2znxXl0YOp+BQINhMjpLMRjdVWvVdoHZEvT0jKQQy8ELrJBdJhs5LhBURaaAd0VjmyiG OxVzqmZCjDIRQecyMNHiU+LlElv6Gvu7hoOLOIo4NNHs3BeKhJInLmHDjCPnntx/IH7i NMSoo4ddwVx9tJeHSAuK5Ny8i62RGN2PlzStFsZP2SMRCrYP6OEgZfWJtL1IG7sh4PaN iQpQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:dkim-signature; bh=pMkfZ9EIibr4K3KFH7NDHi8SFeCMCdnE2OEuvOfMmWI=; b=VwJFgPL2HtG87zdnAvmElT37IXi0C5enlVJCw3KS6mc047INAkB37U8sBXH2n4vg0B 07p5bb5WgMwIwkdFGXD4ar1nfRCayle5265t6vBgfHOhnMDV4GNN9Vs9JsfT0whZuL9M EuV2Mpwpycp/maddX6x5EBH6rU5qdw20/c8y9bpno5JPt2L/ljZSaMLT4aCx6EwZONVs 5C6XQd9Tap4bkeCcoNItWYfWDupfr9XFdAHpkJYSrR4HZLjZEm2TXpb1QCchMavPFTY8 0oOCjQKSPfCpiE52OwRxKc13XvQ7VGRdEjyJuyEfq+37rcMODe8kbURtpHvq65LUoa0T uLeg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=ropSb77Z; spf=pass (google.com: domain of ulf.hansson@linaro.org designates 209.85.220.41 as permitted sender) smtp.mailfrom=ulf.hansson@linaro.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from mail-sor-f41.google.com (mail-sor-f41.google.com. [209.85.220.41]) by mx.google.com with SMTPS id e29sor728250lfc.62.2021.05.06.07.58.38 for (Google Transport Security); Thu, 06 May 2021 07:58:38 -0700 (PDT) Received-SPF: pass (google.com: domain of ulf.hansson@linaro.org designates 209.85.220.41 as permitted sender) client-ip=209.85.220.41; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=ropSb77Z; spf=pass (google.com: domain of ulf.hansson@linaro.org designates 209.85.220.41 as permitted sender) smtp.mailfrom=ulf.hansson@linaro.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=pMkfZ9EIibr4K3KFH7NDHi8SFeCMCdnE2OEuvOfMmWI=; b=ropSb77Z7ZrvZWrWv2bmJfXeH/HzlRDinr63ZcMxxBBVdHQotkVsjMZbDvofMAONzz qT8r+iXzXXOD01g+ip5mkthcRroRfqlQbSrm3pmVcFQ9EzTCPTHCYgg7uvt47fHJm1AM dO4PbF9DwlRbrtRTMQfnLLtWxfp1ZksVh4bnjzwQHUyWsjr1zmL1EQS3DL2VoDPLOOLX 4SZlpMdyET23pLEL0Mln9+bsUfsMn6qbv9JFMjw1nP48U31xrY6uDocaCh29tO2BZTGt z4toTYgG2gLPmxQGkYlCDC1IWGiWlsY/evMJY1Hp+UAtsSB2HM4rhl2/ve4bhnQgZhfx Gheg== 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:mime-version:content-transfer-encoding; bh=pMkfZ9EIibr4K3KFH7NDHi8SFeCMCdnE2OEuvOfMmWI=; b=Jh6b0DLgowNQ7pBSYxCxXnGp63ZKpZDEFUjhnTwauksiqso58Q3cN3S5fv2lDcB7TV Mz9Z6sNnHXdaPaqx/jl3K/OYnzvlql192/kS1EHaBm5664ho1zETlZ5Zmusmp/4vS7Vl /BO2253wznC+iK6LAUTOjfwwFF48Xq+GHeIXI7BY6OdvbdoGdJ/mIJXMgwKED/46ED/r jsKzQSl0Mjs/3dX61dy02W8ByjIJeIC8MTifzYOf1aBAEx8rfDw5VkxH8w5uOqVb+Rq3 zidPI6h41/Jn2zsu162OftAkwcd5OI1kYUK4GVBv+FHboel+0+nDdkCLLqeo0PWfvG2p OQzw== X-Gm-Message-State: AOAM532qmc19/3vXu4BW5pp2An9liI6RK0oDLdL2zWJnmTgbSKKZqihm wfaKQiKUUauyszU4R0CdpfMyXO5W X-Google-Smtp-Source: ABdhPJxqAiOCtWASA9ZL0VYB9iWkxgoY7P6chLaBXA9n4TxQrVRKBX1sDd549LroNkvZ/HS6sG43Ug== X-Received: by 2002:ac2:48a5:: with SMTP id u5mr3244496lfg.346.1620313118333; Thu, 06 May 2021 07:58:38 -0700 (PDT) Return-Path: Received: from localhost.localdomain (h-155-4-129-146.NA.cust.bahnhof.se. [155.4.129.146]) by smtp.gmail.com with ESMTPSA id g24sm968774ljl.44.2021.05.06.07.58.36 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 06 May 2021 07:58:37 -0700 (PDT) From: Ulf Hansson To: linux-mmc@vger.kernel.org, Ulf Hansson , Adrian Hunter Cc: Linus Walleij , Wolfram Sang , Shawn Lin , Avri Altman , Masami Hiramatsu , linux-block@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH 1/2] mmc: core: Move eMMC cache flushing to a new bus_ops callback Date: Thu, 6 May 2021 16:58:28 +0200 Message-Id: <20210506145829.198823-2-ulf.hansson@linaro.org> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20210506145829.198823-1-ulf.hansson@linaro.org> References: <20210506145829.198823-1-ulf.hansson@linaro.org> MIME-Version: 1.0 To prepare to add internal cache management for SD cards, let's start by moving the eMMC specific code into a new ->flush_cache() bus_ops callback. In this way, it becomes straight forward to add the SD specific parts, as subsequent changes are about to show. Signed-off-by: Ulf Hansson --- drivers/mmc/core/block.c | 2 +- drivers/mmc/core/core.h | 9 +++++++++ drivers/mmc/core/mmc.c | 25 +++++++++++++++++++++++-- drivers/mmc/core/mmc_ops.c | 21 --------------------- drivers/mmc/core/mmc_ops.h | 1 - 5 files changed, 33 insertions(+), 25 deletions(-) -- 2.25.1 Reviewed-by: Avri Altman Reviewed-by: Linus Walleij diff --git a/drivers/mmc/core/block.c b/drivers/mmc/core/block.c index 689eb9afeeed..d73d7be1af2f 100644 --- a/drivers/mmc/core/block.c +++ b/drivers/mmc/core/block.c @@ -1159,7 +1159,7 @@ static void mmc_blk_issue_flush(struct mmc_queue *mq, struct request *req) struct mmc_card *card = md->queue.card; int ret = 0; - ret = mmc_flush_cache(card); + ret = mmc_flush_cache(card->host); blk_mq_end_request(req, ret ? BLK_STS_IOERR : BLK_STS_OK); } diff --git a/drivers/mmc/core/core.h b/drivers/mmc/core/core.h index db3c9c68875d..0c4de2030b3f 100644 --- a/drivers/mmc/core/core.h +++ b/drivers/mmc/core/core.h @@ -30,6 +30,7 @@ struct mmc_bus_ops { int (*hw_reset)(struct mmc_host *); int (*sw_reset)(struct mmc_host *); bool (*cache_enabled)(struct mmc_host *); + int (*flush_cache)(struct mmc_host *); }; void mmc_attach_bus(struct mmc_host *host, const struct mmc_bus_ops *ops); @@ -172,4 +173,12 @@ static inline bool mmc_cache_enabled(struct mmc_host *host) return false; } +static inline int mmc_flush_cache(struct mmc_host *host) +{ + if (host->bus_ops->flush_cache) + return host->bus_ops->flush_cache(host); + + return 0; +} + #endif diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index 13074aa1f605..838726b68ff3 100644 --- a/drivers/mmc/core/mmc.c +++ b/drivers/mmc/core/mmc.c @@ -28,6 +28,7 @@ #define DEFAULT_CMD6_TIMEOUT_MS 500 #define MIN_CACHE_EN_TIMEOUT_MS 1600 +#define CACHE_FLUSH_TIMEOUT_MS 30000 /* 30s */ static const unsigned int tran_exp[] = { 10000, 100000, 1000000, 10000000, @@ -2036,6 +2037,25 @@ static bool _mmc_cache_enabled(struct mmc_host *host) host->card->ext_csd.cache_ctrl & 1; } +/* + * Flush the internal cache of the eMMC to non-volatile storage. + */ +static int _mmc_flush_cache(struct mmc_host *host) +{ + int err = 0; + + if (_mmc_cache_enabled(host)) { + err = mmc_switch(host->card, EXT_CSD_CMD_SET_NORMAL, + EXT_CSD_FLUSH_CACHE, 1, + CACHE_FLUSH_TIMEOUT_MS); + if (err) + pr_err("%s: cache flush error %d\n", + mmc_hostname(host), err); + } + + return err; +} + static int _mmc_suspend(struct mmc_host *host, bool is_suspend) { int err = 0; @@ -2047,7 +2067,7 @@ static int _mmc_suspend(struct mmc_host *host, bool is_suspend) if (mmc_card_suspended(host->card)) goto out; - err = mmc_flush_cache(host->card); + err = _mmc_flush_cache(host); if (err) goto out; @@ -2188,7 +2208,7 @@ static int _mmc_hw_reset(struct mmc_host *host) * In the case of recovery, we can't expect flushing the cache to work * always, but we have a go and ignore errors. */ - mmc_flush_cache(host->card); + _mmc_flush_cache(host); if ((host->caps & MMC_CAP_HW_RESET) && host->ops->hw_reset && mmc_can_reset(card)) { @@ -2216,6 +2236,7 @@ static const struct mmc_bus_ops mmc_ops = { .shutdown = mmc_shutdown, .hw_reset = _mmc_hw_reset, .cache_enabled = _mmc_cache_enabled, + .flush_cache = _mmc_flush_cache, }; /* diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c index b1da8f1950ee..af423acc4c88 100644 --- a/drivers/mmc/core/mmc_ops.c +++ b/drivers/mmc/core/mmc_ops.c @@ -20,7 +20,6 @@ #include "mmc_ops.h" #define MMC_BKOPS_TIMEOUT_MS (120 * 1000) /* 120s */ -#define MMC_CACHE_FLUSH_TIMEOUT_MS (30 * 1000) /* 30s */ #define MMC_SANITIZE_TIMEOUT_MS (240 * 1000) /* 240s */ static const u8 tuning_blk_pattern_4bit[] = { @@ -964,26 +963,6 @@ void mmc_run_bkops(struct mmc_card *card) } EXPORT_SYMBOL(mmc_run_bkops); -/* - * Flush the cache to the non-volatile storage. - */ -int mmc_flush_cache(struct mmc_card *card) -{ - int err = 0; - - if (mmc_cache_enabled(card->host)) { - err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, - EXT_CSD_FLUSH_CACHE, 1, - MMC_CACHE_FLUSH_TIMEOUT_MS); - if (err) - pr_err("%s: cache flush error %d\n", - mmc_hostname(card->host), err); - } - - return err; -} -EXPORT_SYMBOL(mmc_flush_cache); - static int mmc_cmdq_switch(struct mmc_card *card, bool enable) { u8 val = enable ? EXT_CSD_CMDQ_MODE_ENABLED : 0; diff --git a/drivers/mmc/core/mmc_ops.h b/drivers/mmc/core/mmc_ops.h index 2b1d730e56bf..c3c1d9c2577e 100644 --- a/drivers/mmc/core/mmc_ops.h +++ b/drivers/mmc/core/mmc_ops.h @@ -51,7 +51,6 @@ int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value, int mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value, unsigned int timeout_ms); void mmc_run_bkops(struct mmc_card *card); -int mmc_flush_cache(struct mmc_card *card); int mmc_cmdq_enable(struct mmc_card *card); int mmc_cmdq_disable(struct mmc_card *card); int mmc_sanitize(struct mmc_card *card, unsigned int timeout_ms); From patchwork Thu May 6 14:58:29 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ulf Hansson X-Patchwork-Id: 431665 Delivered-To: patches@linaro.org Received: by 2002:a02:c901:0:0:0:0:0 with SMTP id t1csp1523365jao; Thu, 6 May 2021 07:58:40 -0700 (PDT) X-Received: by 2002:a05:6512:38c2:: with SMTP id p2mr3262772lft.259.1620313120730; Thu, 06 May 2021 07:58:40 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1620313120; cv=none; d=google.com; s=arc-20160816; b=bvC2NulWJpIYUC3tGDv6+s3liIioxZh0h0hmb7ToYqJ5U9zjnLGmuOxuW7Do1bl81O WMh6YUhBH5GmYr6jGR48qdSjQ7VyfPvZX4JFj9rcU5EiqvN/X2wsIp7VCu7HoBx/xXEG L+lXaUsTASbsDtmyQnK3rhWvyBgMb7Pj0x9GcaSrLqByXn02WWm/BpBaiC+zYaXmY9jR 79BlxHIsU4bPe3+R8gAafzDYHyVNbI1oS1oCjQOtmhiP3NqOf7B/NpESr9QhVkIbbwRJ BQ4rHn3UIEvDCw4RxGrgVvsC2Uu7qhZVlnw+sFhHtdZeMo3UVRin2Lh77agQtlD/jOsO 2ppw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:dkim-signature; bh=82Mp/+3WiDiX0+TFdKaDBvNV5KTPMZG8BPbOyDcjQEo=; b=R7bEFscCosOSW34LgWWjWjJ72JdDHMjuzrnpZM47dpm/VcYZtY19wOryWgz6wq4DbC O6k+y3LJ93t9BcFkUYNFRRsntpbfX6jljtyRdnMAaSkCStry8pOpGYjckmMCVEtLdASy 2fOMFwJUJvLVzMEgu8oNdkID3GteW914GqGciSuzNuVVC7j3J5U9MiMtiolooCduFrHo Se4WdhzfT7H3tFPyzXLVQ5myU0DA1dNPRbpwK38tjN8+bG2UpA0l8zkC5EXuKW7zQAKo od6KWOHnKUUKH2ebS8CeEToLSi+Ln4A5ua9eZFuJv/pP48AWqZwn3QcwWkd0eV2SPskG UdJQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=Hfeq2mPT; spf=pass (google.com: domain of ulf.hansson@linaro.org designates 209.85.220.41 as permitted sender) smtp.mailfrom=ulf.hansson@linaro.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from mail-sor-f41.google.com (mail-sor-f41.google.com. [209.85.220.41]) by mx.google.com with SMTPS id a25sor1391279lji.41.2021.05.06.07.58.40 for (Google Transport Security); Thu, 06 May 2021 07:58:40 -0700 (PDT) Received-SPF: pass (google.com: domain of ulf.hansson@linaro.org designates 209.85.220.41 as permitted sender) client-ip=209.85.220.41; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=Hfeq2mPT; spf=pass (google.com: domain of ulf.hansson@linaro.org designates 209.85.220.41 as permitted sender) smtp.mailfrom=ulf.hansson@linaro.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=82Mp/+3WiDiX0+TFdKaDBvNV5KTPMZG8BPbOyDcjQEo=; b=Hfeq2mPTtjJcg4XLGumY1HeGkmZp7vTnsf8ptjdjVyfbfVoChqCpfWdWAyyc10l/lX TxSSni46a86kKQc2v8mfXyUBFob+vdfUhDWwERSIJE5KgN5oHMzx/YlCfCOC7PXmtDGv liwv/n2QfLNI+MWE+6kg38Y52VyiBBuNVfN3LlRnFDSPyhiviDbH+xI7ykeXFDB04an7 QH8Cdy+e3hpOaMO9WV2pPSzXedbnlr/rvNKW1gg1ZLKzMnHj1XZf8BXJXFSYqH8enxmu Duj7IlwYWRP41oAUyJJ0m7KYsIGYGZlLsYNqKMIOWYuANq2QpVMgbo307MZN72Xl1XUs heEw== 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:mime-version:content-transfer-encoding; bh=82Mp/+3WiDiX0+TFdKaDBvNV5KTPMZG8BPbOyDcjQEo=; b=EySKamoONQCNrhlTs0kTdQenBBqey0ajOMAv23X5hgP6r+2SfBxeqTLY9kHAAmz0oI 6dnKkTiNyKyBuHir+yAfFaH2GixRPnkunKh3W+SbVPsEMkwDqUNYkzCvFip1NsB3U+zz 9f1X3Kbih45eGIDHwQLXqRgalq8CZhl+w3jKuSa3iKnqSvExb7yajJnR38X4LtWF+nZ/ l6uDEssEgDqkE0dnYi7u5AjFiMXVx0WCDIWmjrlnGFEBEa6+2mPWNIzT7zKdvwuTI9sp nsVhMw8OYxQVpGhponLCxMl/6d2GbVMPbljKgWvR6jYT81SSfJwv0eoo/tzcuf6iz7WA buqA== X-Gm-Message-State: AOAM532of9djEnwt1lCYwjNiz3nCkIfMpuJfPfgdCUETHJUuOO+tt6yb 90HYrhepojmgJAIDARnPpgjuAixl X-Google-Smtp-Source: ABdhPJydchd1pmp2rGfbHH/jeQdqsrTGtFFsDh++WDcg8vT9ARXlabU2aXYLJVWd+CZNAnOqlqk/FQ== X-Received: by 2002:a2e:9f49:: with SMTP id v9mr3688514ljk.44.1620313120233; Thu, 06 May 2021 07:58:40 -0700 (PDT) Return-Path: Received: from localhost.localdomain (h-155-4-129-146.NA.cust.bahnhof.se. [155.4.129.146]) by smtp.gmail.com with ESMTPSA id g24sm968774ljl.44.2021.05.06.07.58.38 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 06 May 2021 07:58:39 -0700 (PDT) From: Ulf Hansson To: linux-mmc@vger.kernel.org, Ulf Hansson , Adrian Hunter Cc: Linus Walleij , Wolfram Sang , Shawn Lin , Avri Altman , Masami Hiramatsu , linux-block@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH 2/2] mmc: core: Add support for cache ctrl for SD cards Date: Thu, 6 May 2021 16:58:29 +0200 Message-Id: <20210506145829.198823-3-ulf.hansson@linaro.org> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20210506145829.198823-1-ulf.hansson@linaro.org> References: <20210506145829.198823-1-ulf.hansson@linaro.org> MIME-Version: 1.0 In SD spec v6.x the SD function extension registers for performance enhancements were introduced. As a part of this an optional internal cache on the SD card, can be used to improve performance. The let the SD card use the cache, the host needs to enable it and manage flushing of the cache, so let's add support for this. Note that for an SD card supporting the cache it's mandatory for it, to also support the poweroff notification feature. According to the SD spec, if the cache has been enabled and a poweroff notification is sent to the card, that implicitly also means that the card should flush its internal cache. Therefore, dealing with cache flushing for REQ_OP_FLUSH block requests is sufficient. Signed-off-by: Ulf Hansson --- drivers/mmc/core/mmc_ops.c | 1 + drivers/mmc/core/mmc_ops.h | 1 + drivers/mmc/core/sd.c | 98 ++++++++++++++++++++++++++++++++++++++ include/linux/mmc/card.h | 1 + 4 files changed, 101 insertions(+) -- 2.25.1 Reviewed-by: Linus Walleij diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c index af423acc4c88..3c58f6d0f482 100644 --- a/drivers/mmc/core/mmc_ops.c +++ b/drivers/mmc/core/mmc_ops.c @@ -456,6 +456,7 @@ static int mmc_busy_cb(void *cb_data, bool *busy) err = R1_STATUS(status) ? -EIO : 0; break; case MMC_BUSY_HPI: + case MMC_BUSY_EXTR_SINGLE: break; default: err = -EINVAL; diff --git a/drivers/mmc/core/mmc_ops.h b/drivers/mmc/core/mmc_ops.h index c3c1d9c2577e..41ab4f573a31 100644 --- a/drivers/mmc/core/mmc_ops.h +++ b/drivers/mmc/core/mmc_ops.h @@ -14,6 +14,7 @@ enum mmc_busy_cmd { MMC_BUSY_CMD6, MMC_BUSY_ERASE, MMC_BUSY_HPI, + MMC_BUSY_EXTR_SINGLE, }; struct mmc_host; diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c index 760aa86bd54d..773444853607 100644 --- a/drivers/mmc/core/sd.c +++ b/drivers/mmc/core/sd.c @@ -67,6 +67,7 @@ static const unsigned int sd_au_size[] = { }) #define SD_POWEROFF_NOTIFY_TIMEOUT_MS 2000 +#define SD_WRITE_EXTR_SINGLE_TIMEOUT_MS 1000 struct sd_busy_data { struct mmc_card *card; @@ -1287,6 +1288,94 @@ static int sd_read_ext_regs(struct mmc_card *card) return err; } +static bool sd_cache_enabled(struct mmc_host *host) +{ + return host->card->ext_perf.feature_enabled & SD_EXT_PERF_CACHE; +} + +static int sd_flush_cache(struct mmc_host *host) +{ + struct mmc_card *card = host->card; + u8 *reg_buf, fno, page; + u16 offset; + int err; + + if (!sd_cache_enabled(host)) + return 0; + + reg_buf = kzalloc(512, GFP_KERNEL); + if (!reg_buf) + return -ENOMEM; + + /* + * Set the Flush Cache bit in the performance enhancement register at + * 261 bytes offset. + */ + fno = card->ext_perf.fno; + page = card->ext_perf.page; + offset = card->ext_perf.offset + 261; + + err = sd_write_ext_reg(card, fno, page, offset, 0x1); + if (err) { + pr_warn("%s: error %d writing Cache Flush bit\n", + mmc_hostname(host), err); + goto out; + } + + err = mmc_poll_for_busy(card, SD_WRITE_EXTR_SINGLE_TIMEOUT_MS, false, + MMC_BUSY_EXTR_SINGLE); + if (err) + goto out; + + /* + * Read the Flush Cache bit. The card shall reset it, to confirm that + * it's has completed the flushing of the cache. + */ + err = sd_read_ext_reg(card, fno, page, offset, 1, reg_buf); + if (err) { + pr_warn("%s: error %d reading Cache Flush bit\n", + mmc_hostname(host), err); + goto out; + } + + if (reg_buf[0] & 0x1) + err = -ETIMEDOUT; +out: + kfree(reg_buf); + return err; +} + +static int sd_enable_cache(struct mmc_card *card) +{ + u8 *reg_buf; + int err; + + reg_buf = kzalloc(512, GFP_KERNEL); + if (!reg_buf) + return -ENOMEM; + + /* + * Set the Cache Enable bit in the performance enhancement register at + * 260 bytes offset. + */ + err = sd_write_ext_reg(card, card->ext_perf.fno, card->ext_perf.page, + card->ext_perf.offset + 260, 0x1); + if (err) { + pr_warn("%s: error %d writing Cache Enable bit\n", + mmc_hostname(card->host), err); + goto out; + } + + err = mmc_poll_for_busy(card, SD_WRITE_EXTR_SINGLE_TIMEOUT_MS, false, + MMC_BUSY_EXTR_SINGLE); + if (!err) + card->ext_perf.feature_enabled |= SD_EXT_PERF_CACHE; + +out: + kfree(reg_buf); + return err; +} + /* * Handle the detection and initialisation of a card. * @@ -1442,6 +1531,13 @@ static int mmc_sd_init_card(struct mmc_host *host, u32 ocr, goto free_card; } + /* Enable internal SD cache if supported. */ + if (card->ext_perf.feature_support & SD_EXT_PERF_CACHE) { + err = sd_enable_cache(card); + if (err) + goto free_card; + } + if (host->cqe_ops && !host->cqe_enabled) { err = host->cqe_ops->cqe_enable(host, card); if (!err) { @@ -1694,6 +1790,8 @@ static const struct mmc_bus_ops mmc_sd_ops = { .alive = mmc_sd_alive, .shutdown = mmc_sd_suspend, .hw_reset = mmc_sd_hw_reset, + .cache_enabled = sd_cache_enabled, + .flush_cache = sd_flush_cache, }; /* diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h index 2867af0635f8..74e6c0624d27 100644 --- a/include/linux/mmc/card.h +++ b/include/linux/mmc/card.h @@ -196,6 +196,7 @@ struct sd_ext_reg { u8 page; u16 offset; u8 rev; + u8 feature_enabled; u8 feature_support; /* Power Management Function. */ #define SD_EXT_POWER_OFF_NOTIFY (1<<0)