]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - drivers/net/bonding/bond_main.c
Merge branch 'pm-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael...
[karo-tx-linux.git] / drivers / net / bonding / bond_main.c
index d72c37f03e506d269de69c1c3b4e1f5240d28e9e..435984ad8b2f1a8bedd54ba49eb4269f3991bd3a 100644 (file)
@@ -431,17 +431,13 @@ int bond_dev_queue_xmit(struct bonding *bond, struct sk_buff *skb,
 static int bond_vlan_rx_add_vid(struct net_device *bond_dev, uint16_t vid)
 {
        struct bonding *bond = netdev_priv(bond_dev);
-       struct slave *slave;
+       struct slave *slave, *stop_at;
        int i, res;
 
        bond_for_each_slave(bond, slave, i) {
-               struct net_device *slave_dev = slave->dev;
-               const struct net_device_ops *slave_ops = slave_dev->netdev_ops;
-
-               if ((slave_dev->features & NETIF_F_HW_VLAN_FILTER) &&
-                   slave_ops->ndo_vlan_rx_add_vid) {
-                       slave_ops->ndo_vlan_rx_add_vid(slave_dev, vid);
-               }
+               res = vlan_vid_add(slave->dev, vid);
+               if (res)
+                       goto unwind;
        }
 
        res = bond_add_vlan(bond, vid);
@@ -452,6 +448,14 @@ static int bond_vlan_rx_add_vid(struct net_device *bond_dev, uint16_t vid)
        }
 
        return 0;
+
+unwind:
+       /* unwind from head to the slave that failed */
+       stop_at = slave;
+       bond_for_each_slave_from_to(bond, slave, i, bond->first_slave, stop_at)
+               vlan_vid_del(slave->dev, vid);
+
+       return res;
 }
 
 /**
@@ -465,15 +469,8 @@ static int bond_vlan_rx_kill_vid(struct net_device *bond_dev, uint16_t vid)
        struct slave *slave;
        int i, res;
 
-       bond_for_each_slave(bond, slave, i) {
-               struct net_device *slave_dev = slave->dev;
-               const struct net_device_ops *slave_ops = slave_dev->netdev_ops;
-
-               if ((slave_dev->features & NETIF_F_HW_VLAN_FILTER) &&
-                   slave_ops->ndo_vlan_rx_kill_vid) {
-                       slave_ops->ndo_vlan_rx_kill_vid(slave_dev, vid);
-               }
-       }
+       bond_for_each_slave(bond, slave, i)
+               vlan_vid_del(slave->dev, vid);
 
        res = bond_del_vlan(bond, vid);
        if (res) {
@@ -488,30 +485,26 @@ static int bond_vlan_rx_kill_vid(struct net_device *bond_dev, uint16_t vid)
 static void bond_add_vlans_on_slave(struct bonding *bond, struct net_device *slave_dev)
 {
        struct vlan_entry *vlan;
-       const struct net_device_ops *slave_ops = slave_dev->netdev_ops;
-
-       if (!(slave_dev->features & NETIF_F_HW_VLAN_FILTER) ||
-           !(slave_ops->ndo_vlan_rx_add_vid))
-               return;
+       int res;
 
-       list_for_each_entry(vlan, &bond->vlan_list, vlan_list)
-               slave_ops->ndo_vlan_rx_add_vid(slave_dev, vlan->vlan_id);
+       list_for_each_entry(vlan, &bond->vlan_list, vlan_list) {
+               res = vlan_vid_add(slave_dev, vlan->vlan_id);
+               if (res)
+                       pr_warning("%s: Failed to add vlan id %d to device %s\n",
+                                  bond->dev->name, vlan->vlan_id,
+                                  slave_dev->name);
+       }
 }
 
 static void bond_del_vlans_from_slave(struct bonding *bond,
                                      struct net_device *slave_dev)
 {
-       const struct net_device_ops *slave_ops = slave_dev->netdev_ops;
        struct vlan_entry *vlan;
 
-       if (!(slave_dev->features & NETIF_F_HW_VLAN_FILTER) ||
-           !(slave_ops->ndo_vlan_rx_kill_vid))
-               return;
-
        list_for_each_entry(vlan, &bond->vlan_list, vlan_list) {
                if (!vlan->vlan_id)
                        continue;
-               slave_ops->ndo_vlan_rx_kill_vid(slave_dev, vlan->vlan_id);
+               vlan_vid_del(slave_dev, vlan->vlan_id);
        }
 }
 
@@ -1829,7 +1822,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
                                 "but new slave device does not support netpoll.\n",
                                 bond_dev->name);
                        res = -EBUSY;
-                       goto err_close;
+                       goto err_detach;
                }
        }
 #endif
@@ -1838,7 +1831,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
 
        res = bond_create_slave_symlinks(bond_dev, slave_dev);
        if (res)
-               goto err_close;
+               goto err_detach;
 
        res = netdev_rx_handler_register(slave_dev, bond_handle_frame,
                                         new_slave);
@@ -1859,6 +1852,11 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
 err_dest_symlinks:
        bond_destroy_slave_symlinks(bond_dev, slave_dev);
 
+err_detach:
+       write_lock_bh(&bond->lock);
+       bond_detach_slave(bond, new_slave);
+       write_unlock_bh(&bond->lock);
+
 err_close:
        dev_close(slave_dev);