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

diff -urN linux-2.4.19-pre5/CREDITS linux-2.4.19-pre6/CREDITS
--- linux-2.4.19-pre5/CREDITS	Thu Apr  4 22:04:19 2002
+++ linux-2.4.19-pre6/CREDITS	Thu Apr  4 22:04:30 2002
@@ -1910,6 +1910,7 @@
 N: Petko Manolov
 E: petkan@users.sourceforge.net
 D: USB ethernet pegasus/pegasus-II driver
+D: USB ethernet rtl8150 driver
 D: i[45]86 optimized string routines
 D: i386 task switching hacks
 S: 482 Shadowgraph Dr.
diff -urN linux-2.4.19-pre5/Documentation/Configure.help linux-2.4.19-pre6/Documentation/Configure.help
--- linux-2.4.19-pre5/Documentation/Configure.help	Thu Apr  4 22:04:19 2002
+++ linux-2.4.19-pre6/Documentation/Configure.help	Thu Apr  4 22:04:30 2002
@@ -12815,18 +12815,6 @@
   of debug messages to the system log. Select this if you are having a
   problem with USB support and want to see more of what is going on.
 
-USB fetch large config
-CONFIG_USB_LARGE_CONFIG
-  This option changes the initial request for a config descriptor so
-  that some poorly designed devices will still work.  Some APC UPSes
-  need it.  Basically, the usb subsystem sends a request for a short
-  (8 byte) config, just to find out how large the real config is.
-  Incorrectly implemented devices may choke on this small config
-  request.  This option make the initial request for a quite large
-  config (1009 bytes), and things just work.
-
-  If you have an APC UPS, say Y; otherwise say N.
-
 USB long timeout for slow-responding devices (some MGE Ellipse UPSes)
 CONFIG_USB_LONG_TIMEOUT
   This option makes the standard time out a bit longer.  Basically,
@@ -12922,9 +12910,13 @@
 CONFIG_USB_HID
   Say Y here if you want full HID support to connect keyboards,
   mice, joysticks, graphic tablets, or any other HID based devices
-  to your computer via USB. You can't use this driver and the
-  HIDBP (Boot Protocol) keyboard and mouse drivers at the same time.
-  More information is available: <file:Documentation/input/input.txt>.
+  to your computer via USB. You also need to select HID Input layer
+  support (below) if you want to use keyboards, mice, joysticks and
+  the like.
+
+  You can't use this driver and the HIDBP (Boot Protocol) keyboard
+  and mouse drivers at the same time. More information is available:
+  <file:Documentation/input/input.txt>.
 
   If unsure, say Y.
 
@@ -12933,6 +12925,14 @@
   The module will be called hid.o. If you want to compile it as a
   module, say M here and read <file:Documentation/modules.txt>.
 
+USB HID Input layer support
+CONFIG_USB_HIDINPUT
+  Say Y here if you want to use a USB keyboard, mouse or joystick,
+  or any other HID input device. You also need Input layer support, 
+  (CONFIG_INPUT) which you select under "Input core support".
+
+  If unsure, say Y.
+
 /dev/usb/hiddev raw HID device support
 CONFIG_USB_HIDDEV
   Say Y here if you want to support HID devices (from the USB
@@ -12943,33 +12943,37 @@
   event interface on /dev/usb/hiddevX (char 180:96 to 180:111).
   This driver requires CONFIG_USB_HID.
 
-  If unsure, say N.
+  If unsure, say Y.
 
 USB HIDBP Keyboard (basic) support
 CONFIG_USB_KBD
-  Say Y here if you don't want to use the generic HID driver for your
-  USB keyboard and prefer to use the keyboard in its limited Boot
-  Protocol mode instead. This driver is much smaller than the HID one.
+  Say Y here only if you are absolutely sure that you don't want
+  to use the generic HID driver for your USB keyboard and prefer
+  to use the keyboard in its limited Boot Protocol mode instead.
+
+  This is almost certainly not what you want.
 
   This code 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 usbkbd.o. If you want to compile it as a
   module, say M here and read <file:Documentation/modules.txt>.
 
-  If unsure, say N.
+  If even remotely unsure, say N.
 
 USB HIDBP Mouse (basic) support
 CONFIG_USB_MOUSE
-  Say Y here if you don't want to use the generic HID driver for your
-  USB mouse and prefer to use the mouse in its limited Boot Protocol
-  mode instead. This driver is much smaller than the HID one.
+  Say Y here only if you are absolutely sure that you don't want
+  to use the generic HID driver for your USB keyboard and prefer
+  to use the keyboard in its limited Boot Protocol mode instead.
+
+  This is almost certainly not what you want.
 
   This code 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 usbmouse.o. If you want to compile it as
   a module, say M here and read <file:Documentation/modules.txt>.
 
-  If unsure, say N.
+  If even remotely unsure, say N.
 
 Wacom Intuos/Graphire tablet support
 CONFIG_USB_WACOM
@@ -13475,6 +13479,7 @@
         * Motorola (DM100 and SB4100)
         * Broadcom Cable Modem (reference design)
         * Toshiba PCX1100U and possibly other cable modems
+        * Sharp Zaurus SL-5000D
 
   The device creates a network device (ethX, where X depends on what
   other networking devices you have in use), as for a normal PCI
@@ -13574,12 +13579,23 @@
   If your particular adapter is not in the list and you are _sure_ it
   is Pegasus or Pegasus-II based then send me (pmanolov@users.sourceforge.net)
   vendor and device IDs.
-
+  
   This code 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 pegasus.o. If you want to compile it as a
   module, say M here and read <file:Documentation/modules.txt>.
 
+Realtek RTL8150 based USB-Ethernet device support
+CONFIG_USB_RTL8150
+  Say Y here if you have RTL8150 based usb-ethernet adapter.
+  Send me (petkan@users.sourceforge.net) any comments you may have.
+  You can also check for updates at http://pegasus2.sourceforge.net/
+
+  This code 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 rtl8150.o. If you want to compile it as a
+  module, say M here and read <file:Documentation/modules.txt>.
+
 USB KLSI KL5USB101-based Ethernet device support
 CONFIG_USB_KAWETH
   Say Y here if you want to use one of the following 10Mbps only
diff -urN linux-2.4.19-pre5/Documentation/DocBook/kernel-hacking.tmpl linux-2.4.19-pre6/Documentation/DocBook/kernel-hacking.tmpl
--- linux-2.4.19-pre5/Documentation/DocBook/kernel-hacking.tmpl	Mon Feb 25 11:37:51 2002
+++ linux-2.4.19-pre6/Documentation/DocBook/kernel-hacking.tmpl	Thu Apr  4 22:04:30 2002
@@ -1026,7 +1026,7 @@
     Similar to <function>EXPORT_SYMBOL()</function> except that the
     symbols exported by <function>EXPORT_SYMBOL_GPL()</function> can
     only be seen by modules with a
-    <function>MODULE_LICENCE()</function> that specifies a GPL
+    <function>MODULE_LICENSE()</function> that specifies a GPL
     compatible license.
    </para>
   </sect1>
diff -urN linux-2.4.19-pre5/Documentation/filesystems/devfs/ChangeLog linux-2.4.19-pre6/Documentation/filesystems/devfs/ChangeLog
--- linux-2.4.19-pre5/Documentation/filesystems/devfs/ChangeLog	Mon Feb 25 11:37:51 2002
+++ linux-2.4.19-pre6/Documentation/filesystems/devfs/ChangeLog	Thu Apr  4 22:04:30 2002
@@ -1880,3 +1880,33 @@
 - Updated README from master HTML file
 
 - Fixed kdev_none macro in include/linux/kdev_t.h
+===============================================================================
+Changes for patch v199.9
+
+- Added KERN_* to remaining messages
+
+- Cleaned up declaration of <stat_read>
+
+- Updated README from master HTML file
+===============================================================================
+Changes for patch v199.10
+
+- Changed <devfs_rmdir> to allow later additions if not yet empty
+
+- Added calls to <devfs_register_partitions> in drivers/block/blkpc.c
+  <add_partition> and <del_partition>
+
+- Updated README from master HTML file
+
+- Fixed bug in <devfs_alloc_unique_number>: was clearing beyond
+  bitfield
+
+- Fixed bitfield data type for <devfs_*alloc_devnum>
+
+- Made major bitfield type and initialiser 64 bit safe
+===============================================================================
+Changes for patch v199.11
+
+- Ported to kernel 2.4.19-pre5
+
+- Updated README from master HTML file
diff -urN linux-2.4.19-pre5/Documentation/filesystems/devfs/README linux-2.4.19-pre6/Documentation/filesystems/devfs/README
--- linux-2.4.19-pre5/Documentation/filesystems/devfs/README	Mon Feb 25 11:37:51 2002
+++ linux-2.4.19-pre6/Documentation/filesystems/devfs/README	Thu Apr  4 22:04:30 2002
@@ -3,7 +3,7 @@
 
 Linux Devfs (Device File System) FAQ
 Richard Gooch
-20-JAN-2002
+29-MAR-2002
 
 
 Document languages:
@@ -803,12 +803,19 @@
 
 add the following lines to your /etc/devfsd.conf file:
 
-REGISTER	^pt[sy]/.*	IGNORE
-CHANGE		^pt[sy]/.*	IGNORE
+REGISTER	^pt[sy]		IGNORE
+CREATE		^pt[sy]		IGNORE
+CHANGE		^pt[sy]		IGNORE
+DELETE		^pt[sy]		IGNORE
 REGISTER	.*		COPY	/dev-state/$devname $devpath
-CHANGE		.*		COPY	$devpath /dev-state/$devname
 CREATE		.*		COPY	$devpath /dev-state/$devname
+CHANGE		.*		COPY	$devpath /dev-state/$devname
+DELETE		.*		CFUNCTION GLOBAL unlink /dev-state/$devname
+RESTORE		/dev-state
 
+Note that the sample devfsd.conf file contains these lines,
+as well as other sample configurations you may find useful. See the
+devfsd distribution
 
 
 reboot.
@@ -872,7 +879,8 @@
 (for example, by starting with /etc/fstab), and then limiting the
 compatibility entries that devfsd creates.
 
-MAKE SURE YOU INSTALL DEVFSD BEFORE YOU BOOT A DEVFS-ENABLED KERNEL!
+IF YOU CONFIGURE TO MOUNT DEVFS AT BOOT, MAKE SURE YOU INSTALL DEVFSD
+BEFORE YOU BOOT A DEVFS-ENABLED KERNEL!
 
 Now that devfs has gone into the 2.3.46 kernel, I'm getting a lot of
 reports back. Many of these are because people are trying to run
@@ -1565,6 +1573,24 @@
 the existence of the entry should be relied upon.
 
 
+When I start devfsd, I see the error:
+Error opening file: ".devfsd"   No such file or directory?
+
+This means that devfs is not mounted. Make sure you have devfs mounted.
+
+
+How do I mount devfs?
+
+First make sure you have devfs compiled into your kernel (see
+above). Then you will either need to:
+
+set CONFIG_DEVFS_MOUNT=y in your kernel config
+pass devfs=mount to your boot loader
+mount devfs manually in your boot scripts with:
+mount -t none devfs /dev
+
+
+
 
 
 
@@ -1925,11 +1951,7 @@
 
 A Korean translation by viatoris@nownuri.net is available at
 
-http://home.nownuri.net/~viatoris/devfs/devfs.html
-
-A newer version is under construcation at
-
-http://viatoris.new21.org/devfs/devfs.html
+http://your.destiny.pe.kr/devfs/devfs.html
 
 
 
diff -urN linux-2.4.19-pre5/Documentation/sonypi.txt linux-2.4.19-pre6/Documentation/sonypi.txt
--- linux-2.4.19-pre5/Documentation/sonypi.txt	Mon Feb 25 11:37:51 2002
+++ linux-2.4.19-pre6/Documentation/sonypi.txt	Thu Apr  4 22:04:30 2002
@@ -43,7 +43,7 @@
 to /etc/modules.conf file, when the driver is compiled as a module or by
 adding the following to the kernel command line (in your bootloader):
 
-	sonypi=minor[[[[,camera],fnkeyinit],verbose],compat]
+	sonypi=minor[[[[[,camera],fnkeyinit],verbose],compat],nojogdial]
 
 where:
 
@@ -71,6 +71,9 @@
 			(prior to version 1.5) and does not work anymore,
 			add this option and report to the author.
 
+	nojogdial:	gives more accurate PKEY events on those Vaio models
+			which don't have a jogdial (like the FX series).
+
 Module use:
 -----------
 
diff -urN linux-2.4.19-pre5/MAINTAINERS linux-2.4.19-pre6/MAINTAINERS
--- linux-2.4.19-pre5/MAINTAINERS	Thu Apr  4 22:04:19 2002
+++ linux-2.4.19-pre6/MAINTAINERS	Thu Apr  4 22:04:30 2002
@@ -1395,6 +1395,13 @@
 M:	mingo@redhat.com
 S:	Maintained
 
+SIS 5513 IDE CONTROLLER DRIVER
+P:      Lionel Bouton
+M:      Lionel.Bouton@inet6.fr
+W:      http://inet6.dyn.dhs.org/sponsoring/sis5513/index.html
+W:      http://gyver.homeip.net/sis5513/index.html
+S:      Maintained
+
 SIS 900/7016 FAST ETHERNET DRIVER
 P:	Ollie Lho
 M:	ollie@sis.com.tw
@@ -1509,12 +1516,10 @@
 S:	Maintained
 
 TLAN NETWORK DRIVER
-P:	Torben Mathiasen
-M:	torben.mathiasen@compaq.com
-M:	torben@kernel.dk
-L:	tlan@vuser.vu.union.edu
-L:	linux-net@vger.kernel.org
-W:	http://tlan.kernel.dk
+P:	Samuel Chessman
+M:	chessman@tux.org
+L:	tlan-devel@lists.sourceforge.net
+W:	http://sourceforge.net/projects/tlan/
 S:	Maintained
 
 TOKEN-RING NETWORK DRIVER
diff -urN linux-2.4.19-pre5/Makefile linux-2.4.19-pre6/Makefile
--- linux-2.4.19-pre5/Makefile	Thu Apr  4 22:04:19 2002
+++ linux-2.4.19-pre6/Makefile	Thu Apr  4 22:04:30 2002
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 4
 SUBLEVEL = 19
-EXTRAVERSION = -pre5
+EXTRAVERSION = -pre6
 
 KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
 
@@ -89,7 +89,10 @@
 CPPFLAGS := -D__KERNEL__ -I$(HPATH)
 
 CFLAGS := $(CPPFLAGS) -Wall -Wstrict-prototypes -Wno-trigraphs -O2 \
-	  -fomit-frame-pointer -fno-strict-aliasing -fno-common
+	  -fno-strict-aliasing -fno-common
+ifndef CONFIG_FRAME_POINTER
+CFLAGS += -fomit-frame-pointer
+endif
 AFLAGS := -D__ASSEMBLY__ $(CPPFLAGS)
 
 #
@@ -243,6 +246,16 @@
 
 include arch/$(ARCH)/Makefile
 
+# Extra cflags for kbuild 2.4.  The default is to forbid includes by kernel code
+# from user space headers.  Some UML code requires user space headers, in the
+# UML Makefiles add 'kbuild_2_4_nostdinc :=' before include Rules.make.  No
+# other kernel code should include user space headers, if you need
+# 'kbuild_2_4_nostdinc :=' or -I/usr/include for kernel code and you are not UML
+# then your code is broken!  KAO.
+
+kbuild_2_4_nostdinc	:= -nostdinc $(shell $(CC) -print-search-dirs | sed -ne 's/install: \(.*\)/-I \1include/gp')
+export kbuild_2_4_nostdinc
+
 export	CPPFLAGS CFLAGS CFLAGS_KERNEL AFLAGS AFLAGS_KERNEL
 
 export	NETWORKS DRIVERS LIBS HEAD LDFLAGS LINKFLAGS MAKEBOOT ASFLAGS
diff -urN linux-2.4.19-pre5/Rules.make linux-2.4.19-pre6/Rules.make
--- linux-2.4.19-pre5/Rules.make	Thu Apr  4 22:04:19 2002
+++ linux-2.4.19-pre6/Rules.make	Thu Apr  4 22:04:30 2002
@@ -32,6 +32,7 @@
 unexport subdir-
 
 comma	:= ,
+EXTRA_CFLAGS_nostdinc := $(EXTRA_CFLAGS) $(kbuild_2_4_nostdinc)
 
 #
 # Get things started.
@@ -50,15 +51,15 @@
 #
 
 %.s: %.c
-	$(CC) $(CFLAGS) $(EXTRA_CFLAGS) -DKBUILD_BASENAME=$(subst $(comma),_,$(subst -,_,$(*F))) $(CFLAGS_$@) -S $< -o $@
+	$(CC) $(CFLAGS) $(EXTRA_CFLAGS_nostdinc) -DKBUILD_BASENAME=$(subst $(comma),_,$(subst -,_,$(*F))) $(CFLAGS_$@) -S $< -o $@
 
 %.i: %.c
-	$(CPP) $(CFLAGS) $(EXTRA_CFLAGS) -DKBUILD_BASENAME=$(subst $(comma),_,$(subst -,_,$(*F))) $(CFLAGS_$@) $< > $@
+	$(CPP) $(CFLAGS) $(EXTRA_CFLAGS_nostdinc) -DKBUILD_BASENAME=$(subst $(comma),_,$(subst -,_,$(*F))) $(CFLAGS_$@) $< > $@
 
 %.o: %.c
-	$(CC) $(CFLAGS) $(EXTRA_CFLAGS) -DKBUILD_BASENAME=$(subst $(comma),_,$(subst -,_,$(*F))) $(CFLAGS_$@) -c -o $@ $<
+	$(CC) $(CFLAGS) $(EXTRA_CFLAGS_nostdinc) -DKBUILD_BASENAME=$(subst $(comma),_,$(subst -,_,$(*F))) $(CFLAGS_$@) -c -o $@ $<
 	@ ( \
-	    echo 'ifeq ($(strip $(subst $(comma),:,$(CFLAGS) $(EXTRA_CFLAGS) $(CFLAGS_$@))),$$(strip $$(subst $$(comma),:,$$(CFLAGS) $$(EXTRA_CFLAGS) $$(CFLAGS_$@))))' ; \
+	    echo 'ifeq ($(strip $(subst $(comma),:,$(CFLAGS) $(EXTRA_CFLAGS_nostdinc) $(CFLAGS_$@))),$$(strip $$(subst $$(comma),:,$$(CFLAGS) $$(EXTRA_CFLAGS_nostdinc) $$(CFLAGS_$@))))' ; \
 	    echo 'FILES_FLAGS_UP_TO_DATE += $@' ; \
 	    echo 'endif' \
 	) > $(dir $@)/.$(notdir $@).flags
@@ -81,7 +82,7 @@
 endif
 
 %.lst: %.c
-	$(CC) $(CFLAGS) $(EXTRA_CFLAGS) $(CFLAGS_$@) -g -c -o $*.o $<
+	$(CC) $(CFLAGS) $(EXTRA_CFLAGS_nostdinc) $(CFLAGS_$@) -g -c -o $*.o $<
 	$(TOPDIR)/scripts/makelst $* $(TOPDIR) $(OBJDUMP)
 #
 #
@@ -125,7 +126,7 @@
 # This make dependencies quickly
 #
 fastdep: dummy
-	$(TOPDIR)/scripts/mkdep $(CFLAGS) $(EXTRA_CFLAGS) -- $(wildcard *.[chS]) > .depend
+	$(TOPDIR)/scripts/mkdep $(CFLAGS) $(EXTRA_CFLAGS_nostdinc) -- $(wildcard *.[chS]) > .depend
 ifdef ALL_SUB_DIRS
 	$(MAKE) $(patsubst %,_sfdep_%,$(ALL_SUB_DIRS)) _FASTDEP_ALL_SUB_DIRS="$(ALL_SUB_DIRS)"
 endif
@@ -224,9 +225,9 @@
 
 $(MODINCL)/%.ver: %.c
 	@if [ ! -r $(MODINCL)/$*.stamp -o $(MODINCL)/$*.stamp -ot $< ]; then \
-		echo '$(CC) $(CFLAGS) $(EXTRA_CFLAGS) -E -D__GENKSYMS__ $<'; \
+		echo '$(CC) $(CFLAGS) $(EXTRA_CFLAGS_nostdinc) -E -D__GENKSYMS__ $<'; \
 		echo '| $(GENKSYMS) $(genksyms_smp_prefix) -k $(VERSION).$(PATCHLEVEL).$(SUBLEVEL) > $@.tmp'; \
-		$(CC) $(CFLAGS) $(EXTRA_CFLAGS) -E -D__GENKSYMS__ $< \
+		$(CC) $(CFLAGS) $(EXTRA_CFLAGS_nostdinc) -E -D__GENKSYMS__ $< \
 		| $(GENKSYMS) $(genksyms_smp_prefix) -k $(VERSION).$(PATCHLEVEL).$(SUBLEVEL) > $@.tmp; \
 		if [ -r $@ ] && cmp -s $@ $@.tmp; then echo $@ is unchanged; rm -f $@.tmp; \
 		else echo mv $@.tmp $@; mv -f $@.tmp $@; fi; \
@@ -272,9 +273,9 @@
 
 ifneq "$(strip $(export-objs))" ""
 $(export-objs): $(export-objs:.o=.c) $(TOPDIR)/include/linux/modversions.h
-	$(CC) $(CFLAGS) $(EXTRA_CFLAGS) -DKBUILD_BASENAME=$(subst $(comma),_,$(subst -,_,$(*F))) $(CFLAGS_$@) -DEXPORT_SYMTAB -c $(@:.o=.c)
+	$(CC) $(CFLAGS) $(EXTRA_CFLAGS_nostdinc) -DKBUILD_BASENAME=$(subst $(comma),_,$(subst -,_,$(*F))) $(CFLAGS_$@) -DEXPORT_SYMTAB -c $(@:.o=.c)
 	@ ( \
-	    echo 'ifeq ($(strip $(subst $(comma),:,$(CFLAGS) $(EXTRA_CFLAGS) $(CFLAGS_$@) -DEXPORT_SYMTAB)),$$(strip $$(subst $$(comma),:,$$(CFLAGS) $$(EXTRA_CFLAGS) $$(CFLAGS_$@) -DEXPORT_SYMTAB)))' ; \
+	    echo 'ifeq ($(strip $(subst $(comma),:,$(CFLAGS) $(EXTRA_CFLAGS_nostdinc) $(CFLAGS_$@) -DEXPORT_SYMTAB)),$$(strip $$(subst $$(comma),:,$$(CFLAGS) $$(EXTRA_CFLAGS_nostdinc) $$(CFLAGS_$@) -DEXPORT_SYMTAB)))' ; \
 	    echo 'FILES_FLAGS_UP_TO_DATE += $@' ; \
 	    echo 'endif' \
 	) > $(dir $@)/.$(notdir $@).flags
diff -urN linux-2.4.19-pre5/arch/alpha/kernel/setup.c linux-2.4.19-pre6/arch/alpha/kernel/setup.c
--- linux-2.4.19-pre5/arch/alpha/kernel/setup.c	Fri Nov 16 18:38:39 2001
+++ linux-2.4.19-pre6/arch/alpha/kernel/setup.c	Thu Apr  4 22:04:30 2002
@@ -440,12 +440,6 @@
         return MKDEV(TTY_MAJOR, 64 + c->index);
 }
 
-static int srm_console_wait_key(struct console *co)
-{
-  /* Huh? */
-	return 1;
-}
-
 static int __init srm_console_setup(struct console *co, char *options)
 {
 	return 1;
@@ -455,7 +449,6 @@
 	name:		"srm0",
 	write:		srm_console_write,
 	device:		srm_console_device,
-	wait_key:	srm_console_wait_key,
 	setup:		srm_console_setup,
 	flags:		CON_PRINTBUFFER | CON_ENABLED, /* fake it out */
 	index:		-1,
diff -urN linux-2.4.19-pre5/arch/i386/config.in linux-2.4.19-pre6/arch/i386/config.in
--- linux-2.4.19-pre5/arch/i386/config.in	Thu Apr  4 22:04:20 2002
+++ linux-2.4.19-pre6/arch/i386/config.in	Thu Apr  4 22:04:30 2002
@@ -424,6 +424,7 @@
    bool '  Memory mapped I/O debugging' CONFIG_DEBUG_IOVIRT
    bool '  Magic SysRq key' CONFIG_MAGIC_SYSRQ
    bool '  Spinlock debugging' CONFIG_DEBUG_SPINLOCK
+   bool '  Compile the kernel with frame pointers' CONFIG_FRAME_POINTER
 fi
 
 endmenu
diff -urN linux-2.4.19-pre5/arch/i386/kernel/semaphore.c linux-2.4.19-pre6/arch/i386/kernel/semaphore.c
--- linux-2.4.19-pre5/arch/i386/kernel/semaphore.c	Fri Nov  9 13:58:02 2001
+++ linux-2.4.19-pre6/arch/i386/kernel/semaphore.c	Thu Apr  4 22:04:31 2002
@@ -182,6 +182,10 @@
 ".align 4\n"
 ".globl __down_failed\n"
 "__down_failed:\n\t"
+#if defined(CONFIG_FRAME_POINTER)
+	"pushl %ebp\n\t"
+	"movl  %esp,%ebp\n\t"
+#endif
 	"pushl %eax\n\t"
 	"pushl %edx\n\t"
 	"pushl %ecx\n\t"
@@ -189,6 +193,10 @@
 	"popl %ecx\n\t"
 	"popl %edx\n\t"
 	"popl %eax\n\t"
+#if defined(CONFIG_FRAME_POINTER)
+	"movl %ebp,%esp\n\t"
+	"popl %ebp\n\t"
+#endif
 	"ret"
 );
 
@@ -197,11 +205,19 @@
 ".align 4\n"
 ".globl __down_failed_interruptible\n"
 "__down_failed_interruptible:\n\t"
+#if defined(CONFIG_FRAME_POINTER)
+	"pushl %ebp\n\t"
+	"movl  %esp,%ebp\n\t"
+#endif
 	"pushl %edx\n\t"
 	"pushl %ecx\n\t"
 	"call __down_interruptible\n\t"
 	"popl %ecx\n\t"
 	"popl %edx\n\t"
+#if defined(CONFIG_FRAME_POINTER)
+	"movl %ebp,%esp\n\t"
+	"popl %ebp\n\t"
+#endif
 	"ret"
 );
 
@@ -210,11 +226,19 @@
 ".align 4\n"
 ".globl __down_failed_trylock\n"
 "__down_failed_trylock:\n\t"
+#if defined(CONFIG_FRAME_POINTER)
+	"pushl %ebp\n\t"
+	"movl  %esp,%ebp\n\t"
+#endif
 	"pushl %edx\n\t"
 	"pushl %ecx\n\t"
 	"call __down_trylock\n\t"
 	"popl %ecx\n\t"
 	"popl %edx\n\t"
+#if defined(CONFIG_FRAME_POINTER)
+	"movl %ebp,%esp\n\t"
+	"popl %ebp\n\t"
+#endif
 	"ret"
 );
 
diff -urN linux-2.4.19-pre5/arch/i386/kernel/smp.c linux-2.4.19-pre6/arch/i386/kernel/smp.c
--- linux-2.4.19-pre5/arch/i386/kernel/smp.c	Fri Dec 21 09:41:53 2001
+++ linux-2.4.19-pre6/arch/i386/kernel/smp.c	Thu Apr  4 22:04:31 2002
@@ -301,8 +301,7 @@
  */
 static void inline leave_mm (unsigned long cpu)
 {
-	if (cpu_tlbstate[cpu].state == TLBSTATE_OK)
-		BUG();
+	BUG_ON(cpu_tlbstate[cpu].state == TLBSTATE_OK);
 	clear_bit(cpu, &cpu_tlbstate[cpu].active_mm->cpu_vm_mask);
 }
 
diff -urN linux-2.4.19-pre5/arch/ia64/hp/hpsim_console.c linux-2.4.19-pre6/arch/ia64/hp/hpsim_console.c
--- linux-2.4.19-pre5/arch/ia64/hp/hpsim_console.c	Thu Oct 12 14:20:48 2000
+++ linux-2.4.19-pre6/arch/ia64/hp/hpsim_console.c	Thu Apr  4 22:04:31 2002
@@ -24,14 +24,12 @@
 
 static int simcons_init (struct console *, char *);
 static void simcons_write (struct console *, const char *, unsigned);
-static int simcons_wait_key (struct console *);
 static kdev_t simcons_console_device (struct console *);
 
 struct console hpsim_cons = {
 	name:		"simcons",
 	write:		simcons_write,
 	device:		simcons_console_device,
-	wait_key:	simcons_wait_key,
 	setup:		simcons_init,
 	flags:		CON_PRINTBUFFER,
 	index:		-1,
@@ -56,17 +54,6 @@
 	}
 }
 
-static int
-simcons_wait_key (struct console *cons)
-{
-	char ch;
-
-	do {
-		ch = ia64_ssc(0, 0, 0, 0, SSC_GETCHAR);
-	} while (ch == '\0');
-	return ch;
-}
-
 static kdev_t
 simcons_console_device (struct console *c)
 {
diff -urN linux-2.4.19-pre5/arch/m68k/amiga/config.c linux-2.4.19-pre6/arch/m68k/amiga/config.c
--- linux-2.4.19-pre5/arch/m68k/amiga/config.c	Thu Sep 13 15:21:32 2001
+++ linux-2.4.19-pre6/arch/m68k/amiga/config.c	Thu Apr  4 22:04:31 2002
@@ -98,7 +98,6 @@
 extern void amiga_floppy_setup(char *, int *);
 #endif
 static void amiga_reset (void);
-static int amiga_wait_key (struct console *co);
 extern void amiga_init_sound(void);
 static void amiga_savekmsg_init(void);
 static void amiga_mem_console_write(struct console *co, const char *b,
@@ -112,7 +111,6 @@
 
 static struct console amiga_console_driver = {
 	name:		"debug",
-	wait_key:	amiga_wait_key,
 	flags:		CON_PRINTBUFFER,
 	index:		-1,
 };
@@ -742,33 +740,6 @@
 	return 0;
 }
 
-static int amiga_wait_key (struct console *co)
-{
-    int i;
-
-    while (1) {
-	while (ciaa.pra & 0x40);
-
-	/* debounce */
-	for (i = 0; i < 1000; i++);
-
-	if (!(ciaa.pra & 0x40))
-	    break;
-    }
-
-    /* wait for button up */
-    while (1) {
-	while (!(ciaa.pra & 0x40));
-
-	/* debounce */
-	for (i = 0; i < 1000; i++);
-
-	if (ciaa.pra & 0x40)
-	    break;
-    }
-    return 0;
-}
-
 static NORET_TYPE void amiga_reset( void )
     ATTRIB_NORET;
 
diff -urN linux-2.4.19-pre5/arch/m68k/kernel/setup.c linux-2.4.19-pre6/arch/m68k/kernel/setup.c
--- linux-2.4.19-pre5/arch/m68k/kernel/setup.c	Thu Apr  4 22:04:20 2002
+++ linux-2.4.19-pre6/arch/m68k/kernel/setup.c	Thu Apr  4 22:04:31 2002
@@ -94,7 +94,6 @@
 long mach_max_dma_address = 0x00ffffff; /* default set to the lower 16MB */
 #if defined(CONFIG_AMIGA_FLOPPY) || defined(CONFIG_ATARI_FLOPPY) 
 void (*mach_floppy_setup) (char *, int *) __initdata = NULL;
-void (*mach_floppy_eject) (void) = NULL;
 #endif
 #ifdef CONFIG_HEARTBEAT
 void (*mach_heartbeat) (int) = NULL;
@@ -534,11 +533,6 @@
 		mach_floppy_setup (str, ints);
 }
 
-void floppy_eject(void)
-{
-	if (mach_floppy_eject)
-		mach_floppy_eject();
-}
 #endif
 
 /* for "kbd-reset" cmdline param */
diff -urN linux-2.4.19-pre5/arch/m68k/mac/debug.c linux-2.4.19-pre6/arch/m68k/mac/debug.c
--- linux-2.4.19-pre5/arch/m68k/mac/debug.c	Mon Jun 11 19:15:27 2001
+++ linux-2.4.19-pre6/arch/m68k/mac/debug.c	Thu Apr  4 22:04:31 2002
@@ -235,32 +235,6 @@
     }
 }
 
-#if defined(CONFIG_SERIAL_CONSOLE) || defined(DEBUG_SERIAL)
-int mac_sccb_console_wait_key(struct console *co)
-{
-    int i;
-    do {
-	for( i = uSEC; i > 0; --i )
-		barrier();
-    } while( !(scc.cha_b_ctrl & 0x01) ); /* wait for rx buf filled */
-    for( i = uSEC; i > 0; --i )
-	barrier();
-    return( scc.cha_b_data );
-}
-
-int mac_scca_console_wait_key(struct console *co)
-{
-    int i;
-    do {
-	for( i = uSEC; i > 0; --i )
-		barrier();
-    } while( !(scc.cha_a_ctrl & 0x01) ); /* wait for rx buf filled */
-    for( i = uSEC; i > 0; --i )
-	barrier();
-    return( scc.cha_a_data );
-}
-#endif
-
 /* The following two functions do a quick'n'dirty initialization of the MFP or
  * SCC serial ports. They're used by the debugging interface, kgdb, and the
  * serial console code. */
@@ -395,18 +369,12 @@
 	/* Mac modem port */
 	mac_init_scc_port( B9600|CS8, 0 );
 	mac_console_driver.write = mac_scca_console_write;
-#ifdef CONFIG_SERIAL_CONSOLE
-	mac_console_driver.wait_key = mac_scca_console_wait_key;
-#endif
 	scc_port = 0;
     }
     else if (!strcmp( m68k_debug_device, "ser2" )) {
 	/* Mac printer port */
 	mac_init_scc_port( B9600|CS8, 1 );
 	mac_console_driver.write = mac_sccb_console_write;
-#ifdef CONFIG_SERIAL_CONSOLE
-	mac_console_driver.wait_key = mac_sccb_console_wait_key;
-#endif
 	scc_port = 1;
     }
 #endif
diff -urN linux-2.4.19-pre5/arch/m68k/mvme147/config.c linux-2.4.19-pre6/arch/m68k/mvme147/config.c
--- linux-2.4.19-pre5/arch/m68k/mvme147/config.c	Mon Jun 11 19:15:27 2001
+++ linux-2.4.19-pre6/arch/m68k/mvme147/config.c	Thu Apr  4 22:04:32 2002
@@ -241,31 +241,7 @@
 	restore_flags(flags);
 }
 
-
-static int m147_scc_wait_key (struct console *co)
-{
-	volatile unsigned char *p = (volatile char *)M147_SCC_A_ADDR;
-	unsigned long	flags;
-	int		c;
-
-	/* wait for rx buf filled */
-	while ((*p & 0x01) == 0)
-		;
-
-	save_flags(flags);
-	cli();
-
-	*p = 8;
-	scc_delay();
-	c = *p;
-
-	restore_flags(flags);
-	return c;
-}
-
-
 void mvme147_init_console_port (struct console *co, int cflag)
 {
 	co->write    = m147_scc_write;
-	co->wait_key = m147_scc_wait_key;
 }
diff -urN linux-2.4.19-pre5/arch/m68k/q40/config.c linux-2.4.19-pre6/arch/m68k/q40/config.c
--- linux-2.4.19-pre5/arch/m68k/q40/config.c	Mon Jun 11 19:15:27 2001
+++ linux-2.4.19-pre6/arch/m68k/q40/config.c	Thu Apr  4 22:04:32 2002
@@ -36,7 +36,6 @@
 #include <asm/q40_master.h>
 #include <asm/keyboard.h>
 
-extern void floppy_eject(void);
 extern void floppy_setup(char *str, int *ints);
 
 extern int q40kbd_translate(unsigned char scancode, unsigned char *keycode,
@@ -73,10 +72,8 @@
 
 extern int ql_ticks;
 
-static int q40_wait_key(struct console *co){return 0;}
 static struct console q40_console_driver = {
 	name:		"debug",
-	wait_key:	q40_wait_key,
 	flags:		CON_PRINTBUFFER,
 	index:		-1,
 };
diff -urN linux-2.4.19-pre5/arch/m68k/sun3x/prom.c linux-2.4.19-pre6/arch/m68k/sun3x/prom.c
--- linux-2.4.19-pre5/arch/m68k/sun3x/prom.c	Mon Jun 11 19:15:27 2001
+++ linux-2.4.19-pre6/arch/m68k/sun3x/prom.c	Thu Apr  4 22:04:32 2002
@@ -96,7 +96,6 @@
 	sun3x_prom_write,  	/* write */
 	NULL,			/* read */
 	NULL,			/* device */
-	NULL,			/* wait_key */
 	NULL,			/* unblank */
 	NULL,			/* setup */
 	CON_PRINTBUFFER,
diff -urN linux-2.4.19-pre5/arch/mips/au1000/common/serial.c linux-2.4.19-pre6/arch/mips/au1000/common/serial.c
--- linux-2.4.19-pre5/arch/mips/au1000/common/serial.c	Thu Apr  4 22:04:20 2002
+++ linux-2.4.19-pre6/arch/mips/au1000/common/serial.c	Thu Apr  4 22:04:32 2002
@@ -2933,35 +2933,6 @@
 	serial_out(info, UART_IER, ier);
 }
 
-/*
- *	Receive character from the serial port
- */
-static int serial_console_wait_key(struct console *co)
-{
-	static struct async_struct *info;
-	int ier, c;
-
-	info = &async_sercons;
-
-	/*
-	 *	First save the IER then disable the interrupts so
-	 *	that the real driver for the port does not get the
-	 *	character.
-	 */
-	ier = serial_in(info, UART_IER);
-	serial_out(info, UART_IER, 0x00);
- 
-	while ((serial_in(info, UART_LSR) & UART_LSR_DR) == 0);
-	c = serial_in(info, UART_RX);
-
-	/*
-	 *	Restore the interrupts
-	 */
-	serial_out(info, UART_IER, ier);
-
-	return c;
-}
-
 static kdev_t serial_console_device(struct console *c)
 {
 	return MKDEV(TTY_MAJOR, 64 + c->index);
@@ -3086,7 +3057,6 @@
 	name:		"ttyS",
 	write:		serial_console_write,
 	device:		serial_console_device,
-	wait_key:	serial_console_wait_key,
 	setup:		serial_console_setup,
 	flags:		CON_PRINTBUFFER,
 	index:		-1,
diff -urN linux-2.4.19-pre5/arch/mips/baget/vacserial.c linux-2.4.19-pre6/arch/mips/baget/vacserial.c
--- linux-2.4.19-pre5/arch/mips/baget/vacserial.c	Thu Apr  4 22:04:20 2002
+++ linux-2.4.19-pre6/arch/mips/baget/vacserial.c	Thu Apr  4 22:04:32 2002
@@ -2622,43 +2622,6 @@
 	serial_outp(&scr_info, VAC_UART_INT_MASK, ier);
 }
 
-/*
- *	Receive character from the serial port
- */
-static int serial_console_wait_key(struct console *co)
-{
-	struct serial_state *ser;
-	int ier;
-	int lsr;
-	int c;
-	struct async_struct scr_info; /* serial_{in,out} because HUB6 */
-
-	ser = rs_table + co->index;
-	scr_info.magic = SERIAL_MAGIC;
-	scr_info.port = ser->port;
-	scr_info.flags = ser->flags;
-
-	/*
-	 *	First save the IER then disable the interrupts so
-	 *	that the real driver for the port does not get the
-	 *	character.
-	 */
-	ier = serial_inp(&scr_info, VAC_UART_INT_MASK);
-	serial_outp(&scr_info, VAC_UART_INT_MASK, 0x00);
-
-	do {
-		lsr = serial_inp(&scr_info, VAC_UART_INT_STATUS);
-	} while (!(lsr & VAC_UART_STATUS_RX_READY));
-	c = serial_inp(&scr_info, VAC_UART_RX);
-
-	/*
-	 *	Restore the interrupts
-	 */
-	serial_outp(&scr_info, VAC_UART_INT_MASK, ier);
-
-	return c;
-}
-
 static kdev_t serial_console_device(struct console *c)
 {
 	return MKDEV(TTY_MAJOR, 64 + c->index);
@@ -2812,7 +2775,6 @@
 	name:		"ttyS",
 	write:		serial_console_write,
 	device:		serial_console_device,
-	wait_key:	serial_console_wait_key,
 	setup:		serial_console_setup,
 	flags:		CON_PRINTBUFFER,
 	index:		-1,
diff -urN linux-2.4.19-pre5/arch/mips/dec/promcon.c linux-2.4.19-pre6/arch/mips/dec/promcon.c
--- linux-2.4.19-pre5/arch/mips/dec/promcon.c	Thu Oct 12 14:20:48 2000
+++ linux-2.4.19-pre6/arch/mips/dec/promcon.c	Thu Apr  4 22:04:32 2002
@@ -30,11 +30,6 @@
     }
 }
 
-static int prom_console_wait_key(struct console *co)
-{
-    return prom_getchar();
-}
-
 static int __init prom_console_setup(struct console *co, char *options)
 {
     return 0;
@@ -50,7 +45,6 @@
     name:	"ttyS",
     write:	prom_console_write,
     device:	prom_console_device,
-    wait_key:	prom_console_wait_key,
     setup:	prom_console_setup,
     flags:	CON_PRINTBUFFER,
     index:	-1,
diff -urN linux-2.4.19-pre5/arch/mips64/arc/arc_con.c linux-2.4.19-pre6/arch/mips64/arc/arc_con.c
--- linux-2.4.19-pre5/arch/mips64/arc/arc_con.c	Thu Apr  4 22:04:20 2002
+++ linux-2.4.19-pre6/arch/mips64/arc/arc_con.c	Thu Apr  4 22:04:34 2002
@@ -39,11 +39,6 @@
 	}
 }
 
-static int prom_console_wait_key(struct console *co)
-{
-	return 0;
-}
-
 static kdev_t prom_console_device(struct console *c)
 {
 	return MKDEV(TTY_MAJOR, 64 + c->index);
@@ -53,7 +48,6 @@
     name:	"ttyS",
     write:	prom_console_write,
     device:	prom_console_device,
-    wait_key:	prom_console_wait_key,
     flags:	CON_PRINTBUFFER,
     index:	-1,
 };
diff -urN linux-2.4.19-pre5/arch/parisc/kernel/pdc_cons.c linux-2.4.19-pre6/arch/parisc/kernel/pdc_cons.c
--- linux-2.4.19-pre5/arch/parisc/kernel/pdc_cons.c	Sun Sep 16 21:23:15 2001
+++ linux-2.4.19-pre6/arch/parisc/kernel/pdc_cons.c	Thu Apr  4 22:04:35 2002
@@ -105,10 +105,6 @@
 static struct console pdc_cons = {
 	name:		"ttyB",
 	write:		pdc_console_write,
-	read:		NULL,
-	device:		NULL, 
-	wait_key:	pdc_console_wait_key,
-	unblank:	NULL,
 	setup:		pdc_console_setup,
 	flags:		CON_PRINTBUFFER|CON_ENABLED,  // |CON_CONSDEV,
 	index:		-1,
diff -urN linux-2.4.19-pre5/arch/ppc/8260_io/uart.c linux-2.4.19-pre6/arch/ppc/8260_io/uart.c
--- linux-2.4.19-pre5/arch/ppc/8260_io/uart.c	Mon Feb 25 11:37:53 2002
+++ linux-2.4.19-pre6/arch/ppc/8260_io/uart.c	Thu Apr  4 22:04:35 2002
@@ -2216,54 +2216,6 @@
 		info->tx_cur = (cbd_t *)bdp;
 }
 
-/*
- * Receive character from the serial port.  This only works well
- * before the port is initialize for real use.
- */
-static int serial_console_wait_key(struct console *co)
-{
-	struct serial_state		*ser;
-	u_char				c, *cp;
-	ser_info_t			*info;
-	volatile	cbd_t		*bdp;
-	volatile	smc_uart_t	*up;
-
-	ser = rs_table + co->index;
-
-	/* Pointer to UART in parameter ram.
-	*/
-	up = (smc_uart_t *)&immr->im_dprambase[ser->port];
-
-	/* Get the address of the host memory buffer.
-	 * If the port has been initialized for general use, we must
-	 * use information from the port structure.
-	 */
-	if ((info = (ser_info_t *)ser->info))
-		bdp = info->rx_cur;
-	else
-		bdp = (cbd_t *)&immr->im_dprambase[up->smc_rbase];
-
-	/*
-	 * We need to gracefully shut down the receiver, disable
-	 * interrupts, then read the input.
-	 */
-	while (bdp->cbd_sc & BD_SC_EMPTY);	/* Wait for a character */
-	cp = __va(bdp->cbd_bufaddr);
-
-	if (info) {
-		if (bdp->cbd_sc & BD_SC_WRAP) {
-			bdp = info->rx_bd_base;
-		}
-		else {
-			bdp++;
-		}
-		info->rx_cur = (cbd_t *)bdp;
-	}
-
-	c = *cp;
-	return((int)c);
-}
-
 static kdev_t serial_console_device(struct console *c)
 {
 	return MKDEV(TTYAUX_MAJOR, 64 + c->index);
@@ -2274,7 +2226,6 @@
 	name:		"ttyS",
 	write:		serial_console_write,
 	device:		serial_console_device,
-	wait_key:	serial_console_wait_key,
 	setup:		serial_console_setup,
 	flags:		CON_PRINTBUFFER,
 	index:		CONFIG_SERIAL_CONSOLE_PORT,
diff -urN linux-2.4.19-pre5/arch/ppc/8xx_io/uart.c linux-2.4.19-pre6/arch/ppc/8xx_io/uart.c
--- linux-2.4.19-pre5/arch/ppc/8xx_io/uart.c	Mon Feb 25 11:37:54 2002
+++ linux-2.4.19-pre6/arch/ppc/8xx_io/uart.c	Thu Apr  4 22:04:35 2002
@@ -97,7 +97,6 @@
 static void serial_console_write(struct console *c, const char *s,
 				unsigned count);
 static kdev_t serial_console_device(struct console *c);
-static int serial_console_wait_key(struct console *co);
 
 #if defined(CONFIG_SERIAL_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
 static unsigned long break_pressed; /* break, really ... */
@@ -218,7 +217,6 @@
 	name:		"ttyS",
 	write:		serial_console_write,
 	device:		serial_console_device,
-	wait_key:	serial_console_wait_key,
 	setup:		serial_console_setup,
 	flags:		CON_PRINTBUFFER,
 	index:		CONFIG_SERIAL_CONSOLE_PORT,
@@ -2402,11 +2400,6 @@
 	return((int)c);
 }
 
-static int serial_console_wait_key(struct console *co)
-{
-	return(my_console_wait_key(co->index, 0, NULL));
-}
-
 #ifdef CONFIG_XMON
 int
 xmon_8xx_read_poll(void)
diff -urN linux-2.4.19-pre5/arch/ppc/amiga/config.c linux-2.4.19-pre6/arch/ppc/amiga/config.c
--- linux-2.4.19-pre5/arch/ppc/amiga/config.c	Thu Apr  4 22:04:20 2002
+++ linux-2.4.19-pre6/arch/ppc/amiga/config.c	Thu Apr  4 22:04:35 2002
@@ -103,7 +103,6 @@
 extern void amiga_floppy_setup(char *, int *);
 #endif
 static void amiga_reset (void);
-static int amiga_wait_key (struct console *co);
 extern void amiga_init_sound(void);
 static void amiga_savekmsg_init(void);
 static void amiga_mem_console_write(struct console *co, const char *b,
@@ -117,7 +116,6 @@
 
 static struct console amiga_console_driver = {
 	name:		"debug",
-	wait_key:	amiga_wait_key,
 	flags:		CON_PRINTBUFFER,
 	index:		-1,
 };
@@ -735,33 +733,6 @@
 	return 0;
 }
 
-static int amiga_wait_key (struct console *co)
-{
-    int i;
-
-    while (1) {
-	while (ciaa.pra & 0x40);
-
-	/* debounce */
-	for (i = 0; i < 1000; i++);
-
-	if (!(ciaa.pra & 0x40))
-	    break;
-    }
-
-    /* wait for button up */
-    while (1) {
-	while (!(ciaa.pra & 0x40));
-
-	/* debounce */
-	for (i = 0; i < 1000; i++);
-
-	if (ciaa.pra & 0x40)
-	    break;
-    }
-    return 0;
-}
-
 static NORET_TYPE void amiga_reset( void )
     ATTRIB_NORET;
 
diff -urN linux-2.4.19-pre5/arch/ppc/kernel/apus_setup.c linux-2.4.19-pre6/arch/ppc/kernel/apus_setup.c
--- linux-2.4.19-pre5/arch/ppc/kernel/apus_setup.c	Fri Nov 16 10:10:08 2001
+++ linux-2.4.19-pre6/arch/ppc/kernel/apus_setup.c	Thu Apr  4 22:04:36 2002
@@ -106,7 +106,6 @@
 long mach_max_dma_address = 0x00ffffff; /* default set to the lower 16MB */
 #if defined(CONFIG_AMIGA_FLOPPY)
 void (*mach_floppy_setup) (char *, int *) __initdata = NULL;
-void (*mach_floppy_eject) (void) = NULL;
 #endif
 #ifdef CONFIG_HEARTBEAT
 void (*mach_heartbeat) (int) = NULL;
@@ -404,12 +403,6 @@
 	if (mach_floppy_setup)
 		mach_floppy_setup (str, ints);
 }
-
-void floppy_eject(void)
-{
-	if (mach_floppy_eject)
-		mach_floppy_eject();
-}
 #endif
 
 /*********************************************************** MEMORY */
diff -urN linux-2.4.19-pre5/arch/ppc/kernel/m8xx_setup.c linux-2.4.19-pre6/arch/ppc/kernel/m8xx_setup.c
--- linux-2.4.19-pre5/arch/ppc/kernel/m8xx_setup.c	Fri Nov 16 10:10:08 2001
+++ linux-2.4.19-pre6/arch/ppc/kernel/m8xx_setup.c	Thu Apr  4 22:04:36 2002
@@ -55,12 +55,6 @@
 
 extern void m8xx_ide_init(void);
 
-#ifdef CONFIG_BLK_DEV_RAM
-extern int rd_doload;		/* 1 = load ramdisk, 0 = don't load */
-extern int rd_prompt;		/* 1 = prompt for ramdisk, 0 = don't prompt */
-extern int rd_image_start;	/* starting block # of image */
-#endif
-
 extern unsigned long find_available_memory(void);
 extern void m8xx_cpm_reset(uint);
 
diff -urN linux-2.4.19-pre5/arch/ppc/kernel/prep_setup.c linux-2.4.19-pre6/arch/ppc/kernel/prep_setup.c
--- linux-2.4.19-pre5/arch/ppc/kernel/prep_setup.c	Mon Feb 25 11:37:55 2002
+++ linux-2.4.19-pre6/arch/ppc/kernel/prep_setup.c	Thu Apr  4 22:04:36 2002
@@ -111,12 +111,6 @@
 extern int probingmem;
 extern unsigned long loops_per_jiffy;
 
-#ifdef CONFIG_BLK_DEV_RAM
-extern int rd_doload;		/* 1 = load ramdisk, 0 = don't load */
-extern int rd_prompt;		/* 1 = prompt for ramdisk, 0 = don't prompt */
-extern int rd_image_start;	/* starting block # of image */
-#endif
-
 #ifdef CONFIG_SOUND_MODULE
 EXPORT_SYMBOL(ppc_cs4232_dma);
 EXPORT_SYMBOL(ppc_cs4232_dma2);
diff -urN linux-2.4.19-pre5/arch/ppc/kernel/time.c linux-2.4.19-pre6/arch/ppc/kernel/time.c
--- linux-2.4.19-pre5/arch/ppc/kernel/time.c	Mon Feb 25 11:37:55 2002
+++ linux-2.4.19-pre6/arch/ppc/kernel/time.c	Thu Apr  4 22:04:36 2002
@@ -358,7 +358,7 @@
 #define	STARTOFTIME		1970
 #define SECDAY			86400L
 #define SECYR			(SECDAY * 365)
-#define	leapyear(year)		((year) % 4 == 0)
+#define	leapyear(y)		((!(y % 4) && (y % 100)) || !(y % 400))
 #define	days_in_year(a) 	(leapyear(a) ? 366 : 365)
 #define	days_in_month(a) 	(month_days[(a) - 1])
 
diff -urN linux-2.4.19-pre5/arch/sh/kernel/setup.c linux-2.4.19-pre6/arch/sh/kernel/setup.c
--- linux-2.4.19-pre5/arch/sh/kernel/setup.c	Fri Nov 16 18:38:39 2001
+++ linux-2.4.19-pre6/arch/sh/kernel/setup.c	Thu Apr  4 22:04:47 2002
@@ -140,15 +140,6 @@
     	sh_bios_console_write(s, count);
 }
 
-/*
- *	Receive character from the serial port
- */
-static int sh_console_wait_key(struct console *co)
-{
-	/* Not implemented yet */
-	return 0;
-}
-
 static kdev_t sh_console_device(struct console *c)
 {
     	/* TODO: this is totally bogus */
@@ -183,7 +174,6 @@
 	name:		"bios",
 	write:		sh_console_write,
 	device:		sh_console_device,
-	wait_key:	sh_console_wait_key,
 	setup:		sh_console_setup,
 	flags:		CON_PRINTBUFFER,
 	index:		-1,
diff -urN linux-2.4.19-pre5/drivers/acorn/block/fd1772.c linux-2.4.19-pre6/drivers/acorn/block/fd1772.c
--- linux-2.4.19-pre5/drivers/acorn/block/fd1772.c	Sun Aug 12 10:38:48 2001
+++ linux-2.4.19-pre6/drivers/acorn/block/fd1772.c	Thu Apr  4 22:04:54 2002
@@ -1620,7 +1620,3 @@
 
 	return 0;
 }
-
-void floppy_eject(void)
-{
-}
diff -urN linux-2.4.19-pre5/drivers/block/blkpg.c linux-2.4.19-pre6/drivers/block/blkpg.c
--- linux-2.4.19-pre5/drivers/block/blkpg.c	Mon Feb 25 11:37:57 2002
+++ linux-2.4.19-pre6/drivers/block/blkpg.c	Thu Apr  4 22:04:55 2002
@@ -110,6 +110,7 @@
 	g->part[minor].nr_sects = plength;
 	if (g->sizes)
 		g->sizes[minor] = (plength >> (BLOCK_SIZE_BITS - 9));
+	devfs_register_partitions (g, first_minor, 0);
 	return 0;
 }
 
@@ -157,6 +158,7 @@
 	g->part[minor].nr_sects = 0;
 	if (g->sizes)
 		g->sizes[minor] = 0;
+	devfs_register_partitions (g, first_minor, 0);
 
 	return 0;
 }
diff -urN linux-2.4.19-pre5/drivers/block/floppy.c linux-2.4.19-pre6/drivers/block/floppy.c
--- linux-2.4.19-pre5/drivers/block/floppy.c	Thu Apr  4 22:04:21 2002
+++ linux-2.4.19-pre6/drivers/block/floppy.c	Thu Apr  4 22:04:55 2002
@@ -4490,22 +4490,6 @@
 
 __setup ("floppy=", floppy_setup);
 
-/* eject the boot floppy (if we need the drive for a different root floppy) */
-/* This should only be called at boot time when we're sure that there's no
- * resource contention. */
-void floppy_eject(void)
-{
-	int dummy;
-	if (have_no_fdc)
-		return;
-	if(floppy_grab_irq_and_dma()==0)
-	{
-		lock_fdc(MAXTIMEOUT,0);
-		dummy=fd_eject(0);
-		process_fd_request();
-		floppy_release_irq_and_dma();
-	}
-}
 #endif
 
 EXPORT_NO_SYMBOLS;
diff -urN linux-2.4.19-pre5/drivers/block/genhd.c linux-2.4.19-pre6/drivers/block/genhd.c
--- linux-2.4.19-pre5/drivers/block/genhd.c	Mon Feb 25 11:37:57 2002
+++ linux-2.4.19-pre6/drivers/block/genhd.c	Thu Apr  4 22:04:55 2002
@@ -135,20 +135,39 @@
 get_partition_list(char *page, char **start, off_t offset, int count)
 {
 	struct gendisk *gp;
+	struct hd_struct *hd;
 	char buf[64];
 	int len, n;
 
-	len = sprintf(page, "major minor  #blocks  name\n\n");
+	len = sprintf(page, "major minor  #blocks  name     "
+			"rio rmerge rsect ruse wio wmerge "
+			"wsect wuse running use aveq\n\n");
+		
+		
 	read_lock(&gendisk_lock);
 	for (gp = gendisk_head; gp; gp = gp->next) {
 		for (n = 0; n < (gp->nr_real << gp->minor_shift); n++) {
 			if (gp->part[n].nr_sects == 0)
 				continue;
 
-			len += snprintf(page + len, 63,
-					"%4d  %4d %10d %s\n",
+			hd = &gp->part[n]; disk_round_stats(hd);
+			len += sprintf(page + len,
+					"%4d  %4d %10d %s "
+					"%d %d %d %d %d %d %d %d %d %d %d\n",
 					gp->major, n, gp->sizes[n],
-					disk_name(gp, n, buf));
+					disk_name(gp, n, buf),
+					hd->rd_ios, hd->rd_merges,
+					hd->rd_sectors,
+#define MSEC(x) ((x) * 1000 / HZ)
+					MSEC(hd->rd_ticks),
+					hd->wr_ios, hd->wr_merges,
+					hd->wr_sectors,
+					MSEC(hd->wr_ticks),
+					hd->ios_in_flight,
+					MSEC(hd->io_ticks),
+					MSEC(hd->aveq));
+#undef MSEC
+
 			if (len < offset)
 				offset -= len, len = 0;
 			else if (len >= offset + count)
diff -urN linux-2.4.19-pre5/drivers/block/ll_rw_blk.c linux-2.4.19-pre6/drivers/block/ll_rw_blk.c
--- linux-2.4.19-pre5/drivers/block/ll_rw_blk.c	Thu Apr  4 22:04:21 2002
+++ linux-2.4.19-pre6/drivers/block/ll_rw_blk.c	Thu Apr  4 22:04:55 2002
@@ -336,14 +336,17 @@
  */
 int blk_grow_request_list(request_queue_t *q, int nr_requests)
 {
-	spin_lock_irq(&io_request_lock);
+	unsigned long flags;
+	/* Several broken drivers assume that this function doesn't sleep,
+	 * this causes system hangs during boot.
+	 * As a temporary fix, make the the function non-blocking.
+	 */
+	spin_lock_irqsave(&io_request_lock, flags);
 	while (q->nr_requests < nr_requests) {
 		struct request *rq;
 		int rw;
 
-		spin_unlock_irq(&io_request_lock);
-		rq = kmem_cache_alloc(request_cachep, SLAB_KERNEL);
-		spin_lock_irq(&io_request_lock);
+		rq = kmem_cache_alloc(request_cachep, SLAB_ATOMIC);
 		if (rq == NULL)
 			break;
 		memset(rq, 0, sizeof(*rq));
@@ -356,7 +359,7 @@
 	q->batch_requests = q->nr_requests / 4;
 	if (q->batch_requests > 32)
 		q->batch_requests = 32;
-	spin_unlock_irq(&io_request_lock);
+	spin_unlock_irqrestore(&io_request_lock, flags);
 	return q->nr_requests;
 }
 
@@ -591,6 +594,121 @@
 		printk(KERN_ERR "drive_stat_acct: cmd not R/W?\n");
 }
 
+/* Return up to two hd_structs on which to do IO accounting for a given
+ * request.  On a partitioned device, we want to account both against
+ * the partition and against the whole disk.  */
+static void locate_hd_struct(struct request *req, 
+			     struct hd_struct **hd1,
+			     struct hd_struct **hd2)
+{
+	struct gendisk *gd;
+
+	*hd1 = NULL;
+	*hd2 = NULL;
+	
+	gd = get_gendisk(req->rq_dev);
+	if (gd && gd->part) {
+		/* Mask out the partition bits: account for the entire disk */
+		int devnr = MINOR(req->rq_dev) >> gd->minor_shift;
+		int whole_minor = devnr << gd->minor_shift;
+		*hd1 = &gd->part[whole_minor];
+		if (whole_minor != MINOR(req->rq_dev))
+			*hd2= &gd->part[MINOR(req->rq_dev)];
+	}
+}
+
+/* Round off the performance stats on an hd_struct.  The average IO
+ * queue length and utilisation statistics are maintained by observing
+ * the current state of the queue length and the amount of time it has
+ * been in this state for.  Normally, that accounting is done on IO
+ * completion, but that can result in more than a second's worth of IO
+ * being accounted for within any one second, leading to >100%
+ * utilisation.  To deal with that, we do a round-off before returning
+ * the results when reading /proc/partitions, accounting immediately for
+ * all queue usage up to the current jiffies and restarting the counters
+ * again. */
+void disk_round_stats(struct hd_struct *hd)
+{
+	unsigned long now = jiffies;
+	
+	hd->aveq += (hd->ios_in_flight * (jiffies - hd->last_queue_change));
+	hd->last_queue_change = now;
+
+	if (hd->ios_in_flight)
+		hd->io_ticks += (now - hd->last_idle_time);
+	hd->last_idle_time = now;	
+}
+
+
+static inline void down_ios(struct hd_struct *hd)
+{
+	disk_round_stats(hd);	
+	--hd->ios_in_flight;
+}
+
+static inline void up_ios(struct hd_struct *hd)
+{
+	disk_round_stats(hd);
+	++hd->ios_in_flight;
+}
+
+static void account_io_start(struct hd_struct *hd, struct request *req,
+			     int merge, int sectors)
+{
+	switch (req->cmd) {
+	case READ:
+		if (merge)
+			hd->rd_merges++;
+		hd->rd_sectors += sectors;
+		break;
+	case WRITE:
+		if (merge)
+			hd->wr_merges++;
+		hd->wr_sectors += sectors;
+		break;
+	default:
+	}
+	if (!merge)
+		up_ios(hd);
+}
+
+static void account_io_end(struct hd_struct *hd, struct request *req)
+{
+	unsigned long duration = jiffies - req->start_time;
+	switch (req->cmd) {
+	case READ:
+		hd->rd_ticks += duration;
+		hd->rd_ios++;
+		break;
+	case WRITE:
+		hd->wr_ticks += duration;
+		hd->wr_ios++;
+		break;
+	default:
+	}
+	down_ios(hd);
+}
+
+void req_new_io(struct request *req, int merge, int sectors)
+{
+	struct hd_struct *hd1, *hd2;
+	locate_hd_struct(req, &hd1, &hd2);
+	if (hd1)
+		account_io_start(hd1, req, merge, sectors);
+	if (hd2)
+		account_io_start(hd2, req, merge, sectors);
+}
+
+void req_finished_io(struct request *req)
+{
+	struct hd_struct *hd1, *hd2;
+	locate_hd_struct(req, &hd1, &hd2);
+	if (hd1)
+		account_io_end(hd1, req);
+	if (hd2)	
+		account_io_end(hd2, req);
+}
+
 /*
  * add-request adds a request to the linked list.
  * io_request_lock is held and interrupts disabled, as we muck with the
@@ -648,6 +766,7 @@
 			  int max_segments)
 {
 	struct request *next;
+	struct hd_struct *hd1, *hd2;
   
 	next = blkdev_next_request(req);
 	if (req->sector + req->nr_sectors != next->sector)
@@ -671,6 +790,15 @@
 	req->bhtail = next->bhtail;
 	req->nr_sectors = req->hard_nr_sectors += next->hard_nr_sectors;
 	list_del(&next->queue);
+
+	/* One last thing: we have removed a request, so we now have one
+	   less expected IO to complete for accounting purposes. */
+
+	locate_hd_struct(req, &hd1, &hd2);
+	if (hd1)
+		down_ios(hd1);
+	if (hd2)	
+		down_ios(hd2);
 	blkdev_release_request(next);
 }
 
@@ -778,6 +906,7 @@
 			req->nr_sectors = req->hard_nr_sectors += count;
 			blk_started_io(count);
 			drive_stat_acct(req->rq_dev, req->cmd, count, 0);
+			req_new_io(req, 1, count);
 			attempt_back_merge(q, req, max_sectors, max_segments);
 			goto out;
 
@@ -795,6 +924,7 @@
 			req->nr_sectors = req->hard_nr_sectors += count;
 			blk_started_io(count);
 			drive_stat_acct(req->rq_dev, req->cmd, count, 0);
+			req_new_io(req, 1, count);
 			attempt_front_merge(q, head, req, max_sectors, max_segments);
 			goto out;
 
@@ -856,6 +986,8 @@
 	req->bh = bh;
 	req->bhtail = bh;
 	req->rq_dev = bh->b_rdev;
+	req->start_time = jiffies;
+	req_new_io(req, 0, count);
 	blk_started_io(count);
 	add_request(q, req, insert_here);
 out:
@@ -1169,6 +1301,7 @@
 {
 	if (req->waiting != NULL)
 		complete(req->waiting);
+	req_finished_io(req);
 
 	blkdev_release_request(req);
 }
@@ -1197,9 +1330,6 @@
 #ifdef CONFIG_STRAM_SWAP
 	stram_device_init();
 #endif
-#ifdef CONFIG_BLK_DEV_RAM
-	rd_init();
-#endif
 #ifdef CONFIG_ISP16_CDI
 	isp16_init();
 #endif
@@ -1309,4 +1439,5 @@
 EXPORT_SYMBOL(blk_queue_make_request);
 EXPORT_SYMBOL(generic_make_request);
 EXPORT_SYMBOL(blkdev_release_request);
+EXPORT_SYMBOL(req_finished_io);
 EXPORT_SYMBOL(generic_unplug_device);
diff -urN linux-2.4.19-pre5/drivers/block/rd.c linux-2.4.19-pre6/drivers/block/rd.c
--- linux-2.4.19-pre5/drivers/block/rd.c	Thu Apr  4 22:04:21 2002
+++ linux-2.4.19-pre6/drivers/block/rd.c	Thu Apr  4 22:04:55 2002
@@ -43,26 +43,13 @@
  */
 
 #include <linux/config.h>
-#include <linux/sched.h>
-#include <linux/fs.h>
-#include <linux/kernel.h>
-#include <linux/hdreg.h>
 #include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/mman.h>
 #include <linux/slab.h>
-#include <linux/ioctl.h>
-#include <linux/fd.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/devfs_fs_kernel.h>
 #include <linux/smp_lock.h>
-
-#include <asm/system.h>
 #include <asm/uaccess.h>
-#include <asm/byteorder.h>
-
-extern void wait_for_keypress(void);
 
 /*
  * 35 has been officially registered as the RAMDISK major number, but
@@ -78,6 +65,8 @@
 
 #ifdef CONFIG_BLK_DEV_INITRD
 static int initrd_users;
+unsigned long initrd_start, initrd_end;
+int initrd_below_start_ok;
 #endif
 
 /* Various static variables go here.  Most are used only in the RAM disk code.
@@ -110,70 +99,6 @@
  */
 int rd_blocksize = BLOCK_SIZE;			/* blocksize of the RAM disks */
 
-#ifndef MODULE
-
-int rd_doload;			/* 1 = load RAM disk, 0 = don't load */
-int rd_prompt = 1;		/* 1 = prompt for RAM disk, 0 = don't prompt */
-int rd_image_start;		/* starting block # of image */
-#ifdef CONFIG_BLK_DEV_INITRD
-unsigned long initrd_start, initrd_end;
-int mount_initrd = 1;		/* zero if initrd should not be mounted */
-int initrd_below_start_ok;
-
-static int __init no_initrd(char *str)
-{
-	mount_initrd = 0;
-	return 1;
-}
-
-__setup("noinitrd", no_initrd);
-
-#endif
-
-static int __init ramdisk_start_setup(char *str)
-{
-	rd_image_start = simple_strtol(str,NULL,0);
-	return 1;
-}
-
-static int __init load_ramdisk(char *str)
-{
-	rd_doload = simple_strtol(str,NULL,0) & 3;
-	return 1;
-}
-
-static int __init prompt_ramdisk(char *str)
-{
-	rd_prompt = simple_strtol(str,NULL,0) & 1;
-	return 1;
-}
-
-static int __init ramdisk_size(char *str)
-{
-	rd_size = simple_strtol(str,NULL,0);
-	return 1;
-}
-
-static int __init ramdisk_size2(char *str)
-{
-	return ramdisk_size(str);
-}
-
-static int __init ramdisk_blocksize(char *str)
-{
-	rd_blocksize = simple_strtol(str,NULL,0);
-	return 1;
-}
-
-__setup("ramdisk_start=", ramdisk_start_setup);
-__setup("load_ramdisk=", load_ramdisk);
-__setup("prompt_ramdisk=", prompt_ramdisk);
-__setup("ramdisk=", ramdisk_size);
-__setup("ramdisk_size=", ramdisk_size2);
-__setup("ramdisk_blocksize=", ramdisk_blocksize);
-
-#endif
-
 /*
  * Copyright (C) 2000 Linus Torvalds.
  *               2000 Transmeta Corp.
@@ -463,7 +388,6 @@
 	ioctl:		rd_ioctl,
 };
 
-#ifdef MODULE
 /* Before freeing the module, invalidate all of the protected buffers! */
 static void __exit rd_cleanup (void)
 {
@@ -483,10 +407,9 @@
 	blksize_size[MAJOR_NR] = NULL;
 	blk_size[MAJOR_NR] = NULL;
 }
-#endif
 
 /* This is the registration and initialization section of the RAM disk driver */
-int __init rd_init (void)
+static int __init rd_init (void)
 {
 	int		i;
 
@@ -540,12 +463,31 @@
 	return 0;
 }
 
-#ifdef MODULE
 module_init(rd_init);
 module_exit(rd_cleanup);
+
+/* options - nonmodular */
+#ifndef MODULE
+static int __init ramdisk_size(char *str)
+{
+	rd_size = simple_strtol(str,NULL,0);
+	return 1;
+}
+static int __init ramdisk_size2(char *str)	/* kludge */
+{
+	return ramdisk_size(str);
+}
+static int __init ramdisk_blocksize(char *str)
+{
+	rd_blocksize = simple_strtol(str,NULL,0);
+	return 1;
+}
+__setup("ramdisk=", ramdisk_size);
+__setup("ramdisk_size=", ramdisk_size2);
+__setup("ramdisk_blocksize=", ramdisk_blocksize);
 #endif
 
-/* loadable module support */
+/* options - modular */
 MODULE_PARM     (rd_size, "1i");
 MODULE_PARM_DESC(rd_size, "Size of each RAM disk in kbytes.");
 MODULE_PARM     (rd_blocksize, "i");
diff -urN linux-2.4.19-pre5/drivers/block/swim3.c linux-2.4.19-pre6/drivers/block/swim3.c
--- linux-2.4.19-pre5/drivers/block/swim3.c	Mon Feb 25 11:37:57 2002
+++ linux-2.4.19-pre6/drivers/block/swim3.c	Thu Apr  4 22:04:55 2002
@@ -811,16 +811,6 @@
 	return err;
 }
 
-int swim3_fd_eject(int devnum)
-{
-	if (devnum >= floppy_count)
-		return -ENODEV;
-	/* Do not check this - this function should ONLY be called early
-	 * in the boot process! */
-	/* if (floppy_states[devnum].ref_count != 1) return -EBUSY; */
-	return fd_eject(&floppy_states[devnum]);
-}
-
 static struct floppy_struct floppy_type =
 	{ 2880,18,2,80,0,0x1B,0x00,0xCF,0x6C,NULL };	/*  7 1.44MB 3.5"   */
 
diff -urN linux-2.4.19-pre5/drivers/char/Config.in linux-2.4.19-pre6/drivers/char/Config.in
--- linux-2.4.19-pre5/drivers/char/Config.in	Thu Apr  4 22:04:21 2002
+++ linux-2.4.19-pre6/drivers/char/Config.in	Thu Apr  4 22:04:55 2002
@@ -177,18 +177,11 @@
 bool 'Watchdog Timer Support'	CONFIG_WATCHDOG
 if [ "$CONFIG_WATCHDOG" != "n" ]; then
    bool '  Disable watchdog shutdown on close' CONFIG_WATCHDOG_NOWAYOUT
-   tristate '  Software Watchdog' CONFIG_SOFT_WATCHDOG
-   tristate '  WDT Watchdog timer' CONFIG_WDT
-   tristate '  WDT PCI Watchdog timer' CONFIG_WDTPCI
-   if [ "$CONFIG_WDT" != "n" ]; then
-      bool '    WDT501 features' CONFIG_WDT_501
-      if [ "$CONFIG_WDT_501" = "y" ]; then
-         bool '      Fan Tachometer' CONFIG_WDT_501_FAN
-      fi
-   fi
-   tristate '  Berkshire Products PC Watchdog' CONFIG_PCWATCHDOG
    tristate '  Acquire SBC Watchdog Timer' CONFIG_ACQUIRE_WDT
    tristate '  Advantech SBC Watchdog Timer' CONFIG_ADVANTECH_WDT
+   tristate '  ALi M7101 PMU Watchdog Timer' CONFIG_ALIM7101_WDT
+   tristate '  AMD "Elan" SC520 Watchdog Timer' CONFIG_SC520_WDT
+   tristate '  Berkshire Products PC Watchdog' CONFIG_PCWATCHDOG
    if [ "$CONFIG_FOOTBRIDGE" = "y" ]; then
       tristate '  DC21285 watchdog' CONFIG_21285_WATCHDOG
       if [ "$CONFIG_ARCH_NETWINDER" = "y" ]; then
@@ -197,14 +190,25 @@
    fi
    tristate '  Eurotech CPU-1220/1410 Watchdog Timer' CONFIG_EUROTECH_WDT
    tristate '  IB700 SBC Watchdog Timer' CONFIG_IB700_WDT
+   tristate '  ICP ELectronics Wafer 5823 Watchdog' CONFIG_WAFER_WDT
+   if [ "$CONFIG_SGI_IP22" = "y" ]; then
+      dep_tristate '  Indy/I2 Hardware Watchdog' CONFIG_INDYDOG $CONFIG_SGI_IP22
+   fi
    tristate '  Intel i810 TCO timer / Watchdog' CONFIG_I810_TCO
    tristate '  Mixcom Watchdog' CONFIG_MIXCOMWD 
    tristate '  SBC-60XX Watchdog Timer' CONFIG_60XX_WDT
+   dep_tristate '  SC1200 Watchdog Timer (EXPERIMENTAL)' CONFIG_SC1200_WDT $CONFIG_EXPERIMENTAL
+   tristate '  Software Watchdog' CONFIG_SOFT_WATCHDOG
    tristate '  W83877F (EMACS) Watchdog Timer' CONFIG_W83877F_WDT
-   tristate '  ZF MachZ Watchdog' CONFIG_MACHZ_WDT
-   if [ "$CONFIG_SGI_IP22" = "y" ]; then
-      tristate '  Indy/I2 Hardware Watchdog' CONFIG_INDYDOG
+   tristate '  WDT Watchdog timer' CONFIG_WDT
+   tristate '  WDT PCI Watchdog timer' CONFIG_WDTPCI
+   if [ "$CONFIG_WDT" != "n" ]; then
+      bool '    WDT501 features' CONFIG_WDT_501
+      if [ "$CONFIG_WDT_501" = "y" ]; then
+         bool '      Fan Tachometer' CONFIG_WDT_501_FAN
+      fi
    fi
+   tristate '  ZF MachZ Watchdog' CONFIG_MACHZ_WDT
 fi
 endmenu
 
@@ -217,8 +221,12 @@
    tristate 'NetWinder flash support' CONFIG_NWFLASH
 fi
 
-dep_tristate 'AMD 768 Random Number Generator support' CONFIG_AMD_RNG $CONFIG_PCI
-dep_tristate 'Intel i8x0 Random Number Generator support' CONFIG_INTEL_RNG $CONFIG_PCI
+if [ "$CONFIG_X86" = "y" -o "$CONFIG_X86_64" = "y" ]; then
+   dep_tristate 'AMD 768 Random Number Generator support' CONFIG_AMD_RNG $CONFIG_PCI
+fi
+if [ "$CONFIG_X86" = "y" -o "$CONFIG_IA64" = "y" ]; then
+   dep_tristate 'Intel i8x0 Random Number Generator support' CONFIG_INTEL_RNG $CONFIG_PCI
+fi
 tristate '/dev/nvram support' CONFIG_NVRAM
 tristate 'Enhanced Real Time Clock Support' CONFIG_RTC
 if [ "$CONFIG_IA64" = "y" ]; then
@@ -277,4 +285,9 @@
 if [ "$CONFIG_MIPS_ITE8172" = "y" ]; then
   tristate ' ITE GPIO' CONFIG_ITE_GPIO
 fi
+
+if [ "$CONFIG_X86" = "y" ]; then
+   tristate 'ACP Modem (Mwave) support' CONFIG_MWAVE
+fi
+
 endmenu
diff -urN linux-2.4.19-pre5/drivers/char/agp/agp.h linux-2.4.19-pre6/drivers/char/agp/agp.h
--- linux-2.4.19-pre5/drivers/char/agp/agp.h	Mon Feb 25 11:37:57 2002
+++ linux-2.4.19-pre6/drivers/char/agp/agp.h	Thu Apr  4 22:04:55 2002
@@ -248,6 +248,9 @@
 #ifndef PCI_DEVICE_ID_AL_M1641_0
 #define PCI_DEVICE_ID_AL_M1641_0	0x1641
 #endif
+#ifndef PCI_DEVICE_ID_AL_M1644_0
+#define PCI_DEVICE_ID_AL_M1644_0	0x1644
+#endif
 #ifndef PCI_DEVICE_ID_AL_M1647_0
 #define PCI_DEVICE_ID_AL_M1647_0	0x1647
 #endif
diff -urN linux-2.4.19-pre5/drivers/char/agp/agpgart_be.c linux-2.4.19-pre6/drivers/char/agp/agpgart_be.c
--- linux-2.4.19-pre5/drivers/char/agp/agpgart_be.c	Thu Apr  4 22:04:21 2002
+++ linux-2.4.19-pre6/drivers/char/agp/agpgart_be.c	Thu Apr  4 22:04:55 2002
@@ -3484,6 +3484,12 @@
 		"Ali",
 		"M1641",
 		ali_generic_setup },
+	{ PCI_DEVICE_ID_AL_M1644_0,
+		PCI_VENDOR_ID_AL,
+		ALI_M1644,
+		"Ali",
+		"M1644",
+		ali_generic_setup },
 	{ PCI_DEVICE_ID_AL_M1647_0,
 		PCI_VENDOR_ID_AL,
 		ALI_M1647,
@@ -3515,7 +3521,7 @@
 		PCI_VENDOR_ID_AMD,
 		AMD_IRONGATE,
 		"AMD",
-		"AMD 760MP",
+		"760MP",
 		amd_irongate_setup },
 	{ PCI_DEVICE_ID_AMD_761_0,
 		PCI_VENDOR_ID_AMD,
@@ -3527,7 +3533,7 @@
 		PCI_VENDOR_ID_AMD,
 		AMD_762,
 		"AMD",
-		"AMD 760MP",
+		"760MP",
 		amd_irongate_setup },
 	{ 0,
 		PCI_VENDOR_ID_AMD,
diff -urN linux-2.4.19-pre5/drivers/char/console.c linux-2.4.19-pre6/drivers/char/console.c
--- linux-2.4.19-pre5/drivers/char/console.c	Fri Dec 21 09:41:53 2001
+++ linux-2.4.19-pre6/drivers/char/console.c	Thu Apr  4 22:04:55 2002
@@ -2179,7 +2179,6 @@
 	name:		"tty",
 	write:		vt_console_print,
 	device:		vt_console_device,
-	wait_key:	keyboard_wait_for_keypress,
 	unblank:	unblank_screen,
 	flags:		CON_PRINTBUFFER,
 	index:		-1,
diff -urN linux-2.4.19-pre5/drivers/char/drm/drm_agpsupport.h linux-2.4.19-pre6/drivers/char/drm/drm_agpsupport.h
--- linux-2.4.19-pre5/drivers/char/drm/drm_agpsupport.h	Thu Nov 22 11:46:37 2001
+++ linux-2.4.19-pre6/drivers/char/drm/drm_agpsupport.h	Thu Apr  4 22:04:55 2002
@@ -303,6 +303,7 @@
 		case ALI_M1631: 	head->chipset = "ALi M1631";	 break;
 		case ALI_M1632: 	head->chipset = "ALi M1632";	 break;
 		case ALI_M1641: 	head->chipset = "ALi M1641";	 break;
+		case ALI_M1644: 	head->chipset = "ALi M1644";	 break;
 		case ALI_M1647: 	head->chipset = "ALi M1647";	 break;
 		case ALI_M1651: 	head->chipset = "ALi M1651";	 break;
 #endif
diff -urN linux-2.4.19-pre5/drivers/char/dz.c linux-2.4.19-pre6/drivers/char/dz.c
--- linux-2.4.19-pre5/drivers/char/dz.c	Thu Apr  4 22:04:21 2002
+++ linux-2.4.19-pre6/drivers/char/dz.c	Thu Apr  4 22:04:55 2002
@@ -63,7 +63,6 @@
 
 DECLARE_TASK_QUEUE(tq_serial);
 
-extern wait_queue_head_t keypress_wait;
 static struct dz_serial *lines[4];
 static unsigned char tmp_buffer[256];
 
@@ -219,9 +218,6 @@
 		if (info->is_console) {
 			if (ch == 0)
 				return;		/* it's a break ... */
-
-			/* It is a 'keyboard interrupt' ;-) */
-			wake_up(&keypress_wait);
 		}
 #endif
 
@@ -1484,11 +1480,6 @@
 	}
 }
 
-static int dz_console_wait_key(struct console *co)
-{
-	return 0;
-}
-
 static kdev_t dz_console_device(struct console *c)
 {
 	return MKDEV(TTY_MAJOR, 64 + c->index);
@@ -1587,7 +1578,6 @@
     name:	"ttyS",
     write:	dz_console_print,
     device:	dz_console_device,
-    wait_key:	dz_console_wait_key,
     setup:	dz_console_setup,
     flags:	CON_CONSDEV | CON_PRINTBUFFER,
     index:	CONSOLE_LINE,
diff -urN linux-2.4.19-pre5/drivers/char/indydog.c linux-2.4.19-pre6/drivers/char/indydog.c
--- linux-2.4.19-pre5/drivers/char/indydog.c	Thu Apr  4 22:04:21 2002
+++ linux-2.4.19-pre6/drivers/char/indydog.c	Thu Apr  4 22:04:55 2002
@@ -24,7 +24,7 @@
 #include <asm/uaccess.h>
 #include <asm/sgi/sgimc.h>
 
-static int indydog_alive;
+static unsigned long indydog_alive;
 static struct sgimc_misc_ctrl *mcmisc_regs; 
 
 static void indydog_ping()
@@ -41,7 +41,7 @@
 {
 	u32 mc_ctrl0;
 	
-	if(indydog_alive)
+	if( test_and_set_bit(0,&indydog_alive) )
 		return -EBUSY;
 #ifdef CONFIG_WATCHDOG_NOWAYOUT
 	MOD_INC_USE_COUNT;
@@ -55,7 +55,6 @@
 	mcmisc_regs->cpuctrl0 = mc_ctrl0;
 	indydog_ping();
 			
-	indydog_alive=1;
 	printk("Started watchdog timer.\n");
 	return 0;
 }
@@ -66,7 +65,6 @@
 	 *	Shut off the timer.
 	 * 	Lock it in if it's a module and we defined ...NOWAYOUT
 	 */
-	 lock_kernel();
 #ifndef CONFIG_WATCHDOG_NOWAYOUT
 	{
 	u32 mc_ctrl0 = mcmisc_regs->cpuctrl0; 
@@ -75,8 +73,7 @@
 	printk("Stopped watchdog timer.\n");
 	}
 #endif
-	indydog_alive=0;
-	unlock_kernel();
+	clear_bit(0,&indydog_alive);
 	return 0;
 }
 
diff -urN linux-2.4.19-pre5/drivers/char/joystick/a3d.c linux-2.4.19-pre6/drivers/char/joystick/a3d.c
--- linux-2.4.19-pre5/drivers/char/joystick/a3d.c	Wed Sep 12 15:34:06 2001
+++ linux-2.4.19-pre6/drivers/char/joystick/a3d.c	Thu Apr  4 22:04:55 2002
@@ -190,7 +190,7 @@
 
 int a3d_adc_cooked_read(struct gameport *gameport, int *axes, int *buttons)
 {
-	struct a3d *a3d = gameport->private;
+	struct a3d *a3d = gameport->driver;
 	int i;
 	for (i = 0; i < 4; i++)
 		axes[i] = (a3d->axes[i] < 254) ? a3d->axes[i] : -1;
@@ -205,7 +205,7 @@
 
 int a3d_adc_open(struct gameport *gameport, int mode)
 {
-	struct a3d *a3d = gameport->private;
+	struct a3d *a3d = gameport->driver;
 	if (mode != GAMEPORT_MODE_COOKED)
 		return -1;
 	if (!a3d->used++)
@@ -219,7 +219,7 @@
 
 static void a3d_adc_close(struct gameport *gameport)
 {
-	struct a3d *a3d = gameport->private;
+	struct a3d *a3d = gameport->driver;
 	if (!--a3d->used)
 		del_timer(&a3d->timer);
 }
@@ -323,7 +323,7 @@
 		a3d->dev.relbit[0] |= BIT(REL_X) | BIT(REL_Y);
 		a3d->dev.keybit[LONG(BTN_MOUSE)] |= BIT(BTN_RIGHT) | BIT(BTN_LEFT) | BIT(BTN_MIDDLE);
 
-		a3d->adc.private = a3d;
+		a3d->adc.driver = a3d;
 		a3d->adc.open = a3d_adc_open;
 		a3d->adc.close = a3d_adc_close;
 		a3d->adc.cooked_read = a3d_adc_cooked_read;
diff -urN linux-2.4.19-pre5/drivers/char/joystick/lightning.c linux-2.4.19-pre6/drivers/char/joystick/lightning.c
--- linux-2.4.19-pre5/drivers/char/joystick/lightning.c	Wed Sep 12 15:34:06 2001
+++ linux-2.4.19-pre6/drivers/char/joystick/lightning.c	Thu Apr  4 22:04:55 2002
@@ -77,7 +77,7 @@
 
 static int l4_cooked_read(struct gameport *gameport, int *axes, int *buttons)
 {
-	struct l4 *l4 = gameport->private;
+	struct l4 *l4 = gameport->driver;
 	unsigned char status;
 	int i, result = -1;
 
@@ -110,7 +110,7 @@
 
 static int l4_open(struct gameport *gameport, int mode)
 {
-	struct l4 *l4 = gameport->private;
+	struct l4 *l4 = gameport->driver;
         if (l4->port != 0 && mode != GAMEPORT_MODE_COOKED)
 		return -1;
 	outb(L4_SELECT_ANALOG, L4_PORT);
@@ -188,7 +188,7 @@
 {
 	int i, t;
 	int cal[4];
-	struct l4 *l4 = gameport->private;
+	struct l4 *l4 = gameport->driver;
 
 	if (l4_getcal(l4->port, cal))
 		return -1;
@@ -248,7 +248,7 @@
 			l4->port = i * 4 + j;
 
 			gameport = &l4->gameport;
-			gameport->private = l4;
+			gameport->driver = l4;
 			gameport->open = l4_open;
 			gameport->cooked_read = l4_cooked_read;
 			gameport->calibrate = l4_calibrate;
diff -urN linux-2.4.19-pre5/drivers/char/joystick/pcigame.c linux-2.4.19-pre6/drivers/char/joystick/pcigame.c
--- linux-2.4.19-pre5/drivers/char/joystick/pcigame.c	Fri Dec 21 09:41:54 2001
+++ linux-2.4.19-pre6/drivers/char/joystick/pcigame.c	Thu Apr  4 22:04:55 2002
@@ -76,19 +76,19 @@
 
 static unsigned char pcigame_read(struct gameport *gameport)
 {
-	struct pcigame *pcigame = gameport->private;
+	struct pcigame *pcigame = gameport->driver;
 	return readb(pcigame->base + pcigame->data->legacy);
 }
 
 static void pcigame_trigger(struct gameport *gameport)
 {
-	struct pcigame *pcigame = gameport->private;
+	struct pcigame *pcigame = gameport->driver;
 	writeb(0xff, pcigame->base + pcigame->data->legacy);
 }
 
 static int pcigame_cooked_read(struct gameport *gameport, int *axes, int *buttons)
 {
-        struct pcigame *pcigame = gameport->private;
+        struct pcigame *pcigame = gameport->driver;
 	int i;
 
 	*buttons = (~readb(pcigame->base + pcigame->data->legacy) >> 4) & 0xf;
@@ -103,7 +103,7 @@
 
 static int pcigame_open(struct gameport *gameport, int mode)
 {
-	struct pcigame *pcigame = gameport->private;
+	struct pcigame *pcigame = gameport->driver;
 
 	switch (mode) {
 		case GAMEPORT_MODE_COOKED:
@@ -135,7 +135,7 @@
 	pcigame->dev = dev;
 	pci_set_drvdata(dev, pcigame);
 
-	pcigame->gameport.private = pcigame;
+	pcigame->gameport.driver = pcigame;
 	pcigame->gameport.fuzz = 64;
 	
 	pcigame->gameport.read = pcigame_read;
diff -urN linux-2.4.19-pre5/drivers/char/keyboard.c linux-2.4.19-pre6/drivers/char/keyboard.c
--- linux-2.4.19-pre5/drivers/char/keyboard.c	Thu Apr  4 22:04:21 2002
+++ linux-2.4.19-pre6/drivers/char/keyboard.c	Thu Apr  4 22:04:55 2002
@@ -67,15 +67,8 @@
 
 extern void ctrl_alt_del(void);
 
-DECLARE_WAIT_QUEUE_HEAD(keypress_wait);
 struct console;
 
-int keyboard_wait_for_keypress(struct console *co)
-{
-	sleep_on(&keypress_wait);
-	return 0;
-}
-
 /*
  * global state includes the following, and various static variables
  * in this module: prev_scancode, shift_state, diacr, npadch, dead_key_next.
@@ -339,7 +332,6 @@
 	if (forward_chars == fg_console+1){
 		kbd_forward_char (ch);
 	} else {
-		wake_up(&keypress_wait);
 		if (tty) {
 			tty_insert_flip_char(tty, ch, 0);
 			con_schedule_flip(tty);
@@ -349,7 +341,6 @@
 #else
 void put_queue(int ch)
 {
-	wake_up(&keypress_wait);
 	if (tty) {
 		tty_insert_flip_char(tty, ch, 0);
 		con_schedule_flip(tty);
@@ -359,7 +350,6 @@
 
 static void puts_queue(char *cp)
 {
-	wake_up(&keypress_wait);
 	if (!tty)
 		return;
 
diff -urN linux-2.4.19-pre5/drivers/char/sb1250_duart.c linux-2.4.19-pre6/drivers/char/sb1250_duart.c
--- linux-2.4.19-pre5/drivers/char/sb1250_duart.c	Thu Apr  4 22:04:21 2002
+++ linux-2.4.19-pre6/drivers/char/sb1250_duart.c	Thu Apr  4 22:04:55 2002
@@ -774,11 +774,6 @@
 	return MKDEV(TTY_MAJOR, 64 + c->index);
 }
 
-static int ser_console_wait_key(struct console *cons)
-{
-	panic("ser_console_wait_key called");
-}
-
 static int ser_console_setup(struct console *cons, char *str)
 {
 	/* Initialize the transmitter */
@@ -791,7 +786,6 @@
 	name:		"ttyS",
 	write:		ser_console_write,
 	device:		ser_console_device,
-	wait_key:	ser_console_wait_key,
 	setup:		ser_console_setup,
 	flags:		CON_PRINTBUFFER,
 	index:		-1,
diff -urN linux-2.4.19-pre5/drivers/char/serial.c linux-2.4.19-pre6/drivers/char/serial.c
--- linux-2.4.19-pre5/drivers/char/serial.c	Thu Apr  4 22:04:21 2002
+++ linux-2.4.19-pre6/drivers/char/serial.c	Thu Apr  4 22:04:55 2002
@@ -5833,35 +5833,6 @@
 	serial_out(info, UART_IER, ier);
 }
 
-/*
- *	Receive character from the serial port
- */
-static int serial_console_wait_key(struct console *co)
-{
-	static struct async_struct *info;
-	int ier, c;
-
-	info = &async_sercons;
-
-	/*
-	 *	First save the IER then disable the interrupts so
-	 *	that the real driver for the port does not get the
-	 *	character.
-	 */
-	ier = serial_in(info, UART_IER);
-	serial_out(info, UART_IER, 0x00);
- 
-	while ((serial_in(info, UART_LSR) & UART_LSR_DR) == 0);
-	c = serial_in(info, UART_RX);
-
-	/*
-	 *	Restore the interrupts
-	 */
-	serial_out(info, UART_IER, ier);
-
-	return c;
-}
-
 static kdev_t serial_console_device(struct console *c)
 {
 	return MKDEV(TTY_MAJOR, 64 + c->index);
@@ -6002,7 +5973,6 @@
 	name:		"ttyS",
 	write:		serial_console_write,
 	device:		serial_console_device,
-	wait_key:	serial_console_wait_key,
 	setup:		serial_console_setup,
 	flags:		CON_PRINTBUFFER,
 	index:		-1,
diff -urN linux-2.4.19-pre5/drivers/char/serial167.c linux-2.4.19-pre6/drivers/char/serial167.c
--- linux-2.4.19-pre5/drivers/char/serial167.c	Thu Apr  4 22:04:21 2002
+++ linux-2.4.19-pre6/drivers/char/serial167.c	Thu Apr  4 22:04:55 2002
@@ -2814,58 +2814,6 @@
 	restore_flags(flags);
 }
 
-/* This is a hack; if there are multiple chars waiting in the chip we
- * discard all but the last one, and return that.  The cd2401 is not really
- * designed to be driven in polled mode.
- */
-
-int serial167_console_wait_key(struct console *co)
-{
-	volatile unsigned char *base_addr = (u_char *)BASE_ADDR;
-	unsigned long flags;
-	volatile u_char sink;
-	u_char ier;
-	int port;
-	int keypress = 0;
-
-	save_flags(flags); cli();
-
-	/* Ensure receiver is enabled! */
-
-	port = 0;
-	base_addr[CyCAR] = (u_char)port;
-	while (base_addr[CyCCR])
-		;
-	base_addr[CyCCR] = CyENB_RCVR;
-	ier = base_addr[CyIER];
-	base_addr[CyIER] = CyRxData;
-
-	while (!keypress) {
-		if (pcc2chip[PccSCCRICR] & 0x20)
-		{
-			/* We have an Rx int. Acknowledge it */
-			sink = pcc2chip[PccRPIACKR];
-			if ((base_addr[CyLICR] >> 2) == port) {
-				int cnt = base_addr[CyRFOC];
-				while (cnt-- > 0)
-				{
-					keypress = base_addr[CyRDR];
-				}
-				base_addr[CyREOIR] = 0;
-			}
-			else
-				base_addr[CyREOIR] = CyNOTRANS;
-		}
-	}
-
-	base_addr[CyIER] = ier;
-
-	restore_flags(flags);
-
-	return keypress;
-}
-
-
 static kdev_t serial167_console_device(struct console *c)
 {
 	return MKDEV(TTY_MAJOR, 64 + c->index);
@@ -2882,7 +2830,6 @@
 	name:		"ttyS",
 	write:		serial167_console_write,
 	device:		serial167_console_device,
-	wait_key:	serial167_console_wait_key,
 	setup:		serial167_console_setup,
 	flags:		CON_PRINTBUFFER,
 	index:		-1,
diff -urN linux-2.4.19-pre5/drivers/char/serial_21285.c linux-2.4.19-pre6/drivers/char/serial_21285.c
--- linux-2.4.19-pre5/drivers/char/serial_21285.c	Thu Sep 13 15:21:32 2001
+++ linux-2.4.19-pre6/drivers/char/serial_21285.c	Thu Apr  4 22:04:55 2002
@@ -389,17 +389,6 @@
 	enable_irq(IRQ_CONTX);
 }
 
-static int rs285_console_wait_key(struct console *co)
-{
-	int c;
-
-	disable_irq(IRQ_CONRX);
-	while (*CSR_UARTFLG & 0x10);
-	c = *CSR_UARTDR;
-	enable_irq(IRQ_CONRX);
-	return c;
-}
-
 static kdev_t rs285_console_device(struct console *c)
 {
 	return MKDEV(SERIAL_21285_MAJOR, SERIAL_21285_MINOR);
@@ -493,7 +482,6 @@
 	name:		SERIAL_21285_NAME,
 	write:		rs285_console_write,
 	device:		rs285_console_device,
-	wait_key:	rs285_console_wait_key,
 	setup:		rs285_console_setup,
 	flags:		CON_PRINTBUFFER,
 	index:		-1,
diff -urN linux-2.4.19-pre5/drivers/char/serial_amba.c linux-2.4.19-pre6/drivers/char/serial_amba.c
--- linux-2.4.19-pre5/drivers/char/serial_amba.c	Sun Sep 16 21:23:14 2001
+++ linux-2.4.19-pre6/drivers/char/serial_amba.c	Thu Apr  4 22:04:55 2002
@@ -1921,22 +1921,6 @@
 	UART_PUT_CR(port, old_cr);
 }
 
-/*
- *	Receive character from the serial port
- */
-static int ambauart_console_wait_key(struct console *co)
-{
-	struct amba_port *port = &amba_ports[co->index];
-	unsigned int status;
-	int c;
-
-	do {
-		status = UART_GET_FR(port);
-	} while (!UART_RX_DATA(status));
-	c = UART_GET_CHAR(port);
-	return c;
-}
-
 static kdev_t ambauart_console_device(struct console *c)
 {
 	return MKDEV(SERIAL_AMBA_MAJOR, SERIAL_AMBA_MINOR + c->index);
@@ -2015,7 +1999,6 @@
 	read:		ambauart_console_read,
 #endif
 	device:		ambauart_console_device,
-	wait_key:	ambauart_console_wait_key,
 	setup:		ambauart_console_setup,
 	flags:		CON_PRINTBUFFER,
 	index:		-1,
diff -urN linux-2.4.19-pre5/drivers/char/serial_tx3912.c linux-2.4.19-pre6/drivers/char/serial_tx3912.c
--- linux-2.4.19-pre5/drivers/char/serial_tx3912.c	Thu Apr  4 22:04:21 2002
+++ linux-2.4.19-pre6/drivers/char/serial_tx3912.c	Thu Apr  4 22:04:55 2002
@@ -752,21 +752,6 @@
 	outl(int2, TX3912_INT2_ENABLE);
 }
 
-static int serial_console_wait_key(struct console *co)
-{
-	unsigned int int2, res;
-
-	int2 = inl(TX3912_INT2_ENABLE);
-	outl(0, TX3912_INT2_ENABLE);
-
-	while (!(inl(TX3912_UARTA_CTRL1) & TX3912_UART_CTRL1_RXHOLDFULL));
-	res = inl(TX3912_UARTA_DATA);
-	udelay(10);
-	
-	outl(int2, TX3912_INT2_ENABLE);
-	return res;
-}
-
 static void serial_console_write(struct console *co, const char *s,
 	unsigned count)
 {
@@ -866,7 +851,6 @@
 	name:     "ttyS",
 	write:    serial_console_write,
 	device:   serial_console_device,
-	wait_key: serial_console_wait_key,
 	setup:    serial_console_setup,
 	flags:    CON_PRINTBUFFER,
 	index:    -1
diff -urN linux-2.4.19-pre5/drivers/char/serial_txx927.c linux-2.4.19-pre6/drivers/char/serial_txx927.c
--- linux-2.4.19-pre5/drivers/char/serial_txx927.c	Thu Apr  4 22:04:21 2002
+++ linux-2.4.19-pre6/drivers/char/serial_txx927.c	Thu Apr  4 22:04:55 2002
@@ -2181,35 +2181,6 @@
 	sio_reg(info)->dicr = ier;
 }
 
-/*
- *	Receive character from the serial port
- */
-static int serial_console_wait_key(struct console *co)
-{
-	static struct async_struct *info = &async_sercons;
-	int ier;
-	int c;
-
-	/*
-	 *	First save the IER then disable the interrupts so
-	 *	that the real driver for the port does not get the
-	 *	character.
-	 */
-	ier = sio_reg(info)->dicr;
-	sio_reg(info)->dicr = 0;
-
-	while (sio_reg(info)->disr & TXx927_SIDISR_UVALID)
-		;
-	c = sio_reg(info)->rfifo;
-
-	/*
-	 *	Restore the interrupts
-	 */
-	sio_reg(info)->dicr = ier;
-
-	return c;
-}
-
 static kdev_t serial_console_device(struct console *c)
 {
 	return MKDEV(TXX927_TTY_MAJOR, TXX927_TTY_MINOR_START + c->index);
@@ -2343,7 +2314,6 @@
 	name:           TXX927_TTY_NAME,
 	write:          serial_console_write,
 	device:	        serial_console_device,
-	wait_key:	serial_console_wait_key,
 	setup:	        serial_console_setup,
 	flags:	        CON_PRINTBUFFER,
 	index:	        -1,
diff -urN linux-2.4.19-pre5/drivers/char/sh-sci.c linux-2.4.19-pre6/drivers/char/sh-sci.c
--- linux-2.4.19-pre5/drivers/char/sh-sci.c	Mon Feb 25 11:37:57 2002
+++ linux-2.4.19-pre6/drivers/char/sh-sci.c	Thu Apr  4 22:04:55 2002
@@ -1181,15 +1181,6 @@
 	put_string(sercons_port, s, count);
 }
 
-/*
- *	Receive character from the serial port
- */
-static int serial_console_wait_key(struct console *co)
-{
-	/* Not implemented yet */
-	return 0;
-}
-
 static kdev_t serial_console_device(struct console *c)
 {
 	return MKDEV(SCI_MAJOR, SCI_MINOR_START + c->index);
@@ -1273,7 +1264,6 @@
 	name:		"ttySC",
 	write:		serial_console_write,
 	device:		serial_console_device,
-	wait_key:	serial_console_wait_key,
 	setup:		serial_console_setup,
 	flags:		CON_PRINTBUFFER,
 	index:		-1,
diff -urN linux-2.4.19-pre5/drivers/char/sonypi.c linux-2.4.19-pre6/drivers/char/sonypi.c
--- linux-2.4.19-pre5/drivers/char/sonypi.c	Mon Feb 25 11:37:57 2002
+++ linux-2.4.19-pre6/drivers/char/sonypi.c	Thu Apr  4 22:04:55 2002
@@ -50,6 +50,7 @@
 static int fnkeyinit; /* = 0 */
 static int camera; /* = 0 */
 static int compat; /* = 0 */
+static int nojogdial; /* = 0 */
 
 /* Inits the queue */
 static inline void sonypi_initq(void) {
@@ -310,24 +311,28 @@
 	int i;
 	u8 sonypi_jogger_ev, sonypi_fnkey_ev;
 	u8 sonypi_capture_ev, sonypi_bluetooth_ev;
+	u8 sonypi_pkey_ev;
 
 	if (sonypi_device.model == SONYPI_DEVICE_MODEL_TYPE2) {
 		sonypi_jogger_ev = SONYPI_TYPE2_JOGGER_EV;
 		sonypi_fnkey_ev = SONYPI_TYPE2_FNKEY_EV;
 		sonypi_capture_ev = SONYPI_TYPE2_CAPTURE_EV;
 		sonypi_bluetooth_ev = SONYPI_TYPE2_BLUETOOTH_EV;
+		sonypi_pkey_ev = nojogdial ? SONYPI_TYPE2_PKEY_EV 
+					   : SONYPI_TYPE1_PKEY_EV;
 	}
 	else {
 		sonypi_jogger_ev = SONYPI_TYPE1_JOGGER_EV;
 		sonypi_fnkey_ev = SONYPI_TYPE1_FNKEY_EV;
 		sonypi_capture_ev = SONYPI_TYPE1_CAPTURE_EV;
 		sonypi_bluetooth_ev = SONYPI_TYPE1_BLUETOOTH_EV;
+		sonypi_pkey_ev = SONYPI_TYPE1_PKEY_EV;
 	}
 
 	v1 = inb_p(sonypi_device.ioport1);
 	v2 = inb_p(sonypi_device.ioport2);
 
-	if ((v2 & SONYPI_TYPE1_PKEY_EV) == SONYPI_TYPE1_PKEY_EV) {
+	if ((v2 & sonypi_pkey_ev) == sonypi_pkey_ev) {
 		for (i = 0; sonypi_pkeyev[i].event; i++)
 			if (sonypi_pkeyev[i].data == v1) {
 				event = sonypi_pkeyev[i].event;
@@ -713,11 +718,12 @@
 	       SONYPI_DRIVER_MAJORVERSION,
 	       SONYPI_DRIVER_MINORVERSION);
 	printk(KERN_INFO "sonypi: detected %s model, "
-	       "camera = %s, compat = %s\n",
+	       "camera = %s, compat = %s, nojogdial = %s\n",
 	       (sonypi_device.model == SONYPI_DEVICE_MODEL_TYPE1) ?
 			"type1" : "type2",
 	       camera ? "on" : "off",
-	       compat ? "on" : "off");
+	       compat ? "on" : "off",
+	       nojogdial ? "on" : "off");
 	printk(KERN_INFO "sonypi: enabled at irq=%d, port1=0x%x, port2=0x%x\n",
 	       sonypi_device.irq, 
 	       sonypi_device.ioport1, sonypi_device.ioport2);
@@ -791,6 +797,9 @@
 	if (ints[0] == 4)
 		goto out;
 	compat = ints[5];
+	if (ints[0] == 5)
+		goto out;
+	nojogdial = ints[6];
 out:
 	return 1;
 }
@@ -817,5 +826,7 @@
 MODULE_PARM_DESC(camera, "set this if you have a MotionEye camera (PictureBook series)");
 MODULE_PARM(compat,"i");
 MODULE_PARM_DESC(compat, "set this if you want to enable backward compatibility mode");
+MODULE_PARM(nojogdial, "i");
+MODULE_PARM_DESC(nojogdial, "set this if you have a Vaio without a jogdial (like the fx series)");
 
 EXPORT_SYMBOL(sonypi_camera_command);
diff -urN linux-2.4.19-pre5/drivers/char/sonypi.h linux-2.4.19-pre6/drivers/char/sonypi.h
--- linux-2.4.19-pre5/drivers/char/sonypi.h	Mon Feb 25 11:37:57 2002
+++ linux-2.4.19-pre6/drivers/char/sonypi.h	Thu Apr  4 22:04:55 2002
@@ -35,7 +35,7 @@
 #ifdef __KERNEL__
 
 #define SONYPI_DRIVER_MAJORVERSION	 1
-#define SONYPI_DRIVER_MINORVERSION	10
+#define SONYPI_DRIVER_MINORVERSION	11
 
 #include <linux/types.h>
 #include <linux/pci.h>
@@ -141,6 +141,7 @@
 #define SONYPI_TYPE1_BLUETOOTH_EV	0x30
 #define SONYPI_TYPE2_BLUETOOTH_EV	0x08
 #define SONYPI_TYPE1_PKEY_EV		0x40
+#define SONYPI_TYPE2_PKEY_EV		0x08
 #define SONYPI_BACK_EV			0x08
 #define SONYPI_LID_EV			0x38
 
diff -urN linux-2.4.19-pre5/drivers/char/tty_io.c linux-2.4.19-pre6/drivers/char/tty_io.c
--- linux-2.4.19-pre5/drivers/char/tty_io.c	Thu Apr  4 22:04:21 2002
+++ linux-2.4.19-pre6/drivers/char/tty_io.c	Thu Apr  4 22:04:55 2002
@@ -603,12 +603,6 @@
 	read_unlock(&tasklist_lock);
 }
 
-void wait_for_keypress(void)
-{
-        struct console *c = console_drivers;
-        if (c) c->wait_key(c);
-}
-
 void stop_tty(struct tty_struct *tty)
 {
 	if (tty->stopped)
diff -urN linux-2.4.19-pre5/drivers/char/vme_scc.c linux-2.4.19-pre6/drivers/char/vme_scc.c
--- linux-2.4.19-pre5/drivers/char/vme_scc.c	Thu Apr  4 22:04:21 2002
+++ linux-2.4.19-pre6/drivers/char/vme_scc.c	Thu Apr  4 22:04:55 2002
@@ -1082,41 +1082,6 @@
 	restore_flags(flags);
 }
 
-
-static int scc_console_wait_key(struct console *co)
-{
-	unsigned long	flags;
-	volatile char *p = NULL;
-	int c;
-	
-#ifdef CONFIG_MVME147_SCC
-	if (MACH_IS_MVME147)
-		p = (volatile char *)M147_SCC_A_ADDR;
-#endif
-#ifdef CONFIG_MVME162_SCC
-	if (MACH_IS_MVME16x)
-		p = (volatile char *)MVME_SCC_A_ADDR;
-#endif
-#ifdef CONFIG_BVME6000_SCC
-	if (MACH_IS_BVME6000)
-		p = (volatile char *)BVME_SCC_A_ADDR;
-#endif
-
-	save_flags(flags);
-	cli();
-
-	/* wait for rx buf filled */
-	while ((*p & 0x01) == 0)
-		;
-
-	*p = 8;
-	scc_delay();
-	c = *p;
-	restore_flags(flags);
-	return c;
-}
-
-
 static kdev_t scc_console_device(struct console *c)
 {
 	return MKDEV(TTY_MAJOR, SCC_MINOR_BASE + c->index);
@@ -1133,7 +1098,6 @@
 	name:		"ttyS",
 	write:		scc_console_write,
 	device:		scc_console_device,
-	wait_key:	scc_console_wait_key,
 	setup:		scc_console_setup,
 	flags:		CON_PRINTBUFFER,
 	index:		-1,
diff -urN linux-2.4.19-pre5/drivers/char/wdt285.c linux-2.4.19-pre6/drivers/char/wdt285.c
--- linux-2.4.19-pre5/drivers/char/wdt285.c	Mon Feb 25 11:37:57 2002
+++ linux-2.4.19-pre6/drivers/char/wdt285.c	Thu Apr  4 22:04:55 2002
@@ -138,11 +138,9 @@
 		default:
 			return -ENOTTY;
 		case WDIOC_GETSUPPORT:
-			i = verify_area(VERIFY_WRITE, (void*) arg, sizeof(struct watchdog_info));
-			if (i)
-				return i;
-			else
-				return copy_to_user((struct watchdog_info *)arg, &ident, sizeof(ident));
+			if(copy_to_user((struct watchdog_info *)arg, &ident, sizeof(ident)))
+				return -EFAULT;
+			return 0;
 		case WDIOC_GETSTATUS:
 		case WDIOC_GETBOOTSTATUS:
 			return put_user(0,(int *)arg);
diff -urN linux-2.4.19-pre5/drivers/ide/hptraid.c linux-2.4.19-pre6/drivers/ide/hptraid.c
--- linux-2.4.19-pre5/drivers/ide/hptraid.c	Mon Oct 15 13:27:42 2001
+++ linux-2.4.19-pre6/drivers/ide/hptraid.c	Thu Apr  4 22:04:56 2002
@@ -123,13 +123,8 @@
 			return 0;
 		}
 			
-		case BLKROSET:
-		case BLKROGET:
-		case BLKSSZGET:
-			return blk_ioctl(inode->i_rdev, cmd, arg);
-
 		default:
-			return -EINVAL;
+			return blk_ioctl(inode->i_rdev, cmd, arg);
 	};
 
 	return 0;
@@ -366,7 +361,11 @@
 	probedisk(IDE2_MAJOR, 64, device);
 	probedisk(IDE3_MAJOR,  0, device);
 	probedisk(IDE3_MAJOR, 64, device);
-                                                                	
+	probedisk(IDE4_MAJOR,  0, device);
+	probedisk(IDE4_MAJOR, 64, device);
+	probedisk(IDE5_MAJOR,  0, device);
+	probedisk(IDE5_MAJOR, 64, device);
+
 	fill_cutoff(device);
 	
 	/* Initialize the gendisk structure */
diff -urN linux-2.4.19-pre5/drivers/ide/sis5513.c linux-2.4.19-pre6/drivers/ide/sis5513.c
--- linux-2.4.19-pre5/drivers/ide/sis5513.c	Thu Apr  4 22:04:22 2002
+++ linux-2.4.19-pre6/drivers/ide/sis5513.c	Thu Apr  4 22:04:56 2002
@@ -1,12 +1,19 @@
 /*
- * linux/drivers/ide/sis5513.c		Version 0.13	February 14, 2002
+ * linux/drivers/ide/sis5513.c		Version 0.13	March 6, 2002
  *
  * Copyright (C) 1999-2000	Andre Hedrick <andre@linux-ide.org>
  * Copyright (C) 2002		Lionel Bouton <Lionel.Bouton@inet6.fr>, Maintainer
  * May be copied or modified under the terms of the GNU General Public License
  *
- * Thanks to SIS Taiwan for direct support and hardware.
- * Thanks to Daniela Engert for ATA100 support advice.
+ *
+ * Thanks :
+ *
+ * SiS Taiwan		: for direct support and hardware.
+ * Daniela Engert	: for initial ATA100 advices and numerous others.
+ * John Fremlin, Manfred Spraul :
+ *			  for checking code correctness, providing patches.
+ *
+ *
  * Original tests and design on the SiS620/5513 chipset.
  * ATA100 tests and design on the SiS735/5513 chipset.
  * ATA16/33 design from specs
@@ -14,11 +21,11 @@
 
 /*
  * TODO:
- *	- Are there pre-ATA_16 SiS chips ? -> tune init code for them
- *	  or remove ATA_00 defines
  *	- Get ridden of SisHostChipInfo[] completness dependancy.
  *	- Get ATA-133 datasheets, implement ATA-133 init code.
- *	- Check latency timer init correctness.
+ *	- Study drivers/ide/ide-timing.h.
+ *	- Are there pre-ATA_16 SiS5513 chips ? -> tune init code for them
+ *	  or remove ATA_00 define
  *	- More checks in the config registers (force values instead of
  *	  relying on the BIOS setting them correctly).
  *	- Further optimisations ?
@@ -45,62 +52,45 @@
 
 #include "ide_modes.h"
 
-#define DEBUG
-/* if BROKEN_LEVEL is defined it limits the DMA mode
+/* When DEBUG is defined it outputs initial PCI config register
+   values and changes made to them by the driver */   
+// #define DEBUG
+/* When BROKEN_LEVEL is defined it limits the DMA mode
    at boot time to its value */
 // #define BROKEN_LEVEL XFER_SW_DMA_0
 #define DISPLAY_SIS_TIMINGS
 
 /* Miscellaneaous flags */
 #define SIS5513_LATENCY		0x01
-/* ATA transfer mode capabilities */
+
+/* registers layout and init values are chipset family dependant */
+/* 1/ define families */
 #define ATA_00		0x00
 #define ATA_16		0x01
 #define ATA_33		0x02
 #define ATA_66		0x03
-#define ATA_100		0x04
-#define ATA_133		0x05
-
-static unsigned char dma_capability = 0x00;
+#define ATA_100a	0x04 // SiS730 is ATA100 with ATA66 layout
+#define ATA_100		0x05
+#define ATA_133		0x06
+/* 2/ variable holding the controller chipset family value */
+static unsigned char chipset_family;
 
 
 /*
  * Debug code: following IDE config registers' changes
  */
 #ifdef DEBUG
-/* Copy of IDE Config registers 0x00 -> 0x58
+/* Copy of IDE Config registers 0x00 -> 0x57
    Fewer might be used depending on the actual chipset */
-static unsigned char ide_regs_copy[] = {
-	0x0, 0x0, 0x0, 0x0,
-	0x0, 0x0, 0x0, 0x0,
-	0x0, 0x0, 0x0, 0x0,
-	0x0, 0x0, 0x0, 0x0,
-	0x0, 0x0, 0x0, 0x0,
-	0x0, 0x0, 0x0, 0x0,
-	0x0, 0x0, 0x0, 0x0,
-	0x0, 0x0, 0x0, 0x0,
-	0x0, 0x0, 0x0, 0x0,
-	0x0, 0x0, 0x0, 0x0,
-	0x0, 0x0, 0x0, 0x0,
-	0x0, 0x0, 0x0, 0x0,
-	0x0, 0x0, 0x0, 0x0,
-	0x0, 0x0, 0x0, 0x0,
-	0x0, 0x0, 0x0, 0x0,
-	0x0, 0x0, 0x0, 0x0,
-	0x0, 0x0, 0x0, 0x0,
-	0x0, 0x0, 0x0, 0x0,
-	0x0, 0x0, 0x0, 0x0,
-	0x0, 0x0, 0x0, 0x0,
-	0x0, 0x0, 0x0, 0x0,
-	0x0, 0x0, 0x0, 0x0
-};
+static unsigned char ide_regs_copy[0x58];
 
 static byte sis5513_max_config_register(void) {
-	switch(dma_capability) {
+	switch(chipset_family) {
 		case ATA_00:
 		case ATA_16:	return 0x4f;
 		case ATA_33:	return 0x52;
 		case ATA_66:
+		case ATA_100a:
 		case ATA_100:
 		case ATA_133:
 		default:	return 0x57;
@@ -145,7 +135,7 @@
 	printk(" %0#x:%0#x", reg, ide_regs_copy[reg]);
 }
 
-/* Print valuable registers (for ATA100) */
+/* Print valuable registers */
 static void sis5513_print_registers(struct pci_dev* dev, char* marker) {
 	int i;
 	byte max = sis5513_max_config_register();
@@ -176,14 +166,14 @@
 static const struct {
 	const char *name;
 	unsigned short host_id;
-	unsigned char dma_capability;
+	unsigned char chipset_family;
 	unsigned char flags;
 } SiSHostChipInfo[] = {
 	{ "SiS750",	PCI_DEVICE_ID_SI_750,	ATA_100,	SIS5513_LATENCY },
 	{ "SiS745",	PCI_DEVICE_ID_SI_745,	ATA_100,	SIS5513_LATENCY },
 	{ "SiS740",	PCI_DEVICE_ID_SI_740,	ATA_100,	SIS5513_LATENCY },
 	{ "SiS735",	PCI_DEVICE_ID_SI_735,	ATA_100,	SIS5513_LATENCY },
-	{ "SiS730",	PCI_DEVICE_ID_SI_730,	ATA_100,	SIS5513_LATENCY },
+	{ "SiS730",	PCI_DEVICE_ID_SI_730,	ATA_100a,	SIS5513_LATENCY },
 	{ "SiS650",	PCI_DEVICE_ID_SI_650,	ATA_100,	SIS5513_LATENCY },
 	{ "SiS645",	PCI_DEVICE_ID_SI_645,	ATA_100,	SIS5513_LATENCY },
 	{ "SiS635",	PCI_DEVICE_ID_SI_635,	ATA_100,	SIS5513_LATENCY },
@@ -202,14 +192,15 @@
 
 /* Cycle time bits and values vary accross chip dma capabilities
    These three arrays hold the register layout and the values to set.
-   Indexed by dma_capability and (dma_mode - XFER_UDMA_0) */
-static byte cycle_time_offset[] = {0,0,5,4,0,0};
-static byte cycle_time_range[] = {0,0,2,3,4,4};
+   Indexed by chipset_family and (dma_mode - XFER_UDMA_0) */
+static byte cycle_time_offset[] = {0,0,5,4,4,0,0};
+static byte cycle_time_range[] = {0,0,2,3,3,4,4};
 static byte cycle_time_value[][XFER_UDMA_5 - XFER_UDMA_0 + 1] = {
 	{0,0,0,0,0,0}, /* no udma */
 	{0,0,0,0,0,0}, /* no udma */
 	{3,2,1,0,0,0},
 	{7,5,3,2,1,0},
+	{7,5,3,2,1,0},
 	{11,7,5,4,2,1},
 	{0,0,0,0,0,0} /* not yet known, ask SiS */
 };
@@ -283,23 +274,25 @@
 	pci_read_config_byte(bmide_dev, 0x45+2*pos, &reg11);
 
 /* UDMA */
-	if (dma_capability >= ATA_33) {
+	if (chipset_family >= ATA_33) {
 		p += sprintf(p, "                UDMA %s \t \t \t UDMA %s\n",
 			     (reg01 & 0x80)  ? "Enabled" : "Disabled",
 			     (reg11 & 0x80) ? "Enabled" : "Disabled");
 
 		p += sprintf(p, "                UDMA Cycle Time    ");
-		switch(dma_capability) {
+		switch(chipset_family) {
 			case ATA_33:	p += sprintf(p, cycle_time[(reg01 & 0x60) >> 5]); break;
-			case ATA_66:	p += sprintf(p, cycle_time[(reg01 & 0x70) >> 4]); break;
+			case ATA_66:
+			case ATA_100a:	p += sprintf(p, cycle_time[(reg01 & 0x70) >> 4]); break;
 			case ATA_100:	p += sprintf(p, cycle_time[reg01 & 0x0F]); break;
 			case ATA_133:
 			default:	p += sprintf(p, "133+ ?"); break;
 		}
 		p += sprintf(p, " \t UDMA Cycle Time    ");
-		switch(dma_capability) {
+		switch(chipset_family) {
 			case ATA_33:	p += sprintf(p, cycle_time[(reg11 & 0x60) >> 5]); break;
-			case ATA_66:	p += sprintf(p, cycle_time[(reg11 & 0x70) >> 4]); break;
+			case ATA_66:
+			case ATA_100a:	p += sprintf(p, cycle_time[(reg11 & 0x70) >> 4]); break;
 			case ATA_100:	p += sprintf(p, cycle_time[reg11 & 0x0F]); break;
 			case ATA_133:
 			default:	p += sprintf(p, "133+ ?"); break;
@@ -309,21 +302,23 @@
 
 /* Data Active */
 	p += sprintf(p, "                Data Active Time   ");
-	switch(dma_capability) {
+	switch(chipset_family) {
 		case ATA_00:
 		case ATA_16: /* confirmed */
 		case ATA_33:
-		case ATA_66: p += sprintf(p, active_time[reg01 & 0x07]); break;
+		case ATA_66:
+		case ATA_100a: p += sprintf(p, active_time[reg01 & 0x07]); break;
 		case ATA_100: p += sprintf(p, active_time[(reg00 & 0x70) >> 4]); break;
 		case ATA_133:
 		default: p += sprintf(p, "133+ ?"); break;
 	}
 	p += sprintf(p, " \t Data Active Time   ");
-	switch(dma_capability) {
+	switch(chipset_family) {
 		case ATA_00:
 		case ATA_16:
 		case ATA_33:
-		case ATA_66: p += sprintf(p, active_time[reg11 & 0x07]); break;
+		case ATA_66:
+		case ATA_100a: p += sprintf(p, active_time[reg11 & 0x07]); break;
 		case ATA_100: p += sprintf(p, active_time[(reg10 & 0x70) >> 4]); break;
 		case ATA_133:
 		default: p += sprintf(p, "133+ ?"); break;
@@ -356,11 +351,12 @@
 	u16 reg2, reg3;
 
 	p += sprintf(p, "\nSiS 5513 ");
-	switch(dma_capability) {
+	switch(chipset_family) {
 		case ATA_00: p += sprintf(p, "Unknown???"); break;
 		case ATA_16: p += sprintf(p, "DMA 16"); break;
 		case ATA_33: p += sprintf(p, "Ultra 33"); break;
 		case ATA_66: p += sprintf(p, "Ultra 66"); break;
+		case ATA_100a:
 		case ATA_100: p += sprintf(p, "Ultra 100"); break;
 		case ATA_133:
 		default: p+= sprintf(p, "Ultra 133+"); break;
@@ -371,7 +367,7 @@
 /* Status */
 	pci_read_config_byte(bmide_dev, 0x4a, &reg);
 	p += sprintf(p, "Channel Status: ");
-	if (dma_capability < ATA_66) {
+	if (chipset_family < ATA_66) {
 		p += sprintf(p, "%s \t \t \t \t %s\n",
 			     (reg & 0x04) ? "On" : "Off",
 			     (reg & 0x02) ? "On" : "Off");
@@ -388,7 +384,7 @@
 		     (reg & 0x04) ? "Native" : "Compatible");
 
 /* 80-pin cable ? */
-	if (dma_capability > ATA_33) {
+	if (chipset_family > ATA_33) {
 		pci_read_config_byte(bmide_dev, 0x48, &reg);
 		p += sprintf(p, "Cable Type:     %s \t \t \t %s\n",
 			     (reg & 0x10) ? cable_type[1] : cable_type[0],
@@ -489,8 +485,8 @@
 		default:	return;
 	}
 
-	/* register layout changed with ATA100 chips */
-	if (dma_capability < ATA_100) {
+	/* register layout changed with newer ATA100 chips */
+	if (chipset_family < ATA_100) {
 		pci_read_config_byte(dev, drive_pci, &test1);
 		pci_read_config_byte(dev, drive_pci+1, &test2);
 
@@ -570,7 +566,7 @@
 
 	pci_read_config_byte(dev, drive_pci+1, &reg);
 	/* Disable UDMA bit for non UDMA modes on UDMA chips */
-	if ((speed < XFER_UDMA_0) && (dma_capability > ATA_16)) {
+	if ((speed < XFER_UDMA_0) && (chipset_family > ATA_16)) {
 		reg &= 0x7F;
 		pci_write_config_byte(dev, drive_pci+1, reg);
 	}
@@ -584,12 +580,14 @@
 		case XFER_UDMA_2:
 		case XFER_UDMA_1:
 		case XFER_UDMA_0:
+			/* Force the UDMA bit on if we want to use UDMA */
+			reg |= 0x80;
 			/* clean reg cycle time bits */
-			reg &= ~((0xFF >> (8 - cycle_time_range[dma_capability]))
-				 << cycle_time_offset[dma_capability]);
+			reg &= ~((0xFF >> (8 - cycle_time_range[chipset_family]))
+				 << cycle_time_offset[chipset_family]);
 			/* set reg cycle time bits */
-			reg |= cycle_time_value[dma_capability-ATA_00][speed-XFER_UDMA_0]
-				<< cycle_time_offset[dma_capability];
+			reg |= cycle_time_value[chipset_family-ATA_00][speed-XFER_UDMA_0]
+				<< cycle_time_offset[chipset_family];
 			pci_write_config_byte(dev, drive_pci+1, reg);
 			break;
 		case XFER_MW_DMA_2:
@@ -638,17 +636,17 @@
 	       drive->dn, ultra);
 #endif
 
-	if ((id->dma_ultra & 0x0020) && ultra && udma_66 && (dma_capability >= ATA_100))
+	if ((id->dma_ultra & 0x0020) && ultra && udma_66 && (chipset_family >= ATA_100a))
 		speed = XFER_UDMA_5;
-	else if ((id->dma_ultra & 0x0010) && ultra && udma_66 && (dma_capability >= ATA_66))
+	else if ((id->dma_ultra & 0x0010) && ultra && udma_66 && (chipset_family >= ATA_66))
 		speed = XFER_UDMA_4;
-	else if ((id->dma_ultra & 0x0008) && ultra && udma_66 && (dma_capability >= ATA_66))
+	else if ((id->dma_ultra & 0x0008) && ultra && udma_66 && (chipset_family >= ATA_66))
 		speed = XFER_UDMA_3;
-	else if ((id->dma_ultra & 0x0004) && ultra && (dma_capability >= ATA_33))
+	else if ((id->dma_ultra & 0x0004) && ultra && (chipset_family >= ATA_33))
 		speed = XFER_UDMA_2;
-	else if ((id->dma_ultra & 0x0002) && ultra && (dma_capability >= ATA_33))
+	else if ((id->dma_ultra & 0x0002) && ultra && (chipset_family >= ATA_33))
 		speed = XFER_UDMA_1;
-	else if ((id->dma_ultra & 0x0001) && ultra && (dma_capability >= ATA_33))
+	else if ((id->dma_ultra & 0x0001) && ultra && (chipset_family >= ATA_33))
 		speed = XFER_UDMA_0;
 	else if (id->dma_mword & 0x0004)
 		speed = XFER_MW_DMA_2;
@@ -681,6 +679,8 @@
 	struct hd_driveid *id		= drive->id;
 	ide_dma_action_t dma_func	= ide_dma_off_quietly;
 
+	(void) config_chipset_for_pio(drive, 5);
+
 	if (id && (id->capability & 1) && HWIF(drive)->autodma) {
 		/* Consult the list of known "bad" drives */
 		if (ide_dmaproc(ide_dma_bad_drive, drive)) {
@@ -745,10 +745,6 @@
 	struct pci_dev *host;
 	int i = 0;
 
-#ifdef DEBUG
-	sis5513_print_registers(dev, "pci_init_sis5513 start");
-#endif
-
 	/* Find the chip */
 	for (i = 0; i < ARRAY_SIZE(SiSHostChipInfo) && !host_dev; i++) {
 		host = pci_find_device (PCI_VENDOR_ID_SI,
@@ -758,12 +754,16 @@
 			continue;
 
 		host_dev = host;
-		dma_capability = SiSHostChipInfo[i].dma_capability;
+		chipset_family = SiSHostChipInfo[i].chipset_family;
 		printk(SiSHostChipInfo[i].name);
 		printk("\n");
 
+#ifdef DEBUG
+		sis5513_print_registers(dev, "pci_init_sis5513 start");
+#endif
+
 		if (SiSHostChipInfo[i].flags & SIS5513_LATENCY) {
-			byte latency = (dma_capability == ATA_100)? 0x80 : 0x10; /* Lacking specs */
+			byte latency = (chipset_family == ATA_100)? 0x80 : 0x10; /* Lacking specs */
 			pci_write_config_byte(dev, PCI_LATENCY_TIMER, latency);
 		}
 	}
@@ -773,7 +773,7 @@
 	   2/ tell old chips to allow per drive IDE timings */
 	if (host_dev) {
 		byte reg;
-		switch(dma_capability) {
+		switch(chipset_family) {
 			case ATA_133:
 			case ATA_100:
 				/* Set compatibility bit */
@@ -782,6 +782,7 @@
 					pci_write_config_byte(dev, 0x49, reg|0x01);
 				}
 				break;
+			case ATA_100a:
 			case ATA_66:
 				/* On ATA_66 chips the bit was elsewhere */
 				pci_read_config_byte(dev, 0x52, &reg);
@@ -827,7 +828,7 @@
 	byte mask = hwif->channel ? 0x20 : 0x10;
 	pci_read_config_byte(hwif->pci_dev, 0x48, &reg48h);
 
-	if (dma_capability >= ATA_66) {
+	if (chipset_family >= ATA_66) {
 		ata66 = (reg48h & mask) ? 0 : 1;
 	}
         return ata66;
@@ -846,7 +847,7 @@
 
 	if (host_dev) {
 #ifdef CONFIG_BLK_DEV_IDEDMA
-		if (dma_capability > ATA_16) {
+		if (chipset_family > ATA_16) {
 			hwif->autodma = noautodma ? 0 : 1;
 			hwif->dmaproc = &sis5513_dmaproc;
 		} else {
diff -urN linux-2.4.19-pre5/drivers/input/joydev.c linux-2.4.19-pre6/drivers/input/joydev.c
--- linux-2.4.19-pre5/drivers/input/joydev.c	Sun Sep 30 12:26:05 2001
+++ linux-2.4.19-pre6/drivers/input/joydev.c	Thu Apr  4 22:04:57 2002
@@ -411,7 +411,7 @@
 static struct input_handle *joydev_connect(struct input_handler *handler, struct input_dev *dev)
 {
 	struct joydev *joydev;
-	int i, j, minor;
+	int i, j, t, minor;
 
 	if (!(test_bit(EV_KEY, dev->evbit) && test_bit(EV_ABS, dev->evbit) &&
 	     (test_bit(ABS_X, dev->absbit) || test_bit(ABS_Y, dev->absbit)) &&
@@ -470,8 +470,10 @@
 		joydev->corr[i].prec = dev->absfuzz[j];
 		joydev->corr[i].coef[0] = (dev->absmax[j] + dev->absmin[j]) / 2 - dev->absflat[j];
 		joydev->corr[i].coef[1] = (dev->absmax[j] + dev->absmin[j]) / 2 + dev->absflat[j];
-		joydev->corr[i].coef[2] = (1 << 29) / ((dev->absmax[j] - dev->absmin[j]) / 2 - 2 * dev->absflat[j]);
-		joydev->corr[i].coef[3] = (1 << 29) / ((dev->absmax[j] - dev->absmin[j]) / 2 - 2 * dev->absflat[j]);
+		if (!(t = ((dev->absmax[j] - dev->absmin[j]) / 2 - 2 * dev->absflat[j])))
+			continue;
+		joydev->corr[i].coef[2] = (1 << 29) / t;
+		joydev->corr[i].coef[3] = (1 << 29) / t;
 
 		joydev->abs[i] = joydev_correct(dev->abs[j], joydev->corr + i);
 	}
diff -urN linux-2.4.19-pre5/drivers/macintosh/mac_keyb.c linux-2.4.19-pre6/drivers/macintosh/mac_keyb.c
--- linux-2.4.19-pre5/drivers/macintosh/mac_keyb.c	Tue Sep 18 14:23:14 2001
+++ linux-2.4.19-pre6/drivers/macintosh/mac_keyb.c	Thu Apr  4 22:04:57 2002
@@ -256,7 +256,6 @@
 #endif
 
 extern struct kbd_struct kbd_table[];
-extern wait_queue_head_t keypress_wait;
 
 extern void handle_scancode(unsigned char, int);
 
@@ -423,7 +422,6 @@
 	struct tty_struct *tty;
 
 	tty = console_driver.table? console_driver.table[fg_console]: NULL;
-	wake_up(&keypress_wait);
 	if (tty) {
 		tty_insert_flip_char(tty, ch, 0);
 		con_schedule_flip(tty);
diff -urN linux-2.4.19-pre5/drivers/macintosh/macserial.c linux-2.4.19-pre6/drivers/macintosh/macserial.c
--- linux-2.4.19-pre5/drivers/macintosh/macserial.c	Mon Feb 25 11:37:58 2002
+++ linux-2.4.19-pre6/drivers/macintosh/macserial.c	Thu Apr  4 22:04:57 2002
@@ -2866,30 +2866,6 @@
 	/* Don't disable the transmitter. */
 }
 
-/*
- *	Receive character from the serial port
- */
-static int serial_console_wait_key(struct console *co)
-{
-	struct mac_serial *info = zs_soft + co->index;
-	int           val;
-
-	/* Turn of interrupts and enable the transmitter. */
-	write_zsreg(info->zs_channel, R1, info->curregs[1] & ~INT_ALL_Rx);
-	write_zsreg(info->zs_channel, R3, info->curregs[3] | RxENABLE);
-
-	/* Wait for something in the receive buffer. */
-	while((read_zsreg(info->zs_channel, 0) & Rx_CH_AV) == 0)
-		eieio();
-	val = read_zsdata(info->zs_channel);
-
-	/* Restore the values in the registers. */
-	write_zsreg(info->zs_channel, R1, info->curregs[1]);
-	write_zsreg(info->zs_channel, R3, info->curregs[3]);
-
-	return val;
-}
-
 static kdev_t serial_console_device(struct console *c)
 {
 	return MKDEV(TTY_MAJOR, 64 + c->index);
@@ -3080,7 +3056,6 @@
 	name:		"ttyS",
 	write:		serial_console_write,
 	device:		serial_console_device,
-	wait_key:	serial_console_wait_key,
 	setup:		serial_console_setup,
 	flags:		CON_PRINTBUFFER,
 	index:		-1,
diff -urN linux-2.4.19-pre5/drivers/md/md.c linux-2.4.19-pre6/drivers/md/md.c
--- linux-2.4.19-pre5/drivers/md/md.c	Mon Feb 25 11:37:58 2002
+++ linux-2.4.19-pre6/drivers/md/md.c	Thu Apr  4 22:04:58 2002
@@ -3486,7 +3486,7 @@
 	 * this also signals 'finished resyncing' to md_stop
 	 */
 out:
-	wait_event(mddev->recovery_wait, atomic_read(&mddev->recovery_active)==0);
+	wait_disk_event(mddev->recovery_wait, atomic_read(&mddev->recovery_active)==0);
 	up(&mddev->resync_sem);
 out_nolock:
 	mddev->curr_resync = 0;
diff -urN linux-2.4.19-pre5/drivers/md/raid1.c linux-2.4.19-pre6/drivers/md/raid1.c
--- linux-2.4.19-pre5/drivers/md/raid1.c	Mon Feb 25 11:37:58 2002
+++ linux-2.4.19-pre6/drivers/md/raid1.c	Thu Apr  4 22:04:58 2002
@@ -269,8 +269,9 @@
 static int raid1_grow_buffers (raid1_conf_t *conf, int cnt)
 {
 	int i = 0;
+	struct raid1_bh *head = NULL, **tail;
+	tail = &head;
 
-	md_spin_lock_irq(&conf->device_lock);
 	while (i < cnt) {
 		struct raid1_bh *r1_bh;
 		struct page *page;
@@ -287,24 +288,36 @@
 		memset(r1_bh, 0, sizeof(*r1_bh));
 		r1_bh->bh_req.b_page = page;
 		r1_bh->bh_req.b_data = page_address(page);
-		r1_bh->next_r1 = conf->freebuf;
-		conf->freebuf = r1_bh;
+		*tail = r1_bh;
+		r1_bh->next_r1 = NULL;
+		tail = & r1_bh->next_r1;
 		i++;
 	}
+	/* this lock probably isn't needed, as at the time when
+	 * we are allocating buffers, nobody else will be touching the
+	 * freebuf list.  But it doesn't hurt....
+	 */
+	md_spin_lock_irq(&conf->device_lock);
+	*tail = conf->freebuf;
+	conf->freebuf = head;
 	md_spin_unlock_irq(&conf->device_lock);
 	return i;
 }
 
 static void raid1_shrink_buffers (raid1_conf_t *conf)
 {
+	struct raid1_bh *head;
 	md_spin_lock_irq(&conf->device_lock);
-	while (conf->freebuf) {
-		struct raid1_bh *r1_bh = conf->freebuf;
-		conf->freebuf = r1_bh->next_r1;
+	head = conf->freebuf;
+	conf->freebuf = NULL;
+	md_spin_unlock_irq(&conf->device_lock);
+
+	while (head) {
+		struct raid1_bh *r1_bh = head;
+		head = r1_bh->next_r1;
 		__free_page(r1_bh->bh_req.b_page);
 		kfree(r1_bh);
 	}
-	md_spin_unlock_irq(&conf->device_lock);
 }
 
 static int raid1_map (mddev_t *mddev, kdev_t *rdev)
@@ -825,7 +838,7 @@
 	conf->start_ready = conf->start_pending;
 	wait_event_lock_irq(conf->wait_ready, !conf->cnt_pending, conf->segment_lock);
 	conf->start_active =conf->start_ready = conf->start_pending = conf->start_future;
-	conf->start_future = mddev->sb->size+1;
+	conf->start_future = (mddev->sb->size<<1)+1;
 	conf->cnt_pending = conf->cnt_future;
 	conf->cnt_future = 0;
 	conf->phase = conf->phase ^1;
@@ -849,6 +862,14 @@
 	mdk_rdev_t *spare_rdev, *failed_rdev;
 
 	print_raid1_conf(conf);
+
+	switch (state) {
+	case DISKOP_SPARE_ACTIVE:
+	case DISKOP_SPARE_INACTIVE:
+		/* need to wait for pending sync io before locking device */
+		close_sync(conf);
+	}
+
 	md_spin_lock_irq(&conf->device_lock);
 	/*
 	 * find the disk ...
@@ -951,7 +972,11 @@
 	 * Deactivate a spare disk:
 	 */
 	case DISKOP_SPARE_INACTIVE:
-		close_sync(conf);
+		if (conf->start_future > 0) {
+			MD_BUG();
+			err = -EBUSY;
+			break;
+		}
 		sdisk = conf->mirrors + spare_disk;
 		sdisk->operational = 0;
 		sdisk->write_only = 0;
@@ -964,7 +989,11 @@
 	 * property)
 	 */
 	case DISKOP_SPARE_ACTIVE:
-		close_sync(conf);
+		if (conf->start_future > 0) {
+			MD_BUG();
+			err = -EBUSY;
+			break;
+		}
 		sdisk = conf->mirrors + spare_disk;
 		fdisk = conf->mirrors + failed_disk;
 
@@ -1328,23 +1357,25 @@
 	int bsize;
 	int disk;
 	int block_nr;
+	int buffs;
 
+	if (!sector_nr) {
+		/* we want enough buffers to hold twice the window of 128*/
+		buffs = 128 *2 / (PAGE_SIZE>>9);
+		buffs = raid1_grow_buffers(conf, buffs);
+		if (buffs < 2)
+			goto nomem;
+		conf->window = buffs*(PAGE_SIZE>>9)/2;
+	}
 	spin_lock_irq(&conf->segment_lock);
 	if (!sector_nr) {
 		/* initialize ...*/
-		int buffs;
 		conf->start_active = 0;
 		conf->start_ready = 0;
 		conf->start_pending = 0;
 		conf->start_future = 0;
 		conf->phase = 0;
-		/* we want enough buffers to hold twice the window of 128*/
-		buffs = 128 *2 / (PAGE_SIZE>>9);
-		buffs = raid1_grow_buffers(conf, buffs);
-		if (buffs < 2)
-			goto nomem;
 		
-		conf->window = buffs*(PAGE_SIZE>>9)/2;
 		conf->cnt_future += conf->cnt_done+conf->cnt_pending;
 		conf->cnt_done = conf->cnt_pending = 0;
 		if (conf->cnt_ready || conf->cnt_active)
@@ -1429,7 +1460,6 @@
 
 nomem:
 	raid1_shrink_buffers(conf);
-	spin_unlock_irq(&conf->segment_lock);
 	return -ENOMEM;
 }
 
diff -urN linux-2.4.19-pre5/drivers/net/tlan.c linux-2.4.19-pre6/drivers/net/tlan.c
--- linux-2.4.19-pre5/drivers/net/tlan.c	Fri Dec 21 09:41:54 2001
+++ linux-2.4.19-pre6/drivers/net/tlan.c	Thu Apr  4 22:04:59 2002
@@ -8,6 +8,7 @@
  *  (C) 1997-1998 Caldera, Inc.
  *  (C) 1998 James Banks
  *  (C) 1999-2001 Torben Mathiasen
+ *  (C) 2002 Samuel Chessman
  *
  *  This software may be used and distributed according to the terms
  *  of the GNU General Public License, incorporated herein by reference.
@@ -158,6 +159,11 @@
  *
  * 	v1.14a Jan 6, 2001   - Minor adjustments (spinlocks, etc.)
  *
+ *	Samuel Chessman <chessman@tux.org> New Maintainer!
+ *
+ *	v1.15 Apr 4, 2002    - Correct operation when aui=1 to be
+ *	                       10T half duplex no loopback
+ *	                       Thanks to Gunnar Eikman
  *******************************************************************************/
 
                                                                                 
@@ -188,7 +194,7 @@
 static  int speed[MAX_TLAN_BOARDS];
 static  int boards_found;
 
-MODULE_AUTHOR("Maintainer: Torben Mathiasen <torben.mathiasen@compaq.com>");
+MODULE_AUTHOR("Maintainer: Samuel Chessman <chessman@tux.org>");
 MODULE_DESCRIPTION("Driver for TI ThunderLAN based ethernet PCI adapters");
 MODULE_LICENSE("GPL");
 
@@ -213,7 +219,7 @@
 static	int		bbuf;
 static	u8		*TLanPadBuffer;
 static	char		TLanSignature[] = "TLAN";
-static const char tlan_banner[] = "ThunderLAN driver v1.14a\n";
+static const char tlan_banner[] = "ThunderLAN driver v1.15\n";
 static int tlan_have_pci;
 static int tlan_have_eisa;
 
@@ -2603,12 +2609,12 @@
 		TLan_SetTimer( dev, (40*HZ/1000), TLAN_TIMER_PHY_PDOWN );
 		return;
 	}  else if ( priv->phyNum == 0 ) {
+		control = 0;
         	TLan_MiiReadReg( dev, phy, TLAN_TLPHY_CTL, &tctl );
 		if ( priv->aui ) {
                 	tctl |= TLAN_TC_AUISEL;
 		} else { 
                 	tctl &= ~TLAN_TC_AUISEL;
-			control = 0;
 			if ( priv->duplex == TLAN_DUPLEX_FULL ) {
 				control |= MII_GC_DUPLEX;
 				priv->tlanFullDuplex = TRUE;
@@ -2616,8 +2622,8 @@
 			if ( priv->speed == TLAN_SPEED_100 ) {
 				control |= MII_GC_SPEEDSEL;
 			}
-       			TLan_MiiWriteReg( dev, phy, MII_GEN_CTL, control );
 		}
+		TLan_MiiWriteReg( dev, phy, MII_GEN_CTL, control );
         	TLan_MiiWriteReg( dev, phy, TLAN_TLPHY_CTL, tctl );
 	}
 
diff -urN linux-2.4.19-pre5/drivers/pci/pci.c linux-2.4.19-pre6/drivers/pci/pci.c
--- linux-2.4.19-pre5/drivers/pci/pci.c	Thu Apr  4 22:04:23 2002
+++ linux-2.4.19-pre6/drivers/pci/pci.c	Thu Apr  4 22:05:00 2002
@@ -889,7 +889,7 @@
 }
 
 /**
- * pci_set_mwi - enables memory-write-validate PCI transaction
+ * pci_set_mwi - enables memory-write-invalidate PCI transaction
  * @dev: the PCI device for which MWI is enabled
  *
  * Enables the Memory-Write-Invalidate transaction in %PCI_COMMAND,
diff -urN linux-2.4.19-pre5/drivers/pci/setup-bus.c linux-2.4.19-pre6/drivers/pci/setup-bus.c
--- linux-2.4.19-pre5/drivers/pci/setup-bus.c	Thu Oct  4 18:47:08 2001
+++ linux-2.4.19-pre6/drivers/pci/setup-bus.c	Thu Apr  4 22:05:00 2002
@@ -201,6 +201,16 @@
 		b->resource[0]->end = ranges->io_end - 1;
 		b->resource[1]->end = ranges->mem_end - 1;
 
+		/* Add bridge resources to the resource tree. */
+		if (b->resource[0]->end > b->resource[0]->start &&
+		    request_resource(bus->resource[0], b->resource[0]) < 0)
+			printk(KERN_ERR "PCI: failed to reserve IO "
+					"for bus %d\n",	b->number);
+		if (b->resource[1]->end > b->resource[1]->start &&
+		    request_resource(bus->resource[1], b->resource[1]) < 0)
+			printk(KERN_ERR "PCI: failed to reserve MEM "
+					"for bus %d\n", b->number);
+
 		pci_setup_bridge(b);
 	}
 }
diff -urN linux-2.4.19-pre5/drivers/s390/char/tuball.c linux-2.4.19-pre6/drivers/s390/char/tuball.c
--- linux-2.4.19-pre5/drivers/s390/char/tuball.c	Thu Oct 11 09:43:29 2001
+++ linux-2.4.19-pre6/drivers/s390/char/tuball.c	Thu Apr  4 22:05:01 2002
@@ -84,7 +84,6 @@
 	tub3270_con_write,	/* write */
 	NULL,			/* read */
 	tub3270_con_device,	/* device */
-	NULL,			/* wait_key */
 	tub3270_con_unblank,	/* unblank */
 	NULL,			/* setup */
 	CON_PRINTBUFFER,	/* flags */
diff -urN linux-2.4.19-pre5/drivers/sbus/char/sab82532.c linux-2.4.19-pre6/drivers/sbus/char/sab82532.c
--- linux-2.4.19-pre5/drivers/sbus/char/sab82532.c	Wed Oct 17 14:16:39 2001
+++ linux-2.4.19-pre6/drivers/sbus/char/sab82532.c	Thu Apr  4 22:05:03 2002
@@ -361,10 +361,6 @@
 		writeb(SAB82532_CMDR_RMC, &info->regs->w.cmdr);
 	}
 
-#ifdef CONFIG_SERIAL_CONSOLE
-	if (info->is_console)
-		wake_up(&keypress_wait);
-#endif
 	if (!tty)
 		return;
 
@@ -2541,13 +2537,6 @@
 	sab82532_tec_wait(info);
 }
 
-static int
-sab82532_console_wait_key(struct console *con)
-{
-	sleep_on(&keypress_wait);
-	return 0;
-}
-
 static kdev_t
 sab82532_console_device(struct console *con)
 {
@@ -2622,7 +2611,6 @@
 	name:		"ttyS",
 	write:		sab82532_console_write,
 	device:		sab82532_console_device,
-	wait_key:	sab82532_console_wait_key,
 	setup:		sab82532_console_setup,
 	flags:		CON_PRINTBUFFER,
 	index:		-1,
diff -urN linux-2.4.19-pre5/drivers/sbus/char/su.c linux-2.4.19-pre6/drivers/sbus/char/su.c
--- linux-2.4.19-pre5/drivers/sbus/char/su.c	Tue Nov 13 09:16:05 2001
+++ linux-2.4.19-pre6/drivers/sbus/char/su.c	Thu Apr  4 22:05:03 2002
@@ -2854,40 +2854,6 @@
 	su_outb(info, UART_IER, ier);
 }
 
-/*
- *	Receive character from the serial port
- */
-static int
-serial_console_wait_key(struct console *co)
-{
-	struct su_struct *info;
-	int ier;
-	int lsr;
-	int c;
-
-	info = su_table + co->index;
-
-	/*
-	 *	First save the IER then disable the interrupts so
-	 *	that the real driver for the port does not get the
-	 *	character.
-	 */
-	ier = su_inb(info, UART_IER);
-	su_outb(info, UART_IER, 0x00);
-
-	do {
-		lsr = su_inb(info, UART_LSR);
-	} while (!(lsr & UART_LSR_DR));
-	c = su_inb(info, UART_RX);
-
-	/*
-	 *	Restore the interrupts
-	 */
-	su_outb(info, UART_IER, ier);
-
-	return c;
-}
-
 static kdev_t
 serial_console_device(struct console *c)
 {
@@ -3013,7 +2979,6 @@
 	name:		"ttyS",
 	write:		serial_console_write,
 	device:		serial_console_device,
-	wait_key:	serial_console_wait_key,
 	setup:		serial_console_setup,
 	flags:		CON_PRINTBUFFER,
 	index:		-1,
diff -urN linux-2.4.19-pre5/drivers/sbus/char/sunkbd.c linux-2.4.19-pre6/drivers/sbus/char/sunkbd.c
--- linux-2.4.19-pre5/drivers/sbus/char/sunkbd.c	Sun Sep 16 21:22:50 2001
+++ linux-2.4.19-pre6/drivers/sbus/char/sunkbd.c	Thu Apr  4 22:05:03 2002
@@ -82,16 +82,6 @@
 
 struct l1a_kbd_state l1a_state;
 
-#ifndef CONFIG_PCI
-DECLARE_WAIT_QUEUE_HEAD(keypress_wait);
-#endif
-
-int keyboard_wait_for_keypress(struct console *co)
-{
-	sleep_on(&keypress_wait);
-	return 0;
-}
-
 static spinlock_t sunkbd_lock = SPIN_LOCK_UNLOCKED;
 
 /*
@@ -629,7 +619,6 @@
 
 static void put_queue(int ch)
 {
-	wake_up(&keypress_wait);
 	if (tty) {
 		tty_insert_flip_char(tty, ch, 0);
 		con_schedule_flip(tty);
@@ -638,7 +627,6 @@
 
 static void puts_queue(char *cp)
 {
-	wake_up(&keypress_wait);
 	if (!tty)
 		return;
 
diff -urN linux-2.4.19-pre5/drivers/sbus/char/zs.c linux-2.4.19-pre6/drivers/sbus/char/zs.c
--- linux-2.4.19-pre5/drivers/sbus/char/zs.c	Mon Feb 25 11:38:04 2002
+++ linux-2.4.19-pre6/drivers/sbus/char/zs.c	Thu Apr  4 22:05:03 2002
@@ -543,8 +543,6 @@
 				/* Continue execution... */
 				return;
 			}
-			/* It is a 'keyboard interrupt' ;-) */
-			wake_up(&keypress_wait);
 		}
 #ifndef __sparc_v9__
 		/* Look for kgdb 'stop' character, consult the gdb
@@ -2797,13 +2795,6 @@
 #endif
 }
 
-static int
-zs_console_wait_key(struct console *con)
-{
-	sleep_on(&keypress_wait);
-	return 0;
-}
-
 static kdev_t zs_console_device(struct console *con)
 {
 	return MKDEV(TTY_MAJOR, 64 + con->index);
@@ -2881,7 +2872,6 @@
 	name:		"ttyS",
 	write:		zs_console_write,
 	device:		zs_console_device,
-	wait_key:	zs_console_wait_key,
 	setup:		zs_console_setup,
 	flags:		CON_PRINTBUFFER,
 	index:		-1,
diff -urN linux-2.4.19-pre5/drivers/scsi/scsi_lib.c linux-2.4.19-pre6/drivers/scsi/scsi_lib.c
--- linux-2.4.19-pre5/drivers/scsi/scsi_lib.c	Fri Oct 12 15:35:54 2001
+++ linux-2.4.19-pre6/drivers/scsi/scsi_lib.c	Thu Apr  4 22:05:05 2002
@@ -426,6 +426,7 @@
 	if (req->waiting != NULL) {
 		complete(req->waiting);
 	}
+	req_finished_io(req);
 	add_blkdev_randomness(MAJOR(req->rq_dev));
 
         SDpnt = SCpnt->device;
diff -urN linux-2.4.19-pre5/drivers/sgi/char/sgiserial.c linux-2.4.19-pre6/drivers/sgi/char/sgiserial.c
--- linux-2.4.19-pre5/drivers/sgi/char/sgiserial.c	Thu Apr  4 22:04:23 2002
+++ linux-2.4.19-pre6/drivers/sgi/char/sgiserial.c	Thu Apr  4 22:05:05 2002
@@ -49,8 +49,6 @@
 #define NUM_SERIAL 1     /* One chip on board. */
 #define NUM_CHANNELS (NUM_SERIAL * 2)
 
-extern wait_queue_head_t keypress_wait;
-
 struct sgi_zslayout *zs_chips[NUM_SERIAL] = { 0, };
 struct sgi_zschannel *zs_channels[NUM_CHANNELS] = { 0, 0, };
 struct sgi_zschannel *zs_conschan;
@@ -428,8 +426,6 @@
 			show_buffers();
 			return;
 		}
-		/* It is a 'keyboard interrupt' ;-) */
-		wake_up(&keypress_wait);
 	}
 	/* Look for kgdb 'stop' character, consult the gdb documentation
 	 * for remote target debugging and arch/sparc/kernel/sparc-stub.c
@@ -2117,12 +2113,6 @@
 	rs_fair_output();
 }
 
-static int zs_console_wait_key(struct console *con)
-{
-	sleep_on(&keypress_wait);
-	return 0;
-}
-
 static kdev_t zs_console_device(struct console *con)
 {
 	return MKDEV(TTY_MAJOR, 64 + con->index);
@@ -2274,7 +2264,6 @@
 	name:		"ttyS",
 	write:		zs_console_write,
 	device:		zs_console_device,
-	wait_key:	zs_console_wait_key,
 	setup:		zs_console_setup,
 	flags:		CON_PRINTBUFFER,
 	index:		-1,
diff -urN linux-2.4.19-pre5/drivers/sound/cmpci.c linux-2.4.19-pre6/drivers/sound/cmpci.c
--- linux-2.4.19-pre5/drivers/sound/cmpci.c	Fri Nov  9 14:07:41 2001
+++ linux-2.4.19-pre6/drivers/sound/cmpci.c	Thu Apr  4 22:05:06 2002
@@ -2032,7 +2032,7 @@
 		if (s->dma_adc.mapped)
 			s->dma_adc.count &= s->dma_adc.fragsize-1;
 		spin_unlock_irqrestore(&s->lock, flags);
-                return copy_to_user((void *)arg, &cinfo, sizeof(cinfo));
+                return copy_to_user((void *)arg, &cinfo, sizeof(cinfo))  ? -EFAULT : 0;
 
         case SNDCTL_DSP_GETOPTR:
 		if (!(file->f_mode & FMODE_WRITE))
@@ -2049,7 +2049,7 @@
 				s->dma_adc.count &= s->dma_adc.fragsize-1;
 		}
 		spin_unlock_irqrestore(&s->lock, flags);
-                return copy_to_user((void *)arg, &cinfo, sizeof(cinfo));
+                return copy_to_user((void *)arg, &cinfo, sizeof(cinfo)) ? -EFAULT : 0;
 
         case SNDCTL_DSP_GETBLKSIZE:
 		if (file->f_mode & FMODE_WRITE) {
diff -urN linux-2.4.19-pre5/drivers/sound/cs4281/cs4281m.c linux-2.4.19-pre6/drivers/sound/cs4281/cs4281m.c
--- linux-2.4.19-pre5/drivers/sound/cs4281/cs4281m.c	Thu Apr  4 22:04:24 2002
+++ linux-2.4.19-pre6/drivers/sound/cs4281/cs4281m.c	Thu Apr  4 22:05:06 2002
@@ -3576,7 +3576,7 @@
 		if (s->dma_adc.mapped)
 			s->dma_adc.count &= s->dma_adc.fragsize - 1;
 		spin_unlock_irqrestore(&s->lock, flags);
-		return copy_to_user((void *) arg, &cinfo, sizeof(cinfo));
+		return copy_to_user((void *) arg, &cinfo, sizeof(cinfo)) ? -EFAULT : 0;
 
 	case SNDCTL_DSP_GETOPTR:
 		if (!(file->f_mode & FMODE_WRITE))
@@ -3600,7 +3600,7 @@
 		if (s->dma_dac.mapped)
 			s->dma_dac.count &= s->dma_dac.fragsize - 1;
 		spin_unlock_irqrestore(&s->lock, flags);
-		return copy_to_user((void *) arg, &cinfo, sizeof(cinfo));
+		return copy_to_user((void *) arg, &cinfo, sizeof(cinfo)) ? -EFAULT : 0;
 
 	case SNDCTL_DSP_GETBLKSIZE:
 		if (file->f_mode & FMODE_WRITE) {
diff -urN linux-2.4.19-pre5/drivers/sound/cs46xx.c linux-2.4.19-pre6/drivers/sound/cs46xx.c
--- linux-2.4.19-pre5/drivers/sound/cs46xx.c	Mon Feb 25 11:38:04 2002
+++ linux-2.4.19-pre6/drivers/sound/cs46xx.c	Thu Apr  4 22:05:06 2002
@@ -2960,7 +2960,7 @@
 			cinfo.blocks = dmabuf->count/dmabuf->divisor >> dmabuf->fragshift;
 			cinfo.ptr = dmabuf->hwptr/dmabuf->divisor;
 			spin_unlock_irqrestore(&state->card->lock, flags);
-			return copy_to_user((void *)arg, &cinfo, sizeof(cinfo));
+			return copy_to_user((void *)arg, &cinfo, sizeof(cinfo)) ? -EFAULT : 0;
 		}
 		return -ENODEV;
 
@@ -2993,7 +2993,7 @@
 			    "cs46xx: GETOPTR bytes=%d blocks=%d ptr=%d\n",
 				cinfo.bytes,cinfo.blocks,cinfo.ptr) );
 			spin_unlock_irqrestore(&state->card->lock, flags);
-			return copy_to_user((void *)arg, &cinfo, sizeof(cinfo));
+			return copy_to_user((void *)arg, &cinfo, sizeof(cinfo)) ? -EFAULT : 0;
 		}
 		return -ENODEV;
 
diff -urN linux-2.4.19-pre5/drivers/sound/mad16.c linux-2.4.19-pre6/drivers/sound/mad16.c
--- linux-2.4.19-pre5/drivers/sound/mad16.c	Sun Sep 30 12:26:08 2001
+++ linux-2.4.19-pre6/drivers/sound/mad16.c	Thu Apr  4 22:05:08 2002
@@ -42,6 +42,7 @@
 #include <linux/config.h>
 #include <linux/init.h>
 #include <linux/module.h>
+#include <linux/gameport.h>
 
 #include "sound_config.h"
 
@@ -51,6 +52,7 @@
 
 static int      mad16_conf;
 static int      mad16_cdsel;
+static struct gameport gameport;
 
 static int      already_initialized = 0;
 
@@ -664,13 +666,13 @@
 
 	outb((bits | dma_bits[dma] | dma2_bit), config_port);	/* Write IRQ+DMA setup */
 
-	hw_config->slots[0] = ad1848_init("MAD16 WSS", hw_config->io_base + 4,
+	hw_config->slots[0] = ad1848_init("mad16 WSS", hw_config->io_base + 4,
 					  hw_config->irq,
 					  dma,
 					  dma2, 0,
 					  hw_config->osp,
 					  THIS_MODULE);
-	request_region(hw_config->io_base, 4, "MAD16 WSS config");
+	request_region(hw_config->io_base, 4, "mad16 WSS config");
 }
 
 static int __init probe_mad16_mpu(struct address_info *hw_config)
@@ -1010,14 +1012,6 @@
 	}
 
 	printk(".\n");
-        printk(KERN_INFO "Joystick port ");
-        if (joystick == 1)
-                printk("enabled.\n");
-        else
-        {
-                joystick = 0;
-                printk("disabled.\n");
-        }
 
 	cfg.io_base = io;
 	cfg.irq = irq;
@@ -1038,6 +1032,18 @@
 	attach_mad16(&cfg);
 
 	found_mpu = probe_mad16_mpu(&cfg_mpu);
+
+	if (joystick == 1) {
+	        /* register gameport */
+                if (!request_region(0x201, 1, "mad16 gameport"))
+                        printk(KERN_ERR "mad16: gameport address 0x201 already in use\n");
+                else {
+			printk(KERN_ERR "mad16: gameport enabled at 0x201\n");
+                        gameport.io = 0x201;
+		        gameport_register_port(&gameport);
+                }
+	}
+	else printk(KERN_ERR "mad16: gameport disabled.\n");
 	return 0;
 }
 
@@ -1055,16 +1061,17 @@
 static int __init setup_mad16(char *str)
 {
         /* io, irq */
-	int ints[7];
+	int ints[8];
 	
 	str = get_options(str, ARRAY_SIZE(ints), ints);
 
-	io	= ints[1];
-	irq	= ints[2];
-	dma	= ints[3];
-	dma16	= ints[4];
-	mpu_io	= ints[5];
-	mpu_irq = ints[6];
+	io	 = ints[1];
+	irq	 = ints[2];
+	dma	 = ints[3];
+	dma16	 = ints[4];
+	mpu_io	 = ints[5];
+	mpu_irq  = ints[6];
+	joystick = ints[7];
 
 	return 1;
 }
diff -urN linux-2.4.19-pre5/drivers/sound/maestro.c linux-2.4.19-pre6/drivers/sound/maestro.c
--- linux-2.4.19-pre5/drivers/sound/maestro.c	Sun Sep 30 12:26:08 2001
+++ linux-2.4.19-pre6/drivers/sound/maestro.c	Thu Apr  4 22:05:08 2002
@@ -2756,7 +2756,7 @@
 		if (s->dma_adc.mapped)
 			s->dma_adc.count &= s->dma_adc.fragsize-1;
 		spin_unlock_irqrestore(&s->lock, flags);
-                return copy_to_user((void *)arg, &cinfo, sizeof(cinfo));
+                return copy_to_user((void *)arg, &cinfo, sizeof(cinfo)) ? -EFAULT : 0;
 
         case SNDCTL_DSP_GETOPTR:
 		if (!(file->f_mode & FMODE_WRITE))
@@ -2771,7 +2771,7 @@
 		if (s->dma_dac.mapped)
 			s->dma_dac.count &= s->dma_dac.fragsize-1;
 		spin_unlock_irqrestore(&s->lock, flags);
-                return copy_to_user((void *)arg, &cinfo, sizeof(cinfo));
+                return copy_to_user((void *)arg, &cinfo, sizeof(cinfo)) ? -EFAULT : 0;
 
         case SNDCTL_DSP_GETBLKSIZE:
 		if (file->f_mode & FMODE_WRITE) {
diff -urN linux-2.4.19-pre5/drivers/sound/maestro3.c linux-2.4.19-pre6/drivers/sound/maestro3.c
--- linux-2.4.19-pre5/drivers/sound/maestro3.c	Fri Nov  9 13:41:42 2001
+++ linux-2.4.19-pre6/drivers/sound/maestro3.c	Thu Apr  4 22:05:08 2002
@@ -1805,7 +1805,7 @@
         if (s->dma_adc.mapped)
             s->dma_adc.count &= s->dma_adc.fragsize-1;
         spin_unlock_irqrestore(&s->lock, flags);
-        return copy_to_user((void *)arg, &cinfo, sizeof(cinfo));
+        return copy_to_user((void *)arg, &cinfo, sizeof(cinfo)) ? -EFAULT : 0;
 
     case SNDCTL_DSP_GETOPTR:
         if (!(file->f_mode & FMODE_WRITE))
@@ -1818,7 +1818,7 @@
         if (s->dma_dac.mapped)
             s->dma_dac.count &= s->dma_dac.fragsize-1;
         spin_unlock_irqrestore(&s->lock, flags);
-        return copy_to_user((void *)arg, &cinfo, sizeof(cinfo));
+        return copy_to_user((void *)arg, &cinfo, sizeof(cinfo)) ? -EFAULT : 0;
 
     case SNDCTL_DSP_GETBLKSIZE:
         if (file->f_mode & FMODE_WRITE) {
diff -urN linux-2.4.19-pre5/drivers/sound/rme96xx.c linux-2.4.19-pre6/drivers/sound/rme96xx.c
--- linux-2.4.19-pre5/drivers/sound/rme96xx.c	Thu Apr  4 22:04:24 2002
+++ linux-2.4.19-pre6/drivers/sound/rme96xx.c	Thu Apr  4 22:05:09 2002
@@ -1348,7 +1348,7 @@
 			dma->readptr &= s->fragsize<<1;
 		spin_unlock_irqrestore(&s->lock,flags);
 
-                return copy_to_user((void *)arg, &cinfo, sizeof(cinfo));
+                return copy_to_user((void *)arg, &cinfo, sizeof(cinfo)) ? -EFAULT : 0;
 
         case SNDCTL_DSP_GETOPTR:
 		if (!(file->f_mode & FMODE_READ))
@@ -1365,7 +1365,7 @@
 		if (dma->mmapped)
 			dma->writeptr &= s->fragsize<<1;
 		spin_unlock_irqrestore(&s->lock,flags);
-                return copy_to_user((void *)arg, &cinfo, sizeof(cinfo));
+                return copy_to_user((void *)arg, &cinfo, sizeof(cinfo)) ? -EFAULT : 0;
         case SNDCTL_DSP_GETBLKSIZE:
 	     return put_user(s->fragsize, (int *)arg);
 
diff -urN linux-2.4.19-pre5/drivers/sound/sonicvibes.c linux-2.4.19-pre6/drivers/sound/sonicvibes.c
--- linux-2.4.19-pre5/drivers/sound/sonicvibes.c	Mon Feb 25 11:38:07 2002
+++ linux-2.4.19-pre6/drivers/sound/sonicvibes.c	Thu Apr  4 22:05:09 2002
@@ -1802,7 +1802,7 @@
 		if (s->dma_adc.mapped)
 			s->dma_adc.count &= s->dma_adc.fragsize-1;
 		spin_unlock_irqrestore(&s->lock, flags);
-                return copy_to_user((void *)arg, &cinfo, sizeof(cinfo));
+                return copy_to_user((void *)arg, &cinfo, sizeof(cinfo)) ? -EFAULT : 0;
 
         case SNDCTL_DSP_GETOPTR:
 		if (!(file->f_mode & FMODE_WRITE))
@@ -1820,7 +1820,7 @@
 		if (s->dma_dac.mapped)
 			s->dma_dac.count &= s->dma_dac.fragsize-1;
 		spin_unlock_irqrestore(&s->lock, flags);
-                return copy_to_user((void *)arg, &cinfo, sizeof(cinfo));
+                return copy_to_user((void *)arg, &cinfo, sizeof(cinfo)) ? -EFAULT : 0;
 
         case SNDCTL_DSP_GETBLKSIZE:
 		if (file->f_mode & FMODE_WRITE) {
diff -urN linux-2.4.19-pre5/drivers/sound/vwsnd.c linux-2.4.19-pre6/drivers/sound/vwsnd.c
--- linux-2.4.19-pre5/drivers/sound/vwsnd.c	Thu Apr  4 22:04:24 2002
+++ linux-2.4.19-pre6/drivers/sound/vwsnd.c	Thu Apr  4 22:05:09 2002
@@ -2650,7 +2650,7 @@
 		DBGXV("SNDCTL_DSP_GETOSPACE returns { %d %d %d %d }\n",
 		     buf_info.fragments, buf_info.fragstotal,
 		     buf_info.fragsize, buf_info.bytes);
-		return copy_to_user((void *) arg, &buf_info, sizeof buf_info);
+		return copy_to_user((void *) arg, &buf_info, sizeof buf_info) ? -EFAULT : 0;
 
 	case SNDCTL_DSP_GETISPACE:	/* _SIOR ('P',13, audio_buf_info) */
 		DBGX("SNDCTL_DSP_GETISPACE\n");
@@ -2667,7 +2667,7 @@
 		DBGX("SNDCTL_DSP_GETISPACE returns { %d %d %d %d }\n",
 		     buf_info.fragments, buf_info.fragstotal,
 		     buf_info.fragsize, buf_info.bytes);
-		return copy_to_user((void *) arg, &buf_info, sizeof buf_info);
+		return copy_to_user((void *) arg, &buf_info, sizeof buf_info) ? -EFAULT : 0;
 
 	case SNDCTL_DSP_NONBLOCK:	/* _SIO  ('P',14) */
 		DBGX("SNDCTL_DSP_NONBLOCK\n");
@@ -2725,7 +2725,7 @@
 			rport->frag_count = 0;
 		}
 		spin_unlock_irqrestore(&rport->lock, flags);
-		return copy_to_user((void *) arg, &info, sizeof info);
+		return copy_to_user((void *) arg, &info, sizeof info) ? -EFAULT : 0;
 
 	case SNDCTL_DSP_GETOPTR:	/* _SIOR ('P',18, count_info) */
 		DBGX("SNDCTL_DSP_GETOPTR\n");
@@ -2747,7 +2747,7 @@
 			wport->frag_count = 0;
 		}
 		spin_unlock_irqrestore(&wport->lock, flags);
-		return copy_to_user((void *) arg, &info, sizeof info);
+		return copy_to_user((void *) arg, &info, sizeof info) ? -EFAULT : 0;
 
 	case SNDCTL_DSP_GETODELAY:	/* _SIOR ('P', 23, int) */
 		DBGX("SNDCTL_DSP_GETODELAY\n");
diff -urN linux-2.4.19-pre5/drivers/tc/zs.c linux-2.4.19-pre6/drivers/tc/zs.c
--- linux-2.4.19-pre5/drivers/tc/zs.c	Thu Apr  4 22:04:24 2002
+++ linux-2.4.19-pre6/drivers/tc/zs.c	Thu Apr  4 22:05:09 2002
@@ -2125,18 +2125,6 @@
 	}
 }
 
-/*
- *	Receive character from the serial port
- */
-static int serial_console_wait_key(struct console *co)
-{
-	struct dec_serial *info;
-
-        info = zs_soft + co->index;
-
-        return zs_poll_rx_char(info);
-}
-
 static kdev_t serial_console_device(struct console *c)
 {
 	return MKDEV(TTY_MAJOR, 64 + c->index);
@@ -2271,7 +2259,6 @@
 	name:		"ttyS",
 	write:		serial_console_write,
 	device:		serial_console_device,
-	wait_key:	serial_console_wait_key,
 	setup:		serial_console_setup,
 	flags:		CON_PRINTBUFFER,
 	index:		-1,
diff -urN linux-2.4.19-pre5/drivers/usb/CDCEther.c linux-2.4.19-pre6/drivers/usb/CDCEther.c
--- linux-2.4.19-pre5/drivers/usb/CDCEther.c	Fri Dec 21 09:41:55 2001
+++ linux-2.4.19-pre6/drivers/usb/CDCEther.c	Thu Apr  4 22:05:09 2002
@@ -1,4 +1,4 @@
-// Portions of this file taken from 
+// Portions of this file taken from
 // Petko Manolov - Petkan (petkan@dce.bg)
 // from his driver pegasus.c
 
@@ -25,20 +25,27 @@
 #include <linux/delay.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
-#include <linux/usb.h>
 #include <linux/module.h>
+#include <linux/ethtool.h>
+#include <asm/uaccess.h>
+
+#define DEBUG
+#include <linux/usb.h>
+
 #include "CDCEther.h"
 
-static const char *version = __FILE__ ": v0.98.5 22 Sep 2001 Brad Hards and another";
+#define SHORT_DRIVER_DESC "CDC Ethernet Class"
+#define DRIVER_VERSION "0.98.6"
 
-/* Take any CDC device, and sort it out in probe() */
+static const char *version = __FILE__ ": " DRIVER_VERSION " 7 Jan 2002 Brad Hards and another";
+// We only try to claim CDC Ethernet model devices */
 static struct usb_device_id CDCEther_ids[] = {
-	{ USB_DEVICE_INFO(USB_CLASS_COMM, 0, 0) },
-	{ } /* Terminating null entry */
+	{ USB_INTERFACE_INFO(USB_CLASS_COMM, 6, 0) },
+	{ }
 };
 
-/* 
- * module parameter that provides an alternate upper limit on the 
+/*
+ * module parameter that provides an alternate upper limit on the
  * number of multicast filters we use, with a default to use all
  * the filters available to us. Note that the actual number used
  * is the lesser of this parameter and the number returned in the
@@ -47,7 +54,6 @@
  */
 static int multicast_filter_limit = 32767;
 
-
 //////////////////////////////////////////////////////////////////////////////
 // Callback routines from USB device /////////////////////////////////////////
 //////////////////////////////////////////////////////////////////////////////
@@ -59,7 +65,16 @@
 	int count = urb->actual_length, res;
 	struct sk_buff	*skb;
 
-	// Sanity check 
+	switch ( urb->status ) {
+		case USB_ST_NOERROR:
+			break;
+		case USB_ST_URB_KILLED:
+			return;
+		default:
+			dbg("rx status %d", urb->status);
+	}
+
+	// Sanity check
 	if ( !ether_dev || !(ether_dev->flags & CDC_ETHER_RUNNING) ) {
 		dbg("BULK IN callback but driver is not active!");
 		return;
@@ -133,7 +148,7 @@
 	// Give this to the USB subsystem so it can tell us 
 	// when more data arrives.
 	if ( (res = usb_submit_urb(&ether_dev->rx_urb)) ) {
-		warn( __FUNCTION__ " failed submint rx_urb %d", res);
+		warn( __FUNCTION__ " failed submit rx_urb %d", res);
 	}
 	
 	// We are no longer busy, show us the frames!!!
@@ -160,47 +175,69 @@
 
 	// Hmm...  What on Earth could have happened???
 	if ( urb->status ) {
-		info("%s: TX status %d", ether_dev->net->name, urb->status);
+		dbg("%s: TX status %d", ether_dev->net->name, urb->status);
 	}
 
 	// Update the network interface and tell it we are
 	// ready for another frame
 	ether_dev->net->trans_start = jiffies;
 	netif_wake_queue( ether_dev->net );
+
 }
 
-//static void intr_callback( struct urb *urb )
-//{
-//	ether_dev_t *ether_dev = urb->context;
-//	struct net_device *net;
-//	__u8	*d;
-//
-//	if ( !ether_dev )
-//		return;
-//		
-//	switch ( urb->status ) {
-//		case USB_ST_NOERROR:
-//			break;
-//		case USB_ST_URB_KILLED:
-//			return;
-//		default:
-//			info("intr status %d", urb->status);
-//	}
-//
-//	d = urb->transfer_buffer;
-//	net = ether_dev->net;
-//	if ( d[0] & 0xfc ) {
-//		ether_dev->stats.tx_errors++;
-//		if ( d[0] & TX_UNDERRUN )
-//			ether_dev->stats.tx_fifo_errors++;
-//		if ( d[0] & (EXCESSIVE_COL | JABBER_TIMEOUT) )
-//			ether_dev->stats.tx_aborted_errors++;
-//		if ( d[0] & LATE_COL )
-//			ether_dev->stats.tx_window_errors++;
-//		if ( d[0] & (NO_CARRIER | LOSS_CARRIER) )
-//			ether_dev->stats.tx_carrier_errors++;
-//	}
-//}
+#if 0
+static void setpktfilter_done( struct urb *urb )
+{
+	ether_dev_t *ether_dev = urb->context;
+	struct net_device *net;
+
+	if ( !ether_dev )
+		return;
+	dbg("got ctrl callback for setting packet filter");
+	switch ( urb->status ) {
+		case USB_ST_NOERROR:
+			break;
+		case USB_ST_URB_KILLED:
+			return;
+		default:
+			dbg("intr status %d", urb->status);
+	}
+}
+#endif 
+
+static void intr_callback( struct urb *urb )
+{
+	ether_dev_t *ether_dev = urb->context;
+	struct net_device *net;
+	__u8	*d;
+
+	if ( !ether_dev )
+		return;
+	dbg("got intr callback");
+	switch ( urb->status ) {
+		case USB_ST_NOERROR:
+			break;
+		case USB_ST_URB_KILLED:
+			return;
+		default:
+			dbg("intr status %d", urb->status);
+	}
+
+	d = urb->transfer_buffer;
+	dbg("d: %x", d[0]);
+	net = ether_dev->net;
+	if ( d[0] & 0xfc ) {
+		ether_dev->stats.tx_errors++;
+		if ( d[0] & TX_UNDERRUN )
+			ether_dev->stats.tx_fifo_errors++;
+		if ( d[0] & (EXCESSIVE_COL | JABBER_TIMEOUT) )
+			ether_dev->stats.tx_aborted_errors++;
+		if ( d[0] & LATE_COL )
+			ether_dev->stats.tx_window_errors++;
+		if ( d[0] & (NO_CARRIER | LOSS_CARRIER) )
+			netif_carrier_off(net);
+	}
+}
 
 //////////////////////////////////////////////////////////////////////////////
 // Routines for turning net traffic on and off on the USB side ///////////////
@@ -213,8 +250,8 @@
 	// Here would be the time to set the data interface to the configuration where
 	// it has two endpoints that use a protocol we can understand.
 
-	if (usb_set_interface( usb, 
-	                        ether_dev->data_bInterfaceNumber, 
+	if (usb_set_interface( usb,
+	                        ether_dev->data_bInterfaceNumber,
 	                        ether_dev->data_bAlternateSetting_with_traffic ) )  {
 		err("usb_set_interface() failed" );
 		err("Attempted to set interface %d", ether_dev->data_bInterfaceNumber);
@@ -230,8 +267,8 @@
 	// no endpoints.  This is what the spec suggests.
 
 	if (ether_dev->data_interface_altset_num_without_traffic >= 0 ) {
-		if (usb_set_interface( ether_dev->usb, 
-		                        ether_dev->data_bInterfaceNumber, 
+		if (usb_set_interface( ether_dev->usb,
+		                        ether_dev->data_bInterfaceNumber,
 		                        ether_dev->data_bAlternateSetting_without_traffic ) ) 	{
 			err("usb_set_interface() failed");
 		}
@@ -326,6 +363,9 @@
 	return 0;
 }
 
+//////////////////////////////////////////////////////////////////////////////
+// Standard routines for kernel Ethernet Device //////////////////////////////
+//////////////////////////////////////////////////////////////////////////////
 static struct net_device_stats *CDCEther_netdev_stats( struct net_device *net )
 {
 	// Easy enough!
@@ -343,19 +383,33 @@
 		return -EIO;
 	}
 
-	// Prep a receive URB
+	/* Prep a receive URB */
 	FILL_BULK_URB( &ether_dev->rx_urb, ether_dev->usb,
 			usb_rcvbulkpipe(ether_dev->usb, ether_dev->data_ep_in),
-			ether_dev->rx_buff, ether_dev->wMaxSegmentSize, 
+			ether_dev->rx_buff, ether_dev->wMaxSegmentSize,
 			read_bulk_callback, ether_dev );
 
-	// Put it out there so the device can send us stuff
-	if ( (res = usb_submit_urb(&ether_dev->rx_urb)) )
-	{
-		// Hmm...  Okay...
+	/* Put it out there so the device can send us stuff */
+	if ( (res = usb_submit_urb(&ether_dev->rx_urb)) ) {
+		/* Hmm...  Okay... */
 		warn( __FUNCTION__ " failed rx_urb %d", res );
 	}
 
+	if (ether_dev->properties & HAVE_NOTIFICATION_ELEMENT) {
+		/* Arm and submit the interrupt URB */
+		FILL_INT_URB( &ether_dev->intr_urb,
+			ether_dev->usb,
+			usb_rcvintpipe(ether_dev->usb, ether_dev->comm_ep_in),
+			ether_dev->intr_buff,
+			8, /* Transfer buffer length */
+			intr_callback,
+			ether_dev,
+			ether_dev->intr_interval);
+		if ( (res = usb_submit_urb(&ether_dev->intr_urb)) ) {
+			warn( __FUNCTION__ " failed intr_urb %d", res );
+		}
+	}
+
 	// Tell the kernel we are ready to start receiving from it
 	netif_start_queue( net );
 	
@@ -386,92 +440,133 @@
 	usb_unlink_urb( &ether_dev->rx_urb );
 	usb_unlink_urb( &ether_dev->tx_urb );
 	usb_unlink_urb( &ether_dev->intr_urb );
-	
+	usb_unlink_urb( &ether_dev->ctrl_urb );
+
 	// That's it.  I'm done.
 	return 0;
 }
 
-static int CDCEther_ioctl( struct net_device *net, struct ifreq *rq, int cmd )
+static int netdev_ethtool_ioctl(struct net_device *netdev, void *useraddr)
 {
-	//__u16 *data = (__u16 *)&rq->ifr_data;
-	//ether_dev_t	*ether_dev = net->priv;
+	ether_dev_t *ether_dev = netdev->priv;
+	u32 cmd;
+	char tmp[40];
+
+	if (get_user(cmd, (u32 *)useraddr))
+		return -EFAULT;
+
+	switch (cmd) {
+	/* get driver info */
+	case ETHTOOL_GDRVINFO: {
+	struct ethtool_drvinfo info = {ETHTOOL_GDRVINFO};
+		strncpy(info.driver, SHORT_DRIVER_DESC, ETHTOOL_BUSINFO_LEN);
+		strncpy(info.version, DRIVER_VERSION, ETHTOOL_BUSINFO_LEN);
+		sprintf(tmp, "usb%d:%d", ether_dev->usb->bus->busnum, ether_dev->usb->devnum);
+		strncpy(info.bus_info, tmp, ETHTOOL_BUSINFO_LEN);
+		sprintf(tmp, "CDC %x.%x", ((ether_dev->bcdCDC & 0xff00)>>8), (ether_dev->bcdCDC & 0x00ff) );
+		strncpy(info.fw_version, tmp, ETHTOOL_BUSINFO_LEN);
+		if (copy_to_user(useraddr, &info, sizeof(info)))
+			return -EFAULT;
+		return 0;
+	}
+	/* get link status */
+	case ETHTOOL_GLINK: {
+		struct ethtool_value edata = {ETHTOOL_GLINK};
+		edata.data = netif_carrier_ok(netdev);
+		if (copy_to_user(useraddr, &edata, sizeof(edata)))
+			return -EFAULT;
+		return 0;
+	}
+	}
+	dbg("Got unsupported ioctl: %x", cmd);
+	return -EOPNOTSUPP; /* the ethtool user space tool relies on this */
+}
 
-	// No support here yet.
-	// Do we need support???
+static int CDCEther_ioctl( struct net_device *net, struct ifreq *rq, int cmd )
+{
 	switch(cmd) {
-		case SIOCDEVPRIVATE:
-			return -EOPNOTSUPP;
-		case SIOCDEVPRIVATE+1:
-			return -EOPNOTSUPP;
-		case SIOCDEVPRIVATE+2:
-			//return 0;
-			return -EOPNOTSUPP;
-		default:
-			return -EOPNOTSUPP;
+	case SIOCETHTOOL:
+		return netdev_ethtool_ioctl(net, (void *) rq->ifr_data);
+	default:
+		return -ENOTTY; /* per ioctl man page */
 	}
 }
 
+/* Multicast routines */
+
 static void CDC_SetEthernetPacketFilter (ether_dev_t *ether_dev)
 {
-	usb_control_msg(ether_dev->usb,
+#if 0
+	devrequest *dr = &ether_dev->ctrl_dr;
+	int res;
+
+	dr->requesttype = USB_TYPE_CLASS | USB_DIR_OUT | USB_RECIP_INTERFACE;
+	dr->request = SET_ETHERNET_PACKET_FILTER;
+	dr->value = cpu_to_le16(ether_dev->mode_flags);
+	dr->index = cpu_to_le16((u16)ether_dev->comm_interface);
+	dr->length = 0;
+
+	FILL_CONTROL_URB(&ether_dev->ctrl_urb,
+			ether_dev->usb,
 			usb_sndctrlpipe(ether_dev->usb, 0),
-			SET_ETHERNET_PACKET_FILTER, /* request */
-			USB_TYPE_CLASS | USB_DIR_OUT | USB_RECIP_INTERFACE, /* request type */
-			cpu_to_le16(ether_dev->mode_flags), /* value */
-			cpu_to_le16((u16)ether_dev->comm_interface), /* index */
+			dr,
+			NULL,
 			NULL,
-			0, /* size */
-			HZ); /* timeout */
-}	
+			setpktfilter_done,
+			ether_dev);
+	if ( (res = usb_submit_urb(&ether_dev->ctrl_urb)) ) {
+		warn( __FUNCTION__ " failed submit ctrl_urb %d", res);
+	}
+#endif
 
+}
 
 static void CDCEther_set_multicast( struct net_device *net )
 {
 	ether_dev_t *ether_dev = net->priv;
 	int i;
 	__u8 *buff;
-	
 
 	// Tell the kernel to stop sending us frames while we get this
 	// all set up.
 	netif_stop_queue(net);
 
-      /* Note: do not reorder, GCC is clever about common statements. */
-        if (net->flags & IFF_PROMISC) {
-                /* Unconditionally log net taps. */
-                info( "%s: Promiscuous mode enabled", net->name);
+	/* Note: do not reorder, GCC is clever about common statements. */
+	if (net->flags & IFF_PROMISC) {
+		/* Unconditionally log net taps. */
+		dbg( "%s: Promiscuous mode enabled", net->name);
 		ether_dev->mode_flags = MODE_FLAG_PROMISCUOUS |
 			MODE_FLAG_ALL_MULTICAST |
 			MODE_FLAG_DIRECTED |
 			MODE_FLAG_BROADCAST |
 			MODE_FLAG_MULTICAST;
-        } else if (net->mc_count > ether_dev->wNumberMCFilters) {
-                /* Too many to filter perfectly -- accept all multicasts. */
-		info("%s: set too many MC filters, using allmulti", net->name);
+	} else if (net->mc_count > ether_dev->wNumberMCFilters) {
+		/* Too many to filter perfectly -- accept all multicasts. */
+		dbg("%s: too many MC filters for hardware, using allmulti", net->name);
 		ether_dev->mode_flags = MODE_FLAG_ALL_MULTICAST |
 			MODE_FLAG_DIRECTED |
 			MODE_FLAG_BROADCAST |
 			MODE_FLAG_MULTICAST;
 	} else if (net->flags & IFF_ALLMULTI) {
-                /* Filter in software */
-		info("%s: using allmulti", net->name);
+		/* Filter in software */
+		dbg("%s: using allmulti", net->name);
 		ether_dev->mode_flags = MODE_FLAG_ALL_MULTICAST |
 			MODE_FLAG_DIRECTED |
 			MODE_FLAG_BROADCAST |
 			MODE_FLAG_MULTICAST;
-        } else {
+	} else {
 		/* do multicast filtering in hardware */
-                struct dev_mc_list *mclist;
-		info("%s: set multicast filters", net->name);
+		struct dev_mc_list *mclist;
+		dbg("%s: set multicast filters", net->name);
 		ether_dev->mode_flags = MODE_FLAG_ALL_MULTICAST |
 			MODE_FLAG_DIRECTED |
 			MODE_FLAG_BROADCAST |
 			MODE_FLAG_MULTICAST;
 		buff = kmalloc(6 * net->mc_count, in_interrupt() ? GFP_ATOMIC : GFP_KERNEL);
-                for (i = 0, mclist = net->mc_list;
-		     mclist && i < net->mc_count;
-                     i++, mclist = mclist->next) {
-			memcpy(&mclist->dmi_addr, &buff[i * 6], 6);
+		for (i = 0, mclist = net->mc_list;
+			mclist && i < net->mc_count;
+			i++, mclist = mclist->next) {
+				memcpy(&mclist->dmi_addr, &buff[i * 6], 6);
 		}
 #if 0
 		usb_control_msg(ether_dev->usb,
@@ -487,10 +582,9 @@
 		kfree(buff);
 	}
 
-#if 0 
 	CDC_SetEthernetPacketFilter(ether_dev);
-#endif	
-        // Tell the kernel to start giving frames to us again.
+
+	/* Tell the kernel to start giving frames to us again. */
 	netif_wake_queue(net);
 }
 
@@ -498,40 +592,42 @@
 // Routines used to parse out the Functional Descriptors /////////////////////
 //////////////////////////////////////////////////////////////////////////////
 
-static int parse_header_functional_descriptor( int *bFunctionLength, 
-                                               int bDescriptorType, 
+/* Header Descriptor - CDC Spec 5.2.3.1, Table 26 */
+static int parse_header_functional_descriptor( int *bFunctionLength,
+                                               int bDescriptorType,
                                                int bDescriptorSubtype,
                                                unsigned char *data,
                                                ether_dev_t *ether_dev,
                                                int *requirements )
 {
-	// Check to make sure we haven't seen one of these already.
+	/* Check to make sure we haven't seen one of these already. */
 	if ( (~*requirements) & REQ_HDR_FUNC_DESCR ) {
 		err( "Multiple Header Functional Descriptors found." );
 		return -1;
 	}
-	
-	// Is it the right size???
-	if (*bFunctionLength != 5) {
-		info( "Invalid length in Header Functional Descriptor" );
-		// This is a hack to get around a particular device (NO NAMES)
-		// It has this function length set to the length of the
-		// whole class-specific descriptor
-		*bFunctionLength = 5;
+
+	/* Check for appropriate length */
+	if (*bFunctionLength != HEADER_FUNC_DESC_LEN) {
+		dbg( "Invalid length in Header Functional Descriptor, working around it." );
+		/* This is a hack to get around a particular device (NO NAMES)
+		 * It has this function length set to the length of the
+		 * whole class-specific descriptor */
+		*bFunctionLength = HEADER_FUNC_DESC_LEN;
 	}
 	
-	// Nothing extremely useful here.
-	// We'll keep it for posterity
+	/* Nothing extremely useful here */
+	/* We'll keep it for posterity */
 	ether_dev->bcdCDC = data[0] + (data[1] << 8);
-	dbg( "Found Header descriptor, CDC version %x", ether_dev->bcdCDC);
+	dbg( "Found Header descriptor, CDC version %x.", ether_dev->bcdCDC);
 
-	// We've seen one of these
+	/* We've seen one of these */
 	*requirements &= ~REQ_HDR_FUNC_DESCR;
-	
-	// It's all good.
+
+	/* Success */
 	return 0;
 }
 
+/* Union Descriptor - CDC Spec 5.2.3.8, Table 33 */
 static int parse_union_functional_descriptor( int *bFunctionLength, 
                                               int bDescriptorType, 
                                               int bDescriptorSubtype,
@@ -539,77 +635,89 @@
                                               ether_dev_t *ether_dev,
                                               int *requirements )
 {
-	// Check to make sure we haven't seen one of these already.
+	/* Check to make sure we haven't seen one of these already. */
 	if ( (~*requirements) & REQ_UNION_FUNC_DESCR ) {
 		err( "Multiple Union Functional Descriptors found." );
 		return -1;
 	}
 
-	// Is it the right size?
-	if (*bFunctionLength != 5) {
+	/* Check for appropriate length */
+	if (*bFunctionLength != UNION_FUNC_DESC_LEN) {
 		// It is NOT the size we expected.
-		err( "Unsupported length in Union Functional Descriptor" );
+		err( "Invalid length in Union Functional Descriptor." );
 		return -1;
 	}
 	
-	// Sanity check of sorts
+	/* Sanity check of sorts */
 	if (ether_dev->comm_interface != data[0]) {
-		// This tells us that we are chasing the wrong comm
-		// interface or we are crazy or something else weird.
+		/* This tells us that we are chasing the wrong comm
+		 * interface or we are crazy or something else weird. */
 		if (ether_dev->comm_interface == data[1]) {
-			info( "Probably broken Union descriptor, fudging data interface" );
-			// We'll need this in a few microseconds, 
-			// so guess here, and hope for the best
+			dbg( "Probably broken Union descriptor, fudging data interface." );
+			/* We'll need this in a few microseconds,
+			 * so if the comm interface was the first slave,
+			 * then probably the master interface is the data one
+			 * Just hope for the best */
 			ether_dev->data_interface = data[0];
 		} else {
-			err( "Union Functional Descriptor is broken beyond repair" );
+			err( "Union Functional Descriptor is broken beyond repair." );
 			return -1;
 		}
-	} else{ // Descriptor is OK
-       		// We'll need this in a few microseconds!
+	} else{ /* Descriptor is OK */
 		ether_dev->data_interface = data[1];
 	}
 
-	// We've seen one of these now.
+	/* We've seen one of these */
 	*requirements &= ~REQ_UNION_FUNC_DESCR;
-	
-	// Done
+
+	/* Success */
 	return 0;
 }
 
-static int parse_ethernet_functional_descriptor( int *bFunctionLength, 
+/* Ethernet Descriptor - CDC Spec 5.2.3.16, Table 41 */
+static int parse_ethernet_functional_descriptor( int *bFunctionLength,
                                                  int bDescriptorType, 
                                                  int bDescriptorSubtype,
                                                  unsigned char *data,
                                                  ether_dev_t *ether_dev,
                                                  int *requirements )
 {
-	// Check to make sure we haven't seen one of these already.
+	//* Check to make sure we haven't seen one of these already. */
 	if ( (~*requirements) & REQ_ETH_FUNC_DESCR ) {
 		err( "Multiple Ethernet Functional Descriptors found." );
 		return -1;
 	}
 	
-	// Is it the right size?
-	if (*bFunctionLength != 13) {
-		err( "Invalid length in Ethernet Networking Functional Descriptor" );
+	/* Check for appropriate length */
+	if (*bFunctionLength != ETHERNET_FUNC_DESC_LEN) {
+		err( "Invalid length in Ethernet Networking Functional Descriptor." );
 		return -1;
 	}
-	
-	// Lots of goodies from this one.  They are all important.
+
+	/* Lots of goodies from this one.  They are all important. */
 	ether_dev->iMACAddress = data[0];
 	ether_dev->bmEthernetStatistics = data[1] + (data[2] << 8) + (data[3] << 16) + (data[4] << 24);
 	ether_dev->wMaxSegmentSize = data[5] + (data[6] << 8);
-	ether_dev->wNumberMCFilters = (data[7] + (data[8] << 8)) & 0x00007FFF;
+	ether_dev->wNumberMCFilters = (data[7] + (data[8] << 8));
+	if (ether_dev->wNumberMCFilters & (1 << 15)) {
+		ether_dev->properties |= PERFECT_FILTERING;
+		dbg("Perfect filtering support");
+	} else {
+		dbg("Imperfect filtering support - need sw hashing");
+	}
+	if (0 == (ether_dev->wNumberMCFilters & (0x7f))) {
+		ether_dev->properties |= NO_SET_MULTICAST;
+		dbg("Can't use SetEthernetMulticastFilters request");
+	}
 	if (ether_dev->wNumberMCFilters > multicast_filter_limit) {
 		ether_dev->wNumberMCFilters = multicast_filter_limit;
-		}	
+	}
 	ether_dev->bNumberPowerFilters = data[9];
 	
-	// We've seen one of these now.
+	/* We've seen one of these */
 	*requirements &= ~REQ_ETH_FUNC_DESCR;
-	
-	// That's all she wrote.
+
+	/* Success */
 	return 0;
 }
 
@@ -620,15 +728,15 @@
                                                       ether_dev_t *ether_dev,
                                                       int *requirements )
 {
-	// There should only be one type if we are sane
+	/* There should only be one type if we are sane */
 	if (bDescriptorType != CS_INTERFACE) {
-		info( "Invalid bDescriptorType found." );
+		err( "Invalid bDescriptorType found." );
 		return -1;
 	}
 
-	// The Subtype tells the tale.
-	switch (bDescriptorSubtype){
-		case 0x00:	// Header Functional Descriptor
+	/* The Subtype tells the tale - CDC spec Table 25 */
+	switch (bDescriptorSubtype) {
+		case 0x00:	/* Header Functional Descriptor */
 			return parse_header_functional_descriptor( bFunctionLength,
 			                                           bDescriptorType,
 			                                           bDescriptorSubtype,
@@ -636,7 +744,7 @@
 			                                           ether_dev,
 			                                           requirements );
 			break;
-		case 0x06:	// Union Functional Descriptor
+		case 0x06:	/* Union Functional Descriptor */
 			return parse_union_functional_descriptor( bFunctionLength,
 			                                          bDescriptorType,
 			                                          bDescriptorSubtype,
@@ -644,7 +752,7 @@
 			                                          ether_dev,
 			                                          requirements );
 			break;
-		case 0x0F:	// Ethernet Networking Functional Descriptor
+		case 0x0F:	/* Ethernet Networking Functional Descriptor */
 			return parse_ethernet_functional_descriptor( bFunctionLength,
 			                                             bDescriptorType,
 			                                             bDescriptorSubtype,
@@ -652,12 +760,12 @@
 			                                             ether_dev,
 			                                             requirements );
 			break;
-		default:	// We don't support this at this time...
-			// However that doesn't necessarily indicate an error.
-			dbg( "Unexpected header type %x:", bDescriptorSubtype );
+		default:	/* We don't support this at this time... */
+				/* However that doesn't necessarily indicate an error. */
+			dbg( "Unexpected header type %x.", bDescriptorSubtype );
 			return 0;
 	}
-	// How did we get here???
+	/* How did we get here? */
 	return -1;
 }
 
@@ -668,46 +776,49 @@
 	int bFunctionLength;
 	int bDescriptorType;
 	int bDescriptorSubtype;
-	int requirements = REQUIREMENTS_TOTAL;
+	int requirements = REQUIREMENTS_TOTAL; /* We init to our needs, and then clear
+						* bits as we find the descriptors */
 
-	// As long as there is something here, we will try to parse it
+	/* As long as there is something here, we will try to parse it */
+	/* All of the functional descriptors start with the same 3 byte pattern */
 	while (loc < length) {
-		// Length
+		/* Length */
 		bFunctionLength = data[loc];
 		loc++;
-		
-		// Type
+
+		/* Type */
 		bDescriptorType = data[loc];
 		loc++;
-		
-		// Subtype
+
+		/* Subtype */
 		bDescriptorSubtype = data[loc];
 		loc++;
 		
-		// ship this off to be processed elsewhere.
+		/* ship this off to be processed */
 		rc = parse_protocol_unit_functional_descriptor( &bFunctionLength, 
 		                                                bDescriptorType, 
 		                                                bDescriptorSubtype, 
 		                                                &data[loc],
 		                                                ether_dev,
 		                                                &requirements );
-		// Did it process okay?
+		/* Did it process okay? */
 		if (rc)	{
-			// Something was hosed somewhere.
-			// No need to continue;
+			/* Something was hosed somewhere. */
+			/*  No need to continue */
 			err("Bad descriptor parsing: %x", rc );
 			return -1;
 		}
-		// We have already taken three bytes.
+		/* We move the loc pointer along, remembering
+		 * that we have already taken three bytes */
 		loc += (bFunctionLength - 3);
 	}
-	// Check to see if we got everything we need.
+	/* Check to see if we got everything we need. */
 	if (requirements) {
 		// We missed some of the requirements...
-		err( "Not all required functional descriptors present 0x%08X", requirements );
+		err( "Not all required functional descriptors present 0x%08X.", requirements );
 		return -1;
 	}
-	// We got everything.
+	/* We got everything */
 	return 0;
 }
 
@@ -721,28 +832,28 @@
 	struct usb_interface *comm_intf_group = NULL;
 	struct usb_interface_descriptor *comm_intf = NULL;
 	int rc = -1;
-	// The assumption here is that find_ethernet_comm_interface
-	// and find_valid_configuration 
-	// have already filled in the information about where to find
-	// the a valid commication interface.
+	/* The assumption here is that find_ethernet_comm_interface
+	 * and find_valid_configuration
+	 * have already filled in the information about where to find
+	 * the a valid commication interface. */
 
 	conf = &( device->config[ether_dev->configuration_num] );
 	comm_intf_group = &( conf->interface[ether_dev->comm_interface] );
 	comm_intf = &( comm_intf_group->altsetting[ether_dev->comm_interface_altset_num] );
-	// Let's check and see if it has the extra information we need...
 
+	/* Let's check and see if it has the extra information we need */
 	if (comm_intf->extralen > 0) {
-		// This is where the information is SUPPOSED to be.
+		/* This is where the information is SUPPOSED to be */
 		rc = parse_ethernet_class_information( comm_intf->extra, comm_intf->extralen, ether_dev );
 	} else if (conf->extralen > 0) {
-		// This is a hack.  The spec says it should be at the interface 
-		// location checked above.  However I have seen it here also.
-		// This is the same device that requires the functional descriptor hack above
-		warn( "Ethernet information found at device configuration.  This is broken." );
+		/* This is a hack.  The spec says it should be at the interface
+		 * location checked above.  However I have seen it here also.
+		 * This is the same device that requires the functional descriptor hack above */
+		dbg( "Ethernet information found at device configuration.  Trying to use it anyway." );
 		rc = parse_ethernet_class_information( conf->extra, conf->extralen, ether_dev );
 	} else 	{
-		// I don't know where else to look.
-		warn( "No ethernet information found." );
+		/* I don't know where else to look */
+		err( "No ethernet information found." );
 		rc = -1;
 	}
 	return rc;
@@ -757,47 +868,43 @@
 	struct usb_config_descriptor *conf = NULL;
 	struct usb_interface *data_intf_group = NULL;
 	struct usb_interface_descriptor *data_intf = NULL;
-	
-	// Walk through and get to the data interface we are checking.
+
+	/* Walk through and get to the data interface we are checking. */
 	conf = &( device->config[ether_dev->configuration_num] );
 	data_intf_group = &( conf->interface[ether_dev->data_interface] );
 	data_intf = &( data_intf_group->altsetting[ether_dev->data_interface_altset_num_with_traffic] );
 
-	// Start out assuming we won't find anything we can use
+	/* Start out assuming we won't find anything we can use */
 	ether_dev->data_ep_in = 0;
 	ether_dev->data_ep_out = 0;
-	
-	// If these are not BULK endpoints, we don't want them
-	if ( data_intf->endpoint[0].bmAttributes != 0x02 ) {
+
+	/* If these are not BULK endpoints, we don't want them */
+	if ( data_intf->endpoint[0].bmAttributes != USB_ENDPOINT_XFER_BULK ) {
 		return -1;
-	} if ( data_intf->endpoint[1].bmAttributes != 0x02 ) {
+	}
+	if ( data_intf->endpoint[1].bmAttributes != USB_ENDPOINT_XFER_BULK ) {
 		return -1;
 	}
 
-	// Check the first endpoint to see if it is IN or OUT
-	if ( data_intf->endpoint[0].bEndpointAddress & 0x80 ) {
-		// This endpoint is IN
+	/* Check the first endpoint to see if it is IN or OUT */
+	if ( data_intf->endpoint[0].bEndpointAddress & USB_DIR_IN ) {
 		ether_dev->data_ep_in = data_intf->endpoint[0].bEndpointAddress & 0x7F;
 	} else {
-		// This endpoint is OUT
-		ether_dev->data_ep_out = data_intf->endpoint[0].bEndpointAddress & 0x7F;
+		ether_dev->data_ep_out = data_intf->endpoint[0].bEndpointAddress;
 		ether_dev->data_ep_out_size = data_intf->endpoint[0].wMaxPacketSize;
 	}
 
-	// Check the second endpoint to see if it is IN or OUT
-	if ( data_intf->endpoint[1].bEndpointAddress & 0x80 ) {
-		// This endpoint is IN
+	/* Check the second endpoint to see if it is IN or OUT */
+	if ( data_intf->endpoint[1].bEndpointAddress & USB_DIR_IN ) {
 		ether_dev->data_ep_in = data_intf->endpoint[1].bEndpointAddress & 0x7F;
 	} else	{
-		// This endpoint is OUT
-		ether_dev->data_ep_out = data_intf->endpoint[1].bEndpointAddress & 0x7F;
+		ether_dev->data_ep_out = data_intf->endpoint[1].bEndpointAddress;
 		ether_dev->data_ep_out_size = data_intf->endpoint[1].wMaxPacketSize;
 	}
-	
-	// Now make sure we got both an IN and an OUT
+
+	/* Now make sure we got both an IN and an OUT */
 	if (ether_dev->data_ep_in && ether_dev->data_ep_out) {
-		// We did get both, we are in good shape...
-		info( "detected BULK OUT packets of size %d", ether_dev->data_ep_out_size );
+		dbg( "detected BULK OUT packets of size %d", ether_dev->data_ep_out_size );
 		return 0;
 	}
 	return -1;
@@ -887,45 +994,45 @@
 		for ( altset_num = 0; altset_num < comm_intf_group->num_altsetting; altset_num++ ) {
 			comm_intf = &( comm_intf_group->altsetting[altset_num] );
 
-			// Is this a communication class of interface of the
-			// ethernet subclass variety.
-			if ( ( comm_intf->bInterfaceClass == 0x02 )
-			   && ( comm_intf->bInterfaceSubClass == 0x06 )
-			   && ( comm_intf->bInterfaceProtocol == 0x00 ) ) {
-				if ( comm_intf->bNumEndpoints == 1 ) {
-					// Good, we found one, we will try this one
-					// Fill in the structure...
-					ether_dev->comm_interface = intf_num;
-					ether_dev->comm_bInterfaceNumber = comm_intf->bInterfaceNumber;
-					ether_dev->comm_interface_altset_num = altset_num;
-					ether_dev->comm_bAlternateSetting = comm_intf->bAlternateSetting;
-
-					// Look for the Ethernet Functional Descriptors
-					rc = find_and_parse_ethernet_class_information( device, ether_dev );
-					if (rc) {
-						// Nope this was no good after all.
-						continue;
-					}
-
-					// Check that we really can talk to the data
-					// interface 
-					// This includes # of endpoints, protocols,
-					// etc.
-					rc = verify_ethernet_data_interface( device, ether_dev );
-					if (rc)	{
-						// We got something we didn't like
-						continue;
-					}
-					// This communication interface seems to give us everything
-					// we require.  We have all the ethernet info we need.
-					// Let's get out of here and go home right now.
-					return 0;
-				} else {
-                                        // bNumEndPoints != 1
-					// We found an interface that had the wrong number of 
-					// endpoints but would have otherwise been okay
-				} // end bNumEndpoints check.
-			} // end interface specifics check.
+			/* Good, we found one, we will try this one */
+			/* Fill in the structure */
+			ether_dev->comm_interface = intf_num;
+			ether_dev->comm_bInterfaceNumber = comm_intf->bInterfaceNumber;
+			ether_dev->comm_interface_altset_num = altset_num;
+			ether_dev->comm_bAlternateSetting = comm_intf->bAlternateSetting;
+
+			// Look for the Ethernet Functional Descriptors
+			rc = find_and_parse_ethernet_class_information( device, ether_dev );
+			if (rc) {
+				// Nope this was no good after all.
+				continue;
+			}
+
+			/* Check that we really can talk to the data interface
+			 * This includes # of endpoints, protocols, etc. */
+			rc = verify_ethernet_data_interface( device, ether_dev );
+			if (rc)	{
+				/* We got something we didn't like */
+				continue;
+			}
+			/* It is a bit ambiguous whether the Ethernet model really requires
+			 * the notification element (usually an interrupt endpoint) or not
+			 * And some products (eg Sharp Zaurus) don't support it, so we
+			 * only use the notification element if present */
+			/* We check for a sane endpoint before using it */
+			if ( (comm_intf->bNumEndpoints == 1) &&
+				(comm_intf->endpoint[0].bEndpointAddress & USB_DIR_IN) &&
+				(comm_intf->endpoint[0].bmAttributes == USB_ENDPOINT_XFER_INT)) {
+					ether_dev->properties |= HAVE_NOTIFICATION_ELEMENT;
+					ether_dev->comm_ep_in = (comm_intf->endpoint[0].bEndpointAddress & 0x7F);
+					dbg("interrupt address: %x",ether_dev->comm_ep_in);
+					ether_dev->intr_interval = (comm_intf->endpoint[0].bInterval);
+					dbg("interrupt interval: %d",ether_dev->intr_interval);
+			}
+			// This communication interface seems to give us everything
+			// we require.  We have all the ethernet info we need.
+
+			return 0;
 		} // end for altset_num
 	} // end for intf_num
 	return -1;
@@ -1005,8 +1112,8 @@
 
 static inline unsigned char hex2dec( unsigned char digit )
 {
-	// Is there a standard way to do this???
-	// I have written this code TOO MANY times.
+	/* Is there a standard way to do this??? */
+	/* I have written this code TOO MANY times. */
 	if ( (digit >= '0') && (digit <= '9') )	{
 		return (digit - '0');
 	}
@@ -1016,9 +1123,14 @@
 	if ( (digit >= 'A') && (digit <= 'F') )	{
 		return (digit - 'A' + 10);
 	}
-	return 0;
+	return 16;
 }
 
+/* CDC Ethernet devices provide the MAC address as a string */
+/* We get an index to the string in the Ethernet functional header */
+/* This routine retrieves the string, sanity checks it, and sets the */
+/* MAC address in the network device */
+/* The encoding is a bit wacky - see CDC Spec Table 41 for details */
 static void set_ethernet_addr( ether_dev_t *ether_dev )
 {
 	unsigned char	mac_addr[6];
@@ -1026,7 +1138,7 @@
 	int 		len;
 	unsigned char	buffer[13];
 
-	// Let's assume we don't get anything...
+	/* Let's assume we don't get anything */
 	mac_addr[0] = 0x00;
 	mac_addr[1] = 0x00;
 	mac_addr[2] = 0x00;
@@ -1034,22 +1146,30 @@
 	mac_addr[4] = 0x00;
 	mac_addr[5] = 0x00;
 
-	// Let's ask the device...
-	len = usb_string(ether_dev->usb, ether_dev->iMACAddress, buffer, 13);
+	/* Let's ask the device */
+	if (0 > (len = usb_string(ether_dev->usb, ether_dev->iMACAddress, buffer, 13))) {
+		err("Attempting to get MAC address failed: %d", -1*len);
+		return;
+	}
 
-	// Sanity check!
+	/* Sanity check */
 	if (len != 12)	{
-		// You gotta love failing sanity checks
+		/* You gotta love failing sanity checks */
 		err("Attempting to get MAC address returned %d bytes", len);
 		return;
 	}
 
-	// Fill in the mac_addr
+	/* Fill in the mac_addr */
 	for (i = 0; i < 6; i++)	{
-		mac_addr[i] = ( hex2dec( buffer[2 * i] ) << 4 ) + hex2dec( buffer[2 * i + 1] );
+		if ((16 == buffer[2 * i]) || (16 == buffer[2 * i + 1])) {
+			err("Bad value in MAC address");
+		}
+		else {
+			mac_addr[i] = ( hex2dec( buffer[2 * i] ) << 4 ) + hex2dec( buffer[2 * i + 1] );
+		}
 	}
 
-	// Now copy it over to the kernel's network driver.
+	/* Now copy it over to our network device structure */
 	memcpy( ether_dev->net->dev_addr, mac_addr, sizeof(mac_addr) );
 }
 
@@ -1067,12 +1187,12 @@
 	unsigned char sern[256];
 	unsigned char *mac_addr;
 
-	// Default empty strings in case we don't find a real one
+	/* Default empty strings in case we don't find a real one */
 	manu[0] = 0x00;
 	prod[0] = 0x00;
 	sern[0] = 0x00;
 
-	// Try to get the device Manufacturer
+	/*  Try to get the device Manufacturer */
 	string_num = ether_dev->usb->descriptor.iManufacturer;
 	if (string_num)	{
 		// Put it into its buffer
@@ -1081,7 +1201,7 @@
 		manu[len] = 0x00;
 	}
 
-	// Try to get the device Product Name
+	/* Try to get the device Product Name */
 	string_num = ether_dev->usb->descriptor.iProduct;
 	if (string_num)	{
 		// Put it into its buffer
@@ -1090,7 +1210,7 @@
 		prod[len] = 0x00;
 	}
 
-	// Try to get the device Serial Number
+	/* Try to get the device Serial Number */
 	string_num = ether_dev->usb->descriptor.iSerialNumber;
 	if (string_num)	{
 		// Put it into its buffer
@@ -1099,14 +1219,20 @@
 		sern[len] = 0x00;
 	}
 
-	// This makes it easier for us to print
+	/* This makes it easier for us to print */
 	mac_addr = ether_dev->net->dev_addr;
 
-	// Now send everything we found to the syslog
-	info( "%s: %s %s %s %02X:%02X:%02X:%02X:%02X:%02X", 
-	      ether_dev->net->name, manu, prod, sern, mac_addr[0], 
-	      mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], 
-	      mac_addr[5] );
+	/* Now send everything we found to the syslog */
+	info( "%s: %s %s %s", ether_dev->net->name, manu, prod, sern);
+	dbg( "%s: %02X:%02X:%02X:%02X:%02X:%02X",
+		ether_dev->net->name,
+		mac_addr[0],
+		mac_addr[1],
+		mac_addr[2],
+		mac_addr[3],
+		mac_addr[4],
+		mac_addr[5] );
+
 }
 
 /* Forward declaration */
@@ -1227,11 +1353,7 @@
 	// Send a message to syslog about what we are handling
 	log_device_info( ether_dev );
 
-	// I claim this interface to be a CDC Ethernet Networking device
-	usb_driver_claim_interface( &CDCEther_driver, 
-	                            &(usb->config[ether_dev->configuration_num].interface[ether_dev->comm_interface]), 
-	                            ether_dev );
-	// I claim this interface to be a CDC Ethernet Networking device
+	/* We need to manually claim the data interface, while the comm interface gets claimed in the return */
 	usb_driver_claim_interface( &CDCEther_driver, 
 	                            &(usb->config[ether_dev->configuration_num].interface[ether_dev->data_interface]), 
 	                            ether_dev );
@@ -1239,11 +1361,8 @@
 	// Does this REALLY do anything???
 	usb_inc_dev_use( usb );
 
-	// TODO - last minute HACK
-	ether_dev->comm_ep_in = 5;
-
 	// Okay, we are finally done...
-	return NULL;
+	return ether_dev;
 }
 
 
@@ -1313,7 +1432,7 @@
 
 int __init CDCEther_init(void)
 {
-	info( "%s", version );
+	dbg( "%s", version );
 	return usb_register( &CDCEther_driver );
 }
 
@@ -1333,11 +1452,10 @@
 MODULE_DESCRIPTION("USB CDC Ethernet driver");
 MODULE_LICENSE("GPL");
 
+MODULE_DEVICE_TABLE (usb, CDCEther_ids);
 MODULE_PARM (multicast_filter_limit, "i");
 MODULE_PARM_DESC (multicast_filter_limit, "CDCEther maximum number of filtered multicast addresses");
 
-MODULE_DEVICE_TABLE (usb, CDCEther_ids);
-
 //////////////////////////////////////////////////////////////////////////////
 // End of file ///////////////////////////////////////////////////////////////
 //////////////////////////////////////////////////////////////////////////////
diff -urN linux-2.4.19-pre5/drivers/usb/CDCEther.h linux-2.4.19-pre6/drivers/usb/CDCEther.h
--- linux-2.4.19-pre5/drivers/usb/CDCEther.h	Sun Sep 23 09:49:00 2001
+++ linux-2.4.19-pre6/drivers/usb/CDCEther.h	Thu Apr  4 22:05:09 2002
@@ -1,4 +1,4 @@
-// Portions of this file taken from 
+// Portions of this file taken from
 // Petko Manolov - Petkan (petkan@dce.bg)
 // from his driver pegasus.h
 
@@ -18,11 +18,12 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  */
 
-
+/* From CDC Spec Table 24 */
 #define CS_INTERFACE			0x24
 
 #define	CDC_ETHER_MAX_MTU		1536
 
+/* These definitions are used with the ether_dev_t flags element */
 #define	CDC_ETHER_PRESENT		0x00000001
 #define	CDC_ETHER_RUNNING		0x00000002
 #define	CDC_ETHER_TX_BUSY		0x00000004
@@ -31,10 +32,10 @@
 
 #define	CDC_ETHER_TX_TIMEOUT	(HZ*10)
 
-#define	TX_UNDERRUN				0x80
+#define	TX_UNDERRUN			0x80
 #define	EXCESSIVE_COL			0x40
-#define	LATE_COL				0x20
-#define	NO_CARRIER				0x10
+#define	LATE_COL			0x20
+#define	NO_CARRIER			0x10
 #define	LOSS_CARRIER			0x08
 #define	JABBER_TIMEOUT			0x04
 
@@ -43,22 +44,13 @@
 #define	CDC_ETHER_REQ_GET_REGS	0xf0
 #define	CDC_ETHER_REQ_SET_REGS	0xf1
 #define	CDC_ETHER_REQ_SET_REG	PIPERIDER_REQ_SET_REGS
-#define	ALIGN(x)		x __attribute__((aligned(L1_CACHE_BYTES)))
-
-#define MODE_FLAG_PROMISCUOUS   (1<<0)
-#define MODE_FLAG_ALL_MULTICAST (1<<1)
-#define MODE_FLAG_DIRECTED      (1<<2)
-#define MODE_FLAG_BROADCAST     (1<<3)
-#define MODE_FLAG_MULTICAST     (1<<4)
-
-#define SET_ETHERNET_MULTICAST_FILTER    0x40
-#define SET_ETHERNET_PACKET_FILTER       0x43
 
 typedef struct _ether_dev_t {
 	struct usb_device	*usb;
 	struct net_device	*net;
 	struct net_device_stats	stats;
 	unsigned		flags;
+	unsigned		properties;
 	int			configuration_num;
 	int			bConfigurationValue;
 	int			comm_interface;
@@ -79,20 +71,44 @@
 	__u8			iMACAddress;
 	__u32			bmEthernetStatistics;
 	__u16			wMaxSegmentSize;
-	__u16                   mode_flags;
 	__u16			wNumberMCFilters;
 	__u8			bNumberPowerFilters;
+	__u16			mode_flags;
 	int			intr_interval;
-	struct urb		rx_urb, tx_urb, intr_urb;
-	unsigned char		ALIGN(rx_buff[CDC_ETHER_MAX_MTU]);
-	unsigned char		ALIGN(tx_buff[CDC_ETHER_MAX_MTU]);
-	unsigned char		ALIGN(intr_buff[8]);
+	devrequest		ctrl_dr;
+	struct urb		rx_urb, tx_urb, intr_urb, ctrl_urb;
+	unsigned char		rx_buff[CDC_ETHER_MAX_MTU] __attribute__((aligned(L1_CACHE_BYTES)));
+	unsigned char		tx_buff[CDC_ETHER_MAX_MTU] __attribute__((aligned(L1_CACHE_BYTES)));
+	unsigned char		intr_buff[8] __attribute__((aligned(L1_CACHE_BYTES))) ;
 } ether_dev_t;
 
+/* These definitions used in the Ethernet Packet Filtering requests */
+/* See CDC Spec Table 62 */
+#define MODE_FLAG_PROMISCUOUS   (1<<0)
+#define MODE_FLAG_ALL_MULTICAST (1<<1)
+#define MODE_FLAG_DIRECTED      (1<<2)
+#define MODE_FLAG_BROADCAST     (1<<3)
+#define MODE_FLAG_MULTICAST     (1<<4)
+
+/* CDC Spec class requests - CDC Spec Table 46 */
+#define SET_ETHERNET_MULTICAST_FILTER    0x40
+#define SET_ETHERNET_PACKET_FILTER       0x43
+
+
+/* These definitions are used with the ether_dev_t properties field */
+#define HAVE_NOTIFICATION_ELEMENT	0x0001
+#define PERFECT_FILTERING		0x0002
+#define NO_SET_MULTICAST		0x0004
+
+/* These definitions are used in the requirements parser */
 #define REQ_HDR_FUNC_DESCR	0x0001
 #define REQ_UNION_FUNC_DESCR	0x0002
 #define REQ_ETH_FUNC_DESCR	0x0004
-#define REQUIREMENTS_TOTAL	0x0007
+#define REQUIREMENTS_TOTAL	REQ_ETH_FUNC_DESCR | REQ_UNION_FUNC_DESCR | REQ_HDR_FUNC_DESCR
 
+/* Some useful lengths */
+#define HEADER_FUNC_DESC_LEN	0x5
+#define UNION_FUNC_DESC_LEN	0x5
+#define ETHERNET_FUNC_DESC_LEN	0xD /* 13 for all you decimal weenies */
 
 
diff -urN linux-2.4.19-pre5/drivers/usb/Config.in linux-2.4.19-pre6/drivers/usb/Config.in
--- linux-2.4.19-pre5/drivers/usb/Config.in	Thu Apr  4 22:04:24 2002
+++ linux-2.4.19-pre6/drivers/usb/Config.in	Thu Apr  4 22:05:09 2002
@@ -49,17 +49,17 @@
    dep_tristate '  USB Printer support' CONFIG_USB_PRINTER $CONFIG_USB
 
    comment 'USB Human Interface Devices (HID)'
+   dep_tristate '  USB Human Interface Device (full HID) support' CONFIG_USB_HID $CONFIG_USB
    if [ "$CONFIG_INPUT" = "n" ]; then
-      comment '  Input core support is needed for USB HID'
-   else
-      dep_tristate '  USB Human Interface Device (full HID) support' CONFIG_USB_HID $CONFIG_USB $CONFIG_INPUT
-         dep_mbool '    /dev/hiddev raw HID device support (EXPERIMENTAL)' CONFIG_USB_HIDDEV $CONFIG_USB_HID
-      if [ "$CONFIG_USB_HID" != "y" ]; then
-         dep_tristate '  USB HIDBP Keyboard (basic) support' CONFIG_USB_KBD $CONFIG_USB $CONFIG_INPUT
-         dep_tristate '  USB HIDBP Mouse (basic) support' CONFIG_USB_MOUSE $CONFIG_USB $CONFIG_INPUT
-      fi
-      dep_tristate '  Wacom Intuos/Graphire tablet support' CONFIG_USB_WACOM $CONFIG_USB $CONFIG_INPUT
+      comment '    Input core support is needed for USB HID input layer or HIDBP support'
+   fi
+      dep_mbool '    HID input layer support' CONFIG_USB_HIDINPUT $CONFIG_INPUT $CONFIG_USB_HID
+      dep_mbool '    /dev/hiddev raw HID device support' CONFIG_USB_HIDDEV $CONFIG_USB_HID
+   if [ "$CONFIG_USB_HID" != "y" ]; then
+      dep_tristate '  USB HIDBP Keyboard (basic) support' CONFIG_USB_KBD $CONFIG_USB $CONFIG_INPUT
+      dep_tristate '  USB HIDBP Mouse (basic) support' CONFIG_USB_MOUSE $CONFIG_USB $CONFIG_INPUT
    fi
+   dep_tristate '  Wacom Intuos/Graphire tablet support' CONFIG_USB_WACOM $CONFIG_USB $CONFIG_INPUT
 
    comment 'USB Imaging devices'
    dep_tristate '  USB Kodak DC-2xx Camera support' CONFIG_USB_DC2XX $CONFIG_USB
@@ -87,6 +87,7 @@
       comment '  Networking support is needed for USB Networking device support'
    else
       dep_tristate '  USB Pegasus/Pegasus-II based ethernet device support (EXPERIMENTAL)' CONFIG_USB_PEGASUS $CONFIG_USB $CONFIG_NET $CONFIG_EXPERIMENTAL
+      dep_tristate '  USB Realtek RTL8150 based ethernet device support (EXPERIMENTAL)' CONFIG_USB_RTL8150 $CONFIG_USB $CONFIG_NET $CONFIG_EXPERIMENTAL
       dep_tristate '  USB KLSI KL5USB101-based ethernet device support (EXPERIMENTAL)' CONFIG_USB_KAWETH $CONFIG_USB $CONFIG_NET $CONFIG_EXPERIMENTAL
       dep_tristate '  USB CATC NetMate-based Ethernet device support (EXPERIMENTAL)' CONFIG_USB_CATC $CONFIG_USB $CONFIG_NET $CONFIG_EXPERIMENTAL
       dep_tristate '  USB Communication Class Ethernet device support (EXPERIMENTAL)' CONFIG_USB_CDCETHER $CONFIG_USB $CONFIG_NET $CONFIG_EXPERIMENTAL
diff -urN linux-2.4.19-pre5/drivers/usb/Makefile linux-2.4.19-pre6/drivers/usb/Makefile
--- linux-2.4.19-pre5/drivers/usb/Makefile	Thu Apr  4 22:04:24 2002
+++ linux-2.4.19-pre6/drivers/usb/Makefile	Thu Apr  4 22:05:09 2002
@@ -16,7 +16,7 @@
 
 list-multi		:= usbcore.o hid.o pwc.o
 usbcore-objs		:= usb.o usb-debug.o hub.o
-hid-objs		:= hid-core.o hid-input.o
+hid-objs		:= hid-core.o
 pwc-objs		:= pwc-if.o pwc-misc.o pwc-ctrl.o pwc-uncompress.o
 
 
@@ -30,6 +30,10 @@
 	hid-objs	+= hiddev.o
 endif
 
+ifeq ($(CONFIG_USB_HIDINPUT),y)
+	hid-objs	+= hid-input.o
+endif
+
 # Object file lists.
 
 obj-y	:=
@@ -77,6 +81,7 @@
 obj-$(CONFIG_USB_SE401)		+= se401.o
 obj-$(CONFIG_USB_STV680)	+= stv680.o
 obj-$(CONFIG_USB_PEGASUS)	+= pegasus.o
+obj-$(CONFIG_USB_RTL8150)	+= rtl8150.o
 obj-$(CONFIG_USB_CATC)		+= catc.o
 obj-$(CONFIG_USB_KAWETH)        += kaweth.o
 obj-$(CONFIG_USB_CDCETHER)	+= CDCEther.o
diff -urN linux-2.4.19-pre5/drivers/usb/audio.c linux-2.4.19-pre6/drivers/usb/audio.c
--- linux-2.4.19-pre5/drivers/usb/audio.c	Mon Feb 25 11:38:07 2002
+++ linux-2.4.19-pre6/drivers/usb/audio.c	Thu Apr  4 22:05:09 2002
@@ -2536,7 +2536,7 @@
 		if (as->usbin.dma.mapped)
 			as->usbin.dma.count &= as->usbin.dma.fragsize-1;
 		spin_unlock_irqrestore(&as->lock, flags);
-		return copy_to_user((void *)arg, &cinfo, sizeof(cinfo));
+		return copy_to_user((void *)arg, &cinfo, sizeof(cinfo)) ? -EFAULT : 0;
 
 	case SNDCTL_DSP_GETOPTR:
 		if (!(file->f_mode & FMODE_WRITE))
@@ -2548,7 +2548,7 @@
 		if (as->usbout.dma.mapped)
 			as->usbout.dma.count &= as->usbout.dma.fragsize-1;
 		spin_unlock_irqrestore(&as->lock, flags);
-		return copy_to_user((void *)arg, &cinfo, sizeof(cinfo));
+		return copy_to_user((void *)arg, &cinfo, sizeof(cinfo)) ? -EFAULT : 0;
 
        case SNDCTL_DSP_GETBLKSIZE:
 		if (file->f_mode & FMODE_WRITE) {
diff -urN linux-2.4.19-pre5/drivers/usb/catc.c linux-2.4.19-pre6/drivers/usb/catc.c
--- linux-2.4.19-pre5/drivers/usb/catc.c	Thu Apr  4 22:04:24 2002
+++ linux-2.4.19-pre6/drivers/usb/catc.c	Thu Apr  4 22:05:09 2002
@@ -409,7 +409,7 @@
 {
 	struct catc *catc = urb->context;
 	struct ctrl_queue *q;
-	long flags;
+	unsigned long flags;
 
 	if (urb->status)
 		dbg("ctrl_done, status %d, len %d.", urb->status, urb->actual_length);
@@ -443,7 +443,7 @@
 {
 	struct ctrl_queue *q;
 	int retval = 0;
-	long flags;
+	unsigned long flags;
 
 	spin_lock_irqsave(&catc->ctrl_lock, flags);
 	
diff -urN linux-2.4.19-pre5/drivers/usb/hcd/ehci-hcd.c linux-2.4.19-pre6/drivers/usb/hcd/ehci-hcd.c
--- linux-2.4.19-pre5/drivers/usb/hcd/ehci-hcd.c	Thu Apr  4 22:04:24 2002
+++ linux-2.4.19-pre6/drivers/usb/hcd/ehci-hcd.c	Thu Apr  4 22:05:09 2002
@@ -747,8 +747,8 @@
 {
 	dbg (DRIVER_INFO);
 	dbg ("block sizes: qh %d qtd %d itd %d sitd %d",
-		sizeof (struct ehci_qh), sizeof (struct ehci_qtd),
-		sizeof (struct ehci_itd), sizeof (struct ehci_sitd));
+		(int) sizeof (struct ehci_qh), (int) sizeof (struct ehci_qtd),
+		(int) sizeof (struct ehci_itd), (int) sizeof (struct ehci_sitd));
 
 	return pci_module_init (&ehci_pci_driver);
 }
diff -urN linux-2.4.19-pre5/drivers/usb/hcd.c linux-2.4.19-pre6/drivers/usb/hcd.c
--- linux-2.4.19-pre5/drivers/usb/hcd.c	Thu Apr  4 22:04:24 2002
+++ linux-2.4.19-pre6/drivers/usb/hcd.c	Thu Apr  4 22:05:09 2002
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001 by David Brownell
+ * Copyright (c) 2001-2002 by David Brownell
  * 
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the
@@ -31,11 +31,9 @@
 #include <linux/timer.h>
 #include <linux/list.h>
 #include <linux/interrupt.h>
+#include <linux/completion.h>
 #include <linux/uts.h>			/* for UTS_SYSNAME */
 
-#ifndef CONFIG_USB_DEBUG
-	#define CONFIG_USB_DEBUG	/* this is experimental! */
-#endif
 
 #ifdef CONFIG_USB_DEBUG
 	#define DEBUG
@@ -104,6 +102,9 @@
 
 /*-------------------------------------------------------------------------*/
 
+#define KERNEL_REL	((LINUX_VERSION_CODE >> 16) & 0x0ff)
+#define KERNEL_VER	((LINUX_VERSION_CODE >> 8) & 0x0ff)
+
 /* usb 2.0 root hub device descriptor */
 static const u8 usb2_rh_dev_descriptor [18] = {
 	0x12,       /*  __u8  bLength; */
@@ -117,7 +118,7 @@
 
 	0x00, 0x00, /*  __u16 idVendor; */
  	0x00, 0x00, /*  __u16 idProduct; */
- 	0x40, 0x02, /*  __u16 bcdDevice; (v2.4) */
+	KERNEL_VER, KERNEL_REL, /*  __u16 bcdDevice */
 
 	0x03,       /*  __u8  iManufacturer; */
 	0x02,       /*  __u8  iProduct; */
@@ -140,7 +141,7 @@
 
 	0x00, 0x00, /*  __u16 idVendor; */
  	0x00, 0x00, /*  __u16 idProduct; */
- 	0x40, 0x02, /*  __u16 bcdDevice; (v2.4) */
+	KERNEL_VER, KERNEL_REL, /*  __u16 bcdDevice */
 
 	0x03,       /*  __u8  iManufacturer; */
 	0x02,       /*  __u8  iProduct; */
@@ -151,9 +152,56 @@
 
 /*-------------------------------------------------------------------------*/
 
-/* Configuration descriptor for all our root hubs */
+/* Configuration descriptors for our root hubs */
+
+static const u8 fs_rh_config_descriptor [] = {
+
+	/* one configuration */
+	0x09,       /*  __u8  bLength; */
+	0x02,       /*  __u8  bDescriptorType; Configuration */
+	0x19, 0x00, /*  __u16 wTotalLength; */
+	0x01,       /*  __u8  bNumInterfaces; (1) */
+	0x01,       /*  __u8  bConfigurationValue; */
+	0x00,       /*  __u8  iConfiguration; */
+	0x40,       /*  __u8  bmAttributes; 
+				 Bit 7: Bus-powered,
+				     6: Self-powered,
+				     5 Remote-wakwup,
+				     4..0: resvd */
+	0x00,       /*  __u8  MaxPower; */
+      
+	/* USB 1.1:
+	 * USB 2.0, single TT organization (mandatory):
+	 *	one interface, protocol 0
+	 *
+	 * USB 2.0, multiple TT organization (optional):
+	 *	two interfaces, protocols 1 (like single TT)
+	 *	and 2 (multiple TT mode) ... config is
+	 *	sometimes settable
+	 *	NOT IMPLEMENTED
+	 */
+
+	/* one interface */
+	0x09,       /*  __u8  if_bLength; */
+	0x04,       /*  __u8  if_bDescriptorType; Interface */
+	0x00,       /*  __u8  if_bInterfaceNumber; */
+	0x00,       /*  __u8  if_bAlternateSetting; */
+	0x01,       /*  __u8  if_bNumEndpoints; */
+	0x09,       /*  __u8  if_bInterfaceClass; HUB_CLASSCODE */
+	0x00,       /*  __u8  if_bInterfaceSubClass; */
+	0x00,       /*  __u8  if_bInterfaceProtocol; [usb1.1 or single tt] */
+	0x00,       /*  __u8  if_iInterface; */
+     
+	/* one endpoint (status change endpoint) */
+	0x07,       /*  __u8  ep_bLength; */
+	0x05,       /*  __u8  ep_bDescriptorType; Endpoint */
+	0x81,       /*  __u8  ep_bEndpointAddress; IN Endpoint 1 */
+ 	0x03,       /*  __u8  ep_bmAttributes; Interrupt */
+ 	0x02, 0x00, /*  __u16 ep_wMaxPacketSize; 1 + (MAX_ROOT_PORTS / 8) */
+	0xff        /*  __u8  ep_bInterval; (255ms -- usb 2.0 spec) */
+};
 
-static const u8 rh_config_descriptor [] = {
+static const u8 hs_rh_config_descriptor [] = {
 
 	/* one configuration */
 	0x09,       /*  __u8  bLength; */
@@ -197,7 +245,7 @@
 	0x81,       /*  __u8  ep_bEndpointAddress; IN Endpoint 1 */
  	0x03,       /*  __u8  ep_bmAttributes; Interrupt */
  	0x02, 0x00, /*  __u16 ep_wMaxPacketSize; 1 + (MAX_ROOT_PORTS / 8) */
-	0x0c        /*  __u8  ep_bInterval; (12ms -- usb 2.0 spec) */
+	0x0c        /*  __u8  ep_bInterval; (256ms -- usb 2.0 spec) */
 };
 
 /*-------------------------------------------------------------------------*/
@@ -206,12 +254,12 @@
  * helper routine for returning string descriptors in UTF-16LE
  * input can actually be ISO-8859-1; ASCII is its 7-bit subset
  */
-static int ascii2utf (char *ascii, u8 *utf, int utfmax)
+static int ascii2utf (char *s, u8 *utf, int utfmax)
 {
 	int retval;
 
-	for (retval = 0; *ascii && utfmax > 1; utfmax -= 2, retval += 2) {
-		*utf++ = *ascii++ & 0x7f;
+	for (retval = 0; *s && utfmax > 1; utfmax -= 2, retval += 2) {
+		*utf++ = *s++;
 		*utf++ = 0;
 	}
 	return retval;
@@ -230,8 +278,7 @@
  */
 static int rh_string (
 	int		id,
-	struct pci_dev	*pci_desc,
-	char		*type,
+	struct usb_hcd	*hcd,
 	u8		*data,
 	int		len
 ) {
@@ -245,15 +292,16 @@
 
 	// serial number
 	} else if (id == 1) {
-		strcpy (buf, pci_desc->slot_name);
+		strcpy (buf, hcd->bus_name);
 
 	// product description
 	} else if (id == 2) {
-                strcpy (buf, pci_desc->name);
+                strcpy (buf, hcd->product_desc);
 
  	// id 3 == vendor description
 	} else if (id == 3) {
-                sprintf (buf, "%s %s %s", UTS_SYSNAME, UTS_RELEASE, type);
+                sprintf (buf, "%s %s %s", UTS_SYSNAME, UTS_RELEASE,
+			hcd->description);
 
 	// unsupported IDs --> "protocol stall"
 	} else
@@ -315,14 +363,17 @@
 			len = 18;
 			break;
 		case USB_DT_CONFIG << 8:
-			bufp = rh_config_descriptor;
-			len = sizeof rh_config_descriptor;
+			if (hcd->driver->flags & HCD_USB2) {
+				bufp = hs_rh_config_descriptor;
+				len = sizeof hs_rh_config_descriptor;
+			} else {
+				bufp = fs_rh_config_descriptor;
+				len = sizeof fs_rh_config_descriptor;
+			}
 			break;
 		case USB_DT_STRING << 8:
 			urb->actual_length = rh_string (
-				wValue & 0xff,
-				 hcd->pdev,
-				(char *) hcd->description,
+				wValue & 0xff, hcd,
 				ubuf, wLength);
 			break;
 		default:
@@ -412,10 +463,8 @@
 	init_timer (&hcd->rh_timer);
 	hcd->rh_timer.function = rh_report_status;
 	hcd->rh_timer.data = (unsigned long) urb;
-	hcd->rh_timer.expires = jiffies
-		+ (HZ * (urb->interval < 30
-				? 30
-				: urb->interval)) / 1000;
+	/* USB 2.0 spec says 256msec; this is close enough */
+	hcd->rh_timer.expires = jiffies + HZ/4;
 	add_timer (&hcd->rh_timer);
 	return 0;
 }
@@ -521,6 +570,7 @@
  * usb_hcd_pci_probe - initialize PCI-based HCDs
  * @dev: USB Host Controller being probed
  * @id: pci hotplug id connecting controller to HCD framework
+ * Context: !in_interrupt()
  *
  * Allocates basic PCI resources for this USB host controller, and
  * then invokes the start() method for the HCD associated with it
@@ -606,7 +656,7 @@
 			return retval;
 		}
 	}
-	dev->driver_data = hcd;
+	pci_set_drvdata(dev, hcd);
 	hcd->driver = driver;
 	hcd->description = driver->description;
 	hcd->pdev = dev;
@@ -652,6 +702,7 @@
 	}
 	hcd->bus = bus;
 	hcd->bus_name = dev->slot_name;
+	hcd->product_desc = dev->name;
 	bus->hcpriv = (void *) hcd;
 
 	INIT_LIST_HEAD (&hcd->dev_list);
@@ -677,6 +728,7 @@
 /**
  * usb_hcd_pci_remove - shutdown processing for PCI-based HCDs
  * @dev: USB Host Controller being removed
+ * Context: !in_interrupt()
  *
  * Reverses the effect of usb_hcd_pci_probe(), first invoking
  * the HCD's stop() method.  It is always called from a thread
@@ -689,7 +741,7 @@
 	struct usb_hcd		*hcd;
 	struct usb_device	*hub;
 
-	hcd = (struct usb_hcd *) dev->driver_data;
+	hcd = pci_get_drvdata(dev);
 	if (!hcd)
 		return;
 	info ("remove: %s, state %x", hcd->bus_name, hcd->state);
@@ -769,7 +821,7 @@
 	struct usb_hcd		*hcd;
 	int			retval;
 
-	hcd = (struct usb_hcd *) dev->driver_data;
+	hcd = pci_get_drvdata(dev);
 	info ("suspend %s to state %d", hcd->bus_name, state);
 
 	pci_save_state (dev, hcd->pci_state);
@@ -798,7 +850,7 @@
 	struct usb_hcd		*hcd;
 	int			retval;
 
-	hcd = (struct usb_hcd *) dev->driver_data;
+	hcd = pci_get_drvdata(dev);
 	info ("resume %s", hcd->bus_name);
 
 	/* guard against multiple resumes (APM bug?) */
@@ -913,8 +965,29 @@
 
 /*-------------------------------------------------------------------------*/
 
+static void urb_unlink (struct urb *urb)
+{
+	unsigned long		flags;
+	struct usb_device	*dev;
+
+	/* Release any periodic transfer bandwidth */
+	if (urb->bandwidth)
+		usb_release_bandwidth (urb->dev, urb,
+			usb_pipeisoc (urb->pipe));
+
+	/* clear all state linking urb to this dev (and hcd) */
+
+	spin_lock_irqsave (&hcd_data_lock, flags);
+	list_del_init (&urb->urb_list);
+	dev = urb->dev;
+	urb->dev = NULL;
+	usb_dec_dev_use (dev);
+	spin_unlock_irqrestore (&hcd_data_lock, flags);
+}
+
+
 /* may be called in any context with a valid urb->dev usecount */
-/* caller surrenders "ownership" of urb (and chain at urb->next).  */
+/* caller surrenders "ownership" of urb */
 
 static int hcd_submit_urb (struct urb *urb)
 {
@@ -922,7 +995,7 @@
 	struct usb_hcd		*hcd;
 	struct hcd_dev		*dev;
 	unsigned long		flags;
-	int			pipe;
+	int			pipe, temp, max;
 	int			mem_flags;
 
 	if (!urb || urb->hcpriv || !urb->complete)
@@ -930,6 +1003,7 @@
 
 	urb->status = -EINPROGRESS;
 	urb->actual_length = 0;
+	urb->bandwidth = 0;
 	INIT_LIST_HEAD (&urb->urb_list);
 
 	if (!urb->dev || !urb->dev->bus || urb->dev->devnum <= 0)
@@ -943,16 +1017,70 @@
 	if (hcd->state == USB_STATE_QUIESCING || !HCD_IS_RUNNING (hcd->state))
 		return -ESHUTDOWN;
 	pipe = urb->pipe;
+	temp = usb_pipetype (urb->pipe);
 	if (usb_endpoint_halted (urb->dev, usb_pipeendpoint (pipe),
 			usb_pipeout (pipe)))
 		return -EPIPE;
 
-	// FIXME paging/swapping requests over USB should not use GFP_KERNEL
-	// and might even need to use GFP_NOIO ... that flag actually needs
-	// to be passed from the higher level.
+	/* NOTE: 2.5 passes this value explicitly in submit() */
 	mem_flags = in_interrupt () ? GFP_ATOMIC : GFP_KERNEL;
 
+	/* FIXME there should be a sharable lock protecting us against
+	 * config/altsetting changes and disconnects, kicking in here.
+	 */
+
+	/* Sanity check, so HCDs can rely on clean data */
+	max = usb_maxpacket (urb->dev, pipe, usb_pipeout (pipe));
+	if (max <= 0) {
+		err ("bogus endpoint (bad maxpacket)");
+		return -EINVAL;
+	}
+
+	/* "high bandwidth" mode, 1-3 packets/uframe? */
+	if (urb->dev->speed == USB_SPEED_HIGH) {
+		int	mult;
+		switch (temp) {
+		case PIPE_ISOCHRONOUS:
+		case PIPE_INTERRUPT:
+			mult = 1 + ((max >> 11) & 0x03);
+			max &= 0x03ff;
+			max *= mult;
+		}
+	}
+
+	/* periodic transfers limit size per frame/uframe */
+	switch (temp) {
+	case PIPE_ISOCHRONOUS: {
+		int	n, len;
+
+		if (urb->number_of_packets <= 0)		    
+			return -EINVAL;
+		for (n = 0; n < urb->number_of_packets; n++) {
+			len = urb->iso_frame_desc [n].length;
+			if (len < 0 || len > max) 
+				return -EINVAL;
+		}
+
+		}
+		break;
+	case PIPE_INTERRUPT:
+		if (urb->transfer_buffer_length > max)
+			return -EINVAL;
+	}
+
+	/* the I/O buffer must usually be mapped/unmapped */
+	if (urb->transfer_buffer_length < 0)
+		return -EINVAL;
+
+	if (urb->next) {
+		warn ("use explicit queuing not urb->next");
+		return -EINVAL;
+	}
+
 #ifdef DEBUG
+	/* stuff that drivers shouldn't do, but which shouldn't
+	 * cause problems in HCDs if they get it wrong.
+	 */
 	{
 	unsigned int	orig_flags = urb->transfer_flags;
 	unsigned int	allowed;
@@ -960,7 +1088,7 @@
 	/* enforce simple/standard policy */
 	allowed = USB_ASYNC_UNLINK;	// affects later unlinks
 	allowed |= USB_NO_FSBR;		// only affects UHCI
-	switch (usb_pipetype (pipe)) {
+	switch (temp) {
 	case PIPE_CONTROL:
 		allowed |= USB_DISABLE_SPD;
 		break;
@@ -977,17 +1105,61 @@
 	}
 	urb->transfer_flags &= allowed;
 
-	/* warn if submitter gave bogus flags */
-	if (urb->transfer_flags != orig_flags)
-		warn ("BOGUS urb flags, %x --> %x",
+	/* fail if submitter gave bogus flags */
+	if (urb->transfer_flags != orig_flags) {
+		err ("BOGUS urb flags, %x --> %x",
 			orig_flags, urb->transfer_flags);
+		return -EINVAL;
+	}
 	}
 #endif
 	/*
-	 * FIXME:  alloc periodic bandwidth here, for interrupt and iso?
-	 * Need to look at the ring submit mechanism for iso tds ... they
-	 * aren't actually "periodic" in 2.4 kernels.
+	 * Force periodic transfer intervals to be legal values that are
+	 * a power of two (so HCDs don't need to).
 	 *
+	 * FIXME want bus->{intr,iso}_sched_horizon values here.  Each HC
+	 * supports different values... this uses EHCI/UHCI defaults (and
+	 * EHCI can use smaller non-default values).
+	 */
+	switch (temp) {
+	case PIPE_ISOCHRONOUS:
+	case PIPE_INTERRUPT:
+		/* too small? */
+		if (urb->interval <= 0)
+			return -EINVAL;
+		/* too big? */
+		switch (urb->dev->speed) {
+		case USB_SPEED_HIGH:	/* units are microframes */
+			// NOTE usb handles 2^15
+			if (urb->interval > (1024 * 8))
+				urb->interval = 1024 * 8;
+			temp = 1024 * 8;
+			break;
+		case USB_SPEED_FULL:	/* units are frames/msec */
+		case USB_SPEED_LOW:
+			if (temp == PIPE_INTERRUPT) {
+				if (urb->interval > 255)
+					return -EINVAL;
+				// NOTE ohci only handles up to 32
+				temp = 128;
+			} else {
+				if (urb->interval > 1024)
+					urb->interval = 1024;
+				// NOTE usb and ohci handle up to 2^15
+				temp = 1024;
+			}
+			break;
+		default:
+			return -EINVAL;
+		}
+		/* power of two? */
+		while (temp > urb->interval)
+			temp >>= 1;
+		urb->interval = temp;
+	}
+
+
+	/*
 	 * FIXME:  make urb timeouts be generic, keeping the HCD cores
 	 * as simple as possible.
 	 */
@@ -1014,20 +1186,20 @@
 		status = -ESHUTDOWN;
 	}
 	spin_unlock_irqrestore (&hcd_data_lock, flags);
+	if (status)
+		return status;
 
-	if (!status) {
-		if (urb->dev == hcd->bus->root_hub)
-			status = rh_urb_enqueue (hcd, urb);
-		else
-			status = hcd->driver->urb_enqueue (hcd, urb, mem_flags);
-	}
-	if (status) {
-		if (urb->dev) {
-			urb->status = status;
-			usb_hcd_giveback_urb (hcd, urb);
-		}
-	}
-	return 0;
+	if (urb->dev == hcd->bus->root_hub)
+		status = rh_urb_enqueue (hcd, urb);
+	else
+		status = hcd->driver->urb_enqueue (hcd, urb, mem_flags);
+	/* urb->dev got nulled if hcd called giveback for us
+	 * NOTE: ref to urb->dev is a race without (2.5) refcounting,
+	 * unless driver only returns status when it didn't giveback 
+	 */
+	if (status && urb->dev)
+		urb_unlink (urb);
+	return status;
 }
 
 /*-------------------------------------------------------------------------*/
@@ -1043,7 +1215,7 @@
 
 struct completion_splice {		// modified urb context:
 	/* did we complete? */
-	int			done;
+	struct completion	done;
 
 	/* original urb data */
 	void			(*complete)(struct urb *);
@@ -1061,7 +1233,8 @@
 	urb->context = splice->context;
 	urb->complete (urb);
 
-	splice->done = 1;
+	/* then let the synchronous unlink call complete */
+	complete (&splice->done);
 }
 
 /*
@@ -1081,20 +1254,20 @@
 	if (!urb)
 		return -EINVAL;
 
-	// FIXME:  add some explicit records to flag the
-	// state where the URB is "in periodic completion".
-	// Workaround is for driver to set the urb status
-	// to "-EINPROGRESS", so it can get through here
-	// and unlink from the completion handler.
-
 	/*
 	 * we contend for urb->status with the hcd core,
 	 * which changes it while returning the urb.
+	 *
+	 * Caller guaranteed that the urb pointer hasn't been freed, and
+	 * that it was submitted.  But as a rule it can't know whether or
+	 * not it's already been unlinked ... so we respect the reversed
+	 * lock sequence needed for the usb_hcd_giveback_urb() code paths
+	 * (urb lock, then hcd_data_lock) in case some other CPU is now
+	 * unlinking it.
 	 */
 	spin_lock_irqsave (&urb->lock, flags);
-	if (!urb->hcpriv
-			|| urb->status != -EINPROGRESS
-			|| urb->transfer_flags & USB_TIMEOUT_KILLED) {
+	spin_lock (&hcd_data_lock);
+	if (!urb->hcpriv || urb->transfer_flags & USB_TIMEOUT_KILLED) {
 		retval = -EINVAL;
 		goto done;
 	}
@@ -1103,6 +1276,8 @@
 		retval = -ENODEV;
 		goto done;
 	}
+
+	/* giveback clears dev; non-null means it's linked at this level */
 	dev = urb->dev->hcpriv;
 	hcd = urb->dev->bus->hcpriv;
 	if (!dev || !hcd) {
@@ -1110,6 +1285,27 @@
 		goto done;
 	}
 
+	/* For non-periodic transfers, any status except -EINPROGRESS means
+	 * the HCD has already started to unlink this URB from the hardware.
+	 * In that case, there's no more work to do.
+	 *
+	 * For periodic transfers, this is the only way to trigger unlinking
+	 * from the hardware.  Since we (currently) overload urb->status to
+	 * tell the driver to unlink, error status might get clobbered ...
+	 * unless that transfer hasn't yet restarted.  One such case is when
+	 * the URB gets unlinked from its completion handler.
+	 *
+	 * FIXME use an URB_UNLINKED flag to match URB_TIMEOUT_KILLED
+	 */
+	switch (usb_pipetype (urb->pipe)) {
+	case PIPE_CONTROL:
+	case PIPE_BULK:
+		if (urb->status != -EINPROGRESS) {
+			retval = -EINVAL;
+			goto done;
+		}
+	}
+
 	/* maybe set up to block on completion notification */
 	if ((urb->transfer_flags & USB_TIMEOUT_KILLED))
 		urb->status = -ETIMEDOUT;
@@ -1120,7 +1316,7 @@
 			goto done;
 		}
 		/* synchronous unlink: block till we see the completion */
-		splice.done = 0;
+		init_completion (&splice.done);
 		splice.complete = urb->complete;
 		splice.context = urb->context;
 		urb->complete = unlink_complete;
@@ -1130,6 +1326,7 @@
 		/* asynchronous unlink */
 		urb->status = -ECONNRESET;
 	}
+	spin_unlock (&hcd_data_lock);
 	spin_unlock_irqrestore (&urb->lock, flags);
 
 	if (urb == (struct urb *) hcd->rh_timer.data) {
@@ -1145,17 +1342,15 @@
 	if (!(urb->transfer_flags & (USB_ASYNC_UNLINK|USB_TIMEOUT_KILLED))
 			&& HCD_IS_RUNNING (hcd->state)
 			&& !retval) {
-		while (!splice.done) {
-			set_current_state (TASK_UNINTERRUPTIBLE);
-			schedule_timeout ((2/*msec*/ * HZ) / 1000);
-			dbg ("%s: wait for giveback urb %p",
-				hcd->bus_name, urb);
-		}
+		dbg ("%s: wait for giveback urb %p",
+			hcd->bus_name, urb);
+		wait_for_completion (&splice.done);
 	} else if ((urb->transfer_flags & USB_ASYNC_UNLINK) && retval == 0) {
 		return -EINPROGRESS;
 	}
 	goto bye;
 done:
+	spin_unlock (&hcd_data_lock);
 	spin_unlock_irqrestore (&urb->lock, flags);
 bye:
 	if (retval)
@@ -1223,6 +1418,9 @@
 	struct usb_hcd		*hcd = __hcd;
 	int			start = hcd->state;
 
+	if (unlikely (hcd->state == USB_STATE_HALT))	/* irq sharing? */
+		return;
+
 	hcd->driver->irq (hcd);
 	if (hcd->state != start && hcd->state == USB_STATE_HALT)
 		hc_died (hcd);
@@ -1234,6 +1432,7 @@
  * usb_hcd_giveback_urb - return URB from HCD to device driver
  * @hcd: host controller returning the URB
  * @urb: urb being returned to the USB device driver.
+ * Context: in_interrupt()
  *
  * This hands the URB from HCD to its USB device driver, using its
  * completion function.  The HCD has freed all per-urb resources
@@ -1246,34 +1445,13 @@
  * and will be reissued.  They should just call their completion handlers
  * until the urb is returned to the device driver by unlinking.
  *
- * In common cases, urb->next will be submitted before the completion
- * function gets called.  That's not done if the URB includes error
- * status (including unlinking).
+ * NOTE that no urb->next processing is done, even for isochronous URBs.
+ * ISO streaming functionality can be achieved by having completion handlers
+ * re-queue URBs.  Such explicit queuing doesn't discard error reports.
  */
 void usb_hcd_giveback_urb (struct usb_hcd *hcd, struct urb *urb)
 {
-	unsigned long		flags;
-	struct usb_device	*dev;
-
-	/* Release periodic transfer bandwidth */
-	if (urb->bandwidth) {
-		switch (usb_pipetype (urb->pipe)) {
-		case PIPE_INTERRUPT:
-			usb_release_bandwidth (urb->dev, urb, 0);
-			break;
-		case PIPE_ISOCHRONOUS:
-			usb_release_bandwidth (urb->dev, urb, 1);
-			break;
-		}
-	}
-
-	/* clear all state linking urb to this dev (and hcd) */
-
-	spin_lock_irqsave (&hcd_data_lock, flags);
-	list_del_init (&urb->urb_list);
-	dev = urb->dev;
-	urb->dev = NULL;
-	spin_unlock_irqrestore (&hcd_data_lock, flags);
+	urb_unlink (urb);
 
 	// NOTE:  a generic device/urb monitoring hook would go here.
 	// hcd_monitor_hook(MONITOR_URB_FINISH, urb, dev)
@@ -1282,26 +1460,10 @@
 	// hcd_monitor_hook(MONITOR_URB_UPDATE, urb, dev)
 
 	if (urb->status)
-		dbg ("giveback urb %p status %d", urb, urb->status);
-
-	/* if no error, make sure urb->next progresses */
-	else if (urb->next) {
-		int 	status;
-
-		status = usb_submit_urb (urb->next);
-		if (status) {
-			dbg ("urb %p chain fail, %d", urb->next, status);
-			urb->next->status = -ENOTCONN;
-		}
-
-		/* HCDs never modify the urb->next chain, and only use it here,
-		 * so that if urb->complete sees an URB there with -ENOTCONN,
-		 * it knows the driver chained it but it couldn't be submitted.
-		 */
-	}
+		dbg ("giveback urb %p status %d len %d",
+			urb, urb->status, urb->actual_length);
 
 	/* pass ownership to the completion handler */
-	usb_dec_dev_use (dev);
 	urb->complete (urb);
 }
 EXPORT_SYMBOL (usb_hcd_giveback_urb);
diff -urN linux-2.4.19-pre5/drivers/usb/hcd.h linux-2.4.19-pre6/drivers/usb/hcd.h
--- linux-2.4.19-pre5/drivers/usb/hcd.h	Thu Apr  4 22:04:24 2002
+++ linux-2.4.19-pre6/drivers/usb/hcd.h	Thu Apr  4 22:05:09 2002
@@ -37,7 +37,7 @@
 	struct list_head	hcd_list;
 
 	const char		*bus_name;
-
+	const char		*product_desc;
 	const char		*description;	/* "ehci-hcd" etc */
 
 	struct timer_list	rh_timer;	/* drives root hub */
diff -urN linux-2.4.19-pre5/drivers/usb/hid-core.c linux-2.4.19-pre6/drivers/usb/hid-core.c
--- linux-2.4.19-pre5/drivers/usb/hid-core.c	Thu Apr  4 22:04:24 2002
+++ linux-2.4.19-pre6/drivers/usb/hid-core.c	Thu Apr  4 22:05:09 2002
@@ -47,9 +47,7 @@
 #include <linux/usb.h>
 
 #include "hid.h"
-#ifdef CONFIG_USB_HIDDEV
 #include <linux/hiddev.h>
-#endif
 
 /*
  * Version Information
@@ -204,17 +202,13 @@
 		return -1;
 	}
 
-	if (HID_MAIN_ITEM_VARIABLE & ~flags) { /* ARRAY */
-		if (parser->global.logical_maximum <= parser->global.logical_minimum) {
-			dbg("logical range invalid %d %d", parser->global.logical_minimum, parser->global.logical_maximum);
-			return -1;
-		}
-		usages = parser->local.usage_index;
-		/* Hint: we can assume usages < MAX_USAGE here */
-	} else { /* VARIABLE */
-		usages = parser->global.report_count;
+	if (parser->global.logical_maximum <= parser->global.logical_minimum) {
+		dbg("logical range invalid %d %d", parser->global.logical_minimum, parser->global.logical_maximum);
+		return -1;
 	}
 
+	usages = parser->local.usage_index;
+
 	offset = report->size;
 	report->size += parser->global.report_size * parser->global.report_count;
 
@@ -310,7 +304,10 @@
 			return 0;
 
 		case HID_GLOBAL_ITEM_TAG_LOGICAL_MAXIMUM:
-			parser->global.logical_maximum = item_sdata(item);
+			if (parser->global.logical_minimum < 0)
+				parser->global.logical_maximum = item_sdata(item);
+			else
+				parser->global.logical_maximum = item_udata(item);
 			return 0;
 
 		case HID_GLOBAL_ITEM_TAG_PHYSICAL_MINIMUM:
@@ -318,7 +315,10 @@
 			return 0;
 
 		case HID_GLOBAL_ITEM_TAG_PHYSICAL_MAXIMUM:
-			parser->global.physical_maximum = item_sdata(item);
+			if (parser->global.physical_minimum < 0)
+				parser->global.physical_maximum = item_sdata(item);
+			else
+				parser->global.physical_maximum = item_udata(item);
 			return 0;
 
 		case HID_GLOBAL_ITEM_TAG_UNIT_EXPONENT:
@@ -735,10 +735,8 @@
 	hid_dump_input(usage, value);
 	if (hid->claimed & HID_CLAIMED_INPUT)
 		hidinput_hid_event(hid, field, usage, value);
-#ifdef CONFIG_USB_HIDDEV
 	if (hid->claimed & HID_CLAIMED_HIDDEV)
 		hiddev_hid_event(hid, usage->hid, value);
-#endif
 }
 
 
@@ -1239,10 +1237,8 @@
 
 	if (!hidinput_connect(hid))
 		hid->claimed |= HID_CLAIMED_INPUT;
-#ifdef CONFIG_USB_HIDDEV
 	if (!hiddev_connect(hid))
 		hid->claimed |= HID_CLAIMED_HIDDEV;
-#endif
 	printk(KERN_INFO);
 
 	if (hid->claimed & HID_CLAIMED_INPUT)
@@ -1272,13 +1268,10 @@
 
 	dbg("cleanup called");
 	usb_unlink_urb(&hid->urb);
-
 	if (hid->claimed & HID_CLAIMED_INPUT)
 		hidinput_disconnect(hid);
-#ifdef CONFIG_USB_HIDDEV
 	if (hid->claimed & HID_CLAIMED_HIDDEV)
 		hiddev_disconnect(hid);
-#endif
 	hid_free_device(hid);
 }
 
@@ -1299,9 +1292,7 @@
 
 static int __init hid_init(void)
 {
-#ifdef CONFIG_USB_HIDDEV
 	hiddev_init();
-#endif
 	usb_register(&hid_driver);
 	info(DRIVER_VERSION " " DRIVER_AUTHOR);
 	info(DRIVER_DESC);
@@ -1311,9 +1302,7 @@
 
 static void __exit hid_exit(void)
 {
-#ifdef CONFIG_USB_HIDDEV
 	hiddev_exit();
-#endif
 	usb_deregister(&hid_driver);
 }
 
diff -urN linux-2.4.19-pre5/drivers/usb/hid.h linux-2.4.19-pre6/drivers/usb/hid.h
--- linux-2.4.19-pre5/drivers/usb/hid.h	Thu Apr  4 22:04:24 2002
+++ linux-2.4.19-pre6/drivers/usb/hid.h	Thu Apr  4 22:05:09 2002
@@ -352,9 +352,6 @@
 	struct hid_class_descriptor desc[1];
 } __attribute__ ((packed));
 
-void hidinput_hid_event(struct hid_device *, struct hid_field *, struct hid_usage *, __s32);
-int hidinput_connect(struct hid_device *);
-void hidinput_disconnect(struct hid_device *);
 
 #ifdef DEBUG
 #include "hid-debug.h"
@@ -365,7 +362,17 @@
 
 #endif
 
+#ifdef CONFIG_USB_HIDINPUT
 #define IS_INPUT_APPLICATION(a) (((a >= 0x00010000) && (a <= 0x00010008)) || (a == 0x00010080) || ( a == 0x000c0001))
+extern void hidinput_hid_event(struct hid_device *, struct hid_field *, struct hid_usage *, __s32);
+extern int hidinput_connect(struct hid_device *);
+extern void hidinput_disconnect(struct hid_device *);
+#else
+#define IS_INPUT_APPLICATION(a) (0)
+static inline void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct hid_usage *usage, __s32 value) { }
+static inline int hidinput_connect(struct hid_device *hid) { return -ENODEV; }
+static inline void hidinput_disconnect(struct hid_device *hid) { }
+#endif
 
 int hid_open(struct hid_device *);
 void hid_close(struct hid_device *);
diff -urN linux-2.4.19-pre5/drivers/usb/pegasus.c linux-2.4.19-pre6/drivers/usb/pegasus.c
--- linux-2.4.19-pre5/drivers/usb/pegasus.c	Thu Apr  4 22:04:25 2002
+++ linux-2.4.19-pre6/drivers/usb/pegasus.c	Thu Apr  4 22:05:10 2002
@@ -484,14 +484,12 @@
 	__u8	data[4];
 	pegasus_t *pegasus = dev->priv;
 
-
-	if ( read_mii_word(pegasus, pegasus->phy, MII_BMSR, &bmsr) ) 
-		return 1;
-#if 0
-	if ( !(bmsr & 0x20) && !loopback ) 
+	/* read twice 'cos this is a latch bit */
+	read_mii_word(pegasus, pegasus->phy, MII_BMSR, &bmsr);
+	read_mii_word(pegasus, pegasus->phy, MII_BMSR, &bmsr);
+	if ( !(bmsr & 4) && !loopback ) 
 		warn( "%s: link NOT established (0x%x) - check the cable.",
 			dev->name, bmsr );
-#endif
 	if ( read_mii_word(pegasus, pegasus->phy, MII_LPA, &linkpart) )
 		return 2;
 	if ( !(linkpart & 1) )
@@ -1021,11 +1019,11 @@
 		usb_free_urb (pegasus->rx_urb);
 		usb_free_urb (pegasus->ctrl_urb);
 		kfree( pegasus );
-		pegasus = NULL;
-		goto exit;
+		return NULL;
 	}
 
 	init_MUTEX(&pegasus->sem);
+	down(&pegasus->sem);
 	pegasus->usb = dev;
 	pegasus->net = net;
 	SET_MODULE_OWNER(net);
@@ -1072,7 +1070,7 @@
 	}
 
 exit:
-	up(&gsem);
+	up(&pegasus->sem);
 	return pegasus;
 }
 
diff -urN linux-2.4.19-pre5/drivers/usb/rtl8150.c linux-2.4.19-pre6/drivers/usb/rtl8150.c
--- linux-2.4.19-pre5/drivers/usb/rtl8150.c	Wed Dec 31 16:00:00 1969
+++ linux-2.4.19-pre6/drivers/usb/rtl8150.c	Thu Apr  4 22:05:10 2002
@@ -0,0 +1,762 @@
+/*
+ * Copyright (c) 2002 Petko Manolov (petkan@users.sourceforge.net)
+ *
+ *	This program is free software; you can redistribute it and/or
+ *	modify it under the terms of the GNU General Public License as
+ *	published by the Free Software Foundation; either version 2 of
+ *	the License, or (at your option) any later version.
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/sched.h>
+#include <linux/signal.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/mii.h>
+#include <linux/ethtool.h>
+#include <linux/devfs_fs_kernel.h>
+#include <linux/usb.h>
+#include <asm/uaccess.h>
+
+
+
+/* Version Information */
+#define DRIVER_VERSION "v0.4.0 (2002/03/28)"
+#define DRIVER_AUTHOR "Petko Manolov <petkan@users.sourceforge.net>"
+#define DRIVER_DESC "rtl8150 based usb-ethernet driver"
+
+
+#define	IRD			0x0120
+#define	MAR			0x0126
+#define	CR			0x012e
+#define	TCR			0x012f
+#define	RCR			0x0130
+#define	TSR			0x0132
+#define	RSR			0x0133
+#define	CON0			0x0135
+#define	CON1			0x0136
+#define	MSR			0x0137
+#define	PHYADD			0x0138
+#define	PHYDAT			0x0139
+#define	PHYCNT			0x013b
+#define	GPPC			0x013d
+#define	BMCR			0x0140
+#define	BMSR			0x0142
+#define	ANAR			0x0144
+#define	ANLP			0x0146
+#define	AER			0x0148
+
+#define	PHY_READ		0
+#define	PHY_WRITE		0x20
+#define	PHY_GO			0x40
+
+#define	RTL8150_REQT_READ	0xc0
+#define	RTL8150_REQT_WRITE	0x40
+#define	RTL8150_REQ_GET_REGS	0x05
+#define	RTL8150_REQ_SET_REGS	0x05
+
+#define	RTL8150_MTU		1500
+#define	RTL8150_MAX_MTU		1536
+
+#define	RTL8150_TX_TIMEOUT	(HZ)
+
+/* rtl8150 flags */
+#define	RTL8150_FLAG_HWCRC	0
+#define	RX_REG_SET		1
+#define	RTL8150_UNPLUG		2
+
+
+/* Define these values to match your device */
+#define VENDOR_ID_REALTEK		0x0bda
+#define PRODUCT_ID_RTL8150		0x8150
+
+/* table of devices that work with this driver */
+static struct usb_device_id rtl8150_table [] = {
+	{ USB_DEVICE(VENDOR_ID_REALTEK, PRODUCT_ID_RTL8150) },
+	{ }				
+};
+
+MODULE_DEVICE_TABLE (usb, rtl8150_table);
+
+
+struct rtl8150 {
+	unsigned int		flags;
+	struct usb_device	*udev;
+	struct usb_interface	*interface;
+	struct semaphore	sem;
+	struct net_device_stats	stats;
+	struct net_device	*netdev;
+	struct urb		*rx_urb, *tx_urb, *intr_urb, *ctrl_urb;
+	devrequest		dr;
+	int			intr_interval;
+	u16			rx_creg;
+	u8			rx_buff[RTL8150_MAX_MTU];
+	u8			tx_buff[RTL8150_MAX_MTU];
+	u8			intr_buff[8];
+	u8			phy;
+};
+
+typedef	struct rtl8150	rtl8150_t;
+
+
+/* the global usb devfs handle */
+extern devfs_handle_t usb_devfs_handle;
+unsigned long multicast_filter_limit = 32;
+
+
+static void rtl8150_disconnect(struct usb_device *dev, void *ptr);
+static void * rtl8150_probe(struct usb_device *dev, unsigned int ifnum,
+			    const struct usb_device_id *id);
+
+
+static struct usb_driver rtl8150_driver = {
+	name:		"rtl8150",
+	probe:		rtl8150_probe,
+	disconnect:	rtl8150_disconnect,
+	id_table:	rtl8150_table,
+};
+
+
+
+/*
+**
+**	device related part of the code
+**
+*/
+static int get_registers(rtl8150_t *dev, u16 indx, u16 size, void *data)
+{
+	return usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev,0),
+				RTL8150_REQ_GET_REGS, RTL8150_REQT_READ,
+				indx, 0, data, size, HZ/2);
+}
+
+
+static int set_registers(rtl8150_t *dev, u16 indx, u16 size, void *data)
+{
+	return usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev,0),
+				RTL8150_REQ_SET_REGS, RTL8150_REQT_WRITE,
+				indx, 0, data, size, HZ/2);
+}
+
+
+static void ctrl_callback(struct urb *urb)
+{
+	rtl8150_t	*dev;
+	
+	switch (urb->status) {
+	case 0:
+		break;
+	case -EINPROGRESS:
+		break;
+	case -ENOENT:
+		break;
+	default:
+		warn("ctrl urb status %d", urb->status);
+	}
+	dev = urb->context;
+	clear_bit(RX_REG_SET, &dev->flags);
+}
+
+
+static int async_set_registers(rtl8150_t *dev, u16 indx, u16 size, void *data)
+{
+	int	ret;
+
+	if (test_bit(RX_REG_SET, &dev->flags))
+		return -EAGAIN;
+	
+	dev->dr.requesttype = RTL8150_REQT_WRITE;
+	dev->dr.request = RTL8150_REQ_SET_REGS;
+	dev->dr.value = cpu_to_le16(indx);
+	dev->dr.index = 0;
+	dev->dr.length = cpu_to_le16(2);
+	dev->ctrl_urb->transfer_buffer_length = 2;
+	FILL_CONTROL_URB(dev->ctrl_urb, dev->udev, usb_sndctrlpipe(dev->udev,0),
+	                 (char*)&dev->dr, &dev->rx_creg, 2, ctrl_callback, dev);
+	if ((ret = usb_submit_urb(dev->ctrl_urb)))
+		err("control request submission failed: %d", ret);
+	else
+		set_bit(RX_REG_SET, &dev->flags);
+
+	return ret;
+}
+
+
+static int read_mii_word(rtl8150_t *dev, u8 phy, __u8 indx, u16 *reg)
+{
+	int	i;
+	u8	data[3], tmp;
+
+	data[0] = phy;
+	data[1] = data[2] = 0;
+	tmp = indx | PHY_READ | PHY_GO;
+	i = 0;
+
+	set_registers(dev, PHYADD, sizeof(data), data);
+	set_registers(dev, PHYCNT, 1, &tmp);
+	do {
+		get_registers(dev, PHYCNT, 1, data);
+	} while ((data[0] & PHY_GO) && (i++ < HZ));
+
+	if (i < HZ) {
+		get_registers(dev, PHYDAT, 2, data);
+		*reg = le16_to_cpup(data);
+		return 0;
+	} else
+		return 1;
+}
+
+
+static int write_mii_word(rtl8150_t *dev, u8 phy, __u8 indx, u16 reg)
+{
+	int	i;
+	u8	data[3], tmp;
+
+	data[0] = phy;
+	*(data + 1) = cpu_to_le16p(&reg);
+	tmp = indx | PHY_WRITE | PHY_GO;
+	i = 0;
+
+	set_registers(dev, PHYADD, sizeof(data), data);
+	set_registers(dev, PHYCNT, 1, &tmp);
+	do {
+		get_registers(dev, PHYCNT, 1, data);
+	} while((data[0] & PHY_GO) && (i++ < HZ));
+
+	if (i < HZ)
+		return 0;
+	else
+		return 1;
+}
+
+
+static inline void set_ethernet_addr(rtl8150_t *dev)
+{
+	u8	node_id[6];
+
+	get_registers(dev, IRD, sizeof(node_id), node_id);
+	memcpy(dev->netdev->dev_addr, node_id, sizeof(node_id));
+}
+
+
+static int rtl8150_reset(rtl8150_t *dev)
+{
+	u8	data=0x10;
+	int	i=HZ;
+
+	set_registers(dev, CR, 1, &data);
+	do {
+		get_registers(dev, CR, 1, &data);
+	} while ((data & 0x10) && --i);
+	
+	return (i > 0) ? 0 : -1;
+}
+
+
+static int alloc_all_urbs(rtl8150_t *dev)
+{
+	dev->rx_urb = usb_alloc_urb(0);
+	if (!dev->rx_urb)
+		return 0;
+	dev->tx_urb = usb_alloc_urb(0);
+	if (!dev->tx_urb) {
+		usb_free_urb(dev->rx_urb);
+		return 0;
+	}
+	dev->intr_urb = usb_alloc_urb(0);
+	if (!dev->intr_urb) {
+		usb_free_urb(dev->rx_urb);
+		usb_free_urb(dev->tx_urb);
+		return 0;
+	}
+	dev->ctrl_urb = usb_alloc_urb(0);
+	if (!dev->ctrl_urb) {
+		usb_free_urb(dev->rx_urb);
+		usb_free_urb(dev->tx_urb);
+		usb_free_urb(dev->intr_urb);
+		return 0;
+	}
+
+	return 1;
+}
+
+
+static void free_all_urbs(rtl8150_t *dev)
+{
+	usb_free_urb(dev->rx_urb);
+	usb_free_urb(dev->tx_urb);
+	usb_free_urb(dev->intr_urb);
+	usb_free_urb(dev->ctrl_urb);
+}
+
+
+static void unlink_all_urbs(rtl8150_t *dev)
+{
+	usb_unlink_urb(dev->rx_urb);
+	usb_unlink_urb(dev->tx_urb);
+	usb_unlink_urb(dev->intr_urb);
+	usb_unlink_urb(dev->ctrl_urb);
+}
+
+
+static void read_bulk_callback(struct urb *urb)
+{
+	rtl8150_t	*dev;
+	int		pkt_len, res;
+	struct sk_buff	*skb;
+	struct net_device *netdev;
+	u16		rx_stat;
+
+	dev = urb->context;
+	if (!dev) {
+		warn("!dev");
+		return;
+	}
+	netdev = dev->netdev;
+	if (!netif_device_present(netdev)) {
+		warn("netdev is not present");
+		return;
+	}
+	switch (urb->status) {
+	case 0:
+		break;
+	case -ENOENT:
+		return;
+	case -ETIMEDOUT:
+		warn("reset needed may be?..");
+		goto goon;
+	default:
+		warn("Rx status %d", urb->status);
+		goto goon;
+	}
+	
+	pkt_len = urb->actual_length - 4;
+	rx_stat = le16_to_cpu(*(u16 *)(dev->rx_buff + pkt_len));
+
+	if (!(skb = dev_alloc_skb(pkt_len + 2))) 
+		goto goon;
+	skb->dev = netdev;
+	skb_reserve(skb, 2);
+	eth_copy_and_sum(skb, dev->rx_buff, pkt_len, 0);
+	skb_put(skb, pkt_len);
+	skb->protocol = eth_type_trans(skb, netdev);
+	netif_rx(skb);
+	dev->stats.rx_packets++;
+	dev->stats.rx_bytes += pkt_len;
+goon:
+	FILL_BULK_URB(dev->rx_urb, dev->udev, usb_rcvbulkpipe(dev->udev,1),
+	              dev->rx_buff, RTL8150_MAX_MTU, read_bulk_callback, dev);
+	if ((res=usb_submit_urb(dev->rx_urb)))
+		warn("%s: Rx urb submission failed %d", netdev->name, res);
+}
+
+
+static void write_bulk_callback(struct urb *urb)
+{
+	rtl8150_t	*dev;
+
+	dev = urb->context;
+	if (!dev)
+		return;
+	if (!netif_device_present(dev->netdev))
+		return;
+	if (urb->status)
+		info("%s: Tx status %d", dev->netdev->name, urb->status);
+	dev->netdev->trans_start = jiffies;
+	netif_wake_queue(dev->netdev);
+}
+
+
+void intr_callback(struct urb *urb)
+{
+	rtl8150_t	*dev;
+
+	dev = urb->context;
+	if (!dev)
+		return;
+	switch (urb->status) {
+		case 0:
+			break;
+		case -ENOENT:
+			return;
+		default:
+			info("%s: intr status %d", dev->netdev->name,
+			     urb->status);
+	}
+}
+
+
+/*
+**
+**	network related part of the code
+**
+*/
+
+
+static int enable_net_traffic(rtl8150_t *dev)
+{
+	u8	cr, tcr, rcr, msr;
+
+	if (rtl8150_reset(dev)) {
+		warn("%s - device reset failed", __FUNCTION__);
+	}
+	dev->rx_creg = rcr = 0x9e;	/* bit7=1 attach Rx info at the end */
+	tcr = 0xd8;
+	cr = 0x0c;
+	set_registers(dev, RCR, 1, &rcr);
+	set_registers(dev, TCR, 1, &tcr);
+	set_registers(dev, CR, 1, &cr);
+	get_registers(dev, MSR, 1, &msr);
+
+	return 0;
+}
+
+
+static void disable_net_traffic(rtl8150_t *dev)
+{
+	u8	cr;
+
+	get_registers(dev, CR, 1, &cr);
+	cr &= 0xf3;
+	set_registers(dev, CR, 1, &cr);
+}
+
+
+static struct net_device_stats *rtl8150_netdev_stats(struct net_device *dev)
+{
+	return &((rtl8150_t *)dev->priv)->stats;
+}
+
+
+static void rtl8150_tx_timeout(struct net_device *netdev)
+{
+	rtl8150_t	*dev;
+
+	dev = netdev->priv;
+	if (!dev)
+		return;
+	warn("%s: Tx timeout.", netdev->name);
+	dev->tx_urb->transfer_flags |= USB_ASYNC_UNLINK;
+	usb_unlink_urb(dev->tx_urb);
+	dev->stats.tx_errors++;
+}
+
+
+static void rtl8150_set_multicast(struct net_device *netdev)
+{
+	rtl8150_t	*dev;
+
+	dev = netdev->priv;
+	netif_stop_queue(netdev);
+	if (netdev->flags & IFF_PROMISC) {
+		dev->rx_creg |= 0x0001;
+		info("%s: promiscuous mode", netdev->name);
+	} else if ((netdev->mc_count > multicast_filter_limit) ||
+	           (netdev->flags & IFF_ALLMULTI)) {
+		dev->rx_creg &= 0xfffe;
+		dev->rx_creg |= 0x0002;
+		info("%s: allmulti set", netdev->name);
+	} else {
+		/* ~RX_MULTICAST, ~RX_PROMISCUOUS */
+		dev->rx_creg &= 0x00fc;
+	}
+	async_set_registers(dev, RCR, 2, &dev->rx_creg);
+	netif_wake_queue(netdev);
+}
+
+
+static int rtl8150_start_xmit(struct sk_buff *skb, struct net_device *netdev)
+{
+	rtl8150_t	*dev;
+	int		count, res;
+
+	netif_stop_queue(netdev);
+	dev = netdev->priv;
+	count = (skb->len < 60) ? 60 : skb->len;
+	count = (count & 0x3f) ? count : count + 1;
+	memcpy(dev->tx_buff, skb->data, skb->len);
+	FILL_BULK_URB(dev->tx_urb, dev->udev, usb_sndbulkpipe(dev->udev,2),
+		      dev->tx_buff, RTL8150_MAX_MTU, write_bulk_callback, dev);
+	dev->tx_urb->transfer_buffer_length = count;
+
+	if ((res = usb_submit_urb(dev->tx_urb))) {
+		warn("failed tx_urb %d\n", res);
+		dev->stats.tx_errors++;
+		netif_start_queue(netdev);
+	} else {
+		dev->stats.tx_packets++;
+		dev->stats.tx_bytes += skb->len;
+		netdev->trans_start = jiffies;
+	}
+	dev_kfree_skb(skb);
+
+	return 0;
+}
+
+
+static int rtl8150_open(struct net_device *netdev)
+{
+	rtl8150_t	*dev;
+	int		res;
+	
+	dev = netdev->priv;
+	if (dev == NULL) {
+		return -ENODEV;
+	}
+
+	down(&dev->sem);
+	FILL_BULK_URB(dev->rx_urb, dev->udev, usb_rcvbulkpipe(dev->udev,1),
+			dev->rx_buff, RTL8150_MAX_MTU, read_bulk_callback, dev);
+	if ((res=usb_submit_urb(dev->rx_urb)))
+		warn("%s: rx_urb submit failed: %d", __FUNCTION__, res);
+	FILL_INT_URB(dev->intr_urb, dev->udev, usb_rcvintpipe(dev->udev,3),
+			dev->intr_buff, sizeof(dev->intr_buff), intr_callback,
+			dev, dev->intr_interval);
+	if ((res=usb_submit_urb(dev->intr_urb)))
+		warn("%s: intr_urb submit failed: %d", __FUNCTION__, res);
+	netif_start_queue(netdev);
+	enable_net_traffic(dev);
+	up(&dev->sem);
+
+	return res;
+}
+
+
+static int rtl8150_close(struct net_device *netdev)
+{
+	rtl8150_t *dev;
+	int res = 0;
+
+	dev = netdev->priv;
+	if (!dev)
+		return -ENODEV;
+
+	down(&dev->sem);
+	if (!test_bit(RTL8150_UNPLUG, &dev->flags))
+		disable_net_traffic(dev);
+	unlink_all_urbs(dev);
+	netif_stop_queue(netdev);
+	up(&dev->sem);
+
+	return res;
+}
+
+
+static int rtl8150_ethtool_ioctl(struct net_device *netdev, void *uaddr)
+{
+	rtl8150_t	*dev;
+	int		cmd;
+	char		tmp[128];
+
+	dev = netdev->priv;
+	if (get_user(cmd, (int *)uaddr))
+		return -EFAULT;
+
+	switch (cmd) {
+	case ETHTOOL_GDRVINFO: {
+		struct ethtool_drvinfo info = {ETHTOOL_GDRVINFO};
+		
+		strncpy(info.driver, DRIVER_DESC, ETHTOOL_BUSINFO_LEN);
+		strncpy(info.version, DRIVER_VERSION, ETHTOOL_BUSINFO_LEN);
+		sprintf(tmp, "usb%d:%d", dev->udev->bus->busnum,
+		        dev->udev->devnum);
+		strncpy(info.bus_info, tmp, ETHTOOL_BUSINFO_LEN);
+		if (copy_to_user(uaddr, &info, sizeof(info)))
+			return -EFAULT;
+		return 0;
+	}
+	case ETHTOOL_GSET: {
+		struct ethtool_cmd ecmd;
+		short   lpa, bmcr;
+
+		if (copy_from_user(&ecmd, uaddr, sizeof(ecmd)))
+			return -EFAULT;
+		ecmd.supported = (SUPPORTED_10baseT_Half |
+		                  SUPPORTED_10baseT_Full |
+		                  SUPPORTED_100baseT_Half |
+		                  SUPPORTED_100baseT_Full |
+		                  SUPPORTED_Autoneg |
+		                  SUPPORTED_TP |
+		                  SUPPORTED_MII);
+		ecmd.port = PORT_TP;
+		ecmd.transceiver = XCVR_INTERNAL;
+		ecmd.phy_address = dev->phy;
+		get_registers(dev, BMCR, 2, &bmcr);
+		get_registers(dev, ANLP, 2, &lpa);
+		if (bmcr & BMCR_ANENABLE) {
+			ecmd.autoneg = AUTONEG_ENABLE;
+			ecmd.speed = (lpa & (LPA_100HALF | LPA_100FULL)) ?
+			             SPEED_100 : SPEED_10;
+			if (ecmd.speed == SPEED_100)
+				ecmd.duplex = (lpa & LPA_100FULL) ?
+				              DUPLEX_FULL : DUPLEX_HALF;
+			else
+				ecmd.duplex = (lpa & LPA_10FULL) ?
+				              DUPLEX_FULL : DUPLEX_HALF;
+		} else {
+			ecmd.autoneg = AUTONEG_DISABLE;
+			ecmd.speed = (bmcr & BMCR_SPEED100) ?
+			             SPEED_100 : SPEED_10;
+			ecmd.duplex = (bmcr & BMCR_FULLDPLX) ?
+			              DUPLEX_FULL : DUPLEX_HALF;
+		}
+		if (copy_to_user(uaddr, &ecmd, sizeof(ecmd)))
+			return -EFAULT;
+		return 0;
+	}
+	case ETHTOOL_SSET:
+		return -ENOTSUPP;
+	case ETHTOOL_GLINK: {
+		struct ethtool_value edata = {ETHTOOL_GLINK};
+
+		edata.data = netif_carrier_ok(netdev);
+		if (copy_to_user(uaddr, &edata, sizeof(edata)))
+			return -EFAULT;
+		return 0;
+	}
+	default:
+		return -EOPNOTSUPP;
+	}
+}
+
+
+static int rtl8150_ioctl (struct net_device *netdev, struct ifreq *rq, int cmd)
+{
+	rtl8150_t *dev;
+	u16	*data;
+	int	res;
+
+	dev = netdev->priv;
+	data = (u16 *)&rq->ifr_data;
+	res = 0;
+
+	down(&dev->sem);
+	switch (cmd) {
+	case SIOCETHTOOL:
+		res = rtl8150_ethtool_ioctl(netdev, rq->ifr_data);
+		break;
+	case SIOCDEVPRIVATE:
+		data[0] = dev->phy;
+	case SIOCDEVPRIVATE+1:
+		read_mii_word(dev, dev->phy, (data[1] & 0x1f), &data[3]);
+		break;
+	case SIOCDEVPRIVATE+2:
+		if (!capable(CAP_NET_ADMIN)) {
+			up(&dev->sem);
+			return -EPERM;
+		}
+		write_mii_word(dev, dev->phy, (data[1] & 0x1f), data[2]);
+		break;
+	default:
+		res = -EOPNOTSUPP;
+	}
+	up(&dev->sem);
+
+	return res;
+}
+
+
+static void * rtl8150_probe(struct usb_device *udev, unsigned int ifnum,
+			    const struct usb_device_id *id)
+{
+	rtl8150_t *dev;
+	struct net_device *netdev;
+
+	udev->config[0].bConfigurationValue = 1;
+	if (usb_set_configuration(udev, udev->config[0].bConfigurationValue)) {
+		err("usb_set_configuration() failed");
+		return NULL;
+	}
+	if ((udev->descriptor.idVendor != VENDOR_ID_REALTEK) ||
+	    (udev->descriptor.idProduct != PRODUCT_ID_RTL8150)) {
+	    	err("Not the one we are interested about");
+		return NULL;
+	}
+	dev = kmalloc(sizeof(rtl8150_t), GFP_KERNEL);
+	if (!dev) {
+		err ("Out of memory");
+		goto exit;
+	} else
+		memset(dev, 0, sizeof(rtl8150_t));
+
+	netdev = init_etherdev(NULL, 0);
+	if (!netdev) {
+		kfree(dev);
+		err("Oh boy, out of memory again?!?");
+		dev = NULL;
+		goto exit;
+	}
+		
+	init_MUTEX(&dev->sem);
+	dev->udev = udev;
+	dev->netdev = netdev;
+	SET_MODULE_OWNER(netdev);
+	netdev->priv = dev;
+	netdev->open = rtl8150_open;
+	netdev->stop = rtl8150_close;
+	netdev->do_ioctl = rtl8150_ioctl;
+	netdev->watchdog_timeo = RTL8150_TX_TIMEOUT;
+	netdev->tx_timeout = rtl8150_tx_timeout;
+	netdev->hard_start_xmit = rtl8150_start_xmit;
+	netdev->set_multicast_list = rtl8150_set_multicast;
+	netdev->get_stats = rtl8150_netdev_stats;
+	netdev->mtu = RTL8150_MTU;
+	dev->intr_interval = 100;	/* 100ms */
+
+	if (rtl8150_reset(dev) || !alloc_all_urbs(dev)) {
+		err("couldn't reset the device");
+		free_all_urbs(dev);
+		unregister_netdev(dev->netdev);
+		kfree(netdev);
+		kfree(dev);
+		dev = NULL;
+		goto exit;
+	}
+
+	set_ethernet_addr(dev);
+	/* let's not be very nasty :-) */
+	info("%s: rtl8150 is detected", netdev->name);
+exit:
+	return dev;
+}
+
+
+static void rtl8150_disconnect(struct usb_device *udev, void *ptr)
+{
+	rtl8150_t *dev;
+
+	dev = ptr;
+	set_bit(RTL8150_UNPLUG, &dev->flags);
+	unregister_netdev(dev->netdev);
+	unlink_all_urbs(dev);
+	free_all_urbs(dev);
+	kfree(dev->netdev);
+	kfree(dev);
+	dev->netdev = NULL;
+	dev = NULL;
+}
+
+
+
+static int __init usb_rtl8150_init(void)
+{
+	info(DRIVER_DESC " " DRIVER_VERSION);
+	return usb_register(&rtl8150_driver);
+}
+
+
+static void __exit usb_rtl8150_exit(void)
+{
+	usb_deregister(&rtl8150_driver);
+}
+
+
+module_init(usb_rtl8150_init);
+module_exit(usb_rtl8150_exit);
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
diff -urN linux-2.4.19-pre5/drivers/usb/serial/visor.c linux-2.4.19-pre6/drivers/usb/serial/visor.c
--- linux-2.4.19-pre5/drivers/usb/serial/visor.c	Thu Apr  4 22:04:25 2002
+++ linux-2.4.19-pre6/drivers/usb/serial/visor.c	Thu Apr  4 22:05:10 2002
@@ -11,7 +11,11 @@
  *	(at your option) any later version.
  *
  * See Documentation/usb/usb-serial.txt for more information on using this driver
- * 
+ *
+ * (03/23/2002) gkh
+ *	Added support for the Palm i705 device, thanks to Thomas Riemer
+ *	<tom@netmech.com> for the information.
+ *
  * (03/21/2002) gkh
  *	Added support for the Palm m130 device, thanks to Udo Eisenbarth
  *	<udo.eisenbarth@web.de> for the information.
@@ -173,6 +177,7 @@
 	{ USB_DEVICE(PALM_VENDOR_ID, PALM_M515_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) },
 	{ }					/* Terminating entry */
 };
 
@@ -194,6 +199,7 @@
 	{ USB_DEVICE(PALM_VENDOR_ID, PALM_M515_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(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.19-pre5/drivers/usb/serial/visor.h linux-2.4.19-pre6/drivers/usb/serial/visor.h
--- linux-2.4.19-pre5/drivers/usb/serial/visor.h	Thu Apr  4 22:04:25 2002
+++ linux-2.4.19-pre6/drivers/usb/serial/visor.h	Thu Apr  4 22:05:10 2002
@@ -24,6 +24,7 @@
 #define PALM_M500_ID			0x0001
 #define PALM_M505_ID			0x0002
 #define PALM_M515_ID			0x0003
+#define PALM_I705_ID			0x0020
 #define PALM_M125_ID			0x0040
 #define PALM_M130_ID			0x0050
 
diff -urN linux-2.4.19-pre5/drivers/usb/uhci.c linux-2.4.19-pre6/drivers/usb/uhci.c
--- linux-2.4.19-pre5/drivers/usb/uhci.c	Thu Apr  4 22:04:25 2002
+++ linux-2.4.19-pre6/drivers/usb/uhci.c	Thu Apr  4 22:05:10 2002
@@ -336,6 +336,7 @@
 	qh->link = UHCI_PTR_TERM;
 
 	qh->dev = dev;
+	qh->urbp = NULL;
 
 	INIT_LIST_HEAD(&qh->list);
 	INIT_LIST_HEAD(&qh->remove_list);
@@ -410,20 +411,19 @@
 	spin_unlock_irqrestore(&uhci->frame_list_lock, flags);
 }
 
-static void uhci_remove_qh(struct uhci *uhci, struct urb *urb)
+static void uhci_remove_qh(struct uhci *uhci, struct uhci_qh *qh)
 {
-	struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
 	unsigned long flags;
-	struct uhci_qh *qh = urbp->qh, *pqh;
+	struct uhci_qh *pqh;
 
 	if (!qh)
 		return;
 
+	qh->urbp = NULL;
+
 	/* Only go through the hoops if it's actually linked in */
 	spin_lock_irqsave(&uhci->frame_list_lock, flags);
 	if (!list_empty(&qh->list)) {
-		qh->urbp = NULL;
-
 		pqh = list_entry(qh->list.prev, struct uhci_qh, list);
 
 		if (pqh->urbp) {
@@ -1040,7 +1040,7 @@
 	urbp->short_control_packet = 1;
 
 	/* Create a new QH to avoid pointer overwriting problems */
-	uhci_remove_qh(uhci, urb);
+	uhci_remove_qh(uhci, urbp->qh);
 
 	/* Delete all of the TD's except for the status TD at the end */
 	head = &urbp->td_list;
@@ -1259,20 +1259,29 @@
 			data);
 
 		data += pktsze;
-		len -= pktsze;
+		len -= maxsze;
 
 		usb_dotoggle(urb->dev, usb_pipeendpoint(urb->pipe),
 			usb_pipeout(urb->pipe));
 	} while (len > 0);
 
+	/*
+	 * USB_ZERO_PACKET means adding a 0-length packet, if
+	 * direction is OUT and the transfer_length was an
+	 * exact multiple of maxsze, hence
+	 * (len = transfer_length - N * maxsze) == 0
+	 * however, if transfer_length == 0, the zero packet
+	 * was already prepared above.
+	 */
 	if (usb_pipeout(urb->pipe) && (urb->transfer_flags & USB_ZERO_PACKET) &&
-	   urb->transfer_buffer_length) {
+	   !len && urb->transfer_buffer_length) {
 		td = uhci_alloc_td(uhci, urb->dev);
 		if (!td)
 			return -ENOMEM;
 
 		uhci_add_td_to_urb(urb, td);
-		uhci_fill_td(td, status, destination | UHCI_NULL_DATA_SIZE |
+		uhci_fill_td(td, status, destination |
+			(UHCI_NULL_DATA_SIZE << 21) |
 			(usb_gettoggle(urb->dev, usb_pipeendpoint(urb->pipe),
 			 usb_pipeout(urb->pipe)) << TD_TOKEN_TOGGLE),
 			data);
@@ -1728,7 +1737,8 @@
 	uhci_delete_queued_urb(uhci, urb);
 
 	/* The interrupt loop will reclaim the QH's */
-	uhci_remove_qh(uhci, urb);
+	uhci_remove_qh(uhci, urbp->qh);
+	urbp->qh = NULL;
 }
 
 static int uhci_unlink_urb(struct urb *urb)
@@ -2351,15 +2361,15 @@
 	urb->dev = NULL;
 	spin_unlock_irqrestore(&urb->lock, flags);
 
-	if (urb->complete) {
+	if (urb->complete)
 		urb->complete(urb);
 
+	if (resubmit_interrupt)
 		/* Recheck the status. The completion handler may have */
 		/*  unlinked the resubmitting interrupt URB */
 		killed = (urb->status == -ENOENT ||
 			  urb->status == -ECONNABORTED ||
 			  urb->status == -ECONNRESET);
-	}
 
 	if (resubmit_interrupt && !killed) {
 		urb->dev = dev;
diff -urN linux-2.4.19-pre5/drivers/usb/usb-ohci.c linux-2.4.19-pre6/drivers/usb/usb-ohci.c
--- linux-2.4.19-pre5/drivers/usb/usb-ohci.c	Thu Apr  4 22:04:25 2002
+++ linux-2.4.19-pre6/drivers/usb/usb-ohci.c	Thu Apr  4 22:05:10 2002
@@ -12,9 +12,10 @@
  * 
  * History:
  *
+ * 2002/03/08 interrupt unlink fix (Matt Hughes), better cleanup on
+ *	load failure (Matthew Frederickson)
  * 2002/01/20 async unlink fixes:  return -EINPROGRESS (per spec) and
  *	make interrupt unlink-in-completion work (db)
- * 
  * 2001/09/19 USB_ZERO_PACKET support (Jean Tourrilhes)
  * 2001/07/17 power management and pmac cleanup (Benjamin Herrenschmidt)
  * 2001/03/24 td/ed hashing to remove bus_to_virt (Steve Longerbeam);
@@ -1076,6 +1077,28 @@
 
 /*-------------------------------------------------------------------------*/
 
+/* scan the periodic table to find and unlink this ED */
+static void periodic_unlink (
+	struct ohci	*ohci,
+	struct ed	*ed,
+	unsigned	index,
+	unsigned	period
+) {
+	for (; index < NUM_INTS; index += period) {
+		__u32	*ed_p = &ohci->hcca->int_table [index];
+
+		/* ED might have been unlinked through another path */
+		while (*ed_p != 0) {
+			if ((dma_to_ed (ohci, le32_to_cpup (ed_p))) == ed) {
+				*ed_p = ed->hwNextED;		
+				break;
+			}
+			ed_p = & ((dma_to_ed (ohci,
+				le32_to_cpup (ed_p)))->hwNextED);
+		}
+	}	
+}
+
 /* unlink an ed from one of the HC chains. 
  * just the link to the ed is unlinked.
  * the link from the ed still points to another operational ed or 0
@@ -1083,11 +1106,7 @@
 
 static int ep_unlink (ohci_t * ohci, ed_t * ed) 
 {
-	int int_branch;
 	int i;
-	int inter;
-	int interval;
-	__u32 * ed_p;
 
 	ed->hwINFO |= cpu_to_le32 (OHCI_ED_SKIP);
 
@@ -1127,21 +1146,8 @@
 		break;
       
 	case PIPE_INTERRUPT:
-		int_branch = ed->int_branch;
-		interval = ed->int_interval;
-
-		for (i = 0; i < ep_rev (6, interval); i += inter) {
-			for (ed_p = &(ohci->hcca->int_table[ep_rev (5, i) + int_branch]), inter = 1; 
-				(*ed_p != 0) && (*ed_p != ed->hwNextED); 
-				ed_p = &((dma_to_ed (ohci, le32_to_cpup (ed_p)))->hwNextED), 
-				inter = ep_rev (6, (dma_to_ed (ohci, le32_to_cpup (ed_p)))->int_interval)) {				
-					if((dma_to_ed (ohci, le32_to_cpup (ed_p))) == ed) {
-			  			*ed_p = ed->hwNextED;		
-			  			break;
-			  		}
-			  }
-		}
-		for (i = int_branch; i < 32; i += interval)
+		periodic_unlink (ohci, ed, 0, 1);
+		for (i = ed->int_branch; i < 32; i += ed->int_interval)
 		    ohci->ohci_int_load[i] -= ed->int_load;
 #ifdef DEBUG
 		ep_print_int_eds (ohci, "UNLINK_INT");
@@ -1152,23 +1158,13 @@
 		if (ohci->ed_isotail == ed)
 			ohci->ed_isotail = ed->ed_prev;
 		if (ed->hwNextED != 0) 
-		    (dma_to_ed (ohci, le32_to_cpup (&ed->hwNextED)))->ed_prev = ed->ed_prev;
+		    (dma_to_ed (ohci, le32_to_cpup (&ed->hwNextED)))
+		    	->ed_prev = ed->ed_prev;
 				    
-		if (ed->ed_prev != NULL) {
+		if (ed->ed_prev != NULL)
 			ed->ed_prev->hwNextED = ed->hwNextED;
-		} else {
-			for (i = 0; i < 32; i++) {
-				for (ed_p = &(ohci->hcca->int_table[ep_rev (5, i)]); 
-						*ed_p != 0; 
-						ed_p = &((dma_to_ed (ohci, le32_to_cpup (ed_p)))->hwNextED)) {
-					// inter = ep_rev (6, (dma_to_ed (ohci, le32_to_cpup (ed_p)))->int_interval);
-					if((dma_to_ed (ohci, le32_to_cpup (ed_p))) == ed) {
-						*ed_p = ed->hwNextED;		
-						break;
-					}
-				}
-			}	
-		}	
+		else
+			periodic_unlink (ohci, ed, 0, 1);
 #ifdef DEBUG
 		ep_print_int_eds (ohci, "UNLINK_ISO");
 #endif
@@ -2354,7 +2350,6 @@
 static ohci_t * __devinit hc_alloc_ohci (struct pci_dev *dev, void * mem_base)
 {
 	ohci_t * ohci;
-	struct usb_bus * bus;
 
 	ohci = (ohci_t *) kmalloc (sizeof *ohci, GFP_KERNEL);
 	if (!ohci)
@@ -2383,14 +2378,15 @@
 
 	INIT_LIST_HEAD (&ohci->timeout_list);
 
-	bus = usb_alloc_bus (&sohci_device_operations);
-	if (!bus) {
+	ohci->bus = usb_alloc_bus (&sohci_device_operations);
+	if (!ohci->bus) {
+		pci_set_drvdata (dev, NULL);
+		pci_free_consistent (ohci->ohci_dev, sizeof *ohci->hcca,
+				ohci->hcca, ohci->hcca_dma);
 		kfree (ohci);
 		return NULL;
 	}
-
-	ohci->bus = bus;
-	bus->hcpriv = (void *) ohci;
+	ohci->bus->hcpriv = (void *) ohci;
 
 	return ohci;
 } 
@@ -2416,9 +2412,11 @@
 		ohci->irq = -1;
 	}
 	pci_set_drvdata(ohci->ohci_dev, NULL);
-
-	usb_deregister_bus (ohci->bus);
-	usb_free_bus (ohci->bus);
+	if (ohci->bus) {
+		if (ohci->bus->busnum)
+			usb_deregister_bus (ohci->bus);
+		usb_free_bus (ohci->bus);
+	}
 
 	list_del (&ohci->ohci_hcd_list);
 	INIT_LIST_HEAD (&ohci->ohci_hcd_list);
@@ -2566,12 +2564,14 @@
 {
 	unsigned long mem_resource, mem_len;
 	void *mem_base;
+	int status;
 
 	if (pci_enable_device(dev) < 0)
 		return -ENODEV;
 
         if (!dev->irq) {
         	err("found OHCI device with no IRQ assigned. check BIOS settings!");
+		pci_disable_device (dev);
    	        return -ENODEV;
         }
 	
@@ -2580,19 +2580,28 @@
 	mem_len = pci_resource_len(dev, 0);
 	if (!request_mem_region (mem_resource, mem_len, ohci_pci_driver.name)) {
 		dbg ("controller already in use");
+		pci_disable_device (dev);
 		return -EBUSY;
 	}
 
 	mem_base = ioremap_nocache (mem_resource, mem_len);
 	if (!mem_base) {
 		err("Error mapping OHCI memory");
+		release_mem_region (mem_resource, mem_len);
+		pci_disable_device (dev);
 		return -EFAULT;
 	}
 
 	/* controller writes into our memory */
 	pci_set_master (dev);
 
-	return hc_found_ohci (dev, dev->irq, mem_base, id);
+	status = hc_found_ohci (dev, dev->irq, mem_base, id);
+	if (status < 0) {
+		iounmap (mem_base);
+		release_mem_region (mem_resource, mem_len);
+		pci_disable_device (dev);
+	}
+	return status;
 } 
 
 /*-------------------------------------------------------------------------*/
@@ -2630,6 +2639,7 @@
 	hc_release_ohci (ohci);
 
 	release_mem_region (pci_resource_start (dev, 0), pci_resource_len (dev, 0));
+	pci_disable_device (dev);
 }
 
 
diff -urN linux-2.4.19-pre5/drivers/usb/usb-uhci.c linux-2.4.19-pre6/drivers/usb/usb-uhci.c
--- linux-2.4.19-pre5/drivers/usb/usb-uhci.c	Mon Feb 25 11:38:07 2002
+++ linux-2.4.19-pre6/drivers/usb/usb-uhci.c	Thu Apr  4 22:05:10 2002
@@ -170,7 +170,7 @@
 #ifdef CONFIG_USB_UHCI_HIGH_BANDWIDTH
 _static void enable_desc_loop(uhci_t *s, urb_t *urb)
 {
-	int flags;
+	unsigned long flags;
 
 	if (urb->transfer_flags & USB_NO_FSBR)
 		return;
@@ -185,7 +185,7 @@
 /*-------------------------------------------------------------------*/
 _static void disable_desc_loop(uhci_t *s, urb_t *urb)
 {
-	int flags;
+	unsigned long flags;
 
 	if (urb->transfer_flags & USB_NO_FSBR)
 		return;
diff -urN linux-2.4.19-pre5/drivers/usb/usbnet.c linux-2.4.19-pre6/drivers/usb/usbnet.c
--- linux-2.4.19-pre5/drivers/usb/usbnet.c	Mon Feb 25 11:38:07 2002
+++ linux-2.4.19-pre6/drivers/usb/usbnet.c	Thu Apr  4 22:05:10 2002
@@ -989,9 +989,8 @@
 			|| skb->len > FRAMED_SIZE (dev->net.mtu)) {
 		dev->stats.rx_frame_errors++;
 		dbg ("rx framesize %d range %d..%d mtu %d", skb->len,
-			MIN_FRAMED, FRAMED_SIZE (dev->net.mtu),
-			dev->net.mtu
-			);
+			(int)MIN_FRAMED, (int)FRAMED_SIZE (dev->net.mtu),
+			dev->net.mtu);
 		return 0;
 	}
 
diff -urN linux-2.4.19-pre5/fs/Config.in linux-2.4.19-pre6/fs/Config.in
--- linux-2.4.19-pre5/fs/Config.in	Thu Apr  4 22:04:27 2002
+++ linux-2.4.19-pre6/fs/Config.in	Thu Apr  4 22:05:12 2002
@@ -21,7 +21,7 @@
 
 dep_tristate 'BFS file system support (EXPERIMENTAL)' CONFIG_BFS_FS $CONFIG_EXPERIMENTAL
 
-tristate 'Ext3 journalling file system support (EXPERIMENTAL)' CONFIG_EXT3_FS
+tristate 'Ext3 journalling file system support' CONFIG_EXT3_FS
 # CONFIG_JBD could be its own option (even modular), but until there are
 # other users than ext3, we will simply make it be the same as CONFIG_EXT3_FS
 # dep_tristate '  Journal Block Device support (JBD for ext3)' CONFIG_JBD $CONFIG_EXT3_FS
@@ -45,7 +45,7 @@
 fi
 tristate 'Compressed ROM file system support' CONFIG_CRAMFS
 bool 'Virtual memory file system support (former shm fs)' CONFIG_TMPFS
-tristate 'Simple RAM-based file system support' CONFIG_RAMFS
+define_bool CONFIG_RAMFS y
 
 tristate 'ISO 9660 CDROM file system support' CONFIG_ISO9660_FS
 dep_mbool '  Microsoft Joliet CDROM extensions' CONFIG_JOLIET $CONFIG_ISO9660_FS
diff -urN linux-2.4.19-pre5/fs/block_dev.c linux-2.4.19-pre6/fs/block_dev.c
--- linux-2.4.19-pre5/fs/block_dev.c	Mon Feb 25 11:38:08 2002
+++ linux-2.4.19-pre6/fs/block_dev.c	Thu Apr  4 22:05:12 2002
@@ -616,7 +616,7 @@
 
 	down(&bdev->bd_sem);
 	lock_kernel();
-	if (kind == BDEV_FILE)
+	if (kind == BDEV_FILE && bdev->bd_openers == 1)
 		__block_fsync(bd_inode);
 	else if (kind == BDEV_FS)
 		fsync_no_super(rdev);
diff -urN linux-2.4.19-pre5/fs/coda/cache.c linux-2.4.19-pre6/fs/coda/cache.c
--- linux-2.4.19-pre5/fs/coda/cache.c	Fri Dec 21 09:41:55 2001
+++ linux-2.4.19-pre6/fs/coda/cache.c	Thu Apr  4 22:05:12 2002
@@ -14,7 +14,6 @@
 #include <linux/stat.h>
 #include <linux/errno.h>
 #include <linux/locks.h>
-#include <asm/segment.h>
 #include <asm/uaccess.h>
 #include <linux/string.h>
 #include <linux/list.h>
diff -urN linux-2.4.19-pre5/fs/coda/cnode.c linux-2.4.19-pre6/fs/coda/cnode.c
--- linux-2.4.19-pre5/fs/coda/cnode.c	Fri Dec 21 09:41:55 2001
+++ linux-2.4.19-pre6/fs/coda/cnode.c	Thu Apr  4 22:05:12 2002
@@ -12,7 +12,6 @@
 #include <linux/coda_psdev.h>
 
 extern int coda_debug;
-extern int coda_print_entry;
 
 inline int coda_fideq(ViceFid *fid1, ViceFid *fid2)
 {
@@ -58,7 +57,6 @@
         } else if (S_ISLNK(inode->i_mode)) {
 		inode->i_op = &coda_symlink_inode_operations;
 		inode->i_data.a_ops = &coda_symlink_aops;
-		inode->i_mapping = &inode->i_data;
 	} else
                 init_special_inode(inode, inode->i_mode, attr->va_rdev);
 }
@@ -178,24 +176,24 @@
 	if ( !coda_fideq(fid, &cii->c_fid) ) BUG();
 
         CDEBUG(D_INODE, "found %ld\n", inode->i_ino);
-        return inode;
+	return inode;
 }
 
 /* the CONTROL inode is made without asking attributes from Venus */
 int coda_cnode_makectl(struct inode **inode, struct super_block *sb)
 {
-    int error = 0;
+	int error = 0;
 
-    *inode = iget(sb, CTL_INO);
-    if ( *inode ) {
-	(*inode)->i_op = &coda_ioctl_inode_operations;
-	(*inode)->i_fop = &coda_ioctl_operations;
-	(*inode)->i_mode = 0444;
-	error = 0;
-    } else { 
-	error = -ENOMEM;
-    }
+	*inode = iget(sb, CTL_INO);
+	if ( *inode ) {
+		(*inode)->i_op = &coda_ioctl_inode_operations;
+		(*inode)->i_fop = &coda_ioctl_operations;
+		(*inode)->i_mode = 0444;
+		error = 0;
+	} else { 
+		error = -ENOMEM;
+	}
     
-    return error;
+	return error;
 }
 
diff -urN linux-2.4.19-pre5/fs/coda/coda_linux.c linux-2.4.19-pre6/fs/coda/coda_linux.c
--- linux-2.4.19-pre5/fs/coda/coda_linux.c	Thu Apr  4 22:04:27 2002
+++ linux-2.4.19-pre6/fs/coda/coda_linux.c	Thu Apr  4 22:05:12 2002
@@ -15,7 +15,6 @@
 #include <linux/stat.h>
 #include <linux/errno.h>
 #include <linux/locks.h>
-#include <asm/segment.h>
 #include <asm/uaccess.h>
 #include <linux/string.h>
 
@@ -26,7 +25,6 @@
 
 /* initialize the debugging variables */
 int coda_debug;
-int coda_print_entry; 
 int coda_access_cache = 1;
 int coda_fake_statfs;
 
diff -urN linux-2.4.19-pre5/fs/coda/dir.c linux-2.4.19-pre6/fs/coda/dir.c
--- linux-2.4.19-pre5/fs/coda/dir.c	Thu Apr  4 22:04:27 2002
+++ linux-2.4.19-pre6/fs/coda/dir.c	Thu Apr  4 22:05:12 2002
@@ -488,30 +488,41 @@
 /* file operations for directories */
 int coda_readdir(struct file *coda_file, void *dirent, filldir_t filldir)
 {
-        int result = 0;
 	struct dentry *coda_dentry = coda_file->f_dentry;
-	struct inode *coda_inode = coda_dentry->d_inode;
-	struct coda_inode_info *cii = ITOC(coda_inode);
-	struct file *host_file = cii->c_container;
+	struct coda_file_info *cfi;
+	struct file *host_file;
 
-	if (!host_file) BUG();
+	cfi = CODA_FTOC(coda_file);
+	if (!cfi || cfi->cfi_magic != CODA_MAGIC) BUG();
+	host_file = cfi->cfi_container;
 
 	coda_vfs_stat.readdir++;
 
-	/* Access to both host and coda f_pos fields is serialized on the
-	 * coda_file->f_dentry->d_inode->i_sem which has already been taken by
-	 * vfs_readdir. Userspace shouldn't 'play' with the container file as
-	 * long as the file is held open. */
-	host_file->f_pos = coda_file->f_pos;
-
-	if ( !host_file->f_op->readdir )
-		result = coda_venus_readdir(host_file, filldir, dirent,
-					    coda_dentry);
-	else
-		result = vfs_readdir(host_file, filldir, dirent);
+	if ( host_file->f_op->readdir )
+		/* potemkin case: we were handed a directory inode */
+		return vfs_readdir(host_file, filldir, dirent);
 
-	coda_file->f_pos = host_file->f_pos;
-	return result;
+	/* Venus: we must read Venus dirents from the file */
+	return coda_venus_readdir(host_file, filldir, dirent, coda_dentry);
+}
+
+static inline unsigned int CDT2DT(unsigned char cdt)
+{
+	unsigned int dt;
+
+	switch(cdt) {
+	case CDT_UNKNOWN: dt = DT_UNKNOWN; break;
+	case CDT_FIFO:	  dt = DT_FIFO;    break;
+	case CDT_CHR:	  dt = DT_CHR;     break;
+	case CDT_DIR:	  dt = DT_DIR;     break;
+	case CDT_BLK:	  dt = DT_BLK;     break;
+	case CDT_REG:	  dt = DT_REG;     break;
+	case CDT_LNK:	  dt = DT_LNK;     break;
+	case CDT_SOCK:	  dt = DT_SOCK;    break;
+	case CDT_WHT:	  dt = DT_WHT;     break;
+	default:	  dt = DT_UNKNOWN; break;
+	}
+	return dt;
 }
 
 /* support routines */
@@ -522,6 +533,7 @@
 	struct venus_dirent *vdir;
 	unsigned long vdir_size =
 	    (unsigned long)(&((struct venus_dirent *)0)->d_name);
+	unsigned int type;
 	struct qstr name;
 	ino_t ino;
 	int ret, i;
@@ -561,8 +573,7 @@
 			ret = -EBADF;
 			break;
 		}
-
-		/* validate whether the directory entry makes sense */
+		/* validate whether the directory file actually makes sense */
 		if (vdir->d_reclen < vdir_size + vdir->d_namlen ||
 		    vdir->d_namlen > CODA_MAXNAMLEN) {
 			printk("coda_venus_readdir: Invalid dir: %ld\n",
@@ -581,15 +592,17 @@
 
 		/* skip null entries */
 		if (vdir->d_fileno && name.len) {
-			/* try to look for this entry in the dcache, that way
-			 * userspace doesn't have to worry about breaking old
-			 * getcwd implementation by having mismatched inode
-			 * numbers for internal volume mountpoints. */
+			/* try to look up this entry in the dcache, that way
+			 * userspace doesn't have to worry about breaking
+			 * getcwd by having mismatched inode numbers for
+			 * internal volume mountpoints. */
 			ino = find_inode_number(dir, &name);
 			if (!ino) ino = vdir->d_fileno;
 
+			type = CDT2DT(vdir->d_type);
 			ret = filldir(dirent, name.name, name.len, filp->f_pos,
-				      ino, DT_UNKNOWN);
+				      ino, type); 
+			/* failure means no space for filling in this round */
 			if (ret < 0) break;
 			result++;
 		}
@@ -715,7 +728,6 @@
 			goto return_bad_inode;
 		
 		coda_flag_inode_children(inode, C_FLUSH);
-		
 		cii->c_flags &= ~(C_VATTR | C_PURGE | C_FLUSH);
 	}
 
@@ -724,11 +736,6 @@
 	return 0;
 
 return_bad_inode:
-        inode->i_mapping = &inode->i_data;
-	if (cii->c_container) {
-		fput(cii->c_container);
-		cii->c_container = NULL;
-	}
 	make_bad_inode(inode);
 	unlock_kernel();
 	return -EIO;
diff -urN linux-2.4.19-pre5/fs/coda/file.c linux-2.4.19-pre6/fs/coda/file.c
--- linux-2.4.19-pre5/fs/coda/file.c	Thu Apr  4 22:04:27 2002
+++ linux-2.4.19-pre6/fs/coda/file.c	Thu Apr  4 22:05:12 2002
@@ -16,7 +16,6 @@
 #include <linux/errno.h>
 #include <linux/locks.h>
 #include <linux/smp_lock.h>
-#include <asm/segment.h>
 #include <linux/string.h>
 #include <asm/uaccess.h>
 
@@ -31,250 +30,203 @@
 int use_coda_close;
 
 static ssize_t
-coda_file_read(struct file *file, char *buf, size_t count, loff_t *ppos)
+coda_file_read(struct file *coda_file, char *buf, size_t count, loff_t *ppos)
 {
-	struct inode *inode = file->f_dentry->d_inode;
-	struct coda_inode_info *cii = ITOC(inode);
-	struct file *cfile;
-	ssize_t ret;
+	struct coda_file_info *cfi;
+	struct file *host_file;
 
-	cfile = cii->c_container;
-	if (!cfile) BUG();
+	cfi = CODA_FTOC(coda_file);
+	if (!cfi || cfi->cfi_magic != CODA_MAGIC) BUG();
+	host_file = cfi->cfi_container;
 
-	if (!cfile->f_op || !cfile->f_op->read)
+	if (!host_file->f_op || !host_file->f_op->read)
 		return -EINVAL;
 
-	down(&inode->i_sem);
-	ret = cfile->f_op->read(cfile, buf, count, ppos);
-	UPDATE_ATIME(inode);
-	up(&inode->i_sem);
-
-	return ret;
+	return host_file->f_op->read(host_file, buf, count, ppos);
 }
 
 static ssize_t
-coda_file_write(struct file *file,const char *buf,size_t count,loff_t *ppos)
+coda_file_write(struct file *coda_file, const char *buf, size_t count, loff_t *ppos)
 {
-	struct inode *cinode, *inode = file->f_dentry->d_inode;
-	struct coda_inode_info *cii = ITOC(inode);
-	struct file *cfile;
+	struct inode *host_inode, *coda_inode = coda_file->f_dentry->d_inode;
+	struct coda_file_info *cfi;
+	struct file *host_file;
 	ssize_t ret;
-	int flags;
 
-	cfile = cii->c_container;
-	if (!cfile) BUG();
+	cfi = CODA_FTOC(coda_file);
+	if (!cfi || cfi->cfi_magic != CODA_MAGIC) BUG();
+	host_file = cfi->cfi_container;
 
-	if (!cfile->f_op || !cfile->f_op->write)
+	if (!host_file->f_op || !host_file->f_op->write)
 		return -EINVAL;
 
-	cinode = cfile->f_dentry->d_inode;
-	down(&inode->i_sem);
-	flags = cfile->f_flags;
-        cfile->f_flags |= file->f_flags & (O_APPEND | O_SYNC);
-
-	ret = cfile->f_op->write(cfile, buf, count, ppos);
-
-	cfile->f_flags = flags;
-	inode->i_size = cinode->i_size;
-	inode->i_blocks = (inode->i_size + 511) >> 9;
-	inode->i_mtime = inode->i_ctime = CURRENT_TIME;
-	up(&inode->i_sem);
+	host_inode = host_file->f_dentry->d_inode;
+	down(&coda_inode->i_sem);
+
+	ret = host_file->f_op->write(host_file, buf, count, ppos);
+
+	coda_inode->i_size = host_inode->i_size;
+	coda_inode->i_blocks = (coda_inode->i_size + 511) >> 9;
+	coda_inode->i_mtime = coda_inode->i_ctime = CURRENT_TIME;
+	up(&coda_inode->i_sem);
 
 	return ret;
 }
 
 static int
-coda_file_mmap(struct file *file, struct vm_area_struct *vma)
+coda_file_mmap(struct file *coda_file, struct vm_area_struct *vma)
 {
-	struct inode *inode = file->f_dentry->d_inode;
-	struct coda_inode_info *cii = ITOC(inode);
-	struct file *cfile;
-	int ret;
-
-	cfile = cii->c_container;
+	struct coda_file_info *cfi;
+	struct file *host_file;
 
-	if (!cfile) BUG();
+	cfi = CODA_FTOC(coda_file);
+	if (!cfi || cfi->cfi_magic != CODA_MAGIC) BUG();
+	host_file = cfi->cfi_container;
 
-	if (!cfile->f_op || !cfile->f_op->mmap)
+	if (!host_file->f_op || !host_file->f_op->mmap)
 		return -ENODEV;
 
-	down(&inode->i_sem);
-	ret = cfile->f_op->mmap(cfile, vma);
-	UPDATE_ATIME(inode);
-	up(&inode->i_sem);
-
-	return ret;
+	return host_file->f_op->mmap(host_file, vma);
 }
 
-int coda_open(struct inode *i, struct file *f)
+int coda_open(struct inode *coda_inode, struct file *coda_file)
 {
-	struct file *fh = NULL;
-	int error = 0;
-	unsigned short flags = f->f_flags & (~O_EXCL);
+	struct file *host_file = NULL;
+	int error;
+	unsigned short flags = coda_file->f_flags & (~O_EXCL);
 	unsigned short coda_flags = coda_flags_to_cflags(flags);
-	struct coda_cred *cred;
-	struct coda_inode_info *cii;
+	struct coda_file_info *cfi;
 
 	lock_kernel();
 	coda_vfs_stat.open++;
 
-	CDEBUG(D_SPECIAL, "OPEN inode number: %ld, count %d, flags %o.\n", 
-	       f->f_dentry->d_inode->i_ino, atomic_read(&f->f_dentry->d_count), flags);
+	cfi = kmalloc(sizeof(struct coda_file_info), GFP_KERNEL);
+	if (!cfi) {
+		unlock_kernel();
+		return -ENOMEM;
+	}
 
-	error = venus_open(i->i_sb, coda_i2f(i), coda_flags, &fh); 
-	if (error || !fh) {
-	        CDEBUG(D_FILE, "coda_open: venus_open result %d\n", error);
+	error = venus_open(coda_inode->i_sb, coda_i2f(coda_inode), coda_flags,
+			   &host_file); 
+	if (error || !host_file) {
+		kfree(cfi);
 		unlock_kernel();
 		return error;
 	}
 
-	/* coda_upcall returns filehandle of container file object */
-	cii = ITOC(i);
-	if (cii->c_container)
-		fput(cii->c_container);
-
-	cii->c_contcount++;
-	cii->c_container = fh;
-	i->i_mapping = &cii->c_container->f_dentry->d_inode->i_data;
-
-	cred = kmalloc(sizeof(struct coda_cred), GFP_KERNEL);
-
-	/* If the allocation failed, we'll just muddle on. This actually works
-	 * fine for normal cases. (i.e. when open credentials are the same as
-	 * close credentials) */
-	if (cred) {
-		coda_load_creds(cred);
-		f->private_data = cred;
-	}
+	host_file->f_flags |= coda_file->f_flags & (O_APPEND | O_SYNC);
+
+	cfi->cfi_magic = CODA_MAGIC;
+	cfi->cfi_container = host_file;
+	coda_load_creds(&cfi->cfi_cred);
+
+	if (coda_file->private_data != NULL) BUG();
+	coda_file->private_data = cfi;
 
-	CDEBUG(D_FILE, "result %d, coda i->i_count is %d, cii->contcount is %d for ino %ld\n", 
-	       error, atomic_read(&i->i_count), cii->c_contcount, i->i_ino);
-	CDEBUG(D_FILE, "cache ino: %ld, count %d, ops %p\n", 
-	       fh->f_dentry->d_inode->i_ino,
-	       atomic_read(&fh->f_dentry->d_inode->i_count),
-               fh->f_dentry->d_inode->i_op);
 	unlock_kernel();
 	return 0;
 }
 
-
-int coda_flush(struct file *file)
+int coda_flush(struct file *coda_file)
 {
-	unsigned short flags = (file->f_flags) & (~O_EXCL);
-	unsigned short cflags;
-	struct coda_inode_info *cii;
-	struct file *cfile;
-	struct inode *cinode, *inode;
+	unsigned short flags = coda_file->f_flags & ~O_EXCL;
+	unsigned short coda_flags = coda_flags_to_cflags(flags);
+	struct coda_file_info *cfi;
+	struct inode *coda_inode;
 	int err = 0, fcnt;
 
 	coda_vfs_stat.flush++;
 
 	/* No need to make an upcall when we have not made any modifications
 	 * to the file */
-	if ((file->f_flags & O_ACCMODE) == O_RDONLY)
+	if ((coda_file->f_flags & O_ACCMODE) == O_RDONLY)
 		return 0;
 
 	if (use_coda_close)
 		return 0;
 
-	fcnt = file_count(file);
+	fcnt = file_count(coda_file);
 	if (fcnt > 1) return 0;
 
-	cflags = coda_flags_to_cflags(flags);
+	coda_inode = coda_file->f_dentry->d_inode;
 
-	inode = file->f_dentry->d_inode;
-	cii = ITOC(inode);
-	cfile = cii->c_container;
-	if (!cfile) BUG();
+	cfi = CODA_FTOC(coda_file);
+	if (!cfi || cfi->cfi_magic != CODA_MAGIC) BUG();
 
-	cinode = cfile->f_dentry->d_inode;
+	err = venus_store(coda_inode->i_sb, coda_i2f(coda_inode), coda_flags,
+			  &cfi->cfi_cred);
 
-	CDEBUG(D_FILE, "FLUSH coda (file %p ct %d)\n", file, fcnt);
-
-	err = venus_store(inode->i_sb, coda_i2f(inode), cflags,
-                          (struct coda_cred *)file->private_data);
 	if (err == -EOPNOTSUPP) {
 		use_coda_close = 1;
 		err = 0;
 	}
 
-	CDEBUG(D_FILE, "coda_flush: result: %d\n", err);
 	return err;
 }
 
-int coda_release(struct inode *i, struct file *f)
+int coda_release(struct inode *coda_inode, struct file *coda_file)
 {
-	unsigned short flags = (f->f_flags) & (~O_EXCL);
-	unsigned short cflags = coda_flags_to_cflags(flags);
-	struct coda_inode_info *cii;
-	struct file *cfile;
+	unsigned short flags = (coda_file->f_flags) & (~O_EXCL);
+	unsigned short coda_flags = coda_flags_to_cflags(flags);
+	struct coda_file_info *cfi;
 	int err = 0;
 
 	lock_kernel();
 	coda_vfs_stat.release++;
  
 	if (!use_coda_close) {
-		err = venus_release(i->i_sb, coda_i2f(i), cflags);
+		err = venus_release(coda_inode->i_sb, coda_i2f(coda_inode),
+				    coda_flags);
 		if (err == -EOPNOTSUPP) {
 			use_coda_close = 1;
 			err = 0;
 		}
 	}
 
-	if (use_coda_close)
-		err = venus_close(i->i_sb, coda_i2f(i), cflags,
-                                  (struct coda_cred *)f->private_data);
+	cfi = CODA_FTOC(coda_file);
+	if (!cfi || cfi->cfi_magic != CODA_MAGIC) BUG();
 
-	cii = ITOC(i);
-	cfile = cii->c_container;
-	if (!cfile) BUG();
-
-	if (--cii->c_contcount) {
-		unlock_kernel();
-		return err;
-	}
+	if (use_coda_close)
+		err = venus_close(coda_inode->i_sb, coda_i2f(coda_inode),
+				  coda_flags, &cfi->cfi_cred);
 
-	i->i_mapping = &i->i_data;
-	fput(cfile);
-	cii->c_container = NULL;
-
-	if (f->private_data) {
-		kfree(f->private_data);
-		f->private_data = NULL;
-	}
+	fput(cfi->cfi_container);
+	kfree(coda_file->private_data);
+	coda_file->private_data = NULL;
 
 	unlock_kernel();
 	return err;
 }
 
-int coda_fsync(struct file *file, struct dentry *dentry, int datasync)
+int coda_fsync(struct file *coda_file, struct dentry *coda_dentry, int datasync)
 {
-	struct file *cfile;
-	struct dentry *cdentry;
-	struct inode *cinode, *inode = dentry->d_inode;
-	struct coda_inode_info *cii = ITOC(inode);
+	struct file *host_file;
+	struct dentry *host_dentry;
+	struct inode *host_inode, *coda_inode = coda_dentry->d_inode;
+	struct coda_file_info *cfi;
 	int err = 0;
 
-	if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
-	      S_ISLNK(inode->i_mode)))
+	if (!(S_ISREG(coda_inode->i_mode) || S_ISDIR(coda_inode->i_mode) ||
+	      S_ISLNK(coda_inode->i_mode)))
 		return -EINVAL;
 
-	cfile = cii->c_container;
-	if (!cfile) BUG();
+	cfi = CODA_FTOC(coda_file);
+	if (!cfi || cfi->cfi_magic != CODA_MAGIC) BUG();
+	host_file = cfi->cfi_container;
 
 	coda_vfs_stat.fsync++;
 
-	if (cfile->f_op && cfile->f_op->fsync) {
-		cdentry = cfile->f_dentry;
-		cinode = cdentry->d_inode;
-		down(&cinode->i_sem);
-		err = cfile->f_op->fsync(cfile, cdentry, datasync);
-		up(&cinode->i_sem);
+	if (host_file->f_op && host_file->f_op->fsync) {
+		host_dentry = host_file->f_dentry;
+		host_inode = host_dentry->d_inode;
+		down(&host_inode->i_sem);
+		err = host_file->f_op->fsync(host_file, host_dentry, datasync);
+		up(&host_inode->i_sem);
 	}
 
 	if ( !err && !datasync ) {
 		lock_kernel();
-		err = venus_fsync(inode->i_sb, coda_i2f(inode));
+		err = venus_fsync(coda_inode->i_sb, coda_i2f(coda_inode));
 		unlock_kernel();
 	}
 
diff -urN linux-2.4.19-pre5/fs/coda/inode.c linux-2.4.19-pre6/fs/coda/inode.c
--- linux-2.4.19-pre5/fs/coda/inode.c	Mon Feb 25 11:38:08 2002
+++ linux-2.4.19-pre6/fs/coda/inode.c	Thu Apr  4 22:05:12 2002
@@ -25,7 +25,6 @@
 
 #include <linux/fs.h>
 #include <linux/vmalloc.h>
-#include <asm/segment.h>
 
 #include <linux/coda.h>
 #include <linux/coda_linux.h>
@@ -189,22 +188,6 @@
 
         if (!sbi) BUG();
 
-#if 0
-	/* check if the inode is already initialized */
-	if (inode->u.generic_ip) {
-            printk("coda_read_inode: initialized inode");
-            return;
-        }
-
-	inode->u.generic_ip = cii_alloc();
-	if (!inode->u.generic_ip) {
-		CDEBUG(D_CNODE, "coda_read_inode: failed to allocate inode info\n");
-		make_bad_inode(inode);
-		return;
-	}
-	memset(inode->u.generic_ip, 0, sizeof(struct coda_inode_info));
-#endif
-
 	cii = ITOC(inode);
 	if (!coda_isnullfid(&cii->c_fid)) {
             printk("coda_read_inode: initialized inode");
@@ -222,30 +205,21 @@
 	       inode->i_ino, atomic_read(&inode->i_count));        
 	CDEBUG(D_DOWNCALL, "clearing inode: %ld, %x\n", inode->i_ino, cii->c_flags);
 
-	if (cii->c_container) BUG();
-	
         list_del_init(&cii->c_cilist);
-	inode->i_mapping = &inode->i_data;
 	coda_cache_clear_inode(inode);
-
-#if 0
-	cii_free(inode->u.generic_ip);
-	inode->u.generic_ip = NULL;
-#endif
 }
 
 int coda_notify_change(struct dentry *de, struct iattr *iattr)
 {
 	struct inode *inode = de->d_inode;
-        struct coda_vattr vattr;
-        int error;
-	
-	inode->i_ctime = CURRENT_TIME;
+	struct coda_vattr vattr;
+	int error;
 
-        memset(&vattr, 0, sizeof(vattr)); 
-        coda_iattr_to_vattr(iattr, &vattr);
+	memset(&vattr, 0, sizeof(vattr)); 
 
-        vattr.va_type = C_VNON; /* cannot set type */
+	inode->i_ctime = CURRENT_TIME;
+	coda_iattr_to_vattr(iattr, &vattr);
+	vattr.va_type = C_VNON; /* cannot set type */
 	CDEBUG(D_SUPER, "vattr.va_mode %o\n", vattr.va_mode);
 
 	/* Venus is responsible for truncating the container-file!!! */
diff -urN linux-2.4.19-pre5/fs/coda/pioctl.c linux-2.4.19-pre6/fs/coda/pioctl.c
--- linux-2.4.19-pre5/fs/coda/pioctl.c	Fri Dec 21 09:41:55 2001
+++ linux-2.4.19-pre6/fs/coda/pioctl.c	Thu Apr  4 22:05:12 2002
@@ -14,7 +14,6 @@
 #include <linux/stat.h>
 #include <linux/errno.h>
 #include <linux/locks.h>
-#include <asm/segment.h>
 #include <linux/string.h>
 #define __NO_VERSION__
 #include <linux/module.h>
diff -urN linux-2.4.19-pre5/fs/coda/psdev.c linux-2.4.19-pre6/fs/coda/psdev.c
--- linux-2.4.19-pre5/fs/coda/psdev.c	Mon Feb 25 11:38:08 2002
+++ linux-2.4.19-pre6/fs/coda/psdev.c	Thu Apr  4 22:05:12 2002
@@ -38,7 +38,6 @@
 #include <linux/list.h>
 #include <linux/smp_lock.h>
 #include <asm/io.h>
-#include <asm/segment.h>
 #include <asm/system.h>
 #include <asm/poll.h>
 #include <asm/uaccess.h>
diff -urN linux-2.4.19-pre5/fs/coda/sysctl.c linux-2.4.19-pre6/fs/coda/sysctl.c
--- linux-2.4.19-pre5/fs/coda/sysctl.c	Fri Dec 21 09:41:55 2001
+++ linux-2.4.19-pre6/fs/coda/sysctl.c	Thu Apr  4 22:05:12 2002
@@ -21,7 +21,6 @@
 #include <linux/stat.h>
 #include <linux/ctype.h>
 #include <asm/bitops.h>
-#include <asm/segment.h>
 #include <asm/uaccess.h>
 #include <linux/utsname.h>
 #define __NO_VERSION__
@@ -51,7 +50,6 @@
 
 static ctl_table coda_table[] = {
 	{CODA_DEBUG, "debug", &coda_debug, sizeof(int), 0644, NULL, &proc_dointvec},
-	{CODA_ENTRY, "printentry", &coda_print_entry, sizeof(int), 0644, NULL, &proc_dointvec},
  	{CODA_MC, "accesscache", &coda_access_cache, sizeof(int), 0644, NULL, &proc_dointvec}, 
  	{CODA_TIMEOUT, "timeout", &coda_timeout, sizeof(int), 0644, NULL, &proc_dointvec},
  	{CODA_HARD, "hard", &coda_hard, sizeof(int), 0644, NULL, &proc_dointvec},
diff -urN linux-2.4.19-pre5/fs/coda/upcall.c linux-2.4.19-pre6/fs/coda/upcall.c
--- linux-2.4.19-pre5/fs/coda/upcall.c	Fri Dec 21 09:41:55 2001
+++ linux-2.4.19-pre6/fs/coda/upcall.c	Thu Apr  4 22:05:12 2002
@@ -15,7 +15,6 @@
  */
 
 #include <asm/system.h>
-#include <asm/segment.h>
 #include <asm/signal.h>
 #include <linux/signal.h>
 
@@ -176,10 +175,7 @@
 	insize = SIZE(store);
 	UPARG(CODA_STORE);
 	
-	if ( cred ) {
-		memcpy(&(inp->ih.cred), cred, sizeof(*cred));
-	} else 
-		printk("CODA: store without valid file creds.\n");
+	memcpy(&(inp->ih.cred), cred, sizeof(*cred));
 	
         inp->coda_store.VFid = *fid;
         inp->coda_store.flags = flags;
@@ -218,10 +214,7 @@
 	insize = SIZE(release);
 	UPARG(CODA_CLOSE);
 	
-	if ( cred ) {
-		memcpy(&(inp->ih.cred), cred, sizeof(*cred));
-	} else 
-		printk("CODA: close without valid file creds.\n");
+	memcpy(&(inp->ih.cred), cred, sizeof(*cred));
 	
         inp->coda_close.VFid = *fid;
         inp->coda_close.flags = flags;
diff -urN linux-2.4.19-pre5/fs/devfs/base.c linux-2.4.19-pre6/fs/devfs/base.c
--- linux-2.4.19-pre5/fs/devfs/base.c	Mon Feb 25 11:38:08 2002
+++ linux-2.4.19-pre6/fs/devfs/base.c	Thu Apr  4 22:05:12 2002
@@ -608,6 +608,13 @@
 	       Fixed deadlock bug in <devfs_d_revalidate_wait>.
 	       Tag VFS deletable in <devfs_mk_symlink> if handle ignored.
   v1.10
+    20020129   Richard Gooch <rgooch@atnf.csiro.au>
+	       Added KERN_* to remaining messages.
+	       Cleaned up declaration of <stat_read>.
+  v1.11
+    20020219   Richard Gooch <rgooch@atnf.csiro.au>
+	       Changed <devfs_rmdir> to allow later additions if not yet empty.
+  v1.12
 */
 #include <linux/types.h>
 #include <linux/errno.h>
@@ -640,7 +647,7 @@
 #include <asm/bitops.h>
 #include <asm/atomic.h>
 
-#define DEVFS_VERSION            "1.10 (20020120)"
+#define DEVFS_VERSION            "1.12 (20020219)"
 
 #define DEVFS_NAME "devfs"
 
@@ -848,8 +855,8 @@
 			 unsigned int cmd, unsigned long arg);
 static int devfsd_close (struct inode *inode, struct file *file);
 #ifdef CONFIG_DEVFS_DEBUG
-static int stat_read (struct file *file, char *buf, size_t len,
-			    loff_t *ppos);
+static ssize_t stat_read (struct file *file, char *buf, size_t len,
+			  loff_t *ppos);
 static struct file_operations stat_fops =
 {
     read:    stat_read,
@@ -2431,10 +2438,10 @@
     if (bdops->check_media_change == NULL) goto out;
     if ( !bdops->check_media_change (dev) ) goto out;
     retval = 1;
-    printk ( KERN_DEBUG "VFS: Disk change detected on device %s\n",
+    printk (KERN_DEBUG "VFS: Disk change detected on device %s\n",
 	     kdevname (dev) );
-    if (invalidate_device(dev, 0))
-	printk("VFS: busy inodes on changed media..\n");
+    if ( invalidate_device (dev, 0) )
+	printk (KERN_WARNING "VFS: busy inodes on changed media..\n");
     /*  Ugly hack to disable messages about unable to read partition table  */
     tmp = warn_no_part;
     warn_no_part = 0;
@@ -3112,10 +3119,10 @@
     if (de == NULL) return -ENOENT;
     if ( !S_ISDIR (de->mode) ) return -ENOTDIR;
     if (!de->vfs_deletable) return -EPERM;
-    /*  First ensure the directory is empty and will stay thay way  */
+    /*  First ensure the directory is empty and will stay that way  */
     write_lock (&de->u.dir.lock);
-    de->u.dir.no_more_additions = TRUE;
     if (de->u.dir.first) err = -ENOTEMPTY;
+    else de->u.dir.no_more_additions = TRUE;
     write_unlock (&de->u.dir.lock);
     if (err) return err;
     /*  Now unhook the directory from it's parent  */
@@ -3237,7 +3244,7 @@
     return sb;
 
 out_no_root:
-    printk ("devfs_read_super: get root inode failed\n");
+    PRINTK ("(): get root inode failed\n");
     if (root_inode) iput (root_inode);
     return NULL;
 }   /*  End Function devfs_read_super  */
@@ -3464,7 +3471,7 @@
 {
     int err;
 
-    printk ("%s: v%s Richard Gooch (rgooch@atnf.csiro.au)\n",
+    printk (KERN_INFO "%s: v%s Richard Gooch (rgooch@atnf.csiro.au)\n",
 	    DEVFS_NAME, DEVFS_VERSION);
     devfsd_buf_cache = kmem_cache_create ("devfsd_event",
 					  sizeof (struct devfsd_buf_entry),
@@ -3472,9 +3479,9 @@
     if (!devfsd_buf_cache) OOPS ("(): unable to allocate event slab\n");
 #ifdef CONFIG_DEVFS_DEBUG
     devfs_debug = devfs_debug_init;
-    printk ("%s: devfs_debug: 0x%0x\n", DEVFS_NAME, devfs_debug);
+    printk (KERN_INFO "%s: devfs_debug: 0x%0x\n", DEVFS_NAME, devfs_debug);
 #endif
-    printk ("%s: boot_options: 0x%0x\n", DEVFS_NAME, boot_options);
+    printk (KERN_INFO "%s: boot_options: 0x%0x\n", DEVFS_NAME, boot_options);
     err = register_filesystem (&devfs_fs_type);
     if (!err)
     {
@@ -3491,8 +3498,8 @@
 
     if ( !(boot_options & OPTION_MOUNT) ) return;
     err = do_mount ("none", "/dev", "devfs", 0, "");
-    if (err == 0) printk ("Mounted devfs on /dev\n");
-    else printk ("Warning: unable to mount devfs, err: %d\n", err);
+    if (err == 0) printk (KERN_INFO "Mounted devfs on /dev\n");
+    else PRINTK ("(): unable to mount devfs, err: %d\n", err);
 }   /*  End Function mount_devfs_fs  */
 
 module_init(init_devfs_fs)
diff -urN linux-2.4.19-pre5/fs/devfs/util.c linux-2.4.19-pre6/fs/devfs/util.c
--- linux-2.4.19-pre5/fs/devfs/util.c	Thu Oct 11 09:43:30 2001
+++ linux-2.4.19-pre6/fs/devfs/util.c	Thu Apr  4 22:05:12 2002
@@ -1,6 +1,6 @@
 /*  devfs (Device FileSystem) utilities.
 
-    Copyright (C) 1999-2001  Richard Gooch
+    Copyright (C) 1999-2002  Richard Gooch
 
     This library is free software; you can redistribute it and/or
     modify it under the terms of the GNU Library General Public
@@ -48,6 +48,12 @@
     20010818   Richard Gooch <rgooch@atnf.csiro.au>
                Updated major masks up to Linus' "no new majors" proclamation.
 	       Block: were 126 now 122 free, char: were 26 now 19 free.
+    20020324   Richard Gooch <rgooch@atnf.csiro.au>
+               Fixed bug in <devfs_alloc_unique_number>: was clearing beyond
+	       bitfield.
+    20020326   Richard Gooch <rgooch@atnf.csiro.au>
+               Fixed bitfield data type for <devfs_*alloc_devnum>.
+               Made major bitfield type and initialiser 64 bit safe.
 */
 #include <linux/module.h>
 #include <linux/init.h>
@@ -61,67 +67,6 @@
 /*  Private functions follow  */
 
 /**
- *	_devfs_convert_name - Convert from an old style location-based name to new style.
- *	@new: The new name will be written here.
- *	@old: The old name.
- *	@disc: If true, disc partitioning information should be processed.
- */
-
-static void __init _devfs_convert_name (char *new, const char *old, int disc)
-{
-    int host, bus, target, lun;
-    char *ptr;
-    char part[8];
-
-    /*  Decode "c#b#t#u#"  */
-    if (old[0] != 'c') return;
-    host = simple_strtol (old + 1, &ptr, 10);
-    if (ptr[0] != 'b') return;
-    bus = simple_strtol (ptr + 1, &ptr, 10);
-    if (ptr[0] != 't') return;
-    target = simple_strtol (ptr + 1, &ptr, 10);
-    if (ptr[0] != 'u') return;
-    lun = simple_strtol (ptr + 1, &ptr, 10);
-    if (disc)
-    {
-	/*  Decode "p#"  */
-	if (ptr[0] == 'p') sprintf (part, "part%s", ptr + 1);
-	else strcpy (part, "disc");
-    }
-    else part[0] = '\0';
-    sprintf (new, "/host%d/bus%d/target%d/lun%d/%s",
-	     host, bus, target, lun, part);
-}   /*  End Function _devfs_convert_name  */
-
-
-/*  Public functions follow  */
-
-/**
- *	devfs_make_root - Create the root FS device entry if required.
- *	@name: The name of the root FS device, as passed by "root=".
- */
-
-void __init devfs_make_root (const char *name)
-{
-    char dest[64];
-
-    if ( (strncmp (name, "sd/", 3) == 0) || (strncmp (name, "sr/", 3) == 0) )
-    {
-	strcpy (dest, "../scsi");
-	_devfs_convert_name (dest + 7, name + 3, (name[1] == 'd') ? 1 : 0);
-    }
-    else if ( (strncmp (name, "ide/hd/", 7) == 0) ||
-	      (strncmp (name, "ide/cd/", 7) == 0) )
-    {
-	strcpy (dest, "..");
-	_devfs_convert_name (dest + 2, name + 7, (name[4] == 'h') ? 1 : 0);
-    }
-    else return;
-    devfs_mk_symlink (NULL, name, DEVFS_FL_DEFAULT, dest, NULL, NULL);
-}   /*  End Function devfs_make_root  */
-
-
-/**
  *	devfs_register_tape - Register a tape device in the "/dev/tapes" hierarchy.
  *	@de: Any tape device entry in the device directory.
  */
@@ -186,8 +131,13 @@
 struct major_list
 {
     spinlock_t lock;
-    __u32 bits[8];
+    unsigned long bits[256 / BITS_PER_LONG];
 };
+#if BITS_PER_LONG == 32
+#  define INITIALISER64(low,high) (low), (high)
+#else
+#  define INITIALISER64(low,high) ( (high) << 32 | (low) )
+#endif
 
 /*  Block majors already assigned:
     0-3, 7-9, 11-63, 65-99, 101-113, 120-127, 199, 201, 240-255
@@ -195,14 +145,11 @@
 */
 static struct major_list block_major_list =
 {SPIN_LOCK_UNLOCKED,
-    {0xfffffb8f,  /*  Majors 0   to 31   */
-     0xffffffff,  /*  Majors 32  to 63   */
-     0xfffffffe,  /*  Majors 64  to 95   */
-     0xff03ffef,  /*  Majors 96  to 127  */
-     0x00000000,  /*  Majors 128 to 159  */
-     0x00000000,  /*  Majors 160 to 191  */
-     0x00000280,  /*  Majors 192 to 223  */
-     0xffff0000}  /*  Majors 224 to 255  */
+    {INITIALISER64 (0xfffffb8f, 0xffffffff),  /*  Majors 0-31,    32-63    */
+     INITIALISER64 (0xfffffffe, 0xff03ffef),  /*  Majors 64-95,   96-127   */
+     INITIALISER64 (0x00000000, 0x00000000),  /*  Majors 128-159, 160-191  */
+     INITIALISER64 (0x00000280, 0xffff0000),  /*  Majors 192-223, 224-255  */
+    }
 };
 
 /*  Char majors already assigned:
@@ -211,14 +158,11 @@
 */
 static struct major_list char_major_list =
 {SPIN_LOCK_UNLOCKED,
-    {0xfffffeff,  /*  Majors 0   to 31   */
-     0xffffffff,  /*  Majors 32  to 63   */
-     0xffffffff,  /*  Majors 64  to 95   */
-     0xffffffff,  /*  Majors 96  to 127  */
-     0x7cffffff,  /*  Majors 128 to 159  */
-     0xffffffff,  /*  Majors 160 to 191  */
-     0x3f0fffff,  /*  Majors 192 to 223  */
-     0xffff007f}  /*  Majors 224 to 255  */
+    {INITIALISER64 (0xfffffeff, 0xffffffff),  /*  Majors 0-31,    32-63    */
+     INITIALISER64 (0xffffffff, 0xffffffff),  /*  Majors 64-95,   96-127   */
+     INITIALISER64 (0x7cffffff, 0xffffffff),  /*  Majors 128-159, 160-191  */
+     INITIALISER64 (0x3f0fffff, 0xffff007f),  /*  Majors 192-223, 224-255  */
+    }
 };
 
 
@@ -273,7 +217,7 @@
 struct minor_list
 {
     int major;
-    __u32 bits[8];
+    unsigned long bits[256 / BITS_PER_LONG];
     struct minor_list *next;
 };
 
@@ -416,7 +360,6 @@
 {
     int number;
     unsigned int length;
-    __u32 *bits;
 
     /*  Get around stupid lack of semaphore initialiser  */
     spin_lock (&space->init_lock);
@@ -429,6 +372,8 @@
     down (&space->semaphore);
     if (space->num_free < 1)
     {
+	void *bits;
+
 	if (space->length < 16) length = 16;
 	else length = space->length << 1;
 	if ( ( bits = vmalloc (length) ) == NULL )
diff -urN linux-2.4.19-pre5/fs/fat/inode.c linux-2.4.19-pre6/fs/fat/inode.c
--- linux-2.4.19-pre5/fs/fat/inode.c	Mon Feb 25 11:38:08 2002
+++ linux-2.4.19-pre6/fs/fat/inode.c	Thu Apr  4 22:05:12 2002
@@ -434,12 +434,13 @@
 	struct dentry *result;
 
 	if (fhtype != 3)
-		return NULL;
+		return ERR_PTR(-ESTALE);
 	if (len < 5)
-		return NULL;
+		return ERR_PTR(-ESTALE);
+	/* We cannot find the parent,
+	   It better just *be* there */
 	if (parent)
-		return NULL; /* We cannot find the parent,
-				It better just *be* there */
+		return ERR_PTR(-ESTALE);
 
 	inode = iget(sb, fh[0]);
 	if (!inode || is_bad_inode(inode) ||
@@ -501,6 +502,7 @@
 		iput(inode);
 		return ERR_PTR(-ENOMEM);
 	}
+	result->d_op = sb->s_root->d_op;
 	result->d_flags |= DCACHE_NFSD_DISCONNECTED;
 	return result;
 
diff -urN linux-2.4.19-pre5/fs/fcntl.c linux-2.4.19-pre6/fs/fcntl.c
--- linux-2.4.19-pre5/fs/fcntl.c	Mon Sep 17 13:16:30 2001
+++ linux-2.4.19-pre6/fs/fcntl.c	Thu Apr  4 22:05:12 2002
@@ -66,6 +66,10 @@
 
 	write_lock(&files->file_lock);
 	
+	error = -EINVAL;
+	if (orig_start >= current->rlim[RLIMIT_NOFILE].rlim_cur)
+		goto out;
+
 repeat:
 	/*
 	 * Someone might have closed fd's in the range
diff -urN linux-2.4.19-pre5/fs/filesystems.c linux-2.4.19-pre6/fs/filesystems.c
--- linux-2.4.19-pre5/fs/filesystems.c	Tue Apr 17 23:23:12 2001
+++ linux-2.4.19-pre6/fs/filesystems.c	Thu Apr  4 22:05:12 2002
@@ -3,7 +3,7 @@
  *
  *  Copyright (C) 1991, 1992  Linus Torvalds
  *
- *  table of configured filesystems
+ *  nfsservctl system-call when nfsd is not compiled in.
  */
 
 #include <linux/config.h>
@@ -13,28 +13,28 @@
 #include <linux/kmod.h>
 #include <linux/nfsd/interface.h>
 
-#if defined(CONFIG_NFSD_MODULE)
-struct nfsd_linkage *nfsd_linkage = NULL;
+#if ! defined(CONFIG_NFSD)
+struct nfsd_linkage *nfsd_linkage;
 
 long
 asmlinkage sys_nfsservctl(int cmd, void *argp, void *resp)
 {
 	int ret = -ENOSYS;
 	
+#if defined(CONFIG_MODULES)
 	lock_kernel();
 
 	if (nfsd_linkage ||
-	    (request_module ("nfsd") == 0 && nfsd_linkage))
+	    (request_module ("nfsd") == 0 && nfsd_linkage)) {
+		__MOD_INC_USE_COUNT(nfsd_linkage->owner);
+		unlock_kernel();
 		ret = nfsd_linkage->do_nfsservctl(cmd, argp, resp);
-
-	unlock_kernel();
+		__MOD_DEC_USE_COUNT(nfsd_linkage->owner);
+	} else
+		unlock_kernel();
+#endif
 	return ret;
 }
 EXPORT_SYMBOL(nfsd_linkage);
 
-#elif ! defined (CONFIG_NFSD)
-asmlinkage int sys_nfsservctl(int cmd, void *argp, void *resp)
-{
-	return -ENOSYS;
-}
 #endif /* CONFIG_NFSD */
diff -urN linux-2.4.19-pre5/fs/jbd/journal.c linux-2.4.19-pre6/fs/jbd/journal.c
--- linux-2.4.19-pre5/fs/jbd/journal.c	Mon Feb 25 11:38:08 2002
+++ linux-2.4.19-pre6/fs/jbd/journal.c	Thu Apr  4 22:05:12 2002
@@ -204,6 +204,7 @@
 
 	lock_kernel();
 	daemonize();
+	reparent_to_init();
 	spin_lock_irq(&current->sigmask_lock);
 	sigfillset(&current->blocked);
 	recalc_sigpending(current);
@@ -267,6 +268,7 @@
 
 	journal->j_task = NULL;
 	wake_up(&journal->j_wait_done_commit);
+	unlock_kernel();
 	jbd_debug(1, "Journal thread exiting.\n");
 	return 0;
 }
diff -urN linux-2.4.19-pre5/fs/lockd/svc4proc.c linux-2.4.19-pre6/fs/lockd/svc4proc.c
--- linux-2.4.19-pre5/fs/lockd/svc4proc.c	Mon Oct  1 13:45:47 2001
+++ linux-2.4.19-pre6/fs/lockd/svc4proc.c	Thu Apr  4 22:05:12 2002
@@ -447,11 +447,13 @@
 	if (nlmsvc_ops != NULL) {
 		struct svc_client	*clnt;
 		saddr.sin_addr.s_addr = argp->addr;
+		nlmsvc_ops->exp_readlock();
 		if ((clnt = nlmsvc_ops->exp_getclient(&saddr)) != NULL 
 		 && (host = nlm_lookup_host(clnt, &saddr, 0, 0)) != NULL) {
 			nlmsvc_free_host_resources(host);
 		}
 		nlm_release_host(host);
+		nlmsvc_ops->exp_unlock();
 	}
 
 	return rpc_success;
diff -urN linux-2.4.19-pre5/fs/lockd/svcproc.c linux-2.4.19-pre6/fs/lockd/svcproc.c
--- linux-2.4.19-pre5/fs/lockd/svcproc.c	Thu Oct 11 07:52:18 2001
+++ linux-2.4.19-pre6/fs/lockd/svcproc.c	Thu Apr  4 22:05:12 2002
@@ -474,12 +474,14 @@
 	/* If we run on an NFS server, delete all locks held by the client */
 	if (nlmsvc_ops != NULL) {
 		struct svc_client	*clnt;
-		saddr.sin_addr.s_addr = argp->addr;	
+		saddr.sin_addr.s_addr = argp->addr;
+		nlmsvc_ops->exp_readlock();
 		if ((clnt = nlmsvc_ops->exp_getclient(&saddr)) != NULL 
 		 && (host = nlm_lookup_host(clnt, &saddr, 0, 0)) != NULL) {
 			nlmsvc_free_host_resources(host);
 		}
 		nlm_release_host(host);
+		nlmsvc_ops->exp_unlock();
 	}
 
 	return rpc_success;
diff -urN linux-2.4.19-pre5/fs/namei.c linux-2.4.19-pre6/fs/namei.c
--- linux-2.4.19-pre5/fs/namei.c	Thu Apr  4 22:04:27 2002
+++ linux-2.4.19-pre6/fs/namei.c	Thu Apr  4 22:05:12 2002
@@ -903,6 +903,8 @@
 			return -EBUSY;
 	} else if (S_ISDIR(victim->d_inode->i_mode))
 		return -EISDIR;
+	if (IS_DEADDIR(dir))
+		return -ENOENT;
 	return 0;
 }
 
@@ -1395,9 +1397,7 @@
 
 	double_down(&dir->i_zombie, &dentry->d_inode->i_zombie);
 	d_unhash(dentry);
-	if (IS_DEADDIR(dir))
-		error = -ENOENT;
-	else if (d_mountpoint(dentry))
+	if (d_mountpoint(dentry))
 		error = -EBUSY;
 	else {
 		lock_kernel();
@@ -1763,9 +1763,7 @@
 	} else
 		double_down(&old_dir->i_zombie,
 			    &new_dir->i_zombie);
-	if (IS_DEADDIR(old_dir)||IS_DEADDIR(new_dir))
-		error = -ENOENT;
-	else if (d_mountpoint(old_dentry)||d_mountpoint(new_dentry))
+	if (d_mountpoint(old_dentry)||d_mountpoint(new_dentry))
 		error = -EBUSY;
 	else 
 		error = old_dir->i_op->rename(old_dir, old_dentry, new_dir, new_dentry);
diff -urN linux-2.4.19-pre5/fs/namespace.c linux-2.4.19-pre6/fs/namespace.c
--- linux-2.4.19-pre5/fs/namespace.c	Thu Apr  4 22:04:27 2002
+++ linux-2.4.19-pre6/fs/namespace.c	Thu Apr  4 22:05:12 2002
@@ -19,8 +19,9 @@
 #include <asm/uaccess.h>
 
 #include <linux/seq_file.h>
+#include <linux/namespace.h>
 
-struct vfsmount *do_kern_mount(char *type, int flags, char *name, void *data);
+struct vfsmount *do_kern_mount(const char *type, int flags, char *name, void *data);
 int do_remount_sb(struct super_block *sb, int flags, void * data);
 void kill_super(struct super_block *sb);
 
@@ -28,10 +29,6 @@
 static int hash_mask, hash_bits;
 static kmem_cache_t *mnt_cache; 
 
-static LIST_HEAD(vfsmntlist);
-static DECLARE_MUTEX(mount_sem);
-static struct vfsmount *root_vfsmnt;
-
 static inline unsigned long hash(struct vfsmount *mnt, struct dentry *dentry)
 {
 	unsigned long tmp = ((unsigned long) mnt / L1_CACHE_BYTES);
@@ -40,7 +37,7 @@
 	return tmp & hash_mask;
 }
 
-struct vfsmount *alloc_vfsmnt(void)
+struct vfsmount *alloc_vfsmnt(char *name)
 {
 	struct vfsmount *mnt = kmem_cache_alloc(mnt_cache, GFP_KERNEL); 
 	if (mnt) {
@@ -50,6 +47,14 @@
 		INIT_LIST_HEAD(&mnt->mnt_child);
 		INIT_LIST_HEAD(&mnt->mnt_mounts);
 		INIT_LIST_HEAD(&mnt->mnt_list);
+		if (name) {
+			int size = strlen(name)+1;
+			char * newname = kmalloc(size, GFP_KERNEL);
+			if (newname) {
+				memcpy(newname, name, size);
+				mnt->mnt_devname = newname;
+			}
+		}
 	}
 	return mnt;
 }
@@ -61,18 +66,6 @@
 	kmem_cache_free(mnt_cache, mnt);
 }
 
-void set_devname(struct vfsmount *mnt, const char *name)
-{
-	if (name) {
-		int size = strlen(name)+1;
-		char * newname = kmalloc(size, GFP_KERNEL);
-		if (newname) {
-			memcpy(newname, name, size);
-			mnt->mnt_devname = newname;
-		}
-	}
-}
-
 struct vfsmount *lookup_mnt(struct vfsmount *mnt, struct dentry *dentry)
 {
 	struct list_head * head = mount_hashtable + hash(mnt, dentry);
@@ -97,7 +90,7 @@
 	while (mnt->mnt_parent != mnt)
 		mnt = mnt->mnt_parent;
 	spin_unlock(&dcache_lock);
-	return mnt == root_vfsmnt;
+	return mnt == current->namespace->root;
 }
 
 static void detach_mnt(struct vfsmount *mnt, struct nameidata *old_nd)
@@ -140,11 +133,10 @@
 clone_mnt(struct vfsmount *old, struct dentry *root)
 {
 	struct super_block *sb = old->mnt_sb;
-	struct vfsmount *mnt = alloc_vfsmnt();
+	struct vfsmount *mnt = alloc_vfsmnt(old->mnt_devname);
 
 	if (mnt) {
 		mnt->mnt_flags = old->mnt_flags;
-		set_devname(mnt, old->mnt_devname);
 		atomic_inc(&sb->s_active);
 		mnt->mnt_sb = sb;
 		mnt->mnt_root = dget(root);
@@ -165,26 +157,29 @@
 /* iterator */
 static void *m_start(struct seq_file *m, loff_t *pos)
 {
+	struct namespace *n = m->private;
 	struct list_head *p;
-	loff_t n = *pos;
+	loff_t l = *pos;
 
-	down(&mount_sem);
-	list_for_each(p, &vfsmntlist)
-		if (!n--)
+	down_read(&n->sem);
+	list_for_each(p, &n->list)
+		if (!l--)
 			return list_entry(p, struct vfsmount, mnt_list);
 	return NULL;
 }
 
 static void *m_next(struct seq_file *m, void *v, loff_t *pos)
 {
+	struct namespace *n = m->private;
 	struct list_head *p = ((struct vfsmount *)v)->mnt_list.next;
 	(*pos)++;
-	return p==&vfsmntlist ? NULL : list_entry(p, struct vfsmount, mnt_list);
+	return p==&n->list ? NULL : list_entry(p, struct vfsmount, mnt_list);
 }
 
 static void m_stop(struct seq_file *m, void *v)
 {
-	up(&mount_sem);
+	struct namespace *n = m->private;
+	up_read(&n->sem);
 }
 
 static inline void mangle(struct seq_file *m, const char *s)
@@ -330,7 +325,7 @@
 		return retval;
 	}
 
-	down(&mount_sem);
+	down_write(&current->namespace->sem);
 	spin_lock(&dcache_lock);
 
 	if (atomic_read(&sb->s_active) == 1) {
@@ -349,7 +344,7 @@
 		retval = 0;
 	}
 	spin_unlock(&dcache_lock);
-	up(&mount_sem);
+	up_write(&current->namespace->sem);
 	return retval;
 }
 
@@ -479,7 +474,7 @@
 		struct list_head head;
 		attach_mnt(mnt, nd);
 		list_add_tail(&head, &mnt->mnt_list);
-		list_splice(&head, vfsmntlist.prev);
+		list_splice(&head, current->namespace->list.prev);
 		mntget(mnt);
 		err = 0;
 	}
@@ -506,7 +501,7 @@
 	if (err)
 		return err;
 
-	down(&mount_sem);
+	down_write(&current->namespace->sem);
 	err = -EINVAL;
 	if (check_mnt(nd->mnt) && (!recurse || check_mnt(old_nd.mnt))) {
 		err = -ENOMEM;
@@ -526,7 +521,7 @@
 			mntput(mnt);
 	}
 
-	up(&mount_sem);
+	up_write(&current->namespace->sem);
 	path_release(&old_nd);
 	return err;
 }
@@ -573,7 +568,7 @@
 	if (err)
 		return err;
 
-	down(&mount_sem);
+	down_write(&current->namespace->sem);
 	while(d_mountpoint(nd->dentry) && follow_down(&nd->mnt, &nd->dentry))
 		;
 	err = -EINVAL;
@@ -613,7 +608,7 @@
 out1:
 	up(&nd->dentry->d_inode->i_zombie);
 out:
-	up(&mount_sem);
+	up_write(&current->namespace->sem);
 	if (!err)
 		path_release(&parent_nd);
 	path_release(&old_nd);
@@ -623,13 +618,22 @@
 static int do_add_mount(struct nameidata *nd, char *type, int flags,
 			int mnt_flags, char *name, void *data)
 {
-	struct vfsmount *mnt = do_kern_mount(type, flags, name, data);
-	int err = PTR_ERR(mnt);
+	struct vfsmount *mnt;
+	int err;
 
+	if (!type || !memchr(type, 0, PAGE_SIZE))
+		return -EINVAL;
+
+	/* we need capabilities... */
+	if (!capable(CAP_SYS_ADMIN))
+		return -EPERM;
+
+	mnt = do_kern_mount(type, flags, name, data);
+	err = PTR_ERR(mnt);
 	if (IS_ERR(mnt))
 		goto out;
 
-	down(&mount_sem);
+	down_write(&current->namespace->sem);
 	/* Something was mounted here while we slept */
 	while(d_mountpoint(nd->dentry) && follow_down(&nd->mnt, &nd->dentry))
 		;
@@ -645,7 +649,7 @@
 	mnt->mnt_flags = mnt_flags;
 	err = graft_tree(mnt, nd);
 unlock:
-	up(&mount_sem);
+	up_write(&current->namespace->sem);
 	mntput(mnt);
 out:
 	return err;
@@ -745,6 +749,86 @@
 	return retval;
 }
 
+int copy_namespace(int flags, struct task_struct *tsk)
+{
+	struct namespace *namespace = tsk->namespace;
+	struct namespace *new_ns;
+	struct vfsmount *rootmnt = NULL, *pwdmnt = NULL, *altrootmnt = NULL;
+	struct fs_struct *fs = tsk->fs;
+
+	if (!namespace)
+		return 0;
+
+	get_namespace(namespace);
+
+	if (! (flags & CLONE_NEWNS))
+		return 0;
+
+	if (!capable(CAP_SYS_ADMIN)) {
+		put_namespace(namespace);
+		return -EPERM;
+	}
+
+	new_ns = kmalloc(sizeof(struct namespace *), GFP_KERNEL);
+	if (!new_ns)
+		goto out;
+
+	atomic_set(&new_ns->count, 1);
+	init_rwsem(&new_ns->sem);
+	new_ns->root = NULL;
+	INIT_LIST_HEAD(&new_ns->list);
+
+	down_write(&tsk->namespace->sem);
+	/* First pass: copy the tree topology */
+	new_ns->root = copy_tree(namespace->root, namespace->root->mnt_root);
+	spin_lock(&dcache_lock);
+	list_add_tail(&new_ns->list, &new_ns->root->mnt_list);
+	spin_unlock(&dcache_lock);
+
+	/* Second pass: switch the tsk->fs->* elements */
+	if (fs) {
+		struct vfsmount *p, *q;
+		write_lock(&fs->lock);
+
+		p = namespace->root;
+		q = new_ns->root;
+		while (p) {
+			if (p == fs->rootmnt) {
+				rootmnt = p;
+				fs->rootmnt = mntget(q);
+			}
+			if (p == fs->pwdmnt) {
+				pwdmnt = p;
+				fs->pwdmnt = mntget(q);
+			}
+			if (p == fs->altrootmnt) {
+				altrootmnt = p;
+				fs->altrootmnt = mntget(q);
+			}
+			p = next_mnt(p, namespace->root);
+			q = next_mnt(q, new_ns->root);
+		}
+		write_unlock(&fs->lock);
+	}
+	up_write(&tsk->namespace->sem);
+
+	tsk->namespace = new_ns;
+
+	if (rootmnt)
+		mntput(rootmnt);
+	if (pwdmnt)
+		mntput(pwdmnt);
+	if (altrootmnt)
+		mntput(altrootmnt);
+
+	put_namespace(namespace);
+	return 0;
+
+out:
+	put_namespace(namespace);
+	return -ENOMEM;
+}
+
 asmlinkage long sys_mount(char * dev_name, char * dir_name, char * type,
 			  unsigned long flags, void * data)
 {
@@ -863,7 +947,7 @@
 	user_nd.mnt = mntget(current->fs->rootmnt);
 	user_nd.dentry = dget(current->fs->root);
 	read_unlock(&current->fs->lock);
-	down(&mount_sem);
+	down_write(&current->namespace->sem);
 	down(&old_nd.dentry->d_inode->i_zombie);
 	error = -EINVAL;
 	if (!check_mnt(user_nd.mnt))
@@ -908,7 +992,7 @@
 	path_release(&parent_nd);
 out2:
 	up(&old_nd.dentry->d_inode->i_zombie);
-	up(&mount_sem);
+	up_write(&current->namespace->sem);
 	path_release(&user_nd);
 	path_release(&old_nd);
 out1:
@@ -921,95 +1005,34 @@
 	goto out2;
 }
 
-/*
- * Absolutely minimal fake fs - only empty root directory and nothing else.
- * In 2.5 we'll use ramfs or tmpfs, but for now it's all we need - just
- * something to go with root vfsmount.
- */
-static struct inode_operations rootfs_dir_inode_operations;
-static struct file_operations rootfs_dir_operations;
-static int rootfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
-{
-	struct inode * inode = new_inode(dir->i_sb);
-	int error = -ENOSPC;
-	if (inode) {
-		inode->i_mode = S_IFDIR|mode;
-		inode->i_uid = current->fsuid;
-		inode->i_gid = current->fsgid;
-		inode->i_op = &rootfs_dir_inode_operations;
-		inode->i_fop = &rootfs_dir_operations;
-		d_instantiate(dentry, inode);
-		dget(dentry);
-		error = 0;
-	}
-	return error;
-}
-static int rootfs_mknod(struct inode *dir, struct dentry *dentry, int mode, int dev)
-{
-	struct inode * inode = new_inode(dir->i_sb);
-	int error = -ENOSPC;
-	if (inode) {
-		inode->i_uid = current->fsuid;
-		inode->i_gid = current->fsgid;
-		init_special_inode(inode, mode, dev);
-		d_instantiate(dentry, inode);
-		dget(dentry);
-		error = 0;
-	}
-	return error;
-}
-static int rootfs_unlink(struct inode * dir, struct dentry *dentry)
-{
-	dentry->d_inode->i_nlink--;
-	dput(dentry);
-	return 0;
-}
-static struct dentry *rootfs_lookup(struct inode *dir, struct dentry *dentry)
-{
-	d_add(dentry, NULL);
-	return NULL;
-}
-static struct file_operations rootfs_dir_operations = {
-	read:		generic_read_dir,
-	readdir:	dcache_readdir,
-};
-static struct inode_operations rootfs_dir_inode_operations = {
-	lookup:		rootfs_lookup,
-	mkdir:		rootfs_mkdir,
-	mknod:		rootfs_mknod,
-	unlink:		rootfs_unlink,
-};
-static struct super_block *rootfs_read_super(struct super_block * sb, void * data, int silent)
+static void __init init_mount_tree(void)
 {
-	struct inode * inode;
-	struct dentry * root;
-	static struct super_operations s_ops = {};
-	sb->s_op = &s_ops;
-	inode = new_inode(sb);
-	if (!inode)
-		return NULL;
-	inode->i_mode = S_IFDIR|0555;
-	inode->i_uid = inode->i_gid = 0;
-	inode->i_op = &rootfs_dir_inode_operations;
-	inode->i_fop = &rootfs_dir_operations;
-	root = d_alloc_root(inode);
-	if (!root) {
-		iput(inode);
-		return NULL;
+	struct vfsmount *mnt;
+	struct namespace *namespace;
+	struct task_struct *p;
+
+	mnt = do_kern_mount("rootfs", 0, "rootfs", NULL);
+	if (IS_ERR(mnt))
+		panic("Can't create rootfs");
+	namespace = kmalloc(sizeof(*namespace), GFP_KERNEL);
+	if (!namespace)
+		panic("Can't allocate initial namespace");
+	atomic_set(&namespace->count, 1);
+	INIT_LIST_HEAD(&namespace->list);
+	init_rwsem(&namespace->sem);
+	list_add(&mnt->mnt_list, &namespace->list);
+	namespace->root = mnt;
+
+	init_task.namespace = namespace;
+	read_lock(&tasklist_lock);
+	for_each_task(p) {
+		get_namespace(namespace);
+		p->namespace = namespace;
 	}
-	sb->s_root = root;
-	return sb;
-}
-static DECLARE_FSTYPE(root_fs_type, "rootfs", rootfs_read_super, FS_NOMOUNT);
+	read_unlock(&tasklist_lock);
 
-static void __init init_mount_tree(void)
-{
-	register_filesystem(&root_fs_type);
-	root_vfsmnt = do_kern_mount("rootfs", 0, "rootfs", NULL);
-	if (IS_ERR(root_vfsmnt))
-		panic("can't allocate root vfsmount");
-	set_fs_pwd(current->fs, root_vfsmnt, root_vfsmnt->mnt_root);
-	set_fs_root(current->fs, root_vfsmnt, root_vfsmnt->mnt_root);
+	set_fs_pwd(current->fs, namespace->root, namespace->root->mnt_root);
+	set_fs_root(current->fs, namespace->root, namespace->root->mnt_root);
 }
 
 void __init mnt_init(unsigned long mempages)
@@ -1067,5 +1090,6 @@
 		d++;
 		i--;
 	} while (i);
+	init_rootfs();
 	init_mount_tree();
 }
diff -urN linux-2.4.19-pre5/fs/nfs/nfsroot.c linux-2.4.19-pre6/fs/nfs/nfsroot.c
--- linux-2.4.19-pre5/fs/nfs/nfsroot.c	Thu Oct 25 00:02:26 2001
+++ linux-2.4.19-pre6/fs/nfs/nfsroot.c	Thu Apr  4 22:05:12 2002
@@ -163,37 +163,6 @@
 
 
 /*
- *  Extract IP address from the parameter string if needed. Note that we
- *  need to have root_server_addr set _before_ IPConfig gets called as it
- *  can override it.
- */
-static void __init root_nfs_parse_addr(char *name)
-{
-	int octets = 0;
-	char *cp, *cq;
-
-	cp = cq = name;
-	while (octets < 4) {
-		while (*cp >= '0' && *cp <= '9')
-			cp++;
-		if (cp == cq || cp - cq > 3)
-			break;
-		if (*cp == '.' || octets == 3)
-			octets++;
-		if (octets < 4)
-			cp++;
-		cq = cp;
-	}
-	if (octets == 4 && (*cp == ':' || *cp == '\0')) {
-		if (*cp == ':')
-			*cp++ = '\0';
-		root_server_addr = in_aton(name);
-		strcpy(name, cp);
-	}
-}
-
-
-/*
  *  Parse option string.
  */
 static void __init root_nfs_parse(char *name, char *buf)
@@ -344,7 +313,7 @@
 			line[sizeof(nfs_root_name) - strlen(NFS_ROOT) - 1] = '\0';
 		sprintf(nfs_root_name, NFS_ROOT, line);
 	}
-	root_nfs_parse_addr(nfs_root_name);
+	root_server_addr = root_nfs_parse_addr(nfs_root_name);
 	return 1;
 }
 
diff -urN linux-2.4.19-pre5/fs/nfsd/export.c linux-2.4.19-pre6/fs/nfsd/export.c
--- linux-2.4.19-pre5/fs/nfsd/export.c	Wed Oct  3 22:57:36 2001
+++ linux-2.4.19-pre6/fs/nfsd/export.c	Thu Apr  4 22:05:12 2002
@@ -18,6 +18,7 @@
 #include <linux/slab.h>
 #include <linux/stat.h>
 #include <linux/in.h>
+#include <linux/seq_file.h>
 
 #include <linux/sunrpc/svc.h>
 #include <linux/nfsd/nfsd.h>
@@ -31,7 +32,6 @@
 typedef struct svc_client	svc_client;
 typedef struct svc_export	svc_export;
 
-static svc_export *	exp_find(svc_client *clp, kdev_t dev);
 static svc_export *	exp_parent(svc_client *clp, kdev_t dev,
 					struct dentry *dentry);
 static svc_export *	exp_child(svc_client *clp, kdev_t dev,
@@ -65,41 +65,25 @@
 static int			hash_count;
 static DECLARE_WAIT_QUEUE_HEAD(	hash_wait );
 
-
-/*
- * Find a client's export for a device.
- */
-static inline svc_export *
-exp_find(svc_client *clp, kdev_t dev)
-{
-	svc_export *	exp;
-
-	exp = clp->cl_export[EXPORT_HASH(dev)];
-	while (exp && exp->ex_dev != dev)
-		exp = exp->ex_next;
-	return exp;
-}
-
 /*
  * Find the client's export entry matching xdev/xino.
  */
 svc_export *
 exp_get(svc_client *clp, kdev_t dev, ino_t ino)
 {
-	svc_export *	exp;
+	struct list_head *head, *p;
 
 	if (!clp)
 		return NULL;
 
-	exp = clp->cl_export[EXPORT_HASH(dev)];
-	if (exp)
-		do {
-			if (exp->ex_ino == ino && exp->ex_dev == dev)
-				goto out;
-		} while (NULL != (exp = exp->ex_next));
-	exp = NULL;
-out:
-	return exp;
+	head = &clp->cl_export[EXPORT_HASH(dev)];
+	list_for_each(p, head) {
+		svc_export *exp = list_entry(p, svc_export, ex_hash);
+		if (exp->ex_ino == ino && exp->ex_dev == dev)
+			return exp;
+	}
+
+	return NULL;
 }
 
 /*
@@ -108,15 +92,15 @@
 static svc_export *
 exp_parent(svc_client *clp, kdev_t dev, struct dentry *dentry)
 {
-	svc_export      *exp;
+	struct list_head *head = &clp->cl_export[EXPORT_HASH(dev)];
+	struct list_head *p;
 
-	if (clp == NULL)
-		return NULL;
-
-	for (exp = clp->cl_export[EXPORT_HASH(dev)]; exp; exp = exp->ex_next)
+	list_for_each(p,head) {
+		svc_export *exp = list_entry(p, svc_export, ex_hash);
 		if (is_subdir(dentry, exp->ex_dentry))
-			break;
-	return exp;
+			return exp;
+	}
+	return NULL;
 }
 
 /*
@@ -127,17 +111,31 @@
 static svc_export *
 exp_child(svc_client *clp, kdev_t dev, struct dentry *dentry)
 {
-	svc_export      *exp;
+	struct list_head *head = &clp->cl_export[EXPORT_HASH(dev)];
+	struct list_head *p;
 
-	if (clp == NULL)
-		return NULL;
 
-	for (exp = clp->cl_export[EXPORT_HASH(dev)]; exp; exp = exp->ex_next) {
-		struct dentry	*ndentry = exp->ex_dentry;
+	list_for_each(p, head) {
+		svc_export *exp = list_entry(p, svc_export, ex_hash);
+		struct dentry *ndentry = exp->ex_dentry;
+
 		if (ndentry && is_subdir(ndentry->d_parent, dentry))
-			break;
+			return exp;
+	}
+	return NULL;
+}
+
+/* Update parent pointers of all exports */
+static void exp_change_parents(svc_client *clp, svc_export *old, svc_export *new)
+{
+	struct list_head *head = &clp->cl_list;
+	struct list_head *p;
+
+	list_for_each(p, head) {
+		svc_export *exp = list_entry(p, svc_export, ex_list);
+		if (exp->ex_parent == old)
+			exp->ex_parent = new;
 	}
-	return exp;
 }
 
 /*
@@ -148,10 +146,9 @@
 {
 	svc_client	*clp;
 	svc_export	*exp, *parent;
-	svc_export	**head;
 	struct nameidata nd;
 	struct inode	*inode = NULL;
-	int		i, err;
+	int		err;
 	kdev_t		dev;
 	ino_t		ino;
 
@@ -237,8 +234,8 @@
 	strcpy(exp->ex_path, nxp->ex_path);
 	exp->ex_client = clp;
 	exp->ex_parent = parent;
-	exp->ex_dentry = nd.dentry;
-	exp->ex_mnt = nd.mnt;
+	exp->ex_dentry = dget(nd.dentry);
+	exp->ex_mnt = mntget(nd.mnt);
 	exp->ex_flags = nxp->ex_flags;
 	exp->ex_dev = dev;
 	exp->ex_ino = ino;
@@ -246,34 +243,20 @@
 	exp->ex_anon_gid = nxp->ex_anon_gid;
 
 	/* Update parent pointers of all exports */
-	if (parent) {
-		for (i = 0; i < NFSCLNT_EXPMAX; i++) {
-			svc_export *temp = clp->cl_export[i];
-
-			while (temp) {
-				if (temp->ex_parent == parent)
-					temp->ex_parent = exp;
-				temp = temp->ex_next;
-			}
-		}
-	}
+	if (parent)
+		exp_change_parents(clp, parent, exp);
 
-	head = clp->cl_export + EXPORT_HASH(dev);
-	exp->ex_next = *head;
-	*head = exp;
+	list_add(&exp->ex_hash, clp->cl_export + EXPORT_HASH(dev));
+	list_add_tail(&exp->ex_list, &clp->cl_list);
 
 	err = 0;
 
-	/* Unlock hashtable */
+finish:
+	path_release(&nd);
 out_unlock:
 	exp_unlock();
 out:
 	return err;
-
-	/* Release the dentry */
-finish:
-	path_release(&nd);
-	goto out_unlock;
 }
 
 /*
@@ -283,20 +266,14 @@
 static void
 exp_do_unexport(svc_export *unexp)
 {
-	svc_export	*exp;
-	svc_client	*clp;
 	struct dentry	*dentry;
 	struct vfsmount *mnt;
 	struct inode	*inode;
-	int		i;
 
-	/* Update parent pointers. */
-	clp = unexp->ex_client;
-	for (i = 0; i < NFSCLNT_EXPMAX; i++) {
-		for (exp = clp->cl_export[i]; exp; exp = exp->ex_next)
-			if (exp->ex_parent == unexp)
-				exp->ex_parent = unexp->ex_parent;
-	}
+	list_del(&unexp->ex_hash);
+	list_del(&unexp->ex_list);
+
+	exp_change_parents(unexp->ex_client, unexp, unexp->ex_parent);
 
 	dentry = unexp->ex_dentry;
 	mnt = unexp->ex_mnt;
@@ -317,18 +294,13 @@
 static void
 exp_unexport_all(svc_client *clp)
 {
-	svc_export	*exp;
-	int		i;
+	struct list_head *p = &clp->cl_list;
 
 	dprintk("unexporting all fs's for clnt %p\n", clp);
-	for (i = 0; i < NFSCLNT_EXPMAX; i++) {
-		exp = clp->cl_export[i];
-		clp->cl_export[i] = NULL;
-		while (exp) {
-			svc_export *next = exp->ex_next;
-			exp_do_unexport(exp);
-			exp = next;
-		}
+
+	while (!list_empty(p)) {
+		svc_export *exp = list_entry(p->next, svc_export, ex_list);
+		exp_do_unexport(exp);
 	}
 }
 
@@ -339,7 +311,6 @@
 exp_unexport(struct nfsctl_export *nxp)
 {
 	svc_client	*clp;
-	svc_export	**expp, *exp = NULL;
 	int		err;
 
 	/* Consistency check */
@@ -352,17 +323,10 @@
 	err = -EINVAL;
 	clp = exp_getclientbyname(nxp->ex_client);
 	if (clp) {
-		expp = clp->cl_export + EXPORT_HASH(nxp->ex_dev);
-		while ((exp = *expp) != NULL) {
-			if (exp->ex_dev == nxp->ex_dev) {
-				if (exp->ex_ino == nxp->ex_ino) {
-					*expp = exp->ex_next;
-					exp_do_unexport(exp);
-					err = 0;
-					break;
-				}
-			}
-			expp = &(exp->ex_next);
+		svc_export *exp = exp_get(clp, nxp->ex_dev, nxp->ex_ino);
+		if (exp) {
+			exp_do_unexport(exp);
+			err = 0;
 		}
 	}
 
@@ -542,6 +506,68 @@
 	return NULL;
 }
 
+/* Iterator */
+
+static void *e_start(struct seq_file *m, loff_t *pos)
+{
+	loff_t n = *pos;
+	unsigned client, export;
+	svc_client *clp;
+	struct list_head *p;
+	
+	exp_readlock();
+	if (!n--)
+		return (void *)1;
+	client = n >> 32;
+	export = n & ((1LL<<32) - 1);
+	for (clp = clients; client && clp; clp = clp->cl_next, client--)
+		;
+	if (!clp)
+		return NULL;
+	list_for_each(p, &clp->cl_list)
+		if (!export--)
+			return list_entry(p, svc_export, ex_list);
+	n &= ~((1LL<<32) - 1);
+	do {
+		clp = clp->cl_next;
+		n += 1LL<<32;
+	} while(clp && list_empty(&clp->cl_list));
+	if (!clp)
+		return NULL;
+	*pos = n+1;
+	return list_entry(clp->cl_list.next, svc_export, ex_list);
+}
+
+static void *e_next(struct seq_file *m, void *p, loff_t *pos)
+{
+	svc_export *exp = p;
+	svc_client *clp;
+
+	if (p == (void *)1)
+		clp = clients;
+	else if (exp->ex_list.next == &exp->ex_client->cl_list) {
+		clp = exp->ex_client->cl_next;
+		*pos += 1LL<<32;
+	} else {
+		++*pos;
+		return list_entry(exp->ex_list.next, svc_export, ex_list);
+	}
+	*pos &= ~((1LL<<32) - 1);
+	while (clp && list_empty(&clp->cl_list)) {
+		clp = clp->cl_next;
+		*pos += 1LL<<32;
+	}
+	if (!clp)
+		return NULL;
+	++*pos;
+	return list_entry(clp->cl_list.next, svc_export, ex_list);
+}
+
+static void e_stop(struct seq_file *m, void *p)
+{
+	exp_unlock();
+}
+
 struct flags {
 	int flag;
 	char *name[2];
@@ -564,128 +590,77 @@
 	{ 0, {"", ""}}
 };
 
-static int
-exp_flags(char *buffer, int flag)
+static void exp_flags(struct seq_file *m, int flag)
 {
-    int len = 0, first = 0;
-    struct flags *flg = expflags;
+	int first = 0;
+	struct flags *flg;
 
-    for (;flg->flag;flg++) {
-        int state = (flg->flag & flag)?0:1;
-        if (!flg->flag)
-		break;
-        if (*flg->name[state]) {
-		len += sprintf(buffer + len, "%s%s",
-                               first++?",":"", flg->name[state]);
-        }
-    }
-    return len;
+	for (flg = expflags; flg->flag; flg++) {
+		int state = (flg->flag & flag)?0:1;
+		if (*flg->name[state])
+			seq_printf(m, "%s%s", first++?",":"", flg->name[state]);
+	}
 }
 
-
-
-/* mangling borrowed from fs/super.c */
-/* Use octal escapes, like mount does, for embedded spaces etc. */
-static unsigned char need_escaping[] = { ' ', '\t', '\n', '\\' };
-
-static int
-mangle(const unsigned char *s, char *buf, int len) {
-        char *sp;
-        int n;
-
-        sp = buf;
-        while(*s && sp-buf < len-3) {
-                for (n = 0; n < sizeof(need_escaping); n++) {
-                        if (*s == need_escaping[n]) {
-                                *sp++ = '\\';
-                                *sp++ = '0' + ((*s & 0300) >> 6);
-                                *sp++ = '0' + ((*s & 070) >> 3);
-                                *sp++ = '0' + (*s & 07);
-                                goto next;
-                        }
-                }
-                *sp++ = *s;
-        next:
-                s++;
-        }
-        return sp - buf;	/* no trailing NUL */
+static inline void mangle(struct seq_file *m, const char *s)
+{
+	seq_escape(m, s, " \t\n\\");
 }
 
-#define FREEROOM	((int)PAGE_SIZE-200-len)
-#define MANGLE(s)	len += mangle((s), buffer+len, FREEROOM);
-
-int
-exp_procfs_exports(char *buffer, char **start, off_t offset,
-                             int length, int *eof, void *data)
+static int e_show(struct seq_file *m, void *p)
 {
-	struct svc_clnthash	**hp, **head, *tmp;
-	struct svc_client	*clp;
-	svc_export *exp;
-	off_t	pos = 0;
-        off_t	begin = 0;
-        int	len = 0;
-	int	i,j;
+	struct svc_export *exp = p;
+	struct svc_client *clp;
+	int j, first = 0;
 
-        len += sprintf(buffer, "# Version 1.1\n");
-        len += sprintf(buffer+len, "# Path Client(Flags) # IPs\n");
-
-	for (clp = clients; clp; clp = clp->cl_next) {
-		for (i = 0; i < NFSCLNT_EXPMAX; i++) {
-			exp = clp->cl_export[i];
-			while (exp) {
-				int first = 0;
-				MANGLE(exp->ex_path);
-				buffer[len++]='\t';
-				MANGLE(clp->cl_ident);
-				buffer[len++]='(';
-
-				len += exp_flags(buffer+len, exp->ex_flags);
-				len += sprintf(buffer+len, ") # ");
-				for (j = 0; j < clp->cl_naddr; j++) {
-					struct in_addr	addr = clp->cl_addr[j]; 
-
-					head = &clnt_hash[CLIENT_HASH(addr.s_addr)];
-					for (hp = head; (tmp = *hp) != NULL; hp = &(tmp->h_next)) {
-						if (tmp->h_addr.s_addr == addr.s_addr) {
-							if (first++) len += sprintf(buffer+len, "%s", " ");
-							if (tmp->h_client != clp)
-								len += sprintf(buffer+len, "(");
-							len += sprintf(buffer+len, "%d.%d.%d.%d",
-									htonl(addr.s_addr) >> 24 & 0xff,
-									htonl(addr.s_addr) >> 16 & 0xff,
-									htonl(addr.s_addr) >>  8 & 0xff,
-									htonl(addr.s_addr) >>  0 & 0xff);
-							if (tmp->h_client != clp)
-							  len += sprintf(buffer+len, ")");
-							break;
-						}
-					}
-				}
-				exp = exp->ex_next;
-
-				buffer[len++]='\n';
-
-				pos=begin+len;
-				if(pos<offset) {
-					len=0;
-					begin=pos;
-				}
-				if (pos > offset + length)
-					goto done;
-			}
-		}
+	if (p == (void *)1) {
+		seq_puts(m, "# Version 1.1\n");
+		seq_puts(m, "# Path Client(Flags) # IPs\n");
+		return 0;
 	}
 
-	*eof = 1;
+	clp = exp->ex_client;
 
-done:
-	*start = buffer + (offset - begin);
-	len -= (offset - begin);
-	if ( len > length )
-		len = length;
-	return len;
+	mangle(m, exp->ex_path);
+	seq_putc(m, '\t');
+	mangle(m, clp->cl_ident);
+	seq_putc(m, '(');
+	exp_flags(m, exp->ex_flags);
+	seq_puts(m, ") # ");
+	for (j = 0; j < clp->cl_naddr; j++) {
+		struct svc_clnthash **hp, **head, *tmp;
+		struct in_addr addr = clp->cl_addr[j]; 
+
+		head = &clnt_hash[CLIENT_HASH(addr.s_addr)];
+		for (hp = head; (tmp = *hp) != NULL; hp = &(tmp->h_next)) {
+			if (tmp->h_addr.s_addr == addr.s_addr)
+				break;
+		}
+		if (tmp) {
+			if (first++)
+				seq_putc(m, ' ');
+			if (tmp->h_client != clp)
+				seq_putc(m, '(');
+			seq_printf(m, "%d.%d.%d.%d",
+				htonl(addr.s_addr) >> 24 & 0xff,
+				htonl(addr.s_addr) >> 16 & 0xff,
+				htonl(addr.s_addr) >>  8 & 0xff,
+				htonl(addr.s_addr) >>  0 & 0xff);
+			if (tmp->h_client != clp)
+				seq_putc(m, ')');
+		}
+	}
+	seq_putc(m, '\n');
+	return 0;
 }
 
+struct seq_operations nfs_exports_op = {
+	start:	e_start,
+	next:	e_next,
+	stop:	e_stop,
+	show:	e_show,
+};
+
 /*
  * Add or modify a client.
  * Change requests may involve the list of host addresses. The list of
@@ -721,6 +696,9 @@
 		if (!(clp = kmalloc(sizeof(*clp), GFP_KERNEL)))
 			goto out_unlock;
 		memset(clp, 0, sizeof(*clp));
+		for (i = 0; i < NFSCLNT_EXPMAX; i++)
+			INIT_LIST_HEAD(&clp->cl_export[i]);
+		INIT_LIST_HEAD(&clp->cl_list);
 
 		dprintk("created client %s (%p)\n", ncp->cl_ident, clp);
 
diff -urN linux-2.4.19-pre5/fs/nfsd/nfs3proc.c linux-2.4.19-pre6/fs/nfsd/nfs3proc.c
--- linux-2.4.19-pre5/fs/nfsd/nfs3proc.c	Thu Sep 20 21:02:01 2001
+++ linux-2.4.19-pre6/fs/nfsd/nfs3proc.c	Thu Apr  4 22:05:12 2002
@@ -339,7 +339,7 @@
 		    || (argp->ftype == NF3BLK && argp->major >= MAX_BLKDEV)
 		    || argp->minor > 0xFF)
 			RETURN_STATUS(nfserr_inval);
-		rdev = ((argp->major) << 8) | (argp->minor);
+		rdev = MKDEV(argp->major, argp->minor);
 	} else
 		if (argp->ftype != NF3SOCK && argp->ftype != NF3FIFO)
 			RETURN_STATUS(nfserr_inval);
diff -urN linux-2.4.19-pre5/fs/nfsd/nfsctl.c linux-2.4.19-pre6/fs/nfsd/nfsctl.c
--- linux-2.4.19-pre5/fs/nfsd/nfsctl.c	Sun Oct 21 10:32:33 2001
+++ linux-2.4.19-pre6/fs/nfsd/nfsctl.c	Thu Apr  4 22:05:12 2002
@@ -20,6 +20,7 @@
 #include <linux/unistd.h>
 #include <linux/slab.h>
 #include <linux/proc_fs.h>
+#include <linux/seq_file.h>
 
 #include <linux/nfs.h>
 #include <linux/sunrpc/svc.h>
@@ -44,31 +45,26 @@
 static int	nfsctl_ugidupdate(struct nfsctl_ugidmap *data);
 #endif
 
-static int	initialized;
-
-int exp_procfs_exports(char *buffer, char **start, off_t offset,
-                             int length, int *eof, void *data);
+extern struct seq_operations nfs_exports_op;
+static int exports_open(struct inode *inode, struct file *file)
+{
+	return seq_open(file, &nfs_exports_op);
+}
+static struct file_operations exports_operations = {
+	open:		exports_open,
+	read:		seq_read,
+	llseek:		seq_lseek,
+	release:	seq_release,
+};
 
 void proc_export_init(void)
 {
+	struct proc_dir_entry *entry;
 	if (!proc_mkdir("fs/nfs", 0))
 		return;
-	create_proc_read_entry("fs/nfs/exports", 0, 0, exp_procfs_exports,NULL);
-}
-
-
-/*
- * Initialize nfsd
- */
-static void
-nfsd_init(void)
-{
-	nfsd_stat_init();	/* Statistics */
-	nfsd_cache_init();	/* RPC reply cache */
-	nfsd_export_init();	/* Exports table */
-	nfsd_lockd_init();	/* lockd->nfsd callbacks */
-	proc_export_init();
-	initialized = 1;
+	entry = create_proc_entry("fs/nfs/exports", 0, NULL);
+	if (entry)
+		entry->proc_fops =  &exports_operations;
 }
 
 static inline int
@@ -225,10 +221,8 @@
 	int			err;
 	int			argsize, respsize;
 
-	MOD_INC_USE_COUNT;
 	lock_kernel ();
-	if (!initialized)
-		nfsd_init();
+
 	err = -EPERM;
 	if (!capable(CAP_SYS_ADMIN)) {
 		goto done;
@@ -301,38 +295,47 @@
 		kfree(res);
 
 	unlock_kernel ();
-	MOD_DEC_USE_COUNT;
 	return err;
 }
 
-#ifdef MODULE
-/* New-style module support since 2.1.18 */
 EXPORT_NO_SYMBOLS;
 MODULE_AUTHOR("Olaf Kirch <okir@monad.swb.de>");
 MODULE_LICENSE("GPL");
 
+#ifdef MODULE
 struct nfsd_linkage nfsd_linkage_s = {
 	do_nfsservctl: handle_sys_nfsservctl,
+	owner: THIS_MODULE,
 };
+#endif
 
 /*
  * Initialize the module
  */
-int
-init_module(void)
+static int __init
+nfsd_init(void)
 {
 	printk(KERN_INFO "Installing knfsd (copyright (C) 1996 okir@monad.swb.de).\n");
+#ifdef MODULE
 	nfsd_linkage = &nfsd_linkage_s;
+#endif
+	nfsd_stat_init();	/* Statistics */
+	nfsd_cache_init();	/* RPC reply cache */
+	nfsd_export_init();	/* Exports table */
+	nfsd_lockd_init();	/* lockd->nfsd callbacks */
+	proc_export_init();
 	return 0;
 }
 
 /*
  * Clean up the mess before unloading the module
  */
-void
-cleanup_module(void)
+static void __exit
+nfsd_exit(void)
 {
+#ifdef MODULE
 	nfsd_linkage = NULL;
+#endif
 	nfsd_export_shutdown();
 	nfsd_cache_shutdown();
 	remove_proc_entry("fs/nfs/exports", NULL);
@@ -340,4 +343,6 @@
 	nfsd_stat_shutdown();
 	nfsd_lockd_shutdown();
 }
-#endif
+
+module_init(nfsd_init);
+module_exit(nfsd_exit);
diff -urN linux-2.4.19-pre5/fs/nfsd/nfsfh.c linux-2.4.19-pre6/fs/nfsd/nfsfh.c
--- linux-2.4.19-pre5/fs/nfsd/nfsfh.c	Wed Oct  3 22:59:22 2001
+++ linux-2.4.19-pre6/fs/nfsd/nfsfh.c	Thu Apr  4 22:05:12 2002
@@ -576,11 +576,9 @@
 		error = nfserr_stale; 
 		exp = exp_get(rqstp->rq_client, xdev, xino);
 
-		if (!exp) {
+		if (!exp)
 			/* export entry revoked */
-			nfsdstats.fh_stale++;
 			goto out;
-		}
 
 		/* Check if the request originated from a secure port. */
 		error = nfserr_perm;
@@ -657,7 +655,7 @@
 	 * write call).
 	 */
 
-	/* When is type ever negative? */
+	/* Type can be negative to e.g. exclude directories from linking */
 	if (type > 0 && (inode->i_mode & S_IFMT) != type) {
 		error = (type == S_IFDIR)? nfserr_notdir : nfserr_isdir;
 		goto out;
@@ -690,13 +688,11 @@
 				    && !(tdentry->d_inode->i_mode & S_IXOTH)
 					) {
 					error = nfserr_stale;
-					nfsdstats.fh_stale++;
 					dprintk("fh_verify: no root_squashed access.\n");
 				}
 			} while ((tdentry != tdentry->d_parent));
 			if (exp->ex_dentry != tdentry) {
 				error = nfserr_stale;
-				nfsdstats.fh_stale++;
 				printk("nfsd Security: %s/%s bad export.\n",
 				       dentry->d_parent->d_name.name,
 				       dentry->d_name.name);
@@ -716,6 +712,8 @@
 	}
 #endif
 out:
+	if (error == nfserr_stale)
+		nfsdstats.fh_stale++;
 	return error;
 }
 
diff -urN linux-2.4.19-pre5/fs/nfsd/vfs.c linux-2.4.19-pre6/fs/nfsd/vfs.c
--- linux-2.4.19-pre5/fs/nfsd/vfs.c	Fri Dec 21 09:41:55 2001
+++ linux-2.4.19-pre6/fs/nfsd/vfs.c	Thu Apr  4 22:05:12 2002
@@ -216,36 +216,37 @@
 	dentry = fhp->fh_dentry;
 	inode = dentry->d_inode;
 
-	err = inode_change_ok(inode, iap);
-	/* could be a "touch" (utimes) request where the user is not the owner but does
-	 * have write permission. In this case the user should be allowed to set
-	 * both times to the current time.  We could just assume any such SETATTR
-	 * is intended to set the times to "now", but we do a couple of simple tests
-	 * to increase our confidence.
+	/* NFSv2 does not differentiate between "set-[ac]time-to-now"
+	 * which only requires access, and "set-[ac]time-to-X" which
+	 * requires ownership.
+	 * So if it looks like it might be "set both to the same time which
+	 * is close to now", and if inode_change_ok fails, then we
+	 * convert to "set to now" instead of "set to explicit time"
+	 *
+	 * We only call inode_change_ok as the last test as technically
+	 * it is not an interface that we should be using.  It is only
+	 * valid if the filesystem does not define it's own i_op->setattr.
 	 */
 #define BOTH_TIME_SET (ATTR_ATIME_SET | ATTR_MTIME_SET)
 #define	MAX_TOUCH_TIME_ERROR (30*60)
-	if (err
-	    && (iap->ia_valid & BOTH_TIME_SET) == BOTH_TIME_SET
+	if ((iap->ia_valid & BOTH_TIME_SET) == BOTH_TIME_SET
 	    && iap->ia_mtime == iap->ia_atime
 	    ) {
-	    /* looks good.  now just make sure time is in the right ballpark.
-	     * solaris, at least, doesn't seem to care what the time request is
+	    /* Looks probable.  Now just make sure time is in the right ballpark.
+	     * Solaris, at least, doesn't seem to care what the time request is.
+	     * We require it be within 30 minutes of now.
 	     */
 	    time_t delta = iap->ia_atime - CURRENT_TIME;
 	    if (delta<0) delta = -delta;
-	    if (delta < MAX_TOUCH_TIME_ERROR) {
+	    if (delta < MAX_TOUCH_TIME_ERROR &&
+		inode_change_ok(inode, iap) != 0) {
 		/* turn off ATTR_[AM]TIME_SET but leave ATTR_[AM]TIME
 		 * this will cause notify_change to set these times to "now"
 		 */
 		iap->ia_valid &= ~BOTH_TIME_SET;
-		err = inode_change_ok(inode, iap);
 	    }
 	}
 	    
-	if (err)
-		goto out_nfserr;
-
 	/* The size case is special. It changes the file as well as the attributes.  */
 	if (iap->ia_valid & ATTR_SIZE) {
 		if (iap->ia_size < inode->i_size) {
@@ -518,24 +519,33 @@
  * As this calls fsync (not fdatasync) there is no need for a write_inode
  * after it.
  */
+inline void nfsd_dosync(struct file *filp, struct dentry *dp, 
+			struct file_operations *fop)
+{
+	struct inode *inode = dp->d_inode;
+	int (*fsync) (struct file *, struct dentry *, int);
+
+	filemap_fdatasync(inode->i_mapping);
+	if (fop && (fsync = fop->fsync))
+		fsync(filp, dp, 0);
+	filemap_fdatawait(inode->i_mapping);
+}
+	
+
 void
 nfsd_sync(struct file *filp)
 {
+	struct inode *inode = filp->f_dentry->d_inode;
 	dprintk("nfsd: sync file %s\n", filp->f_dentry->d_name.name);
-	down(&filp->f_dentry->d_inode->i_sem);
-	filp->f_op->fsync(filp, filp->f_dentry, 0);
-	up(&filp->f_dentry->d_inode->i_sem);
+	down(&inode->i_sem);
+	nfsd_dosync(filp, filp->f_dentry, filp->f_op);
+	up(&inode->i_sem);
 }
 
 void
 nfsd_sync_dir(struct dentry *dp)
 {
-	struct inode *inode = dp->d_inode;
-	int (*fsync) (struct file *, struct dentry *, int);
-	
-	if (inode->i_fop && (fsync = inode->i_fop->fsync)) {
-		fsync(NULL, dp, 0);
-	}
+	nfsd_dosync(NULL, dp, dp->d_inode->i_fop);
 }
 
 /*
@@ -1380,7 +1390,6 @@
 nfsd_readdir(struct svc_rqst *rqstp, struct svc_fh *fhp, loff_t offset, 
              encode_dent_fn func, u32 *buffer, int *countp, u32 *verf)
 {
-	struct inode	*inode;
 	u32		*p;
 	int		oldlen, eof, err;
 	struct file	file;
@@ -1392,9 +1401,6 @@
 	if (offset > ~(u32) 0)
 		goto out_close;
 
-	err = nfserr_notdir;
-	if (!file.f_op->readdir)
-		goto out_close;
 	file.f_pos = offset;
 
 	/* Set up the readdir context */
@@ -1409,25 +1415,16 @@
 	 * readdir() is not guaranteed to fill up the entire buffer, but
 	 * may choose to do less.
 	 */
-	inode = file.f_dentry->d_inode;
-	down(&inode->i_sem);
-	while (1) {
+
+	do {
 		oldlen = cd.buflen;
 
-		/*
-		dprintk("nfsd: f_op->readdir(%x/%ld @ %d) buflen = %d (%d)\n",
-			file.f_inode->i_dev, file.f_inode->i_ino,
-			(int) file.f_pos, (int) oldlen, (int) cd.buflen);
-		 */
-		err = file.f_op->readdir(&file, &cd, (filldir_t) func);
+		err = vfs_readdir(&file, (filldir_t) func, &cd);
+
 		if (err < 0)
 			goto out_nfserr;
-		if (oldlen == cd.buflen)
-			break;
-		if (cd.eob)
-			break;
-	}
-	up(&inode->i_sem);
+
+	} while (oldlen != cd.buflen && !cd.eob);
 
 	/* If we didn't fill the buffer completely, we're at EOF */
 	eof = !cd.eob;
@@ -1454,7 +1451,6 @@
 	return err;
 
 out_nfserr:
-	up(&inode->i_sem);
 	err = nfserrno(err);
 	goto out_close;
 }
diff -urN linux-2.4.19-pre5/fs/proc/base.c linux-2.4.19-pre6/fs/proc/base.c
--- linux-2.4.19-pre5/fs/proc/base.c	Mon Feb 25 11:38:09 2002
+++ linux-2.4.19-pre6/fs/proc/base.c	Thu Apr  4 22:05:12 2002
@@ -23,6 +23,8 @@
 #include <linux/init.h>
 #include <linux/file.h>
 #include <linux/string.h>
+#include <linux/seq_file.h>
+#include <linux/namespace.h>
 
 /*
  * For hysterical raisins we keep the same inumbers as in the old procfs.
@@ -246,6 +248,46 @@
 	read:		pid_maps_read,
 };
 
+extern struct seq_operations mounts_op;
+static int mounts_open(struct inode *inode, struct file *file)
+{
+	struct task_struct *task = inode->u.proc_i.task;
+	int ret = seq_open(file, &mounts_op);
+
+	if (!ret) {
+		struct seq_file *m = file->private_data;
+		struct namespace *namespace;
+		task_lock(task);
+		namespace = task->namespace;
+		if (namespace)
+			get_namespace(namespace);
+		task_unlock(task);
+
+		if (namespace)
+			m->private = namespace;
+		else {
+			seq_release(inode, file);
+			ret = -EINVAL;
+		}
+	}
+	return ret;
+}
+
+static int mounts_release(struct inode *inode, struct file *file)
+{
+	struct seq_file *m = file->private_data;
+	struct namespace *namespace = m->private;
+	put_namespace(namespace);
+	return seq_release(inode, file);
+}
+
+static struct file_operations proc_mounts_operations = {
+	open:		mounts_open,
+	read:		seq_read,
+	llseek:		seq_lseek,
+	release:	mounts_release,
+};
+
 #define PROC_BLOCK_SIZE	(3*1024)		/* 4K page size but our output routines use some slack for overruns */
 
 static ssize_t proc_info_read(struct file * file, char * buf,
@@ -497,6 +539,7 @@
 	PROC_PID_STATM,
 	PROC_PID_MAPS,
 	PROC_PID_CPU,
+	PROC_PID_MOUNTS,
 	PROC_PID_FD_DIR = 0x8000,	/* 0x8000-0xffff */
 };
 
@@ -516,6 +559,7 @@
   E(PROC_PID_CWD,	"cwd",		S_IFLNK|S_IRWXUGO),
   E(PROC_PID_ROOT,	"root",		S_IFLNK|S_IRWXUGO),
   E(PROC_PID_EXE,	"exe",		S_IFLNK|S_IRWXUGO),
+  E(PROC_PID_MOUNTS,	"mounts",	S_IFREG|S_IRUGO),
   {0,0,NULL,0}
 };
 #undef E
@@ -881,6 +925,9 @@
 			inode->i_op = &proc_mem_inode_operations;
 			inode->i_fop = &proc_mem_operations;
 			break;
+		case PROC_PID_MOUNTS:
+			inode->i_fop = &proc_mounts_operations;
+			break;
 		default:
 			printk("procfs: impossible type (%d)",p->type);
 			iput(inode);
diff -urN linux-2.4.19-pre5/fs/proc/proc_misc.c linux-2.4.19-pre6/fs/proc/proc_misc.c
--- linux-2.4.19-pre5/fs/proc/proc_misc.c	Thu Apr  4 22:04:27 2002
+++ linux-2.4.19-pre6/fs/proc/proc_misc.c	Thu Apr  4 22:05:12 2002
@@ -493,18 +493,6 @@
 	write:		write_profile,
 };
 
-extern struct seq_operations mounts_op;
-static int mounts_open(struct inode *inode, struct file *file)
-{
-	return seq_open(file, &mounts_op);
-}
-static struct file_operations proc_mounts_operations = {
-	open:		mounts_open,
-	read:		seq_read,
-	llseek:		seq_lseek,
-	release:	seq_release,
-};
-
 struct proc_dir_entry *proc_root_kcore;
 
 static void create_seq_entry(char *name, mode_t mode, struct file_operations *f)
@@ -557,11 +545,12 @@
 	for (p = simple_ones; p->name; p++)
 		create_proc_read_entry(p->name, 0, NULL, p->read_proc, NULL);
 
+	proc_symlink("mounts", NULL, "self/mounts");
+
 	/* And now for trickier ones */
 	entry = create_proc_entry("kmsg", S_IRUSR, &proc_root);
 	if (entry)
 		entry->proc_fops = &proc_kmsg_operations;
-	create_seq_entry("mounts", 0, &proc_mounts_operations);
 	create_seq_entry("cpuinfo", 0, &proc_cpuinfo_operations);
 #ifdef CONFIG_MODULES
 	create_seq_entry("ksyms", 0, &proc_ksyms_operations);
diff -urN linux-2.4.19-pre5/fs/ramfs/inode.c linux-2.4.19-pre6/fs/ramfs/inode.c
--- linux-2.4.19-pre5/fs/ramfs/inode.c	Wed Oct 24 15:19:18 2001
+++ linux-2.4.19-pre6/fs/ramfs/inode.c	Thu Apr  4 22:05:12 2002
@@ -325,6 +325,7 @@
 }
 
 static DECLARE_FSTYPE(ramfs_fs_type, "ramfs", ramfs_read_super, FS_LITTER);
+static DECLARE_FSTYPE(rootfs_fs_type, "rootfs", ramfs_read_super, FS_NOMOUNT|FS_LITTER);
 
 static int __init init_ramfs_fs(void)
 {
@@ -338,5 +339,11 @@
 
 module_init(init_ramfs_fs)
 module_exit(exit_ramfs_fs)
+
+int __init init_rootfs(void)
+{
+	return register_filesystem(&rootfs_fs_type);
+}
+
 MODULE_LICENSE("GPL");
 
diff -urN linux-2.4.19-pre5/fs/super.c linux-2.4.19-pre6/fs/super.c
--- linux-2.4.19-pre5/fs/super.c	Thu Apr  4 22:04:27 2002
+++ linux-2.4.19-pre6/fs/super.c	Thu Apr  4 22:05:12 2002
@@ -34,8 +34,6 @@
 #define __NO_VERSION__
 #include <linux/module.h>
 
-int do_remount_sb(struct super_block *sb, int flags, void * data);
-
 LIST_HEAD(super_blocks);
 spinlock_t sb_lock = SPIN_LOCK_UNLOCKED;
 
@@ -377,7 +375,7 @@
 	get_filesystem(type);
 }
 
-void put_unnamed_dev(kdev_t dev);	/* should become static */
+static void put_anon_dev(kdev_t dev);
 
 /**
  *	remove_super	-	makes superblock unreachable
@@ -407,12 +405,11 @@
 	if (bdev)
 		blkdev_put(bdev, BDEV_FS);
 	else
-		put_unnamed_dev(dev);
+		put_anon_dev(dev);
 }
 
-struct vfsmount *alloc_vfsmnt(void);
+struct vfsmount *alloc_vfsmnt(char *name);
 void free_vfsmnt(struct vfsmount *mnt);
-void set_devname(struct vfsmount *mnt, const char *name);
 
 static inline struct super_block * find_super(kdev_t dev)
 {
@@ -530,36 +527,122 @@
 	return err;
 }
 
+/**
+ *	do_remount_sb	-	asks filesystem to change mount options.
+ *	@sb:	superblock in question
+ *	@flags:	numeric part of options
+ *	@data:	the rest of options
+ *
+ *	Alters the mount options of a mounted file system.
+ */
+int do_remount_sb(struct super_block *sb, int flags, void *data)
+{
+	int retval;
+	
+	if (!(flags & MS_RDONLY) && sb->s_dev && is_read_only(sb->s_dev))
+		return -EACCES;
+		/*flags |= MS_RDONLY;*/
+	if (flags & MS_RDONLY)
+		acct_auto_close(sb->s_dev);
+	shrink_dcache_sb(sb);
+	fsync_super(sb);
+	/* If we are remounting RDONLY, make sure there are no rw files open */
+	if ((flags & MS_RDONLY) && !(sb->s_flags & MS_RDONLY))
+		if (!fs_may_remount_ro(sb))
+			return -EBUSY;
+	if (sb->s_op && sb->s_op->remount_fs) {
+		lock_super(sb);
+		retval = sb->s_op->remount_fs(sb, &flags, data);
+		unlock_super(sb);
+		if (retval)
+			return retval;
+	}
+	sb->s_flags = (sb->s_flags & ~MS_RMT_MASK) | (flags & MS_RMT_MASK);
+	return 0;
+}
+
 /*
  * Unnamed block devices are dummy devices used by virtual
  * filesystems which don't use real block-devices.  -- jrs
  */
 
-static unsigned long unnamed_dev_in_use[256/(8*sizeof(unsigned long))];
+enum {Max_anon = 256};
+static unsigned long unnamed_dev_in_use[Max_anon/(8*sizeof(unsigned long))];
+static spinlock_t unnamed_dev_lock = SPIN_LOCK_UNLOCKED;/* protects the above */
 
-kdev_t get_unnamed_dev(void)
+/**
+ *	put_anon_dev	-	release anonymous device number.
+ *	@dev:	device in question
+ */
+static void put_anon_dev(kdev_t dev)
 {
-	int i;
-
-	for (i = 1; i < 256; i++) {
-		if (!test_and_set_bit(i,unnamed_dev_in_use))
-			return MKDEV(UNNAMED_MAJOR, i);
-	}
-	return 0;
+	spin_lock(&unnamed_dev_lock);
+	clear_bit(MINOR(dev), unnamed_dev_in_use);
+	spin_unlock(&unnamed_dev_lock);
 }
 
-void put_unnamed_dev(kdev_t dev)
+/**
+ *	get_anon_super	-	allocate a superblock for non-device fs
+ *	@type:		filesystem type
+ *	@compare:	check if existing superblock is what we want
+ *	@data:		argument for @compare.
+ *
+ *	get_anon_super is a helper for non-blockdevice filesystems.
+ *	It either finds and returns one of the superblocks of given type
+ *	(if it can find one that would satisfy caller) or creates a new
+ *	one.  In the either case we return an active reference to superblock
+ *	with ->s_umount locked.  If superblock is new it gets a new
+ *	anonymous device allocated for it and is inserted into lists -
+ *	other initialization is left to caller.
+ *
+ *	Rather than duplicating all that logics every time when
+ *	we want something that doesn't fit "nodev" and "single" we pull
+ *	the relevant code into common helper and let get_sb_...() call
+ *	it.
+ *
+ *	NB: get_sb_...() is going to become an fs type method, with
+ *	current ->read_super() becoming a callback used by common instances.
+ */
+struct super_block *get_anon_super(struct file_system_type *type,
+	int (*compare)(struct super_block *,void *), void *data)
 {
-	if (!dev || MAJOR(dev) != UNNAMED_MAJOR)
-		return;
-	if (test_and_clear_bit(MINOR(dev), unnamed_dev_in_use))
-		return;
-	printk("VFS: put_unnamed_dev: freeing unused device %s\n",
-			kdevname(dev));
+	struct super_block *s = alloc_super();
+	kdev_t dev;
+	struct list_head *p;
+
+	if (!s)
+		return ERR_PTR(-ENOMEM);
+
+	spin_lock(&unnamed_dev_lock);
+	dev = find_first_zero_bit(unnamed_dev_in_use, Max_anon);
+	if (dev == Max_anon) {
+		spin_unlock(&unnamed_dev_lock);
+		destroy_super(s);
+		return ERR_PTR(-EMFILE);
+	}
+	set_bit(dev, unnamed_dev_in_use);
+	spin_unlock(&unnamed_dev_lock);
+
+retry:
+	spin_lock(&sb_lock);
+	if (compare) list_for_each(p, &type->fs_supers) {
+		struct super_block *old;
+		old = list_entry(p, struct super_block, s_instances);
+		if (!compare(old, data))
+			continue;
+		if (!grab_super(old))
+			goto retry;
+		destroy_super(s);
+		return old;
+	}
+
+	s->s_dev = dev;
+	insert_super(s, type);
+	return s;
 }
 
 static struct super_block *get_sb_bdev(struct file_system_type *fs_type,
-	char *dev_name, int flags, void * data)
+	int flags, char *dev_name, void * data)
 {
 	struct inode *inode;
 	struct block_device *bdev;
@@ -601,17 +684,13 @@
 		goto out;
 	check_disk_change(dev);
 	error = -EACCES;
-	if (!(flags & MS_RDONLY) && is_read_only(dev)) {
-		blkdev_put(bdev, BDEV_FS);
-		goto out;
-	}
+	if (!(flags & MS_RDONLY) && is_read_only(dev))
+		goto out1;
 
 	error = -ENOMEM;
 	s = alloc_super();
-	if (!s) {
-		blkdev_put(bdev, BDEV_FS);
-		goto out;
-	}
+	if (!s)
+		goto out1;
 
 	error = -EBUSY;
 restart:
@@ -625,8 +704,7 @@
 		    ((flags ^ old->s_flags) & MS_RDONLY)) {
 			spin_unlock(&sb_lock);
 			destroy_super(s);
-			blkdev_put(bdev, BDEV_FS);
-			goto out;
+			goto out1;
 		}
 		if (!grab_super(old))
 			goto restart;
@@ -639,97 +717,102 @@
 	s->s_bdev = bdev;
 	s->s_flags = flags;
 	insert_super(s, fs_type);
-
-	error = -EINVAL;
-	lock_super(s);
 	if (!fs_type->read_super(s, data, flags & MS_VERBOSE ? 1 : 0))
-		goto out_fail;
+		goto Einval;
 	s->s_flags |= MS_ACTIVE;
-	unlock_super(s);
 	path_release(&nd);
 	return s;
 
-out_fail:
-	unlock_super(s);
+Einval:
 	deactivate_super(s);
 	remove_super(s);
+	error = -EINVAL;
+	goto out;
+out1:
+	blkdev_put(bdev, BDEV_FS);
 out:
 	path_release(&nd);
 	return ERR_PTR(error);
 }
 
 static struct super_block *get_sb_nodev(struct file_system_type *fs_type,
-	int flags, void * data)
+	int flags, char *dev_name, void *data)
 {
-	struct super_block *s = alloc_super();
+	struct super_block *s = get_anon_super(fs_type, NULL, NULL);
+
+	if (IS_ERR(s))
+		return s;
 
-	if (!s)
-		return ERR_PTR(-ENOMEM);
-	s->s_dev = get_unnamed_dev();
-	if (!s->s_dev) {
-		destroy_super(s);
-		return ERR_PTR(-EMFILE);
-	}
 	s->s_flags = flags;
-	spin_lock(&sb_lock);
-	insert_super(s, fs_type);
-	lock_super(s);
-	if (!fs_type->read_super(s, data, flags & MS_VERBOSE ? 1 : 0))
-		goto out_fail;
+	if (!fs_type->read_super(s, data, flags & MS_VERBOSE ? 1 : 0)) {
+		deactivate_super(s);
+		remove_super(s);
+		return ERR_PTR(-EINVAL);
+	}
 	s->s_flags |= MS_ACTIVE;
-	unlock_super(s);
 	return s;
+}
 
-out_fail:
-	unlock_super(s);
-	deactivate_super(s);
-	remove_super(s);
-	return ERR_PTR(-EINVAL);
+static int compare_single(struct super_block *s, void *p)
+{
+	return 1;
 }
 
 static struct super_block *get_sb_single(struct file_system_type *fs_type,
-	int flags, void *data)
+	int flags, char *dev_name, void *data)
 {
-	struct super_block * s = alloc_super();
-	if (!s)
-		return ERR_PTR(-ENOMEM);
-	/*
-	 * Get the superblock of kernel-wide instance, but
-	 * keep the reference to fs_type.
-	 */
-retry:
-	spin_lock(&sb_lock);
-	if (!list_empty(&fs_type->fs_supers)) {
-		struct super_block *old;
-		old = list_entry(fs_type->fs_supers.next, struct super_block,
-				s_instances);
-		if (!grab_super(old))
-			goto retry;
-		destroy_super(s);
-		do_remount_sb(old, flags, data);
-		return old;
-	} else {
-		s->s_dev = get_unnamed_dev();
-		if (!s->s_dev) {
-			spin_unlock(&sb_lock);
-			destroy_super(s);
-			return ERR_PTR(-EMFILE);
-		}
+	struct super_block *s = get_anon_super(fs_type, compare_single, NULL);
+
+	if (IS_ERR(s))
+		return s;
+	if (!s->s_root) {
 		s->s_flags = flags;
-		insert_super(s, fs_type);
-		lock_super(s);
-		if (!fs_type->read_super(s, data, flags & MS_VERBOSE ? 1 : 0))
-			goto out_fail;
+		if (!fs_type->read_super(s, data, flags & MS_VERBOSE ? 1 : 0)) {
+			deactivate_super(s);
+			remove_super(s);
+			return ERR_PTR(-EINVAL);
+		}
 		s->s_flags |= MS_ACTIVE;
-		unlock_super(s);
-		return s;
-
-	out_fail:
-		unlock_super(s);
-		deactivate_super(s);
-		remove_super(s);
-		return ERR_PTR(-EINVAL);
 	}
+	do_remount_sb(s, flags, data);
+	return s;
+}
+
+struct vfsmount *
+do_kern_mount(const char *fstype, int flags, char *name, void *data)
+{
+	struct file_system_type *type = get_fs_type(fstype);
+	struct super_block *sb = ERR_PTR(-ENOMEM);
+	struct vfsmount *mnt;
+
+	if (!type)
+		return ERR_PTR(-ENODEV);
+
+	mnt = alloc_vfsmnt(name);
+	if (!mnt)
+		goto out;
+	if (type->fs_flags & FS_REQUIRES_DEV)
+		sb = get_sb_bdev(type, flags, name, data);
+	else if (type->fs_flags & FS_SINGLE)
+		sb = get_sb_single(type, flags, name, data);
+	else
+		sb = get_sb_nodev(type, flags, name, data);
+	if (IS_ERR(sb))
+		goto out_mnt;
+	if (type->fs_flags & FS_NOMOUNT)
+		sb->s_flags |= MS_NOUSER;
+	mnt->mnt_sb = sb;
+	mnt->mnt_root = dget(sb->s_root);
+	mnt->mnt_mountpoint = sb->s_root;
+	mnt->mnt_parent = mnt;
+	up_write(&sb->s_umount);
+	put_filesystem(type);
+	return mnt;
+out_mnt:
+	free_vfsmnt(mnt);
+out:
+	put_filesystem(type);
+	return (struct vfsmount *)sb;
 }
 
 void kill_super(struct super_block *sb)
@@ -742,7 +825,6 @@
 		return;
 
 	down_write(&sb->s_umount);
-	lock_kernel();
 	sb->s_root = NULL;
 	/* Need to clean after the sucker */
 	if (fs->fs_flags & FS_LITTER)
@@ -751,6 +833,7 @@
 	dput(root);
 	fsync_super(sb);
 	lock_super(sb);
+	lock_kernel();
 	sb->s_flags &= ~MS_ACTIVE;
 	invalidate_inodes(sb);	/* bad name - it should be evict_inodes() */
 	if (sop) {
@@ -771,96 +854,7 @@
 	remove_super(sb);
 }
 
-/*
- * Alters the mount flags of a mounted file system. Only the mount point
- * is used as a reference - file system type and the device are ignored.
- */
-
-int do_remount_sb(struct super_block *sb, int flags, void *data)
-{
-	int retval;
-	
-	if (!(flags & MS_RDONLY) && sb->s_dev && is_read_only(sb->s_dev))
-		return -EACCES;
-		/*flags |= MS_RDONLY;*/
-	if (flags & MS_RDONLY)
-		acct_auto_close(sb->s_dev);
-	shrink_dcache_sb(sb);
-	fsync_super(sb);
-	/* If we are remounting RDONLY, make sure there are no rw files open */
-	if ((flags & MS_RDONLY) && !(sb->s_flags & MS_RDONLY))
-		if (!fs_may_remount_ro(sb))
-			return -EBUSY;
-	if (sb->s_op && sb->s_op->remount_fs) {
-		lock_super(sb);
-		retval = sb->s_op->remount_fs(sb, &flags, data);
-		unlock_super(sb);
-		if (retval)
-			return retval;
-	}
-	sb->s_flags = (sb->s_flags & ~MS_RMT_MASK) | (flags & MS_RMT_MASK);
-
-	/*
-	 * We can't invalidate inodes as we can loose data when remounting
-	 * (someone might manage to alter data while we are waiting in lock_super()
-	 * or in foo_remount_fs()))
-	 */
-
-	return 0;
-}
-
-struct vfsmount *do_kern_mount(char *type, int flags, char *name, void *data)
-{
-	struct file_system_type * fstype;
-	struct vfsmount *mnt = NULL;
-	struct super_block *sb;
-
-	if (!type || !memchr(type, 0, PAGE_SIZE))
-		return ERR_PTR(-EINVAL);
-
-	/* we need capabilities... */
-	if (!capable(CAP_SYS_ADMIN))
-		return ERR_PTR(-EPERM);
-
-	/* ... filesystem driver... */
-	fstype = get_fs_type(type);
-	if (!fstype)		
-		return ERR_PTR(-ENODEV);
-
-	/* ... allocated vfsmount... */
-	mnt = alloc_vfsmnt();
-	if (!mnt) {
-		mnt = ERR_PTR(-ENOMEM);
-		goto fs_out;
-	}
-	set_devname(mnt, name);
-	/* get locked superblock */
-	if (fstype->fs_flags & FS_REQUIRES_DEV)
-		sb = get_sb_bdev(fstype, name, flags, data);
-	else if (fstype->fs_flags & FS_SINGLE)
-		sb = get_sb_single(fstype, flags, data);
-	else
-		sb = get_sb_nodev(fstype, flags, data);
-
-	if (IS_ERR(sb)) {
-		free_vfsmnt(mnt);
-		mnt = (struct vfsmount *)sb;
-		goto fs_out;
-	}
-	if (fstype->fs_flags & FS_NOMOUNT)
-		sb->s_flags |= MS_NOUSER;
-
-	mnt->mnt_sb = sb;
-	mnt->mnt_root = dget(sb->s_root);
-	mnt->mnt_mountpoint = mnt->mnt_root;
-	mnt->mnt_parent = mnt;
-	up_write(&sb->s_umount);
-fs_out:
-	put_filesystem(fstype);
-	return mnt;
-}
-
 struct vfsmount *kern_mount(struct file_system_type *type)
 {
-	return do_kern_mount((char *)type->name, 0, (char *)type->name, NULL);
+	return do_kern_mount(type->name, 0, (char *)type->name, NULL);
 }
diff -urN linux-2.4.19-pre5/include/asm-i386/types.h linux-2.4.19-pre6/include/asm-i386/types.h
--- linux-2.4.19-pre5/include/asm-i386/types.h	Fri Oct 12 15:35:54 2001
+++ linux-2.4.19-pre6/include/asm-i386/types.h	Thu Apr  4 22:05:13 2002
@@ -45,7 +45,7 @@
 
 /* DMA addresses come in generic and 64-bit flavours.  */
 
-#ifdef CONFIG_HIGHMEM
+#ifdef CONFIG_HIGHMEM64G
 typedef u64 dma_addr_t;
 #else
 typedef u32 dma_addr_t;
diff -urN linux-2.4.19-pre5/include/asm-m68k/machdep.h linux-2.4.19-pre6/include/asm-m68k/machdep.h
--- linux-2.4.19-pre5/include/asm-m68k/machdep.h	Mon Nov 27 17:57:34 2000
+++ linux-2.4.19-pre6/include/asm-m68k/machdep.h	Thu Apr  4 22:05:14 2002
@@ -37,7 +37,6 @@
 extern void (*mach_hd_setup)(char *, int *);
 extern long mach_max_dma_address;
 extern void (*mach_floppy_setup)(char *, int *);
-extern void (*mach_floppy_eject)(void);
 extern void (*mach_heartbeat) (int);
 extern void (*mach_l2_flush) (int);
 extern int mach_sysrq_key;
diff -urN linux-2.4.19-pre5/include/asm-sparc/keyboard.h linux-2.4.19-pre6/include/asm-sparc/keyboard.h
--- linux-2.4.19-pre5/include/asm-sparc/keyboard.h	Tue Aug 28 07:09:44 2001
+++ linux-2.4.19-pre6/include/asm-sparc/keyboard.h	Thu Apr  4 22:05:15 2002
@@ -40,7 +40,6 @@
 #define kbd_init			pcikbd_init
 
 #define compute_shiftstate		pci_compute_shiftstate
-#define keyboard_wait_for_keypress	pci_wait_for_keypress
 #define getkeycode			pci_getkeycode
 #define setkeycode			pci_setkeycode
 #define getledstate			pci_getledstate
diff -urN linux-2.4.19-pre5/include/asm-sparc64/keyboard.h linux-2.4.19-pre6/include/asm-sparc64/keyboard.h
--- linux-2.4.19-pre5/include/asm-sparc64/keyboard.h	Tue Aug 28 07:09:44 2001
+++ linux-2.4.19-pre6/include/asm-sparc64/keyboard.h	Thu Apr  4 22:05:15 2002
@@ -38,7 +38,6 @@
 #define kbd_init			pcikbd_init
 
 #define compute_shiftstate		pci_compute_shiftstate
-#define keyboard_wait_for_keypress	pci_wait_for_keypress
 #define getkeycode			pci_getkeycode
 #define setkeycode			pci_setkeycode
 #define getledstate			pci_getledstate
diff -urN linux-2.4.19-pre5/include/linux/agp_backend.h linux-2.4.19-pre6/include/linux/agp_backend.h
--- linux-2.4.19-pre5/include/linux/agp_backend.h	Fri Nov  9 14:11:15 2001
+++ linux-2.4.19-pre6/include/linux/agp_backend.h	Thu Apr  4 22:05:15 2002
@@ -69,6 +69,7 @@
 	ALI_M1631,
 	ALI_M1632,
 	ALI_M1641,
+	ALI_M1644,
 	ALI_M1647,
 	ALI_M1651,
 	ALI_GENERIC,
diff -urN linux-2.4.19-pre5/include/linux/blk.h linux-2.4.19-pre6/include/linux/blk.h
--- linux-2.4.19-pre5/include/linux/blk.h	Thu Nov 22 11:48:07 2001
+++ linux-2.4.19-pre6/include/linux/blk.h	Thu Apr  4 22:05:15 2002
@@ -59,8 +59,6 @@
 void add_blkdev_randomness(int major);
 
 extern int floppy_init(void);
-extern void rd_load(void);
-extern int rd_init(void);
 extern int rd_doload;		/* 1 = load ramdisk, 0 = don't load */
 extern int rd_prompt;		/* 1 = prompt for ramdisk, 0 = don't prompt */
 extern int rd_image_start;	/* starting block # of image */
@@ -70,7 +68,6 @@
 #define INITRD_MINOR 250 /* shouldn't collide with /dev/ram* too soon ... */
 
 extern unsigned long initrd_start,initrd_end;
-extern int mount_initrd; /* zero if initrd should not be mounted */
 extern int initrd_below_start_ok; /* 1 if it is not an error if initrd_start < memory_start */
 void initrd_init(void);
 
diff -urN linux-2.4.19-pre5/include/linux/blkdev.h linux-2.4.19-pre6/include/linux/blkdev.h
--- linux-2.4.19-pre5/include/linux/blkdev.h	Thu Apr  4 22:04:28 2002
+++ linux-2.4.19-pre6/include/linux/blkdev.h	Thu Apr  4 22:05:15 2002
@@ -30,6 +30,7 @@
 	kdev_t rq_dev;
 	int cmd;		/* READ or WRITE */
 	int errors;
+	unsigned long start_time;
 	unsigned long sector;
 	unsigned long nr_sectors;
 	unsigned long hard_sector, hard_nr_sectors;
diff -urN linux-2.4.19-pre5/include/linux/coda_fs_i.h linux-2.4.19-pre6/include/linux/coda_fs_i.h
--- linux-2.4.19-pre5/include/linux/coda_fs_i.h	Mon Feb 25 11:38:13 2002
+++ linux-2.4.19-pre6/include/linux/coda_fs_i.h	Thu Apr  4 22:05:15 2002
@@ -20,12 +20,22 @@
         struct ViceFid     c_fid;	/* Coda identifier */
         u_short	           c_flags;     /* flags (see below) */
 	struct list_head   c_cilist;    /* list of all coda inodes */
-	struct file	  *c_container; /* container file for this cnode */
-	unsigned int       c_contcount; /* refcount for container file */
         struct coda_cred   c_cached_cred; /* credentials of cached perms */
         unsigned int       c_cached_perm; /* cached access permissions */
 };
 
+/*
+ * coda fs file private data
+ */
+#define CODA_MAGIC 0xC0DAC0DA
+struct coda_file_info {
+	int		 cfi_magic;	/* magic number */
+	struct file	*cfi_container;	/* container file for this cnode */
+	struct coda_cred cfi_cred;	/* credentials of opener */
+};
+
+#define CODA_FTOC(file) ((struct coda_file_info *)((file)->private_data))
+
 /* flags */
 #define C_VATTR       0x1   /* Validity of vattr in inode */
 #define C_FLUSH       0x2   /* used after a flush */
diff -urN linux-2.4.19-pre5/include/linux/coda_linux.h linux-2.4.19-pre6/include/linux/coda_linux.h
--- linux-2.4.19-pre5/include/linux/coda_linux.h	Thu Apr  4 22:04:28 2002
+++ linux-2.4.19-pre6/include/linux/coda_linux.h	Thu Apr  4 22:05:15 2002
@@ -21,6 +21,7 @@
 #include <linux/wait.h>		
 #include <linux/types.h>
 #include <linux/fs.h>
+#include <linux/coda_fs_i.h>
 
 /* operations */
 extern struct inode_operations coda_dir_inode_operations;
@@ -45,7 +46,6 @@
 
 /* global variables */
 extern int coda_debug;
-extern int coda_print_entry;
 extern int coda_access_cache;
 extern int coda_fake_statfs;
 
@@ -91,22 +91,19 @@
     printk(format, ## a); }                                       \
 } while (0)
 
-#define CODA_ALLOC(ptr, cast, size)                                       \
-do {                                                                      \
-    if (size < PAGE_SIZE) {                                               \
-        ptr = (cast)kmalloc((unsigned long) size, GFP_KERNEL);            \
-        CDEBUG(D_MALLOC, "kmalloced: %lx at %p.\n", (long)size, ptr);     \
-     }  else {                                                            \
-        ptr = (cast)vmalloc((unsigned long) size);                        \
-	CDEBUG(D_MALLOC, "vmalloced: %lx at %p .\n", (long)size, ptr);}   \
-    if (ptr == 0) {                                                       \
+#define CODA_ALLOC(ptr, cast, size) do { \
+    if (size < PAGE_SIZE) \
+        ptr = (cast)kmalloc((unsigned long) size, GFP_KERNEL); \
+    else \
+        ptr = (cast)vmalloc((unsigned long) size); \
+    if (!ptr) \
         printk("kernel malloc returns 0 at %s:%d\n", __FILE__, __LINE__); \
-    }                                                                     \
-    else memset( ptr, 0, size );                                          \
+    else memset( ptr, 0, size ); \
 } while (0)
 
 
-#define CODA_FREE(ptr,size) do {if (size < PAGE_SIZE) { kfree((ptr)); CDEBUG(D_MALLOC, "kfreed: %lx at %p.\n", (long) size, ptr); } else { vfree((ptr)); CDEBUG(D_MALLOC, "vfreed: %lx at %p.\n", (long) size, ptr);} } while (0)
+#define CODA_FREE(ptr,size) \
+    do { if (size < PAGE_SIZE) kfree((ptr)); else vfree((ptr)); } while (0)
 
 /* inode to cnode access functions */
 
diff -urN linux-2.4.19-pre5/include/linux/console.h linux-2.4.19-pre6/include/linux/console.h
--- linux-2.4.19-pre5/include/linux/console.h	Thu Nov 22 11:46:19 2001
+++ linux-2.4.19-pre6/include/linux/console.h	Thu Apr  4 22:05:15 2002
@@ -97,7 +97,6 @@
 	void	(*write)(struct console *, const char *, unsigned);
 	int	(*read)(struct console *, const char *, unsigned);
 	kdev_t	(*device)(struct console *);
-	int	(*wait_key)(struct console *);
 	void	(*unblank)(void);
 	int	(*setup)(struct console *, char *);
 	short	flags;
diff -urN linux-2.4.19-pre5/include/linux/devfs_fs_kernel.h linux-2.4.19-pre6/include/linux/devfs_fs_kernel.h
--- linux-2.4.19-pre5/include/linux/devfs_fs_kernel.h	Thu Apr  4 22:04:28 2002
+++ linux-2.4.19-pre6/include/linux/devfs_fs_kernel.h	Thu Apr  4 22:05:15 2002
@@ -54,7 +54,7 @@
     unsigned char sem_initialised;
     unsigned int num_free;          /*  Num free in bits       */
     unsigned int length;            /*  Array length in bytes  */
-    __u32 *bits;
+    unsigned long *bits;
     struct semaphore semaphore;
 };
 
@@ -116,7 +116,6 @@
 					 int number);
 
 extern void mount_devfs_fs (void);
-extern void devfs_make_root (const char *name);
 
 #else  /*  CONFIG_DEVFS_FS  */
 
@@ -312,10 +311,6 @@
 {
     return;
 }
-static inline void devfs_make_root (const char *name)
-{
-    return;
-}
 #endif  /*  CONFIG_DEVFS_FS  */
 
 #endif  /*  _LINUX_DEVFS_FS_KERNEL_H  */
diff -urN linux-2.4.19-pre5/include/linux/fb.h linux-2.4.19-pre6/include/linux/fb.h
--- linux-2.4.19-pre5/include/linux/fb.h	Thu Apr  4 22:04:28 2002
+++ linux-2.4.19-pre6/include/linux/fb.h	Thu Apr  4 22:05:15 2002
@@ -95,6 +95,18 @@
 #define FB_ACCEL_SIS_GLAMOUR    36	/* SiS 300/630/540              */
 #define FB_ACCEL_3DLABS_PERMEDIA3 37	/* 3Dlabs Permedia 3		*/
 
+
+#define FB_ACCEL_NEOMAGIC_NM2070 90	/* NeoMagic NM2070              */
+#define FB_ACCEL_NEOMAGIC_NM2090 91	/* NeoMagic NM2090              */
+#define FB_ACCEL_NEOMAGIC_NM2093 92	/* NeoMagic NM2093              */
+#define FB_ACCEL_NEOMAGIC_NM2097 93	/* NeoMagic NM2097              */
+#define FB_ACCEL_NEOMAGIC_NM2160 94	/* NeoMagic NM2160              */
+#define FB_ACCEL_NEOMAGIC_NM2200 95	/* NeoMagic NM2200              */
+#define FB_ACCEL_NEOMAGIC_NM2230 96	/* NeoMagic NM2230              */
+#define FB_ACCEL_NEOMAGIC_NM2360 97	/* NeoMagic NM2360              */
+#define FB_ACCEL_NEOMAGIC_NM2380 98	/* NeoMagic NM2380              */
+
+
 struct fb_fix_screeninfo {
 	char id[16];			/* identification string eg "TT Builtin" */
 	unsigned long smem_start;	/* Start of frame buffer mem */
diff -urN linux-2.4.19-pre5/include/linux/fd.h linux-2.4.19-pre6/include/linux/fd.h
--- linux-2.4.19-pre5/include/linux/fd.h	Fri Aug 13 12:16:16 1999
+++ linux-2.4.19-pre6/include/linux/fd.h	Thu Apr  4 22:05:15 2002
@@ -369,10 +369,4 @@
 #define FDEJECT _IO(2, 0x5a)
 /* eject the disk */
 
-
-#ifdef __KERNEL__
-/* eject the boot floppy (if we need the drive for a different root floppy) */
-void floppy_eject(void);
-#endif
-
 #endif
diff -urN linux-2.4.19-pre5/include/linux/fs.h linux-2.4.19-pre6/include/linux/fs.h
--- linux-2.4.19-pre5/include/linux/fs.h	Thu Apr  4 22:04:28 2002
+++ linux-2.4.19-pre6/include/linux/fs.h	Thu Apr  4 22:05:15 2002
@@ -993,6 +993,7 @@
 extern struct vfsmount *kern_mount(struct file_system_type *);
 extern int may_umount(struct vfsmount *);
 extern long do_mount(char *, char *, char *, unsigned long, void *);
+extern void umount_tree(struct vfsmount *);
 
 #define kern_umount mntput
 
diff -urN linux-2.4.19-pre5/include/linux/gameport.h linux-2.4.19-pre6/include/linux/gameport.h
--- linux-2.4.19-pre5/include/linux/gameport.h	Thu Nov 22 11:49:20 2001
+++ linux-2.4.19-pre6/include/linux/gameport.h	Thu Apr  4 22:05:15 2002
@@ -38,6 +38,7 @@
 struct gameport {
 
 	void *private;
+	void *driver;
 
 	int number;
 
diff -urN linux-2.4.19-pre5/include/linux/genhd.h linux-2.4.19-pre6/include/linux/genhd.h
--- linux-2.4.19-pre5/include/linux/genhd.h	Mon Feb 25 11:38:13 2002
+++ linux-2.4.19-pre6/include/linux/genhd.h	Thu Apr  4 22:05:15 2002
@@ -63,6 +63,22 @@
 	unsigned long nr_sects;
 	devfs_handle_t de;              /* primary (master) devfs entry  */
 	int number;                     /* stupid old code wastes space  */
+
+	/* Performance stats: */
+	unsigned int ios_in_flight;
+	unsigned int io_ticks;
+	unsigned int last_idle_time;
+	unsigned int last_queue_change;
+	unsigned int aveq;
+	
+	unsigned int rd_ios;
+	unsigned int rd_merges;
+	unsigned int rd_ticks;
+	unsigned int rd_sectors;
+	unsigned int wr_ios;
+	unsigned int wr_merges;
+	unsigned int wr_ticks;
+	unsigned int wr_sectors;	
 };
 
 #define GENHD_FL_REMOVABLE  1
@@ -242,6 +258,19 @@
 
 char *disk_name (struct gendisk *hd, int minor, char *buf);
 
+/*
+ * disk_round_stats is used to round off the IO statistics for a disk
+ * for a complete clock tick.
+ */
+void disk_round_stats(struct hd_struct *hd);
+
+/* 
+ * Account for the completion of an IO request (used by drivers which 
+ * bypass the normal end_request processing) 
+ */
+struct request;
+void req_finished_io(struct request *);
+
 extern void devfs_register_partitions (struct gendisk *dev, int minor,
 				       int unregister);
 
diff -urN linux-2.4.19-pre5/include/linux/hiddev.h linux-2.4.19-pre6/include/linux/hiddev.h
--- linux-2.4.19-pre5/include/linux/hiddev.h	Wed Sep 12 15:34:06 2001
+++ linux-2.4.19-pre6/include/linux/hiddev.h	Thu Apr  4 22:05:15 2002
@@ -185,7 +185,7 @@
 #else
 static inline void *hiddev_connect(struct hid_device *hid) { return NULL; }
 static inline void hiddev_disconnect(struct hid_device *hid) { }
-static inline void hiddev_event(struct hid_device *hid, unsigned int usage, int value) { }
+static inline void hiddev_hid_event(struct hid_device *hid, unsigned int usage, int value) { }
 static inline int hiddev_init(void) { return 0; }
 static inline void hiddev_exit(void) { }
 #endif
diff -urN linux-2.4.19-pre5/include/linux/kbd_kern.h linux-2.4.19-pre6/include/linux/kbd_kern.h
--- linux-2.4.19-pre5/include/linux/kbd_kern.h	Thu Nov 22 11:47:23 2001
+++ linux-2.4.19-pre6/include/linux/kbd_kern.h	Thu Apr  4 22:05:15 2002
@@ -140,7 +140,6 @@
 int getkeycode(unsigned int scancode);
 int setkeycode(unsigned int scancode, unsigned int keycode);
 void compute_shiftstate(void);
-int keyboard_wait_for_keypress(struct console *);
 
 /* defkeymap.c */
 
diff -urN linux-2.4.19-pre5/include/linux/kernel.h linux-2.4.19-pre6/include/linux/kernel.h
--- linux-2.4.19-pre5/include/linux/kernel.h	Thu Apr  4 22:04:28 2002
+++ linux-2.4.19-pre6/include/linux/kernel.h	Thu Apr  4 22:05:15 2002
@@ -184,4 +184,6 @@
 	char _f[20-2*sizeof(long)-sizeof(int)];	/* Padding: libc5 uses this.. */
 };
 
-#endif
+#define BUG_ON(condition) do { if (unlikely((condition)!=0)) BUG(); } while(0)
+
+#endif /* _LINUX_KERNEL_H */
diff -urN linux-2.4.19-pre5/include/linux/keyboard.h linux-2.4.19-pre6/include/linux/keyboard.h
--- linux-2.4.19-pre5/include/linux/keyboard.h	Thu Nov 22 11:47:07 2001
+++ linux-2.4.19-pre6/include/linux/keyboard.h	Thu Apr  4 22:05:15 2002
@@ -26,7 +26,6 @@
 extern const int max_vals[];
 extern unsigned short *key_maps[MAX_NR_KEYMAPS];
 extern unsigned short plain_map[NR_KEYS];
-extern wait_queue_head_t keypress_wait;
 extern unsigned char keyboard_type;
 #endif
 
diff -urN linux-2.4.19-pre5/include/linux/namespace.h linux-2.4.19-pre6/include/linux/namespace.h
--- linux-2.4.19-pre5/include/linux/namespace.h	Wed Dec 31 16:00:00 1969
+++ linux-2.4.19-pre6/include/linux/namespace.h	Thu Apr  4 22:05:15 2002
@@ -0,0 +1,42 @@
+#ifndef _NAMESPACE_H_
+#define _NAMESPACE_H_
+#ifdef __KERNEL__
+
+struct namespace {
+	atomic_t		count;
+	struct vfsmount *	root;
+	struct list_head	list;
+	struct rw_semaphore	sem;
+};
+
+static inline void put_namespace(struct namespace *namespace)
+{
+	if (atomic_dec_and_test(&namespace->count)) {
+		down_write(&namespace->sem);
+		spin_lock(&dcache_lock);
+		umount_tree(namespace->root);
+		spin_unlock(&dcache_lock);
+		up_write(&namespace->sem);
+		kfree(namespace);
+	}
+}
+
+static inline void exit_namespace(struct task_struct *p)
+{
+	struct namespace *namespace = p->namespace;
+	if (namespace) {
+		task_lock(p);
+		p->namespace = NULL;
+		task_unlock(p);
+		put_namespace(namespace);
+	}
+}
+extern int copy_namespace(int, struct task_struct *);
+
+static inline void get_namespace(struct namespace *namespace)
+{
+	atomic_inc(&namespace->count);
+}
+
+#endif
+#endif
diff -urN linux-2.4.19-pre5/include/linux/nfs_fs.h linux-2.4.19-pre6/include/linux/nfs_fs.h
--- linux-2.4.19-pre5/include/linux/nfs_fs.h	Thu Apr  4 22:04:28 2002
+++ linux-2.4.19-pre6/include/linux/nfs_fs.h	Thu Apr  4 22:05:15 2002
@@ -276,6 +276,9 @@
 extern int  nfs_mount(struct sockaddr_in *, char *, struct nfs_fh *);
 extern int  nfs3_mount(struct sockaddr_in *, char *, struct nfs_fh *);
 
+/* linux/net/ipv4/ipconfig.c: trims ip addr off front of name, too. */
+extern u32 root_nfs_parse_addr(char *name); /*__init*/
+
 /*
  * inline functions
  */
diff -urN linux-2.4.19-pre5/include/linux/nfsd/export.h linux-2.4.19-pre6/include/linux/nfsd/export.h
--- linux-2.4.19-pre5/include/linux/nfsd/export.h	Thu Nov 22 11:47:20 2001
+++ linux-2.4.19-pre6/include/linux/nfsd/export.h	Thu Apr  4 22:05:15 2002
@@ -54,11 +54,13 @@
 	int			cl_naddr;
 	struct in_addr		cl_addr[NFSCLNT_ADDRMAX];
 	struct svc_uidmap *	cl_umap;
-	struct svc_export *	cl_export[NFSCLNT_EXPMAX];
+	struct list_head	cl_export[NFSCLNT_EXPMAX];
+	struct list_head	cl_list;
 };
 
 struct svc_export {
-	struct svc_export *	ex_next;
+	struct list_head	ex_hash;
+	struct list_head	ex_list;
 	char			ex_path[NFS_MAXPATHLEN+1];
 	struct svc_export *	ex_parent;
 	struct svc_client *	ex_client;
diff -urN linux-2.4.19-pre5/include/linux/nfsd/interface.h linux-2.4.19-pre6/include/linux/nfsd/interface.h
--- linux-2.4.19-pre5/include/linux/nfsd/interface.h	Wed Oct  3 22:57:36 2001
+++ linux-2.4.19-pre6/include/linux/nfsd/interface.h	Thu Apr  4 22:05:15 2002
@@ -12,12 +12,15 @@
 
 #include <linux/config.h>
 
-#ifdef CONFIG_NFSD_MODULE
+#ifndef CONFIG_NFSD
+# ifdef CONFIG_MODULES
 
 extern struct nfsd_linkage {
 	long (*do_nfsservctl)(int cmd, void *argp, void *resp);
+	struct module *owner;
 } * nfsd_linkage;
 
+# endif
 #endif
 
 #endif /* LINUX_NFSD_INTERFACE_H */
diff -urN linux-2.4.19-pre5/include/linux/pci_ids.h linux-2.4.19-pre6/include/linux/pci_ids.h
--- linux-2.4.19-pre5/include/linux/pci_ids.h	Thu Apr  4 22:04:28 2002
+++ linux-2.4.19-pre6/include/linux/pci_ids.h	Thu Apr  4 22:05:15 2002
@@ -806,6 +806,7 @@
 #define PCI_DEVICE_ID_AL_M1621          0x1621
 #define PCI_DEVICE_ID_AL_M1631          0x1631
 #define PCI_DEVICE_ID_AL_M1641          0x1641
+#define PCI_DEVICE_ID_AL_M1644          0x1644
 #define PCI_DEVICE_ID_AL_M1647          0x1647
 #define PCI_DEVICE_ID_AL_M1651          0x1651
 #define PCI_DEVICE_ID_AL_M1543		0x1543
diff -urN linux-2.4.19-pre5/include/linux/sched.h linux-2.4.19-pre6/include/linux/sched.h
--- linux-2.4.19-pre5/include/linux/sched.h	Thu Apr  4 22:04:28 2002
+++ linux-2.4.19-pre6/include/linux/sched.h	Thu Apr  4 22:05:15 2002
@@ -42,6 +42,7 @@
 #define CLONE_VFORK	0x00004000	/* set if the parent wants the child to wake it up on mm_release */
 #define CLONE_PARENT	0x00008000	/* set if we want to have the same parent as the cloner */
 #define CLONE_THREAD	0x00010000	/* Same thread group? */
+#define CLONE_NEWNS	0x00020000	/* New namespace group? */
 
 #define CLONE_SIGNAL	(CLONE_SIGHAND | CLONE_THREAD)
 
@@ -166,6 +167,7 @@
  */
 #define NR_OPEN_DEFAULT BITS_PER_LONG
 
+struct namespace;
 /*
  * Open file table structure
  */
@@ -391,6 +393,8 @@
 	struct fs_struct *fs;
 /* open file information */
 	struct files_struct *files;
+/* namespace */
+	struct namespace *namespace;
 /* signal handlers */
 	spinlock_t sigmask_lock;	/* Protects signal and blocked */
 	struct signal_struct *sig;
diff -urN linux-2.4.19-pre5/init/do_mounts.c linux-2.4.19-pre6/init/do_mounts.c
--- linux-2.4.19-pre5/init/do_mounts.c	Thu Apr  4 22:04:28 2002
+++ linux-2.4.19-pre6/init/do_mounts.c	Thu Apr  4 22:05:16 2002
@@ -3,13 +3,10 @@
 #include <linux/slab.h>
 #include <linux/devfs_fs_kernel.h>
 #include <linux/unistd.h>
-#include <linux/string.h>
 #include <linux/ctype.h>
-#include <linux/init.h>
-#include <linux/smp_lock.h>
 #include <linux/blk.h>
-#include <linux/tty.h>
 #include <linux/fd.h>
+#include <linux/tty.h>
 
 #include <linux/nfs_fs.h>
 #include <linux/nfs_fs_sb.h>
@@ -18,12 +15,9 @@
 #include <linux/ext2_fs.h>
 #include <linux/romfs_fs.h>
 
-#include <asm/uaccess.h>
-
 #define BUILD_CRAMDISK
 
 extern int get_filesystem_list(char * buf);
-extern void wait_for_keypress(void);
 
 asmlinkage long sys_mount(char *dev_name, char *dir_name, char *type,
 	 unsigned long flags, void *data);
@@ -38,12 +32,21 @@
 
 #ifdef CONFIG_BLK_DEV_INITRD
 unsigned int real_root_dev;	/* do_proc_dointvec cannot handle kdev_t */
-#endif
-#ifdef CONFIG_BLK_DEV_RAM
-extern int rd_doload;
+static int __initdata mount_initrd = 1;
+
+static int __init no_initrd(char *str)
+{
+	mount_initrd = 0;
+	return 1;
+}
+
+__setup("noinitrd", no_initrd);
 #else
-static int rd_doload = 0;
+static int __initdata mount_initrd = 0;
 #endif
+
+int __initdata rd_doload;	/* 1 = load RAM disk, 0 = don't load */
+
 int root_mountflags = MS_RDONLY | MS_VERBOSE;
 static char root_device_name[64];
 
@@ -52,6 +55,13 @@
 
 static int do_devfs = 0;
 
+static int __init load_ramdisk(char *str)
+{
+	rd_doload = simple_strtol(str,NULL,0) & 3;
+	return 1;
+}
+__setup("load_ramdisk=", load_ramdisk);
+
 static int __init readonly(char *str)
 {
 	if (*str)
@@ -351,29 +361,54 @@
 	return sys_symlink(path + n + 5, name);
 }
 
-#ifdef CONFIG_MAC_FLOPPY
-int swim3_fd_eject(int devnum);
-#endif
 static void __init change_floppy(char *fmt, ...)
 {
-	extern void wait_for_keypress(void);
+	struct termios termios;
 	char buf[80];
+	char c;
+	int fd;
 	va_list args;
 	va_start(args, fmt);
 	vsprintf(buf, fmt, args);
 	va_end(args);
-#ifdef CONFIG_BLK_DEV_FD
-	floppy_eject();
-#endif
-#ifdef CONFIG_MAC_FLOPPY
-	swim3_fd_eject(MINOR(ROOT_DEV));
-#endif
+	fd = open("/dev/root", O_RDWR, 0);
+	if (fd >= 0) {
+		sys_ioctl(fd, FDEJECT, 0);
+		close(fd);
+	}
 	printk(KERN_NOTICE "VFS: Insert %s and press ENTER\n", buf);
-	wait_for_keypress();
+	fd = open("/dev/console", O_RDWR, 0);
+	if (fd >= 0) {
+		sys_ioctl(fd, TCGETS, (long)&termios);
+		termios.c_lflag &= ~ICANON;
+		sys_ioctl(fd, TCSETSF, (long)&termios);
+		read(fd, &c, 1);
+		termios.c_lflag |= ICANON;
+		sys_ioctl(fd, TCSETSF, (long)&termios);
+		close(fd);
+	}
 }
 
 #ifdef CONFIG_BLK_DEV_RAM
 
+int __initdata rd_prompt = 1;	/* 1 = prompt for RAM disk, 0 = don't prompt */
+
+static int __init prompt_ramdisk(char *str)
+{
+	rd_prompt = simple_strtol(str,NULL,0) & 1;
+	return 1;
+}
+__setup("prompt_ramdisk=", prompt_ramdisk);
+
+int __initdata rd_image_start;		/* starting block # of image */
+
+static int __init ramdisk_start_setup(char *str)
+{
+	rd_image_start = simple_strtol(str,NULL,0);
+	return 1;
+}
+__setup("ramdisk_start=", ramdisk_start_setup);
+
 static int __init crd_load(int in_fd, int out_fd);
 
 /*
@@ -591,7 +626,6 @@
 static int __init rd_load_disk(int n)
 {
 #ifdef CONFIG_BLK_DEV_RAM
-	extern int rd_prompt;
 	if (rd_prompt)
 		change_floppy("root floppy disk to be loaded into RAM disk");
 	create_dev("/dev/ram", MKDEV(RAMDISK_MAJOR, n), NULL);
@@ -599,6 +633,63 @@
 	return rd_load_image("/dev/root");
 }
 
+#ifdef CONFIG_DEVFS_FS
+
+static void __init convert_name(char *prefix, char *name, char *p, int part)
+{
+	int host, bus, target, lun;
+	char dest[64];
+	char src[64];
+	char *base = p - 1;
+
+	/*  Decode "c#b#t#u#"  */
+	if (*p++ != 'c')
+		return;
+	host = simple_strtol(p, &p, 10);
+	if (*p++ != 'b')
+		return;
+	bus = simple_strtol(p, &p, 10);
+	if (*p++ != 't')
+		return;
+	target = simple_strtol(p, &p, 10);
+	if (*p++ != 'u')
+		return;
+	lun = simple_strtol(p, &p, 10);
+	if (!part)
+		sprintf(dest, "%s/host%d/bus%d/target%d/lun%d",
+				prefix, host, bus, target, lun);
+	else if (*p++ == 'p')
+		sprintf(dest, "%s/host%d/bus%d/target%d/lun%d/part%s",
+				prefix, host, bus, target, lun, p);
+	else
+		sprintf(dest, "%s/host%d/bus%d/target%d/lun%d/disc",
+				prefix, host, bus, target, lun);
+	*base = '\0';
+	sprintf(src, "/dev/%s", name);
+	sys_mkdir(src, 0755);
+	*base = '/';
+	sprintf(src, "/dev/%s", name);
+	sys_symlink(dest, src);
+}
+
+static void __init devfs_make_root(char *name)
+{
+
+	if (!strncmp(name, "sd/", 3))
+		convert_name("../scsi", name, name+3, 1);
+	else if (!strncmp(name, "sr/", 3))
+		convert_name("../scsi", name, name+3, 0);
+	else if (!strncmp(name, "ide/hd/", 7))
+		convert_name("..", name, name + 7, 1);
+	else if (!strncmp(name, "ide/cd/", 7))
+		convert_name("..", name, name + 7, 0);
+}
+#else
+static void __init devfs_make_root(char *name)
+{
+}
+#endif
+
 static void __init mount_root(void)
 {
 #ifdef CONFIG_ROOT_NFS
@@ -718,24 +809,22 @@
  */
 void prepare_namespace(void)
 {
-	int do_initrd = 0;
 	int is_floppy = MAJOR(ROOT_DEV) == FLOPPY_MAJOR;
 #ifdef CONFIG_BLK_DEV_INITRD
 	if (!initrd_start)
 		mount_initrd = 0;
-	if (mount_initrd)
-		do_initrd = 1;
 	real_root_dev = ROOT_DEV;
 #endif
 	sys_mkdir("/dev", 0700);
 	sys_mkdir("/root", 0700);
+	sys_mknod("/dev/console", S_IFCHR|0600, MKDEV(TTYAUX_MAJOR, 1));
 #ifdef CONFIG_DEVFS_FS
 	sys_mount("devfs", "/dev", "devfs", 0, NULL);
 	do_devfs = 1;
 #endif
 
 	create_dev("/dev/root", ROOT_DEV, NULL);
-	if (do_initrd) {
+	if (mount_initrd) {
 		if (initrd_load() && ROOT_DEV != MKDEV(RAMDISK_MAJOR, 0)) {
 			handle_initrd();
 			goto out;
diff -urN linux-2.4.19-pre5/kernel/exit.c linux-2.4.19-pre6/kernel/exit.c
--- linux-2.4.19-pre5/kernel/exit.c	Mon Feb 25 11:38:13 2002
+++ linux-2.4.19-pre6/kernel/exit.c	Thu Apr  4 22:05:16 2002
@@ -12,6 +12,7 @@
 #include <linux/completion.h>
 #include <linux/personality.h>
 #include <linux/tty.h>
+#include <linux/namespace.h>
 #ifdef CONFIG_BSD_PROCESS_ACCT
 #include <linux/acct.h>
 #endif
@@ -316,7 +317,7 @@
 	mm_release();
 	if (mm) {
 		atomic_inc(&mm->mm_count);
-		if (mm != tsk->active_mm) BUG();
+		BUG_ON(mm != tsk->active_mm);
 		/* more a memory barrier than a real lock */
 		task_lock(tsk);
 		tsk->mm = NULL;
@@ -452,6 +453,7 @@
 	sem_exit();
 	__exit_files(tsk);
 	__exit_fs(tsk);
+	exit_namespace(tsk);
 	exit_sighand(tsk);
 	exit_thread();
 
diff -urN linux-2.4.19-pre5/kernel/fork.c linux-2.4.19-pre6/kernel/fork.c
--- linux-2.4.19-pre5/kernel/fork.c	Thu Apr  4 22:04:28 2002
+++ linux-2.4.19-pre6/kernel/fork.c	Thu Apr  4 22:05:16 2002
@@ -19,6 +19,7 @@
 #include <linux/module.h>
 #include <linux/vmalloc.h>
 #include <linux/completion.h>
+#include <linux/namespace.h>
 #include <linux/personality.h>
 
 #include <asm/pgtable.h>
@@ -251,7 +252,7 @@
  */
 inline void __mmdrop(struct mm_struct *mm)
 {
-	if (mm == &init_mm) BUG();
+	BUG_ON(mm == &init_mm);
 	pgd_free(mm->pgd);
 	destroy_context(mm);
 	free_mm(mm);
@@ -569,6 +570,9 @@
 	struct task_struct *p;
 	struct completion vfork;
 
+	if ((clone_flags & (CLONE_NEWNS|CLONE_FS)) == (CLONE_NEWNS|CLONE_FS))
+		return -EINVAL;
+
 	retval = -EPERM;
 
 	/* 
@@ -671,9 +675,11 @@
 		goto bad_fork_cleanup_fs;
 	if (copy_mm(clone_flags, p))
 		goto bad_fork_cleanup_sighand;
+	if (copy_namespace(clone_flags, p))
+		goto bad_fork_cleanup_mm;
 	retval = copy_thread(0, clone_flags, stack_start, stack_size, p, regs);
 	if (retval)
-		goto bad_fork_cleanup_mm;
+		goto bad_fork_cleanup_namespace;
 	p->semundo = NULL;
 	
 	/* Our parent execution domain becomes current domain
@@ -740,6 +746,8 @@
 fork_out:
 	return retval;
 
+bad_fork_cleanup_namespace:
+	exit_namespace(p);
 bad_fork_cleanup_mm:
 	exit_mm(p);
 bad_fork_cleanup_sighand:
diff -urN linux-2.4.19-pre5/kernel/kmod.c linux-2.4.19-pre6/kernel/kmod.c
--- linux-2.4.19-pre5/kernel/kmod.c	Tue Jul 17 18:23:50 2001
+++ linux-2.4.19-pre6/kernel/kmod.c	Thu Apr  4 22:05:16 2002
@@ -24,6 +24,8 @@
 #include <linux/unistd.h>
 #include <linux/kmod.h>
 #include <linux/smp_lock.h>
+#include <linux/slab.h>
+#include <linux/namespace.h>
 #include <linux/completion.h>
 
 #include <asm/uaccess.h>
@@ -36,6 +38,7 @@
 	struct fs_struct *our_fs, *init_fs;
 	struct dentry *root, *pwd;
 	struct vfsmount *rootmnt, *pwdmnt;
+	struct namespace *our_ns, *init_ns;
 
 	/*
 	 * Make modprobe's fs context be a copy of init's.
@@ -55,6 +58,11 @@
 	 */
 
 	init_fs = init_task.fs;
+	init_ns = init_task.namespace;
+	get_namespace(init_ns);
+	our_ns = current->namespace;
+	current->namespace = init_ns;
+	put_namespace(our_ns);
 	read_lock(&init_fs->lock);
 	rootmnt = mntget(init_fs->rootmnt);
 	root = dget(init_fs->root);
diff -urN linux-2.4.19-pre5/kernel/sched.c linux-2.4.19-pre6/kernel/sched.c
--- linux-2.4.19-pre5/kernel/sched.c	Fri Dec 21 09:42:04 2001
+++ linux-2.4.19-pre6/kernel/sched.c	Thu Apr  4 22:05:16 2002
@@ -556,7 +556,7 @@
 
 	spin_lock_prefetch(&runqueue_lock);
 
-	if (!current->active_mm) BUG();
+	BUG_ON(!current->active_mm);
 need_resched_back:
 	prev = current;
 	this_cpu = prev->processor;
@@ -675,12 +675,12 @@
 		struct mm_struct *mm = next->mm;
 		struct mm_struct *oldmm = prev->active_mm;
 		if (!mm) {
-			if (next->active_mm) BUG();
+			BUG_ON(next->active_mm);
 			next->active_mm = oldmm;
 			atomic_inc(&oldmm->mm_count);
 			enter_lazy_tlb(oldmm, next, this_cpu);
 		} else {
-			if (next->active_mm != mm) BUG();
+			BUG_ON(next->active_mm != mm);
 			switch_mm(oldmm, mm, next, this_cpu);
 		}
 
diff -urN linux-2.4.19-pre5/mm/mmap.c linux-2.4.19-pre6/mm/mmap.c
--- linux-2.4.19-pre5/mm/mmap.c	Thu Apr  4 22:04:28 2002
+++ linux-2.4.19-pre6/mm/mmap.c	Thu Apr  4 22:05:16 2002
@@ -14,6 +14,7 @@
 #include <linux/file.h>
 #include <linux/fs.h>
 #include <linux/personality.h>
+#include <linux/compiler.h>
 
 #include <asm/uaccess.h>
 #include <asm/pgalloc.h>
@@ -548,7 +549,30 @@
 	 * Answer: Yes, several device drivers can do it in their
 	 *         f_op->mmap method. -DaveM
 	 */
-	addr = vma->vm_start;
+	if (addr != vma->vm_start) {
+		/*
+		 * It is a bit too late to pretend changing the virtual
+		 * area of the mapping, we just corrupted userspace
+		 * in the do_munmap, so FIXME (not in 2.4 to avoid breaking
+		 * the driver API).
+		 */
+		struct vm_area_struct * stale_vma;
+		/* Since addr changed, we rely on the mmap op to prevent 
+		 * collisions with existing vmas and just use find_vma_prepare 
+		 * to update the tree pointers.
+		 */
+		addr = vma->vm_start;
+		stale_vma = find_vma_prepare(mm, addr, &prev,
+						&rb_link, &rb_parent);
+		/*
+		 * Make sure the lowlevel driver did its job right.
+		 */
+		if (unlikely(stale_vma && stale_vma->vm_start < vma->vm_end)) {
+			printk(KERN_ERR "buggy mmap operation: [<%p>]\n",
+				file ? file->f_op->mmap : NULL);
+			BUG();
+		}
+	}
 
 	vma_link(mm, vma, prev, rb_link, rb_parent);
 	if (correct_wcount)
diff -urN linux-2.4.19-pre5/mm/slab.c linux-2.4.19-pre6/mm/slab.c
--- linux-2.4.19-pre5/mm/slab.c	Thu Apr  4 22:04:28 2002
+++ linux-2.4.19-pre6/mm/slab.c	Thu Apr  4 22:05:16 2002
@@ -665,8 +665,7 @@
 	 * Always checks flags, a caller might be expecting debug
 	 * support which isn't available.
 	 */
-	if (flags & ~CREATE_MASK)
-		BUG();
+	BUG_ON(flags & ~CREATE_MASK);
 
 	/* Get cache's description obj. */
 	cachep = (kmem_cache_t *) kmem_cache_alloc(&cache_cache, SLAB_KERNEL);
diff -urN linux-2.4.19-pre5/mm/vmscan.c linux-2.4.19-pre6/mm/vmscan.c
--- linux-2.4.19-pre5/mm/vmscan.c	Thu Apr  4 22:04:28 2002
+++ linux-2.4.19-pre6/mm/vmscan.c	Thu Apr  4 22:05:16 2002
@@ -233,8 +233,7 @@
 	pgdir = pgd_offset(mm, address);
 
 	end = vma->vm_end;
-	if (address >= end)
-		BUG();
+	BUG_ON(address >= end);
 	do {
 		count = swap_out_pgd(mm, vma, pgdir, address, end, count, classzone);
 		if (!count)
@@ -353,10 +352,8 @@
 
 		page = list_entry(entry, struct page, lru);
 
-		if (unlikely(!PageLRU(page)))
-			BUG();
-		if (unlikely(PageActive(page)))
-			BUG();
+		BUG_ON(!PageLRU(page));
+		BUG_ON(PageActive(page));
 
 		list_del(entry);
 		list_add(entry, &inactive_list);
diff -urN linux-2.4.19-pre5/net/ipv4/ipconfig.c linux-2.4.19-pre6/net/ipv4/ipconfig.c
--- linux-2.4.19-pre5/net/ipv4/ipconfig.c	Mon Feb 25 11:38:14 2002
+++ linux-2.4.19-pre6/net/ipv4/ipconfig.c	Thu Apr  4 22:05:16 2002
@@ -1105,6 +1105,40 @@
 #endif /* CONFIG_PROC_FS */
 
 /*
+ *  Extract IP address from the parameter string if needed. Note that we
+ *  need to have root_server_addr set _before_ IPConfig gets called as it
+ *  can override it.
+ */
+u32 __init root_nfs_parse_addr(char *name)
+{
+	u32 addr;
+	int octets = 0;
+	char *cp, *cq;
+
+	cp = cq = name;
+	while (octets < 4) {
+		while (*cp >= '0' && *cp <= '9')
+			cp++;
+		if (cp == cq || cp - cq > 3)
+			break;
+		if (*cp == '.' || octets == 3)
+			octets++;
+		if (octets < 4)
+			cp++;
+		cq = cp;
+	}
+	if (octets == 4 && (*cp == ':' || *cp == '\0')) {
+		if (*cp == ':')
+			*cp++ = '\0';
+		addr = in_aton(name);
+		strcpy(name, cp);
+	} else
+		addr = INADDR_NONE;
+
+	return addr;
+}
+
+/*
  *	IP Autoconfig dispatcher.
  */
 
@@ -1112,6 +1146,7 @@
 {
 	int retries = CONF_OPEN_RETRIES;
 	unsigned long jiff;
+	u32 addr;
 
 #ifdef CONFIG_PROC_FS
 	proc_net_create("pnp", 0, pnp_get_info);
@@ -1197,6 +1232,10 @@
 		ic_dev = ic_first_dev->dev;
 	}
 
+	addr = root_nfs_parse_addr(root_server_path);
+	if (root_server_addr == INADDR_NONE)
+		root_server_addr = addr;
+
 	/*
 	 * Use defaults whereever applicable.
 	 */
