Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

bnx2x: allow adding VLANs while interface is down

Since implementing VLAN filtering in commit 05cc5a39ddb74
("bnx2x: add vlan filtering offload") bnx2x refuses to add a VLAN while
the interface is down:

# ip link add link enp3s0f0 enp3s0f0_10 type vlan id 10
RTNETLINK answers: Bad address

and in dmesg (with bnx2x.debug=0x20):
bnx2x: [bnx2x_vlan_rx_add_vid:12941(enp3s0f0)]Ignoring VLAN
configuration the interface is down

Other drivers have no problem with this.
Fix this peculiar behavior in the following way:
- Accept requests to add/kill VID regardless of the device state.
Maintain the requested list of VIDs in the bp->vlan_reg list.
- If the device is up, try to configure the VID list into the hardware.
If we run out of VLAN credits or encounter a failure configuring an
entry, fall back to accepting all VLANs.
If we successfully configure all entries from the list, turn the
fallback off.
- Use the same code for reconfiguring VLANs during NIC load.

Signed-off-by: Michal Schmidt <mschmidt@redhat.com>
Acked-by: Yuval Mintz <Yuval.Mintz@qlogic.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Michal Schmidt and committed by
David S. Miller
a02cc9d3 4ef36e15

+62 -89
+62 -89
drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
··· 12895 12895 return rc; 12896 12896 } 12897 12897 12898 - int bnx2x_vlan_reconfigure_vid(struct bnx2x *bp) 12898 + static int bnx2x_vlan_configure_vid_list(struct bnx2x *bp) 12899 12899 { 12900 12900 struct bnx2x_vlan_entry *vlan; 12901 12901 int rc = 0; 12902 12902 12903 - if (!bp->vlan_cnt) { 12904 - DP(NETIF_MSG_IFUP, "No need to re-configure vlan filters\n"); 12905 - return 0; 12906 - } 12907 - 12903 + /* Configure all non-configured entries */ 12908 12904 list_for_each_entry(vlan, &bp->vlan_reg, link) { 12909 - /* Prepare for cleanup in case of errors */ 12910 - if (rc) { 12911 - vlan->hw = false; 12912 - continue; 12913 - } 12914 - 12915 - if (!vlan->hw) 12905 + if (vlan->hw) 12916 12906 continue; 12917 12907 12918 - DP(NETIF_MSG_IFUP, "Re-configuring vlan 0x%04x\n", vlan->vid); 12908 + if (bp->vlan_cnt >= bp->vlan_credit) 12909 + return -ENOBUFS; 12919 12910 12920 12911 rc = __bnx2x_vlan_configure_vid(bp, vlan->vid, true); 12921 12912 if (rc) { 12922 - BNX2X_ERR("Unable to configure VLAN %d\n", vlan->vid); 12923 - vlan->hw = false; 12924 - rc = -EINVAL; 12925 - continue; 12913 + BNX2X_ERR("Unable to config VLAN %d\n", vlan->vid); 12914 + return rc; 12926 12915 } 12916 + 12917 + DP(NETIF_MSG_IFUP, "HW configured for VLAN %d\n", vlan->vid); 12918 + vlan->hw = true; 12919 + bp->vlan_cnt++; 12927 12920 } 12928 12921 12929 - return rc; 12922 + return 0; 12923 + } 12924 + 12925 + static void bnx2x_vlan_configure(struct bnx2x *bp, bool set_rx_mode) 12926 + { 12927 + bool need_accept_any_vlan; 12928 + 12929 + need_accept_any_vlan = !!bnx2x_vlan_configure_vid_list(bp); 12930 + 12931 + if (bp->accept_any_vlan != need_accept_any_vlan) { 12932 + bp->accept_any_vlan = need_accept_any_vlan; 12933 + DP(NETIF_MSG_IFUP, "Accept all VLAN %s\n", 12934 + bp->accept_any_vlan ? "raised" : "cleared"); 12935 + if (set_rx_mode) { 12936 + if (IS_PF(bp)) 12937 + bnx2x_set_rx_mode_inner(bp); 12938 + else 12939 + bnx2x_vfpf_storm_rx_mode(bp); 12940 + } 12941 + } 12942 + } 12943 + 12944 + int bnx2x_vlan_reconfigure_vid(struct bnx2x *bp) 12945 + { 12946 + struct bnx2x_vlan_entry *vlan; 12947 + 12948 + /* The hw forgot all entries after reload */ 12949 + list_for_each_entry(vlan, &bp->vlan_reg, link) 12950 + vlan->hw = false; 12951 + bp->vlan_cnt = 0; 12952 + 12953 + /* Don't set rx mode here. Our caller will do it. */ 12954 + bnx2x_vlan_configure(bp, false); 12955 + 12956 + return 0; 12930 12957 } 12931 12958 12932 12959 static int bnx2x_vlan_rx_add_vid(struct net_device *dev, __be16 proto, u16 vid) 12933 12960 { 12934 12961 struct bnx2x *bp = netdev_priv(dev); 12935 12962 struct bnx2x_vlan_entry *vlan; 12936 - bool hw = false; 12937 - int rc = 0; 12938 - 12939 - if (!netif_running(bp->dev)) { 12940 - DP(NETIF_MSG_IFUP, 12941 - "Ignoring VLAN configuration the interface is down\n"); 12942 - return -EFAULT; 12943 - } 12944 12963 12945 12964 DP(NETIF_MSG_IFUP, "Adding VLAN %d\n", vid); 12946 12965 ··· 12967 12948 if (!vlan) 12968 12949 return -ENOMEM; 12969 12950 12970 - bp->vlan_cnt++; 12971 - if (bp->vlan_cnt > bp->vlan_credit && !bp->accept_any_vlan) { 12972 - DP(NETIF_MSG_IFUP, "Accept all VLAN raised\n"); 12973 - bp->accept_any_vlan = true; 12974 - if (IS_PF(bp)) 12975 - bnx2x_set_rx_mode_inner(bp); 12976 - else 12977 - bnx2x_vfpf_storm_rx_mode(bp); 12978 - } else if (bp->vlan_cnt <= bp->vlan_credit) { 12979 - rc = __bnx2x_vlan_configure_vid(bp, vid, true); 12980 - hw = true; 12981 - } 12982 - 12983 12951 vlan->vid = vid; 12984 - vlan->hw = hw; 12952 + vlan->hw = false; 12953 + list_add_tail(&vlan->link, &bp->vlan_reg); 12985 12954 12986 - if (!rc) { 12987 - list_add(&vlan->link, &bp->vlan_reg); 12988 - } else { 12989 - bp->vlan_cnt--; 12990 - kfree(vlan); 12991 - } 12955 + if (netif_running(dev)) 12956 + bnx2x_vlan_configure(bp, true); 12992 12957 12993 - DP(NETIF_MSG_IFUP, "Adding VLAN result %d\n", rc); 12994 - 12995 - return rc; 12958 + return 0; 12996 12959 } 12997 12960 12998 12961 static int bnx2x_vlan_rx_kill_vid(struct net_device *dev, __be16 proto, u16 vid) 12999 12962 { 13000 12963 struct bnx2x *bp = netdev_priv(dev); 13001 12964 struct bnx2x_vlan_entry *vlan; 12965 + bool found = false; 13002 12966 int rc = 0; 13003 - 13004 - if (!netif_running(bp->dev)) { 13005 - DP(NETIF_MSG_IFUP, 13006 - "Ignoring VLAN configuration the interface is down\n"); 13007 - return -EFAULT; 13008 - } 13009 12967 13010 12968 DP(NETIF_MSG_IFUP, "Removing VLAN %d\n", vid); 13011 12969 13012 - if (!bp->vlan_cnt) { 13013 - BNX2X_ERR("Unable to kill VLAN %d\n", vid); 13014 - return -EINVAL; 13015 - } 13016 - 13017 12970 list_for_each_entry(vlan, &bp->vlan_reg, link) 13018 - if (vlan->vid == vid) 12971 + if (vlan->vid == vid) { 12972 + found = true; 13019 12973 break; 12974 + } 13020 12975 13021 - if (vlan->vid != vid) { 12976 + if (!found) { 13022 12977 BNX2X_ERR("Unable to kill VLAN %d - not found\n", vid); 13023 12978 return -EINVAL; 13024 12979 } 13025 12980 13026 - if (vlan->hw) 12981 + if (netif_running(dev) && vlan->hw) { 13027 12982 rc = __bnx2x_vlan_configure_vid(bp, vid, false); 12983 + DP(NETIF_MSG_IFUP, "HW deconfigured for VLAN %d\n", vid); 12984 + bp->vlan_cnt--; 12985 + } 13028 12986 13029 12987 list_del(&vlan->link); 13030 12988 kfree(vlan); 13031 12989 13032 - bp->vlan_cnt--; 13033 - 13034 - if (bp->vlan_cnt <= bp->vlan_credit && bp->accept_any_vlan) { 13035 - /* Configure all non-configured entries */ 13036 - list_for_each_entry(vlan, &bp->vlan_reg, link) { 13037 - if (vlan->hw) 13038 - continue; 13039 - 13040 - rc = __bnx2x_vlan_configure_vid(bp, vlan->vid, true); 13041 - if (rc) { 13042 - BNX2X_ERR("Unable to config VLAN %d\n", 13043 - vlan->vid); 13044 - continue; 13045 - } 13046 - DP(NETIF_MSG_IFUP, "HW configured for VLAN %d\n", 13047 - vlan->vid); 13048 - vlan->hw = true; 13049 - } 13050 - DP(NETIF_MSG_IFUP, "Accept all VLAN Removed\n"); 13051 - bp->accept_any_vlan = false; 13052 - if (IS_PF(bp)) 13053 - bnx2x_set_rx_mode_inner(bp); 13054 - else 13055 - bnx2x_vfpf_storm_rx_mode(bp); 13056 - } 12990 + if (netif_running(dev)) 12991 + bnx2x_vlan_configure(bp, true); 13057 12992 13058 12993 DP(NETIF_MSG_IFUP, "Removing VLAN result %d\n", rc); 13059 12994