]> Pileus Git - ~andy/linux/blobdiff - drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
qlcnic: Add identifying string for 83xx adapter
[~andy/linux] / drivers / net / ethernet / qlogic / qlcnic / qlcnic_main.c
index 3ee593ee13cf18da1a0fb52fddd66430ec92e1aa..264d5a4f81538a23653c370a7d85df18617c09be 100644 (file)
@@ -86,8 +86,8 @@ static void qlcnic_dev_set_npar_ready(struct qlcnic_adapter *);
 static int qlcnicvf_start_firmware(struct qlcnic_adapter *);
 static void qlcnic_set_netdev_features(struct qlcnic_adapter *,
                                struct qlcnic_esw_func_cfg *);
-static int qlcnic_vlan_rx_add(struct net_device *, u16);
-static int qlcnic_vlan_rx_del(struct net_device *, u16);
+static int qlcnic_vlan_rx_add(struct net_device *, __be16, u16);
+static int qlcnic_vlan_rx_del(struct net_device *, __be16, u16);
 
 #define QLCNIC_IS_TSO_CAPABLE(adapter) \
        ((adapter)->ahw->capabilities & QLCNIC_FW_CAPABILITY_TSO)
@@ -156,25 +156,112 @@ static const u32 qlcnic_reg_tbl[] = {
 };
 
 static const struct qlcnic_board_info qlcnic_boards[] = {
-       {0x1077, 0x8020, 0x1077, 0x203,
-        "8200 Series Single Port 10GbE Converged Network Adapter"
-        "(TCP/IP Networking)"},
-       {0x1077, 0x8020, 0x1077, 0x207,
-        "8200 Series Dual Port 10GbE Converged Network Adapter"
-        "(TCP/IP Networking)"},
-       {0x1077, 0x8020, 0x1077, 0x20b,
-        "3200 Series Dual Port 10Gb Intelligent Ethernet Adapter"},
-       {0x1077, 0x8020, 0x1077, 0x20c,
-        "3200 Series Quad Port 1Gb Intelligent Ethernet Adapter"},
-       {0x1077, 0x8020, 0x1077, 0x20f,
-        "3200 Series Single Port 10Gb Intelligent Ethernet Adapter"},
-       {0x1077, 0x8020, 0x103c, 0x3733,
-        "NC523SFP 10Gb 2-port Server Adapter"},
-       {0x1077, 0x8020, 0x103c, 0x3346,
-        "CN1000Q Dual Port Converged Network Adapter"},
-       {0x1077, 0x8020, 0x1077, 0x210,
-        "QME8242-k 10GbE Dual Port Mezzanine Card"},
-       {0x1077, 0x8020, 0x0, 0x0, "cLOM8214 1/10GbE Controller"},
+       { PCI_VENDOR_ID_QLOGIC,
+         PCI_DEVICE_ID_QLOGIC_QLE834X,
+         PCI_VENDOR_ID_QLOGIC,
+         0x24e,
+         "8300 Series Dual Port 10GbE Converged Network Adapter "
+         "(TCP/IP Networking)" },
+       { PCI_VENDOR_ID_QLOGIC,
+         PCI_DEVICE_ID_QLOGIC_QLE834X,
+         PCI_VENDOR_ID_QLOGIC,
+         0x243,
+         "8300 Series Single Port 10GbE Converged Network Adapter "
+         "(TCP/IP Networking)" },
+       { PCI_VENDOR_ID_QLOGIC,
+         PCI_DEVICE_ID_QLOGIC_QLE834X,
+         PCI_VENDOR_ID_QLOGIC,
+         0x24a,
+         "8300 Series Dual Port 10GbE Converged Network Adapter "
+         "(TCP/IP Networking)" },
+       { PCI_VENDOR_ID_QLOGIC,
+         PCI_DEVICE_ID_QLOGIC_QLE834X,
+         PCI_VENDOR_ID_QLOGIC,
+         0x246,
+         "8300 Series Dual Port 10GbE Converged Network Adapter "
+         "(TCP/IP Networking)" },
+       { PCI_VENDOR_ID_QLOGIC,
+         PCI_DEVICE_ID_QLOGIC_QLE834X,
+         PCI_VENDOR_ID_QLOGIC,
+         0x252,
+         "8300 Series Dual Port 10GbE Converged Network Adapter "
+         "(TCP/IP Networking)" },
+       { PCI_VENDOR_ID_QLOGIC,
+         PCI_DEVICE_ID_QLOGIC_QLE834X,
+         PCI_VENDOR_ID_QLOGIC,
+         0x26e,
+         "8300 Series Dual Port 10GbE Converged Network Adapter "
+         "(TCP/IP Networking)" },
+       { PCI_VENDOR_ID_QLOGIC,
+         PCI_DEVICE_ID_QLOGIC_QLE834X,
+         PCI_VENDOR_ID_QLOGIC,
+         0x260,
+         "8300 Series Dual Port 10GbE Converged Network Adapter "
+         "(TCP/IP Networking)" },
+       { PCI_VENDOR_ID_QLOGIC,
+         PCI_DEVICE_ID_QLOGIC_QLE834X,
+         PCI_VENDOR_ID_QLOGIC,
+         0x266,
+         "8300 Series Single Port 10GbE Converged Network Adapter "
+         "(TCP/IP Networking)" },
+       { PCI_VENDOR_ID_QLOGIC,
+         PCI_DEVICE_ID_QLOGIC_QLE834X,
+         PCI_VENDOR_ID_QLOGIC,
+         0x269,
+         "8300 Series Dual Port 10GbE Converged Network Adapter "
+         "(TCP/IP Networking)" },
+       { PCI_VENDOR_ID_QLOGIC,
+         PCI_DEVICE_ID_QLOGIC_QLE834X,
+         PCI_VENDOR_ID_QLOGIC,
+         0x271,
+         "8300 Series Dual Port 10GbE Converged Network Adapter "
+         "(TCP/IP Networking)" },
+       { PCI_VENDOR_ID_QLOGIC,
+         PCI_DEVICE_ID_QLOGIC_QLE834X,
+         0x0, 0x0, "8300 Series 1/10GbE Controller" },
+       { PCI_VENDOR_ID_QLOGIC,
+         PCI_DEVICE_ID_QLOGIC_QLE824X,
+         PCI_VENDOR_ID_QLOGIC,
+         0x203,
+         "8200 Series Single Port 10GbE Converged Network Adapter"
+         "(TCP/IP Networking)" },
+       { PCI_VENDOR_ID_QLOGIC,
+         PCI_DEVICE_ID_QLOGIC_QLE824X,
+         PCI_VENDOR_ID_QLOGIC,
+         0x207,
+         "8200 Series Dual Port 10GbE Converged Network Adapter"
+         "(TCP/IP Networking)" },
+       { PCI_VENDOR_ID_QLOGIC,
+         PCI_DEVICE_ID_QLOGIC_QLE824X,
+         PCI_VENDOR_ID_QLOGIC,
+         0x20b,
+         "3200 Series Dual Port 10Gb Intelligent Ethernet Adapter" },
+       { PCI_VENDOR_ID_QLOGIC,
+         PCI_DEVICE_ID_QLOGIC_QLE824X,
+         PCI_VENDOR_ID_QLOGIC,
+         0x20c,
+         "3200 Series Quad Port 1Gb Intelligent Ethernet Adapter" },
+       { PCI_VENDOR_ID_QLOGIC,
+         PCI_DEVICE_ID_QLOGIC_QLE824X,
+         PCI_VENDOR_ID_QLOGIC,
+         0x20f,
+         "3200 Series Single Port 10Gb Intelligent Ethernet Adapter" },
+       { PCI_VENDOR_ID_QLOGIC,
+         PCI_DEVICE_ID_QLOGIC_QLE824X,
+         0x103c, 0x3733,
+         "NC523SFP 10Gb 2-port Server Adapter" },
+       { PCI_VENDOR_ID_QLOGIC,
+         PCI_DEVICE_ID_QLOGIC_QLE824X,
+         0x103c, 0x3346,
+         "CN1000Q Dual Port Converged Network Adapter" },
+       { PCI_VENDOR_ID_QLOGIC,
+         PCI_DEVICE_ID_QLOGIC_QLE824X,
+         PCI_VENDOR_ID_QLOGIC,
+         0x210,
+         "QME8242-k 10GbE Dual Port Mezzanine Card" },
+       { PCI_VENDOR_ID_QLOGIC,
+         PCI_DEVICE_ID_QLOGIC_QLE824X,
+         0x0, 0x0, "cLOM8214 1/10GbE Controller" },
 };
 
 #define NUM_SUPPORTED_BOARDS ARRAY_SIZE(qlcnic_boards)
@@ -290,7 +377,7 @@ static int qlcnic_fdb_add(struct ndmsg *ndm, struct nlattr *tb[],
                return err;
 
        if (is_unicast_ether_addr(addr))
-               err = qlcnic_nic_add_mac(adapter, addr);
+               err = qlcnic_nic_add_mac(adapter, addr, 0);
        else if (is_multicast_ether_addr(addr))
                err = dev_mc_add_excl(netdev, addr);
        else
@@ -341,6 +428,12 @@ static const struct net_device_ops qlcnic_netdev_ops = {
 #ifdef CONFIG_NET_POLL_CONTROLLER
        .ndo_poll_controller = qlcnic_poll_controller,
 #endif
+#ifdef CONFIG_QLCNIC_SRIOV
+       .ndo_set_vf_mac         = qlcnic_sriov_set_vf_mac,
+       .ndo_set_vf_tx_rate     = qlcnic_sriov_set_vf_tx_rate,
+       .ndo_get_vf_config      = qlcnic_sriov_get_vf_config,
+       .ndo_set_vf_vlan        = qlcnic_sriov_set_vf_vlan,
+#endif
 };
 
 static const struct net_device_ops qlcnic_netdev_failed_ops = {
@@ -399,6 +492,7 @@ static struct qlcnic_hardware_ops qlcnic_hw_ops = {
        .config_promisc_mode            = qlcnic_82xx_nic_set_promisc,
        .change_l2_filter               = qlcnic_82xx_change_filter,
        .get_board_info                 = qlcnic_82xx_get_board_info,
+       .free_mac_list                  = qlcnic_82xx_free_mac_list,
 };
 
 int qlcnic_enable_msix(struct qlcnic_adapter *adapter, u32 num_msix)
@@ -546,11 +640,10 @@ void qlcnic_teardown_intr(struct qlcnic_adapter *adapter)
        }
 }
 
-static void
-qlcnic_cleanup_pci_map(struct qlcnic_adapter *adapter)
+static void qlcnic_cleanup_pci_map(struct qlcnic_hardware_context *ahw)
 {
-       if (adapter->ahw->pci_base0 != NULL)
-               iounmap(adapter->ahw->pci_base0);
+       if (ahw->pci_base0 != NULL)
+               iounmap(ahw->pci_base0);
 }
 
 static int qlcnic_get_act_pci_func(struct qlcnic_adapter *adapter)
@@ -896,24 +989,50 @@ void qlcnic_set_vlan_config(struct qlcnic_adapter *adapter,
        else
                adapter->flags |= QLCNIC_TAGGING_ENABLED;
 
-       if (esw_cfg->vlan_id)
-               adapter->pvid = esw_cfg->vlan_id;
-       else
-               adapter->pvid = 0;
+       if (esw_cfg->vlan_id) {
+               adapter->rx_pvid = esw_cfg->vlan_id;
+               adapter->tx_pvid = esw_cfg->vlan_id;
+       } else {
+               adapter->rx_pvid = 0;
+               adapter->tx_pvid = 0;
+       }
 }
 
 static int
-qlcnic_vlan_rx_add(struct net_device *netdev, u16 vid)
+qlcnic_vlan_rx_add(struct net_device *netdev, __be16 proto, u16 vid)
 {
        struct qlcnic_adapter *adapter = netdev_priv(netdev);
+       int err;
+
+       if (qlcnic_sriov_vf_check(adapter)) {
+               err = qlcnic_sriov_cfg_vf_guest_vlan(adapter, vid, 1);
+               if (err) {
+                       netdev_err(netdev,
+                                  "Cannot add VLAN filter for VLAN id %d, err=%d",
+                                  vid, err);
+                       return err;
+               }
+       }
+
        set_bit(vid, adapter->vlans);
        return 0;
 }
 
 static int
-qlcnic_vlan_rx_del(struct net_device *netdev, u16 vid)
+qlcnic_vlan_rx_del(struct net_device *netdev, __be16 proto, u16 vid)
 {
        struct qlcnic_adapter *adapter = netdev_priv(netdev);
+       int err;
+
+       if (qlcnic_sriov_vf_check(adapter)) {
+               err = qlcnic_sriov_cfg_vf_guest_vlan(adapter, vid, 0);
+               if (err) {
+                       netdev_err(netdev,
+                                  "Cannot delete VLAN filter for VLAN id %d, err=%d",
+                                  vid, err);
+                       return err;
+               }
+       }
 
        qlcnic_restore_indev_addr(netdev, NETDEV_DOWN);
        clear_bit(vid, adapter->vlans);
@@ -1255,7 +1374,7 @@ qlcnic_request_irq(struct qlcnic_adapter *adapter)
        irq_handler_t handler;
        struct qlcnic_host_sds_ring *sds_ring;
        struct qlcnic_host_tx_ring *tx_ring;
-       int err, ring;
+       int err, ring, num_sds_rings;
 
        unsigned long flags = 0;
        struct net_device *netdev = adapter->netdev;
@@ -1286,10 +1405,20 @@ qlcnic_request_irq(struct qlcnic_adapter *adapter)
                if (qlcnic_82xx_check(adapter) ||
                    (qlcnic_83xx_check(adapter) &&
                     (adapter->flags & QLCNIC_MSIX_ENABLED))) {
-                       for (ring = 0; ring < adapter->max_sds_rings; ring++) {
+                       num_sds_rings = adapter->max_sds_rings;
+                       for (ring = 0; ring < num_sds_rings; ring++) {
                                sds_ring = &recv_ctx->sds_rings[ring];
-                               snprintf(sds_ring->name, sizeof(int) + IFNAMSIZ,
-                                        "%s[%d]", netdev->name, ring);
+                               if (qlcnic_82xx_check(adapter) &&
+                                   (ring == (num_sds_rings - 1)))
+                                       snprintf(sds_ring->name,
+                                                sizeof(sds_ring->name),
+                                                "qlcnic-%s[Tx0+Rx%d]",
+                                                netdev->name, ring);
+                               else
+                                       snprintf(sds_ring->name,
+                                                sizeof(sds_ring->name),
+                                                "qlcnic-%s[Rx%d]",
+                                                netdev->name, ring);
                                err = request_irq(sds_ring->irq, handler, flags,
                                                  sds_ring->name, sds_ring);
                                if (err)
@@ -1303,9 +1432,8 @@ qlcnic_request_irq(struct qlcnic_adapter *adapter)
                        for (ring = 0; ring < adapter->max_drv_tx_rings;
                             ring++) {
                                tx_ring = &adapter->tx_ring[ring];
-                               snprintf(tx_ring->name, sizeof(int) + IFNAMSIZ,
-                                        "%s[%d]", netdev->name,
-                                        adapter->max_sds_rings + ring);
+                               snprintf(tx_ring->name, sizeof(tx_ring->name),
+                                        "qlcnic-%s[Tx%d]", netdev->name, ring);
                                err = request_irq(tx_ring->irq, handler, flags,
                                                  tx_ring->name, tx_ring);
                                if (err)
@@ -1555,7 +1683,9 @@ out:
 
 static int qlcnic_alloc_adapter_resources(struct qlcnic_adapter *adapter)
 {
+       struct qlcnic_hardware_context *ahw = adapter->ahw;
        int err = 0;
+
        adapter->recv_ctx = kzalloc(sizeof(struct qlcnic_recv_context),
                                GFP_KERNEL);
        if (!adapter->recv_ctx) {
@@ -1563,9 +1693,14 @@ static int qlcnic_alloc_adapter_resources(struct qlcnic_adapter *adapter)
                goto err_out;
        }
        /* Initialize interrupt coalesce parameters */
-       adapter->ahw->coal.flag = QLCNIC_INTR_DEFAULT;
-       adapter->ahw->coal.rx_time_us = QLCNIC_DEFAULT_INTR_COALESCE_RX_TIME_US;
-       adapter->ahw->coal.rx_packets = QLCNIC_DEFAULT_INTR_COALESCE_RX_PACKETS;
+       ahw->coal.flag = QLCNIC_INTR_DEFAULT;
+       ahw->coal.type = QLCNIC_INTR_COAL_TYPE_RX;
+       ahw->coal.rx_time_us = QLCNIC_DEF_INTR_COALESCE_RX_TIME_US;
+       ahw->coal.rx_packets = QLCNIC_DEF_INTR_COALESCE_RX_PACKETS;
+       if (qlcnic_83xx_check(adapter)) {
+               ahw->coal.tx_time_us = QLCNIC_DEF_INTR_COALESCE_TX_TIME_US;
+               ahw->coal.tx_packets = QLCNIC_DEF_INTR_COALESCE_TX_PACKETS;
+       }
        /* clear stats */
        memset(&adapter->stats, 0, sizeof(adapter->stats));
 err_out:
@@ -1711,11 +1846,14 @@ qlcnic_setup_netdev(struct qlcnic_adapter *adapter, struct net_device *netdev,
 
        qlcnic_change_mtu(netdev, netdev->mtu);
 
-       SET_ETHTOOL_OPS(netdev, &qlcnic_ethtool_ops);
+       if (qlcnic_sriov_vf_check(adapter))
+               SET_ETHTOOL_OPS(netdev, &qlcnic_sriov_vf_ethtool_ops);
+       else
+               SET_ETHTOOL_OPS(netdev, &qlcnic_ethtool_ops);
 
        netdev->features |= (NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_RXCSUM |
                             NETIF_F_IPV6_CSUM | NETIF_F_GRO |
-                            NETIF_F_HW_VLAN_RX);
+                            NETIF_F_HW_VLAN_CTAG_RX);
        netdev->vlan_features |= (NETIF_F_SG | NETIF_F_IP_CSUM |
                                  NETIF_F_IPV6_CSUM);
 
@@ -1730,7 +1868,10 @@ qlcnic_setup_netdev(struct qlcnic_adapter *adapter, struct net_device *netdev,
        }
 
        if (qlcnic_vlan_tx_check(adapter))
-               netdev->features |= (NETIF_F_HW_VLAN_TX);
+               netdev->features |= (NETIF_F_HW_VLAN_CTAG_TX);
+
+       if (qlcnic_sriov_vf_check(adapter))
+               netdev->features |= NETIF_F_HW_VLAN_CTAG_FILTER;
 
        if (adapter->ahw->capabilities & QLCNIC_FW_CAPABILITY_HW_LRO)
                netdev->features |= NETIF_F_LRO;
@@ -2026,7 +2167,7 @@ err_out_free_netdev:
        free_netdev(netdev);
 
 err_out_iounmap:
-       qlcnic_cleanup_pci_map(adapter);
+       qlcnic_cleanup_pci_map(ahw);
 
 err_out_free_hw_res:
        kfree(ahw);
@@ -2083,7 +2224,7 @@ static void qlcnic_remove(struct pci_dev *pdev)
 
        qlcnic_remove_sysfs(adapter);
 
-       qlcnic_cleanup_pci_map(adapter);
+       qlcnic_cleanup_pci_map(adapter->ahw);
 
        qlcnic_release_firmware(adapter);
 
@@ -2113,6 +2254,7 @@ static int __qlcnic_shutdown(struct pci_dev *pdev)
        if (netif_running(netdev))
                qlcnic_down(adapter, netdev);
 
+       qlcnic_sriov_cleanup(adapter);
        if (qlcnic_82xx_check(adapter))
                qlcnic_clr_all_drv_state(adapter, 0);
 
@@ -3234,20 +3376,40 @@ qlcnicvf_start_firmware(struct qlcnic_adapter *adapter)
        return err;
 }
 
-int qlcnic_validate_max_rss(u8 max_hw, u8 val)
+int qlcnic_validate_max_rss(struct qlcnic_adapter *adapter,
+                           __u32 val)
 {
+       struct net_device *netdev = adapter->netdev;
+       u8 max_hw = adapter->ahw->max_rx_ques;
        u32 max_allowed;
 
-       if (max_hw > QLC_MAX_SDS_RINGS) {
-               max_hw = QLC_MAX_SDS_RINGS;
-               pr_info("max rss reset to %d\n", QLC_MAX_SDS_RINGS);
+       if (val > QLC_MAX_SDS_RINGS) {
+               netdev_err(netdev, "RSS value should not be higher than %u\n",
+                          QLC_MAX_SDS_RINGS);
+               return -EINVAL;
        }
 
        max_allowed = rounddown_pow_of_two(min_t(int, max_hw,
                                                 num_online_cpus()));
        if ((val > max_allowed) || (val < 2) || !is_power_of_2(val)) {
-               pr_info("rss_ring valid range [2 - %x] in powers of 2\n",
-                       max_allowed);
+               if (!is_power_of_2(val))
+                       netdev_err(netdev, "RSS value should be a power of 2\n");
+
+               if (val < 2)
+                       netdev_err(netdev, "RSS value should not be lower than 2\n");
+
+               if (val > max_hw)
+                       netdev_err(netdev,
+                                  "RSS value should not be higher than[%u], the max RSS rings supported by the adapter\n",
+                                  max_hw);
+
+               if (val > num_online_cpus())
+                       netdev_err(netdev,
+                                  "RSS value should not be higher than[%u], number of online CPUs in the system\n",
+                                  num_online_cpus());
+
+               netdev_err(netdev, "Unable to configure %u RSS rings\n", val);
+
                return -EINVAL;
        }
        return 0;
@@ -3267,8 +3429,10 @@ int qlcnic_set_max_rss(struct qlcnic_adapter *adapter, u8 data, size_t len)
 
        qlcnic_detach(adapter);
 
-       if (qlcnic_83xx_check(adapter))
+       if (qlcnic_83xx_check(adapter)) {
                qlcnic_83xx_free_mbx_intr(adapter);
+               qlcnic_83xx_enable_mbx_poll(adapter);
+       }
 
        qlcnic_teardown_intr(adapter);
        err = qlcnic_setup_intr(adapter, data);
@@ -3282,6 +3446,7 @@ int qlcnic_set_max_rss(struct qlcnic_adapter *adapter, u8 data, size_t len)
                /* register for NIC IDC AEN Events */
                qlcnic_83xx_register_nic_idc_func(adapter, 1);
                err = qlcnic_83xx_setup_mbx_intr(adapter);
+               qlcnic_83xx_disable_mbx_poll(adapter);
                if (err) {
                        dev_err(&adapter->pdev->dev,
                                "failed to setup mbx interrupt\n");
@@ -3347,7 +3512,7 @@ void qlcnic_restore_indev_addr(struct net_device *netdev, unsigned long event)
 
        rcu_read_lock();
        for_each_set_bit(vid, adapter->vlans, VLAN_N_VID) {
-               dev = __vlan_find_dev_deep(netdev, vid);
+               dev = __vlan_find_dev_deep(netdev, htons(ETH_P_8021Q), vid);
                if (!dev)
                        continue;
                qlcnic_config_indev_addr(adapter, dev, event);