vserver 1.9.5.x5
[linux-2.6.git] / drivers / net / bonding / bond_main.c
index 778fd07..2a4b7cb 100644 (file)
  *       * Add support for VLAN hardware acceleration capable slaves.
  *       * Add capability to tag self generated packets in ALB/TLB modes.
  *       Set version to 2.6.0.
+ * 2004/10/29 - Mitch Williams <mitch.a.williams at intel dot com>
+ *      - Fixed bug when unloading module while using 802.3ad.  If
+ *        spinlock debugging is turned on, this causes a stack dump.
+ *        Solution is to move call to dev_remove_pack outside of the
+ *        spinlock.
+ *        Set version to 2.6.1.
+ *
  */
 
 //#define BONDING_DEBUG 1
 #include <linux/socket.h>
 #include <linux/ctype.h>
 #include <linux/inet.h>
+#include <linux/bitops.h>
 #include <asm/system.h>
-#include <asm/bitops.h>
 #include <asm/io.h>
 #include <asm/dma.h>
 #include <asm/uaccess.h>
@@ -533,25 +540,25 @@ static char *lacp_rate    = NULL;
 static int arp_interval = BOND_LINK_ARP_INTERV;
 static char *arp_ip_target[BOND_MAX_ARP_TARGETS] = { NULL, };
 
-MODULE_PARM(max_bonds, "i");
+module_param(max_bonds, int, 0);
 MODULE_PARM_DESC(max_bonds, "Max number of bonded devices");
-MODULE_PARM(miimon, "i");
+module_param(miimon, int, 0);
 MODULE_PARM_DESC(miimon, "Link check interval in milliseconds");
-MODULE_PARM(updelay, "i");
+module_param(updelay, int, 0);
 MODULE_PARM_DESC(updelay, "Delay before considering link up, in milliseconds");
-MODULE_PARM(downdelay, "i");
+module_param(downdelay, int, 0);
 MODULE_PARM_DESC(downdelay, "Delay before considering link down, in milliseconds");
-MODULE_PARM(use_carrier, "i");
+module_param(use_carrier, int, 0);
 MODULE_PARM_DESC(use_carrier, "Use netif_carrier_ok (vs MII ioctls) in miimon; 0 for off, 1 for on (default)");
-MODULE_PARM(mode, "s");
+module_param(mode, charp, 0);
 MODULE_PARM_DESC(mode, "Mode of operation : 0 for round robin, 1 for active-backup, 2 for xor");
-MODULE_PARM(primary, "s");
+module_param(primary, charp, 0);
 MODULE_PARM_DESC(primary, "Primary network device to use");
-MODULE_PARM(lacp_rate, "s");
+module_param(lacp_rate, charp, 0);
 MODULE_PARM_DESC(lacp_rate, "LACPDU tx rate to request from 802.3ad partner (slow/fast)");
-MODULE_PARM(arp_interval, "i");
+module_param(arp_interval, int, 0);
 MODULE_PARM_DESC(arp_interval, "arp interval in milliseconds");
-MODULE_PARM(arp_ip_target, "1-" __MODULE_STRING(BOND_MAX_ARP_TARGETS) "s");
+module_param_array(arp_ip_target, charp, NULL, 0);
 MODULE_PARM_DESC(arp_ip_target, "arp targets in n.n.n.n form");
 
 /*----------------------------- Global variables ----------------------------*/
@@ -1103,7 +1110,7 @@ static int bond_check_dev_link(struct bonding *bond, struct net_device *slave_de
 
                /* Yes, the mii is overlaid on the ifreq.ifr_ifru */
                strncpy(ifr.ifr_name, slave_dev->name, IFNAMSIZ);
-               mii = (struct mii_ioctl_data *)&ifr.ifr_data;
+               mii = if_mii(&ifr);
                if (IOCTL(slave_dev, &ifr, SIOCGMIIPHY) == 0) {
                        mii->reg_num = MII_BMSR;
                        if (IOCTL(slave_dev, &ifr, SIOCGMIIREG) == 0) {
@@ -2357,10 +2364,10 @@ static int bond_ioctl_change_active(struct net_device *bond_dev, struct net_devi
 static int bond_ethtool_ioctl(struct net_device *bond_dev, struct ifreq *ifr)
 {
        struct ethtool_drvinfo info;
-       void *addr = ifr->ifr_data;
+       void __user *addr = ifr->ifr_data;
        uint32_t cmd;
 
-       if (get_user(cmd, (uint32_t *)addr)) {
+       if (get_user(cmd, (uint32_t __user *)addr)) {
                return -EFAULT;
        }
 
@@ -3566,15 +3573,15 @@ static int bond_close(struct net_device *bond_dev)
 {
        struct bonding *bond = bond_dev->priv;
 
-       write_lock_bh(&bond->lock);
-
-       bond_mc_list_destroy(bond);
-
        if (bond->params.mode == BOND_MODE_8023AD) {
                /* Unregister the receive of LACPDUs */
                bond_unregister_lacpdu(bond);
        }
 
+       write_lock_bh(&bond->lock);
+
+       bond_mc_list_destroy(bond);
+
        /* signal timers not to re-arm */
        bond->kill_timers = 1;
 
@@ -3667,8 +3674,10 @@ static struct net_device_stats *bond_get_stats(struct net_device *bond_dev)
 static int bond_do_ioctl(struct net_device *bond_dev, struct ifreq *ifr, int cmd)
 {
        struct net_device *slave_dev = NULL;
-       struct ifbond *u_binfo = NULL, k_binfo;
-       struct ifslave *u_sinfo = NULL, k_sinfo;
+       struct ifbond k_binfo;
+       struct ifbond __user *u_binfo = NULL;
+       struct ifslave k_sinfo;
+       struct ifslave __user *u_sinfo = NULL;
        struct mii_ioctl_data *mii = NULL;
        int prev_abi_ver = orig_app_abi_ver;
        int res = 0;
@@ -3680,7 +3689,7 @@ static int bond_do_ioctl(struct net_device *bond_dev, struct ifreq *ifr, int cmd
        case SIOCETHTOOL:
                return bond_ethtool_ioctl(bond_dev, ifr);
        case SIOCGMIIPHY:
-               mii = (struct mii_ioctl_data *)&ifr->ifr_data;
+               mii = if_mii(ifr);
                if (!mii) {
                        return -EINVAL;
                }
@@ -3691,7 +3700,7 @@ static int bond_do_ioctl(struct net_device *bond_dev, struct ifreq *ifr, int cmd
                 * We do this again just in case we were called by SIOCGMIIREG
                 * instead of SIOCGMIIPHY.
                 */
-               mii = (struct mii_ioctl_data *)&ifr->ifr_data;
+               mii = if_mii(ifr);
                if (!mii) {
                        return -EINVAL;
                }
@@ -3711,7 +3720,7 @@ static int bond_do_ioctl(struct net_device *bond_dev, struct ifreq *ifr, int cmd
                return 0;
        case BOND_INFO_QUERY_OLD:
        case SIOCBONDINFOQUERY:
-               u_binfo = (struct ifbond *)ifr->ifr_data;
+               u_binfo = (struct ifbond __user *)ifr->ifr_data;
 
                if (copy_from_user(&k_binfo, u_binfo, sizeof(ifbond))) {
                        return -EFAULT;
@@ -3727,7 +3736,7 @@ static int bond_do_ioctl(struct net_device *bond_dev, struct ifreq *ifr, int cmd
                return res;
        case BOND_SLAVE_INFO_QUERY_OLD:
        case SIOCBONDSLAVEINFOQUERY:
-               u_sinfo = (struct ifslave *)ifr->ifr_data;
+               u_sinfo = (struct ifslave __user *)ifr->ifr_data;
 
                if (copy_from_user(&k_sinfo, u_sinfo, sizeof(ifslave))) {
                        return -EFAULT;
@@ -4212,13 +4221,6 @@ out:
        return 0;
 }
 
-#ifdef CONFIG_NET_FASTROUTE
-static int bond_accept_fastpath(struct net_device *bond_dev, struct dst_entry *dst)
-{
-       return -1;
-}
-#endif
-
 /*------------------------- Device initialization ---------------------------*/
 
 /*
@@ -4292,9 +4294,6 @@ static int __init bond_init(struct net_device *bond_dev, struct bond_params *par
        bond_set_mode_ops(bond_dev, bond->params.mode);
 
        bond_dev->destructor = free_netdev;
-#ifdef CONFIG_NET_FASTROUTE
-       bond_dev->accept_fastpath = bond_accept_fastpath;
-#endif
 
        /* Initialize the device options */
        bond_dev->tx_queue_len = 0;
@@ -4708,6 +4707,7 @@ static void __exit bonding_exit(void)
 module_init(bonding_init);
 module_exit(bonding_exit);
 MODULE_LICENSE("GPL");
+MODULE_VERSION(DRV_VERSION);
 MODULE_DESCRIPTION(DRV_DESCRIPTION ", v" DRV_VERSION);
 MODULE_AUTHOR("Thomas Davis, tadavis@lbl.gov and many others");
 MODULE_SUPPORTED_DEVICE("most ethernet devices");