Skip to content

Commit 6a0b617

Browse files
RajuRangojujgunthorpe
authored andcommitted
rdma/cxgb4: Add support for kernel mode SRQ's
This patch implements the srq specific verbs such as create/destroy/modify and post_srq_recv. And adds srq specific structures and defines to t4.h and uapi. Also updates the cq poll logic to deal with completions that are associated with the SRQ's. This patch also handles kernel mode SRQ_LIMIT events as well as flushed SRQ buffers Signed-off-by: Raju Rangoju <[email protected]> Reviewed-by: Steve Wise <[email protected]> Signed-off-by: Jason Gunthorpe <[email protected]>
1 parent 7fc7a7c commit 6a0b617

File tree

8 files changed

+929
-167
lines changed

8 files changed

+929
-167
lines changed

drivers/infiniband/hw/cxgb4/cm.c

Lines changed: 38 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1853,10 +1853,34 @@ static int rx_data(struct c4iw_dev *dev, struct sk_buff *skb)
18531853
return 0;
18541854
}
18551855

1856+
static void complete_cached_srq_buffers(struct c4iw_ep *ep, u32 srqidx_status)
1857+
{
1858+
enum chip_type adapter_type;
1859+
u32 srqidx;
1860+
u8 status;
1861+
1862+
adapter_type = ep->com.dev->rdev.lldi.adapter_type;
1863+
status = ABORT_RSS_STATUS_G(be32_to_cpu(srqidx_status));
1864+
srqidx = ABORT_RSS_SRQIDX_G(be32_to_cpu(srqidx_status));
1865+
1866+
/*
1867+
* If this TCB had a srq buffer cached, then we must complete
1868+
* it. For user mode, that means saving the srqidx in the
1869+
* user/kernel status page for this qp. For kernel mode, just
1870+
* synthesize the CQE now.
1871+
*/
1872+
if (CHELSIO_CHIP_VERSION(adapter_type) > CHELSIO_T5 && srqidx) {
1873+
if (ep->com.qp->ibqp.uobject)
1874+
t4_set_wq_in_error(&ep->com.qp->wq, srqidx);
1875+
else
1876+
c4iw_flush_srqidx(ep->com.qp, srqidx);
1877+
}
1878+
}
1879+
18561880
static int abort_rpl(struct c4iw_dev *dev, struct sk_buff *skb)
18571881
{
18581882
struct c4iw_ep *ep;
1859-
struct cpl_abort_rpl_rss *rpl = cplhdr(skb);
1883+
struct cpl_abort_rpl_rss6 *rpl = cplhdr(skb);
18601884
int release = 0;
18611885
unsigned int tid = GET_TID(rpl);
18621886

@@ -1865,6 +1889,9 @@ static int abort_rpl(struct c4iw_dev *dev, struct sk_buff *skb)
18651889
pr_warn("Abort rpl to freed endpoint\n");
18661890
return 0;
18671891
}
1892+
1893+
complete_cached_srq_buffers(ep, rpl->srqidx_status);
1894+
18681895
pr_debug("ep %p tid %u\n", ep, ep->hwtid);
18691896
mutex_lock(&ep->com.mutex);
18701897
switch (ep->com.state) {
@@ -2719,28 +2746,35 @@ static int peer_close(struct c4iw_dev *dev, struct sk_buff *skb)
27192746

27202747
static int peer_abort(struct c4iw_dev *dev, struct sk_buff *skb)
27212748
{
2722-
struct cpl_abort_req_rss *req = cplhdr(skb);
2749+
struct cpl_abort_req_rss6 *req = cplhdr(skb);
27232750
struct c4iw_ep *ep;
27242751
struct sk_buff *rpl_skb;
27252752
struct c4iw_qp_attributes attrs;
27262753
int ret;
27272754
int release = 0;
27282755
unsigned int tid = GET_TID(req);
2756+
u8 status;
2757+
27292758
u32 len = roundup(sizeof(struct cpl_abort_rpl), 16);
27302759

27312760
ep = get_ep_from_tid(dev, tid);
27322761
if (!ep)
27332762
return 0;
27342763

2735-
if (cxgb_is_neg_adv(req->status)) {
2764+
status = ABORT_RSS_STATUS_G(be32_to_cpu(req->srqidx_status));
2765+
2766+
if (cxgb_is_neg_adv(status)) {
27362767
pr_debug("Negative advice on abort- tid %u status %d (%s)\n",
2737-
ep->hwtid, req->status, neg_adv_str(req->status));
2768+
ep->hwtid, status, neg_adv_str(status));
27382769
ep->stats.abort_neg_adv++;
27392770
mutex_lock(&dev->rdev.stats.lock);
27402771
dev->rdev.stats.neg_adv++;
27412772
mutex_unlock(&dev->rdev.stats.lock);
27422773
goto deref_ep;
27432774
}
2775+
2776+
complete_cached_srq_buffers(ep, req->srqidx_status);
2777+
27442778
pr_debug("ep %p tid %u state %u\n", ep, ep->hwtid,
27452779
ep->com.state);
27462780
set_bit(PEER_ABORT, &ep->com.history);

drivers/infiniband/hw/cxgb4/cq.c

Lines changed: 120 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@ static int create_cq(struct c4iw_rdev *rdev, struct t4_cq *cq,
182182
return ret;
183183
}
184184

185-
static void insert_recv_cqe(struct t4_wq *wq, struct t4_cq *cq)
185+
static void insert_recv_cqe(struct t4_wq *wq, struct t4_cq *cq, u32 srqidx)
186186
{
187187
struct t4_cqe cqe;
188188

@@ -195,6 +195,8 @@ static void insert_recv_cqe(struct t4_wq *wq, struct t4_cq *cq)
195195
CQE_SWCQE_V(1) |
196196
CQE_QPID_V(wq->sq.qid));
197197
cqe.bits_type_ts = cpu_to_be64(CQE_GENBIT_V((u64)cq->gen));
198+
if (srqidx)
199+
cqe.u.srcqe.abs_rqe_idx = cpu_to_be32(srqidx);
198200
cq->sw_queue[cq->sw_pidx] = cqe;
199201
t4_swcq_produce(cq);
200202
}
@@ -207,7 +209,7 @@ int c4iw_flush_rq(struct t4_wq *wq, struct t4_cq *cq, int count)
207209
pr_debug("wq %p cq %p rq.in_use %u skip count %u\n",
208210
wq, cq, wq->rq.in_use, count);
209211
while (in_use--) {
210-
insert_recv_cqe(wq, cq);
212+
insert_recv_cqe(wq, cq, 0);
211213
flushed++;
212214
}
213215
return flushed;
@@ -458,6 +460,72 @@ void c4iw_count_rcqes(struct t4_cq *cq, struct t4_wq *wq, int *count)
458460
pr_debug("cq %p count %d\n", cq, *count);
459461
}
460462

463+
static void post_pending_srq_wrs(struct t4_srq *srq)
464+
{
465+
struct t4_srq_pending_wr *pwr;
466+
u16 idx = 0;
467+
468+
while (srq->pending_in_use) {
469+
pwr = &srq->pending_wrs[srq->pending_cidx];
470+
srq->sw_rq[srq->pidx].wr_id = pwr->wr_id;
471+
srq->sw_rq[srq->pidx].valid = 1;
472+
473+
pr_debug("%s posting pending cidx %u pidx %u wq_pidx %u in_use %u rq_size %u wr_id %llx\n",
474+
__func__,
475+
srq->cidx, srq->pidx, srq->wq_pidx,
476+
srq->in_use, srq->size,
477+
(unsigned long long)pwr->wr_id);
478+
479+
c4iw_copy_wr_to_srq(srq, &pwr->wqe, pwr->len16);
480+
t4_srq_consume_pending_wr(srq);
481+
t4_srq_produce(srq, pwr->len16);
482+
idx += DIV_ROUND_UP(pwr->len16 * 16, T4_EQ_ENTRY_SIZE);
483+
}
484+
485+
if (idx) {
486+
t4_ring_srq_db(srq, idx, pwr->len16, &pwr->wqe);
487+
srq->queue[srq->size].status.host_wq_pidx =
488+
srq->wq_pidx;
489+
}
490+
}
491+
492+
static u64 reap_srq_cqe(struct t4_cqe *hw_cqe, struct t4_srq *srq)
493+
{
494+
int rel_idx = CQE_ABS_RQE_IDX(hw_cqe) - srq->rqt_abs_idx;
495+
u64 wr_id;
496+
497+
srq->sw_rq[rel_idx].valid = 0;
498+
wr_id = srq->sw_rq[rel_idx].wr_id;
499+
500+
if (rel_idx == srq->cidx) {
501+
pr_debug("%s in order cqe rel_idx %u cidx %u pidx %u wq_pidx %u in_use %u rq_size %u wr_id %llx\n",
502+
__func__, rel_idx, srq->cidx, srq->pidx,
503+
srq->wq_pidx, srq->in_use, srq->size,
504+
(unsigned long long)srq->sw_rq[rel_idx].wr_id);
505+
t4_srq_consume(srq);
506+
while (srq->ooo_count && !srq->sw_rq[srq->cidx].valid) {
507+
pr_debug("%s eat ooo cidx %u pidx %u wq_pidx %u in_use %u rq_size %u ooo_count %u wr_id %llx\n",
508+
__func__, srq->cidx, srq->pidx,
509+
srq->wq_pidx, srq->in_use,
510+
srq->size, srq->ooo_count,
511+
(unsigned long long)
512+
srq->sw_rq[srq->cidx].wr_id);
513+
t4_srq_consume_ooo(srq);
514+
}
515+
if (srq->ooo_count == 0 && srq->pending_in_use)
516+
post_pending_srq_wrs(srq);
517+
} else {
518+
pr_debug("%s ooo cqe rel_idx %u cidx %u pidx %u wq_pidx %u in_use %u rq_size %u ooo_count %u wr_id %llx\n",
519+
__func__, rel_idx, srq->cidx,
520+
srq->pidx, srq->wq_pidx,
521+
srq->in_use, srq->size,
522+
srq->ooo_count,
523+
(unsigned long long)srq->sw_rq[rel_idx].wr_id);
524+
t4_srq_produce_ooo(srq);
525+
}
526+
return wr_id;
527+
}
528+
461529
/*
462530
* poll_cq
463531
*
@@ -475,7 +543,8 @@ void c4iw_count_rcqes(struct t4_cq *cq, struct t4_wq *wq, int *count)
475543
* -EOVERFLOW CQ overflow detected.
476544
*/
477545
static int poll_cq(struct t4_wq *wq, struct t4_cq *cq, struct t4_cqe *cqe,
478-
u8 *cqe_flushed, u64 *cookie, u32 *credit)
546+
u8 *cqe_flushed, u64 *cookie, u32 *credit,
547+
struct t4_srq *srq)
479548
{
480549
int ret = 0;
481550
struct t4_cqe *hw_cqe, read_cqe;
@@ -540,7 +609,7 @@ static int poll_cq(struct t4_wq *wq, struct t4_cq *cq, struct t4_cqe *cqe,
540609
*/
541610
if (CQE_TYPE(hw_cqe) == 1) {
542611
if (CQE_STATUS(hw_cqe))
543-
t4_set_wq_in_error(wq);
612+
t4_set_wq_in_error(wq, 0);
544613
ret = -EAGAIN;
545614
goto skip_cqe;
546615
}
@@ -551,7 +620,7 @@ static int poll_cq(struct t4_wq *wq, struct t4_cq *cq, struct t4_cqe *cqe,
551620
*/
552621
if (CQE_WRID_STAG(hw_cqe) == 1) {
553622
if (CQE_STATUS(hw_cqe))
554-
t4_set_wq_in_error(wq);
623+
t4_set_wq_in_error(wq, 0);
555624
ret = -EAGAIN;
556625
goto skip_cqe;
557626
}
@@ -576,7 +645,7 @@ static int poll_cq(struct t4_wq *wq, struct t4_cq *cq, struct t4_cqe *cqe,
576645

577646
if (CQE_STATUS(hw_cqe) || t4_wq_in_error(wq)) {
578647
*cqe_flushed = (CQE_STATUS(hw_cqe) == T4_ERR_SWFLUSH);
579-
t4_set_wq_in_error(wq);
648+
t4_set_wq_in_error(wq, 0);
580649
}
581650

582651
/*
@@ -590,15 +659,9 @@ static int poll_cq(struct t4_wq *wq, struct t4_cq *cq, struct t4_cqe *cqe,
590659
* then we complete this with T4_ERR_MSN and mark the wq in
591660
* error.
592661
*/
593-
594-
if (t4_rq_empty(wq)) {
595-
t4_set_wq_in_error(wq);
596-
ret = -EAGAIN;
597-
goto skip_cqe;
598-
}
599662
if (unlikely(!CQE_STATUS(hw_cqe) &&
600663
CQE_WRID_MSN(hw_cqe) != wq->rq.msn)) {
601-
t4_set_wq_in_error(wq);
664+
t4_set_wq_in_error(wq, 0);
602665
hw_cqe->header |= cpu_to_be32(CQE_STATUS_V(T4_ERR_MSN));
603666
}
604667
goto proc_cqe;
@@ -657,11 +720,16 @@ static int poll_cq(struct t4_wq *wq, struct t4_cq *cq, struct t4_cqe *cqe,
657720
c4iw_log_wr_stats(wq, hw_cqe);
658721
t4_sq_consume(wq);
659722
} else {
660-
pr_debug("completing rq idx %u\n", wq->rq.cidx);
661-
*cookie = wq->rq.sw_rq[wq->rq.cidx].wr_id;
662-
if (c4iw_wr_log)
663-
c4iw_log_wr_stats(wq, hw_cqe);
664-
t4_rq_consume(wq);
723+
if (!srq) {
724+
pr_debug("completing rq idx %u\n", wq->rq.cidx);
725+
*cookie = wq->rq.sw_rq[wq->rq.cidx].wr_id;
726+
if (c4iw_wr_log)
727+
c4iw_log_wr_stats(wq, hw_cqe);
728+
t4_rq_consume(wq);
729+
} else {
730+
*cookie = reap_srq_cqe(hw_cqe, srq);
731+
}
732+
wq->rq.msn++;
665733
goto skip_cqe;
666734
}
667735

@@ -685,7 +753,7 @@ static int poll_cq(struct t4_wq *wq, struct t4_cq *cq, struct t4_cqe *cqe,
685753
}
686754

687755
static int __c4iw_poll_cq_one(struct c4iw_cq *chp, struct c4iw_qp *qhp,
688-
struct ib_wc *wc)
756+
struct ib_wc *wc, struct c4iw_srq *srq)
689757
{
690758
struct t4_cqe uninitialized_var(cqe);
691759
struct t4_wq *wq = qhp ? &qhp->wq : NULL;
@@ -694,7 +762,8 @@ static int __c4iw_poll_cq_one(struct c4iw_cq *chp, struct c4iw_qp *qhp,
694762
u64 cookie = 0;
695763
int ret;
696764

697-
ret = poll_cq(wq, &(chp->cq), &cqe, &cqe_flushed, &cookie, &credit);
765+
ret = poll_cq(wq, &(chp->cq), &cqe, &cqe_flushed, &cookie, &credit,
766+
srq ? &srq->wq : NULL);
698767
if (ret)
699768
goto out;
700769

@@ -703,6 +772,13 @@ static int __c4iw_poll_cq_one(struct c4iw_cq *chp, struct c4iw_qp *qhp,
703772
wc->vendor_err = CQE_STATUS(&cqe);
704773
wc->wc_flags = 0;
705774

775+
/*
776+
* Simulate a SRQ_LIMIT_REACHED HW notification if required.
777+
*/
778+
if (srq && !(srq->flags & T4_SRQ_LIMIT_SUPPORT) && srq->armed &&
779+
srq->wq.in_use < srq->srq_limit)
780+
c4iw_dispatch_srq_limit_reached_event(srq);
781+
706782
pr_debug("qpid 0x%x type %d opcode %d status 0x%x len %u wrid hi 0x%x lo 0x%x cookie 0x%llx\n",
707783
CQE_QPID(&cqe),
708784
CQE_TYPE(&cqe), CQE_OPCODE(&cqe),
@@ -828,6 +904,7 @@ static int __c4iw_poll_cq_one(struct c4iw_cq *chp, struct c4iw_qp *qhp,
828904
*/
829905
static int c4iw_poll_cq_one(struct c4iw_cq *chp, struct ib_wc *wc)
830906
{
907+
struct c4iw_srq *srq = NULL;
831908
struct c4iw_qp *qhp = NULL;
832909
struct t4_cqe *rd_cqe;
833910
int ret;
@@ -840,10 +917,15 @@ static int c4iw_poll_cq_one(struct c4iw_cq *chp, struct ib_wc *wc)
840917
qhp = get_qhp(chp->rhp, CQE_QPID(rd_cqe));
841918
if (qhp) {
842919
spin_lock(&qhp->lock);
843-
ret = __c4iw_poll_cq_one(chp, qhp, wc);
920+
srq = qhp->srq;
921+
if (srq)
922+
spin_lock(&srq->lock);
923+
ret = __c4iw_poll_cq_one(chp, qhp, wc, srq);
844924
spin_unlock(&qhp->lock);
925+
if (srq)
926+
spin_unlock(&srq->lock);
845927
} else {
846-
ret = __c4iw_poll_cq_one(chp, NULL, wc);
928+
ret = __c4iw_poll_cq_one(chp, NULL, wc, NULL);
847929
}
848930
return ret;
849931
}
@@ -1078,3 +1160,19 @@ int c4iw_arm_cq(struct ib_cq *ibcq, enum ib_cq_notify_flags flags)
10781160
spin_unlock_irqrestore(&chp->lock, flag);
10791161
return ret;
10801162
}
1163+
1164+
void c4iw_flush_srqidx(struct c4iw_qp *qhp, u32 srqidx)
1165+
{
1166+
struct c4iw_cq *rchp = to_c4iw_cq(qhp->ibqp.recv_cq);
1167+
unsigned long flag;
1168+
1169+
/* locking heirarchy: cq lock first, then qp lock. */
1170+
spin_lock_irqsave(&rchp->lock, flag);
1171+
spin_lock(&qhp->lock);
1172+
1173+
/* create a SRQ RECV CQE for srqidx */
1174+
insert_recv_cqe(&qhp->wq, &rchp->cq, srqidx);
1175+
1176+
spin_unlock(&qhp->lock);
1177+
spin_unlock_irqrestore(&rchp->lock, flag);
1178+
}

0 commit comments

Comments
 (0)