Commit 5f6c0181 authored by Jesse Brandeburg's avatar Jesse Brandeburg Committed by David S. Miller

ixgbe: fix bug with vlan strip in promsic mode

The ixgbe driver was setting up 82598 hardware correctly, so that
when promiscuous mode was enabled hardware stripping was turned
off.  But on 82599 the logic to disable/enable hardware stripping
is different, and the code was not updated correctly when the
hardware vlan stripping was enabled as default.

This change comprises the creation of two new helper functions
and calling them from the right locations to disable and enable
hardware stripping of vlan tags at appropriate times.
Signed-off-by: default avatarJesse Brandeburg <jesse.brandeburg@intel.com>
Signed-off-by: default avatarJeff Kirsher <jeffrey.t.kirsher@intel.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent e743d313
...@@ -2482,12 +2482,74 @@ static void ixgbe_vlan_rx_kill_vid(struct net_device *netdev, u16 vid) ...@@ -2482,12 +2482,74 @@ static void ixgbe_vlan_rx_kill_vid(struct net_device *netdev, u16 vid)
hw->mac.ops.set_vfta(&adapter->hw, vid, pool_ndx, false); hw->mac.ops.set_vfta(&adapter->hw, vid, pool_ndx, false);
} }
/**
* ixgbe_vlan_filter_disable - helper to disable hw vlan filtering
* @adapter: driver data
*/
static void ixgbe_vlan_filter_disable(struct ixgbe_adapter *adapter)
{
struct ixgbe_hw *hw = &adapter->hw;
u32 vlnctrl = IXGBE_READ_REG(hw, IXGBE_VLNCTRL);
int i, j;
switch (hw->mac.type) {
case ixgbe_mac_82598EB:
vlnctrl &= ~(IXGBE_VLNCTRL_VME | IXGBE_VLNCTRL_VFE);
vlnctrl &= ~IXGBE_VLNCTRL_CFIEN;
IXGBE_WRITE_REG(hw, IXGBE_VLNCTRL, vlnctrl);
break;
case ixgbe_mac_82599EB:
vlnctrl &= ~IXGBE_VLNCTRL_VFE;
vlnctrl &= ~IXGBE_VLNCTRL_CFIEN;
IXGBE_WRITE_REG(hw, IXGBE_VLNCTRL, vlnctrl);
for (i = 0; i < adapter->num_rx_queues; i++) {
j = adapter->rx_ring[i]->reg_idx;
vlnctrl = IXGBE_READ_REG(hw, IXGBE_RXDCTL(j));
vlnctrl &= ~IXGBE_RXDCTL_VME;
IXGBE_WRITE_REG(hw, IXGBE_RXDCTL(j), vlnctrl);
}
break;
default:
break;
}
}
/**
* ixgbe_vlan_filter_enable - helper to enable hw vlan filtering
* @adapter: driver data
*/
static void ixgbe_vlan_filter_enable(struct ixgbe_adapter *adapter)
{
struct ixgbe_hw *hw = &adapter->hw;
u32 vlnctrl = IXGBE_READ_REG(hw, IXGBE_VLNCTRL);
int i, j;
switch (hw->mac.type) {
case ixgbe_mac_82598EB:
vlnctrl |= IXGBE_VLNCTRL_VME | IXGBE_VLNCTRL_VFE;
vlnctrl &= ~IXGBE_VLNCTRL_CFIEN;
IXGBE_WRITE_REG(hw, IXGBE_VLNCTRL, vlnctrl);
break;
case ixgbe_mac_82599EB:
vlnctrl |= IXGBE_VLNCTRL_VFE;
vlnctrl &= ~IXGBE_VLNCTRL_CFIEN;
IXGBE_WRITE_REG(hw, IXGBE_VLNCTRL, vlnctrl);
for (i = 0; i < adapter->num_rx_queues; i++) {
j = adapter->rx_ring[i]->reg_idx;
vlnctrl = IXGBE_READ_REG(hw, IXGBE_RXDCTL(j));
vlnctrl |= IXGBE_RXDCTL_VME;
IXGBE_WRITE_REG(hw, IXGBE_RXDCTL(j), vlnctrl);
}
break;
default:
break;
}
}
static void ixgbe_vlan_rx_register(struct net_device *netdev, static void ixgbe_vlan_rx_register(struct net_device *netdev,
struct vlan_group *grp) struct vlan_group *grp)
{ {
struct ixgbe_adapter *adapter = netdev_priv(netdev); struct ixgbe_adapter *adapter = netdev_priv(netdev);
u32 ctrl;
int i, j;
if (!test_bit(__IXGBE_DOWN, &adapter->state)) if (!test_bit(__IXGBE_DOWN, &adapter->state))
ixgbe_irq_disable(adapter); ixgbe_irq_disable(adapter);
...@@ -2498,25 +2560,7 @@ static void ixgbe_vlan_rx_register(struct net_device *netdev, ...@@ -2498,25 +2560,7 @@ static void ixgbe_vlan_rx_register(struct net_device *netdev,
* still receive traffic from a DCB-enabled host even if we're * still receive traffic from a DCB-enabled host even if we're
* not in DCB mode. * not in DCB mode.
*/ */
ctrl = IXGBE_READ_REG(&adapter->hw, IXGBE_VLNCTRL); ixgbe_vlan_filter_enable(adapter);
/* Disable CFI check */
ctrl &= ~IXGBE_VLNCTRL_CFIEN;
/* enable VLAN tag stripping */
if (adapter->hw.mac.type == ixgbe_mac_82598EB) {
ctrl |= IXGBE_VLNCTRL_VME;
} else if (adapter->hw.mac.type == ixgbe_mac_82599EB) {
for (i = 0; i < adapter->num_rx_queues; i++) {
u32 ctrl;
j = adapter->rx_ring[i]->reg_idx;
ctrl = IXGBE_READ_REG(&adapter->hw, IXGBE_RXDCTL(j));
ctrl |= IXGBE_RXDCTL_VME;
IXGBE_WRITE_REG(&adapter->hw, IXGBE_RXDCTL(j), ctrl);
}
}
IXGBE_WRITE_REG(&adapter->hw, IXGBE_VLNCTRL, ctrl);
ixgbe_vlan_rx_add_vid(netdev, 0); ixgbe_vlan_rx_add_vid(netdev, 0);
...@@ -2551,17 +2595,17 @@ void ixgbe_set_rx_mode(struct net_device *netdev) ...@@ -2551,17 +2595,17 @@ void ixgbe_set_rx_mode(struct net_device *netdev)
{ {
struct ixgbe_adapter *adapter = netdev_priv(netdev); struct ixgbe_adapter *adapter = netdev_priv(netdev);
struct ixgbe_hw *hw = &adapter->hw; struct ixgbe_hw *hw = &adapter->hw;
u32 fctrl, vlnctrl; u32 fctrl;
/* Check for Promiscuous and All Multicast modes */ /* Check for Promiscuous and All Multicast modes */
fctrl = IXGBE_READ_REG(hw, IXGBE_FCTRL); fctrl = IXGBE_READ_REG(hw, IXGBE_FCTRL);
vlnctrl = IXGBE_READ_REG(hw, IXGBE_VLNCTRL);
if (netdev->flags & IFF_PROMISC) { if (netdev->flags & IFF_PROMISC) {
hw->addr_ctrl.user_set_promisc = 1; hw->addr_ctrl.user_set_promisc = 1;
fctrl |= (IXGBE_FCTRL_UPE | IXGBE_FCTRL_MPE); fctrl |= (IXGBE_FCTRL_UPE | IXGBE_FCTRL_MPE);
vlnctrl &= ~IXGBE_VLNCTRL_VFE; /* don't hardware filter vlans in promisc mode */
ixgbe_vlan_filter_disable(adapter);
} else { } else {
if (netdev->flags & IFF_ALLMULTI) { if (netdev->flags & IFF_ALLMULTI) {
fctrl |= IXGBE_FCTRL_MPE; fctrl |= IXGBE_FCTRL_MPE;
...@@ -2569,12 +2613,11 @@ void ixgbe_set_rx_mode(struct net_device *netdev) ...@@ -2569,12 +2613,11 @@ void ixgbe_set_rx_mode(struct net_device *netdev)
} else { } else {
fctrl &= ~(IXGBE_FCTRL_UPE | IXGBE_FCTRL_MPE); fctrl &= ~(IXGBE_FCTRL_UPE | IXGBE_FCTRL_MPE);
} }
vlnctrl |= IXGBE_VLNCTRL_VFE; ixgbe_vlan_filter_enable(adapter);
hw->addr_ctrl.user_set_promisc = 0; hw->addr_ctrl.user_set_promisc = 0;
} }
IXGBE_WRITE_REG(hw, IXGBE_FCTRL, fctrl); IXGBE_WRITE_REG(hw, IXGBE_FCTRL, fctrl);
IXGBE_WRITE_REG(hw, IXGBE_VLNCTRL, vlnctrl);
/* reprogram secondary unicast list */ /* reprogram secondary unicast list */
hw->mac.ops.update_uc_addr_list(hw, netdev); hw->mac.ops.update_uc_addr_list(hw, netdev);
...@@ -2641,7 +2684,7 @@ static void ixgbe_napi_disable_all(struct ixgbe_adapter *adapter) ...@@ -2641,7 +2684,7 @@ static void ixgbe_napi_disable_all(struct ixgbe_adapter *adapter)
static void ixgbe_configure_dcb(struct ixgbe_adapter *adapter) static void ixgbe_configure_dcb(struct ixgbe_adapter *adapter)
{ {
struct ixgbe_hw *hw = &adapter->hw; struct ixgbe_hw *hw = &adapter->hw;
u32 txdctl, vlnctrl; u32 txdctl;
int i, j; int i, j;
ixgbe_dcb_check_config(&adapter->dcb_cfg); ixgbe_dcb_check_config(&adapter->dcb_cfg);
...@@ -2659,22 +2702,8 @@ static void ixgbe_configure_dcb(struct ixgbe_adapter *adapter) ...@@ -2659,22 +2702,8 @@ static void ixgbe_configure_dcb(struct ixgbe_adapter *adapter)
IXGBE_WRITE_REG(hw, IXGBE_TXDCTL(j), txdctl); IXGBE_WRITE_REG(hw, IXGBE_TXDCTL(j), txdctl);
} }
/* Enable VLAN tag insert/strip */ /* Enable VLAN tag insert/strip */
vlnctrl = IXGBE_READ_REG(hw, IXGBE_VLNCTRL); ixgbe_vlan_filter_enable(adapter);
if (hw->mac.type == ixgbe_mac_82598EB) {
vlnctrl |= IXGBE_VLNCTRL_VME | IXGBE_VLNCTRL_VFE;
vlnctrl &= ~IXGBE_VLNCTRL_CFIEN;
IXGBE_WRITE_REG(hw, IXGBE_VLNCTRL, vlnctrl);
} else if (hw->mac.type == ixgbe_mac_82599EB) {
vlnctrl |= IXGBE_VLNCTRL_VFE;
vlnctrl &= ~IXGBE_VLNCTRL_CFIEN;
IXGBE_WRITE_REG(hw, IXGBE_VLNCTRL, vlnctrl);
for (i = 0; i < adapter->num_rx_queues; i++) {
j = adapter->rx_ring[i]->reg_idx;
vlnctrl = IXGBE_READ_REG(hw, IXGBE_RXDCTL(j));
vlnctrl |= IXGBE_RXDCTL_VME;
IXGBE_WRITE_REG(hw, IXGBE_RXDCTL(j), vlnctrl);
}
}
hw->mac.ops.set_vfta(&adapter->hw, 0, 0, true); hw->mac.ops.set_vfta(&adapter->hw, 0, 0, true);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment