diff options
Diffstat (limited to 'drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c')
-rw-r--r-- | drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c | 151 |
1 files changed, 62 insertions, 89 deletions
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c index c5fe915870ad..a59d55e25d5f 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c | |||
@@ -12895,52 +12895,71 @@ static int __bnx2x_vlan_configure_vid(struct bnx2x *bp, u16 vid, bool add) | |||
12895 | return rc; | 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 | struct bnx2x_vlan_entry *vlan; | 12900 | struct bnx2x_vlan_entry *vlan; |
12901 | int rc = 0; | 12901 | int rc = 0; |
12902 | 12902 | ||
12903 | if (!bp->vlan_cnt) { | 12903 | /* Configure all non-configured entries */ |
12904 | DP(NETIF_MSG_IFUP, "No need to re-configure vlan filters\n"); | ||
12905 | return 0; | ||
12906 | } | ||
12907 | |||
12908 | list_for_each_entry(vlan, &bp->vlan_reg, link) { | 12904 | list_for_each_entry(vlan, &bp->vlan_reg, link) { |
12909 | /* Prepare for cleanup in case of errors */ | 12905 | if (vlan->hw) |
12910 | if (rc) { | ||
12911 | vlan->hw = false; | ||
12912 | continue; | ||
12913 | } | ||
12914 | |||
12915 | if (!vlan->hw) | ||
12916 | continue; | 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 | rc = __bnx2x_vlan_configure_vid(bp, vlan->vid, true); | 12911 | rc = __bnx2x_vlan_configure_vid(bp, vlan->vid, true); |
12921 | if (rc) { | 12912 | if (rc) { |
12922 | BNX2X_ERR("Unable to configure VLAN %d\n", vlan->vid); | 12913 | BNX2X_ERR("Unable to config VLAN %d\n", vlan->vid); |
12923 | vlan->hw = false; | 12914 | return rc; |
12924 | rc = -EINVAL; | ||
12925 | continue; | ||
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 | static int bnx2x_vlan_rx_add_vid(struct net_device *dev, __be16 proto, u16 vid) | 12959 | static int bnx2x_vlan_rx_add_vid(struct net_device *dev, __be16 proto, u16 vid) |
12933 | { | 12960 | { |
12934 | struct bnx2x *bp = netdev_priv(dev); | 12961 | struct bnx2x *bp = netdev_priv(dev); |
12935 | struct bnx2x_vlan_entry *vlan; | 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 | DP(NETIF_MSG_IFUP, "Adding VLAN %d\n", vid); | 12964 | DP(NETIF_MSG_IFUP, "Adding VLAN %d\n", vid); |
12946 | 12965 | ||
@@ -12948,93 +12967,47 @@ static int bnx2x_vlan_rx_add_vid(struct net_device *dev, __be16 proto, u16 vid) | |||
12948 | if (!vlan) | 12967 | if (!vlan) |
12949 | return -ENOMEM; | 12968 | return -ENOMEM; |
12950 | 12969 | ||
12951 | bp->vlan_cnt++; | ||
12952 | if (bp->vlan_cnt > bp->vlan_credit && !bp->accept_any_vlan) { | ||
12953 | DP(NETIF_MSG_IFUP, "Accept all VLAN raised\n"); | ||
12954 | bp->accept_any_vlan = true; | ||
12955 | if (IS_PF(bp)) | ||
12956 | bnx2x_set_rx_mode_inner(bp); | ||
12957 | else | ||
12958 | bnx2x_vfpf_storm_rx_mode(bp); | ||
12959 | } else if (bp->vlan_cnt <= bp->vlan_credit) { | ||
12960 | rc = __bnx2x_vlan_configure_vid(bp, vid, true); | ||
12961 | hw = true; | ||
12962 | } | ||
12963 | |||
12964 | vlan->vid = vid; | 12970 | vlan->vid = vid; |
12965 | vlan->hw = hw; | 12971 | vlan->hw = false; |
12972 | list_add_tail(&vlan->link, &bp->vlan_reg); | ||
12966 | 12973 | ||
12967 | if (!rc) { | 12974 | if (netif_running(dev)) |
12968 | list_add(&vlan->link, &bp->vlan_reg); | 12975 | bnx2x_vlan_configure(bp, true); |
12969 | } else { | ||
12970 | bp->vlan_cnt--; | ||
12971 | kfree(vlan); | ||
12972 | } | ||
12973 | |||
12974 | DP(NETIF_MSG_IFUP, "Adding VLAN result %d\n", rc); | ||
12975 | 12976 | ||
12976 | return rc; | 12977 | return 0; |
12977 | } | 12978 | } |
12978 | 12979 | ||
12979 | static int bnx2x_vlan_rx_kill_vid(struct net_device *dev, __be16 proto, u16 vid) | 12980 | static int bnx2x_vlan_rx_kill_vid(struct net_device *dev, __be16 proto, u16 vid) |
12980 | { | 12981 | { |
12981 | struct bnx2x *bp = netdev_priv(dev); | 12982 | struct bnx2x *bp = netdev_priv(dev); |
12982 | struct bnx2x_vlan_entry *vlan; | 12983 | struct bnx2x_vlan_entry *vlan; |
12984 | bool found = false; | ||
12983 | int rc = 0; | 12985 | int rc = 0; |
12984 | 12986 | ||
12985 | if (!netif_running(bp->dev)) { | ||
12986 | DP(NETIF_MSG_IFUP, | ||
12987 | "Ignoring VLAN configuration the interface is down\n"); | ||
12988 | return -EFAULT; | ||
12989 | } | ||
12990 | |||
12991 | DP(NETIF_MSG_IFUP, "Removing VLAN %d\n", vid); | 12987 | DP(NETIF_MSG_IFUP, "Removing VLAN %d\n", vid); |
12992 | 12988 | ||
12993 | if (!bp->vlan_cnt) { | ||
12994 | BNX2X_ERR("Unable to kill VLAN %d\n", vid); | ||
12995 | return -EINVAL; | ||
12996 | } | ||
12997 | |||
12998 | list_for_each_entry(vlan, &bp->vlan_reg, link) | 12989 | list_for_each_entry(vlan, &bp->vlan_reg, link) |
12999 | if (vlan->vid == vid) | 12990 | if (vlan->vid == vid) { |
12991 | found = true; | ||
13000 | break; | 12992 | break; |
12993 | } | ||
13001 | 12994 | ||
13002 | if (vlan->vid != vid) { | 12995 | if (!found) { |
13003 | BNX2X_ERR("Unable to kill VLAN %d - not found\n", vid); | 12996 | BNX2X_ERR("Unable to kill VLAN %d - not found\n", vid); |
13004 | return -EINVAL; | 12997 | return -EINVAL; |
13005 | } | 12998 | } |
13006 | 12999 | ||
13007 | if (vlan->hw) | 13000 | if (netif_running(dev) && vlan->hw) { |
13008 | rc = __bnx2x_vlan_configure_vid(bp, vid, false); | 13001 | rc = __bnx2x_vlan_configure_vid(bp, vid, false); |
13002 | DP(NETIF_MSG_IFUP, "HW deconfigured for VLAN %d\n", vid); | ||
13003 | bp->vlan_cnt--; | ||
13004 | } | ||
13009 | 13005 | ||
13010 | list_del(&vlan->link); | 13006 | list_del(&vlan->link); |
13011 | kfree(vlan); | 13007 | kfree(vlan); |
13012 | 13008 | ||
13013 | bp->vlan_cnt--; | 13009 | if (netif_running(dev)) |
13014 | 13010 | bnx2x_vlan_configure(bp, true); | |
13015 | if (bp->vlan_cnt <= bp->vlan_credit && bp->accept_any_vlan) { | ||
13016 | /* Configure all non-configured entries */ | ||
13017 | list_for_each_entry(vlan, &bp->vlan_reg, link) { | ||
13018 | if (vlan->hw) | ||
13019 | continue; | ||
13020 | |||
13021 | rc = __bnx2x_vlan_configure_vid(bp, vlan->vid, true); | ||
13022 | if (rc) { | ||
13023 | BNX2X_ERR("Unable to config VLAN %d\n", | ||
13024 | vlan->vid); | ||
13025 | continue; | ||
13026 | } | ||
13027 | DP(NETIF_MSG_IFUP, "HW configured for VLAN %d\n", | ||
13028 | vlan->vid); | ||
13029 | vlan->hw = true; | ||
13030 | } | ||
13031 | DP(NETIF_MSG_IFUP, "Accept all VLAN Removed\n"); | ||
13032 | bp->accept_any_vlan = false; | ||
13033 | if (IS_PF(bp)) | ||
13034 | bnx2x_set_rx_mode_inner(bp); | ||
13035 | else | ||
13036 | bnx2x_vfpf_storm_rx_mode(bp); | ||
13037 | } | ||
13038 | 13011 | ||
13039 | DP(NETIF_MSG_IFUP, "Removing VLAN result %d\n", rc); | 13012 | DP(NETIF_MSG_IFUP, "Removing VLAN result %d\n", rc); |
13040 | 13013 | ||