diff -aurpN -X /home/fletch/.diff.exclude 001-mjb/Documentation/SubmittingPatches 100-netdrvr_2.6.1_rc1_exp1/Documentation/SubmittingPatches --- 001-mjb/Documentation/SubmittingPatches Tue Aug 5 19:59:11 2003 +++ 100-netdrvr_2.6.1_rc1_exp1/Documentation/SubmittingPatches Thu Jan 8 08:54:03 2004 @@ -239,7 +239,7 @@ Let the compiler optimize away the "no-o Simple example, of poor code: - dev = init_etherdev (NULL, 0); + dev = alloc_etherdev (sizeof(struct funky_private)); if (!dev) return -ENODEV; #ifdef CONFIG_NET_FUNKINESS @@ -254,7 +254,7 @@ Cleaned-up example: #endif (in the code itself) - dev = init_etherdev (NULL, 0); + dev = alloc_etherdev (sizeof(struct funky_private)); if (!dev) return -ENODEV; init_funky_net(dev); diff -aurpN -X /home/fletch/.diff.exclude 001-mjb/Documentation/networking/8139too.txt 100-netdrvr_2.6.1_rc1_exp1/Documentation/networking/8139too.txt --- 001-mjb/Documentation/networking/8139too.txt Tue Sep 2 09:55:40 2003 +++ 100-netdrvr_2.6.1_rc1_exp1/Documentation/networking/8139too.txt Wed Dec 31 16:00:00 1969 @@ -1,449 +0,0 @@ - - "8139too" Fast Ethernet driver for Linux - RTL-8139, -8129, and -8130 10/100 Fast Ethernet adapters - - Copyright 2000,2001 Jeff Garzik - - http://sourceforge.net/projects/gkernel/ - - - Architectures supported (all PCI platforms): - x86, Alpha AXP, PowerPC, Sparc64 - - Kernel versions supported: 2.4.x - - - -Disclaimer ----------- - -DO NOT CONTACT DONALD BECKER FOR SUPPORT OF THIS DRIVER, his driver is -completely different and maintained independently of the 8139too code base. - - - -Requirements ------------- -Kernel 2.4.3 or later. -A Fast Ethernet adapter containing an RTL8139-based chip. - - - -Introduction ------------- - -The "8139too" Fast Ethernet driver for Linux 2.4.0 is a substantial -modification of the experimental rtl8139 driver from Donald Becker, -some versions of which appeared in 2.2.x and 2.3.x kernels. The -RTL-8139 is a very low-cost Fast Ethernet chip, which makes it very -popular. - -The step from 2.2.x to 2.4.x kernels brings many new features to Linux -device drivers. Features for MMIO resources, a standard hot-plug API, -and other interfaces are now becoming requirements, as drivers move -off the x86 platform. With that in mind, I have begun updating the -RTL-8139 driver to current 2.3.x (2.4) kernel standards and APIs, and -fixing the problems that users have been encountering. - - - -Features of 8139too -------------------- -[note - this list intended for people familiar with kernel drivers] - -** 100% MMIO, for full speed operation. All users (so far) have -reported performance increases over their existing RTL drivers. - -** Multi-platform support: x86, Alpha, PPC, ... - -** Use proper SMP spinlocking, fixing SMP interrupt bugs, making the -driver portable to non-x86 SMP platforms in the process. - -** Use new PCI driver API for seamless, low-maintenance hot-plug support - -** Several bugs fixes from original rtl8139 1.08r (October 5, 1999), -including the very common "transmit timeout" problem. - -* Use new resource allocation API, required for hot-plug support -* Use new register read/write macros -* initcall support (module_init/exit) -* vastly improved debug tracing support -* code formatting in many places for readability -* use new init_etherdev() facilities - -...and probably some other less important changes which I forgot. - - - -Installation ------------- - -OPTION 1: Build inside kernel tree (into kernel image, or as module) - - (overwrite 8139too driver in kernel tree with different version) - 1) cp 8139too.c $my_source_tree/drivers/net/8139too.c - -OPTION 2: Build outside kernel tree - - Use the included Makefile. - - - -Tested Adapters ---------------- -AOpen ALN-325C -AT-2500TX 10/100 PCI Fast Ethernet Network Adapter Card -D-Link DFE-530TX -Cnet CNF401 'SinglePoint' 10/100 Base-TX -Genius GF 100TXR4 Fast Ethernet 10/100M PCI Network Card -KTI KF-230TX -KTI KF-230TX/2 -Lantech FastNet TX -Ovislink Fast Ethernet -Planet ENW-9504 (V.4) 10/100 -SDT Jeoun Fast PCI-TX -SMC EZNET 10/100 -UNEX NexNIC ND012C - -(please add your adapter model to this list) - - - -Status of Platform Support --------------------------- - -(see errata below for details) - -x86: tested, stable -Alpha AXP: tested, stable -PowerPC: tested, unstable -Sparc64: not tested - - - -Special Thanks --------------- -The following people contributed invaluable testing time, feedback -and/or patches during the development of this driver. Thanks to all -of them. - -Donald Becker, Alan Cox, Richard Stallman, Linus Torvalds - inspiration - -Alan Cox, Gerard Roudier - insight on posted MMIO writes - -Martin Mares - code review - -Tigran Aivazian - testing, code review, and a bug fix - -Chmouel Boudjnah, Alexander Dietrich, Oleg Drokin, -James Fidell, Taso Hatzi, Peter K - intrepid test team - -And thanks to every supporter free software. - -(see top of 8139too.c for further credits and kudos) - - - -Submitting Bug Reports ----------------------- -Obtain and compile the modified rtl8139-diag source code from the -8139too driver Web site, http://sourceforge.net/projects/gkernel/ -This diagnostics programs, originally from Donald Becker, has been -modified to display all registers on your RTL8139 chip, not just the -first 0x80. - -If possible, send the output of a working and broken driver with - rtl8139-diag -mmaaavvveefN > my-output-file.txt - -Send "lspci -vvv" or "cat /proc/pci" output for PCI information. - - - -Known Bugs / Errata / To-Do ---------------------------- -The following issues are known, and are actively being pursued. Patches -to resolve these issues is welcome. If a problem occurs which is not in -the list, please report it. That's why we do beta releases, after all... - - - -1) Work with Donald to merge fixes and updates into his driver. - -2) ETHTOOL_SSET support - -3) PPC platform has stability problems. (XXX: verify this is still true) - -4) Sparc64 platform not tested at all. - -8) Much improved command line / module parameter setup. (patches and -suggestions welcome) (WIP) - -9) Better documentation. (patches welcome) - -12) 10base-T support flaky or slow (todo: verify this is still true) - - - - -Change History --------------- - -Version 0.9.26 - August 9, 2002 - -* Fix MII ioctl phy id corruption. -* Fix big-endian multicast bug. -* Support register dumps via ethtool. -* Fix several uses of 'len' after potential skb free, in dev->hard_start_xmit -* Replace several "magic numbers" with their proper representation - constants in linux/mii.h. -* Support ethtool media interface via generic kernel MII API -* Export NIC-specific statistics via ethtool. -* Proper support for RTL8139 rev K. (can be disabled via - compile-time conditional) -* Add PCI ids for new 8139 boards. -* Use ethernet crc via generic linux/crc32.h kernel API. -* Better RX reset. Old rx-reset method still available via - a compile-time conditional. -* Only account specific RX errors if rx_status is !OK - - -Version 0.9.22 - November 8, 2001 - -* Additional retries before aborting Tx -* Do not write other TxConfig bits when writing clear-abort bit. -* Ack TxErr intr status after each Tx abort, too. -* Fix oops in interface restart - - -Version 0.9.21 - November 1, 2001 - -* Disable early Rx, it hurts performance and creates races. -* Remove DPRINTK macro function tracing. -* Better interrupt sharing behavior. -* Acknowledge PCI errors. -* Remove early-Rx acknowledgement, unnecessary -* Remove code for uncommon case where Tx packets are - properly aligned, and do not need to be copied. - Tx packets are now always copied into a static DMA buffer, - which is allocated at interface open. -* Fix problems with kernel thread exit. - - -Version 0.9.20 - October 18, 2001 - -* Print out notice when 8139C+ chip is detected -* Add id for D-Link DFE690TXD pcmcia cardbus card (Gert Dewit) - - -Version 0.9.19 - October 9, 2001 - -* Eliminate buffer copy for unaligned Tx's (manfred) -* Better RX error recovery (manfred) -* Wake-On-LAN and ETHTOOL_GSET support (Kalle Niemitalo) -* Fix assertion in PIO mode (various) - - -Version 0.9.18 - July 6, 2001 - -* Fix race leading to crashes on some machines. -* Minimize race leading to low performance. -* Correct interrupt acknowledgement to cover all three - relevant Rx events. -* Add ethtool driver info support. -* Collect additional driver-internal statistics. -* Add descriptions for module parameters. -* Support new SIOCxMIIxxx ioctls added in kernel 2.4.6. -* Multicast filter big endian fix. -* Support new PCI PM API added in kernel 2.4.6. - - -Version 0.9.17 - May 7, 2001 - -* Fix chipset wakeup bug which prevent media connection for 8139B -* Print out "media is unconnected..." instead of - "partner ability 0000" - - -Version 0.9.16 - April 14, 2001 - -* Complete MMIO audit, disable read-after-every-write -* Update Rx interrupt handling -* Enable Early Rx thresholds, highly recommended to reduce - Rx FIFO overflow -* Make 8129 support conditional -* Support for new 2.4.3 kernel APIs -* More correct PIO/MMIO PCI BAR region size checking -* Add check for totally dead/missing hardware -* Disable media timer code to "set full duplex" -* s/spin_lock_irq/spin_lock_irqsave/ -* Only set AcceptMulticast if more than one mc address -* Only set rx_mode if changed, in set_rx_mode -* Only suspend/resume if interface is up -* Always print out version upon module load, even if no devices found - - -Version 0.9.15 - February 20, 2001 - -* Call pci_enable_device to wake up/assign resource to device, - before actually using it. -* Support wacky clone PCI ids (report from Norival Toniato Junior) -* Text spelling corrections -* Make sure tp->phys[] is signed -* Always wake queue after hw restart, in tx_timeout -* Record time of last received packet - - -Version 0.9.14 - January 11, 2001 - -* Merge some changes from Becker version 1.13: - * Add DFE 538TX PCI id - * MII read/write functions updated - * Cfg93[45]6 lock/unlock fix - * RTL-8129 (MII) support -* Clean up spinlocking - - -Version 0.9.13 - December, 2000 - -* Clear blocked signals, avoid buffer overrun setting current->comm -* Remove bogus PCI BAR length assertions -* Remove unused 'debug' module parameter - - -Version 0.9.12 - November 23, 2000 - -* Kill major Tx stop/wake queue race -* Use SET_MODULE_OWNER and fix module unload race -* Fix cable length ("Twister") tuning -* Proper media[] array length checking -* Replace timer with kernel thread for twister tuning state machine - and media checking. Fixes mdio_xxx locking, now mdio_xxx is always - protected by rtnl_lock semaphore. -* Correct some sledgehammer a.k.a. overzealous spin-locks -* Performance: Eliminate atomic_t for Tx counters, we don't need it -* Performance: Don't copy Tx buffer if the rare case occurs where it - is aligned perfectly for us. -* Eliminate needless casting of dev->priv -* PIO mode selection and Twister tuning are now CONFIG_xxx options - (though purposefully not in net/Config.in... yet) - - -Version 0.9.11 - October 28, 2000 - -* Do not fail when PIO and MMIO region lengths do not match. - (They don't on some CardBus models, at least) -* Sanity check Rx packet status and size (Tobias) -* When handling a Tx timeout, disable Tx ASAP if not already. -* Do not inline Tx interrupt handler (better register usage) -* Handle dirty_tx signed integer wrap -* Do not abort Rx processing on lack of memory, keep going - until the current Rx ring is completely handling. (Tobias) -* Clean up rtl8139_close -* Whitespace correction for dev_kfree_skb_irq call - - -Version 0.9.10 - September 12, 2000 - -* Never wrap an Rx packet (faster Rx interrupt handling) -* Clear all TxAborted conditions (bug fix) -* Correct copyright -* More credits -* Update NWay doc URL -* Clean up commonly used ifdef switches -* Reorg info displayed at bootup/modprobe time -* Remove some unneeded spinlocks -* Misc cosmetic code cleanup -* Always print interrupt status for abnormal interrupts -* Use RealTek-recommended FIFO and DMA burst settings (1024 bytes) - - -Version 0.9.9 - September 9, 2000 - -* Fix oops-able bug in Rx ring wrap calculation (David Ford) -* Use PIO instead of MMIO when USE_IO_OPS is defined -* Move Rx error handling out of Rx interrupt handler, resulting in - tighter Rx interrupt processing - - -Version 0.9.8 - September 7, 2000 - -* Propagate request_irq error value (andrew morton) -* Correct potential oops bug in PCI DMA unmap code -* Fix bugs related to counting/discounting of 32-bit CRC in each Rx packet -* Fix 16/32-bit bug in interrupt status check -* Timer cleanups (andrew morton) - - -Version 0.9.7 - June 11, 2000 - -* Fix support for older chips (RTL8139 early chips should now work again) - - -Version 0.9.6 - May 30, 2000 - -* Fix 4-extra-bytes bug - (thanks to Markus Westergren, via Santiago Garcia Mantinan) -* Yet more improved chip recognition - - -Version 0.9.5 - May 17, 2000 - -* Improved chip version recognition -* Continue banging away at receiver hang problem -* Use spin_lock_irq in another spot -* Don't print anything on pci_enable_device, it does so for us -* Disable buggy NWay code -* Define TxConfig bitmasks - - -Version 0.9.4.1 - April 27, 2000 - third public beta release - -* Replace several "magic numbers" with symbolic constants -* Differentiate between board-specific info and chip-specific info - (allows for easier support of specific boards or chips) -* Move some of the transmit side outside of the spinlock - by using atomic variables. Use spin_lock_irq instead of - spin_lock_irq{save,restore} in select places, for better performance. -* New module option "media" for forcing media selection. Functions the - same as "options" in other drivers, and will soon be renamed - 'options' to be homogeneous. -* New power management wake-up code -* Slightly more verbose chip id messages in kernel log -* Add/correct chip register constant list -* New chipset wake up (open) logic -* No longer locks CONFIGx updates -* Do not set Interfame Gap (IFG) bits in TxConfig -* Better Rx reset logic in case of Rx FIFO Overflow -* For chips which support it, enable bit to automatically clear Rx - FIFO overflow -* No longer enable and disable interrupts in interrupt handler - (technique borrowed from BSD driver, appears to have problems - with some chips) -* H/W spinlock now protects ioctl -* Chipset-dependent RxConfig settings - - -Version 0.9.3.3.2 - Feb 22, 2000 - second public beta release - -* Begin integration of Daniel Kobras' MMIO flush patch (disabled for now) -* Softnet logic updates to fix bugs and improve performance -* Dynamic sizing of I/O resources (0x80 for older chips, 0xFF for newer ones) -* Remove bogus SiS entries from PCI probe table -* Add support for cards - "Delta Electronics 8139 10/100BaseTX" - "Addtron Technolgy 8139 10/100BaseTX" -* Fix major bug with rx ring buffer size (also present in rtl8139.c 1.08r) -* PCI DMA mapping by Dave Miller -* Complete rewrite of SMP locking logic -* Hotplug support -* Call rtl8139_hw_start from rtl8139_open, and remove duplicated code - from rtl8139_open -* Reset NWay registers to sane defaults on rtl8139_open/hw_start -* Miscellaneous code cleanup - - -Version 0.7.0 - Feb 7, 2000 - first public beta release -* Initial public version, derived from Donald Becker's rtl8139.c v1.08r - -[EOF] - diff -aurpN -X /home/fletch/.diff.exclude 001-mjb/Documentation/networking/bonding.txt 100-netdrvr_2.6.1_rc1_exp1/Documentation/networking/bonding.txt --- 001-mjb/Documentation/networking/bonding.txt Mon Nov 17 18:28:29 2003 +++ 100-netdrvr_2.6.1_rc1_exp1/Documentation/networking/bonding.txt Thu Jan 8 08:54:03 2004 @@ -21,7 +21,7 @@ userspace tools, please follow the links Table of Contents ================= - + Installation Bond Configuration Module Parameters @@ -66,7 +66,7 @@ of the -I option on the ifenslave compil /usr/include/linux. To install ifenslave.c, do: - # gcc -Wall -Wstrict-prototypes -O -I/usr/src/linux/include ifenslave.c -o ifenslave + # gcc -Wall -Wstrict-prototypes -O -I/usr/src/linux/include ifenslave.c -o ifenslave # cp ifenslave /sbin/ifenslave @@ -74,10 +74,10 @@ Bond Configuration ================== You will need to add at least the following line to /etc/modules.conf -so the bonding driver will automatically load when the bond0 interface is -configured. Refer to the modules.conf manual page for specific modules.conf -syntax details. The Module Parameters section of this document describes each -bonding driver parameter. +so the bonding driver will automatically load when the bond0 interface is +configured. Refer to the modules.conf manual page for specific modules.conf +syntax details. The Module Parameters section of this document describes each +bonding driver parameter. alias bond0 bonding @@ -113,7 +113,7 @@ bonding interface (bond1), use MASTER=bo network interface be a slave of bond1. 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'. If the administration tools of your distribution do not support @@ -128,30 +128,30 @@ manually configure the bonding device wi (use appropriate values for your network above) -You can then create a script containing these commands and place it in the +You can then create a script containing these commands and place it in the appropriate rc directory. If you specifically need all network drivers loaded before the bonding driver, -adding the following line to modules.conf will cause the network driver for +adding the following line to modules.conf will cause the network driver for eth0 and eth1 to be loaded before the bonding driver. probeall bond0 eth0 eth1 bonding -Be careful not to reference bond0 itself at the end of the line, or modprobe +Be careful not to reference bond0 itself at the end of the line, or modprobe will die in an endless recursive loop. -To have device characteristics (such as MTU size) propagate to slave devices, -set the bond characteristics before enslaving the device. The characteristics +To have device characteristics (such as MTU size) propagate to slave devices, +set the bond characteristics before enslaving the device. The characteristics are propagated during the enslave process. -If running SNMP agents, the bonding driver should be loaded before any network -drivers participating in a bond. This requirement is due to the the interface -index (ipAdEntIfIndex) being associated to the first interface found with a -given IP address. That is, there is only one ipAdEntIfIndex for each IP -address. For example, if eth0 and eth1 are slaves of bond0 and the driver for -eth0 is loaded before the bonding driver, the interface for the IP address -will be associated with the eth0 interface. This configuration is shown below, -the IP address 192.168.1.1 has an interface index of 2 which indexes to eth0 +If running SNMP agents, the bonding driver should be loaded before any network +drivers participating in a bond. This requirement is due to the the interface +index (ipAdEntIfIndex) being associated to the first interface found with a +given IP address. That is, there is only one ipAdEntIfIndex for each IP +address. For example, if eth0 and eth1 are slaves of bond0 and the driver for +eth0 is loaded before the bonding driver, the interface for the IP address +will be associated with the eth0 interface. This configuration is shown below, +the IP address 192.168.1.1 has an interface index of 2 which indexes to eth0 in the ifDescr table (ifDescr.2). interfaces.ifTable.ifEntry.ifDescr.1 = lo @@ -189,10 +189,10 @@ functions such as Interface_Scan_Next wi Module Parameters ================= -Optional parameters for the bonding driver can be supplied as command line -arguments to the insmod command. Typically, these parameters are specified in -the file /etc/modules.conf (see the manual page for modules.conf). The -available bonding driver parameters are listed below. If a parameter is not +Optional parameters for the bonding driver can be supplied as command line +arguments to the insmod command. Typically, these parameters are specified in +the file /etc/modules.conf (see the manual page for modules.conf). The +available bonding driver parameters are listed below. If a parameter is not specified the default value is used. When initially configuring a bond, it is recommended "tail -f /var/log/messages" be run in a separate window to watch for bonding driver error messages. @@ -202,19 +202,19 @@ parameters be specified, otherwise serio 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 + + 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 + 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 @@ -223,8 +223,8 @@ arp_ip_target 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 + + 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. @@ -247,7 +247,7 @@ max_bonds 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 @@ -258,7 +258,7 @@ mode Specifies one of the bonding policies. The default is round-robin (balance-rr). Possible values are (you can use either the text or numeric option): - + balance-rr or 0 Round-robin policy: Transmit in a sequential order @@ -273,7 +273,7 @@ mode externally visible on only one port (network adapter) to avoid confusing the switch. This mode provides fault tolerance. - + balance-xor or 2 XOR policy: Transmit based on [(source MAC address @@ -293,7 +293,7 @@ mode groups that share the same speed and duplex settings. Transmits and receives on all slaves in the active aggregator. - + Pre-requisites: 1. Ethtool support in the base drivers for retrieving the @@ -317,7 +317,7 @@ mode Ethtool support in the base drivers for retrieving the speed of each slave. - balance-alb or 6 + balance-alb or 6 Adaptive load balancing: includes balance-tlb + receive load balancing (rlb) for IPV4 traffic and does not require @@ -327,7 +327,7 @@ mode 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 @@ -363,25 +363,11 @@ mode 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 + address (the curr_active_slave) while having a unique hw + address for each slave in the bond. If the curr_active_slave + fails it's hw address is swapped with the new curr_active_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 @@ -397,11 +383,11 @@ primary primary is only valid in active-backup mode. updelay - - Specifies the delay time in milli-seconds to enable a link after a + + 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 Specifies whether or not miimon should use MII or ETHTOOL @@ -529,20 +515,20 @@ Verifying Bond Configuration ---------------------------- The bonding driver information files reside in the /proc/net/bonding directory. -Sample contents of /proc/net/bonding/bond0 after the driver is loaded with +Sample contents of /proc/net/bonding/bond0 after the driver is loaded with parameters of mode=0 and miimon=1000 is shown below. - + Bonding Mode: load balancing (round-robin) Currently Active Slave: eth0 MII Status: up MII Polling Interval (ms): 1000 Up Delay (ms): 0 Down Delay (ms): 0 - + Slave Interface: eth1 MII Status: up Link Failure Count: 1 - + Slave Interface: eth0 MII Status: up Link Failure Count: 1 @@ -550,34 +536,34 @@ parameters of mode=0 and miimon=1000 is 2) Network verification ----------------------- The network configuration can be verified using the ifconfig command. In -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 +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 (HWaddr) as bond0 for all modes except TLB and ALB that require a unique MAC address for each slave. [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 inet addr:XXX.XXX.XXX.YYY Bcast:XXX.XXX.XXX.255 Mask:255.255.252.0 UP BROADCAST RUNNING MASTER MULTICAST MTU:1500 Metric:1 RX packets:7224794 errors:0 dropped:0 overruns:0 frame:0 TX packets:3286647 errors:1 dropped:0 overruns:1 carrier:0 - collisions:0 txqueuelen:0 + collisions:0 txqueuelen:0 -eth0 Link encap:Ethernet HWaddr 00:C0:F0:1F:37:B4 +eth0 Link encap:Ethernet HWaddr 00:C0:F0:1F:37:B4 inet addr:XXX.XXX.XXX.YYY Bcast:XXX.XXX.XXX.255 Mask:255.255.252.0 UP BROADCAST RUNNING SLAVE MULTICAST MTU:1500 Metric:1 RX packets:3573025 errors:0 dropped:0 overruns:0 frame:0 TX packets:1643167 errors:1 dropped:0 overruns:1 carrier:0 - collisions:0 txqueuelen:100 - Interrupt:10 Base address:0x1080 + collisions:0 txqueuelen:100 + Interrupt:10 Base address:0x1080 -eth1 Link encap:Ethernet HWaddr 00:C0:F0:1F:37:B4 +eth1 Link encap:Ethernet HWaddr 00:C0:F0:1F:37:B4 inet addr:XXX.XXX.XXX.YYY Bcast:XXX.XXX.XXX.255 Mask:255.255.252.0 UP BROADCAST RUNNING SLAVE MULTICAST MTU:1500 Metric:1 RX packets:3651769 errors:0 dropped:0 overruns:0 frame:0 TX packets:1643480 errors:0 dropped:0 overruns:0 carrier:0 - collisions:0 txqueuelen:100 - Interrupt:9 Base address:0x1400 + collisions:0 txqueuelen:100 + Interrupt:9 Base address:0x1400 Frequently Asked Questions @@ -605,9 +591,9 @@ Frequently Asked Questions 5. What happens when a slave link dies? - If your ethernet cards support MII or ETHTOOL link status monitoring - and the MII monitoring has been enabled in the driver (see description - of module parameters), there will be no adverse consequences. This + If your ethernet cards support MII or ETHTOOL link status monitoring + and the MII monitoring has been enabled in the driver (see description + of module parameters), there will be no adverse consequences. This release of the bonding driver knows how to get the MII information and enables or disables its slaves according to their link status. See section on High Availability for additional information. @@ -622,8 +608,8 @@ Frequently Asked Questions slave. If neither mii_monitor and arp_interval is configured, the bonding - driver will not handle this situation very well. The driver will - continue to send packets but some packets will be lost. Retransmits + driver will not handle this situation very well. The driver will + continue to send packets but some packets will be lost. Retransmits will cause serious degradation of performance (in the case when one of two slave links fails, 50% packets will be lost, which is a serious problem for both TCP and UDP). @@ -636,9 +622,9 @@ Frequently Asked Questions 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: - + * Many Cisco switches and routers (look for EtherChannel support). * SunTrunking software. * Alteon AceDirector switches / WebOS (use Trunks). @@ -646,7 +632,7 @@ Frequently Asked Questions models (450) can define trunks between ports on different physical units. * Linux bonding, of course ! - + In 802.3ad mode, it works with with systems that support IEEE 802.3ad Dynamic Link Aggregation: @@ -667,21 +653,21 @@ Frequently Asked Questions is then passed to all following slaves and remains persistent (even if the the first slave is removed) until the bonding device is brought down or reconfigured. - + If you wish to change the MAC address, you can set it with ifconfig: # ifconfig bond0 hw ether 00:11:22:33:44:55 The MAC address can be also changed by bringing down/up the device and then changing its slaves (or their order): - + # ifconfig bond0 down ; modprobe -r bonding # ifconfig bond0 .... up # ifenslave bond0 eth... This method will automatically take the address from the next slave that will be added. - + To restore your slaves' MAC addresses, you need to detach them from the bond (`ifenslave -d bond0 eth0'), set them down (`ifconfig eth0 down'), unload the drivers (`rmmod 3c59x', for @@ -729,27 +715,27 @@ High Availability ================= To implement high availability using the bonding driver, the driver needs to be -compiled as a module, because currently it is the only way to pass parameters +compiled as a module, because currently it is the only way to pass parameters to the driver. This may change in the future. -High availability is achieved by using MII or ETHTOOL status reporting. You -need to verify that all your interfaces support MII or ETHTOOL link status -reporting. On Linux kernel 2.2.17, all the 100 Mbps capable drivers and -yellowfin gigabit driver support MII. To determine if ETHTOOL link reporting -is available for interface eth0, type "ethtool eth0" and the "Link detected:" -line should contain the correct link status. If your system has an interface -that does not support MII or ETHTOOL status reporting, a failure of its link -will not be detected! A message indicating MII and ETHTOOL is not supported by -a network driver is logged when the bonding driver is loaded with a non-zero +High availability is achieved by using MII or ETHTOOL status reporting. You +need to verify that all your interfaces support MII or ETHTOOL link status +reporting. On Linux kernel 2.2.17, all the 100 Mbps capable drivers and +yellowfin gigabit driver support MII. To determine if ETHTOOL link reporting +is available for interface eth0, type "ethtool eth0" and the "Link detected:" +line should contain the correct link status. If your system has an interface +that does not support MII or ETHTOOL status reporting, a failure of its link +will not be detected! A message indicating MII and ETHTOOL is not supported by +a network driver is logged when the bonding driver is loaded with a non-zero miimon value. The bonding driver can regularly check all its slaves links using the ETHTOOL -IOCTL (ETHTOOL_GLINK command) or by checking the MII status registers. The -check interval is specified by the module argument "miimon" (MII monitoring). -It takes an integer that represents the checking time in milliseconds. It -should not come to close to (1000/HZ) (10 milli-seconds on i386) because it -may then reduce the system interactivity. A value of 100 seems to be a good -starting point. It means that a dead link will be detected at most 100 +IOCTL (ETHTOOL_GLINK command) or by checking the MII status registers. The +check interval is specified by the module argument "miimon" (MII monitoring). +It takes an integer that represents the checking time in milliseconds. It +should not come to close to (1000/HZ) (10 milli-seconds on i386) because it +may then reduce the system interactivity. A value of 100 seems to be a good +starting point. It means that a dead link will be detected at most 100 milli-seconds after it goes down. Example: @@ -761,7 +747,7 @@ Or, put the following lines in /etc/modu alias bond0 bonding options bond0 miimon=100 -There are currently two policies for high availability. They are dependent on +There are currently two policies for high availability. They are dependent on whether: a) hosts are connected to a single host or switch that support trunking @@ -811,7 +797,7 @@ Example 2 : host to switch at twice the # ifenslave bond0 eth0 eth1 -2) High Availability on two or more switches (or a single switch without +2) High Availability on two or more switches (or a single switch without trunking support) --------------------------------------------------------------------------- This mode is more problematic because it relies on the fact that there @@ -870,10 +856,10 @@ by another external mechanism, it is goo connected to one switch and host2's to the other. Such system will survive a failure of a single host, cable, or switch. The worst thing that may happen in the case of a switch failure is that half of the hosts will be temporarily -unreachable until the other switch expires its tables. +unreachable until the other switch expires its tables. Example 2: Using multiple ethernet cards connected to a switch to configure - NIC failover (switch is not required to support trunking). + NIC failover (switch is not required to support trunking). +----------+ +----------+ @@ -957,7 +943,7 @@ The main limitations are : servers, but may be useful when the front switches send multicast information on their links (e.g. VRRP), or even health-check the servers. Use the arp_interval/arp_ip_target parameters to count incoming/outgoing - frames. + frames. @@ -973,13 +959,12 @@ Donald Becker's Ethernet Drivers and dia You will also find a lot of information regarding Ethernet, NWay, MII, etc. at www.scyld.com. -For new versions of the driver, patches for older kernels and the updated -userspace tools, take a look at Willy Tarreau's site : +Patches for 2.2 kernels are at Willy Tarreau's site : - http://wtarreau.free.fr/pub/bonding/ - - http://www-miaif.lip6.fr/willy/pub/bonding/ + - http://www-miaif.lip6.fr/~tarreau/pub/bonding/ To get latest informations about Linux Kernel development, please consult the Linux Kernel Mailing List Archives at : - http://boudicca.tux.org/hypermail/linux-kernel/latest/ + http://www.ussg.iu.edu/hypermail/linux/kernel/ -- END -- diff -aurpN -X /home/fletch/.diff.exclude 001-mjb/Documentation/networking/ifenslave.c 100-netdrvr_2.6.1_rc1_exp1/Documentation/networking/ifenslave.c --- 001-mjb/Documentation/networking/ifenslave.c Mon Nov 17 18:28:29 2003 +++ 100-netdrvr_2.6.1_rc1_exp1/Documentation/networking/ifenslave.c Thu Jan 8 08:54:03 2004 @@ -4,8 +4,6 @@ * This program controls the Linux implementation of running multiple * network interfaces in parallel. * - * Usage: ifenslave [-v] master-interface < slave-interface [metric ] > ... - * * Author: Donald Becker * Copyright 1994-1996 Donald Becker * @@ -90,24 +88,30 @@ * - For opt_c: slave should not be set to the master's setting * while it is running. It was already set during enslave. To * simplify things, it is now handeled separately. + * + * - 2003/09/24 - Shmulik Hen + * - Code cleanup and style changes + * set version to 1.1.0 */ -#define APP_VERSION "1.0.12" -#define APP_RELDATE "June 30, 2003" +#define APP_VERSION "1.1.0" +#define APP_RELDATE "Septemer 24, 2003" #define APP_NAME "ifenslave" static char *version = -APP_NAME ".c:v" APP_VERSION " (" APP_RELDATE ") " "\nDonald Becker (becker@cesdis.gsfc.nasa.gov).\n" -"detach support added on 2000/10/02 by Willy Tarreau (willy at meta-x.org).\n" -"2.4 kernel support added on 2001/02/16 by Chad N. Tindel (ctindel at ieee dot org.\n"; +APP_NAME ".c:v" APP_VERSION " (" APP_RELDATE ")\n" +"o Donald Becker (becker@cesdis.gsfc.nasa.gov).\n" +"o Detach support added on 2000/10/02 by Willy Tarreau (willy at meta-x.org).\n" +"o 2.4 kernel support added on 2001/02/16 by Chad N. Tindel\n" +" (ctindel at ieee dot org).\n"; static const char *usage_msg = -"Usage: ifenslave [-adfrvVh] < [metric ] > ...\n" -" ifenslave -c master-interface slave-if\n"; +"Usage: ifenslave [-f] [...]\n" +" ifenslave -d [...]\n" +" ifenslave -c \n" +" ifenslave --help\n"; -static const char *howto_msg = -"Usage: ifenslave [-adfrvVh] < [metric ] > ...\n" -" ifenslave -c master-interface slave-if\n" +static const char *help_msg = "\n" " To create a bond device, simply follow these three steps :\n" " - ensure that the required drivers are properly loaded :\n" @@ -115,18 +119,32 @@ static const char *howto_msg = " - assign an IP address to the bond device :\n" " # ifconfig bond0 netmask broadcast \n" " - attach all the interfaces you need to the bond device :\n" -" # ifenslave bond0 eth0 eth1 eth2\n" +" # ifenslave [{-f|--force}] bond0 eth0 [eth1 [eth2]...]\n" " If bond0 didn't have a MAC address, it will take eth0's. Then, all\n" " interfaces attached AFTER this assignment will get the same MAC addr.\n" -"\n" -" To detach a dead interface without setting the bond device down :\n" -" # ifenslave -d bond0 eth1\n" +" (except for ALB/TLB modes)\n" "\n" " To set the bond device down and automatically release all the slaves :\n" " # ifconfig bond0 down\n" "\n" +" To detach a dead interface without setting the bond device down :\n" +" # ifenslave {-d|--detach} bond0 eth0 [eth1 [eth2]...]\n" +"\n" " To change active slave :\n" -" # ifenslave -c bond0 eth0\n" +" # ifenslave {-c|--change-active} bond0 eth0\n" +"\n" +" To show master interface info\n" +" # ifenslave bond0\n" +"\n" +" To show all interfaces info\n" +" # ifenslave {-a|--all-interfaces}\n" +"\n" +" To be more verbose\n" +" # ifenslave {-v|--verbose} ...\n" +"\n" +" # ifenslave {-u|--usage} Show usage\n" +" # ifenslave {-V|--version} Show version\n" +" # ifenslave {-h|--help} This message\n" "\n"; #include @@ -153,476 +171,332 @@ typedef __uint8_t u8; /* ditto */ #include struct option longopts[] = { - /* { name has_arg *flag val } */ - {"all-interfaces", 0, 0, 'a'}, /* Show all interfaces. */ - {"force", 0, 0, 'f'}, /* Force the operation. */ - {"help", 0, 0, '?'}, /* Give help */ - {"howto", 0, 0, 'h'}, /* Give some more help */ - {"receive-slave", 0, 0, 'r'}, /* Make a receive-only slave. */ - {"verbose", 0, 0, 'v'}, /* Report each action taken. */ - {"version", 0, 0, 'V'}, /* Emit version information. */ - {"detach", 0, 0, 'd'}, /* Detach a slave interface. */ - {"change-active", 0, 0, 'c'}, /* Change the active slave. */ - { 0, 0, 0, 0 } + /* { name has_arg *flag val } */ + {"all-interfaces", 0, 0, 'a'}, /* Show all interfaces. */ + {"change-active", 0, 0, 'c'}, /* Change the active slave. */ + {"detach", 0, 0, 'd'}, /* Detach a slave interface. */ + {"force", 0, 0, 'f'}, /* Force the operation. */ + {"help", 0, 0, 'h'}, /* Give help */ + {"usage", 0, 0, 'u'}, /* Give usage */ + {"verbose", 0, 0, 'v'}, /* Report each action taken. */ + {"version", 0, 0, 'V'}, /* Emit version information. */ + { 0, 0, 0, 0} }; /* Command-line flags. */ unsigned int -opt_a = 0, /* Show-all-interfaces flag. */ -opt_f = 0, /* Force the operation. */ -opt_r = 0, /* Set up a Rx-only slave. */ -opt_d = 0, /* detach a slave interface. */ -opt_c = 0, /* change-active-slave flag. */ -verbose = 0, /* Verbose flag. */ -opt_version = 0, -opt_howto = 0; -int skfd = -1; /* AF_INET socket for ioctl() calls. */ +opt_a = 0, /* Show-all-interfaces flag. */ +opt_c = 0, /* Change-active-slave flag. */ +opt_d = 0, /* Detach a slave interface. */ +opt_f = 0, /* Force the operation. */ +opt_h = 0, /* Help */ +opt_u = 0, /* Usage */ +opt_v = 0, /* Verbose flag. */ +opt_V = 0; /* Version */ + +int skfd = -1; /* AF_INET socket for ioctl() calls.*/ +int abi_ver = 0; /* userland - kernel ABI version */ +int hwaddr_set = 0; /* Master's hwaddr is set */ +int saved_errno; + +struct ifreq master_mtu, master_flags, master_hwaddr; +struct ifreq slave_mtu, slave_flags, slave_hwaddr; + +struct dev_ifr { + struct ifreq *req_ifr; + char *req_name; + int req_type; +}; + +struct dev_ifr master_ifra[] = { + {&master_mtu, "SIOCGIFMTU", SIOCGIFMTU}, + {&master_flags, "SIOCGIFFLAGS", SIOCGIFFLAGS}, + {&master_hwaddr, "SIOCGIFHWADDR", SIOCGIFHWADDR}, + {NULL, "", 0} +}; + +struct dev_ifr slave_ifra[] = { + {&slave_mtu, "SIOCGIFMTU", SIOCGIFMTU}, + {&slave_flags, "SIOCGIFFLAGS", SIOCGIFFLAGS}, + {&slave_hwaddr, "SIOCGIFHWADDR", SIOCGIFHWADDR}, + {NULL, "", 0} +}; static void if_print(char *ifname); -static int get_abi_ver(char *master_ifname); +static int get_drv_info(char *master_ifname); +static int get_if_settings(char *ifname, struct dev_ifr ifra[]); +static int get_slave_flags(char *slave_ifname); +static int set_master_hwaddr(char *master_ifname, struct sockaddr *hwaddr); +static int set_slave_hwaddr(char *slave_ifname, struct sockaddr *hwaddr); +static int set_slave_mtu(char *slave_ifname, int mtu); +static int set_if_flags(char *ifname, short flags); +static int set_if_up(char *ifname, short flags); +static int set_if_down(char *ifname, short flags); +static int clear_if_addr(char *ifname); +static int set_if_addr(char *master_ifname, char *slave_ifname); +static int change_active(char *master_ifname, char *slave_ifname); +static int enslave(char *master_ifname, char *slave_ifname); +static int release(char *master_ifname, char *slave_ifname); +#define v_print(fmt, args...) \ + if (opt_v) \ + fprintf(stderr, fmt, ## args ) -int -main(int argc, char **argv) +int main(int argc, char *argv[]) { - struct ifreq ifr2, if_hwaddr, if_ipaddr, if_metric, if_mtu, if_dstaddr; - struct ifreq if_netmask, if_brdaddr, if_flags; - int rv, goterr = 0; - int c, errflag = 0; - sa_family_t master_family; char **spp, *master_ifname, *slave_ifname; - int hwaddr_notset; - int abi_ver = 0; + int c, i, rv; + int res = 0; + int exclusive = 0; - while ((c = getopt_long(argc, argv, "acdfrvV?h", longopts, 0)) != EOF) + while ((c = getopt_long(argc, argv, "acdfhuvV", longopts, 0)) != EOF) { switch (c) { - case 'a': opt_a++; break; - case 'f': opt_f++; break; - case 'r': opt_r++; break; - case 'd': opt_d++; break; - case 'c': opt_c++; break; - case 'v': verbose++; break; - case 'V': opt_version++; break; - case 'h': opt_howto++; break; - case '?': errflag++; - } + case 'a': opt_a++; exclusive++; break; + case 'c': opt_c++; exclusive++; break; + case 'd': opt_d++; exclusive++; break; + case 'f': opt_f++; exclusive++; break; + case 'h': opt_h++; exclusive++; break; + case 'u': opt_u++; exclusive++; break; + case 'v': opt_v++; break; + case 'V': opt_V++; exclusive++; break; - /* option check */ - if (opt_c) - if(opt_a || opt_f || opt_r || opt_d || verbose || opt_version || - opt_howto || errflag ) { + case '?': fprintf(stderr, usage_msg); - return 2; + res = 2; + goto out; } + } - if (errflag) { + /* options check */ + if (exclusive > 1) { fprintf(stderr, usage_msg); - return 2; + res = 2; + goto out; } - if (opt_howto) { - fprintf(stderr, howto_msg); - return 0; + if (opt_v || opt_V) { + printf(version); + if (opt_V) { + res = 0; + goto out; + } } - if (verbose || opt_version) { - printf(version); - if (opt_version) - exit(0); + if (opt_u) { + printf(usage_msg); + res = 0; + goto out; } - /* Open a basic socket. */ - if ((skfd = socket(AF_INET, SOCK_DGRAM,0)) < 0) { - perror("socket"); - exit(-1); + if (opt_h) { + printf(usage_msg); + printf(help_msg); + res = 0; + goto out; } - if (verbose) - fprintf(stderr, "DEBUG: argc=%d, optind=%d and argv[optind] is %s.\n", - argc, optind, argv[optind]); + /* Open a basic socket */ + if ((skfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { + perror("socket"); + res = 1; + goto out; + } - /* No remaining args means show all interfaces. */ - if (optind == argc) { - if_print((char *)NULL); - (void) close(skfd); - exit(0); + if (opt_a) { + if (optind == argc) { + /* No remaining args */ + /* show all interfaces */ + if_print((char *)NULL); + goto out; + } else { + /* Just show usage */ + fprintf(stderr, usage_msg); + res = 2; + goto out; + } } - /* Copy the interface name. */ + /* Copy the interface name */ spp = argv + optind; master_ifname = *spp++; - slave_ifname = *spp++; - /* Check command line. */ - if (opt_c) { - char **tempp = spp; - if ((master_ifname == NULL)||(slave_ifname == NULL)||(*tempp++ != NULL)) { - fprintf(stderr, usage_msg); - (void) close(skfd); - return 2; - } + if (master_ifname == NULL) { + fprintf(stderr, usage_msg); + res = 2; + goto out; } - /* A single args means show the configuration for this interface. */ - if (slave_ifname == NULL) { - if_print(master_ifname); - (void) close(skfd); - exit(0); + /* exchange abi version with bonding module */ + res = get_drv_info(master_ifname); + if (res) { + fprintf(stderr, + "Master '%s': Error: handshake with driver failed. " + "Aborting\n", + master_ifname); + goto out; } - /* exchange abi version with bonding driver */ - abi_ver = get_abi_ver(master_ifname); - if (abi_ver < 0) { - (void) close(skfd); - exit(1); - } - - /* Get the vitals from the master interface. */ - { - struct ifreq *ifra[7] = { &if_ipaddr, &if_mtu, &if_dstaddr, - &if_brdaddr, &if_netmask, &if_flags, - &if_hwaddr }; - const char *req_name[7] = { - "IP address", "MTU", "destination address", - "broadcast address", "netmask", "status flags", - "hardware address" }; - const int ioctl_req_type[7] = { - SIOCGIFADDR, SIOCGIFMTU, SIOCGIFDSTADDR, - SIOCGIFBRDADDR, SIOCGIFNETMASK, SIOCGIFFLAGS, - SIOCGIFHWADDR }; - int i; - - for (i = 0; i < 7; i++) { - strncpy(ifra[i]->ifr_name, master_ifname, IFNAMSIZ); - if (ioctl(skfd, ioctl_req_type[i], ifra[i]) < 0) { - fprintf(stderr, - "Something broke getting the master's %s: %s.\n", - req_name[i], strerror(errno)); - } - } - - /* check if master is up; if not then fail any operation */ - if (!(if_flags.ifr_flags & IFF_UP)) { - fprintf(stderr, "Illegal operation; the specified master interface '%s' is not up.\n", master_ifname); - (void) close(skfd); - exit (1); - } + slave_ifname = *spp++; - hwaddr_notset = 1; /* assume master's address not set yet */ - for (i = 0; hwaddr_notset && (i < 6); i++) { - hwaddr_notset &= ((unsigned char *)if_hwaddr.ifr_hwaddr.sa_data)[i] == 0; + if (slave_ifname == NULL) { + if (opt_d || opt_c) { + fprintf(stderr, usage_msg); + res = 2; + goto out; } - /* The family '1' is ARPHRD_ETHER for ethernet. */ - if (if_hwaddr.ifr_hwaddr.sa_family != 1 && !opt_f) { - fprintf(stderr, "The specified master interface '%s' is not" - " ethernet-like.\n This program is designed to work" - " with ethernet-like network interfaces.\n" - " Use the '-f' option to force the operation.\n", - master_ifname); - (void) close(skfd); - exit (1); - } - master_family = if_hwaddr.ifr_hwaddr.sa_family; - if (verbose) { - unsigned char *hwaddr = (unsigned char *)if_hwaddr.ifr_hwaddr.sa_data; - printf("The current hardware address (SIOCGIFHWADDR) of %s is type %d " - "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x.\n", master_ifname, - if_hwaddr.ifr_hwaddr.sa_family, hwaddr[0], hwaddr[1], - hwaddr[2], hwaddr[3], hwaddr[4], hwaddr[5]); - } + /* A single arg means show the + * configuration for this interface + */ + if_print(master_ifname); + goto out; } + res = get_if_settings(master_ifname, master_ifra); + if (res) { + /* Probably a good reason not to go on */ + fprintf(stderr, + "Master '%s': Error: get settings failed: %s. " + "Aborting\n", + master_ifname, strerror(res)); + goto out; + } - /* do this when enslaving interfaces */ - do { - if (opt_d) { /* detach a slave interface from the master */ - strncpy(if_flags.ifr_name, master_ifname, IFNAMSIZ); - strncpy(if_flags.ifr_slave, slave_ifname, IFNAMSIZ); - if ((ioctl(skfd, SIOCBONDRELEASE, &if_flags) < 0) && - (ioctl(skfd, BOND_RELEASE_OLD, &if_flags) < 0)) { - fprintf(stderr, "SIOCBONDRELEASE: cannot detach %s from %s. errno=%s.\n", - slave_ifname, master_ifname, strerror(errno)); - } - else if (abi_ver < 1) { - /* The driver is using an old ABI, so we'll set the interface - * down to avoid any conflicts due to same IP/MAC - */ - strncpy(ifr2.ifr_name, slave_ifname, IFNAMSIZ); - if (ioctl(skfd, SIOCGIFFLAGS, &ifr2) < 0) { - int saved_errno = errno; - fprintf(stderr, "SIOCGIFFLAGS on %s failed: %s\n", slave_ifname, - strerror(saved_errno)); - } - else { - ifr2.ifr_flags &= ~(IFF_UP | IFF_RUNNING); - if (ioctl(skfd, SIOCSIFFLAGS, &ifr2) < 0) { - int saved_errno = errno; - fprintf(stderr, "Shutting down interface %s failed: %s\n", - slave_ifname, strerror(saved_errno)); - } - } - } - } else if (opt_c) { /* change primary slave */ - strncpy(if_flags.ifr_name, master_ifname, IFNAMSIZ); - strncpy(if_flags.ifr_slave, slave_ifname, IFNAMSIZ); - if ((ioctl(skfd, SIOCBONDCHANGEACTIVE, &if_flags) < 0) && - (ioctl(skfd, BOND_CHANGE_ACTIVE_OLD, &if_flags) < 0)) { - fprintf(stderr, "SIOCBONDCHANGEACTIVE: %s.\n", strerror(errno)); - } - } else { /* attach a slave interface to the master */ - - strncpy(ifr2.ifr_name, slave_ifname, IFNAMSIZ); - if (ioctl(skfd, SIOCGIFFLAGS, &ifr2) < 0) { - int saved_errno = errno; - fprintf(stderr, "SIOCGIFFLAGS on %s failed: %s\n", slave_ifname, - strerror(saved_errno)); - (void) close(skfd); - return 1; - } - - if ((ifr2.ifr_flags & IFF_SLAVE) && !opt_r) { - fprintf(stderr, "%s is already a slave\n", slave_ifname); - (void) close(skfd); - return 1; - } - - /* if hwaddr_notset, assign the slave hw address to the master */ - if (hwaddr_notset) { - /* assign the slave hw address to the - * master since it currently does not - * have one; otherwise, slaves may - * have different hw addresses in - * active-backup mode as seen when enslaving - * using "ifenslave bond0 eth0 eth1" because - * hwaddr_notset is set outside this loop. - * TODO: put this and the "else" portion in - * a function. - */ - /* get the slaves MAC address */ - strncpy(if_hwaddr.ifr_name, slave_ifname, - IFNAMSIZ); - rv = ioctl(skfd, SIOCGIFHWADDR, &if_hwaddr); - if (-1 == rv) { - fprintf(stderr, "Could not get MAC " - "address of %s: %s\n", - slave_ifname, - strerror(errno)); - strncpy(if_hwaddr.ifr_name, - master_ifname, IFNAMSIZ); - goterr = 1; - } - - if (!goterr) { - if (abi_ver < 1) { - /* In ABI versions older than 1, the - * master's set_mac routine couldn't - * work if it was up, because it - * used the default ethernet set_mac - * function. - */ - /* bring master down */ - if_flags.ifr_flags &= ~IFF_UP; - if (ioctl(skfd, SIOCSIFFLAGS, - &if_flags) < 0) { - goterr = 1; - fprintf(stderr, - "Shutting down " - "interface %s failed: " - "%s\n", - master_ifname, - strerror(errno)); - } - } - - strncpy(if_hwaddr.ifr_name, - master_ifname, IFNAMSIZ); - if (ioctl(skfd, SIOCSIFHWADDR, - &if_hwaddr) < 0) { - fprintf(stderr, - "Could not set MAC " - "address of %s: %s\n", - master_ifname, - strerror(errno)); - goterr=1; - } else { - hwaddr_notset = 0; - } - - if (abi_ver < 1) { - /* bring master back up */ - if_flags.ifr_flags |= IFF_UP; - if (ioctl(skfd, SIOCSIFFLAGS, - &if_flags) < 0) { - fprintf(stderr, - "Bringing up interface " - "%s failed: %s\n", - master_ifname, - strerror(errno)); - } - } - } - } else if (abi_ver < 1) { /* if (hwaddr_notset) */ - - /* The driver is using an old ABI, so we'll set the interface - * down and assign the master's hwaddr to it - */ - if (ifr2.ifr_flags & IFF_UP) { - ifr2.ifr_flags &= ~IFF_UP; - if (ioctl(skfd, SIOCSIFFLAGS, &ifr2) < 0) { - int saved_errno = errno; - fprintf(stderr, "Shutting down interface %s failed: %s\n", - slave_ifname, strerror(saved_errno)); - } - } - - strncpy(if_hwaddr.ifr_name, slave_ifname, IFNAMSIZ); - if (ioctl(skfd, SIOCSIFHWADDR, &if_hwaddr) < 0) { - int saved_errno = errno; - fprintf(stderr, "SIOCSIFHWADDR on %s failed: %s\n", if_hwaddr.ifr_name, - strerror(saved_errno)); - if (saved_errno == EBUSY) - fprintf(stderr, " The slave device %s is busy: it must be" - " idle before running this command.\n", slave_ifname); - else if (saved_errno == EOPNOTSUPP) - fprintf(stderr, " The slave device you specified does not support" - " setting the MAC address.\n Your kernel likely does not" - " support slave devices.\n"); - else if (saved_errno == EINVAL) - fprintf(stderr, " The slave device's address type does not match" - " the master's address type.\n"); - } else { - if (verbose) { - unsigned char *hwaddr = if_hwaddr.ifr_hwaddr.sa_data; - printf("Slave's (%s) hardware address set to " - "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x.\n", slave_ifname, - hwaddr[0], hwaddr[1], hwaddr[2], hwaddr[3], hwaddr[4], hwaddr[5]); - } - } - } + /* check if master is indeed a master; + * if not then fail any operation + */ + if (!(master_flags.ifr_flags & IFF_MASTER)) { + fprintf(stderr, + "Illegal operation; the specified interface '%s' " + "is not a master. Aborting\n", + master_ifname); + res = 1; + goto out; + } - if (*spp && !strcmp(*spp, "metric")) { - if (*++spp == NULL) { - fprintf(stderr, usage_msg); - (void) close(skfd); - exit(2); - } - if_metric.ifr_metric = atoi(*spp); - strncpy(if_metric.ifr_name, slave_ifname, IFNAMSIZ); - if (ioctl(skfd, SIOCSIFMETRIC, &if_metric) < 0) { - fprintf(stderr, "SIOCSIFMETRIC on %s: %s\n", slave_ifname, - strerror(errno)); - goterr = 1; - } - spp++; - } + /* check if master is up; if not then fail any operation */ + if (!(master_flags.ifr_flags & IFF_UP)) { + fprintf(stderr, + "Illegal operation; the specified master interface " + "'%s' is not up.\n", + master_ifname); + res = 1; + goto out; + } - if (strncpy(if_ipaddr.ifr_name, slave_ifname, IFNAMSIZ) <= 0 - || ioctl(skfd, SIOCSIFADDR, &if_ipaddr) < 0) { - fprintf(stderr, - "Something broke setting the slave's address: %s.\n", - strerror(errno)); - } else { - if (verbose) { - unsigned char *ipaddr = if_ipaddr.ifr_addr.sa_data; - printf("Set the slave's (%s) IP address to %d.%d.%d.%d.\n", - slave_ifname, ipaddr[0], ipaddr[1], ipaddr[2], ipaddr[3]); - } - } + /* Only for enslaving */ + if (!opt_c && !opt_d) { + sa_family_t master_family = master_hwaddr.ifr_hwaddr.sa_family; + unsigned char *hwaddr = + (unsigned char *)master_hwaddr.ifr_hwaddr.sa_data; - if (strncpy(if_mtu.ifr_name, slave_ifname, IFNAMSIZ) <= 0 - || ioctl(skfd, SIOCSIFMTU, &if_mtu) < 0) { - fprintf(stderr, "Something broke setting the slave MTU: %s.\n", - strerror(errno)); - } else { - if (verbose) - printf("Set the slave's (%s) MTU to %d.\n", slave_ifname, if_mtu.ifr_mtu); - } + /* The family '1' is ARPHRD_ETHER for ethernet. */ + if (master_family != 1 && !opt_f) { + fprintf(stderr, + "Illegal operation: The specified master " + "interface '%s' is not ethernet-like.\n " + "This program is designed to work with " + "ethernet-like network interfaces.\n " + "Use the '-f' option to force the " + "operation.\n", + master_ifname); + res = 1; + goto out; + } - if (strncpy(if_dstaddr.ifr_name, slave_ifname, IFNAMSIZ) <= 0 - || ioctl(skfd, SIOCSIFDSTADDR, &if_dstaddr) < 0) { - fprintf(stderr, "Error setting the slave (%s) with SIOCSIFDSTADDR: %s.\n", - slave_ifname, strerror(errno)); - } else { - if (verbose) { - unsigned char *ipaddr = if_dstaddr.ifr_dstaddr.sa_data; - printf("Set the slave's (%s) destination address to %d.%d.%d.%d.\n", - slave_ifname, ipaddr[0], ipaddr[1], ipaddr[2], ipaddr[3]); - } + /* Check master's hw addr */ + for (i = 0; i < 6; i++) { + if (hwaddr[i] != 0) { + hwaddr_set = 1; + break; } + } - if (strncpy(if_brdaddr.ifr_name, slave_ifname, IFNAMSIZ) <= 0 - || ioctl(skfd, SIOCSIFBRDADDR, &if_brdaddr) < 0) { - fprintf(stderr, - "Something broke setting the slave (%s) broadcast address: %s.\n", - slave_ifname, strerror(errno)); - } else { - if (verbose) { - unsigned char *ipaddr = if_brdaddr.ifr_broadaddr.sa_data; - printf("Set the slave's (%s) broadcast address to %d.%d.%d.%d.\n", - slave_ifname, ipaddr[0], ipaddr[1], ipaddr[2], ipaddr[3]); - } - } + if (hwaddr_set) { + v_print("current hardware address of master '%s' " + "is %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x, " + "type %d\n", + master_ifname, + hwaddr[0], hwaddr[1], + hwaddr[2], hwaddr[3], + hwaddr[4], hwaddr[5], + master_family); + } + } - if (strncpy(if_netmask.ifr_name, slave_ifname, IFNAMSIZ) <= 0 - || ioctl(skfd, SIOCSIFNETMASK, &if_netmask) < 0) { - fprintf(stderr, - "Something broke setting the slave (%s) netmask: %s.\n", - slave_ifname, strerror(errno)); - } else { - if (verbose) { - unsigned char *ipaddr = if_netmask.ifr_netmask.sa_data; - printf("Set the slave's (%s) netmask to %d.%d.%d.%d.\n", - slave_ifname, ipaddr[0], ipaddr[1], ipaddr[2], ipaddr[3]); + /* Accepts only one slave */ + if (opt_c) { + /* change active slave */ + res = get_slave_flags(slave_ifname); + if (res) { + fprintf(stderr, + "Slave '%s': Error: get flags failed. " + "Aborting\n", + slave_ifname); + goto out; + } + res = change_active(master_ifname, slave_ifname); + if (res) { + fprintf(stderr, + "Master '%s', Slave '%s': Error: " + "Change active failed\n", + master_ifname, slave_ifname); + } + } else { + /* Accept multiple slaves */ + do { + if (opt_d) { + /* detach a slave interface from the master */ + rv = get_slave_flags(slave_ifname); + if (rv) { + /* Can't work with this slave. */ + /* remember the error and skip it*/ + fprintf(stderr, + "Slave '%s': Error: get flags " + "failed. Skipping\n", + slave_ifname); + res = rv; + continue; } - } - - if (abi_ver < 1) { - - /* The driver is using an old ABI, so we'll set the interface - * up before enslaving it - */ - ifr2.ifr_flags |= IFF_UP; - if ((ifr2.ifr_flags &= ~(IFF_SLAVE | IFF_MASTER)) == 0 - || strncpy(ifr2.ifr_name, slave_ifname, IFNAMSIZ) <= 0 - || ioctl(skfd, SIOCSIFFLAGS, &ifr2) < 0) { - fprintf(stderr, - "Something broke setting the slave (%s) flags: %s.\n", - slave_ifname, strerror(errno)); - } else { - if (verbose) - printf("Set the slave's (%s) flags %4.4x.\n", - slave_ifname, if_flags.ifr_flags); + rv = release(master_ifname, slave_ifname); + if (rv) { + fprintf(stderr, + "Master '%s', Slave '%s': Error: " + "Release failed\n", + master_ifname, slave_ifname); + res = rv; } } else { - /* the bonding module takes care of setting the slave's mac address - * and opening its interface - */ - if (ifr2.ifr_flags & IFF_UP) { /* the interface will need to be down */ - ifr2.ifr_flags &= ~IFF_UP; - if (ioctl(skfd, SIOCSIFFLAGS, &ifr2) < 0) { - int saved_errno = errno; - fprintf(stderr, "Shutting down interface %s failed: %s\n", - slave_ifname, strerror(saved_errno)); - } + /* attach a slave interface to the master */ + rv = get_if_settings(slave_ifname, slave_ifra); + if (rv) { + /* Can't work with this slave. */ + /* remember the error and skip it*/ + fprintf(stderr, + "Slave '%s': Error: get " + "settings failed: %s. " + "Skipping\n", + slave_ifname, strerror(rv)); + res = rv; + continue; } - } - - /* Do the real thing */ - if (!opt_r) { - strncpy(if_flags.ifr_name, master_ifname, IFNAMSIZ); - strncpy(if_flags.ifr_slave, slave_ifname, IFNAMSIZ); - if ((ioctl(skfd, SIOCBONDENSLAVE, &if_flags) < 0) && - (ioctl(skfd, BOND_ENSLAVE_OLD, &if_flags) < 0)) { - fprintf(stderr, "SIOCBONDENSLAVE: %s.\n", strerror(errno)); + rv = enslave(master_ifname, slave_ifname); + if (rv) { + fprintf(stderr, + "Master '%s', Slave '%s': Error: " + "Enslave failed\n", + master_ifname, slave_ifname); + res = rv; } } - } - } while ( (slave_ifname = *spp++) != NULL); + } while ((slave_ifname = *spp++) != NULL); + } - /* Close the socket. */ - (void) close(skfd); +out: + if (skfd >= 0) { + close(skfd); + } - return(goterr); + return res; } static short mif_flags; @@ -631,35 +505,34 @@ static short mif_flags; static int if_getconfig(char *ifname) { struct ifreq ifr; - int metric, mtu; /* Parameters of the master interface. */ + int metric, mtu; /* Parameters of the master interface. */ struct sockaddr dstaddr, broadaddr, netmask; + unsigned char *hwaddr; strcpy(ifr.ifr_name, ifname); if (ioctl(skfd, SIOCGIFFLAGS, &ifr) < 0) return -1; mif_flags = ifr.ifr_flags; printf("The result of SIOCGIFFLAGS on %s is %x.\n", - ifname, ifr.ifr_flags); + ifname, ifr.ifr_flags); strcpy(ifr.ifr_name, ifname); if (ioctl(skfd, SIOCGIFADDR, &ifr) < 0) return -1; printf("The result of SIOCGIFADDR is %2.2x.%2.2x.%2.2x.%2.2x.\n", - ifr.ifr_addr.sa_data[0], ifr.ifr_addr.sa_data[1], - ifr.ifr_addr.sa_data[2], ifr.ifr_addr.sa_data[3]); + ifr.ifr_addr.sa_data[0], ifr.ifr_addr.sa_data[1], + ifr.ifr_addr.sa_data[2], ifr.ifr_addr.sa_data[3]); strcpy(ifr.ifr_name, ifname); if (ioctl(skfd, SIOCGIFHWADDR, &ifr) < 0) return -1; - { - /* Gotta convert from 'char' to unsigned for printf(). */ - unsigned char *hwaddr = (unsigned char *)ifr.ifr_hwaddr.sa_data; - printf("The result of SIOCGIFHWADDR is type %d " - "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x.\n", - ifr.ifr_hwaddr.sa_family, hwaddr[0], hwaddr[1], - hwaddr[2], hwaddr[3], hwaddr[4], hwaddr[5]); - } + /* Gotta convert from 'char' to unsigned for printf(). */ + hwaddr = (unsigned char *)ifr.ifr_hwaddr.sa_data; + printf("The result of SIOCGIFHWADDR is type %d " + "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x.\n", + ifr.ifr_hwaddr.sa_family, hwaddr[0], hwaddr[1], + hwaddr[2], hwaddr[3], hwaddr[4], hwaddr[5]); strcpy(ifr.ifr_name, ifname); if (ioctl(skfd, SIOCGIFMETRIC, &ifr) < 0) { @@ -691,7 +564,7 @@ static int if_getconfig(char *ifname) } else netmask = ifr.ifr_netmask; - return(0); + return 0; } static void if_print(char *ifname) @@ -705,15 +578,16 @@ static void if_print(char *ifname) ifc.ifc_len = sizeof(buff); ifc.ifc_buf = buff; if (ioctl(skfd, SIOCGIFCONF, &ifc) < 0) { - fprintf(stderr, "SIOCGIFCONF: %s\n", strerror(errno)); + perror("SIOCGIFCONF failed"); return; } ifr = ifc.ifc_req; for (i = ifc.ifc_len / sizeof(struct ifreq); --i >= 0; ifr++) { if (if_getconfig(ifr->ifr_name) < 0) { - fprintf(stderr, "%s: unknown interface.\n", - ifr->ifr_name); + fprintf(stderr, + "%s: unknown interface.\n", + ifr->ifr_name); continue; } @@ -721,16 +595,18 @@ static void if_print(char *ifname) /*ife_print(&ife);*/ } } else { - if (if_getconfig(ifname) < 0) - fprintf(stderr, "%s: unknown interface.\n", ifname); + if (if_getconfig(ifname) < 0) { + fprintf(stderr, + "%s: unknown interface.\n", ifname); + } } } -static int get_abi_ver(char *master_ifname) +static int get_drv_info(char *master_ifname) { struct ifreq ifr; struct ethtool_drvinfo info; - int abi_ver = 0; + char *endptr; memset(&ifr, 0, sizeof(ifr)); strncpy(ifr.ifr_name, master_ifname, IFNAMSIZ); @@ -739,24 +615,487 @@ static int get_abi_ver(char *master_ifna info.cmd = ETHTOOL_GDRVINFO; strncpy(info.driver, "ifenslave", 32); snprintf(info.fw_version, 32, "%d", BOND_ABI_VERSION); - if (ioctl(skfd, SIOCETHTOOL, &ifr) >= 0) { - char *endptr; - abi_ver = strtoul(info.fw_version, &endptr, 0); - if (*endptr) { - fprintf(stderr, "Error: got invalid string as an ABI " - "version from the bonding module\n"); - return -1; + if (ioctl(skfd, SIOCETHTOOL, &ifr) < 0) { + if (errno == EOPNOTSUPP) { + goto out; } + + saved_errno = errno; + v_print("Master '%s': Error: get bonding info failed %s\n", + master_ifname, strerror(saved_errno)); + return 1; } - if (verbose) { - printf("ABI ver is %d\n", abi_ver); + abi_ver = strtoul(info.fw_version, &endptr, 0); + if (*endptr) { + v_print("Master '%s': Error: got invalid string as an ABI " + "version from the bonding module\n", + master_ifname); + return 1; } - return abi_ver; + +out: + v_print("ABI ver is %d\n", abi_ver); + + return 0; } +static int change_active(char *master_ifname, char *slave_ifname) +{ + struct ifreq ifr; + int res = 0; + if (!(slave_flags.ifr_flags & IFF_SLAVE)) { + fprintf(stderr, + "Illegal operation: The specified slave interface " + "'%s' is not a slave\n", + slave_ifname); + return 1; + } + + strncpy(ifr.ifr_name, master_ifname, IFNAMSIZ); + strncpy(ifr.ifr_slave, slave_ifname, IFNAMSIZ); + if ((ioctl(skfd, SIOCBONDCHANGEACTIVE, &ifr) < 0) && + (ioctl(skfd, BOND_CHANGE_ACTIVE_OLD, &ifr) < 0)) { + saved_errno = errno; + v_print("Master '%s': Error: SIOCBONDCHANGEACTIVE failed: " + "%s\n", + master_ifname, strerror(saved_errno)); + res = 1; + } + + return res; +} + +static int enslave(char *master_ifname, char *slave_ifname) +{ + struct ifreq ifr; + int res = 0; + + if (slave_flags.ifr_flags & IFF_SLAVE) { + fprintf(stderr, + "Illegal operation: The specified slave interface " + "'%s' is already a slave\n", + slave_ifname); + return 1; + } + + res = set_if_down(slave_ifname, slave_flags.ifr_flags); + if (res) { + fprintf(stderr, + "Slave '%s': Error: bring interface down failed\n", + slave_ifname); + return res; + } + + if (abi_ver < 2) { + /* Older bonding versions would panic if the slave has no IP + * address, so get the IP setting from the master. + */ + res = set_if_addr(master_ifname, slave_ifname); + if (res) { + fprintf(stderr, + "Slave '%s': Error: set address failed\n", + slave_ifname); + return res; + } + } else { + res = clear_if_addr(slave_ifname); + if (res) { + fprintf(stderr, + "Slave '%s': Error: clear address failed\n", + slave_ifname); + return res; + } + } + + if (master_mtu.ifr_mtu != slave_mtu.ifr_mtu) { + res = set_slave_mtu(slave_ifname, master_mtu.ifr_mtu); + if (res) { + fprintf(stderr, + "Slave '%s': Error: set MTU failed\n", + slave_ifname); + return res; + } + } + + if (hwaddr_set) { + /* Master already has an hwaddr + * so set it's hwaddr to the slave + */ + if (abi_ver < 1) { + /* The driver is using an old ABI, so + * the application sets the slave's + * hwaddr + */ + res = set_slave_hwaddr(slave_ifname, + &(master_hwaddr.ifr_hwaddr)); + if (res) { + fprintf(stderr, + "Slave '%s': Error: set hw address " + "failed\n", + slave_ifname); + goto undo_mtu; + } + + /* For old ABI the application needs to bring the + * slave back up + */ + res = set_if_up(slave_ifname, slave_flags.ifr_flags); + if (res) { + fprintf(stderr, + "Slave '%s': Error: bring interface " + "down failed\n", + slave_ifname); + goto undo_slave_mac; + } + } + /* The driver is using a new ABI, + * so the driver takes care of setting + * the slave's hwaddr and bringing + * it up again + */ + } else { + /* No hwaddr for master yet, so + * set the slave's hwaddr to it + */ + if (abi_ver < 1) { + /* For old ABI, the master needs to be + * down before setting it's hwaddr + */ + res = set_if_down(master_ifname, master_flags.ifr_flags); + if (res) { + fprintf(stderr, + "Master '%s': Error: bring interface " + "down failed\n", + master_ifname); + goto undo_mtu; + } + } + + res = set_master_hwaddr(master_ifname, + &(slave_hwaddr.ifr_hwaddr)); + if (res) { + fprintf(stderr, + "Master '%s': Error: set hw address " + "failed\n", + master_ifname); + goto undo_mtu; + } + + if (abi_ver < 1) { + /* For old ABI, bring the master + * back up + */ + res = set_if_up(master_ifname, master_flags.ifr_flags); + if (res) { + fprintf(stderr, + "Master '%s': Error: bring interface " + "up failed\n", + master_ifname); + goto undo_master_mac; + } + } + + hwaddr_set = 1; + } + + /* Do the real thing */ + strncpy(ifr.ifr_name, master_ifname, IFNAMSIZ); + strncpy(ifr.ifr_slave, slave_ifname, IFNAMSIZ); + if ((ioctl(skfd, SIOCBONDENSLAVE, &ifr) < 0) && + (ioctl(skfd, BOND_ENSLAVE_OLD, &ifr) < 0)) { + saved_errno = errno; + v_print("Master '%s': Error: SIOCBONDENSLAVE failed: %s\n", + master_ifname, strerror(saved_errno)); + res = 1; + } + + if (res) { + goto undo_master_mac; + } + + return 0; + +/* rollback (best effort) */ +undo_master_mac: + set_master_hwaddr(master_ifname, &(master_hwaddr.ifr_hwaddr)); + hwaddr_set = 0; + goto undo_mtu; +undo_slave_mac: + set_slave_hwaddr(slave_ifname, &(slave_hwaddr.ifr_hwaddr)); +undo_mtu: + set_slave_mtu(slave_ifname, slave_mtu.ifr_mtu); + return res; +} + +static int release(char *master_ifname, char *slave_ifname) +{ + struct ifreq ifr; + int res = 0; + + if (!(slave_flags.ifr_flags & IFF_SLAVE)) { + fprintf(stderr, + "Illegal operation: The specified slave interface " + "'%s' is not a slave\n", + slave_ifname); + return 1; + } + + strncpy(ifr.ifr_name, master_ifname, IFNAMSIZ); + strncpy(ifr.ifr_slave, slave_ifname, IFNAMSIZ); + if ((ioctl(skfd, SIOCBONDRELEASE, &ifr) < 0) && + (ioctl(skfd, BOND_RELEASE_OLD, &ifr) < 0)) { + saved_errno = errno; + v_print("Master '%s': Error: SIOCBONDRELEASE failed: %s\n", + master_ifname, strerror(saved_errno)); + return 1; + } else if (abi_ver < 1) { + /* The driver is using an old ABI, so we'll set the interface + * down to avoid any conflicts due to same MAC/IP + */ + res = set_if_down(slave_ifname, slave_flags.ifr_flags); + if (res) { + fprintf(stderr, + "Slave '%s': Error: bring interface " + "down failed\n", + slave_ifname); + } + } + + /* set to default mtu */ + set_slave_mtu(slave_ifname, 1500); + + return res; +} + +static int get_if_settings(char *ifname, struct dev_ifr ifra[]) +{ + int i; + int res = 0; + + for (i = 0; ifra[i].req_ifr; i++) { + strncpy(ifra[i].req_ifr->ifr_name, ifname, IFNAMSIZ); + res = ioctl(skfd, ifra[i].req_type, ifra[i].req_ifr); + if (res < 0) { + saved_errno = errno; + v_print("Interface '%s': Error: %s failed: %s\n", + ifname, ifra[i].req_name, + strerror(saved_errno)); + + return saved_errno; + } + } + + return 0; +} + +static int get_slave_flags(char *slave_ifname) +{ + int res = 0; + + strncpy(slave_flags.ifr_name, slave_ifname, IFNAMSIZ); + res = ioctl(skfd, SIOCGIFFLAGS, &slave_flags); + if (res < 0) { + saved_errno = errno; + v_print("Slave '%s': Error: SIOCGIFFLAGS failed: %s\n", + slave_ifname, strerror(saved_errno)); + } else { + v_print("Slave %s: flags %04X.\n", + slave_ifname, slave_flags.ifr_flags); + } + + return res; +} + +static int set_master_hwaddr(char *master_ifname, struct sockaddr *hwaddr) +{ + unsigned char *addr = (unsigned char *)hwaddr->sa_data; + struct ifreq ifr; + int res = 0; + + strncpy(ifr.ifr_name, master_ifname, IFNAMSIZ); + memcpy(&(ifr.ifr_hwaddr), hwaddr, sizeof(struct sockaddr)); + res = ioctl(skfd, SIOCSIFHWADDR, &ifr); + if (res < 0) { + saved_errno = errno; + v_print("Master '%s': Error: SIOCSIFHWADDR failed: %s\n", + master_ifname, strerror(saved_errno)); + return res; + } else { + v_print("Master '%s': hardware address set to " + "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x.\n", + master_ifname, addr[0], addr[1], addr[2], + addr[3], addr[4], addr[5]); + } + + return res; +} + +static int set_slave_hwaddr(char *slave_ifname, struct sockaddr *hwaddr) +{ + unsigned char *addr = (unsigned char *)hwaddr->sa_data; + struct ifreq ifr; + int res = 0; + + strncpy(ifr.ifr_name, slave_ifname, IFNAMSIZ); + memcpy(&(ifr.ifr_hwaddr), hwaddr, sizeof(struct sockaddr)); + res = ioctl(skfd, SIOCSIFHWADDR, &ifr); + if (res < 0) { + saved_errno = errno; + + v_print("Slave '%s': Error: SIOCSIFHWADDR failed: %s\n", + slave_ifname, strerror(saved_errno)); + + if (saved_errno == EBUSY) { + v_print(" The device is busy: it must be idle " + "before running this command.\n"); + } else if (saved_errno == EOPNOTSUPP) { + v_print(" The device does not support setting " + "the MAC address.\n" + " Your kernel likely does not support slave " + "devices.\n"); + } else if (saved_errno == EINVAL) { + v_print(" The device's address type does not match " + "the master's address type.\n"); + } + return res; + } else { + v_print("Slave '%s': hardware address set to " + "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x.\n", + slave_ifname, addr[0], addr[1], addr[2], + addr[3], addr[4], addr[5]); + } + + return res; +} + +static int set_slave_mtu(char *slave_ifname, int mtu) +{ + struct ifreq ifr; + int res = 0; + + ifr.ifr_mtu = mtu; + strncpy(ifr.ifr_name, slave_ifname, IFNAMSIZ); + + res = ioctl(skfd, SIOCSIFMTU, &ifr); + if (res < 0) { + saved_errno = errno; + v_print("Slave '%s': Error: SIOCSIFMTU failed: %s\n", + slave_ifname, strerror(saved_errno)); + } else { + v_print("Slave '%s': MTU set to %d.\n", slave_ifname, mtu); + } + + return res; +} + +static int set_if_flags(char *ifname, short flags) +{ + struct ifreq ifr; + int res = 0; + + ifr.ifr_flags = flags; + strncpy(ifr.ifr_name, ifname, IFNAMSIZ); + + res = ioctl(skfd, SIOCSIFFLAGS, &ifr); + if (res < 0) { + saved_errno = errno; + v_print("Interface '%s': Error: SIOCSIFFLAGS failed: %s\n", + ifname, strerror(saved_errno)); + } else { + v_print("Interface '%s': flags set to %04X.\n", ifname, flags); + } + + return res; +} + +static int set_if_up(char *ifname, short flags) +{ + return set_if_flags(ifname, flags | IFF_UP); +} + +static int set_if_down(char *ifname, short flags) +{ + return set_if_flags(ifname, flags & ~IFF_UP); +} + +static int clear_if_addr(char *ifname) +{ + struct ifreq ifr; + int res = 0; + + strncpy(ifr.ifr_name, ifname, IFNAMSIZ); + ifr.ifr_addr.sa_family = AF_INET; + memset(ifr.ifr_addr.sa_data, 0, sizeof(ifr.ifr_addr.sa_data)); + + res = ioctl(skfd, SIOCSIFADDR, &ifr); + if (res < 0) { + saved_errno = errno; + v_print("Interface '%s': Error: SIOCSIFADDR failed: %s\n", + ifname, strerror(saved_errno)); + } else { + v_print("Interface '%s': address cleared\n", ifname); + } + + return res; +} + +static int set_if_addr(char *master_ifname, char *slave_ifname) +{ + struct ifreq ifr; + int res; + unsigned char *ipaddr; + int i; + struct { + char *req_name; + char *desc; + int g_ioctl; + int s_ioctl; + } ifra[] = { + {"IFADDR", "addr", SIOCGIFADDR, SIOCSIFADDR}, + {"DSTADDR", "destination addr", SIOCGIFDSTADDR, SIOCSIFDSTADDR}, + {"BRDADDR", "broadcast addr", SIOCGIFBRDADDR, SIOCSIFBRDADDR}, + {"NETMASK", "netmask", SIOCGIFNETMASK, SIOCSIFNETMASK}, + {NULL, NULL, 0, 0}, + }; + + for (i = 0; ifra[i].req_name; i++) { + strncpy(ifr.ifr_name, master_ifname, IFNAMSIZ); + res = ioctl(skfd, ifra[i].g_ioctl, &ifr); + if (res < 0) { + int saved_errno = errno; + + v_print("Interface '%s': Error: SIOCG%s failed: %s\n", + master_ifname, ifra[i].req_name, + strerror(saved_errno)); + + ifr.ifr_addr.sa_family = AF_INET; + memset(ifr.ifr_addr.sa_data, 0, + sizeof(ifr.ifr_addr.sa_data)); + } + + strncpy(ifr.ifr_name, slave_ifname, IFNAMSIZ); + res = ioctl(skfd, ifra[i].s_ioctl, &ifr); + if (res < 0) { + int saved_errno = errno; + + v_print("Interface '%s': Error: SIOCS%s failed: %s\n", + slave_ifname, ifra[i].req_name, + strerror(saved_errno)); + + return res; + } + + ipaddr = ifr.ifr_addr.sa_data; + v_print("Interface '%s': set IP %s to %d.%d.%d.%d\n", + slave_ifname, ifra[i].desc, + ipaddr[0], ipaddr[1], ipaddr[2], ipaddr[3]); + } + + return 0; +} /* * Local variables: @@ -768,3 +1107,4 @@ static int get_abi_ver(char *master_ifna * compile-command: "gcc -Wall -Wstrict-prototypes -O -I/usr/src/linux/include ifenslave.c -o ifenslave" * End: */ + diff -aurpN -X /home/fletch/.diff.exclude 001-mjb/Documentation/networking/netconsole.txt 100-netdrvr_2.6.1_rc1_exp1/Documentation/networking/netconsole.txt --- 001-mjb/Documentation/networking/netconsole.txt Wed Dec 31 16:00:00 1969 +++ 100-netdrvr_2.6.1_rc1_exp1/Documentation/networking/netconsole.txt Thu Jan 8 08:54:03 2004 @@ -0,0 +1,57 @@ + +started by Ingo Molnar , 2001.09.17 +2.6 port and netpoll api by Matt Mackall , Sep 9 2003 + +Please send bug reports to Matt Mackall + +This module logs kernel printk messages over UDP allowing debugging of +problem where disk logging fails and serial consoles are impractical. + +It can be used either built-in or as a module. As a built-in, +netconsole initializes immediately after NIC cards and will bring up +the specified interface as soon as possible. While this doesn't allow +capture of early kernel panics, it does capture most of the boot +process. + +It takes a string configuration parameter "netconsole" in the +following format: + + netconsole=[src-port]@[src-ip]/[],[tgt-port]@/[tgt-macaddr] + + where + src-port source for UDP packets (defaults to 6665) + src-ip source IP to use (interface address) + dev network interface (eth0) + tgt-port port for logging agent (6666) + tgt-ip IP address for logging agent + tgt-macaddr ethernet MAC address for logging agent (broadcast) + +Examples: + + linux netconsole=4444@10.0.0.1/eth1,9353@10.0.0.2/12:34:56:78:9a:bc + + or + + insmod netconsole netconsole=@/,@10.0.0.2/ + +Built-in netconsole starts immediately after the TCP stack is +initialized and attempts to bring up the supplied dev at the supplied +address. + +The remote host can run either 'netcat -u -l -p ' or syslogd. + +WARNING: the default target ethernet setting uses the broadcast +ethernet address to send packets, which can cause increased load on +other systems on the same ethernet segment. + +NOTE: the network device (eth1 in the above case) can run any kind +of other network traffic, netconsole is not intrusive. Netconsole +might cause slight delays in other traffic if the volume of kernel +messages is high, but should have no other impact. + +Netconsole was designed to be as instantaneous as possible, to +enable the logging of even the most critical kernel bugs. It works +from IRQ contexts as well, and does not enable interrupts while +sending packets. Due to these unique needs, configuration can not +be more automatic, and some fundamental limitations will remain: +only IP networks, UDP packets and ethernet devices are supported. diff -aurpN -X /home/fletch/.diff.exclude 001-mjb/Documentation/networking/sk98lin.txt 100-netdrvr_2.6.1_rc1_exp1/Documentation/networking/sk98lin.txt --- 001-mjb/Documentation/networking/sk98lin.txt Mon Nov 17 18:28:29 2003 +++ 100-netdrvr_2.6.1_rc1_exp1/Documentation/networking/sk98lin.txt Thu Jan 8 08:54:03 2004 @@ -2,9 +2,9 @@ All rights reserved =========================================================================== -sk98lin.txt created 23-Sep-2003 +sk98lin.txt created 15-Dec-2003 -Readme File for sk98lin v6.18 +Readme File for sk98lin v6.21 Marvell Yukon/SysKonnect SK-98xx Gigabit Ethernet Adapter family driver for LINUX This file contains @@ -466,7 +466,7 @@ The Marvell Yukon/SysKonnect Linux drive Link Aggregation according to IEEE standards 802.1, 802.1q, and 802.3ad. These features are only available after installation of open source modules available on the Internet: -For VLAN go to: http://scry.wanfear.com/~greear/vlan.html +For VLAN go to: http://www.candelatech.com/~greear/vlan.html For Link Aggregation go to: http://www.st.rim.or.jp/~yumo NOTE: SysKonnect GmbH does not offer any support for these open source diff -aurpN -X /home/fletch/.diff.exclude 001-mjb/drivers/char/pcmcia/synclink_cs.c 100-netdrvr_2.6.1_rc1_exp1/drivers/char/pcmcia/synclink_cs.c --- 001-mjb/drivers/char/pcmcia/synclink_cs.c Mon Nov 17 18:29:41 2003 +++ 100-netdrvr_2.6.1_rc1_exp1/drivers/char/pcmcia/synclink_cs.c Thu Jan 8 08:54:03 2004 @@ -244,7 +244,6 @@ typedef struct _mgslpc_info { char netname[10]; struct net_device *netdev; struct net_device_stats netstats; - struct net_device netdevice; #endif } MGSLPC_INFO; @@ -4206,35 +4205,46 @@ void tx_timeout(unsigned long context) #ifdef CONFIG_SYNCLINK_SYNCPPP /* syncppp net device routines */ + +static void mgslpc_setup(struct net_device *dev) +{ + dev->open = mgslpc_sppp_open; + dev->stop = mgslpc_sppp_close; + dev->hard_start_xmit = mgslpc_sppp_tx; + dev->do_ioctl = mgslpc_sppp_ioctl; + dev->get_stats = mgslpc_net_stats; + dev->tx_timeout = mgslpc_sppp_tx_timeout; + dev->watchdog_timeo = 10*HZ; +} void mgslpc_sppp_init(MGSLPC_INFO *info) { struct net_device *d; sprintf(info->netname,"mgslp%d",info->line); + + d = alloc_netdev(0, info->netname, mgslpc_setup); + if (!d) { + printk(KERN_WARNING "%s: alloc_netdev failed.\n", + info->netname); + return; + } info->if_ptr = &info->pppdev; - info->netdev = info->pppdev.dev = &info->netdevice; + info->netdev = info->pppdev.dev = d; sppp_attach(&info->pppdev); - d = info->netdev; - strcpy(d->name,info->netname); d->base_addr = info->io_base; d->irq = info->irq_level; d->priv = info; - d->init = NULL; - d->open = mgslpc_sppp_open; - d->stop = mgslpc_sppp_close; - d->hard_start_xmit = mgslpc_sppp_tx; - d->do_ioctl = mgslpc_sppp_ioctl; - d->get_stats = mgslpc_net_stats; - d->tx_timeout = mgslpc_sppp_tx_timeout; - d->watchdog_timeo = 10*HZ; if (register_netdev(d)) { printk(KERN_WARNING "%s: register_netdev failed.\n", d->name); sppp_detach(info->netdev); + info->netdev = NULL; + info->pppdev.dev = NULL; + free_netdev(d); return; } @@ -4246,8 +4256,11 @@ void mgslpc_sppp_delete(MGSLPC_INFO *inf { if (debug_level >= DEBUG_LEVEL_INFO) printk("mgslpc_sppp_delete(%s)\n",info->netname); - sppp_detach(info->netdev); unregister_netdev(info->netdev); + sppp_detach(info->netdev); + free_netdev(info->netdev); + info->netdev = NULL; + info->pppdev.dev = NULL; } int mgslpc_sppp_open(struct net_device *d) diff -aurpN -X /home/fletch/.diff.exclude 001-mjb/drivers/char/synclink.c 100-netdrvr_2.6.1_rc1_exp1/drivers/char/synclink.c --- 001-mjb/drivers/char/synclink.c Mon Nov 17 18:29:41 2003 +++ 100-netdrvr_2.6.1_rc1_exp1/drivers/char/synclink.c Thu Jan 8 08:54:04 2004 @@ -327,7 +327,6 @@ struct mgsl_struct { char netname[10]; struct net_device *netdev; struct net_device_stats netstats; - struct net_device netdevice; #endif }; @@ -737,8 +736,8 @@ int mgsl_ioctl_common(struct mgsl_struct #ifdef CONFIG_SYNCLINK_SYNCPPP /* SPPP/HDLC stuff */ -void mgsl_sppp_init(struct mgsl_struct *info); -void mgsl_sppp_delete(struct mgsl_struct *info); +static void mgsl_sppp_init(struct mgsl_struct *info); +static void mgsl_sppp_delete(struct mgsl_struct *info); int mgsl_sppp_open(struct net_device *d); int mgsl_sppp_close(struct net_device *d); void mgsl_sppp_tx_timeout(struct net_device *d); @@ -7820,36 +7819,45 @@ int usc_loopmode_send_active( struct mgs #ifdef CONFIG_SYNCLINK_SYNCPPP /* syncppp net device routines */ +static void mgsl_setup(struct net_device *dev) +{ + dev->open = mgsl_sppp_open; + dev->stop = mgsl_sppp_close; + dev->hard_start_xmit = mgsl_sppp_tx; + dev->do_ioctl = mgsl_sppp_ioctl; + dev->get_stats = mgsl_net_stats; + dev->tx_timeout = mgsl_sppp_tx_timeout; + dev->watchdog_timeo = 10*HZ; +} -void mgsl_sppp_init(struct mgsl_struct *info) +static void mgsl_sppp_init(struct mgsl_struct *info) { struct net_device *d; sprintf(info->netname,"mgsl%d",info->line); + d = alloc_netdev(0, info->netname, mgsl_setup); + if (!d) { + printk(KERN_WARNING "%s: alloc_netdev failed.\n", + info->netname); + return; + } + info->if_ptr = &info->pppdev; - info->netdev = info->pppdev.dev = &info->netdevice; + info->netdev = info->pppdev.dev = d; sppp_attach(&info->pppdev); - d = info->netdev; - strcpy(d->name,info->netname); d->base_addr = info->io_base; d->irq = info->irq_level; d->dma = info->dma_level; d->priv = info; - d->init = NULL; - d->open = mgsl_sppp_open; - d->stop = mgsl_sppp_close; - d->hard_start_xmit = mgsl_sppp_tx; - d->do_ioctl = mgsl_sppp_ioctl; - d->get_stats = mgsl_net_stats; - d->tx_timeout = mgsl_sppp_tx_timeout; - d->watchdog_timeo = 10*HZ; if (register_netdev(d)) { printk(KERN_WARNING "%s: register_netdev failed.\n", d->name); sppp_detach(info->netdev); + info->netdev = NULL; + free_netdev(d); return; } @@ -7861,8 +7869,11 @@ void mgsl_sppp_delete(struct mgsl_struct { if (debug_level >= DEBUG_LEVEL_INFO) printk("mgsl_sppp_delete(%s)\n",info->netname); - sppp_detach(info->netdev); unregister_netdev(info->netdev); + sppp_detach(info->netdev); + free_netdev(info->netdev); + info->netdev = NULL; + info->pppdev.dev = NULL; } int mgsl_sppp_open(struct net_device *d) diff -aurpN -X /home/fletch/.diff.exclude 001-mjb/drivers/char/synclinkmp.c 100-netdrvr_2.6.1_rc1_exp1/drivers/char/synclinkmp.c --- 001-mjb/drivers/char/synclinkmp.c Mon Nov 17 18:29:41 2003 +++ 100-netdrvr_2.6.1_rc1_exp1/drivers/char/synclinkmp.c Thu Jan 8 08:54:04 2004 @@ -289,7 +289,6 @@ typedef struct _synclinkmp_info { char netname[10]; struct net_device *netdev; struct net_device_stats netstats; - struct net_device netdevice; #endif } SLMP_INFO; @@ -1627,35 +1626,44 @@ static void set_break(struct tty_struct /* syncppp support and callbacks */ +static void cb_setup(struct net_device *dev) +{ + dev->open = sppp_cb_open; + dev->stop = sppp_cb_close; + dev->hard_start_xmit = sppp_cb_tx; + dev->do_ioctl = sppp_cb_ioctl; + dev->get_stats = sppp_cb_net_stats; + dev->tx_timeout = sppp_cb_tx_timeout; + dev->watchdog_timeo = 10*HZ; +} + static void sppp_init(SLMP_INFO *info) { struct net_device *d; sprintf(info->netname,"mgslm%dp%d",info->adapter_num,info->port_num); + d = alloc_netdev(0, info->netname, cb_setup); + if (!d) { + printk(KERN_WARNING "%s: alloc_netdev failed.\n", + info->netname); + return; + } + info->if_ptr = &info->pppdev; - info->netdev = info->pppdev.dev = &info->netdevice; + info->netdev = info->pppdev.dev = d; sppp_attach(&info->pppdev); - d = info->netdev; - strcpy(d->name,info->netname); - d->base_addr = 0; d->irq = info->irq_level; - d->dma = 0; d->priv = info; - d->init = NULL; - d->open = sppp_cb_open; - d->stop = sppp_cb_close; - d->hard_start_xmit = sppp_cb_tx; - d->do_ioctl = sppp_cb_ioctl; - d->get_stats = sppp_cb_net_stats; - d->tx_timeout = sppp_cb_tx_timeout; - d->watchdog_timeo = 10*HZ; if (register_netdev(d)) { printk(KERN_WARNING "%s: register_netdev failed.\n", d->name); sppp_detach(info->netdev); + info->netdev = NULL; + info->pppdev.dev = NULL; + free_netdev(d); return; } @@ -1667,8 +1675,11 @@ static void sppp_delete(SLMP_INFO *info) { if (debug_level >= DEBUG_LEVEL_INFO) printk("sppp_delete(%s)\n",info->netname); - sppp_detach(info->netdev); unregister_netdev(info->netdev); + sppp_detach(info->netdev); + free_netdev(info->netdev); + info->netdev = NULL; + info->pppdev.dev = NULL; } static int sppp_cb_open(struct net_device *d) diff -aurpN -X /home/fletch/.diff.exclude 001-mjb/drivers/ieee1394/eth1394.c 100-netdrvr_2.6.1_rc1_exp1/drivers/ieee1394/eth1394.c --- 001-mjb/drivers/ieee1394/eth1394.c Thu Jan 8 08:35:32 2004 +++ 100-netdrvr_2.6.1_rc1_exp1/drivers/ieee1394/eth1394.c Thu Jan 8 08:54:04 2004 @@ -375,8 +375,8 @@ static void ether1394_reset_priv (struct } } -/* This function is called by register_netdev */ -static int ether1394_init_dev (struct net_device *dev) +/* This function is called right before register_netdev */ +static void ether1394_init_dev (struct net_device *dev) { /* Our functions */ dev->open = ether1394_open; @@ -403,8 +403,6 @@ static int ether1394_init_dev (struct ne dev->type = ARPHRD_IEEE1394; ether1394_reset_priv (dev, 1); - - return 0; } /* @@ -437,8 +435,6 @@ static void ether1394_add_host (struct h SET_MODULE_OWNER(dev); - dev->init = ether1394_init_dev; - priv = (struct eth1394_priv *)dev->priv; spin_lock_init(&priv->lock); @@ -459,6 +455,8 @@ static void ether1394_add_host (struct h goto out; } + ether1394_init_dev(dev); + if (register_netdev (dev)) { ETH1394_PRINT (KERN_ERR, dev->name, "Error registering network driver\n"); goto out; @@ -483,7 +481,7 @@ static void ether1394_add_host (struct h out: if (dev != NULL) - kfree(dev); + free_netdev(dev); if (hi) hpsb_destroy_hostinfo(ð1394_highlevel, host); diff -aurpN -X /home/fletch/.diff.exclude 001-mjb/drivers/net/3c501.c 100-netdrvr_2.6.1_rc1_exp1/drivers/net/3c501.c --- 001-mjb/drivers/net/3c501.c Mon Nov 17 18:28:49 2003 +++ 100-netdrvr_2.6.1_rc1_exp1/drivers/net/3c501.c Thu Jan 8 08:54:04 2004 @@ -136,17 +136,14 @@ static const char version[] = #include "3c501.h" -/* A zero-terminated list of I/O addresses to be probed. - The 3c501 can be at many locations, but here are the popular ones. */ -static unsigned int netcard_portlist[] __initdata = { - 0x280, 0x300, 0 -}; - - /* * The boilerplate probe code. */ +static int io=0x280; +static int irq=5; +static int mem_start; + /** * el1_probe: - probe for a 3c501 * @dev: The device structure passed in to probe. @@ -160,23 +157,47 @@ static unsigned int netcard_portlist[] _ * probe and failing to find anything. */ -int __init el1_probe(struct net_device *dev) +struct net_device * __init el1_probe(int unit) { - int i; - int base_addr = dev->base_addr; + struct net_device *dev = alloc_etherdev(sizeof(struct net_local)); + static unsigned ports[] = { 0x280, 0x300, 0}; + unsigned *port; + int err = 0; + + if (!dev) + return ERR_PTR(-ENOMEM); + + if (unit >= 0) { + sprintf(dev->name, "eth%d", unit); + netdev_boot_setup_check(dev); + io = dev->base_addr; + irq = dev->irq; + mem_start = dev->mem_start & 7; + } SET_MODULE_OWNER(dev); - if (base_addr > 0x1ff) /* Check a single specified location. */ - return el1_probe1(dev, base_addr); - else if (base_addr != 0) /* Don't probe at all. */ - return -ENXIO; - - for (i = 0; netcard_portlist[i]; i++) - if (el1_probe1(dev, netcard_portlist[i]) == 0) - return 0; - - return -ENODEV; + if (io > 0x1ff) { /* Check a single specified location. */ + err = el1_probe1(dev, io); + } else if (io != 0) { + err = -ENXIO; /* Don't probe at all. */ + } else { + for (port = ports; *port && el1_probe1(dev, *port); port++) + ; + if (!*port) + err = -ENODEV; + } + if (err) + goto out; + err = register_netdev(dev); + if (err) + goto out1; + return dev; +out1: + release_region(dev->base_addr, EL1_IO_EXTENT); +out: + free_netdev(dev); + return ERR_PTR(err); } /** @@ -240,6 +261,8 @@ static int __init el1_probe1(struct net_ * high. */ + dev->irq = irq; + if (dev->irq < 2) { unsigned long irq_mask; @@ -267,8 +290,8 @@ static int __init el1_probe1(struct net_ dev->base_addr = ioaddr; memcpy(dev->dev_addr, station_addr, ETH_ALEN); - if (dev->mem_start & 0xf) - el_debug = dev->mem_start & 0x7; + if (mem_start & 0xf) + el_debug = mem_start & 0x7; if (autoirq) dev->irq = autoirq; @@ -282,17 +305,7 @@ static int __init el1_probe1(struct net_ if (el_debug) printk(KERN_DEBUG "%s", version); - /* - * Initialize the device structure. - */ - - dev->priv = kmalloc(sizeof(struct net_local), GFP_KERNEL); - if (dev->priv == NULL) { - release_region(ioaddr, EL1_IO_EXTENT); - return -ENOMEM; - } memset(dev->priv, 0, sizeof(struct net_local)); - lp=dev->priv; spin_lock_init(&lp->lock); @@ -308,13 +321,6 @@ static int __init el1_probe1(struct net_ dev->get_stats = &el1_get_stats; dev->set_multicast_list = &set_multicast_list; dev->ethtool_ops = &netdev_ethtool_ops; - - /* - * Setup the generic properties - */ - - ether_setup(dev); - return 0; } @@ -884,14 +890,8 @@ static struct ethtool_ops netdev_ethtool #ifdef MODULE -static struct net_device dev_3c501 = { - .init = el1_probe, - .base_addr = 0x280, - .irq = 5, -}; +static struct net_device *dev_3c501; -static int io=0x280; -static int irq=5; MODULE_PARM(io, "i"); MODULE_PARM(irq, "i"); MODULE_PARM_DESC(io, "EtherLink I/O base address"); @@ -911,10 +911,9 @@ MODULE_PARM_DESC(irq, "EtherLink IRQ num int init_module(void) { - dev_3c501.irq=irq; - dev_3c501.base_addr=io; - if (register_netdev(&dev_3c501) != 0) - return -EIO; + dev_3c501 = el1_probe(-1); + if (IS_ERR(dev_3c501)) + return PTR_ERR(dev_3c501); return 0; } @@ -927,19 +926,10 @@ int init_module(void) void cleanup_module(void) { - unregister_netdev(&dev_3c501); - - /* - * Free up the private structure, or leak memory :-) - */ - - kfree(dev_3c501.priv); - dev_3c501.priv = NULL; /* gets re-allocated by el1_probe1 */ - - /* - * If we don't do this, we can't re-insmod it later. - */ - release_region(dev_3c501.base_addr, EL1_IO_EXTENT); + struct net_device *dev = dev_3c501; + unregister_netdev(dev); + release_region(dev->base_addr, EL1_IO_EXTENT); + free_netdev(dev); } #endif /* MODULE */ diff -aurpN -X /home/fletch/.diff.exclude 001-mjb/drivers/net/3c501.h 100-netdrvr_2.6.1_rc1_exp1/drivers/net/3c501.h --- 001-mjb/drivers/net/3c501.h Mon Nov 17 18:28:14 2003 +++ 100-netdrvr_2.6.1_rc1_exp1/drivers/net/3c501.h Thu Jan 8 08:54:04 2004 @@ -3,7 +3,6 @@ * Index to functions. */ -int el1_probe(struct net_device *dev); static int el1_probe1(struct net_device *dev, int ioaddr); static int el_open(struct net_device *dev); static void el_timeout(struct net_device *dev); diff -aurpN -X /home/fletch/.diff.exclude 001-mjb/drivers/net/3c503.c 100-netdrvr_2.6.1_rc1_exp1/drivers/net/3c503.c --- 001-mjb/drivers/net/3c503.c Mon Nov 17 18:28:49 2003 +++ 100-netdrvr_2.6.1_rc1_exp1/drivers/net/3c503.c Thu Jan 8 08:54:04 2004 @@ -60,7 +60,6 @@ static const char version[] = #include "3c503.h" #define WRD_COUNT 4 -int el2_probe(struct net_device *dev); static int el2_pio_probe(struct net_device *dev); static int el2_probe1(struct net_device *dev, int ioaddr); @@ -90,11 +89,11 @@ static struct ethtool_ops netdev_ethtool If the ethercard isn't found there is an optional probe for ethercard jumpered to programmed-I/O mode. */ -int __init -el2_probe(struct net_device *dev) +static int __init do_el2_probe(struct net_device *dev) { int *addr, addrs[] = { 0xddffe, 0xd9ffe, 0xcdffe, 0xc9ffe, 0}; int base_addr = dev->base_addr; + int irq = dev->irq; SET_MODULE_OWNER(dev); @@ -104,16 +103,13 @@ el2_probe(struct net_device *dev) return -ENXIO; for (addr = addrs; *addr; addr++) { - int i; - unsigned int base_bits = isa_readb(*addr); - /* Find first set bit. */ - for(i = 7; i >= 0; i--, base_bits >>= 1) - if (base_bits & 0x1) - break; - if (base_bits != 1) + unsigned base_bits = isa_readb(*addr); + int i = ffs(base_bits) - 1; + if (i == -1 || base_bits != (1 << i)) continue; if (el2_probe1(dev, netcard_portlist[i]) == 0) return 0; + dev->irq = irq; } #if ! defined(no_probe_nonshared_memory) return el2_pio_probe(dev); @@ -128,20 +124,54 @@ static int __init el2_pio_probe(struct net_device *dev) { int i; - int base_addr = dev ? dev->base_addr : 0; + int base_addr = dev->base_addr; + int irq = dev->irq; if (base_addr > 0x1ff) /* Check a single specified location. */ return el2_probe1(dev, base_addr); else if (base_addr != 0) /* Don't probe at all. */ return -ENXIO; - for (i = 0; netcard_portlist[i]; i++) + for (i = 0; netcard_portlist[i]; i++) { if (el2_probe1(dev, netcard_portlist[i]) == 0) return 0; + dev->irq = irq; + } return -ENODEV; } +static void cleanup_card(struct net_device *dev) +{ + /* NB: el2_close() handles free_irq */ + release_region(dev->base_addr, EL2_IO_EXTENT); +} + +struct net_device * __init el2_probe(int unit) +{ + struct net_device *dev = alloc_ei_netdev(); + int err; + + if (!dev) + return ERR_PTR(-ENOMEM); + + sprintf(dev->name, "eth%d", unit); + netdev_boot_setup_check(dev); + + err = do_el2_probe(dev); + if (err) + goto out; + err = register_netdev(dev); + if (err) + goto out1; + return dev; +out1: + cleanup_card(dev); +out: + free_netdev(dev); + return ERR_PTR(err); +} + /* Probe for the Etherlink II card at I/O port base IOADDR, returning non-zero on success. If found, set the station address and memory parameters in DEVICE. */ @@ -152,15 +182,19 @@ el2_probe1(struct net_device *dev, int i static unsigned version_printed; unsigned long vendor_id; - /* FIXME: code reads ioaddr + 0x400, we request ioaddr + 16 */ if (!request_region(ioaddr, EL2_IO_EXTENT, dev->name)) return -EBUSY; + if (!request_region(ioaddr + 0x400, 8, dev->name)) { + retval = -EBUSY; + goto out; + } + /* Reset and/or avoid any lurking NE2000 */ if (inb(ioaddr + 0x408) == 0xff) { mdelay(1); retval = -ENODEV; - goto out; + goto out1; } /* We verify that it's a 3C503 board by checking the first three octets @@ -171,7 +205,7 @@ el2_probe1(struct net_device *dev, int i if ( (iobase_reg & (iobase_reg - 1)) || (membase_reg & (membase_reg - 1))) { retval = -ENODEV; - goto out; + goto out1; } saved_406 = inb_p(ioaddr + 0x406); outb_p(ECNTRL_RESET|ECNTRL_THIN, ioaddr + 0x406); /* Reset it... */ @@ -184,19 +218,13 @@ el2_probe1(struct net_device *dev, int i /* Restore the register we frobbed. */ outb(saved_406, ioaddr + 0x406); retval = -ENODEV; - goto out; + goto out1; } if (ei_debug && version_printed++ == 0) printk(version); dev->base_addr = ioaddr; - /* Allocate dev->priv and fill in 8390 specific dev fields. */ - if (ethdev_init(dev)) { - printk ("3c503: unable to allocate memory for dev->priv.\n"); - retval = -ENOMEM; - goto out; - } printk("%s: 3c503 at i/o base %#3x, node ", dev->name, ioaddr); @@ -322,7 +350,10 @@ el2_probe1(struct net_device *dev, int i printk("\n%s: %s, %dkB RAM, using programmed I/O (REJUMPER for SHARED MEMORY).\n", dev->name, ei_status.name, (wordlength+1)<<3); } + release_region(ioaddr + 0x400, 8); return 0; +out1: + release_region(ioaddr + 0x400, 8); out: release_region(ioaddr, EL2_IO_EXTENT); return retval; @@ -633,7 +664,7 @@ static struct ethtool_ops netdev_ethtool #ifdef MODULE #define MAX_EL2_CARDS 4 /* Max number of EL2 cards per module */ -static struct net_device dev_el2[MAX_EL2_CARDS]; +static struct net_device *dev_el2[MAX_EL2_CARDS]; static int io[MAX_EL2_CARDS]; static int irq[MAX_EL2_CARDS]; static int xcvr[MAX_EL2_CARDS]; /* choose int. or ext. xcvr */ @@ -651,28 +682,34 @@ ISA device autoprobes on a running machi int init_module(void) { + struct net_device *dev; int this_dev, found = 0; for (this_dev = 0; this_dev < MAX_EL2_CARDS; this_dev++) { - struct net_device *dev = &dev_el2[this_dev]; - dev->irq = irq[this_dev]; - dev->base_addr = io[this_dev]; - dev->mem_end = xcvr[this_dev]; /* low 4bits = xcvr sel. */ - dev->init = el2_probe; if (io[this_dev] == 0) { if (this_dev != 0) break; /* only autoprobe 1st one */ printk(KERN_NOTICE "3c503.c: Presently autoprobing (not recommended) for a single card.\n"); } - if (register_netdev(dev) != 0) { - printk(KERN_WARNING "3c503.c: No 3c503 card found (i/o = 0x%x).\n", io[this_dev]); - if (found != 0) { /* Got at least one. */ - return 0; + dev = alloc_ei_netdev(); + if (!dev) + break; + dev->irq = irq[this_dev]; + dev->base_addr = io[this_dev]; + dev->mem_end = xcvr[this_dev]; /* low 4bits = xcvr sel. */ + if (do_el2_probe(dev) == 0) { + if (register_netdev(dev) == 0) { + dev_el2[found++] = dev; + continue; } - return -ENXIO; + cleanup_card(dev); } - found++; + free_netdev(dev); + printk(KERN_WARNING "3c503.c: No 3c503 card found (i/o = 0x%x).\n", io[this_dev]); + break; } - return 0; + if (found) + return 0; + return -ENXIO; } void @@ -681,13 +718,11 @@ cleanup_module(void) int this_dev; for (this_dev = 0; this_dev < MAX_EL2_CARDS; this_dev++) { - struct net_device *dev = &dev_el2[this_dev]; - if (dev->priv != NULL) { - void *priv = dev->priv; - /* NB: el2_close() handles free_irq */ - release_region(dev->base_addr, EL2_IO_EXTENT); + struct net_device *dev = dev_el2[this_dev]; + if (dev) { unregister_netdev(dev); - kfree(priv); + cleanup_card(dev); + free_netdev(dev); } } } diff -aurpN -X /home/fletch/.diff.exclude 001-mjb/drivers/net/3c505.c 100-netdrvr_2.6.1_rc1_exp1/drivers/net/3c505.c --- 001-mjb/drivers/net/3c505.c Mon Nov 17 18:28:49 2003 +++ 100-netdrvr_2.6.1_rc1_exp1/drivers/net/3c505.c Thu Jan 8 08:54:04 2004 @@ -1293,42 +1293,6 @@ static void elp_set_mc_list(struct net_d } } -/****************************************************** - * - * initialise Etherlink Plus board - * - ******************************************************/ - -static inline void elp_init(struct net_device *dev) -{ - elp_device *adapter = dev->priv; - - /* - * set ptrs to various functions - */ - dev->open = elp_open; /* local */ - dev->stop = elp_close; /* local */ - dev->get_stats = elp_get_stats; /* local */ - dev->hard_start_xmit = elp_start_xmit; /* local */ - dev->tx_timeout = elp_timeout; /* local */ - dev->watchdog_timeo = 10*HZ; - dev->set_multicast_list = elp_set_mc_list; /* local */ - dev->ethtool_ops = &netdev_ethtool_ops; /* local */ - - /* Setup the generic properties */ - ether_setup(dev); - - /* - * setup ptr to adapter specific information - */ - memset(&(adapter->stats), 0, sizeof(struct net_device_stats)); - - /* - * memory information - */ - dev->mem_start = dev->mem_end = 0; -} - /************************************************************ * * A couple of tests to see if there's 3C505 or not @@ -1442,12 +1406,13 @@ static int __init elp_autodetect(struct * work at all if it was in a weird state). */ -int __init elplus_probe(struct net_device *dev) +static int __init elplus_setup(struct net_device *dev) { - elp_device *adapter; + elp_device *adapter = dev->priv; int i, tries, tries1, okay; unsigned long timeout; unsigned long cookie = 0; + int err = -ENODEV; SET_MODULE_OWNER(dev); @@ -1456,17 +1421,8 @@ int __init elplus_probe(struct net_devic */ dev->base_addr = elp_autodetect(dev); - if (!(dev->base_addr)) - return -ENODEV; - - /* - * setup ptr to adapter specific information - */ - adapter = (elp_device *) (dev->priv = kmalloc(sizeof(elp_device), GFP_KERNEL)); - if (adapter == NULL) { - printk(KERN_ERR "%s: out of memory\n", dev->name); + if (!dev->base_addr) return -ENODEV; - } adapter->send_pcb_semaphore = 0; @@ -1544,8 +1500,7 @@ int __init elplus_probe(struct net_devic outb_control(adapter->hcr_val & ~(FLSH | ATTN), dev); } printk(KERN_ERR "%s: failed to initialise 3c505\n", dev->name); - release_region(dev->base_addr, ELP_IO_EXTENT); - return -ENODEV; + goto out; okay: if (dev->irq) { /* Is there a preset IRQ? */ @@ -1560,14 +1515,14 @@ int __init elplus_probe(struct net_devic case 0: printk(KERN_ERR "%s: IRQ probe failed: check 3c505 jumpers.\n", dev->name); - return -ENODEV; + goto out; case 1: case 6: case 8: case 13: printk(KERN_ERR "%s: Impossible IRQ %d reported by probe_irq_off().\n", dev->name, dev->irq); - return -ENODEV; + goto out; } /* * Now we have the IRQ number so we can disable the interrupts from @@ -1636,16 +1591,48 @@ int __init elplus_probe(struct net_devic printk(KERN_ERR "%s: adapter configuration failed\n", dev->name); } - /* - * initialise the device - */ - elp_init(dev); + dev->open = elp_open; /* local */ + dev->stop = elp_close; /* local */ + dev->get_stats = elp_get_stats; /* local */ + dev->hard_start_xmit = elp_start_xmit; /* local */ + dev->tx_timeout = elp_timeout; /* local */ + dev->watchdog_timeo = 10*HZ; + dev->set_multicast_list = elp_set_mc_list; /* local */ + dev->ethtool_ops = &netdev_ethtool_ops; /* local */ + + memset(&(adapter->stats), 0, sizeof(struct net_device_stats)); + dev->mem_start = dev->mem_end = 0; + + err = register_netdev(dev); + if (err) + goto out; return 0; +out: + release_region(dev->base_addr, ELP_IO_EXTENT); + return err; +} + +struct net_device * __init elplus_probe(int unit) +{ + struct net_device *dev = alloc_etherdev(sizeof(elp_device)); + int err; + if (!dev) + return ERR_PTR(-ENOMEM); + + sprintf(dev->name, "eth%d", unit); + netdev_boot_setup_check(dev); + + err = elplus_setup(dev); + if (err) { + free_netdev(dev); + return ERR_PTR(err); + } + return dev; } #ifdef MODULE -static struct net_device dev_3c505[ELP_MAX_CARDS]; +static struct net_device *dev_3c505[ELP_MAX_CARDS]; static int io[ELP_MAX_CARDS]; static int irq[ELP_MAX_CARDS]; static int dma[ELP_MAX_CARDS]; @@ -1661,10 +1648,12 @@ int init_module(void) int this_dev, found = 0; for (this_dev = 0; this_dev < ELP_MAX_CARDS; this_dev++) { - struct net_device *dev = &dev_3c505[this_dev]; + struct net_device *dev = alloc_etherdev(sizeof(elp_device)); + if (!dev) + break; + dev->irq = irq[this_dev]; dev->base_addr = io[this_dev]; - dev->init = elplus_probe; if (dma[this_dev]) { dev->dma = dma[this_dev]; } else { @@ -1672,16 +1661,22 @@ int init_module(void) printk(KERN_WARNING "3c505.c: warning, using default DMA channel,\n"); } if (io[this_dev] == 0) { - if (this_dev) break; + if (this_dev) { + free_netdev(dev); + break; + } printk(KERN_NOTICE "3c505.c: module autoprobe not recommended, give io=xx.\n"); } - if (register_netdev(dev) != 0) { + if (elplus_setup(dev) != 0) { printk(KERN_WARNING "3c505.c: Failed to register card at 0x%x.\n", io[this_dev]); - if (found != 0) return 0; - return -ENXIO; + free_netdev(dev); + break; } + dev_3c505[this_dev] = dev; found++; } + if (!found) + return -ENODEV; return 0; } @@ -1690,12 +1685,11 @@ void cleanup_module(void) int this_dev; for (this_dev = 0; this_dev < ELP_MAX_CARDS; this_dev++) { - struct net_device *dev = &dev_3c505[this_dev]; - if (dev->priv != NULL) { + struct net_device *dev = dev_3c505[this_dev]; + if (dev) { unregister_netdev(dev); - kfree(dev->priv); - dev->priv = NULL; release_region(dev->base_addr, ELP_IO_EXTENT); + free_netdev(dev); } } } diff -aurpN -X /home/fletch/.diff.exclude 001-mjb/drivers/net/3c507.c 100-netdrvr_2.6.1_rc1_exp1/drivers/net/3c507.c --- 001-mjb/drivers/net/3c507.c Mon Nov 17 18:28:14 2003 +++ 100-netdrvr_2.6.1_rc1_exp1/drivers/net/3c507.c Thu Jan 8 08:54:04 2004 @@ -74,10 +74,6 @@ static unsigned int net_debug = NET_DEBU #define debug net_debug -/* A zero-terminated list of common I/O addresses to be probed. */ -static unsigned int netcard_portlist[] __initdata = - { 0x300, 0x320, 0x340, 0x280, 0}; - /* Details of the i82586. @@ -286,8 +282,6 @@ static unsigned short init_words[] = { /* Index to functions, as function prototypes. */ -extern int el16_probe(struct net_device *dev); /* Called from Space.c */ - static int el16_probe1(struct net_device *dev, int ioaddr); static int el16_open(struct net_device *dev); static int el16_send_packet(struct sk_buff *skb, struct net_device *dev); @@ -301,6 +295,10 @@ static void hardware_send_packet(struct static void init_82586_mem(struct net_device *dev); static struct ethtool_ops netdev_ethtool_ops; +static int io = 0x300; +static int irq; +static int mem_start; + /* Check for a network adaptor of this type, and return '0' iff one exists. If dev->base_addr == 0, probe all likely locations. @@ -309,23 +307,50 @@ static struct ethtool_ops netdev_ethtool device and return success. */ -int __init el16_probe(struct net_device *dev) +struct net_device * __init el16_probe(int unit) { - int base_addr = dev->base_addr; - int i; + struct net_device *dev = alloc_etherdev(sizeof(struct net_local)); + static unsigned ports[] = { 0x300, 0x320, 0x340, 0x280, 0}; + unsigned *port; + int err = -ENODEV; + + if (!dev) + return ERR_PTR(-ENODEV); + + if (unit >= 0) { + sprintf(dev->name, "eth%d", unit); + netdev_boot_setup_check(dev); + io = dev->base_addr; + irq = dev->irq; + mem_start = dev->mem_start & 15; + } SET_MODULE_OWNER(dev); - if (base_addr > 0x1ff) /* Check a single specified location. */ - return el16_probe1(dev, base_addr); - else if (base_addr != 0) - return -ENXIO; /* Don't probe at all. */ - - for (i = 0; netcard_portlist[i]; i++) - if (el16_probe1(dev, netcard_portlist[i]) == 0) - return 0; + if (io > 0x1ff) /* Check a single specified location. */ + err = el16_probe1(dev, io); + else if (io != 0) + err = -ENXIO; /* Don't probe at all. */ + else { + for (port = ports; *port; port++) { + err = el16_probe1(dev, *port); + if (!err) + break; + } + } - return -ENODEV; + if (err) + goto out; + err = register_netdev(dev); + if (err) + goto out1; + return dev; +out1: + free_irq(dev->irq, dev); + release_region(dev->base_addr, EL16_IO_EXTENT); +out: + free_netdev(dev); + return ERR_PTR(err); } static int __init el16_probe1(struct net_device *dev, int ioaddr) @@ -383,8 +408,8 @@ static int __init el16_probe1(struct net printk(" %02x", dev->dev_addr[i]); } - if ((dev->mem_start & 0xf) > 0) - net_debug = dev->mem_start & 7; + if (mem_start) + net_debug = mem_start & 7; #ifdef MEM_BASE dev->mem_start = MEM_BASE; @@ -416,27 +441,18 @@ static int __init el16_probe1(struct net if (net_debug) printk(version); - /* Initialize the device structure. */ - lp = dev->priv = kmalloc(sizeof(struct net_local), GFP_KERNEL); - if (dev->priv == NULL) { - retval = -ENOMEM; - goto out; - } - memset(dev->priv, 0, sizeof(struct net_local)); + lp = dev->priv; + memset(lp, 0, sizeof(*lp)); spin_lock_init(&lp->lock); - dev->open = el16_open; - dev->stop = el16_close; + dev->open = el16_open; + dev->stop = el16_close; dev->hard_start_xmit = el16_send_packet; dev->get_stats = el16_get_stats; dev->tx_timeout = el16_tx_timeout; dev->watchdog_timeo = TX_TIMEOUT; dev->ethtool_ops = &netdev_ethtool_ops; - - ether_setup(dev); /* Generic ethernet behaviour */ - - dev->flags&=~IFF_MULTICAST; /* Multicast doesn't work */ - + dev->flags &= ~IFF_MULTICAST; /* Multicast doesn't work */ return 0; out: release_region(ioaddr, EL16_IO_EXTENT); @@ -899,9 +915,7 @@ static struct ethtool_ops netdev_ethtool }; #ifdef MODULE -static struct net_device dev_3c507; -static int io = 0x300; -static int irq; +static struct net_device *dev_3c507; MODULE_PARM(io, "i"); MODULE_PARM(irq, "i"); MODULE_PARM_DESC(io, "EtherLink16 I/O base address"); @@ -911,26 +925,18 @@ int init_module(void) { if (io == 0) printk("3c507: You should not use auto-probing with insmod!\n"); - dev_3c507.base_addr = io; - dev_3c507.irq = irq; - dev_3c507.init = el16_probe; - if (register_netdev(&dev_3c507) != 0) { - printk("3c507: register_netdev() returned non-zero.\n"); - return -EIO; - } - return 0; + dev_3c507 = el16_probe(-1); + return IS_ERR(dev_3c507) ? PTR_ERR(dev_3c507) : 0; } void cleanup_module(void) { - unregister_netdev(&dev_3c507); - kfree(dev_3c507.priv); - dev_3c507.priv = NULL; - - /* If we don't do this, we can't re-insmod it later. */ - free_irq(dev_3c507.irq, &dev_3c507); - release_region(dev_3c507.base_addr, EL16_IO_EXTENT); + struct net_device *dev = dev_3c507; + unregister_netdev(dev); + free_irq(dev->irq, dev); + release_region(dev->base_addr, EL16_IO_EXTENT); + free_netdev(dev); } #endif /* MODULE */ MODULE_LICENSE("GPL"); diff -aurpN -X /home/fletch/.diff.exclude 001-mjb/drivers/net/3c515.c 100-netdrvr_2.6.1_rc1_exp1/drivers/net/3c515.c --- 001-mjb/drivers/net/3c515.c Mon Nov 17 18:28:49 2003 +++ 100-netdrvr_2.6.1_rc1_exp1/drivers/net/3c515.c Thu Jan 8 08:54:04 2004 @@ -307,7 +307,8 @@ struct boom_tx_desc { struct corkscrew_private { const char *product_name; - struct net_device *next_module; + struct list_head list; + struct net_device *our_dev; /* The Rx and Tx rings are here to keep them quad-word-aligned. */ struct boom_rx_desc rx_ring[RX_RING_SIZE]; struct boom_tx_desc tx_ring[TX_RING_SIZE]; @@ -329,6 +330,7 @@ struct corkscrew_private { full_bus_master_tx:1, full_bus_master_rx:1, /* Boomerang */ tx_full:1; spinlock_t lock; + struct device *dev; }; /* The action to take with a media selection timer tick. @@ -367,17 +369,12 @@ static struct isapnp_device_id corkscrew MODULE_DEVICE_TABLE(isapnp, corkscrew_isapnp_adapters); -static int corkscrew_isapnp_phys_addr[3]; - static int nopnp; #endif /* __ISAPNP__ */ -static int corkscrew_scan(struct net_device *dev); -static struct net_device *corkscrew_found_device(struct net_device *dev, - int ioaddr, int irq, - int product_index, - int options); -static int corkscrew_probe1(struct net_device *dev); +static struct net_device *corkscrew_scan(int unit); +static void corkscrew_setup(struct net_device *dev, int ioaddr, + struct pnp_dev *idev, int card_number); static int corkscrew_open(struct net_device *dev); static void corkscrew_timer(unsigned long arg); static int corkscrew_start_xmit(struct sk_buff *skb, @@ -413,47 +410,99 @@ static int options[MAX_UNITS] = { -1, -1 #ifdef MODULE static int debug = -1; /* A list of all installed Vortex devices, for removing the driver module. */ -static struct net_device *root_corkscrew_dev; +/* we will need locking (and refcounting) if we ever use it for more */ +static LIST_HEAD(root_corkscrew_dev); int init_module(void) { - int cards_found; - + int found = 0; if (debug >= 0) corkscrew_debug = debug; if (corkscrew_debug) printk(version); - - root_corkscrew_dev = NULL; - cards_found = corkscrew_scan(NULL); - return cards_found ? 0 : -ENODEV; + while (corkscrew_scan(-1)) + found++; + return found ? 0 : -ENODEV; } #else -int tc515_probe(struct net_device *dev) +struct net_device *tc515_probe(int unit) { - int cards_found = 0; + struct net_device *dev = corkscrew_scan(unit); + static int printed; - SET_MODULE_OWNER(dev); - - cards_found = corkscrew_scan(dev); + if (!dev) + return ERR_PTR(-ENODEV); - if (corkscrew_debug > 0 && cards_found) + if (corkscrew_debug > 0 && !printed) { + printed = 1; printk(version); + } - return cards_found ? 0 : -ENODEV; + return dev; } #endif /* not MODULE */ -static int corkscrew_scan(struct net_device *dev) +static int check_device(unsigned ioaddr) +{ + int timer; + + if (!request_region(ioaddr, CORKSCREW_TOTAL_SIZE, "3c515")) + return 0; + /* Check the resource configuration for a matching ioaddr. */ + if ((inw(ioaddr + 0x2002) & 0x1f0) != (ioaddr & 0x1f0)) { + release_region(ioaddr, CORKSCREW_TOTAL_SIZE); + return 0; + } + /* Verify by reading the device ID from the EEPROM. */ + outw(EEPROM_Read + 7, ioaddr + Wn0EepromCmd); + /* Pause for at least 162 us. for the read to take place. */ + for (timer = 4; timer >= 0; timer--) { + udelay(162); + if ((inw(ioaddr + Wn0EepromCmd) & 0x0200) == 0) + break; + } + if (inw(ioaddr + Wn0EepromData) != 0x6d50) { + release_region(ioaddr, CORKSCREW_TOTAL_SIZE); + return 0; + } + return 1; +} + +static void cleanup_card(struct net_device *dev) +{ + struct corkscrew_private *vp = (struct corkscrew_private *) dev->priv; + list_del_init(&vp->list); + if (dev->dma) + free_dma(dev->dma); + outw(TotalReset, dev->base_addr + EL3_CMD); + release_region(dev->base_addr, CORKSCREW_TOTAL_SIZE); + if (vp->dev) + pnp_device_detach(to_pnp_dev(vp->dev)); +} + +static struct net_device *corkscrew_scan(int unit) { - int cards_found = 0; + struct net_device *dev; + static int cards_found = 0; static int ioaddr; + int err; #ifdef __ISAPNP__ short i; static int pnp_cards; #endif + dev = alloc_etherdev(sizeof(struct corkscrew_private)); + if (!dev) + return ERR_PTR(-ENOMEM); + + if (unit >= 0) { + sprintf(dev->name, "eth%d", unit); + netdev_boot_setup_check(dev); + } + + SET_MODULE_OWNER(dev); + #ifdef __ISAPNP__ if(nopnp == 1) goto no_pnp; @@ -470,7 +519,7 @@ static int corkscrew_scan(struct net_dev if (pnp_activate_dev(idev) < 0) { printk("pnp activate failed (out of resources?)\n"); pnp_device_detach(idev); - return -ENOMEM; + continue; } if (!pnp_port_valid(idev, 0) || !pnp_irq_valid(idev, 0)) { pnp_device_detach(idev); @@ -478,40 +527,22 @@ static int corkscrew_scan(struct net_dev } ioaddr = pnp_port_start(idev, 0); irq = pnp_irq(idev, 0); - if(corkscrew_debug) - printk ("ISAPNP reports %s at i/o 0x%x, irq %d\n", - (char*) corkscrew_isapnp_adapters[i].driver_data, ioaddr, irq); - - if ((inw(ioaddr + 0x2002) & 0x1f0) != (ioaddr & 0x1f0)) { + if (!check_device(ioaddr)) { pnp_device_detach(idev); continue; } - /* Verify by reading the device ID from the EEPROM. */ - { - int timer; - outw(EEPROM_Read + 7, ioaddr + Wn0EepromCmd); - /* Pause for at least 162 us. for the read to take place. */ - for (timer = 4; timer >= 0; timer--) { - udelay(162); - if ((inw(ioaddr + Wn0EepromCmd) & 0x0200) - == 0) - break; - } - if (inw(ioaddr + Wn0EepromData) != 0x6d50) { - pnp_device_detach(idev); - continue; - } - } + if(corkscrew_debug) + printk ("ISAPNP reports %s at i/o 0x%x, irq %d\n", + (char*) corkscrew_isapnp_adapters[i].driver_data, ioaddr, irq); printk(KERN_INFO "3c515 Resource configuration register %#4.4x, DCR %4.4x.\n", inl(ioaddr + 0x2002), inw(ioaddr + 0x2000)); /* irq = inw(ioaddr + 0x2002) & 15; */ /* Use the irq from isapnp */ - corkscrew_isapnp_phys_addr[pnp_cards] = ioaddr; - corkscrew_found_device(dev, ioaddr, irq, CORKSCREW_ID, dev - && dev->mem_start ? dev-> - mem_start : options[cards_found]); - dev = 0; + corkscrew_setup(dev, ioaddr, idev, cards_found++); pnp_cards++; - cards_found++; + err = register_netdev(dev); + if (!err) + return dev; + cleanup_card(dev); } } no_pnp: @@ -519,122 +550,64 @@ no_pnp: /* Check all locations on the ISA bus -- evil! */ for (ioaddr = 0x100; ioaddr < 0x400; ioaddr += 0x20) { - int irq; -#ifdef __ISAPNP__ - /* Make sure this was not already picked up by isapnp */ - if(ioaddr == corkscrew_isapnp_phys_addr[0]) continue; - if(ioaddr == corkscrew_isapnp_phys_addr[1]) continue; - if(ioaddr == corkscrew_isapnp_phys_addr[2]) continue; -#endif /* __ISAPNP__ */ - if (check_region(ioaddr, CORKSCREW_TOTAL_SIZE)) - continue; - /* Check the resource configuration for a matching ioaddr. */ - if ((inw(ioaddr + 0x2002) & 0x1f0) != (ioaddr & 0x1f0)) + if (!check_device(ioaddr)) continue; - /* Verify by reading the device ID from the EEPROM. */ - { - int timer; - outw(EEPROM_Read + 7, ioaddr + Wn0EepromCmd); - /* Pause for at least 162 us. for the read to take place. */ - for (timer = 4; timer >= 0; timer--) { - udelay(162); - if ((inw(ioaddr + Wn0EepromCmd) & 0x0200) - == 0) - break; - } - if (inw(ioaddr + Wn0EepromData) != 0x6d50) - continue; - } + printk(KERN_INFO "3c515 Resource configuration register %#4.4x, DCR %4.4x.\n", inl(ioaddr + 0x2002), inw(ioaddr + 0x2000)); - irq = inw(ioaddr + 0x2002) & 15; - corkscrew_found_device(dev, ioaddr, irq, CORKSCREW_ID, - dev && dev->mem_start ? dev->mem_start : - (cards_found >= MAX_UNITS ? -1 : - options[cards_found])); - dev = 0; - cards_found++; + corkscrew_setup(dev, ioaddr, NULL, cards_found++); + err = register_netdev(dev); + if (!err) + return dev; + cleanup_card(dev); } - if (corkscrew_debug) - printk(KERN_INFO "%d 3c515 cards found.\n", cards_found); - return cards_found; + free_netdev(dev); + return NULL; } -static struct net_device *corkscrew_found_device(struct net_device *dev, - int ioaddr, int irq, - int product_index, - int options) +static void corkscrew_setup(struct net_device *dev, int ioaddr, + struct pnp_dev *idev, int card_number) { - struct corkscrew_private *vp; - -#ifdef MODULE - /* Allocate and fill new device structure. */ - int dev_size = sizeof(struct net_device) + sizeof(struct corkscrew_private) + 15; /* Pad for alignment */ + struct corkscrew_private *vp = (struct corkscrew_private *) dev->priv; + unsigned int eeprom[0x40], checksum = 0; /* EEPROM contents */ + int i; + int irq; - dev = (struct net_device *) kmalloc(dev_size, GFP_KERNEL); - if (!dev) - return NULL; - memset(dev, 0, dev_size); - /* Align the Rx and Tx ring entries. */ - dev->priv = (void *) (((long) dev + sizeof(struct net_device) + 15) & ~15); - vp = (struct corkscrew_private *) dev->priv; - dev->base_addr = ioaddr; - dev->irq = irq; - dev->dma = (product_index == CORKSCREW_ID ? inw(ioaddr + 0x2000) & 7 : 0); - dev->init = corkscrew_probe1; - vp->product_name = "3c515"; - vp->options = options; - if (options >= 0) { - vp->media_override = ((options & 7) == 2) ? 0 : options & 7; - vp->full_duplex = (options & 8) ? 1 : 0; - vp->bus_master = (options & 16) ? 1 : 0; + if (idev) { + irq = pnp_irq(idev, 0); + vp->dev = &idev->dev; } else { - vp->media_override = 7; - vp->full_duplex = 0; - vp->bus_master = 0; + irq = inw(ioaddr + 0x2002) & 15; } - ether_setup(dev); - vp->next_module = root_corkscrew_dev; - root_corkscrew_dev = dev; - SET_MODULE_OWNER(dev); - if (register_netdev(dev) != 0) { - kfree(dev); - return NULL; - } -#else /* not a MODULE */ - /* Caution: quad-word alignment required for rings! */ - dev->priv = kmalloc(sizeof(struct corkscrew_private), GFP_KERNEL); - if (!dev->priv) - return NULL; - memset(dev->priv, 0, sizeof(struct corkscrew_private)); - dev = init_etherdev(dev, sizeof(struct corkscrew_private)); + dev->base_addr = ioaddr; dev->irq = irq; - dev->dma = (product_index == CORKSCREW_ID ? inw(ioaddr + 0x2000) & 7 : 0); - vp = (struct corkscrew_private *) dev->priv; + dev->dma = inw(ioaddr + 0x2000) & 7; vp->product_name = "3c515"; - vp->options = options; - if (options >= 0) { - vp->media_override = ((options & 7) == 2) ? 0 : options & 7; - vp->full_duplex = (options & 8) ? 1 : 0; - vp->bus_master = (options & 16) ? 1 : 0; + vp->options = dev->mem_start; + vp->our_dev = dev; + + if (!vp->options) { + if (card_number >= MAX_UNITS) + vp->options = -1; + else + vp->options = options[card_number]; + } + + if (vp->options >= 0) { + vp->media_override = vp->options & 7; + if (vp->media_override == 2) + vp->media_override = 0; + vp->full_duplex = (vp->options & 8) ? 1 : 0; + vp->bus_master = (vp->options & 16) ? 1 : 0; } else { vp->media_override = 7; vp->full_duplex = 0; vp->bus_master = 0; } - - corkscrew_probe1(dev); -#endif /* MODULE */ - return dev; -} - -static int corkscrew_probe1(struct net_device *dev) -{ - int ioaddr = dev->base_addr; - struct corkscrew_private *vp = (struct corkscrew_private *) dev->priv; - unsigned int eeprom[0x40], checksum = 0; /* EEPROM contents */ - int i; +#ifdef MODULE + list_add(&vp->list, &root_corkscrew_dev); +#endif printk(KERN_INFO "%s: 3Com %s at %#3x,", dev->name, vp->product_name, ioaddr); @@ -706,9 +679,6 @@ static int corkscrew_probe1(struct net_d /* vp->full_bus_master_rx = 0; */ vp->full_bus_master_rx = (vp->capabilities & 0x20) ? 1 : 0; - /* We do a request_region() to register /proc/ioports info. */ - request_region(ioaddr, CORKSCREW_TOTAL_SIZE, vp->product_name); - /* The 3c51x-specific entries in the device structure. */ dev->open = &corkscrew_open; dev->hard_start_xmit = &corkscrew_start_xmit; @@ -718,8 +688,6 @@ static int corkscrew_probe1(struct net_d dev->get_stats = &corkscrew_get_stats; dev->set_multicast_list = &set_rx_mode; dev->ethtool_ops = &netdev_ethtool_ops; - - return 0; } @@ -1607,20 +1575,16 @@ static struct ethtool_ops netdev_ethtool #ifdef MODULE void cleanup_module(void) { - struct net_device *next_dev; - - while (root_corkscrew_dev) { - next_dev = - ((struct corkscrew_private *) root_corkscrew_dev-> - priv)->next_module; - if (root_corkscrew_dev->dma) - free_dma(root_corkscrew_dev->dma); - unregister_netdev(root_corkscrew_dev); - outw(TotalReset, root_corkscrew_dev->base_addr + EL3_CMD); - release_region(root_corkscrew_dev->base_addr, - CORKSCREW_TOTAL_SIZE); - free_netdev(root_corkscrew_dev); - root_corkscrew_dev = next_dev; + while (!list_empty(&root_corkscrew_dev)) { + struct net_device *dev; + struct corkscrew_private *vp; + + vp = list_entry(root_corkscrew_dev.next, + struct corkscrew_private, list); + dev = vp->our_dev; + unregister_netdev(dev); + cleanup_card(dev); + free_netdev(dev); } } #endif /* MODULE */ diff -aurpN -X /home/fletch/.diff.exclude 001-mjb/drivers/net/3c523.c 100-netdrvr_2.6.1_rc1_exp1/drivers/net/3c523.c --- 001-mjb/drivers/net/3c523.c Mon Nov 17 18:29:30 2003 +++ 100-netdrvr_2.6.1_rc1_exp1/drivers/net/3c523.c Thu Jan 8 08:54:04 2004 @@ -410,7 +410,7 @@ static int elmc_getinfo(char *buf, int s /*****************************************************************/ -int __init elmc_probe(struct net_device *dev) +static int __init do_elmc_probe(struct net_device *dev) { static int slot; int base_addr = dev->base_addr; @@ -420,7 +420,7 @@ int __init elmc_probe(struct net_device int i = 0; unsigned int size = 0; int retval; - struct priv *pr; + struct priv *pr = dev->priv; SET_MODULE_OWNER(dev); if (MCA_bus == 0) { @@ -455,10 +455,9 @@ int __init elmc_probe(struct net_device } /* we didn't find any 3c523 in the slots we checked for */ - if (slot == MCA_NOTFOUND) { - retval = ((base_addr || irq) ? -ENXIO : -ENODEV); - goto err_out; - } + if (slot == MCA_NOTFOUND) + return ((base_addr || irq) ? -ENXIO : -ENODEV); + mca_set_adapter_name(slot, "3Com 3c523 Etherlink/MC"); mca_set_adapter_procfn(slot, (MCA_ProcFn) elmc_getinfo, dev); @@ -497,13 +496,7 @@ int __init elmc_probe(struct net_device break; } - pr = dev->priv = kmalloc(sizeof(struct priv), GFP_KERNEL); - if (dev->priv == NULL) { - retval = -ENOMEM; - goto err_out; - } memset(pr, 0, sizeof(struct priv)); - pr->slot = slot; printk(KERN_INFO "%s: 3Com 3c523 Rev 0x%x at %#lx\n", dev->name, (int) revision, @@ -530,8 +523,6 @@ int __init elmc_probe(struct net_device if (!check586(dev, dev->mem_start, size)) { printk(KERN_ERR "%s: memprobe, Can't find memory at 0x%lx!\n", dev->name, dev->mem_start); - kfree(dev->priv); - dev->priv = NULL; retval = -ENODEV; goto err_out; } @@ -573,8 +564,6 @@ int __init elmc_probe(struct net_device #endif dev->ethtool_ops = &netdev_ethtool_ops; - ether_setup(dev); - /* note that we haven't actually requested the IRQ from the kernel. That gets done in elmc_open(). I'm not sure that's such a good idea, but it works, so I'll go with it. */ @@ -585,9 +574,41 @@ int __init elmc_probe(struct net_device return 0; err_out: + mca_set_adapter_procfn(slot, NULL, NULL); release_region(dev->base_addr, ELMC_IO_EXTENT); return retval; } + +static void cleanup_card(struct net_device *dev) +{ + mca_set_adapter_procfn(((struct priv *) (dev->priv))->slot, NULL, NULL); + release_region(dev->base_addr, ELMC_IO_EXTENT); +} + +struct net_device * __init elmc_probe(int unit) +{ + struct net_device *dev = alloc_etherdev(sizeof(struct priv)); + int err; + + if (!dev) + return ERR_PTR(-ENOMEM); + + sprintf(dev->name, "eth%d", unit); + netdev_boot_setup_check(dev); + + err = do_elmc_probe(dev); + if (err) + goto out; + err = register_netdev(dev); + if (err) + goto out1; + return dev; +out1: + cleanup_card(dev); +out: + free_netdev(dev); + return ERR_PTR(err); +} /********************************************** * init the chip (elmc-interrupt should be disabled?!) @@ -1245,7 +1266,7 @@ static struct ethtool_ops netdev_ethtool /* Increase if needed ;) */ #define MAX_3C523_CARDS 4 -static struct net_device dev_elmc[MAX_3C523_CARDS]; +static struct net_device *dev_elmc[MAX_3C523_CARDS]; static int irq[MAX_3C523_CARDS]; static int io[MAX_3C523_CARDS]; MODULE_PARM(irq, "1-" __MODULE_STRING(MAX_3C523_CARDS) "i"); @@ -1258,16 +1279,24 @@ int init_module(void) int this_dev,found = 0; /* Loop until we either can't find any more cards, or we have MAX_3C523_CARDS */ - for(this_dev=0; this_devirq=irq[this_dev]; dev->base_addr=io[this_dev]; - dev->init=elmc_probe; - if(register_netdev(dev)!=0) { - if(io[this_dev]==0) break; - printk(KERN_WARNING "3c523.c: No 3c523 card found at io=%#x\n",io[this_dev]); - } else found++; + if (do_elmc_probe(dev) == 0) { + if (register_netdev(dev) == 0) { + dev_elmc[this_dev] = dev; + found++; + continue; + } + cleanup_card(dev); + } + free_netdev(dev); + if (io[this_dev]==0) + break; + printk(KERN_WARNING "3c523.c: No 3c523 card found at io=%#x\n",io[this_dev]); } if(found==0) { @@ -1279,31 +1308,12 @@ int init_module(void) void cleanup_module(void) { int this_dev; - for(this_dev=0; this_devpriv) { - /* shutdown interrupts on the card */ - elmc_id_reset586(); - if (dev->irq != 0) { - /* this should be done by close, but if we failed to - initialize properly something may have gotten hosed. */ - free_irq(dev->irq, dev); - dev->irq = 0; - } - if (dev->base_addr != 0) { - release_region(dev->base_addr, ELMC_IO_EXTENT); - dev->base_addr = 0; - } - irq[this_dev] = 0; - io[this_dev] = 0; + for (this_dev=0; this_devpriv))->slot, - NULL, NULL); - - kfree(dev->priv); - dev->priv = NULL; + cleanup_card(dev); + free_netdev(dev); } } } diff -aurpN -X /home/fletch/.diff.exclude 001-mjb/drivers/net/3c527.c 100-netdrvr_2.6.1_rc1_exp1/drivers/net/3c527.c --- 001-mjb/drivers/net/3c527.c Mon Dec 8 09:55:51 2003 +++ 100-netdrvr_2.6.1_rc1_exp1/drivers/net/3c527.c Thu Jan 8 08:54:04 2004 @@ -1,9 +1,10 @@ -/* 3c527.c: 3Com Etherlink/MC32 driver for Linux 2.4 +/* 3c527.c: 3Com Etherlink/MC32 driver for Linux 2.4 and 2.6. * * (c) Copyright 1998 Red Hat Software Inc * Written by Alan Cox. * Further debugging by Carl Drougge. - * Modified by Richard Procter (rnp@netlink.co.nz) + * Initial SMP support by Fel