static void __vlan_device_event(struct net_device *dev, unsigned long event) { switch (event) { case NETDEV_CHANGENAME: vlan_proc_rem_dev(dev); if (vlan_proc_add_dev(dev) < 0) pr_warn("failed to change proc name for %s\n", dev->name); break; case NETDEV_REGISTER: if (vlan_proc_add_dev(dev) < 0) pr_warn("failed to add proc entry for %s\n", dev->name); break; case NETDEV_UNREGISTER: vlan_proc_rem_dev(dev); break; } }
/* This returns 0 if everything went fine. * It will return 1 if the group was killed as a result. * A negative return indicates failure. * * The RTNL lock must be held. */ static int unregister_vlan_dev(struct net_device *real_dev, unsigned short vlan_id) { struct net_device *dev = NULL; int real_dev_ifindex = real_dev->ifindex; struct vlan_group *grp; int i, ret; #ifdef VLAN_DEBUG printk(VLAN_DBG "%s: VID: %i\n", __FUNCTION__, vlan_id); #endif /* sanity check */ if (vlan_id >= VLAN_VID_MASK) return -EINVAL; spin_lock_bh(&vlan_group_lock); grp = __vlan_find_group(real_dev_ifindex); spin_unlock_bh(&vlan_group_lock); ret = 0; if (grp) { dev = grp->vlan_devices[vlan_id]; if (dev) { /* Remove proc entry */ vlan_proc_rem_dev(dev); /* Take it out of our own structures, but be sure to * interlock with HW accelerating devices or SW vlan * input packet processing. */ if (real_dev->features & (NETIF_F_HW_VLAN_RX | NETIF_F_HW_VLAN_FILTER)) { real_dev->vlan_rx_kill_vid(real_dev, vlan_id); } br_write_lock(BR_NETPROTO_LOCK); grp->vlan_devices[vlan_id] = NULL; br_write_unlock(BR_NETPROTO_LOCK); /* Caller unregisters (and if necessary, puts) * VLAN device, but we get rid of the reference to * real_dev here. */ dev_put(real_dev); /* If the group is now empty, kill off the * group. */ for (i = 0; i < VLAN_VID_MASK; i++) if (grp->vlan_devices[i]) break; if (i == VLAN_VID_MASK) { if (real_dev->features & NETIF_F_HW_VLAN_RX) real_dev->vlan_rx_register(real_dev, NULL); spin_lock_bh(&vlan_group_lock); __grp_unhash(grp); spin_unlock_bh(&vlan_group_lock); /* Free the group, after we have removed it * from the hash. */ kfree(grp); grp = NULL; ret = 1; } MOD_DEC_USE_COUNT; } } return ret; }
/* This returns 0 if everything went fine. * It will return 1 if the group was killed as a result. * A negative return indicates failure. * * The RTNL lock must be held. */ static int unregister_vlan_dev(struct net_device *real_dev, unsigned short vlan_id) { struct net_device *dev = NULL; int real_dev_ifindex = real_dev->ifindex; struct vlan_group *grp; int i, ret; #ifdef VLAN_DEBUG printk(VLAN_DBG "%s: VID: %i\n", __FUNCTION__, vlan_id); #endif /* sanity check */ if (vlan_id >= VLAN_VID_MASK) return -EINVAL; ASSERT_RTNL(); grp = vlan_find_group(real_dev_ifindex); ret = 0; if (grp) { dev = vlan_group_get_device(grp, vlan_id); if (dev) { /* Remove proc entry */ vlan_proc_rem_dev(dev); /* Take it out of our own structures, but be sure to * interlock with HW accelerating devices or SW vlan * input packet processing. */ if (real_dev->features & (NETIF_F_HW_VLAN_RX | NETIF_F_HW_VLAN_FILTER)) { real_dev->vlan_rx_kill_vid(real_dev, vlan_id); } vlan_group_set_device(grp, vlan_id, NULL); synchronize_net(); /* Caller unregisters (and if necessary, puts) * VLAN device, but we get rid of the reference to * real_dev here. */ dev_put(real_dev); /* If the group is now empty, kill off the * group. */ for (i = 0; i < VLAN_VID_MASK; i++) if (vlan_group_get_device(grp, i)) break; if (i == VLAN_VID_MASK) { if (real_dev->features & NETIF_F_HW_VLAN_RX) real_dev->vlan_rx_register(real_dev, NULL); hlist_del_rcu(&grp->hlist); /* Free the group, after all cpu's are done. */ call_rcu(&grp->rcu, vlan_rcu_free); grp = NULL; ret = 1; } } } return ret; }