ixgbe: change handling of multicast filters
authorJacob Keller <jacob.e.keller@intel.com>
Tue, 25 Mar 2014 07:45:27 +0000 (07:45 +0000)
committerJeff Kirsher <jeffrey.t.kirsher@intel.com>
Wed, 23 Apr 2014 06:54:43 +0000 (23:54 -0700)
In line with changes done by Alex Duyck regarding unicast filters, we
now only set multicast filters when the interface is not in promiscuous
mode for multicast packets. This also has an impact on the RAR usage
such that SR-IOV has some RARs reserved for its own usage.

Reported-by: Alex Duyck <alexander.h.duyck@intel.com>
Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
Tested-by: Phil Schmitt <phillip.j.schmitt@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c
drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.h

index 220937ba4e59b66c2a6de4a29c829f883bfcfbf8..84044ed1914d3d7c062bc336bfa755dc146f1f35 100644 (file)
@@ -3845,6 +3845,36 @@ static void ixgbe_restore_vlan(struct ixgbe_adapter *adapter)
                ixgbe_vlan_rx_add_vid(adapter->netdev, htons(ETH_P_8021Q), vid);
 }
 
+/**
+ * ixgbe_write_mc_addr_list - write multicast addresses to MTA
+ * @netdev: network interface device structure
+ *
+ * Writes multicast address list to the MTA hash table.
+ * Returns: -ENOMEM on failure
+ *                0 on no addresses written
+ *                X on writing X addresses to MTA
+ **/
+static int ixgbe_write_mc_addr_list(struct net_device *netdev)
+{
+       struct ixgbe_adapter *adapter = netdev_priv(netdev);
+       struct ixgbe_hw *hw = &adapter->hw;
+
+       if (!netif_running(netdev))
+               return 0;
+
+       if (hw->mac.ops.update_mc_addr_list)
+               hw->mac.ops.update_mc_addr_list(hw, netdev);
+       else
+               return -ENOMEM;
+
+#ifdef CONFIG_PCI_IOV
+       if (adapter->num_vfs)
+               ixgbe_restore_vf_multicasts(adapter);
+#endif
+
+       return netdev_mc_count(netdev);
+}
+
 /**
  * ixgbe_write_uc_addr_list - write unicast addresses to RAR table
  * @netdev: network interface device structure
@@ -3908,7 +3938,6 @@ void ixgbe_set_rx_mode(struct net_device *netdev)
        int count;
 
        /* Check for Promiscuous and All Multicast modes */
-
        fctrl = IXGBE_READ_REG(hw, IXGBE_FCTRL);
        vlnctrl = IXGBE_READ_REG(hw, IXGBE_VLNCTRL);
 
@@ -3924,7 +3953,7 @@ void ixgbe_set_rx_mode(struct net_device *netdev)
        if (netdev->flags & IFF_PROMISC) {
                hw->addr_ctrl.user_set_promisc = true;
                fctrl |= (IXGBE_FCTRL_UPE | IXGBE_FCTRL_MPE);
-               vmolr |= (IXGBE_VMOLR_ROPE | IXGBE_VMOLR_MPE);
+               vmolr |= IXGBE_VMOLR_MPE;
                /* Only disable hardware filter vlans in promiscuous mode
                 * if SR-IOV and VMDQ are disabled - otherwise ensure
                 * that hardware VLAN filters remain enabled.
@@ -3956,11 +3985,13 @@ void ixgbe_set_rx_mode(struct net_device *netdev)
         * then we should just turn on promiscuous mode so
         * that we can at least receive multicast traffic
         */
-       hw->mac.ops.update_mc_addr_list(hw, netdev);
-       vmolr |= IXGBE_VMOLR_ROMPE;
-
-       if (adapter->num_vfs)
-               ixgbe_restore_vf_multicasts(adapter);
+       count = ixgbe_write_mc_addr_list(netdev);
+       if (count < 0) {
+               fctrl |= IXGBE_FCTRL_MPE;
+               vmolr |= IXGBE_VMOLR_MPE;
+       } else if (count) {
+               vmolr |= IXGBE_VMOLR_ROMPE;
+       }
 
        if (hw->mac.type != ixgbe_mac_82598EB) {
                vmolr |= IXGBE_READ_REG(hw, IXGBE_VMOLR(VMDQ_P(0))) &
index e6c68d396c992fffb329a1cca4daadb47169faab..2885cb05e565b8e30380d540cbfbb265c0356144 100644 (file)
@@ -327,6 +327,7 @@ static int ixgbe_set_vf_multicasts(struct ixgbe_adapter *adapter,
        u32 vector_bit;
        u32 vector_reg;
        u32 mta_reg;
+       u32 vmolr = IXGBE_READ_REG(hw, IXGBE_VMOLR(vf));
 
        /* only so many hash values supported */
        entries = min(entries, IXGBE_MAX_VF_MC_ENTRIES);
@@ -353,10 +354,13 @@ static int ixgbe_set_vf_multicasts(struct ixgbe_adapter *adapter,
                mta_reg |= (1 << vector_bit);
                IXGBE_WRITE_REG(hw, IXGBE_MTA(vector_reg), mta_reg);
        }
+       vmolr |= IXGBE_VMOLR_ROMPE;
+       IXGBE_WRITE_REG(hw, IXGBE_VMOLR(vf), vmolr);
 
        return 0;
 }
 
+#ifdef CONFIG_PCI_IOV
 static void ixgbe_restore_vf_macvlans(struct ixgbe_adapter *adapter)
 {
        struct ixgbe_hw *hw = &adapter->hw;
@@ -382,6 +386,7 @@ void ixgbe_restore_vf_multicasts(struct ixgbe_adapter *adapter)
        u32 mta_reg;
 
        for (i = 0; i < adapter->num_vfs; i++) {
+               u32 vmolr = IXGBE_READ_REG(hw, IXGBE_VMOLR(i));
                vfinfo = &adapter->vfinfo[i];
                for (j = 0; j < vfinfo->num_vf_mc_hashes; j++) {
                        hw->addr_ctrl.mta_in_use++;
@@ -391,11 +396,18 @@ void ixgbe_restore_vf_multicasts(struct ixgbe_adapter *adapter)
                        mta_reg |= (1 << vector_bit);
                        IXGBE_WRITE_REG(hw, IXGBE_MTA(vector_reg), mta_reg);
                }
+
+               if (vfinfo->num_vf_mc_hashes)
+                       vmolr |= IXGBE_VMOLR_ROMPE;
+               else
+                       vmolr &= ~IXGBE_VMOLR_ROMPE;
+               IXGBE_WRITE_REG(hw, IXGBE_VMOLR(i), vmolr);
        }
 
        /* Restore any VF macvlans */
        ixgbe_restore_vf_macvlans(adapter);
 }
+#endif
 
 static int ixgbe_set_vf_vlan(struct ixgbe_adapter *adapter, int add, int vid,
                             u32 vf)
@@ -495,8 +507,7 @@ static s32 ixgbe_set_vf_lpe(struct ixgbe_adapter *adapter, u32 *msgbuf, u32 vf)
 static void ixgbe_set_vmolr(struct ixgbe_hw *hw, u32 vf, bool aupe)
 {
        u32 vmolr = IXGBE_READ_REG(hw, IXGBE_VMOLR(vf));
-       vmolr |= (IXGBE_VMOLR_ROMPE |
-                 IXGBE_VMOLR_BAM);
+       vmolr |= IXGBE_VMOLR_BAM;
        if (aupe)
                vmolr |= IXGBE_VMOLR_AUPE;
        else
index 139eaddfb2ed5c8c14a3891137a313b4fcaa3a6a..cea64014760497597710a0697b933771ac75f3a2 100644 (file)
@@ -34,7 +34,9 @@
  */
 #define IXGBE_MAX_VFS_DRV_LIMIT  (IXGBE_MAX_VF_FUNCTIONS - 1)
 
+#ifdef CONFIG_PCI_IOV
 void ixgbe_restore_vf_multicasts(struct ixgbe_adapter *adapter);
+#endif
 void ixgbe_msg_task(struct ixgbe_adapter *adapter);
 int ixgbe_vf_configuration(struct pci_dev *pdev, unsigned int event_mask);
 void ixgbe_disable_tx_rx(struct ixgbe_adapter *adapter);