Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
[firefly-linux-kernel-4.4.55.git] / drivers / net / ethernet / emulex / benet / be_main.c
index fdb50cec6b515aa50271b079ea62f73e1755c582..5a34503b6a149db6a6711007e2fe216f9dac810a 100644 (file)
@@ -719,8 +719,8 @@ static netdev_tx_t be_xmit(struct sk_buff *skb,
         * 60 bytes long.
         * As a workaround disable TX vlan offloading in such cases.
         */
-       if (unlikely(vlan_tx_tag_present(skb) &&
-                    (skb->ip_summed != CHECKSUM_PARTIAL || skb->len <= 60))) {
+       if (vlan_tx_tag_present(skb) &&
+           (skb->ip_summed != CHECKSUM_PARTIAL || skb->len <= 60)) {
                skb = skb_share_check(skb, GFP_ATOMIC);
                if (unlikely(!skb))
                        goto tx_drop;
@@ -786,19 +786,12 @@ static int be_change_mtu(struct net_device *netdev, int new_mtu)
  * A max of 64 (BE_NUM_VLANS_SUPPORTED) vlans can be configured in BE.
  * If the user configures more, place BE in vlan promiscuous mode.
  */
-static int be_vid_config(struct be_adapter *adapter, bool vf, u32 vf_num)
+static int be_vid_config(struct be_adapter *adapter)
 {
-       struct be_vf_cfg *vf_cfg = &adapter->vf_cfg[vf_num];
-       u16 vtag[BE_NUM_VLANS_SUPPORTED];
-       u16 ntags = 0, i;
+       u16 vids[BE_NUM_VLANS_SUPPORTED];
+       u16 num = 0, i;
        int status = 0;
 
-       if (vf) {
-               vtag[0] = cpu_to_le16(vf_cfg->vlan_tag);
-               status = be_cmd_vlan_config(adapter, vf_cfg->if_handle, vtag,
-                                           1, 1, 0);
-       }
-
        /* No need to further configure vids if in promiscuous mode */
        if (adapter->promiscuous)
                return 0;
@@ -809,10 +802,10 @@ static int be_vid_config(struct be_adapter *adapter, bool vf, u32 vf_num)
        /* Construct VLAN Table to give to HW */
        for (i = 0; i < VLAN_N_VID; i++)
                if (adapter->vlan_tag[i])
-                       vtag[ntags++] = cpu_to_le16(i);
+                       vids[num++] = cpu_to_le16(i);
 
        status = be_cmd_vlan_config(adapter, adapter->if_handle,
-                                   vtag, ntags, 1, 0);
+                                   vids, num, 1, 0);
 
        /* Set to VLAN promisc mode as setting VLAN filter failed */
        if (status) {
@@ -841,7 +834,7 @@ static int be_vlan_add_vid(struct net_device *netdev, u16 vid)
 
        adapter->vlan_tag[vid] = 1;
        if (adapter->vlans_added <= (adapter->max_vlans + 1))
-               status = be_vid_config(adapter, false, 0);
+               status = be_vid_config(adapter);
 
        if (!status)
                adapter->vlans_added++;
@@ -863,7 +856,7 @@ static int be_vlan_rem_vid(struct net_device *netdev, u16 vid)
 
        adapter->vlan_tag[vid] = 0;
        if (adapter->vlans_added <= adapter->max_vlans)
-               status = be_vid_config(adapter, false, 0);
+               status = be_vid_config(adapter);
 
        if (!status)
                adapter->vlans_added--;
@@ -890,7 +883,7 @@ static void be_set_rx_mode(struct net_device *netdev)
                be_cmd_rx_filter(adapter, IFF_PROMISC, OFF);
 
                if (adapter->vlans_added)
-                       be_vid_config(adapter, false, 0);
+                       be_vid_config(adapter);
        }
 
        /* Enable multicast promisc if num configured exceeds what we support */
@@ -1057,6 +1050,8 @@ static int be_find_vfs(struct be_adapter *adapter, int vf_state)
        u16 offset, stride;
 
        pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_SRIOV);
+       if (!pos)
+               return 0;
        pci_read_config_word(pdev, pos + PCI_SRIOV_VF_OFFSET, &offset);
        pci_read_config_word(pdev, pos + PCI_SRIOV_VF_STRIDE, &stride);
 
@@ -1898,6 +1893,12 @@ static int be_rx_cqs_create(struct be_adapter *adapter)
         */
        adapter->num_rx_qs = (num_irqs(adapter) > 1) ?
                                num_irqs(adapter) + 1 : 1;
+       if (adapter->num_rx_qs != MAX_RX_QS) {
+               rtnl_lock();
+               netif_set_real_num_rx_queues(adapter->netdev,
+                                            adapter->num_rx_qs);
+               rtnl_unlock();
+       }
 
        adapter->big_page_size = (1 << get_order(rx_frag_size)) * PAGE_SIZE;
        for_all_rx_queues(adapter, rxo, i) {
@@ -2544,7 +2545,6 @@ static int be_clear(struct be_adapter *adapter)
        be_cmd_fw_clean(adapter);
 
        be_msix_disable(adapter);
-       pci_write_config_dword(adapter->pdev, PCICFG_CUST_SCRATCHPAD_CSR, 0);
        return 0;
 }
 
@@ -2602,8 +2602,8 @@ static int be_vf_setup(struct be_adapter *adapter)
        cap_flags = en_flags = BE_IF_FLAGS_UNTAGGED | BE_IF_FLAGS_BROADCAST |
                                BE_IF_FLAGS_MULTICAST;
        for_all_vfs(adapter, vf_cfg, vf) {
-               status = be_cmd_if_create(adapter, cap_flags, en_flags, NULL,
-                                         &vf_cfg->if_handle, NULL, vf + 1);
+               status = be_cmd_if_create(adapter, cap_flags, en_flags,
+                                         &vf_cfg->if_handle, vf + 1);
                if (status)
                        goto err;
        }
@@ -2643,29 +2643,43 @@ static void be_setup_init(struct be_adapter *adapter)
        adapter->phy.forced_port_speed = -1;
 }
 
-static int be_add_mac_from_list(struct be_adapter *adapter, u8 *mac)
+static int be_get_mac_addr(struct be_adapter *adapter, u8 *mac, u32 if_handle,
+                          bool *active_mac, u32 *pmac_id)
 {
-       u32 pmac_id;
-       int status;
-       bool pmac_id_active;
+       int status = 0;
 
-       status = be_cmd_get_mac_from_list(adapter, 0, &pmac_id_active,
-                                                       &pmac_id, mac);
-       if (status != 0)
-               goto do_none;
+       if (!is_zero_ether_addr(adapter->netdev->perm_addr)) {
+               memcpy(mac, adapter->netdev->dev_addr, ETH_ALEN);
+               if (!lancer_chip(adapter) && !be_physfn(adapter))
+                       *active_mac = true;
+               else
+                       *active_mac = false;
 
-       if (pmac_id_active) {
-               status = be_cmd_mac_addr_query(adapter, mac,
-                               MAC_ADDRESS_TYPE_NETWORK,
-                               false, adapter->if_handle, pmac_id);
+               return status;
+       }
 
-               if (!status)
-                       adapter->pmac_id[0] = pmac_id;
+       if (lancer_chip(adapter)) {
+               status = be_cmd_get_mac_from_list(adapter, mac,
+                                                 active_mac, pmac_id, 0);
+               if (*active_mac) {
+                       status = be_cmd_mac_addr_query(adapter, mac,
+                                                      MAC_ADDRESS_TYPE_NETWORK,
+                                                      false, if_handle,
+                                                      *pmac_id);
+               }
+       } else if (be_physfn(adapter)) {
+               /* For BE3, for PF get permanent MAC */
+               status = be_cmd_mac_addr_query(adapter, mac,
+                                              MAC_ADDRESS_TYPE_NETWORK, true,
+                                              0, 0);
+               *active_mac = false;
        } else {
-               status = be_cmd_pmac_add(adapter, mac,
-                               adapter->if_handle, &adapter->pmac_id[0], 0);
+               /* For BE3, for VF get soft MAC assigned by PF*/
+               status = be_cmd_mac_addr_query(adapter, mac,
+                                              MAC_ADDRESS_TYPE_NETWORK, false,
+                                              if_handle, 0);
+               *active_mac = true;
        }
-do_none:
        return status;
 }
 
@@ -2686,12 +2700,12 @@ static int be_get_config(struct be_adapter *adapter)
 
 static int be_setup(struct be_adapter *adapter)
 {
-       struct net_device *netdev = adapter->netdev;
        struct device *dev = &adapter->pdev->dev;
        u32 cap_flags, en_flags;
        u32 tx_fc, rx_fc;
        int status;
        u8 mac[ETH_ALEN];
+       bool active_mac;
 
        be_setup_init(adapter);
 
@@ -2717,14 +2731,6 @@ static int be_setup(struct be_adapter *adapter)
        if (status)
                goto err;
 
-       memset(mac, 0, ETH_ALEN);
-       status = be_cmd_mac_addr_query(adapter, mac, MAC_ADDRESS_TYPE_NETWORK,
-                       true /*permanent */, 0, 0);
-       if (status)
-               return status;
-       memcpy(adapter->netdev->dev_addr, mac, ETH_ALEN);
-       memcpy(adapter->netdev->perm_addr, mac, ETH_ALEN);
-
        en_flags = BE_IF_FLAGS_UNTAGGED | BE_IF_FLAGS_BROADCAST |
                        BE_IF_FLAGS_MULTICAST | BE_IF_FLAGS_PASS_L3L4_ERRORS;
        cap_flags = en_flags | BE_IF_FLAGS_MCAST_PROMISCUOUS |
@@ -2734,27 +2740,29 @@ static int be_setup(struct be_adapter *adapter)
                cap_flags |= BE_IF_FLAGS_RSS;
                en_flags |= BE_IF_FLAGS_RSS;
        }
+
        status = be_cmd_if_create(adapter, cap_flags, en_flags,
-                       netdev->dev_addr, &adapter->if_handle,
-                       &adapter->pmac_id[0], 0);
+                                 &adapter->if_handle, 0);
        if (status != 0)
                goto err;
 
-        /* The VF's permanent mac queried from card is incorrect.
-         * For BEx: Query the mac configued by the PF using if_handle
-         * For Lancer: Get and use mac_list to obtain mac address.
-         */
-       if (!be_physfn(adapter)) {
-               if (lancer_chip(adapter))
-                       status = be_add_mac_from_list(adapter, mac);
-               else
-                       status = be_cmd_mac_addr_query(adapter, mac,
-                                       MAC_ADDRESS_TYPE_NETWORK, false,
-                                       adapter->if_handle, 0);
-               if (!status) {
-                       memcpy(adapter->netdev->dev_addr, mac, ETH_ALEN);
-                       memcpy(adapter->netdev->perm_addr, mac, ETH_ALEN);
-               }
+       memset(mac, 0, ETH_ALEN);
+       active_mac = false;
+       status = be_get_mac_addr(adapter, mac, adapter->if_handle,
+                                &active_mac, &adapter->pmac_id[0]);
+       if (status != 0)
+               goto err;
+
+       if (!active_mac) {
+               status = be_cmd_pmac_add(adapter, mac, adapter->if_handle,
+                                        &adapter->pmac_id[0], 0);
+               if (status != 0)
+                       goto err;
+       }
+
+       if (is_zero_ether_addr(adapter->netdev->dev_addr)) {
+               memcpy(adapter->netdev->dev_addr, mac, ETH_ALEN);
+               memcpy(adapter->netdev->perm_addr, mac, ETH_ALEN);
        }
 
        status = be_tx_qs_create(adapter);
@@ -2763,7 +2771,8 @@ static int be_setup(struct be_adapter *adapter)
 
        be_cmd_get_fw_ver(adapter, adapter->fw_ver, NULL);
 
-       be_vid_config(adapter, false, 0);
+       if (adapter->vlans_added)
+               be_vid_config(adapter);
 
        be_set_rx_mode(adapter->netdev);
 
@@ -2773,8 +2782,6 @@ static int be_setup(struct be_adapter *adapter)
                be_cmd_set_flow_control(adapter, adapter->tx_fc,
                                        adapter->rx_fc);
 
-       pcie_set_readrq(adapter->pdev, 4096);
-
        if (be_physfn(adapter) && num_vfs) {
                if (adapter->dev_num_vfs)
                        be_vf_setup(adapter);
@@ -2788,8 +2795,6 @@ static int be_setup(struct be_adapter *adapter)
 
        schedule_delayed_work(&adapter->work, msecs_to_jiffies(1000));
        adapter->flags |= BE_FLAGS_WORKER_SCHEDULED;
-
-       pci_write_config_dword(adapter->pdev, PCICFG_CUST_SCRATCHPAD_CSR, 1);
        return 0;
 err:
        be_clear(adapter);
@@ -3727,10 +3732,7 @@ reschedule:
 
 static bool be_reset_required(struct be_adapter *adapter)
 {
-       u32 reg;
-
-       pci_read_config_dword(adapter->pdev, PCICFG_CUST_SCRATCHPAD_CSR, &reg);
-       return reg;
+       return be_find_vfs(adapter, ENABLED) > 0 ? false : true;
 }
 
 static int __devinit be_probe(struct pci_dev *pdev,
@@ -3749,7 +3751,7 @@ static int __devinit be_probe(struct pci_dev *pdev,
                goto disable_dev;
        pci_set_master(pdev);
 
-       netdev = alloc_etherdev_mq(sizeof(struct be_adapter), MAX_TX_QS);
+       netdev = alloc_etherdev_mqs(sizeof(*adapter), MAX_TX_QS, MAX_RX_QS);
        if (netdev == NULL) {
                status = -ENOMEM;
                goto rel_reg;