Skip to content

Commit 691eb7c

Browse files
kadesai16rleon
authored andcommitted
RDMA/bnxt_re: handle command completions after driver detect a timedout
If calling context detect command timeout, associated memory stored on stack will not be valid. If firmware complete the same command later, this causes incorrect memory access by driver. Added is_waiter_alive to handle delayed completion by firmware. is_waiter_alive is set and reset under command queue lock. Signed-off-by: Kashyap Desai <kashyap.desai@broadcom.com> Signed-off-by: Selvin Xavier <selvin.xavier@broadcom.com> Link: https://lore.kernel.org/r/1686308514-11996-11-git-send-email-selvin.xavier@broadcom.com Signed-off-by: Leon Romanovsky <leon@kernel.org>
1 parent 354f5bd commit 691eb7c

2 files changed

Lines changed: 34 additions & 26 deletions

File tree

drivers/infiniband/hw/bnxt_re/qplib_rcfw.c

Lines changed: 33 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,6 @@ static int __wait_for_resp(struct bnxt_qplib_rcfw *rcfw, u16 cookie, u8 opcode)
105105
{
106106
struct bnxt_qplib_cmdq_ctx *cmdq;
107107
u16 cbit;
108-
int ret;
109108

110109
cmdq = &rcfw->cmdq;
111110
cbit = cookie % rcfw->cmdq_depth;
@@ -115,9 +114,9 @@ static int __wait_for_resp(struct bnxt_qplib_rcfw *rcfw, u16 cookie, u8 opcode)
115114
return bnxt_qplib_map_rc(opcode);
116115

117116
/* Non zero means command completed */
118-
ret = wait_event_timeout(cmdq->waitq,
119-
!test_bit(cbit, cmdq->cmdq_bitmap),
120-
msecs_to_jiffies(10000));
117+
wait_event_timeout(cmdq->waitq,
118+
!test_bit(cbit, cmdq->cmdq_bitmap),
119+
msecs_to_jiffies(10000));
121120

122121
if (!test_bit(cbit, cmdq->cmdq_bitmap))
123122
return 0;
@@ -170,7 +169,7 @@ static int __block_for_resp(struct bnxt_qplib_rcfw *rcfw, u16 cookie, u8 opcode)
170169
static int __send_message(struct bnxt_qplib_rcfw *rcfw,
171170
struct bnxt_qplib_cmdqmsg *msg)
172171
{
173-
u32 bsize, opcode, free_slots, required_slots;
172+
u32 bsize, free_slots, required_slots;
174173
struct bnxt_qplib_cmdq_ctx *cmdq;
175174
struct bnxt_qplib_crsqe *crsqe;
176175
struct bnxt_qplib_cmdqe *cmdqe;
@@ -185,8 +184,6 @@ static int __send_message(struct bnxt_qplib_rcfw *rcfw,
185184
hwq = &cmdq->hwq;
186185
pdev = rcfw->pdev;
187186

188-
opcode = __get_cmdq_base_opcode(msg->req, msg->req_sz);
189-
190187
if (test_bit(FIRMWARE_TIMED_OUT, &cmdq->flags))
191188
return -ETIMEDOUT;
192189

@@ -216,6 +213,7 @@ static int __send_message(struct bnxt_qplib_rcfw *rcfw,
216213
crsqe->free_slots = free_slots;
217214
crsqe->resp = (struct creq_qp_event *)msg->resp;
218215
crsqe->resp->cookie = cpu_to_le16(cookie);
216+
crsqe->is_waiter_alive = true;
219217
crsqe->req_size = __get_cmdq_base_cmd_size(msg->req, msg->req_sz);
220218
if (__get_cmdq_base_resp_size(msg->req, msg->req_sz) && msg->sb) {
221219
struct bnxt_qplib_rcfw_sbuf *sbuf = msg->sb;
@@ -347,7 +345,9 @@ static int __bnxt_qplib_rcfw_send_message(struct bnxt_qplib_rcfw *rcfw,
347345
struct bnxt_qplib_cmdqmsg *msg)
348346
{
349347
struct creq_qp_event *evnt = (struct creq_qp_event *)msg->resp;
350-
u16 cookie;
348+
struct bnxt_qplib_crsqe *crsqe;
349+
unsigned long flags;
350+
u16 cookie, cbit;
351351
int rc = 0;
352352
u8 opcode;
353353

@@ -363,6 +363,7 @@ static int __bnxt_qplib_rcfw_send_message(struct bnxt_qplib_rcfw *rcfw,
363363

364364
cookie = le16_to_cpu(__get_cmdq_base_cookie(msg->req, msg->req_sz))
365365
& RCFW_MAX_COOKIE_VALUE;
366+
cbit = cookie % rcfw->cmdq_depth;
366367

367368
if (msg->block)
368369
rc = __block_for_resp(rcfw, cookie, opcode);
@@ -378,6 +379,14 @@ static int __bnxt_qplib_rcfw_send_message(struct bnxt_qplib_rcfw *rcfw,
378379
return rc;
379380
}
380381

382+
if (rc) {
383+
spin_lock_irqsave(&rcfw->cmdq.hwq.lock, flags);
384+
crsqe = &rcfw->crsqe_tbl[cbit];
385+
crsqe->is_waiter_alive = false;
386+
spin_unlock_irqrestore(&rcfw->cmdq.hwq.lock, flags);
387+
return -ETIMEDOUT;
388+
}
389+
381390
if (evnt->status) {
382391
/* failed with status */
383392
dev_err(&rcfw->pdev->dev, "cmdq[%#x]=%#x status %#x\n",
@@ -480,15 +489,15 @@ static int bnxt_qplib_process_qp_event(struct bnxt_qplib_rcfw *rcfw,
480489
struct creq_qp_error_notification *err_event;
481490
struct bnxt_qplib_hwq *hwq = &rcfw->cmdq.hwq;
482491
struct bnxt_qplib_crsqe *crsqe;
492+
u32 qp_id, tbl_indx, req_size;
483493
struct bnxt_qplib_qp *qp;
484494
u16 cbit, blocked = 0;
495+
bool is_waiter_alive;
485496
struct pci_dev *pdev;
486497
unsigned long flags;
487498
u32 wait_cmds = 0;
488-
__le16 mcookie;
489499
u16 cookie;
490500
int rc = 0;
491-
u32 qp_id, tbl_indx;
492501

493502
pdev = rcfw->pdev;
494503
switch (qp_event->event) {
@@ -520,31 +529,29 @@ static int bnxt_qplib_process_qp_event(struct bnxt_qplib_rcfw *rcfw,
520529
spin_lock_irqsave_nested(&hwq->lock, flags,
521530
SINGLE_DEPTH_NESTING);
522531
cookie = le16_to_cpu(qp_event->cookie);
523-
mcookie = qp_event->cookie;
524532
blocked = cookie & RCFW_CMD_IS_BLOCKING;
525533
cookie &= RCFW_MAX_COOKIE_VALUE;
526534
cbit = cookie % rcfw->cmdq_depth;
527535
crsqe = &rcfw->crsqe_tbl[cbit];
528-
if (crsqe->resp &&
529-
crsqe->resp->cookie == mcookie) {
530-
memcpy(crsqe->resp, qp_event, sizeof(*qp_event));
531-
crsqe->resp = NULL;
532-
} else {
533-
if (crsqe->resp && crsqe->resp->cookie)
534-
dev_err(&pdev->dev,
535-
"CMD %s cookie sent=%#x, recd=%#x\n",
536-
crsqe->resp ? "mismatch" : "collision",
537-
crsqe->resp ? crsqe->resp->cookie : 0,
538-
mcookie);
539-
}
540536
if (!test_and_clear_bit(cbit, rcfw->cmdq.cmdq_bitmap))
541537
dev_warn(&pdev->dev,
542538
"CMD bit %d was not requested\n", cbit);
543-
hwq->cons += crsqe->req_size;
539+
540+
if (crsqe->is_waiter_alive) {
541+
if (crsqe->resp)
542+
memcpy(crsqe->resp, qp_event, sizeof(*qp_event));
543+
if (!blocked)
544+
wait_cmds++;
545+
}
546+
547+
req_size = crsqe->req_size;
548+
is_waiter_alive = crsqe->is_waiter_alive;
549+
544550
crsqe->req_size = 0;
551+
if (!is_waiter_alive)
552+
crsqe->resp = NULL;
545553

546-
if (!blocked)
547-
wait_cmds++;
554+
hwq->cons += req_size;
548555
spin_unlock_irqrestore(&hwq->lock, flags);
549556
}
550557
*num_wait += wait_cmds;

drivers/infiniband/hw/bnxt_re/qplib_rcfw.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,7 @@ struct bnxt_qplib_crsqe {
152152
u32 req_size;
153153
/* Free slots at the time of submission */
154154
u32 free_slots;
155+
bool is_waiter_alive;
155156
};
156157

157158
struct bnxt_qplib_rcfw_sbuf {

0 commit comments

Comments
 (0)