Changelog: https://cdn.kernel.org/pub/linux/kernel/v6.x/ChangeLog-6.12.35 Remove upstreamed patches: bcm27xx/patches-6.12/950-0961-media-imx335-Use-correct-register-width-for-HNUM.patch [1] bcm27xx/patches-6.12/950-1003-drivers-media-i2c-imx335-Fix-frame-size-enumeration.patch [2] gemini/patches-6.12/0001-net-ethernet-cortina-Use-TOE-TSO-on-all-TCP.patch [3] generic/backport-6.12/300-v6.16-mips-Add-std-flag-specified.patch [4] mvebu/patches-6.12/0004-v6.16-pinctrl-armada-37xx-propagate-error-from-armada_37xx.patch [5] mvebu/patches-6.12/0005-v6.16-pinctrl-armada-37xx-propagate-error-from-armada_37xx.patch [6] mvebu/patches-6.12/0006-v6.16-pinctrl-armada-37xx-propagate-error-from-armada_37xx.patch [7] mvebu/patches-6.12/0007-v6.16-pinctrl-armada-37xx-propagate-error-from-armada_37xx.patch [8] Manually rebased patches: bcm27xx/patches-6.12/950-0392-fbdev-Allow-client-to-request-a-particular-dev-fbN-n.patch [9] All other patches are automatically refreshed. [1] https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?h=v6.12.35&id=b93864e0865f235a791e69dc9ef4f896e559ef77 [2] https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?h=v6.12.35&id=1f78790d988c9d55cf8d4b4d511d4b3e38ecb81d [3] https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?h=v6.12.35&id=2bd434bb0eeb680c2b3dd6c68ca319b30cb8d47f [4] https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?h=v6.12.35&id=6dbda47fe8bd6aa978c150bc9d321a286d2cc3f4 [5] https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?h=v6.12.35&id=2cd2022c38fa26257cc6eec100ae122de9c1541c [6] https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?h=v6.12.35&id=133f17922b3dbae44fe583fb898b92b03558a657 [7] https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?h=v6.12.35&id=aefe45843ea667366e35df4fcfef5ff9051a86c9 [8] https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?h=v6.12.35&id=461d5a73ae45fbe6c300a6e64600f9792684eb52 [9] https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?h=v6.12.35&id=3f2098f4fba7718eb2501207ca6e99d22427f25a Signed-off-by: Shiji Yang <yangshiji66@outlook.com> Link: https://github.com/openwrt/openwrt/pull/19249 Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
182 lines
5.9 KiB
Diff
182 lines
5.9 KiB
Diff
From 514dc2cbb79cc42d4057278d4a207aca13f6afeb Mon Sep 17 00:00:00 2001
|
|
From: Jonathan Bell <jonathan@raspberrypi.com>
|
|
Date: Thu, 20 Jun 2024 14:31:20 +0100
|
|
Subject: [PATCH] mmc: restrict posted write counts for SD cards in CQ mode
|
|
|
|
Command Queueing requires Write Cache and Power off Notification support
|
|
from the card - but using the write cache forms a contract with the host
|
|
whereby the card expects to be told about impending power-down.
|
|
|
|
The implication is that (for performance) the card can do unsafe things
|
|
with pending write data - including reordering what gets committed to
|
|
nonvolatile storage at what time.
|
|
|
|
Exposed SD slots and platforms powered by hotpluggable means (i.e.
|
|
Raspberry Pis) can't guarantee that surprise removal won't happen.
|
|
|
|
To limit the scope for cards to invent new ways to trash filesystems,
|
|
limit pending writes to 1 (equivalent to the non-CQ behaviour).
|
|
|
|
Signed-off-by: Jonathan Bell <jonathan@raspberrypi.com>
|
|
|
|
fixup: mmc: restrict posted write counts for SD cards in CQ mode
|
|
|
|
Leaving card->max_posted_writes unintialised was a bad thing to do.
|
|
|
|
Also, cqe_enable is 1 if hsq is enabled as hsq substitutes the cqhci
|
|
implementation with its own.
|
|
|
|
Signed-off-by: Jonathan Bell <jonathan@raspberrypi.com>
|
|
---
|
|
drivers/mmc/core/block.c | 11 +++++++++--
|
|
drivers/mmc/core/mmc.c | 2 ++
|
|
drivers/mmc/core/queue.c | 9 +++++++++
|
|
drivers/mmc/core/queue.h | 1 +
|
|
drivers/mmc/core/sd.c | 10 ++++++++++
|
|
include/linux/mmc/card.h | 2 ++
|
|
6 files changed, 33 insertions(+), 2 deletions(-)
|
|
|
|
--- a/drivers/mmc/core/block.c
|
|
+++ b/drivers/mmc/core/block.c
|
|
@@ -1617,6 +1617,8 @@ static void mmc_blk_cqe_complete_rq(stru
|
|
|
|
spin_lock_irqsave(&mq->lock, flags);
|
|
|
|
+ if (req_op(req) == REQ_OP_WRITE)
|
|
+ mq->pending_writes--;
|
|
mq->in_flight[issue_type] -= 1;
|
|
|
|
put_card = (mmc_tot_in_flight(mq) == 0);
|
|
@@ -2133,6 +2135,8 @@ static void mmc_blk_mq_complete_rq(struc
|
|
struct mmc_queue_req *mqrq = req_to_mmc_queue_req(req);
|
|
unsigned int nr_bytes = mqrq->brq.data.bytes_xfered;
|
|
|
|
+ if (req_op(req) == REQ_OP_WRITE)
|
|
+ mq->pending_writes--;
|
|
if (nr_bytes) {
|
|
if (blk_update_request(req, BLK_STS_OK, nr_bytes))
|
|
blk_mq_requeue_request(req, true);
|
|
@@ -2227,13 +2231,16 @@ static void mmc_blk_mq_poll_completion(s
|
|
mmc_blk_urgent_bkops(mq, mqrq);
|
|
}
|
|
|
|
-static void mmc_blk_mq_dec_in_flight(struct mmc_queue *mq, enum mmc_issue_type issue_type)
|
|
+static void mmc_blk_mq_dec_in_flight(struct mmc_queue *mq, enum mmc_issue_type issue_type,
|
|
+ struct request *req)
|
|
{
|
|
unsigned long flags;
|
|
bool put_card;
|
|
|
|
spin_lock_irqsave(&mq->lock, flags);
|
|
|
|
+ if (req_op(req) == REQ_OP_WRITE)
|
|
+ mq->pending_writes--;
|
|
mq->in_flight[issue_type] -= 1;
|
|
|
|
put_card = (mmc_tot_in_flight(mq) == 0);
|
|
@@ -2267,7 +2274,7 @@ static void mmc_blk_mq_post_req(struct m
|
|
blk_mq_complete_request(req);
|
|
}
|
|
|
|
- mmc_blk_mq_dec_in_flight(mq, issue_type);
|
|
+ mmc_blk_mq_dec_in_flight(mq, issue_type, req);
|
|
}
|
|
|
|
void mmc_blk_mq_recovery(struct mmc_queue *mq)
|
|
--- a/drivers/mmc/core/mmc.c
|
|
+++ b/drivers/mmc/core/mmc.c
|
|
@@ -1657,6 +1657,7 @@ static int mmc_init_card(struct mmc_host
|
|
card->ocr = ocr;
|
|
card->type = MMC_TYPE_MMC;
|
|
card->rca = 1;
|
|
+ card->max_posted_writes = 1;
|
|
memcpy(card->raw_cid, cid, sizeof(card->raw_cid));
|
|
}
|
|
|
|
@@ -1922,6 +1923,7 @@ static int mmc_init_card(struct mmc_host
|
|
pr_info("%s: Host Software Queue enabled\n",
|
|
mmc_hostname(host));
|
|
}
|
|
+ card->max_posted_writes = card->ext_csd.cmdq_depth;
|
|
}
|
|
}
|
|
|
|
--- a/drivers/mmc/core/queue.c
|
|
+++ b/drivers/mmc/core/queue.c
|
|
@@ -266,6 +266,11 @@ static blk_status_t mmc_mq_queue_rq(stru
|
|
spin_unlock_irq(&mq->lock);
|
|
return BLK_STS_RESOURCE;
|
|
}
|
|
+ if (!host->hsq_enabled && host->cqe_enabled && req_op(req) == REQ_OP_WRITE &&
|
|
+ mq->pending_writes >= card->max_posted_writes) {
|
|
+ spin_unlock_irq(&mq->lock);
|
|
+ return BLK_STS_RESOURCE;
|
|
+ }
|
|
break;
|
|
default:
|
|
/*
|
|
@@ -282,6 +287,8 @@ static blk_status_t mmc_mq_queue_rq(stru
|
|
/* Parallel dispatch of requests is not supported at the moment */
|
|
mq->busy = true;
|
|
|
|
+ if (req_op(req) == REQ_OP_WRITE)
|
|
+ mq->pending_writes++;
|
|
mq->in_flight[issue_type] += 1;
|
|
get_card = (mmc_tot_in_flight(mq) == 1);
|
|
cqe_retune_ok = (mmc_cqe_qcnt(mq) == 1);
|
|
@@ -321,6 +328,8 @@ static blk_status_t mmc_mq_queue_rq(stru
|
|
bool put_card = false;
|
|
|
|
spin_lock_irq(&mq->lock);
|
|
+ if (req_op(req) == REQ_OP_WRITE)
|
|
+ mq->pending_writes--;
|
|
mq->in_flight[issue_type] -= 1;
|
|
if (mmc_tot_in_flight(mq) == 0)
|
|
put_card = true;
|
|
--- a/drivers/mmc/core/queue.h
|
|
+++ b/drivers/mmc/core/queue.h
|
|
@@ -79,6 +79,7 @@ struct mmc_queue {
|
|
struct request_queue *queue;
|
|
spinlock_t lock;
|
|
int in_flight[MMC_ISSUE_MAX];
|
|
+ int pending_writes;
|
|
unsigned int cqe_busy;
|
|
#define MMC_CQE_DCMD_BUSY BIT(0)
|
|
bool busy;
|
|
--- a/drivers/mmc/core/sd.c
|
|
+++ b/drivers/mmc/core/sd.c
|
|
@@ -1115,6 +1115,15 @@ static int sd_parse_ext_reg_perf(struct
|
|
pr_debug("%s: Command Queue supported depth %u\n",
|
|
mmc_hostname(card->host),
|
|
card->ext_csd.cmdq_depth);
|
|
+ /*
|
|
+ * If CQ is enabled, there is a contract between host and card such that
|
|
+ * VDD will be maintained and removed only if a power off notification
|
|
+ * is provided. An SD card in an accessible slot means surprise removal
|
|
+ * is a possibility. As a middle ground, keep the default maximum of 1
|
|
+ * posted write unless the card is "hardwired".
|
|
+ */
|
|
+ if (!mmc_card_is_removable(card->host))
|
|
+ card->max_posted_writes = card->ext_csd.cmdq_depth;
|
|
}
|
|
|
|
card->ext_perf.fno = fno;
|
|
@@ -1378,6 +1387,7 @@ retry:
|
|
|
|
card->ocr = ocr;
|
|
card->type = MMC_TYPE_SD;
|
|
+ card->max_posted_writes = 1;
|
|
memcpy(card->raw_cid, cid, sizeof(card->raw_cid));
|
|
}
|
|
|
|
--- a/include/linux/mmc/card.h
|
|
+++ b/include/linux/mmc/card.h
|
|
@@ -344,6 +344,8 @@ struct mmc_card {
|
|
unsigned int nr_parts;
|
|
|
|
struct workqueue_struct *complete_wq; /* Private workqueue */
|
|
+
|
|
+ unsigned int max_posted_writes; /* command queue posted write limit */
|
|
};
|
|
|
|
static inline bool mmc_large_sector(struct mmc_card *card)
|