162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ 262306a36Sopenharmony_ci 362306a36Sopenharmony_ci/* Authors: Cheng Xu <chengyou@linux.alibaba.com> */ 462306a36Sopenharmony_ci/* Kai Shen <kaishen@linux.alibaba.com> */ 562306a36Sopenharmony_ci/* Copyright (c) 2020-2022, Alibaba Group. */ 662306a36Sopenharmony_ci 762306a36Sopenharmony_ci#ifndef __ERDMA_H__ 862306a36Sopenharmony_ci#define __ERDMA_H__ 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci#include <linux/bitfield.h> 1162306a36Sopenharmony_ci#include <linux/netdevice.h> 1262306a36Sopenharmony_ci#include <linux/pci.h> 1362306a36Sopenharmony_ci#include <linux/xarray.h> 1462306a36Sopenharmony_ci#include <rdma/ib_verbs.h> 1562306a36Sopenharmony_ci 1662306a36Sopenharmony_ci#include "erdma_hw.h" 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_ci#define DRV_MODULE_NAME "erdma" 1962306a36Sopenharmony_ci#define ERDMA_NODE_DESC "Elastic RDMA(iWARP) stack" 2062306a36Sopenharmony_ci 2162306a36Sopenharmony_cistruct erdma_eq { 2262306a36Sopenharmony_ci void *qbuf; 2362306a36Sopenharmony_ci dma_addr_t qbuf_dma_addr; 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_ci spinlock_t lock; 2662306a36Sopenharmony_ci 2762306a36Sopenharmony_ci u32 depth; 2862306a36Sopenharmony_ci 2962306a36Sopenharmony_ci u16 ci; 3062306a36Sopenharmony_ci u16 rsvd; 3162306a36Sopenharmony_ci 3262306a36Sopenharmony_ci atomic64_t event_num; 3362306a36Sopenharmony_ci atomic64_t notify_num; 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_ci void __iomem *db; 3662306a36Sopenharmony_ci u64 *db_record; 3762306a36Sopenharmony_ci}; 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_cistruct erdma_cmdq_sq { 4062306a36Sopenharmony_ci void *qbuf; 4162306a36Sopenharmony_ci dma_addr_t qbuf_dma_addr; 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_ci spinlock_t lock; 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_ci u32 depth; 4662306a36Sopenharmony_ci u16 ci; 4762306a36Sopenharmony_ci u16 pi; 4862306a36Sopenharmony_ci 4962306a36Sopenharmony_ci u16 wqebb_cnt; 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_ci u64 *db_record; 5262306a36Sopenharmony_ci}; 5362306a36Sopenharmony_ci 5462306a36Sopenharmony_cistruct erdma_cmdq_cq { 5562306a36Sopenharmony_ci void *qbuf; 5662306a36Sopenharmony_ci dma_addr_t qbuf_dma_addr; 5762306a36Sopenharmony_ci 5862306a36Sopenharmony_ci spinlock_t lock; 5962306a36Sopenharmony_ci 6062306a36Sopenharmony_ci u32 depth; 6162306a36Sopenharmony_ci u32 ci; 6262306a36Sopenharmony_ci u32 cmdsn; 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_ci u64 *db_record; 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_ci atomic64_t armed_num; 6762306a36Sopenharmony_ci}; 6862306a36Sopenharmony_ci 6962306a36Sopenharmony_cienum { 7062306a36Sopenharmony_ci ERDMA_CMD_STATUS_INIT, 7162306a36Sopenharmony_ci ERDMA_CMD_STATUS_ISSUED, 7262306a36Sopenharmony_ci ERDMA_CMD_STATUS_FINISHED, 7362306a36Sopenharmony_ci ERDMA_CMD_STATUS_TIMEOUT 7462306a36Sopenharmony_ci}; 7562306a36Sopenharmony_ci 7662306a36Sopenharmony_cistruct erdma_comp_wait { 7762306a36Sopenharmony_ci struct completion wait_event; 7862306a36Sopenharmony_ci u32 cmd_status; 7962306a36Sopenharmony_ci u32 ctx_id; 8062306a36Sopenharmony_ci u16 sq_pi; 8162306a36Sopenharmony_ci u8 comp_status; 8262306a36Sopenharmony_ci u8 rsvd; 8362306a36Sopenharmony_ci u32 comp_data[4]; 8462306a36Sopenharmony_ci}; 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_cienum { 8762306a36Sopenharmony_ci ERDMA_CMDQ_STATE_OK_BIT = 0, 8862306a36Sopenharmony_ci ERDMA_CMDQ_STATE_TIMEOUT_BIT = 1, 8962306a36Sopenharmony_ci ERDMA_CMDQ_STATE_CTX_ERR_BIT = 2, 9062306a36Sopenharmony_ci}; 9162306a36Sopenharmony_ci 9262306a36Sopenharmony_ci#define ERDMA_CMDQ_TIMEOUT_MS 15000 9362306a36Sopenharmony_ci#define ERDMA_REG_ACCESS_WAIT_MS 20 9462306a36Sopenharmony_ci#define ERDMA_WAIT_DEV_DONE_CNT 500 9562306a36Sopenharmony_ci 9662306a36Sopenharmony_cistruct erdma_cmdq { 9762306a36Sopenharmony_ci unsigned long *comp_wait_bitmap; 9862306a36Sopenharmony_ci struct erdma_comp_wait *wait_pool; 9962306a36Sopenharmony_ci spinlock_t lock; 10062306a36Sopenharmony_ci 10162306a36Sopenharmony_ci bool use_event; 10262306a36Sopenharmony_ci 10362306a36Sopenharmony_ci struct erdma_cmdq_sq sq; 10462306a36Sopenharmony_ci struct erdma_cmdq_cq cq; 10562306a36Sopenharmony_ci struct erdma_eq eq; 10662306a36Sopenharmony_ci 10762306a36Sopenharmony_ci unsigned long state; 10862306a36Sopenharmony_ci 10962306a36Sopenharmony_ci struct semaphore credits; 11062306a36Sopenharmony_ci u16 max_outstandings; 11162306a36Sopenharmony_ci}; 11262306a36Sopenharmony_ci 11362306a36Sopenharmony_ci#define COMPROMISE_CC ERDMA_CC_CUBIC 11462306a36Sopenharmony_cienum erdma_cc_alg { 11562306a36Sopenharmony_ci ERDMA_CC_NEWRENO = 0, 11662306a36Sopenharmony_ci ERDMA_CC_CUBIC, 11762306a36Sopenharmony_ci ERDMA_CC_HPCC_RTT, 11862306a36Sopenharmony_ci ERDMA_CC_HPCC_ECN, 11962306a36Sopenharmony_ci ERDMA_CC_HPCC_INT, 12062306a36Sopenharmony_ci ERDMA_CC_METHODS_NUM 12162306a36Sopenharmony_ci}; 12262306a36Sopenharmony_ci 12362306a36Sopenharmony_cistruct erdma_devattr { 12462306a36Sopenharmony_ci u32 fw_version; 12562306a36Sopenharmony_ci 12662306a36Sopenharmony_ci unsigned char peer_addr[ETH_ALEN]; 12762306a36Sopenharmony_ci unsigned long cap_flags; 12862306a36Sopenharmony_ci 12962306a36Sopenharmony_ci int numa_node; 13062306a36Sopenharmony_ci enum erdma_cc_alg cc; 13162306a36Sopenharmony_ci u32 irq_num; 13262306a36Sopenharmony_ci 13362306a36Sopenharmony_ci u32 max_qp; 13462306a36Sopenharmony_ci u32 max_send_wr; 13562306a36Sopenharmony_ci u32 max_recv_wr; 13662306a36Sopenharmony_ci u32 max_ord; 13762306a36Sopenharmony_ci u32 max_ird; 13862306a36Sopenharmony_ci 13962306a36Sopenharmony_ci u32 max_send_sge; 14062306a36Sopenharmony_ci u32 max_recv_sge; 14162306a36Sopenharmony_ci u32 max_sge_rd; 14262306a36Sopenharmony_ci u32 max_cq; 14362306a36Sopenharmony_ci u32 max_cqe; 14462306a36Sopenharmony_ci u64 max_mr_size; 14562306a36Sopenharmony_ci u32 max_mr; 14662306a36Sopenharmony_ci u32 max_pd; 14762306a36Sopenharmony_ci u32 max_mw; 14862306a36Sopenharmony_ci u32 local_dma_key; 14962306a36Sopenharmony_ci}; 15062306a36Sopenharmony_ci 15162306a36Sopenharmony_ci#define ERDMA_IRQNAME_SIZE 50 15262306a36Sopenharmony_ci 15362306a36Sopenharmony_cistruct erdma_irq { 15462306a36Sopenharmony_ci char name[ERDMA_IRQNAME_SIZE]; 15562306a36Sopenharmony_ci u32 msix_vector; 15662306a36Sopenharmony_ci cpumask_t affinity_hint_mask; 15762306a36Sopenharmony_ci}; 15862306a36Sopenharmony_ci 15962306a36Sopenharmony_cistruct erdma_eq_cb { 16062306a36Sopenharmony_ci bool ready; 16162306a36Sopenharmony_ci void *dev; /* All EQs use this fields to get erdma_dev struct */ 16262306a36Sopenharmony_ci struct erdma_irq irq; 16362306a36Sopenharmony_ci struct erdma_eq eq; 16462306a36Sopenharmony_ci struct tasklet_struct tasklet; 16562306a36Sopenharmony_ci}; 16662306a36Sopenharmony_ci 16762306a36Sopenharmony_cistruct erdma_resource_cb { 16862306a36Sopenharmony_ci unsigned long *bitmap; 16962306a36Sopenharmony_ci spinlock_t lock; 17062306a36Sopenharmony_ci u32 next_alloc_idx; 17162306a36Sopenharmony_ci u32 max_cap; 17262306a36Sopenharmony_ci}; 17362306a36Sopenharmony_ci 17462306a36Sopenharmony_cienum { 17562306a36Sopenharmony_ci ERDMA_RES_TYPE_PD = 0, 17662306a36Sopenharmony_ci ERDMA_RES_TYPE_STAG_IDX = 1, 17762306a36Sopenharmony_ci ERDMA_RES_CNT = 2, 17862306a36Sopenharmony_ci}; 17962306a36Sopenharmony_ci 18062306a36Sopenharmony_ci#define ERDMA_EXTRA_BUFFER_SIZE ERDMA_DB_SIZE 18162306a36Sopenharmony_ci#define WARPPED_BUFSIZE(size) ((size) + ERDMA_EXTRA_BUFFER_SIZE) 18262306a36Sopenharmony_ci 18362306a36Sopenharmony_cistruct erdma_dev { 18462306a36Sopenharmony_ci struct ib_device ibdev; 18562306a36Sopenharmony_ci struct net_device *netdev; 18662306a36Sopenharmony_ci struct pci_dev *pdev; 18762306a36Sopenharmony_ci struct notifier_block netdev_nb; 18862306a36Sopenharmony_ci struct workqueue_struct *reflush_wq; 18962306a36Sopenharmony_ci 19062306a36Sopenharmony_ci resource_size_t func_bar_addr; 19162306a36Sopenharmony_ci resource_size_t func_bar_len; 19262306a36Sopenharmony_ci u8 __iomem *func_bar; 19362306a36Sopenharmony_ci 19462306a36Sopenharmony_ci struct erdma_devattr attrs; 19562306a36Sopenharmony_ci /* physical port state (only one port per device) */ 19662306a36Sopenharmony_ci enum ib_port_state state; 19762306a36Sopenharmony_ci u32 mtu; 19862306a36Sopenharmony_ci 19962306a36Sopenharmony_ci /* cmdq and aeq use the same msix vector */ 20062306a36Sopenharmony_ci struct erdma_irq comm_irq; 20162306a36Sopenharmony_ci struct erdma_cmdq cmdq; 20262306a36Sopenharmony_ci struct erdma_eq aeq; 20362306a36Sopenharmony_ci struct erdma_eq_cb ceqs[ERDMA_NUM_MSIX_VEC - 1]; 20462306a36Sopenharmony_ci 20562306a36Sopenharmony_ci spinlock_t lock; 20662306a36Sopenharmony_ci struct erdma_resource_cb res_cb[ERDMA_RES_CNT]; 20762306a36Sopenharmony_ci struct xarray qp_xa; 20862306a36Sopenharmony_ci struct xarray cq_xa; 20962306a36Sopenharmony_ci 21062306a36Sopenharmony_ci u32 next_alloc_qpn; 21162306a36Sopenharmony_ci u32 next_alloc_cqn; 21262306a36Sopenharmony_ci 21362306a36Sopenharmony_ci atomic_t num_ctx; 21462306a36Sopenharmony_ci struct list_head cep_list; 21562306a36Sopenharmony_ci}; 21662306a36Sopenharmony_ci 21762306a36Sopenharmony_cistatic inline void *get_queue_entry(void *qbuf, u32 idx, u32 depth, u32 shift) 21862306a36Sopenharmony_ci{ 21962306a36Sopenharmony_ci idx &= (depth - 1); 22062306a36Sopenharmony_ci 22162306a36Sopenharmony_ci return qbuf + (idx << shift); 22262306a36Sopenharmony_ci} 22362306a36Sopenharmony_ci 22462306a36Sopenharmony_cistatic inline struct erdma_dev *to_edev(struct ib_device *ibdev) 22562306a36Sopenharmony_ci{ 22662306a36Sopenharmony_ci return container_of(ibdev, struct erdma_dev, ibdev); 22762306a36Sopenharmony_ci} 22862306a36Sopenharmony_ci 22962306a36Sopenharmony_cistatic inline u32 erdma_reg_read32(struct erdma_dev *dev, u32 reg) 23062306a36Sopenharmony_ci{ 23162306a36Sopenharmony_ci return readl(dev->func_bar + reg); 23262306a36Sopenharmony_ci} 23362306a36Sopenharmony_ci 23462306a36Sopenharmony_cistatic inline u64 erdma_reg_read64(struct erdma_dev *dev, u32 reg) 23562306a36Sopenharmony_ci{ 23662306a36Sopenharmony_ci return readq(dev->func_bar + reg); 23762306a36Sopenharmony_ci} 23862306a36Sopenharmony_ci 23962306a36Sopenharmony_cistatic inline void erdma_reg_write32(struct erdma_dev *dev, u32 reg, u32 value) 24062306a36Sopenharmony_ci{ 24162306a36Sopenharmony_ci writel(value, dev->func_bar + reg); 24262306a36Sopenharmony_ci} 24362306a36Sopenharmony_ci 24462306a36Sopenharmony_cistatic inline void erdma_reg_write64(struct erdma_dev *dev, u32 reg, u64 value) 24562306a36Sopenharmony_ci{ 24662306a36Sopenharmony_ci writeq(value, dev->func_bar + reg); 24762306a36Sopenharmony_ci} 24862306a36Sopenharmony_ci 24962306a36Sopenharmony_cistatic inline u32 erdma_reg_read32_filed(struct erdma_dev *dev, u32 reg, 25062306a36Sopenharmony_ci u32 filed_mask) 25162306a36Sopenharmony_ci{ 25262306a36Sopenharmony_ci u32 val = erdma_reg_read32(dev, reg); 25362306a36Sopenharmony_ci 25462306a36Sopenharmony_ci return FIELD_GET(filed_mask, val); 25562306a36Sopenharmony_ci} 25662306a36Sopenharmony_ci 25762306a36Sopenharmony_ci#define ERDMA_GET(val, name) FIELD_GET(ERDMA_CMD_##name##_MASK, val) 25862306a36Sopenharmony_ci 25962306a36Sopenharmony_ciint erdma_cmdq_init(struct erdma_dev *dev); 26062306a36Sopenharmony_civoid erdma_finish_cmdq_init(struct erdma_dev *dev); 26162306a36Sopenharmony_civoid erdma_cmdq_destroy(struct erdma_dev *dev); 26262306a36Sopenharmony_ci 26362306a36Sopenharmony_civoid erdma_cmdq_build_reqhdr(u64 *hdr, u32 mod, u32 op); 26462306a36Sopenharmony_ciint erdma_post_cmd_wait(struct erdma_cmdq *cmdq, void *req, u32 req_size, 26562306a36Sopenharmony_ci u64 *resp0, u64 *resp1); 26662306a36Sopenharmony_civoid erdma_cmdq_completion_handler(struct erdma_cmdq *cmdq); 26762306a36Sopenharmony_ci 26862306a36Sopenharmony_ciint erdma_ceqs_init(struct erdma_dev *dev); 26962306a36Sopenharmony_civoid erdma_ceqs_uninit(struct erdma_dev *dev); 27062306a36Sopenharmony_civoid notify_eq(struct erdma_eq *eq); 27162306a36Sopenharmony_civoid *get_next_valid_eqe(struct erdma_eq *eq); 27262306a36Sopenharmony_ci 27362306a36Sopenharmony_ciint erdma_aeq_init(struct erdma_dev *dev); 27462306a36Sopenharmony_civoid erdma_aeq_destroy(struct erdma_dev *dev); 27562306a36Sopenharmony_ci 27662306a36Sopenharmony_civoid erdma_aeq_event_handler(struct erdma_dev *dev); 27762306a36Sopenharmony_civoid erdma_ceq_completion_handler(struct erdma_eq_cb *ceq_cb); 27862306a36Sopenharmony_ci 27962306a36Sopenharmony_ci#endif 280