2026-01-21 18:59:54 +08:00

457 lines
12 KiB
C

/* SPDX-License-Identifier: GPL-2.0 */
/* Huawei Hifc PCI Express Linux driver
* Copyright(c) 2017 Huawei Technologies Co., Ltd
*
*/
#ifndef HIFC_HWDEV_H_
#define HIFC_HWDEV_H_
/* to use 0-level CLA, page size must be: 64B(wqebb) * 4096(max_q_depth) */
#define HIFC_DEFAULT_WQ_PAGE_SIZE 0x40000
#define HIFC_HW_WQ_PAGE_SIZE 0x1000
#define HIFC_MSG_TO_MGMT_MAX_LEN 2016
#define HIFC_MGMT_STATUS_ERR_OK 0 /* Ok */
#define HIFC_MGMT_STATUS_ERR_PARAM 1 /* Invalid parameter */
#define HIFC_MGMT_STATUS_ERR_FAILED 2 /* Operation failed */
#define HIFC_MGMT_STATUS_ERR_PORT 3 /* Invalid port */
#define HIFC_MGMT_STATUS_ERR_TIMEOUT 4 /* Operation time out */
#define HIFC_MGMT_STATUS_ERR_NOMATCH 5 /* Version not match */
#define HIFC_MGMT_STATUS_ERR_EXIST 6 /* Entry exists */
#define HIFC_MGMT_STATUS_ERR_NOMEM 7 /* Out of memory */
#define HIFC_MGMT_STATUS_ERR_INIT 8 /* Feature not initialized */
#define HIFC_MGMT_STATUS_ERR_FAULT 9 /* Invalid address */
#define HIFC_MGMT_STATUS_ERR_PERM 10 /* Operation not permitted */
#define HIFC_MGMT_STATUS_ERR_EMPTY 11 /* Table empty */
#define HIFC_MGMT_STATUS_ERR_FULL 12 /* Table full */
#define HIFC_MGMT_STATUS_ERR_NOT_FOUND 13 /* Not found */
#define HIFC_MGMT_STATUS_ERR_BUSY 14 /* Device or resource busy */
#define HIFC_MGMT_STATUS_ERR_RESOURCE 15 /* No resources for operation */
#define HIFC_MGMT_STATUS_ERR_CONFIG 16 /* Invalid configuration */
#define HIFC_MGMT_STATUS_ERR_UNAVAIL 17 /* Feature unavailable */
#define HIFC_MGMT_STATUS_ERR_CRC 18 /* CRC check failed */
#define HIFC_MGMT_STATUS_ERR_NXIO 19 /* No such device or address */
#define HIFC_MGMT_STATUS_ERR_ROLLBACK 20 /* Chip rollback fail */
#define HIFC_MGMT_STATUS_ERR_LEN 32 /* Length too short or too long */
#define HIFC_MGMT_STATUS_ERR_UNSUPPORT 0xFF /* Feature not supported*/
/* Qe buffer relates define */
enum hifc_rx_buf_size {
HIFC_RX_BUF_SIZE_32B = 0x20,
HIFC_RX_BUF_SIZE_64B = 0x40,
HIFC_RX_BUF_SIZE_96B = 0x60,
HIFC_RX_BUF_SIZE_128B = 0x80,
HIFC_RX_BUF_SIZE_192B = 0xC0,
HIFC_RX_BUF_SIZE_256B = 0x100,
HIFC_RX_BUF_SIZE_384B = 0x180,
HIFC_RX_BUF_SIZE_512B = 0x200,
HIFC_RX_BUF_SIZE_768B = 0x300,
HIFC_RX_BUF_SIZE_1K = 0x400,
HIFC_RX_BUF_SIZE_1_5K = 0x600,
HIFC_RX_BUF_SIZE_2K = 0x800,
HIFC_RX_BUF_SIZE_3K = 0xC00,
HIFC_RX_BUF_SIZE_4K = 0x1000,
HIFC_RX_BUF_SIZE_8K = 0x2000,
HIFC_RX_BUF_SIZE_16K = 0x4000,
};
enum hifc_res_state {
HIFC_RES_CLEAN = 0,
HIFC_RES_ACTIVE = 1,
};
enum ppf_tmr_status {
HIFC_PPF_TMR_FLAG_STOP,
HIFC_PPF_TMR_FLAG_START,
};
struct cfg_mgmt_info;
struct hifc_hwif;
struct hifc_wqs;
struct hifc_aeqs;
struct hifc_ceqs;
struct hifc_msg_pf_to_mgmt;
struct hifc_cmdqs;
struct hifc_root_ctxt {
u8 status;
u8 version;
u8 rsvd0[6];
u16 func_idx;
u16 rsvd1;
u8 set_cmdq_depth;
u8 cmdq_depth;
u8 lro_en;
u8 rsvd2;
u8 ppf_idx;
u8 rsvd3;
u16 rq_depth;
u16 rx_buf_sz;
u16 sq_depth;
};
struct hifc_page_addr {
void *virt_addr;
u64 phys_addr;
};
#define HIFC_PCIE_LINK_DOWN 0xFFFFFFFF
#define HIFC_DEV_ACTIVE_FW_TIMEOUT (35 * 1000)
#define HIFC_DEV_BUSY_ACTIVE_FW 0xFE
#define HIFC_HW_WQ_NAME "hifc_hardware"
#define HIFC_HEARTBEAT_PERIOD 1000
#define HIFC_HEARTBEAT_START_EXPIRE 5000
#define HIFC_CHIP_ERROR_TYPE_MAX 1024
#define HIFC_CHIP_FAULT_SIZE \
(HIFC_NODE_ID_MAX * FAULT_LEVEL_MAX * HIFC_CHIP_ERROR_TYPE_MAX)
#define HIFC_CSR_DMA_ATTR_TBL_BASE 0xC80
#define HIFC_CSR_DMA_ATTR_TBL_STRIDE 0x4
#define HIFC_CSR_DMA_ATTR_TBL_ADDR(idx) \
(HIFC_CSR_DMA_ATTR_TBL_BASE \
+ (idx) * HIFC_CSR_DMA_ATTR_TBL_STRIDE)
/* MSI-X registers */
#define HIFC_CSR_MSIX_CNT_BASE 0x2004
#define HIFC_CSR_MSIX_STRIDE 0x8
#define HIFC_CSR_MSIX_CNT_ADDR(idx) \
(HIFC_CSR_MSIX_CNT_BASE + (idx) * HIFC_CSR_MSIX_STRIDE)
enum hifc_node_id {
HIFC_NODE_ID_IPSU = 4,
HIFC_NODE_ID_MGMT_HOST = 21, /*Host CPU send API to uP */
HIFC_NODE_ID_MAX = 22
};
#define HIFC_HWDEV_INIT_MODES_MASK ((1UL << HIFC_HWDEV_ALL_INITED) - 1)
enum hifc_hwdev_func_state {
HIFC_HWDEV_FUNC_INITED = HIFC_HWDEV_ALL_INITED,
HIFC_HWDEV_FUNC_DEINIT,
HIFC_HWDEV_STATE_BUSY = 31,
};
struct hifc_cqm_stats {
atomic_t cqm_cmd_alloc_cnt;
atomic_t cqm_cmd_free_cnt;
atomic_t cqm_send_cmd_box_cnt;
atomic_t cqm_db_addr_alloc_cnt;
atomic_t cqm_db_addr_free_cnt;
atomic_t cqm_fc_srq_create_cnt;
atomic_t cqm_qpc_mpt_create_cnt;
atomic_t cqm_nonrdma_queue_create_cnt;
atomic_t cqm_qpc_mpt_delete_cnt;
atomic_t cqm_nonrdma_queue_delete_cnt;
atomic_t cqm_aeq_callback_cnt[112];
};
struct hifc_link_event_stats {
atomic_t link_down_stats;
atomic_t link_up_stats;
};
struct hifc_fault_event_stats {
atomic_t chip_fault_stats[HIFC_NODE_ID_MAX][FAULT_LEVEL_MAX];
atomic_t fault_type_stat[FAULT_TYPE_MAX];
atomic_t pcie_fault_stats;
};
struct hifc_hw_stats {
atomic_t heart_lost_stats;
atomic_t nic_ucode_event_stats[HIFC_NIC_FATAL_ERROR_MAX];
struct hifc_cqm_stats cqm_stats;
struct hifc_link_event_stats link_event_stats;
struct hifc_fault_event_stats fault_event_stats;
};
struct hifc_fault_info_node {
struct list_head list;
struct hifc_hwdev *hwdev;
struct hifc_fault_recover_info info;
};
enum heartbeat_support_state {
HEARTBEAT_NOT_SUPPORT = 0,
HEARTBEAT_SUPPORT,
};
/* 25s for max 5 heartbeat event lost */
#define HIFC_HEARBEAT_ENHANCED_LOST 25000
struct hifc_heartbeat_enhanced {
bool en; /* enable enhanced heartbeat or not */
unsigned long last_update_jiffies;
u32 last_heartbeat;
unsigned long start_detect_jiffies;
};
#define HIFC_CMD_VER_FUNC_ID 2
#define HIFC_GLB_DMA_SO_RO_REPLACE_ADDR 0x488C
#define HIFC_ICPL_RESERVD_ADDR 0x9204
#define l2nic_msg_to_mgmt_sync(hwdev, cmd, buf_in, in_size, buf_out, out_size)\
hifc_msg_to_mgmt_sync(hwdev, HIFC_MOD_L2NIC, cmd, \
buf_in, in_size, \
buf_out, out_size, 0)
struct hifc_hwdev {
void *adapter_hdl; /* pointer to hifc_pcidev or NDIS_Adapter */
void *pcidev_hdl; /* pointer to pcidev or Handler */
void *dev_hdl; /* pointer to pcidev->dev or Handler, for
* sdk_err() or dma_alloc()
*/
u32 wq_page_size;
void *cqm_hdl;
void *chip_node;
struct hifc_hwif *hwif; /* include void __iomem *bar */
struct cfg_mgmt_info *cfg_mgmt;
struct hifc_wqs *wqs; /* for FC slq */
struct hifc_aeqs *aeqs;
struct hifc_ceqs *ceqs;
struct hifc_msg_pf_to_mgmt *pf_to_mgmt;
struct hifc_clp_pf_to_mgmt *clp_pf_to_mgmt;
struct hifc_cmdqs *cmdqs;
struct hifc_page_addr page_pa0;
struct hifc_page_addr page_pa1;
hifc_event_handler event_callback;
void *event_pri_handle;
bool history_fault_flag;
struct hifc_fault_recover_info history_fault;
struct semaphore fault_list_sem;
struct work_struct timer_work;
struct workqueue_struct *workq;
struct timer_list heartbeat_timer;
/* true represent heartbeat lost, false represent heartbeat restore */
u32 heartbeat_lost;
int chip_present_flag;
struct hifc_heartbeat_enhanced heartbeat_ehd;
struct hifc_hw_stats hw_stats;
u8 *chip_fault_stats;
u32 statufull_ref_cnt;
ulong func_state;
u64 feature_cap; /* enum hifc_func_cap */
/* In bmgw x86 host, driver can't send message to mgmt cpu directly,
* need to trasmit message ppf mbox to bmgw arm host.
*/
struct hifc_board_info board_info;
};
int hifc_init_comm_ch(struct hifc_hwdev *hwdev);
void hifc_uninit_comm_ch(struct hifc_hwdev *hwdev);
enum hifc_set_arm_type {
HIFC_SET_ARM_CMDQ,
HIFC_SET_ARM_SQ,
HIFC_SET_ARM_TYPE_NUM,
};
/* up to driver event */
#define HIFC_PORT_CMD_MGMT_RESET 0x0
struct hifc_vport_state {
u8 status;
u8 version;
u8 rsvd0[6];
u16 func_id;
u16 rsvd1;
u8 state;
u8 rsvd2[3];
};
struct hifc_l2nic_reset {
u8 status;
u8 version;
u8 rsvd0[6];
u16 func_id;
u16 reset_flag;
};
/* HILINK module interface */
/* cmd of mgmt CPU message for HILINK module */
enum hifc_hilink_cmd {
HIFC_HILINK_CMD_GET_LINK_INFO = 0x3,
HIFC_HILINK_CMD_SET_LINK_SETTINGS = 0x8,
};
enum hilink_info_print_event {
HILINK_EVENT_LINK_UP = 1,
HILINK_EVENT_LINK_DOWN,
HILINK_EVENT_CABLE_PLUGGED,
HILINK_EVENT_MAX_TYPE,
};
enum hifc_link_port_type {
LINK_PORT_FIBRE = 1,
LINK_PORT_ELECTRIC,
LINK_PORT_COPPER,
LINK_PORT_AOC,
LINK_PORT_BACKPLANE,
LINK_PORT_BASET,
LINK_PORT_MAX_TYPE,
};
enum hilink_fibre_subtype {
FIBRE_SUBTYPE_SR = 1,
FIBRE_SUBTYPE_LR,
FIBRE_SUBTYPE_MAX,
};
enum hilink_fec_type {
HILINK_FEC_RSFEC,
HILINK_FEC_BASEFEC,
HILINK_FEC_NOFEC,
HILINK_FEC_MAX_TYPE,
};
/* cmd of mgmt CPU message */
enum hifc_port_cmd {
HIFC_PORT_CMD_SET_MAC = 0x9,
HIFC_PORT_CMD_GET_AUTONEG_CAP = 0xf,
HIFC_PORT_CMD_SET_VPORT_ENABLE = 0x5d,
HIFC_PORT_CMD_UPDATE_MAC = 0xa4,
HIFC_PORT_CMD_GET_SFP_INFO = 0xad,
HIFC_PORT_CMD_GET_STD_SFP_INFO = 0xF0,
HIFC_PORT_CMD_GET_SFP_ABS = 0xFB,
};
struct hi30_ffe_data {
u8 PRE2;
u8 PRE1;
u8 POST1;
u8 POST2;
u8 MAIN;
};
struct hi30_ctle_data {
u8 ctlebst[3];
u8 ctlecmband[3];
u8 ctlermband[3];
u8 ctleza[3];
u8 ctlesqh[3];
u8 ctleactgn[3];
u8 ctlepassgn;
};
#define HILINK_MAX_LANE 4
struct hilink_lane {
u8 lane_used;
u8 hi30_ffe[5];
u8 hi30_ctle[19];
u8 hi30_dfe[14];
u8 rsvd4;
};
struct hifc_link_info {
u8 vendor_name[16];
/* port type:
* 1 - fiber; 2 - electric; 3 - copper; 4 - AOC; 5 - backplane;
* 6 - baseT; 0xffff - unknown
*
* port subtype:
* Only when port_type is fiber:
* 1 - SR; 2 - LR
*/
u32 port_type;
u32 port_sub_type;
u32 cable_length;
u8 cable_temp;
u8 cable_max_speed; /* 1(G)/10(G)/25(G)... */
u8 sfp_type; /* 0 - qsfp; 1 - sfp */
u8 rsvd0;
u32 power[4]; /* uW; if is sfp, only power[2] is valid */
u8 an_state; /* 0 - off; 1 - on */
u8 fec; /* 0 - RSFEC; 1 - BASEFEC; 2 - NOFEC */
u16 speed; /* 1(G)/10(G)/25(G)... */
u8 cable_absent; /* 0 - cable present; 1 - cable unpresent */
u8 alos; /* 0 - yes; 1 - no */
u8 rx_los; /* 0 - yes; 1 - no */
u8 pma_status;
u32 pma_dbg_info_reg; /* pma debug info: */
u32 pma_signal_ok_reg; /* signal ok: */
u32 pcs_err_blk_cnt_reg; /* error block counter: */
u32 rf_lf_status_reg; /* RF/LF status: */
u8 pcs_link_reg; /* pcs link: */
u8 mac_link_reg; /* mac link: */
u8 mac_tx_en;
u8 mac_rx_en;
u32 pcs_err_cnt;
/* struct hifc_hilink_lane: 40 bytes */
u8 lane1[40]; /* 25GE lane in old firmware */
u8 rsvd1[266]; /* hilink machine state */
u8 lane2[HILINK_MAX_LANE * 40]; /* max 4 lane for 40GE/100GE */
u8 rsvd2[2];
};
struct hifc_hilink_link_info {
u8 status;
u8 version;
u8 rsvd0[6];
u16 port_id;
u8 info_type; /* 1: link up 2: link down 3 cable plugged */
u8 rsvd1;
struct hifc_link_info info;
u8 rsvd2[352];
};
int hifc_set_arm_bit(void *hwdev, enum hifc_set_arm_type q_type, u16 q_id);
void hifc_set_chip_present(void *hwdev);
void hifc_force_complete_all(void *hwdev);
void hifc_init_heartbeat(struct hifc_hwdev *hwdev);
void hifc_destroy_heartbeat(struct hifc_hwdev *hwdev);
u8 hifc_nic_sw_aeqe_handler(void *handle, u8 event, u64 data);
int hifc_l2nic_reset_base(struct hifc_hwdev *hwdev, u16 reset_flag);
int hifc_pf_msg_to_mgmt_sync(void *hwdev, enum hifc_mod_type mod, u8 cmd,
void *buf_in, u16 in_size,
void *buf_out, u16 *out_size, u32 timeout);
void hifc_swe_fault_handler(struct hifc_hwdev *hwdev, u8 level,
u8 event, u64 val);
bool hifc_mgmt_event_ack_first(u8 mod, u8 cmd);
int hifc_phy_init_status_judge(void *hwdev);
int hifc_api_csr_rd32(void *hwdev, u8 dest, u32 addr, u32 *val);
int hifc_api_csr_wr32(void *hwdev, u8 dest, u32 addr, u32 val);
void mgmt_heartbeat_event_handler(void *hwdev, void *buf_in, u16 in_size,
void *buf_out, u16 *out_size);
struct hifc_sge {
u32 hi_addr;
u32 lo_addr;
u32 len;
};
void hifc_cpu_to_be32(void *data, int len);
void hifc_be32_to_cpu(void *data, int len);
void hifc_set_sge(struct hifc_sge *sge, dma_addr_t addr, u32 len);
#endif