aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKalderon, Michal <Michal.Kalderon@cavium.com>2018-03-05 03:50:10 -0500
committerJason Gunthorpe <jgg@mellanox.com>2018-03-06 21:57:37 -0500
commite3fd112cbf21d049faf64ba1471d72b93c22109a (patch)
treeed94375da425fce885542808e4761442ebc70c10
parentea0ed47803df93d0904b838d6b5afceec3ad0ba4 (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.c3
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;