Merge branch 'upstream' of git://git.kernel.org/pub/scm/linux/kernel/git/linville...
authorJeff Garzik <jeff@garzik.org>
Tue, 26 Sep 2006 00:09:14 +0000 (20:09 -0400)
committerJeff Garzik <jeff@garzik.org>
Tue, 26 Sep 2006 00:09:14 +0000 (20:09 -0400)
28 files changed:
Documentation/networking/bonding.txt
drivers/net/acenic.c
drivers/net/bonding/bond_3ad.c
drivers/net/bonding/bond_main.c
drivers/net/bonding/bond_sysfs.c
drivers/net/bonding/bonding.h
drivers/net/e1000/e1000_hw.h
drivers/net/forcedeth.c
drivers/net/gt64240eth.h [deleted file]
drivers/net/phy/phy_device.c
drivers/net/s2io.c
drivers/net/skge.c
drivers/net/skge.h
drivers/net/smc91x.h
drivers/net/tokenring/lanstreamer.c
drivers/net/tokenring/lanstreamer.h
drivers/net/typhoon.c
include/asm-alpha/libata-portmap.h [deleted file]
include/asm-frv/libata-portmap.h [deleted file]
include/asm-i386/libata-portmap.h [deleted file]
include/asm-ia64/libata-portmap.h [deleted file]
include/asm-powerpc/libata-portmap.h [deleted file]
include/asm-sparc/libata-portmap.h [deleted file]
include/asm-sparc64/libata-portmap.h [deleted file]
include/asm-x86_64/libata-portmap.h [deleted file]
include/linux/if.h
include/linux/libata.h
include/linux/netdevice.h

index afac780..dc942ea 100644 (file)
@@ -192,6 +192,17 @@ or, for backwards compatibility, the option value.  E.g.,
 arp_interval
 
        Specifies the ARP link monitoring frequency in milliseconds.
+
+       The ARP monitor works by periodically checking the slave
+       devices to determine whether they have sent or received
+       traffic recently (the precise criteria depends upon the
+       bonding mode, and the state of the slave).  Regular traffic is
+       generated via ARP probes issued for the addresses specified by
+       the arp_ip_target option.
+
+       This behavior can be modified by the arp_validate option,
+       below.
+
        If ARP monitoring is used in an etherchannel compatible mode
        (modes 0 and 2), the switch should be configured in a mode
        that evenly distributes packets across all links. If the
@@ -213,6 +224,54 @@ arp_ip_target
        maximum number of targets that can be specified is 16.  The
        default value is no IP addresses.
 
+arp_validate
+
+       Specifies whether or not ARP probes and replies should be
+       validated in the active-backup mode.  This causes the ARP
+       monitor to examine the incoming ARP requests and replies, and
+       only consider a slave to be up if it is receiving the
+       appropriate ARP traffic.
+
+       Possible values are:
+
+       none or 0
+
+               No validation is performed.  This is the default.
+
+       active or 1
+
+               Validation is performed only for the active slave.
+
+       backup or 2
+
+               Validation is performed only for backup slaves.
+
+       all or 3
+
+               Validation is performed for all slaves.
+
+       For the active slave, the validation checks ARP replies to
+       confirm that they were generated by an arp_ip_target.  Since
+       backup slaves do not typically receive these replies, the
+       validation performed for backup slaves is on the ARP request
+       sent out via the active slave.  It is possible that some
+       switch or network configurations may result in situations
+       wherein the backup slaves do not receive the ARP requests; in
+       such a situation, validation of backup slaves must be
+       disabled.
+
+       This option is useful in network configurations in which
+       multiple bonding hosts are concurrently issuing ARPs to one or
+       more targets beyond a common switch.  Should the link between
+       the switch and target fail (but not the switch itself), the
+       probe traffic generated by the multiple bonding instances will
+       fool the standard ARP monitor into considering the links as
+       still up.  Use of the arp_validate option can resolve this, as
+       the ARP monitor will only consider ARP requests and replies
+       associated with its own instance of bonding.
+
+       This option was added in bonding version 3.1.0.
+
 downdelay
 
        Specifies the time, in milliseconds, to wait before disabling
index a075246..71a4f60 100644 (file)
@@ -163,11 +163,7 @@ MODULE_DEVICE_TABLE(pci, acenic_pci_tbl);
 #define SET_NETDEV_DEV(net, pdev)      do{} while(0)
 #endif
 
-#if LINUX_VERSION_CODE >= 0x2051c
 #define ace_sync_irq(irq)      synchronize_irq(irq)
-#else
-#define ace_sync_irq(irq)      synchronize_irq()
-#endif
 
 #ifndef offset_in_page
 #define offset_in_page(ptr)    ((unsigned long)(ptr) & ~PAGE_MASK)
index 6a40707..3fb354d 100644 (file)
@@ -85,6 +85,7 @@
 #define     AD_LINK_SPEED_BITMASK_10MBPS      0x2
 #define     AD_LINK_SPEED_BITMASK_100MBPS     0x4
 #define     AD_LINK_SPEED_BITMASK_1000MBPS    0x8
+#define     AD_LINK_SPEED_BITMASK_10000MBPS   0x10
 //endalloun
 
 // compare MAC addresses
@@ -99,7 +100,7 @@ static u16 __get_link_speed(struct port *port);
 static u8 __get_duplex(struct port *port);
 static inline void __initialize_port_locks(struct port *port);
 //conversions
-static void __ntohs_lacpdu(struct lacpdu *lacpdu);
+static void __htons_lacpdu(struct lacpdu *lacpdu);
 static u16 __ad_timer_to_ticks(u16 timer_type, u16 Par);
 
 
@@ -330,7 +331,8 @@ static inline void __release_rx_machine_lock(struct port *port)
  *     0,
  *     %AD_LINK_SPEED_BITMASK_10MBPS,
  *     %AD_LINK_SPEED_BITMASK_100MBPS,
- *     %AD_LINK_SPEED_BITMASK_1000MBPS
+ *     %AD_LINK_SPEED_BITMASK_1000MBPS,
+ *     %AD_LINK_SPEED_BITMASK_10000MBPS
  */
 static u16 __get_link_speed(struct port *port)
 {
@@ -357,6 +359,10 @@ static u16 __get_link_speed(struct port *port)
                        speed = AD_LINK_SPEED_BITMASK_1000MBPS;
                        break;
 
+               case SPEED_10000:
+                       speed = AD_LINK_SPEED_BITMASK_10000MBPS;
+                       break;
+
                default:
                        speed = 0; // unknown speed value from ethtool. shouldn't happen
                        break;
@@ -414,23 +420,23 @@ static inline void __initialize_port_locks(struct port *port)
 
 //conversions
 /**
- * __ntohs_lacpdu - convert the contents of a LACPDU to host byte order
+ * __htons_lacpdu - convert the contents of a LACPDU to network byte order
  * @lacpdu: the speicifed lacpdu
  *
  * For each multi-byte field in the lacpdu, convert its content
  */
-static void __ntohs_lacpdu(struct lacpdu *lacpdu)
+static void __htons_lacpdu(struct lacpdu *lacpdu)
 {
        if (lacpdu) {
-               lacpdu->actor_system_priority =   ntohs(lacpdu->actor_system_priority);
-               lacpdu->actor_key =               ntohs(lacpdu->actor_key);
-               lacpdu->actor_port_priority =     ntohs(lacpdu->actor_port_priority);
-               lacpdu->actor_port =              ntohs(lacpdu->actor_port);
-               lacpdu->partner_system_priority = ntohs(lacpdu->partner_system_priority);
-               lacpdu->partner_key =             ntohs(lacpdu->partner_key);
-               lacpdu->partner_port_priority =   ntohs(lacpdu->partner_port_priority);
-               lacpdu->partner_port =            ntohs(lacpdu->partner_port);
-               lacpdu->collector_max_delay =     ntohs(lacpdu->collector_max_delay);
+               lacpdu->actor_system_priority =   htons(lacpdu->actor_system_priority);
+               lacpdu->actor_key =               htons(lacpdu->actor_key);
+               lacpdu->actor_port_priority =     htons(lacpdu->actor_port_priority);
+               lacpdu->actor_port =              htons(lacpdu->actor_port);
+               lacpdu->partner_system_priority = htons(lacpdu->partner_system_priority);
+               lacpdu->partner_key =             htons(lacpdu->partner_key);
+               lacpdu->partner_port_priority =   htons(lacpdu->partner_port_priority);
+               lacpdu->partner_port =            htons(lacpdu->partner_port);
+               lacpdu->collector_max_delay =     htons(lacpdu->collector_max_delay);
        }
 }
 
@@ -490,11 +496,11 @@ static void __record_pdu(struct lacpdu *lacpdu, struct port *port)
        // validate lacpdu and port
        if (lacpdu && port) {
                // record the new parameter values for the partner operational
-               port->partner_oper_port_number = lacpdu->actor_port;
-               port->partner_oper_port_priority = lacpdu->actor_port_priority;
+               port->partner_oper_port_number = ntohs(lacpdu->actor_port);
+               port->partner_oper_port_priority = ntohs(lacpdu->actor_port_priority);
                port->partner_oper_system = lacpdu->actor_system;
-               port->partner_oper_system_priority = lacpdu->actor_system_priority;
-               port->partner_oper_key = lacpdu->actor_key;
+               port->partner_oper_system_priority = ntohs(lacpdu->actor_system_priority);
+               port->partner_oper_key = ntohs(lacpdu->actor_key);
                // zero partener's lase states
                port->partner_oper_port_state = 0;
                port->partner_oper_port_state |= (lacpdu->actor_state & AD_STATE_LACP_ACTIVITY);
@@ -561,11 +567,11 @@ static void __update_selected(struct lacpdu *lacpdu, struct port *port)
        // validate lacpdu and port
        if (lacpdu && port) {
                // check if any parameter is different
-               if ((lacpdu->actor_port != port->partner_oper_port_number) ||
-                   (lacpdu->actor_port_priority != port->partner_oper_port_priority) ||
+               if ((ntohs(lacpdu->actor_port) != port->partner_oper_port_number) ||
+                   (ntohs(lacpdu->actor_port_priority) != port->partner_oper_port_priority) ||
                    MAC_ADDRESS_COMPARE(&(lacpdu->actor_system), &(port->partner_oper_system)) ||
-                   (lacpdu->actor_system_priority != port->partner_oper_system_priority) ||
-                   (lacpdu->actor_key != port->partner_oper_key) ||
+                   (ntohs(lacpdu->actor_system_priority) != port->partner_oper_system_priority) ||
+                   (ntohs(lacpdu->actor_key) != port->partner_oper_key) ||
                    ((lacpdu->actor_state & AD_STATE_AGGREGATION) != (port->partner_oper_port_state & AD_STATE_AGGREGATION))
                   ) {
                        // update the state machine Selected variable
@@ -628,11 +634,11 @@ static void __choose_matched(struct lacpdu *lacpdu, struct port *port)
        // validate lacpdu and port
        if (lacpdu && port) {
                // check if all parameters are alike
-               if (((lacpdu->partner_port == port->actor_port_number) &&
-                    (lacpdu->partner_port_priority == port->actor_port_priority) &&
+               if (((ntohs(lacpdu->partner_port) == port->actor_port_number) &&
+                    (ntohs(lacpdu->partner_port_priority) == port->actor_port_priority) &&
                     !MAC_ADDRESS_COMPARE(&(lacpdu->partner_system), &(port->actor_system)) &&
-                    (lacpdu->partner_system_priority == port->actor_system_priority) &&
-                    (lacpdu->partner_key == port->actor_oper_port_key) &&
+                    (ntohs(lacpdu->partner_system_priority) == port->actor_system_priority) &&
+                    (ntohs(lacpdu->partner_key) == port->actor_oper_port_key) &&
                     ((lacpdu->partner_state & AD_STATE_AGGREGATION) == (port->actor_oper_port_state & AD_STATE_AGGREGATION))) ||
                    // or this is individual link(aggregation == FALSE)
                    ((lacpdu->actor_state & AD_STATE_AGGREGATION) == 0)
@@ -662,11 +668,11 @@ static void __update_ntt(struct lacpdu *lacpdu, struct port *port)
        // validate lacpdu and port
        if (lacpdu && port) {
                // check if any parameter is different
-               if ((lacpdu->partner_port != port->actor_port_number) ||
-                   (lacpdu->partner_port_priority != port->actor_port_priority) ||
+               if ((ntohs(lacpdu->partner_port) != port->actor_port_number) ||
+                   (ntohs(lacpdu->partner_port_priority) != port->actor_port_priority) ||
                    MAC_ADDRESS_COMPARE(&(lacpdu->partner_system), &(port->actor_system)) ||
-                   (lacpdu->partner_system_priority != port->actor_system_priority) ||
-                   (lacpdu->partner_key != port->actor_oper_port_key) ||
+                   (ntohs(lacpdu->partner_system_priority) != port->actor_system_priority) ||
+                   (ntohs(lacpdu->partner_key) != port->actor_oper_port_key) ||
                    ((lacpdu->partner_state & AD_STATE_LACP_ACTIVITY) != (port->actor_oper_port_state & AD_STATE_LACP_ACTIVITY)) ||
                    ((lacpdu->partner_state & AD_STATE_LACP_TIMEOUT) != (port->actor_oper_port_state & AD_STATE_LACP_TIMEOUT)) ||
                    ((lacpdu->partner_state & AD_STATE_SYNCHRONIZATION) != (port->actor_oper_port_state & AD_STATE_SYNCHRONIZATION)) ||
@@ -775,6 +781,9 @@ static u32 __get_agg_bandwidth(struct aggregator *aggregator)
                case AD_LINK_SPEED_BITMASK_1000MBPS:
                        bandwidth = aggregator->num_of_ports * 1000;
                        break;
+               case AD_LINK_SPEED_BITMASK_10000MBPS:
+                       bandwidth = aggregator->num_of_ports * 10000;
+                       break;
                default:
                        bandwidth=0; // to silent the compilor ....
                }
@@ -847,7 +856,7 @@ static inline void __update_lacpdu_from_port(struct port *port)
         */
 
        /* Convert all non u8 parameters to Big Endian for transmit */
-       __ntohs_lacpdu(lacpdu);
+       __htons_lacpdu(lacpdu);
 }
 
 //////////////////////////////////////////////////////////////////////////////////////
@@ -2171,7 +2180,6 @@ static void bond_3ad_rx_indication(struct lacpdu *lacpdu, struct slave *slave, u
 
                switch (lacpdu->subtype) {
                case AD_TYPE_LACPDU:
-                       __ntohs_lacpdu(lacpdu);
                        dprintk("Received LACPDU on port %d\n", port->actor_port_number);
                        ad_rx_machine(lacpdu, port);
                        break;
index 850aae2..0fb5f65 100644 (file)
@@ -96,6 +96,7 @@ static char *lacp_rate        = NULL;
 static char *xmit_hash_policy = NULL;
 static int arp_interval = BOND_LINK_ARP_INTERV;
 static char *arp_ip_target[BOND_MAX_ARP_TARGETS] = { NULL, };
+static char *arp_validate = NULL;
 struct bond_params bonding_defaults;
 
 module_param(max_bonds, int, 0);
@@ -127,6 +128,8 @@ module_param(arp_interval, int, 0);
 MODULE_PARM_DESC(arp_interval, "arp interval in milliseconds");
 module_param_array(arp_ip_target, charp, NULL, 0);
 MODULE_PARM_DESC(arp_ip_target, "arp targets in n.n.n.n form");
+module_param(arp_validate, charp, 0);
+MODULE_PARM_DESC(arp_validate, "validate src/dst of ARP probes: none (default), active, backup or all");
 
 /*----------------------------- Global variables ----------------------------*/
 
@@ -170,6 +173,14 @@ struct bond_parm_tbl xmit_hashtype_tbl[] = {
 {      NULL,                   -1},
 };
 
+struct bond_parm_tbl arp_validate_tbl[] = {
+{      "none",                 BOND_ARP_VALIDATE_NONE},
+{      "active",               BOND_ARP_VALIDATE_ACTIVE},
+{      "backup",               BOND_ARP_VALIDATE_BACKUP},
+{      "all",                  BOND_ARP_VALIDATE_ALL},
+{      NULL,                   -1},
+};
+
 /*-------------------------- Forward declarations ---------------------------*/
 
 static void bond_send_gratuitous_arp(struct bonding *bond);
@@ -638,6 +649,7 @@ verify:
        case SPEED_10:
        case SPEED_100:
        case SPEED_1000:
+       case SPEED_10000:
                break;
        default:
                return -1;
@@ -1210,10 +1222,14 @@ static int bond_compute_features(struct bonding *bond)
        unsigned long features = BOND_INTERSECT_FEATURES;
        struct slave *slave;
        struct net_device *bond_dev = bond->dev;
+       unsigned short max_hard_header_len = ETH_HLEN;
        int i;
 
-       bond_for_each_slave(bond, slave, i)
+       bond_for_each_slave(bond, slave, i) {
                features &= (slave->dev->features & BOND_INTERSECT_FEATURES);
+               if (slave->dev->hard_header_len > max_hard_header_len)
+                       max_hard_header_len = slave->dev->hard_header_len;
+       }
 
        if ((features & NETIF_F_SG) && 
            !(features & NETIF_F_ALL_CSUM))
@@ -1231,6 +1247,7 @@ static int bond_compute_features(struct bonding *bond)
 
        features |= (bond_dev->features & ~BOND_INTERSECT_FEATURES);
        bond_dev->features = features;
+       bond_dev->hard_header_len = max_hard_header_len;
 
        return 0;
 }
@@ -1365,6 +1382,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
        }
 
        new_slave->dev = slave_dev;
+       slave_dev->priv_flags |= IFF_BONDING;
 
        if ((bond->params.mode == BOND_MODE_TLB) ||
            (bond->params.mode == BOND_MODE_ALB)) {
@@ -1417,6 +1435,8 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
 
        bond_compute_features(bond);
 
+       new_slave->last_arp_rx = jiffies;
+
        if (bond->params.miimon && !bond->params.use_carrier) {
                link_reporting = bond_check_dev_link(bond, slave_dev, 1);
 
@@ -1493,29 +1513,8 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
 
        switch (bond->params.mode) {
        case BOND_MODE_ACTIVEBACKUP:
-               /* if we're in active-backup mode, we need one and
-                * only one active interface. The backup interfaces
-                * will have their SLAVE_INACTIVE flag set because we
-                * need them to be drop all packets. Thus, since we
-                * guarantee that curr_active_slave always point to
-                * the last usable interface, we just have to verify
-                * this interface's flag.
-                */
-               if (((!bond->curr_active_slave) ||
-                    (bond->curr_active_slave->dev->priv_flags & IFF_SLAVE_INACTIVE)) &&
-                   (new_slave->link != BOND_LINK_DOWN)) {
-                       /* first slave or no active slave yet, and this link
-                          is OK, so make this interface the active one */
-                       bond_change_active_slave(bond, new_slave);
-                       printk(KERN_INFO DRV_NAME
-                              ": %s: first active interface up!\n",
-                              bond->dev->name);
-                       netif_carrier_on(bond->dev);
-
-               } else {
-                       dprintk("This is just a backup slave\n");
-                       bond_set_slave_inactive_flags(new_slave);
-               }
+               bond_set_slave_inactive_flags(new_slave);
+               bond_select_active_slave(bond);
                break;
        case BOND_MODE_8023AD:
                /* in 802.3ad mode, the internal mechanism
@@ -1778,7 +1777,8 @@ int bond_release(struct net_device *bond_dev, struct net_device *slave_dev)
        dev_set_mac_address(slave_dev, &addr);
 
        slave_dev->priv_flags &= ~(IFF_MASTER_8023AD | IFF_MASTER_ALB |
-                                  IFF_SLAVE_INACTIVE);
+                                  IFF_SLAVE_INACTIVE | IFF_BONDING |
+                                  IFF_SLAVE_NEEDARP);
 
        kfree(slave);
 
@@ -2291,6 +2291,25 @@ static int bond_has_ip(struct bonding *bond)
        return 0;
 }
 
+static int bond_has_this_ip(struct bonding *bond, u32 ip)
+{
+       struct vlan_entry *vlan, *vlan_next;
+
+       if (ip == bond->master_ip)
+               return 1;
+
+       if (list_empty(&bond->vlan_list))
+               return 0;
+
+       list_for_each_entry_safe(vlan, vlan_next, &bond->vlan_list,
+                                vlan_list) {
+               if (ip == vlan->vlan_ip)
+                       return 1;
+       }
+
+       return 0;
+}
+
 /*
  * We go to the (large) trouble of VLAN tagging ARP frames because
  * switches in VLAN mode (especially if ports are configured as
@@ -2429,6 +2448,93 @@ static void bond_send_gratuitous_arp(struct bonding *bond)
        }
 }
 
+static void bond_validate_arp(struct bonding *bond, struct slave *slave, u32 sip, u32 tip)
+{
+       int i;
+       u32 *targets = bond->params.arp_targets;
+
+       targets = bond->params.arp_targets;
+       for (i = 0; (i < BOND_MAX_ARP_TARGETS) && targets[i]; i++) {
+               dprintk("bva: sip %u.%u.%u.%u tip %u.%u.%u.%u t[%d] "
+                       "%u.%u.%u.%u bhti(tip) %d\n",
+                      NIPQUAD(sip), NIPQUAD(tip), i, NIPQUAD(targets[i]),
+                      bond_has_this_ip(bond, tip));
+               if (sip == targets[i]) {
+                       if (bond_has_this_ip(bond, tip))
+                               slave->last_arp_rx = jiffies;
+                       return;
+               }
+       }
+}
+
+static int bond_arp_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, struct net_device *orig_dev)
+{
+       struct arphdr *arp;
+       struct slave *slave;
+       struct bonding *bond;
+       unsigned char *arp_ptr;
+       u32 sip, tip;
+
+       if (!(dev->priv_flags & IFF_BONDING) || !(dev->flags & IFF_MASTER))
+               goto out;
+
+       bond = dev->priv;
+       read_lock(&bond->lock);
+
+       dprintk("bond_arp_rcv: bond %s skb->dev %s orig_dev %s\n",
+               bond->dev->name, skb->dev ? skb->dev->name : "NULL",
+               orig_dev ? orig_dev->name : "NULL");
+
+       slave = bond_get_slave_by_dev(bond, orig_dev);
+       if (!slave || !slave_do_arp_validate(bond, slave))
+               goto out_unlock;
+
+       /* ARP header, plus 2 device addresses, plus 2 IP addresses.  */
+       if (!pskb_may_pull(skb, (sizeof(struct arphdr) +
+                                (2 * dev->addr_len) +
+                                (2 * sizeof(u32)))))
+               goto out_unlock;
+
+       arp = skb->nh.arph;
+       if (arp->ar_hln != dev->addr_len ||
+           skb->pkt_type == PACKET_OTHERHOST ||
+           skb->pkt_type == PACKET_LOOPBACK ||
+           arp->ar_hrd != htons(ARPHRD_ETHER) ||
+           arp->ar_pro != htons(ETH_P_IP) ||
+           arp->ar_pln != 4)
+               goto out_unlock;
+
+       arp_ptr = (unsigned char *)(arp + 1);
+       arp_ptr += dev->addr_len;
+       memcpy(&sip, arp_ptr, 4);
+       arp_ptr += 4 + dev->addr_len;
+       memcpy(&tip, arp_ptr, 4);
+
+       dprintk("bond_arp_rcv: %s %s/%d av %d sv %d sip %u.%u.%u.%u"
+               " tip %u.%u.%u.%u\n", bond->dev->name, slave->dev->name,
+               slave->state, bond->params.arp_validate,
+               slave_do_arp_validate(bond, slave), NIPQUAD(sip), NIPQUAD(tip));
+
+       /*
+        * Backup slaves won't see the ARP reply, but do come through
+        * here for each ARP probe (so we swap the sip/tip to validate
+        * the probe).  In a "redundant switch, common router" type of
+        * configuration, the ARP probe will (hopefully) travel from
+        * the active, through one switch, the router, then the other
+        * switch before reaching the backup.
+        */
+       if (slave->state == BOND_STATE_ACTIVE)
+               bond_validate_arp(bond, slave, sip, tip);
+       else
+               bond_validate_arp(bond, slave, tip, sip);
+
+out_unlock:
+       read_unlock(&bond->lock);
+out:
+       dev_kfree_skb(skb);
+       return NET_RX_SUCCESS;
+}
+
 /*
  * this function is called regularly to monitor each slave's link
  * ensuring that traffic is being sent and received when arp monitoring
@@ -2593,7 +2699,8 @@ void bond_activebackup_arp_mon(struct net_device *bond_dev)
         */
        bond_for_each_slave(bond, slave, i) {
                if (slave->link != BOND_LINK_UP) {
-                       if ((jiffies - slave->dev->last_rx) <= delta_in_ticks) {
+                       if ((jiffies - slave_last_rx(bond, slave)) <=
+                            delta_in_ticks) {
 
                                slave->link = BOND_LINK_UP;
 
@@ -2638,7 +2745,7 @@ void bond_activebackup_arp_mon(struct net_device *bond_dev)
 
                        if ((slave != bond->curr_active_slave) &&
                            (!bond->current_arp_slave) &&
-                           (((jiffies - slave->dev->last_rx) >= 3*delta_in_ticks) &&
+                           (((jiffies - slave_last_rx(bond, slave)) >= 3*delta_in_ticks) &&
                             bond_has_ip(bond))) {
                                /* a backup slave has gone down; three times
                                 * the delta allows the current slave to be
@@ -2685,7 +2792,7 @@ void bond_activebackup_arp_mon(struct net_device *bond_dev)
                 * if it is up and needs to take over as the curr_active_slave
                 */
                if ((((jiffies - slave->dev->trans_start) >= (2*delta_in_ticks)) ||
-           (((jiffies - slave->dev->last_rx) >= (2*delta_in_ticks)) &&
+           (((jiffies - slave_last_rx(bond, slave)) >= (2*delta_in_ticks)) &&
             bond_has_ip(bond))) &&
                    ((jiffies - slave->jiffies) >= 2*delta_in_ticks)) {
 
@@ -2950,7 +3057,7 @@ static void bond_info_show_slave(struct seq_file *seq, const struct slave *slave
        seq_printf(seq, "\nSlave Interface: %s\n", slave->dev->name);
        seq_printf(seq, "MII Status: %s\n",
                   (slave->link == BOND_LINK_UP) ?  "up" : "down");
-       seq_printf(seq, "Link Failure Count: %d\n",
+       seq_printf(seq, "Link Failure Count: %u\n",
                   slave->link_failure_count);
 
        seq_printf(seq,
@@ -3210,6 +3317,9 @@ static int bond_netdev_event(struct notifier_block *this, unsigned long event, v
                (event_dev ? event_dev->name : "None"),
                event);
 
+       if (!(event_dev->priv_flags & IFF_BONDING))
+               return NOTIFY_DONE;
+
        if (event_dev->flags & IFF_MASTER) {
                dprintk("IFF_MASTER\n");
                return bond_master_netdev_event(event, event_dev);
@@ -3305,6 +3415,21 @@ static void bond_unregister_lacpdu(struct bonding *bond)
        dev_remove_pack(&(BOND_AD_INFO(bond).ad_pkt_type));
 }
 
+void bond_register_arp(struct bonding *bond)
+{
+       struct packet_type *pt = &bond->arp_mon_pt;
+
+       pt->type = htons(ETH_P_ARP);
+       pt->dev = NULL; /*bond->dev;XXX*/
+       pt->func = bond_arp_rcv;
+       dev_add_pack(pt);
+}
+
+void bond_unregister_arp(struct bonding *bond)
+{
+       dev_remove_pack(&bond->arp_mon_pt);
+}
+
 /*---------------------------- Hashing Policies -----------------------------*/
 
 /*
@@ -3391,6 +3516,9 @@ static int bond_open(struct net_device *bond_dev)
                } else {
                        arp_timer->function = (void *)&bond_loadbalance_arp_mon;
                }
+               if (bond->params.arp_validate)
+                       bond_register_arp(bond);
+
                add_timer(arp_timer);
        }
 
@@ -3418,9 +3546,11 @@ static int bond_close(struct net_device *bond_dev)
                bond_unregister_lacpdu(bond);
        }
 
+       if (bond->params.arp_validate)
+               bond_unregister_arp(bond);
+
        write_lock_bh(&bond->lock);
 
-       bond_mc_list_destroy(bond);
 
        /* signal timers not to re-arm */
        bond->kill_timers = 1;
@@ -3451,8 +3581,6 @@ static int bond_close(struct net_device *bond_dev)
                break;
        }
 
-       /* Release the bonded slaves */
-       bond_release_all(bond_dev);
 
        if ((bond->params.mode == BOND_MODE_TLB) ||
            (bond->params.mode == BOND_MODE_ALB)) {
@@ -4179,6 +4307,7 @@ static int bond_init(struct net_device *bond_dev, struct bond_params *params)
        /* Initialize the device options */
        bond_dev->tx_queue_len = 0;
        bond_dev->flags |= IFF_MASTER|IFF_MULTICAST;
+       bond_dev->priv_flags |= IFF_BONDING;
 
        /* At first, we block adding VLANs. That's the only way to
         * prevent problems that occur when adding VLANs over an
@@ -4237,6 +4366,9 @@ static void bond_free_all(void)
        list_for_each_entry_safe(bond, nxt, &bond_dev_list, bond_list) {
                struct net_device *bond_dev = bond->dev;
 
+               bond_mc_list_destroy(bond);
+               /* Release the bonded slaves */
+               bond_release_all(bond_dev);
                unregister_netdevice(bond_dev);
                bond_deinit(bond_dev);
        }
@@ -4270,6 +4402,8 @@ int bond_parse_parm(char *mode_arg, struct bond_parm_tbl *tbl)
 
 static int bond_check_params(struct bond_params *params)
 {
+       int arp_validate_value;
+
        /*
         * Convert string parameters.
         */
@@ -4473,6 +4607,29 @@ static int bond_check_params(struct bond_params *params)
                arp_interval = 0;
        }
 
+       if (arp_validate) {
+               if (bond_mode != BOND_MODE_ACTIVEBACKUP) {
+                       printk(KERN_ERR DRV_NAME
+              ": arp_validate only supported in active-backup mode\n");
+                       return -EINVAL;
+               }
+               if (!arp_interval) {
+                       printk(KERN_ERR DRV_NAME
+                              ": arp_validate requires arp_interval\n");
+                       return -EINVAL;
+               }
+
+               arp_validate_value = bond_parse_parm(arp_validate,
+                                                    arp_validate_tbl);
+               if (arp_validate_value == -1) {
+                       printk(KERN_ERR DRV_NAME
+                              ": Error: invalid arp_validate \"%s\"\n",
+                              arp_validate == NULL ? "NULL" : arp_validate);
+                       return -EINVAL;
+               }
+       } else
+               arp_validate_value = 0;
+
        if (miimon) {
                printk(KERN_INFO DRV_NAME
                       ": MII link monitoring set to %d ms\n",
@@ -4481,8 +4638,10 @@ static int bond_check_params(struct bond_params *params)
                int i;
 
                printk(KERN_INFO DRV_NAME
-                      ": ARP monitoring set to %d ms with %d target(s):",
-                      arp_interval, arp_ip_count);
+                      ": ARP monitoring set to %d ms, validate %s, with %d target(s):",
+                      arp_interval,
+                      arp_validate_tbl[arp_validate_value].modename,
+                      arp_ip_count);
 
                for (i = 0; i < arp_ip_count; i++)
                        printk (" %s", arp_ip_target[i]);
@@ -4516,6 +4675,7 @@ static int bond_check_params(struct bond_params *params)
        params->xmit_policy = xmit_hashtype;
        params->miimon = miimon;
        params->arp_interval = arp_interval;
+       params->arp_validate = arp_validate_value;
        params->updelay = updelay;
        params->downdelay = downdelay;
        params->use_carrier = use_carrier;
index cfe4dc3..ced9ed8 100644 (file)
@@ -51,6 +51,7 @@ extern struct bond_params bonding_defaults;
 extern struct bond_parm_tbl bond_mode_tbl[];
 extern struct bond_parm_tbl bond_lacp_tbl[];
 extern struct bond_parm_tbl xmit_hashtype_tbl[];
+extern struct bond_parm_tbl arp_validate_tbl[];
 
 static int expected_refcount = -1;
 static struct class *netdev_class;
@@ -502,6 +503,53 @@ out:
 }
 static CLASS_DEVICE_ATTR(xmit_hash_policy, S_IRUGO | S_IWUSR, bonding_show_xmit_hash, bonding_store_xmit_hash);
 
+/*
+ * Show and set arp_validate.
+ */
+static ssize_t bonding_show_arp_validate(struct class_device *cd, char *buf)
+{
+       struct bonding *bond = to_bond(cd);
+
+       return sprintf(buf, "%s %d\n",
+                      arp_validate_tbl[bond->params.arp_validate].modename,
+                      bond->params.arp_validate) + 1;
+}
+
+static ssize_t bonding_store_arp_validate(struct class_device *cd, const char *buf, size_t count)
+{
+       int new_value;
+       struct bonding *bond = to_bond(cd);
+
+       new_value = bond_parse_parm((char *)buf, arp_validate_tbl);
+       if (new_value < 0) {
+               printk(KERN_ERR DRV_NAME
+                      ": %s: Ignoring invalid arp_validate value %s\n",
+                      bond->dev->name, buf);
+               return -EINVAL;
+       }
+       if (new_value && (bond->params.mode != BOND_MODE_ACTIVEBACKUP)) {
+               printk(KERN_ERR DRV_NAME
+                      ": %s: arp_validate only supported in active-backup mode.\n",
+                      bond->dev->name);
+               return -EINVAL;
+       }
+       printk(KERN_INFO DRV_NAME ": %s: setting arp_validate to %s (%d).\n",
+              bond->dev->name, arp_validate_tbl[new_value].modename,
+              new_value);
+
+       if (!bond->params.arp_validate && new_value) {
+               bond_register_arp(bond);
+       } else if (bond->params.arp_validate && !new_value) {
+               bond_unregister_arp(bond);
+       }
+
+       bond->params.arp_validate = new_value;
+
+       return count;
+}
+
+static CLASS_DEVICE_ATTR(arp_validate, S_IRUGO | S_IWUSR, bonding_show_arp_validate, bonding_store_arp_validate);
+
 /*
  * Show and set the arp timer interval.  There are two tricky bits
  * here.  First, if ARP monitoring is activated, then we must disable
@@ -914,6 +962,11 @@ static ssize_t bonding_store_miimon(struct class_device *cd, const char *buf, si
                               "ARP monitoring. Disabling ARP monitoring...\n",
                               bond->dev->name);
                        bond->params.arp_interval = 0;
+                       if (bond->params.arp_validate) {
+                               bond_unregister_arp(bond);
+                               bond->params.arp_validate =
+                                       BOND_ARP_VALIDATE_NONE;
+                       }
                        /* Kill ARP timer, else it brings bond's link down */
                        if (bond->mii_timer.function) {
                                printk(KERN_INFO DRV_NAME
@@ -1093,7 +1146,7 @@ static ssize_t bonding_store_active_slave(struct class_device *cd, const char *b
                             strlen(slave->dev->name)) == 0) {
                                old_active = bond->curr_active_slave;
                                new_active = slave;
-                               if (new_active && (new_active == old_active)) {
+                               if (new_active == old_active) {
                                        /* do nothing */
                                        printk(KERN_INFO DRV_NAME
                                               ": %s: %s is already the current active slave.\n",
@@ -1273,6 +1326,7 @@ static CLASS_DEVICE_ATTR(ad_partner_mac, S_IRUGO, bonding_show_ad_partner_mac, N
 static struct attribute *per_bond_attrs[] = {
        &class_device_attr_slaves.attr,
        &class_device_attr_mode.attr,
+       &class_device_attr_arp_validate.attr,
        &class_device_attr_arp_interval.attr,
        &class_device_attr_arp_ip_target.attr,
        &class_device_attr_downdelay.attr,
index 0bdfe2c..db16fee 100644 (file)
@@ -22,8 +22,8 @@
 #include "bond_3ad.h"
 #include "bond_alb.h"
 
-#define DRV_VERSION    "3.0.3"
-#define DRV_RELDATE    "March 23, 2006"
+#define DRV_VERSION    "3.1.0-test"
+#define DRV_RELDATE    "September 9, 2006"
 #define DRV_NAME       "bonding"
 #define DRV_DESCRIPTION        "Ethernet Channel Bonding Driver"
 
@@ -126,6 +126,7 @@ struct bond_params {
        int xmit_policy;
        int miimon;
        int arp_interval;
+       int arp_validate;
        int use_carrier;
        int updelay;
        int downdelay;
@@ -149,8 +150,9 @@ struct slave {
        struct net_device *dev; /* first - useful for panic debug */
        struct slave *next;
        struct slave *prev;
-       s16    delay;
+       int    delay;
        u32    jiffies;
+       u32    last_arp_rx;
        s8     link;    /* one of BOND_LINK_XXXX */
        s8     state;   /* one of BOND_STATE_XXXX */
        u32    original_flags;
@@ -198,6 +200,7 @@ struct bonding {
        struct   bond_params params;
        struct   list_head vlan_list;
        struct   vlan_group *vlgrp;
+       struct   packet_type arp_mon_pt;
 };
 
 /**
@@ -228,6 +231,25 @@ static inline struct bonding *bond_get_bond_by_slave(struct slave *slave)
        return (struct bonding *)slave->dev->master->priv;
 }
 
+#define BOND_ARP_VALIDATE_NONE         0
+#define BOND_ARP_VALIDATE_ACTIVE       (1 << BOND_STATE_ACTIVE)
+#define BOND_ARP_VALIDATE_BACKUP       (1 << BOND_STATE_BACKUP)
+#define BOND_ARP_VALIDATE_ALL          (BOND_ARP_VALIDATE_ACTIVE | \
+                                        BOND_ARP_VALIDATE_BACKUP)
+
+extern inline int slave_do_arp_validate(struct bonding *bond, struct slave *slave)
+{
+       return bond->params.arp_validate & (1 << slave->state);
+}
+
+extern inline u32 slave_last_rx(struct bonding *bond, struct slave *slave)
+{
+       if (slave_do_arp_validate(bond, slave))
+               return slave->last_arp_rx;
+
+       return slave->dev->last_rx;
+}
+
 static inline void bond_set_slave_inactive_flags(struct slave *slave)
 {
        struct bonding *bond = slave->dev->master->priv;
@@ -235,12 +257,14 @@ static inline void bond_set_slave_inactive_flags(struct slave *slave)
            bond->params.mode != BOND_MODE_ALB)
                slave->state = BOND_STATE_BACKUP;
        slave->dev->priv_flags |= IFF_SLAVE_INACTIVE;
+       if (slave_do_arp_validate(bond, slave))
+               slave->dev->priv_flags |= IFF_SLAVE_NEEDARP;
 }
 
 static inline void bond_set_slave_active_flags(struct slave *slave)
 {
        slave->state = BOND_STATE_ACTIVE;
-       slave->dev->priv_flags &= ~IFF_SLAVE_INACTIVE;
+       slave->dev->priv_flags &= ~(IFF_SLAVE_INACTIVE | IFF_SLAVE_NEEDARP);
 }
 
 static inline void bond_set_master_3ad_flags(struct bonding *bond)
@@ -284,6 +308,8 @@ int bond_parse_parm(char *mode_arg, struct bond_parm_tbl *tbl);
 const char *bond_mode_name(int mode);
 void bond_select_active_slave(struct bonding *bond);
 void bond_change_active_slave(struct bonding *bond, struct slave *new_active);
+void bond_register_arp(struct bonding *);
+void bond_unregister_arp(struct bonding *);
 
 #endif /* _LINUX_BONDING_H */
 
index a170e96..4020acb 100644 (file)
@@ -1367,8 +1367,8 @@ struct e1000_hw_stats {
 
 /* Structure containing variables used by the shared code (e1000_hw.c) */
 struct e1000_hw {
-    uint8_t *hw_addr;
-    uint8_t *flash_address;
+    uint8_t __iomem *hw_addr;
+    uint8_t __iomem *flash_address;
     e1000_mac_type mac_type;
     e1000_phy_type phy_type;
     uint32_t phy_init_script;
index 97db910..eea1d66 100644 (file)
@@ -3789,6 +3789,12 @@ static int nv_loopback_test(struct net_device *dev)
        /* setup packet for tx */
        pkt_len = ETH_DATA_LEN;
        tx_skb = dev_alloc_skb(pkt_len);
+       if (!tx_skb) {
+               printk(KERN_ERR "dev_alloc_skb() failed during loopback test"
+                        " of %s\n", dev->name);
+               ret = 0;
+               goto out;
+       }
        pkt_data = skb_put(tx_skb, pkt_len);
        for (i = 0; i < pkt_len; i++)
                pkt_data[i] = (u8)(i & 0xff);
@@ -3853,7 +3859,7 @@ static int nv_loopback_test(struct net_device *dev)
                       tx_skb->end-tx_skb->data,
                       PCI_DMA_TODEVICE);
        dev_kfree_skb_any(tx_skb);
-
+ out:
        /* stop engines */
        nv_stop_rx(dev);
        nv_stop_tx(dev);
diff --git a/drivers/net/gt64240eth.h b/drivers/net/gt64240eth.h
deleted file mode 100644 (file)
index 0d6f486..0000000
+++ /dev/null
@@ -1,402 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 2001 Patton Electronics Company
- * Copyright (C) 2002 Momentum Computer
- *
- * Copyright 2000 MontaVista Software Inc.
- * Author: MontaVista Software, Inc.
- *             stevel@mvista.com or support@mvista.com
- *
- *  This program is free software; you can distribute it and/or modify it
- *  under the terms of the GNU General Public License (Version 2) as
- *  published by the Free Software Foundation.
- *
- *  This program is distributed in the hope it will be useful, but WITHOUT
- *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- *  for more details.
- *
- *  You should have received a copy of the GNU General Public License along
- *  with this program; if not, write to the Free Software Foundation, Inc.,
- *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- *
- * Ethernet driver definitions for the MIPS GT96100 Advanced
- * Communication Controller.
- *
- * Modified for the Marvellous GT64240 Retarded Communication Controller.
- */
-#ifndef _GT64240ETH_H
-#define _GT64240ETH_H
-
-#include <asm/gt64240.h>
-
-#define ETHERNET_PORTS_DIFFERENCE_OFFSETS      0x400
-
-/* Translate those weanie names from Galileo/VxWorks header files: */
-
-#define GT64240_MRR                    MAIN_ROUTING_REGISTER
-#define GT64240_CIU_ARBITER_CONFIG     COMM_UNIT_ARBITER_CONFIGURATION_REGISTER
-#define GT64240_CIU_ARBITER_CONTROL    COMM_UNIT_ARBITER_CONTROL
-#define GT64240_MAIN_LOW_CAUSE         LOW_INTERRUPT_CAUSE_REGISTER
-#define GT64240_MAIN_HIGH_CAUSE        HIGH_INTERRUPT_CAUSE_REGISTER
-#define GT64240_CPU_LOW_MASK           CPU_INTERRUPT_MASK_REGISTER_LOW
-#define GT64240_CPU_HIGH_MASK          CPU_INTERRUPT_MASK_REGISTER_HIGH
-#define GT64240_CPU_SELECT_CAUSE       CPU_SELECT_CAUSE_REGISTER
-
-#define GT64240_ETH_PHY_ADDR_REG       ETHERNET_PHY_ADDRESS_REGISTER
-#define GT64240_ETH_PORT_CONFIG        ETHERNET0_PORT_CONFIGURATION_REGISTER
-#define GT64240_ETH_PORT_CONFIG_EXT    ETHERNET0_PORT_CONFIGURATION_EXTEND_REGISTER
-#define GT64240_ETH_PORT_COMMAND       ETHERNET0_PORT_COMMAND_REGISTER
-#define GT64240_ETH_PORT_STATUS        ETHERNET0_PORT_STATUS_REGISTER
-#define GT64240_ETH_IO_SIZE            ETHERNET_PORTS_DIFFERENCE_OFFSETS
-#define GT64240_ETH_SMI_REG            ETHERNET_SMI_REGISTER
-#define GT64240_ETH_MIB_COUNT_BASE     ETHERNET0_MIB_COUNTER_BASE
-#define GT64240_ETH_SDMA_CONFIG        ETHERNET0_SDMA_CONFIGURATION_REGISTER
-#define GT64240_ETH_SDMA_COMM          ETHERNET0_SDMA_COMMAND_REGISTER
-#define GT64240_ETH_INT_MASK           ETHERNET0_INTERRUPT_MASK_REGISTER
-#define GT64240_ETH_INT_CAUSE          ETHERNET0_INTERRUPT_CAUSE_REGISTER
-#define GT64240_ETH_CURR_TX_DESC_PTR0  ETHERNET0_CURRENT_TX_DESCRIPTOR_POINTER0
-#define GT64240_ETH_CURR_TX_DESC_PTR1  ETHERNET0_CURRENT_TX_DESCRIPTOR_POINTER1
-#define GT64240_ETH_1ST_RX_DESC_PTR0   ETHERNET0_FIRST_RX_DESCRIPTOR_POINTER0
-#define GT64240_ETH_CURR_RX_DESC_PTR0  ETHERNET0_CURRENT_RX_DESCRIPTOR_POINTER0
-#define GT64240_ETH_HASH_TBL_PTR       ETHERNET0_HASH_TABLE_POINTER_REGISTER
-
-/* Turn on NAPI by default */
-
-#define        GT64240_NAPI                    1
-
-/* Some 64240 settings that SHOULD eventually be setup in PROM monitor: */
-/* (Board-specific to the DSL3224 Rev A board ONLY!)                    */
-#define D3224_MPP_CTRL0_SETTING                0x66669900
-#define D3224_MPP_CTRL1_SETTING                0x00000000
-#define D3224_MPP_CTRL2_SETTING                0x00887700
-#define D3224_MPP_CTRL3_SETTING                0x00000044
-#define D3224_GPP_IO_CTRL_SETTING      0x0000e800
-#define D3224_GPP_LEVEL_CTRL_SETTING   0xf001f703
-#define D3224_GPP_VALUE_SETTING                0x00000000
-
-/* Keep the ring sizes a power of two for efficiency. */
-//-#define TX_RING_SIZE 16
-#define TX_RING_SIZE   64      /* TESTING !!! */
-#define RX_RING_SIZE   32
-#define PKT_BUF_SZ     1536    /* Size of each temporary Rx buffer. */
-
-#define RX_HASH_TABLE_SIZE 16384
-#define HASH_HOP_NUMBER 12
-
-#define NUM_INTERFACES 3
-
-#define GT64240ETH_TX_TIMEOUT HZ/4
-
-#define MIPS_GT64240_BASE 0xf4000000
-#define GT64240_ETH0_BASE (MIPS_GT64240_BASE + GT64240_ETH_PORT_CONFIG)
-#define GT64240_ETH1_BASE (GT64240_ETH0_BASE + GT64240_ETH_IO_SIZE)
-#define GT64240_ETH2_BASE (GT64240_ETH1_BASE + GT64240_ETH_IO_SIZE)
-
-#if defined(CONFIG_MIPS_DSL3224)
-#define GT64240_ETHER0_IRQ 4
-#define GT64240_ETHER1_IRQ 4
-#else
-#define GT64240_ETHER0_IRQ -1
-#define GT64240_ETHER1_IRQ -1
-#endif
-
-#define REV_GT64240  0x1
-#define REV_GT64240A 0x10
-
-#define GT64240ETH_READ(gp, offset)                                    \
-       GT_READ((gp)->port_offset + (offset))
-
-#define GT64240ETH_WRITE(gp, offset, data)                             \
-       GT_WRITE((gp)->port_offset + (offset), (data))
-
-#define GT64240ETH_SETBIT(gp, offset, bits)                            \
-       GT64240ETH_WRITE((gp), (offset),                                \
-                        GT64240ETH_READ((gp), (offset)) | (bits))
-
-#define GT64240ETH_CLRBIT(gp, offset, bits)                            \
-       GT64240ETH_WRITE((gp), (offset),                                \
-                        GT64240ETH_READ((gp), (offset)) & ~(bits))
-
-#define GT64240_READ(ofs)              GT_READ(ofs)
-#define GT64240_WRITE(ofs, data)       GT_WRITE((ofs), (data))
-
-/* Bit definitions of the SMI Reg */
-enum {
-       smirDataMask = 0xffff,
-       smirPhyAdMask = 0x1f << 16,
-       smirPhyAdBit = 16,
-       smirRegAdMask = 0x1f << 21,
-       smirRegAdBit = 21,
-       smirOpCode = 1 << 26,
-       smirReadValid = 1 << 27,
-       smirBusy = 1 << 28
-};
-
-/* Bit definitions of the Port Config Reg */
-enum pcr_bits {
-       pcrPM = 1 << 0,
-       pcrRBM = 1 << 1,
-       pcrPBF = 1 << 2,
-       pcrEN = 1 << 7,
-       pcrLPBKMask = 0x3 << 8,
-       pcrLPBKBit = 1 << 8,
-       pcrFC = 1 << 10,
-       pcrHS = 1 << 12,
-       pcrHM = 1 << 13,
-       pcrHDM = 1 << 14,
-       pcrHD = 1 << 15,
-       pcrISLMask = 0x7 << 28,
-       pcrISLBit = 28,
-       pcrACCS = 1 << 31
-};
-
-/* Bit definitions of the Port Config Extend Reg */
-enum pcxr_bits {
-       pcxrIGMP = 1,
-       pcxrSPAN = 2,
-       pcxrPAR = 4,
-       pcxrPRIOtxMask = 0x7 << 3,
-       pcxrPRIOtxBit = 3,
-       pcxrPRIOrxMask = 0x3 << 6,
-       pcxrPRIOrxBit = 6,
-       pcxrPRIOrxOverride = 1 << 8,
-       pcxrDPLXen = 1 << 9,
-       pcxrFCTLen = 1 << 10,
-       pcxrFLP = 1 << 11,
-       pcxrFCTL = 1 << 12,
-       pcxrMFLMask = 0x3 << 14,
-       pcxrMFLBit = 14,
-       pcxrMIBclrMode = 1 << 16,
-       pcxrSpeed = 1 << 18,
-       pcxrSpeeden = 1 << 19,
-       pcxrRMIIen = 1 << 20,
-       pcxrDSCPen = 1 << 21
-};
-
-/* Bit definitions of the Port Command Reg */
-enum pcmr_bits {
-       pcmrFJ = 1 << 15
-};
-
-
-/* Bit definitions of the Port Status Reg */
-enum psr_bits {
-       psrSpeed = 1,
-       psrDuplex = 2,
-       psrFctl = 4,
-       psrLink = 8,
-       psrPause = 1 << 4,
-       psrTxLow = 1 << 5,
-       psrTxHigh = 1 << 6,
-       psrTxInProg = 1 << 7
-};
-
-/* Bit definitions of the SDMA Config Reg */
-enum sdcr_bits {
-       sdcrRCMask = 0xf << 2,
-       sdcrRCBit = 2,
-       sdcrBLMR = 1 << 6,
-       sdcrBLMT = 1 << 7,
-       sdcrPOVR = 1 << 8,
-       sdcrRIFB = 1 << 9,
-       sdcrBSZMask = 0x3 << 12,
-       sdcrBSZBit = 12
-};
-
-/* Bit definitions of the SDMA Command Reg */
-enum sdcmr_bits {
-       sdcmrERD = 1 << 7,
-       sdcmrAR = 1 << 15,
-       sdcmrSTDH = 1 << 16,
-       sdcmrSTDL = 1 << 17,
-       sdcmrTXDH = 1 << 23,
-       sdcmrTXDL = 1 << 24,
-       sdcmrAT = 1 << 31
-};
-
-/* Bit definitions of the Interrupt Cause Reg */
-enum icr_bits {
-       icrRxBuffer = 1,
-       icrTxBufferHigh = 1 << 2,
-       icrTxBufferLow = 1 << 3,
-       icrTxEndHigh = 1 << 6,
-       icrTxEndLow = 1 << 7,
-       icrRxError = 1 << 8,
-       icrTxErrorHigh = 1 << 10,
-       icrTxErrorLow = 1 << 11,
-       icrRxOVR = 1 << 12,
-       icrTxUdr = 1 << 13,
-       icrRxBufferQ0 = 1 << 16,
-       icrRxBufferQ1 = 1 << 17,
-       icrRxBufferQ2 = 1 << 18,
-       icrRxBufferQ3 = 1 << 19,
-       icrRxErrorQ0 = 1 << 20,
-       icrRxErrorQ1 = 1 << 21,
-       icrRxErrorQ2 = 1 << 22,
-       icrRxErrorQ3 = 1 << 23,
-       icrMIIPhySTC = 1 << 28,
-       icrSMIdone = 1 << 29,
-       icrEtherIntSum = 1 << 31
-};
-
-
-/* The Rx and Tx descriptor lists. */
-#ifdef __LITTLE_ENDIAN
-typedef struct {
-       u32 cmdstat;
-       u16 reserved;           //-prk21aug01    u32 reserved:16;
-       u16 byte_cnt;           //-prk21aug01    u32 byte_cnt:16;
-       u32 buff_ptr;
-       u32 next;
-} gt64240_td_t;
-
-typedef struct {
-       u32 cmdstat;
-       u16 byte_cnt;           //-prk21aug01    u32 byte_cnt:16;
-       u16 buff_sz;            //-prk21aug01    u32 buff_sz:16;
-       u32 buff_ptr;
-       u32 next;
-} gt64240_rd_t;
-#elif defined(__BIG_ENDIAN)
-typedef struct {
-       u16 byte_cnt;           //-prk21aug01    u32 byte_cnt:16;
-       u16 reserved;           //-prk21aug01    u32 reserved:16;
-       u32 cmdstat;
-       u32 next;
-       u32 buff_ptr;
-} gt64240_td_t;
-
-typedef struct {
-       u16 buff_sz;            //-prk21aug01    u32 buff_sz:16;
-       u16 byte_cnt;           //-prk21aug01    u32 byte_cnt:16;
-       u32 cmdstat;
-       u32 next;
-       u32 buff_ptr;
-} gt64240_rd_t;
-#else
-#error Either __BIG_ENDIAN or __LITTLE_ENDIAN must be defined!
-#endif
-
-
-/* Values for the Tx command-status descriptor entry. */
-enum td_cmdstat {
-       txOwn = 1 << 31,
-       txAutoMode = 1 << 30,
-       txEI = 1 << 23,
-       txGenCRC = 1 << 22,
-       txPad = 1 << 18,
-       txFirst = 1 << 17,
-       txLast = 1 << 16,
-       txErrorSummary = 1 << 15,
-       txReTxCntMask = 0x0f << 10,
-       txReTxCntBit = 10,
-       txCollision = 1 << 9,
-       txReTxLimit = 1 << 8,
-       txUnderrun = 1 << 6,
-       txLateCollision = 1 << 5
-};
-
-
-/* Values for the Rx command-status descriptor entry. */
-enum rd_cmdstat {
-       rxOwn = 1 << 31,
-       rxAutoMode = 1 << 30,
-       rxEI = 1 << 23,
-       rxFirst = 1 << 17,
-       rxLast = 1 << 16,
-       rxErrorSummary = 1 << 15,
-       rxIGMP = 1 << 14,
-       rxHashExpired = 1 << 13,
-       rxMissedFrame = 1 << 12,
-       rxFrameType = 1 << 11,
-       rxShortFrame = 1 << 8,
-       rxMaxFrameLen = 1 << 7,
-       rxOverrun = 1 << 6,
-       rxCollision = 1 << 4,
-       rxCRCError = 1
-};
-
-/* Bit fields of a Hash Table Entry */
-enum hash_table_entry {
-       hteValid = 1,
-       hteSkip = 2,
-       hteRD = 4
-};
-
-// The MIB counters
-typedef struct {
-       u32 byteReceived;
-       u32 byteSent;
-       u32 framesReceived;
-       u32 framesSent;
-       u32 totalByteReceived;
-       u32 totalFramesReceived;
-       u32 broadcastFramesReceived;
-       u32 multicastFramesReceived;
-       u32 cRCError;
-       u32 oversizeFrames;
-       u32 fragments;
-       u32 jabber;
-       u32 collision;
-       u32 lateCollision;
-       u32 frames64;
-       u32 frames65_127;
-       u32 frames128_255;
-       u32 frames256_511;
-       u32 frames512_1023;
-       u32 frames1024_MaxSize;
-       u32 macRxError;
-       u32 droppedFrames;
-       u32 outMulticastFrames;
-       u32 outBroadcastFrames;
-       u32 undersizeFrames;
-} mib_counters_t;
-
-
-struct gt64240_private {
-       gt64240_rd_t *rx_ring;
-       gt64240_td_t *tx_ring;
-       // The Rx and Tx rings must be 16-byte aligned
-       dma_addr_t rx_ring_dma;
-       dma_addr_t tx_ring_dma;
-       char *hash_table;
-       // The Hash Table must be 8-byte aligned
-       dma_addr_t hash_table_dma;
-       int hash_mode;
-
-       // The Rx buffers must be 8-byte aligned
-       char *rx_buff;
-       dma_addr_t rx_buff_dma;
-       // Tx buffers (tx_skbuff[i]->data) with less than 8 bytes
-       // of payload must be 8-byte aligned
-       struct sk_buff *tx_skbuff[TX_RING_SIZE];
-       int rx_next_out;        /* The next free ring entry to receive */
-       int tx_next_in;         /* The next free ring entry to send */
-       int tx_next_out;        /* The last ring entry the ISR processed */
-       int tx_count;           /* current # of pkts waiting to be sent in Tx ring */
-       int intr_work_done;     /* number of Rx and Tx pkts processed in the isr */
-       int tx_full;            /* Tx ring is full */
-
-       mib_counters_t mib;
-       struct net_device_stats stats;
-
-       int io_size;
-       int port_num;           // 0 or 1
-       u32 port_offset;
-
-       int phy_addr;           // PHY address
-       u32 last_psr;           // last value of the port status register
-
-       int options;            /* User-settable misc. driver options. */
-       int drv_flags;
-       spinlock_t lock;        /* Serialise access to device */
-       struct mii_if_info mii_if;
-
-       u32 msg_enable;
-};
-
-#endif /* _GT64240ETH_H */
index 2d1ecfd..ecd3da1 100644 (file)
@@ -522,7 +522,7 @@ EXPORT_SYMBOL(genphy_read_status);
 
 static int genphy_config_init(struct phy_device *phydev)
 {
-       u32 val;
+       int val;
        u32 features;
 
        /* For now, I'll claim that the generic driver supports
index f5dbeb2..1bf23e4 100644 (file)
@@ -2904,7 +2904,7 @@ static void s2io_mdio_write(u32 mmd_type, u64 addr, u16 value, struct net_device
 {
        u64 val64 = 0x0;
        nic_t *sp = dev->priv;
-       XENA_dev_config_t *bar0 = (XENA_dev_config_t *)sp->bar0;
+       XENA_dev_config_t __iomem *bar0 = sp->bar0;
 
        //address transaction
        val64 = val64 | MDIO_MMD_INDX_ADDR(addr)
@@ -2953,7 +2953,7 @@ static u64 s2io_mdio_read(u32 mmd_type, u64 addr, struct net_device *dev)
        u64 val64 = 0x0;
        u64 rval64 = 0x0;
        nic_t *sp = dev->priv;
-       XENA_dev_config_t *bar0 = (XENA_dev_config_t *)sp->bar0;
+       XENA_dev_config_t __iomem *bar0 = sp->bar0;
 
        /* address transaction */
        val64 = val64 | MDIO_MMD_INDX_ADDR(addr)
@@ -3276,7 +3276,7 @@ static void alarm_intr_handler(struct s2io_nic *nic)
  *   SUCCESS on success and FAILURE on failure.
  */
 
-static int wait_for_cmd_complete(void *addr, u64 busy_bit)
+static int wait_for_cmd_complete(void __iomem *addr, u64 busy_bit)
 {
        int ret = FAILURE, cnt = 0;
        u64 val64;
@@ -4303,11 +4303,11 @@ static struct net_device_stats *s2io_get_stats(struct net_device *dev)
        sp->stats.tx_errors =
                le32_to_cpu(mac_control->stats_info->tmac_any_err_frms);
        sp->stats.rx_errors =
-               le32_to_cpu(mac_control->stats_info->rmac_drop_frms);
+               le64_to_cpu(mac_control->stats_info->rmac_drop_frms);
        sp->stats.multicast =
                le32_to_cpu(mac_control->stats_info->rmac_vld_mcst_frms);
        sp->stats.rx_length_errors =
-               le32_to_cpu(mac_control->stats_info->rmac_long_frms);
+               le64_to_cpu(mac_control->stats_info->rmac_long_frms);
 
        return (&sp->stats);
 }
index 9142d91..705e9a8 100644 (file)
@@ -58,6 +58,7 @@
 #define TX_WATCHDOG            (5 * HZ)
 #define NAPI_WEIGHT            64
 #define BLINK_MS               250
+#define LINK_HZ                        (HZ/2)
 
 MODULE_DESCRIPTION("SysKonnect Gigabit Ethernet driver");
 MODULE_AUTHOR("Stephen Hemminger <shemminger@osdl.org>");
@@ -605,7 +606,12 @@ static void skge_led(struct skge_port *skge, enum led_mode mode)
        if (hw->chip_id == CHIP_ID_GENESIS) {
                switch (mode) {
                case LED_MODE_OFF:
-                       xm_phy_write(hw, port, PHY_BCOM_P_EXT_CTRL, PHY_B_PEC_LED_OFF);
+                       if (hw->phy_type == SK_PHY_BCOM)
+                               xm_phy_write(hw, port, PHY_BCOM_P_EXT_CTRL, PHY_B_PEC_LED_OFF);
+                       else {
+                               skge_write32(hw, SK_REG(port, TX_LED_VAL), 0);
+                               skge_write8(hw, SK_REG(port, TX_LED_CTRL), LED_T_OFF);
+                       }
                        skge_write8(hw, SK_REG(port, LNK_LED_REG), LINKLED_OFF);
                        skge_write32(hw, SK_REG(port, RX_LED_VAL), 0);
                        skge_write8(hw, SK_REG(port, RX_LED_CTRL), LED_T_OFF);
@@ -625,8 +631,14 @@ static void skge_led(struct skge_port *skge, enum led_mode mode)
                        skge_write32(hw, SK_REG(port, RX_LED_VAL), 100);
                        skge_write8(hw, SK_REG(port, RX_LED_CTRL), LED_START);
 
-                       xm_phy_write(hw, port, PHY_BCOM_P_EXT_CTRL, PHY_B_PEC_LED_ON);
-                       break;
+                       if (hw->phy_type == SK_PHY_BCOM)
+                               xm_phy_write(hw, port, PHY_BCOM_P_EXT_CTRL, PHY_B_PEC_LED_ON);
+                       else {
+                               skge_write8(hw, SK_REG(port, TX_LED_TST), LED_T_ON);
+                               skge_write32(hw, SK_REG(port, TX_LED_VAL), 100);
+                               skge_write8(hw, SK_REG(port, TX_LED_CTRL), LED_START);
+                       }
+
                }
        } else {
                switch (mode) {
@@ -879,6 +891,9 @@ static int __xm_phy_read(struct skge_hw *hw, int port, u16 reg, u16 *val)
        xm_write16(hw, port, XM_PHY_ADDR, reg | hw->phy_addr);
        *val = xm_read16(hw, port, XM_PHY_DATA);
 
+       if (hw->phy_type == SK_PHY_XMAC)
+               goto ready;
+
        for (i = 0; i < PHY_RETRIES; i++) {
                if (xm_read16(hw, port, XM_MMU_CMD) & XM_MMU_PHY_RDY)
                        goto ready;
@@ -965,7 +980,8 @@ static void genesis_reset(struct skge_hw *hw, int port)
        xm_write16(hw, port, XM_RX_CMD, 0);     /* reset RX CMD Reg */
 
        /* disable Broadcom PHY IRQ */
-       xm_write16(hw, port, PHY_BCOM_INT_MASK, 0xffff);
+       if (hw->phy_type == SK_PHY_BCOM)
+               xm_write16(hw, port, PHY_BCOM_INT_MASK, 0xffff);
 
        xm_outhash(hw, port, XM_HSM, zero);
 }
@@ -1000,60 +1016,64 @@ static void bcom_check_link(struct skge_hw *hw, int port)
 
                if (netif_carrier_ok(dev))
                        skge_link_down(skge);
-       } else {
-               if (skge->autoneg == AUTONEG_ENABLE &&
-                   (status & PHY_ST_AN_OVER)) {
-                       u16 lpa = xm_phy_read(hw, port, PHY_BCOM_AUNE_LP);
-                       u16 aux = xm_phy_read(hw, port, PHY_BCOM_AUX_STAT);
-
-                       if (lpa & PHY_B_AN_RF) {
-                               printk(KERN_NOTICE PFX "%s: remote fault\n",
-                                      dev->name);
-                               return;
-                       }
+               return;
+       }
 
-                       /* Check Duplex mismatch */
-                       switch (aux & PHY_B_AS_AN_RES_MSK) {
-                       case PHY_B_RES_1000FD:
-                               skge->duplex = DUPLEX_FULL;
-                               break;
-                       case PHY_B_RES_1000HD:
-                               skge->duplex = DUPLEX_HALF;
-                               break;
-                       default:
-                               printk(KERN_NOTICE PFX "%s: duplex mismatch\n",
-                                      dev->name);
-                               return;
-                       }
+       if (skge->autoneg == AUTONEG_ENABLE) {
+               u16 lpa, aux;
 
+               if (!(status & PHY_ST_AN_OVER))
+                       return;
 
-                       /* We are using IEEE 802.3z/D5.0 Table 37-4 */
-                       switch (aux & PHY_B_AS_PAUSE_MSK) {
-                       case PHY_B_AS_PAUSE_MSK:
-                               skge->flow_control = FLOW_MODE_SYMMETRIC;
-                               break;
-                       case PHY_B_AS_PRR:
-                               skge->flow_control = FLOW_MODE_REM_SEND;
-                               break;
-                       case PHY_B_AS_PRT:
-                               skge->flow_control = FLOW_MODE_LOC_SEND;
-                               break;
-                       default:
-                               skge->flow_control = FLOW_MODE_NONE;
-                       }
+               lpa = xm_phy_read(hw, port, PHY_XMAC_AUNE_LP);
+               if (lpa & PHY_B_AN_RF) {
+                       printk(KERN_NOTICE PFX "%s: remote fault\n",
+                              dev->name);
+                       return;
+               }
 
-                       skge->speed = SPEED_1000;
+               aux = xm_phy_read(hw, port, PHY_BCOM_AUX_STAT);
+
+               /* Check Duplex mismatch */
+               switch (aux & PHY_B_AS_AN_RES_MSK) {
+               case PHY_B_RES_1000FD:
+                       skge->duplex = DUPLEX_FULL;
+                       break;
+               case PHY_B_RES_1000HD:
+                       skge->duplex = DUPLEX_HALF;
+                       break;
+               default:
+                       printk(KERN_NOTICE PFX "%s: duplex mismatch\n",
+                              dev->name);
+                       return;
                }
 
-               if (!netif_carrier_ok(dev))
-                       genesis_link_up(skge);
+
+               /* We are using IEEE 802.3z/D5.0 Table 37-4 */
+               switch (aux & PHY_B_AS_PAUSE_MSK) {
+               case PHY_B_AS_PAUSE_MSK:
+                       skge->flow_control = FLOW_MODE_SYMMETRIC;
+                       break;
+               case PHY_B_AS_PRR:
+                       skge->flow_control = FLOW_MODE_REM_SEND;
+                       break;
+               case PHY_B_AS_PRT:
+                       skge->flow_control = FLOW_MODE_LOC_SEND;
+                       break;
+               default:
+                       skge->flow_control = FLOW_MODE_NONE;
+               }
+               skge->speed = SPEED_1000;
        }
+
+       if (!netif_carrier_ok(dev))
+               genesis_link_up(skge);
 }
 
 /* Broadcom 5400 only supports giagabit! SysKonnect did not put an additional
  * Phy on for 100 or 10Mbit operation
  */
-static void bcom_phy_init(struct skge_port *skge, int jumbo)
+static void bcom_phy_init(struct skge_port *skge)
 {
        struct skge_hw *hw = skge->hw;
        int port = skge->port;
@@ -1144,7 +1164,7 @@ static void bcom_phy_init(struct skge_port *skge, int jumbo)
                     phy_pause_map[skge->flow_control] | PHY_AN_CSMA);
 
        /* Handle Jumbo frames */
-       if (jumbo) {
+       if (hw->dev[port]->mtu > ETH_DATA_LEN) {
                xm_phy_write(hw, port, PHY_BCOM_AUX_CTRL,
                             PHY_B_AC_TX_TST | PHY_B_AC_LONG_PACK);
 
@@ -1157,8 +1177,154 @@ static void bcom_phy_init(struct skge_port *skge, int jumbo)
 
        /* Use link status change interrupt */
        xm_phy_write(hw, port, PHY_BCOM_INT_MASK, PHY_B_DEF_MSK);
+}
 
-       bcom_check_link(hw, port);
+static void xm_phy_init(struct skge_port *skge)
+{
+       struct skge_hw *hw = skge->hw;
+       int port = skge->port;
+       u16 ctrl = 0;
+
+       if (skge->autoneg == AUTONEG_ENABLE) {
+               if (skge->advertising & ADVERTISED_1000baseT_Half)
+                       ctrl |= PHY_X_AN_HD;
+               if (skge->advertising & ADVERTISED_1000baseT_Full)
+                       ctrl |= PHY_X_AN_FD;
+
+               switch(skge->flow_control) {
+               case FLOW_MODE_NONE:
+                       ctrl |= PHY_X_P_NO_PAUSE;
+                       break;
+               case FLOW_MODE_LOC_SEND:
+                       ctrl |= PHY_X_P_ASYM_MD;
+                       break;
+               case FLOW_MODE_SYMMETRIC:
+                       ctrl |= PHY_X_P_BOTH_MD;
+                       break;
+               }
+
+               xm_phy_write(hw, port, PHY_XMAC_AUNE_ADV, ctrl);
+
+               /* Restart Auto-negotiation */
+               ctrl = PHY_CT_ANE | PHY_CT_RE_CFG;
+       } else {
+               /* Set DuplexMode in Config register */
+               if (skge->duplex == DUPLEX_FULL)
+                       ctrl |= PHY_CT_DUP_MD;
+               /*
+                * Do NOT enable Auto-negotiation here. This would hold
+                * the link down because no IDLEs are transmitted
+                */
+       }
+
+       xm_phy_write(hw, port, PHY_XMAC_CTRL, ctrl);
+
+       /* Poll PHY for status changes */
+       schedule_delayed_work(&skge->link_thread, LINK_HZ);
+}
+
+static void xm_check_link(struct net_device *dev)
+{
+       struct skge_port *skge = netdev_priv(dev);
+       struct skge_hw *hw = skge->hw;
+       int port = skge->port;
+       u16 status;
+
+       /* read twice because of latch */
+       (void) xm_phy_read(hw, port, PHY_XMAC_STAT);
+       status = xm_phy_read(hw, port, PHY_XMAC_STAT);
+
+       if ((status & PHY_ST_LSYNC) == 0) {
+               u16 cmd = xm_read16(hw, port, XM_MMU_CMD);
+               cmd &= ~(XM_MMU_ENA_RX | XM_MMU_ENA_TX);
+               xm_write16(hw, port, XM_MMU_CMD, cmd);
+               /* dummy read to ensure writing */
+               (void) xm_read16(hw, port, XM_MMU_CMD);
+
+               if (netif_carrier_ok(dev))
+                       skge_link_down(skge);
+               return;
+       }
+
+       if (skge->autoneg == AUTONEG_ENABLE) {
+               u16 lpa, res;
+
+               if (!(status & PHY_ST_AN_OVER))
+                       return;
+
+               lpa = xm_phy_read(hw, port, PHY_XMAC_AUNE_LP);
+               if (lpa & PHY_B_AN_RF) {
+                       printk(KERN_NOTICE PFX "%s: remote fault\n",
+                              dev->name);
+                       return;
+               }
+
+               res = xm_phy_read(hw, port, PHY_XMAC_RES_ABI);
+
+               /* Check Duplex mismatch */
+               switch (res & (PHY_X_RS_HD | PHY_X_RS_FD)) {
+               case PHY_X_RS_FD:
+                       skge->duplex = DUPLEX_FULL;
+                       break;
+               case PHY_X_RS_HD:
+                       skge->duplex = DUPLEX_HALF;
+                       break;
+               default:
+                       printk(KERN_NOTICE PFX "%s: duplex mismatch\n",
+                              dev->name);
+                       return;
+               }
+
+               /* We are using IEEE 802.3z/D5.0 Table 37-4 */
+               if (lpa & PHY_X_P_SYM_MD)
+                       skge->flow_control = FLOW_MODE_SYMMETRIC;
+               else if ((lpa & PHY_X_RS_PAUSE) == PHY_X_P_ASYM_MD)
+                       skge->flow_control = FLOW_MODE_REM_SEND;
+               else if ((lpa & PHY_X_RS_PAUSE) == PHY_X_P_BOTH_MD)
+                       skge->flow_control = FLOW_MODE_LOC_SEND;
+               else
+                       skge->flow_control = FLOW_MODE_NONE;
+
+
+               skge->speed = SPEED_1000;
+       }
+
+       if (!netif_carrier_ok(dev))
+               genesis_link_up(skge);
+}
+
+/* Poll to check for link coming up.
+ * Since internal PHY is wired to a level triggered pin, can't
+ * get an interrupt when carrier is detected.
+ */
+static void xm_link_timer(void *arg)
+{
+       struct net_device *dev = arg;
+       struct skge_port *skge = netdev_priv(arg);
+       struct skge_hw *hw = skge->hw;
+       int port = skge->port;
+
+       if (!netif_running(dev))
+               return;
+
+       if (netif_carrier_ok(dev)) {
+               xm_read16(hw, port, XM_ISRC);
+               if (!(xm_read16(hw, port, XM_ISRC) & XM_IS_INP_ASS))
+                       goto nochange;
+       } else {
+               if (xm_read32(hw, port, XM_GP_PORT) & XM_GP_INP_ASS)
+                       goto nochange;
+               xm_read16(hw, port, XM_ISRC);
+               if (xm_read16(hw, port, XM_ISRC) & XM_IS_INP_ASS)
+                       goto nochange;
+       }
+
+       mutex_lock(&hw->phy_mutex);
+       xm_check_link(dev);
+       mutex_unlock(&hw->phy_mutex);
+
+nochange:
+       schedule_delayed_work(&skge->link_thread, LINK_HZ);
 }
 
 static void genesis_mac_init(struct skge_hw *hw, int port)
@@ -1189,20 +1355,29 @@ static void genesis_mac_init(struct skge_hw *hw, int port)
         * namely for the 1000baseTX cards that use the XMAC's
         * GMII mode.
         */
-       /* Take external Phy out of reset */
-       r = skge_read32(hw, B2_GP_IO);
-       if (port == 0)
-               r |= GP_DIR_0|GP_IO_0;
-       else
-               r |= GP_DIR_2|GP_IO_2;
+       if (hw->phy_type != SK_PHY_XMAC) {
+               /* Take external Phy out of reset */
+               r = skge_read32(hw, B2_GP_IO);
+               if (port == 0)
+                       r |= GP_DIR_0|GP_IO_0;
+               else
+                       r |= GP_DIR_2|GP_IO_2;
 
-       skge_write32(hw, B2_GP_IO, r);
+               skge_write32(hw, B2_GP_IO, r);
 
+               /* Enable GMII interface */
+               xm_write16(hw, port, XM_HW_CFG, XM_HW_GMII_MD);
+       }
 
-       /* Enable GMII interface */
-       xm_write16(hw, port, XM_HW_CFG, XM_HW_GMII_MD);
 
-       bcom_phy_init(skge, jumbo);
+       switch(hw->phy_type) {
+       case SK_PHY_XMAC:
+               xm_phy_init(skge);
+               break;
+       case SK_PHY_BCOM:
+               bcom_phy_init(skge);
+               bcom_check_link(hw, port);
+       }
 
        /* Set Station Address */
        xm_outaddr(hw, port, XM_SA, dev->dev_addr);
@@ -1335,16 +1510,18 @@ static void genesis_stop(struct skge_port *skge)
        skge_write16(hw, SK_REG(port, TX_MFF_CTRL1), MFF_SET_MAC_RST);
 
        /* For external PHYs there must be special handling */
-       reg = skge_read32(hw, B2_GP_IO);
-       if (port == 0) {
-               reg |= GP_DIR_0;
-               reg &= ~GP_IO_0;
-       } else {
-               reg |= GP_DIR_2;
-               reg &= ~GP_IO_2;
+       if (hw->phy_type != SK_PHY_XMAC) {
+               reg = skge_read32(hw, B2_GP_IO);
+               if (port == 0) {
+                       reg |= GP_DIR_0;
+                       reg &= ~GP_IO_0;
+               } else {
+                       reg |= GP_DIR_2;
+                       reg &= ~GP_IO_2;
+               }
+               skge_write32(hw, B2_GP_IO, reg);
+               skge_read32(hw, B2_GP_IO);
        }
-       skge_write32(hw, B2_GP_IO, reg);
-       skge_read32(hw, B2_GP_IO);
 
        xm_write16(hw, port, XM_MMU_CMD,
                        xm_read16(hw, port, XM_MMU_CMD)
@@ -1406,7 +1583,7 @@ static void genesis_link_up(struct skge_port *skge)
        struct skge_hw *hw = skge->hw;
        int port = skge->port;
        u16 cmd;
-       u32 mode, msk;
+       u32 mode;
 
        cmd = xm_read16(hw, port, XM_MMU_CMD);
 
@@ -1454,27 +1631,24 @@ static void genesis_link_up(struct skge_port *skge)
        }
 
        xm_write32(hw, port, XM_MODE, mode);
-
-       msk = XM_DEF_MSK;
-       /* disable GP0 interrupt bit for external Phy */
-       msk |= XM_IS_INP_ASS;
-
-       xm_write16(hw, port, XM_IMSK, msk);
+       xm_write16(hw, port, XM_IMSK, XM_DEF_MSK);
        xm_read16(hw, port, XM_ISRC);
 
        /* get MMU Command Reg. */
        cmd = xm_read16(hw, port, XM_MMU_CMD);
-       if (skge->duplex == DUPLEX_FULL)
+       if (hw->phy_type != SK_PHY_XMAC && skge->duplex == DUPLEX_FULL)
                cmd |= XM_MMU_GMII_FD;
 
        /*
         * Workaround BCOM Errata (#10523) for all BCom Phys
         * Enable Power Management after link up
         */
-       xm_phy_write(hw, port, PHY_BCOM_AUX_CTRL,
-                    xm_phy_read(hw, port, PHY_BCOM_AUX_CTRL)
-                    & ~PHY_B_AC_DIS_PM);
-       xm_phy_write(hw, port, PHY_BCOM_INT_MASK, PHY_B_DEF_MSK);
+       if (hw->phy_type == SK_PHY_BCOM) {
+               xm_phy_write(hw, port, PHY_BCOM_AUX_CTRL,
+                            xm_phy_read(hw, port, PHY_BCOM_AUX_CTRL)
+                            & ~PHY_B_AC_DIS_PM);
+               xm_phy_write(hw, port, PHY_BCOM_INT_MASK, PHY_B_DEF_MSK);
+       }
 
        /* enable Rx/Tx */
        xm_write16(hw, port, XM_MMU_CMD,
@@ -2240,6 +2414,8 @@ static int skge_down(struct net_device *dev)
                printk(KERN_INFO PFX "%s: disabling interface\n", dev->name);
 
        netif_stop_queue(dev);
+       if (hw->chip_id == CHIP_ID_GENESIS && hw->phy_type == SK_PHY_XMAC)
+               cancel_rearming_delayed_work(&skge->link_thread);
 
        skge_write8(skge->hw, SK_REG(skge->port, LNK_LED_REG), LED_OFF);
        if (hw->chip_id == CHIP_ID_GENESIS)
@@ -2862,7 +3038,7 @@ static void skge_extirq(void *arg)
                if (netif_running(dev)) {
                        if (hw->chip_id != CHIP_ID_GENESIS)
                                yukon_phy_intr(skge);
-                       else
+                       else if (hw->phy_type == SK_PHY_BCOM)
                                bcom_phy_intr(skge);
                }
        }
@@ -3014,7 +3190,7 @@ static int skge_reset(struct skge_hw *hw)
 {
        u32 reg;
        u16 ctst, pci_status;
-       u8 t8, mac_cfg, pmd_type, phy_type;
+       u8 t8, mac_cfg, pmd_type;
        int i;
 
        ctst = skge_read16(hw, B0_CTST);
@@ -3038,19 +3214,22 @@ static int skge_reset(struct skge_hw *hw)
                     ctst & (CS_CLK_RUN_HOT|CS_CLK_RUN_RST|CS_CLK_RUN_ENA));
 
        hw->chip_id = skge_read8(hw, B2_CHIP_ID);
-       phy_type = skge_read8(hw, B2_E_1) & 0xf;
+       hw->phy_type = skge_read8(hw, B2_E_1) & 0xf;
        pmd_type = skge_read8(hw, B2_PMD_TYP);
        hw->copper = (pmd_type == 'T' || pmd_type == '1');
 
        switch (hw->chip_id) {
        case CHIP_ID_GENESIS:
-               switch (phy_type) {
+               switch (hw->phy_type) {
+               case SK_PHY_XMAC:
+                       hw->phy_addr = PHY_ADDR_XMAC;
+                       break;
                case SK_PHY_BCOM:
                        hw->phy_addr = PHY_ADDR_BCOM;
                        break;
                default:
                        printk(KERN_ERR PFX "%s: unsupported phy type 0x%x\n",
-                              pci_name(hw->pdev), phy_type);
+                              pci_name(hw->pdev), hw->phy_type);
                        return -EOPNOTSUPP;
                }
                break;
@@ -3058,7 +3237,7 @@ static int skge_reset(struct skge_hw *hw)
        case CHIP_ID_YUKON:
        case CHIP_ID_YUKON_LITE:
        case CHIP_ID_YUKON_LP:
-               if (phy_type < SK_PHY_MARV_COPPER && pmd_type != 'S')
+               if (hw->phy_type < SK_PHY_MARV_COPPER && pmd_type != 'S')
                        hw->copper = 1;
 
                hw->phy_addr = PHY_ADDR_MARV;
@@ -3089,10 +3268,13 @@ static int skge_reset(struct skge_hw *hw)
        else
                hw->ram_size = t8 * 4096;
 
-       hw->intr_mask = IS_HW_ERR | IS_EXT_REG | IS_PORT_1;
+       hw->intr_mask = IS_HW_ERR | IS_PORT_1;
        if (hw->ports > 1)
                hw->intr_mask |= IS_PORT_2;
 
+       if (!(hw->chip_id == CHIP_ID_GENESIS && hw->phy_type == SK_PHY_XMAC))
+               hw->intr_mask |= IS_EXT_REG;
+
        if (hw->chip_id == CHIP_ID_GENESIS)
                genesis_init(hw);
        else {
@@ -3226,6 +3408,9 @@ static struct net_device *skge_devinit(struct skge_hw *hw, int port,
 
        skge->port = port;
 
+       /* Only used for Genesis XMAC */
+       INIT_WORK(&skge->link_thread, xm_link_timer, dev);
+
        if (hw->chip_id != CHIP_ID_GENESIS) {
                dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG;
                skge->rx_csum = 1;
index 79e0927..d0b47d4 100644 (file)
@@ -934,7 +934,7 @@ enum {
        PHY_XMAC_AUNE_ADV       = 0x04,/* 16 bit r/w    Auto-Neg. Advertisement */
        PHY_XMAC_AUNE_LP        = 0x05,/* 16 bit r/o    Link Partner Abi Reg */
        PHY_XMAC_AUNE_EXP       = 0x06,/* 16 bit r/o    Auto-Neg. Expansion Reg */
-       PHY_XMAC_NEPG   = 0x07,/* 16 bit r/w    Next Page Register */
+       PHY_XMAC_NEPG           = 0x07,/* 16 bit r/w    Next Page Register */
        PHY_XMAC_NEPG_LP        = 0x08,/* 16 bit r/o    Next Page Link Partner */
 
        PHY_XMAC_EXT_STAT       = 0x0f,/* 16 bit r/o    Ext Status Register */
@@ -1097,13 +1097,36 @@ enum {
 
 /* Pause Bits (PHY_X_AN_PAUSE and PHY_X_RS_PAUSE) encoding */
 enum {
-       PHY_X_P_NO_PAUSE        = 0<<7,/* Bit  8..7:    no Pause Mode */
+       PHY_X_P_NO_PAUSE= 0<<7,/* Bit  8..7:    no Pause Mode */
        PHY_X_P_SYM_MD  = 1<<7, /* Bit  8..7:   symmetric Pause Mode */
        PHY_X_P_ASYM_MD = 2<<7,/* Bit  8..7:    asymmetric Pause Mode */
        PHY_X_P_BOTH_MD = 3<<7,/* Bit  8..7:    both Pause Mode */
 };
 
 
+/*****  PHY_XMAC_EXT_STAT      16 bit r/w      Extended Status Register *****/
+enum {
+       PHY_X_EX_FD     = 1<<15, /* Bit 15:     Device Supports Full Duplex */
+       PHY_X_EX_HD     = 1<<14, /* Bit 14:     Device Supports Half Duplex */
+};
+
+/*****  PHY_XMAC_RES_ABI       16 bit r/o      PHY Resolved Ability *****/
+enum {
+       PHY_X_RS_PAUSE  = 3<<7, /* Bit  8..7:   selected Pause Mode */
+       PHY_X_RS_HD     = 1<<6, /* Bit  6:      Half Duplex Mode selected */
+       PHY_X_RS_FD     = 1<<5, /* Bit  5:      Full Duplex Mode selected */
+       PHY_X_RS_ABLMIS = 1<<4, /* Bit  4:      duplex or pause cap mismatch */
+       PHY_X_RS_PAUMIS = 1<<3, /* Bit  3:      pause capability mismatch */
+};
+
+/* Remote Fault Bits (PHY_X_AN_RFB) encoding */
+enum {
+       X_RFB_OK        = 0<<12,/* Bit 13..12   No errors, Link OK */
+       X_RFB_LF        = 1<<12,/* Bit 13..12   Link Failure */
+       X_RFB_OFF       = 2<<12,/* Bit 13..12   Offline */
+       X_RFB_AN_ERR    = 3<<12,/* Bit 13..12   Auto-Negotiation Error */
+};
+
 /* Broadcom-Specific */
 /*****  PHY_BCOM_1000T_CTRL    16 bit r/w      1000Base-T Control Reg *****/
 enum {
@@ -2158,8 +2181,8 @@ enum {
        XM_IS_LNK_AE    = 1<<14, /* Bit 14:     Link Asynchronous Event */
        XM_IS_TX_ABORT  = 1<<13, /* Bit 13:     Transmit Abort, late Col. etc */
        XM_IS_FRC_INT   = 1<<12, /* Bit 12:     Force INT bit set in GP */
-       XM_IS_INP_ASS   = 1<<11,        /* Bit 11:      Input Asserted, GP bit 0 set */
-       XM_IS_LIPA_RC   = 1<<10,        /* Bit 10:      Link Partner requests config */
+       XM_IS_INP_ASS   = 1<<11, /* Bit 11:     Input Asserted, GP bit 0 set */
+       XM_IS_LIPA_RC   = 1<<10, /* Bit 10:     Link Partner requests config */
        XM_IS_RX_PAGE   = 1<<9, /* Bit  9:      Page Received */
        XM_IS_TX_PAGE   = 1<<8, /* Bit  8:      Next Page Loaded for Transmit */
        XM_IS_AND       = 1<<7, /* Bit  7:      Auto-Negotiation Done */
@@ -2172,9 +2195,7 @@ enum {
        XM_IS_RX_COMP   = 1<<0, /* Bit  0:      Frame Rx Complete */
 };
 
-#define XM_DEF_MSK     (~(XM_IS_INP_ASS | XM_IS_LIPA_RC | XM_IS_RX_PAGE | \
-                          XM_IS_AND | XM_IS_RXC_OV | XM_IS_TXC_OV | \
-                          XM_IS_RXF_OV | XM_IS_TXF_UR))
+#define XM_DEF_MSK     (~(XM_IS_RXC_OV | XM_IS_TXC_OV | XM_IS_RXF_OV | XM_IS_TXF_UR))
 
 
 /*     XM_HW_CFG       16 bit r/w      Hardware Config Register */
@@ -2396,6 +2417,7 @@ struct skge_hw {
        u8                   chip_rev;
        u8                   copper;
        u8                   ports;
+       u8                   phy_type;
 
        u32                  ram_size;
        u32                  ram_offset;
@@ -2422,6 +2444,7 @@ struct skge_port {
 
        struct net_device_stats net_stats;
 
+       struct work_struct   link_thread;
        u8                   rx_csum;
        u8                   blink_on;
        u8                   flow_control;
index 7aa7fba..c660e33 100644 (file)
@@ -379,6 +379,24 @@ static inline void LPD7_SMC_outsw (unsigned char* a, int r,
 
 #define SMC_IRQ_FLAGS          (0)
 
+#elif  defined(CONFIG_ARCH_VERSATILE)
+
+#define SMC_CAN_USE_8BIT       1
+#define SMC_CAN_USE_16BIT      1
+#define SMC_CAN_USE_32BIT      1
+#define SMC_NOWAIT             1
+
+#define SMC_inb(a, r)          readb((a) + (r))
+#define SMC_inw(a, r)          readw((a) + (r))
+#define SMC_inl(a, r)          readl((a) + (r))
+#define SMC_outb(v, a, r)      writeb(v, (a) + (r))
+#define SMC_outw(v, a, r)      writew(v, (a) + (r))
+#define SMC_outl(v, a, r)      writel(v, (a) + (r))
+#define SMC_insl(a, r, p, l)   readsl((a) + (r), p, l)
+#define SMC_outsl(a, r, p, l)  writesl((a) + (r), p, l)
+
+#define SMC_IRQ_FLAGS          (0)
+
 #else
 
 #define SMC_CAN_USE_8BIT       1
index 0d66700..bfc8c3e 100644 (file)
@@ -1876,7 +1876,6 @@ static int sprintf_info(char *buffer, struct net_device *dev)
                datap[size+1]=io_word & 0xff;
        }
 
-
        size = sprintf(buffer, "\n%6s: Adapter Address   : Node Address      : Functional Addr\n", dev->name);
 
        size += sprintf(buffer + size,
@@ -1932,64 +1931,6 @@ static int sprintf_info(char *buffer, struct net_device *dev)
 #endif
 #endif
 
-#if STREAMER_IOCTL && (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
-static int streamer_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
-{
-        int i;
-       struct streamer_private *streamer_priv = (struct streamer_private *) dev->priv;
-       u8 __iomem *streamer_mmio = streamer_priv->streamer_mmio;
-
-       switch(cmd) {
-       case IOCTL_SISR_MASK:
-               writew(SISR_MI, streamer_mmio + SISR_MASK_SUM);
-               break;
-       case IOCTL_SPIN_LOCK_TEST:
-               printk(KERN_INFO "spin_lock() called.\n");
-               spin_lock(&streamer_priv->streamer_lock);
-               spin_unlock(&streamer_priv->streamer_lock);
-               printk(KERN_INFO "spin_unlock() finished.\n");
-               break;
-       case IOCTL_PRINT_BDAS:
-               printk(KERN_INFO "bdas: RXBDA: %x RXLBDA: %x TX2FDA: %x TX2LFDA: %x\n",
-                      readw(streamer_mmio + RXBDA),
-                      readw(streamer_mmio + RXLBDA),
-                      readw(streamer_mmio + TX2FDA),
-                      readw(streamer_mmio + TX2LFDA));
-               break;
-       case IOCTL_PRINT_REGISTERS:
-               printk(KERN_INFO "registers:\n");
-               printk(KERN_INFO "SISR: %04x MISR: %04x LISR: %04x BCTL: %04x BMCTL: %04x\nmask  %04x mask  %04x\n", 
-                      readw(streamer_mmio + SISR),
-                      readw(streamer_mmio + MISR_RUM),
-                      readw(streamer_mmio + LISR),
-                      readw(streamer_mmio + BCTL),
-                      readw(streamer_mmio + BMCTL_SUM),
-                      readw(streamer_mmio + SISR_MASK),
-                      readw(streamer_mmio + MISR_MASK));
-               break;
-       case IOCTL_PRINT_RX_BUFS:
-               printk(KERN_INFO "Print rx bufs:\n");
-               for(i=0; i<STREAMER_RX_RING_SIZE; i++)
-                       printk(KERN_INFO "rx_ring %d status: 0x%x\n", i, 
-                              streamer_priv->streamer_rx_ring[i].status);
-               break;
-       case IOCTL_PRINT_TX_BUFS:
-               printk(KERN_INFO "Print tx bufs:\n");
-               for(i=0; i<STREAMER_TX_RING_SIZE; i++)
-                       printk(KERN_INFO "tx_ring %d status: 0x%x\n", i, 
-                              streamer_priv->streamer_tx_ring[i].status);
-               break;
-       case IOCTL_RX_CMD:
-               streamer_rx(dev);
-               printk(KERN_INFO "Sent rx command.\n");
-               break;
-       default:
-               printk(KERN_INFO "Bad ioctl!\n");
-       }
-       return 0;
-}
-#endif
-
 static struct pci_driver streamer_pci_driver = {
   .name     = "lanstreamer",
   .id_table = streamer_pci_tbl,
index 5557d8e..e7bb349 100644 (file)
 
 #include <linux/version.h>
 
-#if STREAMER_IOCTL && (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
-#include <asm/ioctl.h>
-#define IOCTL_PRINT_RX_BUFS   SIOCDEVPRIVATE
-#define IOCTL_PRINT_TX_BUFS   SIOCDEVPRIVATE+1
-#define IOCTL_RX_CMD          SIOCDEVPRIVATE+2
-#define IOCTL_TX_CMD          SIOCDEVPRIVATE+3
-#define IOCTL_PRINT_REGISTERS SIOCDEVPRIVATE+4
-#define IOCTL_PRINT_BDAS      SIOCDEVPRIVATE+5
-#define IOCTL_SPIN_LOCK_TEST  SIOCDEVPRIVATE+6
-#define IOCTL_SISR_MASK       SIOCDEVPRIVATE+7
-#endif
-
 /* MAX_INTR - the maximum number of times we can loop
  * inside the interrupt function before returning
  * control to the OS (maximum value is 256)
index 8f6f6fd..d5c32e9 100644 (file)
@@ -333,11 +333,7 @@ enum state_values {
 #define TYPHOON_RESET_TIMEOUT_NOSLEEP  ((6 * 1000000) / TYPHOON_UDELAY)
 #define TYPHOON_WAIT_TIMEOUT           ((1000000 / 2) / TYPHOON_UDELAY)
 
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 28)
-#define typhoon_synchronize_irq(x) synchronize_irq()
-#else
 #define typhoon_synchronize_irq(x) synchronize_irq(x)
-#endif
 
 #if defined(NETIF_F_TSO)
 #define skb_tso_size(x)                (skb_shinfo(x)->gso_size)
diff --git a/include/asm-alpha/libata-portmap.h b/include/asm-alpha/libata-portmap.h
deleted file mode 100644 (file)
index 75484ef..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/libata-portmap.h>
diff --git a/include/asm-frv/libata-portmap.h b/include/asm-frv/libata-portmap.h
deleted file mode 100644 (file)
index 75484ef..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/libata-portmap.h>
diff --git a/include/asm-i386/libata-portmap.h b/include/asm-i386/libata-portmap.h
deleted file mode 100644 (file)
index 75484ef..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/libata-portmap.h>
diff --git a/include/asm-ia64/libata-portmap.h b/include/asm-ia64/libata-portmap.h
deleted file mode 100644 (file)
index 75484ef..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/libata-portmap.h>
diff --git a/include/asm-powerpc/libata-portmap.h b/include/asm-powerpc/libata-portmap.h
deleted file mode 100644 (file)
index 75484ef..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/libata-portmap.h>
diff --git a/include/asm-sparc/libata-portmap.h b/include/asm-sparc/libata-portmap.h
deleted file mode 100644 (file)
index 75484ef..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/libata-portmap.h>
diff --git a/include/asm-sparc64/libata-portmap.h b/include/asm-sparc64/libata-portmap.h
deleted file mode 100644 (file)
index 75484ef..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/libata-portmap.h>
diff --git a/include/asm-x86_64/libata-portmap.h b/include/asm-x86_64/libata-portmap.h
deleted file mode 100644 (file)
index 75484ef..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/libata-portmap.h>
index cd080d7..8018c2e 100644 (file)
@@ -59,6 +59,8 @@
 #define IFF_SLAVE_INACTIVE     0x4     /* bonding slave not the curr. active */
 #define IFF_MASTER_8023AD      0x8     /* bonding master, 802.3ad.     */
 #define IFF_MASTER_ALB 0x10            /* bonding master, balance-alb. */
+#define IFF_BONDING    0x20            /* bonding master or slave      */
+#define IFF_SLAVE_NEEDARP 0x40         /* need ARPs for validation     */
 
 #define IF_GET_IFACE   0x0001          /* for querying only */
 #define IF_GET_PROTO   0x0002
index 1ef3d39..d6a3d4b 100644 (file)
 #include <linux/workqueue.h>
 #include <scsi/scsi_host.h>
 
+/*
+ * Define if arch has non-standard setup.  This is a _PCI_ standard
+ * not a legacy or ISA standard.
+ */
+#ifdef CONFIG_ATA_NONSTANDARD
 #include <asm/libata-portmap.h>
+#else
+#include <asm-generic/libata-portmap.h>
+#endif
 
 /*
  * compile-time options: to be removed as soon as all the drivers are
index ac4f502..13d6d4e 100644 (file)
@@ -1015,7 +1015,8 @@ static inline int netif_needs_gso(struct net_device *dev, struct sk_buff *skb)
 }
 
 /* On bonding slaves other than the currently active slave, suppress
- * duplicates except for 802.3ad ETH_P_SLOW and alb non-mcast/bcast.
+ * duplicates except for 802.3ad ETH_P_SLOW, alb non-mcast/bcast, and
+ * ARP on active-backup slaves with arp_validate enabled.
  */
 static inline int skb_bond_should_drop(struct sk_buff *skb)
 {
@@ -1024,6 +1025,10 @@ static inline int skb_bond_should_drop(struct sk_buff *skb)
 
        if (master &&
            (dev->priv_flags & IFF_SLAVE_INACTIVE)) {
+               if ((dev->priv_flags & IFF_SLAVE_NEEDARP) &&
+                   skb->protocol == __constant_htons(ETH_P_ARP))
+                       return 0;
+
                if (master->priv_flags & IFF_MASTER_ALB) {
                        if (skb->pkt_type != PACKET_BROADCAST &&
                            skb->pkt_type != PACKET_MULTICAST)