Skip to content

Commit c06f909

Browse files
committed
Merge tag 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rdma/rdma
Pull rdma fixes from Jason Gunthorpe: "Several smaller driver fixes and a core RDMA CM regression fix: - Fix improperly accepting flags from userspace in mlx4 - Add missing DMA barriers for irdma - Fix two kcsan warnings in irdma - Report the correct CQ op code to userspace in irdma - Report the correct MW bind error code for irdma - Load the destination address in RDMA CM to resolve a recent regression - Fix a QP regression in mthca - Remove a race processing completions in bnxt_re resulting in a crash - Fix driver unloading races with interrupts and tasklets in bnxt_re - Fix missing error unwind in rxe" * tag 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rdma/rdma: RDMA/irdma: Report correct WC error RDMA/irdma: Fix op_type reporting in CQEs RDMA/rxe: Fix an error handling path in rxe_bind_mw() RDMA/bnxt_re: Fix hang during driver unload RDMA/bnxt_re: Prevent handling any completions after qp destroy RDMA/mthca: Fix crash when polling CQ for shared QPs RDMA/core: Update CMA destination address on rdma_resolve_addr RDMA/irdma: Fix data race on CQP request done RDMA/irdma: Fix data race on CQP completion stats RDMA/irdma: Add missing read barriers RDMA/mlx4: Make check for invalid flags stricter
2 parents 2b17e90 + ae46356 commit c06f909

File tree

16 files changed

+114
-64
lines changed

16 files changed

+114
-64
lines changed

drivers/infiniband/core/cma.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4062,6 +4062,8 @@ static int resolve_prepare_src(struct rdma_id_private *id_priv,
40624062
RDMA_CM_ADDR_QUERY)))
40634063
return -EINVAL;
40644064

4065+
} else {
4066+
memcpy(cma_dst_addr(id_priv), dst_addr, rdma_addr_size(dst_addr));
40654067
}
40664068

40674069
if (cma_family(id_priv) != dst_addr->sa_family) {

drivers/infiniband/hw/bnxt_re/ib_verbs.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -869,7 +869,10 @@ static int bnxt_re_destroy_gsi_sqp(struct bnxt_re_qp *qp)
869869
int bnxt_re_destroy_qp(struct ib_qp *ib_qp, struct ib_udata *udata)
870870
{
871871
struct bnxt_re_qp *qp = container_of(ib_qp, struct bnxt_re_qp, ib_qp);
872+
struct bnxt_qplib_qp *qplib_qp = &qp->qplib_qp;
872873
struct bnxt_re_dev *rdev = qp->rdev;
874+
struct bnxt_qplib_nq *scq_nq = NULL;
875+
struct bnxt_qplib_nq *rcq_nq = NULL;
873876
unsigned int flags;
874877
int rc;
875878

@@ -903,6 +906,15 @@ int bnxt_re_destroy_qp(struct ib_qp *ib_qp, struct ib_udata *udata)
903906
ib_umem_release(qp->rumem);
904907
ib_umem_release(qp->sumem);
905908

909+
/* Flush all the entries of notification queue associated with
910+
* given qp.
911+
*/
912+
scq_nq = qplib_qp->scq->nq;
913+
rcq_nq = qplib_qp->rcq->nq;
914+
bnxt_re_synchronize_nq(scq_nq);
915+
if (scq_nq != rcq_nq)
916+
bnxt_re_synchronize_nq(rcq_nq);
917+
906918
return 0;
907919
}
908920

drivers/infiniband/hw/bnxt_re/qplib_fp.c

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -381,6 +381,24 @@ static void bnxt_qplib_service_nq(struct tasklet_struct *t)
381381
spin_unlock_bh(&hwq->lock);
382382
}
383383

384+
/* bnxt_re_synchronize_nq - self polling notification queue.
385+
* @nq - notification queue pointer
386+
*
387+
* This function will start polling entries of a given notification queue
388+
* for all pending entries.
389+
* This function is useful to synchronize notification entries while resources
390+
* are going away.
391+
*/
392+
393+
void bnxt_re_synchronize_nq(struct bnxt_qplib_nq *nq)
394+
{
395+
int budget = nq->budget;
396+
397+
nq->budget = nq->hwq.max_elements;
398+
bnxt_qplib_service_nq(&nq->nq_tasklet);
399+
nq->budget = budget;
400+
}
401+
384402
static irqreturn_t bnxt_qplib_nq_irq(int irq, void *dev_instance)
385403
{
386404
struct bnxt_qplib_nq *nq = dev_instance;
@@ -402,19 +420,19 @@ void bnxt_qplib_nq_stop_irq(struct bnxt_qplib_nq *nq, bool kill)
402420
if (!nq->requested)
403421
return;
404422

405-
tasklet_disable(&nq->nq_tasklet);
423+
nq->requested = false;
406424
/* Mask h/w interrupt */
407425
bnxt_qplib_ring_nq_db(&nq->nq_db.dbinfo, nq->res->cctx, false);
408426
/* Sync with last running IRQ handler */
409427
synchronize_irq(nq->msix_vec);
410-
if (kill)
411-
tasklet_kill(&nq->nq_tasklet);
412-
413428
irq_set_affinity_hint(nq->msix_vec, NULL);
414429
free_irq(nq->msix_vec, nq);
415430
kfree(nq->name);
416431
nq->name = NULL;
417-
nq->requested = false;
432+
433+
if (kill)
434+
tasklet_kill(&nq->nq_tasklet);
435+
tasklet_disable(&nq->nq_tasklet);
418436
}
419437

420438
void bnxt_qplib_disable_nq(struct bnxt_qplib_nq *nq)

drivers/infiniband/hw/bnxt_re/qplib_fp.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -553,6 +553,7 @@ int bnxt_qplib_process_flush_list(struct bnxt_qplib_cq *cq,
553553
struct bnxt_qplib_cqe *cqe,
554554
int num_cqes);
555555
void bnxt_qplib_flush_cqn_wq(struct bnxt_qplib_qp *qp);
556+
void bnxt_re_synchronize_nq(struct bnxt_qplib_nq *nq);
556557

557558
static inline void *bnxt_qplib_get_swqe(struct bnxt_qplib_q *que, u32 *swq_idx)
558559
{

drivers/infiniband/hw/bnxt_re/qplib_rcfw.c

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -989,19 +989,18 @@ void bnxt_qplib_rcfw_stop_irq(struct bnxt_qplib_rcfw *rcfw, bool kill)
989989
if (!creq->requested)
990990
return;
991991

992-
tasklet_disable(&creq->creq_tasklet);
992+
creq->requested = false;
993993
/* Mask h/w interrupts */
994994
bnxt_qplib_ring_nq_db(&creq->creq_db.dbinfo, rcfw->res->cctx, false);
995995
/* Sync with last running IRQ-handler */
996996
synchronize_irq(creq->msix_vec);
997-
if (kill)
998-
tasklet_kill(&creq->creq_tasklet);
999-
1000997
free_irq(creq->msix_vec, rcfw);
1001998
kfree(creq->irq_name);
1002999
creq->irq_name = NULL;
1003-
creq->requested = false;
10041000
atomic_set(&rcfw->rcfw_intr_enabled, 0);
1001+
if (kill)
1002+
tasklet_kill(&creq->creq_tasklet);
1003+
tasklet_disable(&creq->creq_tasklet);
10051004
}
10061005

10071006
void bnxt_qplib_disable_rcfw_channel(struct bnxt_qplib_rcfw *rcfw)

drivers/infiniband/hw/irdma/ctrl.c

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2712,13 +2712,13 @@ static int irdma_sc_cq_modify(struct irdma_sc_cq *cq,
27122712
*/
27132713
void irdma_check_cqp_progress(struct irdma_cqp_timeout *timeout, struct irdma_sc_dev *dev)
27142714
{
2715-
if (timeout->compl_cqp_cmds != dev->cqp_cmd_stats[IRDMA_OP_CMPL_CMDS]) {
2716-
timeout->compl_cqp_cmds = dev->cqp_cmd_stats[IRDMA_OP_CMPL_CMDS];
2715+
u64 completed_ops = atomic64_read(&dev->cqp->completed_ops);
2716+
2717+
if (timeout->compl_cqp_cmds != completed_ops) {
2718+
timeout->compl_cqp_cmds = completed_ops;
27172719
timeout->count = 0;
2718-
} else {
2719-
if (dev->cqp_cmd_stats[IRDMA_OP_REQ_CMDS] !=
2720-
timeout->compl_cqp_cmds)
2721-
timeout->count++;
2720+
} else if (timeout->compl_cqp_cmds != dev->cqp->requested_ops) {
2721+
timeout->count++;
27222722
}
27232723
}
27242724

@@ -2761,7 +2761,7 @@ static int irdma_cqp_poll_registers(struct irdma_sc_cqp *cqp, u32 tail,
27612761
if (newtail != tail) {
27622762
/* SUCCESS */
27632763
IRDMA_RING_MOVE_TAIL(cqp->sq_ring);
2764-
cqp->dev->cqp_cmd_stats[IRDMA_OP_CMPL_CMDS]++;
2764+
atomic64_inc(&cqp->completed_ops);
27652765
return 0;
27662766
}
27672767
udelay(cqp->dev->hw_attrs.max_sleep_count);
@@ -3121,8 +3121,8 @@ int irdma_sc_cqp_init(struct irdma_sc_cqp *cqp,
31213121
info->dev->cqp = cqp;
31223122

31233123
IRDMA_RING_INIT(cqp->sq_ring, cqp->sq_size);
3124-
cqp->dev->cqp_cmd_stats[IRDMA_OP_REQ_CMDS] = 0;
3125-
cqp->dev->cqp_cmd_stats[IRDMA_OP_CMPL_CMDS] = 0;
3124+
cqp->requested_ops = 0;
3125+
atomic64_set(&cqp->completed_ops, 0);
31263126
/* for the cqp commands backlog. */
31273127
INIT_LIST_HEAD(&cqp->dev->cqp_cmd_head);
31283128

@@ -3274,7 +3274,7 @@ __le64 *irdma_sc_cqp_get_next_send_wqe_idx(struct irdma_sc_cqp *cqp, u64 scratch
32743274
if (ret_code)
32753275
return NULL;
32763276

3277-
cqp->dev->cqp_cmd_stats[IRDMA_OP_REQ_CMDS]++;
3277+
cqp->requested_ops++;
32783278
if (!*wqe_idx)
32793279
cqp->polarity = !cqp->polarity;
32803280
wqe = cqp->sq_base[*wqe_idx].elem;
@@ -3363,6 +3363,9 @@ int irdma_sc_ccq_get_cqe_info(struct irdma_sc_cq *ccq,
33633363
if (polarity != ccq->cq_uk.polarity)
33643364
return -ENOENT;
33653365

3366+
/* Ensure CEQE contents are read after valid bit is checked */
3367+
dma_rmb();
3368+
33663369
get_64bit_val(cqe, 8, &qp_ctx);
33673370
cqp = (struct irdma_sc_cqp *)(unsigned long)qp_ctx;
33683371
info->error = (bool)FIELD_GET(IRDMA_CQ_ERROR, temp);
@@ -3397,7 +3400,7 @@ int irdma_sc_ccq_get_cqe_info(struct irdma_sc_cq *ccq,
33973400
dma_wmb(); /* make sure shadow area is updated before moving tail */
33983401

33993402
IRDMA_RING_MOVE_TAIL(cqp->sq_ring);
3400-
ccq->dev->cqp_cmd_stats[IRDMA_OP_CMPL_CMDS]++;
3403+
atomic64_inc(&cqp->completed_ops);
34013404

34023405
return ret_code;
34033406
}
@@ -4009,13 +4012,17 @@ int irdma_sc_get_next_aeqe(struct irdma_sc_aeq *aeq,
40094012
u8 polarity;
40104013

40114014
aeqe = IRDMA_GET_CURRENT_AEQ_ELEM(aeq);
4012-
get_64bit_val(aeqe, 0, &compl_ctx);
40134015
get_64bit_val(aeqe, 8, &temp);
40144016
polarity = (u8)FIELD_GET(IRDMA_AEQE_VALID, temp);
40154017

40164018
if (aeq->polarity != polarity)
40174019
return -ENOENT;
40184020

4021+
/* Ensure AEQE contents are read after valid bit is checked */
4022+
dma_rmb();
4023+
4024+
get_64bit_val(aeqe, 0, &compl_ctx);
4025+
40194026
print_hex_dump_debug("WQE: AEQ_ENTRY WQE", DUMP_PREFIX_OFFSET, 16, 8,
40204027
aeqe, 16, false);
40214028

drivers/infiniband/hw/irdma/defs.h

Lines changed: 22 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -191,32 +191,30 @@ enum irdma_cqp_op_type {
191191
IRDMA_OP_MANAGE_VF_PBLE_BP = 25,
192192
IRDMA_OP_QUERY_FPM_VAL = 26,
193193
IRDMA_OP_COMMIT_FPM_VAL = 27,
194-
IRDMA_OP_REQ_CMDS = 28,
195-
IRDMA_OP_CMPL_CMDS = 29,
196-
IRDMA_OP_AH_CREATE = 30,
197-
IRDMA_OP_AH_MODIFY = 31,
198-
IRDMA_OP_AH_DESTROY = 32,
199-
IRDMA_OP_MC_CREATE = 33,
200-
IRDMA_OP_MC_DESTROY = 34,
201-
IRDMA_OP_MC_MODIFY = 35,
202-
IRDMA_OP_STATS_ALLOCATE = 36,
203-
IRDMA_OP_STATS_FREE = 37,
204-
IRDMA_OP_STATS_GATHER = 38,
205-
IRDMA_OP_WS_ADD_NODE = 39,
206-
IRDMA_OP_WS_MODIFY_NODE = 40,
207-
IRDMA_OP_WS_DELETE_NODE = 41,
208-
IRDMA_OP_WS_FAILOVER_START = 42,
209-
IRDMA_OP_WS_FAILOVER_COMPLETE = 43,
210-
IRDMA_OP_SET_UP_MAP = 44,
211-
IRDMA_OP_GEN_AE = 45,
212-
IRDMA_OP_QUERY_RDMA_FEATURES = 46,
213-
IRDMA_OP_ALLOC_LOCAL_MAC_ENTRY = 47,
214-
IRDMA_OP_ADD_LOCAL_MAC_ENTRY = 48,
215-
IRDMA_OP_DELETE_LOCAL_MAC_ENTRY = 49,
216-
IRDMA_OP_CQ_MODIFY = 50,
194+
IRDMA_OP_AH_CREATE = 28,
195+
IRDMA_OP_AH_MODIFY = 29,
196+
IRDMA_OP_AH_DESTROY = 30,
197+
IRDMA_OP_MC_CREATE = 31,
198+
IRDMA_OP_MC_DESTROY = 32,
199+
IRDMA_OP_MC_MODIFY = 33,
200+
IRDMA_OP_STATS_ALLOCATE = 34,
201+
IRDMA_OP_STATS_FREE = 35,
202+
IRDMA_OP_STATS_GATHER = 36,
203+
IRDMA_OP_WS_ADD_NODE = 37,
204+
IRDMA_OP_WS_MODIFY_NODE = 38,
205+
IRDMA_OP_WS_DELETE_NODE = 39,
206+
IRDMA_OP_WS_FAILOVER_START = 40,
207+
IRDMA_OP_WS_FAILOVER_COMPLETE = 41,
208+
IRDMA_OP_SET_UP_MAP = 42,
209+
IRDMA_OP_GEN_AE = 43,
210+
IRDMA_OP_QUERY_RDMA_FEATURES = 44,
211+
IRDMA_OP_ALLOC_LOCAL_MAC_ENTRY = 45,
212+
IRDMA_OP_ADD_LOCAL_MAC_ENTRY = 46,
213+
IRDMA_OP_DELETE_LOCAL_MAC_ENTRY = 47,
214+
IRDMA_OP_CQ_MODIFY = 48,
217215

218216
/* Must be last entry*/
219-
IRDMA_MAX_CQP_OPS = 51,
217+
IRDMA_MAX_CQP_OPS = 49,
220218
};
221219

222220
/* CQP SQ WQES */

drivers/infiniband/hw/irdma/hw.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,7 @@ static void irdma_set_flush_fields(struct irdma_sc_qp *qp,
191191
case IRDMA_AE_AMP_MWBIND_INVALID_RIGHTS:
192192
case IRDMA_AE_AMP_MWBIND_BIND_DISABLED:
193193
case IRDMA_AE_AMP_MWBIND_INVALID_BOUNDS:
194+
case IRDMA_AE_AMP_MWBIND_VALID_STAG:
194195
qp->flush_code = FLUSH_MW_BIND_ERR;
195196
qp->event_type = IRDMA_QP_EVENT_ACCESS_ERR;
196197
break;
@@ -2075,7 +2076,7 @@ void irdma_cqp_ce_handler(struct irdma_pci_f *rf, struct irdma_sc_cq *cq)
20752076
cqp_request->compl_info.error = info.error;
20762077

20772078
if (cqp_request->waiting) {
2078-
cqp_request->request_done = true;
2079+
WRITE_ONCE(cqp_request->request_done, true);
20792080
wake_up(&cqp_request->waitq);
20802081
irdma_put_cqp_request(&rf->cqp, cqp_request);
20812082
} else {

drivers/infiniband/hw/irdma/main.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -161,8 +161,8 @@ struct irdma_cqp_request {
161161
void (*callback_fcn)(struct irdma_cqp_request *cqp_request);
162162
void *param;
163163
struct irdma_cqp_compl_info compl_info;
164+
bool request_done; /* READ/WRITE_ONCE macros operate on it */
164165
bool waiting:1;
165-
bool request_done:1;
166166
bool dynamic:1;
167167
};
168168

drivers/infiniband/hw/irdma/puda.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,9 @@ static int irdma_puda_poll_info(struct irdma_sc_cq *cq,
230230
if (valid_bit != cq_uk->polarity)
231231
return -ENOENT;
232232

233+
/* Ensure CQE contents are read after valid bit is checked */
234+
dma_rmb();
235+
233236
if (cq->dev->hw_attrs.uk_attrs.hw_rev >= IRDMA_GEN_2)
234237
ext_valid = (bool)FIELD_GET(IRDMA_CQ_EXTCQE, qword3);
235238

@@ -243,6 +246,9 @@ static int irdma_puda_poll_info(struct irdma_sc_cq *cq,
243246
if (polarity != cq_uk->polarity)
244247
return -ENOENT;
245248

249+
/* Ensure ext CQE contents are read after ext valid bit is checked */
250+
dma_rmb();
251+
246252
IRDMA_RING_MOVE_HEAD_NOCHECK(cq_uk->cq_ring);
247253
if (!IRDMA_RING_CURRENT_HEAD(cq_uk->cq_ring))
248254
cq_uk->polarity = !cq_uk->polarity;

0 commit comments

Comments
 (0)