/*
* Push the promiscuity flag down to appropriate slaves
*/
-static void bond_set_promiscuity(struct bonding *bond, int inc)
+static int bond_set_promiscuity(struct bonding *bond, int inc)
{
+ int err = 0;
if (USES_PRIMARY(bond->params.mode)) {
/* write lock already acquired */
if (bond->curr_active_slave) {
- dev_set_promiscuity(bond->curr_active_slave->dev, inc);
+ err = dev_set_promiscuity(bond->curr_active_slave->dev,
+ inc);
}
} else {
struct slave *slave;
int i;
bond_for_each_slave(bond, slave, i) {
- dev_set_promiscuity(slave->dev, inc);
+ err = dev_set_promiscuity(slave->dev, inc);
+ if (err)
+ return err;
}
}
+ return err;
}
/*
* Push the allmulti flag down to all slaves
*/
-static void bond_set_allmulti(struct bonding *bond, int inc)
+static int bond_set_allmulti(struct bonding *bond, int inc)
{
+ int err = 0;
if (USES_PRIMARY(bond->params.mode)) {
/* write lock already acquired */
if (bond->curr_active_slave) {
- dev_set_allmulti(bond->curr_active_slave->dev, inc);
+ err = dev_set_allmulti(bond->curr_active_slave->dev,
+ inc);
}
} else {
struct slave *slave;
int i;
bond_for_each_slave(bond, slave, i) {
- dev_set_allmulti(slave->dev, inc);
+ err = dev_set_allmulti(slave->dev, inc);
+ if (err)
+ return err;
}
}
+ return err;
}
/*
}
if (new_active) {
+ /* FIXME: Signal errors upstream. */
if (bond->dev->flags & IFF_PROMISC) {
dev_set_promiscuity(new_active->dev, 1);
}
if (!USES_PRIMARY(bond->params.mode)) {
/* set promiscuity level to new slave */
if (bond_dev->flags & IFF_PROMISC) {
- dev_set_promiscuity(slave_dev, 1);
+ res = dev_set_promiscuity(slave_dev, 1);
+ if (res)
+ goto err_close;
}
/* set allmulti level to new slave */
if (bond_dev->flags & IFF_ALLMULTI) {
- dev_set_allmulti(slave_dev, 1);
+ res = dev_set_allmulti(slave_dev, 1);
+ if (res)
+ goto err_close;
}
- netif_tx_lock_bh(bond_dev);
+ netif_addr_lock_bh(bond_dev);
/* upload master's mc_list to new slave */
for (dmi = bond_dev->mc_list; dmi; dmi = dmi->next) {
dev_mc_add (slave_dev, dmi->dmi_addr, dmi->dmi_addrlen, 0);
}
- netif_tx_unlock_bh(bond_dev);
+ netif_addr_unlock_bh(bond_dev);
}
if (bond->params.mode == BOND_MODE_8023AD) {
}
/* flush master's mc_list from slave */
- netif_tx_lock_bh(bond_dev);
+ netif_addr_lock_bh(bond_dev);
bond_mc_list_flush(bond_dev, slave_dev);
- netif_tx_unlock_bh(bond_dev);
+ netif_addr_unlock_bh(bond_dev);
}
netdev_set_master(slave_dev, NULL);
}
/* flush master's mc_list from slave */
- netif_tx_lock_bh(bond_dev);
+ netif_addr_lock_bh(bond_dev);
bond_mc_list_flush(bond_dev, slave_dev);
- netif_tx_unlock_bh(bond_dev);
+ netif_addr_unlock_bh(bond_dev);
}
netdev_set_master(slave_dev, NULL);
* Do promisc before checking multicast_mode
*/
if ((bond_dev->flags & IFF_PROMISC) && !(bond->flags & IFF_PROMISC)) {
+ /*
+ * FIXME: Need to handle the error when one of the multi-slaves
+ * encounters error.
+ */
bond_set_promiscuity(bond, 1);
}
/* set allmulti flag to slaves */
if ((bond_dev->flags & IFF_ALLMULTI) && !(bond->flags & IFF_ALLMULTI)) {
+ /*
+ * FIXME: Need to handle the error when one of the multi-slaves
+ * encounters error.
+ */
bond_set_allmulti(bond, 1);
}
struct net_device *bond_dev = bond->dev;
bond_work_cancel_all(bond);
- netif_tx_lock_bh(bond_dev);
+ netif_addr_lock_bh(bond_dev);
bond_mc_list_destroy(bond);
- netif_tx_unlock_bh(bond_dev);
+ netif_addr_unlock_bh(bond_dev);
/* Release the bonded slaves */
bond_release_all(bond_dev);
bond_destroy(bond);
}
static struct lock_class_key bonding_netdev_xmit_lock_key;
+static struct lock_class_key bonding_netdev_addr_lock_key;
+
+static void bond_set_lockdep_class_one(struct net_device *dev,
+ struct netdev_queue *txq,
+ void *_unused)
+{
+ lockdep_set_class(&txq->_xmit_lock,
+ &bonding_netdev_xmit_lock_key);
+}
+
+static void bond_set_lockdep_class(struct net_device *dev)
+{
+ lockdep_set_class(&dev->addr_list_lock,
+ &bonding_netdev_addr_lock_key);
+ netdev_for_each_tx_queue(dev, bond_set_lockdep_class_one, NULL);
+}
/* Create a new bond based on the specified name and bonding parameters.
* If name is NULL, obtain a suitable "bond%d" name for us.
goto out_bond;
}
- lockdep_set_class(&bond_dev->_xmit_lock, &bonding_netdev_xmit_lock_key);
+ bond_set_lockdep_class(bond_dev);
netif_carrier_off(bond_dev);