rdma/cxgb4: Add support for srq functions & structs

This patch adds kernel mode t4_srq structures and support functions,
uapi structures and defines, as well as firmware work request structures.

Signed-off-by: Raju Rangoju <rajur@chelsio.com>
Reviewed-by: Steve Wise <swise@opengridcomputing.com>
Signed-off-by: Jason Gunthorpe <jgg@mellanox.com>
This commit is contained in:
Raju Rangoju 2018-07-25 21:22:13 +05:30 committed by Jason Gunthorpe
parent 076dd53be5
commit 7fc7a7cffa
4 changed files with 190 additions and 1 deletions

View File

@ -97,6 +97,7 @@ struct c4iw_resource {
struct c4iw_id_table tpt_table;
struct c4iw_id_table qid_table;
struct c4iw_id_table pdid_table;
struct c4iw_id_table srq_table;
};
struct c4iw_qid_list {
@ -130,6 +131,8 @@ struct c4iw_stats {
struct c4iw_stat stag;
struct c4iw_stat pbl;
struct c4iw_stat rqt;
struct c4iw_stat srqt;
struct c4iw_stat srq;
struct c4iw_stat ocqp;
u64 db_full;
u64 db_empty;
@ -549,6 +552,7 @@ struct c4iw_qp {
struct kref kref;
wait_queue_head_t wait;
int sq_sig_all;
struct c4iw_srq *srq;
struct work_struct free_work;
struct c4iw_ucontext *ucontext;
struct c4iw_wr_wait *wr_waitp;
@ -559,6 +563,26 @@ static inline struct c4iw_qp *to_c4iw_qp(struct ib_qp *ibqp)
return container_of(ibqp, struct c4iw_qp, ibqp);
}
struct c4iw_srq {
struct ib_srq ibsrq;
struct list_head db_fc_entry;
struct c4iw_dev *rhp;
struct t4_srq wq;
struct sk_buff *destroy_skb;
u32 srq_limit;
u32 pdid;
int idx;
u32 flags;
spinlock_t lock; /* protects srq */
struct c4iw_wr_wait *wr_waitp;
bool armed;
};
static inline struct c4iw_srq *to_c4iw_srq(struct ib_srq *ibsrq)
{
return container_of(ibsrq, struct c4iw_srq, ibsrq);
}
struct c4iw_ucontext {
struct ib_ucontext ibucontext;
struct c4iw_dev_ucontext uctx;
@ -1040,6 +1064,13 @@ struct ib_cq *c4iw_create_cq(struct ib_device *ibdev,
struct ib_udata *udata);
int c4iw_resize_cq(struct ib_cq *cq, int cqe, struct ib_udata *udata);
int c4iw_arm_cq(struct ib_cq *ibcq, enum ib_cq_notify_flags flags);
int c4iw_modify_srq(struct ib_srq *ib_srq, struct ib_srq_attr *attr,
enum ib_srq_attr_mask srq_attr_mask,
struct ib_udata *udata);
int c4iw_destroy_srq(struct ib_srq *ib_srq);
struct ib_srq *c4iw_create_srq(struct ib_pd *pd,
struct ib_srq_init_attr *attrs,
struct ib_udata *udata);
int c4iw_destroy_qp(struct ib_qp *ib_qp);
struct ib_qp *c4iw_create_qp(struct ib_pd *pd,
struct ib_qp_init_attr *attrs,
@ -1076,12 +1107,19 @@ extern c4iw_handler_func c4iw_handlers[NUM_CPL_CMDS];
void __iomem *c4iw_bar2_addrs(struct c4iw_rdev *rdev, unsigned int qid,
enum cxgb4_bar2_qtype qtype,
unsigned int *pbar2_qid, u64 *pbar2_pa);
int c4iw_alloc_srq_idx(struct c4iw_rdev *rdev);
void c4iw_free_srq_idx(struct c4iw_rdev *rdev, int idx);
extern void c4iw_log_wr_stats(struct t4_wq *wq, struct t4_cqe *cqe);
extern int c4iw_wr_log;
extern int db_fc_threshold;
extern int db_coalescing_threshold;
extern int use_dsgl;
void c4iw_invalidate_mr(struct c4iw_dev *rhp, u32 rkey);
void c4iw_dispatch_srq_limit_reached_event(struct c4iw_srq *srq);
void c4iw_copy_wr_to_srq(struct t4_srq *srq, union t4_recv_wr *wqe, u8 len16);
void c4iw_flush_srqidx(struct c4iw_qp *qhp, u32 srqidx);
int c4iw_post_srq_recv(struct ib_srq *ibsrq, struct ib_recv_wr *wr,
struct ib_recv_wr **bad_wr);
struct c4iw_wr_wait *c4iw_alloc_wr_wait(gfp_t gfp);
typedef int c4iw_restrack_func(struct sk_buff *msg,

View File

@ -52,12 +52,16 @@ struct t4_status_page {
__be16 pidx;
u8 qp_err; /* flit 1 - sw owns */
u8 db_off;
u8 pad;
u8 pad[2];
u16 host_wq_pidx;
u16 host_cidx;
u16 host_pidx;
u16 pad2;
u32 srqidx;
};
#define T4_RQT_ENTRY_SHIFT 6
#define T4_RQT_ENTRY_SIZE BIT(T4_RQT_ENTRY_SHIFT)
#define T4_EQ_ENTRY_SIZE 64
#define T4_SQ_NUM_SLOTS 5
@ -248,6 +252,7 @@ struct t4_cqe {
/* used for RQ completion processing */
#define CQE_WRID_STAG(x) (be32_to_cpu((x)->u.rcqe.stag))
#define CQE_WRID_MSN(x) (be32_to_cpu((x)->u.rcqe.msn))
#define CQE_ABS_RQE_IDX(x) (be32_to_cpu((x)->u.srcqe.abs_rqe_idx))
/* used for SQ completion processing */
#define CQE_WRID_SQ_IDX(x) ((x)->u.scqe.cidx)
@ -331,6 +336,7 @@ struct t4_swrqe {
u64 wr_id;
ktime_t host_time;
u64 sge_ts;
int valid;
};
struct t4_rq {
@ -360,8 +366,98 @@ struct t4_wq {
void __iomem *db;
struct c4iw_rdev *rdev;
int flushed;
u8 *qp_errp;
u32 *srqidxp;
};
struct t4_srq_pending_wr {
u64 wr_id;
union t4_recv_wr wqe;
u8 len16;
};
struct t4_srq {
union t4_recv_wr *queue;
dma_addr_t dma_addr;
DECLARE_PCI_UNMAP_ADDR(mapping);
struct t4_swrqe *sw_rq;
void __iomem *bar2_va;
u64 bar2_pa;
size_t memsize;
u32 bar2_qid;
u32 qid;
u32 msn;
u32 rqt_hwaddr;
u32 rqt_abs_idx;
u16 rqt_size;
u16 size;
u16 cidx;
u16 pidx;
u16 wq_pidx;
u16 wq_pidx_inc;
u16 in_use;
struct t4_srq_pending_wr *pending_wrs;
u16 pending_cidx;
u16 pending_pidx;
u16 pending_in_use;
u16 ooo_count;
};
static inline u32 t4_srq_avail(struct t4_srq *srq)
{
return srq->size - 1 - srq->in_use;
}
static inline void t4_srq_produce(struct t4_srq *srq, u8 len16)
{
srq->in_use++;
if (++srq->pidx == srq->size)
srq->pidx = 0;
srq->wq_pidx += DIV_ROUND_UP(len16 * 16, T4_EQ_ENTRY_SIZE);
if (srq->wq_pidx >= srq->size * T4_RQ_NUM_SLOTS)
srq->wq_pidx %= srq->size * T4_RQ_NUM_SLOTS;
srq->queue[srq->size].status.host_pidx = srq->pidx;
}
static inline void t4_srq_produce_pending_wr(struct t4_srq *srq)
{
srq->pending_in_use++;
srq->in_use++;
if (++srq->pending_pidx == srq->size)
srq->pending_pidx = 0;
}
static inline void t4_srq_consume_pending_wr(struct t4_srq *srq)
{
srq->pending_in_use--;
srq->in_use--;
if (++srq->pending_cidx == srq->size)
srq->pending_cidx = 0;
}
static inline void t4_srq_produce_ooo(struct t4_srq *srq)
{
srq->in_use--;
srq->ooo_count++;
}
static inline void t4_srq_consume_ooo(struct t4_srq *srq)
{
srq->cidx++;
if (srq->cidx == srq->size)
srq->cidx = 0;
srq->queue[srq->size].status.host_cidx = srq->cidx;
srq->ooo_count--;
}
static inline void t4_srq_consume(struct t4_srq *srq)
{
srq->in_use--;
if (++srq->cidx == srq->size)
srq->cidx = 0;
srq->queue[srq->size].status.host_cidx = srq->cidx;
}
static inline int t4_rqes_posted(struct t4_wq *wq)
{
return wq->rq.in_use;
@ -475,6 +571,25 @@ static inline void pio_copy(u64 __iomem *dst, u64 *src)
}
}
static inline void t4_ring_srq_db(struct t4_srq *srq, u16 inc, u8 len16,
union t4_recv_wr *wqe)
{
/* Flush host queue memory writes. */
wmb();
if (inc == 1 && srq->bar2_qid == 0 && wqe) {
pr_debug("%s : WC srq->pidx = %d; len16=%d\n",
__func__, srq->pidx, len16);
pio_copy(srq->bar2_va + SGE_UDB_WCDOORBELL, (u64 *)wqe);
} else {
pr_debug("%s: DB srq->pidx = %d; len16=%d\n",
__func__, srq->pidx, len16);
writel(PIDX_T5_V(inc) | QID_V(srq->bar2_qid),
srq->bar2_va + SGE_UDB_KDOORBELL);
}
/* Flush user doorbell area writes. */
wmb();
}
static inline void t4_ring_sq_db(struct t4_wq *wq, u16 inc, union t4_wr *wqe)
{

View File

@ -263,6 +263,7 @@ enum fw_ri_res_type {
FW_RI_RES_TYPE_SQ,
FW_RI_RES_TYPE_RQ,
FW_RI_RES_TYPE_CQ,
FW_RI_RES_TYPE_SRQ,
};
enum fw_ri_res_op {
@ -296,6 +297,20 @@ struct fw_ri_res {
__be32 r6_lo;
__be64 r7;
} cq;
struct fw_ri_res_srq {
__u8 restype;
__u8 op;
__be16 r3;
__be32 eqid;
__be32 r4[2];
__be32 fetchszm_to_iqid;
__be32 dcaen_to_eqsize;
__be64 eqaddr;
__be32 srqid;
__be32 pdid;
__be32 hwsrqsize;
__be32 hwsrqaddr;
} srq;
} u;
};
@ -707,6 +722,10 @@ enum fw_ri_init_p2ptype {
FW_RI_INIT_P2PTYPE_DISABLED = 0xf,
};
enum fw_ri_init_rqeqid_srq {
FW_RI_INIT_RQEQID_SRQ = 1 << 31,
};
struct fw_ri_wr {
__be32 op_compl;
__be32 flowid_len16;

View File

@ -84,6 +84,23 @@ struct c4iw_create_qp_resp {
__u32 flags;
};
struct c4iw_create_srq_resp {
__aligned_u64 srq_key;
__aligned_u64 srq_db_gts_key;
__aligned_u64 srq_memsize;
__u32 srqid;
__u32 srq_size;
__u32 rqt_abs_idx;
__u32 qid_mask;
__u32 flags;
__u32 reserved; /* explicit padding */
};
enum {
/* HW supports SRQ_LIMIT_REACHED event */
T4_SRQ_LIMIT_SUPPORT = 1 << 0,
};
struct c4iw_alloc_ucontext_resp {
__aligned_u64 status_page_key;
__u32 status_page_size;