Skip to content

Commit 10467ce

Browse files
tatyana-enjgunthorpe
authored andcommitted
RDMA/irdma: Don't arm the CQ more than two times if no CE for this CQ
Completion events (CEs) are lost if the application is allowed to arm the CQ more than two times when no new CE for this CQ has been generated by the HW. Check if arming has been done for the CQ and if not, arm the CQ for any event otherwise promote to arm the CQ for any event only when the last arm event was solicited. Fixes: b48c24c ("RDMA/irdma: Implement device supported verb APIs") Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Tatyana Nikolova <[email protected]> Signed-off-by: Shiraz Saleem <[email protected]> Signed-off-by: Jason Gunthorpe <[email protected]>
1 parent 25b5d6f commit 10467ce

File tree

5 files changed

+38
-5
lines changed

5 files changed

+38
-5
lines changed

drivers/infiniband/hw/irdma/hw.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,8 @@ static void irdma_iwarp_ce_handler(struct irdma_sc_cq *iwcq)
6060
{
6161
struct irdma_cq *cq = iwcq->back_cq;
6262

63+
if (!cq->user_mode)
64+
cq->armed = false;
6365
if (cq->ibcq.comp_handler)
6466
cq->ibcq.comp_handler(&cq->ibcq, cq->ibcq.cq_context);
6567
}

drivers/infiniband/hw/irdma/main.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -542,6 +542,7 @@ int irdma_ah_cqp_op(struct irdma_pci_f *rf, struct irdma_sc_ah *sc_ah, u8 cmd,
542542
void (*callback_fcn)(struct irdma_cqp_request *cqp_request),
543543
void *cb_param);
544544
void irdma_gsi_ud_qp_ah_cb(struct irdma_cqp_request *cqp_request);
545+
bool irdma_cq_empty(struct irdma_cq *iwcq);
545546
int irdma_inetaddr_event(struct notifier_block *notifier, unsigned long event,
546547
void *ptr);
547548
int irdma_inet6addr_event(struct notifier_block *notifier, unsigned long event,

drivers/infiniband/hw/irdma/utils.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2486,3 +2486,18 @@ void irdma_ib_qp_event(struct irdma_qp *iwqp, enum irdma_qp_event_type event)
24862486
ibevent.element.qp = &iwqp->ibqp;
24872487
iwqp->ibqp.event_handler(&ibevent, iwqp->ibqp.qp_context);
24882488
}
2489+
2490+
bool irdma_cq_empty(struct irdma_cq *iwcq)
2491+
{
2492+
struct irdma_cq_uk *ukcq;
2493+
u64 qword3;
2494+
__le64 *cqe;
2495+
u8 polarity;
2496+
2497+
ukcq = &iwcq->sc_cq.cq_uk;
2498+
cqe = IRDMA_GET_CURRENT_CQ_ELEM(ukcq);
2499+
get_64bit_val(cqe, 24, &qword3);
2500+
polarity = (u8)FIELD_GET(IRDMA_CQ_VALID, qword3);
2501+
2502+
return polarity != ukcq->polarity;
2503+
}

drivers/infiniband/hw/irdma/verbs.c

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3584,18 +3584,31 @@ static int irdma_req_notify_cq(struct ib_cq *ibcq,
35843584
struct irdma_cq *iwcq;
35853585
struct irdma_cq_uk *ukcq;
35863586
unsigned long flags;
3587-
enum irdma_cmpl_notify cq_notify = IRDMA_CQ_COMPL_EVENT;
3587+
enum irdma_cmpl_notify cq_notify;
3588+
bool promo_event = false;
3589+
int ret = 0;
35883590

3591+
cq_notify = notify_flags == IB_CQ_SOLICITED ?
3592+
IRDMA_CQ_COMPL_SOLICITED : IRDMA_CQ_COMPL_EVENT;
35893593
iwcq = to_iwcq(ibcq);
35903594
ukcq = &iwcq->sc_cq.cq_uk;
3591-
if (notify_flags == IB_CQ_SOLICITED)
3592-
cq_notify = IRDMA_CQ_COMPL_SOLICITED;
35933595

35943596
spin_lock_irqsave(&iwcq->lock, flags);
3595-
irdma_uk_cq_request_notification(ukcq, cq_notify);
3597+
/* Only promote to arm the CQ for any event if the last arm event was solicited. */
3598+
if (iwcq->last_notify == IRDMA_CQ_COMPL_SOLICITED && notify_flags != IB_CQ_SOLICITED)
3599+
promo_event = true;
3600+
3601+
if (!iwcq->armed || promo_event) {
3602+
iwcq->armed = true;
3603+
iwcq->last_notify = cq_notify;
3604+
irdma_uk_cq_request_notification(ukcq, cq_notify);
3605+
}
3606+
3607+
if ((notify_flags & IB_CQ_REPORT_MISSED_EVENTS) && !irdma_cq_empty(iwcq))
3608+
ret = 1;
35963609
spin_unlock_irqrestore(&iwcq->lock, flags);
35973610

3598-
return 0;
3611+
return ret;
35993612
}
36003613

36013614
static int irdma_roce_port_immutable(struct ib_device *ibdev, u32 port_num,

drivers/infiniband/hw/irdma/verbs.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,8 @@ struct irdma_cq {
110110
u16 cq_size;
111111
u16 cq_num;
112112
bool user_mode;
113+
bool armed;
114+
enum irdma_cmpl_notify last_notify;
113115
u32 polled_cmpls;
114116
u32 cq_mem_size;
115117
struct irdma_dma_mem kmem;

0 commit comments

Comments
 (0)