diff options
author | David S. Miller <davem@davemloft.net> | 2013-05-25 02:05:11 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2013-05-25 02:05:11 -0400 |
commit | 6e2842f4bbb5abcf57d3cb0f10870e0ce20c0ba2 (patch) | |
tree | fbcc1cfbf2e720904bc6d50bc91753d99c6b31a4 | |
parent | f2068b80ca59d63ca21ee1da829c9fe09f25b08e (diff) | |
parent | 6a531b7b1989ddef5ee45c619970037eb2374c0d (diff) |
Merge branch 'qlcnic'
Shahed Shaikh says:
====================
This patch series includes following changes:
* Support for spoof check configuration per VF using
iproute2 tool.
* Set HW mask for 8300 adapter in INT-x mode to stop generating
interrupts.
* Updated IRQ name for 8200 and 8300 Series adapter as per
format used by other multiqueue drivers.
* Remove qlcnic_config_npars module parameter.
* Initialize trans_work and idc_aen_work at VF probe.
* Convert netsted if-else into switch-case statement.
* Change in diagnostics routine.
* Modify reset recovery path in diag mode by providing diagnostics
routines enough time to unwind before proceeding with reset recovery.
* Implement GET_LED_STATUS command for 82xx adapter and refactor
qlcnic_store_beacon() to split 8200 and 8300 specific calls.
* Some cleanup and log enhancements
====================
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | drivers/net/ethernet/qlogic/qlcnic/qlcnic.h | 27 | ||||
-rw-r--r-- | drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c | 77 | ||||
-rw-r--r-- | drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h | 1 | ||||
-rw-r--r-- | drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c | 35 | ||||
-rw-r--r-- | drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_vnic.c | 39 | ||||
-rw-r--r-- | drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c | 45 | ||||
-rw-r--r-- | drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c | 15 | ||||
-rw-r--r-- | drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.h | 1 | ||||
-rw-r--r-- | drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c | 85 | ||||
-rw-r--r-- | drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov.h | 2 | ||||
-rw-r--r-- | drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c | 7 | ||||
-rw-r--r-- | drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_pf.c | 36 | ||||
-rw-r--r-- | drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c | 122 |
13 files changed, 324 insertions, 168 deletions
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h index c1b693cb3df3..534e36ed855a 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 2 | 40 | #define _QLCNIC_LINUX_MINOR 2 |
41 | #define _QLCNIC_LINUX_SUBVERSION 42 | 41 | #define _QLCNIC_LINUX_SUBVERSION 43 |
42 | #define QLCNIC_LINUX_VERSIONID "5.2.42" | 42 | #define QLCNIC_LINUX_VERSIONID "5.2.43" |
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)) |
@@ -303,7 +303,6 @@ extern int qlcnic_use_msi; | |||
303 | extern int qlcnic_use_msi_x; | 303 | extern int qlcnic_use_msi_x; |
304 | extern int qlcnic_auto_fw_reset; | 304 | extern int qlcnic_auto_fw_reset; |
305 | extern int qlcnic_load_fw_file; | 305 | extern int qlcnic_load_fw_file; |
306 | extern int qlcnic_config_npars; | ||
307 | 306 | ||
308 | /* Number of status descriptors to handle per interrupt */ | 307 | /* Number of status descriptors to handle per interrupt */ |
309 | #define MAX_STATUS_HANDLE (64) | 308 | #define MAX_STATUS_HANDLE (64) |
@@ -443,6 +442,7 @@ struct qlcnic_hardware_context { | |||
443 | u16 max_mtu; | 442 | u16 max_mtu; |
444 | u32 msg_enable; | 443 | u32 msg_enable; |
445 | u16 act_pci_func; | 444 | u16 act_pci_func; |
445 | u16 max_pci_func; | ||
446 | 446 | ||
447 | u32 capabilities; | 447 | u32 capabilities; |
448 | u32 capabilities2; | 448 | u32 capabilities2; |
@@ -816,6 +816,7 @@ struct qlcnic_mac_list_s { | |||
816 | #define QLCNIC_FW_CAPABILITY_2_LRO_MAX_TCP_SEG BIT_2 | 816 | #define QLCNIC_FW_CAPABILITY_2_LRO_MAX_TCP_SEG BIT_2 |
817 | #define QLCNIC_FW_CAP2_HW_LRO_IPV6 BIT_3 | 817 | #define QLCNIC_FW_CAP2_HW_LRO_IPV6 BIT_3 |
818 | #define QLCNIC_FW_CAPABILITY_2_OCBB BIT_5 | 818 | #define QLCNIC_FW_CAPABILITY_2_OCBB BIT_5 |
819 | #define QLCNIC_FW_CAPABILITY_2_BEACON BIT_7 | ||
819 | 820 | ||
820 | /* module types */ | 821 | /* module types */ |
821 | #define LINKEVENT_MODULE_NOT_PRESENT 1 | 822 | #define LINKEVENT_MODULE_NOT_PRESENT 1 |
@@ -913,6 +914,9 @@ struct qlcnic_ipaddr { | |||
913 | #define QLCNIC_IS_TSO_CAPABLE(adapter) \ | 914 | #define QLCNIC_IS_TSO_CAPABLE(adapter) \ |
914 | ((adapter)->ahw->capabilities & QLCNIC_FW_CAPABILITY_TSO) | 915 | ((adapter)->ahw->capabilities & QLCNIC_FW_CAPABILITY_TSO) |
915 | 916 | ||
917 | #define QLCNIC_BEACON_EANBLE 0xC | ||
918 | #define QLCNIC_BEACON_DISABLE 0xD | ||
919 | |||
916 | #define QLCNIC_DEF_NUM_STS_DESC_RINGS 4 | 920 | #define QLCNIC_DEF_NUM_STS_DESC_RINGS 4 |
917 | #define QLCNIC_MSIX_TBL_SPACE 8192 | 921 | #define QLCNIC_MSIX_TBL_SPACE 8192 |
918 | #define QLCNIC_PCI_REG_MSIX_TBL 0x44 | 922 | #define QLCNIC_PCI_REG_MSIX_TBL 0x44 |
@@ -932,6 +936,7 @@ struct qlcnic_ipaddr { | |||
932 | #define __QLCNIC_SRIOV_ENABLE 10 | 936 | #define __QLCNIC_SRIOV_ENABLE 10 |
933 | #define __QLCNIC_SRIOV_CAPABLE 11 | 937 | #define __QLCNIC_SRIOV_CAPABLE 11 |
934 | #define __QLCNIC_MBX_POLL_ENABLE 12 | 938 | #define __QLCNIC_MBX_POLL_ENABLE 12 |
939 | #define __QLCNIC_DIAG_MODE 13 | ||
935 | 940 | ||
936 | #define QLCNIC_INTERRUPT_TEST 1 | 941 | #define QLCNIC_INTERRUPT_TEST 1 |
937 | #define QLCNIC_LOOPBACK_TEST 2 | 942 | #define QLCNIC_LOOPBACK_TEST 2 |
@@ -1543,6 +1548,7 @@ int qlcnic_set_default_offload_settings(struct qlcnic_adapter *); | |||
1543 | int qlcnic_reset_npar_config(struct qlcnic_adapter *); | 1548 | int qlcnic_reset_npar_config(struct qlcnic_adapter *); |
1544 | int qlcnic_set_eswitch_port_config(struct qlcnic_adapter *); | 1549 | int qlcnic_set_eswitch_port_config(struct qlcnic_adapter *); |
1545 | void qlcnic_add_lb_filter(struct qlcnic_adapter *, struct sk_buff *, int, u16); | 1550 | void qlcnic_add_lb_filter(struct qlcnic_adapter *, struct sk_buff *, int, u16); |
1551 | int qlcnic_get_beacon_state(struct qlcnic_adapter *, u8 *); | ||
1546 | int qlcnic_83xx_configure_opmode(struct qlcnic_adapter *adapter); | 1552 | int qlcnic_83xx_configure_opmode(struct qlcnic_adapter *adapter); |
1547 | int qlcnic_read_mac_addr(struct qlcnic_adapter *); | 1553 | int qlcnic_read_mac_addr(struct qlcnic_adapter *); |
1548 | int qlcnic_setup_netdev(struct qlcnic_adapter *, struct net_device *, int); | 1554 | int qlcnic_setup_netdev(struct qlcnic_adapter *, struct net_device *, int); |
@@ -1886,6 +1892,21 @@ static inline void qlcnic_enable_int(struct qlcnic_host_sds_ring *sds_ring) | |||
1886 | writel(0xfbff, adapter->tgt_mask_reg); | 1892 | writel(0xfbff, adapter->tgt_mask_reg); |
1887 | } | 1893 | } |
1888 | 1894 | ||
1895 | static inline int qlcnic_get_diag_lock(struct qlcnic_adapter *adapter) | ||
1896 | { | ||
1897 | return test_and_set_bit(__QLCNIC_DIAG_MODE, &adapter->state); | ||
1898 | } | ||
1899 | |||
1900 | static inline void qlcnic_release_diag_lock(struct qlcnic_adapter *adapter) | ||
1901 | { | ||
1902 | clear_bit(__QLCNIC_DIAG_MODE, &adapter->state); | ||
1903 | } | ||
1904 | |||
1905 | static inline int qlcnic_check_diag_status(struct qlcnic_adapter *adapter) | ||
1906 | { | ||
1907 | return test_bit(__QLCNIC_DIAG_MODE, &adapter->state); | ||
1908 | } | ||
1909 | |||
1889 | extern const struct ethtool_ops qlcnic_sriov_vf_ethtool_ops; | 1910 | extern const struct ethtool_ops qlcnic_sriov_vf_ethtool_ops; |
1890 | extern const struct ethtool_ops qlcnic_ethtool_ops; | 1911 | extern const struct ethtool_ops qlcnic_ethtool_ops; |
1891 | extern const struct ethtool_ops qlcnic_ethtool_failed_ops; | 1912 | extern const struct ethtool_ops qlcnic_ethtool_failed_ops; |
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c index b4ff1e35a11d..f63a69570256 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c | |||
@@ -312,6 +312,11 @@ inline void qlcnic_83xx_clear_legacy_intr_mask(struct qlcnic_adapter *adapter) | |||
312 | writel(0, adapter->tgt_mask_reg); | 312 | writel(0, adapter->tgt_mask_reg); |
313 | } | 313 | } |
314 | 314 | ||
315 | inline void qlcnic_83xx_set_legacy_intr_mask(struct qlcnic_adapter *adapter) | ||
316 | { | ||
317 | writel(1, adapter->tgt_mask_reg); | ||
318 | } | ||
319 | |||
315 | /* Enable MSI-x and INT-x interrupts */ | 320 | /* Enable MSI-x and INT-x interrupts */ |
316 | void qlcnic_83xx_enable_intr(struct qlcnic_adapter *adapter, | 321 | void qlcnic_83xx_enable_intr(struct qlcnic_adapter *adapter, |
317 | struct qlcnic_host_sds_ring *sds_ring) | 322 | struct qlcnic_host_sds_ring *sds_ring) |
@@ -458,6 +463,9 @@ void qlcnic_83xx_free_mbx_intr(struct qlcnic_adapter *adapter) | |||
458 | { | 463 | { |
459 | u32 num_msix; | 464 | u32 num_msix; |
460 | 465 | ||
466 | if (!(adapter->flags & QLCNIC_MSIX_ENABLED)) | ||
467 | qlcnic_83xx_set_legacy_intr_mask(adapter); | ||
468 | |||
461 | qlcnic_83xx_disable_mbx_intr(adapter); | 469 | qlcnic_83xx_disable_mbx_intr(adapter); |
462 | 470 | ||
463 | if (adapter->flags & QLCNIC_MSIX_ENABLED) | 471 | if (adapter->flags & QLCNIC_MSIX_ENABLED) |
@@ -474,7 +482,6 @@ int qlcnic_83xx_setup_mbx_intr(struct qlcnic_adapter *adapter) | |||
474 | { | 482 | { |
475 | irq_handler_t handler; | 483 | irq_handler_t handler; |
476 | u32 val; | 484 | u32 val; |
477 | char name[32]; | ||
478 | int err = 0; | 485 | int err = 0; |
479 | unsigned long flags = 0; | 486 | unsigned long flags = 0; |
480 | 487 | ||
@@ -485,9 +492,7 @@ int qlcnic_83xx_setup_mbx_intr(struct qlcnic_adapter *adapter) | |||
485 | if (adapter->flags & QLCNIC_MSIX_ENABLED) { | 492 | if (adapter->flags & QLCNIC_MSIX_ENABLED) { |
486 | handler = qlcnic_83xx_handle_aen; | 493 | handler = qlcnic_83xx_handle_aen; |
487 | val = adapter->msix_entries[adapter->ahw->num_msix - 1].vector; | 494 | val = adapter->msix_entries[adapter->ahw->num_msix - 1].vector; |
488 | snprintf(name, (IFNAMSIZ + 4), | 495 | err = request_irq(val, handler, flags, "qlcnic-MB", adapter); |
489 | "%s[%s]", "qlcnic", "aen"); | ||
490 | err = request_irq(val, handler, flags, name, adapter); | ||
491 | if (err) { | 496 | if (err) { |
492 | dev_err(&adapter->pdev->dev, | 497 | dev_err(&adapter->pdev->dev, |
493 | "failed to register MBX interrupt\n"); | 498 | "failed to register MBX interrupt\n"); |
@@ -1588,16 +1593,24 @@ int qlcnic_83xx_loopback_test(struct net_device *netdev, u8 mode) | |||
1588 | struct qlcnic_hardware_context *ahw = adapter->ahw; | 1593 | struct qlcnic_hardware_context *ahw = adapter->ahw; |
1589 | int ret = 0, loop = 0, max_sds_rings = adapter->max_sds_rings; | 1594 | int ret = 0, loop = 0, max_sds_rings = adapter->max_sds_rings; |
1590 | 1595 | ||
1591 | QLCDB(adapter, DRV, "%s loopback test in progress\n", | ||
1592 | mode == QLCNIC_ILB_MODE ? "internal" : "external"); | ||
1593 | if (ahw->op_mode == QLCNIC_NON_PRIV_FUNC) { | 1596 | if (ahw->op_mode == QLCNIC_NON_PRIV_FUNC) { |
1594 | dev_warn(&adapter->pdev->dev, | 1597 | netdev_warn(netdev, |
1595 | "Loopback test not supported for non privilege function\n"); | 1598 | "Loopback test not supported in non privileged mode\n"); |
1596 | return ret; | 1599 | return ret; |
1597 | } | 1600 | } |
1598 | 1601 | ||
1599 | if (test_and_set_bit(__QLCNIC_RESETTING, &adapter->state)) | 1602 | if (test_bit(__QLCNIC_RESETTING, &adapter->state)) { |
1603 | netdev_info(netdev, "Device is resetting\n"); | ||
1600 | return -EBUSY; | 1604 | return -EBUSY; |
1605 | } | ||
1606 | |||
1607 | if (qlcnic_get_diag_lock(adapter)) { | ||
1608 | netdev_info(netdev, "Device is in diagnostics mode\n"); | ||
1609 | return -EBUSY; | ||
1610 | } | ||
1611 | |||
1612 | netdev_info(netdev, "%s loopback test in progress\n", | ||
1613 | mode == QLCNIC_ILB_MODE ? "internal" : "external"); | ||
1601 | 1614 | ||
1602 | ret = qlcnic_83xx_diag_alloc_res(netdev, QLCNIC_LOOPBACK_TEST, | 1615 | ret = qlcnic_83xx_diag_alloc_res(netdev, QLCNIC_LOOPBACK_TEST, |
1603 | max_sds_rings); | 1616 | max_sds_rings); |
@@ -1638,7 +1651,7 @@ free_diag_res: | |||
1638 | 1651 | ||
1639 | fail_diag_alloc: | 1652 | fail_diag_alloc: |
1640 | adapter->max_sds_rings = max_sds_rings; | 1653 | adapter->max_sds_rings = max_sds_rings; |
1641 | clear_bit(__QLCNIC_RESETTING, &adapter->state); | 1654 | qlcnic_release_diag_lock(adapter); |
1642 | return ret; | 1655 | return ret; |
1643 | } | 1656 | } |
1644 | 1657 | ||
@@ -2121,26 +2134,25 @@ out: | |||
2121 | int qlcnic_83xx_get_pci_info(struct qlcnic_adapter *adapter, | 2134 | int qlcnic_83xx_get_pci_info(struct qlcnic_adapter *adapter, |
2122 | struct qlcnic_pci_info *pci_info) | 2135 | struct qlcnic_pci_info *pci_info) |
2123 | { | 2136 | { |
2137 | struct qlcnic_hardware_context *ahw = adapter->ahw; | ||
2138 | struct device *dev = &adapter->pdev->dev; | ||
2139 | struct qlcnic_cmd_args cmd; | ||
2124 | int i, err = 0, j = 0; | 2140 | int i, err = 0, j = 0; |
2125 | u32 temp; | 2141 | u32 temp; |
2126 | struct qlcnic_cmd_args cmd; | ||
2127 | 2142 | ||
2128 | qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_GET_PCI_INFO); | 2143 | qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_GET_PCI_INFO); |
2129 | err = qlcnic_issue_cmd(adapter, &cmd); | 2144 | err = qlcnic_issue_cmd(adapter, &cmd); |
2130 | 2145 | ||
2131 | adapter->ahw->act_pci_func = 0; | 2146 | ahw->act_pci_func = 0; |
2132 | if (err == QLCNIC_RCODE_SUCCESS) { | 2147 | if (err == QLCNIC_RCODE_SUCCESS) { |
2133 | pci_info->func_count = cmd.rsp.arg[1] & 0xFF; | 2148 | ahw->max_pci_func = cmd.rsp.arg[1] & 0xFF; |
2134 | dev_info(&adapter->pdev->dev, | ||
2135 | "%s: total functions = %d\n", | ||
2136 | __func__, pci_info->func_count); | ||
2137 | for (i = 2, j = 0; j < QLCNIC_MAX_PCI_FUNC; j++, pci_info++) { | 2149 | for (i = 2, j = 0; j < QLCNIC_MAX_PCI_FUNC; j++, pci_info++) { |
2138 | pci_info->id = cmd.rsp.arg[i] & 0xFFFF; | 2150 | pci_info->id = cmd.rsp.arg[i] & 0xFFFF; |
2139 | pci_info->active = (cmd.rsp.arg[i] & 0xFFFF0000) >> 16; | 2151 | pci_info->active = (cmd.rsp.arg[i] & 0xFFFF0000) >> 16; |
2140 | i++; | 2152 | i++; |
2141 | pci_info->type = cmd.rsp.arg[i] & 0xFFFF; | 2153 | pci_info->type = cmd.rsp.arg[i] & 0xFFFF; |
2142 | if (pci_info->type == QLCNIC_TYPE_NIC) | 2154 | if (pci_info->type == QLCNIC_TYPE_NIC) |
2143 | adapter->ahw->act_pci_func++; | 2155 | ahw->act_pci_func++; |
2144 | temp = (cmd.rsp.arg[i] & 0xFFFF0000) >> 16; | 2156 | temp = (cmd.rsp.arg[i] & 0xFFFF0000) >> 16; |
2145 | pci_info->default_port = temp; | 2157 | pci_info->default_port = temp; |
2146 | i++; | 2158 | i++; |
@@ -2152,18 +2164,21 @@ int qlcnic_83xx_get_pci_info(struct qlcnic_adapter *adapter, | |||
2152 | i++; | 2164 | i++; |
2153 | memcpy(pci_info->mac + sizeof(u32), &cmd.rsp.arg[i], 2); | 2165 | memcpy(pci_info->mac + sizeof(u32), &cmd.rsp.arg[i], 2); |
2154 | i = i + 3; | 2166 | i = i + 3; |
2155 | 2167 | if (ahw->op_mode == QLCNIC_MGMT_FUNC) | |
2156 | dev_info(&adapter->pdev->dev, "%s:\n" | 2168 | dev_info(dev, "id = %d active = %d type = %d\n" |
2157 | "\tid = %d active = %d type = %d\n" | 2169 | "\tport = %d min bw = %d max bw = %d\n" |
2158 | "\tport = %d min bw = %d max bw = %d\n" | 2170 | "\tmac_addr = %pM\n", pci_info->id, |
2159 | "\tmac_addr = %pM\n", __func__, | 2171 | pci_info->active, pci_info->type, |
2160 | pci_info->id, pci_info->active, pci_info->type, | 2172 | pci_info->default_port, |
2161 | pci_info->default_port, pci_info->tx_min_bw, | 2173 | pci_info->tx_min_bw, |
2162 | pci_info->tx_max_bw, pci_info->mac); | 2174 | pci_info->tx_max_bw, pci_info->mac); |
2163 | } | 2175 | } |
2176 | if (ahw->op_mode == QLCNIC_MGMT_FUNC) | ||
2177 | dev_info(dev, "Max vNIC functions = %d, active vNIC functions = %d\n", | ||
2178 | ahw->max_pci_func, ahw->act_pci_func); | ||
2179 | |||
2164 | } else { | 2180 | } else { |
2165 | dev_err(&adapter->pdev->dev, "Failed to get PCI Info%d\n", | 2181 | dev_err(dev, "Failed to get PCI Info, error = %d\n", err); |
2166 | err); | ||
2167 | err = -EIO; | 2182 | err = -EIO; |
2168 | } | 2183 | } |
2169 | 2184 | ||
@@ -3113,8 +3128,10 @@ int qlcnic_83xx_interrupt_test(struct net_device *netdev) | |||
3113 | u8 val; | 3128 | u8 val; |
3114 | int ret, max_sds_rings = adapter->max_sds_rings; | 3129 | int ret, max_sds_rings = adapter->max_sds_rings; |
3115 | 3130 | ||
3116 | if (test_and_set_bit(__QLCNIC_RESETTING, &adapter->state)) | 3131 | if (qlcnic_get_diag_lock(adapter)) { |
3117 | return -EIO; | 3132 | netdev_info(netdev, "Device in diagnostics mode\n"); |
3133 | return -EBUSY; | ||
3134 | } | ||
3118 | 3135 | ||
3119 | ret = qlcnic_83xx_diag_alloc_res(netdev, QLCNIC_INTERRUPT_TEST, | 3136 | ret = qlcnic_83xx_diag_alloc_res(netdev, QLCNIC_INTERRUPT_TEST, |
3120 | max_sds_rings); | 3137 | max_sds_rings); |
@@ -3156,7 +3173,7 @@ done: | |||
3156 | 3173 | ||
3157 | fail_diag_irq: | 3174 | fail_diag_irq: |
3158 | adapter->max_sds_rings = max_sds_rings; | 3175 | adapter->max_sds_rings = max_sds_rings; |
3159 | clear_bit(__QLCNIC_RESETTING, &adapter->state); | 3176 | qlcnic_release_diag_lock(adapter); |
3160 | return ret; | 3177 | return ret; |
3161 | } | 3178 | } |
3162 | 3179 | ||
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h index f5db67fc9f55..1bfe283a9412 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h | |||
@@ -314,6 +314,7 @@ struct qlc_83xx_idc { | |||
314 | u8 vnic_state; | 314 | u8 vnic_state; |
315 | u8 vnic_wait_limit; | 315 | u8 vnic_wait_limit; |
316 | u8 quiesce_req; | 316 | u8 quiesce_req; |
317 | u8 delay_reset; | ||
317 | char **name; | 318 | char **name; |
318 | }; | 319 | }; |
319 | 320 | ||
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c index 5e7fb1dfb97b..aa26250d7374 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c | |||
@@ -649,6 +649,7 @@ static void qlcnic_83xx_idc_update_idc_params(struct qlcnic_adapter *adapter) | |||
649 | ahw->idc.collect_dump = 0; | 649 | ahw->idc.collect_dump = 0; |
650 | ahw->reset_context = 0; | 650 | ahw->reset_context = 0; |
651 | adapter->tx_timeo_cnt = 0; | 651 | adapter->tx_timeo_cnt = 0; |
652 | ahw->idc.delay_reset = 0; | ||
652 | 653 | ||
653 | clear_bit(__QLCNIC_RESETTING, &adapter->state); | 654 | clear_bit(__QLCNIC_RESETTING, &adapter->state); |
654 | } | 655 | } |
@@ -883,21 +884,41 @@ static int qlcnic_83xx_idc_need_reset_state(struct qlcnic_adapter *adapter) | |||
883 | int ret = 0; | 884 | int ret = 0; |
884 | 885 | ||
885 | if (adapter->ahw->idc.prev_state != QLC_83XX_IDC_DEV_NEED_RESET) { | 886 | if (adapter->ahw->idc.prev_state != QLC_83XX_IDC_DEV_NEED_RESET) { |
886 | qlcnic_83xx_idc_update_drv_ack_reg(adapter, 1, 1); | ||
887 | qlcnic_83xx_idc_update_audit_reg(adapter, 0, 1); | 887 | qlcnic_83xx_idc_update_audit_reg(adapter, 0, 1); |
888 | set_bit(__QLCNIC_RESETTING, &adapter->state); | 888 | set_bit(__QLCNIC_RESETTING, &adapter->state); |
889 | clear_bit(QLC_83XX_MBX_READY, &adapter->ahw->idc.status); | 889 | clear_bit(QLC_83XX_MBX_READY, &adapter->ahw->idc.status); |
890 | if (adapter->ahw->nic_mode == QLC_83XX_VIRTUAL_NIC_MODE) | 890 | if (adapter->ahw->nic_mode == QLC_83XX_VIRTUAL_NIC_MODE) |
891 | qlcnic_83xx_disable_vnic_mode(adapter, 1); | 891 | qlcnic_83xx_disable_vnic_mode(adapter, 1); |
892 | qlcnic_83xx_idc_detach_driver(adapter); | 892 | |
893 | if (qlcnic_check_diag_status(adapter)) { | ||
894 | dev_info(&adapter->pdev->dev, | ||
895 | "%s: Wait for diag completion\n", __func__); | ||
896 | adapter->ahw->idc.delay_reset = 1; | ||
897 | return 0; | ||
898 | } else { | ||
899 | qlcnic_83xx_idc_update_drv_ack_reg(adapter, 1, 1); | ||
900 | qlcnic_83xx_idc_detach_driver(adapter); | ||
901 | } | ||
893 | } | 902 | } |
894 | 903 | ||
895 | /* Check ACK from other functions */ | 904 | if (qlcnic_check_diag_status(adapter)) { |
896 | ret = qlcnic_83xx_idc_check_reset_ack_reg(adapter); | ||
897 | if (ret) { | ||
898 | dev_info(&adapter->pdev->dev, | 905 | dev_info(&adapter->pdev->dev, |
899 | "%s: Waiting for reset ACK\n", __func__); | 906 | "%s: Wait for diag completion\n", __func__); |
900 | return 0; | 907 | return -1; |
908 | } else { | ||
909 | if (adapter->ahw->idc.delay_reset) { | ||
910 | qlcnic_83xx_idc_update_drv_ack_reg(adapter, 1, 1); | ||
911 | qlcnic_83xx_idc_detach_driver(adapter); | ||
912 | adapter->ahw->idc.delay_reset = 0; | ||
913 | } | ||
914 | |||
915 | /* Check for ACK from other functions */ | ||
916 | ret = qlcnic_83xx_idc_check_reset_ack_reg(adapter); | ||
917 | if (ret) { | ||
918 | dev_info(&adapter->pdev->dev, | ||
919 | "%s: Waiting for reset ACK\n", __func__); | ||
920 | return -1; | ||
921 | } | ||
901 | } | 922 | } |
902 | 923 | ||
903 | /* Transit to INIT state and restart the HW */ | 924 | /* Transit to INIT state and restart the HW */ |
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_vnic.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_vnic.c index b0c3de9ede03..b5054e1d1710 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_vnic.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_vnic.c | |||
@@ -42,27 +42,18 @@ int qlcnic_83xx_disable_vnic_mode(struct qlcnic_adapter *adapter, int lock) | |||
42 | static int qlcnic_83xx_set_vnic_opmode(struct qlcnic_adapter *adapter) | 42 | static int qlcnic_83xx_set_vnic_opmode(struct qlcnic_adapter *adapter) |
43 | { | 43 | { |
44 | u8 id; | 44 | u8 id; |
45 | int i, ret = -EBUSY; | 45 | int ret = -EBUSY; |
46 | u32 data = QLCNIC_MGMT_FUNC; | 46 | u32 data = QLCNIC_MGMT_FUNC; |
47 | struct qlcnic_hardware_context *ahw = adapter->ahw; | 47 | struct qlcnic_hardware_context *ahw = adapter->ahw; |
48 | 48 | ||
49 | if (qlcnic_83xx_lock_driver(adapter)) | 49 | if (qlcnic_83xx_lock_driver(adapter)) |
50 | return ret; | 50 | return ret; |
51 | 51 | ||
52 | if (qlcnic_config_npars) { | 52 | id = ahw->pci_func; |
53 | for (i = 0; i < ahw->act_pci_func; i++) { | 53 | data = QLCRDX(adapter->ahw, QLC_83XX_DRV_OP_MODE); |
54 | id = adapter->npars[i].pci_func; | 54 | data = (data & ~QLC_83XX_SET_FUNC_OPMODE(0x3, id)) | |
55 | if (id == ahw->pci_func) | 55 | QLC_83XX_SET_FUNC_OPMODE(QLCNIC_MGMT_FUNC, id); |
56 | continue; | 56 | |
57 | data |= qlcnic_config_npars & | ||
58 | QLC_83XX_SET_FUNC_OPMODE(0x3, id); | ||
59 | } | ||
60 | } else { | ||
61 | data = QLCRDX(adapter->ahw, QLC_83XX_DRV_OP_MODE); | ||
62 | data = (data & ~QLC_83XX_SET_FUNC_OPMODE(0x3, ahw->pci_func)) | | ||
63 | QLC_83XX_SET_FUNC_OPMODE(QLCNIC_MGMT_FUNC, | ||
64 | ahw->pci_func); | ||
65 | } | ||
66 | QLCWRX(adapter->ahw, QLC_83XX_DRV_OP_MODE, data); | 57 | QLCWRX(adapter->ahw, QLC_83XX_DRV_OP_MODE, data); |
67 | 58 | ||
68 | qlcnic_83xx_unlock_driver(adapter); | 59 | qlcnic_83xx_unlock_driver(adapter); |
@@ -196,20 +187,24 @@ int qlcnic_83xx_config_vnic_opmode(struct qlcnic_adapter *adapter) | |||
196 | else | 187 | else |
197 | priv_level = QLC_83XX_GET_FUNC_PRIVILEGE(op_mode, | 188 | priv_level = QLC_83XX_GET_FUNC_PRIVILEGE(op_mode, |
198 | ahw->pci_func); | 189 | ahw->pci_func); |
199 | 190 | switch (priv_level) { | |
200 | if (priv_level == QLCNIC_NON_PRIV_FUNC) { | 191 | case QLCNIC_NON_PRIV_FUNC: |
201 | ahw->op_mode = QLCNIC_NON_PRIV_FUNC; | 192 | ahw->op_mode = QLCNIC_NON_PRIV_FUNC; |
202 | ahw->idc.state_entry = qlcnic_83xx_idc_ready_state_entry; | 193 | ahw->idc.state_entry = qlcnic_83xx_idc_ready_state_entry; |
203 | nic_ops->init_driver = qlcnic_83xx_init_non_privileged_vnic; | 194 | nic_ops->init_driver = qlcnic_83xx_init_non_privileged_vnic; |
204 | } else if (priv_level == QLCNIC_PRIV_FUNC) { | 195 | break; |
196 | case QLCNIC_PRIV_FUNC: | ||
205 | ahw->op_mode = QLCNIC_PRIV_FUNC; | 197 | ahw->op_mode = QLCNIC_PRIV_FUNC; |
206 | ahw->idc.state_entry = qlcnic_83xx_idc_vnic_pf_entry; | 198 | ahw->idc.state_entry = qlcnic_83xx_idc_vnic_pf_entry; |
207 | nic_ops->init_driver = qlcnic_83xx_init_privileged_vnic; | 199 | nic_ops->init_driver = qlcnic_83xx_init_privileged_vnic; |
208 | } else if (priv_level == QLCNIC_MGMT_FUNC) { | 200 | break; |
201 | case QLCNIC_MGMT_FUNC: | ||
209 | ahw->op_mode = QLCNIC_MGMT_FUNC; | 202 | ahw->op_mode = QLCNIC_MGMT_FUNC; |
210 | ahw->idc.state_entry = qlcnic_83xx_idc_ready_state_entry; | 203 | ahw->idc.state_entry = qlcnic_83xx_idc_ready_state_entry; |
211 | nic_ops->init_driver = qlcnic_83xx_init_mgmt_vnic; | 204 | nic_ops->init_driver = qlcnic_83xx_init_mgmt_vnic; |
212 | } else { | 205 | break; |
206 | default: | ||
207 | dev_err(&adapter->pdev->dev, "Invalid Virtual NIC opmode\n"); | ||
213 | return -EIO; | 208 | return -EIO; |
214 | } | 209 | } |
215 | 210 | ||
@@ -218,8 +213,8 @@ int qlcnic_83xx_config_vnic_opmode(struct qlcnic_adapter *adapter) | |||
218 | else | 213 | else |
219 | adapter->flags &= ~QLCNIC_ESWITCH_ENABLED; | 214 | adapter->flags &= ~QLCNIC_ESWITCH_ENABLED; |
220 | 215 | ||
221 | adapter->ahw->idc.vnic_state = QLCNIC_DEV_NPAR_NON_OPER; | 216 | ahw->idc.vnic_state = QLCNIC_DEV_NPAR_NON_OPER; |
222 | adapter->ahw->idc.vnic_wait_limit = QLCNIC_DEV_NPAR_OPER_TIMEO; | 217 | ahw->idc.vnic_wait_limit = QLCNIC_DEV_NPAR_OPER_TIMEO; |
223 | 218 | ||
224 | return 0; | 219 | return 0; |
225 | } | 220 | } |
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c index 43562c256379..9d0ae11589ce 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c | |||
@@ -37,6 +37,7 @@ static const struct qlcnic_mailbox_metadata qlcnic_mbx_tbl[] = { | |||
37 | {QLCNIC_CMD_TEMP_SIZE, 4, 4}, | 37 | {QLCNIC_CMD_TEMP_SIZE, 4, 4}, |
38 | {QLCNIC_CMD_GET_TEMP_HDR, 4, 1}, | 38 | {QLCNIC_CMD_GET_TEMP_HDR, 4, 1}, |
39 | {QLCNIC_CMD_SET_DRV_VER, 4, 1}, | 39 | {QLCNIC_CMD_SET_DRV_VER, 4, 1}, |
40 | {QLCNIC_CMD_GET_LED_STATUS, 4, 2}, | ||
40 | }; | 41 | }; |
41 | 42 | ||
42 | static inline u32 qlcnic_get_cmd_signature(struct qlcnic_hardware_context *ahw) | 43 | static inline u32 qlcnic_get_cmd_signature(struct qlcnic_hardware_context *ahw) |
@@ -882,11 +883,12 @@ int qlcnic_82xx_get_pci_info(struct qlcnic_adapter *adapter, | |||
882 | 883 | ||
883 | /* Configure eSwitch for port mirroring */ | 884 | /* Configure eSwitch for port mirroring */ |
884 | int qlcnic_config_port_mirroring(struct qlcnic_adapter *adapter, u8 id, | 885 | int qlcnic_config_port_mirroring(struct qlcnic_adapter *adapter, u8 id, |
885 | u8 enable_mirroring, u8 pci_func) | 886 | u8 enable_mirroring, u8 pci_func) |
886 | { | 887 | { |
888 | struct device *dev = &adapter->pdev->dev; | ||
889 | struct qlcnic_cmd_args cmd; | ||
887 | int err = -EIO; | 890 | int err = -EIO; |
888 | u32 arg1; | 891 | u32 arg1; |
889 | struct qlcnic_cmd_args cmd; | ||
890 | 892 | ||
891 | if (adapter->ahw->op_mode != QLCNIC_MGMT_FUNC || | 893 | if (adapter->ahw->op_mode != QLCNIC_MGMT_FUNC || |
892 | !(adapter->eswitch[id].flags & QLCNIC_SWITCH_ENABLE)) | 894 | !(adapter->eswitch[id].flags & QLCNIC_SWITCH_ENABLE)) |
@@ -900,13 +902,11 @@ int qlcnic_config_port_mirroring(struct qlcnic_adapter *adapter, u8 id, | |||
900 | err = qlcnic_issue_cmd(adapter, &cmd); | 902 | err = qlcnic_issue_cmd(adapter, &cmd); |
901 | 903 | ||
902 | if (err != QLCNIC_RCODE_SUCCESS) | 904 | if (err != QLCNIC_RCODE_SUCCESS) |
903 | dev_err(&adapter->pdev->dev, | 905 | dev_err(dev, "Failed to configure port mirroring for vNIC function %d on eSwitch %d\n", |
904 | "Failed to configure port mirroring%d on eswitch:%d\n", | ||
905 | pci_func, id); | 906 | pci_func, id); |
906 | else | 907 | else |
907 | dev_info(&adapter->pdev->dev, | 908 | dev_info(dev, "Configured port mirroring for vNIC function %d on eSwitch %d\n", |
908 | "Configured eSwitch %d for port mirroring:%d\n", | 909 | pci_func, id); |
909 | id, pci_func); | ||
910 | qlcnic_free_mbx_args(&cmd); | 910 | qlcnic_free_mbx_args(&cmd); |
911 | 911 | ||
912 | return err; | 912 | return err; |
@@ -1121,14 +1121,13 @@ err_ret: | |||
1121 | return -EIO; | 1121 | return -EIO; |
1122 | } | 1122 | } |
1123 | 1123 | ||
1124 | static int | 1124 | static int __qlcnic_get_eswitch_port_config(struct qlcnic_adapter *adapter, |
1125 | __qlcnic_get_eswitch_port_config(struct qlcnic_adapter *adapter, | 1125 | u32 *arg1, u32 *arg2) |
1126 | u32 *arg1, u32 *arg2) | ||
1127 | { | 1126 | { |
1128 | int err = -EIO; | 1127 | struct device *dev = &adapter->pdev->dev; |
1129 | struct qlcnic_cmd_args cmd; | 1128 | struct qlcnic_cmd_args cmd; |
1130 | u8 pci_func; | 1129 | u8 pci_func = *arg1 >> 8; |
1131 | pci_func = (*arg1 >> 8); | 1130 | int err = -EIO; |
1132 | 1131 | ||
1133 | qlcnic_alloc_mbx_args(&cmd, adapter, | 1132 | qlcnic_alloc_mbx_args(&cmd, adapter, |
1134 | QLCNIC_CMD_GET_ESWITCH_PORT_CONFIG); | 1133 | QLCNIC_CMD_GET_ESWITCH_PORT_CONFIG); |
@@ -1139,12 +1138,11 @@ __qlcnic_get_eswitch_port_config(struct qlcnic_adapter *adapter, | |||
1139 | qlcnic_free_mbx_args(&cmd); | 1138 | qlcnic_free_mbx_args(&cmd); |
1140 | 1139 | ||
1141 | if (err == QLCNIC_RCODE_SUCCESS) | 1140 | if (err == QLCNIC_RCODE_SUCCESS) |
1142 | dev_info(&adapter->pdev->dev, | 1141 | dev_info(dev, "Get eSwitch port config for vNIC function %d\n", |
1143 | "eSwitch port config for pci func %d\n", pci_func); | 1142 | pci_func); |
1144 | else | 1143 | else |
1145 | dev_err(&adapter->pdev->dev, | 1144 | dev_err(dev, "Failed to get eswitch port config for vNIC function %d\n", |
1146 | "Failed to get eswitch port config for pci func %d\n", | 1145 | pci_func); |
1147 | pci_func); | ||
1148 | return err; | 1146 | return err; |
1149 | } | 1147 | } |
1150 | /* Configure eSwitch port | 1148 | /* Configure eSwitch port |
@@ -1157,9 +1155,10 @@ op_type = 1 for port vlan_id | |||
1157 | int qlcnic_config_switch_port(struct qlcnic_adapter *adapter, | 1155 | int qlcnic_config_switch_port(struct qlcnic_adapter *adapter, |
1158 | struct qlcnic_esw_func_cfg *esw_cfg) | 1156 | struct qlcnic_esw_func_cfg *esw_cfg) |
1159 | { | 1157 | { |
1158 | struct device *dev = &adapter->pdev->dev; | ||
1159 | struct qlcnic_cmd_args cmd; | ||
1160 | int err = -EIO, index; | 1160 | int err = -EIO, index; |
1161 | u32 arg1, arg2 = 0; | 1161 | u32 arg1, arg2 = 0; |
1162 | struct qlcnic_cmd_args cmd; | ||
1163 | u8 pci_func; | 1162 | u8 pci_func; |
1164 | 1163 | ||
1165 | if (adapter->ahw->op_mode != QLCNIC_MGMT_FUNC) | 1164 | if (adapter->ahw->op_mode != QLCNIC_MGMT_FUNC) |
@@ -1216,11 +1215,11 @@ int qlcnic_config_switch_port(struct qlcnic_adapter *adapter, | |||
1216 | qlcnic_free_mbx_args(&cmd); | 1215 | qlcnic_free_mbx_args(&cmd); |
1217 | 1216 | ||
1218 | if (err != QLCNIC_RCODE_SUCCESS) | 1217 | if (err != QLCNIC_RCODE_SUCCESS) |
1219 | dev_err(&adapter->pdev->dev, | 1218 | dev_err(dev, "Failed to configure eswitch for vNIC function %d\n", |
1220 | "Failed to configure eswitch pci func %d\n", pci_func); | 1219 | pci_func); |
1221 | else | 1220 | else |
1222 | dev_info(&adapter->pdev->dev, | 1221 | dev_info(dev, "Configured eSwitch for vNIC function %d\n", |
1223 | "Configured eSwitch for pci func %d\n", pci_func); | 1222 | pci_func); |
1224 | 1223 | ||
1225 | return err; | 1224 | return err; |
1226 | } | 1225 | } |
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c index 106a12f2a02f..218978db2963 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c | |||
@@ -1503,6 +1503,21 @@ int qlcnic_82xx_config_led(struct qlcnic_adapter *adapter, u32 state, u32 rate) | |||
1503 | return rv; | 1503 | return rv; |
1504 | } | 1504 | } |
1505 | 1505 | ||
1506 | int qlcnic_get_beacon_state(struct qlcnic_adapter *adapter, u8 *h_state) | ||
1507 | { | ||
1508 | struct qlcnic_cmd_args cmd; | ||
1509 | int err; | ||
1510 | |||
1511 | err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_GET_LED_STATUS); | ||
1512 | if (!err) { | ||
1513 | err = qlcnic_issue_cmd(adapter, &cmd); | ||
1514 | if (!err) | ||
1515 | *h_state = cmd.rsp.arg[1]; | ||
1516 | } | ||
1517 | qlcnic_free_mbx_args(&cmd); | ||
1518 | return err; | ||
1519 | } | ||
1520 | |||
1506 | void qlcnic_82xx_get_func_no(struct qlcnic_adapter *adapter) | 1521 | void qlcnic_82xx_get_func_no(struct qlcnic_adapter *adapter) |
1507 | { | 1522 | { |
1508 | void __iomem *msix_base_addr; | 1523 | void __iomem *msix_base_addr; |
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.h index b6818f4356b9..812fd07baef3 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.h +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.h | |||
@@ -87,6 +87,7 @@ enum qlcnic_regs { | |||
87 | #define QLCNIC_CMD_CONFIG_VPORT 0x32 | 87 | #define QLCNIC_CMD_CONFIG_VPORT 0x32 |
88 | #define QLCNIC_CMD_GET_MAC_STATS 0x37 | 88 | #define QLCNIC_CMD_GET_MAC_STATS 0x37 |
89 | #define QLCNIC_CMD_SET_DRV_VER 0x38 | 89 | #define QLCNIC_CMD_SET_DRV_VER 0x38 |
90 | #define QLCNIC_CMD_GET_LED_STATUS 0x3C | ||
90 | #define QLCNIC_CMD_CONFIGURE_RSS 0x41 | 91 | #define QLCNIC_CMD_CONFIGURE_RSS 0x41 |
91 | #define QLCNIC_CMD_CONFIG_INTR_COAL 0x43 | 92 | #define QLCNIC_CMD_CONFIG_INTR_COAL 0x43 |
92 | #define QLCNIC_CMD_CONFIGURE_LED 0x44 | 93 | #define QLCNIC_CMD_CONFIGURE_LED 0x44 |
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c index aeb26a850679..da82f2eb73b4 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c | |||
@@ -52,10 +52,6 @@ int qlcnic_load_fw_file; | |||
52 | MODULE_PARM_DESC(load_fw_file, "Load firmware from (0=flash, 1=file)"); | 52 | MODULE_PARM_DESC(load_fw_file, "Load firmware from (0=flash, 1=file)"); |
53 | module_param_named(load_fw_file, qlcnic_load_fw_file, int, 0444); | 53 | module_param_named(load_fw_file, qlcnic_load_fw_file, int, 0444); |
54 | 54 | ||
55 | int qlcnic_config_npars; | ||
56 | module_param(qlcnic_config_npars, int, 0444); | ||
57 | MODULE_PARM_DESC(qlcnic_config_npars, "Configure NPARs (0=disabled, 1=enabled)"); | ||
58 | |||
59 | static int qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent); | 55 | static int qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent); |
60 | static void qlcnic_remove(struct pci_dev *pdev); | 56 | static void qlcnic_remove(struct pci_dev *pdev); |
61 | static int qlcnic_open(struct net_device *netdev); | 57 | static int qlcnic_open(struct net_device *netdev); |
@@ -449,6 +445,7 @@ static const struct net_device_ops qlcnic_netdev_ops = { | |||
449 | .ndo_set_vf_tx_rate = qlcnic_sriov_set_vf_tx_rate, | 445 | .ndo_set_vf_tx_rate = qlcnic_sriov_set_vf_tx_rate, |
450 | .ndo_get_vf_config = qlcnic_sriov_get_vf_config, | 446 | .ndo_get_vf_config = qlcnic_sriov_get_vf_config, |
451 | .ndo_set_vf_vlan = qlcnic_sriov_set_vf_vlan, | 447 | .ndo_set_vf_vlan = qlcnic_sriov_set_vf_vlan, |
448 | .ndo_set_vf_spoofchk = qlcnic_sriov_set_vf_spoofchk, | ||
452 | #endif | 449 | #endif |
453 | }; | 450 | }; |
454 | 451 | ||
@@ -768,7 +765,7 @@ static int | |||
768 | qlcnic_set_function_modes(struct qlcnic_adapter *adapter) | 765 | qlcnic_set_function_modes(struct qlcnic_adapter *adapter) |
769 | { | 766 | { |
770 | u8 id; | 767 | u8 id; |
771 | int i, ret = 1; | 768 | int ret; |
772 | u32 data = QLCNIC_MGMT_FUNC; | 769 | u32 data = QLCNIC_MGMT_FUNC; |
773 | struct qlcnic_hardware_context *ahw = adapter->ahw; | 770 | struct qlcnic_hardware_context *ahw = adapter->ahw; |
774 | 771 | ||
@@ -776,20 +773,10 @@ qlcnic_set_function_modes(struct qlcnic_adapter *adapter) | |||
776 | if (ret) | 773 | if (ret) |
777 | goto err_lock; | 774 | goto err_lock; |
778 | 775 | ||
779 | if (qlcnic_config_npars) { | 776 | id = ahw->pci_func; |
780 | for (i = 0; i < ahw->act_pci_func; i++) { | 777 | data = QLC_SHARED_REG_RD32(adapter, QLCNIC_DRV_OP_MODE); |
781 | id = adapter->npars[i].pci_func; | 778 | data = (data & ~QLC_DEV_SET_DRV(0xf, id)) | |
782 | if (id == ahw->pci_func) | 779 | QLC_DEV_SET_DRV(QLCNIC_MGMT_FUNC, id); |
783 | continue; | ||
784 | data |= (qlcnic_config_npars & | ||
785 | QLC_DEV_SET_DRV(0xf, id)); | ||
786 | } | ||
787 | } else { | ||
788 | data = QLC_SHARED_REG_RD32(adapter, QLCNIC_DRV_OP_MODE); | ||
789 | data = (data & ~QLC_DEV_SET_DRV(0xf, ahw->pci_func)) | | ||
790 | (QLC_DEV_SET_DRV(QLCNIC_MGMT_FUNC, | ||
791 | ahw->pci_func)); | ||
792 | } | ||
793 | QLC_SHARED_REG_WR32(adapter, QLCNIC_DRV_OP_MODE, data); | 780 | QLC_SHARED_REG_WR32(adapter, QLCNIC_DRV_OP_MODE, data); |
794 | qlcnic_api_unlock(adapter); | 781 | qlcnic_api_unlock(adapter); |
795 | err_lock: | 782 | err_lock: |
@@ -875,6 +862,27 @@ static int qlcnic_setup_pci_map(struct pci_dev *pdev, | |||
875 | return 0; | 862 | return 0; |
876 | } | 863 | } |
877 | 864 | ||
865 | static inline bool qlcnic_validate_subsystem_id(struct qlcnic_adapter *adapter, | ||
866 | int index) | ||
867 | { | ||
868 | struct pci_dev *pdev = adapter->pdev; | ||
869 | unsigned short subsystem_vendor; | ||
870 | bool ret = true; | ||
871 | |||
872 | subsystem_vendor = pdev->subsystem_vendor; | ||
873 | |||
874 | if (pdev->device == PCI_DEVICE_ID_QLOGIC_QLE824X || | ||
875 | pdev->device == PCI_DEVICE_ID_QLOGIC_QLE834X) { | ||
876 | if (qlcnic_boards[index].sub_vendor == subsystem_vendor && | ||
877 | qlcnic_boards[index].sub_device == pdev->subsystem_device) | ||
878 | ret = true; | ||
879 | else | ||
880 | ret = false; | ||
881 | } | ||
882 | |||
883 | return ret; | ||
884 | } | ||
885 | |||
878 | static void qlcnic_get_board_name(struct qlcnic_adapter *adapter, char *name) | 886 | static void qlcnic_get_board_name(struct qlcnic_adapter *adapter, char *name) |
879 | { | 887 | { |
880 | struct pci_dev *pdev = adapter->pdev; | 888 | struct pci_dev *pdev = adapter->pdev; |
@@ -882,20 +890,18 @@ static void qlcnic_get_board_name(struct qlcnic_adapter *adapter, char *name) | |||
882 | 890 | ||
883 | for (i = 0; i < NUM_SUPPORTED_BOARDS; ++i) { | 891 | for (i = 0; i < NUM_SUPPORTED_BOARDS; ++i) { |
884 | if (qlcnic_boards[i].vendor == pdev->vendor && | 892 | if (qlcnic_boards[i].vendor == pdev->vendor && |
885 | qlcnic_boards[i].device == pdev->device && | 893 | qlcnic_boards[i].device == pdev->device && |
886 | qlcnic_boards[i].sub_vendor == pdev->subsystem_vendor && | 894 | qlcnic_validate_subsystem_id(adapter, i)) { |
887 | qlcnic_boards[i].sub_device == pdev->subsystem_device) { | 895 | found = 1; |
888 | sprintf(name, "%pM: %s" , | 896 | break; |
889 | adapter->mac_addr, | ||
890 | qlcnic_boards[i].short_name); | ||
891 | found = 1; | ||
892 | break; | ||
893 | } | 897 | } |
894 | |||
895 | } | 898 | } |
896 | 899 | ||
897 | if (!found) | 900 | if (!found) |
898 | sprintf(name, "%pM Gigabit Ethernet", adapter->mac_addr); | 901 | sprintf(name, "%pM Gigabit Ethernet", adapter->mac_addr); |
902 | else | ||
903 | sprintf(name, "%pM: %s" , adapter->mac_addr, | ||
904 | qlcnic_boards[i].short_name); | ||
899 | } | 905 | } |
900 | 906 | ||
901 | static void | 907 | static void |
@@ -1395,16 +1401,23 @@ qlcnic_request_irq(struct qlcnic_adapter *adapter) | |||
1395 | for (ring = 0; ring < num_sds_rings; ring++) { | 1401 | for (ring = 0; ring < num_sds_rings; ring++) { |
1396 | sds_ring = &recv_ctx->sds_rings[ring]; | 1402 | sds_ring = &recv_ctx->sds_rings[ring]; |
1397 | if (qlcnic_82xx_check(adapter) && | 1403 | if (qlcnic_82xx_check(adapter) && |
1398 | (ring == (num_sds_rings - 1))) | 1404 | (ring == (num_sds_rings - 1))) { |
1399 | snprintf(sds_ring->name, | 1405 | if (!(adapter->flags & |
1400 | sizeof(sds_ring->name), | 1406 | QLCNIC_MSIX_ENABLED)) |
1401 | "qlcnic-%s[Tx0+Rx%d]", | 1407 | snprintf(sds_ring->name, |
1402 | netdev->name, ring); | 1408 | sizeof(sds_ring->name), |
1403 | else | 1409 | "qlcnic"); |
1410 | else | ||
1411 | snprintf(sds_ring->name, | ||
1412 | sizeof(sds_ring->name), | ||
1413 | "%s-tx-0-rx-%d", | ||
1414 | netdev->name, ring); | ||
1415 | } else { | ||
1404 | snprintf(sds_ring->name, | 1416 | snprintf(sds_ring->name, |
1405 | sizeof(sds_ring->name), | 1417 | sizeof(sds_ring->name), |
1406 | "qlcnic-%s[Rx%d]", | 1418 | "%s-rx-%d", |
1407 | netdev->name, ring); | 1419 | netdev->name, ring); |
1420 | } | ||
1408 | err = request_irq(sds_ring->irq, handler, flags, | 1421 | err = request_irq(sds_ring->irq, handler, flags, |
1409 | sds_ring->name, sds_ring); | 1422 | sds_ring->name, sds_ring); |
1410 | if (err) | 1423 | if (err) |
@@ -1419,7 +1432,7 @@ qlcnic_request_irq(struct qlcnic_adapter *adapter) | |||
1419 | ring++) { | 1432 | ring++) { |
1420 | tx_ring = &adapter->tx_ring[ring]; | 1433 | tx_ring = &adapter->tx_ring[ring]; |
1421 | snprintf(tx_ring->name, sizeof(tx_ring->name), | 1434 | snprintf(tx_ring->name, sizeof(tx_ring->name), |
1422 | "qlcnic-%s[Tx%d]", netdev->name, ring); | 1435 | "%s-tx-%d", netdev->name, ring); |
1423 | err = request_irq(tx_ring->irq, handler, flags, | 1436 | err = request_irq(tx_ring->irq, handler, flags, |
1424 | tx_ring->name, tx_ring); | 1437 | tx_ring->name, tx_ring); |
1425 | if (err) | 1438 | if (err) |
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov.h index d85fbb57c25b..9176cb015732 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov.h +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov.h | |||
@@ -129,6 +129,7 @@ struct qlcnic_vport { | |||
129 | u8 vlan_mode; | 129 | u8 vlan_mode; |
130 | u16 vlan; | 130 | u16 vlan; |
131 | u8 qos; | 131 | u8 qos; |
132 | bool spoofchk; | ||
132 | u8 mac[6]; | 133 | u8 mac[6]; |
133 | }; | 134 | }; |
134 | 135 | ||
@@ -225,6 +226,7 @@ int qlcnic_sriov_set_vf_tx_rate(struct net_device *, int, int); | |||
225 | int qlcnic_sriov_get_vf_config(struct net_device *, int , | 226 | int qlcnic_sriov_get_vf_config(struct net_device *, int , |
226 | struct ifla_vf_info *); | 227 | struct ifla_vf_info *); |
227 | int qlcnic_sriov_set_vf_vlan(struct net_device *, int, u16, u8); | 228 | int qlcnic_sriov_set_vf_vlan(struct net_device *, int, u16, u8); |
229 | int qlcnic_sriov_set_vf_spoofchk(struct net_device *, int, bool); | ||
228 | #else | 230 | #else |
229 | static inline void qlcnic_sriov_pf_disable(struct qlcnic_adapter *adapter) {} | 231 | static inline void qlcnic_sriov_pf_disable(struct qlcnic_adapter *adapter) {} |
230 | static inline void qlcnic_sriov_pf_cleanup(struct qlcnic_adapter *adapter) {} | 232 | static inline void qlcnic_sriov_pf_cleanup(struct qlcnic_adapter *adapter) {} |
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c index 196b2d100407..bcd200eff981 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c | |||
@@ -35,6 +35,7 @@ static void qlcnic_sriov_vf_cancel_fw_work(struct qlcnic_adapter *); | |||
35 | static void qlcnic_sriov_cleanup_transaction(struct qlcnic_bc_trans *); | 35 | static void qlcnic_sriov_cleanup_transaction(struct qlcnic_bc_trans *); |
36 | static int qlcnic_sriov_vf_mbx_op(struct qlcnic_adapter *, | 36 | static int qlcnic_sriov_vf_mbx_op(struct qlcnic_adapter *, |
37 | struct qlcnic_cmd_args *); | 37 | struct qlcnic_cmd_args *); |
38 | static void qlcnic_sriov_process_bc_cmd(struct work_struct *); | ||
38 | 39 | ||
39 | static struct qlcnic_hardware_ops qlcnic_sriov_vf_hw_ops = { | 40 | static struct qlcnic_hardware_ops qlcnic_sriov_vf_hw_ops = { |
40 | .read_crb = qlcnic_83xx_read_crb, | 41 | .read_crb = qlcnic_83xx_read_crb, |
@@ -179,6 +180,8 @@ int qlcnic_sriov_init(struct qlcnic_adapter *adapter, int num_vfs) | |||
179 | spin_lock_init(&vf->rcv_pend.lock); | 180 | spin_lock_init(&vf->rcv_pend.lock); |
180 | init_completion(&vf->ch_free_cmpl); | 181 | init_completion(&vf->ch_free_cmpl); |
181 | 182 | ||
183 | INIT_WORK(&vf->trans_work, qlcnic_sriov_process_bc_cmd); | ||
184 | |||
182 | if (qlcnic_sriov_pf_check(adapter)) { | 185 | if (qlcnic_sriov_pf_check(adapter)) { |
183 | vp = kzalloc(sizeof(struct qlcnic_vport), GFP_KERNEL); | 186 | vp = kzalloc(sizeof(struct qlcnic_vport), GFP_KERNEL); |
184 | if (!vp) { | 187 | if (!vp) { |
@@ -187,6 +190,7 @@ int qlcnic_sriov_init(struct qlcnic_adapter *adapter, int num_vfs) | |||
187 | } | 190 | } |
188 | sriov->vf_info[i].vp = vp; | 191 | sriov->vf_info[i].vp = vp; |
189 | vp->max_tx_bw = MAX_BW; | 192 | vp->max_tx_bw = MAX_BW; |
193 | vp->spoofchk = true; | ||
190 | random_ether_addr(vp->mac); | 194 | random_ether_addr(vp->mac); |
191 | dev_info(&adapter->pdev->dev, | 195 | dev_info(&adapter->pdev->dev, |
192 | "MAC Address %pM is configured for VF %d\n", | 196 | "MAC Address %pM is configured for VF %d\n", |
@@ -652,6 +656,8 @@ int qlcnic_sriov_vf_init(struct qlcnic_adapter *adapter, int pci_using_dac) | |||
652 | if (qlcnic_read_mac_addr(adapter)) | 656 | if (qlcnic_read_mac_addr(adapter)) |
653 | dev_warn(&adapter->pdev->dev, "failed to read mac addr\n"); | 657 | dev_warn(&adapter->pdev->dev, "failed to read mac addr\n"); |
654 | 658 | ||
659 | INIT_DELAYED_WORK(&adapter->idc_aen_work, qlcnic_83xx_idc_aen_work); | ||
660 | |||
655 | clear_bit(__QLCNIC_RESETTING, &adapter->state); | 661 | clear_bit(__QLCNIC_RESETTING, &adapter->state); |
656 | return 0; | 662 | return 0; |
657 | } | 663 | } |
@@ -864,7 +870,6 @@ static void qlcnic_sriov_schedule_bc_cmd(struct qlcnic_sriov *sriov, | |||
864 | vf->adapter->need_fw_reset) | 870 | vf->adapter->need_fw_reset) |
865 | return; | 871 | return; |
866 | 872 | ||
867 | INIT_WORK(&vf->trans_work, func); | ||
868 | queue_work(sriov->bc.bc_trans_wq, &vf->trans_work); | 873 | queue_work(sriov->bc.bc_trans_wq, &vf->trans_work); |
869 | } | 874 | } |
870 | 875 | ||
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_pf.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_pf.c index 1a66ccded235..ee0c1d307966 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_pf.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_pf.c | |||
@@ -580,6 +580,7 @@ static int qlcnic_sriov_set_vf_acl(struct qlcnic_adapter *adapter, u8 func) | |||
580 | struct qlcnic_cmd_args cmd; | 580 | struct qlcnic_cmd_args cmd; |
581 | struct qlcnic_vport *vp; | 581 | struct qlcnic_vport *vp; |
582 | int err, id; | 582 | int err, id; |
583 | u8 *mac; | ||
583 | 584 | ||
584 | id = qlcnic_sriov_func_to_index(adapter, func); | 585 | id = qlcnic_sriov_func_to_index(adapter, func); |
585 | if (id < 0) | 586 | if (id < 0) |
@@ -591,6 +592,14 @@ static int qlcnic_sriov_set_vf_acl(struct qlcnic_adapter *adapter, u8 func) | |||
591 | return err; | 592 | return err; |
592 | 593 | ||
593 | cmd.req.arg[1] = 0x3 | func << 16; | 594 | cmd.req.arg[1] = 0x3 | func << 16; |
595 | if (vp->spoofchk == true) { | ||
596 | mac = vp->mac; | ||
597 | cmd.req.arg[2] |= BIT_1 | BIT_3 | BIT_8; | ||
598 | cmd.req.arg[4] = mac[5] | mac[4] << 8 | mac[3] << 16 | | ||
599 | mac[2] << 24; | ||
600 | cmd.req.arg[5] = mac[1] | mac[0] << 8; | ||
601 | } | ||
602 | |||
594 | if (vp->vlan_mode == QLC_PVID_MODE) { | 603 | if (vp->vlan_mode == QLC_PVID_MODE) { |
595 | cmd.req.arg[2] |= BIT_6; | 604 | cmd.req.arg[2] |= BIT_6; |
596 | cmd.req.arg[3] |= vp->vlan << 8; | 605 | cmd.req.arg[3] |= vp->vlan << 8; |
@@ -1767,6 +1776,7 @@ int qlcnic_sriov_get_vf_config(struct net_device *netdev, | |||
1767 | memcpy(&ivi->mac, vp->mac, ETH_ALEN); | 1776 | memcpy(&ivi->mac, vp->mac, ETH_ALEN); |
1768 | ivi->vlan = vp->vlan; | 1777 | ivi->vlan = vp->vlan; |
1769 | ivi->qos = vp->qos; | 1778 | ivi->qos = vp->qos; |
1779 | ivi->spoofchk = vp->spoofchk; | ||
1770 | if (vp->max_tx_bw == MAX_BW) | 1780 | if (vp->max_tx_bw == MAX_BW) |
1771 | ivi->tx_rate = 0; | 1781 | ivi->tx_rate = 0; |
1772 | else | 1782 | else |
@@ -1775,3 +1785,29 @@ int qlcnic_sriov_get_vf_config(struct net_device *netdev, | |||
1775 | ivi->vf = vf; | 1785 | ivi->vf = vf; |
1776 | return 0; | 1786 | return 0; |
1777 | } | 1787 | } |
1788 | |||
1789 | int qlcnic_sriov_set_vf_spoofchk(struct net_device *netdev, int vf, bool chk) | ||
1790 | { | ||
1791 | struct qlcnic_adapter *adapter = netdev_priv(netdev); | ||
1792 | struct qlcnic_sriov *sriov = adapter->ahw->sriov; | ||
1793 | struct qlcnic_vf_info *vf_info; | ||
1794 | struct qlcnic_vport *vp; | ||
1795 | |||
1796 | if (!qlcnic_sriov_pf_check(adapter)) | ||
1797 | return -EOPNOTSUPP; | ||
1798 | |||
1799 | if (vf >= sriov->num_vfs) | ||
1800 | return -EINVAL; | ||
1801 | |||
1802 | vf_info = &sriov->vf_info[vf]; | ||
1803 | vp = vf_info->vp; | ||
1804 | if (test_bit(QLC_BC_VF_STATE, &vf_info->state)) { | ||
1805 | netdev_err(netdev, | ||
1806 | "Spoof check change failed for VF %d, as VF driver is loaded. Please unload VF driver and retry the operation\n", | ||
1807 | vf); | ||
1808 | return -EOPNOTSUPP; | ||
1809 | } | ||
1810 | |||
1811 | vp->spoofchk = chk; | ||
1812 | return 0; | ||
1813 | } | ||
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c index e7a2fe21b649..025a7192289d 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c | |||
@@ -114,57 +114,51 @@ static int qlcnic_validate_beacon(struct qlcnic_adapter *adapter, u16 beacon, | |||
114 | return 0; | 114 | return 0; |
115 | } | 115 | } |
116 | 116 | ||
117 | static ssize_t qlcnic_store_beacon(struct device *dev, | 117 | static int qlcnic_83xx_store_beacon(struct qlcnic_adapter *adapter, |
118 | struct device_attribute *attr, | 118 | const char *buf, size_t len) |
119 | const char *buf, size_t len) | ||
120 | { | 119 | { |
121 | struct qlcnic_adapter *adapter = dev_get_drvdata(dev); | ||
122 | struct qlcnic_hardware_context *ahw = adapter->ahw; | 120 | struct qlcnic_hardware_context *ahw = adapter->ahw; |
123 | int err, max_sds_rings = adapter->max_sds_rings; | ||
124 | u16 beacon; | ||
125 | u8 b_state, b_rate; | ||
126 | unsigned long h_beacon; | 121 | unsigned long h_beacon; |
122 | int err; | ||
127 | 123 | ||
128 | if (adapter->ahw->op_mode == QLCNIC_NON_PRIV_FUNC) { | 124 | if (test_bit(__QLCNIC_RESETTING, &adapter->state)) |
129 | dev_warn(dev, | 125 | return -EIO; |
130 | "LED test not supported in non privileged mode\n"); | ||
131 | return -EOPNOTSUPP; | ||
132 | } | ||
133 | 126 | ||
134 | if (qlcnic_83xx_check(adapter) && | 127 | if (kstrtoul(buf, 2, &h_beacon)) |
135 | !test_bit(__QLCNIC_RESETTING, &adapter->state)) { | 128 | return -EINVAL; |
136 | if (kstrtoul(buf, 2, &h_beacon)) | ||
137 | return -EINVAL; | ||
138 | 129 | ||
139 | if (ahw->beacon_state == h_beacon) | 130 | if (ahw->beacon_state == h_beacon) |
140 | return len; | 131 | return len; |
141 | 132 | ||
142 | rtnl_lock(); | 133 | rtnl_lock(); |
143 | if (!ahw->beacon_state) { | 134 | if (!ahw->beacon_state) { |
144 | if (test_and_set_bit(__QLCNIC_LED_ENABLE, | 135 | if (test_and_set_bit(__QLCNIC_LED_ENABLE, &adapter->state)) { |
145 | &adapter->state)) { | 136 | rtnl_unlock(); |
146 | rtnl_unlock(); | 137 | return -EBUSY; |
147 | return -EBUSY; | ||
148 | } | ||
149 | } | ||
150 | if (h_beacon) { | ||
151 | err = qlcnic_83xx_config_led(adapter, 1, h_beacon); | ||
152 | if (err) | ||
153 | goto beacon_err; | ||
154 | } else { | ||
155 | err = qlcnic_83xx_config_led(adapter, 0, !h_beacon); | ||
156 | if (err) | ||
157 | goto beacon_err; | ||
158 | } | 138 | } |
159 | /* set the current beacon state */ | 139 | } |
140 | |||
141 | if (h_beacon) | ||
142 | err = qlcnic_83xx_config_led(adapter, 1, h_beacon); | ||
143 | else | ||
144 | err = qlcnic_83xx_config_led(adapter, 0, !h_beacon); | ||
145 | if (!err) | ||
160 | ahw->beacon_state = h_beacon; | 146 | ahw->beacon_state = h_beacon; |
161 | beacon_err: | ||
162 | if (!ahw->beacon_state) | ||
163 | clear_bit(__QLCNIC_LED_ENABLE, &adapter->state); | ||
164 | 147 | ||
165 | rtnl_unlock(); | 148 | if (!ahw->beacon_state) |
166 | return len; | 149 | clear_bit(__QLCNIC_LED_ENABLE, &adapter->state); |
167 | } | 150 | |
151 | rtnl_unlock(); | ||
152 | return len; | ||
153 | } | ||
154 | |||
155 | static int qlcnic_82xx_store_beacon(struct qlcnic_adapter *adapter, | ||
156 | const char *buf, size_t len) | ||
157 | { | ||
158 | struct qlcnic_hardware_context *ahw = adapter->ahw; | ||
159 | int err, max_sds_rings = adapter->max_sds_rings; | ||
160 | u16 beacon; | ||
161 | u8 h_beacon_state, b_state, b_rate; | ||
168 | 162 | ||
169 | if (len != sizeof(u16)) | 163 | if (len != sizeof(u16)) |
170 | return QL_STATUS_INVALID_PARAM; | 164 | return QL_STATUS_INVALID_PARAM; |
@@ -174,16 +168,29 @@ beacon_err: | |||
174 | if (err) | 168 | if (err) |
175 | return err; | 169 | return err; |
176 | 170 | ||
177 | if (adapter->ahw->beacon_state == b_state) | 171 | if ((ahw->capabilities2 & QLCNIC_FW_CAPABILITY_2_BEACON)) { |
172 | err = qlcnic_get_beacon_state(adapter, &h_beacon_state); | ||
173 | if (!err) { | ||
174 | dev_info(&adapter->pdev->dev, | ||
175 | "Failed to get current beacon state\n"); | ||
176 | } else { | ||
177 | if (h_beacon_state == QLCNIC_BEACON_DISABLE) | ||
178 | ahw->beacon_state = 0; | ||
179 | else if (h_beacon_state == QLCNIC_BEACON_EANBLE) | ||
180 | ahw->beacon_state = 2; | ||
181 | } | ||
182 | } | ||
183 | |||
184 | if (ahw->beacon_state == b_state) | ||
178 | return len; | 185 | return len; |
179 | 186 | ||
180 | rtnl_lock(); | 187 | rtnl_lock(); |
181 | 188 | if (!ahw->beacon_state) { | |
182 | if (!adapter->ahw->beacon_state) | ||
183 | if (test_and_set_bit(__QLCNIC_LED_ENABLE, &adapter->state)) { | 189 | if (test_and_set_bit(__QLCNIC_LED_ENABLE, &adapter->state)) { |
184 | rtnl_unlock(); | 190 | rtnl_unlock(); |
185 | return -EBUSY; | 191 | return -EBUSY; |
186 | } | 192 | } |
193 | } | ||
187 | 194 | ||
188 | if (test_bit(__QLCNIC_RESETTING, &adapter->state)) { | 195 | if (test_bit(__QLCNIC_RESETTING, &adapter->state)) { |
189 | err = -EIO; | 196 | err = -EIO; |
@@ -206,14 +213,37 @@ beacon_err: | |||
206 | if (test_and_clear_bit(__QLCNIC_DIAG_RES_ALLOC, &adapter->state)) | 213 | if (test_and_clear_bit(__QLCNIC_DIAG_RES_ALLOC, &adapter->state)) |
207 | qlcnic_diag_free_res(adapter->netdev, max_sds_rings); | 214 | qlcnic_diag_free_res(adapter->netdev, max_sds_rings); |
208 | 215 | ||
209 | out: | 216 | out: |
210 | if (!adapter->ahw->beacon_state) | 217 | if (!ahw->beacon_state) |
211 | clear_bit(__QLCNIC_LED_ENABLE, &adapter->state); | 218 | clear_bit(__QLCNIC_LED_ENABLE, &adapter->state); |
212 | rtnl_unlock(); | 219 | rtnl_unlock(); |
213 | 220 | ||
214 | return err; | 221 | return err; |
215 | } | 222 | } |
216 | 223 | ||
224 | static ssize_t qlcnic_store_beacon(struct device *dev, | ||
225 | struct device_attribute *attr, | ||
226 | const char *buf, size_t len) | ||
227 | { | ||
228 | struct qlcnic_adapter *adapter = dev_get_drvdata(dev); | ||
229 | int err = 0; | ||
230 | |||
231 | if (adapter->ahw->op_mode == QLCNIC_NON_PRIV_FUNC) { | ||
232 | dev_warn(dev, | ||
233 | "LED test not supported in non privileged mode\n"); | ||
234 | return -EOPNOTSUPP; | ||
235 | } | ||
236 | |||
237 | if (qlcnic_82xx_check(adapter)) | ||
238 | err = qlcnic_82xx_store_beacon(adapter, buf, len); | ||
239 | else if (qlcnic_83xx_check(adapter)) | ||
240 | err = qlcnic_83xx_store_beacon(adapter, buf, len); | ||
241 | else | ||
242 | return -EIO; | ||
243 | |||
244 | return err; | ||
245 | } | ||
246 | |||
217 | static ssize_t qlcnic_show_beacon(struct device *dev, | 247 | static ssize_t qlcnic_show_beacon(struct device *dev, |
218 | struct device_attribute *attr, char *buf) | 248 | struct device_attribute *attr, char *buf) |
219 | { | 249 | { |