mmc: don't reference requests after finishing them

Posted write tracking introduced in the commit below raced with re-use
of the requests between completion and submission, potentially causing
underflow of the pending write count.

Fixes: e6c1e862b2 ("mmc: restrict posted write counts for SD cards in CQ mode")

Signed-off-by: Jonathan Bell <jonathan@raspberrypi.com>
This commit is contained in:
Jonathan Bell
2024-10-15 11:22:53 +01:00
committed by Dom Cobley
parent 5b2a19f87c
commit 24c67c482d

View File

@@ -1570,6 +1570,7 @@ static void mmc_blk_cqe_complete_rq(struct mmc_queue *mq, struct request *req)
struct request_queue *q = req->q; struct request_queue *q = req->q;
struct mmc_host *host = mq->card->host; struct mmc_host *host = mq->card->host;
enum mmc_issue_type issue_type = mmc_issue_type(mq, req); enum mmc_issue_type issue_type = mmc_issue_type(mq, req);
bool write = req_op(req) == REQ_OP_WRITE;
unsigned long flags; unsigned long flags;
bool put_card; bool put_card;
int err; int err;
@@ -1601,7 +1602,7 @@ static void mmc_blk_cqe_complete_rq(struct mmc_queue *mq, struct request *req)
spin_lock_irqsave(&mq->lock, flags); spin_lock_irqsave(&mq->lock, flags);
if (req_op(req) == REQ_OP_WRITE) if (write)
mq->pending_writes--; mq->pending_writes--;
mq->in_flight[issue_type] -= 1; mq->in_flight[issue_type] -= 1;
@@ -2216,15 +2217,16 @@ static void mmc_blk_mq_poll_completion(struct mmc_queue *mq,
} }
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) bool write)
{ {
unsigned long flags; unsigned long flags;
bool put_card; bool put_card;
spin_lock_irqsave(&mq->lock, flags); spin_lock_irqsave(&mq->lock, flags);
if (req_op(req) == REQ_OP_WRITE) if (write)
mq->pending_writes--; mq->pending_writes--;
mq->in_flight[issue_type] -= 1; mq->in_flight[issue_type] -= 1;
put_card = (mmc_tot_in_flight(mq) == 0); put_card = (mmc_tot_in_flight(mq) == 0);
@@ -2239,6 +2241,7 @@ static void mmc_blk_mq_post_req(struct mmc_queue *mq, struct request *req,
bool can_sleep) bool can_sleep)
{ {
enum mmc_issue_type issue_type = mmc_issue_type(mq, req); enum mmc_issue_type issue_type = mmc_issue_type(mq, req);
bool write = req_op(req) == REQ_OP_WRITE;
struct mmc_queue_req *mqrq = req_to_mmc_queue_req(req); struct mmc_queue_req *mqrq = req_to_mmc_queue_req(req);
struct mmc_request *mrq = &mqrq->brq.mrq; struct mmc_request *mrq = &mqrq->brq.mrq;
struct mmc_host *host = mq->card->host; struct mmc_host *host = mq->card->host;
@@ -2258,7 +2261,7 @@ static void mmc_blk_mq_post_req(struct mmc_queue *mq, struct request *req,
blk_mq_complete_request(req); blk_mq_complete_request(req);
} }
mmc_blk_mq_dec_in_flight(mq, issue_type, req); mmc_blk_mq_dec_in_flight(mq, issue_type, write);
} }
void mmc_blk_mq_recovery(struct mmc_queue *mq) void mmc_blk_mq_recovery(struct mmc_queue *mq)