diff options
author | David S. Miller <davem@davemloft.net> | 2013-08-31 22:35:26 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2013-08-31 22:35:26 -0400 |
commit | ba39767288661c01ac7797b6b981f73b6513cf55 (patch) | |
tree | 411bae7d6a3df6d43777ae26f0c35caded95923c | |
parent | eb3c0d83cc78361a28e52e514a7095fdbf771e7e (diff) | |
parent | 693dcd2fb23a19b29ebff786b3283cc7eeb60edb (diff) |
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: David S. Miller <davem@davemloft.net>
-rw-r--r-- | drivers/net/ethernet/qlogic/qlcnic/qlcnic.h | 29 | ||||
-rw-r--r-- | drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c | 84 | ||||
-rw-r--r-- | drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h | 16 | ||||
-rw-r--r-- | drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c | 220 | ||||
-rw-r--r-- | drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_vnic.c | 40 | ||||
-rw-r--r-- | drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c | 152 | ||||
-rw-r--r-- | drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c | 119 | ||||
-rw-r--r-- | drivers/net/ethernet/qlogic/qlcnic/qlcnic_minidump.c | 13 | ||||
-rw-r--r-- | drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c | 15 | ||||
-rw-r--r-- | drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_pf.c | 13 | ||||
-rw-r--r-- | drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c | 19 |
11 files changed, 535 insertions, 185 deletions
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 @@ | |||
38 | 38 | ||
39 | #define _QLCNIC_LINUX_MAJOR 5 | 39 | #define _QLCNIC_LINUX_MAJOR 5 |
40 | #define _QLCNIC_LINUX_MINOR 3 | 40 | #define _QLCNIC_LINUX_MINOR 3 |
41 | #define _QLCNIC_LINUX_SUBVERSION 49 | 41 | #define _QLCNIC_LINUX_SUBVERSION 50 |
42 | #define QLCNIC_LINUX_VERSIONID "5.3.49" | 42 | #define QLCNIC_LINUX_VERSIONID "5.3.50" |
43 | #define QLCNIC_DRV_IDC_VER 0x01 | 43 | #define QLCNIC_DRV_IDC_VER 0x01 |
44 | #define QLCNIC_DRIVER_VERSION ((_QLCNIC_LINUX_MAJOR << 16) |\ | 44 | #define QLCNIC_DRIVER_VERSION ((_QLCNIC_LINUX_MAJOR << 16) |\ |
45 | (_QLCNIC_LINUX_MINOR << 8) | (_QLCNIC_LINUX_SUBVERSION)) | 45 | (_QLCNIC_LINUX_MINOR << 8) | (_QLCNIC_LINUX_SUBVERSION)) |
@@ -392,7 +392,7 @@ struct qlcnic_dump_template_hdr { | |||
392 | 392 | ||
393 | struct qlcnic_fw_dump { | 393 | struct qlcnic_fw_dump { |
394 | u8 clr; /* flag to indicate if dump is cleared */ | 394 | u8 clr; /* flag to indicate if dump is cleared */ |
395 | u8 enable; /* enable/disable dump */ | 395 | bool enable; /* enable/disable dump */ |
396 | u32 size; /* total size of the dump */ | 396 | u32 size; /* total size of the dump */ |
397 | void *data; /* dump data area */ | 397 | void *data; /* dump data area */ |
398 | struct qlcnic_dump_template_hdr *tmpl_hdr; | 398 | struct qlcnic_dump_template_hdr *tmpl_hdr; |
@@ -463,7 +463,7 @@ struct qlcnic_hardware_context { | |||
463 | struct qlcnic_fdt fdt; | 463 | struct qlcnic_fdt fdt; |
464 | struct qlc_83xx_reset reset; | 464 | struct qlc_83xx_reset reset; |
465 | struct qlc_83xx_idc idc; | 465 | struct qlc_83xx_idc idc; |
466 | struct qlc_83xx_fw_info fw_info; | 466 | struct qlc_83xx_fw_info *fw_info; |
467 | struct qlcnic_intrpt_config *intr_tbl; | 467 | struct qlcnic_intrpt_config *intr_tbl; |
468 | struct qlcnic_sriov *sriov; | 468 | struct qlcnic_sriov *sriov; |
469 | u32 *reg_tbl; | 469 | u32 *reg_tbl; |
@@ -837,6 +837,7 @@ struct qlcnic_mac_list_s { | |||
837 | #define QLCNIC_FW_CAP2_HW_LRO_IPV6 BIT_3 | 837 | #define QLCNIC_FW_CAP2_HW_LRO_IPV6 BIT_3 |
838 | #define QLCNIC_FW_CAPABILITY_SET_DRV_VER BIT_5 | 838 | #define QLCNIC_FW_CAPABILITY_SET_DRV_VER BIT_5 |
839 | #define QLCNIC_FW_CAPABILITY_2_BEACON BIT_7 | 839 | #define QLCNIC_FW_CAPABILITY_2_BEACON BIT_7 |
840 | #define QLCNIC_FW_CAPABILITY_2_PER_PORT_ESWITCH_CFG BIT_8 | ||
840 | 841 | ||
841 | /* module types */ | 842 | /* module types */ |
842 | #define LINKEVENT_MODULE_NOT_PRESENT 1 | 843 | #define LINKEVENT_MODULE_NOT_PRESENT 1 |
@@ -1184,6 +1185,7 @@ struct qlcnic_pci_info { | |||
1184 | }; | 1185 | }; |
1185 | 1186 | ||
1186 | struct qlcnic_npar_info { | 1187 | struct qlcnic_npar_info { |
1188 | bool eswitch_status; | ||
1187 | u16 pvid; | 1189 | u16 pvid; |
1188 | u16 min_bw; | 1190 | u16 min_bw; |
1189 | u16 max_bw; | 1191 | u16 max_bw; |
@@ -1403,7 +1405,6 @@ struct qlcnic_esw_statistics { | |||
1403 | struct __qlcnic_esw_statistics tx; | 1405 | struct __qlcnic_esw_statistics tx; |
1404 | }; | 1406 | }; |
1405 | 1407 | ||
1406 | #define QLCNIC_DUMP_MASK_DEF 0x1f | ||
1407 | #define QLCNIC_FORCE_FW_DUMP_KEY 0xdeadfeed | 1408 | #define QLCNIC_FORCE_FW_DUMP_KEY 0xdeadfeed |
1408 | #define QLCNIC_ENABLE_FW_DUMP 0xaddfeed | 1409 | #define QLCNIC_ENABLE_FW_DUMP 0xaddfeed |
1409 | #define QLCNIC_DISABLE_FW_DUMP 0xbadfeed | 1410 | #define QLCNIC_DISABLE_FW_DUMP 0xbadfeed |
@@ -1478,6 +1479,12 @@ int qlcnic_wol_supported(struct qlcnic_adapter *adapter); | |||
1478 | void qlcnic_prune_lb_filters(struct qlcnic_adapter *adapter); | 1479 | void qlcnic_prune_lb_filters(struct qlcnic_adapter *adapter); |
1479 | void qlcnic_delete_lb_filters(struct qlcnic_adapter *adapter); | 1480 | void qlcnic_delete_lb_filters(struct qlcnic_adapter *adapter); |
1480 | int qlcnic_dump_fw(struct qlcnic_adapter *); | 1481 | int qlcnic_dump_fw(struct qlcnic_adapter *); |
1482 | int qlcnic_enable_fw_dump_state(struct qlcnic_adapter *); | ||
1483 | bool qlcnic_check_fw_dump_state(struct qlcnic_adapter *); | ||
1484 | pci_ers_result_t qlcnic_82xx_io_error_detected(struct pci_dev *, | ||
1485 | pci_channel_state_t); | ||
1486 | pci_ers_result_t qlcnic_82xx_io_slot_reset(struct pci_dev *); | ||
1487 | void qlcnic_82xx_io_resume(struct pci_dev *); | ||
1481 | 1488 | ||
1482 | /* Functions from qlcnic_init.c */ | 1489 | /* Functions from qlcnic_init.c */ |
1483 | void qlcnic_schedule_work(struct qlcnic_adapter *, work_func_t, int); | 1490 | void qlcnic_schedule_work(struct qlcnic_adapter *, work_func_t, int); |
@@ -1723,6 +1730,10 @@ struct qlcnic_hardware_ops { | |||
1723 | void (*set_mac_filter_count) (struct qlcnic_adapter *); | 1730 | void (*set_mac_filter_count) (struct qlcnic_adapter *); |
1724 | void (*free_mac_list) (struct qlcnic_adapter *); | 1731 | void (*free_mac_list) (struct qlcnic_adapter *); |
1725 | int (*read_phys_port_id) (struct qlcnic_adapter *); | 1732 | int (*read_phys_port_id) (struct qlcnic_adapter *); |
1733 | pci_ers_result_t (*io_error_detected) (struct pci_dev *, | ||
1734 | pci_channel_state_t); | ||
1735 | pci_ers_result_t (*io_slot_reset) (struct pci_dev *); | ||
1736 | void (*io_resume) (struct pci_dev *); | ||
1726 | }; | 1737 | }; |
1727 | 1738 | ||
1728 | extern struct qlcnic_nic_template qlcnic_vf_ops; | 1739 | extern struct qlcnic_nic_template qlcnic_vf_ops; |
@@ -2069,6 +2080,14 @@ static inline bool qlcnic_82xx_check(struct qlcnic_adapter *adapter) | |||
2069 | return (device == PCI_DEVICE_ID_QLOGIC_QLE824X) ? true : false; | 2080 | return (device == PCI_DEVICE_ID_QLOGIC_QLE824X) ? true : false; |
2070 | } | 2081 | } |
2071 | 2082 | ||
2083 | static inline bool qlcnic_84xx_check(struct qlcnic_adapter *adapter) | ||
2084 | { | ||
2085 | unsigned short device = adapter->pdev->device; | ||
2086 | |||
2087 | return ((device == PCI_DEVICE_ID_QLOGIC_QLE844X) || | ||
2088 | (device == PCI_DEVICE_ID_QLOGIC_VF_QLE844X)) ? true : false; | ||
2089 | } | ||
2090 | |||
2072 | static inline bool qlcnic_83xx_check(struct qlcnic_adapter *adapter) | 2091 | static inline bool qlcnic_83xx_check(struct qlcnic_adapter *adapter) |
2073 | { | 2092 | { |
2074 | unsigned short device = adapter->pdev->device; | 2093 | 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 @@ | |||
11 | #include <linux/ipv6.h> | 11 | #include <linux/ipv6.h> |
12 | #include <linux/ethtool.h> | 12 | #include <linux/ethtool.h> |
13 | #include <linux/interrupt.h> | 13 | #include <linux/interrupt.h> |
14 | #include <linux/aer.h> | ||
14 | 15 | ||
15 | #define QLCNIC_MAX_TX_QUEUES 1 | 16 | #define QLCNIC_MAX_TX_QUEUES 1 |
16 | #define RSS_HASHTYPE_IP_TCP 0x3 | 17 | #define RSS_HASHTYPE_IP_TCP 0x3 |
@@ -177,6 +178,10 @@ static struct qlcnic_hardware_ops qlcnic_83xx_hw_ops = { | |||
177 | .get_board_info = qlcnic_83xx_get_port_info, | 178 | .get_board_info = qlcnic_83xx_get_port_info, |
178 | .set_mac_filter_count = qlcnic_83xx_set_mac_filter_count, | 179 | .set_mac_filter_count = qlcnic_83xx_set_mac_filter_count, |
179 | .free_mac_list = qlcnic_82xx_free_mac_list, | 180 | .free_mac_list = qlcnic_82xx_free_mac_list, |
181 | .io_error_detected = qlcnic_83xx_io_error_detected, | ||
182 | .io_slot_reset = qlcnic_83xx_io_slot_reset, | ||
183 | .io_resume = qlcnic_83xx_io_resume, | ||
184 | |||
180 | }; | 185 | }; |
181 | 186 | ||
182 | static struct qlcnic_nic_template qlcnic_83xx_ops = { | 187 | static struct qlcnic_nic_template qlcnic_83xx_ops = { |
@@ -723,9 +728,8 @@ void qlcnic_dump_mbx(struct qlcnic_adapter *adapter, | |||
723 | pr_info("\n"); | 728 | pr_info("\n"); |
724 | } | 729 | } |
725 | 730 | ||
726 | static inline void | 731 | static void qlcnic_83xx_poll_for_mbx_completion(struct qlcnic_adapter *adapter, |
727 | qlcnic_83xx_poll_for_mbx_completion(struct qlcnic_adapter *adapter, | 732 | struct qlcnic_cmd_args *cmd) |
728 | struct qlcnic_cmd_args *cmd) | ||
729 | { | 733 | { |
730 | struct qlcnic_hardware_context *ahw = adapter->ahw; | 734 | struct qlcnic_hardware_context *ahw = adapter->ahw; |
731 | int opcode = LSW(cmd->req.arg[0]); | 735 | int opcode = LSW(cmd->req.arg[0]); |
@@ -2327,7 +2331,7 @@ int qlcnic_83xx_get_pci_info(struct qlcnic_adapter *adapter, | |||
2327 | pci_info->tx_max_bw, pci_info->mac); | 2331 | pci_info->tx_max_bw, pci_info->mac); |
2328 | } | 2332 | } |
2329 | if (ahw->op_mode == QLCNIC_MGMT_FUNC) | 2333 | if (ahw->op_mode == QLCNIC_MGMT_FUNC) |
2330 | dev_info(dev, "Max vNIC functions = %d, active vNIC functions = %d\n", | 2334 | dev_info(dev, "Max functions = %d, active functions = %d\n", |
2331 | ahw->max_pci_func, ahw->act_pci_func); | 2335 | ahw->max_pci_func, ahw->act_pci_func); |
2332 | 2336 | ||
2333 | } else { | 2337 | } else { |
@@ -3544,7 +3548,7 @@ qlcnic_83xx_notify_cmd_completion(struct qlcnic_adapter *adapter, | |||
3544 | complete(&cmd->completion); | 3548 | complete(&cmd->completion); |
3545 | } | 3549 | } |
3546 | 3550 | ||
3547 | static inline void qlcnic_83xx_flush_mbx_queue(struct qlcnic_adapter *adapter) | 3551 | static void qlcnic_83xx_flush_mbx_queue(struct qlcnic_adapter *adapter) |
3548 | { | 3552 | { |
3549 | struct qlcnic_mailbox *mbx = adapter->ahw->mailbox; | 3553 | struct qlcnic_mailbox *mbx = adapter->ahw->mailbox; |
3550 | struct list_head *head = &mbx->cmd_q; | 3554 | struct list_head *head = &mbx->cmd_q; |
@@ -3564,7 +3568,7 @@ static inline void qlcnic_83xx_flush_mbx_queue(struct qlcnic_adapter *adapter) | |||
3564 | spin_unlock(&mbx->queue_lock); | 3568 | spin_unlock(&mbx->queue_lock); |
3565 | } | 3569 | } |
3566 | 3570 | ||
3567 | static inline int qlcnic_83xx_check_mbx_status(struct qlcnic_adapter *adapter) | 3571 | static int qlcnic_83xx_check_mbx_status(struct qlcnic_adapter *adapter) |
3568 | { | 3572 | { |
3569 | struct qlcnic_hardware_context *ahw = adapter->ahw; | 3573 | struct qlcnic_hardware_context *ahw = adapter->ahw; |
3570 | struct qlcnic_mailbox *mbx = ahw->mailbox; | 3574 | struct qlcnic_mailbox *mbx = ahw->mailbox; |
@@ -3592,8 +3596,8 @@ static inline void qlcnic_83xx_signal_mbx_cmd(struct qlcnic_adapter *adapter, | |||
3592 | QLCWRX(adapter->ahw, QLCNIC_FW_MBX_CTRL, QLCNIC_CLR_OWNER); | 3596 | QLCWRX(adapter->ahw, QLCNIC_FW_MBX_CTRL, QLCNIC_CLR_OWNER); |
3593 | } | 3597 | } |
3594 | 3598 | ||
3595 | static inline void qlcnic_83xx_dequeue_mbx_cmd(struct qlcnic_adapter *adapter, | 3599 | static void qlcnic_83xx_dequeue_mbx_cmd(struct qlcnic_adapter *adapter, |
3596 | struct qlcnic_cmd_args *cmd) | 3600 | struct qlcnic_cmd_args *cmd) |
3597 | { | 3601 | { |
3598 | struct qlcnic_mailbox *mbx = adapter->ahw->mailbox; | 3602 | struct qlcnic_mailbox *mbx = adapter->ahw->mailbox; |
3599 | 3603 | ||
@@ -3653,9 +3657,9 @@ void qlcnic_83xx_detach_mailbox_work(struct qlcnic_adapter *adapter) | |||
3653 | qlcnic_83xx_flush_mbx_queue(adapter); | 3657 | qlcnic_83xx_flush_mbx_queue(adapter); |
3654 | } | 3658 | } |
3655 | 3659 | ||
3656 | static inline int qlcnic_83xx_enqueue_mbx_cmd(struct qlcnic_adapter *adapter, | 3660 | static int qlcnic_83xx_enqueue_mbx_cmd(struct qlcnic_adapter *adapter, |
3657 | struct qlcnic_cmd_args *cmd, | 3661 | struct qlcnic_cmd_args *cmd, |
3658 | unsigned long *timeout) | 3662 | unsigned long *timeout) |
3659 | { | 3663 | { |
3660 | struct qlcnic_mailbox *mbx = adapter->ahw->mailbox; | 3664 | struct qlcnic_mailbox *mbx = adapter->ahw->mailbox; |
3661 | 3665 | ||
@@ -3680,8 +3684,8 @@ static inline int qlcnic_83xx_enqueue_mbx_cmd(struct qlcnic_adapter *adapter, | |||
3680 | return -EBUSY; | 3684 | return -EBUSY; |
3681 | } | 3685 | } |
3682 | 3686 | ||
3683 | static inline int qlcnic_83xx_check_mac_rcode(struct qlcnic_adapter *adapter, | 3687 | static int qlcnic_83xx_check_mac_rcode(struct qlcnic_adapter *adapter, |
3684 | struct qlcnic_cmd_args *cmd) | 3688 | struct qlcnic_cmd_args *cmd) |
3685 | { | 3689 | { |
3686 | u8 mac_cmd_rcode; | 3690 | u8 mac_cmd_rcode; |
3687 | u32 fw_data; | 3691 | u32 fw_data; |
@@ -3820,3 +3824,57 @@ int qlcnic_83xx_init_mailbox_work(struct qlcnic_adapter *adapter) | |||
3820 | set_bit(QLC_83XX_MBX_READY, &mbx->status); | 3824 | set_bit(QLC_83XX_MBX_READY, &mbx->status); |
3821 | return 0; | 3825 | return 0; |
3822 | } | 3826 | } |
3827 | |||
3828 | pci_ers_result_t qlcnic_83xx_io_error_detected(struct pci_dev *pdev, | ||
3829 | pci_channel_state_t state) | ||
3830 | { | ||
3831 | struct qlcnic_adapter *adapter = pci_get_drvdata(pdev); | ||
3832 | |||
3833 | if (state == pci_channel_io_perm_failure) | ||
3834 | return PCI_ERS_RESULT_DISCONNECT; | ||
3835 | |||
3836 | if (state == pci_channel_io_normal) | ||
3837 | return PCI_ERS_RESULT_RECOVERED; | ||
3838 | |||
3839 | set_bit(__QLCNIC_AER, &adapter->state); | ||
3840 | set_bit(__QLCNIC_RESETTING, &adapter->state); | ||
3841 | |||
3842 | qlcnic_83xx_aer_stop_poll_work(adapter); | ||
3843 | |||
3844 | pci_save_state(pdev); | ||
3845 | pci_disable_device(pdev); | ||
3846 | |||
3847 | return PCI_ERS_RESULT_NEED_RESET; | ||
3848 | } | ||
3849 | |||
3850 | pci_ers_result_t qlcnic_83xx_io_slot_reset(struct pci_dev *pdev) | ||
3851 | { | ||
3852 | struct qlcnic_adapter *adapter = pci_get_drvdata(pdev); | ||
3853 | int err = 0; | ||
3854 | |||
3855 | pdev->error_state = pci_channel_io_normal; | ||
3856 | err = pci_enable_device(pdev); | ||
3857 | if (err) | ||
3858 | goto disconnect; | ||
3859 | |||
3860 | pci_set_power_state(pdev, PCI_D0); | ||
3861 | pci_set_master(pdev); | ||
3862 | pci_restore_state(pdev); | ||
3863 | |||
3864 | err = qlcnic_83xx_aer_reset(adapter); | ||
3865 | if (err == 0) | ||
3866 | return PCI_ERS_RESULT_RECOVERED; | ||
3867 | disconnect: | ||
3868 | clear_bit(__QLCNIC_AER, &adapter->state); | ||
3869 | clear_bit(__QLCNIC_RESETTING, &adapter->state); | ||
3870 | return PCI_ERS_RESULT_DISCONNECT; | ||
3871 | } | ||
3872 | |||
3873 | void qlcnic_83xx_io_resume(struct pci_dev *pdev) | ||
3874 | { | ||
3875 | struct qlcnic_adapter *adapter = pci_get_drvdata(pdev); | ||
3876 | |||
3877 | pci_cleanup_aer_uncorrect_error_status(pdev); | ||
3878 | if (test_and_clear_bit(__QLCNIC_AER, &adapter->state)) | ||
3879 | qlcnic_83xx_aer_start_poll_work(adapter); | ||
3880 | } | ||
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 { | |||
274 | 274 | ||
275 | struct qlc_83xx_fw_info { | 275 | struct qlc_83xx_fw_info { |
276 | const struct firmware *fw; | 276 | const struct firmware *fw; |
277 | u16 major_fw_version; | 277 | char fw_file_name[QLC_FW_FILE_NAME_LEN]; |
278 | u8 minor_fw_version; | ||
279 | u8 sub_fw_version; | ||
280 | u8 fw_build_num; | ||
281 | u8 load_from_file; | ||
282 | }; | 278 | }; |
283 | 279 | ||
284 | struct qlc_83xx_reset { | 280 | struct qlc_83xx_reset { |
@@ -297,6 +293,7 @@ struct qlc_83xx_reset { | |||
297 | 293 | ||
298 | #define QLC_83XX_IDC_DISABLE_FW_RESET_RECOVERY 0x1 | 294 | #define QLC_83XX_IDC_DISABLE_FW_RESET_RECOVERY 0x1 |
299 | #define QLC_83XX_IDC_GRACEFULL_RESET 0x2 | 295 | #define QLC_83XX_IDC_GRACEFULL_RESET 0x2 |
296 | #define QLC_83XX_IDC_DISABLE_FW_DUMP 0x4 | ||
300 | #define QLC_83XX_IDC_TIMESTAMP 0 | 297 | #define QLC_83XX_IDC_TIMESTAMP 0 |
301 | #define QLC_83XX_IDC_DURATION 1 | 298 | #define QLC_83XX_IDC_DURATION 1 |
302 | #define QLC_83XX_IDC_INIT_TIMEOUT_SECS 30 | 299 | #define QLC_83XX_IDC_INIT_TIMEOUT_SECS 30 |
@@ -414,6 +411,7 @@ enum qlcnic_83xx_states { | |||
414 | #define QLC_83XX_GET_HW_LRO_CAPABILITY(val) (val & 0x400) | 411 | #define QLC_83XX_GET_HW_LRO_CAPABILITY(val) (val & 0x400) |
415 | #define QLC_83XX_GET_VLAN_ALIGN_CAPABILITY(val) (val & 0x4000) | 412 | #define QLC_83XX_GET_VLAN_ALIGN_CAPABILITY(val) (val & 0x4000) |
416 | #define QLC_83XX_GET_FW_LRO_MSS_CAPABILITY(val) (val & 0x20000) | 413 | #define QLC_83XX_GET_FW_LRO_MSS_CAPABILITY(val) (val & 0x20000) |
414 | #define QLC_83XX_ESWITCH_CAPABILITY BIT_23 | ||
417 | #define QLC_83XX_VIRTUAL_NIC_MODE 0xFF | 415 | #define QLC_83XX_VIRTUAL_NIC_MODE 0xFF |
418 | #define QLC_83XX_DEFAULT_MODE 0x0 | 416 | #define QLC_83XX_DEFAULT_MODE 0x0 |
419 | #define QLC_83XX_SRIOV_MODE 0x1 | 417 | #define QLC_83XX_SRIOV_MODE 0x1 |
@@ -628,6 +626,7 @@ int qlcnic_83xx_config_vnic_opmode(struct qlcnic_adapter *); | |||
628 | int qlcnic_83xx_get_vnic_vport_info(struct qlcnic_adapter *, | 626 | int qlcnic_83xx_get_vnic_vport_info(struct qlcnic_adapter *, |
629 | struct qlcnic_info *, u8); | 627 | struct qlcnic_info *, u8); |
630 | int qlcnic_83xx_get_vnic_pf_info(struct qlcnic_adapter *, struct qlcnic_info *); | 628 | int qlcnic_83xx_get_vnic_pf_info(struct qlcnic_adapter *, struct qlcnic_info *); |
629 | int qlcnic_83xx_enable_port_eswitch(struct qlcnic_adapter *, int); | ||
631 | 630 | ||
632 | void qlcnic_83xx_get_minidump_template(struct qlcnic_adapter *); | 631 | void qlcnic_83xx_get_minidump_template(struct qlcnic_adapter *); |
633 | void qlcnic_83xx_get_stats(struct qlcnic_adapter *adapter, u64 *data); | 632 | void qlcnic_83xx_get_stats(struct qlcnic_adapter *adapter, u64 *data); |
@@ -656,4 +655,11 @@ int qlcnic_83xx_idc_init(struct qlcnic_adapter *); | |||
656 | int qlcnic_83xx_idc_reattach_driver(struct qlcnic_adapter *); | 655 | int qlcnic_83xx_idc_reattach_driver(struct qlcnic_adapter *); |
657 | int qlcnic_83xx_set_vnic_opmode(struct qlcnic_adapter *); | 656 | int qlcnic_83xx_set_vnic_opmode(struct qlcnic_adapter *); |
658 | int qlcnic_83xx_check_vnic_state(struct qlcnic_adapter *); | 657 | int qlcnic_83xx_check_vnic_state(struct qlcnic_adapter *); |
658 | void qlcnic_83xx_aer_stop_poll_work(struct qlcnic_adapter *); | ||
659 | int qlcnic_83xx_aer_reset(struct qlcnic_adapter *); | ||
660 | void qlcnic_83xx_aer_start_poll_work(struct qlcnic_adapter *); | ||
661 | pci_ers_result_t qlcnic_83xx_io_error_detected(struct pci_dev *, | ||
662 | pci_channel_state_t); | ||
663 | pci_ers_result_t qlcnic_83xx_io_slot_reset(struct pci_dev *); | ||
664 | void qlcnic_83xx_io_resume(struct pci_dev *); | ||
659 | #endif | 665 | #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) | |||
797 | ret = qlcnic_83xx_idc_restart_hw(adapter, 1); | 797 | ret = qlcnic_83xx_idc_restart_hw(adapter, 1); |
798 | } else { | 798 | } else { |
799 | ret = qlcnic_83xx_idc_check_timeout(adapter, timeout); | 799 | ret = qlcnic_83xx_idc_check_timeout(adapter, timeout); |
800 | return ret; | ||
801 | } | 800 | } |
802 | 801 | ||
803 | return ret; | 802 | return ret; |
@@ -1268,31 +1267,33 @@ static int qlcnic_83xx_copy_bootloader(struct qlcnic_adapter *adapter) | |||
1268 | 1267 | ||
1269 | static int qlcnic_83xx_copy_fw_file(struct qlcnic_adapter *adapter) | 1268 | static int qlcnic_83xx_copy_fw_file(struct qlcnic_adapter *adapter) |
1270 | { | 1269 | { |
1270 | struct qlc_83xx_fw_info *fw_info = adapter->ahw->fw_info; | ||
1271 | const struct firmware *fw = fw_info->fw; | ||
1271 | u32 dest, *p_cache; | 1272 | u32 dest, *p_cache; |
1272 | u64 addr; | 1273 | int i, ret = -EIO; |
1273 | u8 data[16]; | 1274 | u8 data[16]; |
1274 | size_t size; | 1275 | size_t size; |
1275 | int i, ret = -EIO; | 1276 | u64 addr; |
1276 | 1277 | ||
1277 | dest = QLCRDX(adapter->ahw, QLCNIC_FW_IMAGE_ADDR); | 1278 | dest = QLCRDX(adapter->ahw, QLCNIC_FW_IMAGE_ADDR); |
1278 | size = (adapter->ahw->fw_info.fw->size & ~0xF); | 1279 | size = (fw->size & ~0xF); |
1279 | p_cache = (u32 *)adapter->ahw->fw_info.fw->data; | 1280 | p_cache = (u32 *)fw->data; |
1280 | addr = (u64)dest; | 1281 | addr = (u64)dest; |
1281 | 1282 | ||
1282 | ret = qlcnic_83xx_ms_mem_write128(adapter, addr, | 1283 | ret = qlcnic_83xx_ms_mem_write128(adapter, addr, |
1283 | (u32 *)p_cache, size / 16); | 1284 | (u32 *)p_cache, size / 16); |
1284 | if (ret) { | 1285 | if (ret) { |
1285 | dev_err(&adapter->pdev->dev, "MS memory write failed\n"); | 1286 | dev_err(&adapter->pdev->dev, "MS memory write failed\n"); |
1286 | release_firmware(adapter->ahw->fw_info.fw); | 1287 | release_firmware(fw); |
1287 | adapter->ahw->fw_info.fw = NULL; | 1288 | fw_info->fw = NULL; |
1288 | return -EIO; | 1289 | return -EIO; |
1289 | } | 1290 | } |
1290 | 1291 | ||
1291 | /* alignment check */ | 1292 | /* alignment check */ |
1292 | if (adapter->ahw->fw_info.fw->size & 0xF) { | 1293 | if (fw->size & 0xF) { |
1293 | addr = dest + size; | 1294 | addr = dest + size; |
1294 | for (i = 0; i < (adapter->ahw->fw_info.fw->size & 0xF); i++) | 1295 | for (i = 0; i < (fw->size & 0xF); i++) |
1295 | data[i] = adapter->ahw->fw_info.fw->data[size + i]; | 1296 | data[i] = fw->data[size + i]; |
1296 | for (; i < 16; i++) | 1297 | for (; i < 16; i++) |
1297 | data[i] = 0; | 1298 | data[i] = 0; |
1298 | ret = qlcnic_83xx_ms_mem_write128(adapter, addr, | 1299 | ret = qlcnic_83xx_ms_mem_write128(adapter, addr, |
@@ -1300,13 +1301,13 @@ static int qlcnic_83xx_copy_fw_file(struct qlcnic_adapter *adapter) | |||
1300 | if (ret) { | 1301 | if (ret) { |
1301 | dev_err(&adapter->pdev->dev, | 1302 | dev_err(&adapter->pdev->dev, |
1302 | "MS memory write failed\n"); | 1303 | "MS memory write failed\n"); |
1303 | release_firmware(adapter->ahw->fw_info.fw); | 1304 | release_firmware(fw); |
1304 | adapter->ahw->fw_info.fw = NULL; | 1305 | fw_info->fw = NULL; |
1305 | return -EIO; | 1306 | return -EIO; |
1306 | } | 1307 | } |
1307 | } | 1308 | } |
1308 | release_firmware(adapter->ahw->fw_info.fw); | 1309 | release_firmware(fw); |
1309 | adapter->ahw->fw_info.fw = NULL; | 1310 | fw_info->fw = NULL; |
1310 | 1311 | ||
1311 | return 0; | 1312 | return 0; |
1312 | } | 1313 | } |
@@ -1950,35 +1951,12 @@ static void qlcnic_83xx_init_hw(struct qlcnic_adapter *p_dev) | |||
1950 | dev_err(&p_dev->pdev->dev, "%s: failed\n", __func__); | 1951 | dev_err(&p_dev->pdev->dev, "%s: failed\n", __func__); |
1951 | } | 1952 | } |
1952 | 1953 | ||
1953 | static inline void qlcnic_83xx_get_fw_file_name(struct qlcnic_adapter *adapter, | ||
1954 | char *file_name) | ||
1955 | { | ||
1956 | struct pci_dev *pdev = adapter->pdev; | ||
1957 | |||
1958 | memset(file_name, 0, QLC_FW_FILE_NAME_LEN); | ||
1959 | |||
1960 | switch (pdev->device) { | ||
1961 | case PCI_DEVICE_ID_QLOGIC_QLE834X: | ||
1962 | strncpy(file_name, QLC_83XX_FW_FILE_NAME, | ||
1963 | QLC_FW_FILE_NAME_LEN); | ||
1964 | break; | ||
1965 | case PCI_DEVICE_ID_QLOGIC_QLE844X: | ||
1966 | strncpy(file_name, QLC_84XX_FW_FILE_NAME, | ||
1967 | QLC_FW_FILE_NAME_LEN); | ||
1968 | break; | ||
1969 | default: | ||
1970 | dev_err(&pdev->dev, "%s: Invalid device id\n", | ||
1971 | __func__); | ||
1972 | } | ||
1973 | } | ||
1974 | |||
1975 | static int qlcnic_83xx_load_fw_image_from_host(struct qlcnic_adapter *adapter) | 1954 | static int qlcnic_83xx_load_fw_image_from_host(struct qlcnic_adapter *adapter) |
1976 | { | 1955 | { |
1977 | char fw_file_name[QLC_FW_FILE_NAME_LEN]; | 1956 | struct qlc_83xx_fw_info *fw_info = adapter->ahw->fw_info; |
1978 | int err = -EIO; | 1957 | int err = -EIO; |
1979 | 1958 | ||
1980 | qlcnic_83xx_get_fw_file_name(adapter, fw_file_name); | 1959 | if (request_firmware(&fw_info->fw, fw_info->fw_file_name, |
1981 | if (request_firmware(&adapter->ahw->fw_info.fw, fw_file_name, | ||
1982 | &(adapter->pdev->dev))) { | 1960 | &(adapter->pdev->dev))) { |
1983 | dev_err(&adapter->pdev->dev, | 1961 | dev_err(&adapter->pdev->dev, |
1984 | "No file FW image, loading flash FW image.\n"); | 1962 | "No file FW image, loading flash FW image.\n"); |
@@ -2025,36 +2003,6 @@ static int qlcnic_83xx_restart_hw(struct qlcnic_adapter *adapter) | |||
2025 | return 0; | 2003 | return 0; |
2026 | } | 2004 | } |
2027 | 2005 | ||
2028 | /** | ||
2029 | * qlcnic_83xx_config_default_opmode | ||
2030 | * | ||
2031 | * @adapter: adapter structure | ||
2032 | * | ||
2033 | * Configure default driver operating mode | ||
2034 | * | ||
2035 | * Returns: Error code or Success(0) | ||
2036 | * */ | ||
2037 | int qlcnic_83xx_config_default_opmode(struct qlcnic_adapter *adapter) | ||
2038 | { | ||
2039 | u32 op_mode; | ||
2040 | struct qlcnic_hardware_context *ahw = adapter->ahw; | ||
2041 | |||
2042 | qlcnic_get_func_no(adapter); | ||
2043 | op_mode = QLCRDX(ahw, QLC_83XX_DRV_OP_MODE); | ||
2044 | |||
2045 | if (test_bit(__QLCNIC_SRIOV_CAPABLE, &adapter->state)) | ||
2046 | op_mode = QLC_83XX_DEFAULT_OPMODE; | ||
2047 | |||
2048 | if (op_mode == QLC_83XX_DEFAULT_OPMODE) { | ||
2049 | adapter->nic_ops->init_driver = qlcnic_83xx_init_default_driver; | ||
2050 | ahw->idc.state_entry = qlcnic_83xx_idc_ready_state_entry; | ||
2051 | } else { | ||
2052 | return -EIO; | ||
2053 | } | ||
2054 | |||
2055 | return 0; | ||
2056 | } | ||
2057 | |||
2058 | int qlcnic_83xx_get_nic_configuration(struct qlcnic_adapter *adapter) | 2006 | int qlcnic_83xx_get_nic_configuration(struct qlcnic_adapter *adapter) |
2059 | { | 2007 | { |
2060 | int err; | 2008 | int err; |
@@ -2074,26 +2022,26 @@ int qlcnic_83xx_get_nic_configuration(struct qlcnic_adapter *adapter) | |||
2074 | ahw->max_mac_filters = nic_info.max_mac_filters; | 2022 | ahw->max_mac_filters = nic_info.max_mac_filters; |
2075 | ahw->max_mtu = nic_info.max_mtu; | 2023 | ahw->max_mtu = nic_info.max_mtu; |
2076 | 2024 | ||
2077 | /* VNIC mode is detected by BIT_23 in capabilities. This bit is also | 2025 | /* eSwitch capability indicates vNIC mode. |
2078 | * set in case device is SRIOV capable. VNIC and SRIOV are mutually | 2026 | * vNIC and SRIOV are mutually exclusive operational modes. |
2079 | * exclusive. So in case of sriov capable device load driver in | 2027 | * If SR-IOV capability is detected, SR-IOV physical function |
2080 | * default mode | 2028 | * will get initialized in default mode. |
2029 | * SR-IOV virtual function initialization follows a | ||
2030 | * different code path and opmode. | ||
2031 | * SRIOV mode has precedence over vNIC mode. | ||
2081 | */ | 2032 | */ |
2082 | if (test_bit(__QLCNIC_SRIOV_CAPABLE, &adapter->state)) { | 2033 | if (test_bit(__QLCNIC_SRIOV_CAPABLE, &adapter->state)) |
2083 | ahw->nic_mode = QLC_83XX_DEFAULT_MODE; | 2034 | return QLC_83XX_DEFAULT_OPMODE; |
2084 | return ahw->nic_mode; | ||
2085 | } | ||
2086 | 2035 | ||
2087 | if (ahw->capabilities & BIT_23) | 2036 | if (ahw->capabilities & QLC_83XX_ESWITCH_CAPABILITY) |
2088 | ahw->nic_mode = QLC_83XX_VIRTUAL_NIC_MODE; | 2037 | return QLC_83XX_VIRTUAL_NIC_MODE; |
2089 | else | ||
2090 | ahw->nic_mode = QLC_83XX_DEFAULT_MODE; | ||
2091 | 2038 | ||
2092 | return ahw->nic_mode; | 2039 | return QLC_83XX_DEFAULT_OPMODE; |
2093 | } | 2040 | } |
2094 | 2041 | ||
2095 | int qlcnic_83xx_configure_opmode(struct qlcnic_adapter *adapter) | 2042 | int qlcnic_83xx_configure_opmode(struct qlcnic_adapter *adapter) |
2096 | { | 2043 | { |
2044 | struct qlcnic_hardware_context *ahw = adapter->ahw; | ||
2097 | int ret; | 2045 | int ret; |
2098 | 2046 | ||
2099 | ret = qlcnic_83xx_get_nic_configuration(adapter); | 2047 | ret = qlcnic_83xx_get_nic_configuration(adapter); |
@@ -2101,11 +2049,16 @@ int qlcnic_83xx_configure_opmode(struct qlcnic_adapter *adapter) | |||
2101 | return -EIO; | 2049 | return -EIO; |
2102 | 2050 | ||
2103 | if (ret == QLC_83XX_VIRTUAL_NIC_MODE) { | 2051 | if (ret == QLC_83XX_VIRTUAL_NIC_MODE) { |
2052 | ahw->nic_mode = QLC_83XX_VIRTUAL_NIC_MODE; | ||
2104 | if (qlcnic_83xx_config_vnic_opmode(adapter)) | 2053 | if (qlcnic_83xx_config_vnic_opmode(adapter)) |
2105 | return -EIO; | 2054 | return -EIO; |
2106 | } else if (ret == QLC_83XX_DEFAULT_MODE) { | 2055 | |
2107 | if (qlcnic_83xx_config_default_opmode(adapter)) | 2056 | } else if (ret == QLC_83XX_DEFAULT_OPMODE) { |
2108 | return -EIO; | 2057 | ahw->nic_mode = QLC_83XX_DEFAULT_MODE; |
2058 | adapter->nic_ops->init_driver = qlcnic_83xx_init_default_driver; | ||
2059 | ahw->idc.state_entry = qlcnic_83xx_idc_ready_state_entry; | ||
2060 | } else { | ||
2061 | return -EIO; | ||
2109 | } | 2062 | } |
2110 | 2063 | ||
2111 | return 0; | 2064 | return 0; |
@@ -2174,6 +2127,39 @@ static void qlcnic_83xx_clear_function_resources(struct qlcnic_adapter *adapter) | |||
2174 | } | 2127 | } |
2175 | } | 2128 | } |
2176 | 2129 | ||
2130 | static int qlcnic_83xx_get_fw_info(struct qlcnic_adapter *adapter) | ||
2131 | { | ||
2132 | struct qlcnic_hardware_context *ahw = adapter->ahw; | ||
2133 | struct pci_dev *pdev = adapter->pdev; | ||
2134 | struct qlc_83xx_fw_info *fw_info; | ||
2135 | int err = 0; | ||
2136 | |||
2137 | ahw->fw_info = kzalloc(sizeof(*fw_info), GFP_KERNEL); | ||
2138 | if (!ahw->fw_info) { | ||
2139 | err = -ENOMEM; | ||
2140 | } else { | ||
2141 | fw_info = ahw->fw_info; | ||
2142 | switch (pdev->device) { | ||
2143 | case PCI_DEVICE_ID_QLOGIC_QLE834X: | ||
2144 | strncpy(fw_info->fw_file_name, QLC_83XX_FW_FILE_NAME, | ||
2145 | QLC_FW_FILE_NAME_LEN); | ||
2146 | break; | ||
2147 | case PCI_DEVICE_ID_QLOGIC_QLE844X: | ||
2148 | strncpy(fw_info->fw_file_name, QLC_84XX_FW_FILE_NAME, | ||
2149 | QLC_FW_FILE_NAME_LEN); | ||
2150 | break; | ||
2151 | default: | ||
2152 | dev_err(&pdev->dev, "%s: Invalid device id\n", | ||
2153 | __func__); | ||
2154 | err = -EINVAL; | ||
2155 | break; | ||
2156 | } | ||
2157 | } | ||
2158 | |||
2159 | return err; | ||
2160 | } | ||
2161 | |||
2162 | |||
2177 | int qlcnic_83xx_init(struct qlcnic_adapter *adapter, int pci_using_dac) | 2163 | int qlcnic_83xx_init(struct qlcnic_adapter *adapter, int pci_using_dac) |
2178 | { | 2164 | { |
2179 | struct qlcnic_hardware_context *ahw = adapter->ahw; | 2165 | struct qlcnic_hardware_context *ahw = adapter->ahw; |
@@ -2199,10 +2185,14 @@ int qlcnic_83xx_init(struct qlcnic_adapter *adapter, int pci_using_dac) | |||
2199 | if (!qlcnic_83xx_read_flash_descriptor_table(adapter)) | 2185 | if (!qlcnic_83xx_read_flash_descriptor_table(adapter)) |
2200 | qlcnic_83xx_read_flash_mfg_id(adapter); | 2186 | qlcnic_83xx_read_flash_mfg_id(adapter); |
2201 | 2187 | ||
2202 | err = qlcnic_83xx_idc_init(adapter); | 2188 | err = qlcnic_83xx_get_fw_info(adapter); |
2203 | if (err) | 2189 | if (err) |
2204 | goto detach_mbx; | 2190 | goto detach_mbx; |
2205 | 2191 | ||
2192 | err = qlcnic_83xx_idc_init(adapter); | ||
2193 | if (err) | ||
2194 | goto clear_fw_info; | ||
2195 | |||
2206 | err = qlcnic_setup_intr(adapter, 0, 0); | 2196 | err = qlcnic_setup_intr(adapter, 0, 0); |
2207 | if (err) { | 2197 | if (err) { |
2208 | dev_err(&adapter->pdev->dev, "Failed to setup interrupt\n"); | 2198 | dev_err(&adapter->pdev->dev, "Failed to setup interrupt\n"); |
@@ -2243,9 +2233,67 @@ disable_mbx_intr: | |||
2243 | disable_intr: | 2233 | disable_intr: |
2244 | qlcnic_teardown_intr(adapter); | 2234 | qlcnic_teardown_intr(adapter); |
2245 | 2235 | ||
2236 | clear_fw_info: | ||
2237 | kfree(ahw->fw_info); | ||
2238 | |||
2246 | detach_mbx: | 2239 | detach_mbx: |
2247 | qlcnic_83xx_detach_mailbox_work(adapter); | 2240 | qlcnic_83xx_detach_mailbox_work(adapter); |
2248 | qlcnic_83xx_free_mailbox(ahw->mailbox); | 2241 | qlcnic_83xx_free_mailbox(ahw->mailbox); |
2249 | exit: | 2242 | exit: |
2250 | return err; | 2243 | return err; |
2251 | } | 2244 | } |
2245 | |||
2246 | void qlcnic_83xx_aer_stop_poll_work(struct qlcnic_adapter *adapter) | ||
2247 | { | ||
2248 | struct qlcnic_hardware_context *ahw = adapter->ahw; | ||
2249 | struct qlc_83xx_idc *idc = &ahw->idc; | ||
2250 | |||
2251 | clear_bit(QLC_83XX_MBX_READY, &idc->status); | ||
2252 | cancel_delayed_work_sync(&adapter->fw_work); | ||
2253 | |||
2254 | if (ahw->nic_mode == QLC_83XX_VIRTUAL_NIC_MODE) | ||
2255 | qlcnic_83xx_disable_vnic_mode(adapter, 1); | ||
2256 | |||
2257 | qlcnic_83xx_idc_detach_driver(adapter); | ||
2258 | qlcnic_83xx_register_nic_idc_func(adapter, 0); | ||
2259 | |||
2260 | cancel_delayed_work_sync(&adapter->idc_aen_work); | ||
2261 | } | ||
2262 | |||
2263 | int qlcnic_83xx_aer_reset(struct qlcnic_adapter *adapter) | ||
2264 | { | ||
2265 | struct qlcnic_hardware_context *ahw = adapter->ahw; | ||
2266 | struct qlc_83xx_idc *idc = &ahw->idc; | ||
2267 | int ret = 0; | ||
2268 | u32 owner; | ||
2269 | |||
2270 | /* Mark the previous IDC state as NEED_RESET so | ||
2271 | * that state_entry() will perform the reattachment | ||
2272 | * and bringup the device | ||
2273 | */ | ||
2274 | idc->prev_state = QLC_83XX_IDC_DEV_NEED_RESET; | ||
2275 | owner = qlcnic_83xx_idc_find_reset_owner_id(adapter); | ||
2276 | if (ahw->pci_func == owner) { | ||
2277 | ret = qlcnic_83xx_restart_hw(adapter); | ||
2278 | if (ret < 0) | ||
2279 | return ret; | ||
2280 | qlcnic_83xx_idc_clear_registers(adapter, 0); | ||
2281 | } | ||
2282 | |||
2283 | ret = idc->state_entry(adapter); | ||
2284 | return ret; | ||
2285 | } | ||
2286 | |||
2287 | void qlcnic_83xx_aer_start_poll_work(struct qlcnic_adapter *adapter) | ||
2288 | { | ||
2289 | struct qlcnic_hardware_context *ahw = adapter->ahw; | ||
2290 | struct qlc_83xx_idc *idc = &ahw->idc; | ||
2291 | u32 owner; | ||
2292 | |||
2293 | idc->prev_state = QLC_83XX_IDC_DEV_READY; | ||
2294 | owner = qlcnic_83xx_idc_find_reset_owner_id(adapter); | ||
2295 | if (ahw->pci_func == owner) | ||
2296 | qlcnic_83xx_idc_enter_ready_state(adapter, 0); | ||
2297 | |||
2298 | qlcnic_schedule_work(adapter, qlcnic_83xx_idc_poll_dev_state, 0); | ||
2299 | } | ||
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) | |||
208 | return -EIO; | 208 | return -EIO; |
209 | } | 209 | } |
210 | 210 | ||
211 | if (ahw->capabilities & BIT_23) | 211 | if (ahw->capabilities & QLC_83XX_ESWITCH_CAPABILITY) |
212 | adapter->flags |= QLCNIC_ESWITCH_ENABLED; | 212 | adapter->flags |= QLCNIC_ESWITCH_ENABLED; |
213 | else | 213 | else |
214 | adapter->flags &= ~QLCNIC_ESWITCH_ENABLED; | 214 | adapter->flags &= ~QLCNIC_ESWITCH_ENABLED; |
@@ -239,3 +239,41 @@ int qlcnic_83xx_check_vnic_state(struct qlcnic_adapter *adapter) | |||
239 | 239 | ||
240 | return 0; | 240 | return 0; |
241 | } | 241 | } |
242 | |||
243 | static int qlcnic_83xx_get_eswitch_port_info(struct qlcnic_adapter *adapter, | ||
244 | int func, int *port_id) | ||
245 | { | ||
246 | struct qlcnic_info nic_info; | ||
247 | int err = 0; | ||
248 | |||
249 | memset(&nic_info, 0, sizeof(struct qlcnic_info)); | ||
250 | |||
251 | err = qlcnic_get_nic_info(adapter, &nic_info, func); | ||
252 | if (err) | ||
253 | return err; | ||
254 | |||
255 | if (nic_info.capabilities & QLC_83XX_ESWITCH_CAPABILITY) | ||
256 | *port_id = nic_info.phys_port; | ||
257 | else | ||
258 | err = -EIO; | ||
259 | |||
260 | return err; | ||
261 | } | ||
262 | |||
263 | int qlcnic_83xx_enable_port_eswitch(struct qlcnic_adapter *adapter, int func) | ||
264 | { | ||
265 | int id, err = 0; | ||
266 | |||
267 | err = qlcnic_83xx_get_eswitch_port_info(adapter, func, &id); | ||
268 | if (err) | ||
269 | return err; | ||
270 | |||
271 | if (!(adapter->eswitch[id].flags & QLCNIC_SWITCH_ENABLE)) { | ||
272 | if (!qlcnic_enable_eswitch(adapter, id, 1)) | ||
273 | adapter->eswitch[id].flags |= QLCNIC_SWITCH_ENABLE; | ||
274 | else | ||
275 | err = -EIO; | ||
276 | } | ||
277 | |||
278 | return err; | ||
279 | } | ||
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) | |||
1509 | adapter->ahw->msg_enable = msglvl; | 1509 | adapter->ahw->msg_enable = msglvl; |
1510 | } | 1510 | } |
1511 | 1511 | ||
1512 | int qlcnic_enable_fw_dump_state(struct qlcnic_adapter *adapter) | ||
1513 | { | ||
1514 | struct qlcnic_fw_dump *fw_dump = &adapter->ahw->fw_dump; | ||
1515 | u32 val; | ||
1516 | |||
1517 | if (qlcnic_84xx_check(adapter)) { | ||
1518 | if (qlcnic_83xx_lock_driver(adapter)) | ||
1519 | return -EBUSY; | ||
1520 | |||
1521 | val = QLCRDX(adapter->ahw, QLC_83XX_IDC_CTRL); | ||
1522 | val &= ~QLC_83XX_IDC_DISABLE_FW_DUMP; | ||
1523 | QLCWRX(adapter->ahw, QLC_83XX_IDC_CTRL, val); | ||
1524 | |||
1525 | qlcnic_83xx_unlock_driver(adapter); | ||
1526 | } else { | ||
1527 | fw_dump->enable = true; | ||
1528 | } | ||
1529 | |||
1530 | dev_info(&adapter->pdev->dev, "FW dump enabled\n"); | ||
1531 | |||
1532 | return 0; | ||
1533 | } | ||
1534 | |||
1535 | static int qlcnic_disable_fw_dump_state(struct qlcnic_adapter *adapter) | ||
1536 | { | ||
1537 | struct qlcnic_fw_dump *fw_dump = &adapter->ahw->fw_dump; | ||
1538 | u32 val; | ||
1539 | |||
1540 | if (qlcnic_84xx_check(adapter)) { | ||
1541 | if (qlcnic_83xx_lock_driver(adapter)) | ||
1542 | return -EBUSY; | ||
1543 | |||
1544 | val = QLCRDX(adapter->ahw, QLC_83XX_IDC_CTRL); | ||
1545 | val |= QLC_83XX_IDC_DISABLE_FW_DUMP; | ||
1546 | QLCWRX(adapter->ahw, QLC_83XX_IDC_CTRL, val); | ||
1547 | |||
1548 | qlcnic_83xx_unlock_driver(adapter); | ||
1549 | } else { | ||
1550 | fw_dump->enable = false; | ||
1551 | } | ||
1552 | |||
1553 | dev_info(&adapter->pdev->dev, "FW dump disabled\n"); | ||
1554 | |||
1555 | return 0; | ||
1556 | } | ||
1557 | |||
1558 | bool qlcnic_check_fw_dump_state(struct qlcnic_adapter *adapter) | ||
1559 | { | ||
1560 | struct qlcnic_fw_dump *fw_dump = &adapter->ahw->fw_dump; | ||
1561 | bool state; | ||
1562 | u32 val; | ||
1563 | |||
1564 | if (qlcnic_84xx_check(adapter)) { | ||
1565 | val = QLCRDX(adapter->ahw, QLC_83XX_IDC_CTRL); | ||
1566 | state = (val & QLC_83XX_IDC_DISABLE_FW_DUMP) ? false : true; | ||
1567 | } else { | ||
1568 | state = fw_dump->enable; | ||
1569 | } | ||
1570 | |||
1571 | return state; | ||
1572 | } | ||
1573 | |||
1512 | static int | 1574 | static int |
1513 | qlcnic_get_dump_flag(struct net_device *netdev, struct ethtool_dump *dump) | 1575 | qlcnic_get_dump_flag(struct net_device *netdev, struct ethtool_dump *dump) |
1514 | { | 1576 | { |
@@ -1525,7 +1587,7 @@ qlcnic_get_dump_flag(struct net_device *netdev, struct ethtool_dump *dump) | |||
1525 | else | 1587 | else |
1526 | dump->len = 0; | 1588 | dump->len = 0; |
1527 | 1589 | ||
1528 | if (!fw_dump->enable) | 1590 | if (!qlcnic_check_fw_dump_state(adapter)) |
1529 | dump->flag = ETH_FW_DUMP_DISABLE; | 1591 | dump->flag = ETH_FW_DUMP_DISABLE; |
1530 | else | 1592 | else |
1531 | dump->flag = fw_dump->tmpl_hdr->drv_cap_mask; | 1593 | 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 | return 0; | 1635 | return 0; |
1574 | } | 1636 | } |
1575 | 1637 | ||
1638 | static int qlcnic_set_dump_mask(struct qlcnic_adapter *adapter, u32 mask) | ||
1639 | { | ||
1640 | struct qlcnic_fw_dump *fw_dump = &adapter->ahw->fw_dump; | ||
1641 | struct net_device *netdev = adapter->netdev; | ||
1642 | |||
1643 | if (!qlcnic_check_fw_dump_state(adapter)) { | ||
1644 | netdev_info(netdev, | ||
1645 | "Can not change driver mask to 0x%x. FW dump not enabled\n", | ||
1646 | mask); | ||
1647 | return -EOPNOTSUPP; | ||
1648 | } | ||
1649 | |||
1650 | fw_dump->tmpl_hdr->drv_cap_mask = mask; | ||
1651 | netdev_info(netdev, "Driver mask changed to: 0x%x\n", mask); | ||
1652 | return 0; | ||
1653 | } | ||
1654 | |||
1576 | static int | 1655 | static int |
1577 | qlcnic_set_dump(struct net_device *netdev, struct ethtool_dump *val) | 1656 | qlcnic_set_dump(struct net_device *netdev, struct ethtool_dump *val) |
1578 | { | 1657 | { |
1579 | int i; | ||
1580 | struct qlcnic_adapter *adapter = netdev_priv(netdev); | 1658 | struct qlcnic_adapter *adapter = netdev_priv(netdev); |
1581 | struct qlcnic_fw_dump *fw_dump = &adapter->ahw->fw_dump; | 1659 | struct qlcnic_fw_dump *fw_dump = &adapter->ahw->fw_dump; |
1660 | bool valid_mask = false; | ||
1661 | int i, ret = 0; | ||
1582 | u32 state; | 1662 | u32 state; |
1583 | 1663 | ||
1584 | switch (val->flag) { | 1664 | switch (val->flag) { |
1585 | case QLCNIC_FORCE_FW_DUMP_KEY: | 1665 | case QLCNIC_FORCE_FW_DUMP_KEY: |
1586 | if (!fw_dump->tmpl_hdr) { | 1666 | if (!fw_dump->tmpl_hdr) { |
1587 | netdev_err(netdev, "FW dump not supported\n"); | 1667 | netdev_err(netdev, "FW dump not supported\n"); |
1588 | return -ENOTSUPP; | 1668 | ret = -EOPNOTSUPP; |
1669 | break; | ||
1589 | } | 1670 | } |
1590 | if (!fw_dump->enable) { | 1671 | |
1672 | if (!qlcnic_check_fw_dump_state(adapter)) { | ||
1591 | netdev_info(netdev, "FW dump not enabled\n"); | 1673 | netdev_info(netdev, "FW dump not enabled\n"); |
1592 | return 0; | 1674 | ret = -EOPNOTSUPP; |
1675 | break; | ||
1593 | } | 1676 | } |
1677 | |||
1594 | if (fw_dump->clr) { | 1678 | if (fw_dump->clr) { |
1595 | netdev_info(netdev, | 1679 | netdev_info(netdev, |
1596 | "Previous dump not cleared, not forcing dump\n"); | 1680 | "Previous dump not cleared, not forcing dump\n"); |
1597 | return 0; | 1681 | break; |
1598 | } | 1682 | } |
1683 | |||
1599 | netdev_info(netdev, "Forcing a FW dump\n"); | 1684 | netdev_info(netdev, "Forcing a FW dump\n"); |
1600 | qlcnic_dev_request_reset(adapter, val->flag); | 1685 | qlcnic_dev_request_reset(adapter, val->flag); |
1601 | break; | 1686 | break; |
1602 | case QLCNIC_DISABLE_FW_DUMP: | 1687 | case QLCNIC_DISABLE_FW_DUMP: |
1603 | if (fw_dump->enable && fw_dump->tmpl_hdr) { | 1688 | if (!fw_dump->tmpl_hdr) { |
1604 | netdev_info(netdev, "Disabling FW dump\n"); | 1689 | netdev_err(netdev, "FW dump not supported\n"); |
1605 | fw_dump->enable = 0; | 1690 | ret = -EOPNOTSUPP; |
1691 | break; | ||
1606 | } | 1692 | } |
1607 | return 0; | 1693 | |
1694 | ret = qlcnic_disable_fw_dump_state(adapter); | ||
1695 | break; | ||
1696 | |||
1608 | case QLCNIC_ENABLE_FW_DUMP: | 1697 | case QLCNIC_ENABLE_FW_DUMP: |
1609 | if (!fw_dump->tmpl_hdr) { | 1698 | if (!fw_dump->tmpl_hdr) { |
1610 | netdev_err(netdev, "FW dump not supported\n"); | 1699 | netdev_err(netdev, "FW dump not supported\n"); |
1611 | return -ENOTSUPP; | 1700 | ret = -EOPNOTSUPP; |
1612 | } | 1701 | break; |
1613 | if (!fw_dump->enable) { | ||
1614 | netdev_info(netdev, "Enabling FW dump\n"); | ||
1615 | fw_dump->enable = 1; | ||
1616 | } | 1702 | } |
1617 | return 0; | 1703 | |
1704 | ret = qlcnic_enable_fw_dump_state(adapter); | ||
1705 | break; | ||
1706 | |||
1618 | case QLCNIC_FORCE_FW_RESET: | 1707 | case QLCNIC_FORCE_FW_RESET: |
1619 | netdev_info(netdev, "Forcing a FW reset\n"); | 1708 | netdev_info(netdev, "Forcing a FW reset\n"); |
1620 | qlcnic_dev_request_reset(adapter, val->flag); | 1709 | qlcnic_dev_request_reset(adapter, val->flag); |
1621 | adapter->flags &= ~QLCNIC_FW_RESET_OWNER; | 1710 | adapter->flags &= ~QLCNIC_FW_RESET_OWNER; |
1622 | return 0; | 1711 | break; |
1712 | ; | ||
1623 | case QLCNIC_SET_QUIESCENT: | 1713 | case QLCNIC_SET_QUIESCENT: |
1624 | case QLCNIC_RESET_QUIESCENT: | 1714 | case QLCNIC_RESET_QUIESCENT: |
1625 | state = QLC_SHARED_REG_RD32(adapter, QLCNIC_CRB_DEV_STATE); | 1715 | state = QLC_SHARED_REG_RD32(adapter, QLCNIC_CRB_DEV_STATE); |
1626 | if (state == QLCNIC_DEV_FAILED || (state == QLCNIC_DEV_BADBAD)) | 1716 | if (state == QLCNIC_DEV_FAILED || (state == QLCNIC_DEV_BADBAD)) |
1627 | netdev_info(netdev, "Device in FAILED state\n"); | 1717 | netdev_info(netdev, "Device in FAILED state\n"); |
1628 | return 0; | 1718 | break; |
1719 | |||
1629 | default: | 1720 | default: |
1630 | if (!fw_dump->tmpl_hdr) { | 1721 | if (!fw_dump->tmpl_hdr) { |
1631 | netdev_err(netdev, "FW dump not supported\n"); | 1722 | netdev_err(netdev, "FW dump not supported\n"); |
1632 | return -ENOTSUPP; | 1723 | ret = -EOPNOTSUPP; |
1724 | break; | ||
1633 | } | 1725 | } |
1726 | |||
1634 | for (i = 0; i < ARRAY_SIZE(qlcnic_fw_dump_level); i++) { | 1727 | for (i = 0; i < ARRAY_SIZE(qlcnic_fw_dump_level); i++) { |
1635 | if (val->flag == qlcnic_fw_dump_level[i]) { | 1728 | if (val->flag == qlcnic_fw_dump_level[i]) { |
1636 | fw_dump->tmpl_hdr->drv_cap_mask = | 1729 | valid_mask = true; |
1637 | val->flag; | 1730 | break; |
1638 | netdev_info(netdev, "Driver mask changed to: 0x%x\n", | ||
1639 | fw_dump->tmpl_hdr->drv_cap_mask); | ||
1640 | return 0; | ||
1641 | } | 1731 | } |
1642 | } | 1732 | } |
1643 | netdev_info(netdev, "Invalid dump level: 0x%x\n", val->flag); | 1733 | |
1644 | return -EINVAL; | 1734 | if (valid_mask) { |
1735 | ret = qlcnic_set_dump_mask(adapter, val->flag); | ||
1736 | } else { | ||
1737 | netdev_info(netdev, "Invalid dump level: 0x%x\n", | ||
1738 | val->flag); | ||
1739 | ret = -EINVAL; | ||
1740 | } | ||
1645 | } | 1741 | } |
1646 | return 0; | 1742 | return ret; |
1647 | } | 1743 | } |
1648 | 1744 | ||
1649 | const struct ethtool_ops qlcnic_ethtool_ops = { | 1745 | 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 = { | |||
540 | .set_mac_filter_count = qlcnic_82xx_set_mac_filter_count, | 540 | .set_mac_filter_count = qlcnic_82xx_set_mac_filter_count, |
541 | .free_mac_list = qlcnic_82xx_free_mac_list, | 541 | .free_mac_list = qlcnic_82xx_free_mac_list, |
542 | .read_phys_port_id = qlcnic_82xx_read_phys_port_id, | 542 | .read_phys_port_id = qlcnic_82xx_read_phys_port_id, |
543 | .io_error_detected = qlcnic_82xx_io_error_detected, | ||
544 | .io_slot_reset = qlcnic_82xx_io_slot_reset, | ||
545 | .io_resume = qlcnic_82xx_io_resume, | ||
543 | }; | 546 | }; |
544 | 547 | ||
545 | static void qlcnic_get_multiq_capability(struct qlcnic_adapter *adapter) | 548 | 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 | return ret; | 796 | return ret; |
794 | } | 797 | } |
795 | 798 | ||
799 | static bool qlcnic_port_eswitch_cfg_capability(struct qlcnic_adapter *adapter) | ||
800 | { | ||
801 | bool ret = false; | ||
802 | |||
803 | if (qlcnic_84xx_check(adapter)) { | ||
804 | ret = true; | ||
805 | } else if (qlcnic_83xx_check(adapter)) { | ||
806 | if (adapter->ahw->extra_capability[0] & | ||
807 | QLCNIC_FW_CAPABILITY_2_PER_PORT_ESWITCH_CFG) | ||
808 | ret = true; | ||
809 | else | ||
810 | ret = false; | ||
811 | } | ||
812 | |||
813 | return ret; | ||
814 | } | ||
815 | |||
796 | int qlcnic_init_pci_info(struct qlcnic_adapter *adapter) | 816 | int qlcnic_init_pci_info(struct qlcnic_adapter *adapter) |
797 | { | 817 | { |
798 | struct qlcnic_pci_info *pci_info; | 818 | struct qlcnic_pci_info *pci_info; |
@@ -836,18 +856,30 @@ int qlcnic_init_pci_info(struct qlcnic_adapter *adapter) | |||
836 | (pci_info[i].type != QLCNIC_TYPE_NIC)) | 856 | (pci_info[i].type != QLCNIC_TYPE_NIC)) |
837 | continue; | 857 | continue; |
838 | 858 | ||
859 | if (qlcnic_port_eswitch_cfg_capability(adapter)) { | ||
860 | if (!qlcnic_83xx_enable_port_eswitch(adapter, pfn)) | ||
861 | adapter->npars[j].eswitch_status = true; | ||
862 | else | ||
863 | continue; | ||
864 | } else { | ||
865 | adapter->npars[j].eswitch_status = true; | ||
866 | } | ||
867 | |||
839 | adapter->npars[j].pci_func = pfn; | 868 | adapter->npars[j].pci_func = pfn; |
840 | adapter->npars[j].active = (u8)pci_info[i].active; | 869 | adapter->npars[j].active = (u8)pci_info[i].active; |
841 | adapter->npars[j].type = (u8)pci_info[i].type; | 870 | adapter->npars[j].type = (u8)pci_info[i].type; |
842 | adapter->npars[j].phy_port = (u8)pci_info[i].default_port; | 871 | adapter->npars[j].phy_port = (u8)pci_info[i].default_port; |
843 | adapter->npars[j].min_bw = pci_info[i].tx_min_bw; | 872 | adapter->npars[j].min_bw = pci_info[i].tx_min_bw; |
844 | adapter->npars[j].max_bw = pci_info[i].tx_max_bw; | 873 | adapter->npars[j].max_bw = pci_info[i].tx_max_bw; |
874 | |||
845 | j++; | 875 | j++; |
846 | } | 876 | } |
847 | 877 | ||
848 | for (i = 0; i < QLCNIC_NIU_MAX_XG_PORTS; i++) { | 878 | if (qlcnic_82xx_check(adapter)) { |
849 | adapter->eswitch[i].flags |= QLCNIC_SWITCH_ENABLE; | 879 | for (i = 0; i < QLCNIC_NIU_MAX_XG_PORTS; i++) |
850 | if (qlcnic_83xx_check(adapter)) | 880 | adapter->eswitch[i].flags |= QLCNIC_SWITCH_ENABLE; |
881 | } else if (!qlcnic_port_eswitch_cfg_capability(adapter)) { | ||
882 | for (i = 0; i < QLCNIC_NIU_MAX_XG_PORTS; i++) | ||
851 | qlcnic_enable_eswitch(adapter, i, 1); | 883 | qlcnic_enable_eswitch(adapter, i, 1); |
852 | } | 884 | } |
853 | 885 | ||
@@ -969,8 +1001,8 @@ static int qlcnic_setup_pci_map(struct pci_dev *pdev, | |||
969 | return 0; | 1001 | return 0; |
970 | } | 1002 | } |
971 | 1003 | ||
972 | static inline bool qlcnic_validate_subsystem_id(struct qlcnic_adapter *adapter, | 1004 | static bool qlcnic_validate_subsystem_id(struct qlcnic_adapter *adapter, |
973 | int index) | 1005 | int index) |
974 | { | 1006 | { |
975 | struct pci_dev *pdev = adapter->pdev; | 1007 | struct pci_dev *pdev = adapter->pdev; |
976 | unsigned short subsystem_vendor; | 1008 | unsigned short subsystem_vendor; |
@@ -1272,6 +1304,9 @@ int qlcnic_set_default_offload_settings(struct qlcnic_adapter *adapter) | |||
1272 | return 0; | 1304 | return 0; |
1273 | 1305 | ||
1274 | for (i = 0; i < adapter->ahw->act_pci_func; i++) { | 1306 | for (i = 0; i < adapter->ahw->act_pci_func; i++) { |
1307 | if (!adapter->npars[i].eswitch_status) | ||
1308 | continue; | ||
1309 | |||
1275 | memset(&esw_cfg, 0, sizeof(struct qlcnic_esw_func_cfg)); | 1310 | memset(&esw_cfg, 0, sizeof(struct qlcnic_esw_func_cfg)); |
1276 | esw_cfg.pci_func = adapter->npars[i].pci_func; | 1311 | esw_cfg.pci_func = adapter->npars[i].pci_func; |
1277 | esw_cfg.mac_override = BIT_0; | 1312 | esw_cfg.mac_override = BIT_0; |
@@ -1334,6 +1369,9 @@ int qlcnic_reset_npar_config(struct qlcnic_adapter *adapter) | |||
1334 | for (i = 0; i < adapter->ahw->act_pci_func; i++) { | 1369 | for (i = 0; i < adapter->ahw->act_pci_func; i++) { |
1335 | npar = &adapter->npars[i]; | 1370 | npar = &adapter->npars[i]; |
1336 | pci_func = npar->pci_func; | 1371 | pci_func = npar->pci_func; |
1372 | if (!adapter->npars[i].eswitch_status) | ||
1373 | continue; | ||
1374 | |||
1337 | memset(&nic_info, 0, sizeof(struct qlcnic_info)); | 1375 | memset(&nic_info, 0, sizeof(struct qlcnic_info)); |
1338 | err = qlcnic_get_nic_info(adapter, &nic_info, pci_func); | 1376 | err = qlcnic_get_nic_info(adapter, &nic_info, pci_func); |
1339 | if (err) | 1377 | if (err) |
@@ -2399,6 +2437,7 @@ static void qlcnic_remove(struct pci_dev *pdev) | |||
2399 | qlcnic_83xx_free_mbx_intr(adapter); | 2437 | qlcnic_83xx_free_mbx_intr(adapter); |
2400 | qlcnic_83xx_detach_mailbox_work(adapter); | 2438 | qlcnic_83xx_detach_mailbox_work(adapter); |
2401 | qlcnic_83xx_free_mailbox(ahw->mailbox); | 2439 | qlcnic_83xx_free_mailbox(ahw->mailbox); |
2440 | kfree(ahw->fw_info); | ||
2402 | } | 2441 | } |
2403 | 2442 | ||
2404 | qlcnic_detach(adapter); | 2443 | qlcnic_detach(adapter); |
@@ -3045,7 +3084,7 @@ skip_ack_check: | |||
3045 | qlcnic_api_unlock(adapter); | 3084 | qlcnic_api_unlock(adapter); |
3046 | 3085 | ||
3047 | rtnl_lock(); | 3086 | rtnl_lock(); |
3048 | if (adapter->ahw->fw_dump.enable && | 3087 | if (qlcnic_check_fw_dump_state(adapter) && |
3049 | (adapter->flags & QLCNIC_FW_RESET_OWNER)) { | 3088 | (adapter->flags & QLCNIC_FW_RESET_OWNER)) { |
3050 | QLCDB(adapter, DRV, "Take FW dump\n"); | 3089 | QLCDB(adapter, DRV, "Take FW dump\n"); |
3051 | qlcnic_dump_fw(adapter); | 3090 | qlcnic_dump_fw(adapter); |
@@ -3431,19 +3470,6 @@ static int qlcnic_attach_func(struct pci_dev *pdev) | |||
3431 | return err; | 3470 | return err; |
3432 | } | 3471 | } |
3433 | 3472 | ||
3434 | if (qlcnic_83xx_check(adapter)) { | ||
3435 | /* register for NIC IDC AEN Events */ | ||
3436 | qlcnic_83xx_register_nic_idc_func(adapter, 1); | ||
3437 | err = qlcnic_83xx_setup_mbx_intr(adapter); | ||
3438 | if (err) { | ||
3439 | dev_err(&adapter->pdev->dev, | ||
3440 | "failed to setup mbx interrupt\n"); | ||
3441 | qlcnic_clr_all_drv_state(adapter, 1); | ||
3442 | clear_bit(__QLCNIC_AER, &adapter->state); | ||
3443 | goto done; | ||
3444 | } | ||
3445 | } | ||
3446 | |||
3447 | if (netif_running(netdev)) { | 3473 | if (netif_running(netdev)) { |
3448 | err = qlcnic_attach(adapter); | 3474 | err = qlcnic_attach(adapter); |
3449 | if (err) { | 3475 | if (err) { |
@@ -3464,8 +3490,8 @@ static int qlcnic_attach_func(struct pci_dev *pdev) | |||
3464 | return err; | 3490 | return err; |
3465 | } | 3491 | } |
3466 | 3492 | ||
3467 | static pci_ers_result_t qlcnic_io_error_detected(struct pci_dev *pdev, | 3493 | pci_ers_result_t qlcnic_82xx_io_error_detected(struct pci_dev *pdev, |
3468 | pci_channel_state_t state) | 3494 | pci_channel_state_t state) |
3469 | { | 3495 | { |
3470 | struct qlcnic_adapter *adapter = pci_get_drvdata(pdev); | 3496 | struct qlcnic_adapter *adapter = pci_get_drvdata(pdev); |
3471 | struct net_device *netdev = adapter->netdev; | 3497 | struct net_device *netdev = adapter->netdev; |
@@ -3484,12 +3510,6 @@ static pci_ers_result_t qlcnic_io_error_detected(struct pci_dev *pdev, | |||
3484 | if (netif_running(netdev)) | 3510 | if (netif_running(netdev)) |
3485 | qlcnic_down(adapter, netdev); | 3511 | qlcnic_down(adapter, netdev); |
3486 | 3512 | ||
3487 | if (qlcnic_83xx_check(adapter)) { | ||
3488 | qlcnic_83xx_free_mbx_intr(adapter); | ||
3489 | qlcnic_83xx_register_nic_idc_func(adapter, 0); | ||
3490 | cancel_delayed_work_sync(&adapter->idc_aen_work); | ||
3491 | } | ||
3492 | |||
3493 | qlcnic_detach(adapter); | 3513 | qlcnic_detach(adapter); |
3494 | qlcnic_teardown_intr(adapter); | 3514 | qlcnic_teardown_intr(adapter); |
3495 | 3515 | ||
@@ -3501,13 +3521,13 @@ static pci_ers_result_t qlcnic_io_error_detected(struct pci_dev *pdev, | |||
3501 | return PCI_ERS_RESULT_NEED_RESET; | 3521 | return PCI_ERS_RESULT_NEED_RESET; |
3502 | } | 3522 | } |
3503 | 3523 | ||
3504 | static pci_ers_result_t qlcnic_io_slot_reset(struct pci_dev *pdev) | 3524 | pci_ers_result_t qlcnic_82xx_io_slot_reset(struct pci_dev *pdev) |
3505 | { | 3525 | { |
3506 | return qlcnic_attach_func(pdev) ? PCI_ERS_RESULT_DISCONNECT : | 3526 | return qlcnic_attach_func(pdev) ? PCI_ERS_RESULT_DISCONNECT : |
3507 | PCI_ERS_RESULT_RECOVERED; | 3527 | PCI_ERS_RESULT_RECOVERED; |
3508 | } | 3528 | } |
3509 | 3529 | ||
3510 | static void qlcnic_io_resume(struct pci_dev *pdev) | 3530 | void qlcnic_82xx_io_resume(struct pci_dev *pdev) |
3511 | { | 3531 | { |
3512 | u32 state; | 3532 | u32 state; |
3513 | struct qlcnic_adapter *adapter = pci_get_drvdata(pdev); | 3533 | struct qlcnic_adapter *adapter = pci_get_drvdata(pdev); |
@@ -3517,9 +3537,48 @@ static void qlcnic_io_resume(struct pci_dev *pdev) | |||
3517 | if (state == QLCNIC_DEV_READY && test_and_clear_bit(__QLCNIC_AER, | 3537 | if (state == QLCNIC_DEV_READY && test_and_clear_bit(__QLCNIC_AER, |
3518 | &adapter->state)) | 3538 | &adapter->state)) |
3519 | qlcnic_schedule_work(adapter, qlcnic_fw_poll_work, | 3539 | qlcnic_schedule_work(adapter, qlcnic_fw_poll_work, |
3520 | FW_POLL_DELAY); | 3540 | FW_POLL_DELAY); |
3541 | } | ||
3542 | |||
3543 | static pci_ers_result_t qlcnic_io_error_detected(struct pci_dev *pdev, | ||
3544 | pci_channel_state_t state) | ||
3545 | { | ||
3546 | struct qlcnic_adapter *adapter = pci_get_drvdata(pdev); | ||
3547 | struct qlcnic_hardware_ops *hw_ops = adapter->ahw->hw_ops; | ||
3548 | |||
3549 | if (hw_ops->io_error_detected) { | ||
3550 | return hw_ops->io_error_detected(pdev, state); | ||
3551 | } else { | ||
3552 | dev_err(&pdev->dev, "AER error_detected handler not registered.\n"); | ||
3553 | return PCI_ERS_RESULT_DISCONNECT; | ||
3554 | } | ||
3521 | } | 3555 | } |
3522 | 3556 | ||
3557 | static pci_ers_result_t qlcnic_io_slot_reset(struct pci_dev *pdev) | ||
3558 | { | ||
3559 | struct qlcnic_adapter *adapter = pci_get_drvdata(pdev); | ||
3560 | struct qlcnic_hardware_ops *hw_ops = adapter->ahw->hw_ops; | ||
3561 | |||
3562 | if (hw_ops->io_slot_reset) { | ||
3563 | return hw_ops->io_slot_reset(pdev); | ||
3564 | } else { | ||
3565 | dev_err(&pdev->dev, "AER slot_reset handler not registered.\n"); | ||
3566 | return PCI_ERS_RESULT_DISCONNECT; | ||
3567 | } | ||
3568 | } | ||
3569 | |||
3570 | static void qlcnic_io_resume(struct pci_dev *pdev) | ||
3571 | { | ||
3572 | struct qlcnic_adapter *adapter = pci_get_drvdata(pdev); | ||
3573 | struct qlcnic_hardware_ops *hw_ops = adapter->ahw->hw_ops; | ||
3574 | |||
3575 | if (hw_ops->io_resume) | ||
3576 | hw_ops->io_resume(pdev); | ||
3577 | else | ||
3578 | dev_err(&pdev->dev, "AER resume handler not registered.\n"); | ||
3579 | } | ||
3580 | |||
3581 | |||
3523 | static int | 3582 | static int |
3524 | qlcnicvf_start_firmware(struct qlcnic_adapter *adapter) | 3583 | qlcnicvf_start_firmware(struct qlcnic_adapter *adapter) |
3525 | { | 3584 | { |
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 @@ flash_temp: | |||
1082 | } | 1082 | } |
1083 | 1083 | ||
1084 | tmpl_hdr = ahw->fw_dump.tmpl_hdr; | 1084 | tmpl_hdr = ahw->fw_dump.tmpl_hdr; |
1085 | tmpl_hdr->drv_cap_mask = QLCNIC_DUMP_MASK_DEF; | 1085 | tmpl_hdr->drv_cap_mask = tmpl_hdr->cap_mask; |
1086 | dev_info(&adapter->pdev->dev, | ||
1087 | "Default minidump capture mask 0x%x\n", | ||
1088 | tmpl_hdr->cap_mask); | ||
1086 | 1089 | ||
1087 | if ((tmpl_hdr->version & 0xfffff) >= 0x20001) | 1090 | if ((tmpl_hdr->version & 0xfffff) >= 0x20001) |
1088 | ahw->fw_dump.use_pex_dma = true; | 1091 | ahw->fw_dump.use_pex_dma = true; |
1089 | else | 1092 | else |
1090 | ahw->fw_dump.use_pex_dma = false; | 1093 | ahw->fw_dump.use_pex_dma = false; |
1091 | 1094 | ||
1092 | ahw->fw_dump.enable = 1; | 1095 | qlcnic_enable_fw_dump_state(adapter); |
1093 | 1096 | ||
1094 | return 0; | 1097 | return 0; |
1095 | } | 1098 | } |
@@ -1112,7 +1115,11 @@ int qlcnic_dump_fw(struct qlcnic_adapter *adapter) | |||
1112 | 1115 | ||
1113 | ahw = adapter->ahw; | 1116 | ahw = adapter->ahw; |
1114 | 1117 | ||
1115 | if (!fw_dump->enable) { | 1118 | /* Return if we don't have firmware dump template header */ |
1119 | if (!tmpl_hdr) | ||
1120 | return -EIO; | ||
1121 | |||
1122 | if (!qlcnic_check_fw_dump_state(adapter)) { | ||
1116 | dev_info(&adapter->pdev->dev, "Dump not enabled\n"); | 1123 | dev_info(&adapter->pdev->dev, "Dump not enabled\n"); |
1117 | return -EIO; | 1124 | return -EIO; |
1118 | } | 1125 | } |
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, | |||
398 | } | 398 | } |
399 | 399 | ||
400 | static int qlcnic_sriov_set_pvid_mode(struct qlcnic_adapter *adapter, | 400 | static int qlcnic_sriov_set_pvid_mode(struct qlcnic_adapter *adapter, |
401 | struct qlcnic_cmd_args *cmd, u32 cap) | 401 | struct qlcnic_cmd_args *cmd) |
402 | { | 402 | { |
403 | if (cap & QLC_83XX_PVID_STRIP_CAPABILITY) { | 403 | adapter->rx_pvid = MSW(cmd->rsp.arg[1]) & 0xffff; |
404 | adapter->rx_pvid = 0; | 404 | adapter->flags &= ~QLCNIC_TAGGING_ENABLED; |
405 | } else { | ||
406 | adapter->rx_pvid = (cmd->rsp.arg[1] >> 16) & 0xffff; | ||
407 | adapter->flags &= ~QLCNIC_TAGGING_ENABLED; | ||
408 | } | ||
409 | return 0; | 405 | return 0; |
410 | } | 406 | } |
411 | 407 | ||
@@ -441,9 +437,8 @@ static int qlcnic_sriov_get_vf_acl(struct qlcnic_adapter *adapter, | |||
441 | { | 437 | { |
442 | struct qlcnic_sriov *sriov = adapter->ahw->sriov; | 438 | struct qlcnic_sriov *sriov = adapter->ahw->sriov; |
443 | struct qlcnic_cmd_args cmd; | 439 | struct qlcnic_cmd_args cmd; |
444 | int ret, cap; | 440 | int ret = 0; |
445 | 441 | ||
446 | cap = info->capabilities; | ||
447 | ret = qlcnic_sriov_alloc_bc_mbx_args(&cmd, QLCNIC_BC_CMD_GET_ACL); | 442 | ret = qlcnic_sriov_alloc_bc_mbx_args(&cmd, QLCNIC_BC_CMD_GET_ACL); |
448 | if (ret) | 443 | if (ret) |
449 | return ret; | 444 | return ret; |
@@ -459,7 +454,7 @@ static int qlcnic_sriov_get_vf_acl(struct qlcnic_adapter *adapter, | |||
459 | ret = qlcnic_sriov_set_guest_vlan_mode(adapter, &cmd); | 454 | ret = qlcnic_sriov_set_guest_vlan_mode(adapter, &cmd); |
460 | break; | 455 | break; |
461 | case QLC_PVID_MODE: | 456 | case QLC_PVID_MODE: |
462 | ret = qlcnic_sriov_set_pvid_mode(adapter, &cmd, cap); | 457 | ret = qlcnic_sriov_set_pvid_mode(adapter, &cmd); |
463 | break; | 458 | break; |
464 | } | 459 | } |
465 | } | 460 | } |
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, | |||
1183 | struct qlcnic_vf_info *vf = trans->vf; | 1183 | struct qlcnic_vf_info *vf = trans->vf; |
1184 | struct qlcnic_vport *vp = vf->vp; | 1184 | struct qlcnic_vport *vp = vf->vp; |
1185 | u8 cmd_op, mode = vp->vlan_mode; | 1185 | u8 cmd_op, mode = vp->vlan_mode; |
1186 | struct qlcnic_adapter *adapter; | ||
1187 | |||
1188 | adapter = vf->adapter; | ||
1186 | 1189 | ||
1187 | cmd_op = trans->req_hdr->cmd_op; | 1190 | cmd_op = trans->req_hdr->cmd_op; |
1188 | cmd->rsp.arg[0] |= 1 << 25; | 1191 | cmd->rsp.arg[0] |= 1 << 25; |
1189 | 1192 | ||
1193 | /* For 84xx adapter in case of PVID , PFD should send vlan mode as | ||
1194 | * QLC_NO_VLAN_MODE to VFD which is zero in mailbox response | ||
1195 | */ | ||
1196 | if (qlcnic_84xx_check(adapter) && mode == QLC_PVID_MODE) | ||
1197 | return 0; | ||
1198 | |||
1190 | switch (mode) { | 1199 | switch (mode) { |
1191 | case QLC_GUEST_VLAN_MODE: | 1200 | case QLC_GUEST_VLAN_MODE: |
1192 | cmd->rsp.arg[1] = mode | 1 << 8; | 1201 | cmd->rsp.arg[1] = mode | 1 << 8; |
@@ -1772,8 +1781,8 @@ int qlcnic_sriov_set_vf_vlan(struct net_device *netdev, int vf, | |||
1772 | return 0; | 1781 | return 0; |
1773 | } | 1782 | } |
1774 | 1783 | ||
1775 | static inline __u32 qlcnic_sriov_get_vf_vlan(struct qlcnic_adapter *adapter, | 1784 | static __u32 qlcnic_sriov_get_vf_vlan(struct qlcnic_adapter *adapter, |
1776 | struct qlcnic_vport *vp, int vf) | 1785 | struct qlcnic_vport *vp, int vf) |
1777 | { | 1786 | { |
1778 | __u32 vlan = 0; | 1787 | __u32 vlan = 0; |
1779 | 1788 | ||
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, | |||
465 | memset(&pm_cfg, 0, | 465 | memset(&pm_cfg, 0, |
466 | sizeof(struct qlcnic_pm_func_cfg) * QLCNIC_MAX_PCI_FUNC); | 466 | sizeof(struct qlcnic_pm_func_cfg) * QLCNIC_MAX_PCI_FUNC); |
467 | 467 | ||
468 | for (i = 0; i < adapter->ahw->act_pci_func; i++) { | 468 | for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++) { |
469 | pci_func = adapter->npars[i].pci_func; | 469 | pci_func = adapter->npars[i].pci_func; |
470 | if (!adapter->npars[i].active) | ||
471 | continue; | ||
472 | |||
473 | if (!adapter->npars[i].eswitch_status) | ||
474 | continue; | ||
475 | |||
470 | pm_cfg[pci_func].action = adapter->npars[i].enable_pm; | 476 | pm_cfg[pci_func].action = adapter->npars[i].enable_pm; |
471 | pm_cfg[pci_func].dest_npar = 0; | 477 | pm_cfg[pci_func].dest_npar = 0; |
472 | pm_cfg[pci_func].pci_func = i; | 478 | pm_cfg[pci_func].pci_func = i; |
@@ -632,8 +638,14 @@ static ssize_t qlcnic_sysfs_read_esw_config(struct file *file, | |||
632 | memset(&esw_cfg, 0, | 638 | memset(&esw_cfg, 0, |
633 | sizeof(struct qlcnic_esw_func_cfg) * QLCNIC_MAX_PCI_FUNC); | 639 | sizeof(struct qlcnic_esw_func_cfg) * QLCNIC_MAX_PCI_FUNC); |
634 | 640 | ||
635 | for (i = 0; i < adapter->ahw->act_pci_func; i++) { | 641 | for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++) { |
636 | pci_func = adapter->npars[i].pci_func; | 642 | pci_func = adapter->npars[i].pci_func; |
643 | if (!adapter->npars[i].active) | ||
644 | continue; | ||
645 | |||
646 | if (!adapter->npars[i].eswitch_status) | ||
647 | continue; | ||
648 | |||
637 | esw_cfg[pci_func].pci_func = pci_func; | 649 | esw_cfg[pci_func].pci_func = pci_func; |
638 | if (qlcnic_get_eswitch_port_config(adapter, &esw_cfg[pci_func])) | 650 | if (qlcnic_get_eswitch_port_config(adapter, &esw_cfg[pci_func])) |
639 | return QL_STATUS_INVALID_PARAM; | 651 | return QL_STATUS_INVALID_PARAM; |
@@ -732,6 +744,9 @@ static ssize_t qlcnic_sysfs_read_npar_config(struct file *file, | |||
732 | if (ret) | 744 | if (ret) |
733 | return ret; | 745 | return ret; |
734 | 746 | ||
747 | if (!adapter->npars[i].eswitch_status) | ||
748 | continue; | ||
749 | |||
735 | np_cfg[i].pci_func = i; | 750 | np_cfg[i].pci_func = i; |
736 | np_cfg[i].op_mode = (u8)nic_info.op_mode; | 751 | np_cfg[i].op_mode = (u8)nic_info.op_mode; |
737 | np_cfg[i].port_num = nic_info.phys_port; | 752 | np_cfg[i].port_num = nic_info.phys_port; |