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>
This commit is contained in:
Jiri Pirko 2015-10-09 13:54:11 +02:00 committed by David S. Miller
parent 3703ebe403
commit 0944d6b5a2

View File

@ -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, static int __vlan_vid_add(struct net_device *dev, struct net_bridge *br,
u16 vid, u16 flags) 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; int err;
/* If driver uses VLAN ndo ops, use 8021q to install vid /* Try switchdev op first. In case it is not supported, fallback to
* on device, otherwise try switchdev ops to install vid. * 8021q add.
*/ */
err = switchdev_port_obj_add(dev, &v.obj);
if (ops->ndo_vlan_rx_add_vid) { if (err == -EOPNOTSUPP)
err = vlan_vid_add(dev, br->vlan_proto, vid); return 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;
}
return err; 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, static int __vlan_vid_del(struct net_device *dev, struct net_bridge *br,
u16 vid) u16 vid)
{ {
const struct net_device_ops *ops = dev->netdev_ops; struct switchdev_obj_port_vlan v = {
int err = 0; .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 /* Try switchdev op first. In case it is not supported, fallback to
* on device, otherwise try switchdev ops to delete vid. * 8021q del.
*/ */
err = switchdev_port_obj_del(dev, &v.obj);
if (ops->ndo_vlan_rx_kill_vid) { if (err == -EOPNOTSUPP) {
vlan_vid_del(dev, br->vlan_proto, vid); vlan_vid_del(dev, br->vlan_proto, vid);
} else { return 0;
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 err; return err;
} }