* also added text to distinguish type of load balancing (rr or xor)
* - change arp_ip_target module param from "1-12s" (array of 12 ptrs)
* to "s" (a single ptr)
+ *
+ * 2002/09/18 - Jay Vosburgh <fubar at us dot ibm dot com>
+ * - Fixed up bond_check_dev_link() (and callers): removed some magic
+ * numbers, banished local MII_ defines, wrapped ioctl calls to
+ * prevent EFAULT errors
*/
#include <linux/config.h>
#define BOND_LINK_MON_INTERV 0
#endif
-#undef MII_LINK_UP
-#define MII_LINK_UP 0x04
-
-#undef MII_ENDOF_NWAY
-#define MII_ENDOF_NWAY 0x20
-
-#undef MII_LINK_READY
-#define MII_LINK_READY (MII_LINK_UP)
-
#ifndef BOND_LINK_ARP_INTERV
#define BOND_LINK_ARP_INTERV 0
#endif
return slave;
}
+/*
+ * Less bad way to call ioctl from within the kernel; this needs to be
+ * done some other way to get the call out of interrupt context.
+ * Needs "ioctl" variable to be supplied by calling context.
+ */
+#define IOCTL(dev, arg, cmd) ({ \
+ int ret; \
+ mm_segment_t fs = get_fs(); \
+ set_fs(get_ds()); \
+ ret = ioctl(dev, arg, cmd); \
+ set_fs(fs); \
+ ret; })
+
/*
- * if <dev> supports MII link status reporting, check its link
- * and report it as a bit field in a short int :
- * - 0x04 means link is up,
- * - 0x20 means end of autonegociation
- * If the device doesn't support MII, then we only report 0x24,
- * meaning that the link is up and running since we can't check it.
+ * if <dev> supports MII link status reporting, check its link status.
+ *
+ * Return either BMSR_LSTATUS, meaning that the link is up (or we
+ * can't tell and just pretend it is), or 0, meaning that the link is
+ * down.
*/
static u16 bond_check_dev_link(struct net_device *dev)
{
struct mii_ioctl_data *mii;
struct ethtool_value etool;
- if ((ioctl = dev->do_ioctl) != NULL) { /* ioctl to access MII */
+ ioctl = dev->do_ioctl;
+ if (ioctl) {
/* TODO: set pointer to correct ioctl on a per team member */
/* bases to make this more efficient. that is, once */
/* we determine the correct ioctl, we will always */
/* effect... */
etool.cmd = ETHTOOL_GLINK;
ifr.ifr_data = (char*)&etool;
- if (ioctl(dev, &ifr, SIOCETHTOOL) == 0) {
+ if (IOCTL(dev, &ifr, SIOCETHTOOL) == 0) {
if (etool.data == 1) {
- return(MII_LINK_READY);
+ return BMSR_LSTATUS;
}
else {
return(0);
/* Yes, the mii is overlaid on the ifreq.ifr_ifru */
mii = (struct mii_ioctl_data *)&ifr.ifr_data;
- if (ioctl(dev, &ifr, SIOCGMIIPHY) != 0) {
- return MII_LINK_READY; /* can't tell */
+ if (IOCTL(dev, &ifr, SIOCGMIIPHY) != 0) {
+ return BMSR_LSTATUS; /* can't tell */
}
- mii->reg_num = 1;
- if (ioctl(dev, &ifr, SIOCGMIIREG) == 0) {
- /*
- * mii->val_out contains MII reg 1, BMSR
- * 0x0004 means link established
- */
- return mii->val_out;
+ mii->reg_num = MII_BMSR;
+ if (IOCTL(dev, &ifr, SIOCGMIIREG) == 0) {
+ return mii->val_out & BMSR_LSTATUS;
}
}
- return MII_LINK_READY; /* spoof link up ( we can't check it) */
+ return BMSR_LSTATUS; /* spoof link up ( we can't check it) */
}
static u16 bond_check_mii_link(bonding_t *bond)
read_unlock(&bond->ptrlock);
read_unlock_irqrestore(&bond->lock, flags);
- return (has_active_interface ? MII_LINK_READY : 0);
+ return (has_active_interface ? BMSR_LSTATUS : 0);
}
static int bond_open(struct net_device *dev)
new_slave->link_failure_count = 0;
/* check for initial state */
- if ((miimon <= 0) || ((bond_check_dev_link(slave_dev) & MII_LINK_READY)
- == MII_LINK_READY)) {
+ if ((miimon <= 0) ||
+ (bond_check_dev_link(slave_dev) == BMSR_LSTATUS)) {
#ifdef BONDING_DEBUG
printk(KERN_CRIT "Initial state of slave_dev is BOND_LINK_UP\n");
#endif
switch (slave->link) {
case BOND_LINK_UP: /* the link was up */
- if ((link_state & MII_LINK_UP) == MII_LINK_UP) {
+ if (link_state == BMSR_LSTATUS) {
/* link stays up, tell that this one
is immediately available */
if (IS_UP(dev) && (mindelay > -2)) {
ensure proper action to be taken
*/
case BOND_LINK_FAIL: /* the link has just gone down */
- if ((link_state & MII_LINK_UP) == 0) {
+ if (link_state != BMSR_LSTATUS) {
/* link stays down */
if (slave->delay <= 0) {
/* link down for too long time */
} else {
slave->delay--;
}
- } else if ((link_state & MII_LINK_READY) == MII_LINK_READY) {
+ } else {
/* link up again */
slave->link = BOND_LINK_UP;
printk(KERN_INFO
}
break;
case BOND_LINK_DOWN: /* the link was down */
- if ((link_state & MII_LINK_READY) != MII_LINK_READY) {
+ if (link_state != BMSR_LSTATUS) {
/* the link stays down, nothing more to do */
break;
} else { /* link going up */
case there's something to do.
*/
case BOND_LINK_BACK: /* the link has just come back */
- if ((link_state & MII_LINK_UP) == 0) {
+ if (link_state != BMSR_LSTATUS) {
/* link down again */
slave->link = BOND_LINK_DOWN;
printk(KERN_INFO
master->name,
(updelay - slave->delay) * miimon,
dev->name);
- }
- else if ((link_state & MII_LINK_READY) == MII_LINK_READY) {
+ } else {
/* link stays up */
if (slave->delay == 0) {
/* now the link has been up for long time enough */
len += sprintf(buf + len, "MII Status: ");
len += sprintf(buf + len,
- link == MII_LINK_READY ? "up\n" : "down\n");
+ link == BMSR_LSTATUS ? "up\n" : "down\n");
len += sprintf(buf + len, "MII Polling Interval (ms): %d\n",
miimon);
len += sprintf(buf + len, "Up Delay (ms): %d\n", updelay);