| /* 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_ */ |