diff options
author | Kalderon, Michal <Michal.Kalderon@cavium.com> | 2018-03-05 03:50:10 -0500 |
---|---|---|
committer | Jason Gunthorpe <jgg@mellanox.com> | 2018-03-06 21:57:37 -0500 |
commit | e3fd112cbf21d049faf64ba1471d72b93c22109a (patch) | |
tree | ed94375da425fce885542808e4761442ebc70c10 | |
parent | ea0ed47803df93d0904b838d6b5afceec3ad0ba4 (diff) |
RDMA/qedr: Fix kernel panic when running fio over NFSoRDMA
Race in qedr_poll_cq, lastest_cqe wasn't protected by lock,
leading to a case where two context's accessing poll_cq at
the same time lead to one of them having a pointer to an old
latest_cqe and reading an invalid cqe element
Signed-off-by: Amit Radzi <Amit.Radzi@cavium.com>
Signed-off-by: Michal Kalderon <Michal.Kalderon@cavium.com>
Signed-off-by: Ariel Elior <Ariel.Elior@cavium.com>
Signed-off-by: Jason Gunthorpe <jgg@mellanox.com>
-rw-r--r-- | drivers/infiniband/hw/qedr/verbs.c | 3 |
1 files changed, 2 insertions, 1 deletions
diff --git a/drivers/infiniband/hw/qedr/verbs.c b/drivers/infiniband/hw/qedr/verbs.c index 53f00dbf313f..102b9e0efe9a 100644 --- a/drivers/infiniband/hw/qedr/verbs.c +++ b/drivers/infiniband/hw/qedr/verbs.c | |||
@@ -3724,7 +3724,7 @@ int qedr_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *wc) | |||
3724 | { | 3724 | { |
3725 | struct qedr_dev *dev = get_qedr_dev(ibcq->device); | 3725 | struct qedr_dev *dev = get_qedr_dev(ibcq->device); |
3726 | struct qedr_cq *cq = get_qedr_cq(ibcq); | 3726 | struct qedr_cq *cq = get_qedr_cq(ibcq); |
3727 | union rdma_cqe *cqe = cq->latest_cqe; | 3727 | union rdma_cqe *cqe; |
3728 | u32 old_cons, new_cons; | 3728 | u32 old_cons, new_cons; |
3729 | unsigned long flags; | 3729 | unsigned long flags; |
3730 | int update = 0; | 3730 | int update = 0; |
@@ -3741,6 +3741,7 @@ int qedr_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *wc) | |||
3741 | return qedr_gsi_poll_cq(ibcq, num_entries, wc); | 3741 | return qedr_gsi_poll_cq(ibcq, num_entries, wc); |
3742 | 3742 | ||
3743 | spin_lock_irqsave(&cq->cq_lock, flags); | 3743 | spin_lock_irqsave(&cq->cq_lock, flags); |
3744 | cqe = cq->latest_cqe; | ||
3744 | old_cons = qed_chain_get_cons_idx_u32(&cq->pbl); | 3745 | old_cons = qed_chain_get_cons_idx_u32(&cq->pbl); |
3745 | while (num_entries && is_valid_cqe(cq, cqe)) { | 3746 | while (num_entries && is_valid_cqe(cq, cqe)) { |
3746 | struct qedr_qp *qp; | 3747 | struct qedr_qp *qp; |