X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=drivers%2Fnet%2Fbonding%2Fbond_main.c;h=a641eeaa2a2f488bdef9a074e431c187321135f7;hb=e5a4ad0dda8f79a984ba6391af65274b482b6703;hp=3b6d66a8ab9840e35c8efae00c4c12b141933ccd;hpb=b59f9f74c4c0a569398f08c34a877f1b7b457496;p=linux-2.6 diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 3b6d66a8ab..a641eeaa2a 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -772,39 +772,49 @@ static struct dev_mc_list *bond_mc_list_find_dmi(struct dev_mc_list *dmi, struct /* * 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; } /* @@ -965,6 +975,7 @@ static void bond_mc_swap(struct bonding *bond, struct slave *new_active, struct } if (new_active) { + /* FIXME: Signal errors upstream. */ if (bond->dev->flags & IFF_PROMISC) { dev_set_promiscuity(new_active->dev, 1); } @@ -1544,20 +1555,24 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) 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) { @@ -1921,9 +1936,9 @@ int bond_release(struct net_device *bond_dev, struct net_device *slave_dev) } /* 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); @@ -2044,9 +2059,9 @@ static int bond_release_all(struct net_device *bond_dev) } /* 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); @@ -4065,6 +4080,10 @@ static void bond_set_multicast_list(struct net_device *bond_dev) * 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); } @@ -4074,6 +4093,10 @@ static void bond_set_multicast_list(struct net_device *bond_dev) /* 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); } @@ -4650,9 +4673,9 @@ static void bond_free_all(void) 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); @@ -4750,11 +4773,11 @@ static int bond_check_params(struct bond_params *params) } } - if (max_bonds < 1 || max_bonds > INT_MAX) { + if (max_bonds < 0 || max_bonds > INT_MAX) { printk(KERN_WARNING DRV_NAME ": Warning: max_bonds (%d) not in range %d-%d, so it " "was reset to BOND_DEFAULT_MAX_BONDS (%d)\n", - max_bonds, 1, INT_MAX, BOND_DEFAULT_MAX_BONDS); + max_bonds, 0, INT_MAX, BOND_DEFAULT_MAX_BONDS); max_bonds = BOND_DEFAULT_MAX_BONDS; } @@ -4953,7 +4976,7 @@ static int bond_check_params(struct bond_params *params) printk("\n"); - } else { + } else if (max_bonds) { /* miimon and arp_interval not set, we need one so things * work as expected, see bonding.txt for details */ @@ -5018,6 +5041,22 @@ static int bond_check_params(struct bond_params *params) } 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. @@ -5076,7 +5115,7 @@ int bond_create(char *name, struct bond_params *params) 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);