2026-01-29 22:25:33 +08:00

342 lines
8.8 KiB
C

/* SPDX-License-Identifier: GPL-2.0 */
/* Copyright (C) 2021 - 2023, Shanghai Yunsilicon Technology Co., Ltd.
* All rights reserved.
*/
#ifndef XSC_DRIVER_H
#define XSC_DRIVER_H
#include <linux/kernel.h>
#include <linux/completion.h>
#include <linux/pci.h>
#include <linux/spinlock_types.h>
#include <linux/semaphore.h>
#include <linux/vmalloc.h>
#include <linux/radix-tree.h>
#include "common/device.h"
#include "common/doorbell.h"
#include "common/xsc_core.h"
#include "common/xsc_cmd.h"
#include "common/xsc_hsi.h"
#include "common/qpts.h"
#define LS_64(val, field) (((u64)(val) << field ## _SHIFT) & (field ## _MASK))
#define RS_64(val, field) ((u64)((val) & field ## _MASK) >> field ## _SHIFT)
#define LS_32(val, field) (((val) << field ## _SHIFT) & (field ## _MASK))
#define RS_32(val, field) (((val) & field ## _MASK) >> field ## _SHIFT)
enum {
CMD_OWNER_SW = 0x0,
CMD_OWNER_HW = 0x1,
CMD_STATUS_SUCCESS = 0,
};
enum {
XSC_MAX_FW_PORTS = 1,
};
enum {
XSC_MAX_IRQ_NAME = 32
};
enum {
XSC_MAX_EQ_NAME = 20
};
enum {
XSC_REG_PCAP = 0x5001,
XSC_REG_PMTU = 0x5003,
XSC_REG_PTYS = 0x5004,
XSC_REG_PAOS = 0x5006,
XSC_REG_PMAOS = 0x5012,
XSC_REG_PUDE = 0x5009,
XSC_REG_PMPE = 0x5010,
XSC_REG_PELC = 0x500e,
XSC_REG_PMLP = 0, /* TBD */
XSC_REG_NODE_DESC = 0x6001,
XSC_REG_HOST_ENDIANNESS = 0x7004,
XSC_REG_MCIA = 0x9014,
};
enum dbg_rsc_type {
XSC_DBG_RSC_QP,
XSC_DBG_RSC_EQ,
XSC_DBG_RSC_CQ,
};
struct xsc_field_desc {
struct dentry *dent;
int i;
};
struct xsc_rsc_debug {
struct xsc_core_device *xdev;
void *object;
enum dbg_rsc_type type;
struct dentry *root;
struct xsc_field_desc fields[];
};
struct xsc_buf_list {
void *buf;
dma_addr_t map;
};
struct xsc_buf {
struct xsc_buf_list direct;
struct xsc_buf_list *page_list;
int nbufs;
int npages;
int page_shift;
int size;
};
struct xsc_frag_buf {
struct xsc_buf_list *frags;
int npages;
int size;
u8 page_shift;
};
struct xsc_frag_buf_ctrl {
struct xsc_buf_list *frags;
u32 sz_m1;
u16 frag_sz_m1;
u16 strides_offset;
u8 log_sz;
u8 log_stride;
u8 log_frag_strides;
};
struct xsc_cq_table {
/* protect radix tree
*/
spinlock_t lock;
struct radix_tree_root tree;
};
struct xsc_eq {
struct xsc_core_device *dev;
struct xsc_cq_table cq_table;
u32 doorbell;//offset from bar0/2 space start
u32 cons_index;
struct xsc_buf buf;
int size;
unsigned int irqn;
u16 eqn;
int nent;
cpumask_var_t mask;
char name[XSC_MAX_EQ_NAME];
struct list_head list;
int index;
struct xsc_rsc_debug *dbg;
};
struct xsc_core_mr {
u64 iova;
u64 size;
u32 key;
u32 pd;
u32 access;
};
struct xsc_eq_table {
void __iomem *update_ci;
void __iomem *update_arm_ci;
struct list_head comp_eqs_list;
struct xsc_eq pages_eq;
struct xsc_eq async_eq;
struct xsc_eq cmd_eq;
int num_comp_vectors;
int eq_vec_comp_base;
/* protect EQs list
*/
spinlock_t lock;
};
struct xsc_irq_info {
cpumask_var_t mask;
char name[XSC_MAX_IRQ_NAME];
};
struct xsc_qp_table {
/* protect radix tree
*/
spinlock_t lock;
struct radix_tree_root tree;
};
struct counter_name_map {
int index;
const char *reg_name;
};
struct counter_reg_map {
int index;
int reg_addr;
};
struct xsc_dev_resource {
struct xsc_qp_table qp_table;
struct xsc_cq_table cq_table;
struct xsc_eq_table eq_table;
struct xsc_irq_info *irq_info;
spinlock_t mkey_lock; /* protect mkey */
u8 mkey_key;
struct mutex alloc_mutex; /* protect buffer alocation according to numa node */
int numa_node;
int fw_pages;
int reg_pages;
struct mutex pgdir_mutex; /* protect pgdir_list */
struct list_head pgdir_list;
struct dentry *qp_debugfs;
struct dentry *eq_debugfs;
struct dentry *cq_debugfs;
struct dentry *cmdif_debugfs;
struct dentry *qptrace_debugfs;
struct dentry *dbg_root;
};
struct xsc_db {
__be32 *db;
union {
struct xsc_db_pgdir *pgdir;
struct xsc_ib_user_db_page *user_page;
} u;
dma_addr_t dma;
int index;
};
enum {
XSC_COMP_EQ_SIZE = 1024,
};
/*replace by struct define in ofed*/
struct xsc_db_pgdir {
struct list_head list;
unsigned long *bitmap;
__be32 *db_page;
dma_addr_t db_dma;
};
static inline void *xsc_buf_offset(struct xsc_buf *buf, int offset)
{
if (likely(BITS_PER_LONG == 64 || buf->nbufs == 1))
return buf->direct.buf + offset;
else
return buf->page_list[offset >> PAGE_SHIFT].buf +
(offset & (PAGE_SIZE - 1));
}
static inline struct xsc_core_device *pci2xdev(struct pci_dev *pdev)
{
return pci_get_drvdata(pdev);
}
extern struct dentry *xsc_debugfs_root;
static inline void *xsc_vzalloc(unsigned long size)
{
void *rtn;
rtn = kzalloc(size, GFP_KERNEL | __GFP_NOWARN);
if (!rtn)
rtn = vzalloc(size);
return rtn;
}
static inline void xsc_vfree(const void *addr)
{
if (addr && is_vmalloc_addr(addr))
vfree(addr);
else
kfree(addr);
}
int xsc_dev_init(struct xsc_core_device *xdev);
void xsc_dev_cleanup(struct xsc_core_device *xdev);
int xsc_cmd_init(struct xsc_core_device *xdev);
void xsc_cmd_cleanup(struct xsc_core_device *xdev);
void xsc_cmd_use_events(struct xsc_core_device *xdev);
void xsc_cmd_use_polling(struct xsc_core_device *xdev);
int xsc_cmd_err_handler(struct xsc_core_device *xdev);
void xsc_cmd_resp_handler(struct xsc_core_device *xdev);
int xsc_cmd_status_to_err(struct xsc_outbox_hdr *hdr);
int _xsc_cmd_exec(struct xsc_core_device *xdev, void *in, int in_size, void *out,
int out_size);
int xsc_buf_alloc(struct xsc_core_device *xdev, int size, int max_direct,
struct xsc_buf *buf);
void xsc_buf_free(struct xsc_core_device *dev, struct xsc_buf *buf);
int xsc_core_create_mkey(struct xsc_core_device *dev, struct xsc_core_mr *mr);
int xsc_core_destroy_mkey(struct xsc_core_device *dev, struct xsc_core_mr *mr);
int xsc_core_register_mr(struct xsc_core_device *dev, struct xsc_core_mr *mr,
struct xsc_register_mr_mbox_in *in, int inlen);
int xsc_core_dereg_mr(struct xsc_core_device *dev, struct xsc_core_mr *mr);
void xsc_reg_local_dma_mr(struct xsc_core_device *dev);
int xsc_core_alloc_pd(struct xsc_core_device *xdev, u32 *pdn);
int xsc_core_dealloc_pd(struct xsc_core_device *xdev, u32 pdn);
int xsc_core_mad_ifc(struct xsc_core_device *xdev, void *inb, void *outb,
u16 opmod, int port);
void xsc_register_debugfs(void);
void xsc_unregister_debugfs(void);
int xsc_eq_init(struct xsc_core_device *dev);
void xsc_eq_cleanup(struct xsc_core_device *dev);
void xsc_fill_page_array(struct xsc_buf *buf, __be64 *pas, int npages);
void xsc_fill_page_frag_array(struct xsc_frag_buf *buf, __be64 *pas, int npages);
void xsc_qp_event(struct xsc_core_device *xdev, u32 qpn, int event_type);
int xsc_vector2eqn(struct xsc_core_device *dev, int vector, int *eqn,
unsigned int *irqn);
void xsc_cq_event(struct xsc_core_device *xdev, u32 cqn, int event_type);
int xsc_create_map_eq(struct xsc_core_device *dev, struct xsc_eq *eq, u8 vecidx,
int nent, const char *name);
int xsc_destroy_unmap_eq(struct xsc_core_device *dev, struct xsc_eq *eq);
int xsc_start_eqs(struct xsc_core_device *dev);
void xsc_stop_eqs(struct xsc_core_device *dev);
int xsc_qp_debugfs_init(struct xsc_core_device *dev);
void xsc_qp_debugfs_cleanup(struct xsc_core_device *dev);
int xsc_core_access_reg(struct xsc_core_device *xdev, void *data_in,
int size_in, void *data_out, int size_out,
u16 reg_num, int arg, int write);
int xsc_set_port_caps(struct xsc_core_device *xdev, int port_num, u32 caps);
int xsc_debug_eq_add(struct xsc_core_device *xdev, struct xsc_eq *eq);
void xsc_debug_eq_remove(struct xsc_core_device *xdev, struct xsc_eq *eq);
int xsc_core_eq_query(struct xsc_core_device *dev, struct xsc_eq *eq,
struct xsc_query_eq_mbox_out *out, int outlen);
int xsc_eq_debugfs_init(struct xsc_core_device *dev);
void xsc_eq_debugfs_cleanup(struct xsc_core_device *dev);
int xsc_cq_debugfs_init(struct xsc_core_device *dev);
void xsc_cq_debugfs_cleanup(struct xsc_core_device *dev);
const char *xsc_command_str(int command);
int xsc_cmdif_debugfs_init(struct xsc_core_device *xdev);
void xsc_cmdif_debugfs_cleanup(struct xsc_core_device *xdev);
int xsc_qptrace_debugfs_init(struct xsc_core_device *dev);
void xsc_qptrace_debugfs_cleanup(struct xsc_core_device *dev);
int xsc_db_alloc_node(struct xsc_core_device *xdev, struct xsc_db *db, int node);
int xsc_frag_buf_alloc_node(struct xsc_core_device *xdev, int size,
struct xsc_frag_buf *buf, int node);
void xsc_db_free(struct xsc_core_device *xdev, struct xsc_db *db);
void xsc_frag_buf_free(struct xsc_core_device *xdev, struct xsc_frag_buf *buf);
static inline u32 xsc_mkey_to_idx(u32 mkey)
{
return mkey >> ((MMC_MPT_TBL_MEM_DEPTH == 32768) ? 17 : 18);
}
static inline u32 xsc_idx_to_mkey(u32 mkey_idx)
{
return mkey_idx << ((MMC_MPT_TBL_MEM_DEPTH == 32768) ? 17 : 18);
}
enum {
XSC_PROF_MASK_QP_SIZE = (u64)1 << 0,
XSC_PROF_MASK_CMDIF_CSUM = (u64)1 << 1,
XSC_PROF_MASK_MR_CACHE = (u64)1 << 2,
};
#endif /* XSC_DRIVER_H */