Skip to content

Commit 856cc4c

Browse files
mmarcinidledford
authored andcommitted
IB/hfi1: Add the capability for reserved operations
This fix allows for support of in-kernel reserved operations without impacting the ULP user. The low level driver can register a non-zero value which will be transparently added to the send queue size and hidden from the ULP in every respect. ULP post sends will never see a full queue due to a reserved post send and reserved operations will never exceed that registered value. The s_avail will continue to track the ULP swqe availability and the difference between the reserved value and the reserved in use will track reserved availabity. Reviewed-by: Ashutosh Dixit <[email protected]> Signed-off-by: Mike Marciniszyn <[email protected]> Signed-off-by: Dennis Dalessandro <[email protected]> Signed-off-by: Doug Ledford <[email protected]>
1 parent 23002d5 commit 856cc4c

File tree

3 files changed

+113
-23
lines changed

3 files changed

+113
-23
lines changed

drivers/infiniband/sw/rdmavt/qp.c

Lines changed: 62 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -584,6 +584,7 @@ static void rvt_reset_qp(struct rvt_dev_info *rdi, struct rvt_qp *qp,
584584
qp->r_rq.wq->tail = 0;
585585
}
586586
qp->r_sge.num_sge = 0;
587+
atomic_set(&qp->s_reserved_used, 0);
587588
}
588589

589590
/**
@@ -645,7 +646,8 @@ struct ib_qp *rvt_create_qp(struct ib_pd *ibpd,
645646
return ERR_PTR(-EINVAL);
646647
}
647648
sqsize =
648-
init_attr->cap.max_send_wr + 1;
649+
init_attr->cap.max_send_wr + 1 +
650+
rdi->dparms.reserved_operations;
649651
switch (init_attr->qp_type) {
650652
case IB_QPT_SMI:
651653
case IB_QPT_GSI:
@@ -1335,7 +1337,8 @@ int rvt_query_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
13351337
attr->sq_psn = qp->s_next_psn & rdi->dparms.psn_mask;
13361338
attr->dest_qp_num = qp->remote_qpn;
13371339
attr->qp_access_flags = qp->qp_access_flags;
1338-
attr->cap.max_send_wr = qp->s_size - 1;
1340+
attr->cap.max_send_wr = qp->s_size - 1 -
1341+
rdi->dparms.reserved_operations;
13391342
attr->cap.max_recv_wr = qp->ibqp.srq ? 0 : qp->r_rq.size - 1;
13401343
attr->cap.max_send_sge = qp->s_max_sge;
13411344
attr->cap.max_recv_sge = qp->r_rq.max_sge;
@@ -1494,27 +1497,65 @@ static inline int rvt_qp_valid_operation(
14941497
}
14951498

14961499
/**
1497-
* qp_get_savail - return number of avail send entries
1500+
* rvt_qp_is_avail - determine queue capacity
14981501
* @qp - the qp
1502+
* @rdi - the rdmavt device
1503+
* @reserved_op - is reserved operation
14991504
*
15001505
* This assumes the s_hlock is held but the s_last
15011506
* qp variable is uncontrolled.
15021507
*
1503-
* The return is adjusted to not count device specific
1504-
* reserved operations.
1508+
* For non reserved operations, the qp->s_avail
1509+
* may be changed.
1510+
*
1511+
* The return value is zero or a -ENOMEM.
15051512
*/
1506-
static inline u32 qp_get_savail(struct rvt_qp *qp)
1513+
static inline int rvt_qp_is_avail(
1514+
struct rvt_qp *qp,
1515+
struct rvt_dev_info *rdi,
1516+
bool reserved_op)
15071517
{
15081518
u32 slast;
1509-
u32 ret;
1510-
1519+
u32 avail;
1520+
u32 reserved_used;
1521+
1522+
/* see rvt_qp_wqe_unreserve() */
1523+
smp_mb__before_atomic();
1524+
reserved_used = atomic_read(&qp->s_reserved_used);
1525+
if (unlikely(reserved_op)) {
1526+
/* see rvt_qp_wqe_unreserve() */
1527+
smp_mb__before_atomic();
1528+
if (reserved_used >= rdi->dparms.reserved_operations)
1529+
return -ENOMEM;
1530+
return 0;
1531+
}
1532+
/* non-reserved operations */
1533+
if (likely(qp->s_avail))
1534+
return 0;
15111535
smp_read_barrier_depends(); /* see rc.c */
15121536
slast = ACCESS_ONCE(qp->s_last);
15131537
if (qp->s_head >= slast)
1514-
ret = qp->s_size - (qp->s_head - slast);
1538+
avail = qp->s_size - (qp->s_head - slast);
15151539
else
1516-
ret = slast - qp->s_head;
1517-
return ret - 1;
1540+
avail = slast - qp->s_head;
1541+
1542+
/* see rvt_qp_wqe_unreserve() */
1543+
smp_mb__before_atomic();
1544+
reserved_used = atomic_read(&qp->s_reserved_used);
1545+
avail = avail - 1 -
1546+
(rdi->dparms.reserved_operations - reserved_used);
1547+
/* insure we don't assign a negative s_avail */
1548+
if ((s32)avail <= 0)
1549+
return -ENOMEM;
1550+
qp->s_avail = avail;
1551+
if (WARN_ON(qp->s_avail >
1552+
(qp->s_size - 1 - rdi->dparms.reserved_operations)))
1553+
rvt_pr_err(rdi,
1554+
"More avail entries than QP RB size.\nQP: %u, size: %u, avail: %u\nhead: %u, tail: %u, cur: %u, acked: %u, last: %u",
1555+
qp->ibqp.qp_num, qp->s_size, qp->s_avail,
1556+
qp->s_head, qp->s_tail, qp->s_cur,
1557+
qp->s_acked, qp->s_last);
1558+
return 0;
15181559
}
15191560

15201561
/**
@@ -1537,6 +1578,7 @@ static int rvt_post_one_wr(struct rvt_qp *qp,
15371578
u8 log_pmtu;
15381579
int ret;
15391580
size_t cplen;
1581+
bool reserved_op;
15401582

15411583
BUILD_BUG_ON(IB_QPT_MAX >= (sizeof(u32) * BITS_PER_BYTE));
15421584

@@ -1574,18 +1616,12 @@ static int rvt_post_one_wr(struct rvt_qp *qp,
15741616
}
15751617
}
15761618

1619+
reserved_op = rdi->post_parms[wr->opcode].flags &
1620+
RVT_OPERATION_USE_RESERVE;
15771621
/* check for avail */
1578-
if (unlikely(!qp->s_avail)) {
1579-
qp->s_avail = qp_get_savail(qp);
1580-
if (WARN_ON(qp->s_avail > (qp->s_size - 1)))
1581-
rvt_pr_err(rdi,
1582-
"More avail entries than QP RB size.\nQP: %u, size: %u, avail: %u\nhead: %u, tail: %u, cur: %u, acked: %u, last: %u",
1583-
qp->ibqp.qp_num, qp->s_size, qp->s_avail,
1584-
qp->s_head, qp->s_tail, qp->s_cur,
1585-
qp->s_acked, qp->s_last);
1586-
if (!qp->s_avail)
1587-
return -ENOMEM;
1588-
}
1622+
ret = rvt_qp_is_avail(qp, rdi, reserved_op);
1623+
if (ret)
1624+
return ret;
15891625
next = qp->s_head + 1;
15901626
if (next >= qp->s_size)
15911627
next = 0;
@@ -1653,8 +1689,11 @@ static int rvt_post_one_wr(struct rvt_qp *qp,
16531689
qp->s_next_psn = wqe->lpsn + 1;
16541690
}
16551691
trace_rvt_post_one_wr(qp, wqe);
1692+
if (unlikely(reserved_op))
1693+
rvt_qp_wqe_reserve(qp, wqe);
1694+
else
1695+
qp->s_avail--;
16561696
smp_wmb(); /* see request builders */
1657-
qp->s_avail--;
16581697
qp->s_head = next;
16591698

16601699
return 0;

include/rdma/rdma_vt.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,7 @@ struct rvt_driver_params {
158158
u32 max_mad_size;
159159
u8 qos_shift;
160160
u8 max_rdma_atomic;
161+
u8 reserved_operations;
161162
};
162163

163164
/* Protection domain */

include/rdma/rdmavt_qp.h

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,11 @@
144144
#define RVT_PROCESS_OR_FLUSH_SEND \
145145
(RVT_PROCESS_SEND_OK | RVT_FLUSH_SEND)
146146

147+
/*
148+
* Internal send flags
149+
*/
150+
#define RVT_SEND_RESERVE_USED IB_SEND_RESERVED_START
151+
147152
/*
148153
* Send work request queue entry.
149154
* The size of the sg_list is determined when the QP is created and stored
@@ -232,6 +237,7 @@ struct rvt_ack_entry {
232237
#define RVT_OPERATION_ATOMIC 0x00000002
233238
#define RVT_OPERATION_ATOMIC_SGE 0x00000004
234239
#define RVT_OPERATION_LOCAL 0x00000008
240+
#define RVT_OPERATION_USE_RESERVE 0x00000010
235241

236242
#define RVT_OPERATION_MAX (IB_WR_RESERVED10 + 1)
237243

@@ -328,6 +334,7 @@ struct rvt_qp {
328334
u32 s_next_psn; /* PSN for next request */
329335
u32 s_avail; /* number of entries avail */
330336
u32 s_ssn; /* SSN of tail entry */
337+
atomic_t s_reserved_used; /* reserved entries in use */
331338

332339
spinlock_t s_lock ____cacheline_aligned_in_smp;
333340
u32 s_flags;
@@ -459,6 +466,49 @@ static inline struct rvt_rwqe *rvt_get_rwqe_ptr(struct rvt_rq *rq, unsigned n)
459466
rq->max_sge * sizeof(struct ib_sge)) * n);
460467
}
461468

469+
/**
470+
* rvt_qp_wqe_reserve - reserve operation
471+
* @qp - the rvt qp
472+
* @wqe - the send wqe
473+
*
474+
* This routine used in post send to record
475+
* a wqe relative reserved operation use.
476+
*/
477+
static inline void rvt_qp_wqe_reserve(
478+
struct rvt_qp *qp,
479+
struct rvt_swqe *wqe)
480+
{
481+
wqe->wr.send_flags |= RVT_SEND_RESERVE_USED;
482+
atomic_inc(&qp->s_reserved_used);
483+
}
484+
485+
/**
486+
* rvt_qp_wqe_unreserve - clean reserved operation
487+
* @qp - the rvt qp
488+
* @wqe - the send wqe
489+
*
490+
* This decrements the reserve use count.
491+
*
492+
* This call MUST precede the change to
493+
* s_last to insure that post send sees a stable
494+
* s_avail.
495+
*
496+
* An smp_mp__after_atomic() is used to insure
497+
* the compiler does not juggle the order of the s_last
498+
* ring index and the decrementing of s_reserved_used.
499+
*/
500+
static inline void rvt_qp_wqe_unreserve(
501+
struct rvt_qp *qp,
502+
struct rvt_swqe *wqe)
503+
{
504+
if (unlikely(wqe->wr.send_flags & RVT_SEND_RESERVE_USED)) {
505+
wqe->wr.send_flags &= ~RVT_SEND_RESERVE_USED;
506+
atomic_dec(&qp->s_reserved_used);
507+
/* insure no compiler re-order up to s_last change */
508+
smp_mb__after_atomic();
509+
}
510+
}
511+
462512
extern const int ib_rvt_state_ops[];
463513

464514
struct rvt_dev_info;

0 commit comments

Comments
 (0)