2ba494958ea0bb256b473123c5167de6b513ad00
[openwrt/staging/stintel.git] /
1 From e6c1e862b2b8150a419f4208e5bd7749662b16a1 Mon Sep 17 00:00:00 2001
2 From: Jonathan Bell <jonathan@raspberrypi.com>
3 Date: Thu, 20 Jun 2024 14:31:20 +0100
4 Subject: [PATCH 1167/1215] mmc: restrict posted write counts for SD cards in
5 CQ mode
6
7 Command Queueing requires Write Cache and Power off Notification support
8 from the card - but using the write cache forms a contract with the host
9 whereby the card expects to be told about impending power-down.
10
11 The implication is that (for performance) the card can do unsafe things
12 with pending write data - including reordering what gets committed to
13 nonvolatile storage at what time.
14
15 Exposed SD slots and platforms powered by hotpluggable means (i.e.
16 Raspberry Pis) can't guarantee that surprise removal won't happen.
17
18 To limit the scope for cards to invent new ways to trash filesystems,
19 limit pending writes to 1 (equivalent to the non-CQ behaviour).
20
21 Signed-off-by: Jonathan Bell <jonathan@raspberrypi.com>
22 ---
23 drivers/mmc/core/block.c | 11 +++++++++--
24 drivers/mmc/core/mmc.c | 1 +
25 drivers/mmc/core/queue.c | 9 +++++++++
26 drivers/mmc/core/queue.h | 1 +
27 drivers/mmc/core/sd.c | 8 ++++++++
28 include/linux/mmc/card.h | 2 ++
29 6 files changed, 30 insertions(+), 2 deletions(-)
30
31 --- a/drivers/mmc/core/block.c
32 +++ b/drivers/mmc/core/block.c
33 @@ -1555,6 +1555,8 @@ static void mmc_blk_cqe_complete_rq(stru
34
35 spin_lock_irqsave(&mq->lock, flags);
36
37 + if (req_op(req) == REQ_OP_WRITE)
38 + mq->pending_writes--;
39 mq->in_flight[issue_type] -= 1;
40
41 put_card = (mmc_tot_in_flight(mq) == 0);
42 @@ -2071,6 +2073,8 @@ static void mmc_blk_mq_complete_rq(struc
43 struct mmc_queue_req *mqrq = req_to_mmc_queue_req(req);
44 unsigned int nr_bytes = mqrq->brq.data.bytes_xfered;
45
46 + if (req_op(req) == REQ_OP_WRITE)
47 + mq->pending_writes--;
48 if (nr_bytes) {
49 if (blk_update_request(req, BLK_STS_OK, nr_bytes))
50 blk_mq_requeue_request(req, true);
51 @@ -2165,13 +2169,16 @@ static void mmc_blk_mq_poll_completion(s
52 mmc_blk_urgent_bkops(mq, mqrq);
53 }
54
55 -static void mmc_blk_mq_dec_in_flight(struct mmc_queue *mq, enum mmc_issue_type issue_type)
56 +static void mmc_blk_mq_dec_in_flight(struct mmc_queue *mq, enum mmc_issue_type issue_type,
57 + struct request *req)
58 {
59 unsigned long flags;
60 bool put_card;
61
62 spin_lock_irqsave(&mq->lock, flags);
63
64 + if (req_op(req) == REQ_OP_WRITE)
65 + mq->pending_writes--;
66 mq->in_flight[issue_type] -= 1;
67
68 put_card = (mmc_tot_in_flight(mq) == 0);
69 @@ -2205,7 +2212,7 @@ static void mmc_blk_mq_post_req(struct m
70 blk_mq_complete_request(req);
71 }
72
73 - mmc_blk_mq_dec_in_flight(mq, issue_type);
74 + mmc_blk_mq_dec_in_flight(mq, issue_type, req);
75 }
76
77 void mmc_blk_mq_recovery(struct mmc_queue *mq)
78 --- a/drivers/mmc/core/mmc.c
79 +++ b/drivers/mmc/core/mmc.c
80 @@ -1922,6 +1922,7 @@ static int mmc_init_card(struct mmc_host
81 pr_info("%s: Host Software Queue enabled\n",
82 mmc_hostname(host));
83 }
84 + card->max_posted_writes = card->ext_csd.cmdq_depth;
85 }
86 }
87
88 --- a/drivers/mmc/core/queue.c
89 +++ b/drivers/mmc/core/queue.c
90 @@ -268,6 +268,11 @@ static blk_status_t mmc_mq_queue_rq(stru
91 spin_unlock_irq(&mq->lock);
92 return BLK_STS_RESOURCE;
93 }
94 + if (host->cqe_enabled && req_op(req) == REQ_OP_WRITE &&
95 + mq->pending_writes >= card->max_posted_writes) {
96 + spin_unlock_irq(&mq->lock);
97 + return BLK_STS_RESOURCE;
98 + }
99 break;
100 default:
101 /*
102 @@ -284,6 +289,8 @@ static blk_status_t mmc_mq_queue_rq(stru
103 /* Parallel dispatch of requests is not supported at the moment */
104 mq->busy = true;
105
106 + if (req_op(req) == REQ_OP_WRITE)
107 + mq->pending_writes++;
108 mq->in_flight[issue_type] += 1;
109 get_card = (mmc_tot_in_flight(mq) == 1);
110 cqe_retune_ok = (mmc_cqe_qcnt(mq) == 1);
111 @@ -323,6 +330,8 @@ static blk_status_t mmc_mq_queue_rq(stru
112 bool put_card = false;
113
114 spin_lock_irq(&mq->lock);
115 + if (req_op(req) == REQ_OP_WRITE)
116 + mq->pending_writes--;
117 mq->in_flight[issue_type] -= 1;
118 if (mmc_tot_in_flight(mq) == 0)
119 put_card = true;
120 --- a/drivers/mmc/core/queue.h
121 +++ b/drivers/mmc/core/queue.h
122 @@ -79,6 +79,7 @@ struct mmc_queue {
123 struct request_queue *queue;
124 spinlock_t lock;
125 int in_flight[MMC_ISSUE_MAX];
126 + int pending_writes;
127 unsigned int cqe_busy;
128 #define MMC_CQE_DCMD_BUSY BIT(0)
129 bool busy;
130 --- a/drivers/mmc/core/sd.c
131 +++ b/drivers/mmc/core/sd.c
132 @@ -1104,6 +1104,14 @@ static int sd_parse_ext_reg_perf(struct
133 pr_debug("%s: Command Queue supported depth %u\n",
134 mmc_hostname(card->host),
135 card->ext_csd.cmdq_depth);
136 + /*
137 + * If CQ is enabled, there is a contract between host and card such that VDD will
138 + * be maintained and removed only if a power off notification is provided.
139 + * An SD card in an accessible slot means surprise removal is a possibility.
140 + * As a middle ground, limit max posted writes to 1 unless the card is "hardwired".
141 + */
142 + if (mmc_card_is_removable(card->host))
143 + card->max_posted_writes = 1;
144 }
145
146 card->ext_perf.fno = fno;
147 --- a/include/linux/mmc/card.h
148 +++ b/include/linux/mmc/card.h
149 @@ -343,6 +343,8 @@ struct mmc_card {
150 unsigned int nr_parts;
151
152 struct workqueue_struct *complete_wq; /* Private workqueue */
153 +
154 + unsigned int max_posted_writes; /* command queue posted write limit */
155 };
156
157 static inline bool mmc_large_sector(struct mmc_card *card)