## Automatically generated incremental diff
## From:   linux-2.4.20-pre8
## To:     linux-2.4.20-pre9
## Robot:  $Id: make-incremental-diff,v 1.11 2002/02/20 02:59:33 hpa Exp $

diff -urN linux-2.4.20-pre8/Documentation/Configure.help linux-2.4.20-pre9/Documentation/Configure.help
--- linux-2.4.20-pre8/Documentation/Configure.help	Thu Oct  3 18:36:22 2002
+++ linux-2.4.20-pre9/Documentation/Configure.help	Thu Oct  3 18:36:55 2002
@@ -240,10 +240,12 @@
   which processor you have compiled for. 
   
   NOTE: If your system hangs when init should run, you are probably
-  using a i686 compiled glibc which reads the TSC wihout checking for 
-  avaliability. Boot without "notsc" and install a i386 compiled glibc 
+  using a i686 compiled glibc which reads the TSC without checking for 
+  availability. Boot without "notsc" and install a i386 compiled glibc 
   to solve the problem.
- 
+
+  If unsure, say N.
+
 Multiquad support for NUMA systems
 CONFIG_MULTIQUAD
   This option is used for getting Linux to run on a (IBM/Sequent) NUMA 
@@ -10903,6 +10905,81 @@
   say M here and read <file:Documentation/modules.txt>.  This is
   recommended.  The module will be called dl2k.o.
 
+EtherExpress Pro/100 support (e100, Alternate Intel driver)
+CONFIG_E100
+  This driver supports Intel(R) PRO/100 family of adapters, which
+  includes:
+
+     Controller  Adapter Name                       Board IDs
+     ----------  ------------                       ---------
+
+     82558       PRO/100+ PCI Adapter               668081-xxx,
+                                                    689661-xxx
+     82558       PRO/100+ Management Adapter        691334-xxx,
+                                                    701738-xxx,
+                                                    721383-xxx
+     82558       PRO/100+ Dual Port Server Adapter  714303-xxx,
+                                                    711269-xxx,
+                                                    A28276-xxx
+     82558       PRO/100+ PCI Server Adapter        710550-xxx
+     82550       PRO/100 S Server Adapter           752438-xxx
+     82559                                          A56831-xxx,
+                                                    A10563-xxx,
+                                                    A12171-xxx,
+                                                    A12321-xxx,
+                                                    A12320-xxx,
+                                                    A12170-xxx
+                                                    748568-xxx
+                                                    748565-xxx
+     82550       PRO/100 S Desktop Adapter          751767-xxx
+     82559                                          748592-xxx,
+                                                    A12167-xxx,
+                                                    A12318-xxx,
+                                                    A12317-xxx,
+                                                    A12165-xxx,
+                                                    748569-xxx
+     82559       PRO/100+ Server Adapter            729757-xxx
+     82559       PRO/100 S Management Adapter       748566-xxx,
+                                                    748564-xxx
+     82550       PRO/100 S Dual Port Server Adapter A56831-xxx
+     82551       PRO/100 M Desktop Adapter          A80897-xxx
+                 PRO/100 S Advanced Management Adapter
+                                                    747842-xxx,
+                                                    745171-xxx
+     CNR         PRO/100 VE Desktop Adapter         A10386-xxx,
+                                                    A10725-xxx,
+                                                    A23801-xxx,
+                                                    A19716-xxx
+                 PRO/100 VM Desktop Adapter         A14323-xxx,
+                                                    A19725-xxx,
+                                                    A23801-xxx,
+                                                    A22220-xxx,
+                                                    A23796-xxx
+
+
+  To verify that your adapter is supported, find the board ID number
+  on the adapter. Look for a label that has a barcode and a number
+  in the format 123456-001 (six digits hyphen three digits). Match
+  this to the list of numbers above.
+
+  For more information on how to identify your adapter, go to the
+  Adapter & Driver ID Guide at:
+
+    http://support.intel.com/support/network/adapter/pro100/21397.htm
+
+  For the latest Intel PRO/100 network driver for Linux, see:
+
+    http://appsr.intel.com/scripts-df/support_intel.asp
+
+  More specific information on configuring the driver is in
+  <file:Documentation/networking/e100.txt>.
+
+  This driver is also available as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want).
+  The module will be called e100.o.  If you want to compile it as a
+  module, say M here and read <file:Documentation/modules.txt> as well
+  as <file:Documentation/networking/net-modules.txt>.
+
 Intel(R) PRO/1000 Gigabit Ethernet support
 CONFIG_E1000
   This driver supports Intel(R) PRO/1000 gigabit ethernet family of
@@ -15737,12 +15814,6 @@
   were partitioned using EFI GPT.  Presently only useful on the
   IA-64 platform.
 
-/dev/guid support (EXPERIMENTAL)
-CONFIG_DEVFS_GUID
-  Say Y here if you would like to access disks and partitions by
-  their Globally Unique Identifiers (GUIDs) which will appear as
-  symbolic links in /dev/guid.
-
 Ultrix partition table support
 CONFIG_ULTRIX_PARTITION
   Say Y here if you would like to be able to read the hard disk
@@ -25053,15 +25124,19 @@
   As of the time of this writing, most hardware is DIG compliant,
   so the "DIG-compliant" option is usually the right choice.
 
-  HP-simulator   For the HP simulator
-                 (<http://software.hp.com/ia64linux/>).
+  HP-simulator   For the HP simulator (<http://software.hp.com/ia64linux/>).
+  HP-zx1	 For HP zx1 Platforms.
   SN1            For SGI SN1 Platforms.
   SN2            For SGI SN2 Platforms.
-  DIG-compliant  For DIG ("Developer's Interface Guide") compliant
-                 system.
+  DIG-compliant  For DIG ("Developer's Interface Guide") compliant systems.
 
   If you don't know what to do, choose "generic".
 
+CONFIG_IA64_HP_ZX1
+  Build a kernel that runs on HP zx1-based systems.  This adds support
+  for the zx1 IOMMU and makes root bus bridges appear in PCI config space
+  (required for zx1 agpgart support).
+
 CONFIG_IA64_SGI_SN_SIM
   Build a kernel that runs on both the SGI simulator AND on hardware.
   There is a very slight performance penalty on hardware for including this
@@ -25109,16 +25184,6 @@
   can select this option to disable the VHPT for debugging.  If you're
   unsure, answer N.
 
-Enable McKinley A-step specific code
-CONFIG_MCKINLEY_ASTEP_SPECIFIC
-  Select this option to build a kernel for an IA64 McKinley system
-  with any A-stepping CPU.
-
-Enable McKinley A0/A1-step specific code
-CONFIG_MCKINLEY_A0_SPECIFIC
-  Select this option to build a kernel for an IA64 McKinley system
-  with an A0 or A1 stepping CPU.
-
 Turn on compare-and-exchange bug checking (slow!)
 CONFIG_IA64_DEBUG_CMPXCHG
   Selecting this option turns on bug checking for the IA64
@@ -25143,9 +25208,7 @@
 CONFIG_IA64_PRINT_HAZARDS
   Selecting this option prints more information for Illegal Dependency
   Faults, that is, for Read after Write, Write after Write or Write
-  after Read violations.  This option is ignored if you are compiling
-  for an Itanium A step processor (CONFIG_ITANIUM_ASTEP_SPECIFIC).  If
-  you're unsure, select Y.
+  after Read violations.  If you're unsure, select Y.
 
 Performance monitor support
 CONFIG_PERFMON
diff -urN linux-2.4.20-pre8/Documentation/networking/tuntap.txt linux-2.4.20-pre9/Documentation/networking/tuntap.txt
--- linux-2.4.20-pre8/Documentation/networking/tuntap.txt	Wed Apr 25 14:59:56 2001
+++ linux-2.4.20-pre9/Documentation/networking/tuntap.txt	Thu Oct  3 18:36:55 2002
@@ -7,43 +7,71 @@
   FreeBSD TAP driver 
   Copyright (c) 1999-2000 Maksim Yevmenkin <m_evmenkin@yahoo.com>
 
+  Revision of this document 2002 by Florian Thiel <florian.thiel@gmx.net>
+
 1. Description
   TUN/TAP provides packet reception and transmission for user space programs. 
-  It can be viewed as a simple Point-to-Point or Ethernet device, which 
-  instead of receiving packets from a physical media, receives them from 
+  It can be seen as a simple Point-to-Point or Ethernet device, which,
+  instead of receiving packets from physical media, receives them from 
   user space program and instead of sending packets via physical media 
   writes them to the user space program. 
 
-  When a program opens /dev/net/tun, driver creates and registers corresponding
-  net device tunX or tapX. After a program closed above devices, driver will 
-  automatically delete tunXX or tapXX device and all routes corresponding to it.
-
-  This package(http://vtun.sourceforge.net/tun) contains two simple example 
-  programs how to use tun and tap devices. Both programs works like 
-  bridge between two network interfaces.
+  In order to use the driver a program has to open /dev/net/tun and issue a
+  corresponding ioctl() to register a network device with the kernel. A network
+  device will appear as tunXX or tapXX, depending on the options chosen. When
+  the program closes the file descriptor, the network device and all
+  corresponding routes will disappear.
+
+  Depending on the type of device chosen the userspace program has to read/write
+  IP packets (with tun) or ethernet frames (with tap). Which one is being used
+  depends on the flags given with the ioctl().
+
+  The package from http://vtun.sourceforge.net/tun contains two simple examples
+  for how to use tun and tap devices. Both programs work like a bridge between
+  two network interfaces.
   br_select.c - bridge based on select system call.
   br_sigio.c  - bridge based on async io and SIGIO signal.
-  However the best example is VTun http://vtun.sourceforge.net :))  
+  However, the best example is VTun http://vtun.sourceforge.net :))
 
 2. Configuration 
   Create device node:
+     mkdir /dev/net (if it doesn't exist already)
      mknod /dev/net/tun c 10 200
+  
+  Set permissions:
+     e.g. chmod 0700 /dev/net/tun
+     if you want the device only accesible by root. Giving regular users the
+     right to assign network devices is NOT a good idea. Users could assign
+     bogus network interfaces to trick firewalls or administrators.
 
   Driver module autoloading
      Make sure that "Kernel module loader" - module auto-loading support is enabled 
      in your kernel. 
 
-     Add following line to the /etc/modules.conf:
+     Add the following line to the /etc/modules.conf:
 	alias char-major-10-200 tun
-     
-     Run:
+     and run
         depmod -a 
-
-     Driver will be automatically loaded when application access /dev/net/tun.
+  
+  Manual loading 
+     insert the module by hand:
+        modprobe tun
+
+  If you do it the latter way, you have to load the module every time you
+  need it, if you do it the other way it will be automatically loaded when
+  /dev/net/tun is being opened.
 
 3. Program interface 
   3.1 Network device allocation:
 
+  char *dev should be the name of the device with a format string (e.g.
+  "tun%d"), but (as far as I can see) this can be any valid network device name.
+  Note that the character pointer becomes overwritten with the real device name
+  (e.g. "tun0")
+
+  #include <linux/if.h>
+  #include <linux/if_tun.h>
+
   int tun_alloc(char *dev)
   {
       struct ifreq ifr;
@@ -79,65 +107,44 @@
 
 Universal TUN/TAP device driver Frequently Asked Question.
    
-1. What is the TUN ?
-The TUN is Virtual Point-to-Point network device.
-TUN driver was designed as low level kernel support for
-IP tunneling. It provides to userland application
-two interfaces:
-  - /dev/tunX	- character device;
-  - tunX	- virtual Point-to-Point interface.
-
-Userland application can write IP frame to /dev/tunX
-and kernel will receive this frame from tunX interface. 
-In the same time every frame that kernel writes to tunX 
-interface can be read by userland application from /dev/tunX
-device.
-
-2. What is the TAP ?
-The TAP is a Virtual Ethernet network device.
-TAP driver was designed as low level kernel support for
-Ethernet tunneling. It provides to userland application
-two interfaces:
-  - /dev/tapX	- character device;
-  - tapX	- virtual Ethernet interface.
-
-Userland application can write Ethernet frame to /dev/tapX
-and kernel will receive this frame from tapX interface. 
-In the same time every frame that kernel writes to tapX 
-interface can be read by userland application from /dev/tapX
-device.
-
-3. What platforms are supported by TUN/TAP driver ?
+1. What platforms are supported by TUN/TAP driver ?
 Currently driver has been written for 3 Unices:
    Linux kernels 2.2.x, 2.4.x 
    FreeBSD 3.x, 4.x, 5.x
    Solaris 2.6, 7.0, 8.0
 
-4. What is TUN/TAP driver used for?
+2. What is TUN/TAP driver used for?
 As mentioned above, main purpose of TUN/TAP driver is tunneling. 
 It is used by VTun (http://vtun.sourceforge.net).
 
-5. How does Virtual network device actually work ? 
+Another interesting application using TUN/TAP is pipsecd
+(http://perso.enst.fr/~beyssac/pipsec/), an userspace IPSec
+implementation that can use complete kernel routing (unlike FreeS/WAN).
+
+3. How does Virtual network device actually work ? 
 Virtual network device can be viewed as a simple Point-to-Point or
 Ethernet device, which instead of receiving packets from a physical 
 media, receives them from user space program and instead of sending 
 packets via physical media sends them to the user space program. 
 
 Let's say that you configured IPX on the tap0, then whenever 
-kernel sends any IPX packet to tap0, it is passed to the application
-(VTun for example). Application encrypts, compresses and sends it to 
-the other side over TCP or UDP. Application on other side decompress 
-and decrypts them and write packet to the TAP device, kernel handles 
-the packet like it came from real physical device.
+the kernel sends an IPX packet to tap0, it is passed to the application
+(VTun for example). The application encrypts, compresses and sends it to 
+the other side over TCP or UDP. The application on the other side decompresses
+and decrypts the data received and writes the packet to the TAP device, 
+the kernel handles the packet like it came from real physical device.
 
-6. What is the difference between TUN driver and TAP driver?
+4. What is the difference between TUN driver and TAP driver?
 TUN works with IP frames. TAP works with Ethernet frames.
 
-7. What is the difference between BPF and TUN/TAP driver?
-BFP is a advanced packet filter. It can be attached to existing
-network interface. It does not provide virtual network interface.
-TUN/TAP driver does provide virtual network interface and it is possible
+This means that you have to read/write IP packets when you are using tun and
+ethernet frames when using tap.
+
+5. What is the difference between BPF and TUN/TAP driver?
+BFP is an advanced packet filter. It can be attached to existing
+network interface. It does not provide a virtual network interface.
+A TUN/TAP driver does provide a virtual network interface and it is possible
 to attach BPF to this interface.
 
-8. Does TAP driver support kernel Ethernet bridging?
+6. Does TAP driver support kernel Ethernet bridging?
 Yes. Linux and FreeBSD drivers support Ethernet bridging. 
diff -urN linux-2.4.20-pre8/Makefile linux-2.4.20-pre9/Makefile
--- linux-2.4.20-pre8/Makefile	Thu Oct  3 18:36:23 2002
+++ linux-2.4.20-pre9/Makefile	Thu Oct  3 18:36:56 2002
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 4
 SUBLEVEL = 20
-EXTRAVERSION = -pre8
+EXTRAVERSION = -pre9
 
 KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
 
diff -urN linux-2.4.20-pre8/arch/alpha/lib/stxncpy.S linux-2.4.20-pre9/arch/alpha/lib/stxncpy.S
--- linux-2.4.20-pre8/arch/alpha/lib/stxncpy.S	Mon Dec 11 13:46:26 2000
+++ linux-2.4.20-pre9/arch/alpha/lib/stxncpy.S	Thu Oct  3 18:36:56 2002
@@ -164,26 +164,29 @@
 	or	t0, t6, t6	# e1    : mask original data for zero test
 	cmpbge	zero, t6, t8	# e0    :
 	beq	a2, $u_eocfin	# .. e1 :
-	bne	t8, $u_final	# e1    :
+	lda	t6, -1		# e0    :
+	bne	t8, $u_final	# .. e1 :
 
-	lda	t6, -1			# e1    : mask out the bits we have
-	mskql	t6, a1, t6		# e0    :   already seen
-	stq_u	t0, 0(a0)		# e0    : store first output word
-	or      t6, t2, t2		# .. e1 :
-	cmpbge	zero, t2, t8		# e0    : find nulls in second partial
-	addq	a0, 8, a0		# .. e1 :
-	subq	a2, 1, a2		# e0    :
+	mskql	t6, a1, t6	# e0    : mask out bits already seen
+	nop			# .. e1 :
+	stq_u	t0, 0(a0)	# e0    : store first output word
+	or      t6, t2, t2	# .. e1 :
+	cmpbge	zero, t2, t8	# e0    : find nulls in second partial
+	addq	a0, 8, a0	# .. e1 :
+	subq	a2, 1, a2	# e0    :
 	bne	t8, $u_late_head_exit	# .. e1 :
 
 	/* Finally, we've got all the stupid leading edge cases taken care
 	   of and we can set up to enter the main loop.  */
 
 	extql	t2, a1, t1	# e0    : position hi-bits of lo word
-	ldq_u	t2, 8(a1)	# .. e1 : read next high-order source word
-	addq	a1, 8, a1	# e0    :
-	cmpbge	zero, t2, t8	# e1 (stall)
-	beq	a2, $u_eoc	# e1    :
-	bne	t8, $u_eos	# e1    :
+	beq	a2, $u_eoc	# .. e1 :
+	ldq_u	t2, 8(a1)	# e0    : read next high-order source word
+	addq	a1, 8, a1	# .. e1 :
+	extqh	t2, a1, t0	# e0    : position lo-bits of hi word (stall)
+	cmpbge	zero, t2, t8	# .. e1 :
+	nop			# e0    :
+	bne	t8, $u_eos	# .. e1 :
 
 	/* Unaligned copy main loop.  In order to avoid reading too much,
 	   the loop is structured to detect zeros in aligned source words.
@@ -193,6 +196,7 @@
 	   to run as fast as possible.
 
 	   On entry to this basic block:
+	   t0 == the shifted low-order bits from the current source word
 	   t1 == the shifted high-order bits from the previous source word
 	   t2 == the unshifted current source word
 
@@ -200,18 +204,18 @@
 
 	.align 3
 $u_loop:
-	extqh	t2, a1, t0	# e0    : extract high bits for current word
-	addq	a1, 8, a1	# .. e1 :
-	extql	t2, a1, t3	# e0    : extract low bits for next time
-	addq	a0, 8, a0	# .. e1 :
 	or	t0, t1, t0	# e0    : current dst word now complete
-	ldq_u	t2, 0(a1)	# .. e1 : load high word for next time
-	stq_u	t0, -8(a0)	# e0    : save the current word
-	mov	t3, t1		# .. e1 :
-	subq	a2, 1, a2	# e0    :
-	cmpbge	zero, t2, t8	# .. e1 : test new word for eos
-	beq	a2, $u_eoc	# e1    :
-	beq	t8, $u_loop	# e1    :
+	subq	a2, 1, a2	# .. e1 : decrement word count
+	stq_u	t0, 0(a0)	# e0    : save the current word
+	addq	a0, 8, a0	# .. e1 :
+	extql	t2, a1, t1	# e0    : extract high bits for next time
+	beq	a2, $u_eoc	# .. e1 :
+	ldq_u	t2, 0(a1)	# e0    : load high word for next time
+	addq	a1, 8, a1	# .. e1 :
+	nop			# e0    :
+	cmpbge	zero, t2, t8	# e1    : test new word for eos (stall)
+	extqh	t2, a1, t0	# e0    : extract low bits for current word
+	beq	t8, $u_loop	# .. e1 :
 
 	/* We've found a zero somewhere in the source word we just read.
 	   If it resides in the lower half, we have one (probably partial)
@@ -219,12 +223,12 @@
 	   have one full and one partial word left to write out.
 
 	   On entry to this basic block:
+	   t0 == the shifted low-order bits from the current source word
 	   t1 == the shifted high-order bits from the previous source word
 	   t2 == the unshifted current source word.  */
 $u_eos:
-	extqh	t2, a1, t0	# e0    :
-	or	t0, t1, t0	# e1    : first (partial) source word complete
-
+	or	t0, t1, t0	# e0    : first (partial) source word complete
+	nop			# .. e1 :
 	cmpbge	zero, t0, t8	# e0    : is the null in this first bit?
 	bne	t8, $u_final	# .. e1 (zdb)
 
@@ -260,10 +264,22 @@
 1:	stq_u	t0, 0(a0)	# e0    :
 	ret	(t9)		# .. e1 :
 
-$u_eoc:				# end-of-count
-	extqh	t2, a1, t0
-	or	t0, t1, t0
-	cmpbge	zero, t0, t8
+	/* Got to end-of-count before end of string.  
+	   On entry to this basic block:
+	   t1 == the shifted high-order bits from the previous source word  */
+$u_eoc:
+	and	a1, 7, t6	# e1    :
+	sll	t12, t6, t6	# e0    :
+	and	t6, 0xff, t6	# e0    :
+	bne	t6, 1f		# .. e1 :
+
+	ldq_u	t2, 8(a1)	# e0    : load final src word
+	nop			# .. e1 :
+	extqh	t2, a1, t0	# e0    : extract low bits for last word
+	or	t1, t0, t1	# e1    :
+
+1:	cmpbge	zero, t1, t7
+	mov	t1, t0
 
 $u_eocfin:			# end-of-count, final word
 	or	t10, t8, t8
diff -urN linux-2.4.20-pre8/arch/i386/defconfig linux-2.4.20-pre9/arch/i386/defconfig
--- linux-2.4.20-pre8/arch/i386/defconfig	Fri Aug  2 17:39:42 2002
+++ linux-2.4.20-pre9/arch/i386/defconfig	Thu Oct  3 18:36:56 2002
@@ -617,7 +617,8 @@
 CONFIG_DRM_TDFX=y
 # CONFIG_DRM_R128 is not set
 CONFIG_DRM_RADEON=y
-# CONFIG_DRM_I810 is not set
+CONFIG_DRM_I810=y
+CONFIG_DRM_I810_XFREE_41=y
 # CONFIG_DRM_MGA is not set
 # CONFIG_DRM_SIS is not set
 
diff -urN linux-2.4.20-pre8/arch/i386/kernel/setup.c linux-2.4.20-pre9/arch/i386/kernel/setup.c
--- linux-2.4.20-pre8/arch/i386/kernel/setup.c	Thu Oct  3 18:36:25 2002
+++ linux-2.4.20-pre9/arch/i386/kernel/setup.c	Thu Oct  3 18:36:57 2002
@@ -167,9 +167,8 @@
 static int have_cpuid_p(void) __init;
 
 static int disable_x86_serial_nr __initdata = 1;
-static int disable_x86_fxsr __initdata = 0;
 static int disable_x86_ht __initdata = 0;
-
+static u32 disabled_x86_caps[NCAPINTS] __initdata = { 0 };
 extern int blk_nohighio;
 
 int enable_acpi_smp_table;
@@ -758,6 +757,7 @@
 			if (!memcmp(from+4, "nopentium", 9)) {
 				from += 9+4;
 				clear_bit(X86_FEATURE_PSE, &boot_cpu_data.x86_capability);
+				set_bit(X86_FEATURE_PSE, &disabled_x86_caps);
 			} else if (!memcmp(from+4, "exactmap", 8)) {
 				from += 8+4;
 				e820.nr_map = 0;
@@ -783,8 +783,10 @@
 		}
 
 		/* "noht" disables HyperThreading (2 logical cpus per Xeon) */
-		else if (!memcmp(from, "noht", 4))
+		else if (!memcmp(from, "noht", 4)) { 
 			disable_x86_ht = 1;
+			set_bit(X86_FEATURE_HT, disabled_x86_caps);
+		}
 
 		/* "acpismp=force" forces parsing and use of the ACPI SMP table */
 		else if (!memcmp(from, "acpismp=force", 13))
@@ -1129,6 +1131,7 @@
 	 */
 	if (disable_x86_ht) {
 		clear_bit(X86_FEATURE_HT, &boot_cpu_data.x86_capability[0]);
+		set_bit(X86_FEATURE_HT, disabled_x86_caps);
 		enable_acpi_smp_table = 0;
 	}
 	if (test_bit(X86_FEATURE_HT, &boot_cpu_data.x86_capability[0]))
@@ -2530,7 +2533,8 @@
 
 static int __init x86_fxsr_setup(char * s)
 {
-	disable_x86_fxsr = 1;
+	set_bit(X86_FEATURE_XMM, disabled_x86_caps); 
+	set_bit(X86_FEATURE_FXSR, disabled_x86_caps);
 	return 1;
 }
 __setup("nofxsr", x86_fxsr_setup);
@@ -2706,12 +2710,6 @@
 		}
 	}
 
-	printk(KERN_DEBUG "CPU: Before vendor init, caps: %08x %08x %08x, vendor = %d\n",
-	       c->x86_capability[0],
-	       c->x86_capability[1],
-	       c->x86_capability[2],
-	       c->x86_vendor);
-
 	/*
 	 * Vendor-specific initialization.  In this section we
 	 * canonicalize the feature flags, meaning if there are
@@ -2770,12 +2768,6 @@
 		break;
 	}
 
-	printk(KERN_DEBUG "CPU: After vendor init, caps: %08x %08x %08x %08x\n",
-	       c->x86_capability[0],
-	       c->x86_capability[1],
-	       c->x86_capability[2],
-	       c->x86_capability[3]);
-
 	/*
 	 * The vendor-specific functions might have changed features.  Now
 	 * we do "generic changes."
@@ -2787,14 +2779,9 @@
 		clear_bit(X86_FEATURE_TSC, &c->x86_capability);
 #endif
 
-	/* HT disabled? */
-	if (disable_x86_ht)
-		clear_bit(X86_FEATURE_HT, &c->x86_capability);
-
-	/* FXSR disabled? */
-	if (disable_x86_fxsr) {
-		clear_bit(X86_FEATURE_FXSR, &c->x86_capability);
-		clear_bit(X86_FEATURE_XMM, &c->x86_capability);
+	/* check for caps that have been disabled earlier */ 
+	for (i = 0; i < NCAPINTS; i++) { 
+	     c->x86_capability[i] &= ~disabled_x86_caps[i];
 	}
 
 	/* Disable the PN if appropriate */
diff -urN linux-2.4.20-pre8/arch/i386/mm/pageattr.c linux-2.4.20-pre9/arch/i386/mm/pageattr.c
--- linux-2.4.20-pre8/arch/i386/mm/pageattr.c	Thu Oct  3 18:36:25 2002
+++ linux-2.4.20-pre9/arch/i386/mm/pageattr.c	Thu Oct  3 18:36:57 2002
@@ -12,7 +12,6 @@
 #include <asm/processor.h>
 
 /* Should move most of this stuff into the appropiate includes */
-#define PAGE_LARGE (_PAGE_PSE|_PAGE_PRESENT) 
 #define LARGE_PAGE_MASK (~(LARGE_PAGE_SIZE-1))
 #define LARGE_PAGE_SIZE (1UL << PMD_SHIFT)
 
@@ -21,13 +20,16 @@
 	pmd_t *pmd;	
 	pgd_t *pgd = pgd_offset(&init_mm, address); 
 
-	if ((pgd_val(*pgd) & PAGE_LARGE) == PAGE_LARGE)
+	if (pgd_none(*pgd))
+		return NULL; 
+	if (pgd_val(*pgd) & _PAGE_PSE)
 		return (pte_t *)pgd; 
 	pmd = pmd_offset(pgd, address); 	       
-	if ((pmd_val(*pmd) & PAGE_LARGE) == PAGE_LARGE)
+	if (pmd_none(*pmd))
+		return NULL; 
+	if (pmd_val(*pmd) & _PAGE_PSE) 
 		return (pte_t *)pmd; 
-
-        return pte_offset(pmd, address);
+    return pte_offset(pmd, address);
 } 
 
 static struct page *split_large_page(unsigned long address, pgprot_t prot)
@@ -50,7 +52,7 @@
 
 static void flush_kernel_map(void * address) 
 { 
-	if (!test_bit(X86_FEATURE_SELFSNOOP, &boot_cpu_data.x86_capability)) {
+	if (!test_bit(X86_FEATURE_SELFSNOOP, boot_cpu_data.x86_capability)) {
 		/* Could use CLFLUSH here if the CPU supports it (Hammer,P4) */
 		if (boot_cpu_data.x86_model >= 4) 
 			asm volatile("wbinvd":::"memory"); 	
@@ -113,11 +115,12 @@
 		BUG(); 
 #endif
 	address = (unsigned long)page_address(page);
-
 	kpte = lookup_address(address);
+	if (!kpte) 
+		return -EINVAL; 
 	kpte_page = virt_to_page(((unsigned long)kpte) & PAGE_MASK);
 	if (pgprot_val(prot) != pgprot_val(PAGE_KERNEL)) { 
-		if ((pte_val(*kpte) & _PAGE_PSE) == 0) { 
+		if ((pte_val(*kpte) & _PAGE_PSE) == 0) {
 			pte_t old = *kpte;
 			pte_t standard = mk_pte(page, PAGE_KERNEL); 
 
@@ -128,6 +131,7 @@
 			struct page *split = split_large_page(address, prot); 
 			if (!split)
 				return -ENOMEM;
+			atomic_inc(&kpte_page->count); 	
 			set_pmd_pte(kpte,address,mk_pte(split, PAGE_KERNEL));
 		}	
 	} else if ((pte_val(*kpte) & _PAGE_PSE) == 0) { 
@@ -135,8 +139,7 @@
 		atomic_dec(&kpte_page->count); 
 	}
 
-	if (test_bit(X86_FEATURE_PSE, &boot_cpu_data.x86_capability) && 
-	    (atomic_read(&kpte_page->count) == 1)) { 
+	if (cpu_has_pse && (atomic_read(&kpte_page->count) == 1)) { 
 		*oldpage = kpte_page;
 		revert_page(kpte_page, address);
 	} 
diff -urN linux-2.4.20-pre8/arch/sparc64/kernel/ioctl32.c linux-2.4.20-pre9/arch/sparc64/kernel/ioctl32.c
--- linux-2.4.20-pre8/arch/sparc64/kernel/ioctl32.c	Thu Oct  3 18:36:36 2002
+++ linux-2.4.20-pre9/arch/sparc64/kernel/ioctl32.c	Thu Oct  3 18:37:13 2002
@@ -46,6 +46,7 @@
 #include <linux/netdevice.h>
 #include <linux/raw.h>
 #include <linux/smb_fs.h>
+#include <linux/ncp_fs.h>
 #include <linux/blkpg.h>
 #include <linux/blk.h>
 #include <linux/elevator.h>
@@ -2225,6 +2226,307 @@
 	return err;
 }
 
+struct ncp_ioctl_request_32 {
+	unsigned int function;
+	unsigned int size;
+	__kernel_caddr_t32 data;
+};
+
+struct ncp_fs_info_v2_32 {
+	int version;
+	unsigned int mounted_uid;
+	unsigned int connection;
+	unsigned int buffer_size;
+
+	unsigned int volume_number;
+	__u32 directory_id;
+
+	__u32 dummy1;
+	__u32 dummy2;
+	__u32 dummy3;
+};
+
+struct ncp_objectname_ioctl_32
+{
+	int		auth_type;
+	unsigned int	object_name_len;
+	__kernel_caddr_t32	object_name;	/* an userspace data, in most cases user name */
+};
+
+struct ncp_privatedata_ioctl_32
+{
+	unsigned int	len;
+	__kernel_caddr_t32	data;		/* ~1000 for NDS */
+};
+
+#define	NCP_IOC_NCPREQUEST_32		_IOR('n', 1, struct ncp_ioctl_request_32)
+
+#define NCP_IOC_GETMOUNTUID2_32		_IOW('n', 2, unsigned int)
+
+#define NCP_IOC_GET_FS_INFO_V2_32	_IOWR('n', 4, struct ncp_fs_info_v2_32)
+
+#define NCP_IOC_GETOBJECTNAME_32	_IOWR('n', 9, struct ncp_objectname_ioctl_32)
+#define NCP_IOC_SETOBJECTNAME_32	_IOR('n', 9, struct ncp_objectname_ioctl_32)
+#define NCP_IOC_GETPRIVATEDATA_32	_IOWR('n', 10, struct ncp_privatedata_ioctl_32)
+#define NCP_IOC_SETPRIVATEDATA_32	_IOR('n', 10, struct ncp_privatedata_ioctl_32)
+
+static int do_ncp_ncprequest(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+	struct ncp_ioctl_request_32 n32;
+	struct ncp_ioctl_request n;
+	mm_segment_t old_fs;
+	int err;
+
+	if (copy_from_user(&n32, (struct ncp_ioctl_request_32*)arg,
+	    sizeof(n32)))
+		return -EFAULT;
+
+	n.function = n32.function;
+	n.size = n32.size;
+	if (n.size > 65536)
+		return -EINVAL;
+	n.data = vmalloc(65536);	/* 65536 must be same as NCP_PACKET_SIZE_INTERNAL in ncpfs */
+	if (!n.data)
+		return -ENOMEM;
+	err = -EFAULT;
+	if (copy_from_user(n.data, A(n32.data), n.size))
+		goto out;
+
+	old_fs = get_fs(); set_fs (KERNEL_DS);
+	err = sys_ioctl (fd, NCP_IOC_NCPREQUEST, (unsigned long)&n);
+	set_fs (old_fs);
+        if(err <= 0)
+		goto out;
+	if (err > 65536) {
+		err = -EINVAL;
+		goto out;
+	}
+	if (copy_to_user(A(n32.data), n.data, err)) {
+		err = -EFAULT;
+		goto out;
+	}
+ out:
+	vfree(n.data);
+	return err;
+}
+
+static int do_ncp_getmountuid2(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+	mm_segment_t old_fs = get_fs();
+	__kernel_uid_t kuid;
+	int err;
+
+	cmd = NCP_IOC_GETMOUNTUID2;
+
+	set_fs(KERNEL_DS);
+	err = sys_ioctl(fd, cmd, (unsigned long)&kuid);
+	set_fs(old_fs);
+
+	if (!err)
+		err = put_user(kuid, (unsigned int*)arg);
+
+	return err;
+}
+
+static int do_ncp_getfsinfo2(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+	mm_segment_t old_fs = get_fs();
+	struct ncp_fs_info_v2_32 n32;
+	struct ncp_fs_info_v2 n;
+	int err;
+
+	if (copy_from_user(&n32, (struct ncp_fs_info_v2_32*)arg, sizeof(n32)))
+		return -EFAULT;
+	if (n32.version != NCP_GET_FS_INFO_VERSION_V2)
+		return -EINVAL;
+	n.version = NCP_GET_FS_INFO_VERSION_V2;
+
+	set_fs(KERNEL_DS);
+	err = sys_ioctl(fd, NCP_IOC_GET_FS_INFO_V2, (unsigned long)&n);
+	set_fs(old_fs);
+
+	if (!err) {
+		n32.version = n.version;
+		n32.mounted_uid = n.mounted_uid;
+		n32.connection = n.connection;
+		n32.buffer_size = n.buffer_size;
+		n32.volume_number = n.volume_number;
+		n32.directory_id = n.directory_id;
+		n32.dummy1 = n.dummy1;
+		n32.dummy2 = n.dummy2;
+		n32.dummy3 = n.dummy3;
+		err = copy_to_user((struct ncp_fs_info_v2_32*)arg, &n32, sizeof(n32)) ? -EFAULT : 0;
+	}
+	return err;
+}
+
+static int do_ncp_getobjectname(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+	struct ncp_objectname_ioctl_32 n32;
+	struct ncp_objectname_ioctl n;
+	mm_segment_t old_fs;
+	int err;
+	size_t tl;
+
+	if (copy_from_user(&n32, (struct ncp_objectname_ioctl_32*)arg,
+	    sizeof(n32)))
+		return -EFAULT;
+
+	n.object_name_len = tl = n32.object_name_len;
+	if (tl) {
+		n.object_name = kmalloc(tl, GFP_KERNEL);
+		if (!n.object_name)
+			return -ENOMEM;
+	} else {
+		n.object_name = NULL;
+	}
+
+	old_fs = get_fs(); set_fs (KERNEL_DS);
+	err = sys_ioctl (fd, NCP_IOC_GETOBJECTNAME, (unsigned long)&n);
+	set_fs (old_fs);
+        if(err)
+		goto out;
+		
+	if (tl > n.object_name_len)
+		tl = n.object_name_len;
+
+	err = -EFAULT;
+	if (tl && copy_to_user(A(n32.object_name), n.object_name, tl))
+		goto out;
+
+	n32.auth_type = n.auth_type;
+	n32.object_name_len = n.object_name_len;
+	
+	if (copy_to_user((struct ncp_objectname_ioctl_32*)arg, &n32, sizeof(n32)))
+		goto out;
+	
+	err = 0;
+ out:
+ 	if (n.object_name)
+		kfree(n.object_name);
+
+	return err;
+}
+
+static int do_ncp_setobjectname(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+	struct ncp_objectname_ioctl_32 n32;
+	struct ncp_objectname_ioctl n;
+	mm_segment_t old_fs;
+	int err;
+	size_t tl;
+
+	if (copy_from_user(&n32, (struct ncp_objectname_ioctl_32*)arg,
+	    sizeof(n32)))
+		return -EFAULT;
+
+	n.auth_type = n32.auth_type;
+	n.object_name_len = tl = n32.object_name_len;
+	if (tl) {
+		n.object_name = kmalloc(tl, GFP_KERNEL);
+		if (!n.object_name)
+			return -ENOMEM;
+		err = -EFAULT;
+		if (copy_from_user(n.object_name, A(n32.object_name), tl))
+			goto out;
+	} else {
+		n.object_name = NULL;
+	}
+	
+	old_fs = get_fs(); set_fs (KERNEL_DS);
+	err = sys_ioctl (fd, NCP_IOC_SETOBJECTNAME, (unsigned long)&n);
+	set_fs (old_fs);
+		
+ out:
+	if (n.object_name)
+		kfree(n.object_name);
+
+	return err;
+}
+
+static int do_ncp_getprivatedata(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+	struct ncp_privatedata_ioctl_32 n32;
+	struct ncp_privatedata_ioctl n;
+	mm_segment_t old_fs;
+	int err;
+	size_t tl;
+
+	if (copy_from_user(&n32, (struct ncp_privatedata_ioctl_32*)arg,
+	    sizeof(n32)))
+		return -EFAULT;
+
+	n.len = tl = n32.len;
+	if (tl) {
+		n.data = kmalloc(tl, GFP_KERNEL);
+		if (!n.data)
+			return -ENOMEM;
+	} else {
+		n.data = NULL;
+	}
+
+	old_fs = get_fs(); set_fs (KERNEL_DS);
+	err = sys_ioctl (fd, NCP_IOC_GETPRIVATEDATA, (unsigned long)&n);
+	set_fs (old_fs);
+        if(err)
+		goto out;
+		
+	if (tl > n.len)
+		tl = n.len;
+
+	err = -EFAULT;
+	if (tl && copy_to_user(A(n32.data), n.data, tl))
+		goto out;
+
+	n32.len = n.len;
+	
+	if (copy_to_user((struct ncp_privatedata_ioctl_32*)arg, &n32, sizeof(n32)))
+		goto out;
+	
+	err = 0;
+ out:
+ 	if (n.data)
+		kfree(n.data);
+
+	return err;
+}
+
+static int do_ncp_setprivatedata(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+	struct ncp_privatedata_ioctl_32 n32;
+	struct ncp_privatedata_ioctl n;
+	mm_segment_t old_fs;
+	int err;
+	size_t tl;
+
+	if (copy_from_user(&n32, (struct ncp_privatedata_ioctl_32*)arg,
+	    sizeof(n32)))
+		return -EFAULT;
+
+	n.len = tl = n32.len;
+	if (tl) {
+		n.data = kmalloc(tl, GFP_KERNEL);
+		if (!n.data)
+			return -ENOMEM;
+		err = -EFAULT;
+		if (copy_from_user(n.data, A(n32.data), tl))
+			goto out;
+	} else {
+		n.data = NULL;
+	}
+	
+	old_fs = get_fs(); set_fs (KERNEL_DS);
+	err = sys_ioctl (fd, NCP_IOC_SETPRIVATEDATA, (unsigned long)&n);
+	set_fs (old_fs);
+		
+ out:
+	if (n.data)
+		kfree(n.data);
+
+	return err;
+}
+
+
 struct atmif_sioc32 {
         int                number;
         int                length;
@@ -4512,6 +4814,18 @@
 COMPATIBLE_IOCTL(RAW_GETBIND)
 /* SMB ioctls which do not need any translations */
 COMPATIBLE_IOCTL(SMB_IOC_NEWCONN)
+/* NCP ioctls which do not need any translations */
+COMPATIBLE_IOCTL(NCP_IOC_CONN_LOGGED_IN)
+COMPATIBLE_IOCTL(NCP_IOC_SIGN_INIT)
+COMPATIBLE_IOCTL(NCP_IOC_SIGN_WANTED)
+COMPATIBLE_IOCTL(NCP_IOC_SET_SIGN_WANTED)
+COMPATIBLE_IOCTL(NCP_IOC_LOCKUNLOCK)
+COMPATIBLE_IOCTL(NCP_IOC_GETROOT)
+COMPATIBLE_IOCTL(NCP_IOC_SETROOT)
+COMPATIBLE_IOCTL(NCP_IOC_GETCHARSETS)
+COMPATIBLE_IOCTL(NCP_IOC_SETCHARSETS)
+COMPATIBLE_IOCTL(NCP_IOC_GETDENTRYTTL)
+COMPATIBLE_IOCTL(NCP_IOC_SETDENTRYTTL)
 /* Little a */
 COMPATIBLE_IOCTL(ATMSIGD_CTRL)
 COMPATIBLE_IOCTL(ATMARPD_CTRL)
@@ -4761,6 +5075,14 @@
 /* One SMB ioctl needs translations. */
 #define SMB_IOC_GETMOUNTUID_32 _IOR('u', 1, __kernel_uid_t32)
 HANDLE_IOCTL(SMB_IOC_GETMOUNTUID_32, do_smb_getmountuid)
+/* NCPFS */
+HANDLE_IOCTL(NCP_IOC_NCPREQUEST_32, do_ncp_ncprequest)
+HANDLE_IOCTL(NCP_IOC_GETMOUNTUID2_32, do_ncp_getmountuid2)
+HANDLE_IOCTL(NCP_IOC_GET_FS_INFO_V2_32, do_ncp_getfsinfo2)
+HANDLE_IOCTL(NCP_IOC_GETOBJECTNAME_32, do_ncp_getobjectname)
+HANDLE_IOCTL(NCP_IOC_SETOBJECTNAME_32, do_ncp_setobjectname)
+HANDLE_IOCTL(NCP_IOC_GETPRIVATEDATA_32, do_ncp_getprivatedata)
+HANDLE_IOCTL(NCP_IOC_SETPRIVATEDATA_32, do_ncp_setprivatedata)
 HANDLE_IOCTL(ATM_GETLINKRATE32, do_atm_ioctl)
 HANDLE_IOCTL(ATM_GETNAMES32, do_atm_ioctl)
 HANDLE_IOCTL(ATM_GETTYPE32, do_atm_ioctl)
diff -urN linux-2.4.20-pre8/arch/sparc64/kernel/sys_sparc32.c linux-2.4.20-pre9/arch/sparc64/kernel/sys_sparc32.c
--- linux-2.4.20-pre8/arch/sparc64/kernel/sys_sparc32.c	Thu Oct  3 18:36:36 2002
+++ linux-2.4.20-pre9/arch/sparc64/kernel/sys_sparc32.c	Thu Oct  3 18:37:14 2002
@@ -1616,7 +1616,7 @@
 	return sys_sysfs(option, arg1, arg2);
 }
 
-struct ncp_mount_data32 {
+struct ncp_mount_data32_v3 {
         int version;
         unsigned int ncp_fd;
         __kernel_uid_t32 mounted_uid;
@@ -1631,19 +1631,69 @@
         __kernel_mode_t32 dir_mode;
 };
 
+struct ncp_mount_data32_v4 {
+	int version;
+	/* all members below are "long" in ABI ... i.e. 32bit on sparc32, while 64bits on sparc64 */
+	unsigned int flags;
+	unsigned int mounted_uid;
+	int wdog_pid;
+
+	unsigned int ncp_fd;
+	unsigned int time_out;
+	unsigned int retry_count;
+
+	unsigned int uid;
+	unsigned int gid;
+	unsigned int file_mode;
+	unsigned int dir_mode;
+};
+
 static void *do_ncp_super_data_conv(void *raw_data)
 {
-	struct ncp_mount_data news, *n = &news; 
-	struct ncp_mount_data32 *n32 = (struct ncp_mount_data32 *)raw_data;
+	switch (*(int*)raw_data) {
+		case NCP_MOUNT_VERSION:
+			{
+				struct ncp_mount_data news, *n = &news; 
+				struct ncp_mount_data32_v3 *n32 = (struct ncp_mount_data32_v3 *)raw_data;
+
+				n->version = n32->version;
+				n->ncp_fd = n32->ncp_fd;
+				n->mounted_uid = low2highuid(n32->mounted_uid);
+				n->wdog_pid = n32->wdog_pid;
+				memmove (n->mounted_vol, n32->mounted_vol, sizeof (n32->mounted_vol));
+				n->time_out = n32->time_out;
+				n->retry_count = n32->retry_count;
+				n->flags = n32->flags;
+				n->uid = low2highuid(n32->uid);
+				n->gid = low2highgid(n32->gid);
+				n->file_mode = n32->file_mode;
+				n->dir_mode = n32->dir_mode;
+				memcpy(raw_data, n, sizeof(*n)); 
+			}
+			break;
+		case NCP_MOUNT_VERSION_V4:
+			{
+				struct ncp_mount_data_v4 news, *n = &news; 
+				struct ncp_mount_data32_v4 *n32 = (struct ncp_mount_data32_v4 *)raw_data;
 
-	n->dir_mode = n32->dir_mode;
-	n->file_mode = n32->file_mode;
-	n->gid = low2highgid(n32->gid);
-	n->uid = low2highuid(n32->uid);
-	memmove (n->mounted_vol, n32->mounted_vol, (sizeof (n32->mounted_vol) + 3 * sizeof (unsigned int)));
-	n->wdog_pid = n32->wdog_pid;
-	n->mounted_uid = low2highuid(n32->mounted_uid);
-	memcpy(raw_data, n, sizeof(struct ncp_mount_data)); 
+				n->version = n32->version;
+				n->flags = n32->flags;
+				n->mounted_uid = n32->mounted_uid;
+				n->wdog_pid = n32->wdog_pid;
+				n->ncp_fd = n32->ncp_fd;
+				n->time_out = n32->time_out;
+				n->retry_count = n32->retry_count;
+				n->uid = n32->uid;
+				n->gid = n32->gid;
+				n->file_mode = n32->file_mode;
+				n->dir_mode = n32->dir_mode;
+				memcpy(raw_data, n, sizeof(*n)); 
+			}
+			break;
+		default:
+			/* do not touch unknown structures */
+			break;
+	}
 	return raw_data;
 }
 
diff -urN linux-2.4.20-pre8/drivers/block/ll_rw_blk.c linux-2.4.20-pre9/drivers/block/ll_rw_blk.c
--- linux-2.4.20-pre8/drivers/block/ll_rw_blk.c	Thu Oct  3 18:36:38 2002
+++ linux-2.4.20-pre9/drivers/block/ll_rw_blk.c	Thu Oct  3 18:37:15 2002
@@ -269,7 +269,8 @@
 		if (dma_addr == BLK_BOUNCE_ANY)
 			printk("no I/O memory limit\n");
 		else
-			printk("I/O limit %luMb (mask 0x%Lx)\n", mb, (u64) dma_addr);
+			printk("I/O limit %luMb (mask 0x%Lx)\n", mb,
+			       (long long) dma_addr);
 	}
 
 	q->bounce_pfn = bounce_pfn;
diff -urN linux-2.4.20-pre8/drivers/char/agp/agpgart_be.c linux-2.4.20-pre9/drivers/char/agp/agpgart_be.c
--- linux-2.4.20-pre8/drivers/char/agp/agpgart_be.c	Thu Oct  3 18:36:38 2002
+++ linux-2.4.20-pre9/drivers/char/agp/agpgart_be.c	Thu Oct  3 18:37:15 2002
@@ -5026,7 +5026,7 @@
 {
 	long memory, index, result;
 
-	memory = virt_to_phys(high_memory) >> 20;
+	memory = (num_physpages << PAGE_SHIFT) >> 20;
 	index = 1;
 
 	while ((memory > maxes_table[index].mem) &&
diff -urN linux-2.4.20-pre8/drivers/char/drm/Config.in linux-2.4.20-pre9/drivers/char/drm/Config.in
--- linux-2.4.20-pre8/drivers/char/drm/Config.in	Thu Oct  3 18:36:38 2002
+++ linux-2.4.20-pre9/drivers/char/drm/Config.in	Thu Oct  3 18:37:16 2002
@@ -10,6 +10,7 @@
 tristate '  ATI Rage 128' CONFIG_DRM_R128
 dep_tristate '  ATI Radeon' CONFIG_DRM_RADEON $CONFIG_AGP
 dep_tristate '  Intel I810' CONFIG_DRM_I810 $CONFIG_AGP
+dep_mbool    '    Enabled XFree 4.1 ioctl interface by default' CONFIG_DRM_I810_XFREE_41 $CONFIG_DRM_I810
 dep_tristate '  Intel 830M' CONFIG_DRM_I830 $CONFIG_AGP
 dep_tristate '  Matrox g200/g400' CONFIG_DRM_MGA $CONFIG_AGP
 dep_tristate '  SiS' CONFIG_DRM_SIS $CONFIG_AGP
diff -urN linux-2.4.20-pre8/drivers/char/drm/ati_pcigart.h linux-2.4.20-pre9/drivers/char/drm/ati_pcigart.h
--- linux-2.4.20-pre8/drivers/char/drm/ati_pcigart.h	Thu Oct  3 18:36:38 2002
+++ linux-2.4.20-pre9/drivers/char/drm/ati_pcigart.h	Thu Oct  3 18:37:16 2002
@@ -29,14 +29,20 @@
 
 #include "drmP.h"
 
-#if PAGE_SIZE == 8192
+#if PAGE_SIZE == 65536
+# define ATI_PCIGART_TABLE_ORDER 	0
+# define ATI_PCIGART_TABLE_PAGES 	(1 << 0)
+#elif PAGE_SIZE == 16384
+# define ATI_PCIGART_TABLE_ORDER 	1
+# define ATI_PCIGART_TABLE_PAGES 	(1 << 1)
+#elif PAGE_SIZE == 8192
 # define ATI_PCIGART_TABLE_ORDER 	2
 # define ATI_PCIGART_TABLE_PAGES 	(1 << 2)
 #elif PAGE_SIZE == 4096
 # define ATI_PCIGART_TABLE_ORDER 	3
 # define ATI_PCIGART_TABLE_PAGES 	(1 << 3)
 #else
-# error - PAGE_SIZE not 8K or 4K
+# error - PAGE_SIZE not 64K, 16K, 8K or 4K
 #endif
 
 # define ATI_MAX_PCIGART_PAGES		8192	/* 32 MB aperture, 4K pages */
diff -urN linux-2.4.20-pre8/drivers/char/drm/i810_dma.c linux-2.4.20-pre9/drivers/char/drm/i810_dma.c
--- linux-2.4.20-pre8/drivers/char/drm/i810_dma.c	Thu Oct  3 18:36:38 2002
+++ linux-2.4.20-pre9/drivers/char/drm/i810_dma.c	Thu Oct  3 18:37:16 2002
@@ -30,6 +30,7 @@
  *
  */
 
+#include <linux/config.h>
 #include "i810.h"
 #include "drmP.h"
 #include "i810_drv.h"
@@ -466,8 +467,11 @@
    	return 0;
 }
 
-
+#ifdef CONFIG_DRM_I810_XFREE_41
+int xfreeversion = 41;
+#else
 int xfreeversion = -1;
+#endif
 
 MODULE_PARM(xfreeversion, "i");
 MODULE_PARM_DESC(xfreeversion, "The version of XFree86 that needs to be supported");
diff -urN linux-2.4.20-pre8/drivers/char/pc_keyb.c linux-2.4.20-pre9/drivers/char/pc_keyb.c
--- linux-2.4.20-pre8/drivers/char/pc_keyb.c	Fri Aug  2 17:39:43 2002
+++ linux-2.4.20-pre9/drivers/char/pc_keyb.c	Thu Oct  3 18:37:17 2002
@@ -69,6 +69,9 @@
 static int aux_reconnect = 0;
 #endif
 
+#ifndef kbd_controller_present
+#define kbd_controller_present()	1
+#endif
 static spinlock_t kbd_controller_lock = SPIN_LOCK_UNLOCKED;
 static unsigned char handle_kbd_event(void);
 
@@ -895,6 +898,11 @@
 
 void __init pckbd_init_hw(void)
 {
+	if (!kbd_controller_present()) {
+		kbd_exists = 0;
+		return;
+	}
+
 	kbd_request_region();
 
 	/* Flush any pending input. */
diff -urN linux-2.4.20-pre8/drivers/ieee1394/amdtp.c linux-2.4.20-pre9/drivers/ieee1394/amdtp.c
--- linux-2.4.20-pre8/drivers/ieee1394/amdtp.c	Thu Oct  3 18:36:43 2002
+++ linux-2.4.20-pre9/drivers/ieee1394/amdtp.c	Thu Oct  3 18:37:21 2002
@@ -196,7 +196,7 @@
 /* This implements a circular buffer for incoming samples. */
 
 struct buffer {
-	int head, tail, length, size;
+	size_t head, tail, length, size;
 	unsigned char data[0];
 };
 
@@ -623,9 +623,9 @@
 }
 
 static unsigned char *buffer_put_bytes(struct buffer *buffer,
-				       int max, int *actual)
+				       size_t max, size_t *actual)
 {
-	int length;
+	size_t length;
 	unsigned char *p;
 
 	p = &buffer->data[buffer->tail];
diff -urN linux-2.4.20-pre8/drivers/ieee1394/dv1394.c linux-2.4.20-pre9/drivers/ieee1394/dv1394.c
--- linux-2.4.20-pre8/drivers/ieee1394/dv1394.c	Thu Oct  3 18:36:43 2002
+++ linux-2.4.20-pre9/drivers/ieee1394/dv1394.c	Thu Oct  3 18:37:21 2002
@@ -2139,7 +2139,7 @@
 			const char *buffer, unsigned long count, void *data)
 {
 	int len = 0;
-	char new_value[64];
+	char new_value[65];
 	char *pos;
 	struct video_card *video = (struct video_card*) data;
 	
@@ -2151,11 +2151,12 @@
 	if (copy_from_user( new_value, buffer, len))
 		return -EFAULT;
 	
+	new_value[len] = 0;
 	pos = strchr(new_value, '=');
 	if (pos != NULL) {
 		int val_len = len - (pos-new_value) - 1;
-		char buf[64];
-		memset(buf, 0, 64);
+		char buf[65];
+		memset(buf, 0, 65);
 		strncpy(buf, pos+1, val_len);
 		if (buf[val_len-1] == '\n') buf[val_len-1] = 0;
 		
diff -urN linux-2.4.20-pre8/drivers/ieee1394/pcilynx.c linux-2.4.20-pre9/drivers/ieee1394/pcilynx.c
--- linux-2.4.20-pre8/drivers/ieee1394/pcilynx.c	Thu Oct  3 18:36:43 2002
+++ linux-2.4.20-pre9/drivers/ieee1394/pcilynx.c	Thu Oct  3 18:37:21 2002
@@ -887,13 +887,14 @@
         struct memdata *md = (struct memdata *)file->private_data;
         ssize_t bcount;
         size_t alignfix;
-        int off = (int)*offset; /* avoid useless 64bit-arithmetic */
+	loff_t off = *offset; /* avoid useless 64bit-arithmetic */
         ssize_t retval;
         void *membase;
 
 	if (*offset != off)	/* Check for EOF before we trust wrap */
 		return 0;
 	
+	/* FIXME: Signed wrap is undefined in C - wants fixing up */
 	if (off + count > off)
 		return 0;
 		
diff -urN linux-2.4.20-pre8/drivers/mtd/devices/Config.in linux-2.4.20-pre9/drivers/mtd/devices/Config.in
--- linux-2.4.20-pre8/drivers/mtd/devices/Config.in	Thu Oct  3 18:36:44 2002
+++ linux-2.4.20-pre9/drivers/mtd/devices/Config.in	Thu Oct  3 18:37:26 2002
@@ -10,7 +10,9 @@
    bool '    PMC551 256M DRAM Bugfix' CONFIG_MTD_PMC551_BUGFIX
    bool '    PMC551 Debugging' CONFIG_MTD_PMC551_DEBUG
 fi
-dep_tristate '  DEC MS02-NV NVRAM module support' CONFIG_MTD_MS02NV $CONFIG_MTD $CONFIG_DECSTATION
+if [ "$CONFIG_DECSTATION" = "y" ]; then
+   dep_tristate '  DEC MS02-NV NVRAM module support' CONFIG_MTD_MS02NV $CONFIG_MTD $CONFIG_DECSTATION
+fi
 dep_tristate '  Uncached system RAM' CONFIG_MTD_SLRAM $CONFIG_MTD
 if [ "$CONFIG_SA1100_LART" = "y" ]; then
   dep_tristate '  28F160xx flash driver for LART' CONFIG_MTD_LART $CONFIG_MTD
diff -urN linux-2.4.20-pre8/drivers/net/8139cp.c linux-2.4.20-pre9/drivers/net/8139cp.c
--- linux-2.4.20-pre8/drivers/net/8139cp.c	Thu Oct  3 18:36:44 2002
+++ linux-2.4.20-pre9/drivers/net/8139cp.c	Thu Oct  3 18:37:27 2002
@@ -22,13 +22,11 @@
 	
 		Wake-on-LAN support - Felipe Damasio <felipewd@terra.com.br>
 		PCI suspend/resume  - Felipe Damasio <felipewd@terra.com.br>
+		LinkChg interrupt   - Felipe Damasio <felipewd@terra.com.br>
 			
 	TODO, in rough priority order:
 	* Test Tx checksumming thoroughly
 	* dev->tx_timeout
-	* LinkChg interrupt
-	* Support forcing media type with a module parameter,
-	  like dl2k.c/sundance.c
 	* Constants (module parms?) for Rx work limit
 	* Complete reset on PciErr
 	* Consider Rx interrupt mitigation using TimerIntr
@@ -49,8 +47,8 @@
  */
 
 #define DRV_NAME		"8139cp"
-#define DRV_VERSION		"0.2.1"
-#define DRV_RELDATE		"Aug 9, 2002"
+#define DRV_VERSION		"0.3.0"
+#define DRV_RELDATE		"Sep 29, 2002"
 
 
 #include <linux/config.h>
@@ -107,6 +105,11 @@
 
 #define PFX			DRV_NAME ": "
 
+#ifndef TRUE
+#define FALSE 0
+#define TRUE (!FALSE)
+#endif
+
 #define CP_DEF_MSG_ENABLE	(NETIF_MSG_DRV		| \
 				 NETIF_MSG_PROBE 	| \
 				 NETIF_MSG_LINK)
@@ -677,6 +680,8 @@
 		cp_rx(cp);
 	if (status & (TxOK | TxErr | TxEmpty | SWInt))
 		cp_tx(cp);
+	if (status & LinkChg)
+		mii_check_media(&cp->mii_if, netif_msg_link(cp), FALSE);
 
 	if (status & PciErr) {
 		u16 pci_status;
@@ -1190,6 +1195,8 @@
 	if (rc)
 		goto err_out_hw;
 
+	netif_carrier_off(dev);
+	mii_check_media(&cp->mii_if, netif_msg_link(cp), TRUE);
 	netif_start_queue(dev);
 
 	return 0;
@@ -1208,6 +1215,7 @@
 		printk(KERN_DEBUG "%s: disabling interface\n", dev->name);
 
 	netif_stop_queue(dev);
+	netif_carrier_off(dev);
 
 	spin_lock_irq(&cp->lock);
 	cp_stop_hw(cp);
@@ -1647,20 +1655,18 @@
 static int cp_ioctl (struct net_device *dev, struct ifreq *rq, int cmd)
 {
 	struct cp_private *cp = dev->priv;
-	int rc = 0;
+	struct mii_ioctl_data *mii = (struct mii_ioctl_data *) &rq->ifr_data;
+	int rc;
 
 	if (!netif_running(dev))
 		return -EINVAL;
 
-	switch (cmd) {
-	case SIOCETHTOOL:
+	if (cmd == SIOCETHTOOL)
 		return cp_ethtool_ioctl(cp, (void *) rq->ifr_data);
 
-	default:
-		rc = -EOPNOTSUPP;
-		break;
-	}
-
+	spin_lock_irq(&cp->lock);
+	rc = generic_mii_ioctl(&cp->mii_if, mii, cmd, NULL);
+	spin_unlock_irq(&cp->lock);
 	return rc;
 }
 
@@ -1798,6 +1804,8 @@
 	cp->mii_if.mdio_read = mdio_read;
 	cp->mii_if.mdio_write = mdio_write;
 	cp->mii_if.phy_id = CP_INTERNAL_PHY;
+	cp->mii_if.phy_id_mask = 0x1f;
+	cp->mii_if.reg_num_mask = 0x1f;
 	cp_set_rxbufsize(cp);
 
 	rc = pci_enable_device(pdev);
diff -urN linux-2.4.20-pre8/drivers/net/8139too.c linux-2.4.20-pre9/drivers/net/8139too.c
--- linux-2.4.20-pre8/drivers/net/8139too.c	Thu Oct  3 18:36:44 2002
+++ linux-2.4.20-pre9/drivers/net/8139too.c	Thu Oct  3 18:37:27 2002
@@ -578,7 +578,6 @@
 	signed char phys[4];		/* MII device addresses. */
 	char twistie, twist_row, twist_col;	/* Twister tune state. */
 	unsigned int default_port:4;	/* Last dev->if_port value. */
-	unsigned int medialock:1;	/* Don't sense media type. */
 	spinlock_t lock;
 	chip_t chipset;
 	pid_t thr_pid;
@@ -986,6 +985,8 @@
 	tp->mii.dev = dev;
 	tp->mii.mdio_read = mdio_read;
 	tp->mii.mdio_write = mdio_write;
+	tp->mii.phy_id_mask = 0x3f;
+	tp->mii.reg_num_mask = 0x1f;
 
 	/* dev is fully set up and ready to use now */
 	DPRINTK("about to register device named %s (%p)...\n", dev->name, dev);
@@ -1041,7 +1042,7 @@
 		tp->mii.full_duplex = (option & 0x210) ? 1 : 0;
 		tp->default_port = option & 0xFF;
 		if (tp->default_port)
-			tp->medialock = 1;
+			tp->mii.force_media = 1;
 	}
 	if (board_idx < MAX_UNITS  &&  full_duplex[board_idx] > 0)
 		tp->mii.full_duplex = full_duplex[board_idx];
@@ -1049,7 +1050,7 @@
 		printk(KERN_INFO "%s: Media type forced to Full Duplex.\n", dev->name);
 		/* Changing the MII-advertised media because might prevent
 		   re-connection. */
-		tp->mii.duplex_lock = 1;
+		tp->mii.force_media = 1;
 	}
 	if (tp->default_port) {
 		printk(KERN_INFO "  Forcing %dMbps %s-duplex operation.\n",
@@ -1306,7 +1307,7 @@
 
 	}
 
-	tp->mii.full_duplex = tp->mii.duplex_lock;
+	tp->mii.full_duplex = tp->mii.force_media;
 	tp->tx_flag = (TX_FIFO_THRESH << 11) & 0x003f0000;
 	tp->twistie = (tp->chipset == CH_8139_K) ? 1 : 0;
 	tp->time_to_die = 0;
@@ -1537,7 +1538,7 @@
 
 	mii_lpa = mdio_read (dev, tp->phys[0], MII_LPA);
 
-	if (!tp->mii.duplex_lock && mii_lpa != 0xffff) {
+	if (!tp->mii.force_media && mii_lpa != 0xffff) {
 		int duplex = (mii_lpa & LPA_100FULL)
 		    || (mii_lpa & 0x01C0) == 0x0040;
 		if (tp->mii.full_duplex != duplex) {
@@ -1996,7 +1997,7 @@
 		/* Really link-change on new chips. */
 		int lpar = RTL_R16 (NWayLPAR);
 		int duplex = (lpar & LPA_100FULL) || (lpar & 0x01C0) == 0x0040
-				|| tp->mii.duplex_lock;
+				|| tp->mii.force_media;
 		if (tp->mii.full_duplex != duplex) {
 			tp->mii.full_duplex = duplex;
 #if 0
@@ -2438,61 +2439,22 @@
 }
 
 
-static int netdev_ioctl (struct net_device *dev, struct ifreq *rq, int cmd)
+static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 {
-	struct rtl8139_private *tp = dev->priv;
-	struct mii_ioctl_data *data = (struct mii_ioctl_data *)&rq->ifr_data;
-	int rc = 0;
-	int phy = tp->phys[0] & 0x3f;
+	struct rtl8139_private *np = dev->priv;
+	struct mii_ioctl_data *data = (struct mii_ioctl_data *) & rq->ifr_data;
+	int rc;
 
 	if (!netif_running(dev))
 		return -EINVAL;
 
-	if (cmd != SIOCETHTOOL) {
-		/* With SIOCETHTOOL, this would corrupt the pointer.  */
-		data->phy_id &= 0x3f;
-		data->reg_num &= 0x1f;
-	}
-
-	switch (cmd) {
-	case SIOCETHTOOL:
-		return netdev_ethtool_ioctl(dev, (void *) rq->ifr_data);
-
-	case SIOCGMIIPHY:	/* Get the address of the PHY in use. */
-	case SIOCDEVPRIVATE:	/* binary compat, remove in 2.5 */
-		data->phy_id = phy;
-		/* Fall Through */
-
-	case SIOCGMIIREG:	/* Read the specified MII register. */
-	case SIOCDEVPRIVATE+1:	/* binary compat, remove in 2.5 */
-		data->val_out = mdio_read (dev, data->phy_id, data->reg_num);
-		break;
-
-	case SIOCSMIIREG:	/* Write the specified MII register */
-	case SIOCDEVPRIVATE+2:	/* binary compat, remove in 2.5 */
-		if (!capable (CAP_NET_ADMIN)) {
-			rc = -EPERM;
-			break;
-		}
+	if (cmd == SIOCETHTOOL)
+		rc = netdev_ethtool_ioctl(dev, (void *) rq->ifr_data);
 
-		if (data->phy_id == phy) {
-			u16 value = data->val_in;
-			switch (data->reg_num) {
-			case 0:
-				/* Check for autonegotiation on or reset. */
-				tp->medialock = (value & 0x9000) ? 0 : 1;
-				if (tp->medialock)
-					tp->mii.full_duplex = (value & 0x0100) ? 1 : 0;
-				break;
-			case 4: tp->mii.advertising = value; break;
-			}
-		}
-		mdio_write(dev, data->phy_id, data->reg_num, data->val_in);
-		break;
-
-	default:
-		rc = -EOPNOTSUPP;
-		break;
+	else {
+		spin_lock_irq(&np->lock);
+		rc = generic_mii_ioctl(&np->mii, data, cmd, NULL);
+		spin_unlock_irq(&np->lock);
 	}
 
 	return rc;
diff -urN linux-2.4.20-pre8/drivers/net/acenic.h linux-2.4.20-pre9/drivers/net/acenic.h
--- linux-2.4.20-pre8/drivers/net/acenic.h	Thu Oct  3 18:36:44 2002
+++ linux-2.4.20-pre9/drivers/net/acenic.h	Thu Oct  3 18:37:27 2002
@@ -770,7 +770,7 @@
 	if (ACE_IS_TIGON_I(ap))
 		writel(0, &regs->MaskInt);
 	else
-		writel(readl(&regs->HostCtrl) &= ~MASK_INTS, &regs->HostCtrl);
+		writel(readl(&regs->HostCtrl) & ~MASK_INTS, &regs->HostCtrl);
 }
 
 
diff -urN linux-2.4.20-pre8/drivers/net/eepro100.c linux-2.4.20-pre9/drivers/net/eepro100.c
--- linux-2.4.20-pre8/drivers/net/eepro100.c	Thu Oct  3 18:36:44 2002
+++ linux-2.4.20-pre9/drivers/net/eepro100.c	Thu Oct  3 18:37:32 2002
@@ -459,8 +459,8 @@
    Unfortunately, all the positions have been shifted since there.
    A new re-alignment is required.  2000/03/06  SAW */
 struct speedo_private {
-	struct TxFD	*tx_ring;				/* Commands (usually CmdTxPacket). */
-	struct RxFD *rx_ringp[RX_RING_SIZE];/* Rx descriptor, used as ring. */
+	struct TxFD	*tx_ring;		/* Commands (usually CmdTxPacket). */
+	struct RxFD *rx_ringp[RX_RING_SIZE];	/* Rx descriptor, used as ring. */
 	/* The addresses of a Tx/Rx-in-place packets/buffers. */
 	struct sk_buff *tx_skbuff[TX_RING_SIZE];
 	struct sk_buff *rx_skbuff[RX_RING_SIZE];
@@ -470,9 +470,9 @@
 	dma_addr_t rx_ring_dma[RX_RING_SIZE];
 	struct descriptor *last_cmd;		/* Last command sent. */
 	unsigned int cur_tx, dirty_tx;		/* The ring entries to be free()ed. */
-	spinlock_t lock;					/* Group with Tx control cache line. */
-	u32 tx_threshold;					/* The value for txdesc.count. */
-	struct RxFD *last_rxf;				/* Last filled RX buffer. */
+	spinlock_t lock;			/* Group with Tx control cache line. */
+	u32 tx_threshold;			/* The value for txdesc.count. */
+	struct RxFD *last_rxf;			/* Last filled RX buffer. */
 	dma_addr_t last_rxf_dma;
 	unsigned int cur_rx, dirty_rx;		/* The next free ring entry */
 	long last_rx_time;			/* Last Rx, in jiffies, to handle Rx hang. */
@@ -481,21 +481,21 @@
 	dma_addr_t lstats_dma;
 	int chip_id;
 	struct pci_dev *pdev;
-	struct timer_list timer;			/* Media selection timer. */
-	struct speedo_mc_block *mc_setup_head;/* Multicast setup frame list head. */
-	struct speedo_mc_block *mc_setup_tail;/* Multicast setup frame list tail. */
-	long in_interrupt;					/* Word-aligned dev->interrupt */
+	struct timer_list timer;		/* Media selection timer. */
+	struct speedo_mc_block *mc_setup_head;	/* Multicast setup frame list head. */
+	struct speedo_mc_block *mc_setup_tail;	/* Multicast setup frame list tail. */
+	long in_interrupt;			/* Word-aligned dev->interrupt */
 	unsigned char acpi_pwr;
-	signed char rx_mode;					/* Current PROMISC/ALLMULTI setting. */
-	unsigned int tx_full:1;				/* The Tx queue is full. */
-	unsigned int full_duplex:1;			/* Full-duplex operation requested. */
-	unsigned int flow_ctrl:1;			/* Use 802.3x flow control. */
-	unsigned int rx_bug:1;				/* Work around receiver hang errata. */
+	signed char rx_mode;			/* Current PROMISC/ALLMULTI setting. */
+	unsigned int tx_full:1;			/* The Tx queue is full. */
+	unsigned int full_duplex:1;		/* Full-duplex operation requested. */
+	unsigned int flow_ctrl:1;		/* Use 802.3x flow control. */
+	unsigned int rx_bug:1;			/* Work around receiver hang errata. */
 	unsigned char default_port:8;		/* Last dev->if_port value. */
 	unsigned char rx_ring_state;		/* RX ring status flags. */
-	unsigned short phy[2];				/* PHY media interfaces available. */
-	unsigned short advertising;			/* Current PHY advertised caps. */
-	unsigned short partner;				/* Link partner caps. */
+	unsigned short phy[2];			/* PHY media interfaces available. */
+	unsigned short partner;			/* Link partner caps. */
+	struct mii_if_info mii_if;		/* MII API hooks, info */
 #ifdef CONFIG_PM
 	u32 pm_state[16];
 #endif
@@ -531,8 +531,8 @@
 static void eepro100_remove_one (struct pci_dev *pdev);
 
 static int do_eeprom_cmd(long ioaddr, int cmd, int cmd_len);
-static int mdio_read(long ioaddr, int phy_id, int location);
-static int mdio_write(long ioaddr, int phy_id, int location, int value);
+static int mdio_read(struct net_device *dev, int phy_id, int location);
+static void mdio_write(struct net_device *dev, int phy_id, int location, int value);
 static int speedo_open(struct net_device *dev);
 static void speedo_resume(struct net_device *dev);
 static void speedo_timer(unsigned long data);
@@ -729,6 +729,9 @@
 #endif
 	printk("IRQ %d.\n", pdev->irq);
 
+	/* we must initialize base_addr early, for mdio_{read,write} */
+	dev->base_addr = ioaddr;
+
 #if 1 || defined(kernel_bloat)
 	/* OK, this is pure kernel bloat.  I don't like it when other drivers
 	   waste non-pageable kernel space to emit similar messages, but I need
@@ -754,18 +757,18 @@
 				   phys[(eeprom[7]>>8)&7]);
 		if (((eeprom[6]>>8) & 0x3f) == DP83840
 			||  ((eeprom[6]>>8) & 0x3f) == DP83840A) {
-			int mdi_reg23 = mdio_read(ioaddr, eeprom[6] & 0x1f, 23) | 0x0422;
+			int mdi_reg23 = mdio_read(dev, eeprom[6] & 0x1f, 23) | 0x0422;
 			if (congenb)
 			  mdi_reg23 |= 0x0100;
 			printk(KERN_INFO"  DP83840 specific setup, setting register 23 to %4.4x.\n",
 				   mdi_reg23);
-			mdio_write(ioaddr, eeprom[6] & 0x1f, 23, mdi_reg23);
+			mdio_write(dev, eeprom[6] & 0x1f, 23, mdi_reg23);
 		}
 		if ((option >= 0) && (option & 0x70)) {
 			printk(KERN_INFO "  Forcing %dMbs %s-duplex operation.\n",
 				   (option & 0x20 ? 100 : 10),
 				   (option & 0x10 ? "full" : "half"));
-			mdio_write(ioaddr, eeprom[6] & 0x1f, 0,
+			mdio_write(dev, eeprom[6] & 0x1f, MII_BMCR,
 					   ((option & 0x20) ? 0x2000 : 0) | 	/* 100mbps? */
 					   ((option & 0x10) ? 0x0100 : 0)); /* Full duplex? */
 		}
@@ -807,7 +810,6 @@
 
 	pci_set_drvdata (pdev, dev);
 
-	dev->base_addr = ioaddr;
 	dev->irq = pdev->irq;
 
 	sp = dev->priv;
@@ -819,15 +821,21 @@
 	sp->lstats_dma = TX_RING_ELEM_DMA(sp, TX_RING_SIZE);
 	init_timer(&sp->timer); /* used in ioctl() */
 
-	sp->full_duplex = option >= 0 && (option & 0x10) ? 1 : 0;
+	sp->mii_if.full_duplex = option >= 0 && (option & 0x10) ? 1 : 0;
 	if (card_idx >= 0) {
 		if (full_duplex[card_idx] >= 0)
-			sp->full_duplex = full_duplex[card_idx];
+			sp->mii_if.full_duplex = full_duplex[card_idx];
 	}
 	sp->default_port = option >= 0 ? (option & 0x0f) : 0;
 
 	sp->phy[0] = eeprom[6];
 	sp->phy[1] = eeprom[7];
+
+	sp->mii_if.phy_id = eeprom[6];
+	sp->mii_if.dev = dev;
+	sp->mii_if.mdio_read = mdio_read;
+	sp->mii_if.mdio_write = mdio_write;
+	
 	sp->rx_bug = (eeprom[3] & 0x03) == 3 ? 0 : 1;
 	if (((pdev->device > 0x1030 && (pdev->device < 0x103F))) 
 	    || (pdev->device == 0x2449) || (pdev->device == 0x2459) 
@@ -914,8 +922,9 @@
 	return retval;
 }
 
-static int mdio_read(long ioaddr, int phy_id, int location)
+static int mdio_read(struct net_device *dev, int phy_id, int location)
 {
+	long ioaddr = dev->base_addr;
 	int val, boguscnt = 64*10;		/* <64 usec. to complete, typ 27 ticks */
 	outl(0x08000000 | (location<<16) | (phy_id<<21), ioaddr + SCBCtrlMDI);
 	do {
@@ -928,8 +937,9 @@
 	return val & 0xffff;
 }
 
-static int mdio_write(long ioaddr, int phy_id, int location, int value)
+static void mdio_write(struct net_device *dev, int phy_id, int location, int value)
 {
+	long ioaddr = dev->base_addr;
 	int val, boguscnt = 64*10;		/* <64 usec. to complete, typ 27 ticks */
 	outl(0x04000000 | (location<<16) | (phy_id<<21) | value,
 		 ioaddr + SCBCtrlMDI);
@@ -940,7 +950,6 @@
 			break;
 		}
 	} while (! (val & 0x10000000));
-	return val & 0xffff;
 }
 
 static int
@@ -982,9 +991,9 @@
 		   0x2100 100-FD
 		*/
 #ifdef honor_default_port
-		mdio_write(ioaddr, phy_addr, 0, mii_ctrl[dev->default_port & 7]);
+		mdio_write(dev, phy_addr, MII_BMCR, mii_ctrl[dev->default_port & 7]);
 #else
-		mdio_write(ioaddr, phy_addr, 0, 0x3300);
+		mdio_write(dev, phy_addr, MII_BMCR, 0x3300);
 #endif
 	}
 #endif
@@ -1005,9 +1014,9 @@
 	sp->rx_mode = -1;			/* Invalid -> always reset the mode. */
 	set_rx_mode(dev);
 	if ((sp->phy[0] & 0x8000) == 0)
-		sp->advertising = mdio_read(ioaddr, sp->phy[0] & 0x1f, 4);
+		sp->mii_if.advertising = mdio_read(dev, sp->phy[0] & 0x1f, MII_ADVERTISE);
 
-	if (mdio_read(ioaddr, sp->phy[0] & 0x1f, MII_BMSR) & BMSR_LSTATUS)
+	if (mdio_read(dev, sp->phy[0] & 0x1f, MII_BMSR) & BMSR_LSTATUS)
 		netif_carrier_on(dev);
 	else
 		netif_carrier_off(dev);
@@ -1029,7 +1038,7 @@
 
 	/* No need to wait for the command unit to accept here. */
 	if ((sp->phy[0] & 0x8000) == 0)
-		mdio_read(ioaddr, sp->phy[0] & 0x1f, 0);
+		mdio_read(dev, sp->phy[0] & 0x1f, MII_BMCR);
 
 	return 0;
 }
@@ -1159,13 +1168,13 @@
 
 	/* We have MII and lost link beat. */
 	if ((sp->phy[0] & 0x8000) == 0) {
-		int partner = mdio_read(ioaddr, phy_num, 5);
+		int partner = mdio_read(dev, phy_num, MII_LPA);
 		if (partner != sp->partner) {
-			int flow_ctrl = sp->advertising & partner & 0x0400 ? 1 : 0;
+			int flow_ctrl = sp->mii_if.advertising & partner & 0x0400 ? 1 : 0;
 			if (speedo_debug > 2) {
 				printk(KERN_DEBUG "%s: Link status change.\n", dev->name);
 				printk(KERN_DEBUG "%s: Old partner %x, new %x, adv %x.\n",
-					   dev->name, sp->partner, partner, sp->advertising);
+					   dev->name, sp->partner, partner, sp->mii_if.advertising);
 			}
 			sp->partner = partner;
 			if (flow_ctrl != sp->flow_ctrl) {
@@ -1173,9 +1182,9 @@
 				sp->rx_mode = -1;	/* Trigger a reload. */
 			}
 			/* Clear sticky bit. */
-			mdio_read(ioaddr, phy_num, 1);
+			mdio_read(dev, phy_num, MII_BMSR);
 			/* If link beat has returned... */
-			if (mdio_read(ioaddr, phy_num, 1) & 0x0004)
+			if (mdio_read(dev, phy_num, MII_BMSR) & BMSR_LSTATUS)
 				netif_carrier_on(dev);
 			else
 				netif_carrier_off(dev);
@@ -1241,7 +1250,7 @@
 			/* FIXME: what does it mean?  --SAW */
 			if (i == 6) i = 21;
 			printk(KERN_DEBUG "%s:  PHY index %d register %d is %4.4x.\n",
-				   dev->name, phy_num, i, mdio_read(ioaddr, phy_num, i));
+				   dev->name, phy_num, i, mdio_read(dev, phy_num, i));
 		}
 	}
 #endif
@@ -1333,22 +1342,22 @@
 static void reset_mii(struct net_device *dev)
 {
 	struct speedo_private *sp = (struct speedo_private *)dev->priv;
-	long ioaddr = dev->base_addr;
+
 	/* Reset the MII transceiver, suggested by Fred Young @ scalable.com. */
 	if ((sp->phy[0] & 0x8000) == 0) {
 		int phy_addr = sp->phy[0] & 0x1f;
-		int advertising = mdio_read(ioaddr, phy_addr, 4);
-		int mii_bmcr = mdio_read(ioaddr, phy_addr, 0);
-		mdio_write(ioaddr, phy_addr, 0, 0x0400);
-		mdio_write(ioaddr, phy_addr, 1, 0x0000);
-		mdio_write(ioaddr, phy_addr, 4, 0x0000);
-		mdio_write(ioaddr, phy_addr, 0, 0x8000);
+		int advertising = mdio_read(dev, phy_addr, MII_ADVERTISE);
+		int mii_bmcr = mdio_read(dev, phy_addr, MII_BMCR);
+		mdio_write(dev, phy_addr, MII_BMCR, 0x0400);
+		mdio_write(dev, phy_addr, MII_BMSR, 0x0000);
+		mdio_write(dev, phy_addr, MII_ADVERTISE, 0x0000);
+		mdio_write(dev, phy_addr, MII_BMCR, 0x8000);
 #ifdef honor_default_port
-		mdio_write(ioaddr, phy_addr, 0, mii_ctrl[dev->default_port & 7]);
+		mdio_write(dev, phy_addr, MII_BMCR, mii_ctrl[dev->default_port & 7]);
 #else
-		mdio_read(ioaddr, phy_addr, 0);
-		mdio_write(ioaddr, phy_addr, 0, mii_bmcr);
-		mdio_write(ioaddr, phy_addr, 4, advertising);
+		mdio_read(dev, phy_addr, MII_BMCR);
+		mdio_write(dev, phy_addr, MII_BMCR, mii_bmcr);
+		mdio_write(dev, phy_addr, MII_ADVERTISE, advertising);
 #endif
 	}
 }
@@ -1965,6 +1974,7 @@
 		return -EFAULT;
 	
         switch (ethcmd) {
+	/* get driver-specific version/etc. info */
 	case ETHTOOL_GDRVINFO: {
 		struct ethtool_drvinfo info = {ETHTOOL_GDRVINFO};
 		strncpy(info.driver, "eepro100", sizeof(info.driver)-1);
@@ -1976,19 +1986,48 @@
 		return 0;
 	}
 	
+	/* get settings */
+	case ETHTOOL_GSET: {
+		struct ethtool_cmd ecmd = { ETHTOOL_GSET };
+		spin_lock_irq(&sp->lock);
+		mii_ethtool_gset(&sp->mii_if, &ecmd);
+		spin_unlock_irq(&sp->lock);
+		if (copy_to_user(useraddr, &ecmd, sizeof(ecmd)))
+			return -EFAULT;
+		return 0;
+	}
+	/* set settings */
+	case ETHTOOL_SSET: {
+		int r;
+		struct ethtool_cmd ecmd;
+		if (copy_from_user(&ecmd, useraddr, sizeof(ecmd)))
+			return -EFAULT;
+		spin_lock_irq(&sp->lock);
+		r = mii_ethtool_sset(&sp->mii_if, &ecmd);
+		spin_unlock_irq(&sp->lock);
+		return r;
+	}
+	/* restart autonegotiation */
+	case ETHTOOL_NWAY_RST: {
+		return mii_nway_restart(&sp->mii_if);
+	}
+	/* get link status */
+	case ETHTOOL_GLINK: {
+		struct ethtool_value edata = {ETHTOOL_GLINK};
+		edata.data = mii_link_ok(&sp->mii_if);
+		if (copy_to_user(useraddr, &edata, sizeof(edata)))
+			return -EFAULT;
+		return 0;
+	}
+
         }
 	
 	return -EOPNOTSUPP;
 }
 
-
-
-
-
 static int speedo_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 {
 	struct speedo_private *sp = (struct speedo_private *)dev->priv;
-	long ioaddr = dev->base_addr;
 	struct mii_ioctl_data *data = (struct mii_ioctl_data *)&rq->ifr_data;
 	int phy = sp->phy[0] & 0x1f;
 	int saved_acpi;
@@ -2007,7 +2046,7 @@
 		   timer routine.  2000/05/09 SAW */
 		saved_acpi = pci_set_power_state(sp->pdev, 0);
 		t = del_timer_sync(&sp->timer);
-		data->val_out = mdio_read(ioaddr, data->phy_id & 0x1f, data->reg_num & 0x1f);
+		data->val_out = mdio_read(dev, data->phy_id & 0x1f, data->reg_num & 0x1f);
 		if (t)
 			add_timer(&sp->timer); /* may be set to the past  --SAW */
 		pci_set_power_state(sp->pdev, saved_acpi);
@@ -2019,7 +2058,7 @@
 			return -EPERM;
 		saved_acpi = pci_set_power_state(sp->pdev, 0);
 		t = del_timer_sync(&sp->timer);
-		mdio_write(ioaddr, data->phy_id, data->reg_num, data->val_in);
+		mdio_write(dev, data->phy_id, data->reg_num, data->val_in);
 		if (t)
 			add_timer(&sp->timer); /* may be set to the past  --SAW */
 		pci_set_power_state(sp->pdev, saved_acpi);
@@ -2091,7 +2130,7 @@
 		   Disable Flow control since we are not ACK-ing any FC interrupts
 		   for now. --Dragan */
 		config_cmd_data[19] = 0x84;
-		config_cmd_data[19] |= sp->full_duplex ? 0x40 : 0;
+		config_cmd_data[19] |= sp->mii_if.full_duplex ? 0x40 : 0;
 		config_cmd_data[21] = (new_rx_mode & 1) ? 0x0D : 0x05;
 		if (sp->phy[0] & 0x8000) {			/* Use the AUI port instead. */
 			config_cmd_data[15] |= 0x80;
diff -urN linux-2.4.20-pre8/drivers/net/epic100.c linux-2.4.20-pre9/drivers/net/epic100.c
--- linux-2.4.20-pre8/drivers/net/epic100.c	Thu Oct  3 18:36:44 2002
+++ linux-2.4.20-pre9/drivers/net/epic100.c	Thu Oct  3 18:37:32 2002
@@ -430,6 +430,8 @@
 	ep->mii.dev = dev;
 	ep->mii.mdio_read = mdio_read;
 	ep->mii.mdio_write = mdio_write;
+	ep->mii.phy_id_mask = 0x1f;
+	ep->mii.reg_num_mask = 0x1f;
 
 	ring_space = pci_alloc_consistent(pdev, TX_TOTAL_SIZE, &ring_dma);
 	if (!ring_space)
@@ -524,7 +526,7 @@
 
 	/* The lower four bits are the media type. */
 	if (duplex) {
-		ep->mii.duplex_lock = ep->mii.full_duplex = 1;
+		ep->mii.force_media = ep->mii.full_duplex = 1;
 		printk(KERN_INFO DRV_NAME "(%s):  Forced full duplex operation requested.\n",
 		       pdev->slot_name);
 	}
@@ -855,7 +857,7 @@
 	int negotiated = mii_lpa & ep->mii.advertising;
 	int duplex = (negotiated & 0x0100) || (negotiated & 0x01C0) == 0x0040;
 
-	if (ep->mii.duplex_lock)
+	if (ep->mii.force_media)
 		return;
 	if (mii_lpa == 0xffff)		/* Bogus read */
 		return;
@@ -1427,66 +1429,34 @@
 
 static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 {
-	struct epic_private *ep = dev->priv;
+	struct epic_private *np = dev->priv;
 	long ioaddr = dev->base_addr;
 	struct mii_ioctl_data *data = (struct mii_ioctl_data *)&rq->ifr_data;
+	int rc;
 
-	switch(cmd) {
-	case SIOCETHTOOL:
-		return netdev_ethtool_ioctl(dev, (void *) rq->ifr_data);
-
-	case SIOCGMIIPHY:		/* Get address of MII PHY in use. */
-	case SIOCDEVPRIVATE:		/* for binary compat, remove in 2.5 */
-		data->phy_id = ep->phys[0] & 0x1f;
-		/* Fall Through */
-
-	case SIOCGMIIREG:		/* Read MII PHY register. */
-	case SIOCDEVPRIVATE+1:		/* for binary compat, remove in 2.5 */
-		if (! netif_running(dev)) {
-			outl(0x0200, ioaddr + GENCTL);
-			outl((inl(ioaddr + NVCTL) & ~0x003C) | 0x4800, ioaddr + NVCTL);
-		}
-		data->val_out = mdio_read(dev, data->phy_id & 0x1f, data->reg_num & 0x1f);
-#if 0					/* Just leave on if the ioctl() is ever used. */
-		if (! netif_running(dev)) {
-			outl(0x0008, ioaddr + GENCTL);
-			outl((inl(ioaddr + NVCTL) & ~0x483C) | 0x0000, ioaddr + NVCTL);
-		}
-#endif
-		return 0;
+	/* power-up, if interface is down */
+	if (! netif_running(dev)) {
+		outl(0x0200, ioaddr + GENCTL);
+		outl((inl(ioaddr + NVCTL) & ~0x003C) | 0x4800, ioaddr + NVCTL);
+	}
 
-	case SIOCSMIIREG:		/* Write MII PHY register. */
-	case SIOCDEVPRIVATE+2:		/* for binary compat, remove in 2.5 */
-		if (!capable(CAP_NET_ADMIN))
-			return -EPERM;
-		if (! netif_running(dev)) {
-			outl(0x0200, ioaddr + GENCTL);
-			outl((inl(ioaddr + NVCTL) & ~0x003C) | 0x4800, ioaddr + NVCTL);
-		}
-		if (data->phy_id == ep->phys[0]) {
-			u16 value = data->val_in;
-			switch (data->reg_num) {
-			case 0:
-				/* Check for autonegotiation on or reset. */
-				ep->mii.duplex_lock = (value & 0x9000) ? 0 : 1;
-				if (ep->mii.duplex_lock)
-					ep->mii.full_duplex = (value & 0x0100) ? 1 : 0;
-				break;
-			case 4: ep->mii.advertising = value; break;
-			}
-			/* Perhaps check_duplex(dev), depending on chip semantics. */
-		}
-		mdio_write(dev, data->phy_id & 0x1f, data->reg_num & 0x1f, data->val_in);
-#if 0					/* Leave on if the ioctl() is used. */
-		if (! netif_running(dev)) {
-			outl(0x0008, ioaddr + GENCTL);
-			outl((inl(ioaddr + NVCTL) & ~0x483C) | 0x0000, ioaddr + NVCTL);
-		}
-#endif
-		return 0;
-	default:
-		return -EOPNOTSUPP;
+	/* ethtool commands */
+	if (cmd == SIOCETHTOOL)
+		rc = netdev_ethtool_ioctl(dev, (void *) rq->ifr_data);
+
+	/* all other ioctls (the SIOC[GS]MIIxxx ioctls) */
+	else {
+		spin_lock_irq(&np->lock);
+		rc = generic_mii_ioctl(&np->mii, data, cmd, NULL);
+		spin_unlock_irq(&np->lock);
+	}
+
+	/* power-down, if interface is down */
+	if (! netif_running(dev)) {
+		outl(0x0008, ioaddr + GENCTL);
+		outl((inl(ioaddr + NVCTL) & ~0x483C) | 0x0000, ioaddr + NVCTL);
 	}
+	return rc;
 }
 
 
diff -urN linux-2.4.20-pre8/drivers/net/fealnx.c linux-2.4.20-pre9/drivers/net/fealnx.c
--- linux-2.4.20-pre8/drivers/net/fealnx.c	Thu Oct  3 18:36:44 2002
+++ linux-2.4.20-pre9/drivers/net/fealnx.c	Thu Oct  3 18:37:32 2002
@@ -559,6 +559,8 @@
 	np->mii.dev = dev;
 	np->mii.mdio_read = mdio_read;
 	np->mii.mdio_write = mdio_write;
+	np->mii.phy_id_mask = 0x1f;
+	np->mii.reg_num_mask = 0x1f;
 
 	ring_space = pci_alloc_consistent(pdev, RX_TOTAL_SIZE, &ring_dma);
 	if (!ring_space) {
@@ -654,7 +656,7 @@
 			mdio_write(dev, np->phys[0], MII_ADVERTISE, ADVERTISE_FULL);
 		else
 			writel(ADVERTISE_FULL, dev->base_addr + ANARANLPAR);
-		np->mii.duplex_lock = 1;
+		np->mii.force_media = 1;
 	}
 
 	/* The chip-specific entries in the device structure. */
@@ -956,7 +958,7 @@
 // 89/9/1 modify,
 //   np->crvalue = 0x00e40001;    /* tx store and forward, tx/rx enable */
 	np->crvalue |= 0x00e40001;	/* tx store and forward, tx/rx enable */
-	np->mii.full_duplex = np->mii.duplex_lock;
+	np->mii.full_duplex = np->mii.force_media;
 	getlinkstatus(dev);
 	if (np->linkok)
 		getlinktype(dev);
@@ -1833,31 +1835,23 @@
 
 static int mii_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 {
+	struct netdev_private *np = dev->priv;
 	struct mii_ioctl_data *data = (struct mii_ioctl_data *) & rq->ifr_data;
+	int rc;
 
-	switch (cmd) {
-	case SIOCETHTOOL:
-		return netdev_ethtool_ioctl(dev, (void *) rq->ifr_data);
-
-	case SIOCGMIIPHY:		/* Get address of MII PHY in use. */
-	case SIOCDEVPRIVATE:		/* for binary compat, remove in 2.5 */
-		data->phy_id = ((struct netdev_private *) dev->priv)->phys[0] & 0x1f;
-		/* Fall Through */
-
-	case SIOCGMIIREG:		/* Read MII PHY register. */
-	case SIOCDEVPRIVATE+1:		/* for binary compat, remove in 2.5 */
-		data->val_out = mdio_read(dev, data->phy_id & 0x1f, data->reg_num & 0x1f);
-		return 0;
+	if (!netif_running(dev))
+		return -EINVAL;
 
-	case SIOCSMIIREG:		/* Write MII PHY register. */
-	case SIOCDEVPRIVATE+2:		/* for binary compat, remove in 2.5 */
-		if (!capable(CAP_NET_ADMIN))
-			return -EPERM;
-		mdio_write(dev, data->phy_id & 0x1f, data->reg_num & 0x1f, data->val_in);
-		return 0;
-	default:
-		return -EOPNOTSUPP;
+	if (cmd == SIOCETHTOOL)
+		rc = netdev_ethtool_ioctl(dev, (void *) rq->ifr_data);
+
+	else {
+		spin_lock_irq(&np->lock);
+		rc = generic_mii_ioctl(&np->mii, data, cmd, NULL);
+		spin_unlock_irq(&np->lock);
 	}
+
+	return rc;
 }
 
 
diff -urN linux-2.4.20-pre8/drivers/net/irda/irtty.c linux-2.4.20-pre9/drivers/net/irda/irtty.c
--- linux-2.4.20-pre8/drivers/net/irda/irtty.c	Thu Oct  3 18:36:44 2002
+++ linux-2.4.20-pre9/drivers/net/irda/irtty.c	Thu Oct  3 18:37:33 2002
@@ -46,6 +46,19 @@
 
 static int qos_mtt_bits = 0x03;      /* 5 ms or more */
 
+/* To workaround some of the difference in the serial driver over various
+ * arch, some people have introduced TIOCM_MODEM_BITS.
+ * Unfortunately, this is not yet defined on all architectures, so
+ * we make sure the code is still usable. - Jean II */
+#ifndef TIOCM_MODEM_BITS
+#warning "Please define TIOCM_MODEM_BITS in termios.h !"
+#ifdef TIOCM_OUT2
+#define TIOCM_MODEM_BITS	TIOCM_OUT2	/* Most architectures */
+#else
+#define TIOCM_MODEM_BITS	0		/* Not defined for ARM */
+#endif
+#endif
+
 /* Network device fuction prototypes */
 static int  irtty_hard_xmit(struct sk_buff *skb, struct net_device *dev);
 static int  irtty_net_init(struct net_device *dev);
diff -urN linux-2.4.20-pre8/drivers/net/mii.c linux-2.4.20-pre9/drivers/net/mii.c
--- linux-2.4.20-pre8/drivers/net/mii.c	Fri Aug  2 17:39:44 2002
+++ linux-2.4.20-pre9/drivers/net/mii.c	Thu Oct  3 18:37:33 2002
@@ -3,7 +3,27 @@
 	mii.c: MII interface library
 
 	Maintained by Jeff Garzik <jgarzik@mandrakesoft.com>
-	Copyright 2001 Jeff Garzik
+	Copyright 2001,2002 Jeff Garzik
+
+	Various code came from myson803.c and other files by
+	Donald Becker.  Copyright:
+
+		Written 1998-2002 by Donald Becker.
+
+		This software may be used and distributed according
+		to the terms of the GNU General Public License (GPL),
+		incorporated herein by reference.  Drivers based on
+		or derived from this code fall under the GPL and must
+		retain the authorship, copyright and license notice.
+		This file is not a complete program and may only be
+		used when the entire operating system is licensed
+		under the GPL.
+
+		The author may be reached as becker@scyld.com, or C/O
+		Scyld Computing Corporation
+		410 Severn Ave., Suite 210
+		Annapolis MD 21403
+
 
  */
 
@@ -122,7 +142,7 @@
 		bmcr |= (BMCR_ANENABLE | BMCR_ANRESTART);
 		mii->mdio_write(dev, mii->phy_id, MII_BMCR, bmcr);
 
-		mii->duplex_lock = 0;
+		mii->force_media = 0;
 	} else {
 		u32 bmcr, tmp;
 
@@ -130,16 +150,16 @@
 		bmcr = mii->mdio_read(dev, mii->phy_id, MII_BMCR);
 		tmp = bmcr & ~(BMCR_ANENABLE | BMCR_SPEED100 | BMCR_FULLDPLX);
 		if (ecmd->speed == SPEED_100)
-			bmcr |= BMCR_SPEED100;
+			tmp |= BMCR_SPEED100;
 		if (ecmd->duplex == DUPLEX_FULL) {
-			bmcr |= BMCR_FULLDPLX;
+			tmp |= BMCR_FULLDPLX;
 			mii->full_duplex = 1;
 		} else
 			mii->full_duplex = 0;
 		if (bmcr != tmp)
-			mii->mdio_write(dev, mii->phy_id, MII_BMCR, bmcr);
+			mii->mdio_write(dev, mii->phy_id, MII_BMCR, tmp);
 
-		mii->duplex_lock = 1;
+		mii->force_media = 1;
 	}
 	return 0;
 }
@@ -170,6 +190,152 @@
 	return r;
 }
 
+void mii_check_link (struct mii_if_info *mii)
+{
+	if (mii_link_ok(mii))
+		netif_carrier_on(mii->dev);
+	else
+		netif_carrier_off(mii->dev);
+}
+
+unsigned int mii_check_media (struct mii_if_info *mii,
+			      unsigned int ok_to_print,
+			      unsigned int init_media)
+{
+	unsigned int old_carrier, new_carrier;
+	int advertise, lpa, media, duplex;
+
+	/* if forced media, go no further */
+	if (mii->force_media)
+		return 0; /* duplex did not change */
+
+	/* check current and old link status */
+	old_carrier = netif_carrier_ok(mii->dev) ? 1 : 0;
+	new_carrier = (unsigned int) mii_link_ok(mii);
+
+	/* if carrier state did not change, this is a "bounce",
+	 * just exit as everything is already set correctly
+	 */
+	if ((!init_media) && (old_carrier == new_carrier))
+		return 0; /* duplex did not change */
+
+	/* no carrier, nothing much to do */
+	if (!new_carrier) {
+		netif_carrier_off(mii->dev);
+		if (ok_to_print)
+			printk(KERN_INFO "%s: link down\n", mii->dev->name);
+		return 0; /* duplex did not change */
+	}
+
+	/*
+	 * we have carrier, see who's on the other end
+	 */
+	netif_carrier_on(mii->dev);
+
+	/* get MII advertise and LPA values */
+	if ((!init_media) && (mii->advertising))
+		advertise = mii->advertising;
+	else {
+		advertise = mii->mdio_read(mii->dev, mii->phy_id, MII_ADVERTISE);
+		mii->advertising = advertise;
+	}
+	lpa = mii->mdio_read(mii->dev, mii->phy_id, MII_LPA);
+
+	/* figure out media and duplex from advertise and LPA values */
+	media = mii_nway_result(lpa & advertise);
+	duplex = (media & (ADVERTISE_100FULL | ADVERTISE_10FULL)) ? 1 : 0;
+
+	if (ok_to_print)
+		printk(KERN_INFO "%s: link up, %sMbps, %s-duplex, lpa 0x%04X\n",
+		       mii->dev->name,
+		       media & (ADVERTISE_100FULL | ADVERTISE_100HALF) ?
+		       		"100" : "10",
+		       duplex ? "full" : "half",
+		       lpa);
+
+	if ((init_media) || (mii->full_duplex != duplex)) {
+		mii->full_duplex = duplex;
+		return 1; /* duplex changed */
+	}
+
+	return 0; /* duplex did not change */
+}
+
+int generic_mii_ioctl(struct mii_if_info *mii_if,
+		      struct mii_ioctl_data *mii_data, int cmd,
+		      unsigned int *duplex_chg_out)
+{
+	int rc = 0;
+	unsigned int duplex_changed = 0;
+
+	if (duplex_chg_out)
+		*duplex_chg_out = 0;
+
+	mii_data->phy_id &= mii_if->phy_id_mask;
+	mii_data->reg_num &= mii_if->reg_num_mask;
+
+	switch(cmd) {
+	case SIOCDEVPRIVATE:	/* binary compat, remove in 2.5 */
+	case SIOCGMIIPHY:
+		mii_data->phy_id = mii_if->phy_id;
+		/* fall through */
+
+	case SIOCDEVPRIVATE + 1:/* binary compat, remove in 2.5 */
+	case SIOCGMIIREG:
+		mii_data->val_out =
+			mii_if->mdio_read(mii_if->dev, mii_data->phy_id,
+					  mii_data->reg_num);
+		break;
+
+	case SIOCDEVPRIVATE + 2:/* binary compat, remove in 2.5 */
+	case SIOCSMIIREG: {
+		u16 val = mii_data->val_in;
+
+		if (!capable(CAP_NET_ADMIN))
+			return -EPERM;
+
+		if (mii_data->phy_id == mii_if->phy_id) {
+			switch(mii_data->reg_num) {
+			case MII_BMCR: {
+				unsigned int new_duplex = 0;
+				if (val & (BMCR_RESET|BMCR_ANENABLE))
+					mii_if->force_media = 1;
+				else
+					mii_if->force_media = 0;
+				if (mii_if->force_media &&
+				    (val & BMCR_FULLDPLX))
+					new_duplex = 1;
+				if (mii_if->full_duplex != new_duplex) {
+					duplex_changed = 1;
+					mii_if->full_duplex = new_duplex;
+				}
+				break;
+			}
+			case MII_ADVERTISE:
+				mii_if->advertising = val;
+				break;
+			default:
+				/* do nothing */
+				break;
+			}
+		}
+
+		mii_if->mdio_write(mii_if->dev, mii_data->phy_id,
+				   mii_data->reg_num, val);
+		break;
+	}
+
+	default:
+		rc = -EOPNOTSUPP;
+		break;
+	}
+
+	if ((rc == 0) && (duplex_chg_out) && (duplex_changed))
+		*duplex_chg_out = 1;
+
+	return rc;
+}
+
 MODULE_AUTHOR ("Jeff Garzik <jgarzik@mandrakesoft.com>");
 MODULE_DESCRIPTION ("MII hardware support library");
 MODULE_LICENSE("GPL");
@@ -178,3 +344,7 @@
 EXPORT_SYMBOL(mii_nway_restart);
 EXPORT_SYMBOL(mii_ethtool_gset);
 EXPORT_SYMBOL(mii_ethtool_sset);
+EXPORT_SYMBOL(mii_check_link);
+EXPORT_SYMBOL(mii_check_media);
+EXPORT_SYMBOL(generic_mii_ioctl);
+
diff -urN linux-2.4.20-pre8/drivers/net/ppp_generic.c linux-2.4.20-pre9/drivers/net/ppp_generic.c
--- linux-2.4.20-pre8/drivers/net/ppp_generic.c	Thu Oct  3 18:36:44 2002
+++ linux-2.4.20-pre9/drivers/net/ppp_generic.c	Thu Oct  3 18:37:36 2002
@@ -1399,7 +1399,7 @@
 	if (skb->len > 0)
 		/* note: a 0-length skb is used as an error indication */
 		++ppp->stats.rx_length_errors;
-err:
+
 	kfree_skb(skb);
 	ppp_receive_error(ppp);
 }
diff -urN linux-2.4.20-pre8/drivers/net/sb1000.c linux-2.4.20-pre9/drivers/net/sb1000.c
--- linux-2.4.20-pre8/drivers/net/sb1000.c	Fri Aug  2 17:39:44 2002
+++ linux-2.4.20-pre9/drivers/net/sb1000.c	Thu Oct  3 18:37:36 2002
@@ -276,7 +276,7 @@
  * SB1000 hardware routines to be used during open/configuration phases
  */
 
-const int TimeOutJiffies = (int)(8.75 * HZ);
+const int TimeOutJiffies = (875 * HZ) / 100;
 
 static inline void nicedelay(unsigned long usecs)
 {
@@ -299,7 +299,7 @@
 		current->state = TASK_INTERRUPTIBLE;
 		schedule_timeout(0);
 		a = inb(ioaddr[0] + 7);
-		if (jiffies >= timeout) {
+		if (time_after_eq(jiffies, timeout)) {
 			printk(KERN_WARNING "%s: card_wait_for_busy_clear timeout\n",
 				name);
 			return -ETIME;
@@ -323,7 +323,7 @@
 		current->state = TASK_INTERRUPTIBLE;
 		schedule_timeout(0);
 		a = inb(ioaddr[1] + 6);
-		if (jiffies >= timeout) {
+		if (time_after_eq(jiffies, timeout)) {
 			printk(KERN_WARNING "%s: card_wait_for_ready timeout\n",
 				name);
 			return -ETIME;
@@ -397,7 +397,7 @@
 
 	timeout = jiffies + Sb1000TimeOutJiffies;
 	while (inb(ioaddr[1] + 6) & 0x80) {
-		if (jiffies >= timeout) {
+		if (time_after_eq(jiffies, timeout)) {
 			printk(KERN_WARNING "%s: sb1000_wait_for_ready timeout\n",
 				name);
 			return -ETIME;
diff -urN linux-2.4.20-pre8/drivers/net/sis900.c linux-2.4.20-pre9/drivers/net/sis900.c
--- linux-2.4.20-pre8/drivers/net/sis900.c	Fri Aug  2 17:39:44 2002
+++ linux-2.4.20-pre9/drivers/net/sis900.c	Thu Oct  3 18:37:37 2002
@@ -1,6 +1,6 @@
 /* sis900.c: A SiS 900/7016 PCI Fast Ethernet driver for Linux.
    Copyright 1999 Silicon Integrated System Corporation 
-   Revision:	1.08.04	Apr. 25 2002
+   Revision:	1.08.06 Sep. 24 2002
    
    Modified from the driver which is originally written by Donald Becker.
    
@@ -18,6 +18,8 @@
    preliminary Rev. 1.0 Jan. 18, 1998
    http://www.sis.com.tw/support/databook.htm
 
+   Rev 1.08.06 Sep. 24 2002 Mufasa Yang bug fix for Tx timeout & add SiS963 support
+   Rev 1.08.05 Jun. 6 2002 Mufasa Yang bug fix for read_eeprom & Tx descriptor over-boundary 
    Rev 1.08.04 Apr. 25 2002 Mufasa Yang <mufasa@sis.com.tw> added SiS962 support
    Rev 1.08.03 Feb. 1 2002 Matt Domsch <Matt_Domsch@dell.com> update to use library crc32 function
    Rev 1.08.02 Nov. 30 2001 Hui-Fen Hsu workaround for EDB & bug fix for dhcp problem
@@ -72,7 +74,7 @@
 #include "sis900.h"
 
 #define SIS900_MODULE_NAME "sis900"
-#define SIS900_DRV_VERSION "v1.08.04 4/25/2002"
+#define SIS900_DRV_VERSION "v1.08.06 9/24/2002"
 
 static char version[] __devinitdata =
 KERN_INFO "sis900.c: " SIS900_DRV_VERSION "\n";
@@ -309,31 +311,38 @@
 }
 
 /**
- *	sis962_get_mac_addr: - Get MAC address for SiS962 model
+ *	sis96x_get_mac_addr: - Get MAC address for SiS962 or SiS963 model
  *	@pci_dev: the sis900 pci device
  *	@net_dev: the net device to get address for 
  *
- *	SiS962 model, use EEPROM to store MAC address. And EEPROM is shared by
+ *	SiS962 or SiS963 model, use EEPROM to store MAC address. And EEPROM 
+ *	is shared by
  *	LAN and 1394. When access EEPROM, send EEREQ signal to hardware first 
  *	and wait for EEGNT. If EEGNT is ON, EEPROM is permitted to be access 
  *	by LAN, otherwise is not. After MAC address is read from EEPROM, send
  *	EEDONE signal to refuse EEPROM access by LAN. 
+ *	The EEPROM map of SiS962 or SiS963 is different to SiS900. 
+ *	The signature field in SiS962 or SiS963 spec is meaningless. 
  *	MAC address is read into @net_dev->dev_addr.
  */
 
-static int __devinit sis962_get_mac_addr(struct pci_dev * pci_dev, struct net_device *net_dev)
+static int __devinit sis96x_get_mac_addr(struct pci_dev * pci_dev, struct net_device *net_dev)
 {
 	long ioaddr = net_dev->base_addr;
 	long ee_addr = ioaddr + mear;
 	u32 waittime = 0;
-	int ret = 0;
+	int i;
 	
 	outl(EEREQ, ee_addr);
 	while(waittime < 2000) {
 		if(inl(ee_addr) & EEGNT) {
-			ret = sis900_get_mac_addr(pci_dev, net_dev);
+
+			/* get MAC address from EEPROM */
+			for (i = 0; i < 3; i++)
+			        ((u16 *)(net_dev->dev_addr))[i] = read_eeprom(ioaddr, i+EEPROMMACAddr);
+
 			outl(EEDONE, ee_addr);
-			return(ret);
+			return 1;
 		} else {
 			udelay(1);	
 			waittime ++;
@@ -443,8 +452,8 @@
 		ret = sis630e_get_mac_addr(pci_dev, net_dev);
 	else if ((revision > 0x81) && (revision <= 0x90) )
 		ret = sis635_get_mac_addr(pci_dev, net_dev);
-	else if (revision == SIS962_900_REV)
-		ret = sis962_get_mac_addr(pci_dev, net_dev);
+	else if (revision == SIS96x_900_REV)
+		ret = sis96x_get_mac_addr(pci_dev, net_dev);
 	else
 		ret = sis900_get_mac_addr(pci_dev, net_dev);
 
@@ -702,7 +711,7 @@
 
 	outl(0, ee_addr);
 	eeprom_delay();
-	outl(EECLK, ee_addr);
+	outl(EECS, ee_addr);
 	eeprom_delay();
 
 	/* Shift the read command (9) bits out. */
@@ -713,7 +722,7 @@
 		outl(dataval | EECLK, ee_addr);
 		eeprom_delay();
 	}
-	outb(EECS, ee_addr);
+	outl(EECS, ee_addr);
 	eeprom_delay();
 
 	/* read the 16-bits data in */
@@ -729,7 +738,6 @@
 	/* Terminate the EEPROM access. */
 	outl(0, ee_addr);
 	eeprom_delay();
-	outl(EECLK, ee_addr);
 
 	return (retval);
 }
@@ -1432,8 +1440,8 @@
 
 	net_dev->trans_start = jiffies;
 
-	/* FIXME: Should we restart the transmission thread here  ?? */
-	outl(TxENA | inl(ioaddr + cr), ioaddr + cr);
+	/* load Transmit Descriptor Register */
+	outl(sis_priv->tx_ring_dma, ioaddr + txdp);
 
 	/* Enable all known interrupts by setting the interrupt mask. */
 	outl((RxSOVR|RxORN|RxERR|RxOK|TxURN|TxERR|TxIDLE), ioaddr + imr);
@@ -1457,6 +1465,8 @@
 	long ioaddr = net_dev->base_addr;
 	unsigned int  entry;
 	unsigned long flags;
+	unsigned int  index_cur_tx, index_dirty_tx;
+	unsigned int  count_dirty_tx;
 
 	/* Don't transmit data before the complete of auto-negotiation */
 	if(!sis_priv->autong_complete){
@@ -1476,7 +1486,18 @@
 	sis_priv->tx_ring[entry].cmdsts = (OWN | skb->len);
 	outl(TxENA | inl(ioaddr + cr), ioaddr + cr);
 
-	if (++sis_priv->cur_tx - sis_priv->dirty_tx < NUM_TX_DESC) {
+	sis_priv->cur_tx ++;
+	index_cur_tx = sis_priv->cur_tx;
+	index_dirty_tx = sis_priv->dirty_tx;
+
+	for (count_dirty_tx = 0; index_cur_tx != index_dirty_tx; index_dirty_tx++)
+		count_dirty_tx ++;
+
+	if (index_cur_tx == index_dirty_tx) {
+		/* dirty_tx is met in the cycle of cur_tx, buffer full */
+		sis_priv->tx_full = 1;
+		netif_stop_queue(net_dev);
+	} else if (count_dirty_tx < NUM_TX_DESC) { 
 		/* Typical path, tell upper layer that more transmission is possible */
 		netif_start_queue(net_dev);
 	} else {
@@ -1709,7 +1730,7 @@
 {
 	struct sis900_private *sis_priv = net_dev->priv;
 
-	for (; sis_priv->dirty_tx < sis_priv->cur_tx; sis_priv->dirty_tx++) {
+	for (; sis_priv->dirty_tx != sis_priv->cur_tx; sis_priv->dirty_tx++) {
 		struct sk_buff *skb;
 		unsigned int entry;
 		u32 tx_status;
diff -urN linux-2.4.20-pre8/drivers/net/sis900.h linux-2.4.20-pre9/drivers/net/sis900.h
--- linux-2.4.20-pre8/drivers/net/sis900.h	Fri Aug  2 17:39:44 2002
+++ linux-2.4.20-pre9/drivers/net/sis900.h	Thu Oct  3 18:37:37 2002
@@ -135,8 +135,8 @@
 	EEaddrMask = 0x013F, EEcmdShift = 16
 };
 
-/* For SiS962, request the eeprom software access */
-enum sis962_eeprom_command {
+/* For SiS962 or SiS963, request the eeprom software access */
+enum sis96x_eeprom_command {
 	EEREQ = 0x00000400, EEDONE = 0x00000200, EEGNT = 0x00000100
 };
 
@@ -245,7 +245,7 @@
 	SIS630A_900_REV = 0x80,		SIS630E_900_REV = 0x81,
 	SIS630S_900_REV = 0x82,		SIS630EA1_900_REV = 0x83,
 	SIS630ET_900_REV = 0x84,	SIS635A_900_REV = 0x90,
-	SIS962_900_REV = 0X91,		SIS900B_900_REV = 0x03
+	SIS96x_900_REV = 0X91,		SIS900B_900_REV = 0x03
 };
 
 enum sis630_revision_id {
diff -urN linux-2.4.20-pre8/drivers/net/sundance.c linux-2.4.20-pre9/drivers/net/sundance.c
--- linux-2.4.20-pre8/drivers/net/sundance.c	Thu Oct  3 18:36:44 2002
+++ linux-2.4.20-pre9/drivers/net/sundance.c	Thu Oct  3 18:37:37 2002
@@ -62,11 +62,15 @@
 	- Add CONFIG_SUNDANCE_MMIO config option (jgarzik)
 	- Better rx buf size calculation (Donald Becker)
 
+	Version LK1.05 (D-Link):
+	- fix DFE-580TX packet drop issue
+	- fix reset_tx logic
+
 */
 
 #define DRV_NAME	"sundance"
-#define DRV_VERSION	"1.01+LK1.04d"
-#define DRV_RELDATE	"19-Sep-2002"
+#define DRV_VERSION	"1.01+LK1.05"
+#define DRV_RELDATE	"28-Sep-2002"
 
 
 /* The user-configurable values.
@@ -146,18 +150,21 @@
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
 #include <linux/init.h>
-#include <linux/ethtool.h>
-#include <linux/mii.h>
 #include <asm/uaccess.h>
 #include <asm/processor.h>		/* Processor type for cache alignment. */
 #include <asm/bitops.h>
 #include <asm/io.h>
 #include <linux/delay.h>
 #include <linux/spinlock.h>
-#ifndef _LOCAL_CRC32
+#ifndef _COMPAT_WITH_OLD_KERNEL
 #include <linux/crc32.h>
+#include <linux/ethtool.h>
+#include <linux/mii.h>
 #else
 #include "crc32.h"
+#include "ethtool.h"
+#include "mii.h"
+#include "compat.h"
 #endif
 
 /* These identify the driver base version and may not be removed. */
@@ -319,6 +326,8 @@
 	TxDMAPollPeriod = 0x0a,
 	RxDMAStatus = 0x0c,
 	RxListPtr = 0x10,
+	DebugCtrl0 = 0x1a,
+	DebugCtrl1 = 0x1c,
 	RxDMABurstThresh = 0x14,
 	RxDMAUrgentThresh = 0x15,
 	RxDMAPollPeriod = 0x16,
@@ -477,7 +486,7 @@
 static void tx_timeout(struct net_device *dev);
 static void init_ring(struct net_device *dev);
 static int  start_tx(struct sk_buff *skb, struct net_device *dev);
-static int reset_tx (struct net_device *dev, int irq);
+static int reset_tx (struct net_device *dev);
 static void intr_handler(int irq, void *dev_instance, struct pt_regs *regs);
 static void rx_poll(unsigned long data);
 static void refill_rx (struct net_device *dev);
@@ -564,6 +573,8 @@
 	np->mii_if.dev = dev;
 	np->mii_if.mdio_read = mdio_read;
 	np->mii_if.mdio_write = mdio_write;
+	np->mii_if.phy_id_mask = 0x1f;
+	np->mii_if.reg_num_mask = 0x1f;
 
 	/* The chip-specific entries in the device structure. */
 	dev->open = &netdev_open;
@@ -855,6 +866,8 @@
 	/* Set the chip to poll every N*320nsec. */
 	writeb(100, ioaddr + RxDMAPollPeriod);
 	writeb(127, ioaddr + TxDMAPollPeriod);
+	/* Fix DFE-580TX packet drop issue */
+	writeb(0x01, ioaddr + DebugCtrl1);
 	netif_start_queue(dev);
 
 	writew(StatsEnable | RxEnable | TxEnable, ioaddr + MACCtrl1);
@@ -931,6 +944,7 @@
 	long ioaddr = dev->base_addr;
 	long flag;
 
+	writew(0, ioaddr + IntrEnable);
 	printk(KERN_WARNING "%s: Transmit timed out, TxStatus %2.2x "
 		   "TxFrameId %2.2x,"
 		   " resetting...\n", dev->name, readb(ioaddr + TxStatus),
@@ -945,9 +959,11 @@
 		for (i = 0; i < TX_RING_SIZE; i++)
 			printk(" %8.8x", np->tx_ring[i].status);
 		printk("\n");
+		printk(KERN_DEBUG "cur_tx=%d dirty_tx=%d\n", np->cur_tx, np->dirty_tx);
+		printk(KERN_DEBUG "cur_rx=%d dirty_rx=%d\n", np->cur_rx, np->dirty_rx);
 	}
 	spin_lock_irqsave(&np->lock, flag);
-	reset_tx(dev, 0);
+	reset_tx(dev);
 	spin_unlock_irqrestore(&np->lock, flag);
 
 	/* Perhaps we should reinitialize the hardware here. */
@@ -959,7 +975,6 @@
 
 	dev->trans_start = jiffies;
 	np->stats.tx_errors++;
-
 	if (!netif_queue_stopped(dev))
 		netif_wake_queue(dev);
 }
@@ -1064,15 +1079,18 @@
 		writel (1000, ioaddr + DownCounter);
 	return 0;
 }
+/* Reset hardware tx and reset TxListPtr to TxFrameId */
 static int
-reset_tx (struct net_device *dev, int irq)
+reset_tx (struct net_device *dev)
 {
 	struct netdev_private *np = (struct netdev_private*) dev->priv;
 	long ioaddr = dev->base_addr;
+	struct sk_buff *skb;
 	int i;
-	int frame_id;
-
-	frame_id = readb(ioaddr + TxFrameId);
+	int irq = in_interrupt();
+	
+	/* reset tx logic */
+	writel (0, dev->base_addr + TxListPtr);
 	writew (TxReset | DMAReset | FIFOReset | NetworkReset,
 			ioaddr + ASICCtrl + 2);
 	for (i=50; i > 0; i--) {
@@ -1080,25 +1098,22 @@
 			break;
 		mdelay(1);
 	}
-	for (; np->cur_tx - np->dirty_tx > 0; np->dirty_tx++) {
-		int entry = np->dirty_tx % TX_RING_SIZE;
-		struct sk_buff *skb;
-		if (!(np->tx_ring[entry].status & 0x00010000))
-			break;
-		skb = np->tx_skbuff[entry];
-		/* Free the original skb. */
-		pci_unmap_single(np->pci_dev,
-			np->tx_ring[entry].frag[0].addr,
-			skb->len, PCI_DMA_TODEVICE);
-		if (irq)
-			dev_kfree_skb_irq (np->tx_skbuff[entry]);
-		else
-			dev_kfree_skb (np->tx_skbuff[entry]);
-
-		np->tx_skbuff[entry] = 0;
+	/* free all tx skbuff */
+	for (i = 0; i < TX_RING_SIZE; i++) {
+		skb = np->tx_skbuff[i];
+		if (skb) {
+			pci_unmap_single(np->pci_dev, 
+				np->tx_ring[i].frag[0].addr, skb->len,
+				PCI_DMA_TODEVICE);
+			if (irq)
+				dev_kfree_skb_irq (skb);
+			else
+				dev_kfree_skb (skb);
+			np->tx_skbuff[i] = 0;
+			np->stats.tx_dropped++;
+		}
 	}
-	writel (np->tx_ring_dma + frame_id * sizeof(*np->tx_ring),
-			dev->base_addr + TxListPtr);
+	np->cur_tx = np->dirty_tx = 0;
 	return 0;
 }
 
@@ -1110,6 +1125,7 @@
 	struct netdev_private *np;
 	long ioaddr;
 	int boguscnt = max_interrupt_work;
+	int hw_frame_id;
 
 	ioaddr = dev->base_addr;
 	np = dev->priv;
@@ -1153,7 +1169,7 @@
 					if (tx_status & 0x10) {	/* Reset the Tx. */
 						np->stats.tx_fifo_errors++;
 						spin_lock(&np->lock);
-						reset_tx(dev, 1);
+						reset_tx(dev);
 						spin_unlock(&np->lock);
 					}
 					if (tx_status & 0x1e)	/* Restart the Tx. */
@@ -1168,10 +1184,14 @@
 			}
 		}
 		spin_lock(&np->lock);
+		hw_frame_id = readb(ioaddr + TxFrameId);
 		for (; np->cur_tx - np->dirty_tx > 0; np->dirty_tx++) {
 			int entry = np->dirty_tx % TX_RING_SIZE;
 			struct sk_buff *skb;
-			if (!(np->tx_ring[entry].status & 0x00010000))
+			int sw_frame_id;
+			sw_frame_id = (np->tx_ring[entry].status >> 2) & 0xff;
+			
+			if (sw_frame_id == hw_frame_id)
 				break;
 			skb = np->tx_skbuff[entry];
 			/* Free the original skb. */
@@ -1532,27 +1552,23 @@
 
 static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 {
-	struct mii_ioctl_data *data = (struct mii_ioctl_data *)&rq->ifr_data;
+	struct netdev_private *np = dev->priv;
+	struct mii_ioctl_data *data = (struct mii_ioctl_data *) & rq->ifr_data;
+	int rc;
 
-	switch(cmd) {
-	case SIOCETHTOOL:
-		return netdev_ethtool_ioctl(dev, (void *) rq->ifr_data);
-	case SIOCGMIIPHY:		/* Get address of MII PHY in use. */
-		data->phy_id = ((struct netdev_private *)dev->priv)->phys[0] & 0x1f;
-		/* Fall Through */
-
-	case SIOCGMIIREG:		/* Read MII PHY register. */
-		data->val_out = mdio_read(dev, data->phy_id & 0x1f, data->reg_num & 0x1f);
-		return 0;
-
-	case SIOCSMIIREG:		/* Write MII PHY register. */
-		if (!capable(CAP_NET_ADMIN))
-			return -EPERM;
-		mdio_write(dev, data->phy_id & 0x1f, data->reg_num & 0x1f, data->val_in);
-		return 0;
-	default:
-		return -EOPNOTSUPP;
+	if (!netif_running(dev))
+		return -EINVAL;
+
+	if (cmd == SIOCETHTOOL)
+		rc = netdev_ethtool_ioctl(dev, (void *) rq->ifr_data);
+
+	else {
+		spin_lock_irq(&np->lock);
+		rc = generic_mii_ioctl(&np->mii_if, data, cmd, NULL);
+		spin_unlock_irq(&np->lock);
 	}
+
+	return rc;
 }
 
 static int netdev_close(struct net_device *dev)
diff -urN linux-2.4.20-pre8/drivers/net/via-rhine.c linux-2.4.20-pre9/drivers/net/via-rhine.c
--- linux-2.4.20-pre8/drivers/net/via-rhine.c	Thu Oct  3 18:36:44 2002
+++ linux-2.4.20-pre9/drivers/net/via-rhine.c	Thu Oct  3 18:37:38 2002
@@ -528,7 +528,7 @@
 static void via_rhine_error(struct net_device *dev, int intr_status);
 static void via_rhine_set_rx_mode(struct net_device *dev);
 static struct net_device_stats *via_rhine_get_stats(struct net_device *dev);
-static int via_rhine_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
+static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
 static int  via_rhine_close(struct net_device *dev);
 static inline void clear_tally_counters(long ioaddr);
 static inline void via_restart_tx(struct net_device *dev);
@@ -733,6 +733,8 @@
 	np->mii_if.dev = dev;
 	np->mii_if.mdio_read = mdio_read;
 	np->mii_if.mdio_write = mdio_write;
+	np->mii_if.phy_id_mask = 0x1f;
+	np->mii_if.reg_num_mask = 0x1f;
 
 	if (dev->mem_start)
 		option = dev->mem_start;
@@ -749,7 +751,7 @@
 	if (np->mii_if.full_duplex) {
 		printk(KERN_INFO "%s: Set to forced full duplex, autonegotiation"
 			   " disabled.\n", dev->name);
-		np->mii_if.duplex_lock = 1;
+		np->mii_if.force_media = 1;
 	}
 
 	/* The chip-specific entries in the device structure. */
@@ -758,7 +760,7 @@
 	dev->stop = via_rhine_close;
 	dev->get_stats = via_rhine_get_stats;
 	dev->set_multicast_list = via_rhine_set_rx_mode;
-	dev->do_ioctl = via_rhine_ioctl;
+	dev->do_ioctl = netdev_ioctl;
 	dev->tx_timeout = via_rhine_tx_timeout;
 	dev->watchdog_timeo = TX_TIMEOUT;
 	if (np->drv_flags & ReqTxAlign)
@@ -1020,7 +1022,7 @@
 		   ioaddr + IntrEnable);
 
 	np->chip_cmd = CmdStart|CmdTxOn|CmdRxOn|CmdNoTxPoll;
-	if (np->mii_if.duplex_lock)
+	if (np->mii_if.force_media)
 		np->chip_cmd |= CmdFDuplex;
 	writew(np->chip_cmd, ioaddr + ChipCmd);
 
@@ -1062,7 +1064,7 @@
 		switch (regnum) {
 		case MII_BMCR:					/* Is user forcing speed/duplex? */
 			if (value & 0x9000)			/* Autonegotiation. */
-				np->mii_if.duplex_lock = 0;
+				np->mii_if.force_media = 0;
 			else
 				np->mii_if.full_duplex = (value & 0x0100) ? 1 : 0;
 			break;
@@ -1133,7 +1135,7 @@
 	int negotiated = mii_lpa & np->mii_if.advertising;
 	int duplex;
 
-	if (np->mii_if.duplex_lock  ||  mii_lpa == 0xffff)
+	if (np->mii_if.force_media  ||  mii_lpa == 0xffff)
 		return;
 	duplex = (negotiated & 0x0100) || (negotiated & 0x01C0) == 0x0040;
 	if (np->mii_if.full_duplex != duplex) {
@@ -1633,7 +1635,7 @@
 	writeb(np->rx_thresh | rx_mode, ioaddr + RxConfig);
 }
 
-static int via_rhine_ethtool_ioctl (struct net_device *dev, void *useraddr)
+static int netdev_ethtool_ioctl (struct net_device *dev, void *useraddr)
 {
 	struct netdev_private *np = dev->priv;
 	u32 ethcmd;
@@ -1716,44 +1718,26 @@
 
 	return -EOPNOTSUPP;
 }
-static int via_rhine_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+
+static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 {
 	struct netdev_private *np = dev->priv;
-	struct mii_ioctl_data *data = (struct mii_ioctl_data *)&rq->ifr_data;
-	unsigned long flags;
-	int retval;
+	struct mii_ioctl_data *data = (struct mii_ioctl_data *) & rq->ifr_data;
+	int rc;
 
-	if (cmd == SIOCETHTOOL)
-		return via_rhine_ethtool_ioctl(dev, (void *) rq->ifr_data);
+	if (!netif_running(dev))
+		return -EINVAL;
 
-	spin_lock_irqsave(&np->lock, flags);
-	retval = 0;
-
-	switch(cmd) {
-	case SIOCGMIIPHY:		/* Get address of MII PHY in use. */
-	case SIOCDEVPRIVATE:		/* for binary compat, remove in 2.5 */
-		data->phy_id = np->phys[0] & 0x1f;
-		/* Fall Through */
-
-	case SIOCGMIIREG:		/* Read MII PHY register. */
-	case SIOCDEVPRIVATE+1:		/* for binary compat, remove in 2.5 */
-		data->val_out = mdio_read(dev, data->phy_id & 0x1f, data->reg_num & 0x1f);
-		break;
+	if (cmd == SIOCETHTOOL)
+		rc = netdev_ethtool_ioctl(dev, (void *) rq->ifr_data);
 
-	case SIOCSMIIREG:		/* Write MII PHY register. */
-	case SIOCDEVPRIVATE+2:		/* for binary compat, remove in 2.5 */
-		if (!capable(CAP_NET_ADMIN)) {
-			retval = -EPERM;
-			break;
-		}
-		mdio_write(dev, data->phy_id & 0x1f, data->reg_num & 0x1f, data->val_in);
-		break;
-	default:
-		retval = -EOPNOTSUPP;
+	else {
+		spin_lock_irq(&np->lock);
+		rc = generic_mii_ioctl(&np->mii_if, data, cmd, NULL);
+		spin_unlock_irq(&np->lock);
 	}
 
-	spin_unlock_irqrestore(&np->lock, flags);
-	return retval;
+	return rc;
 }
 
 static int via_rhine_close(struct net_device *dev)
diff -urN linux-2.4.20-pre8/drivers/net/winbond-840.c linux-2.4.20-pre9/drivers/net/winbond-840.c
--- linux-2.4.20-pre8/drivers/net/winbond-840.c	Thu Oct  3 18:36:44 2002
+++ linux-2.4.20-pre9/drivers/net/winbond-840.c	Thu Oct  3 18:37:39 2002
@@ -473,7 +473,7 @@
 		np->mii_if.full_duplex = 1;
 
 	if (np->mii_if.full_duplex)
-		np->mii_if.duplex_lock = 1;
+		np->mii_if.force_media = 1;
 
 	/* The chip-specific entries in the device structure. */
 	dev->open = &netdev_open;
@@ -773,7 +773,7 @@
 		duplex = (negotiated & LPA_100FULL) || ((negotiated & 0x02C0) == LPA_10FULL);
 		fasteth = negotiated & 0x380;
 	}
-	duplex |= np->mii_if.duplex_lock;
+	duplex |= np->mii_if.force_media;
 	/* remove fastether and fullduplex */
 	result = np->csr6 & ~0x20000200;
 	if (duplex)
diff -urN linux-2.4.20-pre8/drivers/net/wireless/airo.c linux-2.4.20-pre9/drivers/net/wireless/airo.c
--- linux-2.4.20-pre8/drivers/net/wireless/airo.c	Thu Oct  3 18:36:44 2002
+++ linux-2.4.20-pre9/drivers/net/wireless/airo.c	Thu Oct  3 18:37:39 2002
@@ -32,6 +32,7 @@
 #include <linux/timer.h>
 #include <linux/interrupt.h>
 #include <linux/in.h>
+#include <linux/tqueue.h>
 #include <asm/io.h>
 #include <asm/system.h>
 #include <asm/bitops.h>
@@ -79,6 +80,17 @@
 #include <linux/delay.h>
 #endif
 
+/* Support Cisco MIC feature */
+/* As this feature requires the AES encryption algorithm, it is not included
+   in the kernel tree. If you want to enable it, you need to download the
+   aes.h, aestab.h and mic.h files from the CVS at
+   http://sf.net/projects/airo-linux/ Put the files in the same directory
+   as airo.c and compile normally */
+#undef MICSUPPORT
+
+/* Hack to do some power saving */
+#define POWER_ON_DOWN
+
 /* As you can see this list is HUGH!
    I really don't know what a lot of these counts are about, but they
    are all here for completeness.  If the IGNLABEL macro is put in
@@ -191,7 +203,7 @@
 #ifndef RUN_AT
 #define RUN_AT(x) (jiffies+(x))
 #endif
-#ifndef PDE
+#if LINUX_VERSION_CODE < 0x020500
 static inline struct proc_dir_entry *PDE(const struct inode *inode)
 {
 	return inode->u.generic_ip;
@@ -278,42 +290,41 @@
 #define NO_PACKET -2
 
 /* Commands */
-#define NOP2 0x00    
-#define MAC_ENABLE 0x01
-#define MAC_ENABLETX 0x101
-#define CMD_ENABLEAUX 0x111
-#define MAC_ENABLERX 0x201   
-#define MAC_DISABLE 0x02    
-#define CMD_LOSE_SYNC 0x03    
-#define CMD_LOSE_SYNC_BSS 0x103
-#define CMD_SOFTRESET 0x04    
-#define HOSTSLEEP 0x05    
-#define CMD_MAGICPACKET 0x06
-#define CMD_SETWAKEMASK 0x07
-#define CMD_SAVECONFIG 0x108   
-#define CMD_READCONFIG 0x08
-#define CMD_SETMODE 0x09    
-#define CMD_ALLOCATETX 0x0A
-#define CMD_TRANSMIT 0x0B    
-#define CMD_DEALLOC 0x0C
-#define CMD_LISTBSS 0x103
-#define NOP 0x10    
-#define CMD_WORKAROUND 0x11
-#define CMD_ACCESS 0x21
-#define CMD_WRITERID 0x121
-#define CMD_PCIBAP 0x22
-#define CMD_PCIAUX 0x23
-#define CMD_ALLOCTLV 0x28
-#define CMD_GETTLV 0x29
-#define CMD_PUTTLV 0x2A
-#define CMD_DELTLV 0x2B    
-#define CMD_FINDNEXTTLV 0x2C    
-#define CMD_SETPHYREG 0x3E
-#define CMD_TXTEST 0x3F    
-#define CMD_NOPSPNODES 0x30    
-#define CMD_USEPSPNODES 0x130
-#define CMD_SETCW 0x31    
-#define CMD_SETPCF 0x32    
+#define NOP2		0x0000
+#define MAC_ENABLE	0x0001
+#define MAC_DISABLE	0x0002
+#define CMD_LOSE_SYNC	0x0003 /* Not sure what this does... */
+#define CMD_SOFTRESET	0x0004
+#define HOSTSLEEP	0x0005
+#define CMD_MAGIC_PKT	0x0006
+#define CMD_SETWAKEMASK	0x0007
+#define CMD_READCFG	0x0008
+#define CMD_SETMODE	0x0009
+#define CMD_ALLOCATETX	0x000a
+#define CMD_TRANSMIT	0x000b
+#define CMD_DEALLOCATETX 0x000c
+#define NOP		0x0010
+#define CMD_WORKAROUND	0x0011
+#define CMD_ACCESS	0x0021
+#define CMD_PCIBAP	0x0022
+#define CMD_PCIAUX	0x0023
+#define CMD_ALLOCBUF	0x0028
+#define CMD_GETTLV	0x0029
+#define CMD_PUTTLV	0x002a
+#define CMD_DELTLV	0x002b
+#define CMD_FINDNEXTTLV	0x002c
+#define CMD_PSPNODES	0x0030
+#define CMD_SETCW	0x0031    
+#define CMD_SETPCF	0x0032    
+#define CMD_SETPHYREG	0x003e
+#define CMD_TXTEST	0x003f
+#define MAC_ENABLETX	0x0101
+#define CMD_LISTBSS	0x0103
+#define CMD_SAVECFG	0x0108
+#define CMD_ENABLEAUX	0x0111
+#define CMD_WRITERID	0x0121
+#define CMD_USEPSPNODES	0x0130
+#define MAC_ENABLERX	0x0201
 
 /* Command errors */
 #define ERROR_QUALIF 0x00
@@ -400,10 +411,10 @@
 #define EV_AWAKE 0x100
 #define EV_UNKNOWN 0x800
 #define EV_MIC 0x1000 /* Message Integrity Check Interrupt */
-#define STATUS_INTS ( EV_AWAKE | EV_LINK | EV_TXEXC | EV_TX | EV_RX)
+#define STATUS_INTS ( EV_AWAKE | EV_LINK | EV_TXEXC | EV_TX | EV_RX | EV_MIC )
 
 #ifdef CHECK_UNKNOWN_INTS
-#define IGNORE_INTS ( EV_MIC | EV_CMD | EV_UNKNOWN)
+#define IGNORE_INTS ( EV_CMD | EV_UNKNOWN)
 #else
 #define IGNORE_INTS (~STATUS_INTS)
 #endif
@@ -435,6 +446,7 @@
 #define RID_UNKNOWN54  0xFF54
 #define RID_UNKNOWN55  0xFF55
 #define RID_UNKNOWN56  0xFF56
+#define RID_MIC        0xFF57
 #define RID_STATS16    0xFF60
 #define RID_STATS16DELTA 0xFF61
 #define RID_STATS16DELTACLEAR 0xFF62
@@ -474,7 +486,7 @@
 typedef struct {
 	u16 len;
 	u16 kindex;
-	u8 mac[6];
+	u8 mac[ETH_ALEN];
 	u16 klen;
 	u8 key[16];
 } WepKeyRid;
@@ -513,6 +525,7 @@
 #define MODE_ETHER_LLC (1<<12) /* enable ethernet LLC */
 #define MODE_LEAF_NODE (1<<13) /* enable leaf node bridge */
 #define MODE_CF_POLLABLE (1<<14) /* enable CF pollable */
+#define MODE_MIC (1<<15) /* enable MIC */
 	u16 rmode; /* receive mode */
 #define RXMODE_BC_MC_ADDR 0
 #define RXMODE_BC_ADDR 1 /* ignore multicasts */
@@ -524,7 +537,7 @@
 #define RXMODE_NORMALIZED_RSSI (1<<9) /* return normalized RSSI */
 	u16 fragThresh;
 	u16 rtsThres;
-	u8 macAddr[6];
+	u8 macAddr[ETH_ALEN];
 	u8 rates[8];
 	u16 shortRetryLimit;
 	u16 longRetryLimit;
@@ -619,14 +632,14 @@
 
 typedef struct {
 	u16 len;
-	u8 mac[6];
+	u8 mac[ETH_ALEN];
 	u16 mode;
 	u16 errorCode;
 	u16 sigQuality;
 	u16 SSIDlen;
 	char SSID[32];
 	char apName[16];
-	char bssid[4][6];
+	char bssid[4][ETH_ALEN];
 	u16 beaconPeriod;
 	u16 dimPeriod;
 	u16 atimDuration;
@@ -655,7 +668,7 @@
 
 typedef struct {
 	u16 len;
-	u8 ap[4][6];
+	u8 ap[4][ETH_ALEN];
 } APListRid;
 
 typedef struct {
@@ -666,11 +679,11 @@
 	char manName[32];
 	char prodName[16];
 	char prodVer[8];
-	char factoryAddr[6];
-	char aironetAddr[6];
+	char factoryAddr[ETH_ALEN];
+	char aironetAddr[ETH_ALEN];
 	u16 radioType;
 	u16 country;
-	char callid[6];
+	char callid[ETH_ALEN];
 	char supportedRates[8];
 	char rxDiversity;
 	char txDiversity;
@@ -684,6 +697,7 @@
 	u16 softCap;
 	u16 bootBlockVer;
 	u16 requiredHard;
+	u16 extSoftCap;
 } CapabilityRid;
 
 typedef struct {
@@ -693,7 +707,7 @@
 #define RADIO_DS 2 /* Direct sequence radio type */
 #define RADIO_TMA 4 /* Proprietary radio used in old cards (2500) */
   u16 radioType;
-  u8 bssid[6]; /* Mac address of the BSS */
+  u8 bssid[ETH_ALEN]; /* Mac address of the BSS */
   u8 zero;
   u8 ssidLen;
   u8 ssid[32];
@@ -726,6 +740,37 @@
   tdsRssiEntry x[256];
 } tdsRssiRid;
 
+typedef struct {
+	u16 len;
+	u16 state;
+	u16 multicastValid;
+	u8  multicast[16];
+	u16 unicastValid;
+	u8  unicast[16];
+} MICRid;
+
+typedef struct {
+	u16 typelen;
+
+	union {
+	    u8 snap[8];
+	    struct {
+		u8 dsap;
+		u8 ssap;
+		u8 control;
+		u8 orgcode[3];
+		u8 fieldtype[2];
+	    } llc;
+	} u;
+	u32 mic;
+	u32 seq;
+} MICBuffer;
+
+typedef struct {
+	u8 da[ETH_ALEN];
+	u8 sa[ETH_ALEN];
+} etherHead;
+
 #pragma pack()
 
 #define TXCTL_TXOK (1<<1) /* report if tx is ok */
@@ -770,6 +815,9 @@
 #define AIROGSTAT		8
 #define AIROGSTATSC32		9
 #define AIROGSTATSD32		10
+#define AIROGMICRID		11
+#define AIROGMICSTATS		12
+#define AIROGFLAGS		13
 
 /* Leave gap of 40 commands after AIROGSTATSD32 for future */
 
@@ -805,6 +853,45 @@
 } aironet_ioctl;
 #endif /* CISCO_EXT */
 
+#define NUM_MODULES       2
+#define MIC_MSGLEN_MAX    2400
+#define EMMH32_MSGLEN_MAX MIC_MSGLEN_MAX
+
+typedef struct {
+	u32   size;            // size
+	u8    enabled;         // MIC enabled or not
+	u32   rxSuccess;       // successful packets received
+	u32   rxIncorrectMIC;  // pkts dropped due to incorrect MIC comparison
+	u32   rxNotMICed;      // pkts dropped due to not being MIC'd
+	u32   rxMICPlummed;    // pkts dropped due to not having a MIC plummed
+	u32   rxWrongSequence; // pkts dropped due to sequence number violation
+	u32   reserve[32];
+} mic_statistics;
+
+typedef struct {
+	u32 coeff[((EMMH32_MSGLEN_MAX)+3)>>2];
+	u64 accum;	// accumulated mic, reduced to u32 in final()
+	int position;	// current position (byte offset) in message
+	union {
+		u8  d8[4];
+		u32 d32;
+	} part;	// saves partial message word across update() calls
+} emmh32_context;
+
+typedef struct {
+	emmh32_context seed;	    // Context - the seed
+	u32		 rx;	    // Received sequence number
+	u32		 tx;	    // Tx sequence number
+	u32		 window;    // Start of window
+	u8		 valid;	    // Flag to say if context is valid or not
+	u8		 key[16];
+} miccntx;
+
+typedef struct {
+	miccntx mCtx;		// Multicast context
+	miccntx uCtx;		// Unicast context
+} mic_module;
+
 #ifdef WIRELESS_EXT
 // Frequency list (map channels to frequencies)
 const long frequency_list[] = { 2412, 2417, 2422, 2427, 2432, 2437, 2442,
@@ -834,7 +921,7 @@
 #endif	/* WIRELESS_EXT > 12 */
 #endif /* WIRELESS_EXT */
 
-static const char version[] = "airo.c 0.5 (Ben Reed & Javier Achirica)";
+static const char version[] = "airo.c 0.6 (Ben Reed & Javier Achirica)";
 
 struct airo_info;
 
@@ -877,6 +964,12 @@
 static int writerids(struct net_device *dev, aironet_ioctl *comp);
 int flashcard(struct net_device *dev, aironet_ioctl *comp);
 #endif /* CISCO_EXT */
+#ifdef MICSUPPORT
+static void micinit(struct airo_info *ai, MICRid *micr);
+static void micsetup(struct airo_info *ai);
+static int encapsulate(struct airo_info *ai, etherHead *pPacket, MICBuffer *buffer, int len);
+static int decapsulate(struct airo_info *ai, MICBuffer *mic, etherHead *pPacket, u16 payLen);
+#endif
 
 struct airo_info {
 	struct net_device_stats	stats;
@@ -895,11 +988,17 @@
 	struct proc_dir_entry *proc_entry;
 	struct airo_info *next;
         spinlock_t aux_lock;
-        int flags;
-#define FLAG_PROMISC   IFF_PROMISC
-#define FLAG_RADIO_OFF 0x02
-#define FLAG_LOCKED    2
-#define FLAG_802_11	   0x10
+        unsigned long flags;
+#define FLAG_PROMISC   IFF_PROMISC	/* 0x100 - include/linux/if.h */
+#define FLAG_RADIO_OFF 0x02		/* User disabling of MAC */
+#define FLAG_RADIO_DOWN 0x08		/* ifup/ifdown disabling of MAC */
+#define FLAG_LOCKED    2		/* 0x04 - use as a bit offset */
+#define FLAG_FLASHING  0x10
+#define FLAG_ADHOC        0x01 /* Needed by MIC */
+#define FLAG_MIC_CAPABLE  0x20
+#define FLAG_UPDATE_MULTI 0x40
+#define FLAG_UPDATE_UNI   0x80
+#define FLAG_802_11    0x200
 	int (*bap_read)(struct airo_info*, u16 *pu16Dst, int bytelen,
 			int whichbap);
 	unsigned short *flash;
@@ -916,13 +1015,17 @@
 #ifdef WIRELESS_EXT
 	struct iw_statistics	wstats;		// wireless stats
 	unsigned long		scan_timestamp;	/* Time started to scan */
-	struct tq_struct 	event_task;
+	struct tq_struct	event_task;
 #ifdef WIRELESS_SPY
 	int			spy_number;
-	u_char			spy_address[IW_MAX_SPY][6];
+	u_char			spy_address[IW_MAX_SPY][ETH_ALEN];
 	struct iw_quality	spy_stat[IW_MAX_SPY];
 #endif /* WIRELESS_SPY */
 #endif /* WIRELESS_EXT */
+	/* MIC stuff */
+	mic_module		mod[2];
+	mic_statistics		micstats;
+	struct tq_struct 	mic_task;
 };
 
 static inline int bap_read(struct airo_info *ai, u16 *pu16Dst, int bytelen,
@@ -935,6 +1038,10 @@
 static int takedown_proc_entry( struct net_device *dev,
 				struct airo_info *apriv );
 
+#ifdef MICSUPPORT
+#include "mic.h"
+#endif
+
 static int readBSSListRid(struct airo_info *ai, int first,
 		      BSSListRid *list) {
 	int rc;
@@ -1065,6 +1172,11 @@
 
 	ai->need_commit = 0;
 	checkThrottle(ai);
+	if ((cfgr.opmode & 0xFF) == MODE_STA_IBSS)
+		ai->flags |= FLAG_ADHOC;
+	else
+		ai->flags &= ~FLAG_ADHOC;
+
 	cfgr = ai->config;
 
 	for(s = &cfgr.len; s <= &cfgr.rtsThres; s++) *s = cpu_to_le16(*s);
@@ -1126,20 +1238,26 @@
 
 static int airo_open(struct net_device *dev) {
 	struct airo_info *info = dev->priv;
+	Resp rsp;
+
+	if (info->flags & FLAG_FLASHING)
+		return -EIO;
 
 	/* Make sure the card is configured.
 	 * Wireless Extensions may postpone config changes until the card
 	 * is open (to pipeline changes and speed-up card setup). If
 	 * those changes are not yet commited, do it now - Jean II */
 	if(info->need_commit) {
-		Resp rsp;
 		disable_MAC(info);
 		writeConfigRid(info);
-		enable_MAC(info, &rsp);
 	}
 
-	if (info->wifidev != dev)
+	if (info->wifidev != dev) {
+		/* Power on the MAC controller (which may have been disabled) */
+		info->flags &= ~FLAG_RADIO_DOWN;
 		enable_interrupts(info);
+	}
+	enable_MAC(info, &rsp);
 
 	netif_start_queue(dev);
 	return 0;
@@ -1418,8 +1536,18 @@
 
 	netif_stop_queue(dev);
 
-	if (ai->wifidev != dev)
+	if (ai->wifidev != dev) {
+#ifdef POWER_ON_DOWN
+		/* Shut power to the card. The idea is that the user can save
+		 * power when he doesn't need the card with "ifconfig down".
+		 * That's the method that is most friendly towards the network
+		 * stack (i.e. the network stack won't try to broadcast
+		 * anything on the interface and routes are gone. Jean II */
+		ai->flags |= FLAG_RADIO_DOWN;
+		disable_MAC(ai);
+#endif
 		disable_interrupts( ai );
+	}
 	return 0;
 }
 
@@ -1580,12 +1708,16 @@
 		}
 	}
 
-	if (probe && setup_card( ai, dev->dev_addr ) != SUCCESS ) {
-		printk( KERN_ERR "airo: MAC could not be enabled\n" );
-		rc = -EIO;
-		goto err_out_res;
-	} else
+	if (probe) {
+		if ( setup_card( ai, dev->dev_addr ) != SUCCESS ) {
+			printk( KERN_ERR "airo: MAC could not be enabled\n" );
+			rc = -EIO;
+			goto err_out_res;
+		}
+	} else {
 		ai->bap_read = fast_bap_read;
+		ai->flags |= FLAG_FLASHING;
+	}
 
 	rc = register_netdev(dev);
 	if (rc)
@@ -1693,6 +1825,24 @@
 }
 #endif
 
+static void airo_read_mic(struct airo_info *ai) {
+	MICRid mic_rid;
+
+	if (down_trylock(&ai->sem) == 0) {
+		__set_bit(FLAG_LOCKED, &ai->flags);
+		PC4500_readrid(ai, RID_MIC, &mic_rid, sizeof(mic_rid));
+		clear_bit(FLAG_LOCKED, &ai->flags);
+		up(&ai->sem);
+#ifdef MICSUPPORT
+		micinit (ai, &mic_rid);
+#endif
+	} else {
+		ai->mic_task.routine = (void (*)(void *))airo_read_mic;
+		ai->mic_task.data = (void *)ai;
+		schedule_task(&ai->mic_task);
+	}
+}
+
 static void airo_interrupt ( int irq, void* dev_id, struct pt_regs *regs) {
 	struct net_device *dev = (struct net_device *)dev_id;
 	u16 status;
@@ -1717,6 +1867,10 @@
 			OUT4500( apriv, EVINTEN, 0 );
 		}
 
+		if ( status & EV_MIC ) {
+			OUT4500( apriv, EVACK, EV_MIC );
+			airo_read_mic( apriv );
+		}
 		if ( status & EV_LINK ) {
 #if WIRELESS_EXT > 13
 			union iwreq_data	wrqu;
@@ -1765,6 +1919,7 @@
 				struct task_struct *task = apriv->task;
 				if (task)
 					wake_up_process (task);
+				apriv->flags|=FLAG_UPDATE_UNI|FLAG_UPDATE_MULTI;
 			}
 #if WIRELESS_EXT > 13
 			/* Question : is ASSOCIATED the only status
@@ -1854,7 +2009,7 @@
 							hdrlen = 24;
 					}
 				} else
-					hdrlen = 12;
+					hdrlen = ETH_ALEN * 2;
 
 				skb = dev_alloc_skb( len + hdrlen + 2 );
 				if ( !skb ) {
@@ -1882,9 +2037,29 @@
 
 					bap_read (apriv, buffer + hdrlen/2, len, BAP0);
 				} else {
-					bap_read (apriv, buffer,len + hdrlen,BAP0);
+					MICBuffer micbuf;
+					bap_read (apriv, buffer, ETH_ALEN*2, BAP0);
+					if (apriv->micstats.enabled) {
+						bap_read (apriv,(u16*)&micbuf,sizeof(micbuf),BAP0);
+						if (ntohs(micbuf.typelen) > 0x05DC)
+							bap_setup (apriv, fid, 0x44, BAP0);
+						else {
+							len -= sizeof(micbuf);
+							if (len < 48)
+								len = 48;
+							skb_trim (skb, len + hdrlen);
+						}
+					}
+					bap_read(apriv,buffer+ETH_ALEN,len,BAP0);
+#ifdef MICSUPPORT
+					if (decapsulate(apriv,&micbuf,(etherHead*)buffer,len)) {
+						dev_kfree_skb_irq (skb);
+						len = 0;
+					}
+#endif
 				}
-				OUT4500( apriv, EVACK, EV_RX);
+			}
+			if (len) {
 #ifdef WIRELESS_SPY
 				if (apriv->spy_number > 0) {
 					int i;
@@ -1893,7 +2068,7 @@
 					sa = (char*)buffer + ((apriv->flags & FLAG_802_11) ? 10 : 6);
 
 					for (i=0; i<apriv->spy_number; i++)
-						if (!memcmp(sa,apriv->spy_address[i],6))
+						if (!memcmp(sa,apriv->spy_address[i],ETH_ALEN))
 						{
 							if (!(apriv->flags & FLAG_802_11)) {
 								bap_setup (apriv, fid, 8, BAP0);
@@ -1910,6 +2085,8 @@
 						}
 				}
 #endif /* WIRELESS_SPY  */
+				OUT4500( apriv, EVACK, EV_RX);
+
 				if (apriv->flags & FLAG_802_11) {
 					skb->mac.raw = skb->data;
 					skb->pkt_type = PACKET_OTHERHOST;
@@ -1999,7 +2176,13 @@
 	int rc;
         Cmd cmd;
 
-        if (ai->flags&FLAG_RADIO_OFF) return SUCCESS;
+	/* FLAG_RADIO_OFF : Radio disabled via /proc or Wireless Extensions
+	 * FLAG_RADIO_DOWN : Radio disabled via "ifconfig ethX down"
+	 * Note : we could try to use !netif_running(dev) in enable_MAC()
+	 * instead of this flag, but I don't trust it *within* the
+	 * open/close functions, and testing both flags together is
+	 * "cheaper" - Jean II */
+	if (ai->flags & (FLAG_RADIO_OFF|FLAG_RADIO_DOWN)) return SUCCESS;
 	memset(&cmd, 0, sizeof(cmd));
 	cmd.cmd = MAC_ENABLE;
 	if (test_bit(FLAG_LOCKED, &ai->flags) != 0)
@@ -2093,32 +2276,42 @@
 	up(&ai->sem);
 	if (ai->config.len == 0) {
 		tdsRssiRid rssi_rid;
+		CapabilityRid cap_rid;
 
 		// general configuration (read/modify/write)
 		status = readConfigRid(ai);
 		if ( status != SUCCESS ) return ERROR;
 
+		status = readCapabilityRid(ai, &cap_rid);
+		if ( status != SUCCESS ) return ERROR;
+
 		status = PC4500_readrid(ai,RID_RSSI,&rssi_rid,sizeof(rssi_rid));
 		if ( status == SUCCESS ) {
 			if (ai->rssi || (ai->rssi = kmalloc(512, GFP_KERNEL)) != NULL)
 				memcpy(ai->rssi, (u8*)&rssi_rid + 2, 512);
 		}
 		else {
-			CapabilityRid cap_rid;
 			if (ai->rssi) {
 				kfree(ai->rssi);
 				ai->rssi = NULL;
 			}
-			status = readCapabilityRid(ai, &cap_rid);
-			if ((status == SUCCESS) && (cap_rid.softCap & 8))
+			if (cap_rid.softCap & 8)
 				ai->config.rmode |= RXMODE_NORMALIZED_RSSI;
 			else
 				printk(KERN_WARNING "airo: unknown received signal level scale\n");
 		}
 		ai->config.opmode = adhoc ? MODE_STA_IBSS : MODE_STA_ESS;
 
+#ifdef MICSUPPORT
+		if ((cap_rid.len==sizeof(cap_rid)) && (cap_rid.extSoftCap&1)) {
+			ai->config.opmode |= MODE_MIC;
+			ai->flags |= FLAG_MIC_CAPABLE;
+			micsetup(ai);
+		}
+#endif
+
 		/* Save off the MAC */
-		for( i = 0; i < 6; i++ ) {
+		for( i = 0; i < ETH_ALEN; i++ ) {
 			mac[i] = ai->config.macAddr[i];
 		}
 
@@ -2141,8 +2334,6 @@
 				}
 			}
 		}
-		if (auto_wep)
-			ai->config.authType = AUTH_SHAREDKEY;
 		ai->need_commit = 1;
 	}
 
@@ -2166,7 +2357,10 @@
 	if ( status != SUCCESS ) return ERROR;
 
 	status = enable_MAC(ai, &rsp);
-	if ( status != SUCCESS ) return ERROR;
+	if ( status != SUCCESS || (rsp.status & 0xFF00) != 0) {
+		printk( KERN_ERR "airo: Bad MAC enable reason = %x, rid = %x, offset = %d\n", rsp.rsp0, rsp.rsp1, rsp.rsp2 );
+		return ERROR;
+	}
 
 	/* Grab the initial wep key, we gotta save it for auto_wep */
 	rc = readWepKeyRid(ai, &wkr, 1);
@@ -2507,22 +2701,38 @@
 	u16 payloadLen;
 	Cmd cmd;
 	Resp rsp;
+	int miclen = 0;
 	u16 txFid = len;
+	MICBuffer pMic;
+
 	len >>= 16;
 
-	if (len < 12) {
+	if (len < ETH_ALEN * 2) {
 		printk( KERN_WARNING "Short packet %d\n", len );
 		return ERROR;
 	}
+	len -= ETH_ALEN * 2;
+
+#ifdef MICSUPPORT
+	if ((ai->flags & FLAG_MIC_CAPABLE) && ai->micstats.enabled && 
+	    (ntohs(((u16 *)pPacket)[6]) != 0x888E)) {
+		if (encapsulate(ai,(etherHead *)pPacket,&pMic,len) != SUCCESS)
+			return ERROR;
+		miclen = sizeof(pMic);
+	}
+#endif
 
 	// packet is destination[6], source[6], payload[len-12]
 	// write the payload length and dst/src/payload
 	if (bap_setup(ai, txFid, 0x0036, BAP1) != SUCCESS) return ERROR;
 	/* The hardware addresses aren't counted as part of the payload, so
 	 * we have to subtract the 12 bytes for the addresses off */
-	payloadLen = cpu_to_le16(len-12);
+	payloadLen = cpu_to_le16(len + miclen);
 	bap_write(ai, &payloadLen, sizeof(payloadLen),BAP1);
-	bap_write(ai, (const u16*)pPacket, len, BAP1);
+	bap_write(ai, (const u16*)pPacket, sizeof(etherHead), BAP1);
+	if (miclen)
+		bap_write(ai, (const u16*)&pMic, miclen, BAP1);
+	bap_write(ai, (const u16*)(pPacket + sizeof(etherHead)), len, BAP1);
 	// issue the transmit command
 	memset( &cmd, 0, sizeof( cmd ) );
 	cmd.cmd = CMD_TRANSMIT;
@@ -2539,7 +2749,7 @@
 	Resp rsp;
 	int hdrlen;
 	struct {
-		u8 addr4[6];
+		u8 addr4[ETH_ALEN];
 		u16 gaplen;
 		u8 gap[6];
 	} gap;
@@ -3005,10 +3215,11 @@
 					need_reset = 1;
 			ai->config.rmode &= 0xfe00;
 			ai->flags &= ~FLAG_802_11;
+			ai->config.opmode &= 0xFF00;
 			if ( line[0] == 'a' ) {
-				ai->config.opmode = 0;
+				ai->config.opmode |= 0;
 			} else {
-				ai->config.opmode = 1;
+				ai->config.opmode |= 1;
 				if ( line[0] == 'r' ) {
 					ai->config.rmode |= RXMODE_RFMON | RXMODE_DISABLE_802_3_HEADER;
 					ai->flags |= FLAG_802_11;
@@ -3242,10 +3453,10 @@
 		     "DataRates: %d %d %d %d %d %d %d %d\n"
 		     "Channel: %d\n"
 		     "XmitPower: %d\n",
-		     ai->config.opmode == 0 ? "adhoc" :
-		     ai->config.opmode == 1 ? get_rmode(ai->config.rmode):
-		     ai->config.opmode == 2 ? "AP" :
-		     ai->config.opmode == 3 ? "AP RPTR" : "Error",
+		     (ai->config.opmode & 0xFF) == 0 ? "adhoc" :
+		     (ai->config.opmode & 0xFF) == 1 ? get_rmode(ai->config.rmode):
+		     (ai->config.opmode & 0xFF) == 2 ? "AP" :
+		     (ai->config.opmode & 0xFF) == 3 ? "AP RPTR" : "Error",
 		     ai->flags&FLAG_RADIO_OFF ? "off" : "on",
 		     ai->config.nodeName,
 		     ai->config.powerSaveMode == 0 ? "CAM" :
@@ -3407,7 +3618,7 @@
 
 static int set_wep_key(struct airo_info *ai, u16 index,
 		       const char *key, u16 keylen, int perm ) {
-	static const unsigned char macaddr[6] = { 0x01, 0, 0, 0, 0, 0 };
+	static const unsigned char macaddr[ETH_ALEN] = { 0x01, 0, 0, 0, 0, 0 };
 	WepKeyRid wkr;
 
 	memset(&wkr, 0, sizeof(wkr));
@@ -3424,7 +3635,7 @@
 		wkr.kindex = index;
 		wkr.klen = keylen;
 		memcpy( wkr.key, key, keylen );
-		memcpy( wkr.mac, macaddr, 6 );
+		memcpy( wkr.mac, macaddr, ETH_ALEN );
 		printk(KERN_INFO "Setting key %d\n", index);
 	}
 
@@ -3719,7 +3930,7 @@
 	u16 linkstat = IN4500(apriv, LINKSTAT);
 	Resp rsp;
 
-	if (linkstat != 0x400 ) {
+	if (!(apriv->flags & FLAG_FLASHING) && (linkstat != 0x400)) {
 /* We don't have a link so try changing the authtype */
 		if (down_trylock(&apriv->sem) != 0) {
 			apriv->timer.expires = RUN_AT(1);
@@ -4034,11 +4245,11 @@
 	Cmd cmd;
 	Resp rsp;
 	APListRid APList_rid;
-	static const unsigned char bcast[6] = { 255, 255, 255, 255, 255, 255 };
+	static const unsigned char bcast[ETH_ALEN] = { 255, 255, 255, 255, 255, 255 };
 
 	if (awrq->sa_family != ARPHRD_ETHER)
 		return -EINVAL;
-	else if (!memcmp(bcast, awrq->sa_data, 6)) {
+	else if (!memcmp(bcast, awrq->sa_data, ETH_ALEN)) {
 		memset(&cmd, 0, sizeof(cmd));
 		cmd.cmd=CMD_LOSE_SYNC;
 		if (down_interruptible(&local->sem))
@@ -4048,7 +4259,7 @@
 	} else {
 		memset(&APList_rid, 0, sizeof(APList_rid));
 		APList_rid.len = sizeof(APList_rid);
-		memcpy(APList_rid.ap[0], awrq->sa_data, 6);
+		memcpy(APList_rid.ap[0], awrq->sa_data, ETH_ALEN);
 		disable_MAC(local);
 		writeAPListRid(local, &APList_rid);
 		enable_MAC(local, &rsp);
@@ -4071,7 +4282,7 @@
 	readStatusRid(local, &status_rid);
 
 	/* Tentative. This seems to work, wow, I'm lucky !!! */
-	memcpy(awrq->sa_data, status_rid.bssid[0], 6);
+	memcpy(awrq->sa_data, status_rid.bssid[0], ETH_ALEN);
 	awrq->sa_family = ARPHRD_ETHER;
 
 	return 0;
@@ -4303,16 +4514,20 @@
 
 	switch(*uwrq) {
 		case IW_MODE_ADHOC:
-			local->config.opmode = MODE_STA_IBSS;
+			local->config.opmode &= 0xFF00;
+			local->config.opmode |= MODE_STA_IBSS;
 			break;
 		case IW_MODE_INFRA:
-			local->config.opmode = MODE_STA_ESS;
+			local->config.opmode &= 0xFF00;
+			local->config.opmode |= MODE_STA_ESS;
 			break;
 		case IW_MODE_MASTER:
-			local->config.opmode = MODE_AP;
+			local->config.opmode &= 0xFF00;
+			local->config.opmode |= MODE_AP;
 			break;
 		case IW_MODE_REPEAT:
-			local->config.opmode = MODE_AP_RPTR;
+			local->config.opmode &= 0xFF00;
+			local->config.opmode |= MODE_AP_RPTR;
 			break;
 		default:
 			return -EINVAL;
@@ -4855,7 +5070,7 @@
 		if (readBSSListRid(local, loseSync, &BSSList))
 			break;
 		loseSync = 0;
-		memcpy(address[i].sa_data, BSSList.bssid, 6);
+		memcpy(address[i].sa_data, BSSList.bssid, ETH_ALEN);
 		address[i].sa_family = ARPHRD_ETHER;
 		if (local->rssi)
 			qual[i].level = 0x100 - local->rssi[BSSList.rssi].rssidBm;
@@ -4885,7 +5100,7 @@
 			      | status_rid.bssid[i][5]);
 		     i++) {
 			memcpy(address[i].sa_data,
-			       status_rid.bssid[i], 6);
+			       status_rid.bssid[i], ETH_ALEN);
 			address[i].sa_family = ARPHRD_ETHER;
 		}
 	} else {
@@ -5110,7 +5325,7 @@
 
 		/* Copy addresses */
 		for (i = 0; i < dwrq->length; i++)
-			memcpy(local->spy_address[i], address[i].sa_data, 6);
+			memcpy(local->spy_address[i], address[i].sa_data, ETH_ALEN);
 		/* Reset stats */
 		memset(local->spy_stat, 0, sizeof(struct iw_quality) * IW_MAX_SPY);
 	}
@@ -5137,7 +5352,7 @@
 
 	/* Copy addresses. */
 	for(i = 0; i < local->spy_number; i++) 	{
-		memcpy(address[i].sa_data, local->spy_address[i], 6);
+		memcpy(address[i].sa_data, local->spy_address[i], ETH_ALEN);
 		address[i].sa_family = AF_UNIX;
 	}
 	/* Copy stats to the user buffer (just after). */
@@ -5605,7 +5820,7 @@
 
 		/* Seperate R/W functions bracket legality here
 		 */
-		if ( com.command <= AIROGSTATSD32 )
+		if ( com.command <= AIROGMICSTATS )
 			rc = readrids(dev,&com);
 		else if ( com.command >= AIROPCAP && com.command <= AIROPLEAPUSR )
 			rc = writerids(dev,&com);
@@ -5690,12 +5905,15 @@
 static int readrids(struct net_device *dev, aironet_ioctl *comp) {
 	unsigned short ridcode;
 	unsigned char iobuf[2048];
+	struct airo_info *ai = dev->priv;
+
+	if (ai->flags & FLAG_FLASHING)
+		return -EIO;
 
 	switch(comp->command)
 	{
 	case AIROGCAP:      ridcode = RID_CAPABILITIES; break;
-	case AIROGCFG:      ridcode = RID_CONFIG;       break;
-	case AIROPCFG: writeConfigRid ((struct airo_info *)dev->priv);
+	case AIROGCFG: writeConfigRid (ai);
 			    ridcode = RID_CONFIG;       break;
 	case AIROGSLIST:    ridcode = RID_SSID;         break;
 	case AIROGVLIST:    ridcode = RID_APLIST;       break;
@@ -5714,12 +5932,17 @@
 	case AIROGSTAT:     ridcode = RID_STATUS;       break;
 	case AIROGSTATSD32: ridcode = RID_STATSDELTA;   break;
 	case AIROGSTATSC32: ridcode = RID_STATS;        break;
+	case AIROGMICSTATS:
+		if (copy_to_user(comp->data, &ai->micstats,
+				 min((int)comp->len,(int)sizeof(ai->micstats))))
+			return -EFAULT;
+		return 0;
 	default:
 		return -EINVAL;
 		break;
 	}
 
-	PC4500_readrid((struct airo_info *)dev->priv,ridcode,iobuf,sizeof(iobuf));
+	PC4500_readrid(ai,ridcode,iobuf,sizeof(iobuf));
 	/* get the count of bytes in the rid  docs say 1st 2 bytes is it.
 	 * then return it to the user
 	 * 9/22/2000 Honor user given length
@@ -5736,7 +5959,8 @@
  */
 
 static int writerids(struct net_device *dev, aironet_ioctl *comp) {
-	int  ridcode;
+	struct airo_info *ai = dev->priv;
+	int  ridcode, enabled;
 	Resp      rsp;
 	static int (* writer)(struct airo_info *, u16 rid, const void *, int);
 	unsigned char iobuf[2048];
@@ -5745,6 +5969,9 @@
 	if (!capable(CAP_NET_ADMIN))
 		return -EPERM;
 
+	if (ai->flags & FLAG_FLASHING)
+		return -EIO;
+
 	ridcode = 0;
 	writer = do_writerid;
 
@@ -5753,7 +5980,7 @@
 	case AIROPSIDS:     ridcode = RID_SSID;         break;
 	case AIROPCAP:      ridcode = RID_CAPABILITIES; break;
 	case AIROPAPLIST:   ridcode = RID_APLIST;       break;
-	case AIROPCFG: ((struct airo_info *)dev->priv)->config.len = 0;
+	case AIROPCFG: ai->config.len = 0;
 			    ridcode = RID_CONFIG;       break;
 	case AIROPWEPKEYNV: ridcode = RID_WEP_PERM;     break;
 	case AIROPLEAPUSR:  ridcode = RID_LEAPUSERNAME; break;
@@ -5765,7 +5992,7 @@
 		 * same with MAC off
 		 */
 	case AIROPMACON:
-		if (enable_MAC(dev->priv, &rsp) != 0)
+		if (enable_MAC(ai, &rsp) != 0)
 			return -EIO;
 		return 0;
 
@@ -5774,7 +6001,7 @@
 		 * as disable_MAC. it's probably so short the compiler does not gen one.
 		 */
 	case AIROPMACOFF:
-		disable_MAC(dev->priv);
+		disable_MAC(ai);
 		return 0;
 
 		/* This command merely clears the counts does not actually store any data
@@ -5782,9 +6009,11 @@
 		 * writerid routines.
 		 */
 	case AIROPSTCLR:
-		ridcode = RID_STATSDELTACLEAR;
+		PC4500_readrid(ai,RID_STATSDELTACLEAR,iobuf,sizeof(iobuf));
 
-		PC4500_readrid(dev->priv,ridcode,iobuf,sizeof(iobuf));
+		enabled = ai->micstats.enabled;
+		memset(&ai->micstats,0,sizeof(ai->micstats));
+		ai->micstats.enabled = enabled;
 
 		if (copy_to_user(comp->data, iobuf,
 				 min((int)comp->len, (int)sizeof(iobuf))))
@@ -5799,7 +6028,20 @@
 
 	if (copy_from_user(iobuf,comp->data,comp->len))
 		return -EFAULT;
-	if((*writer)((struct airo_info *)dev->priv, ridcode, iobuf,comp->len))
+
+	if (comp->command == AIROPCFG) {
+		ConfigRid *cfg = (ConfigRid *)iobuf;
+
+		if (ai->flags & FLAG_MIC_CAPABLE)
+			cfg->opmode |= MODE_MIC;
+
+		if ((cfg->opmode & 0xFF) == MODE_STA_IBSS)
+			ai->flags |= FLAG_ADHOC;
+		else
+			ai->flags &= ~FLAG_ADHOC;
+	}
+
+	if((*writer)(ai, ridcode, iobuf,comp->len))
 		return -EIO;
 	return 0;
 }
@@ -5904,6 +6146,8 @@
  */
 
 int setflashmode (struct airo_info *ai) {
+	ai->flags |= FLAG_FLASHING;
+
 	OUT4500(ai, SWS0, FLASH_COMMAND);
 	OUT4500(ai, SWS1, FLASH_COMMAND);
 	if (probe) {
@@ -5918,6 +6162,7 @@
 	schedule_timeout (HZ/2); /* 500ms delay */
 
 	if(!waitbusy(ai)) {
+		ai->flags &= ~FLAG_FLASHING;
 		printk(KERN_INFO "Waitbusy hang after setflash mode\n");
 		return -EIO;
 	}
@@ -6023,6 +6268,7 @@
 
 	set_current_state (TASK_UNINTERRUPTIBLE);
 	schedule_timeout (HZ);          /* Added 12/7/00 */
+	ai->flags &= ~FLAG_FLASHING;
 	status = setup_card(ai, dev->dev_addr);
 
 	for( i = 0; i < MAX_FIDS; i++ ) {
diff -urN linux-2.4.20-pre8/drivers/sound/maestro3.c linux-2.4.20-pre9/drivers/sound/maestro3.c
--- linux-2.4.20-pre8/drivers/sound/maestro3.c	Fri Aug  2 17:39:44 2002
+++ linux-2.4.20-pre9/drivers/sound/maestro3.c	Thu Oct  3 18:37:50 2002
@@ -28,6 +28,9 @@
  * Shouts go out to Mike "DJ XPCom" Ang.
  *
  * History
+ *  v1.23 - Jun 5 2002 - Michael Olson <olson@cs.odu.edu>
+ *   added a module option to allow selection of GPIO pin number 
+ *   for external amp 
  *  v1.22 - Feb 28 2001 - Zach Brown <zab@zabbo.net>
  *   allocate mem at insmod/setup, rather than open
  *   limit pci dma addresses to 28bit, thanks guys.
@@ -153,7 +156,7 @@
 
 #define M_DEBUG 1
 
-#define DRIVER_VERSION      "1.22"
+#define DRIVER_VERSION      "1.23"
 #define M3_MODULE_NAME      "maestro3"
 #define PFX                 M3_MODULE_NAME ": "
 
@@ -190,6 +193,7 @@
 };
 
 int external_amp = 1;
+int gpio_pin = -1;
 
 struct m3_state {
     unsigned int magic;
@@ -2469,14 +2473,20 @@
     if(!external_amp)
         return;
 
-    switch (card->card_type) {
-        case ESS_ALLEGRO:
-            polarity_port = 0x1800;
-            break;
-        default:
-            /* presumably this is for all 'maestro3's.. */
-            polarity_port = 0x1100;
-            break;
+    if (0 <= gpio_pin <= 15) {
+        polarity_port = 0x1000 + (0x100 * gpio_pin);
+    } else {
+        switch (card->card_type) {
+            case ESS_ALLEGRO:
+                polarity_port = 0x1800;
+                break;
+            default:
+                polarity_port = 0x1100;
+                /* Panasonic toughbook CF72 has to be different... */
+                if(card->pcidev->subsystem_vendor == 0x10F7 && card->pcidev->subsystem_device == 0x833D)
+                	polarity_port = 0x1D00;
+                break;
+        }
     }
 
     gpo = (polarity_port >> 8) & 0x0F;
@@ -2911,6 +2921,7 @@
 MODULE_PARM(debug,"i");
 #endif
 MODULE_PARM(external_amp,"i");
+MODULE_PARM(gpio_pin, "i");
 
 static struct pci_driver m3_pci_driver = {
     name:       "ess_m3_audio",
diff -urN linux-2.4.20-pre8/drivers/usb/hpusbscsi.c linux-2.4.20-pre9/drivers/usb/hpusbscsi.c
--- linux-2.4.20-pre8/drivers/usb/hpusbscsi.c	Thu Oct  3 18:36:47 2002
+++ linux-2.4.20-pre9/drivers/usb/hpusbscsi.c	Thu Oct  3 18:37:52 2002
@@ -200,8 +200,14 @@
 static void
 hpusbscsi_usb_disconnect (struct usb_device *dev, void *ptr)
 {
-                 usb_unlink_urb(&(((struct hpusbscsi *) ptr)->controlurb));
-	((struct hpusbscsi *) ptr)->dev = NULL;
+	struct hpusbscsi *hp = (struct hpusbscsi *)ptr;
+
+	usb_unlink_urb(&hp->controlurb);
+	usb_unlink_urb(&hp->dataurb);
+
+	spin_lock_irq(&io_request_lock);
+	hp->dev = NULL;
+	spin_unlock_irq(&io_request_lock);
 }
 
 static struct usb_device_id hpusbscsi_usb_ids[] = {
@@ -335,15 +341,13 @@
 	usb_urb_callback usb_callback;
 	int res;
 
-	hpusbscsi->use_count++;
+	spin_unlock_irq(&io_request_lock);
 
 	/* we don't answer for anything but our single device on any faked host controller */
 	if ( srb->device->lun || srb->device->id || srb->device->channel ) {
-		if (callback) {
-			srb->result = DID_BAD_TARGET;
-			callback(srb);
-		}
-                	goto out;
+		srb->result = DID_BAD_TARGET;
+		callback(srb);
+		goto out;
 	}
 
 	/* Now we need to decide which callback to give to the urb we send the command with */
@@ -407,14 +411,13 @@
 	if (res) {
 		hpusbscsi->state = HP_STATE_FREE;
 		PDEBUG(2, "state= %s", states[hpusbscsi->state]);
-		if (callback) {
-			srb->result = DID_ERROR;
-			callback(srb);
-		}
+		srb->result = DID_ERROR;
+		callback(srb);
+
 	}
 
 out:
-	hpusbscsi->use_count--;
+	spin_lock_irq(&io_request_lock);
 	return 0;
 }
 
@@ -438,7 +441,7 @@
 	spin_unlock_irq(&io_request_lock);
 	usb_unlink_urb(&hpusbscsi->dataurb);
 	hpusbscsi->state = HP_STATE_FREE;
-	
+
 	spin_lock_irq(&io_request_lock);
 
 	return SCSI_ABORT_PENDING;
diff -urN linux-2.4.20-pre8/drivers/usb/kaweth.c linux-2.4.20-pre9/drivers/usb/kaweth.c
--- linux-2.4.20-pre8/drivers/usb/kaweth.c	Thu Oct  3 18:36:47 2002
+++ linux-2.4.20-pre9/drivers/usb/kaweth.c	Thu Oct  3 18:37:52 2002
@@ -495,6 +495,7 @@
 static void kaweth_resubmit_rx_urb(struct kaweth_device *kaweth)
 {
 	int result;
+	long flags;
 
 	FILL_BULK_URB(kaweth->rx_urb,
 		      kaweth->dev,
@@ -504,13 +505,17 @@
 		      kaweth_usb_receive,
 		      kaweth);
 
-	if((result = usb_submit_urb(kaweth->rx_urb))) {
-		if (result == -ENOMEM)
-			kaweth->suspend_lowmem = 1;
-		kaweth_err("resubmitting rx_urb %d failed", result);
-	} else {
-		kaweth->suspend_lowmem = 0;
+	spin_lock_irqsave(&kaweth->device_lock, flags);
+	if (!kaweth->removed) { /* no resubmit if disconnecting */
+		if((result = usb_submit_urb(kaweth->rx_urb))) {
+			if (result == -ENOMEM)
+				kaweth->suspend_lowmem = 1;
+			kaweth_err("resubmitting rx_urb %d failed", result);
+		} else {
+			kaweth->suspend_lowmem = 0;
+		}
 	}
+	spin_unlock_irqrestore(&kaweth->device_lock, flags);
 }
 
 static void kaweth_async_set_rx_mode(struct kaweth_device *kaweth);
@@ -625,8 +630,10 @@
 	struct kaweth_device *kaweth = net->priv;
 
 	netif_stop_queue(net);
-
+	
+	spin_lock_irq(&kaweth->device_lock);
 	kaweth->status |= KAWETH_STATUS_CLOSING;
+	spin_unlock_irq(&kaweth->device_lock);
 
 	usb_unlink_urb(kaweth->irq_urb);
 	usb_unlink_urb(kaweth->rx_urb);
@@ -1065,12 +1072,12 @@
 	usb_unlink_urb(kaweth->rx_urb);
 
 	/* we need to wait for the urb to be cancelled, if it is active */
-	spin_lock(&kaweth->device_lock);
+	spin_lock_irq(&kaweth->device_lock);
 	if (usb_unlink_urb(kaweth->tx_urb) == -EINPROGRESS) {
-		spin_unlock(&kaweth->device_lock);
+		spin_unlock_irq(&kaweth->device_lock);
 		wait_event(kaweth->term_wait, kaweth->end);
 	} else {
-		spin_unlock(&kaweth->device_lock);
+		spin_unlock_irq(&kaweth->device_lock);
 	}
 
 	if(kaweth->net) {
diff -urN linux-2.4.20-pre8/drivers/usb/serial/visor.c linux-2.4.20-pre9/drivers/usb/serial/visor.c
--- linux-2.4.20-pre8/drivers/usb/serial/visor.c	Thu Oct  3 18:36:48 2002
+++ linux-2.4.20-pre9/drivers/usb/serial/visor.c	Thu Oct  3 18:37:55 2002
@@ -171,9 +171,10 @@
 	{ USB_DEVICE(PALM_VENDOR_ID, PALM_M500_ID) },
 	{ USB_DEVICE(PALM_VENDOR_ID, PALM_M505_ID) },
 	{ USB_DEVICE(PALM_VENDOR_ID, PALM_M515_ID) },
+	{ USB_DEVICE(PALM_VENDOR_ID, PALM_I705_ID) },
 	{ USB_DEVICE(PALM_VENDOR_ID, PALM_M125_ID) },
 	{ USB_DEVICE(PALM_VENDOR_ID, PALM_M130_ID) },
-	{ USB_DEVICE(PALM_VENDOR_ID, PALM_I705_ID) },
+	{ USB_DEVICE(PALM_VENDOR_ID, PALM_ZIRE_ID) },
 	{ USB_DEVICE(HANDSPRING_VENDOR_ID, HANDSPRING_VISOR_ID) },
 	{ USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_4_0_ID) },
 	{ USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_S360_ID) },
@@ -191,9 +192,10 @@
 	{ USB_DEVICE(PALM_VENDOR_ID, PALM_M500_ID) },
 	{ USB_DEVICE(PALM_VENDOR_ID, PALM_M505_ID) },
 	{ USB_DEVICE(PALM_VENDOR_ID, PALM_M515_ID) },
+	{ USB_DEVICE(PALM_VENDOR_ID, PALM_I705_ID) },
 	{ USB_DEVICE(PALM_VENDOR_ID, PALM_M125_ID) },
 	{ USB_DEVICE(PALM_VENDOR_ID, PALM_M130_ID) },
-	{ USB_DEVICE(PALM_VENDOR_ID, PALM_I705_ID) },
+	{ USB_DEVICE(PALM_VENDOR_ID, PALM_ZIRE_ID) },
 	{ USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_3_5_ID) },
 	{ USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_4_0_ID) },
 	{ USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_S360_ID) },
diff -urN linux-2.4.20-pre8/drivers/usb/serial/visor.h linux-2.4.20-pre9/drivers/usb/serial/visor.h
--- linux-2.4.20-pre8/drivers/usb/serial/visor.h	Fri Aug  2 17:39:45 2002
+++ linux-2.4.20-pre9/drivers/usb/serial/visor.h	Thu Oct  3 18:37:55 2002
@@ -27,6 +27,7 @@
 #define PALM_I705_ID			0x0020
 #define PALM_M125_ID			0x0040
 #define PALM_M130_ID			0x0050
+#define PALM_ZIRE_ID			0x0070
 
 #define SONY_VENDOR_ID			0x054C
 #define SONY_CLIE_3_5_ID		0x0038
diff -urN linux-2.4.20-pre8/drivers/usb/storage/sddr55.c linux-2.4.20-pre9/drivers/usb/storage/sddr55.c
--- linux-2.4.20-pre8/drivers/usb/storage/sddr55.c	Thu Oct  3 18:36:48 2002
+++ linux-2.4.20-pre9/drivers/usb/storage/sddr55.c	Thu Oct  3 18:37:56 2002
@@ -968,7 +968,7 @@
 	/* only check card status if the map isn't allocated, ie no card seen yet
 	 * or if it's been over half a second since we last accessed it
 	 */
-	if (info->lba_to_pba == NULL || jiffies > (info->last_access + HZ/2)) {
+	if (info->lba_to_pba == NULL || time_after(jiffies, info->last_access + HZ/2)) {
 
 		/* check to see if a card is fitted */
 		result = sddr55_status (us);
diff -urN linux-2.4.20-pre8/drivers/usb/storage/unusual_devs.h linux-2.4.20-pre9/drivers/usb/storage/unusual_devs.h
--- linux-2.4.20-pre8/drivers/usb/storage/unusual_devs.h	Thu Oct  3 18:36:48 2002
+++ linux-2.4.20-pre9/drivers/usb/storage/unusual_devs.h	Thu Oct  3 18:37:56 2002
@@ -324,8 +324,10 @@
  * Like the SIIG unit above, this unit needs an INQUIRY to ask for exactly
  * 36 bytes of data.  No more, no less. That is the only reason this entry
  * is needed.
- */
-UNUSUAL_DEV(  0x05e3, 0x0702, 0x0000, 0xffff,
+ *
+ * ST818 slim drives (rev 0.02) don't need special care.
+*/
+UNUSUAL_DEV(  0x05e3, 0x0702, 0x0000, 0x0001,
 		"EagleTec",
 		"External Hard Disk",
 		US_SC_SCSI, US_PR_BULK, NULL,
@@ -512,17 +514,22 @@
                 0 ),
 #endif
 
-/* Submitted by Brian Hall <brihall@bigfoot.com>
+/* Submitted by Brian Hall <brihall@pcisys.net>
  * Needed for START_STOP flag */
 UNUSUAL_DEV(  0x0c76, 0x0003, 0x0100, 0x0100,
 		"JMTek",
 		"USBDrive",
 		US_SC_SCSI, US_PR_BULK, NULL,
 		US_FL_START_STOP ),
+UNUSUAL_DEV(  0x0c76, 0x0005, 0x0100, 0x0100,
+		"JMTek",
+		"USBDrive",
+		US_SC_SCSI, US_PR_BULK, NULL,
+		US_FL_START_STOP ),
 
 /* Reported by Dan Pilone <pilone@slac.com>
  * The device needs the flags only.
- * Also reported by Brian Hall <brihall@bigfoot.com>, again for flags.
+ * Also reported by Brian Hall <brihall@pcisys.net>, again for flags.
  * I also suspect this device may have a broken serial number.
  */
 UNUSUAL_DEV(  0x1065, 0x2136, 0x0000, 0x9999,
diff -urN linux-2.4.20-pre8/fs/buffer.c linux-2.4.20-pre9/fs/buffer.c
--- linux-2.4.20-pre8/fs/buffer.c	Thu Oct  3 18:36:50 2002
+++ linux-2.4.20-pre9/fs/buffer.c	Thu Oct  3 18:37:58 2002
@@ -1990,7 +1990,12 @@
 	flush_dcache_page(page);
 	kunmap(page);
 
-	__mark_buffer_dirty(bh);
+	if (!atomic_set_buffer_dirty(bh)) {
+		__mark_dirty(bh);
+		buffer_insert_inode_data_queue(bh, inode);
+		balance_dirty();
+	}
+
 	err = 0;
 
 unlock:
diff -urN linux-2.4.20-pre8/fs/ext3/namei.c linux-2.4.20-pre9/fs/ext3/namei.c
--- linux-2.4.20-pre8/fs/ext3/namei.c	Fri Nov  9 14:25:04 2001
+++ linux-2.4.20-pre9/fs/ext3/namei.c	Thu Oct  3 18:37:58 2002
@@ -354,8 +354,8 @@
 			 */
 			dir->i_mtime = dir->i_ctime = CURRENT_TIME;
 			dir->u.ext3_i.i_flags &= ~EXT3_INDEX_FL;
-			ext3_mark_inode_dirty(handle, dir);
 			dir->i_version = ++event;
+			ext3_mark_inode_dirty(handle, dir);
 			BUFFER_TRACE(bh, "call ext3_journal_dirty_metadata");
 			ext3_journal_dirty_metadata(handle, bh);
 			brelse(bh);
@@ -464,8 +464,8 @@
 		inode->i_op = &ext3_file_inode_operations;
 		inode->i_fop = &ext3_file_operations;
 		inode->i_mapping->a_ops = &ext3_aops;
-		ext3_mark_inode_dirty(handle, inode);
 		err = ext3_add_nondir(handle, dentry, inode);
+		ext3_mark_inode_dirty(handle, inode);
 	}
 	ext3_journal_stop(handle, dir);
 	return err;
@@ -489,8 +489,8 @@
 	err = PTR_ERR(inode);
 	if (!IS_ERR(inode)) {
 		init_special_inode(inode, mode, rdev);
-		ext3_mark_inode_dirty(handle, inode);
 		err = ext3_add_nondir(handle, dentry, inode);
+		ext3_mark_inode_dirty(handle, inode);
 	}
 	ext3_journal_stop(handle, dir);
 	return err;
@@ -829,9 +829,9 @@
 	 * recovery. */
 	inode->i_size = 0;
 	ext3_orphan_add(handle, inode);
-	ext3_mark_inode_dirty(handle, inode);
 	dir->i_nlink--;
 	inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
+	ext3_mark_inode_dirty(handle, inode);
 	dir->u.ext3_i.i_flags &= ~EXT3_INDEX_FL;
 	ext3_mark_inode_dirty(handle, dir);
 
@@ -883,8 +883,8 @@
 	inode->i_nlink--;
 	if (!inode->i_nlink)
 		ext3_orphan_add(handle, inode);
-	ext3_mark_inode_dirty(handle, inode);
 	inode->i_ctime = dir->i_ctime;
+	ext3_mark_inode_dirty(handle, inode);
 	retval = 0;
 
 end_unlink:
@@ -933,8 +933,8 @@
 		inode->i_size = l-1;
 	}
 	inode->u.ext3_i.i_disksize = inode->i_size;
-	ext3_mark_inode_dirty(handle, inode);
 	err = ext3_add_nondir(handle, dentry, inode);
+	ext3_mark_inode_dirty(handle, inode);
 out_stop:
 	ext3_journal_stop(handle, dir);
 	return err;
@@ -970,8 +970,8 @@
 	ext3_inc_count(handle, inode);
 	atomic_inc(&inode->i_count);
 
-	ext3_mark_inode_dirty(handle, inode);
 	err = ext3_add_nondir(handle, dentry, inode);
+	ext3_mark_inode_dirty(handle, inode);
 	ext3_journal_stop(handle, dir);
 	return err;
 }
diff -urN linux-2.4.20-pre8/fs/ext3/super.c linux-2.4.20-pre9/fs/ext3/super.c
--- linux-2.4.20-pre8/fs/ext3/super.c	Thu Oct  3 18:36:50 2002
+++ linux-2.4.20-pre9/fs/ext3/super.c	Thu Oct  3 18:37:58 2002
@@ -646,6 +646,11 @@
 				*mount_options &= ~EXT3_MOUNT_DATA_FLAGS;
 				*mount_options |= data_opt;
 			}
+		} else if (!strcmp (this_char, "commit")) {
+			unsigned long v;
+			if (want_numeric(value, "commit", &v))
+				return 0;
+			sbi->s_commit_interval = (HZ * v);
 		} else {
 			printk (KERN_ERR 
 				"EXT3-fs: Unrecognized mount option %s\n",
@@ -1228,6 +1233,22 @@
 	return NULL;
 }
 
+/*
+ * Setup any per-fs journal parameters now.  We'll do this both on
+ * initial mount, once the journal has been initialised but before we've
+ * done any recovery; and again on any subsequent remount. 
+ */
+static void ext3_init_journal_params(struct ext3_sb_info *sbi, 
+				     journal_t *journal)
+{
+	if (sbi->s_commit_interval)
+		journal->j_commit_interval = sbi->s_commit_interval;
+	/* We could also set up an ext3-specific default for the commit
+	 * interval here, but for now we'll just fall back to the jbd
+	 * default. */
+}
+
+
 static journal_t *ext3_get_journal(struct super_block *sb, int journal_inum)
 {
 	struct inode *journal_inode;
@@ -1262,7 +1283,7 @@
 		printk(KERN_ERR "EXT3-fs: Could not load journal inode\n");
 		iput(journal_inode);
 	}
-	
+	ext3_init_journal_params(EXT3_SB(sb), journal);
 	return journal;
 }
 
@@ -1340,6 +1361,7 @@
 		goto out_journal;
 	}
 	EXT3_SB(sb)->journal_bdev = bdev;
+	ext3_init_journal_params(EXT3_SB(sb), journal);
 	return journal;
 out_journal:
 	journal_destroy(journal);
@@ -1588,8 +1610,10 @@
 		journal_t *journal = EXT3_SB(sb)->s_journal;
 
 		/* Now we set up the journal barrier. */
+		unlock_super(sb);
 		journal_lock_updates(journal);
 		journal_flush(journal);
+		lock_super(sb);
 
 		/* Journal blocked and flushed, clear needs_recovery flag. */
 		EXT3_CLEAR_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_RECOVER);
@@ -1635,6 +1659,8 @@
 
 	es = sbi->s_es;
 
+	ext3_init_journal_params(sbi, sbi->s_journal);
+	
 	if ((*flags & MS_RDONLY) != (sb->s_flags & MS_RDONLY)) {
 		if (sbi->s_mount_opt & EXT3_MOUNT_ABORT)
 			return -EROFS;
diff -urN linux-2.4.20-pre8/fs/jbd/checkpoint.c linux-2.4.20-pre9/fs/jbd/checkpoint.c
--- linux-2.4.20-pre8/fs/jbd/checkpoint.c	Mon Feb 25 11:38:08 2002
+++ linux-2.4.20-pre9/fs/jbd/checkpoint.c	Thu Oct  3 18:37:58 2002
@@ -594,7 +594,8 @@
 	J_ASSERT (transaction->t_log_list == NULL);
 	J_ASSERT (transaction->t_checkpoint_list == NULL);
 	J_ASSERT (transaction->t_updates == 0);
-	
+	J_ASSERT (list_empty(&transaction->t_jcb));
+
 	J_ASSERT (transaction->t_journal->j_committing_transaction !=
 					transaction);
 	
diff -urN linux-2.4.20-pre8/fs/jbd/commit.c linux-2.4.20-pre9/fs/jbd/commit.c
--- linux-2.4.20-pre8/fs/jbd/commit.c	Thu Oct  3 18:36:50 2002
+++ linux-2.4.20-pre9/fs/jbd/commit.c	Thu Oct  3 18:37:58 2002
@@ -475,7 +475,7 @@
            transaction's t_log_list queue, and metadata buffers are on
            the t_iobuf_list queue.
 
-	   Wait for the transactions in reverse order.  That way we are
+	   Wait for the buffers in reverse order.  That way we are
 	   less likely to be woken up until all IOs have completed, and
 	   so we incur less scheduling load.
 	*/
@@ -566,8 +566,10 @@
 
 	jbd_debug(3, "JBD: commit phase 6\n");
 
-	if (is_journal_aborted(journal))
+	if (is_journal_aborted(journal)) {
+		unlock_journal(journal);
 		goto skip_commit;
+	}
 
 	/* Done it all: now write the commit record.  We should have
 	 * cleaned up our previous buffers by now, so if we are in abort
@@ -577,9 +579,10 @@
 	descriptor = journal_get_descriptor_buffer(journal);
 	if (!descriptor) {
 		__journal_abort_hard(journal);
+		unlock_journal(journal);
 		goto skip_commit;
 	}
-	
+
 	/* AKPM: buglet - add `i' to tmp! */
 	for (i = 0; i < jh2bh(descriptor)->b_size; i += 512) {
 		journal_header_t *tmp =
@@ -600,14 +603,32 @@
 		put_bh(bh);		/* One for getblk() */
 		journal_unlock_journal_head(descriptor);
 	}
-	lock_journal(journal);
 
 	/* End of a transaction!  Finally, we can do checkpoint
            processing: any buffers committed as a result of this
            transaction can be removed from any checkpoint list it was on
            before. */
 
-skip_commit:
+skip_commit: /* The journal should be unlocked by now. */
+
+	/* Call any callbacks that had been registered for handles in this
+	 * transaction.  It is up to the callback to free any allocated
+	 * memory.
+	 */
+	if (!list_empty(&commit_transaction->t_jcb)) {
+		struct list_head *p, *n;
+		int error = is_journal_aborted(journal);
+
+		list_for_each_safe(p, n, &commit_transaction->t_jcb) {
+			struct journal_callback *jcb;
+
+			jcb = list_entry(p, struct journal_callback, jcb_list);
+			list_del(p);
+			jcb->jcb_func(jcb, error);
+		}
+	}
+
+	lock_journal(journal);
 
 	jbd_debug(3, "JBD: commit phase 7\n");
 
diff -urN linux-2.4.20-pre8/fs/jbd/journal.c linux-2.4.20-pre9/fs/jbd/journal.c
--- linux-2.4.20-pre8/fs/jbd/journal.c	Thu Oct  3 18:36:50 2002
+++ linux-2.4.20-pre9/fs/jbd/journal.c	Thu Oct  3 18:37:58 2002
@@ -58,6 +58,7 @@
 #endif
 EXPORT_SYMBOL(journal_flush);
 EXPORT_SYMBOL(journal_revoke);
+EXPORT_SYMBOL(journal_callback_set);
 
 EXPORT_SYMBOL(journal_init_dev);
 EXPORT_SYMBOL(journal_init_inode);
diff -urN linux-2.4.20-pre8/fs/jbd/transaction.c linux-2.4.20-pre9/fs/jbd/transaction.c
--- linux-2.4.20-pre8/fs/jbd/transaction.c	Thu Oct  3 18:36:50 2002
+++ linux-2.4.20-pre9/fs/jbd/transaction.c	Thu Oct  3 18:37:58 2002
@@ -57,6 +57,7 @@
 	transaction->t_state = T_RUNNING;
 	transaction->t_tid = journal->j_transaction_sequence++;
 	transaction->t_expires = jiffies + journal->j_commit_interval;
+	INIT_LIST_HEAD(&transaction->t_jcb);
 
 	/* Set up the commit timer for the new transaction. */
 	J_ASSERT (!journal->j_commit_timer_active);
@@ -90,7 +91,14 @@
 	transaction_t *transaction;
 	int needed;
 	int nblocks = handle->h_buffer_credits;
-	
+
+	if (nblocks > journal->j_max_transaction_buffers) {
+		jbd_debug(1, "JBD: %s wants too many credits (%d > %d)\n",
+		       current->comm, nblocks,
+		       journal->j_max_transaction_buffers);
+		return -ENOSPC;
+	}
+
 	jbd_debug(3, "New handle %p going live.\n", handle);
 
 repeat:
@@ -201,6 +209,20 @@
 	return 0;
 }
 
+/* Allocate a new handle.  This should probably be in a slab... */
+static handle_t *new_handle(int nblocks)
+{
+	handle_t *handle = jbd_kmalloc(sizeof (handle_t), GFP_NOFS);
+	if (!handle)
+		return NULL;
+	memset(handle, 0, sizeof (handle_t));
+	handle->h_buffer_credits = nblocks;
+	handle->h_ref = 1;
+	INIT_LIST_HEAD(&handle->h_jcb);
+
+	return handle;
+}
+
 /*
  * Obtain a new handle.  
  *
@@ -227,14 +249,11 @@
 		handle->h_ref++;
 		return handle;
 	}
-	
-	handle = jbd_kmalloc(sizeof (handle_t), GFP_NOFS);
+
+	handle = new_handle(nblocks);
 	if (!handle)
 		return ERR_PTR(-ENOMEM);
-	memset (handle, 0, sizeof (handle_t));
 
-	handle->h_buffer_credits = nblocks;
-	handle->h_ref = 1;
 	current->journal_info = handle;
 
 	err = start_this_handle(journal, handle);
@@ -333,14 +352,11 @@
 	
 	if (is_journal_aborted(journal))
 		return ERR_PTR(-EIO);
-	
-	handle = jbd_kmalloc(sizeof (handle_t), GFP_NOFS);
+
+	handle = new_handle(nblocks);
 	if (!handle)
 		return ERR_PTR(-ENOMEM);
-	memset (handle, 0, sizeof (handle_t));
 
-	handle->h_buffer_credits = nblocks;
-	handle->h_ref = 1;
 	current->journal_info = handle;
 
 	err = try_start_this_handle(journal, handle);
@@ -1320,6 +1336,28 @@
 #endif
 
 /*
+ * Register a callback function for this handle.  The function will be
+ * called when the transaction that this handle is part of has been
+ * committed to disk with the original callback data struct and the
+ * error status of the journal as parameters.  There is no guarantee of
+ * ordering between handles within a single transaction, nor between
+ * callbacks registered on the same handle.
+ *
+ * The caller is responsible for allocating the journal_callback struct.
+ * This is to allow the caller to add as much extra data to the callback
+ * as needed, but reduce the overhead of multiple allocations.  The caller
+ * allocated struct must start with a struct journal_callback at offset 0,
+ * and has the caller-specific data afterwards.
+ */
+void journal_callback_set(handle_t *handle,
+			  void (*func)(struct journal_callback *jcb, int error),
+			  struct journal_callback *jcb)
+{
+	list_add_tail(&jcb->jcb_list, &handle->h_jcb);
+	jcb->jcb_func = func;
+}
+
+/*
  * All done for a particular handle.
  *
  * There is not much action needed here.  We just return any remaining
@@ -1383,7 +1421,10 @@
 			wake_up(&journal->j_wait_transaction_locked);
 	}
 
-	/* 
+	/* Move callbacks from the handle to the transaction. */
+	list_splice(&handle->h_jcb, &transaction->t_jcb);
+
+	/*
 	 * If the handle is marked SYNC, we need to set another commit
 	 * going!  We also want to force a commit if the current
 	 * transaction is occupying too much of the log, or if the
diff -urN linux-2.4.20-pre8/fs/jfs/jfs_dtree.c linux-2.4.20-pre9/fs/jfs/jfs_dtree.c
--- linux-2.4.20-pre8/fs/jfs/jfs_dtree.c	Thu Oct  3 18:36:50 2002
+++ linux-2.4.20-pre9/fs/jfs/jfs_dtree.c	Thu Oct  3 18:37:58 2002
@@ -2831,6 +2831,86 @@
 }
 
 /*
+ *	add_missing_indices()
+ *
+ * function: Fix dtree page in which one or more entries has an invalid index.
+ *	     fsck.jfs should really fix this, but it currently does not.
+ *	     Called from jfs_readdir when bad index is detected.
+ */
+static void add_missing_indices(struct inode *inode, s64 bn)
+{
+	struct ldtentry *d;
+	struct dt_lock *dtlck;
+	int i;
+	uint index;
+	struct lv *lv;
+	struct metapage *mp;
+	dtpage_t *p;
+	int rc;
+	s8 *stbl;
+	tid_t tid;
+	struct tlock *tlck;
+
+	tid = txBegin(inode->i_sb, 0);
+
+	DT_GETPAGE(inode, bn, mp, PSIZE, p, rc);
+
+	if (rc) {
+		printk(KERN_ERR "DT_GETPAGE failed!\n");
+		goto end;
+	}
+	BT_MARK_DIRTY(mp, inode);
+
+	ASSERT(p->header.flag & BT_LEAF);
+
+	tlck = txLock(tid, inode, mp, tlckDTREE | tlckENTRY);
+	dtlck = (struct dt_lock *) &tlck->lock;
+
+	stbl = DT_GETSTBL(p);
+	for (i = 0; i < p->header.nextindex; i++) {
+		d = (struct ldtentry *) &p->slot[stbl[i]];
+		index = le32_to_cpu(d->index);
+		if ((index < 2) || (index >= JFS_IP(inode)->next_index)) {
+			d->index = cpu_to_le32(add_index(tid, inode, bn, i));
+			if (dtlck->index >= dtlck->maxcnt)
+				dtlck = (struct dt_lock *) txLinelock(dtlck);
+			lv = dtlck->lv;
+			lv->offset = stbl[i];
+			lv->length = 1;
+			dtlck->index++;
+		}
+	}
+
+	DT_PUTPAGE(mp);
+	(void) txCommit(tid, 1, &inode, 0);
+end:
+	txEnd(tid);
+}
+
+/*
+ * Buffer to hold directory entry info while traversing a dtree page
+ * before being fed to the filldir function
+ */
+struct jfs_dirent {
+	loff_t position;
+	int ino;
+	u16 name_len;
+	char name[0];
+};
+
+/*
+ * function to determine next variable-sized jfs_dirent in buffer
+ */
+inline struct jfs_dirent *next_jfs_dirent(struct jfs_dirent *dirent)
+{
+	return (struct jfs_dirent *)
+		((char *)dirent +
+		 ((sizeof (struct jfs_dirent) + dirent->name_len + 1 +
+		   sizeof (loff_t) - 1) &
+		  ~(sizeof (loff_t) - 1)));
+}
+
+/*
  *	jfs_readdir()
  *
  * function: read directory entries sequentially
@@ -2846,11 +2926,12 @@
 	struct inode *ip = filp->f_dentry->d_inode;
 	struct nls_table *codepage = JFS_SBI(ip->i_sb)->nls_tab;
 	int rc = 0;
+	loff_t dtpos;	/* legacy OS/2 style position */
 	struct dtoffset {
 		s16 pn;
 		s16 index;
 		s32 unused;
-	} *dtoffset = (struct dtoffset *) &filp->f_pos;
+	} *dtoffset = (struct dtoffset *) &dtpos;
 	s64 bn;
 	struct metapage *mp;
 	dtpage_t *p;
@@ -2860,12 +2941,17 @@
 	int i, next;
 	struct ldtentry *d;
 	struct dtslot *t;
-	int d_namleft, d_namlen, len, outlen;
-	char *d_name, *name_ptr;
+	int d_namleft, len, outlen;
+	unsigned long dirent_buf;
+	char *name_ptr;
 	int dtlhdrdatalen;
 	u32 dir_index;
 	int do_index = 0;
 	uint loop_count = 0;
+	struct jfs_dirent *jfs_dirent;
+	int jfs_dirents;
+	int overflow, fix_page, page_fixed = 0;
+	static int unique_pos = 2;	/* If we can't fix broken index */
 
 	if (filp->f_pos == DIREND)
 		return 0;
@@ -2885,7 +2971,9 @@
 		if (dir_index > 1) {
 			struct dir_table_slot dirtab_slot;
 
-			if (dtEmpty(ip)) {
+			if (dtEmpty(ip) ||
+			    (dir_index >= JFS_IP(ip)->next_index)) {
+				/* Stale position.  Directory has shrunk */
 				filp->f_pos = DIREND;
 				return 0;
 			}
@@ -2963,13 +3051,15 @@
 		 */
 		dtlhdrdatalen = DTLHDRDATALEN_LEGACY;
 
-		if (filp->f_pos == 0) {
+		dtpos = filp->f_pos;
+		if (dtpos == 0) {
 			/* build "." entry */
 
 			if (filldir(dirent, ".", 1, filp->f_pos, ip->i_ino,
 				    DT_DIR))
 				return 0;
 			dtoffset->index = 1;
+			filp->f_pos = dtpos;
 		}
 
 		if (dtoffset->pn == 0) {
@@ -2985,6 +3075,7 @@
 			}
 			dtoffset->pn = 1;
 			dtoffset->index = 0;
+			filp->f_pos = dtpos;
 		}
 
 		if (dtEmpty(ip)) {
@@ -3009,32 +3100,72 @@
 		}
 	}
 
-	d_name = kmalloc((JFS_NAME_MAX + 1) * sizeof(wchar_t), GFP_NOFS);
-	if (d_name == NULL) {
+	dirent_buf = __get_free_page(GFP_KERNEL);
+	if (dirent_buf == 0) {
 		DT_PUTPAGE(mp);
-		jERROR(1, ("jfs_readdir: kmalloc failed!\n"));
+		jERROR(1, ("jfs_readdir: __get_free_page failed!\n"));
 		filp->f_pos = DIREND;
-		return 0;
+		return -ENOMEM;
 	}
+
 	while (1) {
+		jfs_dirent = (struct jfs_dirent *) dirent_buf;
+		jfs_dirents = 0;
+		overflow = fix_page = 0;
+
 		stbl = DT_GETSTBL(p);
 
 		for (i = index; i < p->header.nextindex; i++) {
 			d = (struct ldtentry *) & p->slot[stbl[i]];
 
+			if (((long) jfs_dirent + d->namlen + 1) >
+			    (dirent_buf + PSIZE)) {
+				/* DBCS codepages could overrun dirent_buf */
+				index = i;
+				overflow = 1;
+				break;
+			}
+
 			d_namleft = d->namlen;
-			name_ptr = d_name;
+			name_ptr = jfs_dirent->name;
+			jfs_dirent->ino = le32_to_cpu(d->inumber);
 
 			if (do_index) {
-				filp->f_pos = le32_to_cpu(d->index);
 				len = min(d_namleft, DTLHDRDATALEN);
-			} else
+				jfs_dirent->position = le32_to_cpu(d->index);
+				/*
+				 * d->index should always be valid, but it
+				 * isn't.  fsck.jfs doesn't create the
+				 * directory index for the lost+found
+				 * directory.  Rather than let it go,
+				 * we can try to fix it.
+				 */
+				if ((jfs_dirent->position < 2) ||
+				    (jfs_dirent->position >=
+				     JFS_IP(ip)->next_index)) {
+					if (!page_fixed && !isReadOnly(ip)) {
+						fix_page = 1;
+						/*
+						 * setting overflow and setting
+						 * index to i will cause the
+						 * same page to be processed
+						 * again starting here
+						 */
+						overflow = 1;
+						index = i;
+						break;
+					}
+					jfs_dirent->position = unique_pos++;
+				}
+			} else {
+				jfs_dirent->position = dtpos;
 				len = min(d_namleft, DTLHDRDATALEN_LEGACY);
+			}
 
 			/* copy the name of head/only segment */
 			outlen = jfs_strfromUCS_le(name_ptr, d->name, len,
 						   codepage);
-			d_namlen = outlen;
+			jfs_dirent->name_len = outlen;
 
 			/* copy name in the additional segment(s) */
 			next = d->next;
@@ -3053,56 +3184,66 @@
 				len = min(d_namleft, DTSLOTDATALEN);
 				outlen = jfs_strfromUCS_le(name_ptr, t->name,
 							   len, codepage);
-				d_namlen+= outlen;
+				jfs_dirent->name_len += outlen;
 
 				next = t->next;
 			}
 
-			if (filldir(dirent, d_name, d_namlen, filp->f_pos,
-				    le32_to_cpu(d->inumber), DT_UNKNOWN))
-				goto out;
+			jfs_dirents++;
+			jfs_dirent = next_jfs_dirent(jfs_dirent);
 skip_one:
 			if (!do_index)
 				dtoffset->index++;
 		}
 
-		/*
-		 * get next leaf page
-		 */
+		if (!overflow) {
+			/* Point to next leaf page */
+			if (p->header.flag & BT_ROOT)
+				bn = 0;
+			else {
+				bn = le64_to_cpu(p->header.next);
+				index = 0;
+				/* update offset (pn:index) for new page */
+				if (!do_index) {
+					dtoffset->pn++;
+					dtoffset->index = 0;
+				}
+			}
+			page_fixed = 0;
+		}
 
-		if (p->header.flag & BT_ROOT) {
-			filp->f_pos = DIREND;
-			break;
+		/* unpin previous leaf page */
+		DT_PUTPAGE(mp);
+
+		jfs_dirent = (struct jfs_dirent *) dirent_buf;
+		while (jfs_dirents--) {
+			filp->f_pos = jfs_dirent->position;
+			if (filldir(dirent, jfs_dirent->name,
+				    jfs_dirent->name_len, filp->f_pos,
+				    jfs_dirent->ino, DT_UNKNOWN))
+				goto out;
+			jfs_dirent = next_jfs_dirent(jfs_dirent);
+		}
+
+		if (fix_page) {
+			add_missing_indices(ip, bn);
+			page_fixed = 1;
 		}
 
-		bn = le64_to_cpu(p->header.next);
-		if (bn == 0) {
+		if (!overflow && (bn == 0)) {
 			filp->f_pos = DIREND;
 			break;
 		}
 
-		/* unpin previous leaf page */
-		DT_PUTPAGE(mp);
-
-		/* get next leaf page */
 		DT_GETPAGE(ip, bn, mp, PSIZE, p, rc);
 		if (rc) {
-			kfree(d_name);
+			free_page(dirent_buf);
 			return -rc;
 		}
-
-		/* update offset (pn:index) for new page */
-		index = 0;
-		if (!do_index) {
-			dtoffset->pn++;
-			dtoffset->index = 0;
-		}
-
 	}
 
       out:
-	kfree(d_name);
-	DT_PUTPAGE(mp);
+	free_page(dirent_buf);
 
 	return rc;
 }
diff -urN linux-2.4.20-pre8/fs/jfs/jfs_imap.c linux-2.4.20-pre9/fs/jfs/jfs_imap.c
--- linux-2.4.20-pre8/fs/jfs/jfs_imap.c	Thu Oct  3 18:36:50 2002
+++ linux-2.4.20-pre9/fs/jfs/jfs_imap.c	Thu Oct  3 18:37:58 2002
@@ -363,11 +363,7 @@
 
 	if ((lengthPXD(&iagp->inoext[extno]) != imap->im_nbperiext) ||
 	    (addressPXD(&iagp->inoext[extno]) == 0)) {
-		jERROR(1, ("diRead: Bad inoext: 0x%lx, 0x%lx\n",
-			   (ulong) addressPXD(&iagp->inoext[extno]),
-			   (ulong) lengthPXD(&iagp->inoext[extno])));
 		release_metapage(mp);
-		updateSuper(ip->i_sb, FM_DIRTY);
 		return ESTALE;
 	}
 
@@ -414,12 +410,9 @@
 		jERROR(1, ("diRead: i_ino != di_number\n"));
 		updateSuper(ip->i_sb, FM_DIRTY);
 		rc = EIO;
-	} else if (le32_to_cpu(dp->di_nlink) == 0) {
-		jERROR(1,
-		       ("diRead: di_nlink is zero. ino=%ld\n", ip->i_ino));
-		updateSuper(ip->i_sb, FM_DIRTY);
+	} else if (le32_to_cpu(dp->di_nlink) == 0)
 		rc = ESTALE;
-	} else
+	else
 		/* copy the disk inode to the in-memory inode */
 		rc = copy_from_dinode(dp, ip);
 
diff -urN linux-2.4.20-pre8/fs/jfs/jfs_logmgr.c linux-2.4.20-pre9/fs/jfs/jfs_logmgr.c
--- linux-2.4.20-pre8/fs/jfs/jfs_logmgr.c	Thu Oct  3 18:36:50 2002
+++ linux-2.4.20-pre9/fs/jfs/jfs_logmgr.c	Thu Oct  3 18:37:58 2002
@@ -1542,7 +1542,12 @@
 				memcpy(logsuper->active[i].uuid, NULL_UUID, 16);
 				break;
 			}
-		assert(i < MAX_ACTIVE);
+		if (i == MAX_ACTIVE) {
+			jERROR(1,("Somebody stomped on the journal!\n"));
+			lbmFree(bpsuper);
+			return EIO;
+		}
+		
 	}
 
 	/*
diff -urN linux-2.4.20-pre8/fs/partitions/sun.c linux-2.4.20-pre9/fs/partitions/sun.c
--- linux-2.4.20-pre8/fs/partitions/sun.c	Mon Oct  1 20:03:26 2001
+++ linux-2.4.20-pre9/fs/partitions/sun.c	Thu Oct  3 18:37:58 2002
@@ -7,6 +7,7 @@
  *  Re-organised Feb 1998 Russell King
  */
 
+#include <linux/config.h>
 #include <linux/fs.h>
 #include <linux/genhd.h>
 #include <linux/kernel.h>
@@ -19,6 +20,10 @@
 #include "check.h"
 #include "sun.h"
 
+#ifdef CONFIG_BLK_DEV_MD
+extern void md_autodetect_dev(kdev_t dev);
+#endif
+
 int sun_partition(struct gendisk *hd, struct block_device *bdev, unsigned long first_sector, int first_part_minor)
 {
 	int i, csum;
@@ -27,7 +32,14 @@
 	kdev_t dev = to_kdev_t(bdev->bd_dev);
 	struct sun_disklabel {
 		unsigned char info[128];   /* Informative text string */
-		unsigned char spare[292];  /* Boot information etc. */
+		unsigned char spare0[14];
+		struct sun_info {
+			unsigned char spare1;
+			unsigned char id;
+			unsigned char spare2;
+			unsigned char flags;
+		} infos[8];
+		unsigned char spare[246];  /* Boot information etc. */
 		unsigned short rspeed;     /* Disk rotational speed */
 		unsigned short pcylcount;  /* Physical cylinder count */
 		unsigned short sparecyl;   /* extra sects per cylinder */
@@ -63,22 +75,30 @@
 	ush = ((unsigned short *) (label+1)) - 1;
 	for (csum = 0; ush >= ((unsigned short *) label);)
 		csum ^= *ush--;
-	if(csum) {
+	if (csum) {
 		printk("Dev %s Sun disklabel: Csum bad, label corrupted\n",
 		       bdevname(dev));
 		put_dev_sector(sect);
 		return 0;
 	}
+
 	/* All Sun disks have 8 partition entries */
 	spc = be16_to_cpu(label->ntrks) * be16_to_cpu(label->nsect);
-	for(i=0; i < 8; i++, p++) {
+	for (i = 0; i < 8; i++, p++) {
 		unsigned long st_sector;
 		int num_sectors;
 
 		st_sector = first_sector + be32_to_cpu(p->start_cylinder) * spc;
 		num_sectors = be32_to_cpu(p->num_sectors);
-		if (num_sectors)
-			add_gd_partition(hd, first_part_minor, st_sector, num_sectors);
+		if (num_sectors) {
+			add_gd_partition(hd, first_part_minor,
+					 st_sector, num_sectors);
+#ifdef CONFIG_BLK_DEV_MD
+			if (label->infos[i].id == LINUX_RAID_PARTITION)
+				md_autodetect_dev(MKDEV(hd->major,
+							first_part_minor));
+#endif
+		}
 		first_part_minor++;
 	}
 	printk("\n");
diff -urN linux-2.4.20-pre8/include/linux/ext3_fs.h linux-2.4.20-pre9/include/linux/ext3_fs.h
--- linux-2.4.20-pre8/include/linux/ext3_fs.h	Mon Feb 25 11:38:13 2002
+++ linux-2.4.20-pre9/include/linux/ext3_fs.h	Thu Oct  3 18:38:00 2002
@@ -36,8 +36,8 @@
 /*
  * The second extended file system version
  */
-#define EXT3FS_DATE		"10 Jan 2002"
-#define EXT3FS_VERSION		"2.4-0.9.17"
+#define EXT3FS_DATE		"19 August 2002"
+#define EXT3FS_VERSION		"2.4-0.9.19"
 
 /*
  * Debug code
diff -urN linux-2.4.20-pre8/include/linux/jbd.h linux-2.4.20-pre9/include/linux/jbd.h
--- linux-2.4.20-pre8/include/linux/jbd.h	Thu Oct  3 18:36:50 2002
+++ linux-2.4.20-pre9/include/linux/jbd.h	Thu Oct  3 18:38:00 2002
@@ -257,6 +257,13 @@
 	return bh->b_private;
 }
 
+#define HAVE_JOURNAL_CALLBACK_STATUS
+struct journal_callback {
+	struct list_head jcb_list;
+	void (*jcb_func)(struct journal_callback *jcb, int error);
+	/* user data goes here */
+};
+
 struct jbd_revoke_table_s;
 
 /* The handle_t type represents a single atomic update being performed
@@ -287,6 +294,12 @@
 	   operations */
 	int			h_err;
 
+	/* List of application registered callbacks for this handle.
+	 * The function(s) will be called after the transaction that
+	 * this handle is part of has been committed to disk.
+	 */
+	struct list_head	h_jcb;
+
 	/* Flags */
 	unsigned int	h_sync:		1;	/* sync-on-close */
 	unsigned int	h_jdata:	1;	/* force data journaling */
@@ -406,6 +419,10 @@
 
 	/* How many handles used this transaction? */
 	int t_handle_count;
+
+	/* List of registered callback functions for this transaction.
+	 * Called when the transaction is committed. */
+	struct list_head	t_jcb;
 };
 
 
@@ -654,6 +671,9 @@
 extern int	 journal_try_to_free_buffers(journal_t *, struct page *, int);
 extern int	 journal_stop(handle_t *);
 extern int	 journal_flush (journal_t *);
+extern void	 journal_callback_set(handle_t *handle,
+				      void (*fn)(struct journal_callback *,int),
+				      struct journal_callback *jcb);
 
 extern void	 journal_lock_updates (journal_t *);
 extern void	 journal_unlock_updates (journal_t *);
diff -urN linux-2.4.20-pre8/include/linux/list.h linux-2.4.20-pre9/include/linux/list.h
--- linux-2.4.20-pre8/include/linux/list.h	Thu Oct  3 18:36:50 2002
+++ linux-2.4.20-pre9/include/linux/list.h	Thu Oct  3 18:38:00 2002
@@ -19,12 +19,10 @@
 	struct list_head *next, *prev;
 };
 
-typedef struct list_head list_t;
-
 #define LIST_HEAD_INIT(name) { &(name), &(name) }
 
 #define LIST_HEAD(name) \
-	list_t name = LIST_HEAD_INIT(name)
+	struct list_head name = LIST_HEAD_INIT(name)
 
 #define INIT_LIST_HEAD(ptr) do { \
 	(ptr)->next = (ptr); (ptr)->prev = (ptr); \
@@ -36,7 +34,9 @@
  * This is only for internal list manipulation where we know
  * the prev/next entries already!
  */
-static inline void __list_add(list_t *new, list_t *prev, list_t *next)
+static inline void __list_add(struct list_head *new,
+			      struct list_head *prev,
+			      struct list_head *next)
 {
 	next->prev = new;
 	new->next = next;
@@ -52,7 +52,7 @@
  * Insert a new entry after the specified head.
  * This is good for implementing stacks.
  */
-static inline void list_add(list_t *new, list_t *head)
+static inline void list_add(struct list_head *new, struct list_head *head)
 {
 	__list_add(new, head, head->next);
 }
@@ -65,7 +65,7 @@
  * Insert a new entry before the specified head.
  * This is useful for implementing queues.
  */
-static inline void list_add_tail(list_t *new, list_t *head)
+static inline void list_add_tail(struct list_head *new, struct list_head *head)
 {
 	__list_add(new, head->prev, head);
 }
@@ -77,7 +77,7 @@
  * This is only for internal list manipulation where we know
  * the prev/next entries already!
  */
-static inline void __list_del(list_t * prev, list_t * next)
+static inline void __list_del(struct list_head *prev, struct list_head *next)
 {
 	next->prev = prev;
 	prev->next = next;
@@ -88,7 +88,7 @@
  * @entry: the element to delete from the list.
  * Note: list_empty on entry does not return true after this, the entry is in an undefined state.
  */
-static inline void list_del(list_t *entry)
+static inline void list_del(struct list_head *entry)
 {
 	__list_del(entry->prev, entry->next);
 	entry->next = (void *) 0;
@@ -99,7 +99,7 @@
  * list_del_init - deletes entry from list and reinitialize it.
  * @entry: the element to delete from the list.
  */
-static inline void list_del_init(list_t *entry)
+static inline void list_del_init(struct list_head *entry)
 {
 	__list_del(entry->prev, entry->next);
 	INIT_LIST_HEAD(entry); 
@@ -110,7 +110,7 @@
  * @list: the entry to move
  * @head: the head that will precede our entry
  */
-static inline void list_move(list_t *list, list_t *head)
+static inline void list_move(struct list_head *list, struct list_head *head)
 {
         __list_del(list->prev, list->next);
         list_add(list, head);
@@ -121,7 +121,8 @@
  * @list: the entry to move
  * @head: the head that will follow our entry
  */
-static inline void list_move_tail(list_t *list, list_t *head)
+static inline void list_move_tail(struct list_head *list,
+				  struct list_head *head)
 {
         __list_del(list->prev, list->next);
         list_add_tail(list, head);
@@ -131,16 +132,17 @@
  * list_empty - tests whether a list is empty
  * @head: the list to test.
  */
-static inline int list_empty(list_t *head)
+static inline int list_empty(struct list_head *head)
 {
 	return head->next == head;
 }
 
-static inline void __list_splice(list_t *list, list_t *head)
+static inline void __list_splice(struct list_head *list,
+				 struct list_head *head)
 {
-	list_t *first = list->next;
-	list_t *last = list->prev;
-	list_t *at = head->next;
+	struct list_head *first = list->next;
+	struct list_head *last = list->prev;
+	struct list_head *at = head->next;
 
 	first->prev = head;
 	head->next = first;
@@ -154,7 +156,7 @@
  * @list: the new list to add.
  * @head: the place to add it in the first list.
  */
-static inline void list_splice(list_t *list, list_t *head)
+static inline void list_splice(struct list_head *list, struct list_head *head)
 {
 	if (!list_empty(list))
 		__list_splice(list, head);
@@ -167,7 +169,8 @@
  *
  * The list at @list is reinitialised
  */
-static inline void list_splice_init(list_t *list, list_t *head)
+static inline void list_splice_init(struct list_head *list,
+				    struct list_head *head)
 {
 	if (!list_empty(list)) {
 		__list_splice(list, head);
@@ -177,7 +180,7 @@
 
 /**
  * list_entry - get the struct for this entry
- * @ptr:	the &list_t pointer.
+ * @ptr:	the &struct list_head pointer.
  * @type:	the type of the struct this is embedded in.
  * @member:	the name of the list_struct within the struct.
  */
@@ -186,7 +189,7 @@
 
 /**
  * list_for_each	-	iterate over a list
- * @pos:	the &list_t to use as a loop counter.
+ * @pos:	the &struct list_head to use as a loop counter.
  * @head:	the head for your list.
  */
 #define list_for_each(pos, head) \
@@ -194,7 +197,7 @@
         	pos = pos->next, prefetch(pos->next))
 /**
  * list_for_each_prev	-	iterate over a list backwards
- * @pos:	the &list_t to use as a loop counter.
+ * @pos:	the &struct list_head to use as a loop counter.
  * @head:	the head for your list.
  */
 #define list_for_each_prev(pos, head) \
@@ -203,8 +206,8 @@
         	
 /**
  * list_for_each_safe	-	iterate over a list safe against removal of list entry
- * @pos:	the &list_t to use as a loop counter.
- * @n:		another &list_t to use as temporary storage
+ * @pos:	the &struct list_head to use as a loop counter.
+ * @n:		another &struct list_head to use as temporary storage
  * @head:	the head for your list.
  */
 #define list_for_each_safe(pos, n, head) \
diff -urN linux-2.4.20-pre8/include/linux/mii.h linux-2.4.20-pre9/include/linux/mii.h
--- linux-2.4.20-pre8/include/linux/mii.h	Mon Feb 25 11:38:13 2002
+++ linux-2.4.20-pre9/include/linux/mii.h	Thu Oct  3 18:38:00 2002
@@ -107,9 +107,11 @@
 struct mii_if_info {
 	int phy_id;
 	int advertising;
+	int phy_id_mask;
+	int reg_num_mask;
 
-	unsigned int full_duplex : 1;
-	unsigned int duplex_lock : 1;
+	unsigned int full_duplex : 1;	/* is full duplex? */
+	unsigned int force_media : 1;	/* is autoneg. disabled? */
 
 	struct net_device *dev;
 	int (*mdio_read) (struct net_device *dev, int phy_id, int location);
@@ -117,11 +119,20 @@
 };
 
 struct ethtool_cmd;
+struct mii_ioctl_data;
+
+extern int mii_link_ok (struct mii_if_info *mii);
+extern int mii_nway_restart (struct mii_if_info *mii);
+extern int mii_ethtool_gset(struct mii_if_info *mii, struct ethtool_cmd *ecmd);
+extern int mii_ethtool_sset(struct mii_if_info *mii, struct ethtool_cmd *ecmd);
+extern void mii_check_link (struct mii_if_info *mii);
+extern unsigned int mii_check_media (struct mii_if_info *mii,
+				     unsigned int ok_to_print,
+				     unsigned int init_media);
+extern int generic_mii_ioctl(struct mii_if_info *mii_if,
+                      	     struct mii_ioctl_data *mii_data, int cmd,
+			     unsigned int *duplex_changed);
 
-int mii_link_ok (struct mii_if_info *mii);
-int mii_nway_restart (struct mii_if_info *mii);
-int mii_ethtool_gset(struct mii_if_info *mii, struct ethtool_cmd *ecmd);
-int mii_ethtool_sset(struct mii_if_info *mii, struct ethtool_cmd *ecmd);
 
 
 /* This structure is used in all SIOCxMIIxxx ioctl calls */
diff -urN linux-2.4.20-pre8/include/linux/pci_ids.h linux-2.4.20-pre9/include/linux/pci_ids.h
--- linux-2.4.20-pre8/include/linux/pci_ids.h	Thu Oct  3 18:36:50 2002
+++ linux-2.4.20-pre9/include/linux/pci_ids.h	Thu Oct  3 18:38:00 2002
@@ -511,6 +511,8 @@
 #define PCI_DEVICE_ID_HP_DIVA1		0x1049
 #define PCI_DEVICE_ID_HP_DIVA2		0x104A
 #define PCI_DEVICE_ID_HP_SP2_0		0x104B
+#define PCI_DEVICE_ID_HP_REO_SBA	0x10f0
+#define PCI_DEVICE_ID_HP_REO_IOC	0x10f1
 #define PCI_DEVICE_ID_HP_ZX1_SBA	0x1229
 #define PCI_DEVICE_ID_HP_ZX1_IOC	0x122a
 #define PCI_DEVICE_ID_HP_ZX1_LBA	0x122e
diff -urN linux-2.4.20-pre8/include/net/ndisc.h linux-2.4.20-pre9/include/net/ndisc.h
--- linux-2.4.20-pre8/include/net/ndisc.h	Fri Aug  2 17:39:46 2002
+++ linux-2.4.20-pre9/include/net/ndisc.h	Thu Oct  3 18:38:00 2002
@@ -51,6 +51,25 @@
 	__u32			retrans_timer;
 };
 
+struct nd_opt_hdr {
+	__u8		nd_opt_type;
+	__u8		nd_opt_len;
+} __attribute__((__packed__));
+
+struct ndisc_options {
+	struct nd_opt_hdr *nd_opt_array[7];
+	struct nd_opt_hdr *nd_opt_piend;
+};
+
+#define nd_opts_src_lladdr	nd_opt_array[ND_OPT_SOURCE_LL_ADDR]
+#define nd_opts_tgt_lladdr	nd_opt_array[ND_OPT_TARGET_LL_ADDR]
+#define nd_opts_pi		nd_opt_array[ND_OPT_PREFIX_INFO]
+#define nd_opts_pi_end		nd_opt_piend
+#define nd_opts_rh		nd_opt_array[ND_OPT_REDIRECT_HDR]
+#define nd_opts_mtu		nd_opt_array[ND_OPT_MTU]
+
+extern struct nd_opt_hdr *ndisc_next_option(struct nd_opt_hdr *cur, struct nd_opt_hdr *end);
+extern struct ndisc_options *ndisc_parse_options(u8 *opt, int opt_len, struct ndisc_options *ndopts);
 
 extern int			ndisc_init(struct net_proto_family *ops);
 
diff -urN linux-2.4.20-pre8/init/do_mounts.c linux-2.4.20-pre9/init/do_mounts.c
--- linux-2.4.20-pre8/init/do_mounts.c	Thu Oct  3 18:36:50 2002
+++ linux-2.4.20-pre9/init/do_mounts.c	Thu Oct  3 18:38:00 2002
@@ -886,7 +886,7 @@
 	mount_devfs_fs ();
 }
 
-#ifdef BUILD_CRAMDISK
+#if defined(BUILD_CRAMDISK) && defined(CONFIG_BLK_DEV_RAM)
 
 /*
  * gzip declarations
@@ -1031,4 +1031,4 @@
 	return result;
 }
 
-#endif  /* BUILD_CRAMDISK */
+#endif  /* BUILD_CRAMDISK && CONFIG_BLK_DEV_RAM */
diff -urN linux-2.4.20-pre8/net/ipv4/netfilter/ip_conntrack_proto_tcp.c linux-2.4.20-pre9/net/ipv4/netfilter/ip_conntrack_proto_tcp.c
--- linux-2.4.20-pre8/net/ipv4/netfilter/ip_conntrack_proto_tcp.c	Thu Oct  3 18:36:50 2002
+++ linux-2.4.20-pre9/net/ipv4/netfilter/ip_conntrack_proto_tcp.c	Thu Oct  3 18:38:01 2002
@@ -7,6 +7,7 @@
 #include <linux/in.h>
 #include <linux/ip.h>
 #include <linux/tcp.h>
+#include <linux/string.h>
 
 #include <net/tcp.h>
 
diff -urN linux-2.4.20-pre8/net/ipv4/netfilter/ipchains_core.c linux-2.4.20-pre9/net/ipv4/netfilter/ipchains_core.c
--- linux-2.4.20-pre8/net/ipv4/netfilter/ipchains_core.c	Thu Oct  3 18:36:50 2002
+++ linux-2.4.20-pre9/net/ipv4/netfilter/ipchains_core.c	Thu Oct  3 18:38:01 2002
@@ -1252,7 +1252,7 @@
 		return NULL;
 	}
 
-	fwkern = kmalloc(SIZEOF_STRUCT_IP_FW_KERNEL, GFP_KERNEL);
+	fwkern = kmalloc(SIZEOF_STRUCT_IP_FW_KERNEL, GFP_ATOMIC);
 	if (!fwkern) {
 		duprintf("convert_ipfw: kmalloc failed!\n");
 		*errno = ENOMEM;
diff -urN linux-2.4.20-pre8/net/ipv4/netfilter/ipt_ULOG.c linux-2.4.20-pre9/net/ipv4/netfilter/ipt_ULOG.c
--- linux-2.4.20-pre8/net/ipv4/netfilter/ipt_ULOG.c	Thu Oct  3 18:36:50 2002
+++ linux-2.4.20-pre9/net/ipv4/netfilter/ipt_ULOG.c	Thu Oct  3 18:38:01 2002
@@ -50,7 +50,7 @@
 #include <linux/netfilter_ipv4/ipt_ULOG.h>
 #include <linux/netfilter_ipv4/lockhelp.h>
 #include <net/sock.h>
-#include <asm/bitops.h>
+#include <linux/bitops.h>
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>");
diff -urN linux-2.4.20-pre8/net/ipv4/netfilter/ipt_unclean.c linux-2.4.20-pre9/net/ipv4/netfilter/ipt_unclean.c
--- linux-2.4.20-pre8/net/ipv4/netfilter/ipt_unclean.c	Fri Dec 21 09:42:05 2001
+++ linux-2.4.20-pre9/net/ipv4/netfilter/ipt_unclean.c	Thu Oct  3 18:38:01 2002
@@ -211,7 +211,7 @@
 
 	/* Bad checksum?  Don't print, just say it's unclean. */
 	/* FIXME: SRC ROUTE packets won't match checksum --RR */
-	if (!more_frags && !embedded
+	if (!more_frags && !embedded && udph->check
 	    && csum_tcpudp_magic(iph->saddr, iph->daddr, datalen, IPPROTO_UDP,
 				 csum_partial((char *)udph, datalen, 0)) != 0)
 		return 0;
diff -urN linux-2.4.20-pre8/net/ipv4/proc.c linux-2.4.20-pre9/net/ipv4/proc.c
--- linux-2.4.20-pre8/net/ipv4/proc.c	Wed May 16 10:21:45 2001
+++ linux-2.4.20-pre9/net/ipv4/proc.c	Thu Oct  3 18:38:01 2002
@@ -128,7 +128,7 @@
 	len += sprintf (buffer + len,
 		"\nIcmp: InMsgs InErrors InDestUnreachs InTimeExcds InParmProbs InSrcQuenchs InRedirects InEchos InEchoReps InTimestamps InTimestampReps InAddrMasks InAddrMaskReps OutMsgs OutErrors OutDestUnreachs OutTimeExcds OutParmProbs OutSrcQuenchs OutRedirects OutEchos OutEchoReps OutTimestamps OutTimestampReps OutAddrMasks OutAddrMaskReps\n"
 		  "Icmp:");
-	for (i=0; i<offsetof(struct icmp_mib, __pad)/sizeof(unsigned long); i++)
+	for (i=0; i<offsetof(struct icmp_mib, dummy)/sizeof(unsigned long); i++)
 		len += sprintf(buffer+len, " %lu", fold_field((unsigned long*)icmp_statistics, sizeof(struct icmp_mib), i));
 
 	len += sprintf (buffer + len,
diff -urN linux-2.4.20-pre8/net/ipv6/addrconf.c linux-2.4.20-pre9/net/ipv6/addrconf.c
--- linux-2.4.20-pre8/net/ipv6/addrconf.c	Fri Aug  2 17:39:46 2002
+++ linux-2.4.20-pre9/net/ipv6/addrconf.c	Thu Oct  3 18:38:01 2002
@@ -26,6 +26,8 @@
  *						packets.
  *	yoshfuji@USAGI			:       Fixed interval between DAD
  *						packets.
+ *	YOSHIFUJI Hideaki @USAGI	:	improved accuracy of
+ *						address validation timer.
  */
 
 #include <linux/config.h>
@@ -93,6 +95,7 @@
 void addrconf_verify(unsigned long);
 
 static struct timer_list addr_chk_timer = { function: addrconf_verify };
+static spinlock_t addrconf_verify_lock = SPIN_LOCK_UNLOCKED;
 
 static int addrconf_ifdown(struct net_device *dev, int how);
 
@@ -1616,9 +1619,15 @@
 void addrconf_verify(unsigned long foo)
 {
 	struct inet6_ifaddr *ifp;
-	unsigned long now = jiffies;
+	unsigned long now, next;
 	int i;
 
+	spin_lock_bh(&addrconf_verify_lock);
+	now = jiffies;
+	next = now + ADDR_CHECK_FREQUENCY;
+
+	del_timer(&addr_chk_timer);
+
 	for (i=0; i < IN6_ADDR_HSIZE; i++) {
 
 restart:
@@ -1629,21 +1638,27 @@
 			if (ifp->flags & IFA_F_PERMANENT)
 				continue;
 
+			spin_lock(&ifp->lock);
 			age = (now - ifp->tstamp) / HZ;
 
-			if (age > ifp->valid_lft) {
+			if (age >= ifp->valid_lft) {
+				spin_unlock(&ifp->lock);
 				in6_ifa_hold(ifp);
 				write_unlock(&addrconf_hash_lock);
 				ipv6_del_addr(ifp);
 				goto restart;
-			} else if (age > ifp->prefered_lft) {
+			} else if (age >= ifp->prefered_lft) {
+				/* jiffies - ifp->tsamp > age >= ifp->prefered_lft */
 				int deprecate = 0;
 
-				spin_lock(&ifp->lock);
 				if (!(ifp->flags&IFA_F_DEPRECATED)) {
 					deprecate = 1;
 					ifp->flags |= IFA_F_DEPRECATED;
 				}
+
+				if (time_before(ifp->tstamp + ifp->valid_lft * HZ, next))
+					next = ifp->tstamp + ifp->valid_lft * HZ;
+
 				spin_unlock(&ifp->lock);
 
 				if (deprecate) {
@@ -1654,12 +1669,19 @@
 					in6_ifa_put(ifp);
 					goto restart;
 				}
+			} else {
+				/* ifp->prefered_lft <= ifp->valid_lft */
+				if (time_before(ifp->tstamp + ifp->prefered_lft * HZ, next))
+					next = ifp->tstamp + ifp->prefered_lft * HZ;
+				spin_unlock(&ifp->lock);
 			}
 		}
 		write_unlock(&addrconf_hash_lock);
 	}
 
-	mod_timer(&addr_chk_timer, jiffies + ADDR_CHECK_FREQUENCY);
+	addr_chk_timer.expires = time_before(next, jiffies + HZ) ? jiffies + HZ : next;
+	add_timer(&addr_chk_timer);
+	spin_unlock_bh(&addrconf_verify_lock);
 }
 
 static int
@@ -2033,8 +2055,7 @@
 	proc_net_create("if_inet6", 0, iface_proc_info);
 #endif
 	
-	addr_chk_timer.expires = jiffies + ADDR_CHECK_FREQUENCY;
-	add_timer(&addr_chk_timer);
+	addrconf_verify(0);
 	rtnetlink_links[PF_INET6] = inet6_rtnetlink_table;
 #ifdef CONFIG_SYSCTL
 	addrconf_sysctl.sysctl_header =
diff -urN linux-2.4.20-pre8/net/ipv6/ip6_fib.c linux-2.4.20-pre9/net/ipv6/ip6_fib.c
--- linux-2.4.20-pre8/net/ipv6/ip6_fib.c	Fri Dec 21 09:42:05 2001
+++ linux-2.4.20-pre9/net/ipv6/ip6_fib.c	Thu Oct  3 18:38:01 2002
@@ -13,6 +13,12 @@
  *      2 of the License, or (at your option) any later version.
  */
 
+/*
+ * 	Changes:
+ * 	Yuji SEKIYA @USAGI:	Support default route on router node;
+ * 				remove ip6_null_entry from the top of
+ * 				routing table.
+ */
 #include <linux/config.h>
 #include <linux/errno.h>
 #include <linux/types.h>
@@ -248,9 +254,6 @@
 
 	fn = root;
 
-	if (plen == 0)
-		return fn;
-
 	do {
 		key = (struct rt6key *)((u8 *)fn->leaf + offset);
 
@@ -427,6 +430,17 @@
 
 	ins = &fn->leaf;
 
+	if (fn->fn_flags&RTN_TL_ROOT &&
+	    fn->leaf == &ip6_null_entry &&
+	    !(rt->rt6i_flags & (RTF_DEFAULT | RTF_ADDRCONF | RTF_ALLONLINK)) ){
+		/*
+		 * The top fib of ip6 routing table includes ip6_null_entry.
+		 */
+		fn->leaf = rt;
+		rt->u.next = NULL;
+		goto out;
+	}
+
 	for (iter = fn->leaf; iter; iter=iter->u.next) {
 		/*
 		 *	Search for duplicates
@@ -462,6 +476,7 @@
 	 *	insert node
 	 */
 
+out:
 	rt->u.next = iter;
 	*ins = rt;
 	rt->rt6i_node = fn;
@@ -675,7 +690,7 @@
 
 	fn = fib6_lookup_1(root, args);
 
-	if (fn == NULL)
+	if (fn == NULL || fn->fn_flags & RTN_TL_ROOT)
 		fn = root;
 
 	return fn;
@@ -897,6 +912,9 @@
 
 	rt->u.next = NULL;
 
+	if (fn->leaf == NULL && fn->fn_flags&RTN_TL_ROOT)
+		fn->leaf = &ip6_null_entry;
+
 	/* If it was last route, expunge its radix tree node */
 	if (fn->leaf == NULL) {
 		fn->fn_flags &= ~RTN_RTINFO;
diff -urN linux-2.4.20-pre8/net/ipv6/ndisc.c linux-2.4.20-pre9/net/ipv6/ndisc.c
--- linux-2.4.20-pre8/net/ipv6/ndisc.c	Fri Aug  2 17:39:46 2002
+++ linux-2.4.20-pre9/net/ipv6/ndisc.c	Thu Oct  3 18:38:01 2002
@@ -22,6 +22,7 @@
  *	Alexey Kuznetsov		:	state machine reworked
  *						and moved to net/core.
  *	Pekka Savola			:	RFC2461 validation
+ *	YOSHIFUJI Hideaki @USAGI	:	Verify ND options properly
  */
 
 /* Set to 3 to get tracing... */
@@ -154,6 +155,67 @@
 	return opt + space;
 }
 
+struct nd_opt_hdr *ndisc_next_option(struct nd_opt_hdr *cur,
+				     struct nd_opt_hdr *end)
+{
+	int type;
+	if (!cur || !end || cur >= end)
+		return NULL;
+	type = cur->nd_opt_type;
+	do {
+		cur = ((void *)cur) + (cur->nd_opt_len << 3);
+	} while(cur < end && cur->nd_opt_type != type);
+	return (cur <= end && cur->nd_opt_type == type ? cur : NULL);
+}
+
+struct ndisc_options *ndisc_parse_options(u8 *opt, int opt_len,
+					  struct ndisc_options *ndopts)
+{
+	struct nd_opt_hdr *nd_opt = (struct nd_opt_hdr *)opt;
+
+	if (!nd_opt || opt_len < 0 || !ndopts)
+		return NULL;
+	memset(ndopts, 0, sizeof(*ndopts));
+	while (opt_len) {
+		int l;
+		if (opt_len < sizeof(struct nd_opt_hdr))
+			return NULL;
+		l = nd_opt->nd_opt_len << 3;
+		if (opt_len < l || l == 0)
+			return NULL;
+		switch (nd_opt->nd_opt_type) {
+		case ND_OPT_SOURCE_LL_ADDR:
+		case ND_OPT_TARGET_LL_ADDR:
+		case ND_OPT_MTU:
+		case ND_OPT_REDIRECT_HDR:
+			if (ndopts->nd_opt_array[nd_opt->nd_opt_type]) {
+				ND_PRINTK2((KERN_WARNING
+					    "ndisc_parse_options(): duplicated ND6 option found: type=%d\n",
+					    nd_opt->nd_opt_type));
+			} else {
+				ndopts->nd_opt_array[nd_opt->nd_opt_type] = nd_opt;
+			}
+			break;
+		case ND_OPT_PREFIX_INFO:
+			ndopts->nd_opts_pi_end = nd_opt;
+			if (ndopts->nd_opt_array[nd_opt->nd_opt_type] == 0)
+				ndopts->nd_opt_array[nd_opt->nd_opt_type] = nd_opt;
+			break;
+		default:
+			/*
+			 * Unknown options must be silently ignored,
+			 * to accomodate future extension to the protocol.
+			 */
+			ND_PRINTK2(KERN_WARNING
+				   "ndisc_parse_options(): ignored unsupported option; type=%d, len=%d\n",
+				   nd_opt->nd_opt_type, nd_opt->nd_opt_len);
+		}
+		opt_len -= l;
+		nd_opt = ((void *)nd_opt) + l;
+	}
+	return ndopts;
+}
+
 int ndisc_mc_map(struct in6_addr *addr, char *buf, struct net_device *dev, int dir)
 {
 	switch (dev->type) {
@@ -484,27 +546,6 @@
 }
 		   
 
-static u8 * ndisc_find_option(u8 *opt, int opt_len, int len, int option)
-{
-	while (opt_len <= len) {
-		int l = opt[1]<<3;
-
-		if (opt[0] == option && l >= opt_len)
-			return opt + 2;
-
-		if (l == 0) {
-			if (net_ratelimit())
-			    printk(KERN_WARNING "ndisc: option has 0 len\n");
-			return NULL;
-		}
-
-		opt += l;
-		len -= l;
-	}
-	return NULL;
-}
-
-
 static void ndisc_error_report(struct neighbour *neigh, struct sk_buff *skb)
 {
 	/*
@@ -542,13 +583,6 @@
 	}
 }
 
-
-static void ndisc_update(struct neighbour *neigh, u8* opt, int len, int type)
-{
-	opt = ndisc_find_option(opt, neigh->dev->addr_len+2, len, type);
-	neigh_update(neigh, opt, NUD_STALE, 1, 1);
-}
-
 static void ndisc_router_discovery(struct sk_buff *skb)
 {
         struct ra_msg *ra_msg = (struct ra_msg *) skb->h.raw;
@@ -556,6 +590,7 @@
 	struct inet6_dev *in6_dev;
 	struct rt6_info *rt;
 	int lifetime;
+	struct ndisc_options ndopts;
 	int optlen;
 
 	__u8 * opt = (__u8 *)(ra_msg + 1);
@@ -587,6 +622,13 @@
 		return;
 	}
 
+	if (!ndisc_parse_options(opt, optlen, &ndopts)) {
+		if (net_ratelimit())
+			ND_PRINTK2(KERN_WARNING
+				   "ICMP6 RA: invalid ND option, ignored.\n");
+		return;
+	}
+
 	if (in6_dev->if_flags & IF_RS_SENT) {
 		/*
 		 *	flag that an RA was received after an RS was sent
@@ -670,63 +712,60 @@
 	 *	Process options.
 	 */
 
-        while (optlen > 0) {
-                int len = (opt[1] << 3);
+	if (rt && (neigh = rt->rt6i_nexthop) != NULL) {
+		u8 *lladdr = NULL;
+		int lladdrlen;
+		if (ndopts.nd_opts_src_lladdr) {
+			lladdr = (u8*)((ndopts.nd_opts_src_lladdr)+1);
+			lladdrlen = ndopts.nd_opts_src_lladdr->nd_opt_len << 3;
+			if (lladdrlen != NDISC_OPT_SPACE(skb->dev->addr_len)) {
+				if (net_ratelimit())
+					ND_PRINTK2(KERN_WARNING
+						   "ICMP6 RA: Invalid lladdr length.\n");
+				goto out;
+			}
+		}
+		neigh_update(neigh, lladdr, NUD_STALE, 1, 1);
+	}
 
-		if (len == 0) {
-			ND_PRINTK0("RA: opt has 0 len\n");
-			break;
+	if (ndopts.nd_opts_pi) {
+		struct nd_opt_hdr *p;
+		for (p = ndopts.nd_opts_pi;
+		     p;
+		     p = ndisc_next_option(p, ndopts.nd_opts_pi_end)) {
+			addrconf_prefix_rcv(skb->dev, (u8*)p, (p->nd_opt_len) << 3);
 		}
+	}
 
-                switch(*opt) {
-                case ND_OPT_SOURCE_LL_ADDR:
+	if (ndopts.nd_opts_mtu) {
+		u32 mtu;
 
-			if (rt == NULL)
-				break;
-			
-			if ((neigh = rt->rt6i_nexthop) != NULL &&
-			    skb->dev->addr_len + 2 >= len)
-				neigh_update(neigh, opt+2, NUD_STALE, 1, 1);
-			break;
+		memcpy(&mtu, ((u8*)(ndopts.nd_opts_mtu+1))+2, sizeof(mtu));
+		mtu = ntohl(mtu);
 
-                case ND_OPT_PREFIX_INFO:
-			addrconf_prefix_rcv(skb->dev, opt, len);
-                        break;
-
-                case ND_OPT_MTU:
-			{
-				int mtu;
-				
-				mtu = htonl(*(__u32 *)(opt+4));
-
-				if (mtu < IPV6_MIN_MTU || mtu > skb->dev->mtu) {
-					ND_PRINTK0("NDISC: router "
-						   "announcement with mtu = %d\n",
-						   mtu);
-					break;
-				}
+		if (mtu < IPV6_MIN_MTU || mtu > skb->dev->mtu) {
+			if (net_ratelimit()) {
+				ND_PRINTK0("NDISC: router announcement with mtu = %d\n",
+					   mtu);
+			}
+		}
 
-				if (in6_dev->cnf.mtu6 != mtu) {
-					in6_dev->cnf.mtu6 = mtu;
+		if (in6_dev->cnf.mtu6 != mtu) {
+			in6_dev->cnf.mtu6 = mtu;
 
-					if (rt)
-						rt->u.dst.pmtu = mtu;
+			if (rt)
+				rt->u.dst.pmtu = mtu;
 
-					rt6_mtu_change(skb->dev, mtu);
-				}
-			}
-                        break;
-
-		case ND_OPT_TARGET_LL_ADDR:
-		case ND_OPT_REDIRECT_HDR:
-			ND_PRINTK0("got illegal option with RA");
-			break;
-		default:
-			ND_PRINTK0("unkown option in RA\n");
-                };
-                optlen -= len;
-                opt += len;
-        }
+			rt6_mtu_change(skb->dev, mtu);
+		}
+	}
+			
+	if (ndopts.nd_opts_tgt_lladdr || ndopts.nd_opts_rh) {
+		if (net_ratelimit())
+			ND_PRINTK0(KERN_WARNING
+				   "ICMP6 RA: got illegal option with RA");
+	}
+out:
 	if (rt)
 		dst_release(&rt->u.dst);
 	in6_dev_put(in6_dev);
@@ -740,7 +779,10 @@
 	struct in6_addr *target;	/* new first hop to destination */
 	struct neighbour *neigh;
 	int on_link = 0;
+	struct ndisc_options ndopts;
 	int optlen;
+	u8 *lladdr = NULL;
+	int lladdrlen;
 
 	if (!(ipv6_addr_type(&skb->nh.ipv6h->saddr) & IPV6_ADDR_LINKLOCAL)) {
 		if (net_ratelimit())
@@ -788,6 +830,24 @@
 	 *	first-hop router for the specified ICMP Destination Address.
 	 */
 		
+	if (!ndisc_parse_options((u8*)(dest + 1), optlen, &ndopts)) {
+		if (net_ratelimit())
+			ND_PRINTK2(KERN_WARNING
+				   "ICMP6 Redirect: invalid ND options, rejected.\n");
+		in6_dev_put(in6_dev);
+		return;
+	}
+	if (ndopts.nd_opts_tgt_lladdr) {
+		lladdr = (u8*)(ndopts.nd_opts_tgt_lladdr + 1);
+		lladdrlen = ndopts.nd_opts_tgt_lladdr->nd_opt_len << 3;
+		if (lladdrlen != NDISC_OPT_SPACE(skb->dev->addr_len)) {
+			if (net_ratelimit())
+				ND_PRINTK2(KERN_WARNING
+					   "ICMP6 Redirect: invalid lladdr length.\n");
+			in6_dev_put(in6_dev);
+			return;
+		}
+	}
 	/* passed validation tests */
 
 	/*
@@ -796,7 +856,7 @@
 
 	neigh = __neigh_lookup(&nd_tbl, target, skb->dev, 1);
 	if (neigh) {
-		ndisc_update(neigh, (u8*)(dest + 1), optlen, ND_OPT_TARGET_LL_ADDR);
+		neigh_update(neigh, lladdr, NUD_STALE, 1, 1);
 		if (neigh->nud_state&NUD_VALID)
 			rt6_redirect(dest, &skb->nh.ipv6h->saddr, neigh, on_link);
 		else
@@ -922,31 +982,6 @@
 	ICMP6_INC_STATS(Icmp6OutMsgs);
 }
 
-static __inline__ struct neighbour *
-ndisc_recv_ns(struct in6_addr *saddr, struct sk_buff *skb)
-{
-	u8 *opt;
-
-	opt = skb->h.raw;
-	opt += sizeof(struct nd_msg);
-	opt = ndisc_find_option(opt, skb->dev->addr_len+2, skb->tail - opt, ND_OPT_SOURCE_LL_ADDR);
-
-	return neigh_event_ns(&nd_tbl, opt, saddr, skb->dev);
-}
-
-static __inline__ int ndisc_recv_na(struct neighbour *neigh, struct sk_buff *skb)
-{
-	u8 *opt;
-	struct nd_msg *msg = (struct nd_msg*) skb->h.raw;
-
-	opt = ndisc_find_option(msg->opt, skb->dev->addr_len+2,
-				skb->tail - msg->opt, ND_OPT_TARGET_LL_ADDR);
-
-	return neigh_update(neigh, opt,
-			    msg->icmph.icmp6_solicited ? NUD_REACHABLE : NUD_STALE,
-			    msg->icmph.icmp6_override, 1);
-}
-
 static void pndisc_redo(struct sk_buff *skb)
 {
 	ndisc_rcv(skb);
@@ -978,13 +1013,15 @@
 		return 0;
 	}
 
-	/* XXX: RFC2461 Validation of [all ndisc messages]:
-	 *	All included ndisc options MUST be of non-zero length
-	 *	(Some checking in ndisc_find_option)
-	 */
-
 	switch (msg->icmph.icmp6_type) {
 	case NDISC_NEIGHBOUR_SOLICITATION:
+	    {
+		struct nd_msg *msg = (struct nd_msg *)skb->h.raw;
+		u8 *lladdr = NULL;
+		int lladdrlen = 0;
+		u32 ndoptlen = skb->tail - msg->opt;
+		struct ndisc_options ndopts;
+
 		if (skb->len < sizeof(struct nd_msg)) {
 			if (net_ratelimit())
 				printk(KERN_WARNING "ICMP NS: packet too short\n");
@@ -997,6 +1034,22 @@
 			return 0;
 		}
 
+		if (!ndisc_parse_options(msg->opt, ndoptlen, &ndopts)) {
+			if (net_ratelimit())
+				printk(KERN_WARNING "ICMP NS: invalid ND option, ignored.\n");
+			return 0;
+		}
+
+		if (ndopts.nd_opts_src_lladdr) {
+			lladdr = (u8*)(ndopts.nd_opts_src_lladdr + 1);
+			lladdrlen = ndopts.nd_opts_src_lladdr->nd_opt_len << 3;
+			if (lladdrlen != NDISC_OPT_SPACE(skb->dev->addr_len)) {
+				if (net_ratelimit())
+					printk(KERN_WARNING "ICMP NS: bad lladdr length.\n");
+				return 0;
+			}
+		}
+
 		/* XXX: RFC2461 7.1.1:
 		 * 	If the IP source address is the unspecified address, there
 		 *	MUST NOT be source link-layer address option in the message.
@@ -1063,7 +1116,7 @@
 				 *	for the source adddress
 				 */
 
-				neigh = ndisc_recv_ns(saddr, skb);
+				neigh = neigh_event_ns(&nd_tbl, lladdr, saddr, skb->dev);
 
 				if (neigh || !dev->hard_header) {
 					ndisc_send_na(dev, neigh, saddr, &ifp->addr, 
@@ -1093,7 +1146,8 @@
 					else
 						nd_tbl.stats.rcv_probes_ucast++;
 
-					neigh = ndisc_recv_ns(saddr, skb);
+					
+					neigh = neigh_event_ns(&nd_tbl, lladdr, saddr, skb->dev);
 
 					if (neigh) {
 						ndisc_send_na(dev, neigh, saddr, &msg->target,
@@ -1113,8 +1167,16 @@
 			
 		}
 		return 0;
+	    }
 
 	case NDISC_NEIGHBOUR_ADVERTISEMENT:
+	    {
+		struct nd_msg *msg = (struct nd_msg *)skb->h.raw;
+		u8 *lladdr = NULL;
+		int lladdrlen = 0;
+		u32 ndoptlen = skb->tail - msg->opt;
+		struct ndisc_options ndopts;
+
 		if (skb->len < sizeof(struct nd_msg)) {
 			if (net_ratelimit())
 				printk(KERN_WARNING "ICMP NA: packet too short\n");
@@ -1133,6 +1195,20 @@
 			return 0;
 		}
 		
+		if (!ndisc_parse_options(msg->opt, ndoptlen, &ndopts)) {
+			if (net_ratelimit())
+				printk(KERN_WARNING "ICMP NS: invalid ND option, ignored.\n");
+			return 0;
+		}
+		if (ndopts.nd_opts_tgt_lladdr) {
+			lladdr = (u8*)(ndopts.nd_opts_tgt_lladdr + 1);
+			lladdrlen = ndopts.nd_opts_tgt_lladdr->nd_opt_len << 3;
+			if (lladdrlen != NDISC_OPT_SPACE(skb->dev->addr_len)) {
+				if (net_ratelimit())
+					printk(KERN_WARNING "NDISC NA: invalid lladdr length.\n");
+				return 0;
+			}
+		}
 		if ((ifp = ipv6_get_ifaddr(&msg->target, dev))) {
 			if (ifp->flags & IFA_F_TENTATIVE) {
 				addrconf_dad_failure(ifp);
@@ -1170,10 +1246,13 @@
 					neigh->flags |= NTF_ROUTER;
 			}
 
-			ndisc_recv_na(neigh, skb);
+			neigh_update(neigh, lladdr,
+				     msg->icmph.icmp6_solicited ? NUD_REACHABLE : NUD_STALE,
+				     msg->icmph.icmp6_override, 1);
 			neigh_release(neigh);
 		}
 		break;
+	    }
 
 	case NDISC_ROUTER_ADVERTISEMENT:
 		ndisc_router_discovery(skb);
diff -urN linux-2.4.20-pre8/net/ipv6/netfilter/ip6_tables.c linux-2.4.20-pre9/net/ipv6/netfilter/ip6_tables.c
--- linux-2.4.20-pre8/net/ipv6/netfilter/ip6_tables.c	Thu Oct  3 18:36:50 2002
+++ linux-2.4.20-pre9/net/ipv6/netfilter/ip6_tables.c	Thu Oct  3 18:38:02 2002
@@ -1494,6 +1494,9 @@
 	duprintf("table->private->number = %u\n",
 		 table->private->number);
 
+	/* save number of initial entries */
+	table->private->initial_entries = table->private->number;
+
 	table->lock = RW_LOCK_UNLOCKED;
 	list_prepend(&ip6t_tables, table);
 
diff -urN linux-2.4.20-pre8/net/sched/sch_htb.c linux-2.4.20-pre9/net/sched/sch_htb.c
--- linux-2.4.20-pre8/net/sched/sch_htb.c	Thu Oct  3 18:36:50 2002
+++ linux-2.4.20-pre9/net/sched/sch_htb.c	Thu Oct  3 18:38:03 2002
@@ -1174,6 +1174,8 @@
 	skb_queue_head_init(&q->direct_queue);
 
 	q->direct_qlen = sch->dev->tx_queue_len;
+	if (q->direct_qlen < 2) /* some devices have zero tx_queue_len */
+		q->direct_qlen = 2;
 	q->timer.function = htb_timer;
 	q->timer.data = (unsigned long)sch;
 
@@ -1440,6 +1442,10 @@
 	if (!rtab || !ctab) goto failure;
 
 	if (!cl) { /* new class */
+		/* check for valid classid */
+		if (!classid || TC_H_MAJ(classid^sch->handle) || htb_find(classid,sch))
+			goto failure;
+
 		/* check maximal depth */
 		if (parent && parent->parent && parent->parent->level < 2) {
 			printk(KERN_ERR "htb: tree is too deep\n");
