## Automatically generated incremental diff
## From:   linux-2.4.18-pre4
## To:     linux-2.4.18-pre5
## Robot:  $Id: make-incremental-diff,v 1.9 2001/12/10 00:06:56 hpa Exp $

diff -urN linux-2.4.18-pre4/CREDITS linux/CREDITS
--- linux-2.4.18-pre4/CREDITS	Tue Jan 22 12:01:19 2002
+++ linux/CREDITS	Tue Jan 22 12:01:21 2002
@@ -1282,13 +1282,6 @@
 D: Cobalt Networks (x86) support
 D: This-and-That
 
-N: Tim Hockin
-E: thockin@hockin.org
-W: http://www.hockin.org/~thockin
-D: Natsemi ethernet
-D: Cobalt Networks (x86) support
-D: This-and-That
-
 N: Dirk Hohndel
 E: hohndel@suse.de
 D: The XFree86[tm] Project
@@ -1975,9 +1968,10 @@
 S: Germany 
 
 N: Mark W. McClelland
-E: mwm@i.am
+E: mmcclell@bigfoot.com
 E: mark@alpha.dyndns.org
 W: http://alpha.dyndns.org/ov511/
+P: 1024D/357375CC 317C 58AC 1B39 2AB0 AB96  EB38 0B6F 731F 3573 75CC
 D: OV511 driver
 S: (address available on request)
 S: USA
diff -urN linux-2.4.18-pre4/Documentation/Configure.help linux/Documentation/Configure.help
--- linux-2.4.18-pre4/Documentation/Configure.help	Tue Jan 22 12:01:20 2002
+++ linux/Documentation/Configure.help	Tue Jan 22 12:01:21 2002
@@ -4350,11 +4350,9 @@
 
 Matrox unified accelerated driver
 CONFIG_FB_MATROX
-  Say Y here if you have a Matrox Millennium, Matrox Millennium II,
-  Matrox Mystique, Matrox Mystique 220, Matrox Productiva G100, Matrox
-  Mystique G200, Matrox Millennium G200, Matrox Marvel G200 video,
-  Matrox G400 or G450 card in your box. At this time, support for the
-  G100 is untested and support for G450 is highly experimental.
+  Say Y here if you have a Matrox Millennium, Millennium II, Mystique,
+  Mystique 220, Productiva G100, Mystique G200, Millennium G200,
+  Marvel G200 video, G400, G450, or G550 card in your box.
 
   This driver is also available as a module ( = code which can be
   inserted and removed from the running kernel whenever you want).
@@ -4381,12 +4379,12 @@
   packed pixel and 32 bpp packed pixel. You can also use font widths
   different from 8.
 
-Matrox G100/G200/G400/G450 support
+Matrox G100/G200/G400/G450/G550 support
 CONFIG_FB_MATROX_G100
-  Say Y here if you have a Matrox G100, G200, G400 or G450 based
-  video card. If you select "Advanced lowlevel driver options", you
-  should check 8 bpp packed pixel, 16 bpp packed pixel, 24 bpp packed
-  pixel and 32 bpp packed pixel. You can also use font widths
+  Say Y here if you have a Matrox G100, G200, G400, G450, or G550
+  based video card. If you select "Advanced lowlevel driver options",
+  you should check 8 bpp packed pixel, 16 bpp packed pixel, 24 bpp
+  packed pixel and 32 bpp packed pixel. You can also use font widths
   different from 8.
 
   If you need support for G400 secondary head, you must first say Y to
@@ -4394,6 +4392,9 @@
   section, and then to "Matrox I2C support" and "G400 second head
   support" here in the framebuffer section.
 
+  If you need support for G450 or G550 secondary head, say Y to
+  "Matrox G450/G550 second head support" below.
+
 Matrox I2C support
 CONFIG_FB_MATROX_I2C
   This drivers creates I2C buses which are needed for accessing the
@@ -4440,7 +4441,7 @@
 Matrox G450 second head support
 CONFIG_FB_MATROX_G450
   Say Y or M here if you want to use a secondary head (meaning two
-  monitors in parallel) on G450.
+  monitors in parallel) on G450 or G550.
 
   If you compile it as module, two modules are created,
   matroxfb_crtc2.o and matroxfb_g450.o. Both modules are needed if you
@@ -4451,6 +4452,9 @@
   at <ftp://platan.vc.cvut.cz/pub/linux/matrox-latest/>) to swap
   primary and secondary head outputs.  Secondary head driver always
   start in 640x480 resolution and you must use fbset to change it.
+
+  Note on most G550 cards the analog output is the secondary head,
+  so you will need to say Y here to use it.
 
   Also do not forget that second head supports only 16 and 32 bpp
   packed pixels, so it is a good idea to compile them into the kernel
diff -urN linux-2.4.18-pre4/Documentation/DMA-mapping.txt linux/Documentation/DMA-mapping.txt
--- linux-2.4.18-pre4/Documentation/DMA-mapping.txt	Tue Jan 22 12:01:20 2002
+++ linux/Documentation/DMA-mapping.txt	Tue Jan 22 12:01:21 2002
@@ -720,7 +720,7 @@
    NOTE: DO NOT put a semicolon at the end of the DECLARE_*()
          macro.
 
-2) Use PCI_UNMAP_{ADDR,LEN}_SET to set these values.
+2) Use pci_unmap_{addr,len}_set to set these values.
    Example, before:
 
 	ringp->mapping = FOO;
@@ -728,10 +728,10 @@
 
    after:
 
-	PCI_UNMAP_ADDR_SET(ringp, mapping, FOO);
-	PCI_UNMAP_LEN_SET(ringp, len, BAR);
+	pci_unmap_addr_set(ringp, mapping, FOO);
+	pci_unmap_len_set(ringp, len, BAR);
 
-3) Use PCI_UNMAP_{ADDR,LEN} to access these values.
+3) Use pci_unmap_{addr,len} to access these values.
    Example, before:
 
 	pci_unmap_single(pdev, ringp->mapping, ringp->len,
@@ -740,8 +740,8 @@
    after:
 
 	pci_unmap_single(pdev,
-			 PCI_UNMAP_ADDR(ringp, mapping),
-			 PCI_UNMAP_LEN(ringp, len),
+			 pci_unmap_addr(ringp, mapping),
+			 pci_unmap_len(ringp, len),
 			 PCI_DMA_FROMDEVICE);
 
 It really should be self-explanatory.  We treat the ADDR and LEN
diff -urN linux-2.4.18-pre4/Documentation/filesystems/devfs/ChangeLog linux/Documentation/filesystems/devfs/ChangeLog
--- linux-2.4.18-pre4/Documentation/filesystems/devfs/ChangeLog	Fri Dec 21 09:41:53 2001
+++ linux/Documentation/filesystems/devfs/ChangeLog	Tue Jan 22 12:01:21 2002
@@ -1845,3 +1845,38 @@
 - Improved debugging messages
 
 - Fixed unregister bugs in drivers/md/lvm-fs.c
+===============================================================================
+Changes for patch v199.6
+
+- Corrected (made useful) debugging message in <unregister>
+
+- Moved <kmem_cache_create> in <mount_devfs_fs> to <init_devfs_fs>
+
+- Fixed drivers/md/lvm-fs.c to create "lvm" entry
+
+- Added magic number to guard against scribbling drivers
+
+- Only return old entry in <devfs_mk_dir> if a directory
+
+- Defined macros for error and debug messages
+
+- Updated README from master HTML file
+===============================================================================
+Changes for patch v199.7
+
+- Unregister /dev/root symlink prior to creating second one (for
+  initrd)
+
+- Added support for multiple Compaq cpqarray controllers
+
+- Fixed (rare, old) race in <devfs_lookup>
+===============================================================================
+Changes for patch v199.8
+
+- Fixed deadlock bug in <devfs_d_revalidate_wait>
+
+- Tag VFS deletable in <devfs_mk_symlink> if handle ignored
+
+- Updated README from master HTML file
+
+- Fixed kdev_none macro in include/linux/kdev_t.h
diff -urN linux-2.4.18-pre4/Documentation/filesystems/devfs/README linux/Documentation/filesystems/devfs/README
--- linux-2.4.18-pre4/Documentation/filesystems/devfs/README	Fri Dec 21 09:41:53 2001
+++ linux/Documentation/filesystems/devfs/README	Tue Jan 22 12:01:21 2002
@@ -3,7 +3,16 @@
 
 Linux Devfs (Device File System) FAQ
 Richard Gooch
-13-DEC-2001
+20-JAN-2002
+
+
+Document languages:
+
+
+
+
+
+
 
 -----------------------------------------------------------------------------
 
@@ -68,6 +77,8 @@
 Alternatives to devfs
 What I don't like about devfs
 How to report bugs
+Strange kernel messages
+Compilation problems with devfsd
 
 
 Other resources
@@ -836,8 +847,8 @@
 will now work as before.
 
 Hopefully for most people devfs will have enough support so that they
-can mount devfs directly over /dev without loosing most functionality
-(i.e. loosing access to various devices). As of 22-JAN-1998 (devfs
+can mount devfs directly over /dev without losing most functionality
+(i.e. losing access to various devices). As of 22-JAN-1998 (devfs
 patch version 10) I am now running this way. All the devices I have
 are available in devfs, so I don't lose anything.
 
@@ -1475,6 +1486,8 @@
 Alternatives to devfs
 What I don't like about devfs
 How to report bugs
+Strange kernel messages
+Compilation problems with devfsd
 
 
 
@@ -1675,7 +1688,7 @@
 minor limitation
 
 
-simplying increasing the device number size is insufficient. Apart
+simply increasing the device number size is insufficient. Apart
 from causing a lot of pain, it doesn't solve the management issues
 of a /dev with thousands or more device nodes
 
@@ -1790,6 +1803,65 @@
 
 http://www.chiark.greenend.org.uk/~sgtatham/bugs.html.
 
+
+Strange kernel messages
+
+You may see devfs-related messages in your kernel logs. Below are some
+messages and what they mean (and what you should do about them, if
+anything).
+
+
+
+devfs_register(fred): could not append to parent, err: -17
+
+You need to check what the error code means, but usually 17 means
+EEXIST. This means that a driver attempted to create an entry
+fred in a directory, but there already was an entry with that
+name. This is often caused by flawed boot scripts which untar a bunch
+of inodes into /dev, as a way to restore permissions. This
+message is harmless, as the device nodes will still
+provide access to the driver (unless you use the devfs=only
+boot option, which is only for dedicated souls:-). If you want to get
+rid of these annoying messages, upgrade to devfsd-v1.3.20 and use the
+recommended RESTORE directive to restore permissions.
+
+
+devfs_mk_dir(bill): using old entry in dir: c1808724 ""
+
+This is similar to the message above, except that a driver attempted
+to create a directory named bill, and the parent directory
+has an entry with the same name. In this case, to ensure that drivers
+continue to work properly, the old entry is re-used and given to the
+driver. In 2.5 kernels, the driver is given a NULL entry, and thus,
+under rare circumstances, may not create the require device nodes.
+The solution is the same as above.
+
+
+
+
+
+Compilation problems with devfsd
+
+Usually, you can compile devfsd just by typing in
+make in the source directory, followed by a make
+install (as root). Sometimes, you may have problems, particularly
+on broken configurations.
+
+
+
+error messages relating to DEVFSD_NOTIFY_DELETE
+
+This happened because you have an ancient set of kernel headers
+installed in /usr/include/linux or /usr/src/linux.
+Install kernel 2.4.10 or later. You may need to pass the
+KERNEL_DIR variable to make (if you did not install
+the new kernel sources as /usr/src/linux), or you may copy
+the devfs_fs.h file in the kernel source tree into
+/usr/include/linux.
+
+
+
+
 -----------------------------------------------------------------------------
 
 
@@ -1844,9 +1916,25 @@
 
 
 
+The document master (in English) by rgooch@atnf.csiro.au is
+available at
+
+http://www.atnf.csiro.au/~rgooch/linux/docs/devfs.html
+
+
+
 A Korean translation by viatoris@nownuri.net is available at
 
-http://home.nownuri.net/~viatoris/devfs/devfs.html 
+http://home.nownuri.net/~viatoris/devfs/devfs.html
+
+A newer version is under construcation at
+
+http://viatoris.new21.org/devfs/devfs.html
 
 
 
+
+-----------------------------------------------------------------------------
+Most flags courtesy of ITA's 
+Flags of All Countries
+used with permission. 
diff -urN linux-2.4.18-pre4/Documentation/networking/8139too.txt linux/Documentation/networking/8139too.txt
--- linux-2.4.18-pre4/Documentation/networking/8139too.txt	Fri Nov  9 13:45:35 2001
+++ linux/Documentation/networking/8139too.txt	Tue Jan 22 12:01:21 2002
@@ -96,7 +96,9 @@
 KTI KF-230TX
 KTI KF-230TX/2
 Lantech FastNet TX
+Planet ENW-9504 (V.4) 10/100
 SMC EZNET 10/100
+UNEX NexNIC ND012C
 
 (please add your adapter model to this list)
 
@@ -181,11 +183,18 @@
 Change History
 --------------
 
+Version 0.9.23 - January 16, 2002
+
+* New, compile-time conditional for testing better RX reset
+* Only account specific RX errors if rx_status is !OK
+
+
 Version 0.9.22 - November 8, 2001
 
 * Additional retries before aborting Tx
 * Do not write other TxConfig bits when writing clear-abort bit.
 * Ack TxErr intr status after each Tx abort, too.
+* Fix oops in interface restart
 
 
 Version 0.9.21 - November 1, 2001
diff -urN linux-2.4.18-pre4/Documentation/networking/dl2k.txt linux/Documentation/networking/dl2k.txt
--- linux-2.4.18-pre4/Documentation/networking/dl2k.txt	Tue Jan 22 12:01:20 2002
+++ linux/Documentation/networking/dl2k.txt	Tue Jan 22 12:01:21 2002
@@ -1,7 +1,7 @@
 
     D-Link DL2000-based Gigabit Ethernet Adapter Installation
     for Linux
-    Nov 21, 2001
+    Jan 02, 2002
 
 Contents
 ========
@@ -182,7 +182,7 @@
 mtu=packet_size			- Specifies the maximum packet size. default
 				  is 1500.
 
-media=xxxxxxxxx			- Specifies the media type the NIC operates at.
+media=media_type		- Specifies the media type the NIC operates at.
 				  autosense	Autosensing active media.
 				  10mbps_hd	10Mbps half duplex.
 				  10mbps_fd	10Mbps full duplex.
@@ -202,32 +202,32 @@
 				  Note that only 1000mbps_fd and 1000mbps_hd
 				  types are available for fiber adapter.
 
-vlan=x				- Specifies the VLAN ID. If vlan=0, the
+vlan=[0|1]			- Specifies the VLAN ID. If vlan=0, the
 				  Virtual Local Area Network (VLAN) function is
 				  disable.
 
-jumbo=x				- Specifies the jumbo frame support. If jumbo=1,
+jumbo=[0|1]			- Specifies the jumbo frame support. If jumbo=1,
 				  the NIC accept jumbo frames. By default, this
 				  function is disabled.
 				  Jumbo frame usually improve the performance
 				  int gigabit.
 				  
-rx_coalesce			- Rx frame count each interrupt.
-rx_timeout			- Rx DMA wait time for an interrupt. Proper 
+rx_coalesce=n			- Rx frame count each interrupt.
+rx_timeout=n			- Rx DMA wait time for an interrupt. Proper 
 				  values of rx_coalesce and rx_timeout bring 
 				  a conspicuous performance in the fast machine.
 				  Ex. rx_coalesce=5 and rx_timeout=750 
 
-tx_coalesce			- Tx transmit count each TxComp interrupt.
+tx_coalesce=n			- Tx transmit count each TxComp interrupt.
 				  Setting value larger than 1 will improve 
 				  performance, but this is possible to lower 
 				  stability in slow UP machines. By default, 
-				  tx_coalesce=8. (dl2k)
+				  tx_coalesce=1. (dl2k)
 				  
-tx_flow				- Specifies the Tx flow control. If tx_flow=1, 
+tx_flow=[1|0]			- Specifies the Tx flow control. If tx_flow=1, 
 				  the Tx flow control enable.
 				  
-rx_flow				- Specifies the Rx flow control. If rx_flow=1, 
+rx_flow=[1|0]			- Specifies the Rx flow control. If rx_flow=1, 
 				  the Rx flow control enable.
 
 
diff -urN linux-2.4.18-pre4/MAINTAINERS linux/MAINTAINERS
--- linux-2.4.18-pre4/MAINTAINERS	Tue Jan 22 12:01:20 2002
+++ linux/MAINTAINERS	Tue Jan 22 12:01:21 2002
@@ -1617,7 +1617,7 @@
 
 USB OV511 DRIVER
 P:     Mark McClelland
-M:     mwm@i.am
+M:     mmcclell@bigfoot.com
 L:     linux-usb-users@lists.sourceforge.net
 L:     linux-usb-devel@lists.sourceforge.net
 W:     http://alpha.dyndns.org/ov511/
diff -urN linux-2.4.18-pre4/Makefile linux/Makefile
--- linux-2.4.18-pre4/Makefile	Tue Jan 22 12:01:20 2002
+++ linux/Makefile	Tue Jan 22 12:01:21 2002
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 4
 SUBLEVEL = 18
-EXTRAVERSION = -pre4
+EXTRAVERSION = -pre5
 
 KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
 
diff -urN linux-2.4.18-pre4/arch/ppc/kernel/ppc_ksyms.c linux/arch/ppc/kernel/ppc_ksyms.c
--- linux-2.4.18-pre4/arch/ppc/kernel/ppc_ksyms.c	Tue Jan 22 12:01:20 2002
+++ linux/arch/ppc/kernel/ppc_ksyms.c	Tue Jan 22 12:01:22 2002
@@ -1,5 +1,5 @@
 /*
- * BK Id: SCCS/s.ppc_ksyms.c 1.61 12/01/01 20:09:06 benh
+ * BK Id: SCCS/s.ppc_ksyms.c 1.63 01/20/02 23:53:11 benh
  */
 #include <linux/config.h>
 #include <linux/module.h>
@@ -285,6 +285,7 @@
 EXPORT_SYMBOL_NOVERS(memmove);
 EXPORT_SYMBOL_NOVERS(memscan);
 EXPORT_SYMBOL_NOVERS(memcmp);
+EXPORT_SYMBOL_NOVERS(memchr);
 
 EXPORT_SYMBOL(abs);
 
diff -urN linux-2.4.18-pre4/arch/sparc/defconfig linux/arch/sparc/defconfig
--- linux-2.4.18-pre4/arch/sparc/defconfig	Fri Dec 21 09:41:53 2001
+++ linux/arch/sparc/defconfig	Tue Jan 22 12:01:22 2002
@@ -373,6 +373,7 @@
 # CONFIG_NLS_CODEPAGE_949 is not set
 # CONFIG_NLS_CODEPAGE_874 is not set
 # CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
 # CONFIG_NLS_CODEPAGE_1251 is not set
 # CONFIG_NLS_ISO8859_1 is not set
 # CONFIG_NLS_ISO8859_2 is not set
diff -urN linux-2.4.18-pre4/arch/sparc64/defconfig linux/arch/sparc64/defconfig
--- linux-2.4.18-pre4/arch/sparc64/defconfig	Tue Jan 22 12:01:20 2002
+++ linux/arch/sparc64/defconfig	Tue Jan 22 12:01:22 2002
@@ -483,6 +483,7 @@
 # CONFIG_8139TOO_PIO is not set
 # CONFIG_8139TOO_TUNE_TWISTER is not set
 # CONFIG_8139TOO_8129 is not set
+# CONFIG_8139_NEW_RX_RESET is not set
 CONFIG_SIS900=m
 CONFIG_EPIC100=m
 CONFIG_SUNDANCE=m
@@ -683,6 +684,7 @@
 # CONFIG_NLS_CODEPAGE_949 is not set
 # CONFIG_NLS_CODEPAGE_874 is not set
 # CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
 # CONFIG_NLS_CODEPAGE_1251 is not set
 # CONFIG_NLS_ISO8859_1 is not set
 # CONFIG_NLS_ISO8859_2 is not set
diff -urN linux-2.4.18-pre4/arch/sparc64/kernel/ioctl32.c linux/arch/sparc64/kernel/ioctl32.c
--- linux-2.4.18-pre4/arch/sparc64/kernel/ioctl32.c	Tue Jan 22 12:01:20 2002
+++ linux/arch/sparc64/kernel/ioctl32.c	Tue Jan 22 12:01:22 2002
@@ -1,4 +1,4 @@
-/* $Id: ioctl32.c,v 1.133.2.1 2002/01/04 21:06:49 davem Exp $
+/* $Id: ioctl32.c,v 1.133.2.2 2002/01/14 09:49:29 davem Exp $
  * ioctl32.c: Conversion between 32bit and 64bit native ioctls.
  *
  * Copyright (C) 1997-2000  Jakub Jelinek  (jakub@redhat.com)
@@ -1581,12 +1581,17 @@
 	}
 
 	err |= __get_user(sbp32, &sg_io32->sbp);
-	sg_io64.sbp = kmalloc(64, GFP_KERNEL);
+	sg_io64.sbp = kmalloc(sg_io64.mx_sb_len, GFP_KERNEL);
 	if (!sg_io64.sbp) {
 		err = -ENOMEM;
 		goto out;
 	}
-	memset(sg_io64.sbp, 0, 64);
+	if (copy_from_user(sg_io64.sbp,
+			   (void *) A(sbp32),
+			   sg_io64.mx_sb_len)) {
+		err = -EFAULT;
+		goto out;
+	}
 
 	err |= __get_user(dxferp32, &sg_io32->dxferp);
 	if (sg_io64.iovec_count) {
@@ -1634,7 +1639,7 @@
 	err |= __put_user(sg_io64.resid, &sg_io32->resid);
 	err |= __put_user(sg_io64.duration, &sg_io32->duration);
 	err |= __put_user(sg_io64.info, &sg_io32->info);
-	err |= copy_to_user((void *)A(sbp32), sg_io64.sbp, 64);
+	err |= copy_to_user((void *)A(sbp32), sg_io64.sbp, sg_io64.mx_sb_len);
 	if (sg_io64.dxferp) {
 		if (sg_io64.iovec_count)
 			err |= copy_back_sg_iovec(&sg_io64, dxferp32);
diff -urN linux-2.4.18-pre4/arch/sparc64/kernel/pci_common.c linux/arch/sparc64/kernel/pci_common.c
--- linux-2.4.18-pre4/arch/sparc64/kernel/pci_common.c	Tue Aug 14 19:57:28 2001
+++ linux/arch/sparc64/kernel/pci_common.c	Tue Jan 22 12:01:22 2002
@@ -1,4 +1,4 @@
-/* $Id: pci_common.c,v 1.27 2001/08/12 13:18:22 davem Exp $
+/* $Id: pci_common.c,v 1.27.2.1 2002/01/14 05:46:47 davem Exp $
  * pci_common.c: PCI controller common support.
  *
  * Copyright (C) 1999 David S. Miller (davem@redhat.com)
@@ -183,6 +183,17 @@
 		pcp->prom_name[err] = 0;
 	else
 		pcp->prom_name[0] = 0;
+
+	err = prom_getproperty(device_prom_node,
+			       "assigned-addresses",
+			       (char *)pcp->prom_assignments,
+			       sizeof(pcp->prom_assignments));
+	if (err == 0 || err == -1)
+		pcp->num_prom_assignments = 0;
+	else
+		pcp->num_prom_assignments =
+			(err / sizeof(pcp->prom_assignments[0]));
+
 	if (strcmp(pcp->prom_name, "ebus") == 0) {
 		struct linux_prom_ebus_ranges erng[PROM_PCIRNG_MAX];
 		int iter;
@@ -208,16 +219,6 @@
 			ap->size_lo = ep->size;
 		}
 		pcp->num_prom_assignments = err;
-	} else {
-		err = prom_getproperty(device_prom_node,
-				       "assigned-addresses",
-				       (char *)pcp->prom_assignments,
-				       sizeof(pcp->prom_assignments));
-		if (err == 0 || err == -1)
-			pcp->num_prom_assignments = 0;
-		else
-			pcp->num_prom_assignments =
-				(err / sizeof(pcp->prom_assignments[0]));
 	}
 
 	fixup_obp_assignments(pdev, pcp);
diff -urN linux-2.4.18-pre4/arch/sparc64/lib/U3copy_from_user.S linux/arch/sparc64/lib/U3copy_from_user.S
--- linux-2.4.18-pre4/arch/sparc64/lib/U3copy_from_user.S	Thu Nov  9 15:57:41 2000
+++ linux/arch/sparc64/lib/U3copy_from_user.S	Tue Jan 22 12:01:22 2002
@@ -1,4 +1,4 @@
-/* $Id: U3copy_from_user.S,v 1.3 2000/11/01 09:29:19 davem Exp $
+/* $Id: U3copy_from_user.S,v 1.3.2.1 2002/01/15 07:17:47 davem Exp $
  * U3memcpy.S: UltraSparc-III optimized copy from userspace.
  *
  * Copyright (C) 1999, 2000 David S. Miller (davem@redhat.com)
@@ -13,7 +13,7 @@
 	.section .fixup;		\
 	.align 4;			\
 99:	VISExitHalf;			\
-	ba,pt %xcc, U3cfu_fixup;	\
+	ba U3cfu_fixup;			\
 	 a, b, %o1;			\
 	.section __ex_table;		\
 	.align 4;			\
@@ -25,7 +25,7 @@
 	.section .fixup;		\
 	.align 4;			\
 99:	VISExitHalf;			\
-	ba,pt %xcc, U3cfu_fixup;	\
+	ba U3cfu_fixup;			\
 	 a, b, %o1;			\
 	.section __ex_table;		\
 	.align 4;			\
@@ -39,7 +39,7 @@
 99:	VISExitHalf;			\
 	and %o2, (0x40 - 1), %o1;	\
 	add %o1, %o4, %o1;		\
-	ba,pt %xcc, U3cfu_fixup;	\
+	ba U3cfu_fixup;			\
 	 add %o1, 0x1c0, %o1;		\
 	.section __ex_table;		\
 	.align 4;			\
@@ -54,7 +54,7 @@
 	and %o2, (0x40 - 1), %o1;	\
 	sll %g3, 6, %g3;		\
 	add %o1, 0x80, %o1;		\
-	ba,pt %xcc, U3cfu_fixup;	\
+	ba U3cfu_fixup;			\
 	 add %o1, %g3, %o1;		\
 	.section __ex_table;		\
 	.align 4;			\
@@ -68,7 +68,7 @@
 99:	VISExitHalf;			\
 	and %o2, (0x40 - 1), %o1;	\
 	add %o1, 0x40, %o1;		\
-	ba,pt %xcc, U3cfu_fixup;	\
+	ba U3cfu_fixup;			\
 	 add %o1, %g3, %o1;		\
 	.section __ex_table;		\
 	.align 4;			\
diff -urN linux-2.4.18-pre4/drivers/block/cpqarray.c linux/drivers/block/cpqarray.c
--- linux-2.4.18-pre4/drivers/block/cpqarray.c	Fri Nov  9 14:28:46 2001
+++ linux/drivers/block/cpqarray.c	Tue Jan 22 12:01:22 2002
@@ -32,6 +32,7 @@
 #include <linux/blkpg.h>
 #include <linux/timer.h>
 #include <linux/proc_fs.h>
+#include <linux/devfs_fs_kernel.h>
 #include <linux/init.h>
 #include <linux/hdreg.h>
 #include <linux/spinlock.h>
@@ -70,6 +71,7 @@
 
 static int nr_ctlr;
 static ctlr_info_t *hba[MAX_CTLR];
+static devfs_handle_t de_arr[MAX_CTLR][NWD];
 
 static int eisa[8];
 
@@ -338,6 +340,7 @@
 
 		del_gendisk(&ida_gendisk[i]);
 	}
+	devfs_unregister(devfs_find_handle(NULL, "ida", 0, 0, 0, 0));
 	remove_proc_entry("cpqarray", proc_root_driver);
 	kfree(ida);
 	kfree(ida_sizes);
@@ -540,6 +543,8 @@
 		ida_gendisk[i].part = ida + (i*256);
 		ida_gendisk[i].sizes = ida_sizes + (i*256);
 		ida_gendisk[i].nr_real = 0; 
+		ida_gendisk[i].de_arr = de_arr[i]; 
+		ida_gendisk[i].fops = &ida_fops; 
 	
 		/* Get on the disk list */
 		add_gendisk(&ida_gendisk[i]);
@@ -1881,6 +1886,14 @@
                 			kfree(id_ldrive);
                 			return;
 
+				}
+				if (!de_arr[ctlr][log_unit]) {
+					char txt[16];
+
+					sprintf(txt, "ida/c%dd%d", ctlr,
+						log_unit);
+					de_arr[ctlr][log_unit] =
+						devfs_mk_dir(NULL, txt, NULL);
 				}
 				info_p->phys_drives =
 				    sense_config_buf->ctlr_phys_drv;
diff -urN linux-2.4.18-pre4/drivers/char/advantechwdt.c linux/drivers/char/advantechwdt.c
--- linux-2.4.18-pre4/drivers/char/advantechwdt.c	Thu Sep 13 15:21:32 2001
+++ linux/drivers/char/advantechwdt.c	Tue Jan 22 12:01:22 2002
@@ -64,6 +64,7 @@
 #define WDT_START 0x443
 
 #define WD_TIMO 60		/* 1 minute */
+static int wd_margin = WD_TIMO;
 
 /*
  *	Kernel methods.
@@ -73,7 +74,7 @@
 advwdt_ping(void)
 {
 	/* Write a watchdog value */
-	outb_p(WD_TIMO, WDT_START);
+	outb_p(wd_margin, WDT_START);
 }
 
 static ssize_t
@@ -100,8 +101,9 @@
 advwdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
 	  unsigned long arg)
 {
+	int new_margin;
 	static struct watchdog_info ident = {
-		WDIOF_KEEPALIVEPING, 1, "Advantech WDT"
+		WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT, 1, "Advantech WDT"
 	};
 	
 	switch (cmd) {
@@ -117,6 +119,19 @@
 
 	case WDIOC_KEEPALIVE:
 	  advwdt_ping();
+	  break;
+
+	case WDIOC_SETTIMEOUT:
+	  if (get_user(new_margin, (int *)arg))
+		  return -EFAULT;
+	  if ((new_margin < 1) || (new_margin > 63))
+		  return -EINVAL;
+	  wd_margin = new_margin;
+	  advwdt_ping();
+	  /* Fall */
+
+	case WDIOC_GETTIMEOUT:
+	  return put_user(wd_margin, (int *)arg);
 	  break;
 
 	default:
diff -urN linux-2.4.18-pre4/drivers/char/eurotechwdt.c linux/drivers/char/eurotechwdt.c
--- linux-2.4.18-pre4/drivers/char/eurotechwdt.c	Thu Oct 25 13:53:47 2001
+++ linux/drivers/char/eurotechwdt.c	Tue Jan 22 12:01:22 2002
@@ -233,7 +233,7 @@
         unsigned int cmd, unsigned long arg)
 {
    static struct watchdog_info ident = {
-      options		: WDIOF_CARDRESET,
+      options		: WDIOF_CARDRESET | WDIOF_SETTIMEOUT,
       firmware_version	: 1,
       identity		: "WDT Eurotech CPU-1220/1410"
    };
@@ -265,7 +265,10 @@
 
          eurwdt_timeout = time; 
          eurwdt_set_timeout(time); 
-         return 0;
+	 /* Fall */
+
+      case WDIOC_GETTIMEOUT:
+	 return put_user(eurwdt_timeout, (int *)arg);
    }
 }
 
diff -urN linux-2.4.18-pre4/drivers/char/i810-tco.c linux/drivers/char/i810-tco.c
--- linux-2.4.18-pre4/drivers/char/i810-tco.c	Thu Sep 13 15:21:32 2001
+++ linux/drivers/char/i810-tco.c	Tue Jan 22 12:01:22 2002
@@ -181,7 +181,7 @@
 	/*
 	 *      Shut off the timer.
 	 */
-#ifdef CONFIG_WATCHDOG_NOWAYOUT
+#ifndef CONFIG_WATCHDOG_NOWAYOUT
 	tco_timer_stop ();
 	timer_alive = 0;
 #endif	
@@ -208,8 +208,10 @@
 static int i810tco_ioctl (struct inode *inode, struct file *file,
 			  unsigned int cmd, unsigned long arg)
 {
+	int new_margin, u_margin;
+
 	static struct watchdog_info ident = {
-		0,
+		WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING,
 		0,
 		"i810 TCO timer"
 	};
@@ -229,6 +231,19 @@
 	case WDIOC_KEEPALIVE:
 		tco_timer_reload ();
 		return 0;
+	case WDIOC_SETTIMEOUT:
+		if (get_user(u_margin, (int *) arg))
+			return -EFAULT;
+		new_margin = (u_margin * 10 + 5) / 6;
+		if ((new_margin < 3) || (new_margin > 63))
+			return -EINVAL;
+		if (tco_timer_settimer((unsigned char)new_margin))
+		    return -EINVAL;
+		i810_margin = new_margin;
+		tco_timer_reload();
+		/* Fall */
+	case WDIOC_GETTIMEOUT:
+		return put_user((int)(i810_margin * 6 / 10), (int *) arg);
 	}
 }
 
diff -urN linux-2.4.18-pre4/drivers/char/ib700wdt.c linux/drivers/char/ib700wdt.c
--- linux-2.4.18-pre4/drivers/char/ib700wdt.c	Thu Oct 11 09:07:00 2001
+++ linux/drivers/char/ib700wdt.c	Tue Jan 22 12:01:22 2002
@@ -87,11 +87,34 @@
  *
  */
 
+static int wd_times[] = {
+	30,	/* 0x0 */
+	28,	/* 0x1 */
+	26,	/* 0x2 */
+	24,	/* 0x3 */
+	22,	/* 0x4 */
+	20,	/* 0x5 */
+	18,	/* 0x6 */
+	16,	/* 0x7 */
+	14,	/* 0x8 */
+	12,	/* 0x9 */
+	10,	/* 0xA */
+	8,	/* 0xB */
+	6,	/* 0xC */
+	4,	/* 0xD */
+	2,	/* 0xE */
+	0,	/* 0xF */
+};
+
 #define WDT_STOP 0x441
 #define WDT_START 0x443
 
+/* Default timeout */
 #define WD_TIMO 0		/* 30 seconds +/- 20%, from table */
 
+static int wd_margin = WD_TIMO;
+
+
 /*
  *	Kernel methods.
  */
@@ -100,7 +123,7 @@
 ibwdt_ping(void)
 {
 	/* Write a watchdog value */
-	outb_p(WD_TIMO, WDT_START);
+	outb_p(wd_times[wd_margin], WDT_START);
 }
 
 static ssize_t
@@ -127,8 +150,10 @@
 ibwdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
 	  unsigned long arg)
 {
+	int i, new_margin;
+
 	static struct watchdog_info ident = {
-		WDIOF_KEEPALIVEPING, 1, "IB700 WDT"
+		WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT, 1, "IB700 WDT"
 	};
 
 	switch (cmd) {
@@ -146,6 +171,22 @@
 	  ibwdt_ping();
 	  break;
 
+	case WDIOC_SETTIMEOUT:
+	  if (get_user(new_margin, (int *)arg))
+		  return -EFAULT;
+	  if ((new_margin < 0) || (new_margin > 30))
+		  return -EINVAL;
+	  for (i = 0x0F; i > -1; i--)
+		  if (wd_times[i] > new_margin)
+			  break;
+	  wd_margin = i;
+	  ibwdt_ping();
+	  /* Fall */
+
+	case WDIOC_GETTIMEOUT:
+	  return put_user(wd_times[wd_margin], (int *)arg);
+	  break;
+
 	default:
 	  return -ENOTTY;
 	}
@@ -182,7 +223,7 @@
 	if (MINOR(inode->i_rdev) == WATCHDOG_MINOR) {
 		spin_lock(&ibwdt_lock);
 #ifndef CONFIG_WATCHDOG_NOWAYOUT
-		outb_p(WD_TIMO, WDT_STOP);
+		outb_p(wd_times[wd_margin], WDT_STOP);
 #endif
 		ibwdt_is_open = 0;
 		spin_unlock(&ibwdt_lock);
@@ -201,7 +242,7 @@
 {
 	if (code == SYS_DOWN || code == SYS_HALT) {
 		/* Turn the WDT off */
-		outb_p(WD_TIMO, WDT_STOP);
+		outb_p(wd_times[wd_margin], WDT_STOP);
 	}
 	return NOTIFY_DONE;
 }
diff -urN linux-2.4.18-pre4/drivers/char/softdog.c linux/drivers/char/softdog.c
--- linux-2.4.18-pre4/drivers/char/softdog.c	Sun Sep 30 12:26:05 2001
+++ linux/drivers/char/softdog.c	Tue Jan 22 12:01:22 2002
@@ -26,6 +26,11 @@
  *
  *  19980911 Alan Cox
  *	Made SMP safe for 2.3.x
+ *
+ *  20011127 Joel Becker (jlbec@evilplan.org>
+ *	Added soft_noboot; Allows testing the softdog trigger without 
+ *	requiring a recompile.
+ *	Added WDIOC_GETTIMEOUT and WDIOC_SETTIMOUT.
  */
  
 #include <linux/module.h>
@@ -44,8 +49,14 @@
 #define TIMER_MARGIN	60		/* (secs) Default is 1 minute */
 
 static int soft_margin = TIMER_MARGIN;	/* in seconds */
+#ifdef ONLY_TESTING
+static int soft_noboot = 1;
+#else
+static int soft_noboot = 0;
+#endif  /* ONLY_TESTING */
 
 MODULE_PARM(soft_margin,"i");
+MODULE_PARM(soft_noboot,"i");
 MODULE_LICENSE("GPL");
 
 /*
@@ -66,13 +77,14 @@
  
 static void watchdog_fire(unsigned long data)
 {
-#ifdef ONLY_TESTING
-		printk(KERN_CRIT "SOFTDOG: Would Reboot.\n");
-#else
-	printk(KERN_CRIT "SOFTDOG: Initiating system reboot.\n");
-	machine_restart(NULL);
-	printk("WATCHDOG: Reboot didn't ?????\n");
-#endif
+	if (soft_noboot)
+		printk(KERN_CRIT "SOFTDOG: Triggered - Reboot ignored.\n");
+	else
+	{
+		printk(KERN_CRIT "SOFTDOG: Initiating system reboot.\n");
+		machine_restart(NULL);
+		printk("SOFTDOG: Reboot didn't ?????\n");
+	}
 }
 
 /*
@@ -128,8 +140,11 @@
 static int softdog_ioctl(struct inode *inode, struct file *file,
 	unsigned int cmd, unsigned long arg)
 {
+	int new_margin;
 	static struct watchdog_info ident = {
-		identity: "Software Watchdog",
+		WDIOF_SETTIMEOUT,
+		0,
+		"Software Watchdog"
 	};
 	switch (cmd) {
 		default:
@@ -144,6 +159,16 @@
 		case WDIOC_KEEPALIVE:
 			mod_timer(&watchdog_ticktock, jiffies+(soft_margin*HZ));
 			return 0;
+		case WDIOC_SETTIMEOUT:
+			if (get_user(new_margin, (int *)arg))
+				return -EFAULT;
+			if (new_margin < 1)
+				return -EINVAL;
+			soft_margin = new_margin;
+			mod_timer(&watchdog_ticktock, jiffies+(soft_margin*HZ));
+			/* Fall */
+		case WDIOC_GETTIMEOUT:
+			return put_user(soft_margin, (int *)arg);
 	}
 }
 
diff -urN linux-2.4.18-pre4/drivers/char/wdt.c linux/drivers/char/wdt.c
--- linux-2.4.18-pre4/drivers/char/wdt.c	Fri Sep  7 09:28:38 2001
+++ linux/drivers/char/wdt.c	Tue Jan 22 12:01:22 2002
@@ -27,6 +27,7 @@
  *		Tim Hockin	:	Added insmod parameters, comment cleanup
  *					Parameterized timeout
  *		Tigran Aivazian	:	Restructured wdt_init() to handle failures
+ *		Joel Becker	:	Added WDIOC_GET/SETTIMEOUT
  */
 
 #include <linux/config.h>
@@ -60,8 +61,11 @@
 static int io=0x240;
 static int irq=11;
 
+/* Default margin */
 #define WD_TIMO (100*60)		/* 1 minute */
 
+static int wd_margin = WD_TIMO;
+
 #ifndef MODULE
 
 /**
@@ -216,7 +220,7 @@
 	/* Write a watchdog value */
 	inb_p(WDT_DC);
 	wdt_ctr_mode(1,2);
-	wdt_ctr_load(1,WD_TIMO);		/* Timeout */
+	wdt_ctr_load(1,wd_margin);		/* Timeout */
 	outb_p(0, WDT_DC);
 }
 
@@ -294,10 +298,13 @@
 static int wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
 	unsigned long arg)
 {
+	int new_margin;
+
 	static struct watchdog_info ident=
 	{
 		WDIOF_OVERHEAT|WDIOF_POWERUNDER|WDIOF_POWEROVER
-			|WDIOF_EXTERN1|WDIOF_EXTERN2|WDIOF_FANFAULT,
+			|WDIOF_EXTERN1|WDIOF_EXTERN2|WDIOF_FANFAULT
+			|WDIOF_SETTIMEOUT,
 		1,
 		"WDT500/501"
 	};
@@ -317,6 +324,17 @@
 		case WDIOC_KEEPALIVE:
 			wdt_ping();
 			return 0;
+		case WDIOC_SETTIMEOUT:
+			if (get_user(new_margin, (int *)arg))
+				return -EFAULT;
+			/* Arbitrary, can't find the card's limits */
+			if ((new_margin < 0) || (new_margin > 60))
+				return -EINVAL;
+			wd_margin = new_margin * 100;
+			wdt_ping();
+			/* Fall */
+		case WDIOC_GETTIMEOUT:
+			return put_user(wd_margin / 100, (int *)arg);
 	}
 }
 
@@ -349,7 +367,7 @@
 			wdt_ctr_mode(1,2);
 			wdt_ctr_mode(2,0);
 			wdt_ctr_load(0, 8948);		/* count at 100Hz */
-			wdt_ctr_load(1,WD_TIMO);	/* Timeout 120 seconds */
+			wdt_ctr_load(1,wd_margin);	/* Timeout 120 seconds */
 			wdt_ctr_load(2,65535);
 			outb_p(0, WDT_DC);	/* Enable */
 			return 0;
diff -urN linux-2.4.18-pre4/drivers/char/wdt285.c linux/drivers/char/wdt285.c
--- linux-2.4.18-pre4/drivers/char/wdt285.c	Fri Sep  7 09:28:38 2001
+++ linux/drivers/char/wdt285.c	Tue Jan 22 12:01:22 2002
@@ -126,10 +126,10 @@
 static int watchdog_ioctl(struct inode *inode, struct file *file,
 	unsigned int cmd, unsigned long arg)
 {
-	int i;
+	int i, new_margin;
 	static struct watchdog_info ident=
 	{
-		0,
+		WDIOF_SETTIMEOUT,
 		0,
 		"Footbridge Watchdog"
 	};
@@ -149,6 +149,17 @@
 		case WDIOC_KEEPALIVE:
 			watchdog_ping();
 			return 0;
+		case WDIOC_SETTIMEOUT:
+			if (get_user(new_margin, (int *)arg))
+				return -EFAULT;
+			/* Arbitrary, can't find the card's limits */
+			if ((new_marg < 0) || (new_margin > 60))
+				return -EINVAL;
+			soft_margin = new_margin;
+			watchdog_ping();
+			/* Fall */
+		case WDIOC_GETTIMEOUT:
+			return put_user(soft_margin, (int *)arg);
 	}
 }
 
diff -urN linux-2.4.18-pre4/drivers/char/wdt_pci.c linux/drivers/char/wdt_pci.c
--- linux-2.4.18-pre4/drivers/char/wdt_pci.c	Fri Sep  7 09:28:38 2001
+++ linux/drivers/char/wdt_pci.c	Tue Jan 22 12:01:22 2002
@@ -30,6 +30,7 @@
  *		Alan Cox	:	Split ISA and PCI cards into two drivers
  *		Jeff Garzik	:	PCI cleanups
  *		Tigran Aivazian	:	Restructured wdtpci_init_one() to handle failures
+ *		Joel Becker	:	Added WDIOC_GET/SETTIMEOUT
  */
 
 #include <linux/config.h>
@@ -81,8 +82,11 @@
 static int io=0x240;
 static int irq=11;
 
+/* Default timeout */
 #define WD_TIMO (100*60)		/* 1 minute */
 
+static int wd_margin = WD_TIMO;
+
 #ifndef MODULE
 
 /**
@@ -232,7 +236,7 @@
 	/* Write a watchdog value */
 	inb_p(WDT_DC);
 	wdtpci_ctr_mode(1,2);
-	wdtpci_ctr_load(1,WD_TIMO);		/* Timeout */
+	wdtpci_ctr_load(1,wd_margin);		/* Timeout */
 	outb_p(0, WDT_DC);
 }
 
@@ -310,10 +314,12 @@
 static int wdtpci_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
 	unsigned long arg)
 {
+	int new_margin;
 	static struct watchdog_info ident=
 	{
 		WDIOF_OVERHEAT|WDIOF_POWERUNDER|WDIOF_POWEROVER
-			|WDIOF_EXTERN1|WDIOF_EXTERN2|WDIOF_FANFAULT,
+			|WDIOF_EXTERN1|WDIOF_EXTERN2|WDIOF_FANFAULT
+			|WDIOF_SETTIMEOUT,
 		1,
 		"WDT500/501PCI"
 	};
@@ -333,6 +339,17 @@
 		case WDIOC_KEEPALIVE:
 			wdtpci_ping();
 			return 0;
+		case WDIOC_SETTIMEOUT:
+			if (get_user(new_margin, (int *)arg))
+				return -EFAULT;
+			/* Arbitrary, can't find the card's limits */
+			if ((new_margin < 0) || (new_margin > 60))
+				return -EINVAL;
+			wd_margin = new_margin * 100;
+			wdtpci_ping();
+			/* Fall */
+		case WDIOC_GETTIMEOUT:
+			return put_user(wd_margin, (int *)arg);
 	}
 }
 
@@ -385,7 +402,7 @@
 			wdtpci_ctr_mode(1,2);
 			wdtpci_ctr_mode(2,1);
 			wdtpci_ctr_load(0,20833);	/* count at 100Hz */
-			wdtpci_ctr_load(1,WD_TIMO);/* Timeout 60 seconds */
+			wdtpci_ctr_load(1,wd_margin);/* Timeout 60 seconds */
 			/* DO NOT LOAD CTR2 on PCI card! -- JPN */
 			outb_p(0, WDT_DC);	/* Enable */
 			return 0;
diff -urN linux-2.4.18-pre4/drivers/hotplug/cpqphp_core.c linux/drivers/hotplug/cpqphp_core.c
--- linux-2.4.18-pre4/drivers/hotplug/cpqphp_core.c	Fri Nov  9 14:01:21 2001
+++ linux/drivers/hotplug/cpqphp_core.c	Tue Jan 22 12:01:22 2002
@@ -404,6 +404,10 @@
 		result = pci_hp_register (new_slot->hotplug_slot);
 		if (result) {
 			err ("pci_hp_register failed with error %d\n", result);
+			kfree (new_slot->hotplug_slot->info);
+			kfree (new_slot->hotplug_slot->name);
+			kfree (new_slot->hotplug_slot);
+			kfree (new_slot);
 			return result;
 		}
 		
@@ -429,6 +433,8 @@
 	while (old_slot) {
 		next_slot = old_slot->next;
 		pci_hp_deregister (old_slot->hotplug_slot);
+		kfree(old_slot->hotplug_slot->info);
+		kfree(old_slot->hotplug_slot->name);
 		kfree(old_slot->hotplug_slot);
 		kfree(old_slot);
 		old_slot = next_slot;
diff -urN linux-2.4.18-pre4/drivers/macintosh/apm_emu.c linux/drivers/macintosh/apm_emu.c
--- linux-2.4.18-pre4/drivers/macintosh/apm_emu.c	Tue Jan 22 12:01:20 2002
+++ linux/drivers/macintosh/apm_emu.c	Tue Jan 22 12:01:22 2002
@@ -455,13 +455,16 @@
 			if (!ac_line_status)
 				time_units += pmu_batteries[i].time_remaining / 60;
 			real_count++;
-			if (pmu_batteries[i].flags & PMU_BATT_CHARGING)
-				battery_flag |= 0x08;
+			if (!(pmu_batteries[i].flags & PMU_BATT_CHARGING))
+				battery_flag &= ~0x08;
 		}
 	}
 	if (real_count) {
 		percentage /= real_count;
-		if (percentage <= APM_CRITICAL) {
+		if (battery_flag & 0x08) {
+			battery_status = 0x03;
+			battery_flag = 0x08;
+		} else if (percentage <= APM_CRITICAL) {
 			battery_status = 0x02;
 			battery_flag = 0x04;
 		} else if (percentage <= APM_LOW) {
@@ -471,8 +474,6 @@
 			battery_status = 0x00;
 			battery_flag = 0x01;
 		}
-		if (battery_flag & 0x08)
-			battery_status = 0x03;
 	}
 	p += sprintf(p, "%s %d.%d 0x%02x 0x%02x 0x%02x 0x%02x %d%% %d %s\n",
 		     driver_version,
diff -urN linux-2.4.18-pre4/drivers/macintosh/via-pmu.c linux/drivers/macintosh/via-pmu.c
--- linux-2.4.18-pre4/drivers/macintosh/via-pmu.c	Tue Jan 22 12:01:20 2002
+++ linux/drivers/macintosh/via-pmu.c	Tue Jan 22 12:01:22 2002
@@ -1180,7 +1180,7 @@
 		out_8(&via[IFR], intr);
 		if (intr & SR_INT)
 			pmu_sr_intr(regs);
-		else if (intr & CB1_INT)
+		if (intr & CB1_INT)
 			adb_int_pending = 1;
 	}
 
diff -urN linux-2.4.18-pre4/drivers/md/lvm-fs.c linux/drivers/md/lvm-fs.c
--- linux-2.4.18-pre4/drivers/md/lvm-fs.c	Fri Dec 21 09:41:54 2001
+++ linux/drivers/md/lvm-fs.c	Tue Jan 22 12:01:22 2002
@@ -65,9 +65,7 @@
 
 static void _show_uuid(const char *src, char *b, char *e);
 
-#if 0
 static devfs_handle_t lvm_devfs_handle;
-#endif
 static devfs_handle_t vg_devfs_handle[MAX_VG];
 static devfs_handle_t ch_devfs_handle[MAX_VG];
 static devfs_handle_t lv_devfs_handle[MAX_LV];
@@ -81,13 +79,11 @@
 void __init lvm_init_fs() {
 	struct proc_dir_entry *pde;
 
-/* User-space has already registered this */
-#if 0
+	/*  Must create device node. Think about "devfs=only" situation  */
 	lvm_devfs_handle = devfs_register(
 		0 , "lvm", 0, LVM_CHAR_MAJOR, 0,
 		S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP,
 		&lvm_chr_fops, NULL);
-#endif
 
 	lvm_proc_dir = create_proc_entry(LVM_DIR, S_IFDIR, &proc_root);
 	if (lvm_proc_dir) {
@@ -99,9 +95,7 @@
 }
 
 void lvm_fin_fs() {
-#if 0
 	devfs_unregister (lvm_devfs_handle);
-#endif
 
 	remove_proc_entry(LVM_GLOBAL, lvm_proc_dir);
 	remove_proc_entry(LVM_VG_SUBDIR, lvm_proc_dir);
diff -urN linux-2.4.18-pre4/drivers/net/acenic.c linux/drivers/net/acenic.c
--- linux-2.4.18-pre4/drivers/net/acenic.c	Tue Jan 22 12:01:20 2002
+++ linux/drivers/net/acenic.c	Tue Jan 22 12:01:22 2002
@@ -847,7 +847,7 @@
 				dma_addr_t mapping;
 
 				ringp = &ap->skb->rx_std_skbuff[i];
-				mapping = PCI_UNMAP_ADDR(ringp, mapping);
+				mapping = pci_unmap_addr(ringp, mapping);
 				pci_unmap_page(ap->pdev, mapping,
 					       ACE_STD_BUFSIZE - (2 + 16),
 					       PCI_DMA_FROMDEVICE);
@@ -866,7 +866,7 @@
 					dma_addr_t mapping;
 
 					ringp = &ap->skb->rx_mini_skbuff[i];
-					mapping = PCI_UNMAP_ADDR(ringp,mapping);
+					mapping = pci_unmap_addr(ringp,mapping);
 					pci_unmap_page(ap->pdev, mapping,
 						       ACE_MINI_BUFSIZE - (2 + 16),
 						       PCI_DMA_FROMDEVICE);
@@ -884,7 +884,7 @@
 				dma_addr_t mapping;
 
 				ringp = &ap->skb->rx_jumbo_skbuff[i];
-				mapping = PCI_UNMAP_ADDR(ringp, mapping);
+				mapping = pci_unmap_addr(ringp, mapping);
 				pci_unmap_page(ap->pdev, mapping,
 					       ACE_JUMBO_BUFSIZE - (2 + 16),
 					       PCI_DMA_FROMDEVICE);
@@ -1842,7 +1842,7 @@
 				       ACE_STD_BUFSIZE - (2 + 16),
 				       PCI_DMA_FROMDEVICE);
 		ap->skb->rx_std_skbuff[idx].skb = skb;
-		PCI_UNMAP_ADDR_SET(&ap->skb->rx_std_skbuff[idx],
+		pci_unmap_addr_set(&ap->skb->rx_std_skbuff[idx],
 				   mapping, mapping);
 
 		rd = &ap->rx_std_ring[idx];
@@ -1908,7 +1908,7 @@
 				       ACE_MINI_BUFSIZE - (2 + 16),
 				       PCI_DMA_FROMDEVICE);
 		ap->skb->rx_mini_skbuff[idx].skb = skb;
-		PCI_UNMAP_ADDR_SET(&ap->skb->rx_mini_skbuff[idx],
+		pci_unmap_addr_set(&ap->skb->rx_mini_skbuff[idx],
 				   mapping, mapping);
 
 		rd = &ap->rx_mini_ring[idx];
@@ -1969,7 +1969,7 @@
 				       ACE_JUMBO_BUFSIZE - (2 + 16),
 				       PCI_DMA_FROMDEVICE);
 		ap->skb->rx_jumbo_skbuff[idx].skb = skb;
-		PCI_UNMAP_ADDR_SET(&ap->skb->rx_jumbo_skbuff[idx],
+		pci_unmap_addr_set(&ap->skb->rx_jumbo_skbuff[idx],
 				   mapping, mapping);
 
 		rd = &ap->rx_jumbo_ring[idx];
@@ -2177,7 +2177,7 @@
 		skb = rip->skb;
 		rip->skb = NULL;
 		pci_unmap_page(ap->pdev,
-			       PCI_UNMAP_ADDR(rip, mapping),
+			       pci_unmap_addr(rip, mapping),
 			       mapsize,
 			       PCI_DMA_FROMDEVICE);
 		skb_put(skb, retdesc->size);
@@ -2244,13 +2244,13 @@
 
 		info = ap->skb->tx_skbuff + idx;
 		skb = info->skb;
-		mapping = PCI_UNMAP_ADDR(info, mapping);
+		mapping = pci_unmap_addr(info, mapping);
 
 		if (mapping) {
 			pci_unmap_page(ap->pdev, mapping,
-				       PCI_UNMAP_LEN(info, maplen),
+				       pci_unmap_len(info, maplen),
 				       PCI_DMA_TODEVICE);
-			PCI_UNMAP_ADDR_SET(info, mapping, 0);
+			pci_unmap_addr_set(info, mapping, 0);
 		}
 
 		if (skb) {
@@ -2534,14 +2534,14 @@
 
 		info = ap->skb->tx_skbuff + i;
 		skb = info->skb;
-		mapping = PCI_UNMAP_ADDR(info, mapping);
+		mapping = pci_unmap_addr(info, mapping);
 
 		if (mapping) {
 			memset(ap->tx_ring + i, 0, sizeof(struct tx_desc));
 			pci_unmap_page(ap->pdev, mapping,
-				       PCI_UNMAP_LEN(info, maplen),
+				       pci_unmap_len(info, maplen),
 				       PCI_DMA_TODEVICE);
-			PCI_UNMAP_ADDR_SET(info, mapping, 0);
+			pci_unmap_addr_set(info, mapping, 0);
 		}
 		if (skb) {
 			dev_kfree_skb(skb);
@@ -2575,8 +2575,8 @@
 
 	info = ap->skb->tx_skbuff + idx;
 	info->skb = tail;
-	PCI_UNMAP_ADDR_SET(info, mapping, mapping);
-	PCI_UNMAP_LEN_SET(info, maplen, skb->len);
+	pci_unmap_addr_set(info, mapping, mapping);
+	pci_unmap_len_set(info, maplen, skb->len);
 	return mapping;
 }
 
@@ -2677,8 +2677,8 @@
 			} else {
 				info->skb = NULL;
 			}
-			PCI_UNMAP_ADDR_SET(info, mapping, mapping);
-			PCI_UNMAP_LEN_SET(info, maplen, frag->size);
+			pci_unmap_addr_set(info, mapping, mapping);
+			pci_unmap_len_set(info, maplen, frag->size);
 			ace_load_tx_bd(desc, mapping, flagsize);
 		}
 	}
diff -urN linux-2.4.18-pre4/drivers/net/au1000_eth.c linux/drivers/net/au1000_eth.c
--- linux-2.4.18-pre4/drivers/net/au1000_eth.c	Sun Sep  9 10:43:01 2001
+++ linux/drivers/net/au1000_eth.c	Tue Jan 22 12:01:22 2002
@@ -1156,6 +1156,8 @@
 		//data[3] = mdio_read(ioaddr, data[0], data[1]); 
 		return 0;
 		case SIOCDEVPRIVATE+2:		/* Write the specified MII register */
+		if (!capable(CAP_NET_ADMIN))
+			return -EPERM;
 		//mdio_write(ioaddr, data[0], data[1], data[2]);
 		return 0;
 		default:
diff -urN linux-2.4.18-pre4/drivers/net/cs89x0.c linux/drivers/net/cs89x0.c
--- linux-2.4.18-pre4/drivers/net/cs89x0.c	Sun Sep 30 12:26:06 2001
+++ linux/drivers/net/cs89x0.c	Tue Jan 22 12:01:22 2002
@@ -537,7 +537,7 @@
                         dev->dev_addr[i*2+1] = eeprom_buff[i] >> 8;
                 }
 		if (net_debug > 1)
-			printk(KERN_DEBUG "%s: new adapter_cnf: 0%x\n",
+			printk(KERN_DEBUG "%s: new adapter_cnf: 0x%x\n",
 				dev->name, lp->adapter_cnf);
         }
 
@@ -582,8 +582,8 @@
 		i = lp->isa_config & INT_NO_MASK;
 		if (lp->chip_type == CS8900) {
 			/* Translate the IRQ using the IRQ mapping table. */
-			if (i > sizeof(cs8900_irq_map)/sizeof(cs8900_irq_map[0]))
-				printk("\ncs89x0: bug: isa_config is %d\n", i);
+			if (i >= sizeof(cs8900_irq_map)/sizeof(cs8900_irq_map[0]))
+				printk("\ncs89x0: invalid ISA interrupt number %d\n", i);
 			else
 				i = cs8900_irq_map[i];
 			
diff -urN linux-2.4.18-pre4/drivers/net/dl2k.c linux/drivers/net/dl2k.c
--- linux-2.4.18-pre4/drivers/net/dl2k.c	Tue Jan 22 12:01:20 2002
+++ linux/drivers/net/dl2k.c	Tue Jan 22 12:01:22 2002
@@ -25,12 +25,14 @@
     1.06	2001/12/13	Fixed disconnect bug at 10Mbps mode.
     				Fixed tx_full flag incorrect.
 				Added tx_coalesce paramter.
-*/
+    1.07	2002/01/03	Fixed miscount of RX frame error.
+    1.08	2002/01/17	Fixed the multicast bug.
+ */
 
 #include "dl2k.h"
 
 static char version[] __devinitdata =
-    KERN_INFO "D-Link DL2000-based linux driver v1.06 2001/12/13\n";
+    KERN_INFO "D-Link DL2000-based linux driver v1.08 2002/01/17\n";
 
 #define MAX_UNITS 8
 static int mtu[MAX_UNITS];
@@ -40,9 +42,9 @@
 static int tx_flow[MAX_UNITS];
 static int rx_flow[MAX_UNITS];
 static int copy_thresh;
-static int rx_coalesce = 5;	/* Rx frame count each interrupt */
-static int rx_timeout = 750;	/* Rx DMA wait time in 64ns increments */
-static int tx_coalesce = 8;	/* HW xmit count each TxComplete */
+static int rx_coalesce = DEFAULT_RXC;
+static int rx_timeout = DEFAULT_RXT;	
+static int tx_coalesce = DEFAULT_TXC;	
 
 MODULE_AUTHOR ("Edward Peng");
 MODULE_DESCRIPTION ("D-Link DL2000-based Gigabit Ethernet Adapter");
@@ -54,9 +56,10 @@
 MODULE_PARM (tx_flow, "1-" __MODULE_STRING (MAX_UNITS) "i");
 MODULE_PARM (rx_flow, "1-" __MODULE_STRING (MAX_UNITS) "i");
 MODULE_PARM (copy_thresh, "i");
-MODULE_PARM (rx_coalesce, "i");
-MODULE_PARM (rx_timeout, "i");
-MODULE_PARM (tx_coalesce, "i");
+MODULE_PARM (rx_coalesce, "i");	/* Rx frame count each interrupt */
+MODULE_PARM (rx_timeout, "i");	/* Rx DMA wait time in 64ns increments */
+MODULE_PARM (tx_coalesce, "i"); /* HW xmit count each TxComplete [1-8] */
+
 
 /* Enable the default interrupts */
 #define DEFAULT_INTR (RxDMAComplete | HostError | IntRequested | TxComplete| \
@@ -201,6 +204,8 @@
 		np->rx_flow = (rx_flow[card_idx]) ? 1 : 0;
 		if (tx_coalesce < 1)
 			tx_coalesce = 1;
+		if (tx_coalesce > 8)
+			tx_coalesce = 8;
 	}
 	dev->open = &rio_open;
 	dev->hard_start_xmit = &start_xmit;
@@ -799,7 +804,7 @@
 			if (frame_status & 0x00300000)
 				np->stats.rx_length_errors++;
 			if (frame_status & 0x00010000)
-				np->stats.rx_fifo_errors++;
+	 			np->stats.rx_fifo_errors++;
 			if (frame_status & 0x00060000)
 				np->stats.rx_frame_errors++;
 			if (frame_status & 0x00080000)
@@ -948,11 +953,11 @@
 	    readl (ioaddr + FramesWDeferredXmt) + temp2;
 
 	/* detailed rx_error */
-	np->stats.rx_length_errors += readw (ioaddr + InRangeLengthErrors) +
-	    readw (ioaddr + FrameTooLongErrors);
+	np->stats.rx_length_errors += readw (ioaddr + FrameTooLongErrors);
 	np->stats.rx_crc_errors += readw (ioaddr + FrameCheckSeqError);
 
 	/* Clear all other statistic register. */
+	readw (ioaddr + InRangeLengthErrors);
 	readw (ioaddr + MacControlFramesXmtd);
 	readw (ioaddr + BcstFramesXmtdOk);
 	readl (ioaddr + McstFramesXmtdOk);
@@ -1012,36 +1017,42 @@
 	u32 hash_table[2];
 	u16 rx_mode = 0;
 	int i;
+	int bit;
+	int index, crc;
 	struct dev_mc_list *mclist;
 	struct netdev_private *np = dev->priv;
-
-	/* Default: receive broadcast and unicast */
-	rx_mode = ReceiveBroadcast | ReceiveUnicast;
+	
+	hash_table[0] = hash_table[1] = 0;
+	/* RxFlowcontrol DA: 01-80-C2-00-00-01. Hash index=0x39 */
+	hash_table[1] |= 0x02000000;
 	if (dev->flags & IFF_PROMISC) {
 		/* Receive all frames promiscuously. */
-		rx_mode |= ReceiveAllFrames;
-	} else if (((dev->flags & IFF_MULTICAST)
-		    && (dev->mc_count > multicast_filter_limit))
-		   || (dev->flags & IFF_ALLMULTI)) {
+		rx_mode = ReceiveAllFrames;
+	} else if ((dev->flags & IFF_ALLMULTI) || 
+			(dev->mc_count > multicast_filter_limit)) {
 		/* Receive broadcast and multicast frames */
-		rx_mode |= ReceiveBroadcast | ReceiveMulticast | ReceiveUnicast;
-	} else if ((dev->flags & IFF_MULTICAST) & (dev->mc_count > 0)) {
-		/* Receive broadcast frames and multicast frames filtering by Hashtable */
-		rx_mode |=
+		rx_mode = ReceiveBroadcast | ReceiveMulticast | ReceiveUnicast;
+	} else if (dev->mc_count > 0) {
+		/* Receive broadcast frames and multicast frames filtering 
+		   by Hashtable */
+		rx_mode =
 		    ReceiveBroadcast | ReceiveMulticastHash | ReceiveUnicast;
+		for (i=0, mclist = dev->mc_list; mclist && i < dev->mc_count; 
+				i++, mclist=mclist->next) {
+			crc = get_crc (mclist->dmi_addr, ETH_ALEN);
+			for (index=0, bit=0; bit<6; bit++, crc<<=1) {
+				if (crc & 0x80000000) index |= 1 << bit;
+			}
+			hash_table[index / 32] |= (1 << (index % 32));
+		}
+	} else {
+		rx_mode = ReceiveBroadcast | ReceiveUnicast;
 	}
 	if (np->vlan) {
 		/* ReceiveVLANMatch field in ReceiveMode */
 		rx_mode |= ReceiveVLANMatch;
 	}
-	hash_table[0] = 0x00000000;
-	hash_table[1] = 0x00000000;
 
-	for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count;
-	     i++, mclist = mclist->next) {
-		set_bit (get_crc (mclist->dmi_addr, ETH_ALEN) & 0x3f,
-			 hash_table);
-	}
 	writel (hash_table[0], ioaddr + HashTable0);
 	writel (hash_table[1], ioaddr + HashTable1);
 	writew (rx_mode, ioaddr + ReceiveMode);
@@ -1074,6 +1085,8 @@
 		miidata->out_value = mii_read (dev, phy_addr, miidata->reg_num);
 		break;
 	case SIOCDEVPRIVATE + 2:
+		if (!capable(CAP_NET_ADMIN))
+			return -EPERM;
 		mii_write (dev, phy_addr, miidata->reg_num, miidata->in_value);
 		break;
 	case SIOCDEVPRIVATE + 3:
diff -urN linux-2.4.18-pre4/drivers/net/dl2k.h linux/drivers/net/dl2k.h
--- linux-2.4.18-pre4/drivers/net/dl2k.h	Tue Jan 22 12:01:20 2002
+++ linux/drivers/net/dl2k.h	Tue Jan 22 12:01:22 2002
@@ -182,12 +182,12 @@
 
 /* Bits in the ReceiveMode register. */
 enum ReceiveMode_bits {
-	ReceiveIPMulticast = 0x0020,
-	ReceiveMulticastHash = 0x0010,
-	ReceiveAllFrames = 0x0008,
-	ReceiveBroadcast = 0x0004,
-	ReceiveMulticast = 0x0002,
 	ReceiveUnicast = 0x0001,
+	ReceiveMulticast = 0x0002,
+	ReceiveBroadcast = 0x0004,
+	ReceiveAllFrames = 0x0008,
+	ReceiveMulticastHash = 0x0010,
+	ReceiveIPMulticast = 0x0020,
 	ReceiveVLANMatch = 0x0100,
 	ReceiveVLANHash = 0x0200,
 };
@@ -662,7 +662,7 @@
 	unsigned int coalesce:1;	/* Rx coalescing enable */
 	unsigned int tx_flow:1;		/* Tx flow control enable */
 	unsigned int rx_flow:1;		/* Rx flow control enable */
-	unsigned int phy_media:1;	/* 1: fiber, 0: copper */ 
+	unsigned int phy_media:1;	/* 1: fiber, 0: copper */
 	struct netdev_desc *last_tx;	/* Last Tx descriptor used. */
 	unsigned long cur_rx, old_rx;	/* Producer/consumer ring indices */
 	unsigned long cur_tx, old_tx;
@@ -699,6 +699,10 @@
 #define PACKET_SIZE		1536
 #define MAX_JUMBO		8000
 #define RIO_IO_SIZE             340
+#define DEFAULT_RXC		5
+#define DEFAULT_RXT		750
+#define DEFAULT_TXC		1
+#define MAX_TXC			8
 #ifdef RIO_DEBUG
 #define DEBUG_TFD_DUMP(x) debug_tfd_dump(x)
 #define DEBUG_RFD_DUMP(x,flag) debug_rfd_dump(x,flag)
diff -urN linux-2.4.18-pre4/drivers/net/dmfe.c linux/drivers/net/dmfe.c
--- linux-2.4.18-pre4/drivers/net/dmfe.c	Fri Nov  9 13:50:01 2001
+++ linux/drivers/net/dmfe.c	Tue Jan 22 12:01:22 2002
@@ -61,8 +61,8 @@
 */
 
 #define DRV_NAME	"dmfe"
-#define DRV_VERSION	"1.36.3"
-#define DRV_RELDATE	"2001-11-06"
+#define DRV_VERSION	"1.36.4"
+#define DRV_RELDATE	"2002-01-17"
 
 #include <linux/module.h>
 
@@ -98,7 +98,6 @@
 #define PCI_DM9100_ID   0x91001282      /* Davicom DM9100 ID */
 #define PCI_DM9009_ID   0x90091282      /* Davicom DM9009 ID */
 
-#define DMFE_SUCC       0
 #define DM9102_IO_SIZE  0x80
 #define DM9102A_IO_SIZE 0x100
 #define TX_MAX_SEND_CNT 0x1             /* Maximum tx packet per time */
@@ -527,7 +526,7 @@
 }
 
 
-static void __exit dmfe_remove_one (struct pci_dev *pdev)
+static void __devexit dmfe_remove_one (struct pci_dev *pdev)
 {
 	struct net_device *dev = pci_get_drvdata(pdev);
 	struct dmfe_board_info *db = dev->priv;
@@ -2059,7 +2058,7 @@
 	name:		"dmfe",
 	id_table:	dmfe_pci_tbl,
 	probe:		dmfe_init_one,
-	remove:		dmfe_remove_one,
+	remove:		__devexit_p(dmfe_remove_one),
 };
 
 MODULE_AUTHOR("Sten Wang, sten_wang@davicom.com.tw");
diff -urN linux-2.4.18-pre4/drivers/net/eepro100.c linux/drivers/net/eepro100.c
--- linux-2.4.18-pre4/drivers/net/eepro100.c	Fri Dec 21 09:41:54 2001
+++ linux/drivers/net/eepro100.c	Tue Jan 22 12:01:22 2002
@@ -28,7 +28,7 @@
 */
 
 static const char *version =
-"eepro100.c:v1.09j-t 9/29/99 Donald Becker http://cesdis.gsfc.nasa.gov/linux/drivers/eepro100.html\n"
+"eepro100.c:v1.09j-t 9/29/99 Donald Becker http://www.scyld.com/network/eepro100.html\n"
 "eepro100.c: $Revision: 1.36 $ 2000/11/17 Modified by Andrey V. Savochkin <saw@saw.sw.com.sg> and others\n";
 
 /* A few user-configurable values that apply to all boards.
diff -urN linux-2.4.18-pre4/drivers/net/ns83820.c linux/drivers/net/ns83820.c
--- linux-2.4.18-pre4/drivers/net/ns83820.c	Fri Dec 21 09:41:54 2001
+++ linux/drivers/net/ns83820.c	Tue Jan 22 12:01:22 2002
@@ -848,7 +848,7 @@
 			skb->protocol = eth_type_trans(skb, &dev->net_dev);
 			if (NET_RX_DROP == netif_rx(skb))
 				dev->stats.rx_dropped ++;
-#ifndef __i386__
+#if 0 //ndef __i386__
 		done:;
 #endif
 		} else {
diff -urN linux-2.4.18-pre4/drivers/net/slip.c linux/drivers/net/slip.c
--- linux-2.4.18-pre4/drivers/net/slip.c	Sun Sep 30 12:26:07 2001
+++ linux/drivers/net/slip.c	Tue Jan 22 12:01:22 2002
@@ -483,7 +483,7 @@
 		 *      14 Oct 1994 Dmitry Gorodchanin.
 		 */
 #ifdef SL_CHECK_TRANSMIT
-		if (jiffies - dev->trans_start  < 20 * HZ)  {
+		if (time_before(jiffies, dev->trans_start + 20 * HZ))  {
 			/* 20 sec timeout not reached */
 			goto out;
 		}
@@ -1387,7 +1387,7 @@
 	int i;
 
 	if (slip_ctrls != NULL) {
-		unsigned long start = jiffies;
+		unsigned long timeout = jiffies + HZ;
 		int busy = 0;
 
 		/* First of all: check for active disciplines and hangup them.
@@ -1412,7 +1412,7 @@
 				spin_unlock(&slc->ctrl.lock);
 			}
 			local_bh_enable();
-		} while (busy && jiffies - start < 1*HZ);
+		} while (busy && time_before(jiffies, timeout));
 
 		busy = 0;
 		for (i = 0; i < slip_maxdev; i++) {
diff -urN linux-2.4.18-pre4/drivers/net/sungem.c linux/drivers/net/sungem.c
--- linux-2.4.18-pre4/drivers/net/sungem.c	Tue Jan 22 12:01:20 2002
+++ linux/drivers/net/sungem.c	Tue Jan 22 12:01:22 2002
@@ -1,4 +1,4 @@
-/* $Id: sungem.c,v 1.44 2001/12/08 04:06:27 davem Exp $
+/* $Id: sungem.c,v 1.44.2.2 2002/01/15 06:26:56 davem Exp $
  * sungem.c: Sun GEM ethernet driver.
  *
  * Copyright (C) 2000, 2001 David S. Miller (davem@redhat.com)
@@ -57,6 +57,10 @@
 
 #include "sungem.h"
 
+#define DEFAULT_MSG	(NETIF_MSG_DRV		| \
+			 NETIF_MSG_PROBE	| \
+			 NETIF_MSG_LINK)
+
 #define DRV_NAME	"sungem"
 #define DRV_VERSION	"0.96"
 #define DRV_RELDATE	"11/17/01"
@@ -70,9 +74,11 @@
 MODULE_LICENSE("GPL");
 
 MODULE_PARM(gem_debug, "i");
-MODULE_PARM_DESC(gem_debug, "(ignored)");
+MODULE_PARM_DESC(gem_debug, "bitmapped message enable number");
 MODULE_PARM(link_mode, "i");
+MODULE_PARM_DESC(link_mode, "default link mode");
 
+int gem_debug = -1;
 static int link_mode;
 
 static u16 link_modes[] __devinitdata = {
@@ -88,12 +94,6 @@
 #define GEM_MODULE_NAME	"gem"
 #define PFX GEM_MODULE_NAME ": "
 
-#ifdef GEM_DEBUG
-int gem_debug = GEM_DEBUG;
-#else
-int gem_debug = 1;
-#endif
-
 static struct pci_device_id gem_pci_tbl[] __devinitdata = {
 	{ PCI_VENDOR_ID_SUN, PCI_DEVICE_ID_SUN_GEM,
 	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
@@ -109,6 +109,8 @@
 	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
 	{ PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_UNI_N_GMAC,
 	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
+	{ PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_UNI_N_GMACP,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
 	{0, }
 };
 
@@ -174,6 +176,8 @@
 
 static void gem_handle_mif_event(struct gem *gp, u32 reg_val, u32 changed_bits)
 {
+	if (netif_msg_intr(gp))
+		printk(KERN_DEBUG "%s: mif interrupt\n", gp->dev->name);
 }
 
 static int gem_pcs_interrupt(struct net_device *dev, struct gem *gp, u32 gem_status)
@@ -181,6 +185,10 @@
 	u32 pcs_istat = readl(gp->regs + PCS_ISTAT);
 	u32 pcs_miistat;
 
+	if (netif_msg_intr(gp))
+		printk(KERN_DEBUG "%s: pcs interrupt, pcs_istat: 0x%x\n",
+			gp->dev->name, pcs_istat);
+
 	if (!(pcs_istat & PCS_ISTAT_LSC)) {
 		printk(KERN_ERR "%s: PCS irq but no link status change???\n",
 		       dev->name);
@@ -230,6 +238,10 @@
 {
 	u32 txmac_stat = readl(gp->regs + MAC_TXSTAT);
 
+	if (netif_msg_intr(gp))
+		printk(KERN_DEBUG "%s: txmac interrupt, txmac_stat: 0x%x\n",
+			gp->dev->name, txmac_stat);
+
 	/* Defer timer expiration is quite normal,
 	 * don't even log the event.
 	 */
@@ -275,6 +287,10 @@
 {
 	u32 rxmac_stat = readl(gp->regs + MAC_RXSTAT);
 
+	if (netif_msg_intr(gp))
+		printk(KERN_DEBUG "%s: rxmac interrupt, rxmac_stat: 0x%x\n",
+			gp->dev->name, rxmac_stat);
+
 	if (rxmac_stat & MAC_RXSTAT_OFLW) {
 		printk(KERN_ERR "%s: RX MAC fifo overflow.\n",
 		       dev->name);
@@ -301,6 +317,10 @@
 {
 	u32 mac_cstat = readl(gp->regs + MAC_CSTAT);
 
+	if (netif_msg_intr(gp))
+		printk(KERN_DEBUG "%s: mac interrupt, mac_cstat: 0x%x\n",
+			gp->dev->name, mac_cstat);
+
 	/* This interrupt is just for pause frame and pause
 	 * tracking.  It is useful for diagnostics and debug
 	 * but probably by default we will mask these events.
@@ -401,11 +421,17 @@
 {
 	if (gem_status & GREG_STAT_RXNOBUF) {
 		/* Frame arrived, no free RX buffers available. */
+		if (netif_msg_rx_err(gp))
+			printk(KERN_DEBUG "%s: no buffer for rx frame\n",
+				gp->dev->name);
 		gp->net_stats.rx_dropped++;
 	}
 
 	if (gem_status & GREG_STAT_RXTAGERR) {
 		/* corrupt RX tag framing */
+		if (netif_msg_rx_err(gp))
+			printk(KERN_DEBUG "%s: corrupt rx tag framing\n",
+				gp->dev->name);
 		gp->net_stats.rx_errors++;
 
 		goto do_reset;
@@ -454,6 +480,10 @@
 {
 	int entry, limit;
 
+	if (netif_msg_intr(gp))
+		printk(KERN_DEBUG "%s: tx interrupt, gem_status: 0x%x\n",
+			gp->dev->name, gem_status);
+
 	entry = gp->tx_old;
 	limit = ((gem_status & GREG_STAT_TXNR) >> GREG_STAT_TXNR_SHIFT);
 	while (entry != limit) {
@@ -463,6 +493,9 @@
 		u32 dma_len;
 		int frag;
 
+		if (netif_msg_tx_done(gp))
+			printk(KERN_DEBUG "%s: tx done, slot %d\n",
+				gp->dev->name, entry);
 		skb = gp->tx_skbs[entry];
 		if (skb_shinfo(skb)->nr_frags) {
 			int last = entry + skb_shinfo(skb)->nr_frags;
@@ -534,6 +567,10 @@
 {
 	int entry, drops;
 
+	if (netif_msg_intr(gp))
+		printk(KERN_DEBUG "%s: rx interrupt, done: %d, rx_new: %d\n",
+			gp->dev->name, readl(gp->regs + RXDMA_DONE), gp->rx_new);
+
 	entry = gp->rx_new;
 	drops = 0;
 	for (;;) {
@@ -785,6 +822,9 @@
 	if (TX_BUFFS_AVAIL(gp) <= 0)
 		netif_stop_queue(dev);
 
+	if (netif_msg_tx_queued(gp))
+		printk(KERN_DEBUG "%s: tx queued, slot %d, skblen %d\n",
+		       dev->name, entry, skb->len);
 	writel(gp->tx_new, gp->regs + TXDMA_KICK);
 	spin_unlock_irq(&gp->lock);
 
@@ -992,8 +1032,9 @@
 		speed = 1000;
 	}
 
-	printk(KERN_INFO "%s: Link is up at %d Mbps, %s-duplex.\n",
-	       gp->dev->name, speed, (full_duplex ? "full" : "half"));
+	if (netif_msg_link(gp))
+		printk(KERN_INFO "%s: Link is up at %d Mbps, %s-duplex.\n",
+			gp->dev->name, speed, (full_duplex ? "full" : "half"));
 
 	val = (MAC_TXCFG_EIPG0 | MAC_TXCFG_NGU);
 	if (full_duplex) {
@@ -1058,15 +1099,21 @@
 
 static int gem_mdio_link_not_up(struct gem *gp)
 {
+	u16 val;
+	
 	if (gp->lstate == link_force_ret) {
-		printk(KERN_INFO "%s: Autoneg failed again, keeping"
-			" forced mode\n", gp->dev->name);
+		if (netif_msg_link(gp))
+			printk(KERN_INFO "%s: Autoneg failed again, keeping"
+				" forced mode\n", gp->dev->name);
 		phy_write(gp, MII_BMCR, gp->link_fcntl);
 		gp->timer_ticks = 5;
 		gp->lstate = link_force_ok;
 	} else if (gp->lstate == link_aneg) {
-		u16 val = phy_read(gp, MII_BMCR);
+		val = phy_read(gp, MII_BMCR);
 
+		if (netif_msg_link(gp))
+			printk(KERN_INFO "%s: switching to forced 100bt\n",
+				gp->dev->name);
 		/* Try forced modes. */
 		val &= ~(BMCR_ANRESTART | BMCR_ANENABLE);
 		val &= ~(BMCR_FULLDPLX);
@@ -1079,14 +1126,16 @@
 		 * If already at 10Mbps, warn user about the
 		 * situation every 10 ticks.
 		 */
-		u16 val = phy_read(gp, MII_BMCR);
+		val = phy_read(gp, MII_BMCR);
 		if (val & BMCR_SPEED100) {
 			val &= ~BMCR_SPEED100;
 			phy_write(gp, MII_BMCR, val);
 			gp->timer_ticks = 5;
-		} else {
+			if (netif_msg_link(gp))
+				printk(KERN_INFO "%s: switching to forced 10bt\n",
+					gp->dev->name);
+		} else
 			return 1;
-		}
 	}
 	return 0;
 }
@@ -1139,22 +1188,16 @@
 	if (gp->phy_type == phy_mii_mdio0 ||
 	    gp->phy_type == phy_mii_mdio1) {
 		u16 val = phy_read(gp, MII_BMSR);
+		u16 cntl = phy_read(gp, MII_BMCR);
 		int up;
 
 		/* When using autoneg, we really wait for ANEGCOMPLETE or we may
 		 * get a "transcient" incorrect link state
 		 */
-#if 0
-		{
-			u16 cntl = phy_read(gp, MII_BMCR);
-			if (cntl & BMCR_ANENABLE)
-				up = (val & (BMSR_ANEGCOMPLETE | BMSR_LSTATUS)) == (BMSR_ANEGCOMPLETE | BMSR_LSTATUS);
-			else
-				up = (val & BMSR_LSTATUS) != 0;
-		}
-#else
-		up = (val & BMSR_LSTATUS) != 0;
-#endif
+		if (cntl & BMCR_ANENABLE)
+			up = (val & (BMSR_ANEGCOMPLETE | BMSR_LSTATUS)) == (BMSR_ANEGCOMPLETE | BMSR_LSTATUS);
+		else
+			up = (val & BMSR_LSTATUS) != 0;
 		if (up) {
 			/* Ok, here we got a link. If we had it due to a forced
 			 * fallback, and we were configured for autoneg, we do
@@ -1165,8 +1208,9 @@
 				gp->lstate = link_force_ret;
 				gp->link_fcntl = phy_read(gp, MII_BMCR);
 				gp->timer_ticks = 5;
-				printk(KERN_INFO "%s: Got link after fallback, retrying autoneg"
-				       " once...\n", gp->dev->name);
+				if (netif_msg_link(gp))
+					printk(KERN_INFO "%s: Got link after fallback, retrying"
+						" autoneg once...\n", gp->dev->name);
 				phy_write(gp, MII_BMCR,
 					  gp->link_fcntl | BMCR_ANENABLE | BMCR_ANRESTART);
 			} else if (gp->lstate != link_up) {
@@ -1182,7 +1226,9 @@
 			 */
 			if (gp->lstate == link_up) {
 				gp->lstate = link_down;
-				printk(KERN_INFO "%s: Link down\n", gp->dev->name);
+				if (netif_msg_link(gp))
+					printk(KERN_INFO "%s: Link down\n",
+						gp->dev->name);
 				gp->reset_task_pending = 1;
 				schedule_task(&gp->reset_task);
 				restart = 1;
@@ -1651,6 +1697,58 @@
 
 #define CRC_POLYNOMIAL_LE 0xedb88320UL  /* Ethernet CRC, little endian */
 
+static u32
+gem_setup_multicast(struct gem *gp)
+{
+	u32 rxcfg = 0;
+	int i;
+	
+	if ((gp->dev->flags & IFF_ALLMULTI) ||
+	    (gp->dev->mc_count > 256)) {
+	    	for (i=0; i<16; i++)
+			writel(0xffff, gp->regs + MAC_HASH0 + (i << 2));
+		rxcfg |= MAC_RXCFG_HFE;
+	} else if (gp->dev->flags & IFF_PROMISC) {
+		rxcfg |= MAC_RXCFG_PROM;
+	} else {
+		u16 hash_table[16];
+		u32 crc, poly = CRC_POLYNOMIAL_LE;
+		struct dev_mc_list *dmi = gp->dev->mc_list;
+		int i, j, bit, byte;
+
+		for (i = 0; i < 16; i++)
+			hash_table[i] = 0;
+
+		for (i = 0; i < gp->dev->mc_count; i++) {
+			char *addrs = dmi->dmi_addr;
+
+			dmi = dmi->next;
+
+			if (!(*addrs & 1))
+				continue;
+
+			crc = 0xffffffffU;
+			for (byte = 0; byte < 6; byte++) {
+				for (bit = *addrs++, j = 0; j < 8; j++, bit >>= 1) {
+					int test;
+
+					test = ((bit ^ crc) & 0x01);
+					crc >>= 1;
+					if (test)
+						crc = crc ^ poly;
+				}
+			}
+			crc >>= 24;
+			hash_table[crc >> 4] |= 1 << (15 - (crc & 0xf));
+		}
+	    	for (i=0; i<16; i++)
+			writel(hash_table[i], gp->regs + MAC_HASH0 + (i << 2));
+		rxcfg |= MAC_RXCFG_HFE;
+	}
+
+	return rxcfg;
+}
+
 static void gem_init_mac(struct gem *gp)
 {
 	unsigned char *e = &gp->dev->dev_addr[0];
@@ -1691,75 +1789,7 @@
 	writel(0, gp->regs + MAC_AF21MSK);
 	writel(0, gp->regs + MAC_AF0MSK);
 
-	rxcfg = 0;
-	if ((gp->dev->flags & IFF_ALLMULTI) ||
-	    (gp->dev->mc_count > 256)) {
-		writel(0xffff, gp->regs + MAC_HASH0);
-		writel(0xffff, gp->regs + MAC_HASH1);
-		writel(0xffff, gp->regs + MAC_HASH2);
-		writel(0xffff, gp->regs + MAC_HASH3);
-		writel(0xffff, gp->regs + MAC_HASH4);
-		writel(0xffff, gp->regs + MAC_HASH5);
-		writel(0xffff, gp->regs + MAC_HASH6);
-		writel(0xffff, gp->regs + MAC_HASH7);
-		writel(0xffff, gp->regs + MAC_HASH8);
-		writel(0xffff, gp->regs + MAC_HASH9);
-		writel(0xffff, gp->regs + MAC_HASH10);
-		writel(0xffff, gp->regs + MAC_HASH11);
-		writel(0xffff, gp->regs + MAC_HASH12);
-		writel(0xffff, gp->regs + MAC_HASH13);
-		writel(0xffff, gp->regs + MAC_HASH14);
-		writel(0xffff, gp->regs + MAC_HASH15);
-	} else if (gp->dev->flags & IFF_PROMISC) {
-		rxcfg |= MAC_RXCFG_PROM;
-	} else {
-		u16 hash_table[16];
-		u32 crc, poly = CRC_POLYNOMIAL_LE;
-		struct dev_mc_list *dmi = gp->dev->mc_list;
-		int i, j, bit, byte;
-
-		for (i = 0; i < 16; i++)
-			hash_table[i] = 0;
-
-		for (i = 0; i < gp->dev->mc_count; i++) {
-			char *addrs = dmi->dmi_addr;
-
-			dmi = dmi->next;
-
-			if (!(*addrs & 1))
-				continue;
-
-			crc = 0xffffffffU;
-			for (byte = 0; byte < 6; byte++) {
-				for (bit = *addrs++, j = 0; j < 8; j++, bit >>= 1) {
-					int test;
-
-					test = ((bit ^ crc) & 0x01);
-					crc >>= 1;
-					if (test)
-						crc = crc ^ poly;
-				}
-			}
-			crc >>= 24;
-			hash_table[crc >> 4] |= 1 << (crc & 0xf);
-		}
-		writel(hash_table[0], gp->regs + MAC_HASH0);
-		writel(hash_table[1], gp->regs + MAC_HASH1);
-		writel(hash_table[2], gp->regs + MAC_HASH2);
-		writel(hash_table[3], gp->regs + MAC_HASH3);
-		writel(hash_table[4], gp->regs + MAC_HASH4);
-		writel(hash_table[5], gp->regs + MAC_HASH5);
-		writel(hash_table[6], gp->regs + MAC_HASH6);
-		writel(hash_table[7], gp->regs + MAC_HASH7);
-		writel(hash_table[8], gp->regs + MAC_HASH8);
-		writel(hash_table[9], gp->regs + MAC_HASH9);
-		writel(hash_table[10], gp->regs + MAC_HASH10);
-		writel(hash_table[11], gp->regs + MAC_HASH11);
-		writel(hash_table[12], gp->regs + MAC_HASH12);
-		writel(hash_table[13], gp->regs + MAC_HASH13);
-		writel(hash_table[14], gp->regs + MAC_HASH14);
-		writel(hash_table[15], gp->regs + MAC_HASH15);
-	}
+	rxcfg = gem_setup_multicast(gp);
 
 	writel(0, gp->regs + MAC_NCOLL);
 	writel(0, gp->regs + MAC_FASUCC);
@@ -2052,16 +2082,14 @@
 		schedule();
 	
 	/* Actually stop the chip */
-	if (gp->pdev->vendor == PCI_VENDOR_ID_APPLE)
+	if (gp->pdev->vendor == PCI_VENDOR_ID_APPLE) {
 		gem_stop_phy(gp);
-	else
-		gem_stop(gp);
-
 #ifdef CONFIG_ALL_PPC
-	/* Power down the chip */
-	if (gp->pdev->vendor == PCI_VENDOR_ID_APPLE)
+		/* Power down the chip */
 		gem_apple_powerdown(gp);
 #endif /* CONFIG_ALL_PPC */
+	} else
+		gem_stop(gp);
 }
 
 static void gem_pm_task(void *data)
@@ -2123,6 +2151,7 @@
 	 */
 	if (request_irq(gp->pdev->irq, gem_interrupt,
 			SA_SHIRQ, dev->name, (void *)dev)) {
+		printk(KERN_ERR "%s: failed to request irq !\n", gp->dev->name);
 #ifdef CONFIG_ALL_PPC
 		if (!hw_was_up && gp->pdev->vendor == PCI_VENDOR_ID_APPLE)
 			gem_apple_powerdown(gp);
@@ -2285,91 +2314,28 @@
 static void gem_set_multicast(struct net_device *dev)
 {
 	struct gem *gp = dev->priv;
-
+	u32 rxcfg, rxcfg_new;
+	int limit = 10000;
+	
 	if (!gp->hw_running)
 		return;
 		
 	netif_stop_queue(dev);
 
-	if ((gp->dev->flags & IFF_ALLMULTI) ||
-	    (gp->dev->mc_count > 256)) {
-		writel(0xffff, gp->regs + MAC_HASH0);
-		writel(0xffff, gp->regs + MAC_HASH1);
-		writel(0xffff, gp->regs + MAC_HASH2);
-		writel(0xffff, gp->regs + MAC_HASH3);
-		writel(0xffff, gp->regs + MAC_HASH4);
-		writel(0xffff, gp->regs + MAC_HASH5);
-		writel(0xffff, gp->regs + MAC_HASH6);
-		writel(0xffff, gp->regs + MAC_HASH7);
-		writel(0xffff, gp->regs + MAC_HASH8);
-		writel(0xffff, gp->regs + MAC_HASH9);
-		writel(0xffff, gp->regs + MAC_HASH10);
-		writel(0xffff, gp->regs + MAC_HASH11);
-		writel(0xffff, gp->regs + MAC_HASH12);
-		writel(0xffff, gp->regs + MAC_HASH13);
-		writel(0xffff, gp->regs + MAC_HASH14);
-		writel(0xffff, gp->regs + MAC_HASH15);
-	} else if (gp->dev->flags & IFF_PROMISC) {
-		u32 rxcfg = readl(gp->regs + MAC_RXCFG);
-		int limit = 10000;
-
-		writel(rxcfg & ~MAC_RXCFG_ENAB, gp->regs + MAC_RXCFG);
-		while (readl(gp->regs + MAC_RXCFG) & MAC_RXCFG_ENAB) {
-			if (!limit--)
-				break;
-			udelay(10);
-		}
-
-		rxcfg |= MAC_RXCFG_PROM;
-		writel(rxcfg, gp->regs + MAC_RXCFG);
-	} else {
-		u16 hash_table[16];
-		u32 crc, poly = CRC_POLYNOMIAL_LE;
-		struct dev_mc_list *dmi = gp->dev->mc_list;
-		int i, j, bit, byte;
-
-		for (i = 0; i < 16; i++)
-			hash_table[i] = 0;
-
-		for (i = 0; i < dev->mc_count; i++) {
-			char *addrs = dmi->dmi_addr;
-
-			dmi = dmi->next;
-
-			if (!(*addrs & 1))
-				continue;
+	rxcfg = readl(gp->regs + MAC_RXCFG);
+	rxcfg_new = gem_setup_multicast(gp);
+	
+	writel(rxcfg & ~MAC_RXCFG_ENAB, gp->regs + MAC_RXCFG);
+	while (readl(gp->regs + MAC_RXCFG) & MAC_RXCFG_ENAB) {
+		if (!limit--)
+			break;
+		udelay(10);
+	}
 
-			crc = 0xffffffffU;
-			for (byte = 0; byte < 6; byte++) {
-				for (bit = *addrs++, j = 0; j < 8; j++, bit >>= 1) {
-					int test;
+	rxcfg &= ~(MAC_RXCFG_PROM | MAC_RXCFG_HFE);
+	rxcfg |= rxcfg_new;
 
-					test = ((bit ^ crc) & 0x01);
-					crc >>= 1;
-					if (test)
-						crc = crc ^ poly;
-				}
-			}
-			crc >>= 24;
-			hash_table[crc >> 4] |= 1 << (crc & 0xf);
-		}
-		writel(hash_table[0], gp->regs + MAC_HASH0);
-		writel(hash_table[1], gp->regs + MAC_HASH1);
-		writel(hash_table[2], gp->regs + MAC_HASH2);
-		writel(hash_table[3], gp->regs + MAC_HASH3);
-		writel(hash_table[4], gp->regs + MAC_HASH4);
-		writel(hash_table[5], gp->regs + MAC_HASH5);
-		writel(hash_table[6], gp->regs + MAC_HASH6);
-		writel(hash_table[7], gp->regs + MAC_HASH7);
-		writel(hash_table[8], gp->regs + MAC_HASH8);
-		writel(hash_table[9], gp->regs + MAC_HASH9);
-		writel(hash_table[10], gp->regs + MAC_HASH10);
-		writel(hash_table[11], gp->regs + MAC_HASH11);
-		writel(hash_table[12], gp->regs + MAC_HASH12);
-		writel(hash_table[13], gp->regs + MAC_HASH13);
-		writel(hash_table[14], gp->regs + MAC_HASH14);
-		writel(hash_table[15], gp->regs + MAC_HASH15);
-	}
+	writel(rxcfg, gp->regs + MAC_RXCFG);
 
 	/* Hrm... we may walk on the reset task here... */
 	netif_wake_queue(dev);
@@ -2491,7 +2457,7 @@
 	case ETHTOOL_GMSGLVL: {
 		struct ethtool_value edata = { cmd: ETHTOOL_GMSGLVL };
 
-		edata.data = gem_debug;
+		edata.data = gp->msg_enable;
 		if (copy_to_user(ep_user, &edata, sizeof(edata)))
 			return -EFAULT;
 		return 0;
@@ -2503,7 +2469,7 @@
 
 		if (copy_from_user(&edata, ep_user, sizeof(edata)))
 			return -EFAULT;
-		gem_debug = edata.data;
+		gp->msg_enable = edata.data;
 		return 0;
 	}
 
@@ -2699,6 +2665,8 @@
 	dev->base_addr = (long) pdev;
 	gp->dev = dev;
 
+	gp->msg_enable = (gem_debug < 0 ? DEFAULT_MSG : gem_debug);
+
 	spin_lock_init(&gp->lock);
 	init_MUTEX(&gp->pm_sem);
 
@@ -2733,25 +2701,15 @@
 	 * not have properly shut down the PHY.
 	 */
 #ifdef CONFIG_ALL_PPC
-	if (pdev->vendor == PCI_VENDOR_ID_APPLE) {
+	if (pdev->vendor == PCI_VENDOR_ID_APPLE)
 		gem_apple_powerup(gp);
-		if (gem_check_invariants(gp))
-			goto err_out_iounmap;
-		gem_stop(gp);
-		gp->hw_running = 1;
-		gem_init_phy(gp);
-		gem_begin_auto_negotiation(gp, NULL);
-	}
 #endif
-	/* Non Apple hardware, we just reset the chip and check
-	 * for invariants
-	 */
-	if (pdev->vendor != PCI_VENDOR_ID_APPLE) {
-		gem_stop(gp);
-		if (gem_check_invariants(gp))
-			goto err_out_iounmap;
-		gp->hw_running = 1;
-	}
+	gem_stop(gp);
+	if (gem_check_invariants(gp))
+		goto err_out_iounmap;
+	gp->hw_running = 1;
+	gem_init_phy(gp);
+	gem_begin_auto_negotiation(gp, NULL);
 
 	/* It is guarenteed that the returned buffer will be at least
 	 * PAGE_SIZE aligned.
diff -urN linux-2.4.18-pre4/drivers/net/sungem.h linux/drivers/net/sungem.h
--- linux-2.4.18-pre4/drivers/net/sungem.h	Fri Dec 21 09:41:54 2001
+++ linux/drivers/net/sungem.h	Tue Jan 22 12:01:22 2002
@@ -1,4 +1,4 @@
-/* $Id: sungem.h,v 1.10 2001/11/29 03:57:33 davem Exp $
+/* $Id: sungem.h,v 1.10.2.1 2002/01/12 07:19:27 davem Exp $
  * sungem.h: Definitions for Sun GEM ethernet driver.
  *
  * Copyright (C) 2000 David S. Miller (davem@redhat.com)
@@ -972,6 +972,8 @@
 	struct sk_buff *rx_skbs[RX_RING_SIZE];
 	struct sk_buff *tx_skbs[RX_RING_SIZE];
 
+	u32			msg_enable;
+
 	struct net_device_stats net_stats;
 
 	enum gem_phy_type	phy_type;
@@ -995,8 +997,8 @@
 	volatile int		reset_task_pending;
 	
 	/* Diagnostic counters and state. */
-	u64 pause_entered;
-	u16 pause_last_time_recvd;
+	u64			pause_entered;
+	u16			pause_last_time_recvd;
 
 	dma_addr_t gblock_dvma;
 	struct pci_dev *pdev;
diff -urN linux-2.4.18-pre4/drivers/net/sunlance.c linux/drivers/net/sunlance.c
--- linux-2.4.18-pre4/drivers/net/sunlance.c	Tue Oct 30 15:08:11 2001
+++ linux/drivers/net/sunlance.c	Tue Jan 22 12:01:22 2002
@@ -1,4 +1,4 @@
-/* $Id: sunlance.c,v 1.109 2001/10/21 06:35:29 davem Exp $
+/* $Id: sunlance.c,v 1.109.2.1 2002/01/14 10:07:56 davem Exp $
  * lance.c: Linux/Sparc/Lance driver
  *
  *	Written 1995, 1996 by Miguel de Icaza
@@ -923,13 +923,13 @@
 
 	last_dev = dev;
 
+	STOP_LANCE(lp);
+
 	if (request_irq(dev->irq, &lance_interrupt, SA_SHIRQ,
 			lancestr, (void *) dev)) {
 		printk(KERN_ERR "Lance: Can't get irq %s\n", __irq_itoa(dev->irq));
 		return -EAGAIN;
 	}
-
-	STOP_LANCE(lp);
 
 	/* On the 4m, setup the ledma to provide the upper bits for buffers */
 	if (lp->dregs) {
diff -urN linux-2.4.18-pre4/drivers/net/wireless/airport.c linux/drivers/net/wireless/airport.c
--- linux-2.4.18-pre4/drivers/net/wireless/airport.c	Tue Jan 22 12:01:20 2002
+++ linux/drivers/net/wireless/airport.c	Tue Jan 22 12:01:22 2002
@@ -1,4 +1,4 @@
-/* airport.c 0.09
+/* airport.c 0.09b
  *
  * A driver for "Hermes" chipset based Apple Airport wireless
  * card.
@@ -42,7 +42,7 @@
 #include "hermes.h"
 #include "orinoco.h"
 
-static char version[] __initdata = "airport.c 0.09 (Benjamin Herrenschmidt <benh@kernel.crashing.org>)";
+static char version[] __initdata = "airport.c 0.09b (Benjamin Herrenschmidt <benh@kernel.crashing.org>)";
 MODULE_AUTHOR("Benjamin Herrenschmidt <benh@kernel.crashing.org>");
 MODULE_DESCRIPTION("Driver for the Apple Airport wireless card.");
 MODULE_LICENSE("Dual MPL/GPL");
@@ -70,7 +70,6 @@
 
 static struct orinoco_private* airport_attach(struct device_node *of_node);
 static void airport_detach(struct orinoco_private* priv);
-static int airport_init(struct net_device *dev);
 static int airport_open(struct net_device *dev);
 static int airport_stop(struct net_device *dev);
 
@@ -86,19 +85,6 @@
 
 static struct orinoco_private *airport_dev;
 
-static int airport_init(struct net_device *dev)
-{
-	int rc;
-	
-	MOD_INC_USE_COUNT;
-
-	rc = orinoco_init(dev);
-
-	MOD_DEC_USE_COUNT;
-
-	return rc;
-}
-
 static int
 airport_open(struct net_device *dev)
 {
@@ -223,8 +209,11 @@
 		return NULL;
 	}
 
+
+	ndev->name[0] = '\0';	/* register_netdev will give us an ethX name */
+	SET_MODULE_OWNER(ndev);
+
 	/* Overrides */
-	ndev->init = airport_init;
 	ndev->open = airport_open;
 	ndev->stop = airport_stop;
 
@@ -248,8 +237,6 @@
 	}
 	card->irq_requested = 1;
 	
-	/* register_netdev will give us an ethX name */
-	ndev->name[0] = '\0';
 	/* Tell the stack we exist */
 	if (register_netdev(ndev) != 0) {
 		printk(KERN_ERR "airport: register_netdev() failed\n");
@@ -257,8 +244,6 @@
 	}
 	printk(KERN_DEBUG "airport: card registered for interface %s\n", ndev->name);
 	card->ndev_registered = 1;
-
-	SET_MODULE_OWNER(ndev);
 
 	/* And give us the proc nodes for debugging */
 	if (orinoco_proc_dev_init(priv) != 0)
diff -urN linux-2.4.18-pre4/drivers/net/wireless/hermes.c linux/drivers/net/wireless/hermes.c
--- linux-2.4.18-pre4/drivers/net/wireless/hermes.c	Tue Jan 22 12:01:20 2002
+++ linux/drivers/net/wireless/hermes.c	Tue Jan 22 12:01:22 2002
@@ -53,10 +53,12 @@
 
 #include "hermes.h"
 
-static char version[] __initdata = "hermes.c: 3 Oct 2001 David Gibson <hermes@gibson.dropbear.id.au>";
+static char version[] __initdata = "hermes.c: 16 Jan 2002 David Gibson <hermes@gibson.dropbear.id.au>";
 MODULE_DESCRIPTION("Low-level driver helper for Lucent Hermes chipset and Prism II HFA384x wireless MAC controller");
 MODULE_AUTHOR("David Gibson <hermes@gibson.dropbear.id.au>");
+#ifdef MODULE_LICENSE
 MODULE_LICENSE("Dual MPL/GPL");
+#endif
 
 /* These are maximum timeouts. Most often, card wil react much faster */
 #define CMD_BUSY_TIMEOUT (100) /* In iterations of ~1us */
@@ -103,7 +105,7 @@
 
 	/* First wait for the command register to unbusy */
 	reg = hermes_read_regn(hw, CMD);
-	while ( (reg % HERMES_CMD_BUSY) && k ) {
+	while ( (reg & HERMES_CMD_BUSY) && k ) {
 		k--;
 		udelay(1);
 		reg = hermes_read_regn(hw, CMD);
diff -urN linux-2.4.18-pre4/drivers/net/wireless/hermes.h linux/drivers/net/wireless/hermes.h
--- linux-2.4.18-pre4/drivers/net/wireless/hermes.h	Tue Jan 22 12:01:20 2002
+++ linux/drivers/net/wireless/hermes.h	Tue Jan 22 12:01:22 2002
@@ -153,6 +153,11 @@
  * Frame structures and constants
  */
 
+#define HERMES_DESCRIPTOR_OFFSET	0
+#define HERMES_802_11_OFFSET		(14)
+#define HERMES_802_3_OFFSET		(14+32)
+#define HERMES_802_2_OFFSET		(14+32+14)
+
 struct hermes_rx_descriptor {
 	u16 status;
 	u32 time;
diff -urN linux-2.4.18-pre4/drivers/net/wireless/orinoco.c linux/drivers/net/wireless/orinoco.c
--- linux-2.4.18-pre4/drivers/net/wireless/orinoco.c	Tue Jan 22 12:01:20 2002
+++ linux/drivers/net/wireless/orinoco.c	Tue Jan 22 12:01:22 2002
@@ -1,4 +1,4 @@
-/* orinoco.c 0.09a	- (formerly known as dldwd_cs.c and orinoco_cs.c)
+/* orinoco.c 0.09b	- (formerly known as dldwd_cs.c and orinoco_cs.c)
  *
  * A driver for "Hermes" chipset based PCMCIA wireless adaptors, such
  * as the Lucent WavelanIEEE/Orinoco cards and their OEM (Cabletron/
@@ -226,10 +226,31 @@
  *	o Fixed stupid mistake in multicast list handling, triggering
  *	  a BUG()
  *
- * TODO - Jean II
- *	o inline functions (lots of candidate, need to reorder code)
- *	o Test PrismII/Symbol cards & firmware versions
- *	o Find and kill remaining Tx timeout problems */
+ * v0.09a -> v0.09b - 16/1/2002 - David Gibson
+ *	o Fixed even stupider mistake in new interrupt handling, which
+ *	  seriously broke things on big-endian machines.
+ *	o Removed a bunch of redundand includes and exports.
+ *	o Removed a redundant MOD_{INC,DEC}_USE_COUNT pair in airport.c
+ *	o Don't attempt to do hardware level multicast reception on
+ *	  Intersil firmware, just go promisc instead.
+ *	o Typo fixed in hermes_issue_cmd()
+ *	o Eliminated WIRELESS_SPY #ifdefs
+ *	o Status code reported on Tx exceptions
+ *	o Moved netif_wake_queue() from ALLOC interrupts to TX and TXEXC
+ *	  interrupts, which should fix the timeouts we're seeing.
+ *
+ * TODO
+ *	o Find and kill remaining Tx timeout problems
+ *	o Fix WEP / order of iwconfig wierdness on Intersil firmware
+ *	o Convert /proc debugging stuff to seqfile
+ *	o Re-assess our encapsulation detection strategy
+ *	o Handle de-encapsulation within NET framework, provide 802.11
+ *	  headers
+ *	o Fix possible races in SPY handling.
+ *	o Take the xmit lock when calling orinoco_reset from an
+ *	  ioctl(), because that protects the multicast list.
+ *	o Fix allocation lengths.
+ */
 /* Notes on locking:
  *
  * The basic principle of operation is that everything except the
@@ -244,10 +265,11 @@
  * that the Rx path uses one of the Hermes chipset's BAPs while
  * everything else uses the other.
  *
- * Actually, the current updating of the statistics from the interrupt
- * handler is unsafe.  However all it can do is perturb the
- * packet/byte counts slightly, so we just put up with it.  We could
- * fix this to use atomic types, but it's probably not worth it.
+ * Actually, strictly speaking, the updating of the statistics from
+ * the interrupt handler isn't safe without a lock.  However the worst
+ * that can happen is that we perturb the packet/byte counts slightly.
+ * We could fix this to use atomic types, but it's probably not worth
+ * it.
  *
  * The big exception is that that we don't want the irq handler
  * running when we actually reset or shut down the card, because
@@ -279,14 +301,6 @@
 #include <linux/wireless.h>
 #include <linux/list.h>
 
-#include <pcmcia/version.h>
-#include <pcmcia/cs_types.h>
-#include <pcmcia/cs.h>
-#include <pcmcia/cistpl.h>
-#include <pcmcia/cisreg.h>
-#include <pcmcia/ds.h>
-#include <pcmcia/bus_ops.h>
-
 #include "hermes.h"
 #include "hermes_rid.h"
 #include "orinoco.h"
@@ -297,10 +311,19 @@
 #define SIOCIWFIRSTPRIV		SIOCDEVPRIVATE
 #endif /* SIOCIWFIRSTPRIV */
 
-static char version[] __initdata = "orinoco.c 0.09a (David Gibson <hermes@gibson.dropbear.id.au> and others)";
+/* We do this this way to avoid ifdefs in the actual code */
+#ifdef WIRELESS_SPY
+#define SPY_NUMBER(priv)	(priv->spy_number)
+#else
+#define SPY_NUMBER(priv)	0
+#endif /* WIRELESS_SPY */
+
+static char version[] __initdata = "orinoco.c 0.09b (David Gibson <hermes@gibson.dropbear.id.au> and others)";
 MODULE_AUTHOR("David Gibson <hermes@gibson.dropbear.id.au>");
 MODULE_DESCRIPTION("Driver for Lucent Orinoco, Prism II based and similar wireless cards");
+#ifdef MODULE_LICENSE
 MODULE_LICENSE("Dual MPL/GPL");
+#endif
 
 /* Level of debugging. Used in the macros in orinoco.h */
 #ifdef ORINOCO_DEBUG
@@ -327,6 +350,14 @@
 
 #define DUMMY_FID		0xFFFF
 
+#define MAX_MULTICAST(priv)	(priv->firmware_type == FIRMWARE_TYPE_AGERE ? \
+				 HERMES_MAX_MULTICAST : 0)
+
+/*
+ * Data tables
+ */
+
+/* The frequency of each channel in MHz */
 const long channel_frequency[] = {
 	2412, 2417, 2422, 2427, 2432, 2437, 2442,
 	2447, 2452, 2457, 2462, 2467, 2472, 2484
@@ -334,8 +365,7 @@
 
 #define NUM_CHANNELS ( sizeof(channel_frequency) / sizeof(channel_frequency[0]) )
 
-/* This tables gives the actual meanings of the bitrate IDs returned by the firmware.
-   It gives the rate in halfMb/s, negative indicates auto mode */
+/* This tables gives the actual meanings of the bitrate IDs returned by the firmware. */
 struct {
 	int bitrate; /* in 100s of kilbits */
 	int automatic;
@@ -386,9 +416,6 @@
 	0xaa, 0xaa, 0x03, {0x00, 0x00, 0x00}
 };
 
-/* How many times to retry if we get an EIO reading the BAP in the Rx path */
-#define RX_EIO_RETRY		10
-
 typedef struct orinoco_commsqual {
 	u16 qual, signal, noise;
 } __attribute__ ((packed)) orinoco_commsqual_t;
@@ -1017,6 +1044,7 @@
 	return 0;
 }
 
+#if 0
 #ifndef ORINOCO_DEBUG
 static inline void show_rx_frame(struct orinoco_rxframe_hdr *frame) {}
 #else
@@ -1077,6 +1105,7 @@
 	printk(KERN_DEBUG "  ethertype  = 0x%04x\n", frame->ethertype);
 }
 #endif
+#endif
 
 /*
  * Interrupt handler
@@ -1109,7 +1138,7 @@
 	
 	if (! events) { /* Sometimes the card generates Tx interrupts without setting EVSTAT,
 			   or so I've heard - FIXME does it really happen? */
-		printk(KERN_WARNING "%s: NULL event in orinoco_interrupt!\n", priv->ndev.name);
+		printk(KERN_WARNING "%s: Null event in orinoco_interrupt!\n", priv->ndev.name);
 		__orinoco_ev_alloc(priv, hw);
 	}
 
@@ -1260,7 +1289,6 @@
 	struct net_device_stats *stats = &priv->stats;
 	struct iw_statistics *wstats = &priv->wstats;
 	struct sk_buff *skb = NULL;
-	int l = RX_EIO_RETRY;
 	u16 rxfid, status;
 	int length, data_len, data_off;
 	char *p;
@@ -1275,16 +1303,10 @@
 	   necessary, since we ignore most of it, but it's
 	   conceptually simpler. We can tune this later if
 	   necessary. */
-	do {
-		err = hermes_bap_pread(hw, IRQ_BAP, &hdr, sizeof(hdr),
-				       rxfid, 0);
-	} while ( (err == -EIO) && (--l) );
+	err = hermes_bap_pread(hw, IRQ_BAP, &hdr, sizeof(hdr), rxfid, 0);
 	if (err) {
-		if (err == -EIO)
-			DEBUG(1, "%s: EIO reading frame header.\n", dev->name);
-		else
-			printk(KERN_ERR "%s: error %d reading frame header. "
-			       "Frame dropped.\n", dev->name, err);
+		printk(KERN_ERR "%s: error %d reading frame header. "
+		       "Frame dropped.\n", dev->name, err);
 		stats->rx_errors++;
 		goto drop;
 	}
@@ -1374,10 +1396,8 @@
 	}
 
 	p = skb_put(skb, data_len);
-	do {
-		err = hermes_bap_pread(hw, IRQ_BAP, p, RUP_EVEN(data_len),
-				       rxfid, data_off);
-	} while ( (err == -EIO) && (--l) );
+	err = hermes_bap_pread(hw, IRQ_BAP, p, RUP_EVEN(data_len),
+			       rxfid, data_off);
 	if (err) {
 		if (err == -EIO)
 			DEBUG(1, "%s: EIO reading frame header.\n", dev->name);
@@ -1414,24 +1434,43 @@
 	struct net_device *dev = &priv->ndev;
 	struct net_device_stats *stats = &priv->stats;
 	u16 fid = hermes_read_regn(hw, TXCOMPLFID);
+	struct hermes_tx_descriptor desc;
+	int err = 0;
 
-	if (fid != DUMMY_FID) {
-		printk(KERN_INFO "%s: Tx error (FID=%04X)!\n", dev->name, fid);
-		stats->tx_errors++;
-		stats->tx_packets--; /* Reverse the increment done in _ev_alloc */
+	if (fid == DUMMY_FID)
+		return; /* Nothing's really happened */
+
+	err = hermes_bap_pread(hw, USER_BAP, &desc, sizeof(desc), fid, 0);
+	if (err) {
+		printk(KERN_WARNING "%s: Unable to read descriptor on Tx error "
+		       "(FID=%04X error %d)\n",
+		       dev->name, fid, err);
+	} else {
+		printk(KERN_INFO "%s: Tx error, status %d (FID=%04X)\n",
+		       dev->name, le16_to_cpu(desc.status), fid);
 	}
+	
+	stats->tx_errors++;
+	netif_wake_queue(dev);
 
 	hermes_write_regn(hw, TXCOMPLFID, DUMMY_FID);
 }
 
 static void __orinoco_ev_tx(struct orinoco_private *priv, hermes_t *hw)
 {
+	struct net_device *dev = &priv->ndev;
+	struct net_device_stats *stats = &priv->stats;
+/*  	u16 fid = hermes_read_regn(hw, TXCOMPLFID); */
+
 	/* We don't generally use the Tx event (to cut down on
 	   interrupts) - we do the transmit complet processing once
 	   the transmit buffer is reclaimed in __orinoco_ev_alloc() ,
 	   hence nothing here */
 
-	DEBUG(2, "%s: Transmit completed (FID=%04X)\n", priv->ndev.name, fid);
+/*  	DEBUG(2, "%s: Transmit completed (FID=%04X)\n", priv->ndev.name, fid); */
+
+	stats->tx_packets++;
+	netif_wake_queue(dev);
 
 	hermes_write_regn(hw, TXCOMPLFID, DUMMY_FID);
 }
@@ -1439,7 +1478,6 @@
 static void __orinoco_ev_alloc(struct orinoco_private *priv, hermes_t *hw)
 {
 	struct net_device *dev = &priv->ndev;
-	struct net_device_stats *stats = &priv->stats;
 	u16 fid = hermes_read_regn(hw, ALLOCFID);
 
 	DEBUG(3, "%s: Allocation complete FID=0x%04x\n", priv->ndev.name, fid);
@@ -1450,12 +1488,11 @@
 	   with the transmit buffer */
 
 	if (fid != priv->txfid) {
-		printk(KERN_WARNING "%s: Allocate event on unexpected fid (%04X)\n",
-		      dev->name, fid);
+		if (fid != DUMMY_FID)
+			printk(KERN_WARNING "%s: Allocate event on unexpected fid (%04X)\n",
+			       dev->name, fid);
 		return;
 	}
-	stats->tx_packets++;
-	netif_wake_queue(dev);
 
 	hermes_write_regn(hw, ALLOCFID, DUMMY_FID);
 }
@@ -1774,16 +1811,14 @@
 
 	if (priv->iw_mode == IW_MODE_ADHOC) {
 		memset(&wstats->qual, 0, sizeof(wstats->qual));
-#ifdef WIRELESS_SPY
 		/* If a spy address is defined, we report stats of the
 		 * first spy address - Jean II */
-		if (priv->spy_number > 0) {
+		if (SPY_NUMBER(priv)) {
 			wstats->qual.qual = priv->spy_stat[0].qual;
 			wstats->qual.level = priv->spy_stat[0].level;
 			wstats->qual.noise = priv->spy_stat[0].noise;
 			wstats->qual.updated = priv->spy_stat[0].updated;
 		}
-#endif /* WIRELESS_SPY */
 	} else {
 		orinoco_commsqual_t cq;
 
@@ -1802,8 +1837,8 @@
 	/* We can't really wait for the tallies inquiry command to
 	 * complete, so we just use the previous results and trigger
 	 * a new tallies inquiry command for next time - Jean II */
-	/* Hmm.. seems a bit ugly, I wonder if there's a way to do
-	   better - dgibson */
+	/* FIXME: Hmm.. seems a bit ugly, I wonder if there's a way to
+	   do better - dgibson */
 	err = hermes_inquire(hw, HERMES_INQ_TALLIES);
                
 	orinoco_unlock(priv);
@@ -1814,7 +1849,6 @@
 	return wstats;
 }
 
-#ifdef WIRELESS_SPY
 static inline void orinoco_spy_gather(struct net_device *dev, u_char *mac,
 				    int level, int noise)
 {
@@ -1831,7 +1865,6 @@
 			priv->spy_stat[i].updated = 7;
 		}
 }
-#endif /* WIRELESS_SPY */
 
 void
 orinoco_stat_gather( struct net_device *dev,
@@ -1848,14 +1881,12 @@
 	 * Note that to get here, you need both WIRELESS_SPY
 	 * compiled in AND some addresses in the list !!!
 	 */
-#ifdef WIRELESS_SPY
 	/* Note : gcc will optimise the whole section away if
 	 * WIRELESS_SPY is not defined... - Jean II */
-	if (priv->spy_number > 0) {
+	if (SPY_NUMBER(priv)) {
 		orinoco_spy_gather(dev, skb->mac.raw + ETH_ALEN,
 				   hdr->desc.signal, hdr->desc.silence);
 	}
-#endif /* WIRELESS_SPY */
 }
 
 int
@@ -1888,6 +1919,7 @@
 	orinoco_lock(priv);
 
 	/* Length of the packet body */
+	/* FIXME: what if the skb is smaller than this? */
 	len = max_t(int,skb->len - ETH_HLEN, ETH_ZLEN);
 
 	eh = (struct ethhdr *)skb->data;
@@ -1900,7 +1932,7 @@
 
 	/* Request an interrupt on Tx failures, but not sucesses (we
            use the buffer reclaim allocation event instead */
-	hdr.desc.tx_control = HERMES_TXCTRL_TX_EX;
+	hdr.desc.tx_control = cpu_to_le16(HERMES_TXCTRL_TX_EX | HERMES_TXCTRL_TX_OK);
 
 	/* Encapsulate Ethernet-II frames */
 	if (ntohs(eh->h_proto) > 1500) { /* Ethernet-II frame */
@@ -1923,15 +1955,6 @@
 		err  = hermes_bap_pwrite(hw, USER_BAP, &hdr, sizeof(hdr),
 					 txfid, 0);
 		if (err) {
-#if 0
-			if (err == -EIO)
-				/* We get these errors reported by the
-				   firmware every so often apparently at
-				   random.  Let the upper layers
-				   handle the retry */
-				DEBUG(1, "%s: DEBUG: EIO writing packet header to BAP\n", dev->name);
-			else
-#endif
 				printk(KERN_ERR "%s: Error %d writing packet header to BAP\n",
 				       dev->name, err);
 			stats->tx_errors++;
@@ -1958,11 +1981,8 @@
 	/* Round up for odd length packets */
 	err = hermes_bap_pwrite(hw, USER_BAP, p, RUP_EVEN(data_len), txfid, data_off);
 	if (err) {
-/*  		if (err == -EIO) */
-/*  			DEBUG(1, "%s: DEBUG: EIO writing packet header to BAP\n", dev->name); */
-/*  		else */
-			printk(KERN_ERR "%s: Error %d writing packet header to BAP\n",
-			       dev->name, err);
+		printk(KERN_ERR "%s: Error %d writing packet header to BAP\n",
+		       dev->name, err);
 		stats->tx_errors++;
 		goto fail;
 	}
@@ -1975,6 +1995,7 @@
 		goto fail;
 	}
 
+	atomic_inc(&priv->queue_length);
 	dev->trans_start = jiffies;
 	stats->tx_bytes += data_off + data_len;
 
@@ -3386,13 +3407,10 @@
 
 	TRACE_ENTER(dev->name);
 
-	DEBUG(3, "dev->flags=0x%x, priv->promiscuous=%d, dev->mc_count=%d priv->mc_count=%d\n",
-	      dev->flags, priv->promiscuous, dev->mc_count, priv->mc_count);
-
 	/* The Hermes doesn't seem to have an allmulti mode, so we go
 	 * into promiscuous mode and let the upper levels deal. */
 	if ( (dev->flags & IFF_PROMISC) || (dev->flags & IFF_ALLMULTI) ||
-	     (dev->mc_count > HERMES_MAX_MULTICAST) ) {
+	     (dev->mc_count > MAX_MULTICAST(priv)) ) {
 		promisc = 1;
 		mc_count = 0;
 	} else {
@@ -3429,11 +3447,9 @@
 			p = p->next;
 		}
 		
-		/* More paranoia */
-		if (p != dev->mc_list) {
-			printk(KERN_ERR "Multicast list is longer than mc_count\n");
-		}
-		
+		if (p)
+			printk(KERN_WARNING "Multicast list is longer than mc_count\n");
+
 		err = hermes_write_ltv(hw, USER_BAP, HERMES_RID_CNFGROUPADDRESSES,
 				       HERMES_BYTES_TO_RECLEN(priv->mc_count * ETH_ALEN),
 				       &mclist);
@@ -3925,12 +3941,6 @@
 #ifdef ORINOCO_DEBUG
 EXPORT_SYMBOL(orinoco_debug);
 #endif
-EXPORT_SYMBOL(orinoco_init);
-EXPORT_SYMBOL(orinoco_xmit);
-EXPORT_SYMBOL(orinoco_tx_timeout);
-EXPORT_SYMBOL(orinoco_ioctl);
-EXPORT_SYMBOL(orinoco_change_mtu);
-EXPORT_SYMBOL(orinoco_set_multicast_list);
 EXPORT_SYMBOL(orinoco_shutdown);
 EXPORT_SYMBOL(orinoco_reset);
 EXPORT_SYMBOL(orinoco_setup);
diff -urN linux-2.4.18-pre4/drivers/net/wireless/orinoco.h linux/drivers/net/wireless/orinoco.h
--- linux-2.4.18-pre4/drivers/net/wireless/orinoco.h	Tue Jan 22 12:01:20 2002
+++ linux/drivers/net/wireless/orinoco.h	Tue Jan 22 12:01:22 2002
@@ -8,7 +8,7 @@
 #define _ORINOCO_H
 
 /* To enable debug messages */
-// #define ORINOCO_DEBUG		3
+//#define ORINOCO_DEBUG		3
 
 #if (! defined (WIRELESS_EXT)) || (WIRELESS_EXT < 10)
 #error "orinoco driver requires Wireless extensions v10 or later."
@@ -36,12 +36,12 @@
 	long state;
 #define ORINOCO_STATE_INIRQ 0
 #define ORINOCO_STATE_DOIRQ 1
+	atomic_t queue_length;
 
 	/* Net device stuff */
 	struct net_device ndev;
 	struct net_device_stats stats;
 	struct iw_statistics wstats;
-
 
 	/* Hardware control variables */
 	hermes_t hw;
diff -urN linux-2.4.18-pre4/drivers/net/wireless/orinoco_cs.c linux/drivers/net/wireless/orinoco_cs.c
--- linux-2.4.18-pre4/drivers/net/wireless/orinoco_cs.c	Tue Jan 22 12:01:20 2002
+++ linux/drivers/net/wireless/orinoco_cs.c	Tue Jan 22 12:01:22 2002
@@ -1,4 +1,4 @@
-/* orinoco_cs.c 0.09	- (formerly known as dldwd_cs.c)
+/* orinoco_cs.c 0.09b	- (formerly known as dldwd_cs.c)
  *
  * A driver for "Hermes" chipset based PCMCIA wireless adaptors, such
  * as the Lucent WavelanIEEE/Orinoco cards and their OEM (Cabletron/
@@ -44,11 +44,13 @@
 
 /*====================================================================*/
 
-static char version[] __initdata = "orinoco_cs.c 0.09 (David Gibson <hermes@gibson.dropbear.id.au> and others)";
+static char version[] __initdata = "orinoco_cs.c 0.09b (David Gibson <hermes@gibson.dropbear.id.au> and others)";
 
 MODULE_AUTHOR("David Gibson <hermes@gibson.dropbear.id.au>");
 MODULE_DESCRIPTION("Driver for PCMCIA Lucent Orinoco, Prism II based and similar wireless cards");
+#ifdef MODULE_LICENSE
 MODULE_LICENSE("Dual MPL/GPL");
+#endif
 
 /* Parameters that can be set with 'insmod' */
 
diff -urN linux-2.4.18-pre4/drivers/net/wireless/orinoco_plx.c linux/drivers/net/wireless/orinoco_plx.c
--- linux-2.4.18-pre4/drivers/net/wireless/orinoco_plx.c	Tue Jan 22 12:01:20 2002
+++ linux/drivers/net/wireless/orinoco_plx.c	Tue Jan 22 12:01:22 2002
@@ -1,4 +1,4 @@
-/* orinoco_plx.c 0.09
+/* orinoco_plx.c 0.09b
  * 
  * Driver for Prism II devices which would usually be driven by orinoco_cs,
  * but are connected to the PCI bus by a PLX9052. 
@@ -140,12 +140,12 @@
 #include "hermes.h"
 #include "orinoco.h"
 
-static char version[] __initdata = "orinoco_plx.c 0.09 (Daniel Barlow <dan@telent.net>)";
+static char version[] __initdata = "orinoco_plx.c 0.09b (Daniel Barlow <dan@telent.net>)";
 MODULE_AUTHOR("Daniel Barlow <dan@telent.net>");
 MODULE_DESCRIPTION("Driver for wireless LAN cards using the PLX9052 PCI bridge");
+#ifdef MODULE_LICENSE
 MODULE_LICENSE("Dual MPL/GPL");
-
-
+#endif
 
 static dev_info_t dev_info = "orinoco_plx";
 
diff -urN linux-2.4.18-pre4/drivers/sbus/char/envctrl.c linux/drivers/sbus/char/envctrl.c
--- linux-2.4.18-pre4/drivers/sbus/char/envctrl.c	Wed Oct 10 23:42:47 2001
+++ linux/drivers/sbus/char/envctrl.c	Tue Jan 22 12:01:22 2002
@@ -1,4 +1,4 @@
-/* $Id: envctrl.c,v 1.24 2001/10/08 22:19:51 davem Exp $
+/* $Id: envctrl.c,v 1.24.2.1 2002/01/15 09:01:39 davem Exp $
  * envctrl.c: Temperature and Fan monitoring on Machines providing it.
  *
  * Copyright (C) 1998  Eddie C. Dost  (ecd@skynet.be)
@@ -776,24 +776,19 @@
 static void envctrl_init_adc(struct i2c_child_t *pchild, int node)
 {
 	char chnls_desc[CHANNEL_DESC_SZ];
-	int i, len, j = 0;
-	char *ptr;
+	int i = 0, len;
+	char *pos = chnls_desc;
 
-	/* Firmware describe channels into a stream separated by a '\0'.
-	 * Replace all '\0' with a space.
-	 */
-        len = prom_getproperty(node, "channels-description", chnls_desc,
+	/* Firmware describe channels into a stream separated by a '\0'. */
+	len = prom_getproperty(node, "channels-description", chnls_desc,
 			       CHANNEL_DESC_SZ);
-        for (i = 0; i < len; i++) {
-                if (chnls_desc[i] == '\0')
-                        chnls_desc[i] = ' ';
-        }
-
-	ptr = strtok(chnls_desc, " ");
-	while (ptr != NULL) {
-		envctrl_set_mon(pchild, ptr, j);
-		ptr = strtok(NULL, " ");
-		j++;
+	chnls_desc[CHANNEL_DESC_SZ - 1] = '\0';
+
+	while (len > 0) {
+		int l = strlen(pos) + 1;
+		envctrl_set_mon(pchild, pos, i++);
+		len -= l;
+		pos += l;
 	}
 
 	/* Get optional properties. */
diff -urN linux-2.4.18-pre4/drivers/sbus/char/riowatchdog.c linux/drivers/sbus/char/riowatchdog.c
--- linux-2.4.18-pre4/drivers/sbus/char/riowatchdog.c	Wed Oct 10 23:42:47 2001
+++ linux/drivers/sbus/char/riowatchdog.c	Tue Jan 22 12:01:22 2002
@@ -127,7 +127,9 @@
 static int riowd_ioctl(struct inode *inode, struct file *filp,
 		       unsigned int cmd, unsigned long arg)
 {
-	static struct watchdog_info info = { 0, 0, "Natl. Semiconductor PC97317" };
+	static struct watchdog_info info = {
+	       	WDIOF_SETTIMEOUT, 0, "Natl. Semiconductor PC97317"
+	};
 	unsigned int options;
 
 	switch (cmd) {
@@ -158,6 +160,18 @@
 			return -EINVAL;
 
 		break;
+
+	case WDIOC_SETTIMEOUT:
+		if (get_user(new_margin, (int *)arg))
+			return -EFAULT;
+		if ((new_margin < 60) || (new_margin > (255 * 60)))
+		    return -EINVAL;
+		riowd_timeout = (new_margin + 59) / 60;
+		riowd_pingtimer();
+		/* Fall */
+
+	case WDIOC_GETTIMEOUT:
+		return put_user(riowd_timeout * 60, (int *)arg);
 
 	default:
 		return -EINVAL;
diff -urN linux-2.4.18-pre4/drivers/sbus/char/zs.c linux/drivers/sbus/char/zs.c
--- linux-2.4.18-pre4/drivers/sbus/char/zs.c	Tue Jan 22 12:01:20 2002
+++ linux/drivers/sbus/char/zs.c	Tue Jan 22 12:01:22 2002
@@ -1,4 +1,4 @@
-/* $Id: zs.c,v 1.68.2.1 2002/01/04 21:12:09 davem Exp $
+/* $Id: zs.c,v 1.68.2.2 2002/01/12 07:04:33 davem Exp $
  * zs.c: Zilog serial port driver for the Sparc.
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -7,6 +7,10 @@
  *
  * Fixed to use tty_get_baud_rate().
  *   Theodore Ts'o <tytso@mit.edu>, 2001-Oct-12
+ *
+ * /proc/tty/driver/serial now exists and is readable.
+ *   Alex Buell <alex.buell@tahallah.demon.co.uk>, 2001-12-23
+ *
  */
 
 #include <linux/errno.h>
@@ -1655,6 +1659,81 @@
 }
 
 /*
+ *
+ * line_info - returns information about each channel
+ *
+ */
+static inline int line_info(char *buf, struct sun_serial *info)
+{
+	unsigned char status;
+	char stat_buf[30];
+	int ret;
+
+	ret = sprintf(buf, "%d: uart:Zilog8530 port:%x irq:%d",
+		info->line, info->port, info->irq);
+
+	cli();
+	status = sbus_readb(&info->zs_channel->control);
+	ZSDELAY();
+	ZSLOG(REGCTRL, status, 0);
+	sti();
+
+	stat_buf[0] = 0;
+	stat_buf[1] = 0;
+	if (info->curregs[5] & RTS)
+		strcat(stat_buf, "|RTS");
+	if (status & CTS)
+		strcat(stat_buf, "|CTS");
+	if (info->curregs[5] & DTR)
+		strcat(stat_buf, "|DTR");
+	if (status & SYNC)
+		strcat(stat_buf, "|DSR");
+	if (status & DCD)
+		strcat(stat_buf, "|CD");
+
+	ret += sprintf(buf + ret, " baud:%d %s\n", info->zs_baud, stat_buf + 1);
+	return ret;
+}
+
+/*
+ *
+ * zs_read_proc() - called when /proc/tty/driver/serial is read.
+ *
+ */
+int zs_read_proc(char *page, char **start, off_t off, int count,
+                 int *eof, void *data)
+{
+	char *revision = "$Revision: 1.68.2.2 $";
+	char *version, *p;
+	int i, len = 0, l;
+	off_t begin = 0;
+
+	version = strchr(revision, ' ');
+	p = strchr(++version, ' ');
+	*p = '\0';
+	len += sprintf(page, "serinfo:1.0 driver:%s\n", version);
+	*p = ' ';
+
+	for (i = 0; i < NUM_CHANNELS && len < 4000; i++) {
+		l = line_info(page + len, &zs_soft[i]);
+		len += l;
+		if (len+begin > off+count)
+			goto done;
+		if (len+begin < off) {
+			begin += len;
+			len = 0;
+		}
+	}
+
+	*eof = 1;
+done:
+	if (off >= len+begin)
+		return 0;
+	*start = page + (off-begin);
+	return ((count < begin+len-off) ? count : begin+len-off);
+}
+
+/*
  * ------------------------------------------------------------
  * zs_open() and friends
  * ------------------------------------------------------------
@@ -1889,7 +1968,7 @@
 
 static void show_serial_version(void)
 {
-	char *revision = "$Revision: 1.68.2.1 $";
+	char *revision = "$Revision: 1.68.2.2 $";
 	char *version, *p;
 
 	version = strchr(revision, ' ');
@@ -2400,8 +2479,8 @@
 	serial_driver.hangup = zs_hangup;
 
 	/* I'm too lazy, someone write versions of this for us. -DaveM */
-	serial_driver.read_proc = 0;
-	serial_driver.proc_entry = 0;
+	/* I just did. :-) -AIB 2001-12-23 */
+	serial_driver.read_proc = zs_read_proc;
 
 	/*
 	 * The callout device is just like normal device except for
@@ -2411,6 +2490,8 @@
 	callout_driver.name = "cua/%d";
 	callout_driver.major = TTYAUX_MAJOR;
 	callout_driver.subtype = SERIAL_TYPE_CALLOUT;
+	callout_driver.read_proc = 0;
+	callout_driver.proc_entry = 0;
 
 	if (tty_register_driver(&serial_driver))
 		panic("Couldn't register serial driver\n");
diff -urN linux-2.4.18-pre4/drivers/sound/cs4281/cs4281_wrapper.h linux/drivers/sound/cs4281/cs4281_wrapper.h
--- linux-2.4.18-pre4/drivers/sound/cs4281/cs4281_wrapper.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/sound/cs4281/cs4281_wrapper.h	Tue Jan 22 12:01:22 2002
@@ -0,0 +1,54 @@
+/*******************************************************************************
+*
+*      "cs4281_wrapper.h" --  Cirrus Logic-Crystal CS4281 linux audio driver.
+*
+*      Copyright (C) 2000,2001  Cirrus Logic Corp.  
+*            -- tom woller (twoller@crystal.cirrus.com) or
+*               (audio@crystal.cirrus.com).
+*
+*      This program is free software; you can redistribute it and/or modify
+*      it under the terms of the GNU General Public License as published by
+*      the Free Software Foundation; either version 2 of the License, or
+*      (at your option) any later version.
+*
+*      This program is distributed in the hope that it will be useful,
+*      but WITHOUT ANY WARRANTY; without even the implied warranty of
+*      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+*      GNU General Public License for more details.
+*
+*      You should have received a copy of the GNU General Public License
+*      along with this program; if not, write to the Free Software
+*      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+* 12/22/00 trw - new file. 
+* 04/18/01 trw - rework entire wrapper logic.
+*
+*******************************************************************************/
+#ifndef __CS4281_WRAPPER_H
+#define __CS4281_WRAPPER_H
+
+/* 2.4.x wrapper */
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,4,12)
+static int cs4281_null_suspend(struct pci_dev *pcidev, u32 unused) { return 0; }
+static int cs4281_null_resume(struct pci_dev *pcidev) { return 0; }
+#else
+#define no_llseek cs4281_llseek
+static loff_t cs4281_llseek(struct file *file, loff_t offset, int origin)
+{
+	return -ESPIPE;
+}
+void cs4281_null_suspend(struct pci_dev *pcidev) { return; }
+void cs4281_null_resume(struct pci_dev *pcidev) { return; }
+#endif
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,3)
+/* Some versions of 2.4.2 resolve pci_set_dma_mask and some do not... 
+*  but 2.4.0 definitely does not 
+*/
+#define pci_set_dma_mask(dev,data) 0;
+#else
+#endif
+#define cs4x_mem_map_reserve(page) mem_map_reserve(page)
+#define cs4x_mem_map_unreserve(page) mem_map_unreserve(page)
+
+#endif /* #ifndef __CS4281_WRAPPER_H */
diff -urN linux-2.4.18-pre4/drivers/sound/emu10k1/audio.c linux/drivers/sound/emu10k1/audio.c
--- linux-2.4.18-pre4/drivers/sound/emu10k1/audio.c	Tue Oct  9 10:53:17 2001
+++ linux/drivers/sound/emu10k1/audio.c	Tue Jan 22 12:01:22 2002
@@ -983,11 +983,11 @@
 	unsigned long pgoff;
 	int rd, wr;
 
-	DPF(4, "emu10k1_mm_nopage()\n");
-	DPD(4, "addr: %#lx\n", address);
+	DPF(3, "emu10k1_mm_nopage()\n");
+	DPD(3, "addr: %#lx\n", address);
 
 	if (address > vma->vm_end) {
-		DPF(2, "EXIT, returning NOPAGE_SIGBUS\n");
+		DPF(1, "EXIT, returning NOPAGE_SIGBUS\n");
 		return NOPAGE_SIGBUS; /* Disallow mremap */
 	}
 
@@ -1009,14 +1009,14 @@
 			pgoff -= woinst->buffer.pages;
 			dmapage = virt_to_page ((u8 *) wiinst->buffer.addr + pgoff * PAGE_SIZE);
 		} else
-			dmapage = virt_to_page (woinst->buffer.mem[0].addr[pgoff]);
+			dmapage = virt_to_page (woinst->voice[0].mem.addr[pgoff]);
 	} else {
 		dmapage = virt_to_page ((u8 *) wiinst->buffer.addr + pgoff * PAGE_SIZE);
 	}
 
 	get_page (dmapage);
 
-	DPD(4, "page: %#lx\n", dmapage);
+	DPD(3, "page: %#lx\n", (unsigned long) dmapage);
 	return dmapage;
 }
 
@@ -1083,8 +1083,8 @@
 	n_pages = ((vma->vm_end - vma->vm_start) + PAGE_SIZE - 1) >> PAGE_SHIFT;
 	pgoffset = vma->vm_pgoff;
 
-	DPD(3, "vma_start: %#lx, vma_end: %#lx, vma_offset: %d\n", vma->vm_start, vma->vm_end, pgoffset);
-	DPD(3, "n_pages: %d, max_pages: %d\n", n_pages, max_pages);
+	DPD(2, "vma_start: %#lx, vma_end: %#lx, vma_offset: %ld\n", vma->vm_start, vma->vm_end, pgoffset);
+	DPD(2, "n_pages: %ld, max_pages: %ld\n", n_pages, max_pages);
 
 	if (pgoffset + n_pages > max_pages)
 		return -EINVAL;
@@ -1092,7 +1092,6 @@
 	vma->vm_flags |= VM_RESERVED;
 	vma->vm_ops = &emu10k1_mm_ops;
 	vma->vm_private_data = wave_dev;
-
 	return 0;
 }
 
@@ -1211,7 +1210,7 @@
 		woinst->num_voices = 1;
 		for (i = 0; i < WAVEOUT_MAXVOICES; i++) {
 			woinst->voice[i].usage = VOICE_USAGE_FREE;
-			woinst->buffer.mem[i].emupageindex = -1;
+			woinst->voice[i].mem.emupageindex = -1;
 		}
 
 		init_waitqueue_head(&woinst->wait_queue);
@@ -1330,23 +1329,13 @@
 	if (file->f_mode & FMODE_READ) {
 		spin_lock_irqsave(&wiinst->lock, flags);
 
-		if (wiinst->state == WAVE_STATE_CLOSED) {
-			calculate_ifrag(wiinst);
-			if (emu10k1_wavein_open(wave_dev) < 0) {
-				spin_unlock_irqrestore(&wiinst->lock, flags);
-				return (mask |= POLLERR);
-			}
-		}
+		if (wiinst->state & WAVE_STATE_OPEN) {
+			emu10k1_wavein_update(wave_dev->card, wiinst);
+			emu10k1_wavein_getxfersize(wiinst, &bytestocopy);
 
-		if (!(wiinst->state & WAVE_STATE_STARTED)) {
-			wave_dev->enablebits |= PCM_ENABLE_INPUT;
-			emu10k1_wavein_start(wave_dev);
+			if (bytestocopy >= wiinst->buffer.fragment_size)
+				mask |= POLLIN | POLLRDNORM;
 		}
-		emu10k1_wavein_update(wave_dev->card, wiinst);
-		emu10k1_wavein_getxfersize(wiinst, &bytestocopy);
-
-		if (bytestocopy >= wiinst->buffer.fragment_size)
-			mask |= POLLIN | POLLRDNORM;
 
 		spin_unlock_irqrestore(&wiinst->lock, flags);
 	}
diff -urN linux-2.4.18-pre4/drivers/sound/emu10k1/audio.h linux/drivers/sound/emu10k1/audio.h
--- linux-2.4.18-pre4/drivers/sound/emu10k1/audio.h	Mon Aug 14 08:32:48 2000
+++ linux/drivers/sound/emu10k1/audio.h	Tue Jan 22 12:01:22 2002
@@ -33,7 +33,7 @@
 #ifndef _AUDIO_H
 #define _AUDIO_H
 
-#define MINFRAGS	2	/* _don't_ got bellow 2 */
+#define MINFRAGS	3	/* _don't_ go bellow 3 */
 
 struct emu10k1_wavedevice
 {
diff -urN linux-2.4.18-pre4/drivers/sound/emu10k1/cardwi.c linux/drivers/sound/emu10k1/cardwi.c
--- linux-2.4.18-pre4/drivers/sound/emu10k1/cardwi.c	Mon Sep 10 09:06:10 2001
+++ linux/drivers/sound/emu10k1/cardwi.c	Tue Jan 22 12:01:22 2002
@@ -96,6 +96,7 @@
 	wave_fmt->bytesperchannel = wave_fmt->bitsperchannel >> 3;
 	wave_fmt->bytespersample = wave_fmt->channels * wave_fmt->bytesperchannel;
 	wave_fmt->bytespersec = wave_fmt->bytespersample * wave_fmt->samplingrate;
+	wave_fmt->bytespervoicesample = wave_fmt->bytespersample;
 }
 
 static int alloc_buffer(struct emu10k1_card *card, struct wavein_buffer *buffer)
diff -urN linux-2.4.18-pre4/drivers/sound/emu10k1/cardwo.c linux/drivers/sound/emu10k1/cardwo.c
--- linux-2.4.18-pre4/drivers/sound/emu10k1/cardwo.c	Mon Sep 10 09:06:10 2001
+++ linux/drivers/sound/emu10k1/cardwo.c	Tue Jan 22 12:01:22 2002
@@ -108,95 +108,20 @@
 	}
 
 	wave_fmt->bytesperchannel = wave_fmt->bitsperchannel >> 3;
+	wave_fmt->bytespersample = wave_fmt->channels * wave_fmt->bytesperchannel;
+	wave_fmt->bytespersec = wave_fmt->bytespersample * wave_fmt->samplingrate;
 
 	if (wave_fmt->channels == 2)
 		wave_fmt->bytespervoicesample = wave_fmt->channels * wave_fmt->bytesperchannel;
 	else
 		wave_fmt->bytespervoicesample = wave_fmt->bytesperchannel;
-
-	wave_fmt->bytespersample = wave_fmt->channels * wave_fmt->bytesperchannel;
-	wave_fmt->bytespersec = wave_fmt->bytespersample * wave_fmt->samplingrate;
-}
-
-/**
- * alloc_buffer -
- *
- * allocates the memory buffer for a voice. Two page tables are kept for each buffer.
- * One (dma_handle) keeps track of the host memory pages used and the other (virtualpagetable)
- * is passed to the device so that it can do DMA to host memory. 
- *
- */
-static int alloc_buffer(struct emu10k1_card *card, struct waveout_buffer *buffer, unsigned int voicenum)
-{
-	u32 pageindex, pagecount;
-	unsigned long busaddx;
-	int i;
-
-	DPD(2, "requested pages is: %d\n", buffer->pages);
-
-	if ((buffer->mem[voicenum].emupageindex =
-	 emu10k1_addxmgr_alloc(buffer->pages * PAGE_SIZE, card)) < 0)
-		return -1;
-
-	/* Fill in virtual memory table */
-	for (pagecount = 0; pagecount < buffer->pages; pagecount++) {
-		if ((buffer->mem[voicenum].addr[pagecount] =
-		 pci_alloc_consistent(card->pci_dev, PAGE_SIZE,
-		 &buffer->mem[voicenum].dma_handle[pagecount])) == NULL) {
-			buffer->pages = pagecount;
-			return -1;
-		}
-
-		DPD(2, "Virtual Addx: %p\n", buffer->mem[voicenum].addr[pagecount]);
-
-		for (i = 0; i < PAGE_SIZE / EMUPAGESIZE; i++) {
-			busaddx = buffer->mem[voicenum].dma_handle[pagecount] + i * EMUPAGESIZE;
-
-			DPD(3, "Bus Addx: %#lx\n", busaddx);
-
-			pageindex = buffer->mem[voicenum].emupageindex + pagecount * PAGE_SIZE / EMUPAGESIZE + i;
-
-			((u32 *) card->virtualpagetable.addr)[pageindex] = cpu_to_le32((busaddx * 2) | pageindex);
-		}
-	}
-
-	return 0;
-}
-
-/**
- * free_buffer -
- *
- * frees the memory buffer for a voice.
- */
-static void free_buffer(struct emu10k1_card *card, struct waveout_buffer *buffer, unsigned int voicenum)
-{
-	u32 pagecount, pageindex;
-	int i;
-
-	if (buffer->mem[voicenum].emupageindex < 0)
-		return;
-
-	for (pagecount = 0; pagecount < buffer->pages; pagecount++) {
-		pci_free_consistent(card->pci_dev, PAGE_SIZE,
-		 buffer->mem[voicenum].addr[pagecount],
-		 buffer->mem[voicenum].dma_handle[pagecount]);
-
-		for (i = 0; i < PAGE_SIZE / EMUPAGESIZE; i++) {
-			pageindex = buffer->mem[voicenum].emupageindex + pagecount * PAGE_SIZE / EMUPAGESIZE + i;
-			((u32 *) card->virtualpagetable.addr)[pageindex] =
-			 cpu_to_le32((card->silentpage.dma_handle * 2) | pageindex);
-		}
-	}
-
-	emu10k1_addxmgr_free(card, buffer->mem[voicenum].emupageindex);
-	buffer->mem[voicenum].emupageindex = -1;
 }
 
 static int get_voice(struct emu10k1_card *card, struct woinst *woinst, unsigned int voicenum)
 {
 	struct emu_voice *voice = &woinst->voice[voicenum];
-	/* Allocate voices here, if no voices available, return error.
-	 * Init voice_allocdesc first.*/
+
+	/* Allocate voices here, if no voices available, return error. */
 
 	voice->usage = VOICE_USAGE_PLAYBACK;
 
@@ -219,7 +144,7 @@
 
 	DPD(2, "Initial pitch --> %#x\n", voice->initial_pitch);
 
-	voice->startloop = (woinst->buffer.mem[voicenum].emupageindex << 12) /
+	voice->startloop = (voice->mem.emupageindex << 12) /
 	 woinst->format.bytespervoicesample;
 	voice->endloop = voice->startloop + woinst->buffer.size / woinst->format.bytespervoicesample;
 	voice->start = voice->startloop;
@@ -302,7 +227,7 @@
 	DPF(2, "emu10k1_waveout_open()\n");
 
 	for (voicenum = 0; voicenum < woinst->num_voices; voicenum++) {
-		if (alloc_buffer(card, buffer, voicenum) < 0) {
+		if (emu10k1_voice_alloc_buffer(card, &woinst->voice[voicenum].mem, woinst->buffer.pages) < 0) {
 			ERROR();
 			emu10k1_waveout_close(wave_dev);
 			return -1;
@@ -324,7 +249,7 @@
 	delay = (48000 * woinst->buffer.fragment_size) /
 		 (woinst->format.samplingrate * woinst->format.bytespervoicesample);
 
-	emu10k1_timer_install(card, &woinst->timer, delay / 2);
+	emu10k1_timer_install(card, &woinst->timer, delay);
 
 	woinst->state = WAVE_STATE_OPEN;
 
@@ -345,7 +270,7 @@
 
 	for (voicenum = 0; voicenum < woinst->num_voices; voicenum++) {
 		emu10k1_voice_free(&woinst->voice[voicenum]);
-		free_buffer(card, &woinst->buffer, voicenum);
+		emu10k1_voice_free_buffer(card, &woinst->voice[voicenum].mem);
 	}
 
 	woinst->state = WAVE_STATE_CLOSED;
@@ -404,7 +329,7 @@
 		delay = (48000 * woinst->buffer.fragment_size) /
 			 (woinst->format.samplingrate * woinst->format.bytespervoicesample);
 
-		emu10k1_timer_install(card, &woinst->timer, delay / 2);
+		emu10k1_timer_install(card, &woinst->timer, delay);
 	}
 
 	return 0;
@@ -449,7 +374,7 @@
 
 	pending_bytes = buffer->size - buffer->free_bytes;
 
-	buffer->fill_silence = (pending_bytes < (signed) buffer->fragment_size) ? 1 : 0;
+	buffer->fill_silence = (pending_bytes < (signed) buffer->fragment_size * 2) ? 1 : 0;
 
 	if (pending_bytes > (signed) buffer->silence_bytes) {
 		*total_free_bytes = (buffer->free_bytes + buffer->silence_bytes);
@@ -508,14 +433,14 @@
         unsigned int pg;
 	unsigned int pgoff;
 	unsigned int voice_num;
-	struct waveout_mem *mem = woinst->buffer.mem;
+	struct emu_voice *voice = woinst->voice;
 
 	pg = str / PAGE_SIZE;
 	pgoff = str % PAGE_SIZE;
 
 	while (len) { 
 		for (voice_num = 0; voice_num < woinst->num_voices; voice_num++) {
-			__copy_from_user((u8 *)(mem[voice_num].addr[pg]) + pgoff, src, woinst->format.bytespervoicesample);
+			__copy_from_user((u8 *)(voice[voice_num].mem.addr[pg]) + pgoff, src, woinst->format.bytespervoicesample);
 			src += woinst->format.bytespervoicesample;
 		}
 
@@ -540,7 +465,7 @@
 	unsigned int pg;
 	unsigned int pgoff;
 	unsigned int voice_num;
-        struct waveout_mem *mem = woinst->buffer.mem;
+        struct emu_voice *voice = woinst->voice;
 	unsigned int  k;
 
 	pg = str / PAGE_SIZE;
@@ -549,22 +474,22 @@
 	if (len > PAGE_SIZE - pgoff) {
 		k = PAGE_SIZE - pgoff;
 		for (voice_num = 0; voice_num < woinst->num_voices; voice_num++)
-			memset((u8 *)mem[voice_num].addr[pg] + pgoff, data, k);
+			memset((u8 *)voice[voice_num].mem.addr[pg] + pgoff, data, k);
 		len -= k;
 		while (len > PAGE_SIZE) {
 			pg++;
 			for (voice_num = 0; voice_num < woinst->num_voices; voice_num++)
-				memset(mem[voice_num].addr[pg], data, PAGE_SIZE);
+				memset(voice[voice_num].mem.addr[pg], data, PAGE_SIZE);
 
 			len -= PAGE_SIZE;
 		}
 		pg++;
 		for (voice_num = 0; voice_num < woinst->num_voices; voice_num++)
-			memset(mem[voice_num].addr[pg], data, len);
+			memset(voice[voice_num].mem.addr[pg], data, len);
 
 	} else {
 		for (voice_num = 0; voice_num < woinst->num_voices; voice_num++)
-			memset((u8 *)mem[voice_num].addr[pg] + pgoff, data, len);
+			memset((u8 *)voice[voice_num].mem.addr[pg] + pgoff, data, len);
 	}
 }
 
@@ -578,6 +503,7 @@
 void emu10k1_waveout_xferdata(struct woinst *woinst, u8 *data, u32 *size)
 {
 	struct waveout_buffer *buffer = &woinst->buffer;
+	struct voice_mem *mem = &woinst->voice[0].mem;
 	u32 sizetocopy, sizetocopy_now, start;
 	unsigned long flags;
 
@@ -606,14 +532,14 @@
 			copy_ilv_block(woinst, start, data, sizetocopy_now);
 			copy_ilv_block(woinst, 0, data + sizetocopy_now * woinst->num_voices, sizetocopy);
 		} else {
-			copy_block(buffer->mem[0].addr, start, data, sizetocopy_now);
-			copy_block(buffer->mem[0].addr, 0, data + sizetocopy_now, sizetocopy);
+			copy_block(mem->addr, start, data, sizetocopy_now);
+			copy_block(mem->addr, 0, data + sizetocopy_now, sizetocopy);
 		}
 	} else {
 		if (woinst->num_voices > 1)
 			copy_ilv_block(woinst, start, data, sizetocopy);
 		else
-			copy_block(buffer->mem[0].addr, start, data, sizetocopy);
+			copy_block(mem->addr, start, data, sizetocopy);
 	}
 }
 
@@ -670,7 +596,7 @@
 {
 	u32 hw_pos;
 	u32 diff;
-	
+
 	/* There is no actual start yet */
 	if (!(woinst->state & WAVE_STATE_STARTED)) {
 		hw_pos = woinst->buffer.hw_pos;
diff -urN linux-2.4.18-pre4/drivers/sound/emu10k1/cardwo.h linux/drivers/sound/emu10k1/cardwo.h
--- linux-2.4.18-pre4/drivers/sound/emu10k1/cardwo.h	Fri Aug 10 21:02:18 2001
+++ linux/drivers/sound/emu10k1/cardwo.h	Tue Jan 22 12:01:22 2002
@@ -47,20 +47,12 @@
 #define WAVEOUT_MINFRAGSHIFT	6
 #define WAVEOUT_MAXVOICES 6
 
-/* waveout_mem is cardwo internal */
-struct waveout_mem {
-	int emupageindex;
-	void *addr[BUFMAXPAGES];
-	dma_addr_t dma_handle[BUFMAXPAGES];
-};
-
 struct waveout_buffer {
 	u16 ossfragshift;
 	u32 numfrags;
 	u32 fragment_size;	/* in bytes units */
 	u32 size;		/* in bytes units */
 	u32 pages;		/* buffer size in page units*/
-	struct waveout_mem mem[WAVEOUT_MAXVOICES];
 	u32 silence_pos;	/* software cursor position (including silence bytes) */
 	u32 hw_pos;		/* hardware cursor position */
 	u32 free_bytes;		/* free bytes available on the buffer (not including silence bytes) */
diff -urN linux-2.4.18-pre4/drivers/sound/emu10k1/efxmgr.c linux/drivers/sound/emu10k1/efxmgr.c
--- linux-2.4.18-pre4/drivers/sound/emu10k1/efxmgr.c	Tue Oct  9 10:53:18 2001
+++ linux/drivers/sound/emu10k1/efxmgr.c	Tue Jan 22 12:01:22 2002
@@ -173,7 +173,7 @@
 	unsigned long flags;
 	int muting;
 
-	const s32 log2lin[5] ={                  //  attenuation (dB)
+	static const s32 log2lin[4] ={           //  attenuation (dB)
 		0x7fffffff,                      //       0.0         
 		0x7fffffff * 0.840896415253715 , //       1.5          
 		0x7fffffff * 0.707106781186548,  //       3.0
diff -urN linux-2.4.18-pre4/drivers/sound/emu10k1/hwaccess.h linux/drivers/sound/emu10k1/hwaccess.h
--- linux-2.4.18-pre4/drivers/sound/emu10k1/hwaccess.h	Thu Oct 25 14:01:57 2001
+++ linux/drivers/sound/emu10k1/hwaccess.h	Tue Jan 22 12:01:22 2002
@@ -126,6 +126,7 @@
 #define CMD_SETMCH_FX		_IOW('D', 17, struct mixer_private_ioctl)
 #define CMD_SETPASSTHROUGH	_IOW('D', 18, struct mixer_private_ioctl)
 #define CMD_PRIVATE3_VERSION	_IOW('D', 19, struct mixer_private_ioctl)
+#define CMD_AC97_BOOST		_IOW('D', 20, struct mixer_private_ioctl)
 
 //up this number when breaking compatibility
 #define PRIVATE3_VERSION 1
@@ -216,7 +217,7 @@
 
 void sblive_writeptr(struct emu10k1_card *, u32 , u32 , u32 );
 void sblive_writeptr_tag(struct emu10k1_card *card, u32 channel, ...);
-#define TAGLIST_END 0
+#define TAGLIST_END	0
 
 u32 sblive_readptr(struct emu10k1_card *, u32 , u32 );
 
diff -urN linux-2.4.18-pre4/drivers/sound/emu10k1/irqmgr.c linux/drivers/sound/emu10k1/irqmgr.c
--- linux-2.4.18-pre4/drivers/sound/emu10k1/irqmgr.c	Fri Aug 10 21:02:18 2001
+++ linux/drivers/sound/emu10k1/irqmgr.c	Tue Jan 22 12:01:22 2002
@@ -1,4 +1,3 @@
-
 /*
  **********************************************************************
  *     irqmgr.c - IRQ manager for emu10k1 driver
@@ -41,7 +40,7 @@
 void emu10k1_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
 	struct emu10k1_card *card = (struct emu10k1_card *) dev_id;
-	u32 irqstatus;
+	u32 irqstatus, irqstatus_tmp;
 
 	DPD(4, "emu10k1_interrupt called, irq =  %u\n", irq);
 
@@ -60,8 +59,7 @@
 	while ((irqstatus = inl(card->iobase + IPR))) {
 		DPD(4, "irq status %#x\n", irqstatus);
 
-		/* acknowledge interrupt */
-		outl(irqstatus, card->iobase + IPR);
+		irqstatus_tmp = irqstatus;
 
 		if (irqstatus & IRQTYPE_TIMER) {
 			emu10k1_timer_irqhandler(card);
@@ -98,7 +96,15 @@
 			irqstatus &=~IPR_VOLDECR;
 		}
 
-		if (irqstatus)
-			emu10k1_irq_disable(card, irqstatus);
+		if (irqstatus){
+			printk(KERN_ERR "emu10k1: Warning, unhandled interrupt: %#08x\n", irqstatus);
+			//make sure any interrupts we don't handle are disabled:
+			emu10k1_irq_disable(card, ~(INTE_MIDIRXENABLE | INTE_MIDITXENABLE | INTE_INTERVALTIMERENB |
+						INTE_VOLDECRENABLE | INTE_VOLINCRENABLE | INTE_MUTEENABLE |
+						INTE_FXDSPENABLE));
+		}
+
+		/* acknowledge interrupt */
+                outl(irqstatus_tmp, card->iobase + IPR);
 	}
 }
diff -urN linux-2.4.18-pre4/drivers/sound/emu10k1/main.c linux/drivers/sound/emu10k1/main.c
--- linux-2.4.18-pre4/drivers/sound/emu10k1/main.c	Fri Dec 21 09:41:55 2001
+++ linux/drivers/sound/emu10k1/main.c	Tue Jan 22 12:01:22 2002
@@ -1,4 +1,4 @@
-/*
+ /*
  **********************************************************************
  *     main.c - Creative EMU10K1 audio driver
  *     Copyright 1999, 2000 Creative Labs, Inc.
@@ -69,6 +69,15 @@
  *     0.16 Mixer improvements, added old treble/bass support (Daniel Bertrand)
  *          Small code format cleanup.
  *          Deadlock bug fix for emu10k1_volxxx_irqhandler().
+ *     0.17 Fix for mixer SOUND_MIXER_INFO ioctl.
+ *	    Fix for HIGHMEM machines (emu10k1 can only do 31 bit bus master) 
+ *	    midi poll initial implementation.
+ *	    Small mixer fixes/cleanups.
+ *	    Improved support for 5.1 cards.
+ *     0.18 Fix for possible leak in pci_alloc_consistent()
+ *          Cleaned up poll() functions (audio and midi). Don't start input.
+ *	    Restrict DMA pages used to 512Mib range.
+ *	    New AC97_BOOST mixer ioctl.
  *
  *********************************************************************/
 
@@ -102,11 +111,10 @@
 #define SNDCARD_EMU10K1 46
 #endif
  
-#define DRIVER_VERSION "0.16"
+#define DRIVER_VERSION "0.18"
 
-/* FIXME: is this right? */
-/* does the card support 32 bit bus master?*/
-#define EMU10K1_DMA_MASK                0xffffffff	/* DMA buffer mask for pci_alloc_consist */
+/* the emu10k1 _seems_ to only supports 29 bit (512MiB) bit bus master */
+#define EMU10K1_DMA_MASK                0x1fffffff	/* DMA buffer mask for pci_alloc_consist */
 
 #ifndef PCI_VENDOR_ID_CREATIVE
 #define PCI_VENDOR_ID_CREATIVE 0x1102
@@ -211,6 +219,8 @@
 static int __devinit emu10k1_mixer_init(struct emu10k1_card *card)
 {
 	char s[32];
+
+	struct ac97_codec *codec = &card->ac97;
 	card->ac97.dev_mixer = register_sound_mixer(&emu10k1_mixer_fops, -1);
 	if (card->ac97.dev_mixer < 0) {
 		printk(KERN_ERR "emu10k1: cannot register mixer device\n");
@@ -228,11 +238,14 @@
 			printk(KERN_ERR "emu10k1: unable to probe AC97 codec\n");
 			goto err_out;
 		}
-		/* 5.1: Enable the additional AC97 Slots. If the emu10k1 version
-			does not support this, it shouldn't do any harm */
-		sblive_writeptr(card, AC97SLOT, 0, AC97SLOT_CNTR | AC97SLOT_LFE);
+		/* 5.1: Enable the additional AC97 Slots and unmute extra channels on AC97 codec */
+		if (codec->codec_read(codec, AC97_EXTENDED_ID) & 0x0080){
+			printk(KERN_INFO "emu10k1: SBLive! 5.1 card detected\n"); 
+			sblive_writeptr(card, AC97SLOT, 0, AC97SLOT_CNTR | AC97SLOT_LFE);
+			codec->codec_write(codec, AC97_SURROUND_MASTER, 0x0);
+		}
 
-		// Force 5bit
+		// Force 5bit:		    
 		//card->ac97.bit_resolution=5;
 
 		if (!proc_mkdir ("driver/emu10k1", 0)) {
@@ -586,15 +599,15 @@
 	CONNECT(PCM1_IN_R, ANALOG_REAR_R);
 
 	/* Digital In + PCM + AC97 In + MULTI_FRONT --> Digital out */
-	OP(6, 0x10b, 0x100, 0x102, 0x10c);
-	OP(6, 0x10b, 0x10b, 0x113, 0x40);
+	OP(6, 0x10a, 0x100, 0x102, 0x10c);
+	OP(6, 0x10a, 0x10a, 0x113, 0x40);
 
 	CONNECT(MULTI_FRONT_L, DIGITAL_OUT_L);
 	CONNECT(PCM_IN_L, DIGITAL_OUT_L);
 	CONNECT(AC97_IN_L, DIGITAL_OUT_L);
 	CONNECT(SPDIF_CD_L, DIGITAL_OUT_L);
 
-	OP(6, 0x10a, 0x101, 0x103, 0x10e);
+	OP(6, 0x10b, 0x101, 0x103, 0x10e);
 	OP(6, 0x10b, 0x10b, 0x114, 0x40);
 
 	CONNECT(MULTI_FRONT_R, DIGITAL_OUT_R);
@@ -768,7 +781,7 @@
 				    VTFT, 0xffff,
 				    CVCF, 0xffff,
 				    PTRX, 0,
-				    CPF, 0,
+				    //CPF, 0,
 				    CCR, 0,
 
 				    PSST, 0,
@@ -794,7 +807,9 @@
 				    ENVVOL, 0,
 				    ENVVAL, 0,
                                     TAGLIST_END);
+		sblive_writeptr(card, CPF, nCh, 0);
 	}
+	
 
 	/*
 	 ** Init to 0x02109204 :
@@ -951,8 +966,9 @@
 				    VTFT, 0,
 				    CVCF, 0,
 				    PTRX, 0,
-				    CPF, 0,
+				    //CPF, 0,
 				    TAGLIST_END);
+		sblive_writeptr(card, CPF, ch, 0);
 	}
 
 	/* Disable audio and lock cache */
diff -urN linux-2.4.18-pre4/drivers/sound/emu10k1/midi.c linux/drivers/sound/emu10k1/midi.c
--- linux-2.4.18-pre4/drivers/sound/emu10k1/midi.c	Tue Oct  9 10:53:18 2001
+++ linux/drivers/sound/emu10k1/midi.c	Tue Jan 22 12:01:22 2002
@@ -31,6 +31,7 @@
 
 #define __NO_VERSION__
 #include <linux/module.h>
+#include <linux/poll.h>
 #include <linux/slab.h>
 #include <linux/version.h>
 #include <linux/sched.h>
@@ -371,8 +372,32 @@
 
 static unsigned int emu10k1_midi_poll(struct file *file, struct poll_table_struct *wait)
 {
+	struct emu10k1_mididevice *midi_dev = (struct emu10k1_mididevice *) file->private_data;
+	unsigned long flags;
+	unsigned int mask = 0;
+
 	DPF(4, "emu10k1_midi_poll() called\n");
-	return 0;
+
+	if (file->f_mode & FMODE_WRITE)
+		poll_wait(file, &midi_dev->oWait, wait);
+
+	if (file->f_mode & FMODE_READ)
+		poll_wait(file, &midi_dev->iWait, wait);
+
+	spin_lock_irqsave(&midi_spinlock, flags);
+
+	if (file->f_mode & FMODE_WRITE)
+		mask |= POLLOUT | POLLWRNORM;
+
+	if (file->f_mode & FMODE_READ) {
+		if (midi_dev->mistate == MIDIIN_STATE_STARTED)
+			if (midi_dev->icnt > 0)
+				mask |= POLLIN | POLLRDNORM;
+	}
+
+	spin_unlock_irqrestore(&midi_spinlock, flags);
+
+	return mask;
 }
 
 int emu10k1_midi_callback(unsigned long msg, unsigned long refdata, unsigned long *pmsg)
diff -urN linux-2.4.18-pre4/drivers/sound/emu10k1/mixer.c linux/drivers/sound/emu10k1/mixer.c
--- linux-2.4.18-pre4/drivers/sound/emu10k1/mixer.c	Tue Oct  9 10:53:18 2001
+++ linux/drivers/sound/emu10k1/mixer.c	Tue Jan 22 12:01:22 2002
@@ -444,6 +444,7 @@
 
 		case CMD_SETGPR2OSS:
 			id = ctl->val[0];
+			/* 0 == left, 1 == right */
 			ch = ctl->val[1];
 			addr = ctl->val[2];
 
@@ -460,13 +461,13 @@
 			if (addr >= 0) {
 				unsigned int state = card->ac97.mixer_state[id];
 
-				if (ch) {
+				if (ch == 1) {
 					state >>= 8;
 					card->ac97.stereo_mixers |= (1 << id);
-				} else {
-					card->ac97.supported_mixers |= (1 << id);
 				}
 
+				card->ac97.supported_mixers |= (1 << id);
+
 				if (id == SOUND_MIXER_TREBLE) {
 					set_treble(card, card->ac97.mixer_state[id] & 0xff, (card->ac97.mixer_state[id] >> 8) & 0xff);
 				} else if (id == SOUND_MIXER_BASS) {
@@ -475,10 +476,10 @@
 					emu10k1_set_volume_gpr(card, addr, state & 0xff,
 							       volume_params[id]);
 			} else {
-				if (ch) {
-					card->ac97.stereo_mixers &= ~(1 << id);
-					card->ac97.stereo_mixers |= card->ac97_stereo_mixers;
-				} else {
+				card->ac97.stereo_mixers &= ~(1 << id);
+				card->ac97.stereo_mixers |= card->ac97_stereo_mixers;
+
+				if (ch == 0) {
 					card->ac97.supported_mixers &= ~(1 << id);
 					card->ac97.supported_mixers |= card->ac97_supported_mixers;
 				}
@@ -499,6 +500,12 @@
 				ret = -EFAULT;
 			break;
 
+		case CMD_AC97_BOOST:
+			if(ctl->val[0])
+				emu10k1_ac97_write(&card->ac97, 0x18, 0x0);	
+			else
+				emu10k1_ac97_write(&card->ac97, 0x18, 0x0808);
+			break;
 		default:
 			ret = -EINVAL;
 			break;
@@ -572,6 +579,8 @@
 	int val;
 	int scale;
 
+	card->ac97.modcnt++;
+
 	if (get_user(val, (int *)arg))
 		return -EFAULT;
 
@@ -626,7 +635,7 @@
 			return 0;
 		}
 
-		if ((_IOC_DIR(cmd) == (_IOC_WRITE|_IOC_READ)) && oss_mixer <= SOUND_MIXER_NRDEVICES)
+		if ((_SIOC_DIR(cmd) == (_SIOC_WRITE|_SIOC_READ)) && oss_mixer <= SOUND_MIXER_NRDEVICES)
 			ret = emu10k1_dsp_mixer(card, oss_mixer, arg);
 		else
 			ret = card->ac97.mixer_ioctl(&card->ac97, cmd, arg);
diff -urN linux-2.4.18-pre4/drivers/sound/emu10k1/recmgr.c linux/drivers/sound/emu10k1/recmgr.c
--- linux-2.4.18-pre4/drivers/sound/emu10k1/recmgr.c	Fri Aug 10 21:02:19 2001
+++ linux/drivers/sound/emu10k1/recmgr.c	Tue Jan 22 12:01:22 2002
@@ -130,7 +130,7 @@
 		break;
 	}
 
-	DPD(2, "bus addx: %#x\n", buffer->dma_handle);
+	DPD(2, "bus addx: %#lx\n", (unsigned long) buffer->dma_handle);
 
 	sblive_writeptr(card, buffer->addrreg, 0, buffer->dma_handle);
 
diff -urN linux-2.4.18-pre4/drivers/sound/emu10k1/voicemgr.c linux/drivers/sound/emu10k1/voicemgr.c
--- linux-2.4.18-pre4/drivers/sound/emu10k1/voicemgr.c	Fri Aug 10 21:02:19 2001
+++ linux/drivers/sound/emu10k1/voicemgr.c	Tue Jan 22 12:01:22 2002
@@ -32,6 +32,84 @@
 #include "voicemgr.h"
 #include "8010.h"
 
+/**
+ * emu10k1_voice_alloc_buffer -
+ *
+ * allocates the memory buffer for a voice. Two page tables are kept for each buffer.
+ * One (dma_handle) keeps track of the host memory pages used and the other (virtualpagetable)
+ * is passed to the device so that it can do DMA to host memory.
+ *
+ */
+int emu10k1_voice_alloc_buffer(struct emu10k1_card *card, struct voice_mem *mem, u32 pages)
+{
+	u32 pageindex, pagecount;
+	unsigned long busaddx;
+	int i;
+
+	DPD(2, "requested pages is: %d\n", pages);
+
+	if ((mem->emupageindex = emu10k1_addxmgr_alloc(pages * PAGE_SIZE, card)) < 0)
+	{
+		DPF(1, "couldn't allocate emu10k1 address space\n");
+		return -1;
+	}
+
+	/* Fill in virtual memory table */
+	for (pagecount = 0; pagecount < pages; pagecount++) {
+		if ((mem->addr[pagecount] = pci_alloc_consistent(card->pci_dev, PAGE_SIZE, &mem->dma_handle[pagecount]))
+			== NULL) {
+			mem->pages = pagecount;
+			DPF(1, "couldn't allocate dma memory\n");
+			return -1;
+		}
+
+		DPD(2, "Virtual Addx: %p\n", mem->addr[pagecount]);
+
+		for (i = 0; i < PAGE_SIZE / EMUPAGESIZE; i++) {
+			busaddx = mem->dma_handle[pagecount] + i * EMUPAGESIZE;
+
+			DPD(3, "Bus Addx: %#lx\n", busaddx);
+
+			pageindex = mem->emupageindex + pagecount * PAGE_SIZE / EMUPAGESIZE + i;
+
+			((u32 *) card->virtualpagetable.addr)[pageindex] = cpu_to_le32((busaddx * 2) | pageindex);
+		}
+	}
+
+	mem->pages = pagecount;
+
+	return 0;
+}
+
+/**
+ * emu10k1_voice_free_buffer -
+ *
+ * frees the memory buffer for a voice.
+ */
+void emu10k1_voice_free_buffer(struct emu10k1_card *card, struct voice_mem *mem)
+{
+	u32 pagecount, pageindex;
+	int i;
+
+	if (mem->emupageindex < 0)
+		return;
+
+	for (pagecount = 0; pagecount < mem->pages; pagecount++) {
+		pci_free_consistent(card->pci_dev, PAGE_SIZE,
+					mem->addr[pagecount],
+					mem->dma_handle[pagecount]);
+
+		for (i = 0; i < PAGE_SIZE / EMUPAGESIZE; i++) {
+			pageindex = mem->emupageindex + pagecount * PAGE_SIZE / EMUPAGESIZE + i;
+			((u32 *) card->virtualpagetable.addr)[pageindex] =
+				cpu_to_le32((card->silentpage.dma_handle * 2) | pageindex);
+		}
+	}
+
+	emu10k1_addxmgr_free(card, mem->emupageindex);
+	mem->emupageindex = -1;
+}
+
 int emu10k1_voice_alloc(struct emu10k1_card *card, struct emu_voice *voice)
 {
 	u8 *voicetable = card->voicetable;
@@ -96,8 +174,10 @@
 							VTFT, 0x0000ffff,
 							PTRX_PITCHTARGET, 0,
 							CVCF, 0x0000ffff,
-							CPF, 0,
+							//CPF, 0,
 							TAGLIST_END);
+		
+		sblive_writeptr(card, CPF, voice->num + i, 0);
 	}
 
 	voice->usage = VOICE_USAGE_FREE;
diff -urN linux-2.4.18-pre4/drivers/sound/emu10k1/voicemgr.h linux/drivers/sound/emu10k1/voicemgr.h
--- linux-2.4.18-pre4/drivers/sound/emu10k1/voicemgr.h	Fri Aug 10 21:02:19 2001
+++ linux/drivers/sound/emu10k1/voicemgr.h	Tue Jan 22 12:01:22 2002
@@ -64,6 +64,12 @@
 	u32 byampl_env_decay;
 };
 
+struct voice_mem {
+	int emupageindex;
+	void *addr[BUFMAXPAGES];
+	dma_addr_t dma_handle[BUFMAXPAGES];
+	u32 pages;
+};
 
 struct emu_voice
 {
@@ -72,16 +78,20 @@
 	u8 num;			/* Voice ID */
 	u8 flags;		/* Stereo/mono, 8/16 bit */
 
-        u32 startloop;
-        u32 endloop;
+	u32 startloop;
+	u32 endloop;
 	u32 start;
 
 	u32 initial_pitch;
 	u32 pitch_target;
 
 	struct voice_param params[2];
+
+	struct voice_mem mem;
 };
 
+int emu10k1_voice_alloc_buffer(struct emu10k1_card *, struct voice_mem *, u32);
+void emu10k1_voice_free_buffer(struct emu10k1_card *, struct voice_mem *);
 int emu10k1_voice_alloc(struct emu10k1_card *, struct emu_voice *);
 void emu10k1_voice_free(struct emu_voice *);
 void emu10k1_voice_playback_setup(struct emu_voice *);
diff -urN linux-2.4.18-pre4/drivers/usb/serial/ir-usb.c linux/drivers/usb/serial/ir-usb.c
--- linux-2.4.18-pre4/drivers/usb/serial/ir-usb.c	Mon Nov 12 09:53:56 2001
+++ linux/drivers/usb/serial/ir-usb.c	Tue Jan 22 12:01:22 2002
@@ -2,6 +2,7 @@
  * USB IR Dongle driver
  *
  *	Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com)
+ *	Copyright (C) 2002 Gary Brubaker (xavyer@ix.netcom.com)
  *
  *	This program is free software; you can redistribute it and/or modify
  *	it under the terms of the GNU General Public License as published by
@@ -20,6 +21,12 @@
  *
  * See Documentation/usb/usb-serial.txt for more information on using this driver
  *
+ * 2002_Jan_14  gb
+ *	Added module parameter to force specific number of XBOFs.
+ *	Added ir_xbof_change().
+ *	Reorganized read_bulk_callback error handling.
+ *	Switched from FILL_BULK_URB() to usb_fill_bulk_urb().
+ *
  * 2001_Nov_08  greg kh
  *	Changed the irda_usb_find_class_desc() function based on comments and
  *	code from Martin Diehl.
@@ -62,13 +69,15 @@
 /*
  * Version Information
  */
-#define DRIVER_VERSION "v0.3"
+#define DRIVER_VERSION "v0.4"
 #define DRIVER_AUTHOR "Greg Kroah-Hartman <greg@kroah.com>"
 #define DRIVER_DESC "USB IR Dongle driver"
 
 /* if overridden by the user, then use their value for the size of the read and
  * write urbs */
 static int buffer_size = 0;
+/* if overridden by the user, then use the specified number of XBOFs */
+static int xbof = -1;
 
 static int  ir_startup (struct usb_serial *serial);
 static int  ir_open (struct usb_serial_port *port, struct file *filep);
@@ -78,6 +87,9 @@
 static void ir_read_bulk_callback (struct urb *urb);
 static void ir_set_termios (struct usb_serial_port *port, struct termios *old_termios);
 
+static u8 ir_baud = 0;
+static u8 ir_xbof = 0;
+static u8 ir_add_bof = 0;
 
 static __devinitdata struct usb_device_id id_table [] = {
 	{ USB_DEVICE(0x050f, 0x0180) },		/* KC Technology, KC-180 */
@@ -150,14 +162,16 @@
 			USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
 			0, ifnum, desc, sizeof(*desc), MSECS_TO_JIFFIES(500));
 	
-	dbg(__FUNCTION__ " -  ret=%d", ret);
+	dbg("%s -  ret=%d", __FUNCTION__, ret);
 	if (ret < sizeof(*desc)) {
-		dbg(__FUNCTION__ " - class descriptor read %s (%d)",
-				(ret<0) ? "failed" : "too short", ret);
+		dbg("%s - class descriptor read %s (%d)",
+				__FUNCTION__, 
+				(ret<0) ? "failed" : "too short",
+				ret);
 		goto error;
 	}
 	if (desc->bDescriptorType != USB_DT_IRDA) {
-		dbg(__FUNCTION__ " - bad class descriptor type");
+		dbg("%s - bad class descriptor type", __FUNCTION__);
 		goto error;
 	}
 	
@@ -168,6 +182,28 @@
 	return NULL;
 }
 
+
+static u8 ir_xbof_change(u8 xbof)
+{
+	u8 result;
+	/* reference irda-usb.c */
+	switch(xbof) {
+		case 48: result = 0x10; break;
+		case 28:
+		case 24: result = 0x20; break;
+		default:
+		case 12: result = 0x30; break;
+		case  5:
+		case  6: result = 0x40; break;
+		case  3: result = 0x50; break;
+		case  2: result = 0x60; break;
+		case  1: result = 0x70; break;
+		case  0: result = 0x80; break;
+	}
+	return(result);
+}
+
+
 static int ir_startup (struct usb_serial *serial)
 {
 	struct irda_class_desc *irda_desc;
@@ -177,16 +213,30 @@
 		err ("IRDA class descriptor not found, device not bound");
 		return -ENODEV;
 	}
-	dbg (__FUNCTION__" - Baud rates supported: %s%s%s%s%s%s%s%s%s",
-	     (irda_desc->wBaudRate & 0x0001) ? "2400 " : "",
-	     irda_desc->wBaudRate & 0x0002 ? "9600 " : "",
-	     irda_desc->wBaudRate & 0x0004 ? "19200 " : "",
-	     irda_desc->wBaudRate & 0x0008 ? "38400 " : "",
-	     irda_desc->wBaudRate & 0x0010 ? "57600 " : "",
-	     irda_desc->wBaudRate & 0x0020 ? "115200 " : "",
-	     irda_desc->wBaudRate & 0x0040 ? "576000 " : "",
-	     irda_desc->wBaudRate & 0x0080 ? "1152000 " : "",
-	     irda_desc->wBaudRate & 0x0100 ? "4000000 " : "");
+
+	dbg ("%s - Baud rates supported:%s%s%s%s%s%s%s%s%s",
+		__FUNCTION__,
+		(irda_desc->wBaudRate & 0x0001) ? " 2400"    : "",
+		(irda_desc->wBaudRate & 0x0002) ? " 9600"    : "",
+		(irda_desc->wBaudRate & 0x0004) ? " 19200"   : "",
+		(irda_desc->wBaudRate & 0x0008) ? " 38400"   : "",
+		(irda_desc->wBaudRate & 0x0010) ? " 57600"   : "",
+		(irda_desc->wBaudRate & 0x0020) ? " 115200"  : "",
+		(irda_desc->wBaudRate & 0x0040) ? " 576000"  : "",
+		(irda_desc->wBaudRate & 0x0080) ? " 1152000" : "",
+		(irda_desc->wBaudRate & 0x0100) ? " 4000000" : "");
+
+	switch( irda_desc->bmAdditionalBOFs ) {
+		case 0x01: ir_add_bof = 48; break;
+		case 0x02: ir_add_bof = 24; break;
+		case 0x04: ir_add_bof = 12; break;
+		case 0x08: ir_add_bof =  6; break;
+		case 0x10: ir_add_bof =  3; break;
+		case 0x20: ir_add_bof =  2; break;
+		case 0x40: ir_add_bof =  1; break;
+		case 0x80: ir_add_bof =  0; break;
+		default:
+	}
 
 	kfree (irda_desc);
 
@@ -202,7 +252,7 @@
 	if (port_paranoia_check (port, __FUNCTION__))
 		return -ENODEV;
 	
-	dbg(__FUNCTION__ " - port %d", port->number);
+	dbg("%s - port %d", __FUNCTION__, port->number);
 
 	down (&port->sem);
 	
@@ -216,7 +266,7 @@
 			/* override the default buffer sizes */
 			buffer = kmalloc (buffer_size, GFP_KERNEL);
 			if (!buffer) {
-				err (__FUNCTION__ " - out of memory.");
+				err ("%s - out of memory.", __FUNCTION__);
 				return -ENOMEM;
 			}
 			kfree (port->read_urb->transfer_buffer);
@@ -225,7 +275,7 @@
 
 			buffer = kmalloc (buffer_size, GFP_KERNEL);
 			if (!buffer) {
-				err (__FUNCTION__ " - out of memory.");
+				err ("%s - out of memory.", __FUNCTION__);
 				return -ENOMEM;
 			}
 			kfree (port->write_urb->transfer_buffer);
@@ -235,13 +285,18 @@
 		}
 
 		/* Start reading from the device */
-		FILL_BULK_URB(port->read_urb, serial->dev, 
-			      usb_rcvbulkpipe(serial->dev, port->bulk_in_endpointAddress),
-			      port->read_urb->transfer_buffer, port->read_urb->transfer_buffer_length,
-			      ir_read_bulk_callback, port);
+		usb_fill_bulk_urb (
+			port->read_urb,
+			serial->dev, 
+			usb_rcvbulkpipe(serial->dev, port->bulk_in_endpointAddress),
+			port->read_urb->transfer_buffer,
+			port->read_urb->transfer_buffer_length,
+			ir_read_bulk_callback,
+			port);
+		port->read_urb->transfer_flags = USB_QUEUE_BULK;
 		result = usb_submit_urb(port->read_urb);
 		if (result)
-			err(__FUNCTION__ " - failed submitting read urb, error %d", result);
+			err("%s - failed submitting read urb, error %d", __FUNCTION__, result);
 	}
 	
 	up (&port->sem);
@@ -256,7 +311,7 @@
 	if (port_paranoia_check (port, __FUNCTION__))
 		return;
 	
-	dbg(__FUNCTION__ " - port %d", port->number);
+	dbg("%s - port %d", __FUNCTION__, port->number);
 			 
 	serial = get_usb_serial (port, __FUNCTION__);
 	if (!serial)
@@ -283,11 +338,12 @@
 {
 	unsigned char *transfer_buffer;
 	int result;
+	int transfer_size;
 
-	dbg(__FUNCTION__ " - port = %d, count = %d", port->number, count);
+	dbg("%s - port = %d, count = %d", __FUNCTION__, port->number, count);
 
 	if (!port->tty) {
-		err (__FUNCTION__ " - no tty???");
+		err ("%s - no tty???", __FUNCTION__);
 		return 0;
 	}
 
@@ -295,37 +351,49 @@
 		return 0;
 
 	if (port->write_urb->status == -EINPROGRESS) {
-		dbg (__FUNCTION__ " - already writing");
+		dbg ("%s - already writing", __FUNCTION__);
 		return 0;
 	}
 
+	transfer_buffer = port->write_urb->transfer_buffer;
+	transfer_size = min(count, port->bulk_out_size - 1);
+
 	/*
-	 * The first byte of the packet we send to the device contains a BOD
-	 * and baud rate change.  So we set it to 0.
+	 * The first byte of the packet we send to the device contains an
+	 * inband header which indicates an additional number of BOFs and
+	 * a baud rate change.
+	 *
 	 * See section 5.4.2.2 of the USB IrDA spec.
 	 */
-	transfer_buffer = port->write_urb->transfer_buffer;
-	count = min (port->bulk_out_size-1, count);
+	*transfer_buffer = ir_xbof | ir_baud;
+	++transfer_buffer;
+
 	if (from_user) {
-		if (copy_from_user (&transfer_buffer[1], buf, count))
+		if (copy_from_user (transfer_buffer, buf, transfer_size))
 			return -EFAULT;
 	} else {
-		memcpy (&transfer_buffer[1], buf, count);
+		memcpy (transfer_buffer, buf, transfer_size);
 	}
 
-	/* use 12 XBOF's as default */
-	transfer_buffer[0] = 0x30;
-
-	usb_serial_debug_data (__FILE__, __FUNCTION__, count+1, transfer_buffer);
+	usb_fill_bulk_urb (
+		port->write_urb,
+		port->serial->dev,
+		usb_sndbulkpipe(port->serial->dev,
+			port->bulk_out_endpointAddress),
+		port->write_urb->transfer_buffer,
+		transfer_size + 1,
+		ir_write_bulk_callback,
+		port);
+
+	port->write_urb->transfer_flags
+		= USB_QUEUE_BULK
+		| USB_ZERO_PACKET;
 
-	port->write_urb->transfer_buffer_length = count + 1;
-	port->write_urb->dev = port->serial->dev;
-	port->write_urb->transfer_flags |= USB_ZERO_PACKET;
 	result = usb_submit_urb (port->write_urb);
 	if (result)
-		err(__FUNCTION__ " - failed submitting write urb, error %d", result);
+		err("%s - failed submitting write urb, error %d", __FUNCTION__, result);
 	else
-		result = count;
+		result = transfer_size;
 
 	return result;
 }
@@ -337,13 +405,19 @@
 	if (port_paranoia_check (port, __FUNCTION__))
 		return;
 	
-	dbg(__FUNCTION__ " - port %d", port->number);
+	dbg("%s - port %d", __FUNCTION__, port->number);
 	
 	if (urb->status) {
-		dbg(__FUNCTION__ " - nonzero write bulk status received: %d", urb->status);
+		dbg("%s - nonzero write bulk status received: %d", __FUNCTION__, urb->status);
 		return;
 	}
 
+	usb_serial_debug_data (
+		__FILE__,
+		__FUNCTION__,
+		urb->actual_length,
+		urb->transfer_buffer);
+
 	queue_task(&port->tqueue, &tq_immediate);
 	mark_bh(IMMEDIATE_BH);
 	
@@ -361,34 +435,87 @@
 	if (port_paranoia_check (port, __FUNCTION__))
 		return;
 
-	dbg(__FUNCTION__ " - port %d", port->number);
+	dbg("%s - port %d", __FUNCTION__, port->number);
 
 	if (!serial) {
-		dbg(__FUNCTION__ " - bad serial pointer, exiting");
+		dbg("%s - bad serial pointer, exiting", __FUNCTION__);
 		return;
 	}
 
-	if (urb->status) {
-		dbg(__FUNCTION__ " - nonzero read bulk status received: %d", urb->status);
+	if (!port->active) {
+		dbg("%s - port closed.", __FUNCTION__);
 		return;
 	}
 
-	usb_serial_debug_data (__FILE__, __FUNCTION__, urb->actual_length, data);
+	switch (urb->status) {
+
+		case 0: /* Successful */
+
+			/*
+			 * The first byte of the packet we get from the device
+			 * contains a busy indicator and baud rate change.
+			 * See section 5.4.1.2 of the USB IrDA spec.
+			 */
+			if((*data & 0x0f) > 0) ir_baud = *data & 0x0f;
+
+			usb_serial_debug_data (
+				__FILE__,
+				__FUNCTION__,
+				urb->actual_length,
+				data);
+
+			/*
+			 * Bypass flip-buffers, and feed the ldisc directly
+			 * due to our potentally large buffer size.  Since we
+			 * used to set low_latency, this is exactly what the
+			 * tty layer did anyway :)
+			 */
+			tty = port->tty;
+
+			tty->ldisc.receive_buf(
+				tty,
+				data+1,
+				NULL,
+				urb->actual_length-1);
+
+			/*
+			 * No break here.
+			 * We want to resubmit the urb so we can read
+			 * again.
+			 */
+
+		case -EPROTO: /* taking inspiration from pl2303.c */
+
+			/* Continue trying to always read */
+			usb_fill_bulk_urb (
+				port->read_urb,
+				serial->dev, 
+				usb_rcvbulkpipe(serial->dev,
+					port->bulk_in_endpointAddress),
+				port->read_urb->transfer_buffer,
+				port->read_urb->transfer_buffer_length,
+				ir_read_bulk_callback,
+				port);
+
+			port->read_urb->transfer_flags = USB_QUEUE_BULK;
+
+			result = usb_submit_urb(port->read_urb);
+
+			if (result)
+				err("%s - failed resubmitting read urb, error %d",
+					__FUNCTION__, 
+					result);
+
+			break ;
+
+		default:
+			dbg("%s - nonzero read bulk status received: %d",
+				__FUNCTION__, 
+				urb->status);
+			break ;
+
+	}
 
-	/* Bypass flip-buffers, and feed the ldisc directly due to our 
-	 * potentally large buffer size.  Since we used to set low_latency,
-	 * this is exactly what the tty layer did anyway :) */
-	tty = port->tty;
-	tty->ldisc.receive_buf(tty, data+1, NULL, urb->actual_length-1);
-
-	/* Continue trying to always read  */
-	FILL_BULK_URB(port->read_urb, serial->dev, 
-		      usb_rcvbulkpipe(serial->dev, port->bulk_in_endpointAddress),
-		      port->read_urb->transfer_buffer, port->read_urb->transfer_buffer_length,
-		      ir_read_bulk_callback, port);
-	result = usb_submit_urb(port->read_urb);
-	if (result)
-		err(__FUNCTION__ " - failed resubmitting read urb, error %d", result);
 	return;
 }
 
@@ -397,12 +524,11 @@
 	unsigned char *transfer_buffer;
 	unsigned int cflag;
 	int result;
-	u8 baud;
 
-	dbg(__FUNCTION__ " - port %d", port->number);
+	dbg("%s - port %d", __FUNCTION__, port->number);
 
 	if ((!port->tty) || (!port->tty->termios)) {
-		dbg(__FUNCTION__" - no tty structures");
+		dbg("%s - no tty structures", __FUNCTION__);
 		return;
 	}
 
@@ -411,44 +537,70 @@
 	if (old_termios) {
 		if ((cflag == old_termios->c_cflag) &&
 		    (RELEVANT_IFLAG(port->tty->termios->c_iflag) == RELEVANT_IFLAG(old_termios->c_iflag))) {
-			dbg(__FUNCTION__ " - nothing to change...");
+			dbg("%s - nothing to change...", __FUNCTION__);
 			return;
 		}
 	}
 
 	/* All we can change is the baud rate */
 	if (cflag & CBAUD) {
-		dbg (__FUNCTION__ " - asking for baud %d", tty_get_baud_rate(port->tty));
+
+		dbg ("%s - asking for baud %d",
+			__FUNCTION__,
+			tty_get_baud_rate(port->tty));
+
 		/* 
 		 * FIXME, we should compare the baud request against the
 		 * capability stated in the IR header that we got in the
 		 * startup funtion.
 		 */
 		switch (cflag & CBAUD) {
-			case B2400:	baud = SPEED_2400;	break;
-			case B9600:	baud = SPEED_9600;	break;
-			case B19200:	baud = SPEED_19200;	break;
-			case B38400:	baud = SPEED_38400;	break;
-			case B57600:	baud = SPEED_57600;	break;
-			case B115200:	baud = SPEED_115200;	break;
-			case B576000:	baud = SPEED_576000;	break;
-			case B1152000:	baud = SPEED_1152000;	break;
-			case B4000000:	baud = SPEED_4000000;	break;
+			case B2400:    ir_baud = SPEED_2400;    break;
 			default:
-				err ("ir-usb driver does not support the baudrate (%d) requested", tty_get_baud_rate(port->tty));
-				return;
+			case B9600:    ir_baud = SPEED_9600;    break;
+			case B19200:   ir_baud = SPEED_19200;   break;
+			case B38400:   ir_baud = SPEED_38400;   break;
+			case B57600:   ir_baud = SPEED_57600;   break;
+			case B115200:  ir_baud = SPEED_115200;  break;
+			case B576000:  ir_baud = SPEED_576000;  break;
+			case B1152000: ir_baud = SPEED_1152000; break;
+			case B4000000: ir_baud = SPEED_4000000; break;
 		}
-		
+
+		if (xbof == -1) {
+			ir_xbof = ir_xbof_change(ir_add_bof);
+		} else {
+			ir_xbof = ir_xbof_change(xbof) ;
+		}
+
+		/* Notify the tty driver that the termios have changed. */
+		port->tty->ldisc.set_termios(port->tty, NULL);
+
 		/* FIXME need to check to see if our write urb is busy right
-		 * now, or use a urb pool. */
-		/* send the baud change out on an "empty" data packet */
+		 * now, or use a urb pool.
+		 *
+		 * send the baud change out on an "empty" data packet
+		 */
 		transfer_buffer = port->write_urb->transfer_buffer;
-		transfer_buffer[0] = baud;
-		port->write_urb->transfer_buffer_length = 1;
-		port->write_urb->dev = port->serial->dev;
+		*transfer_buffer = ir_xbof | ir_baud;
+
+		usb_fill_bulk_urb (
+			port->write_urb,
+			port->serial->dev,
+			usb_sndbulkpipe(port->serial->dev,
+				port->bulk_out_endpointAddress),
+			port->write_urb->transfer_buffer,
+			1,
+			ir_write_bulk_callback,
+			port);
+
+		port->write_urb->transfer_flags
+			= USB_QUEUE_BULK
+			| USB_ZERO_PACKET;
+
 		result = usb_submit_urb (port->write_urb);
 		if (result)
-			err(__FUNCTION__ " - failed submitting write urb, error %d", result);
+			err("%s - failed submitting write urb, error %d", __FUNCTION__, result);
 	}
 	return;
 }
@@ -477,6 +629,8 @@
 
 MODULE_PARM(debug, "i");
 MODULE_PARM_DESC(debug, "Debug enabled or not");
+MODULE_PARM(xbof, "i");
+MODULE_PARM_DESC(xbof, "Force specific number of XBOFs");
 MODULE_PARM(buffer_size, "i");
 MODULE_PARM_DESC(buffer_size, "Size of the transfer buffers");
 
diff -urN linux-2.4.18-pre4/drivers/usb/serial/usb-serial.h linux/drivers/usb/serial/usb-serial.h
--- linux-2.4.18-pre4/drivers/usb/serial/usb-serial.h	Wed Oct 10 23:42:47 2001
+++ linux/drivers/usb/serial/usb-serial.h	Tue Jan 22 12:01:22 2002
@@ -132,8 +132,12 @@
 
 	struct list_head	driver_list;
 	
-	/* function call to make before accepting driver */
-	/* return 0 to continue initialization, anything else to abort */
+	/* function call to make before accepting driver
+	 * return 0 to continue initialization,
+	 * < 0 aborts startup,
+	 * > 0 does not set up anything else and is useful for devices that have
+	 * downloaded firmware, and will reset themselves shortly.
+	 */
 	int (*startup) (struct usb_serial *serial);
 	
 	void (*shutdown) (struct usb_serial *serial);
diff -urN linux-2.4.18-pre4/drivers/usb/serial/usbserial.c linux/drivers/usb/serial/usbserial.c
--- linux-2.4.18-pre4/drivers/usb/serial/usbserial.c	Fri Dec 21 09:41:55 2001
+++ linux/drivers/usb/serial/usbserial.c	Tue Jan 22 12:01:22 2002
@@ -1203,9 +1203,11 @@
 
 	/* if this device type has a startup function, call it */
 	if (type->startup) {
-		if (type->startup (serial)) {
+		i = type->startup (serial);
+		if (i < 0)
 			goto probe_error;
-		}
+		if (i > 0)
+			return serial;
 	}
 
 	/* set up the endpoint information */
diff -urN linux-2.4.18-pre4/drivers/usb/storage/protocol.c linux/drivers/usb/storage/protocol.c
--- linux-2.4.18-pre4/drivers/usb/storage/protocol.c	Sun Jul 29 21:11:50 2001
+++ linux/drivers/usb/storage/protocol.c	Tue Jan 22 12:01:22 2002
@@ -1,6 +1,6 @@
 /* Driver for USB Mass Storage compliant devices
  *
- * $Id: protocol.c,v 1.10 2001/07/30 00:27:59 mdharm Exp $
+ * $Id: protocol.c,v 1.11 2002/01/13 06:40:25 mdharm Exp $
  *
  * Current development and maintenance by:
  *   (c) 1999, 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net)
@@ -76,7 +76,7 @@
 		data_ptr = (unsigned char *)srb->request_buffer;
 
 	/* Change the SCSI revision number */
-	data_ptr[2] |= 0x2;
+	data_ptr[2] = (data_ptr[2] & ~7) | 2;
 }
 
 /***********************************************************************
diff -urN linux-2.4.18-pre4/drivers/usb/storage/unusual_devs.h linux/drivers/usb/storage/unusual_devs.h
--- linux-2.4.18-pre4/drivers/usb/storage/unusual_devs.h	Tue Jan 22 12:01:20 2002
+++ linux/drivers/usb/storage/unusual_devs.h	Tue Jan 22 12:01:22 2002
@@ -1,7 +1,7 @@
 /* Driver for USB Mass Storage compliant devices
  * Ununsual Devices File
  *
- * $Id: unusual_devs.h,v 1.24 2001/12/29 03:12:45 mdharm Exp $
+ * $Id: unusual_devs.h,v 1.25 2002/01/13 06:39:17 mdharm Exp $
  *
  * Current development and maintenance by:
  *   (c) 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net)
@@ -458,6 +458,14 @@
                 US_SC_ISD200, US_PR_BULK, isd200_Initialization,
                 0 ),
 #endif
+
+/* Submitted by Brian Hall <brihall@bigfoot.com>
+ * Needed for START_STOP flag */
+UNUSUAL_DEV(  0x0c76, 0x0003, 0x0100, 0x0100,
+		"JMTek",
+		"USBDrive",
+		US_SC_SCSI, US_PR_BULK, NULL,
+		US_FL_START_STOP ),
 
 /* Reported by Dan Pilone <pilone@slac.com>
  * The device needs the flags only.
diff -urN linux-2.4.18-pre4/drivers/usb/storage/usb.c linux/drivers/usb/storage/usb.c
--- linux-2.4.18-pre4/drivers/usb/storage/usb.c	Sun Nov 11 10:01:32 2001
+++ linux/drivers/usb/storage/usb.c	Tue Jan 22 12:01:22 2002
@@ -1,6 +1,6 @@
 /* Driver for USB Mass Storage compliant devices
  *
- * $Id: usb.c,v 1.69 2001/11/11 03:33:03 mdharm Exp $
+ * $Id: usb.c,v 1.70 2002/01/06 07:14:12 mdharm Exp $
  *
  * Current development and maintenance by:
  *   (c) 1999, 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net)
@@ -318,6 +318,13 @@
 	current->files = init_task.files;
 	atomic_inc(&current->files->count);
 	daemonize();
+
+	/* avoid getting signals */
+	spin_lock_irq(&current->sigmask_lock);
+	flush_signals(current);
+	sigfillset(&current->blocked);
+	recalc_sigpending(current);
+	spin_unlock_irq(&current->sigmask_lock);
 
 	/* set our name for identification purposes */
 	sprintf(current->comm, "usb-storage-%d", us->host_number);
diff -urN linux-2.4.18-pre4/drivers/usb/usb.c linux/drivers/usb/usb.c
--- linux-2.4.18-pre4/drivers/usb/usb.c	Wed Nov 21 09:59:11 2001
+++ linux/drivers/usb/usb.c	Tue Jan 22 12:01:22 2002
@@ -1952,6 +1952,14 @@
 		return -EINVAL;
 	}
 
+	/* 9.4.10 says devices don't need this, if the interface
+	   only has one alternate setting */
+	if (iface->num_altsetting == 1) {
+		warn("ignoring set_interface for dev %d, iface %d, alt %d",
+			dev->devnum, interface, alternate);
+		return 0;
+	}
+
 	if ((ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
 	    USB_REQ_SET_INTERFACE, USB_RECIP_INTERFACE, alternate,
 	    interface, NULL, 0, HZ * 5)) < 0)
diff -urN linux-2.4.18-pre4/drivers/video/Config.in linux/drivers/video/Config.in
--- linux-2.4.18-pre4/drivers/video/Config.in	Wed Nov 14 15:16:31 2001
+++ linux/drivers/video/Config.in	Tue Jan 22 12:01:22 2002
@@ -121,14 +121,14 @@
 	 if [ "$CONFIG_FB_MATROX" != "n" ]; then
 	    bool '    Millennium I/II support' CONFIG_FB_MATROX_MILLENIUM
 	    bool '    Mystique support' CONFIG_FB_MATROX_MYSTIQUE
-	    bool '    G100/G200/G400/G450 support' CONFIG_FB_MATROX_G100
+	    bool '    G100/G200/G400/G450/G550 support' CONFIG_FB_MATROX_G100
             if [ "$CONFIG_I2C" != "n" ]; then
 	       dep_tristate '      Matrox I2C support' CONFIG_FB_MATROX_I2C $CONFIG_FB_MATROX $CONFIG_I2C_ALGOBIT
 	       if [ "$CONFIG_FB_MATROX_G100" = "y" ]; then
 	          dep_tristate '      G400 second head support' CONFIG_FB_MATROX_MAVEN $CONFIG_FB_MATROX_I2C
 	       fi
             fi
-            dep_tristate '      G450 second head support' CONFIG_FB_MATROX_G450 $CONFIG_FB_MATROX_G100
+            dep_tristate '      G450/G550 second head support' CONFIG_FB_MATROX_G450 $CONFIG_FB_MATROX_G100
 	    bool '    Multihead support' CONFIG_FB_MATROX_MULTIHEAD
 	 fi
 	 tristate '  ATI Mach64 display support (EXPERIMENTAL)' CONFIG_FB_ATY
diff -urN linux-2.4.18-pre4/drivers/video/aty/atyfb_base.c linux/drivers/video/aty/atyfb_base.c
--- linux-2.4.18-pre4/drivers/video/aty/atyfb_base.c	Tue Jan 22 12:01:21 2002
+++ linux/drivers/video/aty/atyfb_base.c	Tue Jan 22 12:01:22 2002
@@ -350,7 +350,7 @@
     { 0x4751, 0x4751, 0x00, 0x00, m64n_gtc_ppl, 230, 100, M64F_GT | M64F_INTEGRATED | M64F_RESET_3D | M64F_GTB_DSP | M64F_SDRAM_MAGIC_PLL | M64F_EXTRA_BRIGHT },
 
     /* 3D RAGE XL */
-    { 0x4752, 0x4752, 0x00, 0x00, m64n_xl, 230, 120, M64F_GT | M64F_INTEGRATED | M64F_RESET_3D | M64F_GTB_DSP | M64F_SDRAM_MAGIC_PLL | M64F_EXTRA_BRIGHT | M64F_XL_DLL },
+    { 0x4752, 0x4752, 0x00, 0x00, m64n_xl, 230, 100, M64F_GT | M64F_INTEGRATED | M64F_RESET_3D | M64F_GTB_DSP | M64F_SDRAM_MAGIC_PLL | M64F_EXTRA_BRIGHT | M64F_XL_DLL },
 
     /* Mach64 LT PRO */
     { 0x4c42, 0x4c42, 0x00, 0x00, m64n_ltp_a,   230, 100, M64F_GT | M64F_INTEGRATED | M64F_RESET_3D | M64F_GTB_DSP },
diff -urN linux-2.4.18-pre4/drivers/video/aty/mach64_accel.c linux/drivers/video/aty/mach64_accel.c
--- linux-2.4.18-pre4/drivers/video/aty/mach64_accel.c	Tue Jul 31 14:43:29 2001
+++ linux/drivers/video/aty/mach64_accel.c	Tue Jan 22 12:01:22 2002
@@ -326,7 +326,7 @@
 		     fbcon_cfb##width##_clear_margins(conp, p, bottom_only), \
 		     int bottom_only) \
  \
-const struct display_switch fbcon_aty##width## = { \
+const struct display_switch fbcon_aty##width = { \
     setup:		fbcon_cfb##width##_setup, \
     bmove:		fbcon_aty_bmove, \
     clear:		fbcon_aty_clear, \
diff -urN linux-2.4.18-pre4/drivers/video/radeon.h linux/drivers/video/radeon.h
--- linux-2.4.18-pre4/drivers/video/radeon.h	Thu Oct 25 13:53:52 2001
+++ linux/drivers/video/radeon.h	Tue Jan 22 12:01:22 2002
@@ -96,7 +96,9 @@
 #define MEM_VGA_WP_SEL                         0x0038  
 #define MEM_VGA_RP_SEL                         0x003C  
 #define HDP_DEBUG                              0x0138  
-#define SW_SEMAPHORE                           0x013C  
+#define SW_SEMAPHORE                           0x013C
+#define CRTC2_GEN_CNTL                         0x03f8  
+#define CRTC2_DISPLAY_BASE_ADDR                0x033c
 #define SURFACE_CNTL                           0x0B00  
 #define SURFACE0_LOWER_BOUND                   0x0B04  
 #define SURFACE1_LOWER_BOUND                   0x0B14  
@@ -337,6 +339,7 @@
 #define DST_Y_X				       0x1438
 #define DST_WIDTH_HEIGHT		       0x1598
 #define DST_HEIGHT_WIDTH		       0x143c
+#define DST_OFFSET                             0x1404
 #define SRC_CLUT_ADDRESS                       0x1780  
 #define SRC_CLUT_DATA                          0x1784  
 #define SRC_CLUT_DATA_RD                       0x1788  
@@ -380,6 +383,7 @@
 #define LVDS_GEN_CNTL			       0x02d0
 #define LVDS_PLL_CNTL			       0x02d4
 #define TMDS_CRC			       0x02a0
+#define TMDS_TRANSMITTER_CNTL		       0x02a4
 
 #define RADEON_BASE_CODE		       0x0f0b
 #define RADEON_BIOS_0_SCRATCH		       0x0010
@@ -406,11 +410,11 @@
 #define SPLL_CNTL                                  0x000c
 #define SCLK_CNTL                                  0x000d
 #define MPLL_CNTL                                  0x000e
+#define MDLL_CKO                                   0x000f
 #define MCLK_CNTL                                  0x0012
 #define AGP_PLL_CNTL                               0x000b
 #define PLL_TEST_CNTL                              0x0013
 
-
 /* MCLK_CNTL bit constants */
 #define FORCEON_MCLKA				   (1 << 16)
 #define FORCEON_MCLKB         		   	   (1 << 17)
@@ -474,10 +478,17 @@
 #define CRTC_INTERLACE_EN			   (1 << 1)
 #define CRTC_EXT_DISP_EN      			   (1 << 24)
 #define CRTC_EN					   (1 << 25)
+#define CRTC_DISP_REQ_EN_B                         (1 << 26)
 
 /* CRTC_STATUS bit constants */
 #define CRTC_VBLANK                                0x00000001
 
+/* CRTC2_GEN_CNTL bit constants */
+#define CRT2_ON                                    (1 << 7)
+#define CRTC2_DISPLAY_DIS                          (1 << 23)
+#define CRTC2_EN                                   (1 << 25)
+#define CRTC2_DISP_REQ_EN_B                        (1 << 26)
+
 /* CUR_OFFSET, CUR_HORZ_VERT_POSN, CUR_HORZ_VERT_OFF bit constants */
 #define CUR_LOCK                                   0x80000000
 
@@ -523,14 +534,26 @@
 #define LVDS_PANEL_TYPE				   (1 << 2)
 #define LVDS_PANEL_FORMAT			   (1 << 3)
 #define LVDS_EN					   (1 << 7)
+#define LVDS_BL_MOD_LEVEL_MASK			   0x0000ff00
+#define LVDS_BL_MOD_LEVEL_SHIFT			   8
+#define LVDS_BL_MOD_EN				   (1 << 16)
 #define LVDS_DIGON				   (1 << 18)
 #define LVDS_BLON				   (1 << 19)
 #define LVDS_SEL_CRTC2				   (1 << 23)
+#define LVDS_STATE_MASK	\
+	(LVDS_ON | LVDS_DISPLAY_DIS | LVDS_BL_MOD_LEVEL_MASK | \
+	 LVDS_EN | LVDS_DIGON | LVDS_BLON)
 
 /* LVDS_PLL_CNTL bit constatns */
 #define HSYNC_DELAY_SHIFT			   0x1c
 #define HSYNC_DELAY_MASK			   (0xf << 0x1c)
 
+/* TMDS_TRANSMITTER_CNTL bit constants */
+#define TMDS_PLL_EN				   (1 << 0)
+#define TMDS_PLLRST				   (1 << 1)
+#define TMDS_RAN_PAT_RST			   (1 << 7)
+#define ICHCSEL					   (1 << 28)
+
 /* FP_HORZ_STRETCH bit constants */
 #define HORZ_STRETCH_RATIO_MASK			   0xffff
 #define HORZ_STRETCH_RATIO_MAX			   4096
@@ -561,6 +584,7 @@
 #define DAC_4BPP_PIX_ORDER                         0x00000200
 #define DAC_CRC_EN                                 0x00080000
 #define DAC_MASK_ALL				   (0xff << 24)
+#define DAC_EXPAND_MODE				   (1 << 14)
 #define DAC_VGA_ADR_EN				   (1 << 13)
 #define DAC_RANGE_CNTL				   (3 << 0)
 #define DAC_BLANKING				   (1 << 2)
@@ -742,6 +766,15 @@
 #define DP_SRC_HOST                                0x00000300
 #define DP_SRC_HOST_BYTEALIGN                      0x00000400
 
+/* MPLL_CNTL bit constants */
+#define MPLL_RESET                                 0x00000001
+
+/* MDLL_CKO bit constants */
+#define MDLL_CKO__MCKOA_RESET                      0x00000002
+
+/* VCLK_ECP_CNTL constants */
+#define PIXCLK_ALWAYS_ONb                          0x00000040
+#define PIXCLK_DAC_ALWAYS_ONb                      0x00000080
 
 /* masks */
 
diff -urN linux-2.4.18-pre4/drivers/video/radeonfb.c linux/drivers/video/radeonfb.c
--- linux-2.4.18-pre4/drivers/video/radeonfb.c	Tue Jan 22 12:01:21 2002
+++ linux/drivers/video/radeonfb.c	Tue Jan 22 12:01:22 2002
@@ -18,13 +18,14 @@
  *	2001-11-17	Radeon M6 (ppc) support, Daniel Berlin, 0.1.2
  *	2001-11-18	DFP fixes, Kevin Hendricks, 0.1.3
  *	2001-11-29	more cmap, backlight fixes, Benjamin Herrenschmidt
+ *	2002-01-18	DFP panel detection via BIOS, Michael Clark, 0.1.4
  *
  *	Special thanks to ATI DevRel team for their hardware donations.
  *
  */
 
 
-#define RADEON_VERSION	"0.1.3"
+#define RADEON_VERSION	"0.1.4"
 
 
 #include <linux/config.h>
@@ -263,6 +264,7 @@
 	struct pci_dev *pdev;
 
 	unsigned char *EDID;
+	unsigned char *bios_seg;
 
 	struct display disp;
 	int currcon;
@@ -277,6 +279,7 @@
 	int xres, yres, pixclock;
 
 	int use_default_var;
+	int got_dfpinfo;
 
 	int hasCRTC2;
 	int crtDisp_type;
@@ -646,6 +649,7 @@
 static void radeon_get_pllinfo(struct radeonfb_info *rinfo, char *bios_seg);
 static void radeon_get_moninfo (struct radeonfb_info *rinfo);
 static int radeon_get_dfpinfo (struct radeonfb_info *rinfo);
+static int radeon_get_dfpinfo_BIOS(struct radeonfb_info *rinfo);
 static void radeon_get_EDID(struct radeonfb_info *rinfo);
 static int radeon_dfp_parse_EDID(struct radeonfb_info *rinfo);
 static void radeon_update_default_var(struct radeonfb_info *rinfo);
@@ -750,7 +754,6 @@
 	struct radeonfb_info *rinfo;
 	u32 tmp;
 	int i, j;
-	char *bios_seg = NULL;
 
 	RTRACE("radeonfb_pci_register BEGIN\n");
 
@@ -909,8 +912,8 @@
 			break;
 	}
 
-	bios_seg = radeon_find_rom(rinfo);
-	radeon_get_pllinfo(rinfo, bios_seg);
+	rinfo->bios_seg = radeon_find_rom(rinfo);
+	radeon_get_pllinfo(rinfo, rinfo->bios_seg);
 
 	RTRACE("radeonfb: probed %s %dk videoram\n", (rinfo->ram_type), (rinfo->video_ram/1024));
 
@@ -1327,6 +1330,11 @@
 			rinfo->vAct_high = 1;
 	}
 
+	printk("radeonfb: detected DFP panel size from EDID: %dx%d\n",
+		rinfo->panel_xres, rinfo->panel_yres);
+
+	rinfo->got_dfpinfo = 1;
+
 	return 1;
 }
 
@@ -1364,77 +1372,139 @@
 }
 
 
+static int radeon_get_dfpinfo_BIOS(struct radeonfb_info *rinfo)
+{
+	char *fpbiosstart, *tmp, *tmp0;
+	char stmp[30];
+	int i;
+
+	if (!rinfo->bios_seg)
+		return 0;
+
+	if (!(fpbiosstart = rinfo->bios_seg + readw(rinfo->bios_seg + 0x48))) {
+		printk("radeonfb: Failed to detect DFP panel info using BIOS\n");
+		return 0;
+	}
+
+	if (!(tmp = rinfo->bios_seg + readw(fpbiosstart + 0x40))) {
+		printk("radeonfb: Failed to detect DFP panel info using BIOS\n");
+		return 0;
+	}
+
+	for(i=0; i<24; i++)
+		stmp[i] = readb(tmp+i+1);
+	stmp[24] = 0;
+	printk("radeonfb: panel ID string: %s\n", stmp);
+	rinfo->panel_xres = readw(tmp + 25);
+	rinfo->panel_yres = readw(tmp + 27);
+	printk("radeonfb: detected DFP panel size from BIOS: %dx%d\n",
+		rinfo->panel_xres, rinfo->panel_yres);
+
+	for(i=0; i<20; i++) {
+		tmp0 = rinfo->bios_seg + readw(tmp+64+i*2);
+		if (tmp0 == 0)
+			break;
+		if ((readw(tmp0) == rinfo->panel_xres) &&
+		    (readw(tmp0+2) == rinfo->panel_yres)) {
+			rinfo->hblank = (readw(tmp0+17) - readw(tmp0+19)) * 8;
+			rinfo->hOver_plus = ((readw(tmp0+21) - readw(tmp0+19) -1) * 8) & 0x7fff;
+			rinfo->hSync_width = readb(tmp0+23) * 8;
+			rinfo->vblank = readw(tmp0+24) - readw(tmp0+26);
+			rinfo->vOver_plus = (readw(tmp0+28) & 0x7ff) - readw(tmp0+26);
+			rinfo->vSync_width = (readw(tmp0+28) & 0xf800) >> 11;
+			rinfo->clock = readw(tmp0+9);
+
+			rinfo->got_dfpinfo = 1;
+			return 1;
+		}
+	}
+
+	return 0;
+}
+
+
 
 static int radeon_get_dfpinfo (struct radeonfb_info *rinfo)
 {
 	unsigned int tmp;
 	unsigned short a, b;
 
+	if (radeon_get_dfpinfo_BIOS(rinfo))
+		radeon_update_default_var(rinfo);
+
 	if (radeon_dfp_parse_EDID(rinfo))
 		radeon_update_default_var(rinfo);
 
-	if (panel_yres) {
-		rinfo->panel_yres = panel_yres;
-	} else {
-		tmp = INREG(FP_VERT_STRETCH);
-		tmp &= 0x00fff000;
-		rinfo->panel_yres = (unsigned short)(tmp >> 0x0c) + 1;
-	}
+	if (!rinfo->got_dfpinfo) {
+		/*
+		 * it seems all else has failed now and we
+		 * resort to probing registers for our DFP info
+	         */
+		if (panel_yres) {
+			rinfo->panel_yres = panel_yres;
+		} else {
+			tmp = INREG(FP_VERT_STRETCH);
+			tmp &= 0x00fff000;
+			rinfo->panel_yres = (unsigned short)(tmp >> 0x0c) + 1;
+		}
 
-	switch (rinfo->panel_yres) {
-		case 480:
-			rinfo->panel_xres = 640;
-			break;
-		case 600:
-			rinfo->panel_xres = 800;
-			break;
-		case 768:
+		switch (rinfo->panel_yres) {
+			case 480:
+				rinfo->panel_xres = 640;
+				break;
+			case 600:
+				rinfo->panel_xres = 800;
+				break;
+			case 768:
 #if defined(__powerpc__)
-			if (rinfo->dviDisp_type == MT_LCD)
-				rinfo->panel_xres = 1152;
-			else
+				if (rinfo->dviDisp_type == MT_LCD)
+					rinfo->panel_xres = 1152;
+				else
 #endif
-			rinfo->panel_xres = 1024;
-			break;
-		case 1024:
-			rinfo->panel_xres = 1280;
-			break;
-		case 1050:
-			rinfo->panel_xres = 1400;
-			break;
-		case 1200:
-			rinfo->panel_xres = 1600;
-			break;
-		default:
-			printk("radeonfb: Failed to detect DFP panel size\n");
-			return 0;
-	}
+				rinfo->panel_xres = 1024;
+				break;
+			case 1024:
+				rinfo->panel_xres = 1280;
+				break;
+			case 1050:
+				rinfo->panel_xres = 1400;
+				break;
+			case 1200:
+				rinfo->panel_xres = 1600;
+				break;
+			default:
+				printk("radeonfb: Failed to detect DFP panel size\n");
+				return 0;
+		}
 
-	printk("radeonfb: detected DFP panel size: %dx%d\n",
-		rinfo->panel_xres, rinfo->panel_yres);
+		printk("radeonfb: detected DFP panel size from registers: %dx%d\n",
+			rinfo->panel_xres, rinfo->panel_yres);
+
+		tmp = INREG(FP_CRTC_H_TOTAL_DISP);
+		a = (tmp & FP_CRTC_H_TOTAL_MASK) + 4;
+		b = (tmp & 0x01ff0000) >> FP_CRTC_H_DISP_SHIFT;
+		rinfo->hblank = (a - b + 1) * 8;
+
+		tmp = INREG(FP_H_SYNC_STRT_WID);
+		rinfo->hOver_plus = (unsigned short) ((tmp & FP_H_SYNC_STRT_CHAR_MASK) >>
+					FP_H_SYNC_STRT_CHAR_SHIFT) - b - 1;
+		rinfo->hOver_plus *= 8;
+		rinfo->hSync_width = (unsigned short) ((tmp & FP_H_SYNC_WID_MASK) >>
+					FP_H_SYNC_WID_SHIFT);
+		rinfo->hSync_width *= 8;
+		tmp = INREG(FP_CRTC_V_TOTAL_DISP);
+		a = (tmp & FP_CRTC_V_TOTAL_MASK) + 1;
+		b = (tmp & FP_CRTC_V_DISP_MASK) >> FP_CRTC_V_DISP_SHIFT;
+		rinfo->vblank = a - b /* + 24 */ ;
+
+		tmp = INREG(FP_V_SYNC_STRT_WID);
+		rinfo->vOver_plus = (unsigned short) (tmp & FP_V_SYNC_STRT_MASK)
+					- b + 1;
+		rinfo->vSync_width = (unsigned short) ((tmp & FP_V_SYNC_WID_MASK) >>
+					FP_V_SYNC_WID_SHIFT);
 
-	tmp = INREG(FP_CRTC_H_TOTAL_DISP);
-	a = (tmp & FP_CRTC_H_TOTAL_MASK) + 4;
-	b = (tmp & 0x01ff0000) >> FP_CRTC_H_DISP_SHIFT;
-	rinfo->hblank = (a - b + 1) * 8;
-
-	tmp = INREG(FP_H_SYNC_STRT_WID);
-	rinfo->hOver_plus = (unsigned short) ((tmp & FP_H_SYNC_STRT_CHAR_MASK) >>
-				FP_H_SYNC_STRT_CHAR_SHIFT) - b - 1;
-	rinfo->hOver_plus *= 8;
-	rinfo->hSync_width = (unsigned short) ((tmp & FP_H_SYNC_WID_MASK) >>
-				FP_H_SYNC_WID_SHIFT);
-	rinfo->hSync_width *= 8;
-	tmp = INREG(FP_CRTC_V_TOTAL_DISP);
-	a = (tmp & FP_CRTC_V_TOTAL_MASK) + 1;
-	b = (tmp & FP_CRTC_V_DISP_MASK) >> FP_CRTC_V_DISP_SHIFT;
-	rinfo->vblank = a - b /* + 24 */ ;
-
-	tmp = INREG(FP_V_SYNC_STRT_WID);
-	rinfo->vOver_plus = (unsigned short) (tmp & FP_V_SYNC_STRT_MASK)
-				- b + 1;
-	rinfo->vSync_width = (unsigned short) ((tmp & FP_V_SYNC_WID_MASK) >>
-				FP_V_SYNC_WID_SHIFT);
+		return 1;
+	}
 
 	return 1;
 }
@@ -2949,7 +3019,6 @@
 	OUTREG(DST_Y_X, (srcy << 16) | srcx);
 	OUTREG(DST_WIDTH_HEIGHT, (width << 16) | height);
 }
-
 
 
 
diff -urN linux-2.4.18-pre4/fs/Config.in linux/fs/Config.in
--- linux-2.4.18-pre4/fs/Config.in	Mon Nov 12 09:34:16 2001
+++ linux/fs/Config.in	Tue Jan 22 12:01:23 2002
@@ -8,9 +8,9 @@
 tristate 'Kernel automounter support' CONFIG_AUTOFS_FS
 tristate 'Kernel automounter version 4 support (also supports v3)' CONFIG_AUTOFS4_FS
 
-dep_tristate 'Reiserfs support' CONFIG_REISERFS_FS $CONFIG_EXPERIMENTAL
-dep_mbool '  Have reiserfs do extra internal checking' CONFIG_REISERFS_CHECK $CONFIG_REISERFS_FS $CONFIG_EXPERIMENTAL
-dep_mbool '  Stats in /proc/fs/reiserfs' CONFIG_REISERFS_PROC_INFO $CONFIG_REISERFS_FS $CONFIG_EXPERIMENTAL
+tristate 'Reiserfs support' CONFIG_REISERFS_FS
+dep_mbool '  Have reiserfs do extra internal checking' CONFIG_REISERFS_CHECK $CONFIG_REISERFS_FS
+dep_mbool '  Stats in /proc/fs/reiserfs' CONFIG_REISERFS_PROC_INFO $CONFIG_REISERFS_FS
 
 dep_tristate 'ADFS file system support' CONFIG_ADFS_FS $CONFIG_EXPERIMENTAL
 dep_mbool '  ADFS write support (DANGEROUS)' CONFIG_ADFS_FS_RW $CONFIG_ADFS_FS $CONFIG_EXPERIMENTAL
diff -urN linux-2.4.18-pre4/fs/buffer.c linux/fs/buffer.c
--- linux-2.4.18-pre4/fs/buffer.c	Tue Jan 22 12:01:21 2002
+++ linux/fs/buffer.c	Tue Jan 22 12:01:23 2002
@@ -1686,7 +1686,7 @@
 	do {
 		block_end = block_start+blocksize;
 		if (block_end <= from)
-			continue;
+			goto next_bh;
 		if (block_start >= to)
 			break;
 		if (buffer_new(bh)) {
@@ -1696,6 +1696,7 @@
 			set_bit(BH_Uptodate, &bh->b_state);
 			mark_buffer_dirty(bh);
 		}
+next_bh:
 		block_start = block_end;
 		bh = bh->b_this_page;
 	} while (bh != head);
@@ -1820,6 +1821,52 @@
 	return 0;
 }
 
+/* utility function for filesystems that need to do work on expanding
+ * truncates.  Uses prepare/commit_write to allow the filesystem to
+ * deal with the hole.  
+ */
+int generic_cont_expand(struct inode *inode, loff_t size)
+{
+	struct address_space *mapping = inode->i_mapping;
+	struct page *page;
+	unsigned long index, offset, limit;
+	int err;
+
+	err = -EFBIG;
+        limit = current->rlim[RLIMIT_FSIZE].rlim_cur;
+	if (limit != RLIM_INFINITY && size > (loff_t)limit) {
+		send_sig(SIGXFSZ, current, 0);
+		goto out;
+	}
+	if (size > inode->i_sb->s_maxbytes)
+		goto out;
+
+	offset = (size & (PAGE_CACHE_SIZE-1)); /* Within page */
+
+	/* ugh.  in prepare/commit_write, if from==to==start of block, we 
+	** skip the prepare.  make sure we never send an offset for the start
+	** of a block
+	*/
+	if ((offset & (inode->i_sb->s_blocksize - 1)) == 0) {
+		offset++;
+	}
+	index = size >> PAGE_CACHE_SHIFT;
+	err = -ENOMEM;
+	page = grab_cache_page(mapping, index);
+	if (!page)
+		goto out;
+	err = mapping->a_ops->prepare_write(NULL, page, offset, offset);
+	if (!err) {
+		err = mapping->a_ops->commit_write(NULL, page, offset, offset);
+	}
+	UnlockPage(page);
+	page_cache_release(page);
+	if (err > 0)
+		err = 0;
+out:
+	return err;
+}
+
 /*
  * For moronic filesystems that do not allow holes in file.
  * We may have to extend the file.
@@ -2063,8 +2110,10 @@
 {
 	int i, nr_blocks, retval;
 	unsigned long * blocks = iobuf->blocks;
+	int length;
 
-	nr_blocks = iobuf->length / blocksize;
+	length = iobuf->length;
+	nr_blocks = length / blocksize;
 	/* build the blocklist */
 	for (i = 0; i < nr_blocks; i++, blocknr++) {
 		struct buffer_head bh;
@@ -2074,8 +2123,14 @@
 		bh.b_size = blocksize;
 
 		retval = get_block(inode, blocknr, &bh, rw == READ ? 0 : 1);
-		if (retval)
-			goto out;
+		if (retval) {
+			if (!i)
+				/* report error to userspace */
+				goto out;
+			else
+				/* do short I/O utill 'i' */
+				break;
+		}
 
 		if (rw == READ) {
 			if (buffer_new(&bh))
@@ -2094,9 +2149,13 @@
 		blocks[i] = bh.b_blocknr;
 	}
 
+	/* patch length to handle short I/O */
+	iobuf->length = i * blocksize;
 	retval = brw_kiovec(rw, 1, &iobuf, inode->i_dev, iobuf->blocks, blocksize);
-
+	/* restore orig length */
+	iobuf->length = length;
  out:
+
 	return retval;
 }
 
diff -urN linux-2.4.18-pre4/fs/devfs/base.c linux/fs/devfs/base.c
--- linux-2.4.18-pre4/fs/devfs/base.c	Fri Dec 21 09:41:55 2001
+++ linux/fs/devfs/base.c	Tue Jan 22 12:01:23 2002
@@ -1,6 +1,6 @@
 /*  devfs (Device FileSystem) driver.
 
-    Copyright (C) 1998-2001  Richard Gooch
+    Copyright (C) 1998-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
@@ -592,6 +592,22 @@
 	       Added poisoning to <devfs_put>.
 	       Improved debugging messages.
   v1.7
+    20011221   Richard Gooch <rgooch@atnf.csiro.au>
+	       Corrected (made useful) debugging message in <unregister>.
+	       Moved <kmem_cache_create> in <mount_devfs_fs> to <init_devfs_fs>
+    20011224   Richard Gooch <rgooch@atnf.csiro.au>
+	       Added magic number to guard against scribbling drivers.
+    20011226   Richard Gooch <rgooch@atnf.csiro.au>
+	       Only return old entry in <devfs_mk_dir> if a directory.
+	       Defined macros for error and debug messages.
+  v1.8
+    20020113   Richard Gooch <rgooch@atnf.csiro.au>
+	       Fixed (rare, old) race in <devfs_lookup>.
+  v1.9
+    20020120   Richard Gooch <rgooch@atnf.csiro.au>
+	       Fixed deadlock bug in <devfs_d_revalidate_wait>.
+	       Tag VFS deletable in <devfs_mk_symlink> if handle ignored.
+  v1.10
 */
 #include <linux/types.h>
 #include <linux/errno.h>
@@ -624,7 +640,7 @@
 #include <asm/bitops.h>
 #include <asm/atomic.h>
 
-#define DEVFS_VERSION            "1.7 (20011216)"
+#define DEVFS_VERSION            "1.10 (20020120)"
 
 #define DEVFS_NAME "devfs"
 
@@ -633,6 +649,7 @@
 #define STRING_LENGTH 256
 #define FAKE_BLOCK_SIZE 1024
 #define POISON_PTR ( *(void **) poison_array )
+#define MAGIC_VALUE 0x327db823
 
 #ifndef TRUE
 #  define TRUE 1
@@ -669,9 +686,28 @@
 #define OPTION_MOUNT            0x01
 #define OPTION_ONLY             0x02
 
-#define OOPS(format, args...) {printk (format, ## args); \
-                               printk ("Forcing Oops\n"); \
-                               BUG();}
+#define PRINTK(format, args...) \
+   {printk (KERN_ERR "%s" format, __FUNCTION__ , ## args);}
+
+#define OOPS(format, args...) \
+   {printk (KERN_CRIT "%s" format, __FUNCTION__ , ## args); \
+    printk ("Forcing Oops\n"); \
+    BUG();}
+
+#ifdef CONFIG_DEVFS_DEBUG
+#  define VERIFY_ENTRY(de) \
+   {if ((de) && (de)->magic_number != MAGIC_VALUE) \
+        OOPS ("(%p): bad magic value: %x\n", (de), (de)->magic_number);}
+#  define WRITE_ENTRY_MAGIC(de,magic) (de)->magic_number = (magic)
+#  define DPRINTK(flag, format, args...) \
+   {if (devfs_debug & flag) \
+	printk (KERN_INFO "%s" format, __FUNCTION__ , ## args);}
+#else
+#  define VERIFY_ENTRY(de)
+#  define WRITE_ENTRY_MAGIC(de,magic)
+#  define DPRINTK(flag, format, args...)
+#endif
+
 
 struct directory_type
 {
@@ -728,6 +764,9 @@
 
 struct devfs_entry
 {
+#ifdef CONFIG_DEVFS_DEBUG
+    unsigned int magic_number;
+#endif
     void *info;
     atomic_t refcount;           /*  When this drops to zero, it's unused    */
     union 
@@ -746,7 +785,7 @@
     umode_t mode;
     unsigned short namelen;      /*  I think 64k+ filenames are a way off... */
     unsigned char hide:1;
-    unsigned char vfs_created:1; /*  Whether created by driver or VFS        */
+    unsigned char vfs_deletable:1;/*  Whether the VFS may delete the entry   */
     char name[1];                /*  This is just a dummy: the allocated array
 				     is bigger. This is NULL-terminated      */
 };
@@ -837,6 +876,7 @@
 
 static struct devfs_entry *devfs_get (struct devfs_entry *de)
 {
+    VERIFY_ENTRY (de);
     if (de) atomic_inc (&de->refcount);
     return de;
 }   /*  End Function devfs_get  */
@@ -849,25 +889,22 @@
 void devfs_put (devfs_handle_t de)
 {
     if (!de) return;
-    if (de->info == POISON_PTR)
-	OOPS ("%s: devfs_put(%p): poisoned pointer\n", DEVFS_NAME, de);
+    VERIFY_ENTRY (de);
+    if (de->info == POISON_PTR) OOPS ("(%p): poisoned pointer\n", de);
     if ( !atomic_dec_and_test (&de->refcount) ) return;
-    if (de == root_entry)
-	OOPS ("%s: devfs_put(): root entry being freed\n", DEVFS_NAME);
-#ifdef CONFIG_DEVFS_DEBUG
-    if (devfs_debug & DEBUG_FREE)
-	printk ("%s: devfs_put(%s): de: %p, parent: %p \"%s\"\n",
-		DEVFS_NAME, de->name, de, de->parent,
-		de->parent ? de->parent->name : "no parent");
-#endif
+    if (de == root_entry) OOPS ("(%p): root entry being freed\n", de);
+    DPRINTK (DEBUG_FREE, "(%s): de: %p, parent: %p \"%s\"\n",
+	     de->name, de, de->parent,
+	     de->parent ? de->parent->name : "no parent");
     if ( S_ISLNK (de->mode) ) kfree (de->u.symlink.linkname);
     if ( ( S_ISCHR (de->mode) || S_ISBLK (de->mode) ) && de->u.fcb.autogen )
     {
 	devfs_dealloc_devnum ( S_ISCHR (de->mode) ? DEVFS_SPECIAL_CHR :
 			       DEVFS_SPECIAL_BLK,
-			       MKDEV (de->u.fcb.u.device.major,
-				      de->u.fcb.u.device.minor) );
+			       mk_kdev (de->u.fcb.u.device.major,
+					de->u.fcb.u.device.minor) );
     }
+    WRITE_ENTRY_MAGIC (de, 0);
 #ifdef CONFIG_DEVFS_DEBUG
     spin_lock (&stat_lock);
     --stat_num_entries;
@@ -898,7 +935,7 @@
 
     if ( !S_ISDIR (dir->mode) )
     {
-	printk ("%s: search_dir(%s): not a directory\n", DEVFS_NAME,dir->name);
+	PRINTK ("(%s): not a directory\n", dir->name);
 	return NULL;
     }
     for (curr = dir->u.dir.first; curr != NULL; curr = curr->next)
@@ -940,6 +977,7 @@
     spin_unlock (&counter_lock);
     if (name) memcpy (new->name, name, namelen);
     new->namelen = namelen;
+    WRITE_ENTRY_MAGIC (new, MAGIC_VALUE);
 #ifdef CONFIG_DEVFS_DEBUG
     spin_lock (&stat_lock);
     ++stat_num_entries;
@@ -972,8 +1010,7 @@
     if (old_de) *old_de = NULL;
     if ( !S_ISDIR (dir->mode) )
     {
-	printk ("%s: append_entry(%s): dir: \"%s\" is not a directory\n",
-		DEVFS_NAME, de->name, dir->name);
+	PRINTK ("(%s): dir: \"%s\" is not a directory\n", de->name, dir->name);
 	devfs_put (de);
 	return -ENOTDIR;
     }
@@ -1033,16 +1070,16 @@
     if ( ( new = _devfs_alloc_entry (".devfsd", 0, S_IFCHR |S_IRUSR |S_IWUSR) )
 	 == NULL ) return NULL;
     devnum = devfs_alloc_devnum (DEVFS_SPECIAL_CHR);
-    new->u.fcb.u.device.major = MAJOR (devnum);
-    new->u.fcb.u.device.minor = MINOR (devnum);
+    new->u.fcb.u.device.major = major (devnum);
+    new->u.fcb.u.device.minor = minor (devnum);
     new->u.fcb.ops = &devfsd_fops;
     _devfs_append_entry (root_entry, new, FALSE, NULL);
 #ifdef CONFIG_DEVFS_DEBUG
     if ( ( new = _devfs_alloc_entry (".stat", 0, S_IFCHR | S_IRUGO | S_IWUGO) )
 	 == NULL ) return NULL;
     devnum = devfs_alloc_devnum (DEVFS_SPECIAL_CHR);
-    new->u.fcb.u.device.major = MAJOR (devnum);
-    new->u.fcb.u.device.minor = MINOR (devnum);
+    new->u.fcb.u.device.major = major (devnum);
+    new->u.fcb.u.device.minor = minor (devnum);
     new->u.fcb.ops = &stat_fops;
     _devfs_append_entry (root_entry, new, FALSE, NULL);
 #endif
@@ -1143,15 +1180,13 @@
     if ( ( *dir = _devfs_make_parent_for_leaf (*dir, name, namelen,
 					       &leaf_pos) ) == NULL )
     {
-	printk ("%s: prepare_leaf(%s): could not create parent path\n",
-		DEVFS_NAME, name);
+	PRINTK ("(%s): could not create parent path\n", name);
 	return NULL;
     }
     if ( ( de = _devfs_alloc_entry (name + leaf_pos, namelen - leaf_pos,mode) )
 	 == NULL )
     {
-	printk ("%s: prepare_leaf(%s): could not allocate entry\n",
-		DEVFS_NAME, name);
+	PRINTK ("(%s): could not allocate entry\n", name);
 	devfs_put (*dir);
 	return NULL;
     }
@@ -1198,7 +1233,7 @@
 
 
 /**
- *	find_by_dev - Find a devfs entry in a directory.
+ *	_devfs_find_by_dev - Find a devfs entry in a directory.
  *	@dir: The directory where to search
  *	@major: The major number to search for.
  *	@minor: The minor number to search for.
@@ -1209,9 +1244,9 @@
  *	devfs_get() is performed.
  */
 
-static struct devfs_entry *find_by_dev (struct devfs_entry *dir,
-					unsigned int major, unsigned int minor,
-					char type)
+static struct devfs_entry *_devfs_find_by_dev (struct devfs_entry *dir,
+					       unsigned int major,
+					       unsigned int minor, char type)
 {
     struct devfs_entry *entry, *de;
 
@@ -1219,7 +1254,7 @@
     if (dir == NULL) return NULL;
     if ( !S_ISDIR (dir->mode) )
     {
-	printk ("%s: find_by_dev(): not a directory\n", DEVFS_NAME);
+	PRINTK ("(%p): not a directory\n", dir);
 	devfs_put (dir);
 	return NULL;
     }
@@ -1244,7 +1279,7 @@
     for (entry = dir->u.dir.first; entry != NULL; entry = entry->next)
     {
 	if ( !S_ISDIR (entry->mode) ) continue;
-	de = find_by_dev (entry, major, minor, type);
+	de = _devfs_find_by_dev (entry, major, minor, type);
 	if (de)
 	{
 	    read_unlock (&dir->u.dir.lock);
@@ -1255,11 +1290,11 @@
     read_unlock (&dir->u.dir.lock);
     devfs_put (dir);
     return NULL;
-}   /*  End Function find_by_dev  */
+}   /*  End Function _devfs_find_by_dev  */
 
 
 /**
- *	find_entry - Find a devfs entry.
+ *	_devfs_find_entry - Find a devfs entry.
  *	@dir: The handle to the parent devfs directory entry. If this is %NULL the
  *		name is relative to the root of the devfs.
  *	@name: The name of the entry. This may be %NULL.
@@ -1275,9 +1310,11 @@
  *	devfs_get() is performed.
  */
 
-static struct devfs_entry *find_entry (devfs_handle_t dir, const char *name,
-				       unsigned int major, unsigned int minor,
-				       char type, int traverse_symlink)
+static struct devfs_entry *_devfs_find_entry (devfs_handle_t dir,
+					      const char *name,
+					      unsigned int major,
+					      unsigned int minor,
+					      char type, int traverse_symlink)
 {
     struct devfs_entry *entry;
 
@@ -1290,14 +1327,14 @@
 	    /*  Skip leading pathname component  */
 	    if (namelen < 2)
 	    {
-		printk ("%s: find_entry(%s): too short\n", DEVFS_NAME, name);
+		PRINTK ("(%s): too short\n", name);
 		return NULL;
 	    }
 	    for (++name, --namelen; (*name != '/') && (namelen > 0);
 		 ++name, --namelen);
 	    if (namelen < 2)
 	    {
-		printk ("%s: find_entry(%s): too short\n", DEVFS_NAME, name);
+		PRINTK ("(%s): too short\n", name);
 		return NULL;
 	    }
 	    ++name;
@@ -1308,12 +1345,13 @@
     }
     /*  Have to search by major and minor: slow  */
     if ( (major == 0) && (minor == 0) ) return NULL;
-    return find_by_dev (root_entry, major, minor, type);
-}   /*  End Function find_entry  */
+    return _devfs_find_by_dev (root_entry, major, minor, type);
+}   /*  End Function _devfs_find_entry  */
 
 static struct devfs_entry *get_devfs_entry_from_vfs_inode (struct inode *inode)
 {
     if (inode == NULL) return NULL;
+    VERIFY_ENTRY ( (struct devfs_entry *) inode->u.generic_ip );
     return inode->u.generic_ip;
 }   /*  End Function get_devfs_entry_from_vfs_inode  */
 
@@ -1495,7 +1533,7 @@
 
     if (name == NULL)
     {
-	printk ("%s: devfs_register(): NULL name pointer\n", DEVFS_NAME);
+	PRINTK ("(): NULL name pointer\n");
 	return NULL;
     }
     if (ops == NULL)
@@ -1503,54 +1541,48 @@
 	if ( S_ISBLK (mode) ) ops = (void *) get_blkfops (major);
 	if (ops == NULL)
 	{
-	    printk ("%s: devfs_register(%s): NULL ops pointer\n",
-		    DEVFS_NAME, name);
+	    PRINTK ("(%s): NULL ops pointer\n", name);
 	    return NULL;
 	}
-	printk ("%s: devfs_register(%s): NULL ops, got %p from major table\n",
-		DEVFS_NAME, name, ops);
+	PRINTK ("(%s): NULL ops, got %p from major table\n", name, ops);
     }
     if ( S_ISDIR (mode) )
     {
-	printk("%s: devfs_register(%s): creating directories is not allowed\n",
-	       DEVFS_NAME, name);
+	PRINTK ("(%s): creating directories is not allowed\n", name);
 	return NULL;
     }
     if ( S_ISLNK (mode) )
     {
-	printk ("%s: devfs_register(%s): creating symlinks is not allowed\n",
-		DEVFS_NAME, name);
+	PRINTK ("(%s): creating symlinks is not allowed\n", name);
 	return NULL;
     }
     if ( ( S_ISCHR (mode) || S_ISBLK (mode) ) &&
 	 (flags & DEVFS_FL_AUTO_DEVNUM) )
     {
-	if ( ( devnum = devfs_alloc_devnum (devtype) ) == NODEV )
+	if ( kdev_none ( devnum = devfs_alloc_devnum (devtype) ) )
 	{
-	    printk ("%s: devfs_register(%s): exhausted %s device numbers\n",
-		    DEVFS_NAME, name, S_ISCHR (mode) ? "char" : "block");
+	    PRINTK ("(%s): exhausted %s device numbers\n",
+		    name, S_ISCHR (mode) ? "char" : "block");
 	    return NULL;
 	}
-	major = MAJOR (devnum);
-	minor = MINOR (devnum);
+	major = major (devnum);
+	minor = minor (devnum);
     }
     if ( ( de = _devfs_prepare_leaf (&dir, name, mode) ) == NULL )
     {
-	printk ("%s: devfs_register(%s): could not prepare leaf\n",
-		DEVFS_NAME, name);
-	if (devnum != NODEV) devfs_dealloc_devnum (devtype, devnum);
+	PRINTK ("(%s): could not prepare leaf\n", name);
+	if ( !kdev_none (devnum) ) devfs_dealloc_devnum (devtype, devnum);
 	return NULL;
     }
     if ( S_ISCHR (mode) || S_ISBLK (mode) )
     {
 	de->u.fcb.u.device.major = major;
 	de->u.fcb.u.device.minor = minor;
-	de->u.fcb.autogen = (devnum == NODEV) ? FALSE : TRUE;
+	de->u.fcb.autogen = kdev_none (devnum) ? FALSE : TRUE;
     }
     else if ( !S_ISREG (mode) )
     {
-	printk ("%s: devfs_register(%s): illegal mode: %x\n",
-		DEVFS_NAME, name, mode);
+	PRINTK ("(%s): illegal mode: %x\n", name, mode);
 	devfs_put (de);
 	devfs_put (dir);
 	return (NULL);
@@ -1574,17 +1606,13 @@
     if ( ( err = _devfs_append_entry (dir, de, de->u.fcb.removable, NULL) )
 	 != 0 )
     {
-	printk("%s: devfs_register(%s): could not append to parent, err: %d\n",
-	       DEVFS_NAME, name, err);
+	PRINTK ("(%s): could not append to parent, err: %d\n", name, err);
 	devfs_put (dir);
-	if (devnum != NODEV) devfs_dealloc_devnum (devtype, devnum);
+	if ( !kdev_none (devnum) ) devfs_dealloc_devnum (devtype, devnum);
 	return NULL;
     }
-#ifdef CONFIG_DEVFS_DEBUG
-    if (devfs_debug & DEBUG_REGISTER)
-	printk ("%s: devfs_register(%s): de: %p dir: %p \"%s\"  pp: %p\n",
-		DEVFS_NAME, name, de, dir, dir->name, dir->parent);
-#endif
+    DPRINTK (DEBUG_REGISTER, "(%s): de: %p dir: %p \"%s\"  pp: %p\n",
+	     name, de, dir, dir->name, dir->parent);
     devfsd_notify (de, DEVFSD_NOTIFY_REGISTERED, flags & DEVFS_FL_WAIT);
     devfs_put (dir);
     return de;
@@ -1620,7 +1648,7 @@
 
 
 /**
- *	unregister - Unregister a device entry from it's parent.
+ *	_devfs_unregister - Unregister a device entry from it's parent.
  *	@dir: The parent directory.
  *	@de: The entry to unregister.
  *
@@ -1628,7 +1656,7 @@
  *	unlocked by this function.
  */
 
-static void unregister (struct devfs_entry *dir, struct devfs_entry *de)
+static void _devfs_unregister (struct devfs_entry *dir, struct devfs_entry *de)
 {
     int unhooked = _devfs_unhook (de);
 
@@ -1647,17 +1675,14 @@
 	write_lock (&de->u.dir.lock);
 	de->u.dir.no_more_additions = TRUE;
 	child = de->u.dir.first;
-	unregister (de, child);
+	VERIFY_ENTRY (child);
+	_devfs_unregister (de, child);
 	if (!child) break;
-#ifdef CONFIG_DEVFS_DEBUG
-	if (devfs_debug & DEBUG_UNREGISTER)
-	    printk ( "%s: unregister(%s): child: %p  refcount: %d\n",
-		     DEVFS_NAME, child->name, child,
-		     atomic_read (&de->refcount) );
-#endif
+	DPRINTK (DEBUG_UNREGISTER, "(%s): child: %p  refcount: %d\n",
+		 child->name, child, atomic_read (&child->refcount) );
 	devfs_put (child);
     }
-}   /*  End Function unregister  */
+}   /*  End Function _devfs_unregister  */
 
 
 /**
@@ -1668,14 +1693,12 @@
 
 void devfs_unregister (devfs_handle_t de)
 {
+    VERIFY_ENTRY (de);
     if ( (de == NULL) || (de->parent == NULL) ) return;
-#ifdef CONFIG_DEVFS_DEBUG
-    if (devfs_debug & DEBUG_UNREGISTER)
-	printk ( "%s: devfs_unregister(%s): de: %p  refcount: %d\n",
-		 DEVFS_NAME, de->name, de, atomic_read (&de->refcount) );
-#endif
+    DPRINTK (DEBUG_UNREGISTER, "(%s): de: %p  refcount: %d\n",
+	     de->name, de, atomic_read (&de->refcount) );
     write_lock (&de->parent->u.dir.lock);
-    unregister (de->parent, de);
+    _devfs_unregister (de->parent, de);
     devfs_put (de);
 }   /*  End Function devfs_unregister  */
 
@@ -1691,16 +1714,12 @@
     if (handle != NULL) *handle = NULL;
     if (name == NULL)
     {
-	printk ("%s: devfs_do_symlink(): NULL name pointer\n", DEVFS_NAME);
+	PRINTK ("(): NULL name pointer\n");
 	return -EINVAL;
     }
-#ifdef CONFIG_DEVFS_DEBUG
-    if (devfs_debug & DEBUG_REGISTER)
-	printk ("%s: devfs_do_symlink(%s)\n", DEVFS_NAME, name);
-#endif
     if (link == NULL)
     {
-	printk ("%s: devfs_do_symlink(): NULL link pointer\n", DEVFS_NAME);
+	PRINTK ("(%s): NULL link pointer\n", name);
 	return -EINVAL;
     }
     linklength = strlen (link);
@@ -1711,8 +1730,7 @@
     if ( ( de = _devfs_prepare_leaf (&dir, name, S_IFLNK | S_IRUGO | S_IXUGO) )
 	 == NULL )
     {
-	printk ("%s: devfs_do_symlink(%s): could not prepare leaf\n",
-		DEVFS_NAME, name);
+	PRINTK ("(%s): could not prepare leaf\n", name);
 	kfree (newlink);
 	return -ENOTDIR;
     }
@@ -1722,8 +1740,7 @@
     de->u.symlink.length = linklength;
     if ( ( err = _devfs_append_entry (dir, de, FALSE, NULL) ) != 0 )
     {
-	printk ("%s: devfs_do_symlink(%s): could not append to parent, err: %d\n",
-		DEVFS_NAME, name, err);
+	PRINTK ("(%s): could not append to parent, err: %d\n", name, err);
 	devfs_put (dir);
 	return err;
     }
@@ -1758,9 +1775,11 @@
     devfs_handle_t de;
 
     if (handle != NULL) *handle = NULL;
+    DPRINTK (DEBUG_REGISTER, "(%s)\n", name);
     err = devfs_do_symlink (dir, name, flags, link, &de, info);
     if (err) return err;
-    if (handle != NULL) *handle = de;
+    if (handle == NULL) de->vfs_deletable = TRUE;
+    else *handle = de;
     devfsd_notify (de, DEVFSD_NOTIFY_REGISTERED, flags & DEVFS_FL_WAIT);
     return 0;
 }   /*  End Function devfs_mk_symlink  */
@@ -1787,39 +1806,35 @@
 
     if (name == NULL)
     {
-	printk ("%s: devfs_mk_dir(): NULL name pointer\n", DEVFS_NAME);
+	PRINTK ("(): NULL name pointer\n");
 	return NULL;
     }
     if ( ( de = _devfs_prepare_leaf (&dir, name, MODE_DIR) ) == NULL )
     {
-	printk ("%s: devfs_mk_dir(%s): could not prepare leaf\n",
-		DEVFS_NAME, name);
+	PRINTK ("(%s): could not prepare leaf\n", name);
 	return NULL;
     }
     de->info = info;
     if ( ( err = _devfs_append_entry (dir, de, FALSE, &old) ) != 0 )
     {
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,1)
-	if (old)
+	if ( old && S_ISDIR (old->mode) )
 	{
-	    printk("%s: devfs_mk_dir(%s): using old entry in dir: %p \"%s\"\n",
-		   DEVFS_NAME, name, dir, dir->name);
-	    old->vfs_created = FALSE;
+	    PRINTK ("(%s): using old entry in dir: %p \"%s\"\n",
+		    name, dir, dir->name);
+	    old->vfs_deletable = FALSE;
 	    devfs_put (dir);
 	    return old;
 	}
 #endif
-	printk ("%s: devfs_mk_dir(%s): could not append to dir: %p \"%s\", err: %d\n",
-		DEVFS_NAME, name, dir, dir->name, err);
+	PRINTK ("(%s): could not append to dir: %p \"%s\", err: %d\n",
+		name, dir, dir->name, err);
 	devfs_put (old);
 	devfs_put (dir);
 	return NULL;
     }
-#ifdef CONFIG_DEVFS_DEBUG
-    if (devfs_debug & DEBUG_REGISTER)
-	printk ("%s: devfs_mk_dir(%s): de: %p dir: %p \"%s\"\n",
-		DEVFS_NAME, name, de, dir, dir->name);
-#endif
+    DPRINTK (DEBUG_REGISTER, "(%s): de: %p dir: %p \"%s\"\n",
+	     name, de, dir, dir->name);
     devfsd_notify (de, DEVFSD_NOTIFY_REGISTERED, 0);
     devfs_put (dir);
     return de;
@@ -1850,7 +1865,7 @@
 				 char type, int traverse_symlinks)
 {
     if ( (name != NULL) && (name[0] == '\0') ) name = NULL;
-    return find_entry (dir, name, major, minor, type, traverse_symlinks);
+    return _devfs_find_entry (dir, name, major, minor, type,traverse_symlinks);
 }   /*  End Function devfs_get_handle  */
 
 
@@ -1881,6 +1896,7 @@
     unsigned int fl = 0;
 
     if (de == NULL) return -EINVAL;
+    VERIFY_ENTRY (de);
     if (de->hide) fl |= DEVFS_FL_HIDE;
     if ( S_ISCHR (de->mode) || S_ISBLK (de->mode) || S_ISREG (de->mode) )
     {
@@ -1904,11 +1920,8 @@
 int devfs_set_flags (devfs_handle_t de, unsigned int flags)
 {
     if (de == NULL) return -EINVAL;
-#ifdef CONFIG_DEVFS_DEBUG
-    if (devfs_debug & DEBUG_SET_FLAGS)
-	printk ("%s: devfs_set_flags(): de->name: \"%s\"\n",
-		DEVFS_NAME, de->name);
-#endif
+    VERIFY_ENTRY (de);
+    DPRINTK (DEBUG_SET_FLAGS, "(%s): flags: %x\n", de->name, flags);
     de->hide = (flags & DEVFS_FL_HIDE) ? TRUE : FALSE;
     if ( S_ISCHR (de->mode) || S_ISBLK (de->mode) || S_ISREG (de->mode) )
     {
@@ -1932,6 +1945,7 @@
 		       unsigned int *minor)
 {
     if (de == NULL) return -EINVAL;
+    VERIFY_ENTRY (de);
     if ( S_ISDIR (de->mode) ) return -EISDIR;
     if ( !S_ISCHR (de->mode) && !S_ISBLK (de->mode) ) return -EINVAL;
     if (major != NULL) *major = de->u.fcb.u.device.major;
@@ -1972,6 +1986,7 @@
 #define NAMEOF(de) ( (de)->mode ? (de)->name : (de)->u.name )
 
     if (de == NULL) return -EINVAL;
+    VERIFY_ENTRY (de);
     if (de->namelen >= buflen) return -ENAMETOOLONG; /*  Must be first       */
     path[buflen - 1] = '\0';
     if (de->parent == NULL) return buflen - 1;       /*  Don't prepend root  */
@@ -2001,6 +2016,7 @@
     struct module *owner;
 
     if (de == NULL) return NULL;
+    VERIFY_ENTRY (de);
     if ( !S_ISCHR (de->mode) && !S_ISBLK (de->mode) && !S_ISREG (de->mode) )
 	return NULL;
     if (de->u.fcb.ops == NULL) return NULL;
@@ -2031,6 +2047,7 @@
     struct module *owner;
 
     if (de == NULL) return;
+    VERIFY_ENTRY (de);
     if ( !S_ISCHR (de->mode) && !S_ISBLK (de->mode) && !S_ISREG (de->mode) )
 	return;
     if (de->u.fcb.ops == NULL) return;
@@ -2052,6 +2069,7 @@
 int devfs_set_file_size (devfs_handle_t de, unsigned long size)
 {
     if (de == NULL) return -EINVAL;
+    VERIFY_ENTRY (de);
     if ( !S_ISREG (de->mode) ) return -EINVAL;
     if (de->u.fcb.u.file.size == size) return 0;
     de->u.fcb.u.file.size = size;
@@ -2071,6 +2089,7 @@
 void *devfs_get_info (devfs_handle_t de)
 {
     if (de == NULL) return NULL;
+    VERIFY_ENTRY (de);
     return de->info;
 }   /*  End Function devfs_get_info  */
 
@@ -2085,6 +2104,7 @@
 int devfs_set_info (devfs_handle_t de, void *info)
 {
     if (de == NULL) return -EINVAL;
+    VERIFY_ENTRY (de);
     de->info = info;
     return 0;
 }   /*  End Function devfs_set_info  */
@@ -2099,6 +2119,7 @@
 devfs_handle_t devfs_get_parent (devfs_handle_t de)
 {
     if (de == NULL) return NULL;
+    VERIFY_ENTRY (de);
     return de->parent;
 }   /*  End Function devfs_get_parent  */
 
@@ -2113,6 +2134,7 @@
 devfs_handle_t devfs_get_first_child (devfs_handle_t de)
 {
     if (de == NULL) return NULL;
+    VERIFY_ENTRY (de);
     if ( !S_ISDIR (de->mode) ) return NULL;
     return de->u.dir.first;
 }   /*  End Function devfs_get_first_child  */
@@ -2128,6 +2150,7 @@
 devfs_handle_t devfs_get_next_sibling (devfs_handle_t de)
 {
     if (de == NULL) return NULL;
+    VERIFY_ENTRY (de);
     return de->next;
 }   /*  End Function devfs_get_next_sibling  */
 
@@ -2143,14 +2166,15 @@
 void devfs_auto_unregister (devfs_handle_t master, devfs_handle_t slave)
 {
     if (master == NULL) return;
+    VERIFY_ENTRY (master);
+    VERIFY_ENTRY (slave);
     if (master->slave != NULL)
     {
 	/*  Because of the dumbness of the layers above, ignore duplicates  */
 	if (master->slave == slave) return;
-	printk ("%s: devfs_auto_unregister(): only one slave allowed\n",
-		DEVFS_NAME);
-	OOPS ("  master: \"%s\"  old slave: \"%s\"  new slave: \"%s\"\n",
-	      master->name, master->slave->name, slave->name);
+	PRINTK ("(%s): only one slave allowed\n", master->name);
+	OOPS ("():  old slave: \"%s\"  new slave: \"%s\"\n",
+	      master->slave->name, slave->name);
     }
     master->slave = slave;
 }   /*  End Function devfs_auto_unregister  */
@@ -2166,6 +2190,7 @@
 devfs_handle_t devfs_get_unregister_slave (devfs_handle_t master)
 {
     if (master == NULL) return NULL;
+    VERIFY_ENTRY (master);
     return master->slave;
 }   /*  End Function devfs_get_unregister_slave  */
 
@@ -2181,6 +2206,7 @@
 const char *devfs_get_name (devfs_handle_t de, unsigned int *namelen)
 {
     if (de == NULL) return NULL;
+    VERIFY_ENTRY (de);
     if (namelen != NULL) *namelen = de->namelen;
     return de->name;
 }   /*  End Function devfs_get_name  */
@@ -2360,7 +2386,7 @@
  *	@buf: A working area that will be used. This must not go out of scope
  *            until devfsd is idle again.
  *
- *	Returns 0 on success, else a negative error code.
+ *	Returns 0 on success (event was queued), else a negative error code.
  */
 
 static int try_modload (struct devfs_entry *parent, struct fs_info *fs_info,
@@ -2375,10 +2401,11 @@
     buf->parent = parent;
     buf->namelen = namelen;
     buf->u.name = name;
+    WRITE_ENTRY_MAGIC (buf, MAGIC_VALUE);
     if ( !devfsd_notify_de (buf, DEVFSD_NOTIFY_LOOKUP, 0,
 			    current->euid, current->egid, fs_info, 0) )
 	return -ENOENT;
-    /*  Possible success  */
+    /*  Possible success: event has been queued  */
     return 0;
 }   /*  End Function try_modload  */
 
@@ -2394,7 +2421,7 @@
 {
     int tmp;
     int retval = 0;
-    kdev_t dev = MKDEV (de->u.fcb.u.device.major, de->u.fcb.u.device.minor);
+    kdev_t dev = mk_kdev (de->u.fcb.u.device.major, de->u.fcb.u.device.minor);
     struct block_device_operations *bdops;
     extern int warn_no_part;
 
@@ -2487,16 +2514,10 @@
     if (retval != 0) return retval;
     retval = inode_setattr (inode, iattr);
     if (retval != 0) return retval;
-#ifdef CONFIG_DEVFS_DEBUG
-    if (devfs_debug & DEBUG_I_CHANGE)
-    {
-	printk ("%s: notify_change(%d): VFS inode: %p  devfs_entry: %p\n",
-		DEVFS_NAME, (int) inode->i_ino, inode, de);
-	printk ("%s:   mode: 0%o  uid: %d  gid: %d\n",
-		DEVFS_NAME, (int) inode->i_mode,
-		(int) inode->i_uid, (int) inode->i_gid);
-    }
-#endif
+    DPRINTK (DEBUG_I_CHANGE, "(%d): VFS inode: %p  devfs_entry: %p\n",
+	     (int) inode->i_ino, inode, de);
+    DPRINTK (DEBUG_I_CHANGE, "():   mode: 0%o  uid: %d  gid: %d\n",
+	     (int) inode->i_mode, (int) inode->i_uid, (int) inode->i_gid);
     /*  Inode is not on hash chains, thus must save permissions here rather
 	than in a write_inode() method  */
     if ( ( !S_ISREG (inode->i_mode) && !S_ISCHR (inode->i_mode) &&
@@ -2541,7 +2562,7 @@
 
 
 /**
- *	get_vfs_inode - Get a VFS inode.
+ *	_devfs_get_vfs_inode - Get a VFS inode.
  *	@sb: The super block.
  *	@de: The devfs inode.
  *	@dentry: The dentry to register with the devfs inode.
@@ -2550,9 +2571,9 @@
  *       performed if the inode is created.
  */
 
-static struct inode *get_vfs_inode (struct super_block *sb,
-				    struct devfs_entry *de,
-				    struct dentry *dentry)
+static struct inode *_devfs_get_vfs_inode (struct super_block *sb,
+					   struct devfs_entry *de,
+					   struct dentry *dentry)
 {
     int is_fcb = FALSE;
     struct inode *inode;
@@ -2560,8 +2581,7 @@
     if (de->prev == de) return NULL;  /*  Quick check to see if unhooked  */
     if ( ( inode = new_inode (sb) ) == NULL )
     {
-	printk ("%s: get_vfs_inode(%s): new_inode() failed, de: %p\n",
-		DEVFS_NAME, de->name, de);
+	PRINTK ("(%s): new_inode() failed, de: %p\n", de->name, de);
 	return NULL;
     }
     if (de->parent)
@@ -2578,11 +2598,8 @@
     }
     inode->u.generic_ip = devfs_get (de);
     inode->i_ino = de->inode.ino;
-#ifdef CONFIG_DEVFS_DEBUG
-    if (devfs_debug & DEBUG_I_GET)
-	printk ("%s: get_vfs_inode(%d): VFS inode: %p  devfs_entry: %p\n",
-		DEVFS_NAME, (int) inode->i_ino, inode, de);
-#endif
+    DPRINTK (DEBUG_I_GET, "(%d): VFS inode: %p  devfs_entry: %p\n",
+	     (int) inode->i_ino, inode, de);
     inode->i_blocks = 0;
     inode->i_blksize = FAKE_BLOCK_SIZE;
     inode->i_op = &devfs_iops;
@@ -2590,22 +2607,21 @@
     inode->i_rdev = NODEV;
     if ( S_ISCHR (de->mode) )
     {
-	inode->i_rdev = MKDEV (de->u.fcb.u.device.major,
-			       de->u.fcb.u.device.minor);
+	inode->i_rdev = mk_kdev (de->u.fcb.u.device.major,
+				 de->u.fcb.u.device.minor);
 	inode->i_cdev = cdget ( kdev_t_to_nr (inode->i_rdev) );
 	is_fcb = TRUE;
     }
     else if ( S_ISBLK (de->mode) )
     {
-	inode->i_rdev = MKDEV (de->u.fcb.u.device.major,
-			       de->u.fcb.u.device.minor);
+	inode->i_rdev = mk_kdev (de->u.fcb.u.device.major,
+				 de->u.fcb.u.device.minor);
 	if (bd_acquire (inode) == 0)
 	{
 	    if (!inode->i_bdev->bd_op && de->u.fcb.ops)
 		inode->i_bdev->bd_op = de->u.fcb.ops;
 	}
-	else printk ("%s: get_vfs_inode(%d): no block device from bdget()\n",
-		     DEVFS_NAME, (int) inode->i_ino);
+	else PRINTK ("(%d): no block device from bdget()\n",(int)inode->i_ino);
 	is_fcb = TRUE;
     }
     else if ( S_ISFIFO (de->mode) ) inode->i_fop = &def_fifo_fops;
@@ -2632,14 +2648,10 @@
     inode->i_atime = de->inode.atime;
     inode->i_mtime = de->inode.mtime;
     inode->i_ctime = de->inode.ctime;
-#ifdef CONFIG_DEVFS_DEBUG
-    if (devfs_debug & DEBUG_I_GET)
-	printk ("%s:   mode: 0%o  uid: %d  gid: %d\n",
-		DEVFS_NAME, (int) inode->i_mode,
-		(int) inode->i_uid, (int) inode->i_gid);
-#endif
+    DPRINTK (DEBUG_I_GET, "():   mode: 0%o  uid: %d  gid: %d\n",
+	     (int) inode->i_mode, (int) inode->i_uid, (int) inode->i_gid);
     return inode;
-}   /*  End Function get_vfs_inode  */
+}   /*  End Function _devfs_get_vfs_inode  */
 
 
 /*  File operations for device entries follow  */
@@ -2655,11 +2667,8 @@
     fs_info = inode->i_sb->u.generic_sbp;
     parent = get_devfs_entry_from_vfs_inode (file->f_dentry->d_inode);
     if ( (long) file->f_pos < 0 ) return -EINVAL;
-#ifdef CONFIG_DEVFS_DEBUG
-    if (devfs_debug & DEBUG_F_READDIR)
-	printk ("%s: readdir(): fs_info: %p  pos: %ld\n", DEVFS_NAME,
-		fs_info, (long) file->f_pos);
-#endif
+    DPRINTK (DEBUG_F_READDIR, "(%s): fs_info: %p  pos: %ld\n",
+	     parent->name, fs_info, (long) file->f_pos);
     switch ( (long) file->f_pos )
     {
       case 0:
@@ -2779,13 +2788,7 @@
 
 static void devfs_d_release (struct dentry *dentry)
 {
-#ifdef CONFIG_DEVFS_DEBUG
-    struct inode *inode = dentry->d_inode;
-
-    if (devfs_debug & DEBUG_D_RELEASE)
-	printk ("%s: d_release(): dentry: %p inode: %p\n",
-		DEVFS_NAME, dentry, inode);
-#endif
+    DPRINTK (DEBUG_D_RELEASE, "(%p): inode: %p\n", dentry, dentry->d_inode);
 }   /*  End Function devfs_d_release  */
 
 /**
@@ -2799,14 +2802,11 @@
     struct devfs_entry *de;
 
     de = get_devfs_entry_from_vfs_inode (inode);
-#ifdef CONFIG_DEVFS_DEBUG
-    if (devfs_debug & DEBUG_D_IPUT)
-	printk ("%s: d_iput(): dentry: %p inode: %p de: %p  de->dentry: %p\n",
-		DEVFS_NAME, dentry, inode, de, de->inode.dentry);
-#endif
+    DPRINTK (DEBUG_D_IPUT,"(%s): dentry: %p inode: %p de: %p de->dentry: %p\n",
+	     de->name, dentry, inode, de, de->inode.dentry);
     if ( de->inode.dentry && (de->inode.dentry != dentry) )
-	OOPS ("%s: d_iput(%s): de: %p dentry: %p de->dentry: %p\n",
-	      DEVFS_NAME, de->name, de, dentry, de->inode.dentry);
+	OOPS ("(%s): de: %p dentry: %p de->dentry: %p\n",
+	      de->name, de, dentry, de->inode.dentry);
     de->inode.dentry = NULL;
     iput (inode);
     devfs_put (de);
@@ -2846,20 +2846,13 @@
     /*  Unhash dentry if negative (has no inode)  */
     if (inode == NULL)
     {
-#ifdef CONFIG_DEVFS_DEBUG
-	if (devfs_debug & DEBUG_D_DELETE)
-	    printk ("%s: d_delete(): dropping negative dentry: %p\n",
-		    DEVFS_NAME, dentry);
-#endif
+	DPRINTK (DEBUG_D_DELETE, "(%p): dropping negative dentry\n", dentry);
 	return 1;
     }
     fs_info = inode->i_sb->u.generic_sbp;
     de = get_devfs_entry_from_vfs_inode (inode);
-#ifdef CONFIG_DEVFS_DEBUG
-    if (devfs_debug & DEBUG_D_DELETE)
-	printk ("%s: d_delete(): dentry: %p  inode: %p  devfs_entry: %p\n",
-		DEVFS_NAME, dentry, inode, de);
-#endif
+    DPRINTK (DEBUG_D_DELETE, "(%p): inode: %p  devfs_entry: %p\n",
+	     dentry, inode, de);
     if (de == NULL) return 0;
     if ( !S_ISCHR (de->mode) && !S_ISBLK (de->mode) && !S_ISREG (de->mode) )
 	return 0;
@@ -2876,40 +2869,58 @@
     return 0;
 }   /*  End Function devfs_d_delete  */
 
+struct devfs_lookup_struct
+{
+    devfs_handle_t de;
+    wait_queue_head_t wait_queue;
+};
+
 static int devfs_d_revalidate_wait (struct dentry *dentry, int flags)
 {
     struct inode *dir = dentry->d_parent->d_inode;
     struct fs_info *fs_info = dir->i_sb->u.generic_sbp;
+    devfs_handle_t parent = get_devfs_entry_from_vfs_inode (dir);
+    struct devfs_lookup_struct *lookup_info = dentry->d_fsdata;
+    DECLARE_WAITQUEUE (wait, current);
 
-    if ( !dentry->d_inode && is_devfsd_or_child (fs_info) )
+    if ( is_devfsd_or_child (fs_info) )
     {
-	devfs_handle_t de;
-	devfs_handle_t parent = get_devfs_entry_from_vfs_inode (dir);
+	devfs_handle_t de = lookup_info->de;
 	struct inode *inode;
 
-#ifdef CONFIG_DEVFS_DEBUG
-	if (devfs_debug & DEBUG_I_LOOKUP)
-	    printk ("%s: d_revalidate(%s): dentry: %p by: \"%s\"\n",
-		    DEVFS_NAME, dentry->d_name.name, dentry, current->comm);
-#endif
-	read_lock (&parent->u.dir.lock);
-	de = _devfs_search_dir (parent, dentry->d_name.name,
-				dentry->d_name.len);
-	read_unlock (&parent->u.dir.lock);
-	if (de == NULL) return 1;
+	DPRINTK (DEBUG_I_LOOKUP,
+		 "(%s): dentry: %p inode: %p de: %p by: \"%s\"\n",
+		 dentry->d_name.name, dentry, dentry->d_inode, de,
+		 current->comm);
+	if (dentry->d_inode) return 1;
+	if (de == NULL)
+	{
+	    read_lock (&parent->u.dir.lock);
+	    de = _devfs_search_dir (parent, dentry->d_name.name,
+				    dentry->d_name.len);
+	    read_unlock (&parent->u.dir.lock);
+	    if (de == NULL) return 1;
+	    lookup_info->de = de;
+	}
 	/*  Create an inode, now that the driver information is available  */
-	inode = get_vfs_inode (dir->i_sb, de, dentry);
-	devfs_put (de);
+	inode = _devfs_get_vfs_inode (dir->i_sb, de, dentry);
 	if (!inode) return 1;
-#ifdef CONFIG_DEVFS_DEBUG
-	if (devfs_debug & DEBUG_I_LOOKUP)
-	    printk ("%s: d_revalidate(): new VFS inode(%u): %p  devfs_entry: %p\n",
-		    DEVFS_NAME, de->inode.ino, inode, de);
-#endif
+	DPRINTK (DEBUG_I_LOOKUP,
+		 "(%s): new VFS inode(%u): %p de: %p by: \"%s\"\n",
+		 de->name, de->inode.ino, inode, de, current->comm);
 	d_instantiate (dentry, inode);
 	return 1;
     }
-    if ( wait_for_devfsd_finished (fs_info) ) dentry->d_op = &devfs_dops;
+    if (lookup_info == NULL) return 1;  /*  Early termination  */
+    read_lock (&parent->u.dir.lock);
+    if (dentry->d_fsdata)
+    {
+	add_wait_queue (&lookup_info->wait_queue, &wait);
+	current->state = TASK_UNINTERRUPTIBLE;
+	read_unlock (&parent->u.dir.lock);
+	schedule ();
+    }
+    else read_unlock (&parent->u.dir.lock);
     return 1;
 }   /*  End Function devfs_d_revalidate_wait  */
 
@@ -2918,20 +2929,20 @@
 
 static struct dentry *devfs_lookup (struct inode *dir, struct dentry *dentry)
 {
+    struct devfs_entry tmp;  /*  Must stay in scope until devfsd idle again  */
+    struct devfs_lookup_struct lookup_info;
     struct fs_info *fs_info = dir->i_sb->u.generic_sbp;
     struct devfs_entry *parent, *de;
     struct inode *inode;
+    struct dentry *retval = NULL;
 
     /*  Set up the dentry operations before anything else, to ensure cleaning
 	up on any error  */
     dentry->d_op = &devfs_dops;
     /*  First try to get the devfs entry for this directory  */
     parent = get_devfs_entry_from_vfs_inode (dir);
-#ifdef CONFIG_DEVFS_DEBUG
-    if (devfs_debug & DEBUG_I_LOOKUP)
-	printk ("%s: lookup(%s): dentry: %p parent: %p by: \"%s\"\n",
-		DEVFS_NAME, dentry->d_name.name, dentry, parent,current->comm);
-#endif
+    DPRINTK (DEBUG_I_LOOKUP, "(%s): dentry: %p parent: %p by: \"%s\"\n",
+	     dentry->d_name.name, dentry, parent, current->comm);
     if (parent == NULL) return ERR_PTR (-ENOENT);
     read_lock (&parent->u.dir.lock);
     de = _devfs_search_dir (parent, dentry->d_name.name, dentry->d_name.len);
@@ -2945,63 +2956,61 @@
 				dentry->d_name.len);
 	read_unlock (&parent->u.dir.lock);
     }
+    lookup_info.de = de;
+    init_waitqueue_head (&lookup_info.wait_queue);
+    dentry->d_fsdata = &lookup_info;
     if (de == NULL)
     {   /*  Try with devfsd. For any kind of failure, leave a negative dentry
 	    so someone else can deal with it (in the case where the sysadmin
 	    does a mknod()). It's important to do this before hashing the
 	    dentry, so that the devfsd queue is filled before revalidates
 	    can start  */
-	struct devfs_entry tmp;
-
 	if (try_modload (parent, fs_info,
 			 dentry->d_name.name, dentry->d_name.len, &tmp) < 0)
-	{
+	{   /*  Lookup event was not queued to devfsd  */
 	    d_add (dentry, NULL);
 	    return NULL;
 	}
-	/*  devfsd claimed success  */
-	dentry->d_op = &devfs_wait_dops;
-	d_add (dentry, NULL);  /*  Open the floodgates  */
-	/*  Unlock directory semaphore, which will release any waiters. They
-	    will get the hashed dentry, and may be forced to wait for
-	    revalidation  */
-	up (&dir->i_sem);
-	devfs_d_revalidate_wait (dentry, 0);  /*  I might have to wait too   */
-	down (&dir->i_sem);      /*  Grab it again because them's the rules  */
-	/*  If someone else has been so kind as to make the inode, we go home
-	    early  */
-	if (dentry->d_inode) return NULL;
+    }
+    dentry->d_op = &devfs_wait_dops;
+    d_add (dentry, NULL);  /*  Open the floodgates  */
+    /*  Unlock directory semaphore, which will release any waiters. They
+	will get the hashed dentry, and may be forced to wait for
+	revalidation  */
+    up (&dir->i_sem);
+    wait_for_devfsd_finished (fs_info);  /*  If I'm not devfsd, must wait  */
+    down (&dir->i_sem);      /*  Grab it again because them's the rules  */
+    de = lookup_info.de;
+    /*  If someone else has been so kind as to make the inode, we go home
+	early  */
+    if (dentry->d_inode) goto out;
+    if (de == NULL)
+    {
 	read_lock (&parent->u.dir.lock);
 	de = _devfs_search_dir (parent, dentry->d_name.name,
 				dentry->d_name.len);
 	read_unlock (&parent->u.dir.lock);
-	if (de == NULL) return NULL;
+	if (de == NULL) goto out;
 	/*  OK, there's an entry now, but no VFS inode yet  */
     }
-    else
+    /*  Create an inode, now that the driver information is available  */
+    inode = _devfs_get_vfs_inode (dir->i_sb, de, dentry);
+    if (!inode)
     {
-	dentry->d_op = &devfs_wait_dops;
-	d_add (dentry, NULL);  /*  Open the floodgates  */
+	retval = ERR_PTR (-ENOMEM);
+	goto out;
     }
-    /*  Create an inode, now that the driver information is available  */
-    inode = get_vfs_inode (dir->i_sb, de, dentry);
-    devfs_put (de);
-    if (!inode) return ERR_PTR (-ENOMEM);
-#ifdef CONFIG_DEVFS_DEBUG
-    if (devfs_debug & DEBUG_I_LOOKUP)
-	printk ("%s: lookup(): new VFS inode(%u): %p  devfs_entry: %p\n",
-		DEVFS_NAME, de->inode.ino, inode, de);
-#endif
+    DPRINTK (DEBUG_I_LOOKUP, "(%s): new VFS inode(%u): %p de: %p by: \"%s\"\n",
+	     de->name, de->inode.ino, inode, de, current->comm);
     d_instantiate (dentry, inode);
-    if (dentry->d_op == &devfs_wait_dops)
-    {   /*  Unlock directory semaphore, which will release any waiters. They
-	    will get the hashed dentry, and may be forced to wait for
-	    revalidation  */
-	up (&dir->i_sem);
-	devfs_d_revalidate_wait (dentry, 0);  /*  I might have to wait too   */
-	down (&dir->i_sem);      /*  Grab it again because them's the rules  */
-    }
-    return NULL;
+out:
+    dentry->d_op = &devfs_dops;
+    dentry->d_fsdata = NULL;
+    write_lock (&parent->u.dir.lock);
+    wake_up (&lookup_info.wait_queue);
+    write_unlock (&parent->u.dir.lock);
+    devfs_put (de);
+    return retval;
 }   /*  End Function devfs_lookup  */
 
 static int devfs_unlink (struct inode *dir, struct dentry *dentry)
@@ -3011,13 +3020,10 @@
     struct inode *inode = dentry->d_inode;
     struct fs_info *fs_info = dir->i_sb->u.generic_sbp;
 
-#ifdef CONFIG_DEVFS_DEBUG
-    if (devfs_debug & DEBUG_I_UNLINK)
-	printk ("%s: unlink(%s)\n", DEVFS_NAME, dentry->d_name.name);
-#endif
     de = get_devfs_entry_from_vfs_inode (inode);
+    DPRINTK (DEBUG_I_UNLINK, "(%s): de: %p\n", dentry->d_name.name, de);
     if (de == NULL) return -ENOENT;
-    if (!de->vfs_created) return -EPERM;
+    if (!de->vfs_deletable) return -EPERM;
     write_lock (&de->parent->u.dir.lock);
     unhooked = _devfs_unhook (de);
     write_unlock (&de->parent->u.dir.lock);
@@ -3043,25 +3049,19 @@
     if (parent == NULL) return -ENOENT;
     err = devfs_do_symlink (parent, dentry->d_name.name, DEVFS_FL_NONE,
 			    symname, &de, NULL);
-#ifdef CONFIG_DEVFS_DEBUG
-    if (devfs_debug & DEBUG_DISABLED)
-	printk ("%s: symlink(): errcode from <devfs_do_symlink>: %d\n",
-		DEVFS_NAME, err);
-#endif
+    DPRINTK (DEBUG_DISABLED, "(%s): errcode from <devfs_do_symlink>: %d\n",
+	     dentry->d_name.name, err);
     if (err < 0) return err;
-    de->vfs_created = TRUE;
+    de->vfs_deletable = TRUE;
     de->inode.uid = current->euid;
     de->inode.gid = current->egid;
     de->inode.atime = CURRENT_TIME;
     de->inode.mtime = CURRENT_TIME;
     de->inode.ctime = CURRENT_TIME;
-    if ( ( inode = get_vfs_inode (dir->i_sb, de, dentry) ) == NULL )
+    if ( ( inode = _devfs_get_vfs_inode (dir->i_sb, de, dentry) ) == NULL )
 	return -ENOMEM;
-#ifdef CONFIG_DEVFS_DEBUG
-    if (devfs_debug & DEBUG_DISABLED)
-	printk ("%s: symlink(): new VFS inode(%u): %p  dentry: %p\n",
-		DEVFS_NAME, de->inode.ino, inode, dentry);
-#endif
+    DPRINTK (DEBUG_DISABLED, "(%s): new VFS inode(%u): %p  dentry: %p\n",
+	     dentry->d_name.name, de->inode.ino, inode, dentry);
     d_instantiate (dentry, inode);
     if ( !is_devfsd_or_child (fs_info) )
 	devfsd_notify_de (de, DEVFSD_NOTIFY_CREATE, inode->i_mode,
@@ -3081,7 +3081,7 @@
     if (parent == NULL) return -ENOENT;
     de = _devfs_alloc_entry (dentry->d_name.name, dentry->d_name.len, mode);
     if (!de) return -ENOMEM;
-    de->vfs_created = TRUE;
+    de->vfs_deletable = TRUE;
     if ( ( err = _devfs_append_entry (parent, de, FALSE, NULL) ) != 0 )
 	return err;
     de->inode.uid = current->euid;
@@ -3089,13 +3089,10 @@
     de->inode.atime = CURRENT_TIME;
     de->inode.mtime = CURRENT_TIME;
     de->inode.ctime = CURRENT_TIME;
-    if ( ( inode = get_vfs_inode (dir->i_sb, de, dentry) ) == NULL )
+    if ( ( inode = _devfs_get_vfs_inode (dir->i_sb, de, dentry) ) == NULL )
 	return -ENOMEM;
-#ifdef CONFIG_DEVFS_DEBUG
-    if (devfs_debug & DEBUG_DISABLED)
-	printk ("%s: mkdir(): new VFS inode(%u): %p  dentry: %p\n",
-		DEVFS_NAME, de->inode.ino, inode, dentry);
-#endif
+    DPRINTK (DEBUG_DISABLED, "(%s): new VFS inode(%u): %p  dentry: %p\n",
+	     dentry->d_name.name, de->inode.ino, inode, dentry);
     d_instantiate (dentry, inode);
     if ( !is_devfsd_or_child (fs_info) )
 	devfsd_notify_de (de, DEVFSD_NOTIFY_CREATE, inode->i_mode,
@@ -3114,7 +3111,7 @@
     de = get_devfs_entry_from_vfs_inode (inode);
     if (de == NULL) return -ENOENT;
     if ( !S_ISDIR (de->mode) ) return -ENOTDIR;
-    if (!de->vfs_created) return -EPERM;
+    if (!de->vfs_deletable) return -EPERM;
     /*  First ensure the directory is empty and will stay thay way  */
     write_lock (&de->u.dir.lock);
     de->u.dir.no_more_additions = TRUE;
@@ -3142,16 +3139,13 @@
     struct devfs_entry *parent, *de;
     struct inode *inode;
 
-#ifdef CONFIG_DEVFS_DEBUG
-    if (devfs_debug & DEBUG_I_MKNOD)
-	printk ("%s: mknod(%s): mode: 0%o  dev: %d\n",
-		DEVFS_NAME, dentry->d_name.name, mode, rdev);
-#endif
+    DPRINTK (DEBUG_I_MKNOD, "(%s): mode: 0%o  dev: %d\n",
+	     dentry->d_name.name, mode, rdev);
     parent = get_devfs_entry_from_vfs_inode (dir);
     if (parent == NULL) return -ENOENT;
     de = _devfs_alloc_entry (dentry->d_name.name, dentry->d_name.len, mode);
     if (!de) return -ENOMEM;
-    de->vfs_created = TRUE;
+    de->vfs_deletable = TRUE;
     if ( S_ISBLK (mode) || S_ISCHR (mode) )
     {
 	de->u.fcb.u.device.major = MAJOR (rdev);
@@ -3164,13 +3158,10 @@
     de->inode.atime = CURRENT_TIME;
     de->inode.mtime = CURRENT_TIME;
     de->inode.ctime = CURRENT_TIME;
-    if ( ( inode = get_vfs_inode (dir->i_sb, de, dentry) ) == NULL )
+    if ( ( inode = _devfs_get_vfs_inode (dir->i_sb, de, dentry) ) == NULL )
 	return -ENOMEM;
-#ifdef CONFIG_DEVFS_DEBUG
-    if (devfs_debug & DEBUG_I_MKNOD)
-	printk ("%s:   new VFS inode(%u): %p  dentry: %p\n",
-		DEVFS_NAME, de->inode.ino, inode, dentry);
-#endif
+    DPRINTK (DEBUG_I_MKNOD, ":   new VFS inode(%u): %p  dentry: %p\n",
+	     de->inode.ino, inode, dentry);
     d_instantiate (dentry, inode);
     if ( !is_devfsd_or_child (fs_info) )
 	devfsd_notify_de (de, DEVFSD_NOTIFY_CREATE, inode->i_mode,
@@ -3238,15 +3229,11 @@
     sb->s_blocksize_bits = 10;
     sb->s_magic = DEVFS_SUPER_MAGIC;
     sb->s_op = &devfs_sops;
-    if ( ( root_inode = get_vfs_inode (sb, root_entry, NULL) ) == NULL )
+    if ( ( root_inode = _devfs_get_vfs_inode (sb, root_entry, NULL) ) == NULL )
 	goto out_no_root;
     sb->s_root = d_alloc_root (root_inode);
     if (!sb->s_root) goto out_no_root;
-#ifdef CONFIG_DEVFS_DEBUG
-    if (devfs_debug & DEBUG_S_READ)
-	printk ("%s: read super, made devfs ptr: %p\n",
-		DEVFS_NAME, sb->u.generic_sbp);
-#endif
+    DPRINTK (DEBUG_S_READ, "(): made devfs ptr: %p\n", sb->u.generic_sbp);
     return sb;
 
 out_no_root:
@@ -3479,6 +3466,10 @@
 
     printk ("%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),
+					  0, 0, NULL, NULL);
+    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);
@@ -3498,9 +3489,6 @@
 {
     int err;
 
-    devfsd_buf_cache = kmem_cache_create ("devfsd_event",
-					  sizeof (struct devfsd_buf_entry),
-					  0, 0, NULL, NULL);
     if ( !(boot_options & OPTION_MOUNT) ) return;
     err = do_mount ("none", "/dev", "devfs", 0, "");
     if (err == 0) printk ("Mounted devfs on /dev\n");
diff -urN linux-2.4.18-pre4/fs/ext3/ialloc.c linux/fs/ext3/ialloc.c
--- linux-2.4.18-pre4/fs/ext3/ialloc.c	Fri Nov  9 14:25:04 2001
+++ linux/fs/ext3/ialloc.c	Tue Jan 22 12:01:23 2002
@@ -506,7 +506,7 @@
 	if (IS_SYNC(inode))
 		handle->h_sync = 1;
 	insert_inode_hash(inode);
-	inode->i_generation = event++;
+	inode->i_generation = sb->u.ext3_sb.s_next_generation++;
 
 	inode->u.ext3_i.i_state = EXT3_STATE_NEW;
 	err = ext3_mark_inode_dirty(handle, inode);
diff -urN linux-2.4.18-pre4/fs/ext3/super.c linux/fs/ext3/super.c
--- linux-2.4.18-pre4/fs/ext3/super.c	Fri Dec 21 09:41:55 2001
+++ linux/fs/ext3/super.c	Tue Jan 22 12:01:23 2002
@@ -29,6 +29,7 @@
 #include <linux/locks.h>
 #include <linux/blkdev.h>
 #include <linux/smp_lock.h>
+#include <linux/random.h>
 #include <asm/uaccess.h>
 
 #ifdef CONFIG_JBD_DEBUG
@@ -1115,6 +1116,7 @@
 	sbi->s_loaded_inode_bitmaps = 0;
 	sbi->s_loaded_block_bitmaps = 0;
 	sbi->s_gdb_count = db_count;
+	get_random_bytes(&sbi->s_next_generation, sizeof(u32));
 	/*
 	 * set up enough so that it can read an inode
 	 */
diff -urN linux-2.4.18-pre4/fs/fat/inode.c linux/fs/fat/inode.c
--- linux-2.4.18-pre4/fs/fat/inode.c	Tue Nov 20 14:15:26 2001
+++ linux/fs/fat/inode.c	Tue Jan 22 12:01:23 2002
@@ -406,7 +406,7 @@
 	}
 	inode->i_blksize = 1 << sbi->cluster_bits;
 	inode->i_blocks = ((inode->i_size + inode->i_blksize - 1)
-			   & ~(inode->i_blksize - 1)) / 512;
+			   & ~(inode->i_blksize - 1)) >> 9;
 	MSDOS_I(inode)->i_logstart = 0;
 	MSDOS_I(inode)->mmu_private = inode->i_size;
 
@@ -952,7 +952,7 @@
 	/* this is as close to the truth as we can get ... */
 	inode->i_blksize = 1 << sbi->cluster_bits;
 	inode->i_blocks = ((inode->i_size + inode->i_blksize - 1)
-			   & ~(inode->i_blksize - 1)) / 512;
+			   & ~(inode->i_blksize - 1)) >> 9;
 	inode->i_mtime = inode->i_atime =
 		date_dos2unix(CF_LE_W(de->time),CF_LE_W(de->date));
 	inode->i_ctime =
diff -urN linux-2.4.18-pre4/fs/intermezzo/presto.c linux/fs/intermezzo/presto.c
--- linux-2.4.18-pre4/fs/intermezzo/presto.c	Tue Jan 22 12:01:21 2002
+++ linux/fs/intermezzo/presto.c	Tue Jan 22 12:01:23 2002
@@ -190,7 +190,7 @@
         }
 
         EXIT;
-        return ((int)dentry->d_fsdata & flag);
+        return ((int)(long)dentry->d_fsdata & flag);
 }
 
 /* set a bit in the dentry flags */
@@ -211,7 +211,7 @@
                 }
         } else {
                 CDEBUG(D_INODE, "Setting dentry->d_fsdata\n");
-                ((int)dentry->d_fsdata) |= flag;
+                ((int)(long)dentry->d_fsdata) |= flag;
         }
 }
 
@@ -491,10 +491,10 @@
                 CDEBUG(D_INODE, "fset %p, flags %x data %x\n", 
                        fset, fset->fset_flags, fset->fset_data);
         } else {
-                ((int)dentry->d_fsdata) &= and_flag;
-                ((int)dentry->d_fsdata) |= or_flag;
+                ((int)(long)dentry->d_fsdata) &= and_flag;
+                ((int)(long)dentry->d_fsdata) |= or_flag;
                 if (res) 
-                        *res = (int)dentry->d_fsdata;
+                        *res = (int)(long)dentry->d_fsdata;
         }
 
         /* indicate if we were the only users while changing the flag */
diff -urN linux-2.4.18-pre4/fs/jbd/checkpoint.c linux/fs/jbd/checkpoint.c
--- linux-2.4.18-pre4/fs/jbd/checkpoint.c	Fri Nov  9 14:25:04 2001
+++ linux/fs/jbd/checkpoint.c	Tue Jan 22 12:01:23 2002
@@ -448,11 +448,8 @@
 			struct journal_head *last_jh = jh->b_cpprev;
 			struct journal_head *next_jh = jh;
 			do {
-				struct buffer_head *bh;
-
 				jh = next_jh;
 				next_jh = jh->b_cpnext;
-				bh = jh2bh(jh);
 				ret += __try_to_free_cp_buf(jh);
 			} while (jh != last_jh);
 		}
diff -urN linux-2.4.18-pre4/fs/jbd/commit.c linux/fs/jbd/commit.c
--- linux-2.4.18-pre4/fs/jbd/commit.c	Fri Dec 21 09:41:55 2001
+++ linux/fs/jbd/commit.c	Tue Jan 22 12:01:23 2002
@@ -26,7 +26,7 @@
 /*
  * Default IO end handler for temporary BJ_IO buffer_heads.
  */
-static void journal_end_buffer_io_sync(struct buffer_head *bh, int uptodate)
+void journal_end_buffer_io_sync(struct buffer_head *bh, int uptodate)
 {
 	BUFFER_TRACE(bh, "");
 	mark_buffer_uptodate(bh, uptodate);
@@ -410,6 +410,7 @@
 		flags = journal_write_metadata_buffer(commit_transaction,
 						      jh, &new_jh, blocknr);
 		set_bit(BH_JWrite, &jh2bh(new_jh)->b_state);
+		set_bit(BH_Lock, &jh2bh(new_jh)->b_state);
 		wbuf[bufs++] = jh2bh(new_jh);
 
 		/* Record the new block's tag in the current descriptor
@@ -453,7 +454,6 @@
 			unlock_journal(journal);
 			for (i=0; i<bufs; i++) {
 				struct buffer_head *bh = wbuf[i];
-				set_bit(BH_Lock, &bh->b_state);
 				clear_bit(BH_Dirty, &bh->b_state);
 				bh->b_end_io = journal_end_buffer_io_sync;
 				submit_bh(WRITE, bh);
@@ -561,8 +561,7 @@
 		journal_unfile_buffer(jh);
 		jh->b_transaction = NULL;
 		journal_unlock_journal_head(jh);
-		__brelse(bh);		/* One for getblk */
-		/* AKPM: bforget here */
+		put_bh(bh);			/* One for getblk */
 	}
 
 	jbd_debug(3, "JBD: commit phase 6\n");
@@ -594,9 +593,11 @@
 	JBUFFER_TRACE(descriptor, "write commit block");
 	{
 		struct buffer_head *bh = jh2bh(descriptor);
-		ll_rw_block(WRITE, 1, &bh);
+		clear_bit(BH_Dirty, &bh->b_state);
+		bh->b_end_io = journal_end_buffer_io_sync;
+		submit_bh(WRITE, bh);
 		wait_on_buffer(bh);
-		__brelse(bh);		/* One for getblk() */
+		put_bh(bh);		/* One for getblk() */
 		journal_unlock_journal_head(descriptor);
 	}
 	lock_journal(journal);
diff -urN linux-2.4.18-pre4/fs/jbd/journal.c linux/fs/jbd/journal.c
--- linux-2.4.18-pre4/fs/jbd/journal.c	Fri Dec 21 09:41:55 2001
+++ linux/fs/jbd/journal.c	Tue Jan 22 12:01:23 2002
@@ -654,6 +654,8 @@
  * We play buffer_head aliasing tricks to write data/metadata blocks to
  * the journal without copying their contents, but for journal
  * descriptor blocks we do need to generate bona fide buffers.
+ *
+ * We return a jh whose bh is locked and ready to be populated.
  */
 
 struct journal_head * journal_get_descriptor_buffer(journal_t *journal)
@@ -668,7 +670,7 @@
 		return NULL;
 
 	bh = getblk(journal->j_dev, blocknr, journal->j_blocksize);
-	bh->b_state |= (1 << BH_Dirty);
+	lock_buffer(bh);
 	BUFFER_TRACE(bh, "return this buffer");
 	return journal_add_journal_head(bh);
 }
diff -urN linux-2.4.18-pre4/fs/jbd/recovery.c linux/fs/jbd/recovery.c
--- linux-2.4.18-pre4/fs/jbd/recovery.c	Fri Dec 21 09:41:55 2001
+++ linux/fs/jbd/recovery.c	Tue Jan 22 12:01:23 2002
@@ -472,6 +472,7 @@
 						goto failed;
 					}
 
+					lock_buffer(nbh);
 					memcpy(nbh->b_data, obh->b_data,
 							journal->j_blocksize);
 					if (flags & JFS_FLAG_ESCAPE) {
@@ -483,6 +484,7 @@
 					mark_buffer_dirty(nbh);
 					BUFFER_TRACE(nbh, "marking uptodate");
 					mark_buffer_uptodate(nbh, 1);
+					unlock_buffer(nbh);
 					++info->nr_replays;
 					/* ll_rw_block(WRITE, 1, &nbh); */
 					brelse(obh);
diff -urN linux-2.4.18-pre4/fs/jbd/revoke.c linux/fs/jbd/revoke.c
--- linux-2.4.18-pre4/fs/jbd/revoke.c	Fri Dec 21 09:41:55 2001
+++ linux/fs/jbd/revoke.c	Tue Jan 22 12:01:23 2002
@@ -531,6 +531,7 @@
 
 	if (is_journal_aborted(journal)) {
 		JBUFFER_TRACE(descriptor, "brelse");
+		unlock_buffer(jh2bh(descriptor));
 		__brelse(jh2bh(descriptor));
 		return;
 	}
@@ -541,7 +542,9 @@
 	{
 		struct buffer_head *bh = jh2bh(descriptor);
 		BUFFER_TRACE(bh, "write");
-		ll_rw_block (WRITE, 1, &bh);
+		clear_bit(BH_Dirty, &bh->b_state);
+		bh->b_end_io = journal_end_buffer_io_sync;
+		submit_bh(WRITE, bh);
 	}
 }
 
diff -urN linux-2.4.18-pre4/fs/jbd/transaction.c linux/fs/jbd/transaction.c
--- linux-2.4.18-pre4/fs/jbd/transaction.c	Fri Dec 21 09:41:55 2001
+++ linux/fs/jbd/transaction.c	Tue Jan 22 12:01:23 2002
@@ -97,6 +97,8 @@
 
 	lock_journal(journal);
 
+repeat_locked:
+
 	if (is_journal_aborted(journal) ||
 	    (journal->j_errno != 0 && !(journal->j_flags & JFS_ACK_ERR))) {
 		unlock_journal(journal);
@@ -110,7 +112,6 @@
 		goto repeat;
 	}
 	
-repeat_locked:
 	if (!journal->j_running_transaction)
 		get_transaction(journal, 0);
 	/* @@@ Error? */
@@ -604,6 +605,7 @@
 		spin_unlock(&journal_datalist_lock);
 		unlock_buffer(jh2bh(jh));
 		lock_journal(journal);
+		goto repeat;
 	}
 
 	J_ASSERT_JH(jh, !buffer_locked(jh2bh(jh)));
diff -urN linux-2.4.18-pre4/fs/ntfs/Makefile linux/fs/ntfs/Makefile
--- linux-2.4.18-pre4/fs/ntfs/Makefile	Fri Dec 21 09:42:03 2001
+++ linux/fs/ntfs/Makefile	Tue Jan 22 12:01:23 2002
@@ -5,7 +5,7 @@
 obj-y   := fs.o sysctl.o support.o util.o inode.o dir.o super.o attr.o unistr.o
 obj-m   := $(O_TARGET)
 # New version format started 3 February 2001.
-EXTRA_CFLAGS = -DNTFS_VERSION=\"1.1.21\" #-DDEBUG
+EXTRA_CFLAGS = -DNTFS_VERSION=\"1.1.22\" #-DDEBUG
 
 include $(TOPDIR)/Rules.make
 
diff -urN linux-2.4.18-pre4/fs/ntfs/support.h linux/fs/ntfs/support.h
--- linux-2.4.18-pre4/fs/ntfs/support.h	Sun Sep  9 16:45:12 2001
+++ linux/fs/ntfs/support.h	Tue Jan 22 12:01:23 2002
@@ -32,9 +32,39 @@
 
 #define ntfs_free(ptr)     kfree(ptr)
 
-#define ntfs_vmalloc(size)	vmalloc_32(size)
+/**
+ * ntfs_vmalloc - allocate memory in multiples of pages
+ * @size	number of bytes to allocate
+ *
+ * Allocates @size bytes of memory, rounded up to multiples of PAGE_SIZE and
+ * returns a pointer to the allocated memory.
+ *
+ * If there was insufficient memory to complete the request, return NULL.
+ */
+static inline void *ntfs_vmalloc(unsigned long size)
+{
+	if (size <= PAGE_SIZE) {
+		if (size) {
+			/* kmalloc() has per-CPU caches so if faster for now. */
+			return kmalloc(PAGE_SIZE, GFP_NOFS);
+			/* return (void *)__get_free_page(GFP_NOFS |
+					__GFP_HIGHMEM); */
+		}
+		BUG();
+	}
+	if (size >> PAGE_SHIFT < num_physpages)
+		return __vmalloc(size, GFP_NOFS | __GFP_HIGHMEM, PAGE_KERNEL);
+	return NULL;
+}
 
-#define ntfs_vfree(ptr)		vfree(ptr)
+static inline void ntfs_vfree(void *addr)
+{
+	if ((unsigned long)addr < VMALLOC_START) {
+		return kfree(addr);
+		/* return free_page((unsigned long)addr); */
+	}
+	vfree(addr);
+}
 
 void ntfs_bzero(void *s, int n);
 
diff -urN linux-2.4.18-pre4/fs/reiserfs/Makefile linux/fs/reiserfs/Makefile
--- linux-2.4.18-pre4/fs/reiserfs/Makefile	Wed Nov 21 09:56:28 2001
+++ linux/fs/reiserfs/Makefile	Tue Jan 22 12:01:23 2002
@@ -9,7 +9,7 @@
 
 O_TARGET := reiserfs.o
 obj-y   := bitmap.o do_balan.o namei.o inode.o file.o dir.o fix_node.o super.o prints.o objectid.o \
-lbalance.o ibalance.o stree.o hashes.o buffer2.o tail_conversion.o journal.o resize.o tail_conversion.o version.o item_ops.o ioctl.o procfs.o
+lbalance.o ibalance.o stree.o hashes.o buffer2.o tail_conversion.o journal.o resize.o version.o item_ops.o ioctl.o procfs.o
 
 obj-m   := $(O_TARGET)
 
diff -urN linux-2.4.18-pre4/fs/reiserfs/file.c linux/fs/reiserfs/file.c
--- linux-2.4.18-pre4/fs/reiserfs/file.c	Fri Dec 21 09:42:03 2001
+++ linux/fs/reiserfs/file.c	Tue Jan 22 12:01:23 2002
@@ -100,6 +100,20 @@
 	if (get_inode_item_key_version(inode) == KEY_FORMAT_3_5 &&
 	    attr->ia_size > MAX_NON_LFS)
             return -EFBIG ;
+
+	/* fill in hole pointers in the expanding truncate case. */
+        if (attr->ia_size > inode->i_size) {
+	    error = generic_cont_expand(inode, attr->ia_size) ;
+	    if (inode->u.reiserfs_i.i_prealloc_count > 0) {
+		struct reiserfs_transaction_handle th ;
+		/* we're changing at most 2 bitmaps, inode + super */
+		journal_begin(&th, inode->i_sb, 4) ;
+		reiserfs_discard_prealloc (&th, inode);
+		journal_end(&th, inode->i_sb, 4) ;
+	    }
+	    if (error)
+	        return error ;
+	}
     }
 
     if ((((attr->ia_valid & ATTR_UID) && (attr->ia_uid & ~0xffff)) ||
diff -urN linux-2.4.18-pre4/fs/reiserfs/inode.c linux/fs/reiserfs/inode.c
--- linux-2.4.18-pre4/fs/reiserfs/inode.c	Tue Jan 22 12:01:21 2002
+++ linux/fs/reiserfs/inode.c	Tue Jan 22 12:01:23 2002
@@ -2042,7 +2042,7 @@
     /* we test for O_SYNC here so we can commit the transaction
     ** for any packed tails the file might have had
     */
-    if (f->f_flags & O_SYNC) {
+    if (f && (f->f_flags & O_SYNC)) {
 	lock_kernel() ;
  	reiserfs_commit_for_inode(inode) ;
 	unlock_kernel();
diff -urN linux-2.4.18-pre4/fs/super.c linux/fs/super.c
--- linux-2.4.18-pre4/fs/super.c	Fri Dec 21 09:42:03 2001
+++ linux/fs/super.c	Tue Jan 22 12:01:23 2002
@@ -1056,6 +1056,7 @@
 	putname(fs_names);
 	if (path_start >= 0) {
 		name = path + path_start;
+		devfs_unregister (devfs_find_handle(NULL, "root", 0, 0, 0, 0));
 		devfs_mk_symlink (NULL, "root", DEVFS_FL_DEFAULT,
 				  name + 5, NULL, NULL);
 		memcpy (name, "/dev/", 5);
diff -urN linux-2.4.18-pre4/fs/ufs/balloc.c linux/fs/ufs/balloc.c
--- linux-2.4.18-pre4/fs/ufs/balloc.c	Mon Nov 19 14:55:46 2001
+++ linux/fs/ufs/balloc.c	Tue Jan 22 12:01:23 2002
@@ -284,16 +284,16 @@
 			return 0;
 		}
 	}
-	
+
 	/*
 	 * There is not enough space for user on the device
 	 */
-	if (!fsuser() && ufs_freespace(usb1, UFS_MINFREE) <= 0) {
+	if (!capable(CAP_SYS_RESOURCE) && ufs_freespace(usb1, UFS_MINFREE) <= 0) {
 		unlock_super (sb);
 		UFSD(("EXIT (FAILED)\n"))
 		return 0;
-	} 
-	
+	}
+
 	if (goal >= uspi->s_size) 
 		goal = 0;
 	if (goal == 0) 
diff -urN linux-2.4.18-pre4/include/asm-alpha/pci.h linux/include/asm-alpha/pci.h
--- linux-2.4.18-pre4/include/asm-alpha/pci.h	Tue Jan 22 12:01:21 2002
+++ linux/include/asm-alpha/pci.h	Tue Jan 22 12:01:23 2002
@@ -106,13 +106,13 @@
 	dma_addr_t ADDR_NAME;
 #define DECLARE_PCI_UNMAP_LEN(LEN_NAME)		\
 	__u32 LEN_NAME;
-#define PCI_UNMAP_ADDR(PTR, ADDR_NAME)			\
+#define pci_unmap_addr(PTR, ADDR_NAME)			\
 	((PTR)->ADDR_NAME)
-#define PCI_UNMAP_ADDR_SET(PTR, ADDR_NAME, VAL)		\
+#define pci_unmap_addr_set(PTR, ADDR_NAME, VAL)		\
 	(((PTR)->ADDR_NAME) = (VAL))
-#define PCI_UNMAP_LEN(PTR, LEN_NAME)			\
+#define pci_unmap_len(PTR, LEN_NAME)			\
 	((PTR)->LEN_NAME)
-#define PCI_UNMAP_LEN_SET(PTR, LEN_NAME, VAL)		\
+#define pci_unmap_len_set(PTR, LEN_NAME, VAL)		\
 	(((PTR)->LEN_NAME) = (VAL))
 
 /* Map a set of buffers described by scatterlist in streaming mode for
diff -urN linux-2.4.18-pre4/include/asm-arm/pci.h linux/include/asm-arm/pci.h
--- linux-2.4.18-pre4/include/asm-arm/pci.h	Tue Jan 22 12:01:21 2002
+++ linux/include/asm-arm/pci.h	Tue Jan 22 12:01:23 2002
@@ -95,21 +95,21 @@
 	dma_addr_t ADDR_NAME;
 #define DECLARE_PCI_UNMAP_LEN(LEN_NAME)		\
 	__u32 LEN_NAME;
-#define PCI_UNMAP_ADDR(PTR, ADDR_NAME)			\
+#define pci_unmap_addr(PTR, ADDR_NAME)			\
 	((PTR)->ADDR_NAME)
-#define PCI_UNMAP_ADDR_SET(PTR, ADDR_NAME, VAL)		\
+#define pci_unmap_addr_set(PTR, ADDR_NAME, VAL)		\
 	(((PTR)->ADDR_NAME) = (VAL))
-#define PCI_UNMAP_LEN(PTR, LEN_NAME)			\
+#define pci_unmap_len(PTR, LEN_NAME)			\
 	((PTR)->LEN_NAME)
-#define PCI_UNMAP_LEN_SET(PTR, LEN_NAME, VAL)		\
+#define pci_unmap_len_set(PTR, LEN_NAME, VAL)		\
 	(((PTR)->LEN_NAME) = (VAL))
 #else /* !(CONFIG_SA1111) */
 #define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME)
 #define DECLARE_PCI_UNMAP_LEN(LEN_NAME)
-#define PCI_UNMAP_ADDR(PTR, ADDR_NAME)		(0)
-#define PCI_UNMAP_ADDR_SET(PTR, ADDR_NAME, VAL)	do { } while (0)
-#define PCI_UNMAP_LEN(PTR, LEN_NAME)		(0)
-#define PCI_UNMAP_LEN_SET(PTR, LEN_NAME, VAL)	do { } while (0)
+#define pci_unmap_addr(PTR, ADDR_NAME)		(0)
+#define pci_unmap_addr_set(PTR, ADDR_NAME, VAL)	do { } while (0)
+#define pci_unmap_len(PTR, LEN_NAME)		(0)
+#define pci_unmap_len_set(PTR, LEN_NAME, VAL)	do { } while (0)
 #endif /* CONFIG_SA1111 */
 
 /* Map a set of buffers described by scatterlist in streaming
diff -urN linux-2.4.18-pre4/include/asm-i386/pci.h linux/include/asm-i386/pci.h
--- linux-2.4.18-pre4/include/asm-i386/pci.h	Tue Jan 22 12:01:21 2002
+++ linux/include/asm-i386/pci.h	Tue Jan 22 12:01:23 2002
@@ -117,10 +117,10 @@
 /* pci_unmap_{page,single} is a nop so... */
 #define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME)
 #define DECLARE_PCI_UNMAP_LEN(LEN_NAME)
-#define PCI_UNMAP_ADDR(PTR, ADDR_NAME)		(0)
-#define PCI_UNMAP_ADDR_SET(PTR, ADDR_NAME, VAL)	do { } while (0)
-#define PCI_UNMAP_LEN(PTR, LEN_NAME)		(0)
-#define PCI_UNMAP_LEN_SET(PTR, LEN_NAME, VAL)	do { } while (0)
+#define pci_unmap_addr(PTR, ADDR_NAME)		(0)
+#define pci_unmap_addr_SET(PTR, ADDR_NAME, VAL)	do { } while (0)
+#define pci_unmap_len(PTR, LEN_NAME)		(0)
+#define pci_unmap_len_set(PTR, LEN_NAME, VAL)	do { } while (0)
 
 /* Map a set of buffers described by scatterlist in streaming
  * mode for DMA.  This is the scather-gather version of the
diff -urN linux-2.4.18-pre4/include/asm-ia64/pci.h linux/include/asm-ia64/pci.h
--- linux-2.4.18-pre4/include/asm-ia64/pci.h	Tue Jan 22 12:01:21 2002
+++ linux/include/asm-ia64/pci.h	Tue Jan 22 12:01:23 2002
@@ -51,13 +51,13 @@
 	dma_addr_t ADDR_NAME;
 #define DECLARE_PCI_UNMAP_LEN(LEN_NAME)		\
 	__u32 LEN_NAME;
-#define PCI_UNMAP_ADDR(PTR, ADDR_NAME)			\
+#define pci_unmap_addr(PTR, ADDR_NAME)			\
 	((PTR)->ADDR_NAME)
-#define PCI_UNMAP_ADDR_SET(PTR, ADDR_NAME, VAL)		\
+#define pci_unmap_addr_set(PTR, ADDR_NAME, VAL)		\
 	(((PTR)->ADDR_NAME) = (VAL))
-#define PCI_UNMAP_LEN(PTR, LEN_NAME)			\
+#define pci_unmap_len(PTR, LEN_NAME)			\
 	((PTR)->LEN_NAME)
-#define PCI_UNMAP_LEN_SET(PTR, LEN_NAME, VAL)		\
+#define pci_unmap_len_set(PTR, LEN_NAME, VAL)		\
 	(((PTR)->LEN_NAME) = (VAL))
 
 /*
diff -urN linux-2.4.18-pre4/include/asm-mips/pci.h linux/include/asm-mips/pci.h
--- linux-2.4.18-pre4/include/asm-mips/pci.h	Tue Jan 22 12:01:21 2002
+++ linux/include/asm-mips/pci.h	Tue Jan 22 12:01:23 2002
@@ -117,10 +117,10 @@
 /* pci_unmap_{page,single} is a nop so... */
 #define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME)
 #define DECLARE_PCI_UNMAP_LEN(LEN_NAME)
-#define PCI_UNMAP_ADDR(PTR, ADDR_NAME)		(0)
-#define PCI_UNMAP_ADDR_SET(PTR, ADDR_NAME, VAL)	do { } while (0)
-#define PCI_UNMAP_LEN(PTR, LEN_NAME)		(0)
-#define PCI_UNMAP_LEN_SET(PTR, LEN_NAME, VAL)	do { } while (0)
+#define pci_unmap_addr(PTR, ADDR_NAME)		(0)
+#define pci_unmap_addr_set(PTR, ADDR_NAME, VAL)	do { } while (0)
+#define pci_unmap_len(PTR, LEN_NAME)		(0)
+#define pci_unmap_len_set(PTR, LEN_NAME, VAL)	do { } while (0)
 
 /*
  * Map a set of buffers described by scatterlist in streaming
diff -urN linux-2.4.18-pre4/include/asm-mips64/pci.h linux/include/asm-mips64/pci.h
--- linux-2.4.18-pre4/include/asm-mips64/pci.h	Tue Jan 22 12:01:21 2002
+++ linux/include/asm-mips64/pci.h	Tue Jan 22 12:01:23 2002
@@ -91,13 +91,13 @@
 	dma_addr_t ADDR_NAME;
 #define DECLARE_PCI_UNMAP_LEN(LEN_NAME)		\
 	__u32 LEN_NAME;
-#define PCI_UNMAP_ADDR(PTR, ADDR_NAME)			\
+#define pci_unmap_addr(PTR, ADDR_NAME)			\
 	((PTR)->ADDR_NAME)
-#define PCI_UNMAP_ADDR_SET(PTR, ADDR_NAME, VAL)		\
+#define pci_unmap_addr_set(PTR, ADDR_NAME, VAL)		\
 	(((PTR)->ADDR_NAME) = (VAL))
-#define PCI_UNMAP_LEN(PTR, LEN_NAME)			\
+#define pci_unmap_len(PTR, LEN_NAME)			\
 	((PTR)->LEN_NAME)
-#define PCI_UNMAP_LEN_SET(PTR, LEN_NAME, VAL)		\
+#define pci_unmap_len_set(PTR, LEN_NAME, VAL)		\
 	(((PTR)->LEN_NAME) = (VAL))
 
 #else /* CONFIG_MAPPED_PCI_IO  */
@@ -141,10 +141,10 @@
 /* pci_unmap_{page,single} is a nop so... */
 #define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME)
 #define DECLARE_PCI_UNMAP_LEN(LEN_NAME)
-#define PCI_UNMAP_ADDR(PTR, ADDR_NAME)		(0)
-#define PCI_UNMAP_ADDR_SET(PTR, ADDR_NAME, VAL)	do { } while (0)
-#define PCI_UNMAP_LEN(PTR, LEN_NAME)		(0)
-#define PCI_UNMAP_LEN_SET(PTR, LEN_NAME, VAL)	do { } while (0)
+#define pci_unmap_addr(PTR, ADDR_NAME)		(0)
+#define pci_unmap_addr_set(PTR, ADDR_NAME, VAL)	do { } while (0)
+#define pci_unmap_len(PTR, LEN_NAME)		(0)
+#define pci_unmap_len_set(PTR, LEN_NAME, VAL)	do { } while (0)
 
 /*
  * Map a set of buffers described by scatterlist in streaming
diff -urN linux-2.4.18-pre4/include/asm-parisc/pci.h linux/include/asm-parisc/pci.h
--- linux-2.4.18-pre4/include/asm-parisc/pci.h	Tue Jan 22 12:01:21 2002
+++ linux/include/asm-parisc/pci.h	Tue Jan 22 12:01:23 2002
@@ -177,13 +177,13 @@
 	dma_addr_t ADDR_NAME;
 #define DECLARE_PCI_UNMAP_LEN(LEN_NAME)		\
 	__u32 LEN_NAME;
-#define PCI_UNMAP_ADDR(PTR, ADDR_NAME)			\
+#define pci_unmap_addr(PTR, ADDR_NAME)			\
 	((PTR)->ADDR_NAME)
-#define PCI_UNMAP_ADDR_SET(PTR, ADDR_NAME, VAL)		\
+#define pci_unmap_addr_set(PTR, ADDR_NAME, VAL)		\
 	(((PTR)->ADDR_NAME) = (VAL))
-#define PCI_UNMAP_LEN(PTR, LEN_NAME)			\
+#define pci_unmap_len(PTR, LEN_NAME)			\
 	((PTR)->LEN_NAME)
-#define PCI_UNMAP_LEN_SET(PTR, LEN_NAME, VAL)		\
+#define pci_unmap_len_set(PTR, LEN_NAME, VAL)		\
 	(((PTR)->LEN_NAME) = (VAL))
 
 /* For U2/Astro/Ike based platforms (which are fully I/O coherent)
diff -urN linux-2.4.18-pre4/include/asm-ppc/pci.h linux/include/asm-ppc/pci.h
--- linux-2.4.18-pre4/include/asm-ppc/pci.h	Tue Jan 22 12:01:21 2002
+++ linux/include/asm-ppc/pci.h	Tue Jan 22 12:01:23 2002
@@ -105,10 +105,10 @@
 /* pci_unmap_{page,single} is a nop so... */
 #define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME)
 #define DECLARE_PCI_UNMAP_LEN(LEN_NAME)
-#define PCI_UNMAP_ADDR(PTR, ADDR_NAME)		(0)
-#define PCI_UNMAP_ADDR_SET(PTR, ADDR_NAME, VAL)	do { } while (0)
-#define PCI_UNMAP_LEN(PTR, LEN_NAME)		(0)
-#define PCI_UNMAP_LEN_SET(PTR, LEN_NAME, VAL)	do { } while (0)
+#define pci_unmap_addr(PTR, ADDR_NAME)		(0)
+#define pci_unmap_addr_set(PTR, ADDR_NAME, VAL)	do { } while (0)
+#define pci_unmap_len(PTR, LEN_NAME)		(0)
+#define pci_unmap_len_set(PTR, LEN_NAME, VAL)	do { } while (0)
 
 /*
  * pci_{map,unmap}_single_page maps a kernel page to a dma_addr_t. identical
diff -urN linux-2.4.18-pre4/include/asm-sh/pci.h linux/include/asm-sh/pci.h
--- linux-2.4.18-pre4/include/asm-sh/pci.h	Tue Jan 22 12:01:21 2002
+++ linux/include/asm-sh/pci.h	Tue Jan 22 12:01:23 2002
@@ -97,21 +97,21 @@
 	dma_addr_t ADDR_NAME;
 #define DECLARE_PCI_UNMAP_LEN(LEN_NAME)		\
 	__u32 LEN_NAME;
-#define PCI_UNMAP_ADDR(PTR, ADDR_NAME)			\
+#define pci_unmap_addr(PTR, ADDR_NAME)			\
 	((PTR)->ADDR_NAME)
-#define PCI_UNMAP_ADDR_SET(PTR, ADDR_NAME, VAL)		\
+#define pci_unmap_addr_set(PTR, ADDR_NAME, VAL)		\
 	(((PTR)->ADDR_NAME) = (VAL))
-#define PCI_UNMAP_LEN(PTR, LEN_NAME)			\
+#define pci_unmap_len(PTR, LEN_NAME)			\
 	((PTR)->LEN_NAME)
-#define PCI_UNMAP_LEN_SET(PTR, LEN_NAME, VAL)		\
+#define pci_unmap_len_set(PTR, LEN_NAME, VAL)		\
 	(((PTR)->LEN_NAME) = (VAL))
 #else
 #define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME)
 #define DECLARE_PCI_UNMAP_LEN(LEN_NAME)
-#define PCI_UNMAP_ADDR(PTR, ADDR_NAME)		(0)
-#define PCI_UNMAP_ADDR_SET(PTR, ADDR_NAME, VAL)	do { } while (0)
-#define PCI_UNMAP_LEN(PTR, LEN_NAME)		(0)
-#define PCI_UNMAP_LEN_SET(PTR, LEN_NAME, VAL)	do { } while (0)
+#define pci_unmap_addr(PTR, ADDR_NAME)		(0)
+#define pci_unmap_addr_set(PTR, ADDR_NAME, VAL)	do { } while (0)
+#define pci_unmap_len(PTR, LEN_NAME)		(0)
+#define pci_unmap_len_set(PTR, LEN_NAME, VAL)	do { } while (0)
 #endif
 
 /* Unmap a single streaming mode DMA translation.  The dma_addr and size
diff -urN linux-2.4.18-pre4/include/asm-sparc/pci.h linux/include/asm-sparc/pci.h
--- linux-2.4.18-pre4/include/asm-sparc/pci.h	Tue Jan 22 12:01:21 2002
+++ linux/include/asm-sparc/pci.h	Tue Jan 22 12:01:23 2002
@@ -68,13 +68,13 @@
 	dma_addr_t ADDR_NAME;
 #define DECLARE_PCI_UNMAP_LEN(LEN_NAME)		\
 	__u32 LEN_NAME;
-#define PCI_UNMAP_ADDR(PTR, ADDR_NAME)			\
+#define pci_unmap_addr(PTR, ADDR_NAME)			\
 	((PTR)->ADDR_NAME)
-#define PCI_UNMAP_ADDR_SET(PTR, ADDR_NAME, VAL)		\
+#define pci_unmap_addr_set(PTR, ADDR_NAME, VAL)		\
 	(((PTR)->ADDR_NAME) = (VAL))
-#define PCI_UNMAP_LEN(PTR, LEN_NAME)			\
+#define pci_unmap_len(PTR, LEN_NAME)			\
 	((PTR)->LEN_NAME)
-#define PCI_UNMAP_LEN_SET(PTR, LEN_NAME, VAL)		\
+#define pci_unmap_len_set(PTR, LEN_NAME, VAL)		\
 	(((PTR)->LEN_NAME) = (VAL))
 
 /* Map a set of buffers described by scatterlist in streaming
diff -urN linux-2.4.18-pre4/include/asm-sparc64/pci.h linux/include/asm-sparc64/pci.h
--- linux-2.4.18-pre4/include/asm-sparc64/pci.h	Tue Jan 22 12:01:21 2002
+++ linux/include/asm-sparc64/pci.h	Tue Jan 22 12:01:23 2002
@@ -82,13 +82,13 @@
 	dma_addr_t ADDR_NAME;
 #define DECLARE_PCI_UNMAP_LEN(LEN_NAME)		\
 	__u32 LEN_NAME;
-#define PCI_UNMAP_ADDR(PTR, ADDR_NAME)			\
+#define pci_unmap_addr(PTR, ADDR_NAME)			\
 	((PTR)->ADDR_NAME)
-#define PCI_UNMAP_ADDR_SET(PTR, ADDR_NAME, VAL)		\
+#define pci_unmap_addr_set(PTR, ADDR_NAME, VAL)		\
 	(((PTR)->ADDR_NAME) = (VAL))
-#define PCI_UNMAP_LEN(PTR, LEN_NAME)			\
+#define pci_unmap_len(PTR, LEN_NAME)			\
 	((PTR)->LEN_NAME)
-#define PCI_UNMAP_LEN_SET(PTR, LEN_NAME, VAL)		\
+#define pci_unmap_len_set(PTR, LEN_NAME, VAL)		\
 	(((PTR)->LEN_NAME) = (VAL))
 
 /* Map a set of buffers described by scatterlist in streaming
diff -urN linux-2.4.18-pre4/include/linux/ext3_fs.h linux/include/linux/ext3_fs.h
--- linux-2.4.18-pre4/include/linux/ext3_fs.h	Fri Dec 21 09:42:03 2001
+++ linux/include/linux/ext3_fs.h	Tue Jan 22 12:01:23 2002
@@ -36,8 +36,8 @@
 /*
  * The second extended file system version
  */
-#define EXT3FS_DATE		"02 Dec 2001"
-#define EXT3FS_VERSION		"2.4-0.9.16"
+#define EXT3FS_DATE		"10 Jan 2002"
+#define EXT3FS_VERSION		"2.4-0.9.17"
 
 /*
  * Debug code
diff -urN linux-2.4.18-pre4/include/linux/ext3_fs_sb.h linux/include/linux/ext3_fs_sb.h
--- linux-2.4.18-pre4/include/linux/ext3_fs_sb.h	Thu Nov 22 11:46:19 2001
+++ linux/include/linux/ext3_fs_sb.h	Tue Jan 22 12:01:23 2002
@@ -61,6 +61,7 @@
 	int s_desc_per_block_bits;
 	int s_inode_size;
 	int s_first_ino;
+	u32 s_next_generation;
 
 	/* Journaling */
 	struct inode * s_journal_inode;
diff -urN linux-2.4.18-pre4/include/linux/fs.h linux/include/linux/fs.h
--- linux-2.4.18-pre4/include/linux/fs.h	Tue Jan 22 12:01:21 2002
+++ linux/include/linux/fs.h	Tue Jan 22 12:01:23 2002
@@ -1384,6 +1384,7 @@
 extern int block_prepare_write(struct page*, unsigned, unsigned, get_block_t*);
 extern int cont_prepare_write(struct page*, unsigned, unsigned, get_block_t*,
 				unsigned long *);
+extern int generic_cont_expand(struct inode *inode, loff_t size) ;
 extern int block_commit_write(struct page *page, unsigned from, unsigned to);
 extern int block_sync_page(struct page *);
 
diff -urN linux-2.4.18-pre4/include/linux/genhd.h linux/include/linux/genhd.h
--- linux-2.4.18-pre4/include/linux/genhd.h	Thu Nov 22 11:47:05 2001
+++ linux/include/linux/genhd.h	Tue Jan 22 12:01:23 2002
@@ -37,6 +37,7 @@
 /* Ours is not to wonder why.. */
 	BSD_PARTITION =	FREEBSD_PARTITION,
 	MINIX_PARTITION = 0x81,  /* Minix Partition ID */
+	PLAN9_PARTITION = 0x39,  /* Plan 9 Partition ID */
 	UNIXWARE_PARTITION = 0x63,		/* Partition ID, same as */
 						/* GNU_HURD and SCO Unix */
 };
diff -urN linux-2.4.18-pre4/include/linux/jbd.h linux/include/linux/jbd.h
--- linux-2.4.18-pre4/include/linux/jbd.h	Fri Dec 21 09:42:03 2001
+++ linux/include/linux/jbd.h	Tue Jan 22 12:01:23 2002
@@ -567,6 +567,7 @@
 int journal_next_log_block(journal_t *, unsigned long *);
 
 /* Commit management */
+void journal_end_buffer_io_sync(struct buffer_head *bh, int uptodate);
 extern void journal_commit_transaction(journal_t *);
 
 /* Checkpoint list management */
@@ -799,8 +800,6 @@
 #define BJ_Reserved	8	/* Buffer is reserved for access by journal */
 #define BJ_Types	9
  
-extern int jbd_blocks_per_page(struct inode *inode);
-
 #ifdef __KERNEL__
 
 extern spinlock_t jh_splice_lock;
diff -urN linux-2.4.18-pre4/include/linux/kdev_t.h linux/include/linux/kdev_t.h
--- linux-2.4.18-pre4/include/linux/kdev_t.h	Tue Jan 22 12:01:21 2002
+++ linux/include/linux/kdev_t.h	Tue Jan 22 12:01:23 2002
@@ -81,7 +81,7 @@
 #define major(d) MAJOR(d)
 #define minor(d) MINOR(d)
 #define kdev_same(a,b) (a==b)
-#define kdev_none(d) (!d)
+#define kdev_none(d) (!(d))
 
 /*
 As long as device numbers in the outside world have 16 bits only,
diff -urN linux-2.4.18-pre4/include/linux/watchdog.h linux/include/linux/watchdog.h
--- linux-2.4.18-pre4/include/linux/watchdog.h	Fri Nov  9 14:11:15 2001
+++ linux/include/linux/watchdog.h	Tue Jan 22 12:01:23 2002
@@ -25,7 +25,8 @@
 #define	WDIOC_GETTEMP		_IOR(WATCHDOG_IOCTL_BASE, 3, int)
 #define	WDIOC_SETOPTIONS	_IOR(WATCHDOG_IOCTL_BASE, 4, int)
 #define	WDIOC_KEEPALIVE		_IOR(WATCHDOG_IOCTL_BASE, 5, int)
-#define	WDIOC_SETTIMEOUT        _IOW(WATCHDOG_IOCTL_BASE, 6, int)
+#define	WDIOC_SETTIMEOUT        _IOWR(WATCHDOG_IOCTL_BASE, 6, int)
+#define	WDIOC_GETTIMEOUT        _IOR(WATCHDOG_IOCTL_BASE, 7, int)
 
 #define	WDIOF_UNKNOWN		-1	/* Unknown flag error */
 #define	WDIOS_UNKNOWN		-1	/* Unknown status error */
@@ -37,6 +38,7 @@
 #define	WDIOF_POWERUNDER	0x0010	/* Power bad/power fault */
 #define	WDIOF_CARDRESET		0x0020	/* Card previously reset the CPU */
 #define WDIOF_POWEROVER		0x0040	/* Power over voltage */
+#define WDIOF_SETTIMEOUT	0x0080  /* Set timeout (in seconds) */
 #define	WDIOF_KEEPALIVEPING	0x8000	/* Keep alive ping reply */
 
 #define	WDIOS_DISABLECARD	0x0001	/* Turn off the watchdog timer */
diff -urN linux-2.4.18-pre4/kernel/ksyms.c linux/kernel/ksyms.c
--- linux-2.4.18-pre4/kernel/ksyms.c	Tue Jan 22 12:01:21 2002
+++ linux/kernel/ksyms.c	Tue Jan 22 12:01:23 2002
@@ -204,6 +204,7 @@
 EXPORT_SYMBOL(block_read_full_page);
 EXPORT_SYMBOL(block_prepare_write);
 EXPORT_SYMBOL(block_sync_page);
+EXPORT_SYMBOL(generic_cont_expand);
 EXPORT_SYMBOL(cont_prepare_write);
 EXPORT_SYMBOL(generic_commit_write);
 EXPORT_SYMBOL(block_truncate_page);
diff -urN linux-2.4.18-pre4/mm/swapfile.c linux/mm/swapfile.c
--- linux-2.4.18-pre4/mm/swapfile.c	Fri Dec 21 09:42:05 2001
+++ linux/mm/swapfile.c	Tue Jan 22 12:01:23 2002
@@ -344,7 +344,7 @@
 	if (page) {
 		page_cache_get(page);
 		/* Only cache user (+us), or swap space full? Free it! */
-		if (page_count(page) == 2 || vm_swap_full()) {
+		if (page_count(page) - !!page->buffers == 2 || vm_swap_full()) {
 			delete_from_swap_cache(page);
 			SetPageDirty(page);
 		}
diff -urN linux-2.4.18-pre4/net/bridge/br_fdb.c linux/net/bridge/br_fdb.c
--- linux-2.4.18-pre4/net/bridge/br_fdb.c	Thu Nov  9 15:57:53 2000
+++ linux/net/bridge/br_fdb.c	Tue Jan 22 12:01:23 2002
@@ -5,7 +5,7 @@
  *	Authors:
  *	Lennert Buytenhek		<buytenh@gnu.org>
  *
- *	$Id: br_fdb.c,v 1.5 2000/11/08 05:16:40 davem Exp $
+ *	$Id: br_fdb.c,v 1.5.2.1 2002/01/17 00:59:01 davem Exp $
  *
  *	This program is free software; you can redistribute it and/or
  *	modify it under the terms of the GNU General Public License
@@ -292,7 +292,8 @@
 	write_lock_bh(&br->hash_lock);
 	fdb = br->hash[hash];
 	while (fdb != NULL) {
-		if (!memcmp(fdb->addr.addr, addr, ETH_ALEN)) {
+		if (!fdb->is_local &&
+		    !memcmp(fdb->addr.addr, addr, ETH_ALEN)) {
 			__fdb_possibly_replace(fdb, source, is_local);
 			write_unlock_bh(&br->hash_lock);
 			return;
diff -urN linux-2.4.18-pre4/net/core/dev.c linux/net/core/dev.c
--- linux-2.4.18-pre4/net/core/dev.c	Wed Nov  7 14:39:36 2001
+++ linux/net/core/dev.c	Tue Jan 22 12:01:23 2002
@@ -238,7 +238,7 @@
 
 #ifdef CONFIG_NET_FASTROUTE
 	/* Hack to detect packet socket */
-	if (pt->data) {
+	if ((pt->data) && ((int)(pt->data)!=1)) {
 		netdev_fastroute_obstacles++;
 		dev_clear_fastroute(pt->dev);
 	}
diff -urN linux-2.4.18-pre4/net/ipv4/icmp.c linux/net/ipv4/icmp.c
--- linux-2.4.18-pre4/net/ipv4/icmp.c	Tue Jan 22 12:01:21 2002
+++ linux/net/ipv4/icmp.c	Tue Jan 22 12:01:23 2002
@@ -495,7 +495,7 @@
 	icmp_param.data.icmph.checksum=0;
 	icmp_param.csum=0;
 	icmp_param.skb=skb_in;
-	icmp_param.offset=skb_in->nh.raw - skb_in->data;
+	icmp_param.offset=skb_in->data - skb_in->nh.raw;
 	icmp_out_count(icmp_param.data.icmph.type);
 	icmp_socket->sk->protinfo.af_inet.tos = tos;
 	ipc.addr = iph->saddr;
diff -urN linux-2.4.18-pre4/net/ipv6/icmp.c linux/net/ipv6/icmp.c
--- linux-2.4.18-pre4/net/ipv6/icmp.c	Thu Sep 20 14:12:56 2001
+++ linux/net/ipv6/icmp.c	Tue Jan 22 12:01:23 2002
@@ -361,7 +361,7 @@
 	msg.icmph.icmp6_pointer = htonl(info);
 
 	msg.skb = skb;
-	msg.offset = skb->nh.raw - skb->data;
+	msg.offset = skb->data - skb->nh.raw; 
 	msg.csum = 0;
 	msg.daddr = &hdr->saddr;
 
diff -urN linux-2.4.18-pre4/net/netsyms.c linux/net/netsyms.c
--- linux-2.4.18-pre4/net/netsyms.c	Fri Dec 21 09:42:06 2001
+++ linux/net/netsyms.c	Tue Jan 22 12:01:23 2002
@@ -519,6 +519,10 @@
 EXPORT_SYMBOL(hippi_type_trans);
 #endif
 
+#ifdef CONFIG_NET_FASTROUTE
+EXPORT_SYMBOL(netdev_fastroute);
+#endif
+
 #ifdef CONFIG_SYSCTL
 EXPORT_SYMBOL(sysctl_wmem_max);
 EXPORT_SYMBOL(sysctl_rmem_max);
