mirror of
				https://github.com/torvalds/linux.git
				synced 2025-10-31 16:48:26 +02:00 
			
		
		
		
	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:
		
							parent
							
								
									3703ebe403
								
							
						
					
					
						commit
						0944d6b5a2
					
				
					 1 changed files with 22 additions and 36 deletions
				
			
		|  | @ -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; | ||||
| } | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
		Reference in a new issue
	
	 Jiri Pirko
						Jiri Pirko