diff options
Diffstat (limited to 'drivers/infiniband/hw/ionic/ionic_ibdev.h')
| -rw-r--r-- | drivers/infiniband/hw/ionic/ionic_ibdev.h | 517 | 
1 files changed, 517 insertions, 0 deletions
diff --git a/drivers/infiniband/hw/ionic/ionic_ibdev.h b/drivers/infiniband/hw/ionic/ionic_ibdev.h new file mode 100644 index 000000000000..82fda1e3cdb6 --- /dev/null +++ b/drivers/infiniband/hw/ionic/ionic_ibdev.h @@ -0,0 +1,517 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright (C) 2018-2025, Advanced Micro Devices, Inc. */ + +#ifndef _IONIC_IBDEV_H_ +#define _IONIC_IBDEV_H_ + +#include <rdma/ib_umem.h> +#include <rdma/ib_verbs.h> +#include <rdma/ib_pack.h> +#include <rdma/uverbs_ioctl.h> + +#include <rdma/ionic-abi.h> +#include <ionic_api.h> +#include <ionic_regs.h> + +#include "ionic_fw.h" +#include "ionic_queue.h" +#include "ionic_res.h" + +#include "ionic_lif_cfg.h" + +/* Config knobs */ +#define IONIC_EQ_DEPTH 511 +#define IONIC_EQ_COUNT 32 +#define IONIC_AQ_DEPTH 63 +#define IONIC_AQ_COUNT 4 +#define IONIC_EQ_ISR_BUDGET 10 +#define IONIC_EQ_WORK_BUDGET 1000 +#define IONIC_MAX_RD_ATOM 16 +#define IONIC_PKEY_TBL_LEN 1 +#define IONIC_GID_TBL_LEN 256 + +#define IONIC_MAX_QPID 0xffffff +#define IONIC_SPEC_HIGH 8 +#define IONIC_MAX_PD 1024 +#define IONIC_SPEC_HIGH 8 +#define IONIC_SQCMB_ORDER 5 +#define IONIC_RQCMB_ORDER 0 + +#define IONIC_META_LAST		((void *)1ul) +#define IONIC_META_POSTED	((void *)2ul) + +#define IONIC_CQ_GRACE 100 + +#define IONIC_ROCE_UDP_SPORT	28272 +#define IONIC_DMA_LKEY		0 +#define IONIC_DMA_RKEY		IONIC_DMA_LKEY + +#define IONIC_CMB_SUPPORTED \ +	(IONIC_CMB_ENABLE | IONIC_CMB_REQUIRE | IONIC_CMB_EXPDB | \ +	 IONIC_CMB_WC | IONIC_CMB_UC) + +/* resource is not reserved on the device, indicated in tbl_order */ +#define IONIC_RES_INVALID	-1 + +struct ionic_aq; +struct ionic_cq; +struct ionic_eq; +struct ionic_vcq; + +enum ionic_admin_state { +	IONIC_ADMIN_ACTIVE, /* submitting admin commands to queue */ +	IONIC_ADMIN_PAUSED, /* not submitting, but may complete normally */ +	IONIC_ADMIN_KILLED, /* not submitting, locally completed */ +}; + +enum ionic_admin_flags { +	IONIC_ADMIN_F_BUSYWAIT  = BIT(0),	/* Don't sleep */ +	IONIC_ADMIN_F_TEARDOWN  = BIT(1),	/* In destroy path */ +	IONIC_ADMIN_F_INTERRUPT = BIT(2),	/* Interruptible w/timeout */ +}; + +enum ionic_mmap_flag { +	IONIC_MMAP_WC = BIT(0), +}; + +struct ionic_mmap_entry { +	struct rdma_user_mmap_entry rdma_entry; +	unsigned long size; +	unsigned long pfn; +	u8 mmap_flags; +}; + +struct ionic_ibdev { +	struct ib_device	ibdev; + +	struct ionic_lif_cfg	lif_cfg; + +	struct xarray		qp_tbl; +	struct xarray		cq_tbl; + +	struct ionic_resid_bits	inuse_dbid; +	struct ionic_resid_bits	inuse_pdid; +	struct ionic_resid_bits	inuse_ahid; +	struct ionic_resid_bits	inuse_mrid; +	struct ionic_resid_bits	inuse_qpid; +	struct ionic_resid_bits	inuse_cqid; + +	u8			half_cqid_udma_shift; +	u8			half_qpid_udma_shift; +	u8			next_qpid_udma_idx; +	u8			next_mrkey; + +	struct work_struct	reset_work; +	bool			reset_posted; +	u32			reset_cnt; + +	struct delayed_work	admin_dwork; +	struct ionic_aq		**aq_vec; +	atomic_t		admin_state; + +	struct ionic_eq		**eq_vec; + +	struct ionic_v1_stat	*hw_stats; +	void			*hw_stats_buf; +	struct rdma_stat_desc	*hw_stats_hdrs; +	struct ionic_counter_stats *counter_stats; +	int			hw_stats_count; +}; + +struct ionic_eq { +	struct ionic_ibdev	*dev; + +	u32			eqid; +	u32			intr; + +	struct ionic_queue	q; + +	int			armed; +	bool			enable; + +	struct work_struct	work; + +	int			irq; +	char			name[32]; +}; + +struct ionic_admin_wr { +	struct completion		work; +	struct list_head		aq_ent; +	struct ionic_v1_admin_wqe	wqe; +	struct ionic_v1_cqe		cqe; +	struct ionic_aq			*aq; +	int				status; +}; + +struct ionic_admin_wr_q { +	struct ionic_admin_wr	*wr; +	int			wqe_strides; +}; + +struct ionic_aq { +	struct ionic_ibdev	*dev; +	struct ionic_vcq	*vcq; + +	struct work_struct	work; + +	atomic_t		admin_state; +	unsigned long		stamp; +	bool			armed; + +	u32			aqid; +	u32			cqid; + +	spinlock_t		lock; /* for posting */ +	struct ionic_queue	q; +	struct ionic_admin_wr_q	*q_wr; +	struct list_head	wr_prod; +	struct list_head	wr_post; +}; + +struct ionic_ctx { +	struct ib_ucontext	ibctx; +	u32			dbid; +	struct rdma_user_mmap_entry	*mmap_dbell; +}; + +struct ionic_tbl_buf { +	u32		tbl_limit; +	u32		tbl_pages; +	size_t		tbl_size; +	__le64		*tbl_buf; +	dma_addr_t	tbl_dma; +	u8		page_size_log2; +}; + +struct ionic_pd { +	struct ib_pd		ibpd; + +	u32			pdid; +	u32			flags; +}; + +struct ionic_cq { +	struct ionic_vcq	*vcq; + +	u32			cqid; +	u32			eqid; + +	spinlock_t		lock; /* for polling */ +	struct list_head	poll_sq; +	bool			flush; +	struct list_head	flush_sq; +	struct list_head	flush_rq; +	struct list_head	ibkill_flush_ent; + +	struct ionic_queue	q; +	bool			color; +	int			credit; +	u16			arm_any_prod; +	u16			arm_sol_prod; + +	struct kref		cq_kref; +	struct completion	cq_rel_comp; + +	/* infrequently accessed, keep at end */ +	struct ib_umem		*umem; +}; + +struct ionic_vcq { +	struct ib_cq		ibcq; +	struct ionic_cq		cq[2]; +	u8			udma_mask; +	u8			poll_idx; +}; + +struct ionic_sq_meta { +	u64			wrid; +	u32			len; +	u16			seq; +	u8			ibop; +	u8			ibsts; +	u8			remote:1; +	u8			signal:1; +	u8			local_comp:1; +}; + +struct ionic_rq_meta { +	struct ionic_rq_meta	*next; +	u64			wrid; +}; + +struct ionic_qp { +	struct ib_qp		ibqp; +	enum ib_qp_state	state; + +	u32			qpid; +	u32			ahid; +	u32			sq_cqid; +	u32			rq_cqid; +	u8			udma_idx; +	u8			has_ah:1; +	u8			has_sq:1; +	u8			has_rq:1; +	u8			sig_all:1; + +	struct list_head	qp_list_counter; + +	struct list_head	cq_poll_sq; +	struct list_head	cq_flush_sq; +	struct list_head	cq_flush_rq; +	struct list_head	ibkill_flush_ent; + +	spinlock_t		sq_lock; /* for posting and polling */ +	struct ionic_queue	sq; +	struct ionic_sq_meta	*sq_meta; +	u16			*sq_msn_idx; +	int			sq_spec; +	u16			sq_old_prod; +	u16			sq_msn_prod; +	u16			sq_msn_cons; +	u8			sq_cmb; +	bool			sq_flush; +	bool			sq_flush_rcvd; + +	spinlock_t		rq_lock; /* for posting and polling */ +	struct ionic_queue	rq; +	struct ionic_rq_meta	*rq_meta; +	struct ionic_rq_meta	*rq_meta_head; +	int			rq_spec; +	u16			rq_old_prod; +	u8			rq_cmb; +	bool			rq_flush; + +	struct kref		qp_kref; +	struct completion	qp_rel_comp; + +	/* infrequently accessed, keep at end */ +	int			sgid_index; +	int			sq_cmb_order; +	u32			sq_cmb_pgid; +	phys_addr_t		sq_cmb_addr; +	struct rdma_user_mmap_entry *mmap_sq_cmb; + +	struct ib_umem		*sq_umem; + +	int			rq_cmb_order; +	u32			rq_cmb_pgid; +	phys_addr_t		rq_cmb_addr; +	struct rdma_user_mmap_entry *mmap_rq_cmb; + +	struct ib_umem		*rq_umem; + +	int			dcqcn_profile; + +	struct ib_ud_header	*hdr; +}; + +struct ionic_ah { +	struct ib_ah		ibah; +	u32			ahid; +	int			sgid_index; +	struct ib_ud_header	hdr; +}; + +struct ionic_mr { +	union { +		struct ib_mr	ibmr; +		struct ib_mw	ibmw; +	}; + +	u32			mrid; +	int			flags; + +	struct ib_umem		*umem; +	struct ionic_tbl_buf	buf; +	bool			created; +}; + +struct ionic_counter_stats { +	int queue_stats_count; +	struct ionic_v1_stat *hdr; +	struct rdma_stat_desc *stats_hdrs; +	struct xarray xa_counters; +}; + +struct ionic_counter { +	void *vals; +	struct list_head qp_list; +}; + +static inline struct ionic_ibdev *to_ionic_ibdev(struct ib_device *ibdev) +{ +	return container_of(ibdev, struct ionic_ibdev, ibdev); +} + +static inline struct ionic_ctx *to_ionic_ctx(struct ib_ucontext *ibctx) +{ +	return container_of(ibctx, struct ionic_ctx, ibctx); +} + +static inline struct ionic_ctx *to_ionic_ctx_uobj(struct ib_uobject *uobj) +{ +	if (!uobj) +		return NULL; + +	if (!uobj->context) +		return NULL; + +	return to_ionic_ctx(uobj->context); +} + +static inline struct ionic_pd *to_ionic_pd(struct ib_pd *ibpd) +{ +	return container_of(ibpd, struct ionic_pd, ibpd); +} + +static inline struct ionic_mr *to_ionic_mr(struct ib_mr *ibmr) +{ +	return container_of(ibmr, struct ionic_mr, ibmr); +} + +static inline struct ionic_mr *to_ionic_mw(struct ib_mw *ibmw) +{ +	return container_of(ibmw, struct ionic_mr, ibmw); +} + +static inline struct ionic_vcq *to_ionic_vcq(struct ib_cq *ibcq) +{ +	return container_of(ibcq, struct ionic_vcq, ibcq); +} + +static inline struct ionic_cq *to_ionic_vcq_cq(struct ib_cq *ibcq, +					       uint8_t udma_idx) +{ +	return &to_ionic_vcq(ibcq)->cq[udma_idx]; +} + +static inline struct ionic_qp *to_ionic_qp(struct ib_qp *ibqp) +{ +	return container_of(ibqp, struct ionic_qp, ibqp); +} + +static inline struct ionic_ah *to_ionic_ah(struct ib_ah *ibah) +{ +	return container_of(ibah, struct ionic_ah, ibah); +} + +static inline u32 ionic_ctx_dbid(struct ionic_ibdev *dev, +				 struct ionic_ctx *ctx) +{ +	if (!ctx) +		return dev->lif_cfg.dbid; + +	return ctx->dbid; +} + +static inline u32 ionic_obj_dbid(struct ionic_ibdev *dev, +				 struct ib_uobject *uobj) +{ +	return ionic_ctx_dbid(dev, to_ionic_ctx_uobj(uobj)); +} + +static inline bool ionic_ibop_is_local(enum ib_wr_opcode op) +{ +	return op == IB_WR_LOCAL_INV || op == IB_WR_REG_MR; +} + +static inline void ionic_qp_complete(struct kref *kref) +{ +	struct ionic_qp *qp = container_of(kref, struct ionic_qp, qp_kref); + +	complete(&qp->qp_rel_comp); +} + +static inline void ionic_cq_complete(struct kref *kref) +{ +	struct ionic_cq *cq = container_of(kref, struct ionic_cq, cq_kref); + +	complete(&cq->cq_rel_comp); +} + +/* ionic_admin.c */ +extern struct workqueue_struct *ionic_evt_workq; +void ionic_admin_post(struct ionic_ibdev *dev, struct ionic_admin_wr *wr); +int ionic_admin_wait(struct ionic_ibdev *dev, struct ionic_admin_wr *wr, +		     enum ionic_admin_flags); + +int ionic_rdma_reset_devcmd(struct ionic_ibdev *dev); + +int ionic_create_rdma_admin(struct ionic_ibdev *dev); +void ionic_destroy_rdma_admin(struct ionic_ibdev *dev); +void ionic_kill_rdma_admin(struct ionic_ibdev *dev, bool fatal_path); + +/* ionic_controlpath.c */ +int ionic_create_cq_common(struct ionic_vcq *vcq, +			   struct ionic_tbl_buf *buf, +			   const struct ib_cq_init_attr *attr, +			   struct ionic_ctx *ctx, +			   struct ib_udata *udata, +			   struct ionic_qdesc *req_cq, +			   __u32 *resp_cqid, +			   int udma_idx); +void ionic_destroy_cq_common(struct ionic_ibdev *dev, struct ionic_cq *cq); +void ionic_flush_qp(struct ionic_ibdev *dev, struct ionic_qp *qp); +void ionic_notify_flush_cq(struct ionic_cq *cq); + +int ionic_alloc_ucontext(struct ib_ucontext *ibctx, struct ib_udata *udata); +void ionic_dealloc_ucontext(struct ib_ucontext *ibctx); +int ionic_mmap(struct ib_ucontext *ibctx, struct vm_area_struct *vma); +void ionic_mmap_free(struct rdma_user_mmap_entry *rdma_entry); +int ionic_alloc_pd(struct ib_pd *ibpd, struct ib_udata *udata); +int ionic_dealloc_pd(struct ib_pd *ibpd, struct ib_udata *udata); +int ionic_create_ah(struct ib_ah *ibah, struct rdma_ah_init_attr *init_attr, +		    struct ib_udata *udata); +int ionic_query_ah(struct ib_ah *ibah, struct rdma_ah_attr *ah_attr); +int ionic_destroy_ah(struct ib_ah *ibah, u32 flags); +struct ib_mr *ionic_get_dma_mr(struct ib_pd *ibpd, int access); +struct ib_mr *ionic_reg_user_mr(struct ib_pd *ibpd, u64 start, u64 length, +				u64 addr, int access, struct ib_dmah *dmah, +				struct ib_udata *udata); +struct ib_mr *ionic_reg_user_mr_dmabuf(struct ib_pd *ibpd, u64 offset, +				       u64 length, u64 addr, int fd, int access, +					   struct ib_dmah *dmah, +				       struct uverbs_attr_bundle *attrs); +int ionic_dereg_mr(struct ib_mr *ibmr, struct ib_udata *udata); +struct ib_mr *ionic_alloc_mr(struct ib_pd *ibpd, enum ib_mr_type type, +			     u32 max_sg); +int ionic_map_mr_sg(struct ib_mr *ibmr, struct scatterlist *sg, int sg_nents, +		    unsigned int *sg_offset); +int ionic_alloc_mw(struct ib_mw *ibmw, struct ib_udata *udata); +int ionic_dealloc_mw(struct ib_mw *ibmw); +int ionic_create_cq(struct ib_cq *ibcq, const struct ib_cq_init_attr *attr, +		    struct uverbs_attr_bundle *attrs); +int ionic_destroy_cq(struct ib_cq *ibcq, struct ib_udata *udata); +int ionic_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *attr, +		    struct ib_udata *udata); +int ionic_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int mask, +		    struct ib_udata *udata); +int ionic_query_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int mask, +		   struct ib_qp_init_attr *init_attr); +int ionic_destroy_qp(struct ib_qp *ibqp, struct ib_udata *udata); + +/* ionic_datapath.c */ +int ionic_post_send(struct ib_qp *ibqp, const struct ib_send_wr *wr, +		    const struct ib_send_wr **bad); +int ionic_post_recv(struct ib_qp *ibqp, const struct ib_recv_wr *wr, +		    const struct ib_recv_wr **bad); +int ionic_poll_cq(struct ib_cq *ibcq, int nwc, struct ib_wc *wc); +int ionic_req_notify_cq(struct ib_cq *ibcq, enum ib_cq_notify_flags flags); + +/* ionic_hw_stats.c */ +void ionic_stats_init(struct ionic_ibdev *dev); +void ionic_stats_cleanup(struct ionic_ibdev *dev); + +/* ionic_pgtbl.c */ +__le64 ionic_pgtbl_dma(struct ionic_tbl_buf *buf, u64 va); +__be64 ionic_pgtbl_off(struct ionic_tbl_buf *buf, u64 va); +int ionic_pgtbl_page(struct ionic_tbl_buf *buf, u64 dma); +int ionic_pgtbl_init(struct ionic_ibdev *dev, +		     struct ionic_tbl_buf *buf, +		     struct ib_umem *umem, +		     dma_addr_t dma, +		     int limit, +		     u64 page_size); +void ionic_pgtbl_unbuf(struct ionic_ibdev *dev, struct ionic_tbl_buf *buf); +#endif /* _IONIC_IBDEV_H_ */  | 
