diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h index 22bd425cfd84..461596096383 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h @@ -38,8 +38,8 @@ #define _QLCNIC_LINUX_MAJOR 5 #define _QLCNIC_LINUX_MINOR 3 -#define _QLCNIC_LINUX_SUBVERSION 49 -#define QLCNIC_LINUX_VERSIONID "5.3.49" +#define _QLCNIC_LINUX_SUBVERSION 50 +#define QLCNIC_LINUX_VERSIONID "5.3.50" #define QLCNIC_DRV_IDC_VER 0x01 #define QLCNIC_DRIVER_VERSION ((_QLCNIC_LINUX_MAJOR << 16) |\ (_QLCNIC_LINUX_MINOR << 8) | (_QLCNIC_LINUX_SUBVERSION)) @@ -392,7 +392,7 @@ struct qlcnic_dump_template_hdr { struct qlcnic_fw_dump { u8 clr; /* flag to indicate if dump is cleared */ - u8 enable; /* enable/disable dump */ + bool enable; /* enable/disable dump */ u32 size; /* total size of the dump */ void *data; /* dump data area */ struct qlcnic_dump_template_hdr *tmpl_hdr; @@ -463,7 +463,7 @@ struct qlcnic_hardware_context { struct qlcnic_fdt fdt; struct qlc_83xx_reset reset; struct qlc_83xx_idc idc; - struct qlc_83xx_fw_info fw_info; + struct qlc_83xx_fw_info *fw_info; struct qlcnic_intrpt_config *intr_tbl; struct qlcnic_sriov *sriov; u32 *reg_tbl; @@ -837,6 +837,7 @@ struct qlcnic_mac_list_s { #define QLCNIC_FW_CAP2_HW_LRO_IPV6 BIT_3 #define QLCNIC_FW_CAPABILITY_SET_DRV_VER BIT_5 #define QLCNIC_FW_CAPABILITY_2_BEACON BIT_7 +#define QLCNIC_FW_CAPABILITY_2_PER_PORT_ESWITCH_CFG BIT_8 /* module types */ #define LINKEVENT_MODULE_NOT_PRESENT 1 @@ -1184,6 +1185,7 @@ struct qlcnic_pci_info { }; struct qlcnic_npar_info { + bool eswitch_status; u16 pvid; u16 min_bw; u16 max_bw; @@ -1403,7 +1405,6 @@ struct qlcnic_esw_statistics { struct __qlcnic_esw_statistics tx; }; -#define QLCNIC_DUMP_MASK_DEF 0x1f #define QLCNIC_FORCE_FW_DUMP_KEY 0xdeadfeed #define QLCNIC_ENABLE_FW_DUMP 0xaddfeed #define QLCNIC_DISABLE_FW_DUMP 0xbadfeed @@ -1478,6 +1479,12 @@ int qlcnic_wol_supported(struct qlcnic_adapter *adapter); void qlcnic_prune_lb_filters(struct qlcnic_adapter *adapter); void qlcnic_delete_lb_filters(struct qlcnic_adapter *adapter); int qlcnic_dump_fw(struct qlcnic_adapter *); +int qlcnic_enable_fw_dump_state(struct qlcnic_adapter *); +bool qlcnic_check_fw_dump_state(struct qlcnic_adapter *); +pci_ers_result_t qlcnic_82xx_io_error_detected(struct pci_dev *, + pci_channel_state_t); +pci_ers_result_t qlcnic_82xx_io_slot_reset(struct pci_dev *); +void qlcnic_82xx_io_resume(struct pci_dev *); /* Functions from qlcnic_init.c */ void qlcnic_schedule_work(struct qlcnic_adapter *, work_func_t, int); @@ -1723,6 +1730,10 @@ struct qlcnic_hardware_ops { void (*set_mac_filter_count) (struct qlcnic_adapter *); void (*free_mac_list) (struct qlcnic_adapter *); int (*read_phys_port_id) (struct qlcnic_adapter *); + pci_ers_result_t (*io_error_detected) (struct pci_dev *, + pci_channel_state_t); + pci_ers_result_t (*io_slot_reset) (struct pci_dev *); + void (*io_resume) (struct pci_dev *); }; extern struct qlcnic_nic_template qlcnic_vf_ops; @@ -2069,6 +2080,14 @@ static inline bool qlcnic_82xx_check(struct qlcnic_adapter *adapter) return (device == PCI_DEVICE_ID_QLOGIC_QLE824X) ? true : false; } +static inline bool qlcnic_84xx_check(struct qlcnic_adapter *adapter) +{ + unsigned short device = adapter->pdev->device; + + return ((device == PCI_DEVICE_ID_QLOGIC_QLE844X) || + (device == PCI_DEVICE_ID_QLOGIC_VF_QLE844X)) ? true : false; +} + static inline bool qlcnic_83xx_check(struct qlcnic_adapter *adapter) { unsigned short device = adapter->pdev->device; diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c index 8fce1d36a79c..a1818dae47b6 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c @@ -11,6 +11,7 @@ #include #include #include +#include #define QLCNIC_MAX_TX_QUEUES 1 #define RSS_HASHTYPE_IP_TCP 0x3 @@ -177,6 +178,10 @@ static struct qlcnic_hardware_ops qlcnic_83xx_hw_ops = { .get_board_info = qlcnic_83xx_get_port_info, .set_mac_filter_count = qlcnic_83xx_set_mac_filter_count, .free_mac_list = qlcnic_82xx_free_mac_list, + .io_error_detected = qlcnic_83xx_io_error_detected, + .io_slot_reset = qlcnic_83xx_io_slot_reset, + .io_resume = qlcnic_83xx_io_resume, + }; static struct qlcnic_nic_template qlcnic_83xx_ops = { @@ -723,9 +728,8 @@ void qlcnic_dump_mbx(struct qlcnic_adapter *adapter, pr_info("\n"); } -static inline void -qlcnic_83xx_poll_for_mbx_completion(struct qlcnic_adapter *adapter, - struct qlcnic_cmd_args *cmd) +static void qlcnic_83xx_poll_for_mbx_completion(struct qlcnic_adapter *adapter, + struct qlcnic_cmd_args *cmd) { struct qlcnic_hardware_context *ahw = adapter->ahw; int opcode = LSW(cmd->req.arg[0]); @@ -2327,7 +2331,7 @@ int qlcnic_83xx_get_pci_info(struct qlcnic_adapter *adapter, pci_info->tx_max_bw, pci_info->mac); } if (ahw->op_mode == QLCNIC_MGMT_FUNC) - dev_info(dev, "Max vNIC functions = %d, active vNIC functions = %d\n", + dev_info(dev, "Max functions = %d, active functions = %d\n", ahw->max_pci_func, ahw->act_pci_func); } else { @@ -3544,7 +3548,7 @@ qlcnic_83xx_notify_cmd_completion(struct qlcnic_adapter *adapter, complete(&cmd->completion); } -static inline void qlcnic_83xx_flush_mbx_queue(struct qlcnic_adapter *adapter) +static void qlcnic_83xx_flush_mbx_queue(struct qlcnic_adapter *adapter) { struct qlcnic_mailbox *mbx = adapter->ahw->mailbox; struct list_head *head = &mbx->cmd_q; @@ -3564,7 +3568,7 @@ static inline void qlcnic_83xx_flush_mbx_queue(struct qlcnic_adapter *adapter) spin_unlock(&mbx->queue_lock); } -static inline int qlcnic_83xx_check_mbx_status(struct qlcnic_adapter *adapter) +static int qlcnic_83xx_check_mbx_status(struct qlcnic_adapter *adapter) { struct qlcnic_hardware_context *ahw = adapter->ahw; struct qlcnic_mailbox *mbx = ahw->mailbox; @@ -3592,8 +3596,8 @@ static inline void qlcnic_83xx_signal_mbx_cmd(struct qlcnic_adapter *adapter, QLCWRX(adapter->ahw, QLCNIC_FW_MBX_CTRL, QLCNIC_CLR_OWNER); } -static inline void qlcnic_83xx_dequeue_mbx_cmd(struct qlcnic_adapter *adapter, - struct qlcnic_cmd_args *cmd) +static void qlcnic_83xx_dequeue_mbx_cmd(struct qlcnic_adapter *adapter, + struct qlcnic_cmd_args *cmd) { struct qlcnic_mailbox *mbx = adapter->ahw->mailbox; @@ -3653,9 +3657,9 @@ void qlcnic_83xx_detach_mailbox_work(struct qlcnic_adapter *adapter) qlcnic_83xx_flush_mbx_queue(adapter); } -static inline int qlcnic_83xx_enqueue_mbx_cmd(struct qlcnic_adapter *adapter, - struct qlcnic_cmd_args *cmd, - unsigned long *timeout) +static int qlcnic_83xx_enqueue_mbx_cmd(struct qlcnic_adapter *adapter, + struct qlcnic_cmd_args *cmd, + unsigned long *timeout) { struct qlcnic_mailbox *mbx = adapter->ahw->mailbox; @@ -3680,8 +3684,8 @@ static inline int qlcnic_83xx_enqueue_mbx_cmd(struct qlcnic_adapter *adapter, return -EBUSY; } -static inline int qlcnic_83xx_check_mac_rcode(struct qlcnic_adapter *adapter, - struct qlcnic_cmd_args *cmd) +static int qlcnic_83xx_check_mac_rcode(struct qlcnic_adapter *adapter, + struct qlcnic_cmd_args *cmd) { u8 mac_cmd_rcode; u32 fw_data; @@ -3820,3 +3824,57 @@ int qlcnic_83xx_init_mailbox_work(struct qlcnic_adapter *adapter) set_bit(QLC_83XX_MBX_READY, &mbx->status); return 0; } + +pci_ers_result_t qlcnic_83xx_io_error_detected(struct pci_dev *pdev, + pci_channel_state_t state) +{ + struct qlcnic_adapter *adapter = pci_get_drvdata(pdev); + + if (state == pci_channel_io_perm_failure) + return PCI_ERS_RESULT_DISCONNECT; + + if (state == pci_channel_io_normal) + return PCI_ERS_RESULT_RECOVERED; + + set_bit(__QLCNIC_AER, &adapter->state); + set_bit(__QLCNIC_RESETTING, &adapter->state); + + qlcnic_83xx_aer_stop_poll_work(adapter); + + pci_save_state(pdev); + pci_disable_device(pdev); + + return PCI_ERS_RESULT_NEED_RESET; +} + +pci_ers_result_t qlcnic_83xx_io_slot_reset(struct pci_dev *pdev) +{ + struct qlcnic_adapter *adapter = pci_get_drvdata(pdev); + int err = 0; + + pdev->error_state = pci_channel_io_normal; + err = pci_enable_device(pdev); + if (err) + goto disconnect; + + pci_set_power_state(pdev, PCI_D0); + pci_set_master(pdev); + pci_restore_state(pdev); + + err = qlcnic_83xx_aer_reset(adapter); + if (err == 0) + return PCI_ERS_RESULT_RECOVERED; +disconnect: + clear_bit(__QLCNIC_AER, &adapter->state); + clear_bit(__QLCNIC_RESETTING, &adapter->state); + return PCI_ERS_RESULT_DISCONNECT; +} + +void qlcnic_83xx_io_resume(struct pci_dev *pdev) +{ + struct qlcnic_adapter *adapter = pci_get_drvdata(pdev); + + pci_cleanup_aer_uncorrect_error_status(pdev); + if (test_and_clear_bit(__QLCNIC_AER, &adapter->state)) + qlcnic_83xx_aer_start_poll_work(adapter); +} diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h index 0fc56160d584..533e150503af 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h @@ -274,11 +274,7 @@ struct qlcnic_macvlan_mbx { struct qlc_83xx_fw_info { const struct firmware *fw; - u16 major_fw_version; - u8 minor_fw_version; - u8 sub_fw_version; - u8 fw_build_num; - u8 load_from_file; + char fw_file_name[QLC_FW_FILE_NAME_LEN]; }; struct qlc_83xx_reset { @@ -297,6 +293,7 @@ struct qlc_83xx_reset { #define QLC_83XX_IDC_DISABLE_FW_RESET_RECOVERY 0x1 #define QLC_83XX_IDC_GRACEFULL_RESET 0x2 +#define QLC_83XX_IDC_DISABLE_FW_DUMP 0x4 #define QLC_83XX_IDC_TIMESTAMP 0 #define QLC_83XX_IDC_DURATION 1 #define QLC_83XX_IDC_INIT_TIMEOUT_SECS 30 @@ -414,6 +411,7 @@ enum qlcnic_83xx_states { #define QLC_83XX_GET_HW_LRO_CAPABILITY(val) (val & 0x400) #define QLC_83XX_GET_VLAN_ALIGN_CAPABILITY(val) (val & 0x4000) #define QLC_83XX_GET_FW_LRO_MSS_CAPABILITY(val) (val & 0x20000) +#define QLC_83XX_ESWITCH_CAPABILITY BIT_23 #define QLC_83XX_VIRTUAL_NIC_MODE 0xFF #define QLC_83XX_DEFAULT_MODE 0x0 #define QLC_83XX_SRIOV_MODE 0x1 @@ -628,6 +626,7 @@ int qlcnic_83xx_config_vnic_opmode(struct qlcnic_adapter *); int qlcnic_83xx_get_vnic_vport_info(struct qlcnic_adapter *, struct qlcnic_info *, u8); int qlcnic_83xx_get_vnic_pf_info(struct qlcnic_adapter *, struct qlcnic_info *); +int qlcnic_83xx_enable_port_eswitch(struct qlcnic_adapter *, int); void qlcnic_83xx_get_minidump_template(struct qlcnic_adapter *); void qlcnic_83xx_get_stats(struct qlcnic_adapter *adapter, u64 *data); @@ -656,4 +655,11 @@ int qlcnic_83xx_idc_init(struct qlcnic_adapter *); int qlcnic_83xx_idc_reattach_driver(struct qlcnic_adapter *); int qlcnic_83xx_set_vnic_opmode(struct qlcnic_adapter *); int qlcnic_83xx_check_vnic_state(struct qlcnic_adapter *); +void qlcnic_83xx_aer_stop_poll_work(struct qlcnic_adapter *); +int qlcnic_83xx_aer_reset(struct qlcnic_adapter *); +void qlcnic_83xx_aer_start_poll_work(struct qlcnic_adapter *); +pci_ers_result_t qlcnic_83xx_io_error_detected(struct pci_dev *, + pci_channel_state_t); +pci_ers_result_t qlcnic_83xx_io_slot_reset(struct pci_dev *); +void qlcnic_83xx_io_resume(struct pci_dev *); #endif diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c index a969ac27633c..f09e787af0b2 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c @@ -797,7 +797,6 @@ static int qlcnic_83xx_idc_init_state(struct qlcnic_adapter *adapter) ret = qlcnic_83xx_idc_restart_hw(adapter, 1); } else { ret = qlcnic_83xx_idc_check_timeout(adapter, timeout); - return ret; } return ret; @@ -1268,31 +1267,33 @@ static int qlcnic_83xx_copy_bootloader(struct qlcnic_adapter *adapter) static int qlcnic_83xx_copy_fw_file(struct qlcnic_adapter *adapter) { + struct qlc_83xx_fw_info *fw_info = adapter->ahw->fw_info; + const struct firmware *fw = fw_info->fw; u32 dest, *p_cache; - u64 addr; + int i, ret = -EIO; u8 data[16]; size_t size; - int i, ret = -EIO; + u64 addr; dest = QLCRDX(adapter->ahw, QLCNIC_FW_IMAGE_ADDR); - size = (adapter->ahw->fw_info.fw->size & ~0xF); - p_cache = (u32 *)adapter->ahw->fw_info.fw->data; + size = (fw->size & ~0xF); + p_cache = (u32 *)fw->data; addr = (u64)dest; ret = qlcnic_83xx_ms_mem_write128(adapter, addr, (u32 *)p_cache, size / 16); if (ret) { dev_err(&adapter->pdev->dev, "MS memory write failed\n"); - release_firmware(adapter->ahw->fw_info.fw); - adapter->ahw->fw_info.fw = NULL; + release_firmware(fw); + fw_info->fw = NULL; return -EIO; } /* alignment check */ - if (adapter->ahw->fw_info.fw->size & 0xF) { + if (fw->size & 0xF) { addr = dest + size; - for (i = 0; i < (adapter->ahw->fw_info.fw->size & 0xF); i++) - data[i] = adapter->ahw->fw_info.fw->data[size + i]; + for (i = 0; i < (fw->size & 0xF); i++) + data[i] = fw->data[size + i]; for (; i < 16; i++) data[i] = 0; ret = qlcnic_83xx_ms_mem_write128(adapter, addr, @@ -1300,13 +1301,13 @@ static int qlcnic_83xx_copy_fw_file(struct qlcnic_adapter *adapter) if (ret) { dev_err(&adapter->pdev->dev, "MS memory write failed\n"); - release_firmware(adapter->ahw->fw_info.fw); - adapter->ahw->fw_info.fw = NULL; + release_firmware(fw); + fw_info->fw = NULL; return -EIO; } } - release_firmware(adapter->ahw->fw_info.fw); - adapter->ahw->fw_info.fw = NULL; + release_firmware(fw); + fw_info->fw = NULL; return 0; } @@ -1950,35 +1951,12 @@ static void qlcnic_83xx_init_hw(struct qlcnic_adapter *p_dev) dev_err(&p_dev->pdev->dev, "%s: failed\n", __func__); } -static inline void qlcnic_83xx_get_fw_file_name(struct qlcnic_adapter *adapter, - char *file_name) -{ - struct pci_dev *pdev = adapter->pdev; - - memset(file_name, 0, QLC_FW_FILE_NAME_LEN); - - switch (pdev->device) { - case PCI_DEVICE_ID_QLOGIC_QLE834X: - strncpy(file_name, QLC_83XX_FW_FILE_NAME, - QLC_FW_FILE_NAME_LEN); - break; - case PCI_DEVICE_ID_QLOGIC_QLE844X: - strncpy(file_name, QLC_84XX_FW_FILE_NAME, - QLC_FW_FILE_NAME_LEN); - break; - default: - dev_err(&pdev->dev, "%s: Invalid device id\n", - __func__); - } -} - static int qlcnic_83xx_load_fw_image_from_host(struct qlcnic_adapter *adapter) { - char fw_file_name[QLC_FW_FILE_NAME_LEN]; + struct qlc_83xx_fw_info *fw_info = adapter->ahw->fw_info; int err = -EIO; - qlcnic_83xx_get_fw_file_name(adapter, fw_file_name); - if (request_firmware(&adapter->ahw->fw_info.fw, fw_file_name, + if (request_firmware(&fw_info->fw, fw_info->fw_file_name, &(adapter->pdev->dev))) { dev_err(&adapter->pdev->dev, "No file FW image, loading flash FW image.\n"); @@ -2025,36 +2003,6 @@ static int qlcnic_83xx_restart_hw(struct qlcnic_adapter *adapter) return 0; } -/** -* qlcnic_83xx_config_default_opmode -* -* @adapter: adapter structure -* -* Configure default driver operating mode -* -* Returns: Error code or Success(0) -* */ -int qlcnic_83xx_config_default_opmode(struct qlcnic_adapter *adapter) -{ - u32 op_mode; - struct qlcnic_hardware_context *ahw = adapter->ahw; - - qlcnic_get_func_no(adapter); - op_mode = QLCRDX(ahw, QLC_83XX_DRV_OP_MODE); - - if (test_bit(__QLCNIC_SRIOV_CAPABLE, &adapter->state)) - op_mode = QLC_83XX_DEFAULT_OPMODE; - - if (op_mode == QLC_83XX_DEFAULT_OPMODE) { - adapter->nic_ops->init_driver = qlcnic_83xx_init_default_driver; - ahw->idc.state_entry = qlcnic_83xx_idc_ready_state_entry; - } else { - return -EIO; - } - - return 0; -} - int qlcnic_83xx_get_nic_configuration(struct qlcnic_adapter *adapter) { int err; @@ -2074,26 +2022,26 @@ int qlcnic_83xx_get_nic_configuration(struct qlcnic_adapter *adapter) ahw->max_mac_filters = nic_info.max_mac_filters; ahw->max_mtu = nic_info.max_mtu; - /* VNIC mode is detected by BIT_23 in capabilities. This bit is also - * set in case device is SRIOV capable. VNIC and SRIOV are mutually - * exclusive. So in case of sriov capable device load driver in - * default mode + /* eSwitch capability indicates vNIC mode. + * vNIC and SRIOV are mutually exclusive operational modes. + * If SR-IOV capability is detected, SR-IOV physical function + * will get initialized in default mode. + * SR-IOV virtual function initialization follows a + * different code path and opmode. + * SRIOV mode has precedence over vNIC mode. */ - if (test_bit(__QLCNIC_SRIOV_CAPABLE, &adapter->state)) { - ahw->nic_mode = QLC_83XX_DEFAULT_MODE; - return ahw->nic_mode; - } + if (test_bit(__QLCNIC_SRIOV_CAPABLE, &adapter->state)) + return QLC_83XX_DEFAULT_OPMODE; - if (ahw->capabilities & BIT_23) - ahw->nic_mode = QLC_83XX_VIRTUAL_NIC_MODE; - else - ahw->nic_mode = QLC_83XX_DEFAULT_MODE; + if (ahw->capabilities & QLC_83XX_ESWITCH_CAPABILITY) + return QLC_83XX_VIRTUAL_NIC_MODE; - return ahw->nic_mode; + return QLC_83XX_DEFAULT_OPMODE; } int qlcnic_83xx_configure_opmode(struct qlcnic_adapter *adapter) { + struct qlcnic_hardware_context *ahw = adapter->ahw; int ret; ret = qlcnic_83xx_get_nic_configuration(adapter); @@ -2101,11 +2049,16 @@ int qlcnic_83xx_configure_opmode(struct qlcnic_adapter *adapter) return -EIO; if (ret == QLC_83XX_VIRTUAL_NIC_MODE) { + ahw->nic_mode = QLC_83XX_VIRTUAL_NIC_MODE; if (qlcnic_83xx_config_vnic_opmode(adapter)) return -EIO; - } else if (ret == QLC_83XX_DEFAULT_MODE) { - if (qlcnic_83xx_config_default_opmode(adapter)) - return -EIO; + + } else if (ret == QLC_83XX_DEFAULT_OPMODE) { + ahw->nic_mode = QLC_83XX_DEFAULT_MODE; + adapter->nic_ops->init_driver = qlcnic_83xx_init_default_driver; + ahw->idc.state_entry = qlcnic_83xx_idc_ready_state_entry; + } else { + return -EIO; } return 0; @@ -2174,6 +2127,39 @@ static void qlcnic_83xx_clear_function_resources(struct qlcnic_adapter *adapter) } } +static int qlcnic_83xx_get_fw_info(struct qlcnic_adapter *adapter) +{ + struct qlcnic_hardware_context *ahw = adapter->ahw; + struct pci_dev *pdev = adapter->pdev; + struct qlc_83xx_fw_info *fw_info; + int err = 0; + + ahw->fw_info = kzalloc(sizeof(*fw_info), GFP_KERNEL); + if (!ahw->fw_info) { + err = -ENOMEM; + } else { + fw_info = ahw->fw_info; + switch (pdev->device) { + case PCI_DEVICE_ID_QLOGIC_QLE834X: + strncpy(fw_info->fw_file_name, QLC_83XX_FW_FILE_NAME, + QLC_FW_FILE_NAME_LEN); + break; + case PCI_DEVICE_ID_QLOGIC_QLE844X: + strncpy(fw_info->fw_file_name, QLC_84XX_FW_FILE_NAME, + QLC_FW_FILE_NAME_LEN); + break; + default: + dev_err(&pdev->dev, "%s: Invalid device id\n", + __func__); + err = -EINVAL; + break; + } + } + + return err; +} + + int qlcnic_83xx_init(struct qlcnic_adapter *adapter, int pci_using_dac) { struct qlcnic_hardware_context *ahw = adapter->ahw; @@ -2199,10 +2185,14 @@ int qlcnic_83xx_init(struct qlcnic_adapter *adapter, int pci_using_dac) if (!qlcnic_83xx_read_flash_descriptor_table(adapter)) qlcnic_83xx_read_flash_mfg_id(adapter); - err = qlcnic_83xx_idc_init(adapter); + err = qlcnic_83xx_get_fw_info(adapter); if (err) goto detach_mbx; + err = qlcnic_83xx_idc_init(adapter); + if (err) + goto clear_fw_info; + err = qlcnic_setup_intr(adapter, 0, 0); if (err) { dev_err(&adapter->pdev->dev, "Failed to setup interrupt\n"); @@ -2243,9 +2233,67 @@ int qlcnic_83xx_init(struct qlcnic_adapter *adapter, int pci_using_dac) disable_intr: qlcnic_teardown_intr(adapter); +clear_fw_info: + kfree(ahw->fw_info); + detach_mbx: qlcnic_83xx_detach_mailbox_work(adapter); qlcnic_83xx_free_mailbox(ahw->mailbox); exit: return err; } + +void qlcnic_83xx_aer_stop_poll_work(struct qlcnic_adapter *adapter) +{ + struct qlcnic_hardware_context *ahw = adapter->ahw; + struct qlc_83xx_idc *idc = &ahw->idc; + + clear_bit(QLC_83XX_MBX_READY, &idc->status); + cancel_delayed_work_sync(&adapter->fw_work); + + if (ahw->nic_mode == QLC_83XX_VIRTUAL_NIC_MODE) + qlcnic_83xx_disable_vnic_mode(adapter, 1); + + qlcnic_83xx_idc_detach_driver(adapter); + qlcnic_83xx_register_nic_idc_func(adapter, 0); + + cancel_delayed_work_sync(&adapter->idc_aen_work); +} + +int qlcnic_83xx_aer_reset(struct qlcnic_adapter *adapter) +{ + struct qlcnic_hardware_context *ahw = adapter->ahw; + struct qlc_83xx_idc *idc = &ahw->idc; + int ret = 0; + u32 owner; + + /* Mark the previous IDC state as NEED_RESET so + * that state_entry() will perform the reattachment + * and bringup the device + */ + idc->prev_state = QLC_83XX_IDC_DEV_NEED_RESET; + owner = qlcnic_83xx_idc_find_reset_owner_id(adapter); + if (ahw->pci_func == owner) { + ret = qlcnic_83xx_restart_hw(adapter); + if (ret < 0) + return ret; + qlcnic_83xx_idc_clear_registers(adapter, 0); + } + + ret = idc->state_entry(adapter); + return ret; +} + +void qlcnic_83xx_aer_start_poll_work(struct qlcnic_adapter *adapter) +{ + struct qlcnic_hardware_context *ahw = adapter->ahw; + struct qlc_83xx_idc *idc = &ahw->idc; + u32 owner; + + idc->prev_state = QLC_83XX_IDC_DEV_READY; + owner = qlcnic_83xx_idc_find_reset_owner_id(adapter); + if (ahw->pci_func == owner) + qlcnic_83xx_idc_enter_ready_state(adapter, 0); + + qlcnic_schedule_work(adapter, qlcnic_83xx_idc_poll_dev_state, 0); +} diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_vnic.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_vnic.c index 599d1fda52f2..0248a4c2f5dd 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_vnic.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_vnic.c @@ -208,7 +208,7 @@ int qlcnic_83xx_config_vnic_opmode(struct qlcnic_adapter *adapter) return -EIO; } - if (ahw->capabilities & BIT_23) + if (ahw->capabilities & QLC_83XX_ESWITCH_CAPABILITY) adapter->flags |= QLCNIC_ESWITCH_ENABLED; else adapter->flags &= ~QLCNIC_ESWITCH_ENABLED; @@ -239,3 +239,41 @@ int qlcnic_83xx_check_vnic_state(struct qlcnic_adapter *adapter) return 0; } + +static int qlcnic_83xx_get_eswitch_port_info(struct qlcnic_adapter *adapter, + int func, int *port_id) +{ + struct qlcnic_info nic_info; + int err = 0; + + memset(&nic_info, 0, sizeof(struct qlcnic_info)); + + err = qlcnic_get_nic_info(adapter, &nic_info, func); + if (err) + return err; + + if (nic_info.capabilities & QLC_83XX_ESWITCH_CAPABILITY) + *port_id = nic_info.phys_port; + else + err = -EIO; + + return err; +} + +int qlcnic_83xx_enable_port_eswitch(struct qlcnic_adapter *adapter, int func) +{ + int id, err = 0; + + err = qlcnic_83xx_get_eswitch_port_info(adapter, func, &id); + if (err) + return err; + + if (!(adapter->eswitch[id].flags & QLCNIC_SWITCH_ENABLE)) { + if (!qlcnic_enable_eswitch(adapter, id, 1)) + adapter->eswitch[id].flags |= QLCNIC_SWITCH_ENABLE; + else + err = -EIO; + } + + return err; +} diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c index 7b0c90efb365..332aa71798f6 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c @@ -1509,6 +1509,68 @@ static void qlcnic_set_msglevel(struct net_device *netdev, u32 msglvl) adapter->ahw->msg_enable = msglvl; } +int qlcnic_enable_fw_dump_state(struct qlcnic_adapter *adapter) +{ + struct qlcnic_fw_dump *fw_dump = &adapter->ahw->fw_dump; + u32 val; + + if (qlcnic_84xx_check(adapter)) { + if (qlcnic_83xx_lock_driver(adapter)) + return -EBUSY; + + val = QLCRDX(adapter->ahw, QLC_83XX_IDC_CTRL); + val &= ~QLC_83XX_IDC_DISABLE_FW_DUMP; + QLCWRX(adapter->ahw, QLC_83XX_IDC_CTRL, val); + + qlcnic_83xx_unlock_driver(adapter); + } else { + fw_dump->enable = true; + } + + dev_info(&adapter->pdev->dev, "FW dump enabled\n"); + + return 0; +} + +static int qlcnic_disable_fw_dump_state(struct qlcnic_adapter *adapter) +{ + struct qlcnic_fw_dump *fw_dump = &adapter->ahw->fw_dump; + u32 val; + + if (qlcnic_84xx_check(adapter)) { + if (qlcnic_83xx_lock_driver(adapter)) + return -EBUSY; + + val = QLCRDX(adapter->ahw, QLC_83XX_IDC_CTRL); + val |= QLC_83XX_IDC_DISABLE_FW_DUMP; + QLCWRX(adapter->ahw, QLC_83XX_IDC_CTRL, val); + + qlcnic_83xx_unlock_driver(adapter); + } else { + fw_dump->enable = false; + } + + dev_info(&adapter->pdev->dev, "FW dump disabled\n"); + + return 0; +} + +bool qlcnic_check_fw_dump_state(struct qlcnic_adapter *adapter) +{ + struct qlcnic_fw_dump *fw_dump = &adapter->ahw->fw_dump; + bool state; + u32 val; + + if (qlcnic_84xx_check(adapter)) { + val = QLCRDX(adapter->ahw, QLC_83XX_IDC_CTRL); + state = (val & QLC_83XX_IDC_DISABLE_FW_DUMP) ? false : true; + } else { + state = fw_dump->enable; + } + + return state; +} + static int qlcnic_get_dump_flag(struct net_device *netdev, struct ethtool_dump *dump) { @@ -1525,7 +1587,7 @@ qlcnic_get_dump_flag(struct net_device *netdev, struct ethtool_dump *dump) else dump->len = 0; - if (!fw_dump->enable) + if (!qlcnic_check_fw_dump_state(adapter)) dump->flag = ETH_FW_DUMP_DISABLE; else dump->flag = fw_dump->tmpl_hdr->drv_cap_mask; @@ -1573,77 +1635,111 @@ qlcnic_get_dump_data(struct net_device *netdev, struct ethtool_dump *dump, return 0; } +static int qlcnic_set_dump_mask(struct qlcnic_adapter *adapter, u32 mask) +{ + struct qlcnic_fw_dump *fw_dump = &adapter->ahw->fw_dump; + struct net_device *netdev = adapter->netdev; + + if (!qlcnic_check_fw_dump_state(adapter)) { + netdev_info(netdev, + "Can not change driver mask to 0x%x. FW dump not enabled\n", + mask); + return -EOPNOTSUPP; + } + + fw_dump->tmpl_hdr->drv_cap_mask = mask; + netdev_info(netdev, "Driver mask changed to: 0x%x\n", mask); + return 0; +} + static int qlcnic_set_dump(struct net_device *netdev, struct ethtool_dump *val) { - int i; struct qlcnic_adapter *adapter = netdev_priv(netdev); struct qlcnic_fw_dump *fw_dump = &adapter->ahw->fw_dump; + bool valid_mask = false; + int i, ret = 0; u32 state; switch (val->flag) { case QLCNIC_FORCE_FW_DUMP_KEY: if (!fw_dump->tmpl_hdr) { netdev_err(netdev, "FW dump not supported\n"); - return -ENOTSUPP; + ret = -EOPNOTSUPP; + break; } - if (!fw_dump->enable) { + + if (!qlcnic_check_fw_dump_state(adapter)) { netdev_info(netdev, "FW dump not enabled\n"); - return 0; + ret = -EOPNOTSUPP; + break; } + if (fw_dump->clr) { netdev_info(netdev, - "Previous dump not cleared, not forcing dump\n"); - return 0; + "Previous dump not cleared, not forcing dump\n"); + break; } + netdev_info(netdev, "Forcing a FW dump\n"); qlcnic_dev_request_reset(adapter, val->flag); break; case QLCNIC_DISABLE_FW_DUMP: - if (fw_dump->enable && fw_dump->tmpl_hdr) { - netdev_info(netdev, "Disabling FW dump\n"); - fw_dump->enable = 0; + if (!fw_dump->tmpl_hdr) { + netdev_err(netdev, "FW dump not supported\n"); + ret = -EOPNOTSUPP; + break; } - return 0; + + ret = qlcnic_disable_fw_dump_state(adapter); + break; + case QLCNIC_ENABLE_FW_DUMP: if (!fw_dump->tmpl_hdr) { netdev_err(netdev, "FW dump not supported\n"); - return -ENOTSUPP; + ret = -EOPNOTSUPP; + break; } - if (!fw_dump->enable) { - netdev_info(netdev, "Enabling FW dump\n"); - fw_dump->enable = 1; - } - return 0; + + ret = qlcnic_enable_fw_dump_state(adapter); + break; + case QLCNIC_FORCE_FW_RESET: netdev_info(netdev, "Forcing a FW reset\n"); qlcnic_dev_request_reset(adapter, val->flag); adapter->flags &= ~QLCNIC_FW_RESET_OWNER; - return 0; + break; +; case QLCNIC_SET_QUIESCENT: case QLCNIC_RESET_QUIESCENT: state = QLC_SHARED_REG_RD32(adapter, QLCNIC_CRB_DEV_STATE); if (state == QLCNIC_DEV_FAILED || (state == QLCNIC_DEV_BADBAD)) netdev_info(netdev, "Device in FAILED state\n"); - return 0; + break; + default: if (!fw_dump->tmpl_hdr) { netdev_err(netdev, "FW dump not supported\n"); - return -ENOTSUPP; + ret = -EOPNOTSUPP; + break; } + for (i = 0; i < ARRAY_SIZE(qlcnic_fw_dump_level); i++) { if (val->flag == qlcnic_fw_dump_level[i]) { - fw_dump->tmpl_hdr->drv_cap_mask = - val->flag; - netdev_info(netdev, "Driver mask changed to: 0x%x\n", - fw_dump->tmpl_hdr->drv_cap_mask); - return 0; + valid_mask = true; + break; } } - netdev_info(netdev, "Invalid dump level: 0x%x\n", val->flag); - return -EINVAL; + + if (valid_mask) { + ret = qlcnic_set_dump_mask(adapter, val->flag); + } else { + netdev_info(netdev, "Invalid dump level: 0x%x\n", + val->flag); + ret = -EINVAL; + } } - return 0; + return ret; } const struct ethtool_ops qlcnic_ethtool_ops = { diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c index 7dde3ba6d9a4..c4c5023e1fdf 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c @@ -540,6 +540,9 @@ static struct qlcnic_hardware_ops qlcnic_hw_ops = { .set_mac_filter_count = qlcnic_82xx_set_mac_filter_count, .free_mac_list = qlcnic_82xx_free_mac_list, .read_phys_port_id = qlcnic_82xx_read_phys_port_id, + .io_error_detected = qlcnic_82xx_io_error_detected, + .io_slot_reset = qlcnic_82xx_io_slot_reset, + .io_resume = qlcnic_82xx_io_resume, }; static void qlcnic_get_multiq_capability(struct qlcnic_adapter *adapter) @@ -793,6 +796,23 @@ static int qlcnic_get_act_pci_func(struct qlcnic_adapter *adapter) return ret; } +static bool qlcnic_port_eswitch_cfg_capability(struct qlcnic_adapter *adapter) +{ + bool ret = false; + + if (qlcnic_84xx_check(adapter)) { + ret = true; + } else if (qlcnic_83xx_check(adapter)) { + if (adapter->ahw->extra_capability[0] & + QLCNIC_FW_CAPABILITY_2_PER_PORT_ESWITCH_CFG) + ret = true; + else + ret = false; + } + + return ret; +} + int qlcnic_init_pci_info(struct qlcnic_adapter *adapter) { struct qlcnic_pci_info *pci_info; @@ -836,18 +856,30 @@ int qlcnic_init_pci_info(struct qlcnic_adapter *adapter) (pci_info[i].type != QLCNIC_TYPE_NIC)) continue; + if (qlcnic_port_eswitch_cfg_capability(adapter)) { + if (!qlcnic_83xx_enable_port_eswitch(adapter, pfn)) + adapter->npars[j].eswitch_status = true; + else + continue; + } else { + adapter->npars[j].eswitch_status = true; + } + adapter->npars[j].pci_func = pfn; adapter->npars[j].active = (u8)pci_info[i].active; adapter->npars[j].type = (u8)pci_info[i].type; adapter->npars[j].phy_port = (u8)pci_info[i].default_port; adapter->npars[j].min_bw = pci_info[i].tx_min_bw; adapter->npars[j].max_bw = pci_info[i].tx_max_bw; + j++; } - for (i = 0; i < QLCNIC_NIU_MAX_XG_PORTS; i++) { - adapter->eswitch[i].flags |= QLCNIC_SWITCH_ENABLE; - if (qlcnic_83xx_check(adapter)) + if (qlcnic_82xx_check(adapter)) { + for (i = 0; i < QLCNIC_NIU_MAX_XG_PORTS; i++) + adapter->eswitch[i].flags |= QLCNIC_SWITCH_ENABLE; + } else if (!qlcnic_port_eswitch_cfg_capability(adapter)) { + for (i = 0; i < QLCNIC_NIU_MAX_XG_PORTS; i++) qlcnic_enable_eswitch(adapter, i, 1); } @@ -969,8 +1001,8 @@ static int qlcnic_setup_pci_map(struct pci_dev *pdev, return 0; } -static inline bool qlcnic_validate_subsystem_id(struct qlcnic_adapter *adapter, - int index) +static bool qlcnic_validate_subsystem_id(struct qlcnic_adapter *adapter, + int index) { struct pci_dev *pdev = adapter->pdev; unsigned short subsystem_vendor; @@ -1272,6 +1304,9 @@ int qlcnic_set_default_offload_settings(struct qlcnic_adapter *adapter) return 0; for (i = 0; i < adapter->ahw->act_pci_func; i++) { + if (!adapter->npars[i].eswitch_status) + continue; + memset(&esw_cfg, 0, sizeof(struct qlcnic_esw_func_cfg)); esw_cfg.pci_func = adapter->npars[i].pci_func; esw_cfg.mac_override = BIT_0; @@ -1334,6 +1369,9 @@ int qlcnic_reset_npar_config(struct qlcnic_adapter *adapter) for (i = 0; i < adapter->ahw->act_pci_func; i++) { npar = &adapter->npars[i]; pci_func = npar->pci_func; + if (!adapter->npars[i].eswitch_status) + continue; + memset(&nic_info, 0, sizeof(struct qlcnic_info)); err = qlcnic_get_nic_info(adapter, &nic_info, pci_func); if (err) @@ -2399,6 +2437,7 @@ static void qlcnic_remove(struct pci_dev *pdev) qlcnic_83xx_free_mbx_intr(adapter); qlcnic_83xx_detach_mailbox_work(adapter); qlcnic_83xx_free_mailbox(ahw->mailbox); + kfree(ahw->fw_info); } qlcnic_detach(adapter); @@ -3045,7 +3084,7 @@ qlcnic_fwinit_work(struct work_struct *work) qlcnic_api_unlock(adapter); rtnl_lock(); - if (adapter->ahw->fw_dump.enable && + if (qlcnic_check_fw_dump_state(adapter) && (adapter->flags & QLCNIC_FW_RESET_OWNER)) { QLCDB(adapter, DRV, "Take FW dump\n"); qlcnic_dump_fw(adapter); @@ -3431,19 +3470,6 @@ static int qlcnic_attach_func(struct pci_dev *pdev) return err; } - if (qlcnic_83xx_check(adapter)) { - /* register for NIC IDC AEN Events */ - qlcnic_83xx_register_nic_idc_func(adapter, 1); - err = qlcnic_83xx_setup_mbx_intr(adapter); - if (err) { - dev_err(&adapter->pdev->dev, - "failed to setup mbx interrupt\n"); - qlcnic_clr_all_drv_state(adapter, 1); - clear_bit(__QLCNIC_AER, &adapter->state); - goto done; - } - } - if (netif_running(netdev)) { err = qlcnic_attach(adapter); if (err) { @@ -3464,8 +3490,8 @@ static int qlcnic_attach_func(struct pci_dev *pdev) return err; } -static pci_ers_result_t qlcnic_io_error_detected(struct pci_dev *pdev, - pci_channel_state_t state) +pci_ers_result_t qlcnic_82xx_io_error_detected(struct pci_dev *pdev, + pci_channel_state_t state) { struct qlcnic_adapter *adapter = pci_get_drvdata(pdev); struct net_device *netdev = adapter->netdev; @@ -3484,12 +3510,6 @@ static pci_ers_result_t qlcnic_io_error_detected(struct pci_dev *pdev, if (netif_running(netdev)) qlcnic_down(adapter, netdev); - if (qlcnic_83xx_check(adapter)) { - qlcnic_83xx_free_mbx_intr(adapter); - qlcnic_83xx_register_nic_idc_func(adapter, 0); - cancel_delayed_work_sync(&adapter->idc_aen_work); - } - qlcnic_detach(adapter); qlcnic_teardown_intr(adapter); @@ -3501,13 +3521,13 @@ static pci_ers_result_t qlcnic_io_error_detected(struct pci_dev *pdev, return PCI_ERS_RESULT_NEED_RESET; } -static pci_ers_result_t qlcnic_io_slot_reset(struct pci_dev *pdev) +pci_ers_result_t qlcnic_82xx_io_slot_reset(struct pci_dev *pdev) { return qlcnic_attach_func(pdev) ? PCI_ERS_RESULT_DISCONNECT : PCI_ERS_RESULT_RECOVERED; } -static void qlcnic_io_resume(struct pci_dev *pdev) +void qlcnic_82xx_io_resume(struct pci_dev *pdev) { u32 state; struct qlcnic_adapter *adapter = pci_get_drvdata(pdev); @@ -3517,9 +3537,48 @@ static void qlcnic_io_resume(struct pci_dev *pdev) if (state == QLCNIC_DEV_READY && test_and_clear_bit(__QLCNIC_AER, &adapter->state)) qlcnic_schedule_work(adapter, qlcnic_fw_poll_work, - FW_POLL_DELAY); + FW_POLL_DELAY); } +static pci_ers_result_t qlcnic_io_error_detected(struct pci_dev *pdev, + pci_channel_state_t state) +{ + struct qlcnic_adapter *adapter = pci_get_drvdata(pdev); + struct qlcnic_hardware_ops *hw_ops = adapter->ahw->hw_ops; + + if (hw_ops->io_error_detected) { + return hw_ops->io_error_detected(pdev, state); + } else { + dev_err(&pdev->dev, "AER error_detected handler not registered.\n"); + return PCI_ERS_RESULT_DISCONNECT; + } +} + +static pci_ers_result_t qlcnic_io_slot_reset(struct pci_dev *pdev) +{ + struct qlcnic_adapter *adapter = pci_get_drvdata(pdev); + struct qlcnic_hardware_ops *hw_ops = adapter->ahw->hw_ops; + + if (hw_ops->io_slot_reset) { + return hw_ops->io_slot_reset(pdev); + } else { + dev_err(&pdev->dev, "AER slot_reset handler not registered.\n"); + return PCI_ERS_RESULT_DISCONNECT; + } +} + +static void qlcnic_io_resume(struct pci_dev *pdev) +{ + struct qlcnic_adapter *adapter = pci_get_drvdata(pdev); + struct qlcnic_hardware_ops *hw_ops = adapter->ahw->hw_ops; + + if (hw_ops->io_resume) + hw_ops->io_resume(pdev); + else + dev_err(&pdev->dev, "AER resume handler not registered.\n"); +} + + static int qlcnicvf_start_firmware(struct qlcnic_adapter *adapter) { diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_minidump.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_minidump.c index 79e54efe07b9..15513608d480 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_minidump.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_minidump.c @@ -1082,14 +1082,17 @@ int qlcnic_fw_cmd_get_minidump_temp(struct qlcnic_adapter *adapter) } tmpl_hdr = ahw->fw_dump.tmpl_hdr; - tmpl_hdr->drv_cap_mask = QLCNIC_DUMP_MASK_DEF; + tmpl_hdr->drv_cap_mask = tmpl_hdr->cap_mask; + dev_info(&adapter->pdev->dev, + "Default minidump capture mask 0x%x\n", + tmpl_hdr->cap_mask); if ((tmpl_hdr->version & 0xfffff) >= 0x20001) ahw->fw_dump.use_pex_dma = true; else ahw->fw_dump.use_pex_dma = false; - ahw->fw_dump.enable = 1; + qlcnic_enable_fw_dump_state(adapter); return 0; } @@ -1112,7 +1115,11 @@ int qlcnic_dump_fw(struct qlcnic_adapter *adapter) ahw = adapter->ahw; - if (!fw_dump->enable) { + /* Return if we don't have firmware dump template header */ + if (!tmpl_hdr) + return -EIO; + + if (!qlcnic_check_fw_dump_state(adapter)) { dev_info(&adapter->pdev->dev, "Dump not enabled\n"); return -EIO; } diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c index 26f9aa66403d..652cc13c5023 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c @@ -398,14 +398,10 @@ int qlcnic_sriov_get_vf_vport_info(struct qlcnic_adapter *adapter, } static int qlcnic_sriov_set_pvid_mode(struct qlcnic_adapter *adapter, - struct qlcnic_cmd_args *cmd, u32 cap) + struct qlcnic_cmd_args *cmd) { - if (cap & QLC_83XX_PVID_STRIP_CAPABILITY) { - adapter->rx_pvid = 0; - } else { - adapter->rx_pvid = (cmd->rsp.arg[1] >> 16) & 0xffff; - adapter->flags &= ~QLCNIC_TAGGING_ENABLED; - } + adapter->rx_pvid = MSW(cmd->rsp.arg[1]) & 0xffff; + adapter->flags &= ~QLCNIC_TAGGING_ENABLED; return 0; } @@ -441,9 +437,8 @@ static int qlcnic_sriov_get_vf_acl(struct qlcnic_adapter *adapter, { struct qlcnic_sriov *sriov = adapter->ahw->sriov; struct qlcnic_cmd_args cmd; - int ret, cap; + int ret = 0; - cap = info->capabilities; ret = qlcnic_sriov_alloc_bc_mbx_args(&cmd, QLCNIC_BC_CMD_GET_ACL); if (ret) return ret; @@ -459,7 +454,7 @@ static int qlcnic_sriov_get_vf_acl(struct qlcnic_adapter *adapter, ret = qlcnic_sriov_set_guest_vlan_mode(adapter, &cmd); break; case QLC_PVID_MODE: - ret = qlcnic_sriov_set_pvid_mode(adapter, &cmd, cap); + ret = qlcnic_sriov_set_pvid_mode(adapter, &cmd); break; } } diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_pf.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_pf.c index 2d6faf0fcc10..a9bc651e9ffa 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_pf.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_pf.c @@ -1183,10 +1183,19 @@ static int qlcnic_sriov_pf_get_acl_cmd(struct qlcnic_bc_trans *trans, struct qlcnic_vf_info *vf = trans->vf; struct qlcnic_vport *vp = vf->vp; u8 cmd_op, mode = vp->vlan_mode; + struct qlcnic_adapter *adapter; + + adapter = vf->adapter; cmd_op = trans->req_hdr->cmd_op; cmd->rsp.arg[0] |= 1 << 25; + /* For 84xx adapter in case of PVID , PFD should send vlan mode as + * QLC_NO_VLAN_MODE to VFD which is zero in mailbox response + */ + if (qlcnic_84xx_check(adapter) && mode == QLC_PVID_MODE) + return 0; + switch (mode) { case QLC_GUEST_VLAN_MODE: cmd->rsp.arg[1] = mode | 1 << 8; @@ -1772,8 +1781,8 @@ int qlcnic_sriov_set_vf_vlan(struct net_device *netdev, int vf, return 0; } -static inline __u32 qlcnic_sriov_get_vf_vlan(struct qlcnic_adapter *adapter, - struct qlcnic_vport *vp, int vf) +static __u32 qlcnic_sriov_get_vf_vlan(struct qlcnic_adapter *adapter, + struct qlcnic_vport *vp, int vf) { __u32 vlan = 0; diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c index 660c3f5b2237..c6165d05cc13 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c @@ -465,8 +465,14 @@ static ssize_t qlcnic_sysfs_read_pm_config(struct file *filp, memset(&pm_cfg, 0, sizeof(struct qlcnic_pm_func_cfg) * QLCNIC_MAX_PCI_FUNC); - for (i = 0; i < adapter->ahw->act_pci_func; i++) { + for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++) { pci_func = adapter->npars[i].pci_func; + if (!adapter->npars[i].active) + continue; + + if (!adapter->npars[i].eswitch_status) + continue; + pm_cfg[pci_func].action = adapter->npars[i].enable_pm; pm_cfg[pci_func].dest_npar = 0; pm_cfg[pci_func].pci_func = i; @@ -632,8 +638,14 @@ static ssize_t qlcnic_sysfs_read_esw_config(struct file *file, memset(&esw_cfg, 0, sizeof(struct qlcnic_esw_func_cfg) * QLCNIC_MAX_PCI_FUNC); - for (i = 0; i < adapter->ahw->act_pci_func; i++) { + for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++) { pci_func = adapter->npars[i].pci_func; + if (!adapter->npars[i].active) + continue; + + if (!adapter->npars[i].eswitch_status) + continue; + esw_cfg[pci_func].pci_func = pci_func; if (qlcnic_get_eswitch_port_config(adapter, &esw_cfg[pci_func])) return QL_STATUS_INVALID_PARAM; @@ -732,6 +744,9 @@ static ssize_t qlcnic_sysfs_read_npar_config(struct file *file, if (ret) return ret; + if (!adapter->npars[i].eswitch_status) + continue; + np_cfg[i].pci_func = i; np_cfg[i].op_mode = (u8)nic_info.op_mode; np_cfg[i].port_num = nic_info.phys_port;