summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJacob Keller <jacob.e.keller@intel.com>2016-11-08 13:05:15 -0800
committerJeff Kirsher <jeffrey.t.kirsher@intel.com>2016-12-06 20:43:44 -0800
commit1596b5ddbf25c3dd05aed208ea0bb57eac1c5524 (patch)
tree8ce6c6925b4487920aed88e93a7a29aa1061d91c
parent4293d5f528b5a0a1b0c1b0c6eb522366822a965a (diff)
i40e: restore workaround for removing default MAC filter
A previous commit 53cb6e9e8949 ("i40e: Removal of workaround for simple MAC address filter deletion") removed a workaround for some firmware versions which was reported to not be necessary in production NICs. Unfortunately this workaround is necessary in some configurations, specifically the Ethernet Controller XL710 for 40GbE QSFP+ (8086:1583). Without this patch, the mentioned NICs with current firmware exhibit issues when adding VLANs, as outlined by the following reproduction: $modprobe i40e $ip link set <device> up $ip link add link <device> vlan100 type vlan id 100 $dmesg | tail <snip> kernel: i40e 0000:82:00.0: Error I40E_AQ_RC_EINVAL adding RX filters on PF, promiscuous mode forced on This results in filters being marked as FAILED and setting the device in promiscuous mode. The root cause of receiving the -EINVAL error response appears to be due to a conflict with the default MAC filter which still exists on the default firmware for this device. Attempting to add a new VLAN filter on the default MAC address conflicts with the IGNORE_VLAN setting on the default rule. Change-ID: I4d8f6d48ac5f60cfe981b3baad30eb4d7c170d61 Signed-off-by: Jacob Keller <jacob.e.keller@intel.com> Tested-by: Andrew Bowers <andrewx.bowers@intel.com> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_main.c41
1 files changed, 41 insertions, 0 deletions
diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c
index 4534d41fa340..c467cc49ce91 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_main.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_main.c
@@ -1226,6 +1226,39 @@ bool i40e_is_vsi_in_vlan(struct i40e_vsi *vsi)
}
/**
+ * i40e_rm_default_mac_filter - Remove the default MAC filter set by NVM
+ * @vsi: the PF Main VSI - inappropriate for any other VSI
+ * @macaddr: the MAC address
+ *
+ * Remove whatever filter the firmware set up so the driver can manage
+ * its own filtering intelligently.
+ **/
+static void i40e_rm_default_mac_filter(struct i40e_vsi *vsi, u8 *macaddr)
+{
+ struct i40e_aqc_remove_macvlan_element_data element;
+ struct i40e_pf *pf = vsi->back;
+
+ /* Only appropriate for the PF main VSI */
+ if (vsi->type != I40E_VSI_MAIN)
+ return;
+
+ memset(&element, 0, sizeof(element));
+ ether_addr_copy(element.mac_addr, macaddr);
+ element.vlan_tag = 0;
+ /* Ignore error returns, some firmware does it this way... */
+ element.flags = I40E_AQC_MACVLAN_DEL_PERFECT_MATCH;
+ i40e_aq_remove_macvlan(&pf->hw, vsi->seid, &element, 1, NULL);
+
+ memset(&element, 0, sizeof(element));
+ ether_addr_copy(element.mac_addr, macaddr);
+ element.vlan_tag = 0;
+ /* ...and some firmware does it this way. */
+ element.flags = I40E_AQC_MACVLAN_DEL_PERFECT_MATCH |
+ I40E_AQC_MACVLAN_DEL_IGNORE_VLAN;
+ i40e_aq_remove_macvlan(&pf->hw, vsi->seid, &element, 1, NULL);
+}
+
+/**
* i40e_add_filter - Add a mac/vlan filter to the VSI
* @vsi: the VSI to be searched
* @macaddr: the MAC address
@@ -9295,6 +9328,12 @@ static int i40e_config_netdev(struct i40e_vsi *vsi)
if (vsi->type == I40E_VSI_MAIN) {
SET_NETDEV_DEV(netdev, &pf->pdev->dev);
ether_addr_copy(mac_addr, hw->mac.perm_addr);
+ /* The following steps are necessary to prevent reception
+ * of tagged packets - some older NVM configurations load a
+ * default a MAC-VLAN filter that accepts any tagged packet
+ * which must be replaced by a normal filter.
+ */
+ i40e_rm_default_mac_filter(vsi, mac_addr);
spin_lock_bh(&vsi->mac_filter_hash_lock);
i40e_add_filter(vsi, mac_addr, I40E_VLAN_ANY);
spin_unlock_bh(&vsi->mac_filter_hash_lock);
@@ -9828,6 +9867,8 @@ static struct i40e_vsi *i40e_vsi_reinit_setup(struct i40e_vsi *vsi)
pf->vsi[pf->lan_vsi]->tc_config.enabled_tc = 0;
pf->vsi[pf->lan_vsi]->seid = pf->main_vsi_seid;
i40e_vsi_config_tc(pf->vsi[pf->lan_vsi], enabled_tc);
+ if (vsi->type == I40E_VSI_MAIN)
+ i40e_rm_default_mac_filter(vsi, pf->hw.mac.perm_addr);
/* assign it some queues */
ret = i40e_alloc_rings(vsi);