Commit 8128c97e authored by Linus Torvalds's avatar Linus Torvalds

Merge bk://gkernel.bkbits.net/net-drivers-2.5

into home.osdl.org:/home/torvalds/v2.5/linux
parents 42098570 0fa2e9bd
...@@ -43,10 +43,10 @@ Installation ...@@ -43,10 +43,10 @@ Installation
For the latest version of the bonding driver, use kernel 2.4.12 or above For the latest version of the bonding driver, use kernel 2.4.12 or above
(otherwise you will need to apply a patch). (otherwise you will need to apply a patch).
Configure kernel with `make menuconfig/xconfig/config', and select Configure kernel with `make menuconfig/xconfig/config', and select "Bonding
"Bonding driver support" in the "Network device support" section. It is driver support" in the "Network device support" section. It is recommended
recommended to configure the driver as module since it is currently the only way to configure the driver as module since it is currently the only way to
to pass parameters to the driver and configure more than one bonding device. pass parameters to the driver and configure more than one bonding device.
Build and install the new kernel and modules. Build and install the new kernel and modules.
...@@ -108,17 +108,17 @@ MASTER=bond0 ...@@ -108,17 +108,17 @@ MASTER=bond0
SLAVE=yes SLAVE=yes
BOOTPROTO=none BOOTPROTO=none
Use DEVICE=eth1 in the ifcfg-eth1 config file. If you configure a second bonding Use DEVICE=eth1 in the ifcfg-eth1 config file. If you configure a second
interface (bond1), use MASTER=bond1 in the config file to make the network bonding interface (bond1), use MASTER=bond1 in the config file to make the
interface be a slave of bond1. network interface be a slave of bond1.
Restart the networking subsystem or just bring up the bonding device if your Restart the networking subsystem or just bring up the bonding device if your
administration tools allow it. Otherwise, reboot. On Red Hat distros you can administration tools allow it. Otherwise, reboot. On Red Hat distros you can
issue `ifup bond0' or `/etc/rc.d/init.d/network restart'. issue `ifup bond0' or `/etc/rc.d/init.d/network restart'.
If the administration tools of your distribution do not support master/slave If the administration tools of your distribution do not support
notation in configuring network interfaces, you will need to manually configure master/slave notation in configuring network interfaces, you will need to
the bonding device with the following commands: manually configure the bonding device with the following commands:
# /sbin/ifconfig bond0 192.168.1.1 netmask 255.255.255.0 \ # /sbin/ifconfig bond0 192.168.1.1 netmask 255.255.255.0 \
broadcast 192.168.1.255 up broadcast 192.168.1.255 up
...@@ -167,7 +167,8 @@ in the ifDescr table (ifDescr.2). ...@@ -167,7 +167,8 @@ in the ifDescr table (ifDescr.2).
This problem is avoided by loading the bonding driver before any network This problem is avoided by loading the bonding driver before any network
drivers participating in a bond. Below is an example of loading the bonding drivers participating in a bond. Below is an example of loading the bonding
driver first, the IP address 192.168.1.1 is correctly associated with ifDescr.2. driver first, the IP address 192.168.1.1 is correctly associated with
ifDescr.2.
interfaces.ifTable.ifEntry.ifDescr.1 = lo interfaces.ifTable.ifEntry.ifDescr.1 = lo
interfaces.ifTable.ifEntry.ifDescr.2 = bond0 interfaces.ifTable.ifEntry.ifDescr.2 = bond0
...@@ -200,6 +201,44 @@ It is critical that either the miimon or arp_interval and arp_ip_target ...@@ -200,6 +201,44 @@ It is critical that either the miimon or arp_interval and arp_ip_target
parameters be specified, otherwise serious network degradation will occur parameters be specified, otherwise serious network degradation will occur
during link failures. during link failures.
arp_interval
Specifies the ARP monitoring frequency in milli-seconds.
If ARP monitoring is used in a load-balancing mode (mode 0 or 2), the
switch should be configured in a mode that evenly distributes packets
across all links - such as round-robin. If the switch is configured to
distribute the packets in an XOR fashion, all replies from the ARP
targets will be received on the same link which could cause the other
team members to fail. ARP monitoring should not be used in conjunction
with miimon. A value of 0 disables ARP monitoring. The default value
is 0.
arp_ip_target
Specifies the ip addresses to use when arp_interval is > 0. These
are the targets of the ARP request sent to determine the health of
the link to the targets. Specify these values in ddd.ddd.ddd.ddd
format. Multiple ip adresses must be seperated by a comma. At least
one ip address needs to be given for ARP monitoring to work. The
maximum number of targets that can be specified is set at 16.
downdelay
Specifies the delay time in milli-seconds to disable a link after a
link failure has been detected. This should be a multiple of miimon
value, otherwise the value will be rounded. The default value is 0.
lacp_rate
Option specifying the rate in which we'll ask our link partner to
transmit LACPDU packets in 802.3ad mode. Possible values are:
slow or 0
Request partner to transmit LACPDUs every 30 seconds (default)
fast or 1
Request partner to transmit LACPDUs every 1 second
max_bonds max_bonds
Specifies the number of bonding devices to create for this Specifies the number of bonding devices to create for this
...@@ -207,18 +246,27 @@ max_bonds ...@@ -207,18 +246,27 @@ max_bonds
the bonding driver is not already loaded, then bond0, bond1 the bonding driver is not already loaded, then bond0, bond1
and bond2 will be created. The default value is 1. and bond2 will be created. The default value is 1.
miimon
Specifies the frequency in milli-seconds that MII link monitoring
will occur. A value of zero disables MII link monitoring. A value
of 100 is a good starting point. See High Availability section for
additional information. The default value is 0.
mode mode
Specifies one of four bonding policies. The default is Specifies one of the bonding policies. The default is
round-robin (balance-rr). Possible values are (you can use either the round-robin (balance-rr). Possible values are (you can use
text or numeric option): either the text or numeric option):
balance-rr or 0 balance-rr or 0
Round-robin policy: Transmit in a sequential order Round-robin policy: Transmit in a sequential order
from the first available slave through the last. This from the first available slave through the last. This
mode provides load balancing and fault tolerance. mode provides load balancing and fault tolerance.
active-backup or 1 active-backup or 1
Active-backup policy: Only one slave in the bond is Active-backup policy: Only one slave in the bond is
active. A different slave becomes active if, and only active. A different slave becomes active if, and only
if, the active slave fails. The bond's MAC address is if, the active slave fails. The bond's MAC address is
...@@ -227,6 +275,7 @@ text or numeric option): ...@@ -227,6 +275,7 @@ text or numeric option):
fault tolerance. fault tolerance.
balance-xor or 2 balance-xor or 2
XOR policy: Transmit based on [(source MAC address XOR policy: Transmit based on [(source MAC address
XOR'd with destination MAC address) modula slave XOR'd with destination MAC address) modula slave
count]. This selects the same slave for each count]. This selects the same slave for each
...@@ -234,15 +283,124 @@ text or numeric option): ...@@ -234,15 +283,124 @@ text or numeric option):
balancing and fault tolerance. balancing and fault tolerance.
broadcast or 3 broadcast or 3
Broadcast policy: transmits everything on all slave Broadcast policy: transmits everything on all slave
interfaces. This mode provides fault tolerance. interfaces. This mode provides fault tolerance.
miimon 802.3ad or 4
Specifies the frequency in milli-seconds that MII link monitoring will IEEE 802.3ad Dynamic link aggregation. Creates aggregation
occur. A value of zero disables MII link monitoring. A value of groups that share the same speed and duplex settings.
100 is a good starting point. See High Availability section for Transmits and receives on all slaves in the active
additional information. The default value is 0. aggregator.
Pre-requisites:
1. Ethtool support in the base drivers for retrieving the
speed and duplex of each slave.
2. A switch that supports IEEE 802.3ad Dynamic link
aggregation.
balance-tlb or 5
Adaptive transmit load balancing: channel bonding that does
not require any special switch support. The outgoing
traffic is distributed according to the current load
(computed relative to the speed) on each slave. Incoming
traffic is received by the current slave. If the receiving
slave fails, another slave takes over the MAC address of
the failed receiving slave.
Prerequisite:
Ethtool support in the base drivers for retrieving the
speed of each slave.
balance-alb or 6
Adaptive load balancing: includes balance-tlb + receive
load balancing (rlb) for IPV4 traffic and does not require
any special switch support. The receive load balancing is
achieved by ARP negotiation. The bonding driver intercepts
the ARP Replies sent by the server on their way out and
overwrites the src hw address with the unique hw address of
one of the slaves in the bond such that different clients
use different hw addresses for the server.
Receive traffic from connections created by the server is
also balanced. When the server sends an ARP Request the
bonding driver copies and saves the client's IP information
from the ARP. When the ARP Reply arrives from the client,
its hw address is retrieved and the bonding driver
initiates an ARP reply to this client assigning it to one
of the slaves in the bond. A problematic outcome of using
ARP negotiation for balancing is that each time that an ARP
request is broadcasted it uses the hw address of the
bond. Hence, clients learn the hw address of the bond and
the balancing of receive traffic collapses to the current
salve. This is handled by sending updates (ARP Replies) to
all the clients with their assigned hw address such that
the traffic is redistributed. Receive traffic is also
redistributed when a new slave is added to the bond and
when an inactive slave is re-activated. The receive load is
distributed sequentially (round robin) among the group of
highest speed slaves in the bond.
When a link is reconnected or a new slave joins the bond
the receive traffic is redistributed among all active
slaves in the bond by intiating ARP Replies with the
selected mac address to each of the clients. The updelay
modeprobe parameter must be set to a value equal or greater
than the switch's forwarding delay so that the ARP Replies
sent to the clients will not be blocked by the switch.
Prerequisites:
1. Ethtool support in the base drivers for retrieving the
speed of each slave.
2. Base driver support for setting the hw address of a
device also when it is open. This is required so that there
will always be one slave in the team using the bond hw
address (the current_slave) while having a unique hw
address for each slave in the bond. If the current_slave
fails it's hw address is swapped with the new current_slave
that was chosen.
multicast
Option specifying the mode of operation for multicast support.
Possible values are:
disabled or 0
Disabled (no multicast support)
active or 1
Enabled on active slave only, useful in active-backup mode
all or 2
Enabled on all slaves, this is the default
primary
A string (eth0, eth2, etc) to equate to a primary device. If this
value is entered, and the device is on-line, it will be used first
as the output media. Only when this device is off-line, will
alternate devices be used. Otherwise, once a failover is detected
and a new default output is chosen, it will remain the output media
until it too fails. This is useful when one slave was preferred
over another, i.e. when one slave is 1000Mbps and another is
100Mbps. If the 1000Mbps slave fails and is later restored, it may
be preferred the faster slave gracefully become the active slave -
without deliberately failing the 100Mbps slave. Specifying a
primary is only valid in active-backup mode.
updelay
Specifies the delay time in milli-seconds to enable a link after a
link up status has been detected. This should be a multiple of miimon
value, otherwise the value will be rounded. The default value is 0.
use_carrier use_carrier
...@@ -265,80 +423,27 @@ use_carrier ...@@ -265,80 +423,27 @@ use_carrier
0 will use the deprecated MII / ETHTOOL ioctls. The default 0 will use the deprecated MII / ETHTOOL ioctls. The default
value is 1. value is 1.
downdelay
Specifies the delay time in milli-seconds to disable a link after a
link failure has been detected. This should be a multiple of miimon
value, otherwise the value will be rounded. The default value is 0.
updelay
Specifies the delay time in milli-seconds to enable a link after a
link up status has been detected. This should be a multiple of miimon
value, otherwise the value will be rounded. The default value is 0.
arp_interval
Specifies the ARP monitoring frequency in milli-seconds.
If ARP monitoring is used in a load-balancing mode (mode 0 or 2), the
switch should be configured in a mode that evenly distributes packets
across all links - such as round-robin. If the switch is configured to
distribute the packets in an XOR fashion, all replies from the ARP
targets will be received on the same link which could cause the other
team members to fail. ARP monitoring should not be used in conjunction
with miimon. A value of 0 disables ARP monitoring. The default value
is 0.
arp_ip_target
Specifies the ip addresses to use when arp_interval is > 0. These are
the targets of the ARP request sent to determine the health of the link
to the targets. Specify these values in ddd.ddd.ddd.ddd format.
Multiple ip addresses must be separated by a comma. At least one ip
address needs to be given for ARP monitoring to work. The maximum number
of targets that can be specified is set at 16.
primary
A string (eth0, eth2, etc) to equate to a primary device. If this
value is entered, and the device is on-line, it will be used first as
the output media. Only when this device is off-line, will alternate
devices be used. Otherwise, once a failover is detected and a new
default output is chosen, it will remain the output media until it too
fails. This is useful when one slave was preferred over another, i.e.
when one slave is 1000Mbps and another is 100Mbps. If the 1000Mbps
slave fails and is later restored, it may be preferred the faster slave
gracefully become the active slave - without deliberately failing the
100Mbps slave. Specifying a primary is only valid in active-backup mode.
multicast
Option specifying the mode of operation for multicast support.
Possible values are:
disabled or 0
Disabled (no multicast support)
active or 1
Enabled on active slave only, useful in active-backup mode
all or 2
Enabled on all slaves, this is the default
Configuring Multiple Bonds Configuring Multiple Bonds
========================== ==========================
If several bonding interfaces are required, the driver must be loaded If several bonding interfaces are required, either specify the max_bonds
multiple times. For example, to configure two bonding interfaces with link parameter (described above), or load the driver multiple times. Using
monitoring performed every 100 milli-seconds, the /etc/conf.modules should the max_bonds parameter is less complicated, but has the limitation that
all bonding instances created will have the same options. Loading the
driver multiple times allows each instance of the driver to have differing
options.
For example, to configure two bonding interfaces, one with mii link
monitoring performed every 100 milliseconds, and one with ARP link
monitoring performed every 200 milliseconds, the /etc/conf.modules should
resemble the following: resemble the following:
alias bond0 bonding alias bond0 bonding
alias bond1 bonding alias bond1 bonding
options bond0 miimon=100 options bond0 miimon=100
options bond1 -o bonding1 miimon=100 options bond1 -o bonding1 arp_interval=200 arp_ip_target=10.0.0.1
Configuring Multiple ARP Targets Configuring Multiple ARP Targets
================================ ================================
...@@ -347,8 +452,9 @@ While ARP monitoring can be done with just one target, it can be useful ...@@ -347,8 +452,9 @@ While ARP monitoring can be done with just one target, it can be useful
in a High Availability setup to have several targets to monitor. In the in a High Availability setup to have several targets to monitor. In the
case of just one target, the target itself may go down or have a problem case of just one target, the target itself may go down or have a problem
making it unresponsive to ARP requests. Having an additional target (or making it unresponsive to ARP requests. Having an additional target (or
several) would increase the reliability of the ARP monitoring. several) increases the reliability of the ARP monitoring.
Multiple ARP targets must be separated by commas as follows:
Multiple ARP targets must be seperated by commas as follows:
# example options for ARP monitoring with three targets # example options for ARP monitoring with three targets
alias bond0 bonding alias bond0 bonding
...@@ -410,9 +516,10 @@ additions may cause trouble. ...@@ -410,9 +516,10 @@ additions may cause trouble.
Switch Configuration Switch Configuration
==================== ====================
While the switch does not need to be configured when the active-backup While the switch does not need to be configured when the active-backup,
policy is used (mode=1), it does need to be configured for the round-robin, balance-tlb or balance-alb policies (mode=1,5,6) are used, it does need to
XOR, and broadcast policies (mode=0, mode=2, and mode=3). be configured for the round-robin, XOR, broadcast, or 802.3ad policies
(mode=0,2,3,4).
Verifying Bond Configuration Verifying Bond Configuration
...@@ -445,7 +552,8 @@ parameters of mode=0 and miimon=1000 is shown below. ...@@ -445,7 +552,8 @@ parameters of mode=0 and miimon=1000 is shown below.
The network configuration can be verified using the ifconfig command. In The network configuration can be verified using the ifconfig command. In
the example below, the bond0 interface is the master (MASTER) while eth0 and the example below, the bond0 interface is the master (MASTER) while eth0 and
eth1 are slaves (SLAVE). Notice all slaves of bond0 have the same MAC address eth1 are slaves (SLAVE). Notice all slaves of bond0 have the same MAC address
(HWaddr) as bond0. (HWaddr) as bond0 for all modes except TLB and ALB that require a unique MAC
address for each slave.
[root]# /sbin/ifconfig [root]# /sbin/ifconfig
bond0 Link encap:Ethernet HWaddr 00:C0:F0:1F:37:B4 bond0 Link encap:Ethernet HWaddr 00:C0:F0:1F:37:B4
...@@ -488,8 +596,7 @@ Frequently Asked Questions ...@@ -488,8 +596,7 @@ Frequently Asked Questions
3. How many bonding devices can I have? 3. How many bonding devices can I have?
One for each module you load. See section on Module Parameters for how There is no limit.
to accomplish this.
4. How many slaves can a bonding device have? 4. How many slaves can a bonding device have?
...@@ -508,10 +615,11 @@ Frequently Asked Questions ...@@ -508,10 +615,11 @@ Frequently Asked Questions
For ethernet cards not supporting MII status, the arp_interval and For ethernet cards not supporting MII status, the arp_interval and
arp_ip_target parameters must be specified for bonding to work arp_ip_target parameters must be specified for bonding to work
correctly. If packets have not been sent or received during the correctly. If packets have not been sent or received during the
specified arp_interval durration, an ARP request is sent to the targets specified arp_interval durration, an ARP request is sent to the
to generate send and receive traffic. If after this interval, either targets to generate send and receive traffic. If after this
the successful send and/or receive count has not incremented, the next interval, either the successful send and/or receive count has not
slave in the sequence will become the active slave. incremented, the next slave in the sequence will become the active
slave.
If neither mii_monitor and arp_interval is configured, the bonding If neither mii_monitor and arp_interval is configured, the bonding
driver will not handle this situation very well. The driver will driver will not handle this situation very well. The driver will
...@@ -523,14 +631,15 @@ Frequently Asked Questions ...@@ -523,14 +631,15 @@ Frequently Asked Questions
6. Can bonding be used for High Availability? 6. Can bonding be used for High Availability?
Yes, if you use MII monitoring and ALL your cards support MII link Yes, if you use MII monitoring and ALL your cards support MII link
status reporting. See section on High Availability for more information. status reporting. See section on High Availability for more
information.
7. Which switches/systems does it work with? 7. Which switches/systems does it work with?
In round-robin and XOR mode, it works with systems that support In round-robin and XOR mode, it works with systems that support
trunking: trunking:
* Cisco 5500 series (look for EtherChannel support). * Many Cisco switches and routers (look for EtherChannel support).
* SunTrunking software. * SunTrunking software.
* Alteon AceDirector switches / WebOS (use Trunks). * Alteon AceDirector switches / WebOS (use Trunks).
* BayStack Switches (trunks must be explicitly configured). Stackable * BayStack Switches (trunks must be explicitly configured). Stackable
...@@ -538,7 +647,17 @@ Frequently Asked Questions ...@@ -538,7 +647,17 @@ Frequently Asked Questions
units. units.
* Linux bonding, of course ! * Linux bonding, of course !
In active-backup mode, it should work with any Layer-II switche. In 802.3ad mode, it works with with systems that support IEEE 802.3ad
Dynamic Link Aggregation:
* Extreme networks Summit 7i (look for link-aggregation).
* Many Cisco switches and routers (look for LACP support; this may
require an upgrade to your IOS software; LACP support was added
by Cisco in late 2002).
* Foundry Big Iron 4000
In active-backup, balance-tlb and balance-alb modes, it should work
with any Layer-II switch.
8. Where does a bonding device get its MAC address from? 8. Where does a bonding device get its MAC address from?
...@@ -591,6 +710,20 @@ Frequently Asked Questions ...@@ -591,6 +710,20 @@ Frequently Asked Questions
Broadcast policy transmits everything on all slave interfaces. Broadcast policy transmits everything on all slave interfaces.
802.3ad, based on XOR but distributes traffic among all interfaces
in the active aggregator.
Transmit load balancing (balance-tlb) balances the traffic
according to the current load on each slave. The balancing is
clients based and the least loaded slave is selected for each new
client. The load of each slave is calculated relative to its speed
and enables load balancing in mixed speed teams.
Adaptive load balancing (balance-alb) uses the Transmit load
balancing for the transmit load. The receive load is balanced only
among the group of highest speed active slaves in the bond. The
load is distributed with round-robin i.e. next available slave in
the high speed group of active slaves.
High Availability High Availability
================= =================
...@@ -826,10 +959,6 @@ The main limitations are : ...@@ -826,10 +959,6 @@ The main limitations are :
Use the arp_interval/arp_ip_target parameters to count incoming/outgoing Use the arp_interval/arp_ip_target parameters to count incoming/outgoing
frames. frames.
- A Transmit Load Balancing policy is not currently available. This mode
allows every slave in the bond to transmit while only one receives. If
the "receiving" slave fails, another slave takes over the MAC address of
the failed receiving slave.
Resources and Links Resources and Links
......
...@@ -140,8 +140,7 @@ static const char *howto_msg = ...@@ -140,8 +140,7 @@ static const char *howto_msg =
#include <sys/types.h> #include <sys/types.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <sys/ioctl.h> #include <sys/ioctl.h>
#include <linux/if.h> #include <net/if_arp.h>
#include <linux/if_arp.h>
#include <linux/if_ether.h> #include <linux/if_ether.h>
#include <linux/if_bonding.h> #include <linux/if_bonding.h>
#include <linux/sockios.h> #include <linux/sockios.h>
......
...@@ -109,7 +109,8 @@ in the event that chatty debug messages are desired - jjs 12/30/98 */ ...@@ -109,7 +109,8 @@ in the event that chatty debug messages are desired - jjs 12/30/98 */
#include <linux/module.h> #include <linux/module.h>
#ifdef PCMCIA #ifdef PCMCIA /* required for ibmtr_cs.c to build */
#undef MODULE /* yes, really */
#undef ENABLE_PAGING #undef ENABLE_PAGING
#else #else
#define ENABLE_PAGING 1 #define ENABLE_PAGING 1
......
...@@ -1021,6 +1021,8 @@ struct airo_info { ...@@ -1021,6 +1021,8 @@ struct airo_info {
#define FLAG_UPDATE_MULTI 0x40 #define FLAG_UPDATE_MULTI 0x40
#define FLAG_UPDATE_UNI 0x80 #define FLAG_UPDATE_UNI 0x80
#define FLAG_802_11 0x200 #define FLAG_802_11 0x200
#define FLAG_PENDING_XMIT 0x400
#define FLAG_PENDING_XMIT11 0x800
int (*bap_read)(struct airo_info*, u16 *pu16Dst, int bytelen, int (*bap_read)(struct airo_info*, u16 *pu16Dst, int bytelen,
int whichbap); int whichbap);
unsigned short *flash; unsigned short *flash;
...@@ -1345,6 +1347,7 @@ static void airo_do_xmit(struct net_device *dev) { ...@@ -1345,6 +1347,7 @@ static void airo_do_xmit(struct net_device *dev) {
u32 *fids = priv->fids; u32 *fids = priv->fids;
if (down_trylock(&priv->sem) != 0) { if (down_trylock(&priv->sem) != 0) {
priv->flags |= FLAG_PENDING_XMIT;
netif_stop_queue(dev); netif_stop_queue(dev);
priv->xmit.task.func = (void (*)(void *))airo_do_xmit; priv->xmit.task.func = (void (*)(void *))airo_do_xmit;
priv->xmit.task.data = (void *)dev; priv->xmit.task.data = (void *)dev;
...@@ -1353,6 +1356,7 @@ static void airo_do_xmit(struct net_device *dev) { ...@@ -1353,6 +1356,7 @@ static void airo_do_xmit(struct net_device *dev) {
} }
status = transmit_802_3_packet (priv, fids[fid], skb->data); status = transmit_802_3_packet (priv, fids[fid], skb->data);
up(&priv->sem); up(&priv->sem);
priv->flags &= ~FLAG_PENDING_XMIT;
i = 0; i = 0;
if ( status == SUCCESS ) { if ( status == SUCCESS ) {
...@@ -1364,14 +1368,12 @@ static void airo_do_xmit(struct net_device *dev) { ...@@ -1364,14 +1368,12 @@ static void airo_do_xmit(struct net_device *dev) {
} }
if (i < MAX_FIDS / 2) if (i < MAX_FIDS / 2)
netif_wake_queue(dev); netif_wake_queue(dev);
else
netif_stop_queue(dev);
dev_kfree_skb(skb); dev_kfree_skb(skb);
} }
static int airo_start_xmit(struct sk_buff *skb, struct net_device *dev) { static int airo_start_xmit(struct sk_buff *skb, struct net_device *dev) {
s16 len; s16 len;
int i; int i, j;
struct airo_info *priv = dev->priv; struct airo_info *priv = dev->priv;
u32 *fids = priv->fids; u32 *fids = priv->fids;
...@@ -1382,11 +1384,16 @@ static int airo_start_xmit(struct sk_buff *skb, struct net_device *dev) { ...@@ -1382,11 +1384,16 @@ static int airo_start_xmit(struct sk_buff *skb, struct net_device *dev) {
/* Find a vacant FID */ /* Find a vacant FID */
for( i = 0; i < MAX_FIDS / 2 && (fids[i] & 0xffff0000); i++ ); for( i = 0; i < MAX_FIDS / 2 && (fids[i] & 0xffff0000); i++ );
for( j = i + 1; j < MAX_FIDS / 2 && (fids[j] & 0xffff0000); j++ );
if ( i == MAX_FIDS / 2 ) { if ( j >= MAX_FIDS / 2 ) {
netif_stop_queue(dev);
if (i == MAX_FIDS / 2) {
priv->stats.tx_fifo_errors++; priv->stats.tx_fifo_errors++;
dev_kfree_skb(skb); return 1;
} else { }
}
/* check min length*/ /* check min length*/
len = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN; len = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
/* Mark fid as used & save length for later */ /* Mark fid as used & save length for later */
...@@ -1394,7 +1401,6 @@ static int airo_start_xmit(struct sk_buff *skb, struct net_device *dev) { ...@@ -1394,7 +1401,6 @@ static int airo_start_xmit(struct sk_buff *skb, struct net_device *dev) {
priv->xmit.skb = skb; priv->xmit.skb = skb;
priv->xmit.fid = i; priv->xmit.fid = i;
airo_do_xmit(dev); airo_do_xmit(dev);
}
return 0; return 0;
} }
...@@ -1407,6 +1413,7 @@ static void airo_do_xmit11(struct net_device *dev) { ...@@ -1407,6 +1413,7 @@ static void airo_do_xmit11(struct net_device *dev) {
u32 *fids = priv->fids; u32 *fids = priv->fids;
if (down_trylock(&priv->sem) != 0) { if (down_trylock(&priv->sem) != 0) {
priv->flags |= FLAG_PENDING_XMIT11;
netif_stop_queue(dev); netif_stop_queue(dev);
priv->xmit11.task.func = (void (*)(void *))airo_do_xmit11; priv->xmit11.task.func = (void (*)(void *))airo_do_xmit11;
priv->xmit11.task.data = (void *)dev; priv->xmit11.task.data = (void *)dev;
...@@ -1415,6 +1422,7 @@ static void airo_do_xmit11(struct net_device *dev) { ...@@ -1415,6 +1422,7 @@ static void airo_do_xmit11(struct net_device *dev) {
} }
status = transmit_802_11_packet (priv, fids[fid], skb->data); status = transmit_802_11_packet (priv, fids[fid], skb->data);
up(&priv->sem); up(&priv->sem);
priv->flags &= ~FLAG_PENDING_XMIT11;
i = MAX_FIDS / 2; i = MAX_FIDS / 2;
if ( status == SUCCESS ) { if ( status == SUCCESS ) {
...@@ -1426,14 +1434,12 @@ static void airo_do_xmit11(struct net_device *dev) { ...@@ -1426,14 +1434,12 @@ static void airo_do_xmit11(struct net_device *dev) {
} }
if (i < MAX_FIDS) if (i < MAX_FIDS)
netif_wake_queue(dev); netif_wake_queue(dev);
else
netif_stop_queue(dev);
dev_kfree_skb(skb); dev_kfree_skb(skb);
} }
static int airo_start_xmit11(struct sk_buff *skb, struct net_device *dev) { static int airo_start_xmit11(struct sk_buff *skb, struct net_device *dev) {
s16 len; s16 len;
int i; int i, j;
struct airo_info *priv = dev->priv; struct airo_info *priv = dev->priv;
u32 *fids = priv->fids; u32 *fids = priv->fids;
...@@ -1444,11 +1450,16 @@ static int airo_start_xmit11(struct sk_buff *skb, struct net_device *dev) { ...@@ -1444,11 +1450,16 @@ static int airo_start_xmit11(struct sk_buff *skb, struct net_device *dev) {
/* Find a vacant FID */ /* Find a vacant FID */
for( i = MAX_FIDS / 2; i < MAX_FIDS && (fids[i] & 0xffff0000); i++ ); for( i = MAX_FIDS / 2; i < MAX_FIDS && (fids[i] & 0xffff0000); i++ );
for( j = i + 1; j < MAX_FIDS && (fids[j] & 0xffff0000); j++ );
if ( j >= MAX_FIDS ) {
netif_stop_queue(dev);
if ( i == MAX_FIDS ) { if (i == MAX_FIDS) {
priv->stats.tx_fifo_errors++; priv->stats.tx_fifo_errors++;
dev_kfree_skb(skb); return 1;
} else { }
}
/* check min length*/ /* check min length*/
len = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN; len = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
/* Mark fid as used & save length for later */ /* Mark fid as used & save length for later */
...@@ -1456,7 +1467,6 @@ static int airo_start_xmit11(struct sk_buff *skb, struct net_device *dev) { ...@@ -1456,7 +1467,6 @@ static int airo_start_xmit11(struct sk_buff *skb, struct net_device *dev) {
priv->xmit11.skb = skb; priv->xmit11.skb = skb;
priv->xmit11.fid = i; priv->xmit11.fid = i;
airo_do_xmit11(dev); airo_do_xmit11(dev);
}
return 0; return 0;
} }
...@@ -1593,6 +1603,8 @@ void stop_airo_card( struct net_device *dev, int freeres ) ...@@ -1593,6 +1603,8 @@ void stop_airo_card( struct net_device *dev, int freeres )
{ {
struct airo_info *ai = dev->priv; struct airo_info *ai = dev->priv;
flush_scheduled_work(); flush_scheduled_work();
disable_interrupts(ai);
free_irq( dev->irq, dev );
if (ai->flash) if (ai->flash)
kfree(ai->flash); kfree(ai->flash);
if (ai->rssi) if (ai->rssi)
...@@ -1607,8 +1619,6 @@ void stop_airo_card( struct net_device *dev, int freeres ) ...@@ -1607,8 +1619,6 @@ void stop_airo_card( struct net_device *dev, int freeres )
} }
ai->registered = 0; ai->registered = 0;
} }
disable_interrupts(ai);
free_irq( dev->irq, dev );
if (auto_wep) del_timer_sync(&ai->timer); if (auto_wep) del_timer_sync(&ai->timer);
if (freeres) { if (freeres) {
/* PCMCIA frees this stuff, so only for PCI and ISA */ /* PCMCIA frees this stuff, so only for PCI and ISA */
...@@ -2188,7 +2198,13 @@ static irqreturn_t airo_interrupt ( int irq, void* dev_id, struct pt_regs *regs) ...@@ -2188,7 +2198,13 @@ static irqreturn_t airo_interrupt ( int irq, void* dev_id, struct pt_regs *regs)
OUT4500( apriv, EVACK, status & (EV_TX | EV_TXEXC)); OUT4500( apriv, EVACK, status & (EV_TX | EV_TXEXC));
/* Set up to be used again */ /* Set up to be used again */
apriv->fids[index] &= 0xffff; apriv->fids[index] &= 0xffff;
if (index < MAX_FIDS / 2) {
if (!(apriv->flags & FLAG_PENDING_XMIT))
netif_wake_queue(dev); netif_wake_queue(dev);
} else {
if (!(apriv->flags & FLAG_PENDING_XMIT11))
netif_wake_queue(apriv->wifidev);
}
} else { } else {
OUT4500( apriv, EVACK, status & (EV_TX | EV_TXEXC)); OUT4500( apriv, EVACK, status & (EV_TX | EV_TXEXC));
printk( KERN_ERR "airo: Unallocated FID was used to xmit\n" ); printk( KERN_ERR "airo: Unallocated FID was used to xmit\n" );
...@@ -2710,6 +2726,7 @@ static int PC4500_writerid(struct airo_info *ai, u16 rid, ...@@ -2710,6 +2726,7 @@ static int PC4500_writerid(struct airo_info *ai, u16 rid,
one for now. */ one for now. */
static u16 transmit_allocate(struct airo_info *ai, int lenPayload, int raw) static u16 transmit_allocate(struct airo_info *ai, int lenPayload, int raw)
{ {
unsigned int loop = 3000;
Cmd cmd; Cmd cmd;
Resp rsp; Resp rsp;
u16 txFid; u16 txFid;
...@@ -2730,7 +2747,12 @@ static u16 transmit_allocate(struct airo_info *ai, int lenPayload, int raw) ...@@ -2730,7 +2747,12 @@ static u16 transmit_allocate(struct airo_info *ai, int lenPayload, int raw)
/* wait for the allocate event/indication /* wait for the allocate event/indication
* It makes me kind of nervous that this can just sit here and spin, * It makes me kind of nervous that this can just sit here and spin,
* but in practice it only loops like four times. */ * but in practice it only loops like four times. */
while ( (IN4500(ai, EVSTAT) & EV_ALLOC) == 0) ; while (((IN4500(ai, EVSTAT) & EV_ALLOC) == 0) && --loop);
if (!loop) {
txFid = ERROR;
goto done;
}
// get the allocated fid and acknowledge // get the allocated fid and acknowledge
txFid = IN4500(ai, TXALLOCFID); txFid = IN4500(ai, TXALLOCFID);
OUT4500(ai, EVACK, EV_ALLOC); OUT4500(ai, EVACK, EV_ALLOC);
...@@ -3288,15 +3310,18 @@ static void proc_config_on_close( struct inode *inode, struct file *file ) { ...@@ -3288,15 +3310,18 @@ static void proc_config_on_close( struct inode *inode, struct file *file ) {
ai->config.rmode &= 0xfe00; ai->config.rmode &= 0xfe00;
ai->flags &= ~FLAG_802_11; ai->flags &= ~FLAG_802_11;
ai->config.opmode &= 0xFF00; ai->config.opmode &= 0xFF00;
ai->config.scanMode = SCANMODE_ACTIVE;
if ( line[0] == 'a' ) { if ( line[0] == 'a' ) {
ai->config.opmode |= 0; ai->config.opmode |= 0;
} else { } else {
ai->config.opmode |= 1; ai->config.opmode |= 1;
if ( line[0] == 'r' ) { if ( line[0] == 'r' ) {
ai->config.rmode |= RXMODE_RFMON | RXMODE_DISABLE_802_3_HEADER; ai->config.rmode |= RXMODE_RFMON | RXMODE_DISABLE_802_3_HEADER;
ai->config.scanMode = SCANMODE_PASSIVE;
ai->flags |= FLAG_802_11; ai->flags |= FLAG_802_11;
} else if ( line[0] == 'y' ) { } else if ( line[0] == 'y' ) {
ai->config.rmode |= RXMODE_RFMON_ANYBSS | RXMODE_DISABLE_802_3_HEADER; ai->config.rmode |= RXMODE_RFMON_ANYBSS | RXMODE_DISABLE_802_3_HEADER;
ai->config.scanMode = SCANMODE_PASSIVE;
ai->flags |= FLAG_802_11; ai->flags |= FLAG_802_11;
} else if ( line[0] == 'l' ) } else if ( line[0] == 'l' )
ai->config.rmode |= RXMODE_LANMON; ai->config.rmode |= RXMODE_LANMON;
...@@ -4571,24 +4596,28 @@ static int airo_set_mode(struct net_device *dev, ...@@ -4571,24 +4596,28 @@ static int airo_set_mode(struct net_device *dev,
local->config.opmode &= 0xFF00; local->config.opmode &= 0xFF00;
local->config.opmode |= MODE_STA_IBSS; local->config.opmode |= MODE_STA_IBSS;
local->config.rmode &= 0xfe00; local->config.rmode &= 0xfe00;
local->config.scanMode = SCANMODE_ACTIVE;
local->flags &= ~FLAG_802_11; local->flags &= ~FLAG_802_11;
break; break;
case IW_MODE_INFRA: case IW_MODE_INFRA:
local->config.opmode &= 0xFF00; local->config.opmode &= 0xFF00;
local->config.opmode |= MODE_STA_ESS; local->config.opmode |= MODE_STA_ESS;
local->config.rmode &= 0xfe00; local->config.rmode &= 0xfe00;
local->config.scanMode = SCANMODE_ACTIVE;
local->flags &= ~FLAG_802_11; local->flags &= ~FLAG_802_11;
break; break;
case IW_MODE_MASTER: case IW_MODE_MASTER:
local->config.opmode &= 0xFF00; local->config.opmode &= 0xFF00;
local->config.opmode |= MODE_AP; local->config.opmode |= MODE_AP;
local->config.rmode &= 0xfe00; local->config.rmode &= 0xfe00;
local->config.scanMode = SCANMODE_ACTIVE;
local->flags &= ~FLAG_802_11; local->flags &= ~FLAG_802_11;
break; break;
case IW_MODE_REPEAT: case IW_MODE_REPEAT:
local->config.opmode &= 0xFF00; local->config.opmode &= 0xFF00;
local->config.opmode |= MODE_AP_RPTR; local->config.opmode |= MODE_AP_RPTR;
local->config.rmode &= 0xfe00; local->config.rmode &= 0xfe00;
local->config.scanMode = SCANMODE_ACTIVE;
local->flags &= ~FLAG_802_11; local->flags &= ~FLAG_802_11;
break; break;
case IW_MODE_MONITOR: case IW_MODE_MONITOR:
...@@ -4596,6 +4625,7 @@ static int airo_set_mode(struct net_device *dev, ...@@ -4596,6 +4625,7 @@ static int airo_set_mode(struct net_device *dev,
local->config.opmode |= MODE_STA_ESS; local->config.opmode |= MODE_STA_ESS;
local->config.rmode &= 0xfe00; local->config.rmode &= 0xfe00;
local->config.rmode |= RXMODE_RFMON | RXMODE_DISABLE_802_3_HEADER; local->config.rmode |= RXMODE_RFMON | RXMODE_DISABLE_802_3_HEADER;
local->config.scanMode = SCANMODE_PASSIVE;
local->flags |= FLAG_802_11; local->flags |= FLAG_802_11;
break; break;
default: default:
...@@ -5952,7 +5982,6 @@ static int airo_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) ...@@ -5952,7 +5982,6 @@ static int airo_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
* *
* TODO : * TODO :
* o Check if work in Ad-Hoc mode (otherwise, use SPY, as in wvlan_cs) * o Check if work in Ad-Hoc mode (otherwise, use SPY, as in wvlan_cs)
* o Find the noise level
* *
* Jean * Jean
*/ */
...@@ -5976,8 +6005,13 @@ struct iw_statistics *airo_get_wireless_stats(struct net_device *dev) ...@@ -5976,8 +6005,13 @@ struct iw_statistics *airo_get_wireless_stats(struct net_device *dev)
local->wstats.qual.level = 0x100 - local->rssi[status_rid.sigQuality].rssidBm; local->wstats.qual.level = 0x100 - local->rssi[status_rid.sigQuality].rssidBm;
else else
local->wstats.qual.level = (status_rid.normalizedSignalStrength + 321) / 2; local->wstats.qual.level = (status_rid.normalizedSignalStrength + 321) / 2;
if (status_rid.len >= 124) {
local->wstats.qual.noise = 256 - status_rid.noisedBm;
local->wstats.qual.updated = 7;
} else {
local->wstats.qual.noise = 0; local->wstats.qual.noise = 0;
local->wstats.qual.updated = 3; local->wstats.qual.updated = 3;
}
/* Packets discarded in the wireless adapter due to wireless /* Packets discarded in the wireless adapter due to wireless
* specific problems */ * specific problems */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment