From 2bc0b8a89be3273815f2e1cae45bd7b0bf14b269 Mon Sep 17 00:00:00 2001 From: Chiqijun Date: Thu, 6 Aug 2020 10:34:00 +0000 Subject: [PATCH] net/hinic: Add read chip register interface driver inclusion category: bugfix bugzilla: 4472 ----------------------------------------------------------------------- When the chip is abnormal, it is necessary to read some of the chip registers, so add an interface to read the chip registers. Signed-off-by: Chiqijun Signed-off-by: Yang Yingliang --- drivers/net/ethernet/huawei/hinic/hinic_dbg.h | 2 + .../net/ethernet/huawei/hinic/hinic_dfx_def.h | 10 +- .../net/ethernet/huawei/hinic/hinic_hwdev.h | 1 + .../net/ethernet/huawei/hinic/hinic_nictool.c | 171 +++++++++++------- .../net/ethernet/huawei/hinic/hinic_sml_lt.c | 78 ++++++-- 5 files changed, 189 insertions(+), 73 deletions(-) diff --git a/drivers/net/ethernet/huawei/hinic/hinic_dbg.h b/drivers/net/ethernet/huawei/hinic/hinic_dbg.h index f87bedfc113e..1b4789fc1de2 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_dbg.h +++ b/drivers/net/ethernet/huawei/hinic/hinic_dbg.h @@ -79,6 +79,8 @@ int hinic_api_csr_wr32(void *hwdev, u8 dest, u32 addr, u32 val); int hinic_api_csr_rd64(void *hwdev, u8 dest, u32 addr, u64 *val); +int hinic_api_csr_wr64(void *hwdev, u8 dest, u32 addr, u64 val); + int hinic_dbg_get_hw_stats(const void *hwdev, u8 *hw_stats, u16 *out_size); u16 hinic_dbg_clear_hw_stats(void *hwdev); diff --git a/drivers/net/ethernet/huawei/hinic/hinic_dfx_def.h b/drivers/net/ethernet/huawei/hinic/hinic_dfx_def.h index 95cb7c40bf12..8767cc077871 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_dfx_def.h +++ b/drivers/net/ethernet/huawei/hinic/hinic_dfx_def.h @@ -102,6 +102,8 @@ enum driver_cmd_type { WIN_CSR_WRITE = 0x62, WIN_API_CMD_RD = 0x63, + GET_NICTOOL_CAP = 0x74, + VM_COMPAT_TEST = 0xFF }; @@ -114,7 +116,9 @@ enum hinic_nic_link_mode { enum api_chain_cmd_type { API_CSR_READ, - API_CSR_WRITE + API_CSR_WRITE, + API_CSR_READ_8B, + API_CSR_WRITE_8B, }; enum sm_cmd_type { @@ -139,4 +143,8 @@ struct hinic_show_item { #define UCODE_COMP_TIME_OUT_VAL 0xFF00000 #define NIC_TOOL_MAGIC 'x' +enum hinic_nictool_drv_cap { + NICTOOL_SUPPORT_API_CSR = 0x1, +}; + #endif /* __HINIC_DFX_DEF_H__ */ diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hwdev.h b/drivers/net/ethernet/huawei/hinic/hinic_hwdev.h index 876bba922839..32e285939d4a 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_hwdev.h +++ b/drivers/net/ethernet/huawei/hinic/hinic_hwdev.h @@ -109,6 +109,7 @@ struct mqm_addr_trans_tbl_info { (HINIC_NODE_ID_MAX * FAULT_LEVEL_MAX * HINIC_CHIP_ERROR_TYPE_MAX) enum hinic_node_id { + HINIC_NODE_ID_CPI = 0, HINIC_NODE_ID_IPSU = 4, HINIC_NODE_ID_MGMT_HOST = 21, /* Host CPU send API to uP */ HINIC_NODE_ID_MAX = 22 diff --git a/drivers/net/ethernet/huawei/hinic/hinic_nictool.c b/drivers/net/ethernet/huawei/hinic/hinic_nictool.c index 54184bdb3fc8..3fcb855bd605 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_nictool.c +++ b/drivers/net/ethernet/huawei/hinic/hinic_nictool.c @@ -1603,74 +1603,87 @@ static int send_to_ucode(void *hwdev, struct msg_module *nt_msg, return ret; } +enum api_csr_op_width { + OP_WIDTH_4B, + OP_WIDTH_8B, + OP_WIDTH_UNKNOWN, +}; + static int api_csr_read(void *hwdev, struct msg_module *nt_msg, - void *buf_in, u32 in_size, void *buf_out, u32 *out_size) + void *buf_in, u32 in_size, void *buf_out, u32 *out_size, + enum api_csr_op_width width) { struct up_log_msg_st *up_log_msg = (struct up_log_msg_st *)buf_in; + u32 op_bytes = (width == OP_WIDTH_4B ? sizeof(u32) : sizeof(u64)); int ret = 0; - u32 rd_len; - u32 rd_addr; - u32 rd_cnt = 0; + u32 rd_len, rd_addr, rd_cnt; u32 offset = 0; u8 node_id; u32 i; if (!buf_in || !buf_out || in_size != sizeof(*up_log_msg) || - *out_size != up_log_msg->rd_len) + *out_size != up_log_msg->rd_len || width >= OP_WIDTH_UNKNOWN) return -EINVAL; rd_len = up_log_msg->rd_len; rd_addr = up_log_msg->addr; node_id = (u8)nt_msg->up_cmd.up_db.comm_mod_type; - rd_cnt = rd_len / 4; + rd_cnt = rd_len / op_bytes; - if (rd_len % 4) + if (rd_len % op_bytes) rd_cnt++; for (i = 0; i < rd_cnt; i++) { - ret = hinic_api_csr_rd32(hwdev, node_id, - rd_addr + offset, - (u32 *)(((u8 *)buf_out) + offset)); + if (width == OP_WIDTH_4B) + ret = hinic_api_csr_rd32(hwdev, node_id, + rd_addr + offset, + (u32 *)(((u8 *)buf_out) + + offset)); + else + ret = hinic_api_csr_rd64(hwdev, node_id, + rd_addr + offset, + (u64 *)(((u8 *)buf_out) + + offset)); if (ret) { - pr_err("Csr rd fail, err: %d, node_id: %d, csr addr: 0x%08x\n", + pr_err("Read csr failed, err: %d, node_id: %d, csr addr: 0x%08x\n", ret, node_id, rd_addr + offset); return ret; } - offset += 4; + offset += op_bytes; } *out_size = rd_len; return ret; } -static int api_csr_write(void *hwdev, struct msg_module *nt_msg, - void *buf_in, u32 in_size, void *buf_out, - u32 *out_size) +static int api_csr_write(void *hwdev, struct msg_module *nt_msg, void *buf_in, + u32 in_size, void *buf_out, u32 *out_size, + enum api_csr_op_width width) { struct csr_write_st *csr_write_msg = (struct csr_write_st *)buf_in; + u32 op_bytes = (width == OP_WIDTH_4B ? sizeof(u32) : sizeof(u64)); int ret = 0; - u32 rd_len; - u32 rd_addr; - u32 rd_cnt = 0; + u32 rd_len, rd_addr, rd_cnt; u32 offset = 0; u8 node_id; u32 i; - u8 *data; + u8 *data = NULL; - if (!buf_in || in_size != sizeof(*csr_write_msg)) + if (!buf_in || in_size != sizeof(*csr_write_msg) || + width >= OP_WIDTH_UNKNOWN) return -EINVAL; rd_len = csr_write_msg->rd_len; rd_addr = csr_write_msg->addr; node_id = (u8)nt_msg->up_cmd.up_db.comm_mod_type; - if (rd_len % 4) { - pr_err("Csr length must be a multiple of 4\n"); + if (rd_len % op_bytes) { + pr_err("Csr length must be a multiple of %d\n", op_bytes); return -EFAULT; } - rd_cnt = rd_len / 4; + rd_cnt = rd_len / op_bytes; data = kzalloc(rd_len, GFP_KERNEL); if (!data) { pr_err("No more memory\n"); @@ -1683,16 +1696,21 @@ static int api_csr_write(void *hwdev, struct msg_module *nt_msg, } for (i = 0; i < rd_cnt; i++) { - ret = hinic_api_csr_wr32(hwdev, node_id, - rd_addr + offset, - *((u32 *)(data + offset))); + if (width == OP_WIDTH_4B) + ret = hinic_api_csr_wr32(hwdev, node_id, + rd_addr + offset, + *((u32 *)(data + offset))); + else + ret = hinic_api_csr_wr64(hwdev, node_id, + rd_addr + offset, + *((u64 *)(data + offset))); if (ret) { - pr_err("Csr wr fail, ret: %d, node_id: %d, csr addr: 0x%08x\n", + pr_err("Write csr failed, ret: %d, node_id: %d, csr addr: 0x%08x\n", ret, rd_addr + offset, node_id); kfree(data); return ret; } - offset += 4; + offset += op_bytes; } *out_size = 0; @@ -1756,14 +1774,29 @@ static int send_to_up(void *hwdev, struct msg_module *nt_msg, if (check_useparam_valid(nt_msg, buf_in)) return -EINVAL; - if (nt_msg->up_cmd.up_db.chipif_cmd == API_CSR_WRITE) { - ret = api_csr_write(hwdev, nt_msg, buf_in, - in_size, buf_out, out_size); - return ret; + switch (nt_msg->up_cmd.up_db.chipif_cmd) { + case API_CSR_WRITE: + ret = api_csr_write(hwdev, nt_msg, buf_in, in_size, + buf_out, out_size, OP_WIDTH_4B); + break; + case API_CSR_READ: + ret = api_csr_read(hwdev, nt_msg, buf_in, in_size, + buf_out, out_size, OP_WIDTH_4B); + break; + case API_CSR_WRITE_8B: + ret = api_csr_write(hwdev, nt_msg, buf_in, in_size, + buf_out, out_size, OP_WIDTH_8B); + break; + case API_CSR_READ_8B: + ret = api_csr_read(hwdev, nt_msg, buf_in, in_size, + buf_out, out_size, OP_WIDTH_8B); + break; + default: + pr_err("Unsupported chipif cmd: %d\n", + nt_msg->up_cmd.up_db.chipif_cmd); + ret = -EINVAL; + break; } - - ret = api_csr_read(hwdev, nt_msg, buf_in, - in_size, buf_out, out_size); } return ret; @@ -2167,42 +2200,58 @@ static int nictool_exec_cmd(void *hwdev, struct msg_module *nt_msg, return ret; } -static bool hinic_is_special_handling_cmd(struct msg_module *nt_msg, int *ret) +static int get_nictool_drv_cap(struct msg_module *nt_msg) { - unsigned int cmd_raw = nt_msg->module; + int ret; + u64 support = 0; - /* Get self test result directly whatever driver probe success or not */ - if (cmd_raw == SEND_TO_HW_DRIVER && - nt_msg->msg_formate == GET_SELF_TEST_RES) { - *ret = get_self_test_cmd(nt_msg); - return true; + if (nt_msg->lenInfo.outBuffLen != sizeof(u64)) { + pr_err("Unexpect out buf size from user: %d, expect: %lu\n", + nt_msg->lenInfo.outBuffLen, sizeof(u64)); + return -EINVAL; } - if (cmd_raw == SEND_TO_HW_DRIVER && - nt_msg->msg_formate == GET_CHIP_ID) { - *ret = get_all_chip_id_cmd(nt_msg); - return true; - } + support |= NICTOOL_SUPPORT_API_CSR; - if (cmd_raw == SEND_TO_HW_DRIVER && - nt_msg->msg_formate == GET_PF_DEV_INFO) { - *ret = get_pf_dev_info(nt_msg->device_name, nt_msg); - return true; - } + ret = copy_buf_out_to_user(nt_msg, sizeof(support), &support); + if (ret) + pr_err("%s:%d:: Copy to user failed\n", __func__, __LINE__); - if (cmd_raw == SEND_TO_HW_DRIVER && - nt_msg->msg_formate == CMD_FREE_MEM) { - *ret = knl_free_mem(nt_msg->device_name, nt_msg); - return true; - } + return ret; +} - if (cmd_raw == SEND_TO_HW_DRIVER && - nt_msg->msg_formate == GET_CHIP_INFO) { +static bool hinic_is_special_handling_cmd(struct msg_module *nt_msg, int *ret) +{ + bool handled = true; + + if (nt_msg->module != SEND_TO_HW_DRIVER) + return false; + + switch (nt_msg->msg_formate) { + case GET_SELF_TEST_RES: + *ret = get_self_test_cmd(nt_msg); + break; + case GET_CHIP_ID: + *ret = get_all_chip_id_cmd(nt_msg); + break; + case GET_PF_DEV_INFO: + *ret = get_pf_dev_info(nt_msg->device_name, nt_msg); + break; + case CMD_FREE_MEM: + *ret = knl_free_mem(nt_msg->device_name, nt_msg); + break; + case GET_CHIP_INFO: *ret = get_card_func_info(nt_msg->device_name, nt_msg); - return true; + break; + case GET_NICTOOL_CAP: + *ret = get_nictool_drv_cap(nt_msg); + break; + default: + handled = false; + break; } - return false; + return handled; } static long nictool_k_unlocked_ioctl(struct file *pfile, diff --git a/drivers/net/ethernet/huawei/hinic/hinic_sml_lt.c b/drivers/net/ethernet/huawei/hinic/hinic_sml_lt.c index ad13f70d0ffa..c4afc1a14109 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_sml_lt.c +++ b/drivers/net/ethernet/huawei/hinic/hinic_sml_lt.c @@ -27,6 +27,8 @@ #include "hinic_sm_lt.h" #include "hinic_hw.h" #include "hinic_hwdev.h" +#include "hinic_hw_mgmt.h" +#include "hinic_hwif.h" #include "hinic_dbg.h" #define ACK 1 @@ -35,6 +37,9 @@ #define LT_LOAD16_API_SIZE (16 + 4) #define LT_STORE16_API_SIZE (32 + 4) +#define HINIC_API_RD_8B 8 +#define HINIC_API_RD_4B 4 + static inline void sm_lt_build_head(sml_lt_req_head_u *head, u8 instance_id, u8 op_id, u8 ack, @@ -132,7 +137,8 @@ EXPORT_SYMBOL(hinic_dbg_lt_wr_16byte_mask); int hinic_api_csr_rd32(void *hwdev, u8 dest, u32 addr, u32 *val) { - struct hinic_csr_request_api_data api_data = {0}; + struct hinic_hwdev *dev = hwdev; + struct hinic_csr_request_api_data api_data = { 0 }; u32 csr_val = 0; u16 in_size = sizeof(api_data); int ret; @@ -140,7 +146,11 @@ int hinic_api_csr_rd32(void *hwdev, u8 dest, u32 addr, u32 *val) if (!hwdev || !val) return -EFAULT; - memset(&api_data, 0, sizeof(struct hinic_csr_request_api_data)); + if (dest == HINIC_NODE_ID_CPI) { + *val = readl(dev->hwif->cfg_regs_base + addr); + return 0; + } + api_data.dw0 = 0; api_data.dw1.bits.operation_id = HINIC_CSR_OPERATION_READ_CSR; api_data.dw1.bits.need_response = HINIC_CSR_NEED_RESP_DATA; @@ -150,10 +160,10 @@ int hinic_api_csr_rd32(void *hwdev, u8 dest, u32 addr, u32 *val) api_data.dw2.val32 = cpu_to_be32(api_data.dw2.val32); ret = hinic_api_cmd_read_ack(hwdev, dest, (u8 *)(&api_data), - in_size, &csr_val, 4); + in_size, &csr_val, HINIC_API_RD_4B); if (ret) { sdk_err(((struct hinic_hwdev *)hwdev)->dev_hdl, - "Read 32 bit csr fail, dest %d addr 0x%x, ret: 0x%x\n", + "Read 32 bit csr failed, dest %d addr 0x%x, ret: 0x%x\n", dest, addr, ret); return ret; } @@ -166,14 +176,19 @@ EXPORT_SYMBOL(hinic_api_csr_rd32); int hinic_api_csr_wr32(void *hwdev, u8 dest, u32 addr, u32 val) { - struct hinic_csr_request_api_data api_data; + struct hinic_hwdev *dev = hwdev; + struct hinic_csr_request_api_data api_data = { 0 }; u16 in_size = sizeof(api_data); int ret; if (!hwdev) return -EFAULT; - memset(&api_data, 0, sizeof(struct hinic_csr_request_api_data)); + if (dest == HINIC_NODE_ID_CPI) { + writel(val, dev->hwif->cfg_regs_base + addr); + return 0; + } + api_data.dw1.bits.operation_id = HINIC_CSR_OPERATION_WRITE_CSR; api_data.dw1.bits.need_response = HINIC_CSR_NO_RESP_DATA; api_data.dw1.bits.data_size = HINIC_CSR_DATA_SZ_32; @@ -186,7 +201,7 @@ int hinic_api_csr_wr32(void *hwdev, u8 dest, u32 addr, u32 val) ret = hinic_api_cmd_write_nack(hwdev, dest, (u8 *)(&api_data), in_size); if (ret) { sdk_err(((struct hinic_hwdev *)hwdev)->dev_hdl, - "Write 32 bit csr fail! dest %d addr 0x%x val 0x%x\n", + "Write 32 bit csr failed, dest %d addr 0x%x val 0x%x\n", dest, addr, val); return ret; } @@ -197,7 +212,7 @@ EXPORT_SYMBOL(hinic_api_csr_wr32); int hinic_api_csr_rd64(void *hwdev, u8 dest, u32 addr, u64 *val) { - struct hinic_csr_request_api_data api_data = {0}; + struct hinic_csr_request_api_data api_data = { 0 }; u64 csr_val = 0; u16 in_size = sizeof(api_data); int ret; @@ -205,7 +220,12 @@ int hinic_api_csr_rd64(void *hwdev, u8 dest, u32 addr, u64 *val) if (!hwdev || !val) return -EFAULT; - memset(&api_data, 0, sizeof(struct hinic_csr_request_api_data)); + if (dest == HINIC_NODE_ID_CPI) { + sdk_err(((struct hinic_hwdev *)hwdev)->dev_hdl, + "Unsupport to read 64 bit csr from cpi\n"); + return -EOPNOTSUPP; + } + api_data.dw0 = 0; api_data.dw1.bits.operation_id = HINIC_CSR_OPERATION_READ_CSR; api_data.dw1.bits.need_response = HINIC_CSR_NEED_RESP_DATA; @@ -215,10 +235,10 @@ int hinic_api_csr_rd64(void *hwdev, u8 dest, u32 addr, u64 *val) api_data.dw2.val32 = cpu_to_be32(api_data.dw2.val32); ret = hinic_api_cmd_read_ack(hwdev, dest, (u8 *)(&api_data), - in_size, &csr_val, 8); + in_size, &csr_val, HINIC_API_RD_8B); if (ret) { sdk_err(((struct hinic_hwdev *)hwdev)->dev_hdl, - "Read 64 bit csr fail, dest %d addr 0x%x\n", + "Read 64 bit csr failed, dest %d addr 0x%x\n", dest, addr); return ret; } @@ -228,3 +248,39 @@ int hinic_api_csr_rd64(void *hwdev, u8 dest, u32 addr, u64 *val) return 0; } EXPORT_SYMBOL(hinic_api_csr_rd64); + +int hinic_api_csr_wr64(void *hwdev, u8 dest, u32 addr, u64 val) +{ + struct hinic_csr_request_api_data api_data = { 0 }; + u16 in_size = sizeof(api_data); + int ret; + + if (!hwdev || !val) + return -EFAULT; + + if (dest == HINIC_NODE_ID_CPI) { + sdk_err(((struct hinic_hwdev *)hwdev)->dev_hdl, + "Unsupport to write 64 bit csr from cpi\n"); + return -EOPNOTSUPP; + } + + api_data.dw0 = 0; + api_data.dw1.bits.operation_id = HINIC_CSR_OPERATION_WRITE_CSR; + api_data.dw1.bits.need_response = HINIC_CSR_NO_RESP_DATA; + api_data.dw1.bits.data_size = HINIC_CSR_DATA_SZ_64; + api_data.dw1.val32 = cpu_to_be32(api_data.dw1.val32); + api_data.dw2.bits.csr_addr = addr; + api_data.dw2.val32 = cpu_to_be32(api_data.dw2.val32); + api_data.csr_write_data_h = cpu_to_be32(upper_32_bits(val)); + api_data.csr_write_data_l = cpu_to_be32(lower_32_bits(val)); + + ret = hinic_api_cmd_write_nack(hwdev, dest, (u8 *)(&api_data), in_size); + if (ret) { + sdk_err(((struct hinic_hwdev *)hwdev)->dev_hdl, + "Write 64 bit csr failed, dest %d addr 0x%x val 0x%llx\n", + dest, addr, val); + return ret; + } + + return 0; +} -- GitLab