/* SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause */ /* * Copyright 2019-2023 Amazon.com, Inc. or its affiliates. All rights reserved. */ #ifndef __EFA_H__ #define __EFA_H__ #include #include #include #include #include #include "efa-abi.h" #include "efa_io_defs.h" #include "efadv.h" #define EFA_GET(ptr, mask) FIELD_GET(mask##_MASK, *(ptr)) #define EFA_SET(ptr, mask, value) \ ({ \ typeof(ptr) _ptr = ptr; \ *_ptr = (*_ptr & ~(mask##_MASK)) | \ FIELD_PREP(mask##_MASK, value); \ }) struct efa_context { struct verbs_context ibvctx; uint32_t cmds_supp_udata_mask; uint16_t sub_cqs_per_cq; uint16_t inline_buf_size; uint32_t max_llq_size; uint32_t device_caps; uint32_t max_sq_wr; uint32_t max_rq_wr; uint16_t max_sq_sge; uint16_t max_rq_sge; uint32_t max_rdma_size; uint16_t max_wr_rdma_sge; uint16_t max_tx_batch; uint16_t min_sq_wr; size_t cqe_size; size_t ex_cqe_size; struct efa_qp **qp_table; unsigned int qp_table_sz_m1; pthread_spinlock_t qp_table_lock; }; struct efa_pd { struct ibv_pd ibvpd; uint16_t pdn; }; struct efa_sub_cq { uint16_t consumed_cnt; int phase; uint8_t *buf; int qmask; int cqe_size; uint32_t ref_cnt; }; struct efa_cq { struct verbs_cq verbs_cq; struct efadv_cq dv_cq; uint32_t cqn; size_t cqe_size; uint8_t *buf; size_t buf_size; uint32_t *db; uint16_t cc; /* Consumer Counter */ uint8_t cmd_sn; uint16_t num_sub_cqs; /* Index of next sub cq idx to poll. This is used to guarantee fairness for sub cqs */ uint16_t next_poll_idx; pthread_spinlock_t lock; struct efa_wq *cur_wq; struct efa_io_cdesc_common *cur_cqe; struct ibv_device *dev; struct efa_sub_cq sub_cq_arr[]; }; struct efa_wq { uint64_t *wrid; /* wrid_idx_pool: Pool of free indexes in the wrid array, used to select the * wrid entry to be used to hold the next tx packet's context. * At init time, entry N will hold value N, as OOO tx-completions arrive, * the value stored in a given entry might not equal the entry's index. */ uint32_t *wrid_idx_pool; uint32_t wqe_cnt; uint32_t wqe_posted; uint32_t wqe_completed; uint16_t pc; /* Producer counter */ uint16_t desc_mask; /* wrid_idx_pool_next: Index of the next entry to use in wrid_idx_pool. */ uint16_t wrid_idx_pool_next; int max_sge; int phase; pthread_spinlock_t wqlock; uint32_t *db; uint16_t sub_cq_idx; }; struct efa_rq { struct efa_wq wq; uint8_t *buf; size_t buf_size; }; struct efa_sq { struct efa_wq wq; uint8_t *desc; uint32_t desc_offset; size_t desc_ring_mmap_size; size_t max_inline_data; size_t max_wr_rdma_sge; uint16_t max_batch_wr; /* Buffer for pending WR entries in the current session */ uint8_t *local_queue; /* Number of WR entries posted in the current session */ uint32_t num_wqe_pending; /* Phase before current session */ int phase_rb; /* Current wqe being built */ struct efa_io_tx_wqe *curr_tx_wqe; }; struct efa_qp { struct verbs_qp verbs_qp; struct efa_sq sq; struct efa_rq rq; int page_size; int sq_sig_all; int wr_session_err; struct ibv_device *dev; }; struct efa_mr { struct verbs_mr vmr; }; struct efa_ah { struct ibv_ah ibvah; uint16_t efa_ah; }; struct efa_dev { struct verbs_device vdev; uint32_t pg_sz; }; static inline struct efa_dev *to_efa_dev(struct ibv_device *ibvdev) { return container_of(ibvdev, struct efa_dev, vdev.device); } static inline struct efa_context *to_efa_context(struct ibv_context *ibvctx) { return container_of(ibvctx, struct efa_context, ibvctx.context); } static inline struct efa_pd *to_efa_pd(struct ibv_pd *ibvpd) { return container_of(ibvpd, struct efa_pd, ibvpd); } static inline struct efa_cq *to_efa_cq(struct ibv_cq *ibvcq) { return container_of(ibvcq, struct efa_cq, verbs_cq.cq); } static inline struct efa_cq *to_efa_cq_ex(struct ibv_cq_ex *ibvcqx) { return container_of(ibvcqx, struct efa_cq, verbs_cq.cq_ex); } static inline struct efa_cq *efadv_cq_to_efa_cq(struct efadv_cq *efadv_cq) { return container_of(efadv_cq, struct efa_cq, dv_cq); } static inline struct efa_qp *to_efa_qp(struct ibv_qp *ibvqp) { return container_of(ibvqp, struct efa_qp, verbs_qp.qp); } static inline struct efa_qp *to_efa_qp_ex(struct ibv_qp_ex *ibvqpx) { return container_of(ibvqpx, struct efa_qp, verbs_qp.qp_ex); } static inline struct efa_ah *to_efa_ah(struct ibv_ah *ibvah) { return container_of(ibvah, struct efa_ah, ibvah); } bool is_efa_dev(struct ibv_device *device); #endif /* __EFA_H__ */