|
@@ -459,13 +459,13 @@ static void e1000_receive_skb(struct e1000_adapter *adapter,
|
|
|
struct net_device *netdev, struct sk_buff *skb,
|
|
|
u8 status, __le16 vlan)
|
|
|
{
|
|
|
+ u16 tag = le16_to_cpu(vlan);
|
|
|
skb->protocol = eth_type_trans(skb, netdev);
|
|
|
|
|
|
- if (adapter->vlgrp && (status & E1000_RXD_STAT_VP))
|
|
|
- vlan_gro_receive(&adapter->napi, adapter->vlgrp,
|
|
|
- le16_to_cpu(vlan), skb);
|
|
|
- else
|
|
|
- napi_gro_receive(&adapter->napi, skb);
|
|
|
+ if (status & E1000_RXD_STAT_VP)
|
|
|
+ __vlan_hwaccel_put_tag(skb, tag);
|
|
|
+
|
|
|
+ napi_gro_receive(&adapter->napi, skb);
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -2433,6 +2433,8 @@ static void e1000_vlan_rx_add_vid(struct net_device *netdev, u16 vid)
|
|
|
vfta |= (1 << (vid & 0x1F));
|
|
|
hw->mac.ops.write_vfta(hw, index, vfta);
|
|
|
}
|
|
|
+
|
|
|
+ set_bit(vid, adapter->active_vlans);
|
|
|
}
|
|
|
|
|
|
static void e1000_vlan_rx_kill_vid(struct net_device *netdev, u16 vid)
|
|
@@ -2441,13 +2443,6 @@ static void e1000_vlan_rx_kill_vid(struct net_device *netdev, u16 vid)
|
|
|
struct e1000_hw *hw = &adapter->hw;
|
|
|
u32 vfta, index;
|
|
|
|
|
|
- if (!test_bit(__E1000_DOWN, &adapter->state))
|
|
|
- e1000_irq_disable(adapter);
|
|
|
- vlan_group_set_device(adapter->vlgrp, vid, NULL);
|
|
|
-
|
|
|
- if (!test_bit(__E1000_DOWN, &adapter->state))
|
|
|
- e1000_irq_enable(adapter);
|
|
|
-
|
|
|
if ((adapter->hw.mng_cookie.status &
|
|
|
E1000_MNG_DHCP_COOKIE_STATUS_VLAN) &&
|
|
|
(vid == adapter->mng_vlan_id)) {
|
|
@@ -2463,93 +2458,105 @@ static void e1000_vlan_rx_kill_vid(struct net_device *netdev, u16 vid)
|
|
|
vfta &= ~(1 << (vid & 0x1F));
|
|
|
hw->mac.ops.write_vfta(hw, index, vfta);
|
|
|
}
|
|
|
+
|
|
|
+ clear_bit(vid, adapter->active_vlans);
|
|
|
}
|
|
|
|
|
|
-static void e1000_update_mng_vlan(struct e1000_adapter *adapter)
|
|
|
+/**
|
|
|
+ * e1000e_vlan_filter_disable - helper to disable hw VLAN filtering
|
|
|
+ * @adapter: board private structure to initialize
|
|
|
+ **/
|
|
|
+static void e1000e_vlan_filter_disable(struct e1000_adapter *adapter)
|
|
|
{
|
|
|
struct net_device *netdev = adapter->netdev;
|
|
|
- u16 vid = adapter->hw.mng_cookie.vlan_id;
|
|
|
- u16 old_vid = adapter->mng_vlan_id;
|
|
|
-
|
|
|
- if (!adapter->vlgrp)
|
|
|
- return;
|
|
|
+ struct e1000_hw *hw = &adapter->hw;
|
|
|
+ u32 rctl;
|
|
|
|
|
|
- if (!vlan_group_get_device(adapter->vlgrp, vid)) {
|
|
|
- adapter->mng_vlan_id = E1000_MNG_VLAN_NONE;
|
|
|
- if (adapter->hw.mng_cookie.status &
|
|
|
- E1000_MNG_DHCP_COOKIE_STATUS_VLAN) {
|
|
|
- e1000_vlan_rx_add_vid(netdev, vid);
|
|
|
- adapter->mng_vlan_id = vid;
|
|
|
+ if (adapter->flags & FLAG_HAS_HW_VLAN_FILTER) {
|
|
|
+ /* disable VLAN receive filtering */
|
|
|
+ rctl = er32(RCTL);
|
|
|
+ rctl &= ~(E1000_RCTL_VFE | E1000_RCTL_CFIEN);
|
|
|
+ ew32(RCTL, rctl);
|
|
|
+
|
|
|
+ if (adapter->mng_vlan_id != (u16)E1000_MNG_VLAN_NONE) {
|
|
|
+ e1000_vlan_rx_kill_vid(netdev, adapter->mng_vlan_id);
|
|
|
+ adapter->mng_vlan_id = E1000_MNG_VLAN_NONE;
|
|
|
}
|
|
|
-
|
|
|
- if ((old_vid != (u16)E1000_MNG_VLAN_NONE) &&
|
|
|
- (vid != old_vid) &&
|
|
|
- !vlan_group_get_device(adapter->vlgrp, old_vid))
|
|
|
- e1000_vlan_rx_kill_vid(netdev, old_vid);
|
|
|
- } else {
|
|
|
- adapter->mng_vlan_id = vid;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+/**
|
|
|
+ * e1000e_vlan_filter_enable - helper to enable HW VLAN filtering
|
|
|
+ * @adapter: board private structure to initialize
|
|
|
+ **/
|
|
|
+static void e1000e_vlan_filter_enable(struct e1000_adapter *adapter)
|
|
|
+{
|
|
|
+ struct e1000_hw *hw = &adapter->hw;
|
|
|
+ u32 rctl;
|
|
|
+
|
|
|
+ if (adapter->flags & FLAG_HAS_HW_VLAN_FILTER) {
|
|
|
+ /* enable VLAN receive filtering */
|
|
|
+ rctl = er32(RCTL);
|
|
|
+ rctl |= E1000_RCTL_VFE;
|
|
|
+ rctl &= ~E1000_RCTL_CFIEN;
|
|
|
+ ew32(RCTL, rctl);
|
|
|
+ }
|
|
|
+}
|
|
|
|
|
|
-static void e1000_vlan_rx_register(struct net_device *netdev,
|
|
|
- struct vlan_group *grp)
|
|
|
+/**
|
|
|
+ * e1000e_vlan_strip_enable - helper to disable HW VLAN stripping
|
|
|
+ * @adapter: board private structure to initialize
|
|
|
+ **/
|
|
|
+static void e1000e_vlan_strip_disable(struct e1000_adapter *adapter)
|
|
|
{
|
|
|
- struct e1000_adapter *adapter = netdev_priv(netdev);
|
|
|
struct e1000_hw *hw = &adapter->hw;
|
|
|
- u32 ctrl, rctl;
|
|
|
+ u32 ctrl;
|
|
|
|
|
|
- if (!test_bit(__E1000_DOWN, &adapter->state))
|
|
|
- e1000_irq_disable(adapter);
|
|
|
- adapter->vlgrp = grp;
|
|
|
+ /* disable VLAN tag insert/strip */
|
|
|
+ ctrl = er32(CTRL);
|
|
|
+ ctrl &= ~E1000_CTRL_VME;
|
|
|
+ ew32(CTRL, ctrl);
|
|
|
+}
|
|
|
|
|
|
- if (grp) {
|
|
|
- /* enable VLAN tag insert/strip */
|
|
|
- ctrl = er32(CTRL);
|
|
|
- ctrl |= E1000_CTRL_VME;
|
|
|
- ew32(CTRL, ctrl);
|
|
|
+/**
|
|
|
+ * e1000e_vlan_strip_enable - helper to enable HW VLAN stripping
|
|
|
+ * @adapter: board private structure to initialize
|
|
|
+ **/
|
|
|
+static void e1000e_vlan_strip_enable(struct e1000_adapter *adapter)
|
|
|
+{
|
|
|
+ struct e1000_hw *hw = &adapter->hw;
|
|
|
+ u32 ctrl;
|
|
|
|
|
|
- if (adapter->flags & FLAG_HAS_HW_VLAN_FILTER) {
|
|
|
- /* enable VLAN receive filtering */
|
|
|
- rctl = er32(RCTL);
|
|
|
- rctl &= ~E1000_RCTL_CFIEN;
|
|
|
- ew32(RCTL, rctl);
|
|
|
- e1000_update_mng_vlan(adapter);
|
|
|
- }
|
|
|
- } else {
|
|
|
- /* disable VLAN tag insert/strip */
|
|
|
- ctrl = er32(CTRL);
|
|
|
- ctrl &= ~E1000_CTRL_VME;
|
|
|
- ew32(CTRL, ctrl);
|
|
|
+ /* enable VLAN tag insert/strip */
|
|
|
+ ctrl = er32(CTRL);
|
|
|
+ ctrl |= E1000_CTRL_VME;
|
|
|
+ ew32(CTRL, ctrl);
|
|
|
+}
|
|
|
|
|
|
- if (adapter->flags & FLAG_HAS_HW_VLAN_FILTER) {
|
|
|
- if (adapter->mng_vlan_id !=
|
|
|
- (u16)E1000_MNG_VLAN_NONE) {
|
|
|
- e1000_vlan_rx_kill_vid(netdev,
|
|
|
- adapter->mng_vlan_id);
|
|
|
- adapter->mng_vlan_id = E1000_MNG_VLAN_NONE;
|
|
|
- }
|
|
|
- }
|
|
|
+static void e1000_update_mng_vlan(struct e1000_adapter *adapter)
|
|
|
+{
|
|
|
+ struct net_device *netdev = adapter->netdev;
|
|
|
+ u16 vid = adapter->hw.mng_cookie.vlan_id;
|
|
|
+ u16 old_vid = adapter->mng_vlan_id;
|
|
|
+
|
|
|
+ if (adapter->hw.mng_cookie.status &
|
|
|
+ E1000_MNG_DHCP_COOKIE_STATUS_VLAN) {
|
|
|
+ e1000_vlan_rx_add_vid(netdev, vid);
|
|
|
+ adapter->mng_vlan_id = vid;
|
|
|
}
|
|
|
|
|
|
- if (!test_bit(__E1000_DOWN, &adapter->state))
|
|
|
- e1000_irq_enable(adapter);
|
|
|
+ if ((old_vid != (u16)E1000_MNG_VLAN_NONE) && (vid != old_vid))
|
|
|
+ e1000_vlan_rx_kill_vid(netdev, old_vid);
|
|
|
}
|
|
|
|
|
|
static void e1000_restore_vlan(struct e1000_adapter *adapter)
|
|
|
{
|
|
|
u16 vid;
|
|
|
|
|
|
- e1000_vlan_rx_register(adapter->netdev, adapter->vlgrp);
|
|
|
-
|
|
|
- if (!adapter->vlgrp)
|
|
|
- return;
|
|
|
+ e1000_vlan_rx_add_vid(adapter->netdev, 0);
|
|
|
|
|
|
- for (vid = 0; vid < VLAN_N_VID; vid++) {
|
|
|
- if (!vlan_group_get_device(adapter->vlgrp, vid))
|
|
|
- continue;
|
|
|
+ for_each_set_bit(vid, adapter->active_vlans, VLAN_N_VID)
|
|
|
e1000_vlan_rx_add_vid(adapter->netdev, vid);
|
|
|
- }
|
|
|
}
|
|
|
|
|
|
static void e1000_init_manageability_pt(struct e1000_adapter *adapter)
|
|
@@ -3039,6 +3046,8 @@ static void e1000_set_multi(struct net_device *netdev)
|
|
|
if (netdev->flags & IFF_PROMISC) {
|
|
|
rctl |= (E1000_RCTL_UPE | E1000_RCTL_MPE);
|
|
|
rctl &= ~E1000_RCTL_VFE;
|
|
|
+ /* Do not hardware filter VLANs in promisc mode */
|
|
|
+ e1000e_vlan_filter_disable(adapter);
|
|
|
} else {
|
|
|
if (netdev->flags & IFF_ALLMULTI) {
|
|
|
rctl |= E1000_RCTL_MPE;
|
|
@@ -3046,8 +3055,7 @@ static void e1000_set_multi(struct net_device *netdev)
|
|
|
} else {
|
|
|
rctl &= ~(E1000_RCTL_UPE | E1000_RCTL_MPE);
|
|
|
}
|
|
|
- if (adapter->flags & FLAG_HAS_HW_VLAN_FILTER)
|
|
|
- rctl |= E1000_RCTL_VFE;
|
|
|
+ e1000e_vlan_filter_enable(adapter);
|
|
|
}
|
|
|
|
|
|
ew32(RCTL, rctl);
|
|
@@ -3072,6 +3080,11 @@ static void e1000_set_multi(struct net_device *netdev)
|
|
|
*/
|
|
|
e1000_update_mc_addr_list(hw, NULL, 0);
|
|
|
}
|
|
|
+
|
|
|
+ if (netdev->features & NETIF_F_HW_VLAN_RX)
|
|
|
+ e1000e_vlan_strip_enable(adapter);
|
|
|
+ else
|
|
|
+ e1000e_vlan_strip_disable(adapter);
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -3721,10 +3734,8 @@ static int e1000_close(struct net_device *netdev)
|
|
|
* kill manageability vlan ID if supported, but not if a vlan with
|
|
|
* the same ID is registered on the host OS (let 8021q kill it)
|
|
|
*/
|
|
|
- if ((adapter->hw.mng_cookie.status &
|
|
|
- E1000_MNG_DHCP_COOKIE_STATUS_VLAN) &&
|
|
|
- !(adapter->vlgrp &&
|
|
|
- vlan_group_get_device(adapter->vlgrp, adapter->mng_vlan_id)))
|
|
|
+ if (adapter->hw.mng_cookie.status &
|
|
|
+ E1000_MNG_DHCP_COOKIE_STATUS_VLAN)
|
|
|
e1000_vlan_rx_kill_vid(netdev, adapter->mng_vlan_id);
|
|
|
|
|
|
/*
|
|
@@ -5759,7 +5770,6 @@ static const struct net_device_ops e1000e_netdev_ops = {
|
|
|
.ndo_tx_timeout = e1000_tx_timeout,
|
|
|
.ndo_validate_addr = eth_validate_addr,
|
|
|
|
|
|
- .ndo_vlan_rx_register = e1000_vlan_rx_register,
|
|
|
.ndo_vlan_rx_add_vid = e1000_vlan_rx_add_vid,
|
|
|
.ndo_vlan_rx_kill_vid = e1000_vlan_rx_kill_vid,
|
|
|
#ifdef CONFIG_NET_POLL_CONTROLLER
|