Commit ba397672 authored by David S. Miller's avatar David S. Miller

Merge branch 'qlcnic'

Shahed Shaikh says:

====================
This patch series contains -
* Enhanced PVID handling for 84xx adapters by
  not indicating PVID configuration to VF driver and
  keeping VF driver in no VLAN configuration mode becasue
  adapter supports VLAN stripping.
* Removed inappropriate usage of inline keyword.
* Enhanced minidump feature by using firmware recommended
  dump capture mask and using CAMRAM register to store
  firmware dump state.
* AER handling support for 83xx adapter.
* Added support for per port eswitch configuration.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents eb3c0d83 693dcd2f
...@@ -38,8 +38,8 @@ ...@@ -38,8 +38,8 @@
#define _QLCNIC_LINUX_MAJOR 5 #define _QLCNIC_LINUX_MAJOR 5
#define _QLCNIC_LINUX_MINOR 3 #define _QLCNIC_LINUX_MINOR 3
#define _QLCNIC_LINUX_SUBVERSION 49 #define _QLCNIC_LINUX_SUBVERSION 50
#define QLCNIC_LINUX_VERSIONID "5.3.49" #define QLCNIC_LINUX_VERSIONID "5.3.50"
#define QLCNIC_DRV_IDC_VER 0x01 #define QLCNIC_DRV_IDC_VER 0x01
#define QLCNIC_DRIVER_VERSION ((_QLCNIC_LINUX_MAJOR << 16) |\ #define QLCNIC_DRIVER_VERSION ((_QLCNIC_LINUX_MAJOR << 16) |\
(_QLCNIC_LINUX_MINOR << 8) | (_QLCNIC_LINUX_SUBVERSION)) (_QLCNIC_LINUX_MINOR << 8) | (_QLCNIC_LINUX_SUBVERSION))
...@@ -392,7 +392,7 @@ struct qlcnic_dump_template_hdr { ...@@ -392,7 +392,7 @@ struct qlcnic_dump_template_hdr {
struct qlcnic_fw_dump { struct qlcnic_fw_dump {
u8 clr; /* flag to indicate if dump is cleared */ 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 */ u32 size; /* total size of the dump */
void *data; /* dump data area */ void *data; /* dump data area */
struct qlcnic_dump_template_hdr *tmpl_hdr; struct qlcnic_dump_template_hdr *tmpl_hdr;
...@@ -463,7 +463,7 @@ struct qlcnic_hardware_context { ...@@ -463,7 +463,7 @@ struct qlcnic_hardware_context {
struct qlcnic_fdt fdt; struct qlcnic_fdt fdt;
struct qlc_83xx_reset reset; struct qlc_83xx_reset reset;
struct qlc_83xx_idc idc; 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_intrpt_config *intr_tbl;
struct qlcnic_sriov *sriov; struct qlcnic_sriov *sriov;
u32 *reg_tbl; u32 *reg_tbl;
...@@ -837,6 +837,7 @@ struct qlcnic_mac_list_s { ...@@ -837,6 +837,7 @@ struct qlcnic_mac_list_s {
#define QLCNIC_FW_CAP2_HW_LRO_IPV6 BIT_3 #define QLCNIC_FW_CAP2_HW_LRO_IPV6 BIT_3
#define QLCNIC_FW_CAPABILITY_SET_DRV_VER BIT_5 #define QLCNIC_FW_CAPABILITY_SET_DRV_VER BIT_5
#define QLCNIC_FW_CAPABILITY_2_BEACON BIT_7 #define QLCNIC_FW_CAPABILITY_2_BEACON BIT_7
#define QLCNIC_FW_CAPABILITY_2_PER_PORT_ESWITCH_CFG BIT_8
/* module types */ /* module types */
#define LINKEVENT_MODULE_NOT_PRESENT 1 #define LINKEVENT_MODULE_NOT_PRESENT 1
...@@ -1184,6 +1185,7 @@ struct qlcnic_pci_info { ...@@ -1184,6 +1185,7 @@ struct qlcnic_pci_info {
}; };
struct qlcnic_npar_info { struct qlcnic_npar_info {
bool eswitch_status;
u16 pvid; u16 pvid;
u16 min_bw; u16 min_bw;
u16 max_bw; u16 max_bw;
...@@ -1403,7 +1405,6 @@ struct qlcnic_esw_statistics { ...@@ -1403,7 +1405,6 @@ struct qlcnic_esw_statistics {
struct __qlcnic_esw_statistics tx; struct __qlcnic_esw_statistics tx;
}; };
#define QLCNIC_DUMP_MASK_DEF 0x1f
#define QLCNIC_FORCE_FW_DUMP_KEY 0xdeadfeed #define QLCNIC_FORCE_FW_DUMP_KEY 0xdeadfeed
#define QLCNIC_ENABLE_FW_DUMP 0xaddfeed #define QLCNIC_ENABLE_FW_DUMP 0xaddfeed
#define QLCNIC_DISABLE_FW_DUMP 0xbadfeed #define QLCNIC_DISABLE_FW_DUMP 0xbadfeed
...@@ -1478,6 +1479,12 @@ int qlcnic_wol_supported(struct qlcnic_adapter *adapter); ...@@ -1478,6 +1479,12 @@ int qlcnic_wol_supported(struct qlcnic_adapter *adapter);
void qlcnic_prune_lb_filters(struct qlcnic_adapter *adapter); void qlcnic_prune_lb_filters(struct qlcnic_adapter *adapter);
void qlcnic_delete_lb_filters(struct qlcnic_adapter *adapter); void qlcnic_delete_lb_filters(struct qlcnic_adapter *adapter);
int qlcnic_dump_fw(struct qlcnic_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 */ /* Functions from qlcnic_init.c */
void qlcnic_schedule_work(struct qlcnic_adapter *, work_func_t, int); void qlcnic_schedule_work(struct qlcnic_adapter *, work_func_t, int);
...@@ -1723,6 +1730,10 @@ struct qlcnic_hardware_ops { ...@@ -1723,6 +1730,10 @@ struct qlcnic_hardware_ops {
void (*set_mac_filter_count) (struct qlcnic_adapter *); void (*set_mac_filter_count) (struct qlcnic_adapter *);
void (*free_mac_list) (struct qlcnic_adapter *); void (*free_mac_list) (struct qlcnic_adapter *);
int (*read_phys_port_id) (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; extern struct qlcnic_nic_template qlcnic_vf_ops;
...@@ -2069,6 +2080,14 @@ static inline bool qlcnic_82xx_check(struct qlcnic_adapter *adapter) ...@@ -2069,6 +2080,14 @@ static inline bool qlcnic_82xx_check(struct qlcnic_adapter *adapter)
return (device == PCI_DEVICE_ID_QLOGIC_QLE824X) ? true : false; 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) static inline bool qlcnic_83xx_check(struct qlcnic_adapter *adapter)
{ {
unsigned short device = adapter->pdev->device; unsigned short device = adapter->pdev->device;
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include <linux/ipv6.h> #include <linux/ipv6.h>
#include <linux/ethtool.h> #include <linux/ethtool.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/aer.h>
#define QLCNIC_MAX_TX_QUEUES 1 #define QLCNIC_MAX_TX_QUEUES 1
#define RSS_HASHTYPE_IP_TCP 0x3 #define RSS_HASHTYPE_IP_TCP 0x3
...@@ -177,6 +178,10 @@ static struct qlcnic_hardware_ops qlcnic_83xx_hw_ops = { ...@@ -177,6 +178,10 @@ static struct qlcnic_hardware_ops qlcnic_83xx_hw_ops = {
.get_board_info = qlcnic_83xx_get_port_info, .get_board_info = qlcnic_83xx_get_port_info,
.set_mac_filter_count = qlcnic_83xx_set_mac_filter_count, .set_mac_filter_count = qlcnic_83xx_set_mac_filter_count,
.free_mac_list = qlcnic_82xx_free_mac_list, .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 = { static struct qlcnic_nic_template qlcnic_83xx_ops = {
...@@ -723,8 +728,7 @@ void qlcnic_dump_mbx(struct qlcnic_adapter *adapter, ...@@ -723,8 +728,7 @@ void qlcnic_dump_mbx(struct qlcnic_adapter *adapter,
pr_info("\n"); pr_info("\n");
} }
static inline void static void qlcnic_83xx_poll_for_mbx_completion(struct qlcnic_adapter *adapter,
qlcnic_83xx_poll_for_mbx_completion(struct qlcnic_adapter *adapter,
struct qlcnic_cmd_args *cmd) struct qlcnic_cmd_args *cmd)
{ {
struct qlcnic_hardware_context *ahw = adapter->ahw; struct qlcnic_hardware_context *ahw = adapter->ahw;
...@@ -2327,7 +2331,7 @@ int qlcnic_83xx_get_pci_info(struct qlcnic_adapter *adapter, ...@@ -2327,7 +2331,7 @@ int qlcnic_83xx_get_pci_info(struct qlcnic_adapter *adapter,
pci_info->tx_max_bw, pci_info->mac); pci_info->tx_max_bw, pci_info->mac);
} }
if (ahw->op_mode == QLCNIC_MGMT_FUNC) 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); ahw->max_pci_func, ahw->act_pci_func);
} else { } else {
...@@ -3544,7 +3548,7 @@ qlcnic_83xx_notify_cmd_completion(struct qlcnic_adapter *adapter, ...@@ -3544,7 +3548,7 @@ qlcnic_83xx_notify_cmd_completion(struct qlcnic_adapter *adapter,
complete(&cmd->completion); 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 qlcnic_mailbox *mbx = adapter->ahw->mailbox;
struct list_head *head = &mbx->cmd_q; struct list_head *head = &mbx->cmd_q;
...@@ -3564,7 +3568,7 @@ static inline void qlcnic_83xx_flush_mbx_queue(struct qlcnic_adapter *adapter) ...@@ -3564,7 +3568,7 @@ static inline void qlcnic_83xx_flush_mbx_queue(struct qlcnic_adapter *adapter)
spin_unlock(&mbx->queue_lock); 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_hardware_context *ahw = adapter->ahw;
struct qlcnic_mailbox *mbx = ahw->mailbox; struct qlcnic_mailbox *mbx = ahw->mailbox;
...@@ -3592,7 +3596,7 @@ static inline void qlcnic_83xx_signal_mbx_cmd(struct qlcnic_adapter *adapter, ...@@ -3592,7 +3596,7 @@ static inline void qlcnic_83xx_signal_mbx_cmd(struct qlcnic_adapter *adapter,
QLCWRX(adapter->ahw, QLCNIC_FW_MBX_CTRL, QLCNIC_CLR_OWNER); QLCWRX(adapter->ahw, QLCNIC_FW_MBX_CTRL, QLCNIC_CLR_OWNER);
} }
static inline void qlcnic_83xx_dequeue_mbx_cmd(struct qlcnic_adapter *adapter, static void qlcnic_83xx_dequeue_mbx_cmd(struct qlcnic_adapter *adapter,
struct qlcnic_cmd_args *cmd) struct qlcnic_cmd_args *cmd)
{ {
struct qlcnic_mailbox *mbx = adapter->ahw->mailbox; struct qlcnic_mailbox *mbx = adapter->ahw->mailbox;
...@@ -3653,7 +3657,7 @@ void qlcnic_83xx_detach_mailbox_work(struct qlcnic_adapter *adapter) ...@@ -3653,7 +3657,7 @@ void qlcnic_83xx_detach_mailbox_work(struct qlcnic_adapter *adapter)
qlcnic_83xx_flush_mbx_queue(adapter); qlcnic_83xx_flush_mbx_queue(adapter);
} }
static inline int qlcnic_83xx_enqueue_mbx_cmd(struct qlcnic_adapter *adapter, static int qlcnic_83xx_enqueue_mbx_cmd(struct qlcnic_adapter *adapter,
struct qlcnic_cmd_args *cmd, struct qlcnic_cmd_args *cmd,
unsigned long *timeout) unsigned long *timeout)
{ {
...@@ -3680,7 +3684,7 @@ static inline int qlcnic_83xx_enqueue_mbx_cmd(struct qlcnic_adapter *adapter, ...@@ -3680,7 +3684,7 @@ static inline int qlcnic_83xx_enqueue_mbx_cmd(struct qlcnic_adapter *adapter,
return -EBUSY; return -EBUSY;
} }
static inline int qlcnic_83xx_check_mac_rcode(struct qlcnic_adapter *adapter, static int qlcnic_83xx_check_mac_rcode(struct qlcnic_adapter *adapter,
struct qlcnic_cmd_args *cmd) struct qlcnic_cmd_args *cmd)
{ {
u8 mac_cmd_rcode; u8 mac_cmd_rcode;
...@@ -3820,3 +3824,57 @@ int qlcnic_83xx_init_mailbox_work(struct qlcnic_adapter *adapter) ...@@ -3820,3 +3824,57 @@ int qlcnic_83xx_init_mailbox_work(struct qlcnic_adapter *adapter)
set_bit(QLC_83XX_MBX_READY, &mbx->status); set_bit(QLC_83XX_MBX_READY, &mbx->status);
return 0; 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);
}
...@@ -274,11 +274,7 @@ struct qlcnic_macvlan_mbx { ...@@ -274,11 +274,7 @@ struct qlcnic_macvlan_mbx {
struct qlc_83xx_fw_info { struct qlc_83xx_fw_info {
const struct firmware *fw; const struct firmware *fw;
u16 major_fw_version; char fw_file_name[QLC_FW_FILE_NAME_LEN];
u8 minor_fw_version;
u8 sub_fw_version;
u8 fw_build_num;
u8 load_from_file;
}; };
struct qlc_83xx_reset { struct qlc_83xx_reset {
...@@ -297,6 +293,7 @@ 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_DISABLE_FW_RESET_RECOVERY 0x1
#define QLC_83XX_IDC_GRACEFULL_RESET 0x2 #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_TIMESTAMP 0
#define QLC_83XX_IDC_DURATION 1 #define QLC_83XX_IDC_DURATION 1
#define QLC_83XX_IDC_INIT_TIMEOUT_SECS 30 #define QLC_83XX_IDC_INIT_TIMEOUT_SECS 30
...@@ -414,6 +411,7 @@ enum qlcnic_83xx_states { ...@@ -414,6 +411,7 @@ enum qlcnic_83xx_states {
#define QLC_83XX_GET_HW_LRO_CAPABILITY(val) (val & 0x400) #define QLC_83XX_GET_HW_LRO_CAPABILITY(val) (val & 0x400)
#define QLC_83XX_GET_VLAN_ALIGN_CAPABILITY(val) (val & 0x4000) #define QLC_83XX_GET_VLAN_ALIGN_CAPABILITY(val) (val & 0x4000)
#define QLC_83XX_GET_FW_LRO_MSS_CAPABILITY(val) (val & 0x20000) #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_VIRTUAL_NIC_MODE 0xFF
#define QLC_83XX_DEFAULT_MODE 0x0 #define QLC_83XX_DEFAULT_MODE 0x0
#define QLC_83XX_SRIOV_MODE 0x1 #define QLC_83XX_SRIOV_MODE 0x1
...@@ -628,6 +626,7 @@ int qlcnic_83xx_config_vnic_opmode(struct qlcnic_adapter *); ...@@ -628,6 +626,7 @@ int qlcnic_83xx_config_vnic_opmode(struct qlcnic_adapter *);
int qlcnic_83xx_get_vnic_vport_info(struct qlcnic_adapter *, int qlcnic_83xx_get_vnic_vport_info(struct qlcnic_adapter *,
struct qlcnic_info *, u8); struct qlcnic_info *, u8);
int qlcnic_83xx_get_vnic_pf_info(struct qlcnic_adapter *, struct qlcnic_info *); 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_minidump_template(struct qlcnic_adapter *);
void qlcnic_83xx_get_stats(struct qlcnic_adapter *adapter, u64 *data); void qlcnic_83xx_get_stats(struct qlcnic_adapter *adapter, u64 *data);
...@@ -656,4 +655,11 @@ int qlcnic_83xx_idc_init(struct qlcnic_adapter *); ...@@ -656,4 +655,11 @@ int qlcnic_83xx_idc_init(struct qlcnic_adapter *);
int qlcnic_83xx_idc_reattach_driver(struct qlcnic_adapter *); int qlcnic_83xx_idc_reattach_driver(struct qlcnic_adapter *);
int qlcnic_83xx_set_vnic_opmode(struct qlcnic_adapter *); int qlcnic_83xx_set_vnic_opmode(struct qlcnic_adapter *);
int qlcnic_83xx_check_vnic_state(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 #endif
...@@ -797,7 +797,6 @@ static int qlcnic_83xx_idc_init_state(struct qlcnic_adapter *adapter) ...@@ -797,7 +797,6 @@ static int qlcnic_83xx_idc_init_state(struct qlcnic_adapter *adapter)
ret = qlcnic_83xx_idc_restart_hw(adapter, 1); ret = qlcnic_83xx_idc_restart_hw(adapter, 1);
} else { } else {
ret = qlcnic_83xx_idc_check_timeout(adapter, timeout); ret = qlcnic_83xx_idc_check_timeout(adapter, timeout);
return ret;
} }
return ret; return ret;
...@@ -1268,31 +1267,33 @@ static int qlcnic_83xx_copy_bootloader(struct qlcnic_adapter *adapter) ...@@ -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) 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; u32 dest, *p_cache;
u64 addr; int i, ret = -EIO;
u8 data[16]; u8 data[16];
size_t size; size_t size;
int i, ret = -EIO; u64 addr;
dest = QLCRDX(adapter->ahw, QLCNIC_FW_IMAGE_ADDR); dest = QLCRDX(adapter->ahw, QLCNIC_FW_IMAGE_ADDR);
size = (adapter->ahw->fw_info.fw->size & ~0xF); size = (fw->size & ~0xF);
p_cache = (u32 *)adapter->ahw->fw_info.fw->data; p_cache = (u32 *)fw->data;
addr = (u64)dest; addr = (u64)dest;
ret = qlcnic_83xx_ms_mem_write128(adapter, addr, ret = qlcnic_83xx_ms_mem_write128(adapter, addr,
(u32 *)p_cache, size / 16); (u32 *)p_cache, size / 16);
if (ret) { if (ret) {
dev_err(&adapter->pdev->dev, "MS memory write failed\n"); dev_err(&adapter->pdev->dev, "MS memory write failed\n");
release_firmware(adapter->ahw->fw_info.fw); release_firmware(fw);
adapter->ahw->fw_info.fw = NULL; fw_info->fw = NULL;
return -EIO; return -EIO;
} }
/* alignment check */ /* alignment check */
if (adapter->ahw->fw_info.fw->size & 0xF) { if (fw->size & 0xF) {
addr = dest + size; addr = dest + size;
for (i = 0; i < (adapter->ahw->fw_info.fw->size & 0xF); i++) for (i = 0; i < (fw->size & 0xF); i++)
data[i] = adapter->ahw->fw_info.fw->data[size + i]; data[i] = fw->data[size + i];
for (; i < 16; i++) for (; i < 16; i++)
data[i] = 0; data[i] = 0;
ret = qlcnic_83xx_ms_mem_write128(adapter, addr, ret = qlcnic_83xx_ms_mem_write128(adapter, addr,
...@@ -1300,13 +1301,13 @@ static int qlcnic_83xx_copy_fw_file(struct qlcnic_adapter *adapter) ...@@ -1300,13 +1301,13 @@ static int qlcnic_83xx_copy_fw_file(struct qlcnic_adapter *adapter)
if (ret) { if (ret) {
dev_err(&adapter->pdev->dev, dev_err(&adapter->pdev->dev,
"MS memory write failed\n"); "MS memory write failed\n");
release_firmware(adapter->ahw->fw_info.fw); release_firmware(fw);
adapter->ahw->fw_info.fw = NULL; fw_info->fw = NULL;
return -EIO; return -EIO;
} }
} }
release_firmware(adapter->ahw->fw_info.fw); release_firmware(fw);
adapter->ahw->fw_info.fw = NULL; fw_info->fw = NULL;
return 0; return 0;
} }
...@@ -1950,35 +1951,12 @@ static void qlcnic_83xx_init_hw(struct qlcnic_adapter *p_dev) ...@@ -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__); 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) 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; int err = -EIO;
qlcnic_83xx_get_fw_file_name(adapter, fw_file_name); if (request_firmware(&fw_info->fw, fw_info->fw_file_name,
if (request_firmware(&adapter->ahw->fw_info.fw, fw_file_name,
&(adapter->pdev->dev))) { &(adapter->pdev->dev))) {
dev_err(&adapter->pdev->dev, dev_err(&adapter->pdev->dev,
"No file FW image, loading flash FW image.\n"); "No file FW image, loading flash FW image.\n");
...@@ -2025,36 +2003,6 @@ static int qlcnic_83xx_restart_hw(struct qlcnic_adapter *adapter) ...@@ -2025,36 +2003,6 @@ static int qlcnic_83xx_restart_hw(struct qlcnic_adapter *adapter)
return 0; 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 qlcnic_83xx_get_nic_configuration(struct qlcnic_adapter *adapter)
{ {
int err; int err;
...@@ -2074,26 +2022,26 @@ int qlcnic_83xx_get_nic_configuration(struct qlcnic_adapter *adapter) ...@@ -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_mac_filters = nic_info.max_mac_filters;
ahw->max_mtu = nic_info.max_mtu; ahw->max_mtu = nic_info.max_mtu;
/* VNIC mode is detected by BIT_23 in capabilities. This bit is also /* eSwitch capability indicates vNIC mode.
* set in case device is SRIOV capable. VNIC and SRIOV are mutually * vNIC and SRIOV are mutually exclusive operational modes.
* exclusive. So in case of sriov capable device load driver in * If SR-IOV capability is detected, SR-IOV physical function
* default mode * 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)) { if (test_bit(__QLCNIC_SRIOV_CAPABLE, &adapter->state))
ahw->nic_mode = QLC_83XX_DEFAULT_MODE; return QLC_83XX_DEFAULT_OPMODE;
return ahw->nic_mode;
}
if (ahw->capabilities & BIT_23) if (ahw->capabilities & QLC_83XX_ESWITCH_CAPABILITY)
ahw->nic_mode = QLC_83XX_VIRTUAL_NIC_MODE; return QLC_83XX_VIRTUAL_NIC_MODE;
else
ahw->nic_mode = QLC_83XX_DEFAULT_MODE;
return ahw->nic_mode; return QLC_83XX_DEFAULT_OPMODE;
} }
int qlcnic_83xx_configure_opmode(struct qlcnic_adapter *adapter) int qlcnic_83xx_configure_opmode(struct qlcnic_adapter *adapter)
{ {
struct qlcnic_hardware_context *ahw = adapter->ahw;
int ret; int ret;
ret = qlcnic_83xx_get_nic_configuration(adapter); ret = qlcnic_83xx_get_nic_configuration(adapter);
...@@ -2101,10 +2049,15 @@ int qlcnic_83xx_configure_opmode(struct qlcnic_adapter *adapter) ...@@ -2101,10 +2049,15 @@ int qlcnic_83xx_configure_opmode(struct qlcnic_adapter *adapter)
return -EIO; return -EIO;
if (ret == QLC_83XX_VIRTUAL_NIC_MODE) { if (ret == QLC_83XX_VIRTUAL_NIC_MODE) {
ahw->nic_mode = QLC_83XX_VIRTUAL_NIC_MODE;
if (qlcnic_83xx_config_vnic_opmode(adapter)) if (qlcnic_83xx_config_vnic_opmode(adapter))
return -EIO; return -EIO;
} else if (ret == QLC_83XX_DEFAULT_MODE) {
if (qlcnic_83xx_config_default_opmode(adapter)) } 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 -EIO;
} }
...@@ -2174,6 +2127,39 @@ static void qlcnic_83xx_clear_function_resources(struct qlcnic_adapter *adapter) ...@@ -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) int qlcnic_83xx_init(struct qlcnic_adapter *adapter, int pci_using_dac)
{ {
struct qlcnic_hardware_context *ahw = adapter->ahw; struct qlcnic_hardware_context *ahw = adapter->ahw;
...@@ -2199,10 +2185,14 @@ int qlcnic_83xx_init(struct qlcnic_adapter *adapter, int pci_using_dac) ...@@ -2199,10 +2185,14 @@ int qlcnic_83xx_init(struct qlcnic_adapter *adapter, int pci_using_dac)
if (!qlcnic_83xx_read_flash_descriptor_table(adapter)) if (!qlcnic_83xx_read_flash_descriptor_table(adapter))
qlcnic_83xx_read_flash_mfg_id(adapter); qlcnic_83xx_read_flash_mfg_id(adapter);
err = qlcnic_83xx_idc_init(adapter); err = qlcnic_83xx_get_fw_info(adapter);
if (err) if (err)
goto detach_mbx; goto detach_mbx;
err = qlcnic_83xx_idc_init(adapter);
if (err)
goto clear_fw_info;
err = qlcnic_setup_intr(adapter, 0, 0); err = qlcnic_setup_intr(adapter, 0, 0);
if (err) { if (err) {
dev_err(&adapter->pdev->dev, "Failed to setup interrupt\n"); 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) ...@@ -2243,9 +2233,67 @@ int qlcnic_83xx_init(struct qlcnic_adapter *adapter, int pci_using_dac)
disable_intr: disable_intr:
qlcnic_teardown_intr(adapter); qlcnic_teardown_intr(adapter);
clear_fw_info:
kfree(ahw->fw_info);
detach_mbx: detach_mbx:
qlcnic_83xx_detach_mailbox_work(adapter); qlcnic_83xx_detach_mailbox_work(adapter);
qlcnic_83xx_free_mailbox(ahw->mailbox); qlcnic_83xx_free_mailbox(ahw->mailbox);
exit: exit:
return err; 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);
}
...@@ -208,7 +208,7 @@ int qlcnic_83xx_config_vnic_opmode(struct qlcnic_adapter *adapter) ...@@ -208,7 +208,7 @@ int qlcnic_83xx_config_vnic_opmode(struct qlcnic_adapter *adapter)
return -EIO; return -EIO;
} }
if (ahw->capabilities & BIT_23) if (ahw->capabilities & QLC_83XX_ESWITCH_CAPABILITY)
adapter->flags |= QLCNIC_ESWITCH_ENABLED; adapter->flags |= QLCNIC_ESWITCH_ENABLED;
else else
adapter->flags &= ~QLCNIC_ESWITCH_ENABLED; adapter->flags &= ~QLCNIC_ESWITCH_ENABLED;
...@@ -239,3 +239,41 @@ int qlcnic_83xx_check_vnic_state(struct qlcnic_adapter *adapter) ...@@ -239,3 +239,41 @@ int qlcnic_83xx_check_vnic_state(struct qlcnic_adapter *adapter)
return 0; 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;
}
...@@ -1509,6 +1509,68 @@ static void qlcnic_set_msglevel(struct net_device *netdev, u32 msglvl) ...@@ -1509,6 +1509,68 @@ static void qlcnic_set_msglevel(struct net_device *netdev, u32 msglvl)
adapter->ahw->msg_enable = 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 static int
qlcnic_get_dump_flag(struct net_device *netdev, struct ethtool_dump *dump) 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) ...@@ -1525,7 +1587,7 @@ qlcnic_get_dump_flag(struct net_device *netdev, struct ethtool_dump *dump)
else else
dump->len = 0; dump->len = 0;
if (!fw_dump->enable) if (!qlcnic_check_fw_dump_state(adapter))
dump->flag = ETH_FW_DUMP_DISABLE; dump->flag = ETH_FW_DUMP_DISABLE;
else else
dump->flag = fw_dump->tmpl_hdr->drv_cap_mask; 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, ...@@ -1573,77 +1635,111 @@ qlcnic_get_dump_data(struct net_device *netdev, struct ethtool_dump *dump,
return 0; 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 static int
qlcnic_set_dump(struct net_device *netdev, struct ethtool_dump *val) qlcnic_set_dump(struct net_device *netdev, struct ethtool_dump *val)
{ {
int i;
struct qlcnic_adapter *adapter = netdev_priv(netdev); struct qlcnic_adapter *adapter = netdev_priv(netdev);
struct qlcnic_fw_dump *fw_dump = &adapter->ahw->fw_dump; struct qlcnic_fw_dump *fw_dump = &adapter->ahw->fw_dump;
bool valid_mask = false;
int i, ret = 0;
u32 state; u32 state;
switch (val->flag) { switch (val->flag) {
case QLCNIC_FORCE_FW_DUMP_KEY: case QLCNIC_FORCE_FW_DUMP_KEY:
if (!fw_dump->tmpl_hdr) { if (!fw_dump->tmpl_hdr) {
netdev_err(netdev, "FW dump not supported\n"); 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"); netdev_info(netdev, "FW dump not enabled\n");
return 0; ret = -EOPNOTSUPP;
break;
} }
if (fw_dump->clr) { if (fw_dump->clr) {
netdev_info(netdev, netdev_info(netdev,
"Previous dump not cleared, not forcing dump\n"); "Previous dump not cleared, not forcing dump\n");
return 0; break;
} }
netdev_info(netdev, "Forcing a FW dump\n"); netdev_info(netdev, "Forcing a FW dump\n");
qlcnic_dev_request_reset(adapter, val->flag); qlcnic_dev_request_reset(adapter, val->flag);
break; break;
case QLCNIC_DISABLE_FW_DUMP: case QLCNIC_DISABLE_FW_DUMP:
if (fw_dump->enable && fw_dump->tmpl_hdr) { if (!fw_dump->tmpl_hdr) {
netdev_info(netdev, "Disabling FW dump\n"); netdev_err(netdev, "FW dump not supported\n");
fw_dump->enable = 0; ret = -EOPNOTSUPP;
break;
} }
return 0;
ret = qlcnic_disable_fw_dump_state(adapter);
break;
case QLCNIC_ENABLE_FW_DUMP: case QLCNIC_ENABLE_FW_DUMP:
if (!fw_dump->tmpl_hdr) { if (!fw_dump->tmpl_hdr) {
netdev_err(netdev, "FW dump not supported\n"); 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: case QLCNIC_FORCE_FW_RESET:
netdev_info(netdev, "Forcing a FW reset\n"); netdev_info(netdev, "Forcing a FW reset\n");
qlcnic_dev_request_reset(adapter, val->flag); qlcnic_dev_request_reset(adapter, val->flag);
adapter->flags &= ~QLCNIC_FW_RESET_OWNER; adapter->flags &= ~QLCNIC_FW_RESET_OWNER;
return 0; break;
;
case QLCNIC_SET_QUIESCENT: case QLCNIC_SET_QUIESCENT:
case QLCNIC_RESET_QUIESCENT: case QLCNIC_RESET_QUIESCENT:
state = QLC_SHARED_REG_RD32(adapter, QLCNIC_CRB_DEV_STATE); state = QLC_SHARED_REG_RD32(adapter, QLCNIC_CRB_DEV_STATE);
if (state == QLCNIC_DEV_FAILED || (state == QLCNIC_DEV_BADBAD)) if (state == QLCNIC_DEV_FAILED || (state == QLCNIC_DEV_BADBAD))
netdev_info(netdev, "Device in FAILED state\n"); netdev_info(netdev, "Device in FAILED state\n");
return 0; break;
default: default:
if (!fw_dump->tmpl_hdr) { if (!fw_dump->tmpl_hdr) {
netdev_err(netdev, "FW dump not supported\n"); netdev_err(netdev, "FW dump not supported\n");
return -ENOTSUPP; ret = -EOPNOTSUPP;
break;
} }
for (i = 0; i < ARRAY_SIZE(qlcnic_fw_dump_level); i++) { for (i = 0; i < ARRAY_SIZE(qlcnic_fw_dump_level); i++) {
if (val->flag == qlcnic_fw_dump_level[i]) { if (val->flag == qlcnic_fw_dump_level[i]) {
fw_dump->tmpl_hdr->drv_cap_mask = valid_mask = true;
val->flag; break;
netdev_info(netdev, "Driver mask changed to: 0x%x\n",
fw_dump->tmpl_hdr->drv_cap_mask);
return 0;
} }
} }
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 = { const struct ethtool_ops qlcnic_ethtool_ops = {
......
...@@ -540,6 +540,9 @@ static struct qlcnic_hardware_ops qlcnic_hw_ops = { ...@@ -540,6 +540,9 @@ static struct qlcnic_hardware_ops qlcnic_hw_ops = {
.set_mac_filter_count = qlcnic_82xx_set_mac_filter_count, .set_mac_filter_count = qlcnic_82xx_set_mac_filter_count,
.free_mac_list = qlcnic_82xx_free_mac_list, .free_mac_list = qlcnic_82xx_free_mac_list,
.read_phys_port_id = qlcnic_82xx_read_phys_port_id, .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) 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) ...@@ -793,6 +796,23 @@ static int qlcnic_get_act_pci_func(struct qlcnic_adapter *adapter)
return ret; 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) int qlcnic_init_pci_info(struct qlcnic_adapter *adapter)
{ {
struct qlcnic_pci_info *pci_info; struct qlcnic_pci_info *pci_info;
...@@ -836,18 +856,30 @@ int qlcnic_init_pci_info(struct qlcnic_adapter *adapter) ...@@ -836,18 +856,30 @@ int qlcnic_init_pci_info(struct qlcnic_adapter *adapter)
(pci_info[i].type != QLCNIC_TYPE_NIC)) (pci_info[i].type != QLCNIC_TYPE_NIC))
continue; 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].pci_func = pfn;
adapter->npars[j].active = (u8)pci_info[i].active; adapter->npars[j].active = (u8)pci_info[i].active;
adapter->npars[j].type = (u8)pci_info[i].type; adapter->npars[j].type = (u8)pci_info[i].type;
adapter->npars[j].phy_port = (u8)pci_info[i].default_port; 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].min_bw = pci_info[i].tx_min_bw;
adapter->npars[j].max_bw = pci_info[i].tx_max_bw; adapter->npars[j].max_bw = pci_info[i].tx_max_bw;
j++; j++;
} }
for (i = 0; i < QLCNIC_NIU_MAX_XG_PORTS; i++) { if (qlcnic_82xx_check(adapter)) {
for (i = 0; i < QLCNIC_NIU_MAX_XG_PORTS; i++)
adapter->eswitch[i].flags |= QLCNIC_SWITCH_ENABLE; adapter->eswitch[i].flags |= QLCNIC_SWITCH_ENABLE;
if (qlcnic_83xx_check(adapter)) } else if (!qlcnic_port_eswitch_cfg_capability(adapter)) {
for (i = 0; i < QLCNIC_NIU_MAX_XG_PORTS; i++)
qlcnic_enable_eswitch(adapter, i, 1); qlcnic_enable_eswitch(adapter, i, 1);
} }
...@@ -969,7 +1001,7 @@ static int qlcnic_setup_pci_map(struct pci_dev *pdev, ...@@ -969,7 +1001,7 @@ static int qlcnic_setup_pci_map(struct pci_dev *pdev,
return 0; return 0;
} }
static inline bool qlcnic_validate_subsystem_id(struct qlcnic_adapter *adapter, static bool qlcnic_validate_subsystem_id(struct qlcnic_adapter *adapter,
int index) int index)
{ {
struct pci_dev *pdev = adapter->pdev; struct pci_dev *pdev = adapter->pdev;
...@@ -1272,6 +1304,9 @@ int qlcnic_set_default_offload_settings(struct qlcnic_adapter *adapter) ...@@ -1272,6 +1304,9 @@ int qlcnic_set_default_offload_settings(struct qlcnic_adapter *adapter)
return 0; return 0;
for (i = 0; i < adapter->ahw->act_pci_func; i++) { 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)); memset(&esw_cfg, 0, sizeof(struct qlcnic_esw_func_cfg));
esw_cfg.pci_func = adapter->npars[i].pci_func; esw_cfg.pci_func = adapter->npars[i].pci_func;
esw_cfg.mac_override = BIT_0; esw_cfg.mac_override = BIT_0;
...@@ -1334,6 +1369,9 @@ int qlcnic_reset_npar_config(struct qlcnic_adapter *adapter) ...@@ -1334,6 +1369,9 @@ int qlcnic_reset_npar_config(struct qlcnic_adapter *adapter)
for (i = 0; i < adapter->ahw->act_pci_func; i++) { for (i = 0; i < adapter->ahw->act_pci_func; i++) {
npar = &adapter->npars[i]; npar = &adapter->npars[i];
pci_func = npar->pci_func; pci_func = npar->pci_func;
if (!adapter->npars[i].eswitch_status)
continue;
memset(&nic_info, 0, sizeof(struct qlcnic_info)); memset(&nic_info, 0, sizeof(struct qlcnic_info));
err = qlcnic_get_nic_info(adapter, &nic_info, pci_func); err = qlcnic_get_nic_info(adapter, &nic_info, pci_func);
if (err) if (err)
...@@ -2399,6 +2437,7 @@ static void qlcnic_remove(struct pci_dev *pdev) ...@@ -2399,6 +2437,7 @@ static void qlcnic_remove(struct pci_dev *pdev)
qlcnic_83xx_free_mbx_intr(adapter); qlcnic_83xx_free_mbx_intr(adapter);
qlcnic_83xx_detach_mailbox_work(adapter); qlcnic_83xx_detach_mailbox_work(adapter);
qlcnic_83xx_free_mailbox(ahw->mailbox); qlcnic_83xx_free_mailbox(ahw->mailbox);
kfree(ahw->fw_info);
} }
qlcnic_detach(adapter); qlcnic_detach(adapter);
...@@ -3045,7 +3084,7 @@ qlcnic_fwinit_work(struct work_struct *work) ...@@ -3045,7 +3084,7 @@ qlcnic_fwinit_work(struct work_struct *work)
qlcnic_api_unlock(adapter); qlcnic_api_unlock(adapter);
rtnl_lock(); rtnl_lock();
if (adapter->ahw->fw_dump.enable && if (qlcnic_check_fw_dump_state(adapter) &&
(adapter->flags & QLCNIC_FW_RESET_OWNER)) { (adapter->flags & QLCNIC_FW_RESET_OWNER)) {
QLCDB(adapter, DRV, "Take FW dump\n"); QLCDB(adapter, DRV, "Take FW dump\n");
qlcnic_dump_fw(adapter); qlcnic_dump_fw(adapter);
...@@ -3431,19 +3470,6 @@ static int qlcnic_attach_func(struct pci_dev *pdev) ...@@ -3431,19 +3470,6 @@ static int qlcnic_attach_func(struct pci_dev *pdev)
return err; 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)) { if (netif_running(netdev)) {
err = qlcnic_attach(adapter); err = qlcnic_attach(adapter);
if (err) { if (err) {
...@@ -3464,7 +3490,7 @@ static int qlcnic_attach_func(struct pci_dev *pdev) ...@@ -3464,7 +3490,7 @@ static int qlcnic_attach_func(struct pci_dev *pdev)
return err; return err;
} }
static pci_ers_result_t qlcnic_io_error_detected(struct pci_dev *pdev, pci_ers_result_t qlcnic_82xx_io_error_detected(struct pci_dev *pdev,
pci_channel_state_t state) pci_channel_state_t state)
{ {
struct qlcnic_adapter *adapter = pci_get_drvdata(pdev); struct qlcnic_adapter *adapter = pci_get_drvdata(pdev);
...@@ -3484,12 +3510,6 @@ static pci_ers_result_t qlcnic_io_error_detected(struct pci_dev *pdev, ...@@ -3484,12 +3510,6 @@ static pci_ers_result_t qlcnic_io_error_detected(struct pci_dev *pdev,
if (netif_running(netdev)) if (netif_running(netdev))
qlcnic_down(adapter, 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_detach(adapter);
qlcnic_teardown_intr(adapter); qlcnic_teardown_intr(adapter);
...@@ -3501,13 +3521,13 @@ static pci_ers_result_t qlcnic_io_error_detected(struct pci_dev *pdev, ...@@ -3501,13 +3521,13 @@ static pci_ers_result_t qlcnic_io_error_detected(struct pci_dev *pdev,
return PCI_ERS_RESULT_NEED_RESET; 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 : return qlcnic_attach_func(pdev) ? PCI_ERS_RESULT_DISCONNECT :
PCI_ERS_RESULT_RECOVERED; PCI_ERS_RESULT_RECOVERED;
} }
static void qlcnic_io_resume(struct pci_dev *pdev) void qlcnic_82xx_io_resume(struct pci_dev *pdev)
{ {
u32 state; u32 state;
struct qlcnic_adapter *adapter = pci_get_drvdata(pdev); struct qlcnic_adapter *adapter = pci_get_drvdata(pdev);
...@@ -3520,6 +3540,45 @@ static void qlcnic_io_resume(struct pci_dev *pdev) ...@@ -3520,6 +3540,45 @@ static void qlcnic_io_resume(struct pci_dev *pdev)
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 static int
qlcnicvf_start_firmware(struct qlcnic_adapter *adapter) qlcnicvf_start_firmware(struct qlcnic_adapter *adapter)
{ {
......
...@@ -1082,14 +1082,17 @@ int qlcnic_fw_cmd_get_minidump_temp(struct qlcnic_adapter *adapter) ...@@ -1082,14 +1082,17 @@ int qlcnic_fw_cmd_get_minidump_temp(struct qlcnic_adapter *adapter)
} }
tmpl_hdr = ahw->fw_dump.tmpl_hdr; 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) if ((tmpl_hdr->version & 0xfffff) >= 0x20001)
ahw->fw_dump.use_pex_dma = true; ahw->fw_dump.use_pex_dma = true;
else else
ahw->fw_dump.use_pex_dma = false; ahw->fw_dump.use_pex_dma = false;
ahw->fw_dump.enable = 1; qlcnic_enable_fw_dump_state(adapter);
return 0; return 0;
} }
...@@ -1112,7 +1115,11 @@ int qlcnic_dump_fw(struct qlcnic_adapter *adapter) ...@@ -1112,7 +1115,11 @@ int qlcnic_dump_fw(struct qlcnic_adapter *adapter)
ahw = adapter->ahw; 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"); dev_info(&adapter->pdev->dev, "Dump not enabled\n");
return -EIO; return -EIO;
} }
......
...@@ -398,14 +398,10 @@ int qlcnic_sriov_get_vf_vport_info(struct qlcnic_adapter *adapter, ...@@ -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, 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 = MSW(cmd->rsp.arg[1]) & 0xffff;
adapter->rx_pvid = 0;
} else {
adapter->rx_pvid = (cmd->rsp.arg[1] >> 16) & 0xffff;
adapter->flags &= ~QLCNIC_TAGGING_ENABLED; adapter->flags &= ~QLCNIC_TAGGING_ENABLED;
}
return 0; return 0;
} }
...@@ -441,9 +437,8 @@ static int qlcnic_sriov_get_vf_acl(struct qlcnic_adapter *adapter, ...@@ -441,9 +437,8 @@ static int qlcnic_sriov_get_vf_acl(struct qlcnic_adapter *adapter,
{ {
struct qlcnic_sriov *sriov = adapter->ahw->sriov; struct qlcnic_sriov *sriov = adapter->ahw->sriov;
struct qlcnic_cmd_args cmd; 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); ret = qlcnic_sriov_alloc_bc_mbx_args(&cmd, QLCNIC_BC_CMD_GET_ACL);
if (ret) if (ret)
return ret; return ret;
...@@ -459,7 +454,7 @@ static int qlcnic_sriov_get_vf_acl(struct qlcnic_adapter *adapter, ...@@ -459,7 +454,7 @@ static int qlcnic_sriov_get_vf_acl(struct qlcnic_adapter *adapter,
ret = qlcnic_sriov_set_guest_vlan_mode(adapter, &cmd); ret = qlcnic_sriov_set_guest_vlan_mode(adapter, &cmd);
break; break;
case QLC_PVID_MODE: case QLC_PVID_MODE:
ret = qlcnic_sriov_set_pvid_mode(adapter, &cmd, cap); ret = qlcnic_sriov_set_pvid_mode(adapter, &cmd);
break; break;
} }
} }
......
...@@ -1183,10 +1183,19 @@ static int qlcnic_sriov_pf_get_acl_cmd(struct qlcnic_bc_trans *trans, ...@@ -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_vf_info *vf = trans->vf;
struct qlcnic_vport *vp = vf->vp; struct qlcnic_vport *vp = vf->vp;
u8 cmd_op, mode = vp->vlan_mode; u8 cmd_op, mode = vp->vlan_mode;
struct qlcnic_adapter *adapter;
adapter = vf->adapter;
cmd_op = trans->req_hdr->cmd_op; cmd_op = trans->req_hdr->cmd_op;
cmd->rsp.arg[0] |= 1 << 25; 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) { switch (mode) {
case QLC_GUEST_VLAN_MODE: case QLC_GUEST_VLAN_MODE:
cmd->rsp.arg[1] = mode | 1 << 8; cmd->rsp.arg[1] = mode | 1 << 8;
...@@ -1772,7 +1781,7 @@ int qlcnic_sriov_set_vf_vlan(struct net_device *netdev, int vf, ...@@ -1772,7 +1781,7 @@ int qlcnic_sriov_set_vf_vlan(struct net_device *netdev, int vf,
return 0; return 0;
} }
static inline __u32 qlcnic_sriov_get_vf_vlan(struct qlcnic_adapter *adapter, static __u32 qlcnic_sriov_get_vf_vlan(struct qlcnic_adapter *adapter,
struct qlcnic_vport *vp, int vf) struct qlcnic_vport *vp, int vf)
{ {
__u32 vlan = 0; __u32 vlan = 0;
......
...@@ -465,8 +465,14 @@ static ssize_t qlcnic_sysfs_read_pm_config(struct file *filp, ...@@ -465,8 +465,14 @@ static ssize_t qlcnic_sysfs_read_pm_config(struct file *filp,
memset(&pm_cfg, 0, memset(&pm_cfg, 0,
sizeof(struct qlcnic_pm_func_cfg) * QLCNIC_MAX_PCI_FUNC); 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; 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].action = adapter->npars[i].enable_pm;
pm_cfg[pci_func].dest_npar = 0; pm_cfg[pci_func].dest_npar = 0;
pm_cfg[pci_func].pci_func = i; pm_cfg[pci_func].pci_func = i;
...@@ -632,8 +638,14 @@ static ssize_t qlcnic_sysfs_read_esw_config(struct file *file, ...@@ -632,8 +638,14 @@ static ssize_t qlcnic_sysfs_read_esw_config(struct file *file,
memset(&esw_cfg, 0, memset(&esw_cfg, 0,
sizeof(struct qlcnic_esw_func_cfg) * QLCNIC_MAX_PCI_FUNC); 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; 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; esw_cfg[pci_func].pci_func = pci_func;
if (qlcnic_get_eswitch_port_config(adapter, &esw_cfg[pci_func])) if (qlcnic_get_eswitch_port_config(adapter, &esw_cfg[pci_func]))
return QL_STATUS_INVALID_PARAM; return QL_STATUS_INVALID_PARAM;
...@@ -732,6 +744,9 @@ static ssize_t qlcnic_sysfs_read_npar_config(struct file *file, ...@@ -732,6 +744,9 @@ static ssize_t qlcnic_sysfs_read_npar_config(struct file *file,
if (ret) if (ret)
return ret; return ret;
if (!adapter->npars[i].eswitch_status)
continue;
np_cfg[i].pci_func = i; np_cfg[i].pci_func = i;
np_cfg[i].op_mode = (u8)nic_info.op_mode; np_cfg[i].op_mode = (u8)nic_info.op_mode;
np_cfg[i].port_num = nic_info.phys_port; np_cfg[i].port_num = nic_info.phys_port;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment