summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIvan Khoronzhuk <ivan.khoronzhuk@linaro.org>2018-11-08 15:27:55 -0500
committerDavid S. Miller <davem@davemloft.net>2018-11-08 23:30:58 -0500
commit960abf68d2023f0d0b08c6f5d05971630496cfb0 (patch)
tree25842b3d8f4e9a29ee448b5c9dee3317a7924575
parente7946760de5852f32c4e52ce47f37e85346981b9 (diff)
net: 8021q: vlan_core: allow use list of vlans for real device
It's redundancy for the drivers to hold the list of vlans when absolutely the same list exists in vlan core. In most cases it's needed only to traverse the vlan devices, their vids and sync some settings with h/w, so add API to simplify this. At least some of these drivers also can benefit: grep "for_each.*vid" -r drivers/net/ethernet/ drivers/net/ethernet/hisilicon/hns3/hns3_enet.c: drivers/net/ethernet/synopsys/dwc-xlgmac-hw.c: drivers/net/ethernet/qlogic/qlge/qlge_main.c: drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c: drivers/net/ethernet/via/via-rhine.c: drivers/net/ethernet/via/via-velocity.c: drivers/net/ethernet/intel/igb/igb_main.c: drivers/net/ethernet/intel/ice/ice_main.c: drivers/net/ethernet/intel/e1000/e1000_main.c: drivers/net/ethernet/intel/i40e/i40e_main.c: drivers/net/ethernet/intel/e1000e/netdev.c: drivers/net/ethernet/intel/igbvf/netdev.c: drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c: drivers/net/ethernet/intel/ixgb/ixgb_main.c: drivers/net/ethernet/intel/ixgbe/ixgbe_main.c: drivers/net/ethernet/amd/xgbe/xgbe-dev.c: drivers/net/ethernet/emulex/benet/be_main.c: drivers/net/ethernet/neterion/vxge/vxge-main.c: drivers/net/ethernet/adaptec/starfire.c: drivers/net/ethernet/brocade/bna/bnad.c: Reviewed-by: Grygorii Strashko <grygorii.strashko@ti.com> Signed-off-by: Ivan Khoronzhuk <ivan.khoronzhuk@linaro.org> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--include/linux/if_vlan.h11
-rw-r--r--net/8021q/vlan_core.c27
2 files changed, 38 insertions, 0 deletions
diff --git a/include/linux/if_vlan.h b/include/linux/if_vlan.h
index 03b08ffded07..1be5230921b5 100644
--- a/include/linux/if_vlan.h
+++ b/include/linux/if_vlan.h
@@ -133,6 +133,9 @@ struct vlan_pcpu_stats {
133 133
134extern struct net_device *__vlan_find_dev_deep_rcu(struct net_device *real_dev, 134extern struct net_device *__vlan_find_dev_deep_rcu(struct net_device *real_dev,
135 __be16 vlan_proto, u16 vlan_id); 135 __be16 vlan_proto, u16 vlan_id);
136extern int vlan_for_each(struct net_device *dev,
137 int (*action)(struct net_device *dev, int vid,
138 void *arg), void *arg);
136extern struct net_device *vlan_dev_real_dev(const struct net_device *dev); 139extern struct net_device *vlan_dev_real_dev(const struct net_device *dev);
137extern u16 vlan_dev_vlan_id(const struct net_device *dev); 140extern u16 vlan_dev_vlan_id(const struct net_device *dev);
138extern __be16 vlan_dev_vlan_proto(const struct net_device *dev); 141extern __be16 vlan_dev_vlan_proto(const struct net_device *dev);
@@ -236,6 +239,14 @@ __vlan_find_dev_deep_rcu(struct net_device *real_dev,
236 return NULL; 239 return NULL;
237} 240}
238 241
242static inline int
243vlan_for_each(struct net_device *dev,
244 int (*action)(struct net_device *dev, int vid, void *arg),
245 void *arg)
246{
247 return 0;
248}
249
239static inline struct net_device *vlan_dev_real_dev(const struct net_device *dev) 250static inline struct net_device *vlan_dev_real_dev(const struct net_device *dev)
240{ 251{
241 BUG(); 252 BUG();
diff --git a/net/8021q/vlan_core.c b/net/8021q/vlan_core.c
index 4f60e86f4b8d..6308b5427a66 100644
--- a/net/8021q/vlan_core.c
+++ b/net/8021q/vlan_core.c
@@ -223,6 +223,33 @@ static int vlan_kill_rx_filter_info(struct net_device *dev, __be16 proto, u16 vi
223 return -ENODEV; 223 return -ENODEV;
224} 224}
225 225
226int vlan_for_each(struct net_device *dev,
227 int (*action)(struct net_device *dev, int vid, void *arg),
228 void *arg)
229{
230 struct vlan_vid_info *vid_info;
231 struct vlan_info *vlan_info;
232 struct net_device *vdev;
233 int ret;
234
235 ASSERT_RTNL();
236
237 vlan_info = rtnl_dereference(dev->vlan_info);
238 if (!vlan_info)
239 return 0;
240
241 list_for_each_entry(vid_info, &vlan_info->vid_list, list) {
242 vdev = vlan_group_get_device(&vlan_info->grp, vid_info->proto,
243 vid_info->vid);
244 ret = action(vdev, vid_info->vid, arg);
245 if (ret)
246 return ret;
247 }
248
249 return 0;
250}
251EXPORT_SYMBOL(vlan_for_each);
252
226int vlan_filter_push_vids(struct vlan_info *vlan_info, __be16 proto) 253int vlan_filter_push_vids(struct vlan_info *vlan_info, __be16 proto)
227{ 254{
228 struct net_device *real_dev = vlan_info->real_dev; 255 struct net_device *real_dev = vlan_info->real_dev;