summaryrefslogtreecommitdiffstats
path: root/net/bridge
diff options
context:
space:
mode:
authorJiri Pirko <jiri@mellanox.com>2015-10-09 13:54:11 +0200
committerDavid S. Miller <davem@davemloft.net>2015-10-13 04:35:20 +0200
commit0944d6b5a2fad9ba3b7abb2e94a6b7d40cd4a935 (patch)
treec59017b588ec662c7d324bfb502a71b3b30cc644 /net/bridge
parentBNX2: free temp_stats_blk on error path (diff)
downloadlinux-0944d6b5a2fad9ba3b7abb2e94a6b7d40cd4a935.tar.xz
linux-0944d6b5a2fad9ba3b7abb2e94a6b7d40cd4a935.zip
bridge: try switchdev op first in __vlan_vid_add/del
Some drivers need to implement both switchdev vlan ops and vid_add/kill ndos. For that to work in bridge code, we need to try switchdev op first when adding/deleting vlan id. Signed-off-by: Jiri Pirko <jiri@mellanox.com> Signed-off-by: Ido Schimmel <idosch@mellanox.com> Acked-by: Scott Feldman <sfeldma@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/bridge')
-rw-r--r--net/bridge/br_vlan.c58
1 files changed, 22 insertions, 36 deletions
diff --git a/net/bridge/br_vlan.c b/net/bridge/br_vlan.c
index 7a95e31f782f..ad7e4f6b6d6b 100644
--- a/net/bridge/br_vlan.c
+++ b/net/bridge/br_vlan.c
@@ -72,28 +72,20 @@ static void __vlan_add_flags(struct net_bridge_vlan *v, u16 flags)
static int __vlan_vid_add(struct net_device *dev, struct net_bridge *br,
u16 vid, u16 flags)
{
- const struct net_device_ops *ops = dev->netdev_ops;
+ struct switchdev_obj_port_vlan v = {
+ .obj.id = SWITCHDEV_OBJ_ID_PORT_VLAN,
+ .flags = flags,
+ .vid_begin = vid,
+ .vid_end = vid,
+ };
int err;
- /* If driver uses VLAN ndo ops, use 8021q to install vid
- * on device, otherwise try switchdev ops to install vid.
+ /* Try switchdev op first. In case it is not supported, fallback to
+ * 8021q add.
*/
-
- if (ops->ndo_vlan_rx_add_vid) {
- err = vlan_vid_add(dev, br->vlan_proto, vid);
- } else {
- struct switchdev_obj_port_vlan v = {
- .obj.id = SWITCHDEV_OBJ_ID_PORT_VLAN,
- .flags = flags,
- .vid_begin = vid,
- .vid_end = vid,
- };
-
- err = switchdev_port_obj_add(dev, &v.obj);
- if (err == -EOPNOTSUPP)
- err = 0;
- }
-
+ err = switchdev_port_obj_add(dev, &v.obj);
+ if (err == -EOPNOTSUPP)
+ return vlan_vid_add(dev, br->vlan_proto, vid);
return err;
}
@@ -122,27 +114,21 @@ static void __vlan_del_list(struct net_bridge_vlan *v)
static int __vlan_vid_del(struct net_device *dev, struct net_bridge *br,
u16 vid)
{
- const struct net_device_ops *ops = dev->netdev_ops;
- int err = 0;
+ struct switchdev_obj_port_vlan v = {
+ .obj.id = SWITCHDEV_OBJ_ID_PORT_VLAN,
+ .vid_begin = vid,
+ .vid_end = vid,
+ };
+ int err;
- /* If driver uses VLAN ndo ops, use 8021q to delete vid
- * on device, otherwise try switchdev ops to delete vid.
+ /* Try switchdev op first. In case it is not supported, fallback to
+ * 8021q del.
*/
-
- if (ops->ndo_vlan_rx_kill_vid) {
+ err = switchdev_port_obj_del(dev, &v.obj);
+ if (err == -EOPNOTSUPP) {
vlan_vid_del(dev, br->vlan_proto, vid);
- } else {
- struct switchdev_obj_port_vlan v = {
- .obj.id = SWITCHDEV_OBJ_ID_PORT_VLAN,
- .vid_begin = vid,
- .vid_end = vid,
- };
-
- err = switchdev_port_obj_del(dev, &v.obj);
- if (err == -EOPNOTSUPP)
- err = 0;
+ return 0;
}
-
return err;
}