// SPDX-License-Identifier: GPL-2.0 /* Huawei Hifc PCI Express Linux driver * Copyright(c) 2017 Huawei Technologies Co., Ltd * */ #define pr_fmt(fmt) KBUILD_MODNAME ": [COMM]" fmt #include #include #include #include #include #include #include "hifc_knl_adp.h" #include "hifc_hw.h" #include "hifc_hwdev.h" #include "hifc_hwif.h" #include "hifc_api_cmd.h" #include "hifc_mgmt.h" #include "hifc_cfg.h" #include "hifc_lld.h" #include "hifc_sml.h" #include "hifc_tool.h" static atomic_t tool_used_cnt; typedef int (*hw_driv_module)(void *hwdev, void *buf_in, u32 in_size, void *buf_out, u32 *out_size); struct hw_drv_module_handle { enum driver_cmd_type driv_cmd_name; hw_driv_module driv_func; }; u8 hifc_physical_port_id(void *hwdev) { struct hifc_hwdev *dev = hwdev; if (!dev) { pr_err("Hwdev pointer is NULL for getting physical port id\n"); return 0; } return dev->cfg_mgmt->svc_cap.port_id; } int hifc_clp_to_mgmt(void *hwdev, enum hifc_mod_type mod, u8 cmd, void *buf_in, u16 in_size, void *buf_out, u16 *out_size) { struct hifc_hwdev *dev = hwdev; int err; if (!dev) return -EINVAL; if (!dev->chip_present_flag) return -EPERM; if (!hifc_is_hwdev_mod_inited(hwdev, HIFC_HWDEV_CLP_INITED)) return -EPERM; err = hifc_pf_clp_to_mgmt(dev, mod, cmd, buf_in, in_size, buf_out, out_size); return err; } static int get_func_type(void *hwdev, void *buf_in, u32 in_size, void *buf_out, u32 *out_size) { u16 func_typ; func_typ = hifc_func_type(hwdev); if (!buf_out || *out_size != sizeof(u16)) { pr_err("Unexpect out buf size from user :%d, expect: %lu\n", *out_size, sizeof(u16)); return -EFAULT; } *(u16 *)buf_out = func_typ; return 0; } static int get_func_id(void *hwdev, void *buf_in, u32 in_size, void *buf_out, u32 *out_size) { u16 func_id; if (!buf_out || *out_size != sizeof(u16)) { pr_err("Unexpect out buf size from user :%d, expect: %lu\n", *out_size, sizeof(u16)); return -EFAULT; } func_id = hifc_global_func_id_hw(hwdev); *(u16 *)buf_out = func_id; *out_size = sizeof(u16); return 0; } static int get_drv_version(void *hwdev, void *buf_in, u32 in_size, void *buf_out, u32 *out_size) { struct drv_version_info *ver_info; char ver_str[MAX_VER_INFO_LEN] = {0}; if (*out_size != sizeof(*ver_info)) { pr_err("Unexpect out buf size from user :%d, expect: %lu\n", *out_size, sizeof(*ver_info)); return -EFAULT; } snprintf(ver_str, sizeof(ver_str), "%s %s", HIFC_DRV_VERSION, __TIME_STR__); ver_info = (struct drv_version_info *)buf_out; memcpy(ver_info->ver, ver_str, sizeof(ver_str)); return 0; } static int clear_hw_stats(void *hwdev, void *buf_in, u32 in_size, void *buf_out, u32 *out_size) { return 0; } static int get_hw_stats(void *hwdev, void *buf_in, u32 in_size, void *buf_out, u32 *out_size) { return 0; } static void hifc_get_chip_fault_stats(const void *hwdev, u8 *chip_fault_stats, int offset) { int copy_len = offset + MAX_DRV_BUF_SIZE - HIFC_CHIP_FAULT_SIZE; if (offset < 0 || offset > HIFC_CHIP_FAULT_SIZE) { pr_err("Invalid chip offset value: %d\n", offset); return; } if (offset + MAX_DRV_BUF_SIZE <= HIFC_CHIP_FAULT_SIZE) memcpy(chip_fault_stats, ((struct hifc_hwdev *)hwdev)->chip_fault_stats + offset, MAX_DRV_BUF_SIZE); else memcpy(chip_fault_stats, ((struct hifc_hwdev *)hwdev)->chip_fault_stats + offset, copy_len); } static int get_chip_faults_stats(void *hwdev, void *buf_in, u32 in_size, void *buf_out, u32 *out_size) { int offset = 0; struct chip_fault_stats *fault_info; if (!buf_in || !buf_out || *out_size != sizeof(*fault_info) || in_size != sizeof(*fault_info)) { pr_err("Unexpect out buf size from user :%d, expect: %lu\n", *out_size, sizeof(*fault_info)); return -EFAULT; } fault_info = (struct chip_fault_stats *)buf_in; offset = fault_info->offset; fault_info = (struct chip_fault_stats *)buf_out; hifc_get_chip_fault_stats(hwdev, fault_info->chip_faults, offset); return 0; } static int get_chip_id_test(void *hwdev, void *buf_in, u32 in_size, void *buf_out, u32 *out_size) { return 0; } static int get_single_card_info(void *hwdev, void *buf_in, u32 in_size, void *buf_out, u32 *out_size) { if (!buf_in || !buf_out || in_size != sizeof(struct card_info) || *out_size != sizeof(struct card_info)) { pr_err("Unexpect out buf size from user :%d, expect: %lu\n", *out_size, sizeof(struct card_info)); return -EFAULT; } hifc_get_card_info(hwdev, buf_out); *out_size = in_size; return 0; } #define GET_FIRMWARE_ACTIVE_STATUS_TIMEOUT 30 static int get_firmware_active_status(void *hwdev, void *buf_in, u32 in_size, void *buf_out, u32 *out_size) { u32 loop_cnt = 0; while (loop_cnt < GET_FIRMWARE_ACTIVE_STATUS_TIMEOUT) { if (!hifc_get_mgmt_channel_status(hwdev)) return 0; msleep(1000); loop_cnt++; } if (loop_cnt == GET_FIRMWARE_ACTIVE_STATUS_TIMEOUT) return -ETIMEDOUT; return 0; } static int get_device_id(void *hwdev, void *buf_in, u32 in_size, void *buf_out, u32 *out_size) { u16 dev_id; int err; if (!buf_out || !buf_in || *out_size != sizeof(u16) || in_size != sizeof(u16)) { pr_err("Unexpect out buf size from user :%d, expect: %lu\n", *out_size, sizeof(u16)); return -EFAULT; } err = hifc_get_device_id(hwdev, &dev_id); if (err) return err; *((u32 *)buf_out) = dev_id; *out_size = in_size; return 0; } bool hifc_is_in_host(void) { struct card_node *chip_node; struct hifc_pcidev *dev; lld_dev_hold(); list_for_each_entry(chip_node, &g_hinic_chip_list, node) { list_for_each_entry(dev, &chip_node->func_list, node) { if (test_bit(HIFC_FUNC_IN_REMOVE, &dev->flag)) continue; if (dev->init_state > HIFC_INIT_STATE_PCI_INITED) { lld_dev_put(); return true; } } } lld_dev_put(); return false; } static int is_driver_in_vm(void *hwdev, void *buf_in, u32 in_size, void *buf_out, u32 *out_size) { bool in_host; if (!buf_out || (*out_size != sizeof(u8))) return -EINVAL; in_host = hifc_is_in_host(); if (in_host) *((u8 *)buf_out) = 0; else *((u8 *)buf_out) = 1; return 0; } static int get_pf_id(void *hwdev, void *buf_in, u32 in_size, void *buf_out, u32 *out_size) { struct hifc_pf_info *pf_info; u32 port_id = 0; int err; if (!buf_out || (*out_size != sizeof(*pf_info)) || !buf_in || in_size != sizeof(u32)) return -EINVAL; port_id = *((u32 *)buf_in); pf_info = (struct hifc_pf_info *)buf_out; err = hifc_get_pf_id(hwdev, port_id, &pf_info->pf_id, &pf_info->isvalid); if (err) return err; *out_size = sizeof(*pf_info); return 0; } static struct hw_drv_module_handle hw_driv_module_cmd_handle[] = { {FUNC_TYPE, get_func_type}, {GET_FUNC_IDX, get_func_id}, {GET_DRV_VERSION, get_drv_version}, {GET_HW_STATS, get_hw_stats}, {CLEAR_HW_STATS, clear_hw_stats}, {GET_CHIP_FAULT_STATS, get_chip_faults_stats}, {GET_CHIP_ID, get_chip_id_test}, {GET_SINGLE_CARD_INFO, get_single_card_info}, {GET_FIRMWARE_ACTIVE_STATUS, get_firmware_active_status}, {GET_DEVICE_ID, get_device_id}, {IS_DRV_IN_VM, is_driver_in_vm}, {GET_PF_ID, get_pf_id}, }; int send_to_hw_driver(void *hwdev, struct msg_module *nt_msg, void *buf_in, u32 in_size, void *buf_out, u32 *out_size) { int index, num_cmds = sizeof(hw_driv_module_cmd_handle) / sizeof(hw_driv_module_cmd_handle[0]); enum driver_cmd_type cmd_type; int err = 0; if (!nt_msg) { pr_err("Input param invalid!\n"); return -EINVAL; } cmd_type = (enum driver_cmd_type)(nt_msg->msg_formate); for (index = 0; index < num_cmds; index++) { if (cmd_type == hw_driv_module_cmd_handle[index].driv_cmd_name) { err = hw_driv_module_cmd_handle[index].driv_func (hwdev, buf_in, in_size, buf_out, out_size); break; } } if (index == num_cmds) return -EINVAL; return err; } typedef int (*sm_module)(void *hwdev, u32 id, u8 instance, u8 node, struct sm_out_st *buf_out); static int sm_rd32(void *hwdev, u32 id, u8 instance, u8 node, struct sm_out_st *buf_out) { u32 val1; int ret; ret = hifc_sm_ctr_rd32(hwdev, node, instance, id, &val1); if (ret) { pr_err("Get sm ctr information (32 bits)failed!\n"); val1 = 0xffffffff; } buf_out->val1 = val1; return ret; } static int sm_rd64_pair(void *hwdev, u32 id, u8 instance, u8 node, struct sm_out_st *buf_out) { u64 val1 = 0, val2 = 0; int ret; ret = hifc_sm_ctr_rd64_pair(hwdev, node, instance, id, &val1, &val2); if (ret) { pr_err("Get sm ctr information (64 bits pair)failed!\n"); val1 = 0xffffffff; } buf_out->val1 = val1; buf_out->val2 = val2; return ret; } static int sm_rd64(void *hwdev, u32 id, u8 instance, u8 node, struct sm_out_st *buf_out) { u64 val1; int ret; ret = hifc_sm_ctr_rd64(hwdev, node, instance, id, &val1); if (ret) { pr_err("Get sm ctr information (64 bits)failed!\n"); val1 = 0xffffffff; } buf_out->val1 = val1; return ret; } struct sm_module_handle { enum sm_cmd_type sm_cmd_name; sm_module sm_func; }; struct sm_module_handle sm_module_cmd_handle[] = { {SM_CTR_RD32, sm_rd32}, {SM_CTR_RD64_PAIR, sm_rd64_pair}, {SM_CTR_RD64, sm_rd64} }; int send_to_sm(void *hwdev, struct msg_module *nt_msg, void *buf_in, u32 in_size, void *buf_out, u32 *out_size) { struct sm_in_st *sm_in = buf_in; struct sm_out_st *sm_out = buf_out; u32 msg_formate; int index, num_cmds = sizeof(sm_module_cmd_handle) / sizeof(sm_module_cmd_handle[0]); int ret = 0; if ((!nt_msg) || (!buf_in) || (!buf_out) || (in_size != sizeof(*sm_in)) || (*out_size != sizeof(*sm_out))) { pr_err("Input param invalid!\n"); return -EINVAL; } msg_formate = nt_msg->msg_formate; for (index = 0; index < num_cmds; index++) { if (msg_formate == sm_module_cmd_handle[index].sm_cmd_name) ret = sm_module_cmd_handle[index].sm_func(hwdev, (u32)sm_in->id, (u8)sm_in->instance, (u8)sm_in->node, sm_out); } if (ret) pr_err("Get sm information fail!\n"); *out_size = sizeof(struct sm_out_st); return ret; } static u32 get_up_timeout_val(enum hifc_mod_type mod, u8 cmd) { #define UP_UPDATEFW_TIME_OUT_VAL 20000U if (mod == HIFC_MOD_L2NIC && cmd == NIC_UP_CMD_UPDATE_FW) return UP_UPDATEFW_TIME_OUT_VAL; else return UP_COMP_TIME_OUT_VAL; } static int api_csr_write(void *hwdev, struct msg_module *nt_msg, void *buf_in, u32 in_size, void *buf_out, u32 *out_size) { struct csr_write_st *csr_write_msg = (struct csr_write_st *)buf_in; int ret = 0; u32 rd_len; u32 rd_addr; u32 rd_cnt = 0; u32 offset = 0; u8 node_id; u32 i; u8 *data; if (!buf_in || in_size != sizeof(*csr_write_msg)) 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"); return -EFAULT; } rd_cnt = rd_len / 4; data = kzalloc(rd_len, GFP_KERNEL); if (!data) { pr_err("No more memory\n"); return -EFAULT; } if (copy_from_user(data, (void *)csr_write_msg->data, rd_len)) { pr_err("Copy information from user failed\n"); kfree(data); return -EFAULT; } for (i = 0; i < rd_cnt; i++) { ret = hifc_api_csr_wr32(hwdev, node_id, rd_addr + offset, *((u32 *)(data + offset))); if (ret) { pr_err("Csr wr fail, ret: %d, node_id: %d, csr addr: 0x%08x\n", ret, rd_addr + offset, node_id); kfree(data); return ret; } offset += 4; } *out_size = 0; kfree(data); return ret; } static int api_csr_read(void *hwdev, struct msg_module *nt_msg, void *buf_in, u32 in_size, void *buf_out, u32 *out_size) { struct up_log_msg_st *up_log_msg = (struct up_log_msg_st *)buf_in; int ret = 0; u32 rd_len; u32 rd_addr; u32 rd_cnt = 0; 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) 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; if (rd_len % 4) rd_cnt++; for (i = 0; i < rd_cnt; i++) { ret = hifc_api_csr_rd32(hwdev, node_id, rd_addr + offset, (u32 *)(((u8 *)buf_out) + offset)); if (ret) { pr_err("Csr rd fail, err: %d, node_id: %d, csr addr: 0x%08x\n", ret, node_id, rd_addr + offset); return ret; } offset += 4; } *out_size = rd_len; return ret; } int send_to_up(void *hwdev, struct msg_module *nt_msg, void *buf_in, u32 in_size, void *buf_out, u32 *out_size) { int ret = 0; if ((!nt_msg) || (!hwdev) || (!buf_in) || (!buf_out)) { pr_err("Input param invalid!\n"); return -EINVAL; } if ((nt_msg->up_cmd.up_db.up_api_type == API_CMD) || (nt_msg->up_cmd.up_db.up_api_type == API_CLP)) { enum hifc_mod_type mod; u8 cmd; u32 timeout; mod = (enum hifc_mod_type)nt_msg->up_cmd.up_db.comm_mod_type; cmd = nt_msg->up_cmd.up_db.chipif_cmd; timeout = get_up_timeout_val(mod, cmd); if (nt_msg->up_cmd.up_db.up_api_type == API_CMD) ret = hifc_msg_to_mgmt_sync(hwdev, mod, cmd, buf_in, (u16)in_size, buf_out, (u16 *)out_size, timeout); else ret = hifc_clp_to_mgmt(hwdev, mod, cmd, buf_in, (u16)in_size, buf_out, (u16 *)out_size); if (ret) { pr_err("Message to mgmt cpu return fail, mod: %d, cmd: %d\n", mod, cmd); return ret; } } else if (nt_msg->up_cmd.up_db.up_api_type == API_CHAIN) { 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; } ret = api_csr_read(hwdev, nt_msg, buf_in, in_size, buf_out, out_size); } return ret; } int send_to_ucode(void *hwdev, struct msg_module *nt_msg, void *buf_in, u32 in_size, void *buf_out, u32 *out_size) { int ret = 0; if ((!nt_msg) || (!hwdev) || (!buf_in)) { pr_err("Input param invalid!\n"); return -EINVAL; } if (nt_msg->ucode_cmd.ucode_db.ucode_imm) { ret = hifc_cmdq_direct_resp (hwdev, nt_msg->ucode_cmd.ucode_db.cmdq_ack_type, nt_msg->ucode_cmd.ucode_db.comm_mod_type, nt_msg->ucode_cmd.ucode_db.ucode_cmd_type, buf_in, buf_out, 0); if (ret) pr_err("Send direct cmdq err: %d!\n", ret); } else { ret = hifc_cmdq_detail_resp (hwdev, nt_msg->ucode_cmd.ucode_db.cmdq_ack_type, nt_msg->ucode_cmd.ucode_db.comm_mod_type, nt_msg->ucode_cmd.ucode_db.ucode_cmd_type, buf_in, buf_out, 0); if (ret) pr_err("Send detail cmdq err: %d!\n", ret); } return ret; } void hifc_tool_cnt_inc(void) { atomic_inc(&tool_used_cnt); } void hifc_tool_cnt_dec(void) { atomic_dec(&tool_used_cnt); } static bool __is_pcidev_match_chip_name(const char *ifname, struct hifc_pcidev *dev, struct card_node *chip_node, enum func_type type) { if (!strncmp(chip_node->chip_name, ifname, IFNAMSIZ)) { if (type == TYPE_UNKNOWN) { if (dev->init_state < HIFC_INIT_STATE_HW_PART_INITED) return false; } else { if (dev->init_state >= HIFC_INIT_STATE_HW_PART_INITED && hifc_func_type(dev->hwdev) != type) return false; } return true; } return false; } static struct hifc_pcidev *_get_pcidev_by_chip_name(char *ifname, enum func_type type) { struct card_node *chip_node; struct hifc_pcidev *dev; lld_dev_hold(); list_for_each_entry(chip_node, &g_hinic_chip_list, node) { list_for_each_entry(dev, &chip_node->func_list, node) { if (test_bit(HIFC_FUNC_IN_REMOVE, &dev->flag)) continue; if (__is_pcidev_match_chip_name(ifname, dev, chip_node, type)) { lld_dev_put(); return dev; } } } lld_dev_put(); return NULL; } static struct hifc_pcidev *hifc_get_pcidev_by_chip_name(char *ifname) { struct hifc_pcidev *dev, *dev_hw_init; /* find hw init device first */ dev_hw_init = _get_pcidev_by_chip_name(ifname, TYPE_UNKNOWN); if (dev_hw_init) { if (hifc_func_type(dev_hw_init->hwdev) == TYPE_PPF) return dev_hw_init; } dev = _get_pcidev_by_chip_name(ifname, TYPE_PPF); if (dev) { if (dev_hw_init && (dev_hw_init->init_state >= dev->init_state)) return dev_hw_init; return dev; } dev = _get_pcidev_by_chip_name(ifname, TYPE_PF); if (dev) { if (dev_hw_init && (dev_hw_init->init_state >= dev->init_state)) return dev_hw_init; return dev; } return NULL; } static struct hifc_pcidev *hifc_get_pcidev_by_ifname(char *ifname) { struct hifc_pcidev *dev; /* support search hwdev by chip name, net device name, * or fc device name */ /* Find pcidev by chip_name first */ dev = hifc_get_pcidev_by_chip_name(ifname); if (dev) return dev; /* If ifname not a chip name, * find pcidev by FC name or netdevice name */ return hifc_get_pcidev_by_dev_name(ifname); } void *hifc_get_hwdev_by_ifname(char *ifname) { struct hifc_pcidev *dev; if (!ifname) { pr_err("Input param invalid!\n"); return NULL; } dev = hifc_get_pcidev_by_ifname(ifname); if (dev) return dev->hwdev; return NULL; } enum hifc_init_state hifc_get_init_state_by_ifname(char *ifname) { struct hifc_pcidev *dev; if (!ifname) { pr_err("Input param invalid!\n"); return HIFC_INIT_STATE_NONE; } dev = hifc_get_pcidev_by_ifname(ifname); if (dev) return dev->init_state; pr_err("Can not get device %s\n", ifname); return HIFC_INIT_STATE_NONE; } void get_fc_devname(char *devname) { struct card_node *chip_node; struct hifc_pcidev *dev; if (!devname) { pr_err("Input param invalid!\n"); return; } lld_dev_hold(); list_for_each_entry(chip_node, &g_hinic_chip_list, node) { list_for_each_entry(dev, &chip_node->func_list, node) { if (test_bit(HIFC_FUNC_IN_REMOVE, &dev->flag)) continue; if (dev->init_state < HIFC_INIT_STATE_ALL_INITED) continue; if (dev->uld_dev) { strlcpy(devname, (char *)dev->uld_dev_name, IFNAMSIZ); lld_dev_put(); return; } } } lld_dev_put(); } void hifc_get_all_chip_id(void *id_info) { struct nic_card_id *card_id = (struct nic_card_id *)id_info; struct card_node *chip_node; int i = 0; int id, err; if (!card_id) { pr_err("Input param invalid!\n"); return; } lld_dev_hold(); list_for_each_entry(chip_node, &g_hinic_chip_list, node) { err = sscanf(chip_node->chip_name, HIFC_CHIP_NAME "%d", &id); if (err < 0) pr_err("Failed to get hifc id\n"); card_id->id[i] = id; i++; } lld_dev_put(); card_id->num = i; } static struct card_node *hifc_get_chip_node_by_hwdev(const void *hwdev) { struct card_node *chip_node = NULL; struct card_node *node_tmp = NULL; struct hifc_pcidev *dev; if (!hwdev) return NULL; lld_dev_hold(); list_for_each_entry(node_tmp, &g_hinic_chip_list, node) { if (!chip_node) { list_for_each_entry(dev, &node_tmp->func_list, node) { if (test_bit(HIFC_FUNC_IN_REMOVE, &dev->flag)) continue; if (dev->hwdev == hwdev) { chip_node = node_tmp; break; } } } } lld_dev_put(); return chip_node; } int hifc_get_device_id(void *hwdev, u16 *dev_id) { struct card_node *chip_node = NULL; struct hifc_pcidev *dev; u16 vendor_id = 0; u16 device_id = 0; if ((!dev_id) || (!hwdev)) { pr_err("Input param invalid!\n"); return -ENODEV; } chip_node = hifc_get_chip_node_by_hwdev(hwdev); if (!chip_node) return -ENODEV; lld_dev_hold(); list_for_each_entry(dev, &chip_node->func_list, node) { if (test_bit(HIFC_FUNC_IN_REMOVE, &dev->flag)) continue; pci_read_config_word(dev->pcidev, 0, &vendor_id); if (vendor_id == HIFC_PCI_VENDOR_ID) { pci_read_config_word(dev->pcidev, 2, &device_id); break; } } lld_dev_put(); *dev_id = device_id; return 0; } int hifc_get_pf_id(void *hwdev, u32 port_id, u32 *pf_id, u32 *isvalid) { struct card_node *chip_node = NULL; struct hifc_pcidev *dev; if ((!isvalid) || (!pf_id) || (!hwdev)) { pr_err("Input param invalid!\n"); return -ENODEV; } chip_node = hifc_get_chip_node_by_hwdev(hwdev); if (!chip_node) return -ENODEV; lld_dev_hold(); list_for_each_entry(dev, &chip_node->func_list, node) { if (hifc_physical_port_id(dev->hwdev) == port_id) { *pf_id = hifc_global_func_id(dev->hwdev); *isvalid = 1; break; } } lld_dev_put(); return 0; } bool hifc_is_valid_bar_addr(u64 offset) { struct card_node *chip_node = NULL; struct hifc_pcidev *dev; lld_dev_hold(); list_for_each_entry(chip_node, &g_hinic_chip_list, node) { list_for_each_entry(dev, &chip_node->func_list, node) { if (test_bit(HIFC_FUNC_IN_REMOVE, &dev->flag)) continue; if (offset == pci_resource_start(dev->pcidev, 0)) { lld_dev_put(); return true; } } } lld_dev_put(); return false; } void hifc_get_card_func_info_by_card_name( const char *chip_name, struct hifc_card_func_info *card_func) { struct card_node *chip_node = NULL; struct hifc_pcidev *dev; struct func_pdev_info *pdev_info; if ((!card_func) || (!chip_name)) { pr_err("Input param invalid!\n"); return; } card_func->num_pf = 0; lld_dev_hold(); list_for_each_entry(chip_node, &g_hinic_chip_list, node) { if (strncmp(chip_node->chip_name, chip_name, IFNAMSIZ)) continue; list_for_each_entry(dev, &chip_node->func_list, node) { if (hifc_func_type(dev->hwdev) == TYPE_VF) continue; if (test_bit(HIFC_FUNC_IN_REMOVE, &dev->flag)) continue; pdev_info = &card_func->pdev_info[card_func->num_pf]; pdev_info->bar0_size = pci_resource_len(dev->pcidev, 0); pdev_info->bar0_phy_addr = pci_resource_start(dev->pcidev, 0); card_func->num_pf++; if (card_func->num_pf >= MAX_SIZE) break; } } lld_dev_put(); } static bool __is_func_valid(struct hifc_pcidev *dev) { if (test_bit(HIFC_FUNC_IN_REMOVE, &dev->flag)) return false; if (dev->init_state < HIFC_INIT_STATE_HWDEV_INITED) return false; return true; } void hifc_get_card_info(void *hwdev, void *bufin) { struct card_node *chip_node = NULL; struct card_info *info = (struct card_info *)bufin; struct hifc_pcidev *dev; u32 idx = 0; if ((!bufin) || (!hwdev)) { pr_err("Input param invalid!\n"); return; } info->pf_num = 0; chip_node = hifc_get_chip_node_by_hwdev(hwdev); if (!chip_node) return; lld_dev_hold(); list_for_each_entry(dev, &chip_node->func_list, node) { if (!__is_func_valid(dev)) continue; strlcpy(info->pf[idx].name, dev->uld_dev_name, IFNAMSIZ); info->pf[idx].pf_type = (u32)BIT(SERVICE_T_FC); strlcpy(info->pf[idx].bus_info, pci_name(dev->pcidev), sizeof(info->pf[idx].bus_info)); info->pf_num++; idx++; } lld_dev_put(); }