diff -Nur --show-c-function linux-2.4.25/arch/i386/defconfig linux-2.4.26-pre2/arch/i386/defconfig
--- linux-2.4.25/arch/i386/defconfig	2004-02-18 10:36:30.000000000 -0300
+++ linux-2.4.26-pre2/arch/i386/defconfig	2004-03-06 15:14:08.000000000 -0300
@@ -2,7 +2,6 @@
 # Automatically generated make config: don't edit
 #
 CONFIG_X86=y
-CONFIG_ISA=y
 # CONFIG_SBUS is not set
 CONFIG_UID16=y
 
@@ -31,12 +30,14 @@ CONFIG_MPENTIUMIII=y
 # CONFIG_MPENTIUM4 is not set
 # CONFIG_MK6 is not set
 # CONFIG_MK7 is not set
+# CONFIG_MK8 is not set
 # CONFIG_MELAN is not set
 # CONFIG_MCRUSOE is not set
 # CONFIG_MWINCHIPC6 is not set
 # CONFIG_MWINCHIP2 is not set
 # CONFIG_MWINCHIP3D is not set
 # CONFIG_MCYRIXIII is not set
+# CONFIG_MVIAC3_2 is not set
 CONFIG_X86_WP_WORKS_OK=y
 CONFIG_X86_INVLPG=y
 CONFIG_X86_CMPXCHG=y
@@ -46,26 +47,29 @@ CONFIG_X86_POPAD_OK=y
 # CONFIG_RWSEM_GENERIC_SPINLOCK is not set
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 CONFIG_X86_L1_CACHE_SHIFT=5
-CONFIG_X86_TSC=y
+CONFIG_X86_HAS_TSC=y
 CONFIG_X86_GOOD_APIC=y
 CONFIG_X86_PGE=y
 CONFIG_X86_USE_PPRO_CHECKSUM=y
+CONFIG_X86_F00F_WORKS_OK=y
 CONFIG_X86_MCE=y
 # CONFIG_TOSHIBA is not set
 # CONFIG_I8K is not set
 # CONFIG_MICROCODE is not set
 # CONFIG_X86_MSR is not set
 # CONFIG_X86_CPUID is not set
-# CONFIG_EDD is not set
 CONFIG_NOHIGHMEM=y
 # CONFIG_HIGHMEM4G is not set
 # CONFIG_HIGHMEM64G is not set
+# CONFIG_HIGHMEM is not set
 # CONFIG_MATH_EMULATION is not set
 # CONFIG_MTRR is not set
 CONFIG_SMP=y
-# CONFIG_MULTIQUAD is not set
-CONFIG_HAVE_DEC_LOCK=y
 CONFIG_NR_CPUS=32
+# CONFIG_X86_NUMA is not set
+# CONFIG_X86_TSC_DISABLE is not set
+CONFIG_X86_TSC=y
+CONFIG_HAVE_DEC_LOCK=y
 
 #
 # General setup
@@ -79,6 +83,7 @@ CONFIG_PCI=y
 CONFIG_PCI_GOANY=y
 CONFIG_PCI_BIOS=y
 CONFIG_PCI_DIRECT=y
+CONFIG_ISA=y
 CONFIG_PCI_NAMES=y
 # CONFIG_EISA is not set
 # CONFIG_MCA is not set
@@ -100,7 +105,6 @@ CONFIG_CARDBUS=y
 # CONFIG_HOTPLUG_PCI_COMPAQ is not set
 # CONFIG_HOTPLUG_PCI_COMPAQ_NVRAM is not set
 # CONFIG_HOTPLUG_PCI_IBM is not set
-# CONFIG_HOTPLUG_PCI_ACPI is not set
 CONFIG_SYSVIPC=y
 # CONFIG_BSD_PROCESS_ACCT is not set
 CONFIG_SYSCTL=y
@@ -109,10 +113,17 @@ CONFIG_KCORE_ELF=y
 CONFIG_BINFMT_AOUT=y
 CONFIG_BINFMT_ELF=y
 CONFIG_BINFMT_MISC=y
+# CONFIG_OOM_KILLER is not set
 CONFIG_PM=y
 # CONFIG_APM is not set
 
 #
+# ACPI Support
+#
+# CONFIG_ACPI is not set
+CONFIG_ACPI_BOOT=y
+
+#
 # Memory Technology Devices (MTD)
 #
 # CONFIG_MTD is not set
@@ -137,12 +148,14 @@ CONFIG_BLK_DEV_FD=y
 # CONFIG_BLK_CPQ_DA is not set
 # CONFIG_BLK_CPQ_CISS_DA is not set
 # CONFIG_CISS_SCSI_TAPE is not set
+# CONFIG_CISS_MONITOR_THREAD is not set
 # CONFIG_BLK_DEV_DAC960 is not set
 # CONFIG_BLK_DEV_UMEM is not set
 # CONFIG_BLK_DEV_LOOP is not set
 # CONFIG_BLK_DEV_NBD is not set
 # CONFIG_BLK_DEV_RAM is not set
 # CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_BLK_STATS is not set
 
 #
 # Multi-device support (RAID and LVM)
@@ -224,15 +237,6 @@ CONFIG_BLK_DEV_IDE=y
 CONFIG_BLK_DEV_IDEDISK=y
 CONFIG_IDEDISK_MULTI_MODE=y
 # CONFIG_IDEDISK_STROKE is not set
-# CONFIG_BLK_DEV_IDEDISK_VENDOR is not set
-# CONFIG_BLK_DEV_IDEDISK_FUJITSU is not set
-# CONFIG_BLK_DEV_IDEDISK_IBM is not set
-# CONFIG_BLK_DEV_IDEDISK_MAXTOR is not set
-# CONFIG_BLK_DEV_IDEDISK_QUANTUM is not set
-# CONFIG_BLK_DEV_IDEDISK_SEAGATE is not set
-# CONFIG_BLK_DEV_IDEDISK_WD is not set
-# CONFIG_BLK_DEV_COMMERIAL is not set
-# CONFIG_BLK_DEV_TIVO is not set
 # CONFIG_BLK_DEV_IDECS is not set
 CONFIG_BLK_DEV_IDECD=y
 # CONFIG_BLK_DEV_IDETAPE is not set
@@ -246,8 +250,8 @@ CONFIG_BLK_DEV_IDECD=y
 CONFIG_BLK_DEV_CMD640=y
 # CONFIG_BLK_DEV_CMD640_ENHANCED is not set
 # CONFIG_BLK_DEV_ISAPNP is not set
-CONFIG_BLK_DEV_RZ1000=y
 CONFIG_BLK_DEV_IDEPCI=y
+# CONFIG_BLK_DEV_GENERIC is not set
 CONFIG_IDEPCI_SHARE_IRQ=y
 CONFIG_BLK_DEV_IDEDMA_PCI=y
 # CONFIG_BLK_DEV_OFFBOARD is not set
@@ -256,30 +260,29 @@ CONFIG_IDEDMA_PCI_AUTO=y
 # CONFIG_IDEDMA_ONLYDISK is not set
 CONFIG_BLK_DEV_IDEDMA=y
 # CONFIG_IDEDMA_PCI_WIP is not set
-# CONFIG_BLK_DEV_IDEDMA_TIMEOUT is not set
-# CONFIG_IDEDMA_NEW_DRIVE_LISTINGS is not set
-CONFIG_BLK_DEV_ADMA=y
+# CONFIG_BLK_DEV_ADMA100 is not set
 # CONFIG_BLK_DEV_AEC62XX is not set
-# CONFIG_AEC62XX_TUNING is not set
 # CONFIG_BLK_DEV_ALI15X3 is not set
 # CONFIG_WDC_ALI15X3 is not set
 # CONFIG_BLK_DEV_AMD74XX is not set
 # CONFIG_AMD74XX_OVERRIDE is not set
 # CONFIG_BLK_DEV_CMD64X is not set
-# CONFIG_BLK_DEV_CMD680 is not set
+# CONFIG_BLK_DEV_TRIFLEX is not set
 # CONFIG_BLK_DEV_CY82C693 is not set
 # CONFIG_BLK_DEV_CS5530 is not set
 # CONFIG_BLK_DEV_HPT34X is not set
 # CONFIG_HPT34X_AUTODMA is not set
 # CONFIG_BLK_DEV_HPT366 is not set
 CONFIG_BLK_DEV_PIIX=y
-CONFIG_PIIX_TUNING=y
 # CONFIG_BLK_DEV_NS87415 is not set
 # CONFIG_BLK_DEV_OPTI621 is not set
-# CONFIG_BLK_DEV_PDC202XX is not set
+# CONFIG_BLK_DEV_PDC202XX_OLD is not set
 # CONFIG_PDC202XX_BURST is not set
-# CONFIG_PDC202XX_FORCE is not set
+# CONFIG_BLK_DEV_PDC202XX_NEW is not set
+CONFIG_BLK_DEV_RZ1000=y
+# CONFIG_BLK_DEV_SC1200 is not set
 # CONFIG_BLK_DEV_SVWKS is not set
+# CONFIG_BLK_DEV_SIIMAGE is not set
 # CONFIG_BLK_DEV_SIS5513 is not set
 # CONFIG_BLK_DEV_SLC90E66 is not set
 # CONFIG_BLK_DEV_TRM290 is not set
@@ -291,6 +294,7 @@ CONFIG_IDEDMA_AUTO=y
 # CONFIG_BLK_DEV_ATARAID is not set
 # CONFIG_BLK_DEV_ATARAID_PDC is not set
 # CONFIG_BLK_DEV_ATARAID_HPT is not set
+# CONFIG_BLK_DEV_ATARAID_SII is not set
 
 #
 # SCSI support
@@ -325,12 +329,14 @@ CONFIG_SCSI_CONSTANTS=y
 # CONFIG_SCSI_AHA1542 is not set
 # CONFIG_SCSI_AHA1740 is not set
 # CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_AIC79XX is not set
 # CONFIG_SCSI_AIC7XXX_OLD is not set
 # CONFIG_SCSI_DPT_I2O is not set
 # CONFIG_SCSI_ADVANSYS is not set
 # CONFIG_SCSI_IN2000 is not set
 # CONFIG_SCSI_AM53C974 is not set
 # CONFIG_SCSI_MEGARAID is not set
+# CONFIG_SCSI_MEGARAID2 is not set
 # CONFIG_SCSI_BUSLOGIC is not set
 # CONFIG_SCSI_CPQFCTS is not set
 # CONFIG_SCSI_DMX3191D is not set
@@ -370,6 +376,7 @@ CONFIG_SCSI_NCR53C8XX_SYNC=20
 # CONFIG_SCSI_T128 is not set
 # CONFIG_SCSI_U14_34F is not set
 # CONFIG_SCSI_ULTRASTOR is not set
+# CONFIG_SCSI_NSP32 is not set
 
 #
 # PCMCIA SCSI adapter support
@@ -429,16 +436,19 @@ CONFIG_NET_ETHERNET=y
 # CONFIG_NET_ISA is not set
 CONFIG_NET_PCI=y
 # CONFIG_PCNET32 is not set
+# CONFIG_AMD8111_ETH is not set
 # CONFIG_ADAPTEC_STARFIRE is not set
 # CONFIG_AC3200 is not set
 # CONFIG_APRICOT is not set
+# CONFIG_B44 is not set
 # CONFIG_CS89x0 is not set
 # CONFIG_TULIP is not set
-# CONFIG_TC35815 is not set
 # CONFIG_DE4X5 is not set
 # CONFIG_DGRS is not set
 # CONFIG_DM9102 is not set
 CONFIG_EEPRO100=y
+# CONFIG_EEPRO100_PIO is not set
+# CONFIG_E100 is not set
 # CONFIG_LNE390 is not set
 # CONFIG_FEALNX is not set
 # CONFIG_NATSEMI is not set
@@ -450,10 +460,11 @@ CONFIG_EEPRO100=y
 # CONFIG_8139TOO_PIO is not set
 # CONFIG_8139TOO_TUNE_TWISTER is not set
 # CONFIG_8139TOO_8129 is not set
-# CONFIG_8139_NEW_RX_RESET is not set
+# CONFIG_8139_OLD_RX_RESET is not set
 # CONFIG_SIS900 is not set
 # CONFIG_EPIC100 is not set
 # CONFIG_SUNDANCE is not set
+# CONFIG_SUNDANCE_MMIO is not set
 # CONFIG_TLAN is not set
 # CONFIG_VIA_RHINE is not set
 # CONFIG_VIA_RHINE_MMIO is not set
@@ -465,10 +476,12 @@ CONFIG_EEPRO100=y
 #
 # CONFIG_ACENIC is not set
 # CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
 # CONFIG_MYRI_SBUS is not set
 # CONFIG_NS83820 is not set
 # CONFIG_HAMACHI is not set
 # CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
 # CONFIG_SK98LIN is not set
 # CONFIG_TIGON3 is not set
 # CONFIG_FDDI is not set
@@ -542,6 +555,7 @@ CONFIG_PCMCIA_RAYCS=y
 # CONFIG_INPUT_MOUSEDEV is not set
 # CONFIG_INPUT_JOYDEV is not set
 # CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_UINPUT is not set
 
 #
 # Character devices
@@ -583,13 +597,22 @@ CONFIG_PSMOUSE=y
 # Input core support is needed for joysticks
 #
 # CONFIG_QIC02_TAPE is not set
+# CONFIG_IPMI_HANDLER is not set
+# CONFIG_IPMI_PANIC_EVENT is not set
+# CONFIG_IPMI_DEVICE_INTERFACE is not set
+# CONFIG_IPMI_KCS is not set
+# CONFIG_IPMI_WATCHDOG is not set
 
 #
 # Watchdog Cards
 #
 # CONFIG_WATCHDOG is not set
+# CONFIG_SCx200 is not set
+# CONFIG_SCx200_GPIO is not set
 # CONFIG_AMD_RNG is not set
 # CONFIG_INTEL_RNG is not set
+# CONFIG_HW_RANDOM is not set
+# CONFIG_AMD_PM768 is not set
 # CONFIG_NVRAM is not set
 # CONFIG_RTC is not set
 # CONFIG_DTLK is not set
@@ -605,9 +628,16 @@ CONFIG_AGP_INTEL=y
 CONFIG_AGP_I810=y
 CONFIG_AGP_VIA=y
 CONFIG_AGP_AMD=y
+# CONFIG_AGP_AMD_K8 is not set
 CONFIG_AGP_SIS=y
 CONFIG_AGP_ALI=y
 # CONFIG_AGP_SWORKS is not set
+# CONFIG_AGP_NVIDIA is not set
+# CONFIG_AGP_ATI is not set
+
+#
+# Direct Rendering Manager (XFree86 DRI support)
+#
 CONFIG_DRM=y
 # CONFIG_DRM_OLD is not set
 
@@ -616,10 +646,12 @@ CONFIG_DRM=y
 #
 CONFIG_DRM_NEW=y
 CONFIG_DRM_TDFX=y
+# CONFIG_DRM_GAMMA is not set
 # CONFIG_DRM_R128 is not set
 CONFIG_DRM_RADEON=y
 CONFIG_DRM_I810=y
 CONFIG_DRM_I810_XFREE_41=y
+# CONFIG_DRM_I830 is not set
 # CONFIG_DRM_MGA is not set
 # CONFIG_DRM_SIS is not set
 
@@ -627,7 +659,9 @@ CONFIG_DRM_I810_XFREE_41=y
 # PCMCIA character devices
 #
 # CONFIG_PCMCIA_SERIAL_CS is not set
+# CONFIG_SYNCLINK_CS is not set
 # CONFIG_MWAVE is not set
+# CONFIG_OBMOUSE is not set
 
 #
 # Multimedia devices
@@ -638,6 +672,7 @@ CONFIG_DRM_I810_XFREE_41=y
 # File systems
 #
 # CONFIG_QUOTA is not set
+# CONFIG_QFMT_V2 is not set
 # CONFIG_AUTOFS_FS is not set
 CONFIG_AUTOFS4_FS=y
 # CONFIG_REISERFS_FS is not set
@@ -647,6 +682,9 @@ CONFIG_AUTOFS4_FS=y
 # CONFIG_ADFS_FS_RW is not set
 # CONFIG_AFFS_FS is not set
 # CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BEFS_DEBUG is not set
 # CONFIG_BFS_FS is not set
 # CONFIG_EXT3_FS is not set
 # CONFIG_JBD is not set
@@ -664,6 +702,9 @@ CONFIG_RAMFS=y
 CONFIG_ISO9660_FS=y
 # CONFIG_JOLIET is not set
 # CONFIG_ZISOFS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_JFS_DEBUG is not set
+# CONFIG_JFS_STATISTICS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_VXFS_FS is not set
 # CONFIG_NTFS_FS is not set
@@ -683,6 +724,11 @@ CONFIG_EXT2_FS=y
 # CONFIG_UDF_RW is not set
 # CONFIG_UFS_FS is not set
 # CONFIG_UFS_FS_WRITE is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_XFS_QUOTA is not set
+# CONFIG_XFS_RT is not set
+# CONFIG_XFS_TRACE is not set
+# CONFIG_XFS_DEBUG is not set
 
 #
 # Network File Systems
@@ -691,9 +737,11 @@ CONFIG_EXT2_FS=y
 # CONFIG_INTERMEZZO_FS is not set
 CONFIG_NFS_FS=y
 # CONFIG_NFS_V3 is not set
+# CONFIG_NFS_DIRECTIO is not set
 # CONFIG_ROOT_NFS is not set
 CONFIG_NFSD=y
 # CONFIG_NFSD_V3 is not set
+# CONFIG_NFSD_TCP is not set
 CONFIG_SUNRPC=y
 CONFIG_LOCKD=y
 # CONFIG_SMB_FS is not set
@@ -707,7 +755,6 @@ CONFIG_LOCKD=y
 # CONFIG_NCPFS_NLS is not set
 # CONFIG_NCPFS_EXTRAS is not set
 # CONFIG_ZISOFS_FS is not set
-# CONFIG_ZLIB_FS_INFLATE is not set
 
 #
 # Partition Types
@@ -727,6 +774,7 @@ CONFIG_VGA_CONSOLE=y
 # Sound
 #
 CONFIG_SOUND=y
+# CONFIG_SOUND_ALI5455 is not set
 # CONFIG_SOUND_BT878 is not set
 # CONFIG_SOUND_CMPCI is not set
 # CONFIG_SOUND_EMU10K1 is not set
@@ -738,6 +786,7 @@ CONFIG_SOUND_ES1371=y
 # CONFIG_SOUND_ESSSOLO1 is not set
 # CONFIG_SOUND_MAESTRO is not set
 # CONFIG_SOUND_MAESTRO3 is not set
+# CONFIG_SOUND_FORTE is not set
 # CONFIG_SOUND_ICH is not set
 # CONFIG_SOUND_RME96XX is not set
 # CONFIG_SOUND_SONICVIBES is not set
@@ -748,6 +797,8 @@ CONFIG_SOUND_ES1371=y
 # CONFIG_MIDI_VIA82CXXX is not set
 # CONFIG_SOUND_OSS is not set
 # CONFIG_SOUND_TVMIXER is not set
+# CONFIG_SOUND_AD1980 is not set
+# CONFIG_SOUND_WM97XX is not set
 
 #
 # USB support
@@ -760,7 +811,6 @@ CONFIG_USB=y
 #
 # CONFIG_USB_DEVICEFS is not set
 # CONFIG_USB_BANDWIDTH is not set
-# CONFIG_USB_LONG_TIMEOUT is not set
 
 #
 # USB Host Controller Drivers
@@ -768,13 +818,15 @@ CONFIG_USB=y
 # CONFIG_USB_EHCI_HCD is not set
 CONFIG_USB_UHCI_ALT=y
 # CONFIG_USB_OHCI is not set
+# CONFIG_USB_SL811HS_ALT is not set
+# CONFIG_USB_SL811HS is not set
 
 #
 # USB Device Class drivers
 #
 # CONFIG_USB_AUDIO is not set
 # CONFIG_USB_EMI26 is not set
-# CONFIG_USB_BLUETOOTH is not set
+# CONFIG_USB_MIDI is not set
 CONFIG_USB_STORAGE=y
 # CONFIG_USB_STORAGE_DEBUG is not set
 # CONFIG_USB_STORAGE_DATAFAB is not set
@@ -783,6 +835,7 @@ CONFIG_USB_STORAGE=y
 # CONFIG_USB_STORAGE_DPCM is not set
 # CONFIG_USB_STORAGE_HP8200e is not set
 # CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_STORAGE_SDDR55 is not set
 # CONFIG_USB_STORAGE_JUMPSHOT is not set
 # CONFIG_USB_ACM is not set
 # CONFIG_USB_PRINTER is not set
@@ -799,7 +852,10 @@ CONFIG_USB_STORAGE=y
 # CONFIG_USB_HIDDEV is not set
 # CONFIG_USB_KBD is not set
 # CONFIG_USB_MOUSE is not set
+# CONFIG_USB_AIPTEK is not set
 # CONFIG_USB_WACOM is not set
+# CONFIG_USB_KBTAB is not set
+# CONFIG_USB_POWERMATE is not set
 
 #
 # USB Imaging devices
@@ -837,39 +893,20 @@ CONFIG_USB_STORAGE=y
 # USB Serial Converter support
 #
 # CONFIG_USB_SERIAL is not set
-# CONFIG_USB_SERIAL_GENERIC is not set
-# CONFIG_USB_SERIAL_BELKIN is not set
-# CONFIG_USB_SERIAL_WHITEHEAT is not set
-# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set
-# CONFIG_USB_SERIAL_EMPEG is not set
-# CONFIG_USB_SERIAL_FTDI_SIO is not set
-# CONFIG_USB_SERIAL_VISOR is not set
-# CONFIG_USB_SERIAL_IPAQ is not set
-# CONFIG_USB_SERIAL_IR is not set
-# CONFIG_USB_SERIAL_EDGEPORT is not set
-# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set
-# CONFIG_USB_SERIAL_KEYSPAN is not set
-# CONFIG_USB_SERIAL_KEYSPAN_USA28 is not set
-# CONFIG_USB_SERIAL_KEYSPAN_USA28X is not set
-# CONFIG_USB_SERIAL_KEYSPAN_USA28XA is not set
-# CONFIG_USB_SERIAL_KEYSPAN_USA28XB is not set
-# CONFIG_USB_SERIAL_KEYSPAN_USA19 is not set
-# CONFIG_USB_SERIAL_KEYSPAN_USA18X is not set
-# CONFIG_USB_SERIAL_KEYSPAN_USA19W is not set
-# CONFIG_USB_SERIAL_KEYSPAN_USA49W is not set
-# CONFIG_USB_SERIAL_MCT_U232 is not set
-# CONFIG_USB_SERIAL_KLSI is not set
-# CONFIG_USB_SERIAL_PL2303 is not set
-# CONFIG_USB_SERIAL_CYBERJACK is not set
-# CONFIG_USB_SERIAL_XIRCOM is not set
-# CONFIG_USB_SERIAL_OMNINET is not set
 
 #
 # USB Miscellaneous drivers
 #
 # CONFIG_USB_RIO500 is not set
 # CONFIG_USB_AUERSWALD is not set
+# CONFIG_USB_TIGL is not set
 # CONFIG_USB_BRLVGER is not set
+# CONFIG_USB_LCD is not set
+
+#
+# Support for USB gadgets
+#
+# CONFIG_USB_GADGET is not set
 
 #
 # Bluetooth support
@@ -880,3 +917,16 @@ CONFIG_USB_STORAGE=y
 # Kernel hacking
 #
 # CONFIG_DEBUG_KERNEL is not set
+CONFIG_LOG_BUF_SHIFT=0
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Library routines
+#
+CONFIG_CRC32=y
+# CONFIG_ZLIB_INFLATE is not set
+# CONFIG_ZLIB_DEFLATE is not set
diff -Nur --show-c-function linux-2.4.25/arch/i386/kernel/acpi.c linux-2.4.26-pre2/arch/i386/kernel/acpi.c
--- linux-2.4.25/arch/i386/kernel/acpi.c	2004-02-18 10:36:30.000000000 -0300
+++ linux-2.4.26-pre2/arch/i386/kernel/acpi.c	2004-03-06 15:20:53.000000000 -0300
@@ -49,14 +49,14 @@
 
 #define PREFIX			"ACPI: "
 
-int acpi_lapic = 0;
-int acpi_ioapic = 0;
+int acpi_lapic;
+int acpi_ioapic;
+int acpi_strict;
 
 /* --------------------------------------------------------------------------
                               Boot-time Configuration
    -------------------------------------------------------------------------- */
 
-#ifdef CONFIG_ACPI_BOOT
 int acpi_noirq __initdata = 0;  /* skip ACPI IRQ initialization */
 int acpi_ht __initdata = 1;     /* enable HT */
 
@@ -472,7 +472,6 @@ acpi_boot_init (void)
 	return 0;
 }
 
-#endif /*CONFIG_ACPI_BOOT*/
 
 #ifdef	CONFIG_ACPI_BUS
 /*
@@ -480,7 +479,7 @@ acpi_boot_init (void)
  * programs the PIC-mode SCI to Level Trigger.
  * (NO-OP if the BIOS set Level Trigger already)
  *
- * If a PIC-mode SCI is not recogznied or gives spurious IRQ7's
+ * If a PIC-mode SCI is not recognized or gives spurious IRQ7's
  * it may require Edge Trigger -- use "acpi_pic_sci=edge"
  * (NO-OP if the BIOS set Edge Trigger already)
  *
diff -Nur --show-c-function linux-2.4.25/arch/i386/kernel/i386_ksyms.c linux-2.4.26-pre2/arch/i386/kernel/i386_ksyms.c
--- linux-2.4.25/arch/i386/kernel/i386_ksyms.c	2004-02-18 10:36:30.000000000 -0300
+++ linux-2.4.26-pre2/arch/i386/kernel/i386_ksyms.c	2004-03-06 15:23:37.000000000 -0300
@@ -146,6 +146,10 @@ EXPORT_SYMBOL(smp_call_function);
 
 /* TLB flushing */
 EXPORT_SYMBOL(flush_tlb_page);
+
+/* HT support */
+EXPORT_SYMBOL(smp_num_siblings);
+EXPORT_SYMBOL(cpu_sibling_map);
 #endif
 
 #ifdef CONFIG_X86_IO_APIC
diff -Nur --show-c-function linux-2.4.25/arch/i386/kernel/microcode.c linux-2.4.26-pre2/arch/i386/kernel/microcode.c
--- linux-2.4.25/arch/i386/kernel/microcode.c	2004-02-18 10:36:30.000000000 -0300
+++ linux-2.4.26-pre2/arch/i386/kernel/microcode.c	2004-03-06 15:15:09.000000000 -0300
@@ -1,7 +1,7 @@
 /*
  *	Intel CPU Microcode Update driver for Linux
  *
- *	Copyright (C) 2000 Tigran Aivazian
+ *	Copyright (C) 2000-2004 Tigran Aivazian
  *
  *	This driver allows to upgrade microcode on Intel processors
  *	belonging to IA-32 family - PentiumPro, Pentium II, 
@@ -64,6 +64,10 @@
  *		Removed ->read() method and obsoleted MICROCODE_IOCFREE ioctl
  *		because we no longer hold a copy of applied microcode 
  *		in kernel memory.
+ *	1.14	23 Feb 2004 Tigran Aivazian <tigran@veritas.com>
+ *		Restored devfs regular file entry point which was
+ *		accidentally removed when back-porting changes from the 2.6
+ *		version of the driver.
  */
 
 
@@ -73,6 +77,7 @@
 #include <linux/slab.h>
 #include <linux/vmalloc.h>
 #include <linux/miscdevice.h>
+#include <linux/devfs_fs_kernel.h>
 #include <linux/spinlock.h>
 #include <linux/mm.h>
 
@@ -84,8 +89,8 @@ MODULE_DESCRIPTION("Intel CPU (IA-32) mi
 MODULE_AUTHOR("Tigran Aivazian <tigran@veritas.com>");
 MODULE_LICENSE("GPL");
 
-#define MICROCODE_VERSION 	"1.13"
-#define MICRO_DEBUG 		1
+#define MICROCODE_VERSION 	"1.14"
+#define MICRO_DEBUG 		0
 #if MICRO_DEBUG
 #define dprintk(x...) printk(KERN_INFO x)
 #else
@@ -470,6 +475,7 @@ static int microcode_ioctl (struct inode
 	return -EINVAL;
 }
 
+/* shared between misc device and devfs regular file */
 static struct file_operations microcode_fops = {
 	.owner		= THIS_MODULE,
 	.write		= microcode_write,
@@ -483,29 +489,38 @@ static struct miscdevice microcode_dev =
 	.fops		= &microcode_fops,
 };
 
+static devfs_handle_t devfs_handle;
+
 static int __init microcode_init (void)
 {
 	int error;
 
 	error = misc_register(&microcode_dev);
-	if (error) {
+	if (error)
 		printk(KERN_ERR
 			"microcode: can't misc_register on minor=%d\n",
 			MICROCODE_MINOR);
-		return error;
+	devfs_handle = devfs_register(NULL, "cpu/microcode",
+			DEVFS_FL_DEFAULT, 0, 0, S_IFREG | S_IRUSR | S_IWUSR, 
+			&microcode_fops, NULL);
+	if (devfs_handle == NULL && error) {
+		printk(KERN_ERR "microcode: failed to devfs_register()\n");
+		goto out;
 	}
-
+	error = 0;
 	printk(KERN_INFO 
-		"IA-32 Microcode Update Driver: v%s <tigran@veritas.com>\n", 
-		MICROCODE_VERSION);
-	return 0;
+		"IA-32 Microcode Update Driver: v"
+		MICROCODE_VERSION " <tigran@veritas.com>\n");
+out:
+	return error;
 }
 
 static void __exit microcode_exit (void)
 {
 	misc_deregister(&microcode_dev);
-	printk(KERN_INFO "IA-32 Microcode Update Driver v%s unregistered\n", 
-			MICROCODE_VERSION);
+	devfs_unregister(devfs_handle);
+	printk(KERN_INFO "IA-32 Microcode Update Driver v" 
+		MICROCODE_VERSION " unregistered\n");
 }
 
 module_init(microcode_init)
diff -Nur --show-c-function linux-2.4.25/arch/i386/kernel/mpparse.c linux-2.4.26-pre2/arch/i386/kernel/mpparse.c
--- linux-2.4.25/arch/i386/kernel/mpparse.c	2004-02-18 10:36:30.000000000 -0300
+++ linux-2.4.26-pre2/arch/i386/kernel/mpparse.c	2004-03-06 15:15:49.000000000 -0300
@@ -1118,7 +1118,7 @@ void __init mp_override_legacy_irq (
 	 *      erroneously sets the trigger to level, resulting in a HUGE 
 	 *      increase of timer interrupts!
 	 */
-	if ((bus_irq == 0) && (global_irq == 2) && (trigger == 3))
+	if ((bus_irq == 0) && (trigger == 3))
 		trigger = 1;
 
 	intsrc.mpc_type = MP_INTSRC;
@@ -1139,7 +1139,7 @@ void __init mp_override_legacy_irq (
 	 * Otherwise create a new entry (e.g. global_irq == 2).
 	 */
 	for (i = 0; i < mp_irq_entries; i++) {
-		if ((mp_irqs[i].mpc_dstapic == intsrc.mpc_dstapic) 
+		if ((mp_irqs[i].mpc_srcbus == intsrc.mpc_srcbus) 
 			&& (mp_irqs[i].mpc_srcbusirq == intsrc.mpc_srcbusirq)) {
 			mp_irqs[i] = intsrc;
 			found = 1;
@@ -1200,13 +1200,14 @@ void __init mp_config_acpi_legacy_irqs (
 	 */
 	for (i = 0; i < 16; i++) {
 
-		if (i == 2) continue;			/* Don't connect IRQ2 */
+		if (i == 2)
+			continue;			/* Don't connect IRQ2 */
 
 		mp_irqs[mp_irq_entries].mpc_type = MP_INTSRC;
 		mp_irqs[mp_irq_entries].mpc_irqflag = 0;	/* Conforming */
 		mp_irqs[mp_irq_entries].mpc_srcbus = MP_ISA_BUS;
 		mp_irqs[mp_irq_entries].mpc_dstapic = mp_ioapics[ioapic].mpc_apicid;
-		mp_irqs[mp_irq_entries].mpc_irqtype = i ? mp_INT : mp_ExtINT;   /* 8259A to #0 */
+		mp_irqs[mp_irq_entries].mpc_irqtype = mp_INT;
 		mp_irqs[mp_irq_entries].mpc_srcbusirq = i;	   /* Identity mapped */
 		mp_irqs[mp_irq_entries].mpc_dstirq = i;
 
@@ -1349,7 +1350,7 @@ void __init mp_parse_prt (void)
 			continue;
 		}
 		if ((1<<bit) & mp_ioapic_routing[ioapic].pin_programmed[idx]) {
-			printk(KERN_DEBUG "Pin %d-%d already programmed\n",
+			Dprintk(KERN_DEBUG "Pin %d-%d already programmed\n",
 				mp_ioapic_routing[ioapic].apic_id, ioapic_pin);
 			entry->irq = irq;
 			continue;
diff -Nur --show-c-function linux-2.4.25/arch/i386/kernel/setup.c linux-2.4.26-pre2/arch/i386/kernel/setup.c
--- linux-2.4.25/arch/i386/kernel/setup.c	2004-02-18 10:36:30.000000000 -0300
+++ linux-2.4.26-pre2/arch/i386/kernel/setup.c	2004-03-06 15:17:45.000000000 -0300
@@ -852,6 +852,11 @@ static void __init parse_cmdline_early (
 			if (!acpi_force) acpi_disabled = 1; 
 		} 
 
+		/* acpi=strict disables out-of-spec workarounds */
+		else if (!memcmp(from, "acpi=strict", 11)) {
+			acpi_strict = 1;
+		}
+
 		else if (!memcmp(from, "pci=noacpi", 10)) { 
 			acpi_noirq_set();
 		}
diff -Nur --show-c-function linux-2.4.25/arch/i386/mm/init.c linux-2.4.26-pre2/arch/i386/mm/init.c
--- linux-2.4.25/arch/i386/mm/init.c	2003-06-13 11:51:29.000000000 -0300
+++ linux-2.4.26-pre2/arch/i386/mm/init.c	2004-03-06 15:20:23.000000000 -0300
@@ -510,7 +510,15 @@ void __init mem_init(void)
 
 	if (!mem_map)
 		BUG();
-	
+#ifdef CONFIG_HIGHMEM
+	/* check that fixmap and pkmap do not overlap */
+	if (PKMAP_BASE+LAST_PKMAP*PAGE_SIZE >= FIXADDR_START) {
+		printk(KERN_ERR "fixmap and kmap areas overlap - this will crash\n");
+		printk(KERN_ERR "pkstart: %lxh pkend: %lxh fixstart %lxh\n",
+				PKMAP_BASE, PKMAP_BASE+LAST_PKMAP*PAGE_SIZE, FIXADDR_START);
+		BUG();
+	}
+#endif
 	set_max_mapnr_init();
 
 	high_memory = (void *) __va(max_low_pfn * PAGE_SIZE);
diff -Nur --show-c-function linux-2.4.25/arch/ia64/tools/Makefile linux-2.4.26-pre2/arch/ia64/tools/Makefile
--- linux-2.4.25/arch/ia64/tools/Makefile	2004-02-18 10:36:30.000000000 -0300
+++ linux-2.4.26-pre2/arch/ia64/tools/Makefile	2004-03-06 15:18:23.000000000 -0300
@@ -5,6 +5,7 @@ TARGET	= $(TOPDIR)/include/asm-ia64/offs
 all:
 
 mrproper: clean
+	rm -f $(TARGET)
 
 clean:
 	rm -f print_offsets.s print_offsets offsets.h
diff -Nur --show-c-function linux-2.4.25/arch/sparc/defconfig linux-2.4.26-pre2/arch/sparc/defconfig
--- linux-2.4.25/arch/sparc/defconfig	2004-02-18 10:36:31.000000000 -0300
+++ linux-2.4.26-pre2/arch/sparc/defconfig	2004-03-06 15:20:19.000000000 -0300
@@ -161,9 +161,11 @@ CONFIG_IPV6=m
 #
 CONFIG_IPV6_SCTP__=m
 CONFIG_IP_SCTP=m
-# CONFIG_SCTP_ADLER32 is not set
 # CONFIG_SCTP_DBG_MSG is not set
 # CONFIG_SCTP_DBG_OBJCNT is not set
+# CONFIG_SCTP_HMAC_NONE is not set
+CONFIG_SCTP_HMAC_SHA1=y
+# CONFIG_SCTP_HMAC_MD5 is not set
 # CONFIG_ATM is not set
 # CONFIG_VLAN_8021Q is not set
 
@@ -362,6 +364,7 @@ CONFIG_SUNRPC=y
 CONFIG_LOCKD=y
 CONFIG_SMB_FS=m
 # CONFIG_SMB_NLS_DEFAULT is not set
+# CONFIG_SMB_UNIX is not set
 # CONFIG_NCP_FS is not set
 # CONFIG_NCPFS_PACKET_SIGNING is not set
 # CONFIG_NCPFS_IOCTL_LOCKING is not set
diff -Nur --show-c-function linux-2.4.25/arch/sparc/kernel/sys_sunos.c linux-2.4.26-pre2/arch/sparc/kernel/sys_sunos.c
--- linux-2.4.25/arch/sparc/kernel/sys_sunos.c	2003-11-28 16:26:19.000000000 -0200
+++ linux-2.4.26-pre2/arch/sparc/kernel/sys_sunos.c	2004-03-06 15:16:51.000000000 -0300
@@ -688,8 +688,8 @@ static int get_default (int value, int d
 
 static int sunos_nfs_mount(char *dir_name, int linux_flags, void *data)
 {
-	int  server_fd;
-	char *the_name;
+	int  server_fd, err;
+	char *the_name, *mount_page;
 	struct nfs_mount_data linux_nfs_mount;
 	struct sunos_nfs_mount_args sunos_mount;
 
@@ -742,7 +742,16 @@ static int sunos_nfs_mount(char *dir_nam
 	linux_nfs_mount.hostname [255] = 0;
 	putname (the_name);
 	
-	return do_mount ("", dir_name, "nfs", linux_flags, &linux_nfs_mount);
+	mount_page = (char *) get_zeroed_page(GFP_KERNEL);
+	if (!mount_page)
+		return -ENOMEM;
+
+	memcpy(mount_page, &linux_nfs_mount, sizeof(linux_nfs_mount));
+
+	err = do_mount("", dir_name, "nfs", linux_flags, mount_page);
+
+	free_page((unsigned long) mount_page);
+	return err;
 }
 
 asmlinkage int
diff -Nur --show-c-function linux-2.4.25/arch/sparc64/defconfig linux-2.4.26-pre2/arch/sparc64/defconfig
--- linux-2.4.25/arch/sparc64/defconfig	2004-02-18 10:36:31.000000000 -0300
+++ linux-2.4.26-pre2/arch/sparc64/defconfig	2004-03-06 15:15:59.000000000 -0300
@@ -70,6 +70,7 @@ CONFIG_PARPORT_PC_CML1=m
 # CONFIG_PARPORT_SERIAL is not set
 CONFIG_PARPORT_PC_FIFO=y
 # CONFIG_PARPORT_PC_SUPERIO is not set
+# CONFIG_PARPORT_PC_PCMCIA is not set
 # CONFIG_PARPORT_AMIGA is not set
 # CONFIG_PARPORT_MFC3 is not set
 # CONFIG_PARPORT_ATARI is not set
@@ -122,6 +123,7 @@ CONFIG_FB_CGSIX=y
 CONFIG_FB_PCI=y
 CONFIG_FB_ATY=y
 CONFIG_FB_ATY_CT=y
+# CONFIG_FB_IT8181 is not set
 # CONFIG_FB_VIRTUAL is not set
 # CONFIG_FBCON_ADVANCED is not set
 CONFIG_FBCON_CFB8=y
@@ -314,9 +316,11 @@ CONFIG_IP6_NF_TARGET_MARK=m
 #
 CONFIG_IPV6_SCTP__=m
 CONFIG_IP_SCTP=m
-# CONFIG_SCTP_ADLER32 is not set
 # CONFIG_SCTP_DBG_MSG is not set
 # CONFIG_SCTP_DBG_OBJCNT is not set
+# CONFIG_SCTP_HMAC_NONE is not set
+CONFIG_SCTP_HMAC_SHA1=y
+# CONFIG_SCTP_HMAC_MD5 is not set
 # CONFIG_ATM is not set
 CONFIG_VLAN_8021Q=m
 
@@ -351,6 +355,7 @@ CONFIG_NET_SCHED=y
 CONFIG_NET_SCH_CBQ=m
 CONFIG_NET_SCH_HTB=m
 CONFIG_NET_SCH_CSZ=m
+CONFIG_NET_SCH_HFSC=m
 CONFIG_NET_SCH_PRIO=m
 CONFIG_NET_SCH_RED=m
 CONFIG_NET_SCH_SFQ=m
@@ -617,6 +622,7 @@ CONFIG_E100=m
 CONFIG_FEALNX=m
 CONFIG_NATSEMI=m
 CONFIG_NE2K_PCI=m
+CONFIG_FORCEDETH=m
 # CONFIG_NE3210 is not set
 # CONFIG_ES3210 is not set
 # CONFIG_8139CP is not set
@@ -974,7 +980,6 @@ CONFIG_USB_PEGASUS=m
 CONFIG_USB_RTL8150=m
 CONFIG_USB_KAWETH=m
 CONFIG_USB_CATC=m
-CONFIG_USB_AX8817X=m
 CONFIG_USB_CDCETHER=m
 CONFIG_USB_USBNET=m
 
@@ -1034,13 +1039,19 @@ CONFIG_USB_LCD=m
 # Support for USB gadgets
 #
 CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_NET2280=y
+# CONFIG_USB_GADGET_GOKU is not set
+# CONFIG_USB_GADGET_CONTROLLER is not set
+CONFIG_USB_NET2280=y
+CONFIG_USB_GADGET_CONTROLLER=y
 
 #
-# USB Peripheral Controller Drivers
+# USB Gadget Drivers
 #
-# CONFIG_USB_GADGET_CONTROLLER is not set
-# CONFIG_USB_NET2280 is not set
-# CONFIG_USB_GADGET_CONTROLLER is not set
+# CONFIG_USB_ZERO is not set
+# CONFIG_USB_ETH is not set
+# CONFIG_USB_FILE_STORAGE is not set
+# CONFIG_USB_FILE_STORAGE_TEST is not set
 
 #
 # Bluetooth support
@@ -1084,6 +1095,7 @@ CONFIG_MAGIC_SYSRQ=y
 # CONFIG_DEBUG_SPINLOCK is not set
 # CONFIG_DEBUG_BUGVERBOSE is not set
 # CONFIG_DEBUG_DCFLUSH is not set
+# CONFIG_DEBUG_BOOTMEM is not set
 # CONFIG_STACK_DEBUG is not set
 CONFIG_LOG_BUF_SHIFT=0
 
@@ -1104,6 +1116,8 @@ CONFIG_CRYPTO_TWOFISH=m
 CONFIG_CRYPTO_SERPENT=m
 CONFIG_CRYPTO_AES=m
 CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_ARC4=m
 CONFIG_CRYPTO_DEFLATE=y
 # CONFIG_CRYPTO_TEST is not set
 
diff -Nur --show-c-function linux-2.4.25/arch/sparc64/kernel/sys_sunos32.c linux-2.4.26-pre2/arch/sparc64/kernel/sys_sunos32.c
--- linux-2.4.25/arch/sparc64/kernel/sys_sunos32.c	2003-11-28 16:26:19.000000000 -0200
+++ linux-2.4.26-pre2/arch/sparc64/kernel/sys_sunos32.c	2004-03-06 15:19:21.000000000 -0300
@@ -654,8 +654,8 @@ static int get_default (int value, int d
 /* XXXXXXXXXXXXXXXXXXXX */
 static int sunos_nfs_mount(char *dir_name, int linux_flags, void *data)
 {
-	int  server_fd;
-	char *the_name;
+	int  server_fd, err;
+	char *the_name, *mount_page;
 	struct nfs_mount_data linux_nfs_mount;
 	struct sunos_nfs_mount_args sunos_mount;
 
@@ -708,7 +708,16 @@ static int sunos_nfs_mount(char *dir_nam
 	linux_nfs_mount.hostname [255] = 0;
 	putname (the_name);
 	
-	return do_mount ("", dir_name, "nfs", linux_flags, &linux_nfs_mount);
+	mount_page = (char *) get_zeroed_page(GFP_KERNEL);
+	if (!mount_page)
+		return -ENOMEM;
+
+	memcpy(mount_page, &linux_nfs_mount, sizeof(linux_nfs_mount));
+
+	err = do_mount("", dir_name, "nfs", linux_flags, mount_page);
+
+	free_page((unsigned long) mount_page);
+	return err;
 }
 
 /* XXXXXXXXXXXXXXXXXXXX */
diff -Nur --show-c-function linux-2.4.25/arch/x86_64/kernel/acpi.c linux-2.4.26-pre2/arch/x86_64/kernel/acpi.c
--- linux-2.4.25/arch/x86_64/kernel/acpi.c	2004-02-18 10:36:31.000000000 -0300
+++ linux-2.4.26-pre2/arch/x86_64/kernel/acpi.c	2004-03-06 15:23:06.000000000 -0300
@@ -47,14 +47,14 @@
 
 #define PREFIX			"ACPI: "
 
-int acpi_lapic = 0;
-int acpi_ioapic = 0;
+int acpi_lapic;
+int acpi_ioapic;
+int acpi_strict;
 
 /* --------------------------------------------------------------------------
                               Boot-time Configuration
    -------------------------------------------------------------------------- */
 
-#ifdef CONFIG_ACPI_BOOT
 
 enum acpi_irq_model_id		acpi_irq_model;
 
@@ -296,7 +296,7 @@ acpi_parse_hpet (
  * programs the PIC-mode SCI to Level Trigger.
  * (NO-OP if the BIOS set Level Trigger already)
  *
- * If a PIC-mode SCI is not recogznied or gives spurious IRQ7's
+ * If a PIC-mode SCI is not recognized or gives spurious IRQ7's
  * it may require Edge Trigger -- use "acpi_pic_sci=edge"
  * (NO-OP if the BIOS set Edge Trigger already)
  *
@@ -567,8 +567,6 @@ acpi_boot_init (void)
 	return 0;
 }
 
-#endif /*CONFIG_ACPI_BOOT*/
-
 
 /* --------------------------------------------------------------------------
                               Low-Level Sleep Support
diff -Nur --show-c-function linux-2.4.25/arch/x86_64/kernel/e820.c linux-2.4.26-pre2/arch/x86_64/kernel/e820.c
--- linux-2.4.25/arch/x86_64/kernel/e820.c	2004-02-18 10:36:31.000000000 -0300
+++ linux-2.4.26-pre2/arch/x86_64/kernel/e820.c	2004-03-06 15:16:05.000000000 -0300
@@ -544,6 +544,12 @@ void __init parse_mem_cmdline (char ** c
 #ifdef	CONFIG_ACPI_BOOT
  		else if (!memcmp(from, "acpi=off", 8))
   			acpi_disabled = 1;
+
+		/* acpi=strict disables out-of-spec workarounds */
+		else if (!memcmp(from, "acpi=strict", 11)) {
+			acpi_strict = 1;
+		}
+
 		else if (!memcmp(from, "pci=noacpi", 10)) {
 			acpi_noirq_set();
 		}
diff -Nur --show-c-function linux-2.4.25/arch/x86_64/kernel/mpparse.c linux-2.4.26-pre2/arch/x86_64/kernel/mpparse.c
--- linux-2.4.25/arch/x86_64/kernel/mpparse.c	2003-11-28 16:26:19.000000000 -0200
+++ linux-2.4.26-pre2/arch/x86_64/kernel/mpparse.c	2004-03-06 15:15:49.000000000 -0300
@@ -794,7 +794,7 @@ void __init mp_override_legacy_irq (
 	 *      erroneously sets the trigger to level, resulting in a HUGE 
 	 *      increase of timer interrupts!
 	 */
-	if ((bus_irq == 0) && (global_irq == 2) && (trigger == 3))
+	if ((bus_irq == 0) && (trigger == 3))
 		trigger = 1;
 
 	intsrc.mpc_type = MP_INTSRC;
@@ -815,7 +815,7 @@ void __init mp_override_legacy_irq (
 	 * Otherwise create a new entry (e.g. global_irq == 2).
 	 */
 	for (i = 0; i < mp_irq_entries; i++) {
-		if ((mp_irqs[i].mpc_dstapic == intsrc.mpc_dstapic) 
+		if ((mp_irqs[i].mpc_srcbus == intsrc.mpc_srcbus) 
 			&& (mp_irqs[i].mpc_dstirq == intsrc.mpc_dstirq)) {
 			mp_irqs[i] = intsrc;
 			found = 1;
@@ -862,9 +862,10 @@ void __init mp_config_acpi_legacy_irqs (
 	 */
 	for (i = 0; i < 16; i++) {
 
-		if (i == 2) continue;			/* Don't connect IRQ2 */
+		if (i == 2)
+			continue;			/* Don't connect IRQ2 */
 
-		intsrc.mpc_irqtype = i ? mp_INT : mp_ExtINT;   /* 8259A to #0 */
+		intsrc.mpc_irqtype = mp_INT;
 		intsrc.mpc_srcbusirq = i;		   /* Identity mapped */
 		intsrc.mpc_dstirq = i;
 
@@ -1008,7 +1009,7 @@ void __init mp_parse_prt (void)
 			continue;
 		}
 		if ((1<<bit) & mp_ioapic_routing[ioapic].pin_programmed[idx]) {
-			printk(KERN_DEBUG "Pin %d-%d already programmed\n",
+			Dprintk(KERN_DEBUG "Pin %d-%d already programmed\n",
 				mp_ioapic_routing[ioapic].apic_id, ioapic_pin);
 			entry->irq = irq;
 			continue;
diff -Nur --show-c-function linux-2.4.25/crypto/arc4.c linux-2.4.26-pre2/crypto/arc4.c
--- linux-2.4.25/crypto/arc4.c	1969-12-31 21:00:00.000000000 -0300
+++ linux-2.4.26-pre2/crypto/arc4.c	2004-03-06 15:18:10.000000000 -0300
@@ -0,0 +1,106 @@
+/* 
+ * Cryptographic API
+ *
+ * ARC4 Cipher Algorithm
+ *
+ * Jon Oberheide <jon@focalhost.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ */
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/crypto.h>
+
+#define ARC4_MIN_KEY_SIZE	1
+#define ARC4_MAX_KEY_SIZE	256
+#define ARC4_BLOCK_SIZE		1
+
+struct arc4_ctx {
+	u8 S[256];
+	u8 x, y;
+};
+
+static int arc4_set_key(void *ctx_arg, const u8 *in_key, unsigned int key_len, u32 *flags)
+{
+	struct arc4_ctx *ctx = ctx_arg;
+	int i, j = 0, k = 0;
+
+	ctx->x = 1;
+	ctx->y = 0;
+
+	for(i = 0; i < 256; i++)
+		ctx->S[i] = i;
+
+	for(i = 0; i < 256; i++)
+	{
+		u8 a = ctx->S[i];
+		j = (j + in_key[k] + a) & 0xff;
+		ctx->S[i] = ctx->S[j];
+		ctx->S[j] = a;
+		if(++k >= key_len)
+			k = 0;
+	}
+
+	/* TODO: dump the first 768 bytes generated as recommended
+	   by Ilya Mironov (http://eprint.iacr.org/2002/067/) to 
+	   increase the statistical strength of the state table */
+
+	return 0;
+}
+
+static void arc4_crypt(void *ctx_arg, u8 *out, const u8 *in)
+{
+	struct arc4_ctx *ctx = ctx_arg;
+
+	u8 *const S = ctx->S;
+	u8 x = ctx->x;
+	u8 y = ctx->y;
+
+	u8 a = S[x];
+	y = (y + a) & 0xff;
+	u8 b = S[y];
+	S[x] = b;
+	S[y] = a;
+	x = (x + 1) & 0xff;
+	*out++ = *in ^ S[(a + b) & 0xff];
+
+	ctx->x = x;
+	ctx->y = y;
+}
+
+static struct crypto_alg arc4_alg = {
+	.cra_name		=	"arc4",
+	.cra_flags		=	CRYPTO_ALG_TYPE_CIPHER,
+	.cra_blocksize		=	ARC4_BLOCK_SIZE,
+	.cra_ctxsize		=	sizeof(struct arc4_ctx),
+	.cra_module		=	THIS_MODULE,
+	.cra_list		=	LIST_HEAD_INIT(arc4_alg.cra_list),
+	.cra_u			=	{ .cipher = {
+	.cia_min_keysize	=	ARC4_MIN_KEY_SIZE,
+	.cia_max_keysize	=	ARC4_MAX_KEY_SIZE,
+	.cia_setkey	   	= 	arc4_set_key,
+	.cia_encrypt	 	=	arc4_crypt,
+	.cia_decrypt	  	=	arc4_crypt } }
+};
+
+static int __init arc4_init(void)
+{
+	return crypto_register_alg(&arc4_alg);
+}
+
+
+static void __exit arc4_exit(void)
+{
+	crypto_unregister_alg(&arc4_alg);
+}
+
+module_init(arc4_init);
+module_exit(arc4_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("ARC4 Cipher Algorithm");
+MODULE_AUTHOR("Jon Oberheide <jon@focalhost.com>");
diff -Nur --show-c-function linux-2.4.25/crypto/cipher.c linux-2.4.26-pre2/crypto/cipher.c
--- linux-2.4.25/crypto/cipher.c	2004-02-18 10:36:31.000000000 -0300
+++ linux-2.4.26-pre2/crypto/cipher.c	2004-03-06 15:19:46.000000000 -0300
@@ -4,7 +4,6 @@
  * Cipher operations.
  *
  * Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
- * Generic scatterwalk code by Adam J. Richter <adam@yggdrasil.com>.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
@@ -17,30 +16,13 @@
 #include <linux/errno.h>
 #include <linux/mm.h>
 #include <linux/slab.h>
-#include <linux/pagemap.h>
-#include <linux/highmem.h>
 #include <asm/scatterlist.h>
 #include "internal.h"
+#include "scatterwalk.h"
 
 typedef void (cryptfn_t)(void *, u8 *, const u8 *);
 typedef void (procfn_t)(struct crypto_tfm *, u8 *,
-                        u8*, cryptfn_t, int enc, void *);
-
-struct scatter_walk {
-	struct scatterlist	*sg;
-	struct page		*page;
-	void			*data;
-	unsigned int		len_this_page;
-	unsigned int		len_this_segment;
-	unsigned int		offset;
-};
-
-enum km_type crypto_km_types[] = {
-	KM_USER0,
-	KM_USER1,
-	KM_SOFTIRQ0,
-	KM_SOFTIRQ1,
-};
+                        u8*, cryptfn_t, int enc, void *, int);
 
 static inline void xor_64(u8 *a, const u8 *b)
 {
@@ -57,108 +39,6 @@ static inline void xor_128(u8 *a, const 
 }
 
 
-/* Define sg_next is an inline routine now in case we want to change
-   scatterlist to a linked list later. */
-static inline struct scatterlist *sg_next(struct scatterlist *sg)
-{
-	return sg + 1;
-}
-
-void *which_buf(struct scatter_walk *walk, unsigned int nbytes, void *scratch)
-{
-	if (nbytes <= walk->len_this_page &&
-	    (((unsigned long)walk->data) & (PAGE_CACHE_SIZE - 1)) + nbytes <=
-	    PAGE_CACHE_SIZE)
-		return walk->data;
-	else
-		return scratch;
-}
-
-static void memcpy_dir(void *buf, void *sgdata, size_t nbytes, int out)
-{
-	if (out)
-		memcpy(sgdata, buf, nbytes);
-	else
-		memcpy(buf, sgdata, nbytes);
-}
-
-static void scatterwalk_start(struct scatter_walk *walk, struct scatterlist *sg)
-{
-	unsigned int rest_of_page;
-
-	walk->sg = sg;
-
-	walk->page = sg->page;
-	walk->len_this_segment = sg->length;
-
-	rest_of_page = PAGE_CACHE_SIZE - (sg->offset & (PAGE_CACHE_SIZE - 1));
-	walk->len_this_page = min(sg->length, rest_of_page);
-	walk->offset = sg->offset;
-}
-
-static void scatterwalk_map(struct scatter_walk *walk, int out)
-{
-	walk->data = crypto_kmap(walk->page, out) + walk->offset;
-}
-
-static void scatter_page_done(struct scatter_walk *walk, int out,
-			      unsigned int more)
-{
-	/* walk->data may be pointing the first byte of the next page;
-	   however, we know we transfered at least one byte.  So,
-	   walk->data - 1 will be a virutual address in the mapped page. */
-
-	if (out)
-		flush_dcache_page(walk->page);
-
-	if (more) {
-		walk->len_this_segment -= walk->len_this_page;
-
-		if (walk->len_this_segment) {
-			walk->page++;
-			walk->len_this_page = min(walk->len_this_segment,
-						  (unsigned)PAGE_CACHE_SIZE);
-			walk->offset = 0;
-		}
-		else
-			scatterwalk_start(walk, sg_next(walk->sg));
-	}
-}
-
-static void scatter_done(struct scatter_walk *walk, int out, int more)
-{
-	crypto_kunmap(walk->data, out);
-	if (walk->len_this_page == 0 || !more)
-		scatter_page_done(walk, out, more);
-}
-
-/*
- * Do not call this unless the total length of all of the fragments 
- * has been verified as multiple of the block size.
- */
-static int copy_chunks(void *buf, struct scatter_walk *walk,
-			size_t nbytes, int out)
-{
-	if (buf != walk->data) {
-		while (nbytes > walk->len_this_page) {
-			memcpy_dir(buf, walk->data, walk->len_this_page, out);
-			buf += walk->len_this_page;
-			nbytes -= walk->len_this_page;
-
-			crypto_kunmap(walk->data, out);
-			scatter_page_done(walk, out, 1);
-			scatterwalk_map(walk, out);
-		}
-
-		memcpy_dir(buf, walk->data, nbytes, out);
-	}
-
-	walk->offset += nbytes;
-	walk->len_this_page -= nbytes;
-	walk->len_this_segment -= nbytes;
-	return 0;
-}
-
 /* 
  * Generic encrypt/decrypt wrapper for ciphers, handles operations across
  * multiple page boundaries by using temporary blocks.  In user context,
@@ -191,19 +71,21 @@ static int crypt(struct crypto_tfm *tfm,
 
 		scatterwalk_map(&walk_in, 0);
 		scatterwalk_map(&walk_out, 1);
-		src_p = which_buf(&walk_in, bsize, tmp_src);
-		dst_p = which_buf(&walk_out, bsize, tmp_dst);
+		src_p = scatterwalk_whichbuf(&walk_in, bsize, tmp_src);
+		dst_p = scatterwalk_whichbuf(&walk_out, bsize, tmp_dst);
 
 		nbytes -= bsize;
 
-		copy_chunks(src_p, &walk_in, bsize, 0);
+		scatterwalk_copychunks(src_p, &walk_in, bsize, 0);
 
-		prfn(tfm, dst_p, src_p, crfn, enc, info);
+		prfn(tfm, dst_p, src_p, crfn, enc, info,
+		     scatterwalk_samebuf(&walk_in, &walk_out,
+					 src_p, dst_p));
 
-		scatter_done(&walk_in, 0, nbytes);
+		scatterwalk_done(&walk_in, 0, nbytes);
 
-		copy_chunks(dst_p, &walk_out, bsize, 1);
-		scatter_done(&walk_out, 1, nbytes);
+		scatterwalk_copychunks(dst_p, &walk_out, bsize, 1);
+		scatterwalk_done(&walk_out, 1, nbytes);
 
 		if (!nbytes)
 			return 0;
@@ -212,8 +94,8 @@ static int crypt(struct crypto_tfm *tfm,
 	}
 }
 
-static void cbc_process(struct crypto_tfm *tfm,
-                        u8 *dst, u8 *src, cryptfn_t fn, int enc, void *info)
+static void cbc_process(struct crypto_tfm *tfm, u8 *dst, u8 *src,
+			cryptfn_t fn, int enc, void *info, int in_place)
 {
 	u8 *iv = info;
 	
@@ -226,10 +108,9 @@ static void cbc_process(struct crypto_tf
 		fn(crypto_tfm_ctx(tfm), dst, iv);
 		memcpy(iv, dst, crypto_tfm_alg_blocksize(tfm));
 	} else {
-		const int need_stack = (src == dst);
-		u8 stack[need_stack ? crypto_tfm_alg_blocksize(tfm) : 0];
-		u8 *buf = need_stack ? stack : dst;
-		
+		u8 stack[in_place ? crypto_tfm_alg_blocksize(tfm) : 0];
+		u8 *buf = in_place ? stack : dst;
+
 		fn(crypto_tfm_ctx(tfm), buf, src);
 		tfm->crt_u.cipher.cit_xor_block(buf, iv);
 		memcpy(iv, src, crypto_tfm_alg_blocksize(tfm));
@@ -239,7 +120,7 @@ static void cbc_process(struct crypto_tf
 }
 
 static void ecb_process(struct crypto_tfm *tfm, u8 *dst, u8 *src,
-                        cryptfn_t fn, int enc, void *info)
+			cryptfn_t fn, int enc, void *info, int in_place)
 {
 	fn(crypto_tfm_ctx(tfm), dst, src);
 }
diff -Nur --show-c-function linux-2.4.25/crypto/Config.in linux-2.4.26-pre2/crypto/Config.in
--- linux-2.4.25/crypto/Config.in	2004-02-18 10:36:31.000000000 -0300
+++ linux-2.4.26-pre2/crypto/Config.in	2004-03-06 15:21:48.000000000 -0300
@@ -72,6 +72,7 @@ if [ "$CONFIG_CRYPTO" = "y" ]; then
   tristate       '  AES cipher algorithms' CONFIG_CRYPTO_AES
   tristate       '  CAST5 (CAST-128) cipher algorithm' CONFIG_CRYPTO_CAST5
   tristate       '  CAST6 (CAST-256) cipher algorithm' CONFIG_CRYPTO_CAST6
+  tristate       '  ARC4 cipher algorithm' CONFIG_CRYPTO_ARC4
   if [ "$CONFIG_INET_IPCOMP" = "y" -o \
        "$CONFIG_INET_IPCOMP" = "m" -o \
        "$CONFIG_INET6_IPCOMP" = "y" -o \
diff -Nur --show-c-function linux-2.4.25/crypto/internal.h linux-2.4.26-pre2/crypto/internal.h
--- linux-2.4.25/crypto/internal.h	2003-08-25 08:44:40.000000000 -0300
+++ linux-2.4.26-pre2/crypto/internal.h	2004-03-06 15:18:01.000000000 -0300
@@ -11,6 +11,7 @@
  */
 #ifndef _CRYPTO_INTERNAL_H
 #define _CRYPTO_INTERNAL_H
+#include <linux/crypto.h>
 #include <linux/mm.h>
 #include <linux/highmem.h>
 #include <linux/init.h>
diff -Nur --show-c-function linux-2.4.25/crypto/Makefile linux-2.4.26-pre2/crypto/Makefile
--- linux-2.4.25/crypto/Makefile	2004-02-18 10:36:31.000000000 -0300
+++ linux-2.4.26-pre2/crypto/Makefile	2004-03-06 15:15:20.000000000 -0300
@@ -9,7 +9,7 @@ export-objs := api.o hmac.o
 autoload-crypto-$(CONFIG_KMOD) = autoload.o
 proc-crypto-$(CONFIG_PROC_FS) = proc.o
 
-obj-$(CONFIG_CRYPTO) += api.o cipher.o digest.o compress.o \
+obj-$(CONFIG_CRYPTO) += api.o scatterwalk.o cipher.o digest.o compress.o \
 			$(autoload-crypto-y) $(proc-crypto-y)
 
 obj-$(CONFIG_CRYPTO_HMAC) += hmac.o
@@ -26,6 +26,7 @@ obj-$(CONFIG_CRYPTO_SERPENT) += serpent.
 obj-$(CONFIG_CRYPTO_AES) += aes.o
 obj-$(CONFIG_CRYPTO_CAST5) += cast5.o
 obj-$(CONFIG_CRYPTO_CAST6) += cast6.o
+obj-$(CONFIG_CRYPTO_ARC4) += arc4.o
 obj-$(CONFIG_CRYPTO_DEFLATE) += deflate.o
 
 obj-$(CONFIG_CRYPTO_TEST) += tcrypt.o
diff -Nur --show-c-function linux-2.4.25/crypto/scatterwalk.c linux-2.4.26-pre2/crypto/scatterwalk.c
--- linux-2.4.25/crypto/scatterwalk.c	1969-12-31 21:00:00.000000000 -0300
+++ linux-2.4.26-pre2/crypto/scatterwalk.c	2004-03-06 15:12:58.000000000 -0300
@@ -0,0 +1,124 @@
+/*
+ * Cryptographic API.
+ *
+ * Cipher operations.
+ *
+ * Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
+ *               2002 Adam J. Richter <adam@yggdrasil.com>
+ *               2004 Jean-Luc Cooke <jlcooke@certainkey.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ */
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/pagemap.h>
+#include <linux/highmem.h>
+#include <asm/scatterlist.h>
+#include "internal.h"
+#include "scatterwalk.h"
+
+enum km_type crypto_km_types[] = {
+	KM_USER0,
+	KM_USER1,
+	KM_SOFTIRQ0,
+	KM_SOFTIRQ1,
+};
+
+void *scatterwalk_whichbuf(struct scatter_walk *walk, unsigned int nbytes, void *scratch)
+{
+	if (nbytes <= walk->len_this_page &&
+	    (((unsigned long)walk->data) & (PAGE_CACHE_SIZE - 1)) + nbytes <=
+	    PAGE_CACHE_SIZE)
+		return walk->data;
+	else
+		return scratch;
+}
+
+static void memcpy_dir(void *buf, void *sgdata, size_t nbytes, int out)
+{
+	if (out)
+		memcpy(sgdata, buf, nbytes);
+	else
+		memcpy(buf, sgdata, nbytes);
+}
+
+void scatterwalk_start(struct scatter_walk *walk, struct scatterlist *sg)
+{
+	unsigned int rest_of_page;
+
+	walk->sg = sg;
+
+	walk->page = sg->page;
+	walk->len_this_segment = sg->length;
+
+	rest_of_page = PAGE_CACHE_SIZE - (sg->offset & (PAGE_CACHE_SIZE - 1));
+	walk->len_this_page = min(sg->length, rest_of_page);
+	walk->offset = sg->offset;
+}
+
+void scatterwalk_map(struct scatter_walk *walk, int out)
+{
+	walk->data = crypto_kmap(walk->page, out) + walk->offset;
+}
+
+static void scatterwalk_pagedone(struct scatter_walk *walk, int out,
+				 unsigned int more)
+{
+	/* walk->data may be pointing the first byte of the next page;
+	   however, we know we transfered at least one byte.  So,
+	   walk->data - 1 will be a virutual address in the mapped page. */
+
+	if (out)
+		flush_dcache_page(walk->page);
+
+	if (more) {
+		walk->len_this_segment -= walk->len_this_page;
+
+		if (walk->len_this_segment) {
+			walk->page++;
+			walk->len_this_page = min(walk->len_this_segment,
+						  (unsigned)PAGE_CACHE_SIZE);
+			walk->offset = 0;
+		}
+		else
+			scatterwalk_start(walk, sg_next(walk->sg));
+	}
+}
+
+void scatterwalk_done(struct scatter_walk *walk, int out, int more)
+{
+	crypto_kunmap(walk->data, out);
+	if (walk->len_this_page == 0 || !more)
+		scatterwalk_pagedone(walk, out, more);
+}
+
+/*
+ * Do not call this unless the total length of all of the fragments
+ * has been verified as multiple of the block size.
+ */
+int scatterwalk_copychunks(void *buf, struct scatter_walk *walk,
+			   size_t nbytes, int out)
+{
+	if (buf != walk->data) {
+		while (nbytes > walk->len_this_page) {
+			memcpy_dir(buf, walk->data, walk->len_this_page, out);
+			buf += walk->len_this_page;
+			nbytes -= walk->len_this_page;
+
+			crypto_kunmap(walk->data, out);
+			scatterwalk_pagedone(walk, out, 1);
+			scatterwalk_map(walk, out);
+		}
+
+		memcpy_dir(buf, walk->data, nbytes, out);
+	}
+
+	walk->offset += nbytes;
+	walk->len_this_page -= nbytes;
+	walk->len_this_segment -= nbytes;
+	return 0;
+}
diff -Nur --show-c-function linux-2.4.25/crypto/scatterwalk.h linux-2.4.26-pre2/crypto/scatterwalk.h
--- linux-2.4.25/crypto/scatterwalk.h	1969-12-31 21:00:00.000000000 -0300
+++ linux-2.4.26-pre2/crypto/scatterwalk.h	2004-03-06 15:17:43.000000000 -0300
@@ -0,0 +1,50 @@
+/*
+ * Cryptographic API.
+ *
+ * Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
+ * Copyright (c) 2002 Adam J. Richter <adam@yggdrasil.com>
+ * Copyright (c) 2004 Jean-Luc Cooke <jlcooke@certainkey.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ */
+
+#ifndef _CRYPTO_SCATTERWALK_H
+#define _CRYPTO_SCATTERWALK_H
+#include <linux/mm.h>
+#include <asm/scatterlist.h>
+
+struct scatter_walk {
+	struct scatterlist	*sg;
+	struct page		*page;
+	void			*data;
+	unsigned int		len_this_page;
+	unsigned int		len_this_segment;
+	unsigned int		offset;
+};
+
+/* Define sg_next is an inline routine now in case we want to change
+   scatterlist to a linked list later. */
+static inline struct scatterlist *sg_next(struct scatterlist *sg)
+{
+	return sg + 1;
+}
+
+static inline int scatterwalk_samebuf(struct scatter_walk *walk_in,
+				      struct scatter_walk *walk_out,
+				      void *src_p, void *dst_p)
+{
+	return walk_in->page == walk_out->page &&
+	       walk_in->data == src_p && walk_out->data == dst_p;
+}
+
+void *scatterwalk_whichbuf(struct scatter_walk *walk, unsigned int nbytes, void *scratch);
+void scatterwalk_start(struct scatter_walk *walk, struct scatterlist *sg);
+int scatterwalk_copychunks(void *buf, struct scatter_walk *walk, size_t nbytes, int out);
+void scatterwalk_map(struct scatter_walk *walk, int out);
+void scatterwalk_done(struct scatter_walk *walk, int out, int more);
+
+#endif  /* _CRYPTO_SCATTERWALK_H */
diff -Nur --show-c-function linux-2.4.25/crypto/tcrypt.c linux-2.4.26-pre2/crypto/tcrypt.c
--- linux-2.4.25/crypto/tcrypt.c	2004-02-18 10:36:31.000000000 -0300
+++ linux-2.4.26-pre2/crypto/tcrypt.c	2004-03-06 15:19:34.000000000 -0300
@@ -63,7 +63,7 @@ static char *tvmem;
 static char *check[] = {
 	"des", "md5", "des3_ede", "rot13", "sha1", "sha256", "blowfish",
 	"twofish", "serpent", "sha384", "sha512", "md4", "aes", "cast6", 
-	"deflate", NULL
+	"arc4", "deflate", NULL
 };
 
 static void
@@ -558,6 +558,10 @@ do_test(void)
 		test_cipher ("cast6", MODE_ECB, ENCRYPT, cast6_enc_tv_template, CAST6_ENC_TEST_VECTORS);
 		test_cipher ("cast6", MODE_ECB, DECRYPT, cast6_dec_tv_template, CAST6_DEC_TEST_VECTORS);
 
+		//ARC4
+		test_cipher ("arc4", MODE_ECB, ENCRYPT, arc4_enc_tv_template, ARC4_ENC_TEST_VECTORS);
+		test_cipher ("arc4", MODE_ECB, DECRYPT, arc4_dec_tv_template, ARC4_DEC_TEST_VECTORS);
+
 		test_hash("sha384", sha384_tv_template, SHA384_TEST_VECTORS);
 		test_hash("sha512", sha512_tv_template, SHA512_TEST_VECTORS);
 		test_deflate();		
@@ -640,6 +644,11 @@ do_test(void)
 		test_cipher ("cast6", MODE_ECB, DECRYPT, cast6_dec_tv_template, CAST6_DEC_TEST_VECTORS);
 		break;
 
+	case 16:
+		test_cipher ("arc4", MODE_ECB, ENCRYPT, arc4_enc_tv_template, ARC4_ENC_TEST_VECTORS);
+		test_cipher ("arc4", MODE_ECB, DECRYPT, arc4_dec_tv_template, ARC4_DEC_TEST_VECTORS);
+		break;
+
 #ifdef CONFIG_CRYPTO_HMAC
 	case 100:
 		test_hmac("md5", hmac_md5_tv_template, HMAC_MD5_TEST_VECTORS);
diff -Nur --show-c-function linux-2.4.25/crypto/tcrypt.h linux-2.4.26-pre2/crypto/tcrypt.h
--- linux-2.4.25/crypto/tcrypt.h	2004-02-18 10:36:31.000000000 -0300
+++ linux-2.4.26-pre2/crypto/tcrypt.h	2004-03-06 15:23:09.000000000 -0300
@@ -1488,6 +1488,147 @@ struct cipher_testvec cast5_dec_tv_templ
 	},
 };
 
+/* 
+ * ARC4 test vectors from OpenSSL 
+ */
+#define ARC4_ENC_TEST_VECTORS	7
+#define ARC4_DEC_TEST_VECTORS	7
+
+struct cipher_testvec arc4_enc_tv_template[] =
+{
+	{
+		.key	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
+		.klen	= 8,
+		.input	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
+		.ilen	= 8,
+		.result	= { 0x75, 0xb7, 0x87, 0x80, 0x99, 0xe0, 0xc5, 0x96 },
+		.rlen	= 8,
+	}, {
+		.key	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
+		.klen	= 8,
+		.input	= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+		.ilen	= 8,
+		.result	= { 0x74, 0x94, 0xc2, 0xe7, 0x10, 0x4b, 0x08, 0x79 },
+		.rlen	= 8,
+	}, {
+		.key	= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+		.klen	= 8,
+		.input	= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+		.ilen	= 8,
+		.result	= { 0xde, 0x18, 0x89, 0x41, 0xa3, 0x37, 0x5d, 0x3a },
+		.rlen	= 8,
+	}, {
+		.key	= { 0xef, 0x01, 0x23, 0x45},
+		.klen	= 4,
+		.input	= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			    0x00, 0x00, 0x00, 0x00 },
+		.ilen	= 20,
+		.result	= { 0xd6, 0xa1, 0x41, 0xa7, 0xec, 0x3c, 0x38, 0xdf,
+			    0xbd, 0x61, 0x5a, 0x11, 0x62, 0xe1, 0xc7, 0xba,
+			    0x36, 0xb6, 0x78, 0x58 },
+		.rlen	= 20,
+	}, {
+		.key	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
+		.klen	= 8,
+		.input	= { 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0,
+			    0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0,
+			    0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0,
+			    0x12, 0x34, 0x56, 0x78 },
+		.ilen	= 28,
+		.result	= { 0x66, 0xa0, 0x94, 0x9f, 0x8a, 0xf7, 0xd6, 0x89,
+			    0x1f, 0x7f, 0x83, 0x2b, 0xa8, 0x33, 0xc0, 0x0c,
+			    0x89, 0x2e, 0xbe, 0x30, 0x14, 0x3c, 0xe2, 0x87,
+			    0x40, 0x01, 0x1e, 0xcf },
+		.rlen	= 28,
+	}, {
+		.key	= { 0xef, 0x01, 0x23, 0x45 },
+		.klen	= 4,
+		.input	= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			    0x00, 0x00 },
+		.ilen	= 10,
+		.result	= { 0xd6, 0xa1, 0x41, 0xa7, 0xec, 0x3c, 0x38, 0xdf,
+			    0xbd, 0x61 },
+		.rlen	= 10,
+	}, {
+		.key	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF,
+		            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+		.klen	= 16,
+		.input	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF },
+		.ilen	= 8,
+		.result	= { 0x69, 0x72, 0x36, 0x59, 0x1B, 0x52, 0x42, 0xB1 },
+		.rlen	= 8,
+	},
+};
+
+struct cipher_testvec arc4_dec_tv_template[] =
+{
+	{
+		.key	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
+		.klen	= 8,
+		.input	= { 0x75, 0xb7, 0x87, 0x80, 0x99, 0xe0, 0xc5, 0x96 },
+		.ilen	= 8,
+		.result	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
+		.rlen	= 8,
+	}, {
+		.key	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
+		.klen	= 8,
+		.input	= { 0x74, 0x94, 0xc2, 0xe7, 0x10, 0x4b, 0x08, 0x79 },
+		.ilen	= 8,
+		.result	= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+		.rlen	= 8,
+	}, {
+		.key	= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+		.klen	= 8,
+		.input	= { 0xde, 0x18, 0x89, 0x41, 0xa3, 0x37, 0x5d, 0x3a },
+		.ilen	= 8,
+		.result	= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+		.rlen	= 8,
+	}, {
+		.key	= { 0xef, 0x01, 0x23, 0x45},
+		.klen	= 4,
+		.input	= { 0xd6, 0xa1, 0x41, 0xa7, 0xec, 0x3c, 0x38, 0xdf,
+			    0xbd, 0x61, 0x5a, 0x11, 0x62, 0xe1, 0xc7, 0xba,
+			    0x36, 0xb6, 0x78, 0x58 },
+		.ilen	= 20,
+		.result	= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			    0x00, 0x00, 0x00, 0x00 },
+		.rlen	= 20,
+	}, {
+		.key	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
+		.klen	= 8,
+		.input	= { 0x66, 0xa0, 0x94, 0x9f, 0x8a, 0xf7, 0xd6, 0x89,
+			    0x1f, 0x7f, 0x83, 0x2b, 0xa8, 0x33, 0xc0, 0x0c,
+			    0x89, 0x2e, 0xbe, 0x30, 0x14, 0x3c, 0xe2, 0x87,
+			    0x40, 0x01, 0x1e, 0xcf },
+		.ilen	= 28,
+		.result	= { 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0,
+			    0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0,
+			    0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0,
+			    0x12, 0x34, 0x56, 0x78 },
+		.rlen	= 28,
+	}, {
+		.key	= { 0xef, 0x01, 0x23, 0x45 },
+		.klen	= 4,
+		.input	= { 0xd6, 0xa1, 0x41, 0xa7, 0xec, 0x3c, 0x38, 0xdf,
+			    0xbd, 0x61 },
+		.ilen	= 10,
+		.result	= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			    0x00, 0x00 },
+		.rlen	= 10,
+	}, {
+		.key	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF,
+		            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+		.klen	= 16,
+		.input	= { 0x69, 0x72, 0x36, 0x59, 0x1B, 0x52, 0x42, 0xB1 },
+		.ilen	= 8,
+		.result	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF },
+		.rlen	= 8,
+	},
+};
+
+
 /*
  * Compression stuff.
  */
diff -Nur --show-c-function linux-2.4.25/Documentation/Configure.help linux-2.4.26-pre2/Documentation/Configure.help
--- linux-2.4.25/Documentation/Configure.help	2004-02-18 10:36:30.000000000 -0300
+++ linux-2.4.26-pre2/Documentation/Configure.help	2004-03-06 15:22:36.000000000 -0300
@@ -6206,17 +6206,6 @@ CONFIG_IP_SCTP
 
   If in doubt, say N.
 
-SCTP: Use old checksum (Adler-32)
-CONFIG_SCTP_ADLER32
-  RCF2960 currently specifies the Adler-32 checksum algorithm for SCTP.
-  This has been deprecated and replaced by an algorithm now referred
-  to as crc32c.
-
-  If you say Y, this will use the Adler-32 algorithm, this might be 
-  useful for interoperation with downlevel peers. 
-
-  If unsure, say N.  
-
 SCTP: Debug messages
 CONFIG_SCTP_DBG_MSG
   If you say Y, this will enable verbose debugging messages. 
@@ -6234,6 +6223,29 @@ CONFIG_SCTP_DBG_OBJCNT
 
   If unsure, say N
 
+#choice
+SCTP: HMAC algorithm
+CONFIG_SCTP_HMAC_NONE
+  Choose an HMAC algorithm to be used during association establishment.
+  It can be one of SHA1, MD5 or NONE. It is advised to use either HMAC-MD5
+  or HMAC-SHA1.
+  See configuration for Cryptographic API and enable these algorithms
+  to make usable by SCTP.
+
+SCTP: SHA1 HMAC algorithm
+CONFIG_SCTP_HMAC_SHA1
+  Enable the use of HMAC-SHA1 during association establishment.  It 
+  is advised to use either HMAC-MD5 or HMAC-SHA1.
+  See configuration for Cryptographic API and enable these algorithms
+  to make usable by SCTP.
+
+SCTP: MD5 HMAC algorithm
+config SCTP_HMAC_MD5
+  Enable the use of HMAC-MD5 during association establishment.  It is 
+  advised to use either HMAC-MD5 or HMAC-SHA1.
+  See configuration for Cryptographic API and enable these algorithms
+  to make usable by SCTP.
+
 Kernel httpd acceleration
 CONFIG_KHTTPD
   The kernel httpd acceleration daemon (kHTTPd) is a (limited) web
@@ -10237,6 +10249,19 @@ CONFIG_AIRO_CS
   say M here and read <file:Documentation/modules.txt>.  The module
   will be called airo_cs.o.
 
+Atmel at76c502/at76c504 PCMCIA cards
+CONFIG_PCMCIA_ATMEL
+  A driver for PCMCIA 802.11 wireless cards based on the 
+  Atmel fast-vnet chips. This driver supports standard
+  Linux wireless extensions. 
+
+  Many  cards based on this chipset do not have flash memory
+  and need their firmware loaded at start-up. If yours is 
+  one of these, you will need to provide a firmware image
+  to be loaded into the card by the driver. The Atmel
+  firmware package can be downloaded from
+  http://www.thekelleys.org.uk/atmel/atmel_firmware.tar.gz
+
 Aviator/Raytheon 2.4MHz wireless support
 CONFIG_PCMCIA_RAYCS
   Say Y here if you intend to attach an Aviator/Raytheon PCMCIA
@@ -12358,6 +12383,16 @@ CONFIG_B44
   <file:Documentation/networking/net-modules.txt>.  The module will be
   called b44.
 
+nForce Ethernet support (EXPERIMENTAL)
+CONFIG_FORCEDETH
+  If you have a network (Ethernet) controller of this type, say Y and
+  read the Ethernet-HOWTO, available from
+  <http://www.tldp.org/docs.html#howto>.
+
+  To compile this driver as a module, choose M here and read
+  <file:Documentation/networking/net-modules.txt>.  The module will be
+  called forcedeth.o.
+
 CS89x0 support (Daynaport CS and LC cards)
 CONFIG_CS89x0
   Support for CS89x0 chipset based Ethernet cards. If you have a
@@ -19919,14 +19954,6 @@ CONFIG_ACPI_DEBUG
   of verbosity. Saying Y enables these statements. This will increase
   your kernel size by around 50K.
 
-ACPI Relaxed AML Checking
-CONFIG_ACPI_RELAXED_AML
-  If you say `Y' here, the ACPI interpreter will relax its checking
-  for valid AML and will ignore some AML mistakes, such as off-by-one
-  errors in region sizes.  Some laptops may require this option.  In
-  particular, many Toshiba laptops require this for correct operation
-  of the AC module.
-
 ACPI Button
 CONFIG_ACPI_BUTTON
   This driver registers for events based on buttons, such as the
@@ -28701,6 +28728,13 @@ CONFIG_CRYPTO_CAST6
   The CAST6 encryption algorithm (synonymous with CAST-256) is
   described in RFC2612.
 
+CONFIG_CRYPTO_ARC4
+  ARC4 cipher algorithm.
+  
+  This is a stream cipher using keys ranging from 8 bits to 2048
+  bits in length.  ARC4 is commonly used in protocols such as WEP 
+  and SSL.
+
 CONFIG_CRYPTO_DEFLATE
   This is the Deflate algorithm (RFC1951), specified for use in
   IPSec with the IPCOMP protocol (RFC3173, RFC2394).
diff -Nur --show-c-function linux-2.4.25/Documentation/crypto/api-intro.txt linux-2.4.26-pre2/Documentation/crypto/api-intro.txt
--- linux-2.4.25/Documentation/crypto/api-intro.txt	2004-02-18 10:36:30.000000000 -0300
+++ linux-2.4.26-pre2/Documentation/crypto/api-intro.txt	2004-03-06 15:23:53.000000000 -0300
@@ -185,6 +185,8 @@ Original developers of the crypto algori
   Matthew Skala (Twofish)
   Dag Arne Osvik (Serpent)
   Brian Gladman (AES)
+  Kartikey Mahendra Bhatt (CAST6)
+  Jon Oberheide (ARC4)
 
 SHA1 algorithm contributors:
   Jean-Francois Dive
diff -Nur --show-c-function linux-2.4.25/Documentation/kernel-parameters.txt linux-2.4.26-pre2/Documentation/kernel-parameters.txt
--- linux-2.4.25/Documentation/kernel-parameters.txt	2003-11-28 16:26:19.000000000 -0200
+++ linux-2.4.26-pre2/Documentation/kernel-parameters.txt	2004-03-06 15:24:20.000000000 -0300
@@ -73,6 +73,8 @@ running once the system is up.
 		off	Disable ACPI
 		ht	Limit ACPI to boot-time LAPIC enumeration for HT,
 			disabling the run-time AML interpreter.
+		strict	Be less tolerant of platforms that are not
+			strictly ACPI specification compliant.
 
 	acpi_pic_sci=	[HW,ACPI] ACPI System Conrol Interrupt trigger mode
 		level	Force PIC-mode SCI to Level Trigger (default)
diff -Nur --show-c-function linux-2.4.25/Documentation/networking/bonding.txt linux-2.4.26-pre2/Documentation/networking/bonding.txt
--- linux-2.4.25/Documentation/networking/bonding.txt	2003-11-28 16:26:19.000000000 -0200
+++ linux-2.4.26-pre2/Documentation/networking/bonding.txt	2004-03-06 15:15:25.000000000 -0300
@@ -21,7 +21,7 @@ userspace tools, please follow the links
 
 Table of Contents
 =================
- 
+
 Installation
 Bond Configuration
 Module Parameters
@@ -31,6 +31,7 @@ Verifying Bond Configuration
 Frequently Asked Questions
 High Availability
 Promiscuous Sniffing notes
+8021q VLAN support
 Limitations
 Resources and Links
 
@@ -66,7 +67,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 +75,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 +114,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 +129,26 @@ 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 
-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 +186,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 +199,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 +220,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 +244,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 +255,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 +270,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 +290,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 +314,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 +324,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 +360,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 +380,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 +512,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 +533,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 +588,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.
@@ -615,15 +598,15 @@ Frequently Asked Questions
 	For ethernet cards not supporting MII status, the arp_interval and
         arp_ip_target parameters must be specified for bonding to work
         correctly. If packets have not been sent or received during the
-        specified arp_interval durration, an ARP request is sent to the
+        specified arp_interval duration, an ARP request is sent to the
         targets to generate send and receive traffic. If after this
         interval, either the successful send and/or receive count has not
         incremented, the next slave in the sequence will become the active
         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 +619,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 +629,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,32 +650,24 @@ 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
-	example) and reload them to get the MAC addresses from their
-	eeproms. If the driver is shared by several devices, you need
-	to turn them all down. Another solution is to look for the MAC
-	address at boot time (dmesg or tail /var/log/messages) and to
-	reset it by hand with ifconfig :
 
-	  # ifconfig eth0 down
-	  # ifconfig eth0 hw ether 00:20:40:60:80:A0
+	To restore your slaves' MAC addresses, you need to detach them
+	from the bond (`ifenslave -d bond0 eth0'). The bonding driver will then
+	restore the MAC addresses that the slaves had before they were enslaved.
 
 9.  Which transmit polices can be used?
 
@@ -729,27 +704,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 +736,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 +786,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
@@ -857,7 +832,7 @@ point of failure" solution.
 
 In this configuration, there is an ISL - Inter Switch Link (could be a trunk),
 several servers (host1, host2 ...) attached to both switches each, and one or
-more ports to the outside world (port3...). One an only one slave on each host
+more ports to the outside world (port3...). One and only one slave on each host
 is active at a time, while all links are still monitored (the system can
 detect a failure of active and backup links).
 
@@ -870,10 +845,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).
 
 
           +----------+                          +----------+
@@ -947,6 +922,41 @@ capacity aggregating; but it works fine 
 just ignore all the warnings it emits.
 
 
+8021q VLAN support
+==================
+
+It is possible to configure VLAN devices over a bond interface using the 8021q
+driver. However, only packets coming from the 8021q driver and passing through
+bonding will be tagged by default. Self generated packets, like bonding's
+learning packets or ARP packets generated by either ALB mode or the ARP
+monitor mechanism, are tagged internally by bonding itself. As a result,
+bonding has to "learn" what VLAN IDs are configured on top of it, and it uses
+those IDs to tag self generated packets.
+
+For simplicity reasons, and to support the use of adapters that can do VLAN
+hardware acceleration offloding, the bonding interface declares itself as
+fully hardware offloaing capable, it gets the add_vid/kill_vid notifications
+to gather the necessary information, and it propagates those actions to the
+slaves.
+In case of mixed adapter types, hardware accelerated tagged packets that should
+go through an adapter that is not offloading capable are "un-accelerated" by the
+bonding driver so the VLAN tag sits in the regular location.
+
+VLAN interfaces *must* be added on top of a bonding interface only after
+enslaving at least one slave. This is because until the first slave is added the
+bonding interface has a HW address of 00:00:00:00:00:00, which will be copied by
+the VLAN interface when it is created.
+
+Notice that a problem would occur if all slaves are released from a bond that
+still has VLAN interfaces on top of it. When later coming to add new slaves, the
+bonding interface would get a HW address from the first slave, which might not
+match that of the VLAN interfaces. It is recommended that either all VLANs are
+removed and then re-added, or to manually set the bonding interface's HW
+address so it matches the VLAN's. (Note: changing a VLAN interface's HW address
+would set the underlying device -- i.e. the bonding interface -- to promiscouos
+mode, which might not be what you want).
+
+
 Limitations
 ===========
 The main limitations are :
@@ -957,7 +967,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.
 
 
 
diff -Nur --show-c-function linux-2.4.25/Documentation/networking/ifenslave.c linux-2.4.26-pre2/Documentation/networking/ifenslave.c
--- linux-2.4.25/Documentation/networking/ifenslave.c	2003-11-28 16:26:19.000000000 -0200
+++ linux-2.4.26-pre2/Documentation/networking/ifenslave.c	2004-03-06 15:14:29.000000000 -0300
@@ -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 <N>] > ...
- *
  * Author:	Donald Becker <becker@cesdis.gsfc.nasa.gov>
  *		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/12/01 - Shmulik Hen <shmulik.hen at intel dot com>
+ *	 - 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	"December 1, 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] <master-interface> < <slave-if> [metric <N>] > ...\n"
-"       ifenslave -c master-interface slave-if\n";
+"Usage: ifenslave [-f] <master-if> <slave-if> [<slave-if>...]\n"
+"       ifenslave -d   <master-if> <slave-if> [<slave-if>...]\n"
+"       ifenslave -c   <master-if> <slave-if>\n"
+"       ifenslave --help\n";
 
-static const char *howto_msg =
-"Usage: ifenslave [-adfrvVh] <master-interface> < <slave-if> [metric <N>] > ...\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 <addr> netmask <mask> broadcast <bcast>\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 <unistd.h>
@@ -153,476 +171,332 @@ typedef __uint8_t u8;		/* ditto */
 #include <linux/ethtool.h>
 
 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 -Nur --show-c-function linux-2.4.25/Documentation/networking/ip-sysctl.txt linux-2.4.26-pre2/Documentation/networking/ip-sysctl.txt
--- linux-2.4.25/Documentation/networking/ip-sysctl.txt	2003-06-13 11:51:29.000000000 -0300
+++ linux-2.4.26-pre2/Documentation/networking/ip-sysctl.txt	2004-03-06 15:17:10.000000000 -0300
@@ -481,6 +481,55 @@ arp_filter - BOOLEAN
 	conf/{all,interface}/arp_filter is set to TRUE,
 	it will be disabled otherwise
 
+arp_announce - INTEGER
+	Define different restriction levels for announcing the local
+	source IP address from IP packets in ARP requests sent on
+	interface:
+	0 - (default) Use any local address, configured on any interface
+	1 - Try to avoid local addresses that are not in the target's
+	subnet for this interface. This mode is useful when target
+	hosts reachable via this interface require the source IP
+	address in ARP requests to be part of their logical network
+	configured on the receiving interface. When we generate the
+	request we will check all our subnets that include the
+	target IP and will preserve the source address if it is from
+	such subnet. If there is no such subnet we select source
+	address according to the rules for level 2.
+	2 - Always use the best local address for this target.
+	In this mode we ignore the source address in the IP packet
+	and try to select local address that we prefer for talks with
+	the target host. Such local address is selected by looking
+	for primary IP addresses on all our subnets on the outgoing
+	interface that include the target IP address. If no suitable
+	local address is found we select the first local address
+	we have on the outgoing interface or on all other interfaces,
+	with the hope we will receive reply for our request and
+	even sometimes no matter the source IP address we announce.
+
+	The max value from conf/{all,interface}/arp_announce is used.
+
+	Increasing the restriction level gives more chance for
+	receiving answer from the resolved target while decreasing
+	the level announces more valid sender's information.
+
+arp_ignore - INTEGER
+	Define different modes for sending replies in response to
+	received ARP requests that resolve local target IP addresses:
+	0 - (default): reply for any local target IP address, configured
+	on any interface
+	1 - reply only if the target IP address is local address
+	configured on the incoming interface
+	2 - reply only if the target IP address is local address
+	configured on the incoming interface and both with the
+	sender's IP address are part from same subnet on this interface
+	3 - do not reply for local addresses configured with scope host,
+	only resolutions for global and link addresses are replied
+	4-7 - reserved
+	8 - do not reply for all local addresses
+
+	The max value from conf/{all,interface}/arp_ignore is used
+	when ARP request is received on the {interface}
+
 tag - INTEGER
 	Allows you to write a number, which can be used as required.
 	Default value is 0.
diff -Nur --show-c-function linux-2.4.25/drivers/acpi/Config.in linux-2.4.26-pre2/drivers/acpi/Config.in
--- linux-2.4.25/drivers/acpi/Config.in	2004-02-18 10:36:31.000000000 -0300
+++ linux-2.4.26-pre2/drivers/acpi/Config.in	2004-03-06 15:21:30.000000000 -0300
@@ -25,9 +25,6 @@ if [ "$CONFIG_X86" = "y" ]; then
     tristate     '  Fan'		CONFIG_ACPI_FAN
     tristate     '  Processor'	CONFIG_ACPI_PROCESSOR
     dep_tristate '  Thermal Zone' 	CONFIG_ACPI_THERMAL $CONFIG_ACPI_PROCESSOR
-    if [ "$CONFIG_NUMA" = "y" -a "$CONFIG_X86_64" != "y" ]; then
-      dep_bool       '  NUMA support'     CONFIG_ACPI_NUMA $CONFIG_NUMA
-    fi
     tristate     '  ASUS Laptop Extras'  CONFIG_ACPI_ASUS
     tristate     '  Toshiba Laptop Extras'	CONFIG_ACPI_TOSHIBA
     bool         '  Debug Statements'	CONFIG_ACPI_DEBUG
diff -Nur --show-c-function linux-2.4.25/drivers/acpi/dispatcher/dsmthdat.c linux-2.4.26-pre2/drivers/acpi/dispatcher/dsmthdat.c
--- linux-2.4.25/drivers/acpi/dispatcher/dsmthdat.c	2004-02-18 10:36:31.000000000 -0300
+++ linux-2.4.26-pre2/drivers/acpi/dispatcher/dsmthdat.c	2004-03-06 15:16:21.000000000 -0300
@@ -206,8 +206,7 @@ acpi_ds_method_data_init_args (
 		 * Store the argument in the method/walk descriptor.
 		 * Do not copy the arg in order to implement call by reference
 		 */
-		status = acpi_ds_method_data_set_value (AML_ARG_OP, index, params[index],
-				 walk_state);
+		status = acpi_ds_method_data_set_value (AML_ARG_OP, index, params[index], walk_state);
 		if (ACPI_FAILURE (status)) {
 			return_ACPI_STATUS (status);
 		}
@@ -465,6 +464,7 @@ acpi_ds_method_data_get_value (
 			return_ACPI_STATUS (AE_AML_UNINITIALIZED_LOCAL);
 
 		default:
+			ACPI_REPORT_ERROR (("Not Arg/Local opcode: %X\n", opcode));
 			return_ACPI_STATUS (AE_AML_INTERNAL);
 		}
 	}
@@ -597,7 +597,10 @@ acpi_ds_store_object_to_local (
 
 	/*
 	 * If the reference count on the object is more than one, we must
-	 * take a copy of the object before we store.
+	 * take a copy of the object before we store.  A reference count
+	 * of exactly 1 means that the object was just created during the
+	 * evaluation of an expression, and we can safely use it since it
+	 * is not used anywhere else.
 	 */
 	new_obj_desc = obj_desc;
 	if (obj_desc->common.reference_count > 1) {
diff -Nur --show-c-function linux-2.4.25/drivers/acpi/dispatcher/dsobject.c linux-2.4.26-pre2/drivers/acpi/dispatcher/dsobject.c
--- linux-2.4.25/drivers/acpi/dispatcher/dsobject.c	2004-02-18 10:36:31.000000000 -0300
+++ linux-2.4.26-pre2/drivers/acpi/dispatcher/dsobject.c	2004-03-06 15:13:14.000000000 -0300
@@ -582,6 +582,11 @@ acpi_ds_init_object_from_op (
 
 			obj_desc->reference.opcode = AML_ARG_OP;
 			obj_desc->reference.offset = opcode - AML_ARG_OP;
+
+#ifndef ACPI_NO_METHOD_EXECUTION
+			status = acpi_ds_method_data_get_node (AML_ARG_OP, obj_desc->reference.offset,
+					 walk_state, (struct acpi_namespace_node **) &obj_desc->reference.object);
+#endif
 			break;
 
 		default: /* Other literals, etc.. */
diff -Nur --show-c-function linux-2.4.25/drivers/acpi/dispatcher/dsopcode.c linux-2.4.26-pre2/drivers/acpi/dispatcher/dsopcode.c
--- linux-2.4.25/drivers/acpi/dispatcher/dsopcode.c	2004-02-18 10:36:31.000000000 -0300
+++ linux-2.4.26-pre2/drivers/acpi/dispatcher/dsopcode.c	2004-03-06 15:20:58.000000000 -0300
@@ -243,8 +243,8 @@ acpi_ds_get_buffer_arguments (
 
 	node = obj_desc->buffer.node;
 	if (!node) {
-		ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
-				"No pointer back to NS node in buffer %p\n", obj_desc));
+		ACPI_REPORT_ERROR ((
+				"No pointer back to NS node in buffer obj %p\n", obj_desc));
 		return_ACPI_STATUS (AE_AML_INTERNAL);
 	}
 
@@ -290,7 +290,7 @@ acpi_ds_get_package_arguments (
 
 	node = obj_desc->package.node;
 	if (!node) {
-		ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
+		ACPI_REPORT_ERROR ((
 				"No pointer back to NS node in package %p\n", obj_desc));
 		return_ACPI_STATUS (AE_AML_INTERNAL);
 	}
diff -Nur --show-c-function linux-2.4.25/drivers/acpi/dispatcher/dsutils.c linux-2.4.26-pre2/drivers/acpi/dispatcher/dsutils.c
--- linux-2.4.25/drivers/acpi/dispatcher/dsutils.c	2004-02-18 10:36:31.000000000 -0300
+++ linux-2.4.26-pre2/drivers/acpi/dispatcher/dsutils.c	2004-03-06 15:17:44.000000000 -0300
@@ -280,7 +280,8 @@ acpi_ds_resolve_operands (
 
 	/*
 	 * Attempt to resolve each of the valid operands
-	 * Method arguments are passed by value, not by reference
+	 * Method arguments are passed by reference, not by value.  This means
+	 * that the actual objects are passed, not copies of the objects.
 	 */
 	for (i = 0; i < walk_state->num_operands; i++) {
 		status = acpi_ex_resolve_to_value (&walk_state->operands[i], walk_state);
diff -Nur --show-c-function linux-2.4.25/drivers/acpi/dispatcher/dswstate.c linux-2.4.26-pre2/drivers/acpi/dispatcher/dswstate.c
--- linux-2.4.25/drivers/acpi/dispatcher/dswstate.c	2004-02-18 10:36:31.000000000 -0300
+++ linux-2.4.26-pre2/drivers/acpi/dispatcher/dswstate.c	2004-03-06 15:21:30.000000000 -0300
@@ -328,7 +328,7 @@ acpi_ds_result_push (
 
 	state = walk_state->results;
 	if (!state) {
-		ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "No result stack frame\n"));
+		ACPI_REPORT_ERROR (("No result stack frame during push\n"));
 		return (AE_AML_INTERNAL);
 	}
 
diff -Nur --show-c-function linux-2.4.25/drivers/acpi/executer/exconvrt.c linux-2.4.26-pre2/drivers/acpi/executer/exconvrt.c
--- linux-2.4.25/drivers/acpi/executer/exconvrt.c	2004-02-18 10:36:31.000000000 -0300
+++ linux-2.4.26-pre2/drivers/acpi/executer/exconvrt.c	2004-03-06 15:13:35.000000000 -0300
@@ -55,8 +55,9 @@
  *
  * FUNCTION:    acpi_ex_convert_to_integer
  *
- * PARAMETERS:  *obj_desc       - Object to be converted.  Must be an
+ * PARAMETERS:  obj_desc        - Object to be converted.  Must be an
  *                                Integer, Buffer, or String
+ *              result_desc     - Where the new Integer object is returned
  *              walk_state      - Current method state
  *
  * RETURN:      Status
@@ -189,8 +190,9 @@ acpi_ex_convert_to_integer (
  *
  * FUNCTION:    acpi_ex_convert_to_buffer
  *
- * PARAMETERS:  *obj_desc       - Object to be converted.  Must be an
+ * PARAMETERS:  obj_desc        - Object to be converted.  Must be an
  *                                Integer, Buffer, or String
+ *              result_desc     - Where the new buffer object is returned
  *              walk_state      - Current method state
  *
  * RETURN:      Status
@@ -319,6 +321,7 @@ acpi_ex_convert_to_ascii (
 
 	ACPI_FUNCTION_ENTRY ();
 
+
 	if (data_width < sizeof (acpi_integer)) {
 		leading_zero = FALSE;
 		length = data_width;
@@ -328,22 +331,21 @@ acpi_ex_convert_to_ascii (
 		length = sizeof (acpi_integer);
 	}
 
-
 	switch (base) {
 	case 10:
 
 		remainder = 0;
-		for (i = ACPI_MAX_DECIMAL_DIGITS; i > 0 ; i--) {
+		for (i = ACPI_MAX_DECIMAL_DIGITS; i > 0; i--) {
 			/* Divide by nth factor of 10 */
 
 			digit = integer;
-			for (j = 1; j < i; j++) {
+			for (j = 0; j < i; j++) {
 				(void) acpi_ut_short_divide (&digit, 10, &digit, &remainder);
 			}
 
 			/* Create the decimal digit */
 
-			if (digit != 0) {
+			if (remainder != 0) {
 				leading_zero = FALSE;
 			}
 
@@ -354,6 +356,7 @@ acpi_ex_convert_to_ascii (
 		}
 		break;
 
+
 	case 16:
 
 		/* Copy the integer to the buffer */
@@ -372,13 +375,14 @@ acpi_ex_convert_to_ascii (
 		}
 		break;
 
+
 	default:
 		break;
 	}
 
 	/*
 	 * Since leading zeros are supressed, we must check for the case where
-	 * the integer equals 0.
+	 * the integer equals 0
 	 *
 	 * Finally, null terminate the string and return the length
 	 */
@@ -396,8 +400,11 @@ acpi_ex_convert_to_ascii (
  *
  * FUNCTION:    acpi_ex_convert_to_string
  *
- * PARAMETERS:  *obj_desc       - Object to be converted.  Must be an
- *                                Integer, Buffer, or String
+ * PARAMETERS:  obj_desc        - Object to be converted.  Must be an
+ *                                  Integer, Buffer, or String
+ *              result_desc     - Where the string object is returned
+ *              Base            - 10 or 16
+ *              max_length      - Max length of the returned string
  *              walk_state      - Current method state
  *
  * RETURN:      Status
@@ -415,10 +422,10 @@ acpi_ex_convert_to_string (
 	struct acpi_walk_state          *walk_state)
 {
 	union acpi_operand_object       *ret_desc;
-	u32                             i;
-	u32                             string_length;
 	u8                              *new_buf;
 	u8                              *pointer;
+	u32                             string_length;
+	u32                             i;
 
 
 	ACPI_FUNCTION_TRACE_PTR ("ex_convert_to_string", obj_desc);
@@ -539,7 +546,6 @@ acpi_ex_convert_to_string (
 		return_ACPI_STATUS (AE_TYPE);
 	}
 
-
 	/*
 	 * If we are about to overwrite the original object on the operand stack,
 	 * we must remove a reference on the original object because we are
@@ -562,6 +568,7 @@ acpi_ex_convert_to_string (
  *
  * PARAMETERS:  destination_type    - Current type of the destination
  *              source_desc         - Source object to be converted.
+ *              result_desc         - Where the converted object is returned
  *              walk_state          - Current method state
  *
  * RETURN:      Status
@@ -653,6 +660,8 @@ acpi_ex_convert_to_target_type (
 
 
 		default:
+			ACPI_REPORT_ERROR (("Bad destination type during conversion: %X\n",
+				destination_type));
 			status = AE_AML_INTERNAL;
 			break;
 		}
@@ -672,6 +681,8 @@ acpi_ex_convert_to_target_type (
 			GET_CURRENT_ARG_TYPE (walk_state->op_info->runtime_args),
 			walk_state->op_info->name, acpi_ut_get_type_name (destination_type)));
 
+		ACPI_REPORT_ERROR (("Bad Target Type (ARGI): %X\n",
+			GET_CURRENT_ARG_TYPE (walk_state->op_info->runtime_args)))
 		status = AE_AML_INTERNAL;
 	}
 
diff -Nur --show-c-function linux-2.4.25/drivers/acpi/executer/exfldio.c linux-2.4.26-pre2/drivers/acpi/executer/exfldio.c
--- linux-2.4.25/drivers/acpi/executer/exfldio.c	2004-02-18 10:36:31.000000000 -0300
+++ linux-2.4.26-pre2/drivers/acpi/executer/exfldio.c	2004-03-06 15:15:51.000000000 -0300
@@ -154,8 +154,7 @@ acpi_ex_setup_region (
 			field_datum_byte_offset, obj_desc->common_field.access_byte_width,
 			acpi_ut_get_node_name (rgn_desc->region.node), rgn_desc->region.length));
 
-		#ifdef CONFIG_ACPI_RELAXED_AML
-		{
+		if (!acpi_strict) {
 			/*
 			 * Allow access to the field if it is within the region size
 			 * rounded up to a multiple of the access byte width.  This
@@ -186,9 +185,9 @@ acpi_ex_setup_region (
 				return_ACPI_STATUS (AE_OK);
 			}
 		}
-		#else
+		else {
 			return_ACPI_STATUS (AE_AML_REGION_LIMIT);
-		#endif
+		}
 	}
 
 	return_ACPI_STATUS (AE_OK);
@@ -507,8 +506,8 @@ acpi_ex_field_datum_io (
 
 	default:
 
-		ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "%p, Wrong object type - %s\n",
-			obj_desc, acpi_ut_get_object_type_name (obj_desc)));
+		ACPI_REPORT_ERROR (("Wrong object type in field I/O %X\n",
+			ACPI_GET_OBJECT_TYPE (obj_desc)));
 		status = AE_AML_INTERNAL;
 		break;
 	}
diff -Nur --show-c-function linux-2.4.25/drivers/acpi/executer/exmisc.c linux-2.4.26-pre2/drivers/acpi/executer/exmisc.c
--- linux-2.4.25/drivers/acpi/executer/exmisc.c	2004-02-18 10:36:31.000000000 -0300
+++ linux-2.4.26-pre2/drivers/acpi/executer/exmisc.c	2004-03-06 15:21:10.000000000 -0300
@@ -103,7 +103,7 @@ acpi_ex_get_object_reference (
 
 		default:
 
-			ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unknown Reference subtype %X\n",
+			ACPI_REPORT_ERROR (("Unknown Reference subtype in get ref %X\n",
 				obj_desc->reference.opcode));
 			return_ACPI_STATUS (AE_AML_INTERNAL);
 		}
@@ -121,8 +121,8 @@ acpi_ex_get_object_reference (
 
 	default:
 
-		ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "%p has invalid descriptor [%s]\n",
-				obj_desc, acpi_ut_get_descriptor_name (obj_desc)));
+		ACPI_REPORT_ERROR (("Invalid descriptor type in get ref: %X\n",
+				ACPI_GET_DESCRIPTOR_TYPE (obj_desc)));
 		return_ACPI_STATUS (AE_TYPE);
 	}
 
@@ -349,6 +349,8 @@ acpi_ex_do_concatenate (
 
 		/* Invalid object type, should not happen here */
 
+		ACPI_REPORT_ERROR (("Concat - invalid obj type: %X\n",
+				ACPI_GET_OBJECT_TYPE (obj_desc1)));
 		status = AE_AML_INTERNAL;
 		return_desc = NULL;
 	}
diff -Nur --show-c-function linux-2.4.25/drivers/acpi/executer/exoparg2.c linux-2.4.26-pre2/drivers/acpi/executer/exoparg2.c
--- linux-2.4.25/drivers/acpi/executer/exoparg2.c	2004-02-18 10:36:31.000000000 -0300
+++ linux-2.4.26-pre2/drivers/acpi/executer/exoparg2.c	2004-03-06 15:18:12.000000000 -0300
@@ -329,6 +329,8 @@ acpi_ex_opcode_2A_1T_1R (
 			break;
 
 		default:
+			ACPI_REPORT_ERROR (("Concat - invalid obj type: %X\n",
+					ACPI_GET_OBJECT_TYPE (operand[0])));
 			status = AE_AML_INTERNAL;
 		}
 
@@ -433,7 +435,7 @@ acpi_ex_opcode_2A_1T_1R (
 			}
 
 			return_desc->reference.target_type = ACPI_TYPE_PACKAGE;
-			return_desc->reference.object    = operand[0]->package.elements [index];
+			return_desc->reference.object    = operand[0];
 			return_desc->reference.where     = &operand[0]->package.elements [index];
 		}
 		else {
diff -Nur --show-c-function linux-2.4.25/drivers/acpi/executer/exprep.c linux-2.4.26-pre2/drivers/acpi/executer/exprep.c
--- linux-2.4.25/drivers/acpi/executer/exprep.c	2004-02-18 10:36:31.000000000 -0300
+++ linux-2.4.26-pre2/drivers/acpi/executer/exprep.c	2004-03-06 15:14:32.000000000 -0300
@@ -507,7 +507,7 @@ acpi_ex_prep_field_value (
 			(info->field_bit_position / ACPI_MUL_8 (obj_desc->field.access_byte_width));
 
 		if (!obj_desc->index_field.data_obj || !obj_desc->index_field.index_obj) {
-			ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Null Index Object\n"));
+			ACPI_REPORT_ERROR (("Null Index Object during field prep\n"));
 			return_ACPI_STATUS (AE_AML_INTERNAL);
 		}
 
diff -Nur --show-c-function linux-2.4.25/drivers/acpi/executer/exresolv.c linux-2.4.26-pre2/drivers/acpi/executer/exresolv.c
--- linux-2.4.25/drivers/acpi/executer/exresolv.c	2004-02-18 10:36:31.000000000 -0300
+++ linux-2.4.26-pre2/drivers/acpi/executer/exresolv.c	2004-03-06 15:16:40.000000000 -0300
@@ -238,8 +238,8 @@ acpi_ex_resolve_object_to_value (
 
 				/* Invalid reference object */
 
-				ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
-					"Unknown target_type %X in Index/Reference obj %p\n",
+				ACPI_REPORT_ERROR ((
+					"During resolve, Unknown target_type %X in Index/Reference obj %p\n",
 					stack_desc->reference.target_type, stack_desc));
 				status = AE_AML_INTERNAL;
 				break;
@@ -258,7 +258,7 @@ acpi_ex_resolve_object_to_value (
 
 		default:
 
-			ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unknown Reference opcode %X (%s) in %p\n",
+			ACPI_REPORT_ERROR (("During resolve, Unknown Reference opcode %X (%s) in %p\n",
 				opcode, acpi_ps_get_opcode_name (opcode), stack_desc));
 			status = AE_AML_INTERNAL;
 			break;
diff -Nur --show-c-function linux-2.4.25/drivers/acpi/executer/exresop.c linux-2.4.26-pre2/drivers/acpi/executer/exresop.c
--- linux-2.4.25/drivers/acpi/executer/exresop.c	2004-02-18 10:36:31.000000000 -0300
+++ linux-2.4.26-pre2/drivers/acpi/executer/exresop.c	2004-03-06 15:21:42.000000000 -0300
@@ -154,7 +154,7 @@ acpi_ex_resolve_operands (
 
 	arg_types = op_info->runtime_args;
 	if (arg_types == ARGI_INVALID_OPCODE) {
-		ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Internal - %X is not a valid AML opcode\n",
+		ACPI_REPORT_ERROR (("resolve_operands: %X is not a valid AML opcode\n",
 			opcode));
 
 		return_ACPI_STATUS (AE_AML_INTERNAL);
@@ -172,7 +172,7 @@ acpi_ex_resolve_operands (
 	 */
 	while (GET_CURRENT_ARG_TYPE (arg_types)) {
 		if (!stack_ptr || !*stack_ptr) {
-			ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Internal - null stack entry at %p\n",
+			ACPI_REPORT_ERROR (("resolve_operands: Null stack entry at %p\n",
 				stack_ptr));
 
 			return_ACPI_STATUS (AE_AML_INTERNAL);
diff -Nur --show-c-function linux-2.4.25/drivers/acpi/executer/exstore.c linux-2.4.26-pre2/drivers/acpi/executer/exstore.c
--- linux-2.4.25/drivers/acpi/executer/exstore.c	2004-02-18 10:36:31.000000000 -0300
+++ linux-2.4.26-pre2/drivers/acpi/executer/exstore.c	2004-03-06 15:17:10.000000000 -0300
@@ -125,7 +125,7 @@ acpi_ex_store (
 
 	default:
 
-		/* Destination is not an Reference */
+		/* Destination is not a Reference object */
 
 		ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
 			"Destination is not a Reference or Constant object [%p]\n", dest_desc));
@@ -189,35 +189,38 @@ acpi_ex_store (
 		switch (ACPI_GET_OBJECT_TYPE (source_desc)) {
 		case ACPI_TYPE_INTEGER:
 
-			ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DEBUG_OBJECT, "%8.8X%8.8X\n",
+			ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DEBUG_OBJECT, "0x%8.8X%8.8X\n",
 					ACPI_FORMAT_UINT64 (source_desc->integer.value)));
 			break;
 
 
 		case ACPI_TYPE_BUFFER:
 
-			ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DEBUG_OBJECT, "Length %.2X\n",
+			ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DEBUG_OBJECT, "Length 0x%.2X",
 					(u32) source_desc->buffer.length));
+			ACPI_DUMP_BUFFER (source_desc->buffer.pointer,
+				(source_desc->buffer.length < 32) ? source_desc->buffer.length : 32);
 			break;
 
 
 		case ACPI_TYPE_STRING:
 
-			ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DEBUG_OBJECT, "%s\n", source_desc->string.pointer));
+			ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DEBUG_OBJECT, "Length 0x%.2X, \"%s\"\n",
+					source_desc->string.length, source_desc->string.pointer));
 			break;
 
 
 		case ACPI_TYPE_PACKAGE:
 
-			ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DEBUG_OBJECT, "Elements Ptr - %p\n",
-					source_desc->package.elements));
+			ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DEBUG_OBJECT, "Size 0x%.2X Elements Ptr - %p\n",
+					source_desc->package.count, source_desc->package.elements));
 			break;
 
 
 		default:
 
-			ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DEBUG_OBJECT, "Type %s %p\n",
-					acpi_ut_get_object_type_name (source_desc), source_desc));
+			ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DEBUG_OBJECT, "%p\n",
+					source_desc));
 			break;
 		}
 
@@ -227,7 +230,7 @@ acpi_ex_store (
 
 	default:
 
-		ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unknown Reference opcode %X\n",
+		ACPI_REPORT_ERROR (("ex_store: Unknown Reference opcode %X\n",
 			ref_desc->reference.opcode));
 		ACPI_DUMP_ENTRY (ref_desc, ACPI_LV_ERROR);
 
@@ -263,6 +266,7 @@ acpi_ex_store_object_to_index (
 	union acpi_operand_object       *obj_desc;
 	union acpi_operand_object       *new_desc;
 	u8                              value = 0;
+	u32                             i;
 
 
 	ACPI_FUNCTION_TRACE ("ex_store_object_to_index");
@@ -283,6 +287,7 @@ acpi_ex_store_object_to_index (
 		/*
 		 * The object at *(index_desc->Reference.Where) is the
 		 * element within the package that is to be modified.
+		 * The parent package object is at index_desc->Reference.Object
 		 */
 		obj_desc = *(index_desc->reference.where);
 
@@ -309,6 +314,12 @@ acpi_ex_store_object_to_index (
 			if (new_desc == source_desc) {
 				acpi_ut_add_reference (new_desc);
 			}
+
+			/* Increment reference count by the ref count of the parent package -1 */
+
+			for (i = 1; i < ((union acpi_operand_object *) index_desc->reference.object)->common.reference_count; i++) {
+				acpi_ut_add_reference (new_desc);
+			}
 		}
 		break;
 
diff -Nur --show-c-function linux-2.4.25/drivers/acpi/executer/exstoren.c linux-2.4.26-pre2/drivers/acpi/executer/exstoren.c
--- linux-2.4.25/drivers/acpi/executer/exstoren.c	2004-02-18 10:36:31.000000000 -0300
+++ linux-2.4.26-pre2/drivers/acpi/executer/exstoren.c	2004-03-06 15:14:03.000000000 -0300
@@ -112,6 +112,12 @@ acpi_ex_resolve_object (
 			}
 		}
 
+		/* For copy_object, no further validation necessary */
+
+		if (walk_state->opcode == AML_COPY_OP) {
+			break;
+		}
+
 		/*
 		 * Must have a Integer, Buffer, or String
 		 */
@@ -136,7 +142,7 @@ acpi_ex_resolve_object (
 		/*
 		 * Aliases are resolved by acpi_ex_prep_operands
 		 */
-		ACPI_DEBUG_PRINT ((ACPI_DB_WARN, "Store into Alias - should never happen\n"));
+		ACPI_REPORT_ERROR (("Store into Alias - should never happen\n"));
 		status = AE_AML_INTERNAL;
 		break;
 
diff -Nur --show-c-function linux-2.4.25/drivers/acpi/hardware/hwgpe.c linux-2.4.26-pre2/drivers/acpi/hardware/hwgpe.c
--- linux-2.4.25/drivers/acpi/hardware/hwgpe.c	2004-02-18 10:36:31.000000000 -0300
+++ linux-2.4.26-pre2/drivers/acpi/hardware/hwgpe.c	2004-03-06 15:13:14.000000000 -0300
@@ -528,6 +528,14 @@ acpi_hw_enable_non_wakeup_gpe_block (
 	/* Examine each GPE register within the block */
 
 	for (i = 0; i < gpe_block->register_count; i++) {
+		/* Clear the entire status register */
+
+		status = acpi_hw_low_level_write (8, 0xFF,
+				 &gpe_block->register_info[i].status_address);
+		if (ACPI_FAILURE (status)) {
+			return (status);
+		}
+
 		/*
 		 * We previously stored the enabled status of all GPEs.
 		 * Blast them back in.
diff -Nur --show-c-function linux-2.4.25/drivers/acpi/hardware/hwregs.c linux-2.4.26-pre2/drivers/acpi/hardware/hwregs.c
--- linux-2.4.25/drivers/acpi/hardware/hwregs.c	2004-02-18 10:36:31.000000000 -0300
+++ linux-2.4.26-pre2/drivers/acpi/hardware/hwregs.c	2004-03-06 15:21:12.000000000 -0300
@@ -152,11 +152,11 @@ acpi_get_sleep_type_data (
 	/*
 	 * Evaluate the namespace object containing the values for this state
 	 */
-	status = acpi_ns_evaluate_by_name ((char *) acpi_gbl_db_sleep_states[sleep_state],
+	status = acpi_ns_evaluate_by_name ((char *) acpi_gbl_sleep_state_names[sleep_state],
 			  NULL, &obj_desc);
 	if (ACPI_FAILURE (status)) {
 		ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "%s while evaluating sleep_state [%s]\n",
-			acpi_format_exception (status), acpi_gbl_db_sleep_states[sleep_state]));
+			acpi_format_exception (status), acpi_gbl_sleep_state_names[sleep_state]));
 
 		return_ACPI_STATUS (status);
 	}
@@ -201,7 +201,7 @@ acpi_get_sleep_type_data (
 
 	if (ACPI_FAILURE (status)) {
 		ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "While evaluating sleep_state [%s], bad Sleep object %p type %s\n",
-			acpi_gbl_db_sleep_states[sleep_state], obj_desc, acpi_ut_get_object_type_name (obj_desc)));
+			acpi_gbl_sleep_state_names[sleep_state], obj_desc, acpi_ut_get_object_type_name (obj_desc)));
 	}
 
 	acpi_ut_remove_reference (obj_desc);
diff -Nur --show-c-function linux-2.4.25/drivers/acpi/hardware/hwsleep.c linux-2.4.26-pre2/drivers/acpi/hardware/hwsleep.c
--- linux-2.4.25/drivers/acpi/hardware/hwsleep.c	2004-02-18 10:36:31.000000000 -0300
+++ linux-2.4.26-pre2/drivers/acpi/hardware/hwsleep.c	2004-03-06 15:13:53.000000000 -0300
@@ -48,6 +48,19 @@
 	 ACPI_MODULE_NAME    ("hwsleep")
 
 
+#define METHOD_NAME__BFS        "\\_BFS"
+#define METHOD_NAME__GTS        "\\_GTS"
+#define METHOD_NAME__PTS        "\\_PTS"
+#define METHOD_NAME__SST        "\\_SI._SST"
+#define METHOD_NAME__WAK        "\\_WAK"
+
+#define ACPI_SST_INDICATOR_OFF  0
+#define ACPI_SST_WORKING        1
+#define ACPI_SST_WAKING         2
+#define ACPI_SST_SLEEPING       3
+#define ACPI_SST_SLEEP_CONTEXT  4
+
+
 /******************************************************************************
  *
  * FUNCTION:    acpi_set_firmware_waking_vector
@@ -171,19 +184,41 @@ acpi_enter_sleep_state_prep (
 
 	/* Run the _PTS and _GTS methods */
 
-	status = acpi_evaluate_object (NULL, "\\_PTS", &arg_list, NULL);
+	status = acpi_evaluate_object (NULL, METHOD_NAME__PTS, &arg_list, NULL);
 	if (ACPI_FAILURE (status) && status != AE_NOT_FOUND) {
 		return_ACPI_STATUS (status);
 	}
 
-	status = acpi_evaluate_object (NULL, "\\_GTS", &arg_list, NULL);
+	status = acpi_evaluate_object (NULL, METHOD_NAME__GTS, &arg_list, NULL);
 	if (ACPI_FAILURE (status) && status != AE_NOT_FOUND) {
 		return_ACPI_STATUS (status);
 	}
 
+	/* Setup the argument to _SST */
+
+	switch (sleep_state) {
+	case ACPI_STATE_S0:
+		arg.integer.value = ACPI_SST_WORKING;
+		break;
+
+	case ACPI_STATE_S1:
+	case ACPI_STATE_S2:
+	case ACPI_STATE_S3:
+		arg.integer.value = ACPI_SST_SLEEPING;
+		break;
+
+	case ACPI_STATE_S4:
+		arg.integer.value = ACPI_SST_SLEEP_CONTEXT;
+		break;
+
+	default:
+		arg.integer.value = ACPI_SST_INDICATOR_OFF; /* Default is indicator off */
+		break;
+	}
+
 	/* Set the system indicators to show the desired sleep state. */
 
-	status = acpi_evaluate_object (NULL, "\\_SI._SST", &arg_list, NULL);
+	status = acpi_evaluate_object (NULL, METHOD_NAME__SST, &arg_list, NULL);
 	if (ACPI_FAILURE (status) && status != AE_NOT_FOUND) {
 		 ACPI_REPORT_ERROR (("Method _SST failed, %s\n", acpi_format_exception (status)));
 	}
@@ -477,19 +512,19 @@ acpi_leave_sleep_state (
 
 	/* Ignore any errors from these methods */
 
-	arg.integer.value = 0;
-	status = acpi_evaluate_object (NULL, "\\_SI._SST", &arg_list, NULL);
+	arg.integer.value = ACPI_SST_WAKING;
+	status = acpi_evaluate_object (NULL, METHOD_NAME__SST, &arg_list, NULL);
 	if (ACPI_FAILURE (status) && status != AE_NOT_FOUND) {
 		ACPI_REPORT_ERROR (("Method _SST failed, %s\n", acpi_format_exception (status)));
 	}
 
 	arg.integer.value = sleep_state;
-	status = acpi_evaluate_object (NULL, "\\_BFS", &arg_list, NULL);
+	status = acpi_evaluate_object (NULL, METHOD_NAME__BFS, &arg_list, NULL);
 	if (ACPI_FAILURE (status) && status != AE_NOT_FOUND) {
 		ACPI_REPORT_ERROR (("Method _BFS failed, %s\n", acpi_format_exception (status)));
 	}
 
-	status = acpi_evaluate_object (NULL, "\\_WAK", &arg_list, NULL);
+	status = acpi_evaluate_object (NULL, METHOD_NAME__WAK, &arg_list, NULL);
 	if (ACPI_FAILURE (status) && status != AE_NOT_FOUND) {
 		ACPI_REPORT_ERROR (("Method _WAK failed, %s\n", acpi_format_exception (status)));
 	}
@@ -501,8 +536,25 @@ acpi_leave_sleep_state (
 		return_ACPI_STATUS (status);
 	}
 
+	/* Enable power button */
+
+	acpi_set_register(acpi_gbl_fixed_event_info[ACPI_EVENT_POWER_BUTTON].enable_register_id,
+			1, ACPI_MTX_DO_NOT_LOCK);
+	acpi_set_register(acpi_gbl_fixed_event_info[ACPI_EVENT_POWER_BUTTON].status_register_id,
+			1, ACPI_MTX_DO_NOT_LOCK);
+
 	/* Enable BM arbitration */
 
 	status = acpi_set_register (ACPI_BITREG_ARB_DISABLE, 0, ACPI_MTX_LOCK);
+	if (ACPI_FAILURE (status)) {
+		return_ACPI_STATUS (status);
+	}
+
+	arg.integer.value = ACPI_SST_WORKING;
+	status = acpi_evaluate_object (NULL, METHOD_NAME__SST, &arg_list, NULL);
+	if (ACPI_FAILURE (status) && status != AE_NOT_FOUND) {
+		ACPI_REPORT_ERROR (("Method _SST failed, %s\n", acpi_format_exception (status)));
+	}
+
 	return_ACPI_STATUS (status);
 }
diff -Nur --show-c-function linux-2.4.25/drivers/acpi/namespace/nsaccess.c linux-2.4.26-pre2/drivers/acpi/namespace/nsaccess.c
--- linux-2.4.25/drivers/acpi/namespace/nsaccess.c	2004-02-18 10:36:31.000000000 -0300
+++ linux-2.4.26-pre2/drivers/acpi/namespace/nsaccess.c	2004-03-06 15:23:07.000000000 -0300
@@ -314,7 +314,7 @@ acpi_ns_lookup (
 	else {
 		prefix_node = scope_info->scope.node;
 		if (ACPI_GET_DESCRIPTOR_TYPE (prefix_node) != ACPI_DESC_TYPE_NAMED) {
-			ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "%p Not a namespace node [%s]\n",
+			ACPI_REPORT_ERROR (("ns_lookup: %p is not a namespace node [%s]\n",
 					prefix_node, acpi_ut_get_descriptor_name (prefix_node)));
 			return_ACPI_STATUS (AE_AML_INTERNAL);
 		}
diff -Nur --show-c-function linux-2.4.25/drivers/acpi/namespace/nseval.c linux-2.4.26-pre2/drivers/acpi/namespace/nseval.c
--- linux-2.4.25/drivers/acpi/namespace/nseval.c	2004-02-18 10:36:31.000000000 -0300
+++ linux-2.4.26-pre2/drivers/acpi/namespace/nseval.c	2004-03-06 15:16:49.000000000 -0300
@@ -110,7 +110,7 @@ acpi_ns_evaluate_relative (
 
 	status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
 	if (ACPI_FAILURE (status)) {
-		return_ACPI_STATUS (status);
+		goto cleanup;
 	}
 
 	prefix_node = acpi_ns_map_handle_to_node (handle);
@@ -197,7 +197,7 @@ acpi_ns_evaluate_by_name (
 
 	status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
 	if (ACPI_FAILURE (status)) {
-		return_ACPI_STATUS (status);
+		goto cleanup;
 	}
 
 	/* Lookup the name in the namespace */
diff -Nur --show-c-function linux-2.4.25/drivers/acpi/namespace/nsutils.c linux-2.4.26-pre2/drivers/acpi/namespace/nsutils.c
--- linux-2.4.25/drivers/acpi/namespace/nsutils.c	2004-02-18 10:36:31.000000000 -0300
+++ linux-2.4.26-pre2/drivers/acpi/namespace/nsutils.c	2004-03-06 15:17:57.000000000 -0300
@@ -918,7 +918,7 @@ acpi_ns_get_node_by_path (
 
 	status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
 	if (ACPI_FAILURE (status)) {
-		return_ACPI_STATUS (status);
+		goto cleanup;
 	}
 
 	/* Setup lookup scope (search starting point) */
@@ -936,10 +936,10 @@ acpi_ns_get_node_by_path (
 				internal_path, acpi_format_exception (status)));
 	}
 
-	/* Cleanup */
-
 	(void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
 
+cleanup:
+	/* Cleanup */
 	if (internal_path) {
 		ACPI_MEM_FREE (internal_path);
 	}
diff -Nur --show-c-function linux-2.4.25/drivers/acpi/namespace/nsxfname.c linux-2.4.26-pre2/drivers/acpi/namespace/nsxfname.c
--- linux-2.4.25/drivers/acpi/namespace/nsxfname.c	2004-02-18 10:36:31.000000000 -0300
+++ linux-2.4.26-pre2/drivers/acpi/namespace/nsxfname.c	2004-03-06 15:15:09.000000000 -0300
@@ -326,6 +326,13 @@ acpi_get_object_info (
 			info.valid |= ACPI_VALID_ADR;
 		}
 
+		/* Execute the Device._sx_d methods */
+
+		status = acpi_ut_execute_sxds (node, info.highest_dstates);
+		if (ACPI_SUCCESS (status)) {
+			info.valid |= ACPI_VALID_STA;
+		}
+
 		status = AE_OK;
 	}
 
diff -Nur --show-c-function linux-2.4.25/drivers/acpi/parser/psargs.c linux-2.4.26-pre2/drivers/acpi/parser/psargs.c
--- linux-2.4.25/drivers/acpi/parser/psargs.c	2004-02-18 10:36:31.000000000 -0300
+++ linux-2.4.26-pre2/drivers/acpi/parser/psargs.c	2004-03-06 15:15:40.000000000 -0300
@@ -315,8 +315,8 @@ acpi_ps_get_next_namepath (
 				acpi_ps_append_arg (arg, name_op);
 
 				if (!method_desc) {
-					ACPI_DEBUG_PRINT ((ACPI_DB_PARSE,
-						"Control Method - %p has no attached object\n",
+					ACPI_REPORT_ERROR ((
+						"ps_get_next_namepath: Control Method %p has no attached object\n",
 						node));
 					return_ACPI_STATUS (AE_AML_INTERNAL);
 				}
diff -Nur --show-c-function linux-2.4.25/drivers/acpi/pci_link.c linux-2.4.26-pre2/drivers/acpi/pci_link.c
--- linux-2.4.25/drivers/acpi/pci_link.c	2003-11-28 16:26:19.000000000 -0200
+++ linux-2.4.26-pre2/drivers/acpi/pci_link.c	2004-03-06 15:24:20.000000000 -0300
@@ -767,7 +767,6 @@ __setup("acpi_irq_pci=", acpi_irq_pci);
 
 static int __init acpi_irq_nobalance_set(char *str)
 {
-printk("ACPI STATIC SET\n");
 	acpi_irq_balance = 0;
 	return(1);
 }
@@ -775,7 +774,6 @@ __setup("acpi_irq_nobalance", acpi_irq_n
 
 int __init acpi_irq_balance_set(char *str)
 {
-printk("ACPI BALANCE SET\n");
 	acpi_irq_balance = 1;
 	return(1);
 }
diff -Nur --show-c-function linux-2.4.25/drivers/acpi/resources/rsxface.c linux-2.4.26-pre2/drivers/acpi/resources/rsxface.c
--- linux-2.4.25/drivers/acpi/resources/rsxface.c	2004-02-18 10:36:31.000000000 -0300
+++ linux-2.4.26-pre2/drivers/acpi/resources/rsxface.c	2004-03-06 15:14:15.000000000 -0300
@@ -239,6 +239,7 @@ acpi_walk_resources (
 	acpi_status                         status;
 	struct acpi_buffer                  buffer = {ACPI_ALLOCATE_BUFFER, NULL};
 	struct acpi_resource                *resource;
+	struct acpi_resource                *buffer_end;
 
 
 	ACPI_FUNCTION_TRACE ("acpi_walk_resources");
@@ -255,7 +256,13 @@ acpi_walk_resources (
 		return_ACPI_STATUS (status);
 	}
 
-	resource = (struct acpi_resource *) buffer.pointer;
+	/* Setup pointers */
+
+	resource  = (struct acpi_resource *) buffer.pointer;
+	buffer_end = (struct acpi_resource *) ((u8 *) buffer.pointer + buffer.length);
+
+	/* Walk the resource list */
+
 	for (;;) {
 		if (!resource || resource->id == ACPI_RSTYPE_END_TAG) {
 			break;
@@ -268,6 +275,7 @@ acpi_walk_resources (
 		case AE_CTRL_DEPTH:
 
 			/* Just keep going */
+
 			status = AE_OK;
 			break;
 
@@ -285,7 +293,15 @@ acpi_walk_resources (
 			goto cleanup;
 		}
 
+		/* Get the next resource descriptor */
+
 		resource = ACPI_NEXT_RESOURCE (resource);
+
+		/* Check for end-of-buffer */
+
+		if (resource >= buffer_end) {
+			goto cleanup;
+		}
 	}
 
 cleanup:
diff -Nur --show-c-function linux-2.4.25/drivers/acpi/system.c linux-2.4.26-pre2/drivers/acpi/system.c
--- linux-2.4.25/drivers/acpi/system.c	2003-11-28 16:26:19.000000000 -0200
+++ linux-2.4.26-pre2/drivers/acpi/system.c	2004-03-06 15:16:46.000000000 -0300
@@ -41,14 +41,18 @@
 #include <acpi/acpi_bus.h>
 #include <acpi/acpi_drivers.h>
 
-#ifdef CONFIG_X86
 #ifdef CONFIG_ACPI_SLEEP
 #include <linux/mc146818rtc.h>
 #include <linux/irq.h>
 #include <asm/hw_irq.h>
-#endif
-#endif
 
+acpi_status acpi_system_save_state(u32);
+#else
+static inline acpi_status acpi_system_save_state(u32 state)
+{
+	return AE_OK;
+}
+#endif /* !CONFIG_ACPI_SLEEP */
 
 #define _COMPONENT		ACPI_SYSTEM_COMPONENT
 ACPI_MODULE_NAME		("acpi_system")
@@ -95,6 +99,7 @@ acpi_power_off (void)
 {
 	if (unlikely(in_interrupt())) 
 		BUG();
+	acpi_system_save_state(ACPI_STATE_S5);
 	acpi_enter_sleep_state_prep(ACPI_STATE_S5);
 	ACPI_DISABLE_IRQS();
 	acpi_enter_sleep_state(ACPI_STATE_S5);
diff -Nur --show-c-function linux-2.4.25/drivers/acpi/utilities/uteval.c linux-2.4.26-pre2/drivers/acpi/utilities/uteval.c
--- linux-2.4.25/drivers/acpi/utilities/uteval.c	2004-02-18 10:36:31.000000000 -0300
+++ linux-2.4.26-pre2/drivers/acpi/utilities/uteval.c	2004-03-06 15:13:50.000000000 -0300
@@ -562,3 +562,63 @@ acpi_ut_execute_STA (
 	acpi_ut_remove_reference (obj_desc);
 	return_ACPI_STATUS (status);
 }
+
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ut_execute_Sxds
+ *
+ * PARAMETERS:  device_node         - Node for the device
+ *              *Flags              - Where the status flags are returned
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Executes _STA for selected device and stores results in
+ *              *Flags.
+ *
+ *              NOTE: Internal function, no parameter validation
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_ut_execute_sxds (
+	struct acpi_namespace_node      *device_node,
+	u8                              *highest)
+{
+	union acpi_operand_object       *obj_desc;
+	acpi_status                     status;
+	u32                             i;
+
+
+	ACPI_FUNCTION_TRACE ("ut_execute_Sxds");
+
+
+	for (i = 0; i < 4; i++) {
+		highest[i] = 0xFF;
+		status = acpi_ut_evaluate_object (device_node,
+				 (char *) acpi_gbl_highest_dstate_names[i],
+				 ACPI_BTYPE_INTEGER, &obj_desc);
+		if (ACPI_FAILURE (status)) {
+			if (status != AE_NOT_FOUND) {
+				ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
+					"%s on Device %4.4s, %s\n",
+					(char *) acpi_gbl_highest_dstate_names[i],
+					acpi_ut_get_node_name (device_node),
+					acpi_format_exception (status)));
+
+				return_ACPI_STATUS (status);
+			}
+		}
+		else {
+			/* Extract the Dstate value */
+
+			highest[i] = (u8) obj_desc->integer.value;
+
+			/* Delete the return object */
+
+			acpi_ut_remove_reference (obj_desc);
+		}
+	}
+
+	return_ACPI_STATUS (AE_OK);
+}
diff -Nur --show-c-function linux-2.4.25/drivers/acpi/utilities/utglobal.c linux-2.4.26-pre2/drivers/acpi/utilities/utglobal.c
--- linux-2.4.25/drivers/acpi/utilities/utglobal.c	2004-02-18 10:36:31.000000000 -0300
+++ linux-2.4.26-pre2/drivers/acpi/utilities/utglobal.c	2004-03-06 15:14:03.000000000 -0300
@@ -171,7 +171,7 @@ u8                                  acpi
 
 const u8                            acpi_gbl_decode_to8bit [8] = {1,2,4,8,16,32,64,128};
 
-const char                          *acpi_gbl_db_sleep_states[ACPI_S_STATE_COUNT] = {
+const char                          *acpi_gbl_sleep_state_names[ACPI_S_STATE_COUNT] = {
 			  "\\_S0_",
 			  "\\_S1_",
 			  "\\_S2_",
@@ -179,6 +179,11 @@ const char                          *acp
 			  "\\_S4_",
 			  "\\_S5_"};
 
+const char                          *acpi_gbl_highest_dstate_names[4] = {
+					   "_S1D",
+					   "_S2D",
+					   "_S3D",
+					   "_S4D"};
 
 /******************************************************************************
  *
diff -Nur --show-c-function linux-2.4.25/drivers/i2c/Config.in linux-2.4.26-pre2/drivers/i2c/Config.in
--- linux-2.4.25/drivers/i2c/Config.in	2004-02-18 10:36:31.000000000 -0300
+++ linux-2.4.26-pre2/drivers/i2c/Config.in	2004-03-06 15:23:13.000000000 -0300
@@ -12,7 +12,7 @@ if [ "$CONFIG_I2C" != "n" ]; then
       dep_tristate '  Philips style parallel port adapter' CONFIG_I2C_PHILIPSPAR $CONFIG_I2C_ALGOBIT $CONFIG_PARPORT
       dep_tristate '  ELV adapter' CONFIG_I2C_ELV $CONFIG_I2C_ALGOBIT
       dep_tristate '  Velleman K8000 adapter' CONFIG_I2C_VELLEMAN $CONFIG_I2C_ALGOBIT
-      dep_tristate '  NatSemi SCx200 I2C using GPIO pins' CONFIG_SCx200_I2C $CONFIG_SCx200 $CONFIG_I2C_ALGOBIT
+      dep_tristate '  NatSemi SCx200 I2C using GPIO pins' CONFIG_SCx200_I2C $CONFIG_SCx200_GPIO $CONFIG_I2C_ALGOBIT
       if [ "$CONFIG_SCx200_I2C" != "n" ]; then
          int  '    GPIO pin used for SCL' CONFIG_SCx200_I2C_SCL 12
          int  '    GPIO pin used for SDA' CONFIG_SCx200_I2C_SDA 13
diff -Nur --show-c-function linux-2.4.25/drivers/ide/ide-proc.c linux-2.4.26-pre2/drivers/ide/ide-proc.c
--- linux-2.4.25/drivers/ide/ide-proc.c	2004-02-18 10:36:31.000000000 -0300
+++ linux-2.4.26-pre2/drivers/ide/ide-proc.c	2004-03-06 15:13:37.000000000 -0300
@@ -811,35 +811,6 @@ void create_proc_ide_drives(ide_hwif_t *
 
 EXPORT_SYMBOL(create_proc_ide_drives);
 
-void recreate_proc_ide_device(ide_hwif_t *hwif, ide_drive_t *drive)
-{
-	struct proc_dir_entry *ent;
-	struct proc_dir_entry *parent = hwif->proc;
-	char name[64];
-//	ide_driver_t *driver = drive->driver;
-
-	if (drive->present && !drive->proc) {
-		drive->proc = proc_mkdir(drive->name, parent);
-		if (drive->proc)
-			ide_add_proc_entries(drive->proc, generic_drive_entries, drive);
-
-/*
- * assume that we have these already, however, should test FIXME!
- * if (driver) {
- *      ide_add_proc_entries(drive->proc, generic_subdriver_entries, drive);
- *      ide_add_proc_entries(drive->proc, driver->proc, drive);
- * }
- *
- */
-		sprintf(name,"ide%d/%s", (drive->name[2]-'a')/2, drive->name);
-		ent = proc_symlink(drive->name, proc_ide_root, name);
-		if (!ent)
-			return;
-	}
-}
-
-EXPORT_SYMBOL(recreate_proc_ide_device);
-
 void destroy_proc_ide_device(ide_hwif_t *hwif, ide_drive_t *drive)
 {
 	ide_driver_t *driver = drive->driver;
diff -Nur --show-c-function linux-2.4.25/drivers/ide/pci/generic.h linux-2.4.26-pre2/drivers/ide/pci/generic.h
--- linux-2.4.25/drivers/ide/pci/generic.h	2003-08-25 08:44:41.000000000 -0300
+++ linux-2.4.26-pre2/drivers/ide/pci/generic.h	2004-03-06 15:14:24.000000000 -0300
@@ -148,6 +148,7 @@ static ide_pci_device_t generic_chipsets
 	}
 };
 
+#if 0
 static ide_pci_device_t unknown_chipset[] __devinitdata = {
 	{	/* 0 */
 		.vendor		= 0,
@@ -170,5 +171,6 @@ static ide_pci_device_t unknown_chipset[
 	}
 
 };
+#endif
 
 #endif /* IDE_GENERIC_H */
diff -Nur --show-c-function linux-2.4.25/drivers/ide/pci/siimage.c linux-2.4.26-pre2/drivers/ide/pci/siimage.c
--- linux-2.4.25/drivers/ide/pci/siimage.c	2003-11-28 16:26:20.000000000 -0200
+++ linux-2.4.26-pre2/drivers/ide/pci/siimage.c	2004-03-06 15:20:56.000000000 -0300
@@ -62,6 +62,7 @@ static int pdev_is_sata(struct pci_dev *
 			return 0;
 	}
 	BUG();
+	return 0;
 }
  
 /**
diff -Nur --show-c-function linux-2.4.25/drivers/ieee1394/dma.c linux-2.4.26-pre2/drivers/ieee1394/dma.c
--- linux-2.4.25/drivers/ieee1394/dma.c	2003-08-25 08:44:41.000000000 -0300
+++ linux-2.4.26-pre2/drivers/ieee1394/dma.c	2004-03-06 15:16:19.000000000 -0300
@@ -86,7 +86,7 @@ int dma_region_alloc(struct dma_region *
 	memset(dma->kvirt, 0, n_pages * PAGE_SIZE);
 
 	/* allocate scatter/gather list */
-	dma->sglist = kmalloc(dma->n_pages * sizeof(struct scatterlist), GFP_KERNEL);
+	dma->sglist = vmalloc(dma->n_pages * sizeof(struct scatterlist));
 	if (!dma->sglist) {
 		printk(KERN_ERR "dma_region_alloc: kmalloc(sglist) failed\n");
 		goto err;
@@ -130,7 +130,7 @@ void dma_region_free(struct dma_region *
 	}
 
 	if (dma->sglist) {
-		kfree(dma->sglist);
+		vfree(dma->sglist);
 		dma->sglist = NULL;
 	}
 
diff -Nur --show-c-function linux-2.4.25/drivers/ieee1394/video1394.c linux-2.4.26-pre2/drivers/ieee1394/video1394.c
--- linux-2.4.25/drivers/ieee1394/video1394.c	2003-08-25 08:44:42.000000000 -0300
+++ linux-2.4.26-pre2/drivers/ieee1394/video1394.c	2004-03-06 15:14:20.000000000 -0300
@@ -216,6 +216,7 @@ alloc_dma_iso_ctx(struct ti_ohci *ohci, 
 	d->frame_size = buf_size;
 	d->buf_size = PAGE_ALIGN(buf_size);
 	d->last_buffer = -1;
+	INIT_LIST_HEAD(&d->link);
 	init_waitqueue_head(&d->waitq);
 
 	/* Init the regions for easy cleanup */
diff -Nur --show-c-function linux-2.4.25/drivers/isdn/avmb1/capidrv.c linux-2.4.26-pre2/drivers/isdn/avmb1/capidrv.c
--- linux-2.4.25/drivers/isdn/avmb1/capidrv.c	2003-06-13 11:51:34.000000000 -0300
+++ linux-2.4.26-pre2/drivers/isdn/avmb1/capidrv.c	2004-03-06 15:17:19.000000000 -0300
@@ -523,13 +523,25 @@ static int capidrv_del_ack(struct capidr
 
 static void send_message(capidrv_contr * card, _cmsg * cmsg)
 {
-	struct sk_buff *skb;
-	size_t len;
+	struct sk_buff	*skb;
+	size_t		len;
+	u16		err;
+
 	capi_cmsg2message(cmsg, cmsg->buf);
 	len = CAPIMSG_LEN(cmsg->buf);
 	skb = alloc_skb(len, GFP_ATOMIC);
+	if(!skb) {
+		printk(KERN_ERR "no skb len(%d) memory\n", len);
+		return;
+	}
 	memcpy(skb_put(skb, len), cmsg->buf, len);
-	(*capifuncs->capi_put_message) (global.appid, skb);
+	err = (*capifuncs->capi_put_message) (global.appid, skb);
+	if (err) {
+		printk(KERN_WARNING "%s: capi_put_message error: %04x\n",
+			__FUNCTION__, err);
+		kfree_skb(skb);
+		return;
+	}
 	global.nsentctlpkt++;
 }
 
@@ -2188,10 +2200,10 @@ static int capidrv_delcontr(__u16 contr)
 			free_ncci(card, card->bchans[card->nbchan-1].nccip);
 		if (card->bchans[card->nbchan-1].plcip)
 			free_plci(card, card->bchans[card->nbchan-1].plcip);
-		if (card->plci_list)
-			printk(KERN_ERR "capidrv: bug in free_plci()\n");
 		card->nbchan--;
 	}
+	if (card->plci_list)
+		printk(KERN_ERR "capidrv: bug in free_plci()\n");
 	kfree(card->bchans);
 	card->bchans = 0;
 
diff -Nur --show-c-function linux-2.4.25/drivers/isdn/avmb1/kcapi.c linux-2.4.26-pre2/drivers/isdn/avmb1/kcapi.c
--- linux-2.4.25/drivers/isdn/avmb1/kcapi.c	2003-06-13 11:51:34.000000000 -0300
+++ linux-2.4.26-pre2/drivers/isdn/avmb1/kcapi.c	2004-03-06 15:20:49.000000000 -0300
@@ -546,7 +546,13 @@ static int notify_push(unsigned int cmd,
 static void notify_up(__u32 contr)
 {
 	struct capi_interface_user *p;
+	__u16 appl;
 
+	for (appl = 1; appl <= CAPI_MAXAPPL; appl++) {
+		if (!VALID_APPLID(appl)) continue;
+		if (APPL(appl)->releasing) continue;
+		CARD(contr)->driver->register_appl(CARD(contr), appl, &APPL(appl)->rparam);
+	}
         printk(KERN_NOTICE "kcapi: notify up contr %d\n", contr);
 	spin_lock(&capi_users_lock);
 	for (p = capi_users; p; p = p->next) {
@@ -714,12 +720,16 @@ static void controllercb_appl_released(s
 			nextpp = &(*pp)->next;
 		}
 	}
-	APPL(appl)->releasing--;
-	if (APPL(appl)->releasing <= 0) {
-		APPL(appl)->signal = 0;
-		APPL_MARK_FREE(appl);
-		printk(KERN_INFO "kcapi: appl %d down\n", appl);
-	}
+	if (APPL(appl)->releasing) { /* only release if the application was marked for release */
+		printk(KERN_DEBUG "kcapi: appl %d releasing(%d)\n", appl, APPL(appl)->releasing);
+		APPL(appl)->releasing--;
+		if (APPL(appl)->releasing <= 0) {
+			APPL(appl)->signal = 0;
+			APPL_MARK_FREE(appl);
+			printk(KERN_INFO "kcapi: appl %d down\n", appl);
+		}
+	} else
+		printk(KERN_WARNING "kcapi: appl %d card%d released without request\n", appl, card->cnr);
 }
 /*
  * ncci management
@@ -872,16 +882,7 @@ error:
 
 static void controllercb_ready(struct capi_ctr * card)
 {
-	__u16 appl;
-
 	card->cardstate = CARD_RUNNING;
-
-	for (appl = 1; appl <= CAPI_MAXAPPL; appl++) {
-		if (!VALID_APPLID(appl)) continue;
-		if (APPL(appl)->releasing) continue;
-		card->driver->register_appl(card, appl, &APPL(appl)->rparam);
-	}
-
         printk(KERN_NOTICE "kcapi: card %d \"%s\" ready.\n",
 		CARDNR(card), card->name);
 
diff -Nur --show-c-function linux-2.4.25/drivers/isdn/hisax/isurf.c linux-2.4.26-pre2/drivers/isdn/hisax/isurf.c
--- linux-2.4.25/drivers/isdn/hisax/isurf.c	2002-11-28 21:53:13.000000000 -0200
+++ linux-2.4.26-pre2/drivers/isdn/hisax/isurf.c	2004-03-06 15:18:46.000000000 -0300
@@ -235,8 +235,18 @@ setup_isurf(struct IsdnCard *card)
 				pd->prepare(pd);
 				pd->deactivate(pd);
 				pd->activate(pd);
+				/* The ISA-PnP logic apparently
+				 * expects upper limit address to be
+				 * set. Since the isa-pnp module
+				 * doesn't do this, so we have to make
+				 * up for it.
+				 */
+				isapnp_cfg_begin(pd->bus->number, pd->devfn);
+				isapnp_write_word(ISAPNP_CFG_MEM+3, 
+					pd->resource[8].end >> 8);
+				isapnp_cfg_end();
 				cs->hw.isurf.reset = pd->resource[0].start;
-				cs->hw.isurf.phymem = pd->resource[1].start;
+				cs->hw.isurf.phymem = pd->resource[8].start;
 				cs->irq = pd->irq_resource[0].start;
 				if (!cs->irq || !cs->hw.isurf.reset || !cs->hw.isurf.phymem) {
 					printk(KERN_ERR "ISurfPnP:some resources are missing %d/%x/%lx\n",
diff -Nur --show-c-function linux-2.4.25/drivers/media/video/Config.in linux-2.4.26-pre2/drivers/media/video/Config.in
--- linux-2.4.25/drivers/media/video/Config.in	2004-02-18 10:36:31.000000000 -0300
+++ linux-2.4.26-pre2/drivers/media/video/Config.in	2004-03-06 15:18:48.000000000 -0300
@@ -49,7 +49,7 @@ dep_tristate '  Iomega Buz support' CONF
 dep_tristate '  Miro DC10(+) support' CONFIG_VIDEO_ZORAN_DC10 $CONFIG_VIDEO_ZORAN $CONFIG_VIDEO_DEV $CONFIG_PCI $CONFIG_I2C
 dep_tristate '  Linux Media Labs LML33 support' CONFIG_VIDEO_ZORAN_LML33 $CONFIG_VIDEO_ZORAN $CONFIG_VIDEO_DEV $CONFIG_PCI $CONFIG_I2C
 dep_tristate '  Zoran ZR36120/36125 Video For Linux' CONFIG_VIDEO_ZR36120 $CONFIG_VIDEO_DEV $CONFIG_PCI $CONFIG_I2C
-if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+if [ "$CONFIG_EXPERIMENTAL" = "y" -a "$CONFIG_HIGHMEM64G" != "y" ]; then
   dep_tristate '  Sony Vaio Picturebook Motion Eye Video For Linux (EXPERIMENTAL)' CONFIG_VIDEO_MEYE $CONFIG_VIDEO_DEV $CONFIG_PCI $CONFIG_SONYPI
 fi
 
diff -Nur --show-c-function linux-2.4.25/drivers/media/video/meye.c linux-2.4.26-pre2/drivers/media/video/meye.c
--- linux-2.4.25/drivers/media/video/meye.c	2003-11-28 16:26:20.000000000 -0200
+++ linux-2.4.26-pre2/drivers/media/video/meye.c	2004-03-06 15:19:05.000000000 -0300
@@ -188,23 +188,29 @@ void dma_free_coherent(struct pci_dev *d
         free_pages((unsigned long)vaddr, get_order(size));
 }
 
-/* return a page table pointing to N pages of locked memory */
+/* return a page table pointing to N pages of locked memory
+ *
+ * NOTE: The meye device expects dma_addr_t size to be 32 bits
+ * (the toc must be exactly 1024 entries each of them being 4 bytes
+ * in size, the whole result being 4096 bytes). We're using here
+ * dma_addr_t for corectness but the compilation of this driver is
+ * disabled for HIGHMEM64G=y, where sizeof(dma_addr_t) != 4 */
 static int ptable_alloc(void) {
-	u32 *pt;
+	dma_addr_t *pt;
 	int i;
 
 	memset(meye.mchip_ptable, 0, sizeof(meye.mchip_ptable));
 
-	meye.mchip_ptable[MCHIP_NB_PAGES] = dma_alloc_coherent(meye.mchip_dev, 
-							       PAGE_SIZE, 
-							       &meye.mchip_dmahandle,
-							       GFP_KERNEL);
-	if (!meye.mchip_ptable[MCHIP_NB_PAGES]) {
+	meye.mchip_ptable_toc = dma_alloc_coherent(meye.mchip_dev, 
+						   PAGE_SIZE, 
+						   &meye.mchip_dmahandle,
+						   GFP_KERNEL);
+	if (!meye.mchip_ptable_toc) {
 		meye.mchip_dmahandle = 0;
 		return -1;
 	}
 
-	pt = (u32 *)meye.mchip_ptable[MCHIP_NB_PAGES];
+	pt = meye.mchip_ptable_toc;
 	for (i = 0; i < MCHIP_NB_PAGES; i++) {
 		meye.mchip_ptable[i] = dma_alloc_coherent(meye.mchip_dev, 
 							  PAGE_SIZE,
@@ -212,13 +218,18 @@ static int ptable_alloc(void) {
 							  GFP_KERNEL);
 		if (!meye.mchip_ptable[i]) {
 			int j;
-			pt = (u32 *)meye.mchip_ptable[MCHIP_NB_PAGES];
+			pt = meye.mchip_ptable_toc;
 			for (j = 0; j < i; ++j) {
 				dma_free_coherent(meye.mchip_dev,
 						  PAGE_SIZE,
 						  meye.mchip_ptable[j], *pt);
 				pt++;
 			}
+			dma_free_coherent(meye.mchip_dev,
+					  PAGE_SIZE,
+					  meye.mchip_ptable_toc,
+					  meye.mchip_dmahandle);
+			meye.mchip_ptable_toc = 0;
 			meye.mchip_dmahandle = 0;
 			return -1;
 		}
@@ -228,10 +239,10 @@ static int ptable_alloc(void) {
 }
 
 static void ptable_free(void) {
-	u32 *pt;
+	dma_addr_t *pt;
 	int i;
 
-	pt = (u32 *)meye.mchip_ptable[MCHIP_NB_PAGES];
+	pt = meye.mchip_ptable_toc;
 	for (i = 0; i < MCHIP_NB_PAGES; i++) {
 		if (meye.mchip_ptable[i])
 			dma_free_coherent(meye.mchip_dev, 
@@ -240,13 +251,14 @@ static void ptable_free(void) {
 		pt++;
 	}
 
-	if (meye.mchip_ptable[MCHIP_NB_PAGES])
+	if (meye.mchip_ptable_toc)
 		dma_free_coherent(meye.mchip_dev, 
 				  PAGE_SIZE, 
-				  meye.mchip_ptable[MCHIP_NB_PAGES],
+				  meye.mchip_ptable_toc,
 				  meye.mchip_dmahandle);
 
 	memset(meye.mchip_ptable, 0, sizeof(meye.mchip_ptable));
+	meye.mchip_ptable_toc = 0;
 	meye.mchip_dmahandle = 0;
 }
 
diff -Nur --show-c-function linux-2.4.25/drivers/media/video/meye.h linux-2.4.26-pre2/drivers/media/video/meye.h
--- linux-2.4.25/drivers/media/video/meye.h	2003-11-28 16:26:20.000000000 -0200
+++ linux-2.4.26-pre2/drivers/media/video/meye.h	2004-03-06 15:18:44.000000000 -0300
@@ -298,7 +298,8 @@ struct meye {
 	u8 mchip_fnum;			/* current mchip frame number */
 
 	unsigned char *mchip_mmregs;	/* mchip: memory mapped registers */
-	u8 *mchip_ptable[MCHIP_NB_PAGES+1];/* mchip: ptable + ptable toc */
+	u8 *mchip_ptable[MCHIP_NB_PAGES];/* mchip: ptable */
+	dma_addr_t *mchip_ptable_toc;	/* mchip: ptable toc */
 	dma_addr_t mchip_dmahandle;	/* mchip: dma handle to ptable toc */
 
 	unsigned char *grab_fbuffer;	/* capture framebuffer */
diff -Nur --show-c-function linux-2.4.25/drivers/net/8139too.c linux-2.4.26-pre2/drivers/net/8139too.c
--- linux-2.4.25/drivers/net/8139too.c	2004-02-18 10:36:31.000000000 -0300
+++ linux-2.4.26-pre2/drivers/net/8139too.c	2004-03-06 15:12:46.000000000 -0300
@@ -255,6 +255,10 @@ static struct pci_device_id rtl8139_pci_
 	{0x11db, 0x1234, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 },
 	{0x1432, 0x9130, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 },
 	{0x02ac, 0x1012, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 },
+	{0x018a, 0x0106, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 },
+	{0x126c, 0x1211, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 },
+	{0x1743, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 },
+	{0x021b, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 },
 
 #ifdef CONFIG_SH_SECUREEDGE5410
 	/* Bogus 8139 silicon reports 8129 without external PROM :-( */
diff -Nur --show-c-function linux-2.4.25/drivers/net/bonding/bond_3ad.c linux-2.4.26-pre2/drivers/net/bonding/bond_3ad.c
--- linux-2.4.25/drivers/net/bonding/bond_3ad.c	2003-08-25 08:44:42.000000000 -0300
+++ linux-2.4.26-pre2/drivers/net/bonding/bond_3ad.c	2004-03-06 15:21:42.000000000 -0300
@@ -1,5 +1,5 @@
 /*
- * Copyright(c) 1999 - 2003 Intel Corporation. All rights reserved.
+ * Copyright(c) 1999 - 2004 Intel Corporation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
@@ -47,8 +47,13 @@
  *	- Send LACPDU as highest priority packet to further fix the above
  *	  problem on very high Tx traffic load where packets may get dropped
  *	  by the slave.
+ *
+ * 2003/12/01 - Shmulik Hen <shmulik.hen at intel dot com>
+ *	- Code cleanup and style changes
  */
 
+//#define BONDING_DEBUG 1
+
 #include <linux/skbuff.h>
 #include <linux/if_ether.h>
 #include <linux/netdevice.h>
@@ -119,6 +124,7 @@
 
 static struct mac_addr null_mac_addr = {{0, 0, 0, 0, 0, 0}};
 static u16 ad_ticks_per_sec;
+static const int ad_delta_in_ticks = (AD_TIMER_INTERVAL * HZ) / 1000;
 
 // ================= 3AD api to bonding and kernel code ==================
 static u16 __get_link_speed(struct port *port);
@@ -196,13 +202,11 @@ static inline struct bonding *__get_bond
  */
 static inline struct port *__get_first_port(struct bonding *bond)
 {
-	struct slave *slave = bond->next;
-
-	if (slave == (struct slave *)bond) {
+	if (bond->slave_cnt == 0) {
 		return NULL;
 	}
 
-	return &(SLAVE_AD_INFO(slave).port);
+	return &(SLAVE_AD_INFO(bond->first_slave).port);
 }
 
 /**
@@ -218,7 +222,7 @@ static inline struct port *__get_next_po
 	struct slave *slave = port->slave;
 
 	// If there's no bond for this port, or this is the last slave
-	if ((bond == NULL) || (slave->next == bond->next)) {
+	if ((bond == NULL) || (slave->next == bond->first_slave)) {
 		return NULL;
 	}
 
@@ -236,12 +240,12 @@ static inline struct aggregator *__get_f
 {
 	struct bonding *bond = __get_bond_by_port(port);
 
-	// If there's no bond for this port, or this is the last slave
-	if ((bond == NULL) || (bond->next == (struct slave *)bond)) {
+	// If there's no bond for this port, or bond has no slaves
+	if ((bond == NULL) || (bond->slave_cnt == 0)) {
 		return NULL;
 	}
 
-	return &(SLAVE_AD_INFO(bond->next).aggregator);
+	return &(SLAVE_AD_INFO(bond->first_slave).aggregator);
 }
 
 /**
@@ -257,7 +261,7 @@ static inline struct aggregator *__get_n
 	struct bonding *bond = bond_get_bond_by_slave(slave);
 
 	// If there's no bond for this aggregator, or this is the last slave
-	if ((bond == NULL) || (slave->next == bond->next)) {
+	if ((bond == NULL) || (slave->next == bond->first_slave)) {
 		return NULL;
 	}
 
@@ -392,7 +396,7 @@ static u16 __get_link_speed(struct port 
 		}
 	}
 
-	BOND_PRINT_DBG(("Port %d Received link speed %d update from adapter", port->actor_port_number, speed));
+	dprintk("Port %d Received link speed %d update from adapter\n", port->actor_port_number, speed);
 	return speed;
 }
 
@@ -418,12 +422,12 @@ static u8 __get_duplex(struct port *port
 		switch (slave->duplex) {
 		case DUPLEX_FULL:
 			retval=0x1;
-			BOND_PRINT_DBG(("Port %d Received status full duplex update from adapter", port->actor_port_number));
+			dprintk("Port %d Received status full duplex update from adapter\n", port->actor_port_number);
 			break;
 		case DUPLEX_HALF:
 		default:
 			retval=0x0;
-			BOND_PRINT_DBG(("Port %d Received status NOT full duplex update from adapter", port->actor_port_number));
+			dprintk("Port %d Received status NOT full duplex update from adapter\n", port->actor_port_number);
 			break;
 		}
 	}
@@ -1059,7 +1063,7 @@ static void ad_mux_machine(struct port *
 
 	// check if the state machine was changed
 	if (port->sm_mux_state != last_state) {
-		BOND_PRINT_DBG(("Mux Machine: Port=%d, Last State=%d, Curr State=%d", port->actor_port_number, last_state, port->sm_mux_state));
+		dprintk("Mux Machine: Port=%d, Last State=%d, Curr State=%d\n", port->actor_port_number, last_state, port->sm_mux_state);
 		switch (port->sm_mux_state) {
 		case AD_MUX_DETACHED:
 			__detach_bond_from_agg(port);
@@ -1158,7 +1162,7 @@ static void ad_rx_machine(struct lacpdu 
 
 	// check if the State machine was changed or new lacpdu arrived
 	if ((port->sm_rx_state != last_state) || (lacpdu)) {
-		BOND_PRINT_DBG(("Rx Machine: Port=%d, Last State=%d, Curr State=%d", port->actor_port_number, last_state, port->sm_rx_state));
+		dprintk("Rx Machine: Port=%d, Last State=%d, Curr State=%d\n", port->actor_port_number, last_state, port->sm_rx_state);
 		switch (port->sm_rx_state) {
 		case AD_RX_INITIALIZE:
 			if (!(port->actor_oper_port_key & AD_DUPLEX_KEY_BITS)) {
@@ -1204,7 +1208,7 @@ static void ad_rx_machine(struct lacpdu 
 			// detect loopback situation
 			if (!MAC_ADDRESS_COMPARE(&(lacpdu->actor_system), &(port->actor_system))) {
 				// INFO_RECEIVED_LOOPBACK_FRAMES
-				printk(KERN_ERR "bonding: An illegal loopback occurred on adapter (%s)\n",
+				printk(KERN_ERR DRV_NAME ": An illegal loopback occurred on adapter (%s)\n",
 						port->slave->dev->name);
 				printk(KERN_ERR "Check the configuration to verify that all Adapters "
 						"are connected to 802.3ad compliant switch ports\n");
@@ -1245,7 +1249,7 @@ static void ad_tx_machine(struct port *p
 			__update_lacpdu_from_port(port);
 			// send the lacpdu
 			if (ad_lacpdu_send(port) >= 0) {
-				BOND_PRINT_DBG(("Sent LACPDU on port %d", port->actor_port_number));
+				dprintk("Sent LACPDU on port %d\n", port->actor_port_number);
 				// mark ntt as false, so it will not be sent again until demanded
 				port->ntt = 0;
 			}
@@ -1318,7 +1322,7 @@ static void ad_periodic_machine(struct p
 
 	// check if the state machine was changed
 	if (port->sm_periodic_state != last_state) {
-		BOND_PRINT_DBG(("Periodic Machine: Port=%d, Last State=%d, Curr State=%d", port->actor_port_number, last_state, port->sm_periodic_state));
+		dprintk("Periodic Machine: Port=%d, Last State=%d, Curr State=%d\n", port->actor_port_number, last_state, port->sm_periodic_state);
 		switch (port->sm_periodic_state) {
 		case AD_NO_PERIODIC:
 			port->sm_periodic_timer_counter = 0;	   // zero timer
@@ -1375,7 +1379,7 @@ static void ad_port_selection_logic(stru
 				port->next_port_in_aggregator=NULL;
 				port->actor_port_aggregator_identifier=0;
 
-				BOND_PRINT_DBG(("Port %d left LAG %d", port->actor_port_number, temp_aggregator->aggregator_identifier));
+				dprintk("Port %d left LAG %d\n", port->actor_port_number, temp_aggregator->aggregator_identifier);
 				// if the aggregator is empty, clear its parameters, and set it ready to be attached
 				if (!temp_aggregator->lag_ports) {
 					ad_clear_agg(temp_aggregator);
@@ -1384,7 +1388,7 @@ static void ad_port_selection_logic(stru
 			}
 		}
 		if (!curr_port) { // meaning: the port was related to an aggregator but was not on the aggregator port list
-			printk(KERN_WARNING "bonding: Warning: Port %d (on %s) was "
+			printk(KERN_WARNING DRV_NAME ": Warning: Port %d (on %s) was "
 			       "related to aggregator %d but was not on its port list\n",
 			       port->actor_port_number, port->slave->dev->name,
 			       port->aggregator->aggregator_identifier);
@@ -1417,7 +1421,7 @@ static void ad_port_selection_logic(stru
 			port->next_port_in_aggregator=aggregator->lag_ports;
 			port->aggregator->num_of_ports++;
 			aggregator->lag_ports=port;
-			BOND_PRINT_DBG(("Port %d joined LAG %d(existing LAG)", port->actor_port_number, port->aggregator->aggregator_identifier));
+			dprintk("Port %d joined LAG %d(existing LAG)\n", port->actor_port_number, port->aggregator->aggregator_identifier);
 
 			// mark this port as selected
 			port->sm_vars |= AD_PORT_SELECTED;
@@ -1454,9 +1458,9 @@ static void ad_port_selection_logic(stru
 			// mark this port as selected
 			port->sm_vars |= AD_PORT_SELECTED;
 
-			BOND_PRINT_DBG(("Port %d joined LAG %d(new LAG)", port->actor_port_number, port->aggregator->aggregator_identifier));
+			dprintk("Port %d joined LAG %d(new LAG)\n", port->actor_port_number, port->aggregator->aggregator_identifier);
 		} else {
-			printk(KERN_ERR "bonding: Port %d (on %s) did not find a suitable aggregator\n",
+			printk(KERN_ERR DRV_NAME ": Port %d (on %s) did not find a suitable aggregator\n",
 			       port->actor_port_number, port->slave->dev->name);
 		}
 	}
@@ -1580,30 +1584,30 @@ static void ad_agg_selection_logic(struc
 		    aggregator;
 		    aggregator = __get_next_agg(aggregator)) {
 
-			BOND_PRINT_DBG(("Agg=%d; Ports=%d; a key=%d; p key=%d; Indiv=%d; Active=%d",
+			dprintk("Agg=%d; Ports=%d; a key=%d; p key=%d; Indiv=%d; Active=%d\n",
 					aggregator->aggregator_identifier, aggregator->num_of_ports,
 					aggregator->actor_oper_aggregator_key, aggregator->partner_oper_aggregator_key,
-					aggregator->is_individual, aggregator->is_active));
+					aggregator->is_individual, aggregator->is_active);
 		}
 
 		// check if any partner replys
 		if (best_aggregator->is_individual) {
-			printk(KERN_WARNING "bonding: Warning: No 802.3ad response from the link partner "
+			printk(KERN_WARNING DRV_NAME ": Warning: No 802.3ad response from the link partner "
 					"for any adapters in the bond\n");
 		}
 
 		// check if there are more than one aggregator
 		if (num_of_aggs > 1) {
-			BOND_PRINT_DBG(("Warning: More than one Link Aggregation Group was "
-					"found in the bond. Only one group will function in the bond"));
+			dprintk("Warning: More than one Link Aggregation Group was "
+				"found in the bond. Only one group will function in the bond\n");
 		}
 
 		best_aggregator->is_active = 1;
-		BOND_PRINT_DBG(("LAG %d choosed as the active LAG", best_aggregator->aggregator_identifier));
-		BOND_PRINT_DBG(("Agg=%d; Ports=%d; a key=%d; p key=%d; Indiv=%d; Active=%d",
+		dprintk("LAG %d choosed as the active LAG\n", best_aggregator->aggregator_identifier);
+		dprintk("Agg=%d; Ports=%d; a key=%d; p key=%d; Indiv=%d; Active=%d\n",
 				best_aggregator->aggregator_identifier, best_aggregator->num_of_ports,
 				best_aggregator->actor_oper_aggregator_key, best_aggregator->partner_oper_aggregator_key,
-				best_aggregator->is_individual, best_aggregator->is_active));
+				best_aggregator->is_individual, best_aggregator->is_active);
 
 		// disable the ports that were related to the former active_aggregator
 		if (last_active_aggregator) {
@@ -1644,7 +1648,7 @@ static void ad_clear_agg(struct aggregat
 		aggregator->lag_ports = NULL;
 		aggregator->is_active = 0;
 		aggregator->num_of_ports = 0;
-		BOND_PRINT_DBG(("LAG %d was cleared", aggregator->aggregator_identifier));
+		dprintk("LAG %d was cleared\n", aggregator->aggregator_identifier);
 	}
 }
 
@@ -1729,7 +1733,7 @@ static void ad_initialize_port(struct po
 static void ad_enable_collecting_distributing(struct port *port)
 {
 	if (port->aggregator->is_active) {
-		BOND_PRINT_DBG(("Enabling port %d(LAG %d)", port->actor_port_number, port->aggregator->aggregator_identifier));
+		dprintk("Enabling port %d(LAG %d)\n", port->actor_port_number, port->aggregator->aggregator_identifier);
 		__enable_port(port);
 	}
 }
@@ -1742,7 +1746,7 @@ static void ad_enable_collecting_distrib
 static void ad_disable_collecting_distributing(struct port *port)
 {
 	if (port->aggregator && MAC_ADDRESS_COMPARE(&(port->aggregator->partner_system), &(null_mac_addr))) {
-		BOND_PRINT_DBG(("Disabling port %d(LAG %d)", port->actor_port_number, port->aggregator->aggregator_identifier));
+		dprintk("Disabling port %d(LAG %d)\n", port->actor_port_number, port->aggregator->aggregator_identifier);
 		__disable_port(port);
 	}
 }
@@ -1780,7 +1784,7 @@ static void ad_marker_info_send(struct p
 
 	// send the marker information
 	if (ad_marker_send(port, &marker) >= 0) {
-		BOND_PRINT_DBG(("Sent Marker Information on port %d", port->actor_port_number));
+		dprintk("Sent Marker Information on port %d\n", port->actor_port_number);
 	}
 }
 #endif
@@ -1803,7 +1807,7 @@ static void ad_marker_info_received(stru
 	// send the marker response
 
 	if (ad_marker_send(port, &marker) >= 0) {
-		BOND_PRINT_DBG(("Sent Marker Response on port %d", port->actor_port_number));
+		dprintk("Sent Marker Response on port %d\n", port->actor_port_number);
 	}
 }
 
@@ -1890,13 +1894,13 @@ static u16 aggregator_identifier;
 void bond_3ad_initialize(struct bonding *bond, u16 tick_resolution, int lacp_fast)
 {                         
 	// check that the bond is not initialized yet
-	if (MAC_ADDRESS_COMPARE(&(BOND_AD_INFO(bond).system.sys_mac_addr), &(bond->device->dev_addr))) {
+	if (MAC_ADDRESS_COMPARE(&(BOND_AD_INFO(bond).system.sys_mac_addr), &(bond->dev->dev_addr))) {
 
 		aggregator_identifier = 0;
 
 		BOND_AD_INFO(bond).lacp_fast = lacp_fast;
 		BOND_AD_INFO(bond).system.sys_priority = 0xFFFF;
-		BOND_AD_INFO(bond).system.sys_mac_addr = *((struct mac_addr *)bond->device->dev_addr);
+		BOND_AD_INFO(bond).system.sys_mac_addr = *((struct mac_addr *)bond->dev->dev_addr);
 
 		// initialize how many times this module is called in one second(should be about every 100ms)
 		ad_ticks_per_sec = tick_resolution;
@@ -1921,7 +1925,7 @@ int bond_3ad_bind_slave(struct slave *sl
 	struct aggregator *aggregator;
 
 	if (bond == NULL) {
-		printk(KERN_CRIT "The slave %s is not attached to its bond\n", slave->dev->name);
+		printk(KERN_ERR "The slave %s is not attached to its bond\n", slave->dev->name);
 		return -1;
 	}
 
@@ -1964,7 +1968,7 @@ int bond_3ad_bind_slave(struct slave *sl
 
 		ad_initialize_agg(aggregator);
 
-		aggregator->aggregator_mac_address = *((struct mac_addr *)bond->device->dev_addr);
+		aggregator->aggregator_mac_address = *((struct mac_addr *)bond->dev->dev_addr);
 		aggregator->aggregator_identifier = (++aggregator_identifier);
 		aggregator->slave = slave;
 		aggregator->is_active = 0;
@@ -1996,11 +2000,11 @@ void bond_3ad_unbind_slave(struct slave 
 
 	// if slave is null, the whole port is not initialized
 	if (!port->slave) {
-		printk(KERN_WARNING "bonding: Trying to unbind an uninitialized port on %s\n", slave->dev->name);
+		printk(KERN_WARNING DRV_NAME ": Trying to unbind an uninitialized port on %s\n", slave->dev->name);
 		return;
 	}
 
-	BOND_PRINT_DBG(("Unbinding Link Aggregation Group %d", aggregator->aggregator_identifier));
+	dprintk("Unbinding Link Aggregation Group %d\n", aggregator->aggregator_identifier);
 
 	/* Tell the partner that this port is not suitable for aggregation */
 	port->actor_oper_port_state &= ~AD_STATE_AGGREGATION;
@@ -2024,10 +2028,10 @@ void bond_3ad_unbind_slave(struct slave 
 			// if new aggregator found, copy the aggregator's parameters
 			// and connect the related lag_ports to the new aggregator
 			if ((new_aggregator) && ((!new_aggregator->lag_ports) || ((new_aggregator->lag_ports == port) && !new_aggregator->lag_ports->next_port_in_aggregator))) {
-				BOND_PRINT_DBG(("Some port(s) related to LAG %d - replaceing with LAG %d", aggregator->aggregator_identifier, new_aggregator->aggregator_identifier));
+				dprintk("Some port(s) related to LAG %d - replaceing with LAG %d\n", aggregator->aggregator_identifier, new_aggregator->aggregator_identifier);
 
 				if ((new_aggregator->lag_ports == port) && new_aggregator->is_active) {
-					printk(KERN_INFO "bonding: Removing an active aggregator\n");
+					printk(KERN_INFO DRV_NAME ": Removing an active aggregator\n");
 					// select new active aggregator
 					 select_new_active_agg = 1;
 				}
@@ -2057,7 +2061,7 @@ void bond_3ad_unbind_slave(struct slave 
 					ad_agg_selection_logic(__get_first_agg(port));
 				}
 			} else {
-				printk(KERN_WARNING "bonding: Warning: unbinding aggregator, "
+				printk(KERN_WARNING DRV_NAME ": Warning: unbinding aggregator, "
 				       "and could not find a new aggregator for its ports\n");
 			}
 		} else { // in case that the only port related to this aggregator is the one we want to remove
@@ -2072,7 +2076,7 @@ void bond_3ad_unbind_slave(struct slave 
 		}
 	}
 
-	BOND_PRINT_DBG(("Unbinding port %d", port->actor_port_number));
+	dprintk("Unbinding port %d\n", port->actor_port_number);
 	// find the aggregator that this port is connected to
 	temp_aggregator = __get_first_agg(port);
 	for (; temp_aggregator; temp_aggregator = __get_next_agg(temp_aggregator)) {
@@ -2123,13 +2127,13 @@ void bond_3ad_state_machine_handler(stru
 
 	read_lock(&bond->lock);
 
-	//check if there are any slaves
-	if (bond->next == (struct slave *)bond) {
-		goto end;
+	if (bond->kill_timers) {
+		goto out;
 	}
 
-	if ((bond->device->flags & IFF_UP) != IFF_UP) {
-		goto end;
+	//check if there are any slaves
+	if (bond->slave_cnt == 0) {
+		goto re_arm;
 	}
 
 	// check if agg_select_timer timer after initialize is timed out
@@ -2137,8 +2141,8 @@ void bond_3ad_state_machine_handler(stru
 		// select the active aggregator for the bond
 		if ((port = __get_first_port(bond))) {
 			if (!port->slave) {
-				printk(KERN_WARNING "bonding: Warning: bond's first port is uninitialized\n");
-				goto end;
+				printk(KERN_WARNING DRV_NAME ": Warning: bond's first port is uninitialized\n");
+				goto re_arm;
 			}
 
 			aggregator = __get_first_agg(port);
@@ -2149,8 +2153,8 @@ void bond_3ad_state_machine_handler(stru
 	// for each port run the state machines
 	for (port = __get_first_port(bond); port; port = __get_next_port(port)) {
 		if (!port->slave) {
-			printk(KERN_WARNING "bonding: Warning: Found an uninitialized port\n");
-			goto end;
+			printk(KERN_WARNING DRV_NAME ": Warning: Found an uninitialized port\n");
+			goto re_arm;
 		}
 
 		ad_rx_machine(NULL, port);
@@ -2165,14 +2169,10 @@ void bond_3ad_state_machine_handler(stru
 		}
 	}
 
-end:
+re_arm:
+	mod_timer(&(BOND_AD_INFO(bond).ad_timer), jiffies + ad_delta_in_ticks);
+out:
 	read_unlock(&bond->lock);
-
-
-	if ((bond->device->flags & IFF_UP) == IFF_UP) {
-		/* re-arm the timer */
-		mod_timer(&(BOND_AD_INFO(bond).ad_timer), jiffies + (AD_TIMER_INTERVAL * HZ / 1000));
-	}
 }
 
 /**
@@ -2194,14 +2194,14 @@ void bond_3ad_rx_indication(struct lacpd
 		port = &(SLAVE_AD_INFO(slave).port);
 
 		if (!port->slave) {
-			printk(KERN_WARNING "bonding: Warning: port of slave %s is uninitialized\n", slave->dev->name);
+			printk(KERN_WARNING DRV_NAME ": Warning: port of slave %s is uninitialized\n", slave->dev->name);
 			return;
 		}
 
 		switch (lacpdu->subtype) {
 		case AD_TYPE_LACPDU:
 			__ntohs_lacpdu(lacpdu);
-			BOND_PRINT_DBG(("Received LACPDU on port %d", port->actor_port_number));
+			dprintk("Received LACPDU on port %d\n", port->actor_port_number);
 			ad_rx_machine(lacpdu, port);
 			break;
 
@@ -2210,17 +2210,17 @@ void bond_3ad_rx_indication(struct lacpd
 
 			switch (((struct marker *)lacpdu)->tlv_type) {
 			case AD_MARKER_INFORMATION_SUBTYPE:
-				BOND_PRINT_DBG(("Received Marker Information on port %d", port->actor_port_number));
+				dprintk("Received Marker Information on port %d\n", port->actor_port_number);
 				ad_marker_info_received((struct marker *)lacpdu, port);
 				break;
 
 			case AD_MARKER_RESPONSE_SUBTYPE:
-				BOND_PRINT_DBG(("Received Marker Response on port %d", port->actor_port_number));
+				dprintk("Received Marker Response on port %d\n", port->actor_port_number);
 				ad_marker_response_received((struct marker *)lacpdu, port);
 				break;
 
 			default:
-				BOND_PRINT_DBG(("Received an unknown Marker subtype on slot %d", port->actor_port_number));
+				dprintk("Received an unknown Marker subtype on slot %d\n", port->actor_port_number);
 			}
 		}
 	}
@@ -2240,14 +2240,14 @@ void bond_3ad_adapter_speed_changed(stru
 
 	// if slave is null, the whole port is not initialized
 	if (!port->slave) {
-		printk(KERN_WARNING "bonding: Warning: speed changed for uninitialized port on %s\n",
+		printk(KERN_WARNING DRV_NAME ": Warning: speed changed for uninitialized port on %s\n",
 		       slave->dev->name);
 		return;
 	}
 
 	port->actor_admin_port_key &= ~AD_SPEED_KEY_BITS;
 	port->actor_oper_port_key=port->actor_admin_port_key |= (__get_link_speed(port) << 1);
-	BOND_PRINT_DBG(("Port %d changed speed", port->actor_port_number));
+	dprintk("Port %d changed speed\n", port->actor_port_number);
 	// there is no need to reselect a new aggregator, just signal the
 	// state machines to reinitialize
 	port->sm_vars |= AD_PORT_BEGIN;
@@ -2267,14 +2267,14 @@ void bond_3ad_adapter_duplex_changed(str
 
 	// if slave is null, the whole port is not initialized
 	if (!port->slave) {
-		printk(KERN_WARNING "bonding: Warning: duplex changed for uninitialized port on %s\n",
+		printk(KERN_WARNING DRV_NAME ": Warning: duplex changed for uninitialized port on %s\n",
 		       slave->dev->name);
 		return;
 	}
 
 	port->actor_admin_port_key &= ~AD_DUPLEX_KEY_BITS;
 	port->actor_oper_port_key=port->actor_admin_port_key |= __get_duplex(port);
-	BOND_PRINT_DBG(("Port %d changed duplex", port->actor_port_number));
+	dprintk("Port %d changed duplex\n", port->actor_port_number);
 	// there is no need to reselect a new aggregator, just signal the
 	// state machines to reinitialize
 	port->sm_vars |= AD_PORT_BEGIN;
@@ -2295,10 +2295,8 @@ void bond_3ad_handle_link_change(struct 
 
 	// if slave is null, the whole port is not initialized
 	if (!port->slave) {
-#ifdef BONDING_DEBUG
-		printk(KERN_WARNING "bonding: Warning: link status changed for uninitialized port on %s\n",
-		       slave->dev->name);
-#endif
+		printk(KERN_WARNING DRV_NAME ": Warning: link status changed for uninitialized port on %s\n",
+			slave->dev->name);
 		return;
 	}
 
@@ -2356,41 +2354,28 @@ int bond_3ad_get_active_agg_info(struct 
 
 int bond_3ad_xmit_xor(struct sk_buff *skb, struct net_device *dev)
 {
-	slave_t *slave, *start_at;
-	struct bonding *bond = (struct bonding *) dev->priv;
+	struct slave *slave, *start_at;
+	struct bonding *bond = dev->priv;
 	struct ethhdr *data = (struct ethhdr *)skb->data;
 	int slave_agg_no;
 	int slaves_in_agg;
 	int agg_id;
+	int i;
 	struct ad_info ad_info;
+	int res = 1;
 
-	if (!IS_UP(dev)) { /* bond down */
-		dev_kfree_skb(skb);
-		return 0;
-	}
-
-	if (bond == NULL) {
-		printk(KERN_CRIT "bonding: Error: bond is NULL on device %s\n", dev->name);
-		dev_kfree_skb(skb);
-		return 0;
-	}
-
+	/* make sure that the slaves list will
+	 * not change during tx
+	 */
 	read_lock(&bond->lock);
-	slave = bond->prev;
 
-	/* check if bond is empty */
-	if ((slave == (struct slave *) bond) || (bond->slave_cnt == 0)) {
-		printk(KERN_DEBUG "ERROR: bond is empty\n");
-		dev_kfree_skb(skb);
-		read_unlock(&bond->lock);
-		return 0;
+	if (!BOND_IS_OK(bond)) {
+		goto out;
 	}
 
 	if (bond_3ad_get_active_agg_info(bond, &ad_info)) {
 		printk(KERN_DEBUG "ERROR: bond_3ad_get_active_agg_info failed\n");
-		dev_kfree_skb(skb);
-		read_unlock(&bond->lock);
-		return 0;
+		goto out;
 	}
 
 	slaves_in_agg = ad_info.ports;
@@ -2399,21 +2384,12 @@ int bond_3ad_xmit_xor(struct sk_buff *sk
 	if (slaves_in_agg == 0) {
 		/*the aggregator is empty*/
 		printk(KERN_DEBUG "ERROR: active aggregator is empty\n");
-		dev_kfree_skb(skb);
-		read_unlock(&bond->lock);
-		return 0;
+		goto out;
 	}
 
-	/* we're at the root, get the first slave */
-	if ((slave == NULL) || (slave->dev == NULL)) {
-		/* no suitable interface, frame not sent */
-		dev_kfree_skb(skb);
-		read_unlock(&bond->lock);
-		return 0;
-	}
+	slave_agg_no = (data->h_dest[5]^bond->dev->dev_addr[5]) % slaves_in_agg;
 
-	slave_agg_no = (data->h_dest[5]^slave->dev->dev_addr[5]) % slaves_in_agg;
-	while (slave != (slave_t *)bond) {
+	bond_for_each_slave(bond, slave, i) {
 		struct aggregator *agg = SLAVE_AD_INFO(slave).port.aggregator;
 
 		if (agg && (agg->aggregator_identifier == agg_id)) {
@@ -2422,61 +2398,41 @@ int bond_3ad_xmit_xor(struct sk_buff *sk
 				break;
 			}
 		}
-
-		slave = slave->prev;
-		if (slave == NULL) {
-			printk(KERN_ERR "bonding: Error: slave is NULL\n");
-			dev_kfree_skb(skb);
-			read_unlock(&bond->lock);
-			return 0;
-		}
 	}
 
-	if (slave == (slave_t *)bond) {
-		printk(KERN_ERR "bonding: Error: Couldn't find a slave to tx on for aggregator ID %d\n", agg_id);
-		dev_kfree_skb(skb);
-		read_unlock(&bond->lock);
-		return 0;
+	if (slave_agg_no >= 0) {
+		printk(KERN_ERR DRV_NAME ": Error: Couldn't find a slave to tx on for aggregator ID %d\n", agg_id);
+		goto out;
 	}
 
 	start_at = slave;
 
-	do {
+	bond_for_each_slave_from(bond, slave, i, start_at) {
 		int slave_agg_id = 0;
-		struct aggregator *agg;
-
-		if (slave == NULL) {
-			printk(KERN_ERR "bonding: Error: slave is NULL\n");
-			dev_kfree_skb(skb);
-			read_unlock(&bond->lock);
-			return 0;
-		}
-
-		agg = SLAVE_AD_INFO(slave).port.aggregator;
+		struct aggregator *agg = SLAVE_AD_INFO(slave).port.aggregator;
 
 		if (agg) {
 			slave_agg_id = agg->aggregator_identifier;
 		}
 
-		if (SLAVE_IS_OK(slave) && 
-		    agg && (slave_agg_id == agg_id)) {
-			skb->dev = slave->dev;			
-			skb->priority = 1;
-			dev_queue_xmit(skb);
-			read_unlock(&bond->lock);
-			return 0;
+		if (SLAVE_IS_OK(slave) && agg && (slave_agg_id == agg_id)) {
+			res = bond_dev_queue_xmit(bond, skb, slave->dev);
+			break;
 		}
-	} while ((slave = slave->next) != start_at);
+	}
 
-	/* no suitable interface, frame not sent */
-	dev_kfree_skb(skb);
+out:
+	if (res) {
+		/* no suitable interface, frame not sent */
+		dev_kfree_skb(skb);
+	}
 	read_unlock(&bond->lock);
 	return 0;
 }
 
 int bond_3ad_lacpdu_recv(struct sk_buff *skb, struct net_device *dev, struct packet_type* ptype)
 {
-	struct bonding *bond = (struct bonding *)dev->priv;
+	struct bonding *bond = dev->priv;
 	struct slave *slave = NULL;
 	int ret = NET_RX_DROP;
 
diff -Nur --show-c-function linux-2.4.25/drivers/net/bonding/bond_3ad.h linux-2.4.26-pre2/drivers/net/bonding/bond_3ad.h
--- linux-2.4.25/drivers/net/bonding/bond_3ad.h	2003-08-25 08:44:42.000000000 -0300
+++ linux-2.4.26-pre2/drivers/net/bonding/bond_3ad.h	2004-03-06 15:17:09.000000000 -0300
@@ -1,5 +1,5 @@
 /*
- * Copyright(c) 1999 - 2003 Intel Corporation. All rights reserved.
+ * Copyright(c) 1999 - 2004 Intel Corporation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
@@ -28,6 +28,9 @@
  * 2003/05/01 - Shmulik Hen <shmulik.hen at intel dot com>
  *	- Renamed bond_3ad_link_status_changed() to
  *	  bond_3ad_handle_link_change() for compatibility with TLB.
+ *
+ * 2003/12/01 - Shmulik Hen <shmulik.hen at intel dot com>
+ *	- Code cleanup and style changes
  */
 
 #ifndef __BOND_3AD_H__
diff -Nur --show-c-function linux-2.4.25/drivers/net/bonding/bond_alb.c linux-2.4.26-pre2/drivers/net/bonding/bond_alb.c
--- linux-2.4.25/drivers/net/bonding/bond_alb.c	2003-11-28 16:26:20.000000000 -0200
+++ linux-2.4.26-pre2/drivers/net/bonding/bond_alb.c	2004-03-06 15:15:58.000000000 -0300
@@ -1,5 +1,5 @@
 /*
- * Copyright(c) 1999 - 2003 Intel Corporation. All rights reserved.
+ * Copyright(c) 1999 - 2004 Intel Corporation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the
@@ -28,8 +28,19 @@
  * 2003/08/06 - Amir Noam <amir.noam at intel dot com>
  *	- Add support for setting bond's MAC address with special
  *	  handling required for ALB/TLB.
+ *
+ * 2003/12/01 - Shmulik Hen <shmulik.hen at intel dot com>
+ *	- Code cleanup and style changes
+ *
+ * 2003/12/30 - Amir Noam <amir.noam at intel dot com>
+ *	- Fixed: Cannot remove and re-enslave the original active slave.
+ *
+ * 2004/01/14 - Shmulik Hen <shmulik.hen at intel dot com>
+ *	- Add capability to tag self generated packets in ALB/TLB modes.
  */
 
+//#define BONDING_DEBUG 1
+
 #include <linux/skbuff.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
@@ -42,6 +53,7 @@
 #include <linux/if_arp.h>
 #include <linux/if_ether.h>
 #include <linux/if_bonding.h>
+#include <linux/if_vlan.h>
 #include <net/ipx.h>
 #include <net/arp.h>
 #include <asm/byteorder.h>
@@ -50,11 +62,11 @@
 
 
 #define ALB_TIMER_TICKS_PER_SEC	    10	/* should be a divisor of HZ */
-#define BOND_TLB_REBALANCE_INTERVAL 10	/* in seconds, periodic re-balancing
-					 * used for division - never set
+#define BOND_TLB_REBALANCE_INTERVAL 10	/* In seconds, periodic re-balancing.
+					 * Used for division - never set
 					 * to zero !!!
 					 */
-#define BOND_ALB_LP_INTERVAL	    1	/* in seconds periodic send of
+#define BOND_ALB_LP_INTERVAL	    1	/* In seconds, periodic send of
 					 * learning packets to the switch
 					 */
 
@@ -66,12 +78,12 @@
 
 #define TLB_HASH_TABLE_SIZE 256	/* The size of the clients hash table.
 				 * Note that this value MUST NOT be smaller
-				 * because the key hash table BYTE wide !
+				 * because the key hash table is BYTE wide !
 				 */
 
 
 #define TLB_NULL_INDEX		0xffffffff
-#define MAX_LP_RETRY		3
+#define MAX_LP_BURST		3
 
 /* rlb defs */
 #define RLB_HASH_TABLE_SIZE	256
@@ -86,12 +98,15 @@
  */
 #define RLB_PROMISC_TIMEOUT	10*ALB_TIMER_TICKS_PER_SEC
 
+static const u8 mac_bcast[ETH_ALEN] = {0xff,0xff,0xff,0xff,0xff,0xff};
+static const int alb_delta_in_ticks = HZ / ALB_TIMER_TICKS_PER_SEC;
+
 #pragma pack(1)
 struct learning_pkt {
 	u8 mac_dst[ETH_ALEN];
 	u8 mac_src[ETH_ALEN];
 	u16 type;
-	u8 padding[ETH_ZLEN - (2*ETH_ALEN + 2)];
+	u8 padding[ETH_ZLEN - ETH_HLEN];
 };
 
 struct arp_pkt {
@@ -110,13 +125,12 @@ struct arp_pkt {
 /* Forward declaration */
 static void alb_send_learning_packets(struct slave *slave, u8 mac_addr[]);
 
-static inline u8
-_simple_hash(u8 *hash_start, int hash_size)
+static inline u8 _simple_hash(u8 *hash_start, int hash_size)
 {
 	int i;
 	u8 hash = 0;
 
-	for (i=0; i<hash_size; i++) {
+	for (i = 0; i < hash_size; i++) {
 		hash ^= hash_start[i];
 	}
 
@@ -125,193 +139,151 @@ _simple_hash(u8 *hash_start, int hash_si
 
 /*********************** tlb specific functions ***************************/
 
-static inline void
-_lock_tx_hashtbl(struct bonding *bond)
+static inline void _lock_tx_hashtbl(struct bonding *bond)
 {
 	spin_lock(&(BOND_ALB_INFO(bond).tx_hashtbl_lock));
 }
 
-static inline void
-_unlock_tx_hashtbl(struct bonding *bond)
+static inline void _unlock_tx_hashtbl(struct bonding *bond)
 {
 	spin_unlock(&(BOND_ALB_INFO(bond).tx_hashtbl_lock));
 }
 
 /* Caller must hold tx_hashtbl lock */
-static inline void
-tlb_init_table_entry(struct bonding *bond, u8 index, u8 save_load)
+static inline void tlb_init_table_entry(struct tlb_client_info *entry, int save_load)
 {
-	struct tlb_client_info *entry;
-
-	if (BOND_ALB_INFO(bond).tx_hashtbl == NULL) {
-		return;
-	}
-
-	entry = &(BOND_ALB_INFO(bond).tx_hashtbl[index]);
-	/* at end of cycle, save the load that was transmitted to the client
-	 * during the cycle, and set the tx_bytes counter to 0 for counting
-	 * the load during the next cycle
-	 */
 	if (save_load) {
 		entry->load_history = 1 + entry->tx_bytes /
-			BOND_TLB_REBALANCE_INTERVAL;
+				      BOND_TLB_REBALANCE_INTERVAL;
 		entry->tx_bytes = 0;
 	}
+
 	entry->tx_slave = NULL;
 	entry->next = TLB_NULL_INDEX;
 	entry->prev = TLB_NULL_INDEX;
 }
 
-static inline void
-tlb_init_slave(struct slave *slave)
+static inline void tlb_init_slave(struct slave *slave)
 {
-	struct tlb_slave_info *slave_info = &(SLAVE_TLB_INFO(slave));
-
-	slave_info->load = 0;
-	slave_info->head = TLB_NULL_INDEX;
+	SLAVE_TLB_INFO(slave).load = 0;
+	SLAVE_TLB_INFO(slave).head = TLB_NULL_INDEX;
 }
 
 /* Caller must hold bond lock for read */
-static inline void
-tlb_clear_slave(struct bonding *bond, struct slave *slave, u8 save_load)
+static void tlb_clear_slave(struct bonding *bond, struct slave *slave, int save_load)
 {
-	struct tlb_client_info *tx_hash_table = NULL;
-	u32 index, next_index;
+	struct tlb_client_info *tx_hash_table;
+	u32 index;
 
-	/* clear slave from tx_hashtbl */
 	_lock_tx_hashtbl(bond);
+
+	/* clear slave from tx_hashtbl */
 	tx_hash_table = BOND_ALB_INFO(bond).tx_hashtbl;
 
-	if (tx_hash_table) {
-		index = SLAVE_TLB_INFO(slave).head;
-		while (index != TLB_NULL_INDEX) {
-			next_index = tx_hash_table[index].next;
-			tlb_init_table_entry(bond, index, save_load);
-			index = next_index;
-		}
+	index = SLAVE_TLB_INFO(slave).head;
+	while (index != TLB_NULL_INDEX) {
+		u32 next_index = tx_hash_table[index].next;
+		tlb_init_table_entry(&tx_hash_table[index], save_load);
+		index = next_index;
 	}
+
 	_unlock_tx_hashtbl(bond);
 
 	tlb_init_slave(slave);
 }
 
 /* Must be called before starting the monitor timer */
-static int
-tlb_initialize(struct bonding *bond)
+static int tlb_initialize(struct bonding *bond)
 {
 	struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
+	int size = TLB_HASH_TABLE_SIZE * sizeof(struct tlb_client_info);
 	int i;
-	size_t size;
-
-#if(TLB_HASH_TABLE_SIZE != 256)
-	/* Key to the hash table is byte wide. Check the size! */
-	#error Hash Table size is wrong.
-#endif
 
 	spin_lock_init(&(bond_info->tx_hashtbl_lock));
 
 	_lock_tx_hashtbl(bond);
-	if (bond_info->tx_hashtbl != NULL) {
-		printk (KERN_ERR "%s: TLB hash table is not NULL\n",
-			bond->device->name);
-		_unlock_tx_hashtbl(bond);
-		return -1;
-	}
 
-	size = TLB_HASH_TABLE_SIZE * sizeof(struct tlb_client_info);
 	bond_info->tx_hashtbl = kmalloc(size, GFP_KERNEL);
-	if (bond_info->tx_hashtbl == NULL) {
-		printk (KERN_ERR "%s: Failed to allocate TLB hash table\n",
-			bond->device->name);
+	if (!bond_info->tx_hashtbl) {
+		printk(KERN_ERR DRV_NAME
+		       ": Error: %s: Failed to allocate TLB hash table\n",
+		       bond->dev->name);
 		_unlock_tx_hashtbl(bond);
 		return -1;
 	}
 
 	memset(bond_info->tx_hashtbl, 0, size);
-	for (i=0; i<TLB_HASH_TABLE_SIZE; i++) {
-		tlb_init_table_entry(bond, i, 1);
+
+	for (i = 0; i < TLB_HASH_TABLE_SIZE; i++) {
+		tlb_init_table_entry(&bond_info->tx_hashtbl[i], 1);
 	}
+
 	_unlock_tx_hashtbl(bond);
 
 	return 0;
 }
 
 /* Must be called only after all slaves have been released */
-static void
-tlb_deinitialize(struct bonding *bond)
+static void tlb_deinitialize(struct bonding *bond)
 {
 	struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
 
 	_lock_tx_hashtbl(bond);
-	if (bond_info->tx_hashtbl == NULL) {
-		_unlock_tx_hashtbl(bond);
-		return;
-	}
+
 	kfree(bond_info->tx_hashtbl);
 	bond_info->tx_hashtbl = NULL;
+
 	_unlock_tx_hashtbl(bond);
 }
 
 /* Caller must hold bond lock for read */
-static struct slave*
-tlb_get_least_loaded_slave(struct bonding *bond)
+static struct slave *tlb_get_least_loaded_slave(struct bonding *bond)
 {
-	struct slave *slave;
-	struct slave *least_loaded;
-	s64 curr_gap, max_gap;
+	struct slave *slave, *least_loaded;
+	s64 max_gap;
+	int i, found = 0;
 
 	/* Find the first enabled slave */
-	slave = bond_get_first_slave(bond);
-	while (slave) {
+	bond_for_each_slave(bond, slave, i) {
 		if (SLAVE_IS_OK(slave)) {
+			found = 1;
 			break;
 		}
-		slave = bond_get_next_slave(bond, slave);
 	}
 
-	if (!slave) {
+	if (!found) {
 		return NULL;
 	}
 
 	least_loaded = slave;
-	max_gap = (s64)(slave->speed * 1000000) -
-			(s64)(SLAVE_TLB_INFO(slave).load * 8);
+	max_gap = (s64)(slave->speed << 20) - /* Convert to Megabit per sec */
+			(s64)(SLAVE_TLB_INFO(slave).load << 3); /* Bytes to bits */
 
 	/* Find the slave with the largest gap */
-	slave = bond_get_next_slave(bond, slave);
-	while (slave) {
+	bond_for_each_slave_from(bond, slave, i, least_loaded) {
 		if (SLAVE_IS_OK(slave)) {
-			curr_gap = (s64)(slave->speed * 1000000) -
-					(s64)(SLAVE_TLB_INFO(slave).load * 8);
-			if (max_gap < curr_gap) {
+			s64 gap = (s64)(slave->speed << 20) -
+					(s64)(SLAVE_TLB_INFO(slave).load << 3);
+			if (max_gap < gap) {
 				least_loaded = slave;
-				max_gap = curr_gap;
+				max_gap = gap;
 			}
 		}
-		slave = bond_get_next_slave(bond, slave);
 	}
 
 	return least_loaded;
 }
 
 /* Caller must hold bond lock for read */
-struct slave*
-tlb_choose_channel(struct bonding *bond, u32 hash_index, u32 skb_len)
+struct slave *tlb_choose_channel(struct bonding *bond, u32 hash_index, u32 skb_len)
 {
 	struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
-	struct tlb_client_info *hash_table = NULL;
-	struct slave *assigned_slave = NULL;
+	struct tlb_client_info *hash_table;
+	struct slave *assigned_slave;
 
 	_lock_tx_hashtbl(bond);
 
 	hash_table = bond_info->tx_hashtbl;
-	if (hash_table == NULL) {
-		printk (KERN_ERR "%s: TLB hash table is NULL\n",
-			bond->device->name);
-		_unlock_tx_hashtbl(bond);
-		return NULL;
-	}
-
 	assigned_slave = hash_table[hash_index].tx_slave;
 	if (!assigned_slave) {
 		assigned_slave = tlb_get_least_loaded_slave(bond);
@@ -345,14 +317,12 @@ tlb_choose_channel(struct bonding *bond,
 }
 
 /*********************** rlb specific functions ***************************/
-static inline void
-_lock_rx_hashtbl(struct bonding *bond)
+static inline void _lock_rx_hashtbl(struct bonding *bond)
 {
 	spin_lock(&(BOND_ALB_INFO(bond).rx_hashtbl_lock));
 }
 
-static inline void
-_unlock_rx_hashtbl(struct bonding *bond)
+static inline void _unlock_rx_hashtbl(struct bonding *bond)
 {
 	spin_unlock(&(BOND_ALB_INFO(bond).rx_hashtbl_lock));
 }
@@ -360,26 +330,20 @@ _unlock_rx_hashtbl(struct bonding *bond)
 /* when an ARP REPLY is received from a client update its info
  * in the rx_hashtbl
  */
-static void
-rlb_update_entry_from_arp(struct bonding *bond, struct arp_pkt *arp)
+static void rlb_update_entry_from_arp(struct bonding *bond, struct arp_pkt *arp)
 {
-	u32 hash_index;
-	struct rlb_client_info *client_info = NULL;
 	struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
+	struct rlb_client_info *client_info;
+	u32 hash_index;
 
 	_lock_rx_hashtbl(bond);
 
-	if (bond_info->rx_hashtbl == NULL) {
-		_unlock_rx_hashtbl(bond);
-		return;
-	}
-	hash_index = _simple_hash((u8*)&(arp->ip_src), 4);
+	hash_index = _simple_hash((u8*)&(arp->ip_src), sizeof(arp->ip_src));
 	client_info = &(bond_info->rx_hashtbl[hash_index]);
 
 	if ((client_info->assigned) &&
 	    (client_info->ip_src == arp->ip_dst) &&
 	    (client_info->ip_dst == arp->ip_src)) {
-
 		/* update the clients MAC address */
 		memcpy(client_info->mac_dst, arp->mac_src, ETH_ALEN);
 		client_info->ntt = 1;
@@ -389,66 +353,60 @@ rlb_update_entry_from_arp(struct bonding
 	_unlock_rx_hashtbl(bond);
 }
 
-static int
-rlb_arp_recv(struct sk_buff *skb,
-	     struct net_device *dev,
-	     struct packet_type* ptype)
+static int rlb_arp_recv(struct sk_buff *skb, struct net_device *bond_dev, struct packet_type *ptype)
 {
-	struct bonding *bond = (struct bonding *)dev->priv;
-	int ret = NET_RX_DROP;
+	struct bonding *bond = bond_dev->priv;
 	struct arp_pkt *arp = (struct arp_pkt *)skb->data;
+	int res = NET_RX_DROP;
 
-	if (!(dev->flags & IFF_MASTER)) {
+	if (!(bond_dev->flags & IFF_MASTER)) {
 		goto out;
 	}
 
 	if (!arp) {
-		printk(KERN_ERR "Packet has no ARP data\n");
+		dprintk("Packet has no ARP data\n");
 		goto out;
 	}
 
 	if (skb->len < sizeof(struct arp_pkt)) {
-		printk(KERN_ERR "Packet is too small to be an ARP\n");
+		dprintk("Packet is too small to be an ARP\n");
 		goto out;
 	}
 
 	if (arp->op_code == htons(ARPOP_REPLY)) {
 		/* update rx hash table for this ARP */
 		rlb_update_entry_from_arp(bond, arp);
-		BOND_PRINT_DBG(("Server received an ARP Reply from client"));
+		dprintk("Server received an ARP Reply from client\n");
 	}
 
-	ret = NET_RX_SUCCESS;
+	res = NET_RX_SUCCESS;
 
 out:
 	dev_kfree_skb(skb);
 
-	return ret;
+	return res;
 }
 
 /* Caller must hold bond lock for read */
-static struct slave*
-rlb_next_rx_slave(struct bonding *bond)
+static struct slave *rlb_next_rx_slave(struct bonding *bond)
 {
-	struct slave *rx_slave = NULL, *slave = NULL;
-	unsigned int i = 0;
 	struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
+	struct slave *rx_slave, *slave, *start_at;
+	int i = 0;
 
-	slave = bond_info->next_rx_slave;
-	if (slave == NULL) {
-		slave = bond->next;
+	if (bond_info->next_rx_slave) {
+		start_at = bond_info->next_rx_slave;
+	} else {
+		start_at = bond->first_slave;
 	}
 
-	/* this loop uses the circular linked list property of the
-	 * slave's list to go through all slaves
-	 */
-	for (i = 0; i < bond->slave_cnt; i++, slave = slave->next) {
+	rx_slave = NULL;
 
+	bond_for_each_slave_from(bond, slave, i, start_at) {
 		if (SLAVE_IS_OK(slave)) {
 			if (!rx_slave) {
 				rx_slave = slave;
-			}
-			else if (slave->speed > rx_slave->speed) {
+			} else if (slave->speed > rx_slave->speed) {
 				rx_slave = slave;
 			}
 		}
@@ -464,48 +422,41 @@ rlb_next_rx_slave(struct bonding *bond)
 /* teach the switch the mac of a disabled slave
  * on the primary for fault tolerance
  *
- * Caller must hold bond->ptrlock for write or bond lock for write
+ * Caller must hold bond->curr_slave_lock for write or bond lock for write
  */
-static void
-rlb_teach_disabled_mac_on_primary(struct bonding *bond, u8 addr[])
+static void rlb_teach_disabled_mac_on_primary(struct bonding *bond, u8 addr[])
 {
-	if (!bond->current_slave) {
+	if (!bond->curr_active_slave) {
 		return;
 	}
+
 	if (!bond->alb_info.primary_is_promisc) {
 		bond->alb_info.primary_is_promisc = 1;
-		dev_set_promiscuity(bond->current_slave->dev, 1);
+		dev_set_promiscuity(bond->curr_active_slave->dev, 1);
 	}
+
 	bond->alb_info.rlb_promisc_timeout_counter = 0;
 
-	alb_send_learning_packets(bond->current_slave, addr);
+	alb_send_learning_packets(bond->curr_active_slave, addr);
 }
 
 /* slave being removed should not be active at this point
  *
  * Caller must hold bond lock for read
  */
-static void
-rlb_clear_slave(struct bonding *bond, struct slave *slave)
+static void rlb_clear_slave(struct bonding *bond, struct slave *slave)
 {
-	struct rlb_client_info *rx_hash_table = NULL;
 	struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
-	u8 mac_bcast[ETH_ALEN] = {0xff,0xff,0xff,0xff,0xff,0xff};
+	struct rlb_client_info *rx_hash_table;
 	u32 index, next_index;
 
 	/* clear slave from rx_hashtbl */
 	_lock_rx_hashtbl(bond);
-	rx_hash_table = bond_info->rx_hashtbl;
-
-	if (rx_hash_table == NULL) {
-		_unlock_rx_hashtbl(bond);
-		return;
-	}
 
+	rx_hash_table = bond_info->rx_hashtbl;
 	index = bond_info->rx_hashtbl_head;
 	for (; index != RLB_NULL_INDEX; index = next_index) {
 		next_index = rx_hash_table[index].next;
-
 		if (rx_hash_table[index].slave == slave) {
 			struct slave *assigned_slave = rlb_next_rx_slave(bond);
 
@@ -533,48 +484,63 @@ rlb_clear_slave(struct bonding *bond, st
 
 	_unlock_rx_hashtbl(bond);
 
-	write_lock(&bond->ptrlock);
-	if (slave != bond->current_slave) {
+	write_lock(&bond->curr_slave_lock);
+
+	if (slave != bond->curr_active_slave) {
 		rlb_teach_disabled_mac_on_primary(bond, slave->dev->dev_addr);
 	}
-	write_unlock(&bond->ptrlock);
+
+	write_unlock(&bond->curr_slave_lock);
 }
 
-static void
-rlb_update_client(struct rlb_client_info *client_info)
+static void rlb_update_client(struct rlb_client_info *client_info)
 {
-	int i = 0;
+	int i;
 
-	if (client_info->slave == NULL) {
+	if (!client_info->slave) {
 		return;
 	}
 
-	for (i=0; i<RLB_ARP_BURST_SIZE; i++) {
-		arp_send(ARPOP_REPLY, ETH_P_ARP,
-			 client_info->ip_dst,
-			 client_info->slave->dev,
-			 client_info->ip_src,
-			 client_info->mac_dst,
-			 client_info->slave->dev->dev_addr,
-			 client_info->mac_dst);
+	for (i = 0; i < RLB_ARP_BURST_SIZE; i++) {
+		struct sk_buff *skb;
+
+		skb = arp_create(ARPOP_REPLY, ETH_P_ARP,
+				 client_info->ip_dst,
+				 client_info->slave->dev,
+				 client_info->ip_src,
+				 client_info->mac_dst,
+				 client_info->slave->dev->dev_addr,
+				 client_info->mac_dst);
+		if (!skb) {
+			printk(KERN_ERR DRV_NAME
+			       ": Error: failed to create an ARP packet\n");
+			continue;
+		}
+
+		skb->dev = client_info->slave->dev;
+
+		if (client_info->tag) {
+			skb = vlan_put_tag(skb, client_info->vlan_id);
+			if (!skb) {
+				printk(KERN_ERR DRV_NAME
+				       ": Error: failed to insert VLAN tag\n");
+				continue;
+			}
+		}
+
+		arp_xmit(skb);
 	}
 }
 
 /* sends ARP REPLIES that update the clients that need updating */
-static void
-rlb_update_rx_clients(struct bonding *bond)
+static void rlb_update_rx_clients(struct bonding *bond)
 {
-	u32 hash_index;
-	struct rlb_client_info *client_info = NULL;
 	struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
+	struct rlb_client_info *client_info;
+	u32 hash_index;
 
 	_lock_rx_hashtbl(bond);
 
-	if (bond_info->rx_hashtbl == NULL) {
-		_unlock_rx_hashtbl(bond);
-		return;
-	}
-
 	hash_index = bond_info->rx_hashtbl_head;
 	for (; hash_index != RLB_NULL_INDEX; hash_index = client_info->next) {
 		client_info = &(bond_info->rx_hashtbl[hash_index]);
@@ -595,22 +561,15 @@ rlb_update_rx_clients(struct bonding *bo
 }
 
 /* The slave was assigned a new mac address - update the clients */
-static void
-rlb_req_update_slave_clients(struct bonding *bond, struct slave *slave)
+static void rlb_req_update_slave_clients(struct bonding *bond, struct slave *slave)
 {
-	u32 hash_index;
-	u8 ntt = 0;
 	struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
-	u8 mac_bcast[ETH_ALEN] = {0xff,0xff,0xff,0xff,0xff,0xff};
-	struct rlb_client_info* client_info = NULL;
+	struct rlb_client_info *client_info;
+	int ntt = 0;
+	u32 hash_index;
 
 	_lock_rx_hashtbl(bond);
 
-	if (bond_info->rx_hashtbl == NULL) {
-		_unlock_rx_hashtbl(bond);
-		return;
-	}
-
 	hash_index = bond_info->rx_hashtbl_head;
 	for (; hash_index != RLB_NULL_INDEX; hash_index = client_info->next) {
 		client_info = &(bond_info->rx_hashtbl[hash_index]);
@@ -633,37 +592,31 @@ rlb_req_update_slave_clients(struct bond
 }
 
 /* mark all clients using src_ip to be updated */
-static void
-rlb_req_update_subnet_clients(struct bonding *bond, u32 src_ip)
+static void rlb_req_update_subnet_clients(struct bonding *bond, u32 src_ip)
 {
-	u32 hash_index;
 	struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
-	u8 mac_bcast[ETH_ALEN] = {0xff,0xff,0xff,0xff,0xff,0xff};
-	struct rlb_client_info *client_info = NULL;
+	struct rlb_client_info *client_info;
+	u32 hash_index;
 
 	_lock_rx_hashtbl(bond);
 
-	if (bond_info->rx_hashtbl == NULL) {
-		_unlock_rx_hashtbl(bond);
-		return;
-	}
-
 	hash_index = bond_info->rx_hashtbl_head;
 	for (; hash_index != RLB_NULL_INDEX; hash_index = client_info->next) {
 		client_info = &(bond_info->rx_hashtbl[hash_index]);
 
 		if (!client_info->slave) {
-			printk(KERN_ERR "Bonding: Error: found a client with no"
-			       " channel in the client's hash table\n");
+			printk(KERN_ERR DRV_NAME
+			       ": Error: found a client with no channel in "
+			       "the client's hash table\n");
 			continue;
 		}
 		/*update all clients using this src_ip, that are not assigned
-		 * to the team's address (current_slave) and have a known
+		 * to the team's address (curr_active_slave) and have a known
 		 * unicast mac address.
 		 */
 		if ((client_info->ip_src == src_ip) &&
 		    memcmp(client_info->slave->dev->dev_addr,
-			   bond->device->dev_addr, ETH_ALEN) &&
+			   bond->dev->dev_addr, ETH_ALEN) &&
 		    memcmp(client_info->mac_dst, mac_bcast, ETH_ALEN)) {
 			client_info->ntt = 1;
 			bond_info->rx_ntt = 1;
@@ -674,30 +627,23 @@ rlb_req_update_subnet_clients(struct bon
 }
 
 /* Caller must hold both bond and ptr locks for read */
-struct slave*
-rlb_choose_channel(struct bonding *bond, struct arp_pkt *arp)
+struct slave *rlb_choose_channel(struct sk_buff *skb, struct bonding *bond)
 {
 	struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
-	struct rlb_client_info *client_info = NULL;
+	struct arp_pkt *arp = (struct arp_pkt *)skb->nh.raw;
+	struct slave *assigned_slave;
+	struct rlb_client_info *client_info;
 	u32 hash_index = 0;
-	struct slave *assigned_slave = NULL;
-	u8 mac_bcast[ETH_ALEN] = {0xff,0xff,0xff,0xff,0xff,0xff};
 
 	_lock_rx_hashtbl(bond);
 
-	if (bond_info->rx_hashtbl == NULL) {
-		_unlock_rx_hashtbl(bond);
-		return NULL;
-	}
-
-	hash_index = _simple_hash((u8 *)&arp->ip_dst, 4);
+	hash_index = _simple_hash((u8 *)&arp->ip_dst, sizeof(arp->ip_src));
 	client_info = &(bond_info->rx_hashtbl[hash_index]);
 
-	if (client_info->assigned == 1) {
+	if (client_info->assigned) {
 		if ((client_info->ip_src == arp->ip_src) &&
 		    (client_info->ip_dst == arp->ip_dst)) {
 			/* the entry is already assigned to this client */
-
 			if (memcmp(arp->mac_dst, mac_bcast, ETH_ALEN)) {
 				/* update mac address from arp */
 				memcpy(client_info->mac_dst, arp->mac_dst, ETH_ALEN);
@@ -710,12 +656,12 @@ rlb_choose_channel(struct bonding *bond,
 			}
 		} else {
 			/* the entry is already assigned to some other client,
-			 * move the old client to primary (current_slave) so
+			 * move the old client to primary (curr_active_slave) so
 			 * that the new client can be assigned to this entry.
 			 */
-			if (bond->current_slave &&
-			    client_info->slave != bond->current_slave) {
-				client_info->slave = bond->current_slave;
+			if (bond->curr_active_slave &&
+			    client_info->slave != bond->curr_active_slave) {
+				client_info->slave = bond->curr_active_slave;
 				rlb_update_client(client_info);
 			}
 		}
@@ -736,11 +682,19 @@ rlb_choose_channel(struct bonding *bond,
 		if (memcmp(client_info->mac_dst, mac_bcast, ETH_ALEN)) {
 			client_info->ntt = 1;
 			bond->alb_info.rx_ntt = 1;
-		}
-		else {
+		} else {
 			client_info->ntt = 0;
 		}
 
+		if (!list_empty(&bond->vlan_list)) {
+			unsigned short vlan_id;
+			int res = vlan_get_tag(skb, &vlan_id);
+			if (!res) {
+				client_info->tag = 1;
+				client_info->vlan_id = vlan_id;
+			}
+		}
+
 		if (!client_info->assigned) {
 			u32 prev_tbl_head = bond_info->rx_hashtbl_head;
 			bond_info->rx_hashtbl_head = hash_index;
@@ -760,10 +714,9 @@ rlb_choose_channel(struct bonding *bond,
 
 /* chooses (and returns) transmit channel for arp reply
  * does not choose channel for other arp types since they are
- * sent on the current_slave
+ * sent on the curr_active_slave
  */
-static struct slave*
-rlb_arp_xmit(struct sk_buff *skb, struct bonding *bond)
+static struct slave *rlb_arp_xmit(struct sk_buff *skb, struct bonding *bond)
 {
 	struct arp_pkt *arp = (struct arp_pkt *)skb->nh.raw;
 	struct slave *tx_slave = NULL;
@@ -772,19 +725,18 @@ rlb_arp_xmit(struct sk_buff *skb, struct
 		/* the arp must be sent on the selected
 		* rx channel
 		*/
-		tx_slave = rlb_choose_channel(bond, arp);
+		tx_slave = rlb_choose_channel(skb, bond);
 		if (tx_slave) {
 			memcpy(arp->mac_src,tx_slave->dev->dev_addr, ETH_ALEN);
 		}
-		BOND_PRINT_DBG(("Server sent ARP Reply packet"));
+		dprintk("Server sent ARP Reply packet\n");
 	} else if (arp->op_code == __constant_htons(ARPOP_REQUEST)) {
-
 		/* Create an entry in the rx_hashtbl for this client as a
 		 * place holder.
 		 * When the arp reply is received the entry will be updated
 		 * with the correct unicast address of the client.
 		 */
-		rlb_choose_channel(bond, arp);
+		rlb_choose_channel(skb, bond);
 
 		/* The ARP relpy packets must be delayed so that
 		 * they can cancel out the influence of the ARP request.
@@ -797,34 +749,29 @@ rlb_arp_xmit(struct sk_buff *skb, struct
 		 * updated with their assigned mac.
 		 */
 		rlb_req_update_subnet_clients(bond, arp->ip_src);
-		BOND_PRINT_DBG(("Server sent ARP Request packet"));
+		dprintk("Server sent ARP Request packet\n");
 	}
 
 	return tx_slave;
 }
 
 /* Caller must hold bond lock for read */
-static void
-rlb_rebalance(struct bonding *bond)
+static void rlb_rebalance(struct bonding *bond)
 {
 	struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
-	struct slave *assigned_slave = NULL;
+	struct slave *assigned_slave;
+	struct rlb_client_info *client_info;
+	int ntt;
 	u32 hash_index;
-	struct rlb_client_info *client_info = NULL;
-	u8 ntt = 0;
 
 	_lock_rx_hashtbl(bond);
 
-	if (bond_info->rx_hashtbl == NULL) {
-		_unlock_rx_hashtbl(bond);
-		return;
-	}
-
+	ntt = 0;
 	hash_index = bond_info->rx_hashtbl_head;
 	for (; hash_index != RLB_NULL_INDEX; hash_index = client_info->next) {
 		client_info = &(bond_info->rx_hashtbl[hash_index]);
 		assigned_slave = rlb_next_rx_slave(bond);
-		if (assigned_slave && (client_info->slave != assigned_slave)){
+		if (assigned_slave && (client_info->slave != assigned_slave)) {
 			client_info->slave = assigned_slave;
 			client_info->ntt = 1;
 			ntt = 1;
@@ -839,97 +786,119 @@ rlb_rebalance(struct bonding *bond)
 }
 
 /* Caller must hold rx_hashtbl lock */
-static inline void
-rlb_init_table_entry(struct rlb_client_info *entry)
+static void rlb_init_table_entry(struct rlb_client_info *entry)
 {
+	memset(entry, 0, sizeof(struct rlb_client_info));
 	entry->next = RLB_NULL_INDEX;
 	entry->prev = RLB_NULL_INDEX;
-	entry->assigned = 0;
-	entry->ntt = 0;
 }
 
-static int
-rlb_initialize(struct bonding *bond)
+static int rlb_initialize(struct bonding *bond)
 {
 	struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
 	struct packet_type *pk_type = &(BOND_ALB_INFO(bond).rlb_pkt_type);
+	int size = RLB_HASH_TABLE_SIZE * sizeof(struct rlb_client_info);
 	int i;
-	size_t size;
 
 	spin_lock_init(&(bond_info->rx_hashtbl_lock));
 
 	_lock_rx_hashtbl(bond);
-	if (bond_info->rx_hashtbl != NULL) {
-		printk (KERN_ERR "%s: RLB hash table is not NULL\n",
-			bond->device->name);
-		_unlock_rx_hashtbl(bond);
-		return -1;
-	}
 
-	size = RLB_HASH_TABLE_SIZE * sizeof(struct rlb_client_info);
 	bond_info->rx_hashtbl = kmalloc(size, GFP_KERNEL);
-	if (bond_info->rx_hashtbl == NULL) {
-		printk (KERN_ERR "%s: Failed to allocate"
-			" RLB hash table\n", bond->device->name);
+	if (!bond_info->rx_hashtbl) {
+		printk(KERN_ERR DRV_NAME
+		       ": Error: %s: Failed to allocate RLB hash table\n",
+		       bond->dev->name);
 		_unlock_rx_hashtbl(bond);
 		return -1;
 	}
 
 	bond_info->rx_hashtbl_head = RLB_NULL_INDEX;
 
-	for (i=0; i<RLB_HASH_TABLE_SIZE; i++) {
+	for (i = 0; i < RLB_HASH_TABLE_SIZE; i++) {
 		rlb_init_table_entry(bond_info->rx_hashtbl + i);
 	}
-	_unlock_rx_hashtbl(bond);
 
-	/* register to receive ARPs */
+	_unlock_rx_hashtbl(bond);
 
 	/*initialize packet type*/
 	pk_type->type = __constant_htons(ETH_P_ARP);
-	pk_type->dev = bond->device;
+	pk_type->dev = bond->dev;
 	pk_type->func = rlb_arp_recv;
 	pk_type->data = (void*)1;  /* understand shared skbs */
 
+	/* register to receive ARPs */
 	dev_add_pack(pk_type);
 
 	return 0;
 }
 
-static void
-rlb_deinitialize(struct bonding *bond)
+static void rlb_deinitialize(struct bonding *bond)
 {
 	struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
 
 	dev_remove_pack(&(bond_info->rlb_pkt_type));
 
 	_lock_rx_hashtbl(bond);
-	if (bond_info->rx_hashtbl == NULL) {
-		_unlock_rx_hashtbl(bond);
-		return;
-	}
+
 	kfree(bond_info->rx_hashtbl);
 	bond_info->rx_hashtbl = NULL;
+	bond_info->rx_hashtbl_head = RLB_NULL_INDEX;
+
+	_unlock_rx_hashtbl(bond);
+}
+
+static void rlb_clear_vlan(struct bonding *bond, unsigned short vlan_id)
+{
+	struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
+	u32 curr_index;
+
+	_lock_rx_hashtbl(bond);
+
+	curr_index = bond_info->rx_hashtbl_head;
+	while (curr_index != RLB_NULL_INDEX) {
+		struct rlb_client_info *curr = &(bond_info->rx_hashtbl[curr_index]);
+		u32 next_index = bond_info->rx_hashtbl[curr_index].next;
+		u32 prev_index = bond_info->rx_hashtbl[curr_index].prev;
+
+		if (curr->tag && (curr->vlan_id == vlan_id)) {
+			if (curr_index == bond_info->rx_hashtbl_head) {
+				bond_info->rx_hashtbl_head = next_index;
+			}
+			if (prev_index != RLB_NULL_INDEX) {
+				bond_info->rx_hashtbl[prev_index].next = next_index;
+			}
+			if (next_index != RLB_NULL_INDEX) {
+				bond_info->rx_hashtbl[next_index].prev = prev_index;
+			}
+
+			rlb_init_table_entry(curr);
+		}
+
+		curr_index = next_index;
+	}
+
 	_unlock_rx_hashtbl(bond);
 }
 
 /*********************** tlb/rlb shared functions *********************/
 
-static void
-alb_send_learning_packets(struct slave *slave, u8 mac_addr[])
+static void alb_send_learning_packets(struct slave *slave, u8 mac_addr[])
 {
-	struct sk_buff *skb = NULL;
+	struct bonding *bond = bond_get_bond_by_slave(slave);
 	struct learning_pkt pkt;
-	char *data = NULL;
+	int size = sizeof(struct learning_pkt);
 	int i;
-	unsigned int size = sizeof(struct learning_pkt);
 
 	memset(&pkt, 0, size);
 	memcpy(pkt.mac_dst, mac_addr, ETH_ALEN);
 	memcpy(pkt.mac_src, mac_addr, ETH_ALEN);
 	pkt.type = __constant_htons(ETH_P_LOOP);
 
-	for (i=0; i < MAX_LP_RETRY; i++) {
-		skb = NULL;
+	for (i = 0; i < MAX_LP_BURST; i++) {
+		struct sk_buff *skb;
+		char *data;
+
 		skb = dev_alloc_skb(size);
 		if (!skb) {
 			return;
@@ -937,28 +906,46 @@ alb_send_learning_packets(struct slave *
 
 		data = skb_put(skb, size);
 		memcpy(data, &pkt, size);
+
 		skb->mac.raw = data;
 		skb->nh.raw = data + ETH_HLEN;
 		skb->protocol = pkt.type;
 		skb->priority = TC_PRIO_CONTROL;
 		skb->dev = slave->dev;
+
+		if (!list_empty(&bond->vlan_list)) {
+			struct vlan_entry *vlan;
+
+			vlan = bond_next_vlan(bond,
+					      bond->alb_info.current_alb_vlan);
+
+			bond->alb_info.current_alb_vlan = vlan;
+			if (!vlan) {
+				kfree_skb(skb);
+				continue;
+			}
+
+			skb = vlan_put_tag(skb, vlan->vlan_id);
+			if (!skb) {
+				printk(KERN_ERR DRV_NAME
+				       ": Error: failed to insert VLAN tag\n");
+				continue;
+			}
+		}
+
 		dev_queue_xmit(skb);
 	}
-
 }
 
 /* hw is a boolean parameter that determines whether we should try and
  * set the hw address of the device as well as the hw address of the
  * net_device
  */
-static int
-alb_set_slave_mac_addr(struct slave *slave, u8 addr[], int hw)
+static int alb_set_slave_mac_addr(struct slave *slave, u8 addr[], int hw)
 {
-	struct net_device *dev = NULL;
+	struct net_device *dev = slave->dev;
 	struct sockaddr s_addr;
 
-	dev = slave->dev;
-
 	if (!hw) {
 		memcpy(dev->dev_addr, addr, dev->addr_len);
 		return 0;
@@ -969,26 +956,23 @@ alb_set_slave_mac_addr(struct slave *sla
 	memcpy(s_addr.sa_data, addr, dev->addr_len);
 	s_addr.sa_family = dev->type;
 	if (dev->set_mac_address(dev, &s_addr)) {
-		printk(KERN_DEBUG "bonding: Error: alb_set_slave_mac_addr:"
-				  " dev->set_mac_address of dev %s failed!"
-				  " ALB mode requires that the base driver"
-				  " support setting the hw address also when"
-				  " the network device's interface is open\n",
-				  dev->name);
+		printk(KERN_ERR DRV_NAME
+		       ": Error: dev->set_mac_address of dev %s failed! ALB "
+		       "mode requires that the base driver support setting "
+		       "the hw address also when the network device's "
+		       "interface is open\n",
+		       dev->name);
 		return -EOPNOTSUPP;
 	}
 	return 0;
 }
 
-/* Caller must hold bond lock for write or ptrlock for write*/
-static void
-alb_swap_mac_addr(struct bonding *bond,
-		  struct slave *slave1,
-		  struct slave *slave2)
+/* Caller must hold bond lock for write or curr_slave_lock for write*/
+static void alb_swap_mac_addr(struct bonding *bond, struct slave *slave1, struct slave *slave2)
 {
-	u8 tmp_mac_addr[ETH_ALEN];
 	struct slave *disabled_slave = NULL;
-	u8 slaves_state_differ;
+	u8 tmp_mac_addr[ETH_ALEN];
+	int slaves_state_differ;
 
 	slaves_state_differ = (SLAVE_IS_OK(slave1) != SLAVE_IS_OK(slave2));
 
@@ -1005,8 +989,7 @@ alb_swap_mac_addr(struct bonding *bond,
 			 */
 			rlb_req_update_slave_clients(bond, slave1);
 		}
-	}
-	else {
+	} else {
 		disabled_slave = slave1;
 	}
 
@@ -1018,15 +1001,14 @@ alb_swap_mac_addr(struct bonding *bond,
 			 */
 			rlb_req_update_slave_clients(bond, slave2);
 		}
-	}
-	else {
+	} else {
 		disabled_slave = slave2;
 	}
 
 	if (bond->alb_info.rlb_enabled && slaves_state_differ) {
-			/* A disabled slave was assigned an active mac addr */
-			rlb_teach_disabled_mac_on_primary(bond,
-				disabled_slave->dev->dev_addr);
+		/* A disabled slave was assigned an active mac addr */
+		rlb_teach_disabled_mac_on_primary(bond,
+						  disabled_slave->dev->dev_addr);
 	}
 }
 
@@ -1044,10 +1026,8 @@ alb_swap_mac_addr(struct bonding *bond,
  *
  * Caller must hold bond lock
  */
-static void
-alb_change_hw_addr_on_detach(struct bonding *bond, struct slave *slave)
+static void alb_change_hw_addr_on_detach(struct bonding *bond, struct slave *slave)
 {
-	struct slave *tmp_slave;
 	int perm_curr_diff;
 	int perm_bond_diff;
 
@@ -1055,20 +1035,23 @@ alb_change_hw_addr_on_detach(struct bond
 				slave->dev->dev_addr,
 				ETH_ALEN);
 	perm_bond_diff = memcmp(slave->perm_hwaddr,
-				bond->device->dev_addr,
+				bond->dev->dev_addr,
 				ETH_ALEN);
+
 	if (perm_curr_diff && perm_bond_diff) {
-		tmp_slave = bond_get_first_slave(bond);
-		while (tmp_slave) {
+		struct slave *tmp_slave;
+		int i, found = 0;
+
+		bond_for_each_slave(bond, tmp_slave, i) {
 			if (!memcmp(slave->perm_hwaddr,
-				   tmp_slave->dev->dev_addr,
-				   ETH_ALEN)) {
+				    tmp_slave->dev->dev_addr,
+				    ETH_ALEN)) {
+				found = 1;
 				break;
 			}
-			tmp_slave = bond_get_next_slave(bond, tmp_slave);
 		}
 
-		if (tmp_slave) {
+		if (found) {
 			alb_swap_mac_addr(bond, slave, tmp_slave);
 		}
 	}
@@ -1099,10 +1082,11 @@ alb_change_hw_addr_on_detach(struct bond
  * caller must hold the bond lock for write since the mac addresses are compared
  * and may be swapped.
  */
-static int
-alb_handle_addr_collision_on_attach(struct bonding *bond, struct slave *slave)
+static int alb_handle_addr_collision_on_attach(struct bonding *bond, struct slave *slave)
 {
-	struct slave *tmp_slave1, *tmp_slave2;
+	struct slave *tmp_slave1, *tmp_slave2, *free_mac_slave;
+	struct slave *has_bond_addr = bond->curr_active_slave;
+	int i, j, found = 0;
 
 	if (bond->slave_cnt == 0) {
 		/* this is the first slave */
@@ -1113,65 +1097,78 @@ alb_handle_addr_collision_on_attach(stru
 	 * check uniqueness of slave's mac address against the other
 	 * slaves in the bond.
 	 */
-	if (memcmp(slave->perm_hwaddr, bond->device->dev_addr, ETH_ALEN)) {
-		tmp_slave1 = bond_get_first_slave(bond);
-		for (; tmp_slave1; tmp_slave1 = bond_get_next_slave(bond, tmp_slave1)) {
+	if (memcmp(slave->perm_hwaddr, bond->dev->dev_addr, ETH_ALEN)) {
+		bond_for_each_slave(bond, tmp_slave1, i) {
 			if (!memcmp(tmp_slave1->dev->dev_addr, slave->dev->dev_addr,
 				    ETH_ALEN)) {
+				found = 1;
 				break;
 			}
 		}
-		if (tmp_slave1) {
+
+		if (found) {
 			/* a slave was found that is using the mac address
 			 * of the new slave
 			 */
-			printk(KERN_ERR "bonding: Warning: the hw address "
-			       "of slave %s is not unique - cannot enslave it!"
-			       , slave->dev->name);
+			printk(KERN_ERR DRV_NAME
+			       ": Error: the hw address of slave %s is not "
+			       "unique - cannot enslave it!",
+			       slave->dev->name);
 			return -EINVAL;
 		}
+
 		return 0;
 	}
 
-	/* the slave's address is equal to the address of the bond
-	 * search for a spare address in the bond for this slave.
+	/* The slave's address is equal to the address of the bond.
+	 * Search for a spare address in the bond for this slave.
 	 */
-	tmp_slave1 = bond_get_first_slave(bond);
-	for (; tmp_slave1; tmp_slave1 = bond_get_next_slave(bond, tmp_slave1)) {
-
-		tmp_slave2 = bond_get_first_slave(bond);
-		for (; tmp_slave2; tmp_slave2 = bond_get_next_slave(bond, tmp_slave2)) {
+	free_mac_slave = NULL;
 
+	bond_for_each_slave(bond, tmp_slave1, i) {
+		found = 0;
+		bond_for_each_slave(bond, tmp_slave2, j) {
 			if (!memcmp(tmp_slave1->perm_hwaddr,
 				    tmp_slave2->dev->dev_addr,
 				    ETH_ALEN)) {
-
+				found = 1;
 				break;
 			}
 		}
 
-		if (!tmp_slave2) {
+		if (!found) {
 			/* no slave has tmp_slave1's perm addr
 			 * as its curr addr
 			 */
+			free_mac_slave = tmp_slave1;
 			break;
 		}
+
+		if (!has_bond_addr) {
+			if (!memcmp(tmp_slave1->dev->dev_addr,
+				    bond->dev->dev_addr,
+				    ETH_ALEN)) {
+
+				has_bond_addr = tmp_slave1;
+			}
+		}
 	}
 
-	if (tmp_slave1) {
-		alb_set_slave_mac_addr(slave, tmp_slave1->perm_hwaddr,
+	if (free_mac_slave) {
+		alb_set_slave_mac_addr(slave, free_mac_slave->perm_hwaddr,
 				       bond->alb_info.rlb_enabled);
 
-		printk(KERN_WARNING "bonding: Warning: the hw address "
-		       "of slave %s is in use by the bond; "
-		       "giving it the hw address of %s\n",
-		       slave->dev->name, tmp_slave1->dev->name);
-	} else {
-		printk(KERN_CRIT "bonding: Error: the hw address "
-		       "of slave %s is in use by the bond; "
-		       "couldn't find a slave with a free hw "
-		       "address to give it (this should not have "
-		       "happened)\n", slave->dev->name);
+		printk(KERN_WARNING DRV_NAME
+		       ": Warning: the hw address of slave %s is in use by "
+		       "the bond; giving it the hw address of %s\n",
+		       slave->dev->name, free_mac_slave->dev->name);
+
+	} else if (has_bond_addr) {
+		printk(KERN_ERR DRV_NAME
+		       ": Error: the hw address of slave %s is in use by the "
+		       "bond; couldn't find a slave with a free hw address to "
+		       "give it (this should not have happened)\n",
+		       slave->dev->name);
 		return -EFAULT;
 	}
 
@@ -1189,37 +1186,36 @@ alb_handle_addr_collision_on_attach(stru
  *
  * For each slave, this function sets the interface to the new address and then
  * changes its dev_addr field to its previous value.
- * 
+ *
  * Unwinding assumes bond's mac address has not yet changed.
  */
-static inline int
-alb_set_mac_address(struct bonding *bond, void *addr)
+static int alb_set_mac_address(struct bonding *bond, void *addr)
 {
 	struct sockaddr sa;
-	struct slave *slave;
+	struct slave *slave, *stop_at;
 	char tmp_addr[ETH_ALEN];
-	int error;
+	int res;
+	int i;
 
 	if (bond->alb_info.rlb_enabled) {
 		return 0;
 	}
 
-	slave = bond_get_first_slave(bond);
-	for (; slave; slave = bond_get_next_slave(bond, slave)) {
+	bond_for_each_slave(bond, slave, i) {
 		if (slave->dev->set_mac_address == NULL) {
-			error = -EOPNOTSUPP;
+			res = -EOPNOTSUPP;
 			goto unwind;
 		}
 
 		/* save net_device's current hw address */
 		memcpy(tmp_addr, slave->dev->dev_addr, ETH_ALEN);
 
-		error = slave->dev->set_mac_address(slave->dev, addr);
+		res = slave->dev->set_mac_address(slave->dev, addr);
 
 		/* restore net_device's hw address */
 		memcpy(slave->dev->dev_addr, tmp_addr, ETH_ALEN);
 
-		if (error) {
+		if (res) {
 			goto unwind;
 		}
 	}
@@ -1227,22 +1223,23 @@ alb_set_mac_address(struct bonding *bond
 	return 0;
 
 unwind:
-	memcpy(sa.sa_data, bond->device->dev_addr, bond->device->addr_len);
-	sa.sa_family = bond->device->type;
-	slave = bond_get_first_slave(bond);
-	for (; slave; slave = bond_get_next_slave(bond, slave)) {
+	memcpy(sa.sa_data, bond->dev->dev_addr, bond->dev->addr_len);
+	sa.sa_family = bond->dev->type;
+
+	/* unwind from head to the slave that failed */
+	stop_at = slave;
+	bond_for_each_slave_from_to(bond, slave, i, bond->first_slave, stop_at) {
 		memcpy(tmp_addr, slave->dev->dev_addr, ETH_ALEN);
 		slave->dev->set_mac_address(slave->dev, &sa);
 		memcpy(slave->dev->dev_addr, tmp_addr, ETH_ALEN);
 	}
 
-	return error;
+	return res;
 }
 
 /************************ exported alb funcions ************************/
 
-int
-bond_alb_initialize(struct bonding *bond, int rlb_enabled)
+int bond_alb_initialize(struct bonding *bond, int rlb_enabled)
 {
 	int res;
 
@@ -1264,8 +1261,7 @@ bond_alb_initialize(struct bonding *bond
 	return 0;
 }
 
-void
-bond_alb_deinitialize(struct bonding *bond)
+void bond_alb_deinitialize(struct bonding *bond)
 {
 	struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
 
@@ -1276,49 +1272,39 @@ bond_alb_deinitialize(struct bonding *bo
 	}
 }
 
-int
-bond_alb_xmit(struct sk_buff *skb, struct net_device *dev)
+int bond_alb_xmit(struct sk_buff *skb, struct net_device *bond_dev)
 {
-	struct bonding *bond = (struct bonding *) dev->priv;
-	struct ethhdr *eth_data = (struct ethhdr *)skb->data;
+	struct bonding *bond = bond_dev->priv;
+	struct ethhdr *eth_data = (struct ethhdr *)skb->mac.raw = skb->data;
 	struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
 	struct slave *tx_slave = NULL;
-	char do_tx_balance = 1;
+	static u32 ip_bcast = 0xffffffff;
 	int hash_size = 0;
+	int do_tx_balance = 1;
 	u32 hash_index = 0;
 	u8 *hash_start = NULL;
-	u8 mac_bcast[ETH_ALEN] = {0xff,0xff,0xff,0xff,0xff,0xff};
-
-	if (!IS_UP(dev)) { /* bond down */
-		dev_kfree_skb(skb);
-		return 0;
-	}
+	int res = 1;
 
-	/* make sure that the current_slave and the slaves list do
+	/* make sure that the curr_active_slave and the slaves list do
 	 * not change during tx
 	 */
 	read_lock(&bond->lock);
+	read_lock(&bond->curr_slave_lock);
 
-	if (bond->slave_cnt == 0) {
-		/* no suitable interface, frame not sent */
-		dev_kfree_skb(skb);
-		read_unlock(&bond->lock);
-		return 0;
+	if (!BOND_IS_OK(bond)) {
+		goto out;
 	}
 
-	read_lock(&bond->ptrlock);
-
 	switch (ntohs(skb->protocol)) {
 	case ETH_P_IP:
 		if ((memcmp(eth_data->h_dest, mac_bcast, ETH_ALEN) == 0) ||
-		    (skb->nh.iph->daddr == 0xffffffff)) {
+		    (skb->nh.iph->daddr == ip_bcast)) {
 			do_tx_balance = 0;
 			break;
 		}
 		hash_start = (char*)&(skb->nh.iph->daddr);
-		hash_size = 4;
+		hash_size = sizeof(skb->nh.iph->daddr);
 		break;
-
 	case ETH_P_IPV6:
 		if (memcmp(eth_data->h_dest, mac_bcast, ETH_ALEN) == 0) {
 			do_tx_balance = 0;
@@ -1326,9 +1312,8 @@ bond_alb_xmit(struct sk_buff *skb, struc
 		}
 
 		hash_start = (char*)&(skb->nh.ipv6h->daddr);
-		hash_size = 16;
+		hash_size = sizeof(skb->nh.ipv6h->daddr);
 		break;
-
 	case ETH_P_IPX:
 		if (skb->nh.ipxh->ipx_checksum !=
 		    __constant_htons(IPX_NO_CHECKSUM)) {
@@ -1337,8 +1322,7 @@ bond_alb_xmit(struct sk_buff *skb, struc
 			break;
 		}
 
-		if (skb->nh.ipxh->ipx_type !=
-		    __constant_htons(IPX_TYPE_NCP)) {
+		if (skb->nh.ipxh->ipx_type != IPX_TYPE_NCP) {
 			/* The only protocol worth balancing in
 			 * this family since it has an "ARP" like
 			 * mechanism
@@ -1350,14 +1334,12 @@ bond_alb_xmit(struct sk_buff *skb, struc
 		hash_start = (char*)eth_data->h_dest;
 		hash_size = ETH_ALEN;
 		break;
-
 	case ETH_P_ARP:
 		do_tx_balance = 0;
 		if (bond_info->rlb_enabled) {
 			tx_slave = rlb_arp_xmit(skb, bond);
 		}
 		break;
-
 	default:
 		do_tx_balance = 0;
 		break;
@@ -1370,43 +1352,50 @@ bond_alb_xmit(struct sk_buff *skb, struc
 
 	if (!tx_slave) {
 		/* unbalanced or unassigned, send through primary */
-		tx_slave = bond->current_slave;
+		tx_slave = bond->curr_active_slave;
 		bond_info->unbalanced_load += skb->len;
 	}
 
 	if (tx_slave && SLAVE_IS_OK(tx_slave)) {
-		skb->dev = tx_slave->dev;
-		if (tx_slave != bond->current_slave) {
+		if (tx_slave != bond->curr_active_slave) {
 			memcpy(eth_data->h_source,
-				tx_slave->dev->dev_addr,
-				ETH_ALEN);
+			       tx_slave->dev->dev_addr,
+			       ETH_ALEN);
 		}
-		dev_queue_xmit(skb);
+
+		res = bond_dev_queue_xmit(bond, skb, tx_slave->dev);
 	} else {
-		/* no suitable interface, frame not sent */
 		if (tx_slave) {
 			tlb_clear_slave(bond, tx_slave, 0);
 		}
-		dev_kfree_skb(skb);
 	}
 
-	read_unlock(&bond->ptrlock);
+out:
+	if (res) {
+		/* no suitable interface, frame not sent */
+		dev_kfree_skb(skb);
+	}
+	read_unlock(&bond->curr_slave_lock);
 	read_unlock(&bond->lock);
 	return 0;
 }
 
-void
-bond_alb_monitor(struct bonding *bond)
+void bond_alb_monitor(struct bonding *bond)
 {
 	struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
-	struct slave *slave = NULL;
+	struct slave *slave;
+	int i;
 
 	read_lock(&bond->lock);
 
-	if ((bond->slave_cnt == 0) || !(bond->device->flags & IFF_UP)) {
+	if (bond->kill_timers) {
+		goto out;
+	}
+
+	if (bond->slave_cnt == 0) {
 		bond_info->tx_rebalance_counter = 0;
 		bond_info->lp_counter = 0;
-		goto out;
+		goto re_arm;
 	}
 
 	bond_info->tx_rebalance_counter++;
@@ -1414,51 +1403,53 @@ bond_alb_monitor(struct bonding *bond)
 
 	/* send learning packets */
 	if (bond_info->lp_counter >= BOND_ALB_LP_TICKS) {
-		/* change of current_slave involves swapping of mac addresses.
+		/* change of curr_active_slave involves swapping of mac addresses.
 		 * in order to avoid this swapping from happening while
-		 * sending the learning packets, the ptrlock must be held for
+		 * sending the learning packets, the curr_slave_lock must be held for
 		 * read.
 		 */
-		read_lock(&bond->ptrlock);
-		slave = bond_get_first_slave(bond);
-		while (slave) {
+		read_lock(&bond->curr_slave_lock);
+
+		bond_for_each_slave(bond, slave, i) {
 			alb_send_learning_packets(slave,slave->dev->dev_addr);
-			slave = bond_get_next_slave(bond, slave);
 		}
-		read_unlock(&bond->ptrlock);
+
+		read_unlock(&bond->curr_slave_lock);
 
 		bond_info->lp_counter = 0;
 	}
 
 	/* rebalance tx traffic */
 	if (bond_info->tx_rebalance_counter >= BOND_TLB_REBALANCE_TICKS) {
-		read_lock(&bond->ptrlock);
-		slave = bond_get_first_slave(bond);
-		while (slave) {
+
+		read_lock(&bond->curr_slave_lock);
+
+		bond_for_each_slave(bond, slave, i) {
 			tlb_clear_slave(bond, slave, 1);
-			if (slave == bond->current_slave) {
+			if (slave == bond->curr_active_slave) {
 				SLAVE_TLB_INFO(slave).load =
 					bond_info->unbalanced_load /
 						BOND_TLB_REBALANCE_INTERVAL;
 				bond_info->unbalanced_load = 0;
 			}
-			slave = bond_get_next_slave(bond, slave);
 		}
-		read_unlock(&bond->ptrlock);
+
+		read_unlock(&bond->curr_slave_lock);
+
 		bond_info->tx_rebalance_counter = 0;
 	}
 
 	/* handle rlb stuff */
 	if (bond_info->rlb_enabled) {
 		/* the following code changes the promiscuity of the
-		 * the current_slave. It needs to be locked with a
+		 * the curr_active_slave. It needs to be locked with a
 		 * write lock to protect from other code that also
 		 * sets the promiscuity.
 		 */
-		write_lock(&bond->ptrlock);
+		write_lock(&bond->curr_slave_lock);
+
 		if (bond_info->primary_is_promisc &&
-		    (++bond_info->rlb_promisc_timeout_counter >=
-			RLB_PROMISC_TIMEOUT)) {
+		    (++bond_info->rlb_promisc_timeout_counter >= RLB_PROMISC_TIMEOUT)) {
 
 			bond_info->rlb_promisc_timeout_counter = 0;
 
@@ -1466,12 +1457,13 @@ bond_alb_monitor(struct bonding *bond)
 			 * because a slave was disabled then
 			 * it can now leave promiscuous mode.
 			 */
-			dev_set_promiscuity(bond->current_slave->dev, -1);
+			dev_set_promiscuity(bond->curr_active_slave->dev, -1);
 			bond_info->primary_is_promisc = 0;
 		}
-		write_unlock(&bond->ptrlock);
 
-		if (bond_info->rlb_rebalance == 1) {
+		write_unlock(&bond->curr_slave_lock);
+
+		if (bond_info->rlb_rebalance) {
 			bond_info->rlb_rebalance = 0;
 			rlb_rebalance(bond);
 		}
@@ -1491,28 +1483,23 @@ bond_alb_monitor(struct bonding *bond)
 		}
 	}
 
+re_arm:
+	mod_timer(&(bond_info->alb_timer), jiffies + alb_delta_in_ticks);
 out:
 	read_unlock(&bond->lock);
-
-	if (bond->device->flags & IFF_UP) {
-		/* re-arm the timer */
-		mod_timer(&(bond_info->alb_timer),
-			jiffies + (HZ/ALB_TIMER_TICKS_PER_SEC));
-	}
 }
 
-/* assumption: called before the slave is attched to the bond
+/* assumption: called before the slave is attached to the bond
  * and not locked by the bond lock
  */
-int
-bond_alb_init_slave(struct bonding *bond, struct slave *slave)
+int bond_alb_init_slave(struct bonding *bond, struct slave *slave)
 {
-	int err = 0;
+	int res;
 
-	err = alb_set_slave_mac_addr(slave, slave->perm_hwaddr,
+	res = alb_set_slave_mac_addr(slave, slave->perm_hwaddr,
 				     bond->alb_info.rlb_enabled);
-	if (err) {
-		return err;
+	if (res) {
+		return res;
 	}
 
 	/* caller must hold the bond lock for write since the mac addresses
@@ -1520,12 +1507,12 @@ bond_alb_init_slave(struct bonding *bond
 	 */
 	write_lock_bh(&bond->lock);
 
-	err = alb_handle_addr_collision_on_attach(bond, slave);
+	res = alb_handle_addr_collision_on_attach(bond, slave);
 
 	write_unlock_bh(&bond->lock);
 
-	if (err) {
-		return err;
+	if (res) {
+		return res;
 	}
 
 	tlb_init_slave(slave);
@@ -1541,8 +1528,7 @@ bond_alb_init_slave(struct bonding *bond
 }
 
 /* Caller must hold bond lock for write */
-void
-bond_alb_deinit_slave(struct bonding *bond, struct slave *slave)
+void bond_alb_deinit_slave(struct bonding *bond, struct slave *slave)
 {
 	if (bond->slave_cnt > 1) {
 		alb_change_hw_addr_on_detach(bond, slave);
@@ -1557,9 +1543,7 @@ bond_alb_deinit_slave(struct bonding *bo
 }
 
 /* Caller must hold bond lock for read */
-void
-bond_alb_handle_link_change(struct bonding *bond, struct slave *slave,
-			    char link)
+void bond_alb_handle_link_change(struct bonding *bond, struct slave *slave, char link)
 {
 	struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
 
@@ -1583,112 +1567,126 @@ bond_alb_handle_link_change(struct bondi
 }
 
 /**
- * bond_alb_assign_current_slave - assign new current_slave
+ * bond_alb_handle_active_change - assign new curr_active_slave
  * @bond: our bonding struct
  * @new_slave: new slave to assign
  *
- * Set the bond->current_slave to @new_slave and handle
+ * Set the bond->curr_active_slave to @new_slave and handle
  * mac address swapping and promiscuity changes as needed.
  *
- * Caller must hold bond ptrlock for write (or bond lock for write)
+ * Caller must hold bond curr_slave_lock for write (or bond lock for write)
  */
-void
-bond_alb_assign_current_slave(struct bonding *bond, struct slave *new_slave)
+void bond_alb_handle_active_change(struct bonding *bond, struct slave *new_slave)
 {
-	struct slave *swap_slave = bond->current_slave;
+	struct slave *swap_slave;
+	int i;
 
-	if (bond->current_slave == new_slave) {
+	if (bond->curr_active_slave == new_slave) {
 		return;
 	}
 
-	if (bond->current_slave && bond->alb_info.primary_is_promisc) {
-		dev_set_promiscuity(bond->current_slave->dev, -1);
+	if (bond->curr_active_slave && bond->alb_info.primary_is_promisc) {
+		dev_set_promiscuity(bond->curr_active_slave->dev, -1);
 		bond->alb_info.primary_is_promisc = 0;
 		bond->alb_info.rlb_promisc_timeout_counter = 0;
 	}
 
-	bond->current_slave = new_slave;
+	swap_slave = bond->curr_active_slave;
+	bond->curr_active_slave = new_slave;
 
 	if (!new_slave || (bond->slave_cnt == 0)) {
 		return;
 	}
 
-	/* set the new current_slave to the bonds mac address
-	 * i.e. swap mac addresses of old current_slave and new current_slave
+	/* set the new curr_active_slave to the bonds mac address
+	 * i.e. swap mac addresses of old curr_active_slave and new curr_active_slave
 	 */
 	if (!swap_slave) {
+		struct slave *tmp_slave;
 		/* find slave that is holding the bond's mac address */
-		swap_slave = bond_get_first_slave(bond);
-		while (swap_slave) {
-			if (!memcmp(swap_slave->dev->dev_addr,
-				bond->device->dev_addr, ETH_ALEN)) {
+		bond_for_each_slave(bond, tmp_slave, i) {
+			if (!memcmp(tmp_slave->dev->dev_addr,
+				    bond->dev->dev_addr, ETH_ALEN)) {
+				swap_slave = tmp_slave;
 				break;
 			}
-			swap_slave = bond_get_next_slave(bond, swap_slave);
 		}
 	}
 
-	/* current_slave must be set before calling alb_swap_mac_addr */
+	/* curr_active_slave must be set before calling alb_swap_mac_addr */
 	if (swap_slave) {
 		/* swap mac address */
 		alb_swap_mac_addr(bond, swap_slave, new_slave);
 	} else {
 		/* set the new_slave to the bond mac address */
-		alb_set_slave_mac_addr(new_slave, bond->device->dev_addr,
+		alb_set_slave_mac_addr(new_slave, bond->dev->dev_addr,
 				       bond->alb_info.rlb_enabled);
 		/* fasten bond mac on new current slave */
-		alb_send_learning_packets(new_slave, bond->device->dev_addr);
+		alb_send_learning_packets(new_slave, bond->dev->dev_addr);
 	}
 }
 
-int
-bond_alb_set_mac_address(struct net_device *dev, void *addr)
+int bond_alb_set_mac_address(struct net_device *bond_dev, void *addr)
 {
-	struct bonding *bond = dev->priv;
+	struct bonding *bond = bond_dev->priv;
 	struct sockaddr *sa = addr;
-	struct slave *swap_slave = NULL;
-	int error = 0;
+	struct slave *slave, *swap_slave;
+	int res;
+	int i;
 
 	if (!is_valid_ether_addr(sa->sa_data)) {
 		return -EADDRNOTAVAIL;
 	}
 
-	error = alb_set_mac_address(bond, addr);
-	if (error) {
-		return error;
+	res = alb_set_mac_address(bond, addr);
+	if (res) {
+		return res;
 	}
 
-	memcpy(dev->dev_addr, sa->sa_data, dev->addr_len);
+	memcpy(bond_dev->dev_addr, sa->sa_data, bond_dev->addr_len);
 
-	/* If there is no current_slave there is nothing else to do.
+	/* If there is no curr_active_slave there is nothing else to do.
 	 * Otherwise we'll need to pass the new address to it and handle
 	 * duplications.
 	 */
-	if (bond->current_slave == NULL) {
+	if (!bond->curr_active_slave) {
 		return 0;
 	}
 
-	swap_slave = bond_get_first_slave(bond);
-	while (swap_slave) {
-		if (!memcmp(swap_slave->dev->dev_addr, dev->dev_addr, ETH_ALEN)) {
+	swap_slave = NULL;
+
+	bond_for_each_slave(bond, slave, i) {
+		if (!memcmp(slave->dev->dev_addr, bond_dev->dev_addr, ETH_ALEN)) {
+			swap_slave = slave;
 			break;
 		}
-		swap_slave = bond_get_next_slave(bond, swap_slave);
 	}
 
 	if (swap_slave) {
-		alb_swap_mac_addr(bond, swap_slave, bond->current_slave);
+		alb_swap_mac_addr(bond, swap_slave, bond->curr_active_slave);
 	} else {
-		alb_set_slave_mac_addr(bond->current_slave, dev->dev_addr,
+		alb_set_slave_mac_addr(bond->curr_active_slave, bond_dev->dev_addr,
 				       bond->alb_info.rlb_enabled);
 
-		alb_send_learning_packets(bond->current_slave, dev->dev_addr);
+		alb_send_learning_packets(bond->curr_active_slave, bond_dev->dev_addr);
 		if (bond->alb_info.rlb_enabled) {
 			/* inform clients mac address has changed */
-			rlb_req_update_slave_clients(bond, bond->current_slave);
+			rlb_req_update_slave_clients(bond, bond->curr_active_slave);
 		}
 	}
 
 	return 0;
 }
 
+void bond_alb_clear_vlan(struct bonding *bond, unsigned short vlan_id)
+{
+	if (bond->alb_info.current_alb_vlan &&
+	    (bond->alb_info.current_alb_vlan->vlan_id == vlan_id)) {
+		bond->alb_info.current_alb_vlan = NULL;
+	}
+
+	if (bond->alb_info.rlb_enabled) {
+		rlb_clear_vlan(bond, vlan_id);
+	}
+}
+
diff -Nur --show-c-function linux-2.4.25/drivers/net/bonding/bond_alb.h linux-2.4.26-pre2/drivers/net/bonding/bond_alb.h
--- linux-2.4.25/drivers/net/bonding/bond_alb.h	2003-11-28 16:26:20.000000000 -0200
+++ linux-2.4.26-pre2/drivers/net/bonding/bond_alb.h	2004-03-06 15:19:05.000000000 -0300
@@ -1,5 +1,5 @@
 /*
- * Copyright(c) 1999 - 2003 Intel Corporation. All rights reserved.
+ * Copyright(c) 1999 - 2004 Intel Corporation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the
@@ -24,6 +24,9 @@
  * 2003/08/06 - Amir Noam <amir.noam at intel dot com>
  *	- Add support for setting bond's MAC address with special
  *	  handling required for ALB/TLB.
+ *
+ * 2003/12/01 - Shmulik Hen <shmulik.hen at intel dot com>
+ *	- Code cleanup and style changes
  */
 
 #ifndef __BOND_ALB_H__
@@ -74,6 +77,8 @@ struct rlb_client_info {
 	u8  assigned;		/* checking whether this entry is assigned */
 	u8  ntt;		/* flag - need to transmit client info */
 	struct slave *slave;	/* the slave assigned to this client */
+	u8 tag;			/* flag - need to tag skb */
+	unsigned short vlan_id;	/* VLAN tag associated with IP address */
 };
 
 struct tlb_slave_info {
@@ -119,6 +124,7 @@ struct alb_bond_info {
 						 * rx traffic should be
 						 * rebalanced
 						 */
+	struct vlan_entry	*current_alb_vlan;
 };
 
 int bond_alb_initialize(struct bonding *bond, int rlb_enabled);
@@ -126,10 +132,10 @@ void bond_alb_deinitialize(struct bondin
 int bond_alb_init_slave(struct bonding *bond, struct slave *slave);
 void bond_alb_deinit_slave(struct bonding *bond, struct slave *slave);
 void bond_alb_handle_link_change(struct bonding *bond, struct slave *slave, char link);
-void bond_alb_assign_current_slave(struct bonding *bond, struct slave *new_slave);
-int bond_alb_xmit(struct sk_buff *skb, struct net_device *dev);
+void bond_alb_handle_active_change(struct bonding *bond, struct slave *new_slave);
+int bond_alb_xmit(struct sk_buff *skb, struct net_device *bond_dev);
 void bond_alb_monitor(struct bonding *bond);
-int bond_alb_set_mac_address(struct net_device *dev, void *addr);
-
+int bond_alb_set_mac_address(struct net_device *bond_dev, void *addr);
+void bond_alb_clear_vlan(struct bonding *bond, unsigned short vlan_id);
 #endif /* __BOND_ALB_H__ */
 
diff -Nur --show-c-function linux-2.4.25/drivers/net/bonding/bonding.h linux-2.4.26-pre2/drivers/net/bonding/bonding.h
--- linux-2.4.25/drivers/net/bonding/bonding.h	2003-11-28 16:26:20.000000000 -0200
+++ linux-2.4.26-pre2/drivers/net/bonding/bonding.h	2004-03-06 15:16:46.000000000 -0300
@@ -9,7 +9,7 @@
  *
  *	This software may be used and distributed according to the terms
  *	of the GNU Public License, incorporated herein by reference.
- * 
+ *
  *
  * 2003/03/18 - Amir Noam <amir.noam at intel dot com>,
  *		Tsippy Mendelson <tsippy.mendelson at intel dot com> and
@@ -22,160 +22,231 @@
  *
  * 2003/05/01 - Shmulik Hen <shmulik.hen at intel dot com>
  *	- Added support for Transmit load balancing mode.
+ *
+ * 2003/12/01 - Shmulik Hen <shmulik.hen at intel dot com>
+ *	- Code cleanup and style changes
  */
- 
+
 #ifndef _LINUX_BONDING_H
 #define _LINUX_BONDING_H
 
 #include <linux/timer.h>
 #include <linux/proc_fs.h>
+#include <linux/if_bonding.h>
 #include "bond_3ad.h"
 #include "bond_alb.h"
 
-#ifdef BONDING_DEBUG
+#define DRV_VERSION	"2.6.0"
+#define DRV_RELDATE	"January 14, 2004"
+#define DRV_NAME	"bonding"
+#define DRV_DESCRIPTION	"Ethernet Channel Bonding Driver"
 
-// use this like so: BOND_PRINT_DBG(("foo = %d, bar = %d", foo, bar));
-#define BOND_PRINT_DBG(X)                                     \
-do {                                                          \
-	printk(KERN_DEBUG "%s (%d)", __FUNCTION__, __LINE__); \
-	printk X;                                             \
-	printk("\n");                                         \
-} while(0)
+#define BOND_MAX_ARP_TARGETS	16
 
+#ifdef BONDING_DEBUG
+#define dprintk(fmt, args...) \
+	printk(KERN_DEBUG     \
+	       DRV_NAME ": %s() %d: " fmt, __FUNCTION__, __LINE__ , ## args )
 #else
-#define BOND_PRINT_DBG(X)
+#define dprintk(fmt, args...)
 #endif /* BONDING_DEBUG */
 
-#define IS_UP(dev)  ((((dev)->flags & (IFF_UP)) == (IFF_UP)) && \
-		     (netif_running(dev) && netif_carrier_ok(dev)))
+#define IS_UP(dev)					   \
+	      ((((dev)->flags & IFF_UP) == IFF_UP)	&& \
+	       netif_running(dev)			&& \
+	       netif_carrier_ok(dev))
+
+/*
+ * Checks whether bond is ready for transmit.
+ *
+ * Caller must hold bond->lock
+ */
+#define BOND_IS_OK(bond)			     \
+		   (((bond)->dev->flags & IFF_UP) && \
+		    netif_running((bond)->dev)	  && \
+		    ((bond)->slave_cnt > 0))
 
-/* Checks whether the dev is ready for transmit. We do not check netif_running
- * since a device can be stopped by the driver for short periods of time for
- * maintainance. dev_queue_xmit() handles this by queing the packet until the
- * the dev is running again. Keeping packets ordering requires sticking the
- * same dev as much as possible
- */
-#define SLAVE_IS_OK(slave) \
-		     ((((slave)->dev->flags & (IFF_UP)) == (IFF_UP)) && \
-		     netif_carrier_ok((slave)->dev) && \
+/*
+ * Checks whether slave is ready for transmit.
+ */
+#define SLAVE_IS_OK(slave)			        \
+		    (((slave)->dev->flags & IFF_UP)  && \
+		     netif_running((slave)->dev)     && \
 		     ((slave)->link == BOND_LINK_UP) && \
 		     ((slave)->state == BOND_STATE_ACTIVE))
 
 
-typedef struct slave {
+#define USES_PRIMARY(mode)				\
+		(((mode) == BOND_MODE_ACTIVEBACKUP) ||	\
+		 ((mode) == BOND_MODE_TLB)          ||	\
+		 ((mode) == BOND_MODE_ALB))
+
+/*
+ * Less bad way to call ioctl from within the kernel; this needs to be
+ * done some other way to get the call out of interrupt context.
+ * Needs "ioctl" variable to be supplied by calling context.
+ */
+#define IOCTL(dev, arg, cmd) ({		\
+	int res = 0;			\
+	mm_segment_t fs = get_fs();	\
+	set_fs(get_ds());		\
+	res = ioctl(dev, arg, cmd);	\
+	set_fs(fs);			\
+	res; })
+
+/**
+ * bond_for_each_slave_from - iterate the slaves list from a starting point
+ * @bond:	the bond holding this list.
+ * @pos:	current slave.
+ * @cnt:	counter for max number of moves
+ * @start:	starting point.
+ *
+ * Caller must hold bond->lock
+ */
+#define bond_for_each_slave_from(bond, pos, cnt, start)	\
+	for (cnt = 0, pos = start;				\
+	     cnt < (bond)->slave_cnt;				\
+             cnt++, pos = (pos)->next)
+
+/**
+ * bond_for_each_slave_from_to - iterate the slaves list from start point to stop point
+ * @bond:	the bond holding this list.
+ * @pos:	current slave.
+ * @cnt:	counter for number max of moves
+ * @start:	start point.
+ * @stop:	stop point.
+ *
+ * Caller must hold bond->lock
+ */
+#define bond_for_each_slave_from_to(bond, pos, cnt, start, stop)	\
+	for (cnt = 0, pos = start;					\
+	     ((cnt < (bond)->slave_cnt) && (pos != (stop)->next));	\
+             cnt++, pos = (pos)->next)
+
+/**
+ * bond_for_each_slave - iterate the slaves list from head
+ * @bond:	the bond holding this list.
+ * @pos:	current slave.
+ * @cnt:	counter for max number of moves
+ *
+ * Caller must hold bond->lock
+ */
+#define bond_for_each_slave(bond, pos, cnt)	\
+		bond_for_each_slave_from(bond, pos, cnt, (bond)->first_slave)
+
+
+struct bond_params {
+	int mode;
+	int miimon;
+	int arp_interval;
+	int use_carrier;
+	int updelay;
+	int downdelay;
+	int lacp_fast;
+	char primary[IFNAMSIZ];
+	u32 arp_targets[BOND_MAX_ARP_TARGETS];
+};
+
+struct vlan_entry {
+	struct list_head vlan_list;
+	unsigned short vlan_id;
+};
+
+struct slave {
+	struct net_device *dev; /* first - usefull for panic debug */
 	struct slave *next;
 	struct slave *prev;
-	struct net_device *dev;
-	short  delay;
-	unsigned long jiffies;
-	char   link;    /* one of BOND_LINK_XXXX */
-	char   state;   /* one of BOND_STATE_XXXX */
-	unsigned short original_flags;
-	u32 link_failure_count;
+	s16    delay;
+	u32    jiffies;
+	s8     link;    /* one of BOND_LINK_XXXX */
+	s8     state;   /* one of BOND_STATE_XXXX */
+	u32    original_flags;
+	u32    link_failure_count;
 	u16    speed;
 	u8     duplex;
 	u8     perm_hwaddr[ETH_ALEN];
 	struct ad_slave_info ad_info; /* HUGE - better to dynamically alloc */
 	struct tlb_slave_info tlb_info;
-} slave_t;
+};
 
 /*
  * Here are the locking policies for the two bonding locks:
  *
  * 1) Get bond->lock when reading/writing slave list.
- * 2) Get bond->ptrlock when reading/writing bond->current_slave.
+ * 2) Get bond->curr_slave_lock when reading/writing bond->curr_active_slave.
  *    (It is unnecessary when the write-lock is put with bond->lock.)
- * 3) When we lock with bond->ptrlock, we must lock with bond->lock
+ * 3) When we lock with bond->curr_slave_lock, we must lock with bond->lock
  *    beforehand.
  */
-typedef struct bonding {
-	slave_t *next;
-	slave_t *prev;
-	slave_t *current_slave;
-	slave_t *primary_slave;
-	slave_t *current_arp_slave;
-	__s32 slave_cnt;
+struct bonding {
+	struct   net_device *dev; /* first - usefull for panic debug */
+	struct   slave *first_slave;
+	struct   slave *curr_active_slave;
+	struct   slave *current_arp_slave;
+	struct   slave *primary_slave;
+	s32      slave_cnt; /* never change this value outside the attach/detach wrappers */
 	rwlock_t lock;
-	rwlock_t ptrlock;
-	struct timer_list mii_timer;
-	struct timer_list arp_timer;
-	struct net_device_stats stats;
+	rwlock_t curr_slave_lock;
+	struct   timer_list mii_timer;
+	struct   timer_list arp_timer;
+	s8       kill_timers;
+	struct   net_device_stats stats;
 #ifdef CONFIG_PROC_FS
-	struct proc_dir_entry *bond_proc_file;
-	char procdir_name[IFNAMSIZ];
+	struct   proc_dir_entry *proc_entry;
+	char     proc_file_name[IFNAMSIZ];
 #endif /* CONFIG_PROC_FS */
-	struct list_head bond_list;
-	struct net_device *device;
-	struct dev_mc_list *mc_list;
-	unsigned short flags;
-	struct ad_bond_info ad_info;
-	struct alb_bond_info alb_info;
-} bonding_t;
-
-/* Forward declarations */
-void bond_set_slave_active_flags(slave_t *slave);
-void bond_set_slave_inactive_flags(slave_t *slave);
-
-/**
- * These functions can be used for iterating the slave list
- * (which is circular)
- * Caller must hold bond lock for read
- */
-extern inline struct slave*
-bond_get_first_slave(struct bonding *bond)
-{
-	/* if there are no slaves return NULL */
-	if (bond->next == (slave_t *)bond) {
-		return NULL;
-	}
-	return bond->next;
-}
-
-/**
- * Caller must hold bond lock for read
- */
-extern inline struct slave*
-bond_get_next_slave(struct bonding *bond, struct slave *slave)
-{
-	/* If we have reached the last slave return NULL */
-	if (slave->next == bond->next) {
-		return NULL;
-	}
-	return slave->next;
-}
+	struct   list_head bond_list;
+	struct   dev_mc_list *mc_list;
+	u16      flags;
+	struct   ad_bond_info ad_info;
+	struct   alb_bond_info alb_info;
+	struct   bond_params params;
+	struct   list_head vlan_list;
+	struct   vlan_group *vlgrp;
+};
 
 /**
  * Returns NULL if the net_device does not belong to any of the bond's slaves
  *
  * Caller must hold bond lock for read
  */
-extern inline struct slave*
-bond_get_slave_by_dev(struct bonding *bond, struct net_device *slave_dev)
+extern inline struct slave *bond_get_slave_by_dev(struct bonding *bond, struct net_device *slave_dev)
 {
-	struct slave *our_slave = bond->next;
+	struct slave *slave = NULL;
+	int i;
 
-	/* check if the list of slaves is empty */
-	if (our_slave == (slave_t *)bond) {
-		return NULL;
-	}
-
-	for (; our_slave; our_slave = bond_get_next_slave(bond, our_slave)) {
-		if (our_slave->dev == slave_dev) {
+	bond_for_each_slave(bond, slave, i) {
+		if (slave->dev == slave_dev) {
 			break;
 		}
 	}
-	return our_slave;
+
+	return slave;
 }
 
-extern inline struct bonding*
-bond_get_bond_by_slave(struct slave *slave)
+extern inline struct bonding *bond_get_bond_by_slave(struct slave *slave)
 {
 	if (!slave || !slave->dev->master) {
 		return NULL;
 	}
 
-	return (struct bonding *)(slave->dev->master->priv);
+	return (struct bonding *)slave->dev->master->priv;
 }
 
+extern inline void bond_set_slave_inactive_flags(struct slave *slave)
+{
+	slave->state = BOND_STATE_BACKUP;
+	slave->dev->flags |= IFF_NOARP;
+}
+
+extern inline void bond_set_slave_active_flags(struct slave *slave)
+{
+	slave->state = BOND_STATE_ACTIVE;
+	slave->dev->flags &= ~IFF_NOARP;
+}
+
+struct vlan_entry *bond_next_vlan(struct bonding *bond, struct vlan_entry *curr);
+int bond_dev_queue_xmit(struct bonding *bond, struct sk_buff *skb, struct net_device *slave_dev);
+
 #endif /* _LINUX_BONDING_H */
 
diff -Nur --show-c-function linux-2.4.25/drivers/net/bonding/bond_main.c linux-2.4.26-pre2/drivers/net/bonding/bond_main.c
--- linux-2.4.25/drivers/net/bonding/bond_main.c	2003-11-28 16:26:20.000000000 -0200
+++ linux-2.4.26-pre2/drivers/net/bonding/bond_main.c	2004-03-06 15:16:36.000000000 -0300
@@ -1,7 +1,7 @@
 /*
  * originally based on the dummy device.
  *
- * Copyright 1999, Thomas Davis, tadavis@lbl.gov.  
+ * Copyright 1999, Thomas Davis, tadavis@lbl.gov.
  * Licensed under the GPL. Based on dummy.c, and eql.c devices.
  *
  * bonding.c: an Ethernet Bonding driver
@@ -15,9 +15,9 @@
  *
  * How it works:
  *    ifconfig bond0 ipaddress netmask up
- *      will setup a network device, with an ip address.  No mac address 
- *	will be assigned at this time.  The hw mac address will come from 
- *	the first slave bonded to the channel.  All slaves will then use 
+ *      will setup a network device, with an ip address.  No mac address
+ *	will be assigned at this time.  The hw mac address will come from
+ *	the first slave bonded to the channel.  All slaves will then use
  *	this hw mac address.
  *
  *    ifconfig bond0 down
@@ -26,7 +26,7 @@
  *    ifenslave bond0 eth0
  *	will attach eth0 to bond0 as a slave.  eth0 hw mac address will either
  *	a: be used as initial mac address
- *	b: if a hw mac address already is there, eth0's hw mac address 
+ *	b: if a hw mac address already is there, eth0's hw mac address
  *	   will then be set from bond0.
  *
  * v0.1 - first working version.
@@ -93,14 +93,14 @@
  *
  * 2001/4/5 - Chad N. Tindel <ctindel at ieee dot org>
  *     - Ported to 2.4 Kernel
- * 
+ *
  * 2001/5/2 - Jeffrey E. Mast <jeff at mastfamily dot com>
  *     - When a device is detached from a bond, the slave device is no longer
  *       left thinking that is has a master.
  *
  * 2001/5/16 - Jeffrey E. Mast <jeff at mastfamily dot com>
- *     - memset did not appropriately initialized the bond rw_locks. Used 
- *       rwlock_init to initialize to unlocked state to prevent deadlock when 
+ *     - memset did not appropriately initialized the bond rw_locks. Used
+ *       rwlock_init to initialize to unlocked state to prevent deadlock when
  *       first attempting a lock
  *     - Called SET_MODULE_OWNER for bond device
  *
@@ -119,7 +119,7 @@
  *
  * 2001/6/01 - Chad N. Tindel <ctindel at ieee dot org>
  *     - Added /proc support for getting bond and slave information.
- *       Information is in /proc/net/<bond device>/info. 
+ *       Information is in /proc/net/<bond device>/info.
  *     - Changed the locking when calling bond_close to prevent deadlock.
  *
  * 2001/8/05 - Janice Girouard <girouard at us.ibm.com>
@@ -144,8 +144,8 @@
  *       but only for an up link.
  *
  * 2001/9/20 - Chad N. Tindel <ctindel at ieee dot org>
- *     - Add the device field to bonding_t.  Previously the net_device 
- *       corresponding to a bond wasn't available from the bonding_t 
+ *     - Add the device field to bonding_t.  Previously the net_device
+ *       corresponding to a bond wasn't available from the bonding_t
  *       structure.
  *
  * 2001/9/25 - Janice Girouard <girouard at us.ibm.com>
@@ -155,10 +155,10 @@
  *     - Various memory leak fixes
  *
  * 2001/11/5 - Mark Huth <mark dot huth at mvista dot com>
- *     - Don't take rtnl lock in bond_mii_monitor as it deadlocks under 
- *       certain hotswap conditions.  
+ *     - Don't take rtnl lock in bond_mii_monitor as it deadlocks under
+ *       certain hotswap conditions.
  *       Note:  this same change may be required in bond_arp_monitor ???
- *     - Remove possibility of calling bond_sethwaddr with NULL slave_dev ptr 
+ *     - Remove possibility of calling bond_sethwaddr with NULL slave_dev ptr
  *     - Handle hot swap ethernet interface deregistration events to remove
  *       kernel oops following hot swap of enslaved interface
  *
@@ -222,23 +222,23 @@
  *     - fix deletion of multicast groups after unloading module
  *
  * 2002/11/06 - Kameshwara Rayaprolu <kameshwara.rao * wipro_com>
- *     - Changes to prevent panic from closing the device twice; if we close 
- *       the device in bond_release, we must set the original_flags to down 
+ *     - Changes to prevent panic from closing the device twice; if we close
+ *       the device in bond_release, we must set the original_flags to down
  *       so it won't be closed again by the network layer.
  *
  * 2002/11/07 - Tony Cureington <tony.cureington * hp_com>
  *     - Fix arp_target_hw_addr memory leak
- *     - Created activebackup_arp_monitor function to handle arp monitoring 
- *       in active backup mode - the bond_arp_monitor had several problems... 
- *       such as allowing slaves to tx arps sequentially without any delay 
+ *     - Created activebackup_arp_monitor function to handle arp monitoring
+ *       in active backup mode - the bond_arp_monitor had several problems...
+ *       such as allowing slaves to tx arps sequentially without any delay
  *       for a response
  *     - Renamed bond_arp_monitor to loadbalance_arp_monitor and re-wrote
  *       this function to just handle arp monitoring in load-balancing mode;
  *       it is a lot more compact now
- *     - Changes to ensure one and only one slave transmits in active-backup 
+ *     - Changes to ensure one and only one slave transmits in active-backup
  *       mode
- *     - Robustesize parameters; warn users about bad combinations of 
- *       parameters; also if miimon is specified and a network driver does 
+ *     - Robustesize parameters; warn users about bad combinations of
+ *       parameters; also if miimon is specified and a network driver does
  *       not support MII or ETHTOOL, inform the user of this
  *     - Changes to support link_failure_count when in arp monitoring mode
  *     - Fix up/down delay reported in /proc
@@ -248,7 +248,7 @@
  *
  * 2002/11/16 - Laurent Deniel <laurent.deniel at free.fr>
  *     - fix multicast handling in activebackup_arp_monitor
- *     - remove one unnecessary and confusing current_slave == slave test 
+ *     - remove one unnecessary and confusing curr_active_slave == slave test
  *	 in activebackup_arp_monitor
  *
  *  2002/11/17 - Laurent Deniel <laurent.deniel at free.fr>
@@ -267,7 +267,7 @@
  *	  One change: an invalid choice will cause module load failure,
  *	  rather than the previous behavior of just picking one.
  *	- Minor cleanups; got rid of dup ctype stuff, atoi function
- * 
+ *
  * 2003/02/07 - Jay Vosburgh <fubar at us dot ibm dot com>
  *	- Added use_carrier module parameter that causes miimon to
  *	  use netif_carrier_ok() test instead of MII/ETHTOOL ioctls.
@@ -330,7 +330,7 @@
  *	  new/old ifenslave and new/old bonding.
  *
  * 2003/05/01 - Shmulik Hen <shmulik.hen at intel dot com>
- *	- Fixed bug in bond_release_all(): save old value of current_slave
+ *	- Fixed bug in bond_release_all(): save old value of curr_active_slave
  *	  before setting it to NULL.
  *	- Changed driver versioning scheme to include version number instead
  *	  of release date (that is already in another field). There are 3
@@ -358,7 +358,7 @@
  *
  * 2003/05/01 - Shmulik Hen <shmulik.hen at intel dot com>
  *	- Added support for Transmit load balancing mode.
- *	- Concentrate all assignments of current_slave to a single point
+ *	- Concentrate all assignments of curr_active_slave to a single point
  *	  so specific modes can take actions when the primary adapter is
  *	  changed.
  *	- Take the updelay parameter into consideration during bond_enslave
@@ -426,8 +426,53 @@
  *	- Convert /proc to seq_file interface.
  *	  Change /proc/net/bondX/info to /proc/net/bonding/bondX.
  *	  Set version to 2.4.1.
+ *
+ * 2003/11/20 - Amir Noam <amir.noam at intel dot com>
+ *	- Fix /proc creation/destruction.
+ *
+ * 2003/12/01 - Shmulik Hen <shmulik.hen at intel dot com>
+ *	- Massive cleanup - Set version to 2.5.0
+ *	  Code changes:
+ *	  o Consolidate format of prints and debug prints.
+ *	  o Remove bonding_t/slave_t typedefs and consolidate all casts.
+ *	  o Remove dead code and unnecessary checks.
+ *	  o Consolidate starting/stopping timers.
+ *	  o Consolidate handling of primary module param throughout the code.
+ *	  o Removed multicast module param support - all settings are done
+ *	    according to mode.
+ *	  o Slave list iteration - bond is no longer part of the list,
+ *	    added cyclic list iteration macros.
+ *	  o Consolidate error handling in all xmit functions.
+ *	  Style changes:
+ *	  o Consolidate function naming and declarations.
+ *	  o Consolidate function params and local variables names.
+ *	  o Consolidate return values.
+ *	  o Consolidate curly braces.
+ *	  o Consolidate conditionals format.
+ *	  o Change struct member names and types.
+ *	  o Chomp trailing spaces, remove empty lines, fix indentations.
+ *	  o Re-organize code according to context.
+ *
+ * 2003/12/30 - Amir Noam <amir.noam at intel dot com>
+ *	- Fixed: Cannot remove and re-enslave the original active slave.
+ *	- Fixed: Releasing the original active slave causes mac address
+ *		 duplication.
+ *	- Add support for slaves that use ethtool_ops.
+ *	  Set version to 2.5.3.
+ *
+ * 2004/01/05 - Amir Noam <amir.noam at intel dot com>
+ *	- Save bonding parameters per bond instead of using the global values.
+ *	  Set version to 2.5.4.
+ *
+ * 2004/01/14 - Shmulik Hen <shmulik.hen at intel dot com>
+ *	- Enhance VLAN support:
+ *	  * Add support for VLAN hardware acceleration capable slaves.
+ *	  * Add capability to tag self generated packets in ALB/TLB modes.
+ *	  Set version to 2.6.0.
  */
 
+//#define BONDING_DEBUG 1
+
 #include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
@@ -452,7 +497,6 @@
 #include <asm/dma.h>
 #include <asm/uaccess.h>
 #include <linux/errno.h>
-
 #include <linux/netdevice.h>
 #include <linux/inetdevice.h>
 #include <linux/etherdevice.h>
@@ -461,58 +505,72 @@
 #include <linux/rtnetlink.h>
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
-
-#include <linux/if_bonding.h>
 #include <linux/smp.h>
 #include <linux/if_ether.h>
 #include <net/arp.h>
 #include <linux/mii.h>
 #include <linux/ethtool.h>
+#include <linux/if_vlan.h>
+#include <linux/if_bonding.h>
 #include "bonding.h"
 #include "bond_3ad.h"
 #include "bond_alb.h"
 
-#define DRV_VERSION	"2.4.1"
-#define DRV_RELDATE	"September 15, 2003"
-#define DRV_NAME	"bonding"
-#define DRV_DESCRIPTION	"Ethernet Channel Bonding Driver"
-
-static const char *version =
-DRV_NAME ".c:v" DRV_VERSION " (" DRV_RELDATE ")\n";
+/*---------------------------- Module parameters ----------------------------*/
 
 /* monitor all links that often (in milliseconds). <=0 disables monitoring */
-#ifndef BOND_LINK_MON_INTERV
 #define BOND_LINK_MON_INTERV	0
-#endif
-
-#ifndef BOND_LINK_ARP_INTERV
 #define BOND_LINK_ARP_INTERV	0
-#endif
 
-#ifndef MAX_ARP_IP_TARGETS
-#define MAX_ARP_IP_TARGETS 16
-#endif
+static int max_bonds	= BOND_DEFAULT_MAX_BONDS;
+static int miimon	= BOND_LINK_MON_INTERV;
+static int updelay	= 0;
+static int downdelay	= 0;
+static int use_carrier	= 1;
+static char *mode	= NULL;
+static char *primary	= NULL;
+static char *lacp_rate	= NULL;
+static int arp_interval = BOND_LINK_ARP_INTERV;
+static char *arp_ip_target[BOND_MAX_ARP_TARGETS] = { NULL, };
+
+MODULE_PARM(max_bonds, "i");
+MODULE_PARM_DESC(max_bonds, "Max number of bonded devices");
+MODULE_PARM(miimon, "i");
+MODULE_PARM_DESC(miimon, "Link check interval in milliseconds");
+MODULE_PARM(updelay, "i");
+MODULE_PARM_DESC(updelay, "Delay before considering link up, in milliseconds");
+MODULE_PARM(downdelay, "i");
+MODULE_PARM_DESC(downdelay, "Delay before considering link down, in milliseconds");
+MODULE_PARM(use_carrier, "i");
+MODULE_PARM_DESC(use_carrier, "Use netif_carrier_ok (vs MII ioctls) in miimon; 0 for off, 1 for on (default)");
+MODULE_PARM(mode, "s");
+MODULE_PARM_DESC(mode, "Mode of operation : 0 for round robin, 1 for active-backup, 2 for xor");
+MODULE_PARM(primary, "s");
+MODULE_PARM_DESC(primary, "Primary network device to use");
+MODULE_PARM(lacp_rate, "s");
+MODULE_PARM_DESC(lacp_rate, "LACPDU tx rate to request from 802.3ad partner (slow/fast)");
+MODULE_PARM(arp_interval, "i");
+MODULE_PARM_DESC(arp_interval, "arp interval in milliseconds");
+MODULE_PARM(arp_ip_target, "1-" __MODULE_STRING(BOND_MAX_ARP_TARGETS) "s");
+MODULE_PARM_DESC(arp_ip_target, "arp targets in n.n.n.n form");
 
-#define USES_PRIMARY(mode) \
-		(((mode) == BOND_MODE_ACTIVEBACKUP) || \
-		 ((mode) == BOND_MODE_TLB) || \
-		 ((mode) == BOND_MODE_ALB))
+/*----------------------------- Global variables ----------------------------*/
 
-struct bond_parm_tbl {
-	char *modename;
-	int mode;
-};
+static const char *version =
+	DRV_DESCRIPTION ": v" DRV_VERSION " (" DRV_RELDATE ")\n";
 
-static int arp_interval = BOND_LINK_ARP_INTERV;
-static char *arp_ip_target[MAX_ARP_IP_TARGETS] = { NULL, };
-static u32 arp_target[MAX_ARP_IP_TARGETS] = { 0, } ;
-static int arp_ip_count = 0;
-static u32 my_ip = 0;
-char *arp_target_hw_addr = NULL;
+static LIST_HEAD(bond_dev_list);
 
-static char *primary= NULL;
+#ifdef CONFIG_PROC_FS
+static struct proc_dir_entry *bond_proc_dir = NULL;
+#endif
 
-static int app_abi_ver = 0;
+static u32 arp_target[BOND_MAX_ARP_TARGETS] = { 0, } ;
+static int arp_ip_count	= 0;
+static u32 my_ip	= 0;
+static int bond_mode	= BOND_MODE_ROUNDROBIN;
+static int lacp_fast	= 0;
+static int app_abi_ver	= 0;
 static int orig_app_abi_ver = -1; /* This is used to save the first ABI version
 				   * we receive from the application. Once set,
 				   * it won't be changed, and the module will
@@ -521,14 +579,16 @@ static int orig_app_abi_ver = -1; /* Thi
 				   * another ABI version.
 				   */
 
-static int max_bonds	= BOND_DEFAULT_MAX_BONDS;
-static int miimon	= BOND_LINK_MON_INTERV;
-static int use_carrier	= 1;
-static int bond_mode	= BOND_MODE_ROUNDROBIN;
-static int updelay	= 0;
-static int downdelay	= 0;
+struct bond_parm_tbl {
+	char *modename;
+	int mode;
+};
 
-static char *mode	= NULL;
+static struct bond_parm_tbl bond_lacp_tbl[] = {
+{	"slow",		AD_LACP_SLOW},
+{	"fast",		AD_LACP_FAST},
+{	NULL,		-1},
+};
 
 static struct bond_parm_tbl bond_mode_tbl[] = {
 {	"balance-rr",		BOND_MODE_ROUNDROBIN},
@@ -541,103 +601,15 @@ static struct bond_parm_tbl bond_mode_tb
 {	NULL,			-1},
 };
 
-static int multicast_mode	= BOND_MULTICAST_ALL;
-static char *multicast		= NULL;
-
-static struct bond_parm_tbl bond_mc_tbl[] = {
-{	"disabled",		BOND_MULTICAST_DISABLED},
-{	"active",		BOND_MULTICAST_ACTIVE},
-{	"all",			BOND_MULTICAST_ALL},
-{	NULL,			-1},
-};
-
-static int lacp_fast		= 0;
-static char *lacp_rate		= NULL;
-
-static struct bond_parm_tbl bond_lacp_tbl[] = {
-{	"slow",		AD_LACP_SLOW},
-{	"fast",		AD_LACP_FAST},
-{	NULL,		-1},
-};
-
-static LIST_HEAD(bond_dev_list);
-#ifdef CONFIG_PROC_FS
-static struct proc_dir_entry *bond_proc_dir = NULL;
-#endif
+/*-------------------------- Forward declarations ---------------------------*/
 
-MODULE_PARM(max_bonds, "i");
-MODULE_PARM_DESC(max_bonds, "Max number of bonded devices");
-MODULE_PARM(miimon, "i");
-MODULE_PARM_DESC(miimon, "Link check interval in milliseconds");
-MODULE_PARM(use_carrier, "i");
-MODULE_PARM_DESC(use_carrier, "Use netif_carrier_ok (vs MII ioctls) in miimon; 0 for off, 1 for on (default)");
-MODULE_PARM(mode, "s");
-MODULE_PARM_DESC(mode, "Mode of operation : 0 for round robin, 1 for active-backup, 2 for xor");
-MODULE_PARM(arp_interval, "i");
-MODULE_PARM_DESC(arp_interval, "arp interval in milliseconds");
-MODULE_PARM(arp_ip_target, "1-" __MODULE_STRING(MAX_ARP_IP_TARGETS) "s");
-MODULE_PARM_DESC(arp_ip_target, "arp targets in n.n.n.n form");
-MODULE_PARM(updelay, "i");
-MODULE_PARM_DESC(updelay, "Delay before considering link up, in milliseconds");
-MODULE_PARM(downdelay, "i");
-MODULE_PARM_DESC(downdelay, "Delay before considering link down, in milliseconds");
-MODULE_PARM(primary, "s");
-MODULE_PARM_DESC(primary, "Primary network device to use");
-MODULE_PARM(multicast, "s");
-MODULE_PARM_DESC(multicast, "Mode for multicast support : 0 for none, 1 for active slave, 2 for all slaves (default)");
-MODULE_PARM(lacp_rate, "s");
-MODULE_PARM_DESC(lacp_rate, "LACPDU tx rate to request from 802.3ad partner (slow/fast)");
+static inline void bond_set_mode_ops(struct net_device *bond_dev, int mode);
 
-static int bond_xmit_roundrobin(struct sk_buff *skb, struct net_device *dev);
-static int bond_xmit_xor(struct sk_buff *skb, struct net_device *dev);
-static int bond_xmit_activebackup(struct sk_buff *skb, struct net_device *dev);
-static struct net_device_stats *bond_get_stats(struct net_device *dev);
-static void bond_mii_monitor(struct net_device *dev);
-static void loadbalance_arp_monitor(struct net_device *dev);
-static void activebackup_arp_monitor(struct net_device *dev);
-static void bond_mc_list_destroy(struct bonding *bond);
-static void bond_mc_add(bonding_t *bond, void *addr, int alen);
-static void bond_mc_delete(bonding_t *bond, void *addr, int alen);
-static int bond_mc_list_copy (struct dev_mc_list *src, struct bonding *dst, int gpf_flag);
-static inline int dmi_same(struct dev_mc_list *dmi1, struct dev_mc_list *dmi2);
-static void bond_set_promiscuity(bonding_t *bond, int inc);
-static void bond_set_allmulti(bonding_t *bond, int inc);
-static struct dev_mc_list* bond_mc_list_find_dmi(struct dev_mc_list *dmi, struct dev_mc_list *mc_list);
-static void bond_mc_update(bonding_t *bond, slave_t *new, slave_t *old);
-static int bond_enslave(struct net_device *master, struct net_device *slave);
-static int bond_release(struct net_device *master, struct net_device *slave);
-static int bond_release_all(struct net_device *master);
-static int bond_sethwaddr(struct net_device *master, struct net_device *slave);
-static void change_active_interface(struct bonding *bond, struct slave *new);
-static void reselect_active_interface(struct bonding *bond);
-static struct slave *find_best_interface(struct bonding *bond);
-
-
-/* #define BONDING_DEBUG 1 */
-#ifdef BONDING_DEBUG
-#define dprintk(x...) printk(x...)
-#else /* BONDING_DEBUG */
-#define dprintk(x...) do {} while (0)
-#endif /* BONDING_DEBUG */
-
-/* several macros */
-
-static void arp_send_all(slave_t *slave)
-{	
-	int i; 
-
-	for (i = 0; (i<MAX_ARP_IP_TARGETS) && arp_target[i]; i++) { 
-		arp_send(ARPOP_REQUEST, ETH_P_ARP, arp_target[i], slave->dev, 
-			 my_ip, arp_target_hw_addr, slave->dev->dev_addr,
-			 arp_target_hw_addr); 
-	} 
-}
- 
+/*---------------------------- General routines -----------------------------*/
 
-static const char *
-bond_mode_name(void)
+static const char *bond_mode_name(int mode)
 {
-	switch (bond_mode) {
+	switch (mode) {
 	case BOND_MODE_ROUNDROBIN :
 		return "load balancing (round-robin)";
 	case BOND_MODE_ACTIVEBACKUP :
@@ -657,767 +629,1070 @@ bond_mode_name(void)
 	}
 }
 
-static const char *
-multicast_mode_name(void)
+/*---------------------------------- VLAN -----------------------------------*/
+
+/**
+ * bond_add_vlan - add a new vlan id on bond
+ * @bond: bond that got the notification
+ * @vlan_id: the vlan id to add
+ *
+ * Returns -ENOMEM if allocation failed.
+ */
+static int bond_add_vlan(struct bonding *bond, unsigned short vlan_id)
 {
-	switch(multicast_mode) {
-	case BOND_MULTICAST_DISABLED :
-		return "disabled";
-	case BOND_MULTICAST_ACTIVE :
-		return "active slave only";
-	case BOND_MULTICAST_ALL :
-		return "all slaves";
-	default :
-		return "unknown";
+	struct vlan_entry *vlan;
+
+	dprintk("bond: %s, vlan id %d\n",
+		(bond ? bond->dev->name: "None"), vlan_id);
+
+	vlan = kmalloc(sizeof(struct vlan_entry), GFP_KERNEL);
+	if (!vlan) {
+		return -ENOMEM;
 	}
-}
 
-void bond_set_slave_inactive_flags(slave_t *slave)
-{
-	slave->state = BOND_STATE_BACKUP;
-	slave->dev->flags |= IFF_NOARP;
-}
+	INIT_LIST_HEAD(&vlan->vlan_list);
+	vlan->vlan_id = vlan_id;
 
-void bond_set_slave_active_flags(slave_t *slave)
-{
-	slave->state = BOND_STATE_ACTIVE;
-	slave->dev->flags &= ~IFF_NOARP;
+	write_lock_bh(&bond->lock);
+
+	list_add_tail(&vlan->vlan_list, &bond->vlan_list);
+
+	write_unlock_bh(&bond->lock);
+
+	dprintk("added VLAN ID %d on bond %s\n", vlan_id, bond->dev->name);
+
+	return 0;
 }
 
-/*
- * This function counts and verifies the the number of attached
- * slaves, checking the count against the expected value (given that incr
- * is either 1 or -1, for add or removal of a slave).  Only
- * bond_xmit_xor() uses the slave_cnt value, but this is still a good
- * consistency check.
+/**
+ * bond_del_vlan - delete a vlan id from bond
+ * @bond: bond that got the notification
+ * @vlan_id: the vlan id to delete
+ *
+ * returns -ENODEV if @vlan_id was not found in @bond.
  */
-static inline void
-update_slave_cnt(bonding_t *bond, int incr)
+static int bond_del_vlan(struct bonding *bond, unsigned short vlan_id)
 {
-	slave_t *slave = NULL;
-	int expect = bond->slave_cnt + incr;
+	struct vlan_entry *vlan, *next;
+	int res = -ENODEV;
 
-	bond->slave_cnt = 0;
-	for (slave = bond->prev; slave != (slave_t*)bond;
-	     slave = slave->prev) {
-		bond->slave_cnt++;
+	dprintk("bond: %s, vlan id %d\n", bond->dev->name, vlan_id);
+
+	write_lock_bh(&bond->lock);
+
+	list_for_each_entry_safe(vlan, next, &bond->vlan_list, vlan_list) {
+		if (vlan->vlan_id == vlan_id) {
+			list_del(&vlan->vlan_list);
+
+			if ((bond->params.mode == BOND_MODE_TLB) ||
+			    (bond->params.mode == BOND_MODE_ALB)) {
+				bond_alb_clear_vlan(bond, vlan_id);
+			}
+
+			dprintk("removed VLAN ID %d from bond %s\n", vlan_id,
+				bond->dev->name);
+
+			kfree(vlan);
+
+			if (list_empty(&bond->vlan_list) &&
+			    (bond->slave_cnt == 0)) {
+				/* Last VLAN removed and no slaves, so
+				 * restore block on adding VLANs. This will
+				 * be removed once new slaves that are not
+				 * VLAN challenged will be added.
+				 */
+				bond->dev->features |= NETIF_F_VLAN_CHALLENGED;
+			}
+
+			res = 0;
+			goto out;
+		}
 	}
 
-	if (expect != bond->slave_cnt)
-		BUG();
+	dprintk("couldn't find VLAN ID %d in bond %s\n", vlan_id,
+		bond->dev->name);
+
+out:
+	write_unlock_bh(&bond->lock);
+	return res;
 }
 
-/* 
- * This function detaches the slave <slave> from the list <bond>.
- * WARNING: no check is made to verify if the slave effectively
- * belongs to <bond>. It returns <slave> in case it's needed.
- * Nothing is freed on return, structures are just unchained.
- * If the bond->current_slave pointer was pointing to <slave>,
- * it should be changed by the calling function.
+/**
+ * bond_has_challenged_slaves
+ * @bond: the bond we're working on
  *
- * bond->lock held for writing by caller.
+ * Searches the slave list. Returns 1 if a vlan challenged slave
+ * was found, 0 otherwise.
+ *
+ * Assumes bond->lock is held.
  */
-static slave_t *
-bond_detach_slave(bonding_t *bond, slave_t *slave)
+static int bond_has_challenged_slaves(struct bonding *bond)
 {
-	if ((bond == NULL) || (slave == NULL) ||
-	   ((void *)bond == (void *)slave)) {
-		printk(KERN_ERR
-			"bond_detach_slave(): trying to detach "
-			"slave %p from bond %p\n", bond, slave);
-		return slave;
-	}
-
-	if (bond->next == slave) {  /* is the slave at the head ? */
-		if (bond->prev == slave) {  /* is the slave alone ? */
-			bond->prev = bond->next = (slave_t *)bond;
-		} else { /* not alone */
-			bond->next        = slave->next;
-			slave->next->prev = (slave_t *)bond;
-			bond->prev->next  = slave->next;
-		}
-	} else {
-		slave->prev->next = slave->next;
-		if (bond->prev == slave) {  /* is this slave the last one ? */
-			bond->prev = slave->prev;
-		} else {
-			slave->next->prev = slave->prev;
+	struct slave *slave;
+	int i;
+
+	bond_for_each_slave(bond, slave, i) {
+		if (slave->dev->features & NETIF_F_VLAN_CHALLENGED) {
+			dprintk("found VLAN challenged slave - %s\n",
+				slave->dev->name);
+			return 1;
 		}
 	}
 
-	update_slave_cnt(bond, -1);
-
-	return slave;
+	dprintk("no VLAN challenged slaves found\n");
+	return 0;
 }
 
-/*
- * This function attaches the slave <slave> to the list <bond>.
+/**
+ * bond_next_vlan - safely skip to the next item in the vlans list.
+ * @bond: the bond we're working on
+ * @curr: item we're advancing from
  *
- * bond->lock held for writing by caller.
+ * Returns %NULL if list is empty, bond->next_vlan if @curr is %NULL,
+ * or @curr->next otherwise (even if it is @curr itself again).
+ * 
+ * Caller must hold bond->lock
  */
-static void
-bond_attach_slave(struct bonding *bond, struct slave *new_slave)
+struct vlan_entry *bond_next_vlan(struct bonding *bond, struct vlan_entry *curr)
 {
-	/* 
-	 * queue to the end of the slaves list, make the first element its
-	 * successor, the last one its predecessor, and make it the bond's
-	 * predecessor. 
-	 *
-	 * Just to clarify, so future bonding driver hackers don't go through
-	 * the same confusion stage I did trying to figure this out, the
-	 * slaves are stored in a double linked circular list, sortof.
-	 * In the ->next direction, the last slave points to the first slave,
-	 * bypassing bond; only the slaves are in the ->next direction.
-	 * In the ->prev direction, however, the first slave points to bond
-	 * and bond points to the last slave.
-	 *
-	 * It looks like a circle with a little bubble hanging off one side
-	 * in the ->prev direction only.
-	 *
-	 * When going through the list once, its best to start at bond->prev
-	 * and go in the ->prev direction, testing for bond.  Doing this
-	 * in the ->next direction doesn't work.  Trust me, I know this now.
-	 * :)  -mts 2002.03.14
-	 */
-	new_slave->prev       = bond->prev;
-	new_slave->prev->next = new_slave;
-	bond->prev            = new_slave;
-	new_slave->next       = bond->next;
+	struct vlan_entry *next, *last;
 
-	update_slave_cnt(bond, 1);
-}
+	if (list_empty(&bond->vlan_list)) {
+		return NULL;
+	}
 
+	if (!curr) {
+		next = list_entry(bond->vlan_list.next,
+				  struct vlan_entry, vlan_list);
+	} else {
+		last = list_entry(bond->vlan_list.prev,
+				  struct vlan_entry, vlan_list);
+		if (last == curr) {
+			next = list_entry(bond->vlan_list.next,
+					  struct vlan_entry, vlan_list);
+		} else {
+			next = list_entry(curr->vlan_list.next,
+					  struct vlan_entry, vlan_list);
+		}
+	}
 
-/*
- * Less bad way to call ioctl from within the kernel; this needs to be
- * done some other way to get the call out of interrupt context.
- * Needs "ioctl" variable to be supplied by calling context.
- */
-#define IOCTL(dev, arg, cmd) ({		\
-	int ret;			\
-	mm_segment_t fs = get_fs();	\
-	set_fs(get_ds());		\
-	ret = ioctl(dev, arg, cmd);	\
-	set_fs(fs);			\
-	ret; })
+	return next;
+}
 
-/*
- * Get link speed and duplex from the slave's base driver
- * using ethtool. If for some reason the call fails or the
- * values are invalid, fake speed and duplex to 100/Full
- * and return error.
+/**
+ * bond_dev_queue_xmit - Prepare skb for xmit.
+ * 
+ * @bond: bond device that got this skb for tx.
+ * @skb: hw accel VLAN tagged skb to transmit
+ * @slave_dev: slave that is supposed to xmit this skbuff
+ * 
+ * When the bond gets an skb to tarnsmit that is
+ * already hardware accelerated VLAN tagged, and it
+ * needs to relay this skb to a slave that is not
+ * hw accel capable, the skb needs to be "unaccelerated",
+ * i.e. strip the hwaccel tag and re-insert it as part
+ * of the payload.
+ * 
+ * Assumption - once a VLAN device is created over the bond device, all
+ * packets are going to be hardware accelerated VLAN tagged since the IP
+ * binding is done over the VLAN device
  */
-static int bond_update_speed_duplex(struct slave *slave)
+int bond_dev_queue_xmit(struct bonding *bond, struct sk_buff *skb, struct net_device *slave_dev)
 {
-	struct net_device *dev = slave->dev;
-	static int (* ioctl)(struct net_device *, struct ifreq *, int);
-	struct ifreq ifr;
-	struct ethtool_cmd etool;
+	unsigned short vlan_id;
+	int res;
 
-	ioctl = dev->do_ioctl;
-	if (ioctl) {
-		etool.cmd = ETHTOOL_GSET;
-		ifr.ifr_data = (char*)&etool;
-		if (IOCTL(dev, &ifr, SIOCETHTOOL) == 0) {
-			slave->speed = etool.speed;
-			slave->duplex = etool.duplex;
-		} else {
-			goto err_out;
+	if (!list_empty(&bond->vlan_list) &&
+	    !(slave_dev->features & NETIF_F_HW_VLAN_TX)) {
+		res = vlan_get_tag(skb, &vlan_id);
+		if (res) {
+			return -EINVAL;
 		}
-	} else {
-		goto err_out;
-	}
 
-	switch (slave->speed) {
-		case SPEED_10:
-		case SPEED_100:
-		case SPEED_1000:
-			break;
-		default:
-			goto err_out;
+		skb->dev = slave_dev;
+		skb = vlan_put_tag(skb, vlan_id);
+		if (!skb) {
+			/* vlan_put_tag() frees the skb in case of error,
+			 * so return success here so the calling functions
+			 * won't attempt to free is again.
+			 */
+			return 0;
+		}
+	} else {
+		skb->dev = slave_dev;
 	}
 
-	switch (slave->duplex) {
-		case DUPLEX_FULL:
-		case DUPLEX_HALF:
-			break;
-		default:
-			goto err_out;
-	}
+	skb->priority = 1;
+	dev_queue_xmit(skb);
 
 	return 0;
-
-err_out:
-	/* Fake speed and duplex */
-	slave->speed = SPEED_100;
-	slave->duplex = DUPLEX_FULL;
-	return -1;
 }
 
-/* 
- * if <dev> supports MII link status reporting, check its link status.
- *
- * We either do MII/ETHTOOL ioctls, or check netif_carrier_ok(),
- * depening upon the setting of the use_carrier parameter.
- *
- * Return either BMSR_LSTATUS, meaning that the link is up (or we
- * can't tell and just pretend it is), or 0, meaning that the link is
- * down.
- *
- * If reporting is non-zero, instead of faking link up, return -1 if
- * both ETHTOOL and MII ioctls fail (meaning the device does not
- * support them).  If use_carrier is set, return whatever it says.
- * It'd be nice if there was a good way to tell if a driver supports
- * netif_carrier, but there really isn't.
+/*
+ * In the following 3 functions, bond_vlan_rx_register(), bond_vlan_rx_add_vid
+ * and bond_vlan_rx_kill_vid, We don't protect the slave list iteration with a
+ * lock because:
+ * a. This operation is performed in IOCTL context,
+ * b. The operation is protected by the RTNL semaphore in the 8021q code,
+ * c. Holding a lock with BH disabled while directly calling a base driver
+ *    entry point is generally a BAD idea.
+ * 
+ * The design of synchronization/protection for this operation in the 8021q
+ * module is good for one or more VLAN devices over a single physical device
+ * and cannot be extended for a teaming solution like bonding, so there is a
+ * potential race condition here where a net device from the vlan group might
+ * be referenced (either by a base driver or the 8021q code) while it is being
+ * removed from the system. However, it turns out we're not making matters
+ * worse, and if it works for regular VLAN usage it will work here too.
+*/
+
+/**
+ * bond_vlan_rx_register - Propagates registration to slaves
+ * @bond_dev: bonding net device that got called
+ * @grp: vlan group being registered
  */
-static int
-bond_check_dev_link(struct net_device *dev, int reporting)
+static void bond_vlan_rx_register(struct net_device *bond_dev, struct vlan_group *grp)
 {
-	static int (* ioctl)(struct net_device *, struct ifreq *, int);
-	struct ifreq ifr;
-	struct mii_ioctl_data *mii;
-	struct ethtool_value etool;
+	struct bonding *bond = bond_dev->priv;
+	struct slave *slave;
+	int i;
 
-	if (use_carrier) {
-		return netif_carrier_ok(dev) ? BMSR_LSTATUS : 0;
+	bond->vlgrp = grp;
+
+	bond_for_each_slave(bond, slave, i) {
+		struct net_device *slave_dev = slave->dev;
+
+		if ((slave_dev->features & NETIF_F_HW_VLAN_RX) &&
+		    slave_dev->vlan_rx_register) {
+			slave_dev->vlan_rx_register(slave_dev, grp);
+		}
 	}
+}
 
-	ioctl = dev->do_ioctl;
-	if (ioctl) {
-		/* TODO: set pointer to correct ioctl on a per team member */
-		/*       bases to make this more efficient. that is, once  */
-		/*       we determine the correct ioctl, we will always    */
-		/*       call it and not the others for that team          */
-		/*       member.                                           */
+/**
+ * bond_vlan_rx_add_vid - Propagates adding an id to slaves
+ * @bond_dev: bonding net device that got called
+ * @vid: vlan id being added
+ */
+static void bond_vlan_rx_add_vid(struct net_device *bond_dev, uint16_t vid)
+{
+	struct bonding *bond = bond_dev->priv;
+	struct slave *slave;
+	int i, res;
 
-		/*
-		 * We cannot assume that SIOCGMIIPHY will also read a
-		 * register; not all network drivers (e.g., e100)
-		 * support that.
-		 */
+	bond_for_each_slave(bond, slave, i) {
+		struct net_device *slave_dev = slave->dev;
 
-		/* Yes, the mii is overlaid on the ifreq.ifr_ifru */
-		mii = (struct mii_ioctl_data *)&ifr.ifr_data;
-		if (IOCTL(dev, &ifr, SIOCGMIIPHY) == 0) {
-			mii->reg_num = MII_BMSR;
-			if (IOCTL(dev, &ifr, SIOCGMIIREG) == 0) {
-				return mii->val_out & BMSR_LSTATUS;
-			}
-		}
-
-		/* try SIOCETHTOOL ioctl, some drivers cache ETHTOOL_GLINK */
-		/* for a period of time so we attempt to get link status   */
-		/* from it last if the above MII ioctls fail...            */
-	        etool.cmd = ETHTOOL_GLINK;
-	        ifr.ifr_data = (char*)&etool;
-		if (IOCTL(dev, &ifr, SIOCETHTOOL) == 0) {
-			if (etool.data == 1) {
-				return BMSR_LSTATUS;
-			} else { 
-#ifdef BONDING_DEBUG
-				printk(KERN_INFO 
-					":: SIOCETHTOOL shows link down \n");
-#endif
-				return 0;
-			} 
+		if ((slave_dev->features & NETIF_F_HW_VLAN_FILTER) &&
+		    slave_dev->vlan_rx_add_vid) {
+			slave_dev->vlan_rx_add_vid(slave_dev, vid);
 		}
+	}
 
+	res = bond_add_vlan(bond, vid);
+	if (res) {
+		printk(KERN_ERR DRV_NAME
+		       ": %s: Failed to add vlan id %d\n",
+		       bond_dev->name, vid);
 	}
- 
-	/*
-	 * If reporting, report that either there's no dev->do_ioctl,
-	 * or both SIOCGMIIREG and SIOCETHTOOL failed (meaning that we
-	 * cannot report link status).  If not reporting, pretend
-	 * we're ok.
-	 */
-	return reporting ? -1 : BMSR_LSTATUS;
 }
 
-static u16 bond_check_mii_link(bonding_t *bond)
+/**
+ * bond_vlan_rx_kill_vid - Propagates deleting an id to slaves
+ * @bond_dev: bonding net device that got called
+ * @vid: vlan id being removed
+ */
+static void bond_vlan_rx_kill_vid(struct net_device *bond_dev, uint16_t vid)
 {
-	int has_active_interface = 0;
+	struct bonding *bond = bond_dev->priv;
+	struct slave *slave;
+	struct net_device *vlan_dev;
+	int i, res;
 
-	read_lock_bh(&bond->lock);
-	read_lock(&bond->ptrlock);
-	has_active_interface = (bond->current_slave != NULL);
-	read_unlock(&bond->ptrlock);
-	read_unlock_bh(&bond->lock);
+	bond_for_each_slave(bond, slave, i) {
+		struct net_device *slave_dev = slave->dev;
+
+		if ((slave_dev->features & NETIF_F_HW_VLAN_FILTER) &&
+		    slave_dev->vlan_rx_kill_vid) {
+			/* Save and then restore vlan_dev in the grp array,
+			 * since the slave's driver might clear it.
+			 */
+			vlan_dev = bond->vlgrp->vlan_devices[vid];
+			slave_dev->vlan_rx_kill_vid(slave_dev, vid);
+			bond->vlgrp->vlan_devices[vid] = vlan_dev;
+		}
+	}
 
-	return (has_active_interface ? BMSR_LSTATUS : 0);
+	res = bond_del_vlan(bond, vid);
+	if (res) {
+		printk(KERN_ERR DRV_NAME
+		       ": %s: Failed to remove vlan id %d\n",
+		       bond_dev->name, vid);
+	}
 }
 
-/* register to receive lacpdus on a bond */
-static void bond_register_lacpdu(struct bonding *bond)
+static void bond_add_vlans_on_slave(struct bonding *bond, struct net_device *slave_dev)
 {
-	struct packet_type* pk_type = &(BOND_AD_INFO(bond).ad_pkt_type);
+	struct vlan_entry *vlan;
 
-	/* initialize packet type */
-	pk_type->type = PKT_TYPE_LACPDU;
-	pk_type->dev = bond->device;
-	pk_type->func = bond_3ad_lacpdu_recv;
-	pk_type->data = (void*)1;  /* understand shared skbs */
+	write_lock_bh(&bond->lock);
 
-	dev_add_pack(pk_type);
+	if (list_empty(&bond->vlan_list)) {
+		goto out;
+	}
+
+	if ((slave_dev->features & NETIF_F_HW_VLAN_RX) &&
+	    slave_dev->vlan_rx_register) {
+		slave_dev->vlan_rx_register(slave_dev, bond->vlgrp);
+	}
+
+	if (!(slave_dev->features & NETIF_F_HW_VLAN_FILTER) ||
+	    !(slave_dev->vlan_rx_add_vid)) {
+		goto out;
+	}
+
+	list_for_each_entry(vlan, &bond->vlan_list, vlan_list) {
+		slave_dev->vlan_rx_add_vid(slave_dev, vlan->vlan_id);
+	}
+
+out:
+	write_unlock_bh(&bond->lock);
 }
 
-/* unregister to receive lacpdus on a bond */
-static void bond_unregister_lacpdu(struct bonding *bond)
+static void bond_del_vlans_from_slave(struct bonding *bond, struct net_device *slave_dev)
 {
-	dev_remove_pack(&(BOND_AD_INFO(bond).ad_pkt_type));
+	struct vlan_entry *vlan;
+	struct net_device *vlan_dev;
+
+	write_lock_bh(&bond->lock);
+
+	if (list_empty(&bond->vlan_list)) {
+		goto out;
+	}
+
+	if (!(slave_dev->features & NETIF_F_HW_VLAN_FILTER) ||
+	    !(slave_dev->vlan_rx_kill_vid)) {
+		goto unreg;
+	}
+
+	list_for_each_entry(vlan, &bond->vlan_list, vlan_list) {
+		/* Save and then restore vlan_dev in the grp array,
+		 * since the slave's driver might clear it.
+		 */
+		vlan_dev = bond->vlgrp->vlan_devices[vlan->vlan_id];
+		slave_dev->vlan_rx_kill_vid(slave_dev, vlan->vlan_id);
+		bond->vlgrp->vlan_devices[vlan->vlan_id] = vlan_dev;
+	}
+
+unreg:
+	if ((slave_dev->features & NETIF_F_HW_VLAN_RX) &&
+	    slave_dev->vlan_rx_register) {
+		slave_dev->vlan_rx_register(slave_dev, NULL);
+	}
+
+out:
+	write_unlock_bh(&bond->lock);
 }
 
-static int bond_open(struct net_device *dev)
+/*------------------------------- Link status -------------------------------*/
+
+/*
+ * Get link speed and duplex from the slave's base driver
+ * using ethtool. If for some reason the call fails or the
+ * values are invalid, fake speed and duplex to 100/Full
+ * and return error.
+ */
+static int bond_update_speed_duplex(struct slave *slave)
 {
-	struct bonding *bond = (struct bonding *)(dev->priv);
-	struct timer_list *timer = &((struct bonding *)(dev->priv))->mii_timer;
-	struct timer_list *arp_timer = &((struct bonding *)(dev->priv))->arp_timer;
+	struct net_device *slave_dev = slave->dev;
+	static int (* ioctl)(struct net_device *, struct ifreq *, int);
+	struct ifreq ifr;
+	struct ethtool_cmd etool;
 
-	if ((bond_mode == BOND_MODE_TLB) ||
-	    (bond_mode == BOND_MODE_ALB)) {
-		struct timer_list *alb_timer = &(BOND_ALB_INFO(bond).alb_timer);
+	/* Fake speed and duplex */
+	slave->speed = SPEED_100;
+	slave->duplex = DUPLEX_FULL;
 
-		/* bond_alb_initialize must be called before the timer
-		 * is started.
-		 */
-		if (bond_alb_initialize(bond, (bond_mode == BOND_MODE_ALB))) {
-			/* something went wrong - fail the open operation */
+	if (slave_dev->ethtool_ops) {
+		u32 res;
+
+		if (!slave_dev->ethtool_ops->get_settings) {
 			return -1;
 		}
 
-		init_timer(alb_timer);
-		alb_timer->expires  = jiffies + 1;
-		alb_timer->data     = (unsigned long)bond;
-		alb_timer->function = (void *)&bond_alb_monitor;
-		add_timer(alb_timer);
-	}
+		res = slave_dev->ethtool_ops->get_settings(slave_dev, &etool);
+		if (res < 0) {
+			return -1;
+		}
 
-	if (miimon > 0) {  /* link check interval, in milliseconds. */
-		init_timer(timer);
-		timer->expires  = jiffies + (miimon * HZ / 1000);
-		timer->data     = (unsigned long)dev;
-		timer->function = (void *)&bond_mii_monitor;
-		add_timer(timer);
+		goto verify;
 	}
 
-	if (arp_interval> 0) {  /* arp interval, in milliseconds. */
-		init_timer(arp_timer);
-		arp_timer->expires  = jiffies + (arp_interval * HZ / 1000);
-		arp_timer->data     = (unsigned long)dev;
-		if (bond_mode == BOND_MODE_ACTIVEBACKUP) {
-			arp_timer->function = (void *)&activebackup_arp_monitor;
-		} else {
-			arp_timer->function = (void *)&loadbalance_arp_monitor;
-		}
-		add_timer(arp_timer);
+	ioctl = slave_dev->do_ioctl;
+	strncpy(ifr.ifr_name, slave_dev->name, IFNAMSIZ);
+	etool.cmd = ETHTOOL_GSET;
+	ifr.ifr_data = (char*)&etool;
+	if (!ioctl || (IOCTL(slave_dev, &ifr, SIOCETHTOOL) < 0)) {
+		return -1;
+	}
+
+verify:
+	switch (etool.speed) {
+	case SPEED_10:
+	case SPEED_100:
+	case SPEED_1000:
+		break;
+	default:
+		return -1;
 	}
 
-	if (bond_mode == BOND_MODE_8023AD) {
-		struct timer_list *ad_timer = &(BOND_AD_INFO(bond).ad_timer);
-		init_timer(ad_timer);
-		ad_timer->expires  = jiffies + (AD_TIMER_INTERVAL * HZ / 1000);
-		ad_timer->data     = (unsigned long)bond;
-		ad_timer->function = (void *)&bond_3ad_state_machine_handler;
-		add_timer(ad_timer);
-
-		/* register to receive LACPDUs */
-		bond_register_lacpdu(bond);
+	switch (etool.duplex) {
+	case DUPLEX_FULL:
+	case DUPLEX_HALF:
+		break;
+	default:
+		return -1;
 	}
 
+	slave->speed = etool.speed;
+	slave->duplex = etool.duplex;
+
 	return 0;
 }
 
-static int bond_close(struct net_device *master)
+/*
+ * if <dev> supports MII link status reporting, check its link status.
+ *
+ * We either do MII/ETHTOOL ioctls, or check netif_carrier_ok(),
+ * depening upon the setting of the use_carrier parameter.
+ *
+ * Return either BMSR_LSTATUS, meaning that the link is up (or we
+ * can't tell and just pretend it is), or 0, meaning that the link is
+ * down.
+ *
+ * If reporting is non-zero, instead of faking link up, return -1 if
+ * both ETHTOOL and MII ioctls fail (meaning the device does not
+ * support them).  If use_carrier is set, return whatever it says.
+ * It'd be nice if there was a good way to tell if a driver supports
+ * netif_carrier, but there really isn't.
+ */
+static int bond_check_dev_link(struct bonding *bond, struct net_device *slave_dev, int reporting)
 {
-	bonding_t *bond = (struct bonding *) master->priv;
-
-	write_lock_bh(&bond->lock);
+	static int (* ioctl)(struct net_device *, struct ifreq *, int);
+	struct ifreq ifr;
+	struct mii_ioctl_data *mii;
+	struct ethtool_value etool;
 
-	if (miimon > 0) {  /* link check interval, in milliseconds. */
-		del_timer(&bond->mii_timer);
-	}
-	if (arp_interval> 0) {  /* arp interval, in milliseconds. */
-		del_timer(&bond->arp_timer);
-                if (arp_target_hw_addr != NULL) {
-			kfree(arp_target_hw_addr); 
-			arp_target_hw_addr = NULL;
-		}
+	if (bond->params.use_carrier) {
+		return netif_carrier_ok(slave_dev) ? BMSR_LSTATUS : 0;
 	}
 
-	if (bond_mode == BOND_MODE_8023AD) {
-		del_timer_sync(&(BOND_AD_INFO(bond).ad_timer));
+	ioctl = slave_dev->do_ioctl;
+	if (ioctl) {
+		/* TODO: set pointer to correct ioctl on a per team member */
+		/*       bases to make this more efficient. that is, once  */
+		/*       we determine the correct ioctl, we will always    */
+		/*       call it and not the others for that team          */
+		/*       member.                                           */
 
-		/* Unregister the receive of LACPDUs */
-		bond_unregister_lacpdu(bond);
-	}
+		/*
+		 * We cannot assume that SIOCGMIIPHY will also read a
+		 * register; not all network drivers (e.g., e100)
+		 * support that.
+		 */
 
-	bond_mc_list_destroy (bond);
+		/* Yes, the mii is overlaid on the ifreq.ifr_ifru */
+		strncpy(ifr.ifr_name, slave_dev->name, IFNAMSIZ);
+		mii = (struct mii_ioctl_data *)&ifr.ifr_data;
+		if (IOCTL(slave_dev, &ifr, SIOCGMIIPHY) == 0) {
+			mii->reg_num = MII_BMSR;
+			if (IOCTL(slave_dev, &ifr, SIOCGMIIREG) == 0) {
+				return (mii->val_out & BMSR_LSTATUS);
+			}
+		}
+	}
 
-	write_unlock_bh(&bond->lock);
+	/* try SIOCETHTOOL ioctl, some drivers cache ETHTOOL_GLINK */
+	/* for a period of time so we attempt to get link status   */
+	/* from it last if the above MII ioctls fail...            */
+	if (slave_dev->ethtool_ops) {
+		if (slave_dev->ethtool_ops->get_link) {
+			u32 link;
 
-	/* Release the bonded slaves */
-	bond_release_all(master);
+			link = slave_dev->ethtool_ops->get_link(slave_dev);
 
-	if ((bond_mode == BOND_MODE_TLB) ||
-	    (bond_mode == BOND_MODE_ALB)) {
-		del_timer_sync(&(BOND_ALB_INFO(bond).alb_timer));
+			return link ? BMSR_LSTATUS : 0;
+		}
+	}
 
-		bond_alb_deinitialize(bond);
+	if (ioctl) {
+		strncpy(ifr.ifr_name, slave_dev->name, IFNAMSIZ);
+		etool.cmd = ETHTOOL_GLINK;
+		ifr.ifr_data = (char*)&etool;
+		if (IOCTL(slave_dev, &ifr, SIOCETHTOOL) == 0) {
+			if (etool.data == 1) {
+				return BMSR_LSTATUS;
+			} else {
+				dprintk("SIOCETHTOOL shows link down\n");
+				return 0;
+			}
+		}
 	}
 
-	return 0;
+	/*
+	 * If reporting, report that either there's no dev->do_ioctl,
+	 * or both SIOCGMIIREG and SIOCETHTOOL failed (meaning that we
+	 * cannot report link status).  If not reporting, pretend
+	 * we're ok.
+	 */
+	return (reporting ? -1 : BMSR_LSTATUS);
 }
 
-/* 
- * flush all members of flush->mc_list from device dev->mc_list
+/*----------------------------- Multicast list ------------------------------*/
+
+/*
+ * Returns 0 if dmi1 and dmi2 are the same, non-0 otherwise
  */
-static void bond_mc_list_flush(struct net_device *dev, struct net_device *flush)
-{ 
-	struct dev_mc_list *dmi; 
- 
-	for (dmi = flush->mc_list; dmi != NULL; dmi = dmi->next) 
-		dev_mc_delete(dev, dmi->dmi_addr, dmi->dmi_addrlen, 0);
+static inline int bond_is_dmi_same(struct dev_mc_list *dmi1, struct dev_mc_list *dmi2)
+{
+	return memcmp(dmi1->dmi_addr, dmi2->dmi_addr, dmi1->dmi_addrlen) == 0 &&
+			dmi1->dmi_addrlen == dmi2->dmi_addrlen;
+}
 
-	if (bond_mode == BOND_MODE_8023AD) {
-		/* del lacpdu mc addr from mc list */
-		u8 lacpdu_multicast[ETH_ALEN] = MULTICAST_LACPDU_ADDR;
+/*
+ * returns dmi entry if found, NULL otherwise
+ */
+static struct dev_mc_list *bond_mc_list_find_dmi(struct dev_mc_list *dmi, struct dev_mc_list *mc_list)
+{
+	struct dev_mc_list *idmi;
 
-		dev_mc_delete(dev, lacpdu_multicast, ETH_ALEN, 0);
+	for (idmi = mc_list; idmi; idmi = idmi->next) {
+		if (bond_is_dmi_same(dmi, idmi)) {
+			return idmi;
+		}
 	}
+
+	return NULL;
 }
 
 /*
- * Totally destroys the mc_list in bond
+ * Push the promiscuity flag down to appropriate slaves
  */
-static void bond_mc_list_destroy(struct bonding *bond)
+static void bond_set_promiscuity(struct bonding *bond, int inc)
 {
-	struct dev_mc_list *dmi;
+	if (USES_PRIMARY(bond->params.mode)) {
+		/* write lock already acquired */
+		if (bond->curr_active_slave) {
+			dev_set_promiscuity(bond->curr_active_slave->dev, inc);
+		}
+	} else {
+		struct slave *slave;
+		int i;
+		bond_for_each_slave(bond, slave, i) {
+			dev_set_promiscuity(slave->dev, inc);
+		}
+	}
+}
 
-	dmi = bond->mc_list; 
-	while (dmi) { 
-		bond->mc_list = dmi->next; 
-		kfree(dmi); 
-		dmi = bond->mc_list; 
+/*
+ * Push the allmulti flag down to all slaves
+ */
+static void bond_set_allmulti(struct bonding *bond, int inc)
+{
+	if (USES_PRIMARY(bond->params.mode)) {
+		/* write lock already acquired */
+		if (bond->curr_active_slave) {
+			dev_set_allmulti(bond->curr_active_slave->dev, inc);
+		}
+	} else {
+		struct slave *slave;
+		int i;
+		bond_for_each_slave(bond, slave, i) {
+			dev_set_allmulti(slave->dev, inc);
+		}
 	}
 }
 
 /*
- * Add a Multicast address to every slave in the bonding group
+ * Add a Multicast address to slaves
+ * according to mode
  */
-static void bond_mc_add(bonding_t *bond, void *addr, int alen)
-{ 
-	slave_t *slave;
-	switch (multicast_mode) {
-	case BOND_MULTICAST_ACTIVE :
+static void bond_mc_add(struct bonding *bond, void *addr, int alen)
+{
+	if (USES_PRIMARY(bond->params.mode)) {
 		/* write lock already acquired */
-		if (bond->current_slave != NULL)
-			dev_mc_add(bond->current_slave->dev, addr, alen, 0);
-		break;
-	case BOND_MULTICAST_ALL :
-		for (slave = bond->prev; slave != (slave_t*)bond; slave = slave->prev)
+		if (bond->curr_active_slave) {
+			dev_mc_add(bond->curr_active_slave->dev, addr, alen, 0);
+		}
+	} else {
+		struct slave *slave;
+		int i;
+		bond_for_each_slave(bond, slave, i) {
 			dev_mc_add(slave->dev, addr, alen, 0);
-		break;
-	case BOND_MULTICAST_DISABLED :
-		break;
+		}
 	}
-} 
+}
 
 /*
- * Remove a multicast address from every slave in the bonding group
+ * Remove a multicast address from slave
+ * according to mode
  */
-static void bond_mc_delete(bonding_t *bond, void *addr, int alen)
-{ 
-	slave_t *slave; 
-	switch (multicast_mode) {
-	case BOND_MULTICAST_ACTIVE :
+static void bond_mc_delete(struct bonding *bond, void *addr, int alen)
+{
+	if (USES_PRIMARY(bond->params.mode)) {
 		/* write lock already acquired */
-		if (bond->current_slave != NULL)
-			dev_mc_delete(bond->current_slave->dev, addr, alen, 0);
-		break;
-	case BOND_MULTICAST_ALL :
-		for (slave = bond->prev; slave != (slave_t*)bond; slave = slave->prev)
+		if (bond->curr_active_slave) {
+			dev_mc_delete(bond->curr_active_slave->dev, addr, alen, 0);
+		}
+	} else {
+		struct slave *slave;
+		int i;
+		bond_for_each_slave(bond, slave, i) {
 			dev_mc_delete(slave->dev, addr, alen, 0);
-		break;
-	case BOND_MULTICAST_DISABLED :
-		break;
+		}
+	}
+}
+
+/*
+ * Totally destroys the mc_list in bond
+ */
+static void bond_mc_list_destroy(struct bonding *bond)
+{
+	struct dev_mc_list *dmi;
+
+	dmi = bond->mc_list;
+	while (dmi) {
+		bond->mc_list = dmi->next;
+		kfree(dmi);
+		dmi = bond->mc_list;
 	}
-} 
+}
 
 /*
  * Copy all the Multicast addresses from src to the bonding device dst
  */
-static int bond_mc_list_copy (struct dev_mc_list *src, struct bonding *dst,
- int gpf_flag)
+static int bond_mc_list_copy(struct dev_mc_list *mc_list, struct bonding *bond, int gpf_flag)
 {
 	struct dev_mc_list *dmi, *new_dmi;
 
-   	for (dmi = src; dmi != NULL; dmi = dmi->next) { 
+	for (dmi = mc_list; dmi; dmi = dmi->next) {
 		new_dmi = kmalloc(sizeof(struct dev_mc_list), gpf_flag);
 
-		if (new_dmi == NULL) {
-			return -ENOMEM; 
+		if (!new_dmi) {
+			/* FIXME: Potential memory leak !!! */
+			return -ENOMEM;
 		}
 
-		new_dmi->next = dst->mc_list; 
-		dst->mc_list = new_dmi;
-
-		new_dmi->dmi_addrlen = dmi->dmi_addrlen; 
-		memcpy(new_dmi->dmi_addr, dmi->dmi_addr, dmi->dmi_addrlen); 
+		new_dmi->next = bond->mc_list;
+		bond->mc_list = new_dmi;
+		new_dmi->dmi_addrlen = dmi->dmi_addrlen;
+		memcpy(new_dmi->dmi_addr, dmi->dmi_addr, dmi->dmi_addrlen);
 		new_dmi->dmi_users = dmi->dmi_users;
-		new_dmi->dmi_gusers = dmi->dmi_gusers; 
-	} 
+		new_dmi->dmi_gusers = dmi->dmi_gusers;
+	}
+
 	return 0;
 }
 
 /*
- * Returns 0 if dmi1 and dmi2 are the same, non-0 otherwise
- */
-static inline int dmi_same(struct dev_mc_list *dmi1, struct dev_mc_list *dmi2)
-{ 
-	return memcmp(dmi1->dmi_addr, dmi2->dmi_addr, dmi1->dmi_addrlen) == 0 &&
-	 dmi1->dmi_addrlen == dmi2->dmi_addrlen;
-} 
-
-/*
- * Push the promiscuity flag down to appropriate slaves
+ * flush all members of flush->mc_list from device dev->mc_list
  */
-static void bond_set_promiscuity(bonding_t *bond, int inc)
-{ 
-	slave_t *slave; 
-
-	if (USES_PRIMARY(bond_mode)) {
-		if (bond->current_slave) {
-			dev_set_promiscuity(bond->current_slave->dev, inc);
-		}
+static void bond_mc_list_flush(struct net_device *bond_dev, struct net_device *slave_dev)
+{
+	struct bonding *bond = bond_dev->priv;
+	struct dev_mc_list *dmi;
 
-	} else { 
-		for (slave = bond->prev; slave != (slave_t*)bond;
-		     slave = slave->prev) {
-			dev_set_promiscuity(slave->dev, inc);
-		}
+	for (dmi = bond_dev->mc_list; dmi; dmi = dmi->next) {
+		dev_mc_delete(slave_dev, dmi->dmi_addr, dmi->dmi_addrlen, 0);
 	}
-} 
 
-/*
- * Push the allmulti flag down to all slaves
- */
-static void bond_set_allmulti(bonding_t *bond, int inc)
-{ 
-	slave_t *slave; 
-	switch (multicast_mode) {
-	case BOND_MULTICAST_ACTIVE : 
-		/* write lock already acquired */
-		if (bond->current_slave != NULL)
-			dev_set_allmulti(bond->current_slave->dev, inc);
-		break;
-	case BOND_MULTICAST_ALL :
-		for (slave = bond->prev; slave != (slave_t*)bond; slave = slave->prev)
-			dev_set_allmulti(slave->dev, inc);
-		break;
-	case BOND_MULTICAST_DISABLED :
-		break;
+	if (bond->params.mode == BOND_MODE_8023AD) {
+		/* del lacpdu mc addr from mc list */
+		u8 lacpdu_multicast[ETH_ALEN] = MULTICAST_LACPDU_ADDR;
+
+		dev_mc_delete(slave_dev, lacpdu_multicast, ETH_ALEN, 0);
 	}
-} 
+}
+
+/*--------------------------- Active slave change ---------------------------*/
 
-/* 
- * returns dmi entry if found, NULL otherwise 
+/*
+ * Update the mc list and multicast-related flags for the new and
+ * old active slaves (if any) according to the multicast mode, and
+ * promiscuous flags unconditionally.
  */
-static struct dev_mc_list* bond_mc_list_find_dmi(struct dev_mc_list *dmi,
- struct dev_mc_list *mc_list)
-{ 
-	struct dev_mc_list *idmi;
+static void bond_mc_swap(struct bonding *bond, struct slave *new_active, struct slave *old_active)
+{
+	struct dev_mc_list *dmi;
+
+	if (!USES_PRIMARY(bond->params.mode)) {
+		/* nothing to do -  mc list is already up-to-date on
+		 * all slaves
+		 */
+		return;
+	}
+
+	if (old_active) {
+		if (bond->dev->flags & IFF_PROMISC) {
+			dev_set_promiscuity(old_active->dev, -1);
+		}
 
-	for (idmi = mc_list; idmi != NULL; idmi = idmi->next) {
-		if (dmi_same(dmi, idmi)) {
-			return idmi; 
+		if (bond->dev->flags & IFF_ALLMULTI) {
+			dev_set_allmulti(old_active->dev, -1);
+		}
+
+		for (dmi = bond->dev->mc_list; dmi; dmi = dmi->next) {
+			dev_mc_delete(old_active->dev, dmi->dmi_addr, dmi->dmi_addrlen, 0);
 		}
 	}
-	return NULL;
-} 
 
-static void set_multicast_list(struct net_device *master)
+	if (new_active) {
+		if (bond->dev->flags & IFF_PROMISC) {
+			dev_set_promiscuity(new_active->dev, 1);
+		}
+
+		if (bond->dev->flags & IFF_ALLMULTI) {
+			dev_set_allmulti(new_active->dev, 1);
+		}
+
+		for (dmi = bond->dev->mc_list; dmi; dmi = dmi->next) {
+			dev_mc_add(new_active->dev, dmi->dmi_addr, dmi->dmi_addrlen, 0);
+		}
+	}
+}
+
+/**
+ * find_best_interface - select the best available slave to be the active one
+ * @bond: our bonding struct
+ *
+ * Warning: Caller must hold curr_slave_lock for writing.
+ */
+static struct slave *bond_find_best_slave(struct bonding *bond)
 {
-	bonding_t *bond = master->priv;
-	struct dev_mc_list *dmi;
+	struct slave *new_active, *old_active;
+	struct slave *bestslave = NULL;
+	int mintime = bond->params.updelay;
+	int i;
 
-	write_lock_bh(&bond->lock);
+	new_active = old_active = bond->curr_active_slave;
 
-	/*
-	 * Do promisc before checking multicast_mode
+	if (!new_active) { /* there were no active slaves left */
+		if (bond->slave_cnt > 0) {  /* found one slave */
+			new_active = bond->first_slave;
+		} else {
+			return NULL; /* still no slave, return NULL */
+		}
+	}
+
+	/* first try the primary link; if arping, a link must tx/rx traffic
+	 * before it can be considered the curr_active_slave - also, we would skip
+	 * slaves between the curr_active_slave and primary_slave that may be up
+	 * and able to arp
 	 */
-	if ( (master->flags & IFF_PROMISC) && !(bond->flags & IFF_PROMISC) )
-		bond_set_promiscuity(bond, 1); 
+	if ((bond->primary_slave) &&
+	    (!bond->params.arp_interval) &&
+	    (IS_UP(bond->primary_slave->dev))) {
+		new_active = bond->primary_slave;
+	}
 
-	if ( !(master->flags & IFF_PROMISC) && (bond->flags & IFF_PROMISC) ) 
-		bond_set_promiscuity(bond, -1); 
+	/* remember where to stop iterating over the slaves */
+	old_active = new_active;
 
-	if (multicast_mode == BOND_MULTICAST_DISABLED) {
-		bond->flags = master->flags;
-		write_unlock_bh(&bond->lock);
+	bond_for_each_slave_from(bond, new_active, i, old_active) {
+		if (IS_UP(new_active->dev)) {
+			if (new_active->link == BOND_LINK_UP) {
+				return new_active;
+			} else if (new_active->link == BOND_LINK_BACK) {
+				/* link up, but waiting for stabilization */
+				if (new_active->delay < mintime) {
+					mintime = new_active->delay;
+					bestslave = new_active;
+				}
+			}
+		}
+	}
+
+	return bestslave;
+}
+
+/**
+ * change_active_interface - change the active slave into the specified one
+ * @bond: our bonding struct
+ * @new: the new slave to make the active one
+ *
+ * Set the new slave to the bond's settings and unset them on the old
+ * curr_active_slave.
+ * Setting include flags, mc-list, promiscuity, allmulti, etc.
+ *
+ * If @new's link state is %BOND_LINK_BACK we'll set it to %BOND_LINK_UP,
+ * because it is apparently the best available slave we have, even though its
+ * updelay hasn't timed out yet.
+ *
+ * Warning: Caller must hold curr_slave_lock for writing.
+ */
+static void bond_change_active_slave(struct bonding *bond, struct slave *new_active)
+{
+	struct slave *old_active = bond->curr_active_slave;
+
+	if (old_active == new_active) {
 		return;
 	}
 
-	/* set allmulti flag to slaves */ 
-	if ( (master->flags & IFF_ALLMULTI) && !(bond->flags & IFF_ALLMULTI) ) 
-		bond_set_allmulti(bond, 1); 
+	if (new_active) {
+		if (new_active->link == BOND_LINK_BACK) {
+			if (USES_PRIMARY(bond->params.mode)) {
+				printk(KERN_INFO DRV_NAME
+				       ": %s: making interface %s the new "
+				       "active one %d ms earlier.\n",
+				       bond->dev->name, new_active->dev->name,
+				       (bond->params.updelay - new_active->delay) * bond->params.miimon);
+			}
+
+			new_active->delay = 0;
+			new_active->link = BOND_LINK_UP;
+			new_active->jiffies = jiffies;
 
-	if ( !(master->flags & IFF_ALLMULTI) && (bond->flags & IFF_ALLMULTI) )
-		bond_set_allmulti(bond, -1); 
+			if (bond->params.mode == BOND_MODE_8023AD) {
+				bond_3ad_handle_link_change(new_active, BOND_LINK_UP);
+			}
 
-	bond->flags = master->flags; 
+			if ((bond->params.mode == BOND_MODE_TLB) ||
+			    (bond->params.mode == BOND_MODE_ALB)) {
+				bond_alb_handle_link_change(bond, new_active, BOND_LINK_UP);
+			}
+		} else {
+			if (USES_PRIMARY(bond->params.mode)) {
+				printk(KERN_INFO DRV_NAME
+				       ": %s: making interface %s the new "
+				       "active one.\n",
+				       bond->dev->name, new_active->dev->name);
+			}
+		}
+	}
 
-	/* looking for addresses to add to slaves' mc list */ 
-	for (dmi = master->mc_list; dmi != NULL; dmi = dmi->next) { 
-		if (bond_mc_list_find_dmi(dmi, bond->mc_list) == NULL) 
-		 bond_mc_add(bond, dmi->dmi_addr, dmi->dmi_addrlen); 
-	} 
+	if (bond->params.mode == BOND_MODE_ACTIVEBACKUP) {
+		if (old_active) {
+			bond_set_slave_inactive_flags(old_active);
+		}
 
-	/* looking for addresses to delete from slaves' list */ 
-	for (dmi = bond->mc_list; dmi != NULL; dmi = dmi->next) { 
-		if (bond_mc_list_find_dmi(dmi, master->mc_list) == NULL) 
-		 bond_mc_delete(bond, dmi->dmi_addr, dmi->dmi_addrlen); 
+		if (new_active) {
+			bond_set_slave_active_flags(new_active);
+		}
 	}
 
+	if (USES_PRIMARY(bond->params.mode)) {
+		bond_mc_swap(bond, new_active, old_active);
+	}
 
-	/* save master's multicast list */ 
-	bond_mc_list_destroy (bond);
-	bond_mc_list_copy (master->mc_list, bond, GFP_ATOMIC);
+	if ((bond->params.mode == BOND_MODE_TLB) ||
+	    (bond->params.mode == BOND_MODE_ALB)) {
+		bond_alb_handle_active_change(bond, new_active);
+	} else {
+		bond->curr_active_slave = new_active;
+	}
+}
 
-	write_unlock_bh(&bond->lock);
+/**
+ * bond_select_active_slave - select a new active slave, if needed
+ * @bond: our bonding struct
+ *
+ * This functions shoud be called when one of the following occurs:
+ * - The old curr_active_slave has been released or lost its link.
+ * - The primary_slave has got its link back.
+ * - A slave has got its link back and there's no old curr_active_slave.
+ *
+ * Warning: Caller must hold curr_slave_lock for writing.
+ */
+static void bond_select_active_slave(struct bonding *bond)
+{
+	struct slave *best_slave;
+
+	best_slave = bond_find_best_slave(bond);
+	if (best_slave != bond->curr_active_slave) {
+		bond_change_active_slave(bond, best_slave);
+	}
 }
 
+/*--------------------------- slave list handling ---------------------------*/
+
 /*
- * Update the mc list and multicast-related flags for the new and 
- * old active slaves (if any) according to the multicast mode, and
- * promiscuous flags unconditionally.
+ * This function attaches the slave to the end of list.
+ *
+ * bond->lock held for writing by caller.
  */
-static void bond_mc_update(bonding_t *bond, slave_t *new, slave_t *old)
+static void bond_attach_slave(struct bonding *bond, struct slave *new_slave)
 {
-	struct dev_mc_list *dmi;
+	if (bond->first_slave == NULL) { /* attaching the first slave */
+		new_slave->next = new_slave;
+		new_slave->prev = new_slave;
+		bond->first_slave = new_slave;
+	} else {
+		new_slave->next = bond->first_slave;
+		new_slave->prev = bond->first_slave->prev;
+		new_slave->next->prev = new_slave;
+		new_slave->prev->next = new_slave;
+	}
 
-	if (USES_PRIMARY(bond_mode)) {
-		if (bond->device->flags & IFF_PROMISC) {
-			if (old)
-				dev_set_promiscuity(old->dev, -1);
-			if (new)
-				dev_set_promiscuity(new->dev, 1);
-		}
+	bond->slave_cnt++;
+}
+
+/*
+ * This function detaches the slave from the list.
+ * WARNING: no check is made to verify if the slave effectively
+ * belongs to <bond>.
+ * Nothing is freed on return, structures are just unchained.
+ * If any slave pointer in bond was pointing to <slave>,
+ * it should be changed by the calling function.
+ *
+ * bond->lock held for writing by caller.
+ */
+static void bond_detach_slave(struct bonding *bond, struct slave *slave)
+{
+	if (slave->next) {
+		slave->next->prev = slave->prev;
 	}
 
-	switch(multicast_mode) {
-	case BOND_MULTICAST_ACTIVE :		
-		if (bond->device->flags & IFF_ALLMULTI) {
-			if (old)
-				dev_set_allmulti(old->dev, -1);
-			if (new)
-				dev_set_allmulti(new->dev, 1);
-		}
-		/* first remove all mc addresses from old slave if any,
-		   and _then_ add them to new active slave */
-		if (old) {
-			for (dmi = bond->device->mc_list; dmi != NULL; dmi = dmi->next)
-				dev_mc_delete(old->dev, dmi->dmi_addr, dmi->dmi_addrlen, 0);
-		}
-		if (new) {
-			for (dmi = bond->device->mc_list; dmi != NULL; dmi = dmi->next)
-				dev_mc_add(new->dev, dmi->dmi_addr, dmi->dmi_addrlen, 0);
+	if (slave->prev) {
+		slave->prev->next = slave->next;
+	}
+
+	if (bond->first_slave == slave) { /* slave is the first slave */
+		if (bond->slave_cnt > 1) { /* there are more slave */
+			bond->first_slave = slave->next;
+		} else {
+			bond->first_slave = NULL; /* slave was the last one */
 		}
-		break;
-	case BOND_MULTICAST_ALL :
-		/* nothing to do: mc list is already up-to-date on all slaves */
-		break;
-	case BOND_MULTICAST_DISABLED :
-		break;
 	}
+
+	slave->next = NULL;
+	slave->prev = NULL;
+	bond->slave_cnt--;
+}
+
+/*---------------------------------- IOCTL ----------------------------------*/
+
+static int bond_sethwaddr(struct net_device *bond_dev, struct net_device *slave_dev)
+{
+	dprintk("bond_dev=%p\n", bond_dev);
+	dprintk("slave_dev=%p\n", slave_dev);
+	dprintk("slave_dev->addr_len=%d\n", slave_dev->addr_len);
+	memcpy(bond_dev->dev_addr, slave_dev->dev_addr, slave_dev->addr_len);
+	return 0;
 }
 
 /* enslave device <slave> to bond device <master> */
-static int bond_enslave(struct net_device *master_dev, 
-                        struct net_device *slave_dev)
+static int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
 {
-	bonding_t *bond = NULL;
-	slave_t *new_slave = NULL;
-	unsigned long rflags = 0;
-	int err = 0;
+	struct bonding *bond = bond_dev->priv;
+	struct slave *new_slave = NULL;
 	struct dev_mc_list *dmi;
-	struct in_ifaddr **ifap;
-	struct in_ifaddr *ifa;
-	int link_reporting;
 	struct sockaddr addr;
-
-	if (master_dev == NULL || slave_dev == NULL) {
-		return -ENODEV;
-	}
-	bond = (struct bonding *) master_dev->priv;
+	int link_reporting;
+	int old_features = bond_dev->features;
+	int res = 0;
 
 	if (slave_dev->do_ioctl == NULL) {
-		printk(KERN_DEBUG
-			"Warning : no link monitoring support for %s\n",
-			slave_dev->name);
+		printk(KERN_WARNING DRV_NAME
+		       ": Warning : no link monitoring support for %s\n",
+		       slave_dev->name);
 	}
 
-
 	/* bond must be initialized by bond_open() before enslaving */
-	if (!(master_dev->flags & IFF_UP)) {
-#ifdef BONDING_DEBUG
-		printk(KERN_CRIT "Error, master_dev is not up\n");
-#endif
+	if (!(bond_dev->flags & IFF_UP)) {
+		dprintk("Error, master_dev is not up\n");
 		return -EPERM;
 	}
 
 	/* already enslaved */
-	if (master_dev->flags & IFF_SLAVE || slave_dev->flags & IFF_SLAVE) {
-#ifdef BONDING_DEBUG
-		printk(KERN_CRIT "Error, Device was already enslaved\n");
-#endif
+	if (slave_dev->flags & IFF_SLAVE) {
+		dprintk("Error, Device was already enslaved\n");
 		return -EBUSY;
 	}
 
+	/* vlan challenged mutual exclusion */
+	/* no need to lock since we're protected by rtnl_lock */
+	if (slave_dev->features & NETIF_F_VLAN_CHALLENGED) {
+		dprintk("%s: NETIF_F_VLAN_CHALLENGED\n", slave_dev->name);
+		if (!list_empty(&bond->vlan_list)) {
+			printk(KERN_ERR DRV_NAME
+			       ": Error: cannot enslave VLAN "
+			       "challenged slave %s on VLAN enabled "
+			       "bond %s\n", slave_dev->name,
+			       bond_dev->name);
+			return -EPERM;
+		} else {
+			printk(KERN_WARNING DRV_NAME
+			       ": Warning: enslaved VLAN challenged "
+			       "slave %s. Adding VLANs will be blocked as "
+			       "long as %s is part of bond %s\n",
+			       slave_dev->name, slave_dev->name,
+			       bond_dev->name);
+			bond_dev->features |= NETIF_F_VLAN_CHALLENGED;
+		}
+	} else {
+		dprintk("%s: ! NETIF_F_VLAN_CHALLENGED\n", slave_dev->name);
+		if (bond->slave_cnt == 0) {
+			/* First slave, and it is not VLAN challenged,
+			 * so remove the block of adding VLANs over the bond.
+			 */
+			bond_dev->features &= ~NETIF_F_VLAN_CHALLENGED;
+		}
+	}
+
 	if (app_abi_ver >= 1) {
 		/* The application is using an ABI, which requires the
 		 * slave interface to be closed.
 		 */
 		if ((slave_dev->flags & IFF_UP)) {
-#ifdef BONDING_DEBUG
-			printk(KERN_CRIT "Error, slave_dev is up\n");
-#endif
-			return -EPERM;
+			printk(KERN_ERR DRV_NAME
+			       ": Error: %s is up\n",
+			       slave_dev->name);
+			res = -EPERM;
+			goto err_undo_flags;
 		}
 
 		if (slave_dev->set_mac_address == NULL) {
-			printk(KERN_CRIT
-			       "The slave device you specified does not support"
-			       " setting the MAC address.\n");
-			printk(KERN_CRIT
-			       "Your kernel likely does not support slave"
-			       " devices.\n");
+			printk(KERN_ERR DRV_NAME
+			       ": Error: The slave device you specified does "
+			       "not support setting the MAC address.\n");
+			printk(KERN_ERR
+			       "Your kernel likely does not support slave "
+			       "devices.\n");
 
-			return -EOPNOTSUPP;
+			res = -EOPNOTSUPP;
+			goto err_undo_flags;
 		}
 	} else {
 		/* The application is not using an ABI, which requires the
 		 * slave interface to be open.
 		 */
 		if (!(slave_dev->flags & IFF_UP)) {
-#ifdef BONDING_DEBUG
-			printk(KERN_CRIT "Error, slave_dev is not running\n");
-#endif
-			return -EINVAL;
+			printk(KERN_ERR DRV_NAME
+			       ": Error: %s is not running\n",
+			       slave_dev->name);
+			res = -EINVAL;
+			goto err_undo_flags;
 		}
 
-		if ((bond_mode == BOND_MODE_8023AD) ||
-		    (bond_mode == BOND_MODE_TLB) ||
-		    (bond_mode == BOND_MODE_ALB)) {
-			printk(KERN_ERR
-			       "bonding: Error: to use %s mode, you must "
-			       "upgrade ifenslave.\n", bond_mode_name());
-			return -EOPNOTSUPP;
+		if ((bond->params.mode == BOND_MODE_8023AD) ||
+		    (bond->params.mode == BOND_MODE_TLB)    ||
+		    (bond->params.mode == BOND_MODE_ALB)) {
+			printk(KERN_ERR DRV_NAME
+			       ": Error: to use %s mode, you must upgrade "
+			       "ifenslave.\n",
+			       bond_mode_name(bond->params.mode));
+			res = -EOPNOTSUPP;
+			goto err_undo_flags;
 		}
 	}
 
-	if ((new_slave = kmalloc(sizeof(slave_t), GFP_KERNEL)) == NULL) {
-		return -ENOMEM;
+	new_slave = kmalloc(sizeof(struct slave), GFP_KERNEL);
+	if (!new_slave) {
+		res = -ENOMEM;
+		goto err_undo_flags;
 	}
-	memset(new_slave, 0, sizeof(slave_t));
+
+	memset(new_slave, 0, sizeof(struct slave));
 
 	/* save slave's original flags before calling
 	 * netdev_set_master and dev_open
@@ -1431,37 +1706,29 @@ static int bond_enslave(struct net_devic
 		 */
 		memcpy(new_slave->perm_hwaddr, slave_dev->dev_addr, ETH_ALEN);
 
-		if (bond->slave_cnt > 0) {
-			/* set slave to master's mac address
-			 * The application already set the master's
-			 * mac address to that of the first slave
-			 */
-			memcpy(addr.sa_data, master_dev->dev_addr, master_dev->addr_len);
-			addr.sa_family = slave_dev->type;
-			err = slave_dev->set_mac_address(slave_dev, &addr);
-			if (err) {
-#ifdef BONDING_DEBUG
-				printk(KERN_CRIT "Error %d calling set_mac_address\n", err);
-#endif
-				goto err_free;
-			}
+		/* set slave to master's mac address
+		 * The application already set the master's
+		 * mac address to that of the first slave
+		 */
+		memcpy(addr.sa_data, bond_dev->dev_addr, bond_dev->addr_len);
+		addr.sa_family = slave_dev->type;
+		res = slave_dev->set_mac_address(slave_dev, &addr);
+		if (res) {
+			dprintk("Error %d calling set_mac_address\n", res);
+			goto err_free;
 		}
 
 		/* open the slave since the application closed it */
-		err = dev_open(slave_dev);
-		if (err) {
-#ifdef BONDING_DEBUG
-			printk(KERN_CRIT "Openning slave %s failed\n", slave_dev->name);
-#endif
+		res = dev_open(slave_dev);
+		if (res) {
+			dprintk("Openning slave %s failed\n", slave_dev->name);
 			goto err_restore_mac;
 		}
 	}
 
-	err = netdev_set_master(slave_dev, master_dev);
-	if (err) {
-#ifdef BONDING_DEBUG
-		printk(KERN_CRIT "Error %d calling netdev_set_master\n", err);
-#endif
+	res = netdev_set_master(slave_dev, bond_dev);
+	if (res) {
+		dprintk("Error %d calling netdev_set_master\n", res);
 		if (app_abi_ver < 1) {
 			goto err_free;
 		} else {
@@ -1471,56 +1738,59 @@ static int bond_enslave(struct net_devic
 
 	new_slave->dev = slave_dev;
 
-	if ((bond_mode == BOND_MODE_TLB) ||
-	    (bond_mode == BOND_MODE_ALB)) {
+	if ((bond->params.mode == BOND_MODE_TLB) ||
+	    (bond->params.mode == BOND_MODE_ALB)) {
 		/* bond_alb_init_slave() must be called before all other stages since
 		 * it might fail and we do not want to have to undo everything
 		 */
-		err = bond_alb_init_slave(bond, new_slave);
-		if (err) {
+		res = bond_alb_init_slave(bond, new_slave);
+		if (res) {
 			goto err_unset_master;
 		}
 	}
 
-	/* set promiscuity level to new slave */ 
-	if (master_dev->flags & IFF_PROMISC) {
-		/* If the mode USES_PRIMARY, then the new slave gets the
-		 * master's promisc (and mc) settings only if it becomes the
-		 * current_slave, and that is taken care of later when calling
-		 * bond_change_active()
-		 */
-		if (!USES_PRIMARY(bond_mode)) {
-			dev_set_promiscuity(slave_dev, 1); 
+	/* If the mode USES_PRIMARY, then the new slave gets the
+	 * master's promisc (and mc) settings only if it becomes the
+	 * curr_active_slave, and that is taken care of later when calling
+	 * bond_change_active()
+	 */
+	if (!USES_PRIMARY(bond->params.mode)) {
+		/* set promiscuity level to new slave */
+		if (bond_dev->flags & IFF_PROMISC) {
+			dev_set_promiscuity(slave_dev, 1);
 		}
-	}
- 
-	if (multicast_mode == BOND_MULTICAST_ALL) {
+
 		/* set allmulti level to new slave */
-		if (master_dev->flags & IFF_ALLMULTI) 
-			dev_set_allmulti(slave_dev, 1); 
-		
-		/* upload master's mc_list to new slave */ 
-		for (dmi = master_dev->mc_list; dmi != NULL; dmi = dmi->next) 
+		if (bond_dev->flags & IFF_ALLMULTI) {
+			dev_set_allmulti(slave_dev, 1);
+		}
+
+		/* upload master's mc_list to new slave */
+		for (dmi = bond_dev->mc_list; dmi; dmi = dmi->next) {
 			dev_mc_add (slave_dev, dmi->dmi_addr, dmi->dmi_addrlen, 0);
+		}
 	}
 
-	if (bond_mode == BOND_MODE_8023AD) {
+	if (bond->params.mode == BOND_MODE_8023AD) {
 		/* add lacpdu mc addr to mc list */
 		u8 lacpdu_multicast[ETH_ALEN] = MULTICAST_LACPDU_ADDR;
 
 		dev_mc_addc_delete(slave_dev, lacpdu_multicast, ETH_ALEN, icast, ET the active one
+ * @bond: our bode == BOND_MODE_8023AD) {
 		/* aler must hold curl_slave_lock for writing.
+ */
+static struct slave *bond_find_bsst_slave(struct bonding *bond)
 {
-	bonding_t *bond = master->priv;
-	struct dev_5c,ø€¼œ¥V) &&
+	    (!bond->params.		    ddrlen, 0);
+		}
+	}
+}
+
+/**
+ * find_best_interface - select the best available slave to be the active one
+ * @bond: our bonding struct
+ *
+ * Warning: Caller must hold curr_slave_lock for writing.
+ */
+static struct slave *bond_find_best_slave(struct bonding *bond)
_addr, ETH_ALEN);
 
-		if (bond->el; 
-		kfree(dmi); 
-		fhe '-f' option to force the "
+				"opers one
+ * @bond: our bondinc struct slaev_set_allmulti(new_active->dev, 1);
+		}
+
ond_mc;
+	int res-ev)     && \
 		     ((slave)->active-->curr_active_slave) {
+			dev_set_promiscuity(bond->curr_active       slave->dev	case BOND_MULTICAST_DISABLED :
-		return "disabrip the hwac ddrle = old_actnslow/fast)t
+ *
+nt_slave) {
-			dev_set_promiscuity(bonc->crtt,struct slave  /
-		rety(bonc->			break;
-		d= 0;
-	sa_family_atures & NETIF_F_VLAN_CHALLENGED)ntk(KERN_	bond_unregisterLLENlave  /
-		rety(bonc->			bre
+			p>expp  "challenged slave %s on VLAN b_ND_IS_OK(bond)			   hwac ddrle = old_actnslow/fast)t
+ *
+nt_slave) {
-			dev_set_promiscuity(bonc->crtt,struct slave  /
-		rety(bonc->			break;
-		d= 0;
-	sa_family_atures & NETIF_F_VLAN_CHctive_sl_addr, ETH_ALEN);
 
-		if (bond->(bonc->		TION;
@@ -2) {
+			printk(KERN_ERitoring support for ETH_P_IPX:
 		if (s***************/
#endif
-				goto err_free;
-			}
+		/* se_new_actde) {
-	case BOND_MUprintk(Kuct slave));
 
 	/* save slave's originaltERitoring support for ETH_Ie) {
-	case BOND_MUw_actde) {
-	caonitoring support for nl_lock+		    .sa_data, 0, sizeof(ifr.ifr_addr.sa_data))
+
+/**
+lan_rx_register) {
+		lave));
 
 	/* save slave'		    .sa_data, 0, siady acquired */
-		if (bond->current_slave != NUct bonding *bond = bond_dev->priv;
+	sANs over the bond.
+			 */
+			bond_dev->feat			 arp_tar else {
+		d_