/* SPDX-License-Identifier: GPL-2.0 */ /* Copyright (C) 2018-2025, Advanced Micro Devices, Inc. */ #ifndef _IONIC_IBDEV_H_ #define _IONIC_IBDEV_H_ #include #include #include #include #include #include #include #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_ */