## Automatically generated incremental diff
## From:   linux-2.4.17-pre5
## To:     linux-2.4.17-pre6
## Robot:  $Id: make-incremental-diff,v 1.8 2001/12/04 06:05:04 hpa Exp $

diff -urN linux-2.4.17-pre5/Documentation/Changes linux/Documentation/Changes
--- linux-2.4.17-pre5/Documentation/Changes	Mon Sep 17 23:10:44 2001
+++ linux/Documentation/Changes	Fri Dec  7 14:53:07 2001
@@ -53,7 +53,7 @@
 o  binutils               2.9.1.0.25              # ld -v
 o  util-linux             2.10o                   # fdformat --version
 o  modutils               2.4.2                   # insmod -V
-o  e2fsprogs              1.19                    # tune2fs
+o  e2fsprogs              1.25                    # tune2fs
 o  reiserfsprogs          3.x.0j                  # reiserfsck 2>&1|grep reiserfsprogs
 o  pcmcia-cs              3.1.21                  # cardmgr -V
 o  PPP                    2.4.0                   # pppd --version
@@ -317,8 +317,7 @@
 
 E2fsprogs
 ---------
-o  <http://prdownloads.sourceforge.net/e2fsprogs/e2fsprogs-1.19.tar.gz>
-o  <http://prdownloads.sourceforge.net/e2fsprogs/e2fsprogs-1.19-0.src.rpm>
+o  <http://prdownloads.sourceforge.net/e2fsprogs/e2fsprogs-1.25.tar.gz>
 
 Reiserfsprogs
 -------------
diff -urN linux-2.4.17-pre5/Documentation/Configure.help linux/Documentation/Configure.help
--- linux-2.4.17-pre5/Documentation/Configure.help	Fri Dec  7 14:52:27 2001
+++ linux/Documentation/Configure.help	Fri Dec  7 14:53:07 2001
@@ -2,7 +2,7 @@
 #	Eric S. Raymond <mailto:esr@thyrsus.com>
 #	Steven Cole <mailto:elenstev@mesatop.com>
 #
-# Merged version 2.66: current with 2.4.17-pre2/2.5.1-pre5.
+# Merged version 2.67: current with 2.4.17-pre5/2.5.1-pre6.
 #
 # This version of the Linux kernel configuration help texts
 # corresponds to kernel versions 2.4.x and 2.5.x.
@@ -341,7 +341,7 @@
   "high memory".
 
   If you are compiling a kernel which will never run on a machine with
-  more than 1 Gigabyte total physical RAM, answer "off" here (default
+  more than 960 megabytes of total physical RAM, answer "off" here (default
   choice and suitable for most users). This will result in a "3GB/1GB"
   split: 3GB are mapped so that each process sees a 3GB virtual memory
   space and the remaining part of the 4GB virtual memory space is used
@@ -358,10 +358,10 @@
   processors (Pentium Pro and better). NOTE: If you say "64GB" here,
   then the kernel will not boot on CPUs that don't support PAE!
 
-  The actual amount of total physical memory will either be
-  auto detected or can be forced by using a kernel command line option
-  such as "mem=256M". (Try "man bootparam" or see the documentation of
-  your boot loader (lilo or loadlin) about how to pass options to the
+  The actual amount of total physical memory will either be auto
+  detected or can be forced by using a kernel command line option such
+  as "mem=256M". (Try "man bootparam" or see the documentation of your
+  boot loader (grub, lilo or loadlin) about how to pass options to the
   kernel at boot time.)
 
   If unsure, say "off".
@@ -5206,6 +5206,14 @@
 
   It is safe to say N here for now.
 
+# 2.5 tree only
+IPv6: routing messages via old netlink
+CONFIG_IPV6_NETLINK
+  You can say Y here to receive routing messages from the IPv6 code
+  through the old netlink interface. However, a better option is to
+  say Y to "Kernel/User network link driver" and to "Routing
+  messages" instead.
+
 Kernel httpd acceleration
 CONFIG_KHTTPD
   The kernel httpd acceleration daemon (kHTTPd) is a (limited) web
@@ -5959,6 +5967,34 @@
 
   If unsure, say N.
 
+# 2.5 tree only
+Kernel/User network link driver
+CONFIG_NETLINK
+  This driver allows for two-way communication between the kernel and
+  user processes.  It does so by creating a new socket family,
+  PF_NETLINK.  Over this socket, the kernel can send and receive
+  datagrams carrying information.  It is documented on many systems in
+  netlink(7).
+
+  So far, the kernel uses this feature to publish some network related
+  information if you say Y to "Routing messages", below. You also need
+  to say Y here if you want to use arpd, a daemon that helps keep the
+  internal ARP cache (a mapping between IP addresses and hardware
+  addresses on the local network) small.  The ethertap device, which
+  lets user space programs read and write raw Ethernet frames, also
+  needs the network link driver.
+
+  If unsure, say Y.
+
+# 2.5 tree only
+Routing messages
+CONFIG_RTNETLINK
+  If you say Y here, user space programs can receive some network
+  related routing information over the netlink. 'rtmon', supplied
+  with the iproute2 package (<ftp://ftp.inr.ac.ru/>), can read and
+  interpret this data.  Information sent to the kernel over this link
+  is ignored.
+
 Netlink device emulation
 CONFIG_NETLINK_DEV
   This option will be removed soon. Any programs that want to use
@@ -8712,19 +8748,6 @@
   a module, say M here and read <file:Documentation/modules.txt>.  If
   unsure, say N.
 
-Asix AX88190 PCMCIA support
-CONFIG_PCMCIA_AXNET
-  Say Y here if you intend to attach an Asix AX88190-based PCMCIA
-  (PC-card) Fast Ethernet card to your computer.  These cards are
-  nearly NE2000 compatible but need a separate driver due to a few
-  misfeatures.
-
-  This driver is also available as a module ( = code which can be
-  inserted in and removed from the running kernel whenever you want).
-  The module will be called axnet_cs.o.  If you want to compile it as
-  a module, say M here and read <file:Documentation/modules.txt>.  If
-  unsure, say N.
-
 New Media PCMCIA support
 CONFIG_PCMCIA_NMCLAN
   Say Y here if you intend to attach a New Media Ethernet or LiveWire
@@ -13844,7 +13867,7 @@
 Ext3 journalling file system support (EXPERIMENTAL)
 CONFIG_EXT3_FS
   This is the journalling version of the Second extended file system
-  (often called ext3), the de facto standard Linux file system
+  (often called ext2), the de facto standard Linux file system
   (method to organize files on a storage device) for hard disks.
 
   The journalling code included in this driver means you do not have
@@ -13961,15 +13984,41 @@
   mainframe systems.  Only the basic format is supported so far.  If
   you don't know what CMS is you probably don't want to know any more.
 
+# When the 2.5 version of configure.help goes away, the part of this that 
+# duplicates Documentation/filesystems/tmpfs.txt can drop out.
 Virtual memory file system support
 CONFIG_TMPFS
   Tmpfs is a file system which keeps all files in virtual memory.
-
   Everything in tmpfs is temporary in the sense that no files will be
   created on your hard drive. If you reboot, everything in tmpfs will
   be lost.
 
-  See <file:Documentation/filesystems/tmpfs.txt> for details
+  In contrast to RAM disks, which get allocated a fixed amount of
+  physical RAM, tmpfs grows and shrinks to accommodate the files it
+  contains and is able to swap unneeded pages out to swap space.
+
+  Everything is "virtual" in the sense that no files will be created
+  on your hard drive; if you reboot, everything in tmpfs will be
+  lost.
+
+  You should mount the file system somewhere to be able to use
+  POSIX shared memory. Adding the following line to /etc/fstab should
+  take care of things:
+
+  tmpfs		/dev/shm	tmpfs		defaults	0 0
+
+  Remember to create the directory that you intend to mount tmpfs on
+  if necessary (/dev/shm is automagically created if you use devfs).
+
+  You can set limits for the number of blocks and inodes used by the
+  file system with the mount options "size", "nr_blocks" and
+  "nr_inodes". These parameters accept a suffix k, m or g for kilo,
+  mega and giga and can be changed on remount.
+
+  The initial permissions of the root directory can be set with the
+  mount option "mode".
+
+  See <file:Documentation/filesystems/tmpfs.txt> for details.
 
 Simple RAM-based file system support
 CONFIG_RAMFS
@@ -18846,6 +18895,26 @@
   hardware debugging with a logic analyzer and need to see all traffic
   on the bus.
 
+AU1000 serial console
+CONFIG_AU1000_SERIAL_CONSOLE
+  If you have an Alchemy AU1000 processor (MIPS based) and you want
+  to use a console on a serial port, say Y.  Otherwise, say N.
+
+AU1000 serial support
+CONFIG_AU1000_UART
+  If you have an Alchemy AU1000 processor (MIPS based) and you want
+  to use serial ports, say Y.  Otherwise, say N.
+
+AU1000 ethernet controller on SGI MIPS system
+CONFIG_MIPS_AU1000_ENET
+  If you have an Alchemy Semi AU1000 ethernet controller
+  on an SGI MIPS system, say Y.  Otherwise, say N.
+
+WD93 SCSI Controller on SGI MIPS system
+CONFIG_SGIWD93_SCSI
+  If you have a Western Digital WD93 SCSI controller on
+  an SGI MIPS system, say Y.  Otherwise, say N.
+
 Magic System Request Key support
 CONFIG_MAGIC_SYSRQ
   If you say Y here, you will have some control over the system even
@@ -21467,7 +21536,7 @@
   otherwise say N.
   This driver is also available as a module (w9966.o).
 
-  Check out <file:Documentation/video4linux/w9966.txt> and
+  Check out <file:drivers/media/video4linux/w9966.txt> and
   <file:drivers/media/video/w9966.c> for more information.
 
 CPiA Video For Linux
@@ -23586,6 +23655,42 @@
   To use this option, you have to check that the "/proc file system
   support" (CONFIG_PROC_FS) is enabled, too.
 
+Physical memory granularity (16 MB)
+CONFIG_IA64_GRANULE_16MB
+  IA64 identity-mapped regions use a large page size.  We'll call such
+  large pages "granules".  If you can think of a better name that's
+  unambiguous, let us know...  Unless your identity-mapped regions are
+  very large, select a granule size of 16MB.
+
+Physical memory granularity (64 MB)
+CONFIG_IA64_GRANULE_64MB
+  IA64 identity-mapped regions use a large page size.  We'll call such
+  large pages "granules".  If you can think of a better name that's
+  unambiguous, let us know...  Unless your identity-mapped regions are
+  very large, select a granule size of 16MB.  (This is the "large" choice.)
+
+Enable SGI SN extra debugging code
+CONFIG_IA64_SGI_SN_DEBUG
+  Turns on extra debugging code in the SGI SN (Scalable NUMA) platform
+  for IA64.  Unless you are debugging problems on an SGI SN IA64 box,
+  say N.
+
+Enable SGI Medusa Simulator Support
+CONFIG_IA64_SGI_SN_SIM
+  If you are compiling a kernel that will run under SGI's IA64
+  simulator (Medusa) then say Y, otherwise say N.
+
+PCIBA Support
+CONFIG_PCIBA
+  IRIX PCIBA-inspired user mode PCI interface for the SGI SN (Scalable
+  NUMA) platform for IA64.  Unless you are compiling a kernel for an              SGI SN IA64 box, say N.
+
+Enable protocol mode for the L1 console
+SERIAL_SGI_L1_PROTOCOL
+  Uses protocol mode instead of raw mode for the level 1 console on the
+  SGI SN (Scalable NUMA) platform for IA64.  If you are compiling for
+  an SGI SN box then Y is the recommended value, otherwise say N.
+
 Directly Connected Compact Flash support
 CONFIG_CF_ENABLER
   Compact Flash is a small, removable mass storage device introduced
@@ -23627,6 +23732,19 @@
   best used in conjunction with the NMI watchdog so that spinlock
   deadlocks are also debuggable.
 
+Read-write spinlock debugging
+CONFIG_DEBUG_RWLOCK
+  If you say Y here then read-write lock processing will count how many
+  times it has tried to get the lock and issue an error message after
+  too many attempts.  If you suspect a rwlock problem or a kernel
+  hacker asks for this option then say Y.  Otherwise say N.
+
+Semaphore debugging
+CONFIG_DEBUG_SEMAPHORE
+  If you say Y here then semaphore processing will issue lots of
+  verbose debugging messages.  If you suspect a semaphore problem or a
+  kernel hacker asks for this option then say Y.  Otherwise say N.
+
 Verbose BUG() reporting (adds 70K)
 CONFIG_DEBUG_BUGVERBOSE
   Say Y here to make BUG() panics output the file name and line number
@@ -24042,10 +24160,10 @@
 # LocalWords:  filesystems smbfs ATA ppp PCTech RZ www powerquest txt CMD ESDI
 # LocalWords:  chipset FB multicast MROUTE appletalk ifconfig IBMTR multiport
 # LocalWords:  Multisession STALDRV EasyIO EC EasyConnection ISTALLION ONboard
-# LocalWords:  Brumby pci TNC cis ohio faq usenet dev hydra ca Tyne mem
+# LocalWords:  Brumby pci TNC cis ohio faq usenet NETLINK dev hydra ca Tyne mem
 # LocalWords:  carleton DECstation SUNFD JENSEN Noname XXXM SLiRP LILO's amifb
 # LocalWords:  pppd Zilog ZS SRM bootloader ez mainmenu rarp ipfwadm paride pcd
-# LocalWords:  mknod xos MTU lwared Macs netatalk macs cs Wolff
+# LocalWords:  RTNETLINK mknod xos MTU lwared Macs netatalk macs cs Wolff
 # LocalWords:  dartmouth flowerpt MultiMaster FlashPoint tudelft etherexpress
 # LocalWords:  ICL EtherTeam ETH IDESCSI TXC SmartRAID SmartCache httpd sjc dlp
 # LocalWords:  thesphere TwoServers BOOTP DHCP ncpfs BPQETHER BPQ MG HIPPI cern
diff -urN linux-2.4.17-pre5/Documentation/filesystems/Locking linux/Documentation/filesystems/Locking
--- linux-2.4.17-pre5/Documentation/filesystems/Locking	Fri Feb 16 15:53:08 2001
+++ linux/Documentation/filesystems/Locking	Fri Dec  7 14:53:07 2001
@@ -123,6 +123,10 @@
 	int (*prepare_write)(struct file *, struct page *, unsigned, unsigned);
 	int (*commit_write)(struct file *, struct page *, unsigned, unsigned);
 	int (*bmap)(struct address_space *, long);
+	int (*flushpage) (struct page *, unsigned long);
+	int (*releasepage) (struct page *, int);
+	int (*direct_IO)(int, struct inode *, struct kiobuf *, unsigned long, int);
+
 locking rules:
 	All may block
 		BKL	PageLocked(page)
@@ -132,6 +136,8 @@
 prepare_write:	no	yes
 commit_write:	no	yes
 bmap:		yes
+flushpage:	no	yes
+releasepage:	no	yes
 
 	->prepare_write(), ->commit_write(), ->sync_page() and ->readpage()
 may be called from the request handler (/dev/loop).
@@ -144,6 +150,15 @@
 filesystems and by the swapper. The latter will eventually go away. All
 instances do not actually need the BKL. Please, keep it that way and don't
 breed new callers.
+	->flushpage() is called when the filesystem must attempt to drop
+some or all of the buffers from the page when it is being truncated.  It
+returns zero on success.  If ->flushpage is zero, the kernel uses
+block_flushpage() instead.
+	->releasepage() is called when the kernel is about to try to drop the
+buffers from the page in preparation for freeing it.  It returns zero to
+indicate that the buffers are (or may be) freeable.  If ->flushpage is zero,
+the kernel assumes that the fs has no private interest in the buffers.
+
 	Note: currently almost all instances of address_space methods are
 using BKL for internal serialization and that's one of the worst sources
 of contention. Normally they are calling library functions (in fs/buffer.c)
diff -urN linux-2.4.17-pre5/Documentation/pci.txt linux/Documentation/pci.txt
--- linux-2.4.17-pre5/Documentation/pci.txt	Sun Nov  4 09:31:57 2001
+++ linux/Documentation/pci.txt	Fri Dec  7 14:53:07 2001
@@ -104,6 +104,10 @@
 	If you are sure the driver is not a hotplug driver then use only 
 	__init/exit __initdata/exitdata.
 
+        Pointers to functions marked as __devexit must be created using
+        __devexit_p(function_name).  That will generate the function
+        name or NULL if the __devexit function will be discarded.
+
 
 2. How to find PCI devices manually (the old style)
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
diff -urN linux-2.4.17-pre5/Documentation/sonypi.txt linux/Documentation/sonypi.txt
--- linux-2.4.17-pre5/Documentation/sonypi.txt	Mon Oct 15 08:38:31 2001
+++ linux/Documentation/sonypi.txt	Fri Dec  7 14:53:07 2001
@@ -58,6 +58,10 @@
 			get enabled unless you set this parameter to 1.
 			Do not use this option unless it's actually necessary,
 			some Vaio models don't deal well with this option.
+			This option is available only if the kernel is 
+			compiled without ACPI support (since it conflicts
+			with it and it shouldn't be required anyway if 
+			ACPI is already enabled).
 
 	verbose:	print unknown events from the sonypi device
 
@@ -93,7 +97,10 @@
 	- some users reported that the laptop speed is lower (dhrystone
 	  tested) when using the driver with the fnkeyinit parameter. I cannot
 	  reproduce it on my laptop and not all users have this problem.
-	  Still under investigation.
+	  This happens because the fnkeyinit parameter enables the ACPI 
+	  mode (but without additionnal ACPI control, like processor 
+	  speed handling etc). Use ACPI instead of APM if it works on your
+	  laptop.
 	
 	- since all development was done by reverse engineering, there is
 	  _absolutely no guarantee_ that this driver will not crash your
diff -urN linux-2.4.17-pre5/Makefile linux/Makefile
--- linux-2.4.17-pre5/Makefile	Fri Dec  7 14:52:27 2001
+++ linux/Makefile	Fri Dec  7 14:53:07 2001
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 4
 SUBLEVEL = 17
-EXTRAVERSION = -pre5
+EXTRAVERSION = -pre6
 
 KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
 
diff -urN linux-2.4.17-pre5/arch/alpha/kernel/smp.c linux/arch/alpha/kernel/smp.c
--- linux-2.4.17-pre5/arch/alpha/kernel/smp.c	Wed Nov 21 10:31:09 2001
+++ linux/arch/alpha/kernel/smp.c	Fri Dec  7 14:53:07 2001
@@ -23,6 +23,7 @@
 #include <linux/delay.h>
 #include <linux/spinlock.h>
 #include <linux/irq.h>
+#include <linux/cache.h>
 
 #include <asm/hwrpb.h>
 #include <asm/ptrace.h>
@@ -65,7 +66,7 @@
 	IPI_CPU_STOP,
 };
 
-spinlock_t kernel_flag = SPIN_LOCK_UNLOCKED;
+spinlock_t kernel_flag __cacheline_aligned_in_smp = SPIN_LOCK_UNLOCKED;
 
 /* Set to a secondary's cpuid when it comes online.  */
 static unsigned long smp_secondary_alive;
diff -urN linux-2.4.17-pre5/arch/i386/boot/setup.S linux/arch/i386/boot/setup.S
--- linux-2.4.17-pre5/arch/i386/boot/setup.S	Fri Nov  9 13:58:02 2001
+++ linux/arch/i386/boot/setup.S	Fri Dec  7 14:53:07 2001
@@ -539,7 +539,7 @@
 	cmpw	$0, %cs:realmode_swtch
 	jz	rmodeswtch_normal
 
-	lcall	%cs:realmode_swtch
+	lcall	*%cs:realmode_swtch
 
 	jmp	rmodeswtch_end
 
diff -urN linux-2.4.17-pre5/arch/i386/kernel/smp.c linux/arch/i386/kernel/smp.c
--- linux-2.4.17-pre5/arch/i386/kernel/smp.c	Tue Oct 23 14:17:10 2001
+++ linux/arch/i386/kernel/smp.c	Fri Dec  7 14:53:07 2001
@@ -17,6 +17,7 @@
 #include <linux/smp_lock.h>
 #include <linux/kernel_stat.h>
 #include <linux/mc146818rtc.h>
+#include <linux/cache.h>
 
 #include <asm/mtrr.h>
 #include <asm/pgalloc.h>
@@ -102,7 +103,7 @@
  */
 
 /* The 'big kernel lock' */
-spinlock_t kernel_flag = SPIN_LOCK_UNLOCKED;
+spinlock_t kernel_flag __cacheline_aligned_in_smp = SPIN_LOCK_UNLOCKED;
 
 struct tlb_state cpu_tlbstate[NR_CPUS] = {[0 ... NR_CPUS-1] = { &init_mm, 0 }};
 
diff -urN linux-2.4.17-pre5/arch/ia64/kernel/smp.c linux/arch/ia64/kernel/smp.c
--- linux-2.4.17-pre5/arch/ia64/kernel/smp.c	Fri Nov  9 14:26:17 2001
+++ linux/arch/ia64/kernel/smp.c	Fri Dec  7 14:53:07 2001
@@ -30,6 +30,7 @@
 #include <linux/kernel_stat.h>
 #include <linux/mm.h>
 #include <linux/delay.h>
+#include <linux/cache.h>
 
 #include <asm/atomic.h>
 #include <asm/bitops.h>
@@ -51,7 +52,7 @@
 #include <asm/mca.h>
 
 /* The 'big kernel lock' */
-spinlock_t kernel_flag = SPIN_LOCK_UNLOCKED;
+spinlock_t kernel_flag __cacheline_aligned_in_smp = SPIN_LOCK_UNLOCKED;
 
 /*
  * Structure and data for smp_call_function(). This is designed to minimise static memory
diff -urN linux-2.4.17-pre5/arch/mips/kernel/smp.c linux/arch/mips/kernel/smp.c
--- linux-2.4.17-pre5/arch/mips/kernel/smp.c	Wed Nov 21 10:31:09 2001
+++ linux/arch/mips/kernel/smp.c	Fri Dec  7 14:53:07 2001
@@ -31,6 +31,7 @@
 #include <linux/timex.h>
 #include <linux/sched.h>
 #include <linux/interrupt.h>
+#include <linux/cache.h>
 
 #include <asm/atomic.h>
 #include <asm/processor.h>
@@ -52,7 +53,7 @@
 
 
 /* Ze Big Kernel Lock! */
-spinlock_t kernel_flag = SPIN_LOCK_UNLOCKED;
+spinlock_t kernel_flag __cacheline_aligned_in_smp = SPIN_LOCK_UNLOCKED;
 int smp_threads_ready;  /* Not used */
 int smp_num_cpus;    
 int global_irq_holder = NO_PROC_ID;
diff -urN linux-2.4.17-pre5/arch/mips64/kernel/smp.c linux/arch/mips64/kernel/smp.c
--- linux-2.4.17-pre5/arch/mips64/kernel/smp.c	Wed Jul  4 11:50:39 2001
+++ linux/arch/mips64/kernel/smp.c	Fri Dec  7 14:53:07 2001
@@ -5,6 +5,7 @@
 #include <linux/time.h>
 #include <linux/timex.h>
 #include <linux/sched.h>
+#include <linux/cache.h>
 
 #include <asm/atomic.h>
 #include <asm/processor.h>
@@ -52,7 +53,7 @@
 #endif /* CONFIG_SGI_IP27 */
 
 /* The 'big kernel lock' */
-spinlock_t kernel_flag = SPIN_LOCK_UNLOCKED;
+spinlock_t kernel_flag __cacheline_aligned_in_smp = SPIN_LOCK_UNLOCKED;
 int smp_threads_ready;	/* Not used */
 atomic_t smp_commenced = ATOMIC_INIT(0);
 struct cpuinfo_mips cpu_data[NR_CPUS];
diff -urN linux-2.4.17-pre5/arch/ppc/kernel/smp.c linux/arch/ppc/kernel/smp.c
--- linux-2.4.17-pre5/arch/ppc/kernel/smp.c	Mon Nov 26 05:29:17 2001
+++ linux/arch/ppc/kernel/smp.c	Fri Dec  7 14:53:07 2001
@@ -23,6 +23,7 @@
 #include <linux/unistd.h>
 #include <linux/init.h>
 #include <linux/spinlock.h>
+#include <linux/cache.h>
 
 #include <asm/ptrace.h>
 #include <asm/atomic.h>
@@ -45,7 +46,7 @@
 struct klock_info_struct klock_info = { KLOCK_CLEAR, 0 };
 atomic_t ipi_recv;
 atomic_t ipi_sent;
-spinlock_t kernel_flag __cacheline_aligned = SPIN_LOCK_UNLOCKED;
+spinlock_t kernel_flag __cacheline_aligned_in_smp = SPIN_LOCK_UNLOCKED;
 unsigned int prof_multiplier[NR_CPUS];
 unsigned int prof_counter[NR_CPUS];
 cycles_t cacheflush_time;
diff -urN linux-2.4.17-pre5/arch/s390/kernel/smp.c linux/arch/s390/kernel/smp.c
--- linux-2.4.17-pre5/arch/s390/kernel/smp.c	Wed Nov 21 10:31:09 2001
+++ linux/arch/s390/kernel/smp.c	Fri Dec  7 14:53:07 2001
@@ -29,6 +29,7 @@
 #include <linux/smp_lock.h>
 
 #include <linux/delay.h>
+#include <linux/cache.h>
 
 #include <asm/sigp.h>
 #include <asm/pgalloc.h>
@@ -55,7 +56,7 @@
 int              smp_threads_ready=0;      /* Set when the idlers are all forked. */
 static atomic_t  smp_commenced = ATOMIC_INIT(0);
 
-spinlock_t       kernel_flag = SPIN_LOCK_UNLOCKED;
+spinlock_t       kernel_flag __cacheline_aligned_in_smp = SPIN_LOCK_UNLOCKED;
 
 unsigned long	 cpu_online_map;
 
diff -urN linux-2.4.17-pre5/arch/s390x/kernel/smp.c linux/arch/s390x/kernel/smp.c
--- linux-2.4.17-pre5/arch/s390x/kernel/smp.c	Wed Nov 21 10:31:09 2001
+++ linux/arch/s390x/kernel/smp.c	Fri Dec  7 14:53:07 2001
@@ -29,6 +29,7 @@
 #include <linux/smp_lock.h>
 
 #include <linux/delay.h>
+#include <linux/cache.h>
 
 #include <asm/sigp.h>
 #include <asm/pgalloc.h>
@@ -55,7 +56,7 @@
 int              smp_threads_ready=0;      /* Set when the idlers are all forked. */
 static atomic_t  smp_commenced = ATOMIC_INIT(0);
 
-spinlock_t       kernel_flag = SPIN_LOCK_UNLOCKED;
+spinlock_t       kernel_flag __cacheline_aligned_in_smp = SPIN_LOCK_UNLOCKED;
 
 unsigned long	 cpu_online_map;
 
diff -urN linux-2.4.17-pre5/arch/sparc/kernel/smp.c linux/arch/sparc/kernel/smp.c
--- linux-2.4.17-pre5/arch/sparc/kernel/smp.c	Tue Nov 13 09:16:05 2001
+++ linux/arch/sparc/kernel/smp.c	Fri Dec  7 14:53:07 2001
@@ -18,6 +18,7 @@
 #include <linux/mm.h>
 #include <linux/fs.h>
 #include <linux/seq_file.h>
+#include <linux/cache.h>
 
 #include <asm/ptrace.h>
 #include <asm/atomic.h>
@@ -66,7 +67,7 @@
  */
 
 /* Kernel spinlock */
-spinlock_t kernel_flag = SPIN_LOCK_UNLOCKED;
+spinlock_t kernel_flag __cacheline_aligned_in_smp = SPIN_LOCK_UNLOCKED;
 
 /* Used to make bitops atomic */
 unsigned char bitops_spinlock = 0;
diff -urN linux-2.4.17-pre5/arch/sparc64/kernel/smp.c linux/arch/sparc64/kernel/smp.c
--- linux-2.4.17-pre5/arch/sparc64/kernel/smp.c	Fri Dec  7 14:52:27 2001
+++ linux/arch/sparc64/kernel/smp.c	Fri Dec  7 14:53:07 2001
@@ -17,6 +17,7 @@
 #include <linux/spinlock.h>
 #include <linux/fs.h>
 #include <linux/seq_file.h>
+#include <linux/cache.h>
 
 #include <asm/head.h>
 #include <asm/ptrace.h>
@@ -49,7 +50,7 @@
 static int smp_activated = 0;
 
 /* Kernel spinlock */
-spinlock_t kernel_flag = SPIN_LOCK_UNLOCKED;
+spinlock_t kernel_flag __cacheline_aligned_in_smp = SPIN_LOCK_UNLOCKED;
 
 volatile int smp_processors_ready = 0;
 unsigned long cpu_present_map = 0;
diff -urN linux-2.4.17-pre5/arch/sparc64/kernel/sparc64_ksyms.c linux/arch/sparc64/kernel/sparc64_ksyms.c
--- linux-2.4.17-pre5/arch/sparc64/kernel/sparc64_ksyms.c	Fri Dec  7 14:52:27 2001
+++ linux/arch/sparc64/kernel/sparc64_ksyms.c	Fri Dec  7 14:53:07 2001
@@ -1,4 +1,4 @@
-/* $Id: sparc64_ksyms.c,v 1.118 2001/11/17 00:10:48 davem Exp $
+/* $Id: sparc64_ksyms.c,v 1.119 2001/11/30 01:04:10 davem Exp $
  * arch/sparc64/kernel/sparc64_ksyms.c: Sparc64 specific ksyms support.
  *
  * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
@@ -319,7 +319,6 @@
 EXPORT_SYMBOL(__memcpy);
 EXPORT_SYMBOL(__memset);
 EXPORT_SYMBOL(_clear_page);
-EXPORT_SYMBOL(_copy_page);
 EXPORT_SYMBOL(clear_user_page);
 EXPORT_SYMBOL(copy_user_page);
 EXPORT_SYMBOL(__bzero);
diff -urN linux-2.4.17-pre5/arch/sparc64/lib/blockops.S linux/arch/sparc64/lib/blockops.S
--- linux-2.4.17-pre5/arch/sparc64/lib/blockops.S	Fri Dec  7 14:52:27 2001
+++ linux/arch/sparc64/lib/blockops.S	Fri Dec  7 14:53:07 2001
@@ -33,64 +33,6 @@
 	.text
 
 	.align		32
-	.globl		_copy_page
-	.type		_copy_page,@function
-_copy_page: /* %o0=dest, %o1=src */
-	VISEntry
-	membar		#LoadStore | #StoreStore | #StoreLoad
-	ldda		[%o1] ASI_BLK_P, %f0
-	add		%o1, 0x40, %o1
-	ldda		[%o1] ASI_BLK_P, %f16
-	add		%o1, 0x40, %o1
-	sethi		%hi(PAGE_SIZE), %o2
-1:	TOUCH(f0, f2, f4, f6, f8, f10, f12, f14)
-	ldda		[%o1] ASI_BLK_P, %f32
-	stda		%f48, [%o0] ASI_BLK_P
-	add		%o1, 0x40, %o1
-	sub		%o2, 0x40, %o2
-	add		%o0, 0x40, %o0
-	TOUCH(f16, f18, f20, f22, f24, f26, f28, f30)
-	ldda		[%o1] ASI_BLK_P, %f0
-	stda		%f48, [%o0] ASI_BLK_P
-	add		%o1, 0x40, %o1
-	sub		%o2, 0x40, %o2
-	add		%o0, 0x40, %o0
-	TOUCH(f32, f34, f36, f38, f40, f42, f44, f46)
-	ldda		[%o1] ASI_BLK_P, %f16
-	stda		%f48, [%o0] ASI_BLK_P
-	sub		%o2, 0x40, %o2
-	add		%o1, 0x40, %o1
-	cmp		%o2, PAGE_SIZE_REM
-	bne,pt		%xcc, 1b
-	 add		%o0, 0x40, %o0
-#if (PAGE_SHIFT == 16) || (PAGE_SHIFT == 22)
-	TOUCH(f0, f2, f4, f6, f8, f10, f12, f14)
-	ldda		[%o1] ASI_BLK_P, %f32
-	stda		%f48, [%o0] ASI_BLK_P
-	add		%o1, 0x40, %o1
-	sub		%o2, 0x40, %o2
-	add		%o0, 0x40, %o0
-	TOUCH(f16, f18, f20, f22, f24, f26, f28, f30)
-	ldda		[%o1] ASI_BLK_P, %f0
-	stda		%f48, [%o0] ASI_BLK_P
-	add		%o1, 0x40, %o1
-	sub		%o2, 0x40, %o2
-	add		%o0, 0x40, %o0
-	membar		#Sync
-	stda		%f32, [%o0] ASI_BLK_P
-	add		%o0, 0x40, %o0
-	stda		%f0, [%o0] ASI_BLK_P
-#else
-	membar		#Sync
-	stda		%f0, [%o0] ASI_BLK_P
-	add		%o0, 0x40, %o0
-	stda		%f16, [%o0] ASI_BLK_P
-#endif
-	membar		#Sync
-	VISExit
-	retl
-	 nop
-
 	.globl		copy_user_page
 	.type		copy_user_page,@function
 copy_user_page: /* %o0=dest, %o1=src, %o2=vaddr */
diff -urN linux-2.4.17-pre5/drivers/atm/eni.c linux/drivers/atm/eni.c
--- linux-2.4.17-pre5/drivers/atm/eni.c	Fri Nov  9 13:41:42 2001
+++ linux/drivers/atm/eni.c	Fri Dec  7 14:53:07 2001
@@ -2310,7 +2310,7 @@
 	name:		DEV_LABEL,
 	id_table:	eni_pci_tbl,
 	probe:		eni_init_one,
-	remove:		eni_remove_one,
+	remove:		__devexit_p(eni_remove_one),
 };
 
 
diff -urN linux-2.4.17-pre5/drivers/atm/firestream.c linux/drivers/atm/firestream.c
--- linux-2.4.17-pre5/drivers/atm/firestream.c	Fri Nov  9 13:58:03 2001
+++ linux/drivers/atm/firestream.c	Fri Dec  7 14:53:07 2001
@@ -2102,7 +2102,7 @@
 	name:           "firestream",
 	id_table:       firestream_pci_tbl,
 	probe:          firestream_init_one,
-	remove:         firestream_remove_one,
+	remove:         __devexit_p(firestream_remove_one),
 };
 
 static int __init firestream_init_module (void)
diff -urN linux-2.4.17-pre5/drivers/block/cciss.c linux/drivers/block/cciss.c
--- linux-2.4.17-pre5/drivers/block/cciss.c	Fri Nov  9 14:28:46 2001
+++ linux/drivers/block/cciss.c	Fri Dec  7 14:53:07 2001
@@ -2019,7 +2019,7 @@
 static struct pci_driver cciss_pci_driver = {
 	 name:   "cciss",
 	probe:  cciss_init_one,
-	remove:  cciss_remove_one,
+	remove:  __devexit_p(cciss_remove_one),
 	id_table:  cciss_pci_device_id, /* id_table */
 };
 
diff -urN linux-2.4.17-pre5/drivers/block/paride/Config.in linux/drivers/block/paride/Config.in
--- linux-2.4.17-pre5/drivers/block/paride/Config.in	Thu Oct 25 00:07:39 2001
+++ linux/drivers/block/paride/Config.in	Fri Dec  7 14:53:07 2001
@@ -29,7 +29,7 @@
 dep_tristate '    Shuttle EPAT/EPEZ protocol' CONFIG_PARIDE_EPAT $CONFIG_PARIDE
 if [ "$CONFIG_PARIDE_EPAT" != "n" ]; then
   if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
-    bool '     Support c7/c8 chips (EXPERIMENTAL)' CONFIG_PARIDE_EPATC8 $CONFIG_PARIDE
+    bool '     Support c7/c8 chips (EXPERIMENTAL)' CONFIG_PARIDE_EPATC8
   fi
 fi
 
diff -urN linux-2.4.17-pre5/drivers/char/drm/Config.in linux/drivers/char/drm/Config.in
--- linux-2.4.17-pre5/drivers/char/drm/Config.in	Wed Aug  8 09:42:10 2001
+++ linux/drivers/char/drm/Config.in	Fri Dec  7 14:53:07 2001
@@ -13,4 +13,5 @@
     dep_tristate '  ATI Radeon' CONFIG_DRM_RADEON $CONFIG_AGP
     dep_tristate '  Intel I810' CONFIG_DRM_I810 $CONFIG_AGP
     dep_tristate '  Matrox g200/g400' CONFIG_DRM_MGA $CONFIG_AGP
+    dep_tristate '  SiS' CONFIG_DRM_SIS $CONFIG_AGP
 fi
diff -urN linux-2.4.17-pre5/drivers/char/drm/Makefile linux/drivers/char/drm/Makefile
--- linux-2.4.17-pre5/drivers/char/drm/Makefile	Thu Aug  9 14:09:38 2001
+++ linux/drivers/char/drm/Makefile	Fri Dec  7 14:53:07 2001
@@ -3,7 +3,7 @@
 # Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher.
 
 O_TARGET	:= drm.o
-list-multi	:= gamma.o tdfx.o r128.o mga.o i810.o radeon.o ffb.o
+list-multi	:= gamma.o tdfx.o r128.o mga.o i810.o radeon.o ffb.o sis.o
 
 gamma-objs  := gamma_drv.o gamma_dma.o
 tdfx-objs   := tdfx_drv.o
@@ -12,6 +12,7 @@
 i810-objs   := i810_drv.o i810_dma.o
 radeon-objs := radeon_drv.o radeon_cp.o radeon_state.o
 ffb-objs    := ffb_drv.o ffb_context.o
+sis-objs    := sis_drv.o sis_ds.o sis_mm.o
 
 obj-$(CONFIG_DRM_GAMMA) += gamma.o
 obj-$(CONFIG_DRM_TDFX)	+= tdfx.o
@@ -20,6 +21,7 @@
 obj-$(CONFIG_DRM_MGA)	+= mga.o
 obj-$(CONFIG_DRM_I810)	+= i810.o
 obj-$(CONFIG_DRM_FFB)   += ffb.o
+obj-$(CONFIG_DRM_SIS)   += sis.o
 
 include $(TOPDIR)/Rules.make
 
@@ -43,3 +45,6 @@
 
 ffb.o: $(ffb-objs) $(lib)
 	$(LD) -r -o $@ $(ffb-objs) $(lib)
+
+sis.o: $(sis-objs) $(lib)
+	$(LD) -r -o $@ $(sis-objs) $(lib)
diff -urN linux-2.4.17-pre5/drivers/char/drm/drm.h linux/drivers/char/drm/drm.h
--- linux-2.4.17-pre5/drivers/char/drm/drm.h	Wed Aug  8 09:52:17 2001
+++ linux/drivers/char/drm/drm.h	Fri Dec  7 14:53:07 2001
@@ -104,7 +104,7 @@
 #include "i810_drm.h"
 #include "r128_drm.h"
 #include "radeon_drm.h"
-#ifdef CONFIG_DRM_SIS
+#if defined(CONFIG_DRM_SIS) || defined(CONFIG_DRM_SIS_MODULE)
 #include "sis_drm.h"
 #endif
 
@@ -483,7 +483,7 @@
 #define DRM_IOCTL_RADEON_INDIRECT	DRM_IOWR(0x4d, drm_radeon_indirect_t)
 #define DRM_IOCTL_RADEON_TEXTURE	DRM_IOWR(0x4e, drm_radeon_texture_t)
 
-#ifdef CONFIG_DRM_SIS
+#if defined(CONFIG_DRM_SIS) || defined(CONFIG_DRM_SIS_MODULE)
 /* SiS specific ioctls */
 #define SIS_IOCTL_FB_ALLOC		DRM_IOWR(0x44, drm_sis_mem_t)
 #define SIS_IOCTL_FB_FREE		DRM_IOW( 0x45, drm_sis_mem_t)
diff -urN linux-2.4.17-pre5/drivers/char/drm/drm_context.h linux/drivers/char/drm/drm_context.h
--- linux-2.4.17-pre5/drivers/char/drm/drm_context.h	Thu Nov 22 11:46:37 2001
+++ linux/drivers/char/drm/drm_context.h	Fri Dec  7 14:53:07 2001
@@ -27,6 +27,10 @@
  * Authors:
  *    Rickard E. (Rik) Faith <faith@valinux.com>
  *    Gareth Hughes <gareth@valinux.com>
+ * ChangeLog:
+ *  2001-11-16	Torsten Duwe <duwe@caldera.de>
+ *		added context constructor/destructor hooks,
+ *		needed by SiS driver's memory management.
  */
 
 #define __NO_VERSION__
@@ -316,6 +320,10 @@
 				/* Should this return -EBUSY instead? */
 		return -ENOMEM;
 	}
+#ifdef DRIVER_CTX_CTOR
+	if ( ctx.handle != DRM_KERNEL_CONTEXT )
+		DRIVER_CTX_CTOR(ctx.handle); /* XXX: also pass dev ? */
+#endif
 
 	if ( copy_to_user( (drm_ctx_t *)arg, &ctx, sizeof(ctx) ) )
 		return -EFAULT;
@@ -390,6 +398,9 @@
 		priv->remove_auth_on_close = 1;
 	}
 	if ( ctx.handle != DRM_KERNEL_CONTEXT ) {
+#ifdef DRIVER_CTX_DTOR
+		DRIVER_CTX_DTOR(ctx.handle); /* XXX: also pass dev ? */
+#endif
 		DRM(ctxbitmap_free)( dev, ctx.handle );
 	}
 
diff -urN linux-2.4.17-pre5/drivers/char/drm/sis.h linux/drivers/char/drm/sis.h
--- linux-2.4.17-pre5/drivers/char/drm/sis.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/char/drm/sis.h	Fri Dec  7 14:53:07 2001
@@ -0,0 +1,56 @@
+/* sis_drv.h -- Private header for sis driver -*- linux-c -*-
+ *
+ * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
+ * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
+ * All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ * 
+ */
+/* $XFree86: xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/sis.h,v 1.1 2001/05/19 18:29:22 dawes Exp $ */
+
+#ifndef __SIS_H__
+#define __SIS_H__
+
+/* This remains constant for all DRM template files.
+ * Name it sisdrv_##x as there's a conflict with sis_free/malloc in the kernel
+ * that's used for fb devices 
+ */
+#define DRM(x) sisdrv_##x
+
+/* General customization:
+ */
+#define __HAVE_AGP		1
+#define __MUST_HAVE_AGP		0
+#define __HAVE_MTRR		1
+#define __HAVE_CTX_BITMAP	1
+
+/* Buffer customization:
+ */
+#define DRIVER_AGP_BUFFERS_MAP( dev )					\
+	((drm_sis_private_t *)((dev)->dev_private))->buffers
+
+extern int sis_init_context(int context);
+extern int sis_final_context(int context);
+
+#define DRIVER_CTX_CTOR sis_init_context
+#define DRIVER_CTX_DTOR sis_final_context
+
+#endif
diff -urN linux-2.4.17-pre5/drivers/char/drm/sis_drm.h linux/drivers/char/drm/sis_drm.h
--- linux-2.4.17-pre5/drivers/char/drm/sis_drm.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/char/drm/sis_drm.h	Fri Dec  7 14:53:07 2001
@@ -0,0 +1,36 @@
+
+#ifndef _sis_drm_public_h_
+#define _sis_drm_public_h_
+
+typedef struct {
+  int context;
+  unsigned int offset;
+  unsigned int size;
+  unsigned int free;
+} drm_sis_mem_t;
+
+typedef struct {
+  unsigned int offset, size;
+} drm_sis_agp_t;
+
+typedef struct {
+  unsigned int left, right;
+} drm_sis_flip_t;
+
+#ifdef __KERNEL__
+
+int sis_fb_alloc(struct inode *inode, struct file *filp, unsigned int cmd,
+		  unsigned long arg);
+int sis_fb_free(struct inode *inode, struct file *filp, unsigned int cmd,
+		  unsigned long arg);
+
+int sisp_agp_init(struct inode *inode, struct file *filp, unsigned int cmd,
+		  unsigned long arg);
+int sisp_agp_alloc(struct inode *inode, struct file *filp, unsigned int cmd,
+		  unsigned long arg);
+int sisp_agp_free(struct inode *inode, struct file *filp, unsigned int cmd,
+		  unsigned long arg);
+
+#endif
+
+#endif
diff -urN linux-2.4.17-pre5/drivers/char/drm/sis_drv.c linux/drivers/char/drm/sis_drv.c
--- linux-2.4.17-pre5/drivers/char/drm/sis_drv.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/char/drm/sis_drv.c	Fri Dec  7 14:53:07 2001
@@ -0,0 +1,74 @@
+/* sis.c -- sis driver -*- linux-c -*-
+ *
+ * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
+ * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#include <linux/config.h>
+#include "sis.h"
+#include "drmP.h"
+#include "sis_drm.h"
+#include "sis_drv.h"
+
+#define DRIVER_AUTHOR	 "SIS"
+#define DRIVER_NAME	 "sis"
+#define DRIVER_DESC	 "SIS 300/630/540"
+#define DRIVER_DATE	 "20010503"
+#define DRIVER_MAJOR	 1
+#define DRIVER_MINOR	 0
+#define DRIVER_PATCHLEVEL  0
+
+#define DRIVER_IOCTLS \
+        [DRM_IOCTL_NR(SIS_IOCTL_FB_ALLOC)]   = { sis_fb_alloc,	  1, 1 }, \
+        [DRM_IOCTL_NR(SIS_IOCTL_FB_FREE)]    = { sis_fb_free,	  1, 1 }, \
+        /* AGP Memory Management */					  \
+        [DRM_IOCTL_NR(SIS_IOCTL_AGP_INIT)]   = { sisp_agp_init,	  1, 1 }, \
+        [DRM_IOCTL_NR(SIS_IOCTL_AGP_ALLOC)]  = { sisp_agp_alloc,  1, 1 }, \
+        [DRM_IOCTL_NR(SIS_IOCTL_AGP_FREE)]   = { sisp_agp_free,	  1, 1 }
+#if 0 /* these don't appear to be defined */
+	/* SIS Stereo */						 
+	[DRM_IOCTL_NR(DRM_IOCTL_CONTROL)]    = { sis_control,	  1, 1 }, 
+        [DRM_IOCTL_NR(SIS_IOCTL_FLIP)]       = { sis_flip,	  1, 1 }, 
+        [DRM_IOCTL_NR(SIS_IOCTL_FLIP_INIT)]  = { sis_flip_init,	  1, 1 }, 
+        [DRM_IOCTL_NR(SIS_IOCTL_FLIP_FINAL)] = { sis_flip_final,  1, 1 }
+#endif
+
+#define __HAVE_COUNTERS		5
+
+#include "drm_auth.h"
+#include "drm_agpsupport.h"
+#include "drm_bufs.h"
+#include "drm_context.h"
+#include "drm_dma.h"
+#include "drm_drawable.h"
+#include "drm_drv.h"
+#include "drm_fops.h"
+#include "drm_init.h"
+#include "drm_ioctl.h"
+#include "drm_lists.h"
+#include "drm_lock.h"
+#include "drm_memory.h"
+#include "drm_proc.h"
+#include "drm_vm.h"
+#include "drm_stub.h"
diff -urN linux-2.4.17-pre5/drivers/char/drm/sis_drv.h linux/drivers/char/drm/sis_drv.h
--- linux-2.4.17-pre5/drivers/char/drm/sis_drv.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/char/drm/sis_drv.h	Fri Dec  7 14:53:07 2001
@@ -0,0 +1,45 @@
+/* sis_drv.h -- Private header for sis driver -*- linux-c -*-
+ *
+ * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
+ * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
+ * All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ * 
+ */
+
+#ifndef _SIS_DRV_H_
+#define _SIS_DRV_H_
+
+typedef struct drm_sis_private {
+	drm_map_t *buffers;
+} drm_sis_private_t;
+
+/* Stereo ? - this was never committed */
+
+int sis_flip(struct inode *inode, struct file *filp, unsigned int cmd,
+		  unsigned long arg);
+int sis_flip_init(struct inode *inode, struct file *filp, unsigned int cmd,
+		  unsigned long arg);
+int sis_flip_final(struct inode *inode, struct file *filp, unsigned int cmd,
+		  unsigned long arg);
+void flip_final(void);
+
+#endif
diff -urN linux-2.4.17-pre5/drivers/char/drm/sis_ds.c linux/drivers/char/drm/sis_ds.c
--- linux-2.4.17-pre5/drivers/char/drm/sis_ds.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/char/drm/sis_ds.c	Fri Dec  7 14:53:07 2001
@@ -0,0 +1,406 @@
+/* sis_ds.c -- Private header for Direct Rendering Manager -*- linux-c -*-
+ * Created: Mon Jan  4 10:05:05 1999 by sclin@sis.com.tw
+ *
+ * Copyright 2000 Silicon Integrated Systems Corp, Inc., HsinChu, Taiwan.
+ * All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ * 
+ * Authors:
+ *    Sung-Ching Lin <sclin@sis.com.tw>
+ * 
+ */
+
+#define __NO_VERSION__
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/malloc.h>
+#include <linux/poll.h>
+#include <asm/io.h>
+#include <linux/pci.h>
+
+#include "sis_ds.h"
+
+/* Set Data Structure, not check repeated value
+ * temporarily used
+ */
+
+set_t *setInit(void)
+{
+  int i;
+  set_t *set;
+
+  set = (set_t *)MALLOC(sizeof(set_t));
+  for(i = 0; i < SET_SIZE; i++){
+    set->list[i].free_next = i+1;    
+    set->list[i].alloc_next = -1;
+  }    
+  set->list[SET_SIZE-1].free_next = -1;
+  set->free = 0;
+  set->alloc = -1;
+  set->trace = -1;
+  
+  return set;
+}
+
+int setAdd(set_t *set, ITEM_TYPE item)
+{
+  int free = set->free;
+  
+  if(free != -1){
+    set->list[free].val = item;
+    set->free = set->list[free].free_next;
+  }
+  else{
+    return 0;
+  }
+
+  set->list[free].alloc_next = set->alloc;
+  set->alloc = free;  
+  set->list[free].free_next = -1;    
+
+  return 1;
+}
+
+int setDel(set_t *set, ITEM_TYPE item)
+{
+  int alloc = set->alloc;
+  int prev = -1;  
+  
+  while(alloc != -1){
+    if(set->list[alloc].val == item){
+      if(prev != -1)      
+        set->list[prev].alloc_next = set->list[alloc].alloc_next; 
+      else
+        set->alloc = set->list[alloc].alloc_next;
+      break;
+    }
+    prev = alloc;
+    alloc = set->list[alloc].alloc_next;      
+  }
+
+  if(alloc == -1)
+    return 0;
+  
+  set->list[alloc].free_next = set->free;
+  set->free = alloc;
+  set->list[alloc].alloc_next = -1;   
+
+  return 1;
+}
+
+/* setFirst -> setAdd -> setNext is wrong */
+
+int setFirst(set_t *set, ITEM_TYPE *item)
+{
+  if(set->alloc == -1)
+    return 0;
+
+  *item = set->list[set->alloc].val;
+  set->trace = set->list[set->alloc].alloc_next; 
+
+  return 1;
+}
+
+int setNext(set_t *set, ITEM_TYPE *item)
+{
+  if(set->trace == -1)
+    return 0;
+  
+  *item = set->list[set->trace].val;
+  set->trace = set->list[set->trace].alloc_next;      
+
+  return 1;
+}
+
+int setDestroy(set_t *set)
+{
+  FREE(set);
+
+  return 1;
+}
+
+/*
+ * GLX Hardware Device Driver common code
+ * Copyright (C) 1999 Keith Whitwell
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * KEITH WHITWELL, OR ANY OTHER CONTRIBUTORS BE LIABLE FOR ANY CLAIM, 
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE 
+ * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#define ISFREE(bptr) ((bptr)->free)
+
+#define PRINTF(fmt, arg...) do{}while(0)
+#define fprintf(fmt, arg...) do{}while(0)
+
+static void *calloc(size_t nmemb, size_t size)
+{
+  void *addr;
+  addr = kmalloc(nmemb*size, GFP_KERNEL);
+  memset(addr, 0, nmemb*size);
+  return addr;
+}
+#define free(n) kfree(n)
+           
+void mmDumpMemInfo( memHeap_t *heap )
+{
+  TMemBlock *p;
+
+  PRINTF ("Memory heap %p:\n", heap);
+  if (heap == 0) {
+    PRINTF ("  heap == 0\n");
+  } else {
+    p = (TMemBlock *)heap;
+    while (p) {
+      PRINTF ("  Offset:%08x, Size:%08x, %c%c\n",p->ofs,p->size,
+	     p->free ? '.':'U',
+	     p->reserved ? 'R':'.');
+      p = p->next;
+    }
+  }
+  PRINTF ("End of memory blocks\n");
+}
+
+memHeap_t *mmInit(int ofs,
+		  int size)
+{
+   PMemBlock blocks;
+  
+   if (size <= 0) {
+      return 0;
+   }
+   blocks = (TMemBlock *) calloc(1,sizeof(TMemBlock));
+   if (blocks) {
+      blocks->ofs = ofs;
+      blocks->size = size;
+      blocks->free = 1;
+      return (memHeap_t *)blocks;
+   } else
+      return 0;
+}
+
+/* Kludgey workaround for existing i810 server.  Remove soon.
+ */
+memHeap_t *mmAddRange( memHeap_t *heap,
+		       int ofs,
+		       int size )
+{
+   PMemBlock blocks;
+   blocks = (TMemBlock *) calloc(2,sizeof(TMemBlock));
+   if (blocks) {
+      blocks[0].size = size;
+      blocks[0].free = 1;
+      blocks[0].ofs = ofs;
+      blocks[0].next = &blocks[1];
+
+      /* Discontinuity - stops JoinBlock from trying to join non-adjacent
+       * ranges.
+       */
+      blocks[1].size = 0;
+      blocks[1].free = 0;
+      blocks[1].ofs = ofs+size;
+      blocks[1].next = (PMemBlock) heap;      
+      return (memHeap_t *)blocks;
+   } 
+   else
+      return heap;
+}
+
+static TMemBlock* SliceBlock(TMemBlock *p, 
+			     int startofs, int size, 
+			     int reserved, int alignment)
+{
+  TMemBlock *newblock;
+
+  /* break left */
+  if (startofs > p->ofs) {
+    newblock = (TMemBlock*) calloc(1,sizeof(TMemBlock));
+    newblock->ofs = startofs;
+    newblock->size = p->size - (startofs - p->ofs);
+    newblock->free = 1;
+    newblock->next = p->next;
+    p->size -= newblock->size;
+    p->next = newblock;
+    p = newblock;
+  }
+
+  /* break right */
+  if (size < p->size) {
+    newblock = (TMemBlock*) calloc(1,sizeof(TMemBlock));
+    newblock->ofs = startofs + size;
+    newblock->size = p->size - size;
+    newblock->free = 1;
+    newblock->next = p->next;
+    p->size = size;
+    p->next = newblock;
+  }
+
+  /* p = middle block */
+  p->align = alignment;
+  p->free = 0;
+  p->reserved = reserved;
+  return p;
+}
+
+PMemBlock mmAllocMem( memHeap_t *heap, int size, int align2, int startSearch)
+{
+  int mask,startofs,endofs;
+  TMemBlock *p;
+
+  if (!heap || align2 < 0 || size <= 0)
+    return NULL;
+  mask = (1 << align2)-1;
+  startofs = 0;
+  p = (TMemBlock *)heap;
+  while (p) {
+    if (ISFREE(p)) {
+      startofs = (p->ofs + mask) & ~mask;
+      if ( startofs < startSearch ) {
+      	startofs = startSearch;
+      }
+      endofs = startofs+size;
+      if (endofs <= (p->ofs+p->size))
+	break;
+    }
+    p = p->next;
+  }
+  if (!p)
+    return NULL;
+  p = SliceBlock(p,startofs,size,0,mask+1);
+  p->heap = heap;
+  return p;
+}
+
+static __inline__ int Join2Blocks(TMemBlock *p)
+{
+  if (p->free && p->next && p->next->free) {
+    TMemBlock *q = p->next;
+    p->size += q->size;
+    p->next = q->next;
+    free(q);
+    return 1;
+  }
+  return 0;
+}
+
+int mmFreeMem(PMemBlock b)
+{
+  TMemBlock *p,*prev;
+
+  if (!b)
+    return 0;
+  if (!b->heap) {
+     fprintf(stderr, "no heap\n");
+     return -1;
+  }
+  p = b->heap;
+  prev = NULL;
+  while (p && p != b) {
+    prev = p;
+    p = p->next;
+  }
+  if (!p || p->free || p->reserved) {
+     if (!p)
+	fprintf(stderr, "block not found in heap\n");
+     else if (p->free)
+	fprintf(stderr, "block already free\n");
+     else
+	fprintf(stderr, "block is reserved\n");
+    return -1;
+  }
+  p->free = 1;
+  Join2Blocks(p);
+  if (prev)
+    Join2Blocks(prev);
+  return 0;
+}
+
+int mmReserveMem(memHeap_t *heap, int offset,int size)
+{
+  int endofs;
+  TMemBlock *p;
+
+  if (!heap || size <= 0)
+    return -1;
+  endofs = offset+size;
+  p = (TMemBlock *)heap;
+  while (p && p->ofs <= offset) {
+    if (ISFREE(p) && endofs <= (p->ofs+p->size)) {
+      SliceBlock(p,offset,size,1,1);
+      return 0;
+    }
+    p = p->next;
+  }
+  return -1;
+}
+
+int mmFreeReserved(memHeap_t *heap, int offset)
+{
+  TMemBlock *p,*prev;
+
+  if (!heap)
+    return -1;
+  p = (TMemBlock *)heap;
+  prev = NULL;
+  while (p && p->ofs != offset) {
+    prev = p;
+    p = p->next;
+  }
+  if (!p || !p->reserved)
+    return -1;
+  p->free = 1;
+  p->reserved = 0;
+  Join2Blocks(p);
+  if (prev)
+    Join2Blocks(prev);
+  return 0;
+}
+
+void mmDestroy(memHeap_t *heap)
+{
+  TMemBlock *p,*q;
+
+  if (!heap)
+    return;
+  p = (TMemBlock *)heap;
+  while (p) {
+    q = p->next;
+    free(p);
+    p = q;
+  }
+}
diff -urN linux-2.4.17-pre5/drivers/char/drm/sis_ds.h linux/drivers/char/drm/sis_ds.h
--- linux-2.4.17-pre5/drivers/char/drm/sis_ds.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/char/drm/sis_ds.h	Fri Dec  7 14:53:07 2001
@@ -0,0 +1,163 @@
+/* sis_ds.h -- Private header for Direct Rendering Manager -*- linux-c -*-
+ * Created: Mon Jan  4 10:05:05 1999 by sclin@sis.com.tw
+ *
+ * Copyright 2000 Silicon Integrated Systems Corp, Inc., HsinChu, Taiwan.
+ * All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ * 
+ * Authors:
+ *    Sung-Ching Lin <sclin@sis.com.tw>
+ * 
+ */
+
+#ifndef _sis_ds_h_
+#define _sis_ds_h_
+
+/* Set Data Structure */
+
+#define SET_SIZE 5000
+#define MALLOC(s) kmalloc(s, GFP_KERNEL)
+#define FREE(s) kfree(s)
+
+typedef unsigned int ITEM_TYPE;
+
+typedef struct {
+  ITEM_TYPE val;
+  int alloc_next, free_next;
+} list_item_t;
+
+typedef struct {
+  int alloc;
+  int free;
+  int trace;
+  list_item_t list[SET_SIZE];
+} set_t;
+
+set_t *setInit(void);
+int setAdd(set_t *set, ITEM_TYPE item);
+int setDel(set_t *set, ITEM_TYPE item);
+int setFirst(set_t *set, ITEM_TYPE *item);
+int setNext(set_t *set, ITEM_TYPE *item);
+int setDestroy(set_t *set);
+
+#endif
+
+/*
+ * GLX Hardware Device Driver common code
+ * Copyright (C) 1999 Keith Whitwell
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * KEITH WHITWELL, OR ANY OTHER CONTRIBUTORS BE LIABLE FOR ANY CLAIM, 
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE 
+ * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#ifndef MM_INC
+#define MM_INC
+
+struct mem_block_t {
+  struct mem_block_t *next;
+  struct mem_block_t *heap;
+  int ofs,size;
+  int align;
+  int free:1;
+  int reserved:1;
+};
+typedef struct mem_block_t TMemBlock;
+typedef struct mem_block_t *PMemBlock;
+
+/* a heap is just the first block in a chain */
+typedef struct mem_block_t memHeap_t;
+
+static __inline__ int mmBlockSize(PMemBlock b)
+{ return b->size; }
+
+static __inline__ int mmOffset(PMemBlock b)
+{ return b->ofs; }
+
+static __inline__ void mmMarkReserved(PMemBlock b)
+{ b->reserved = 1; }
+
+/* 
+ * input: total size in bytes
+ * return: a heap pointer if OK, NULL if error
+ */
+memHeap_t *mmInit( int ofs, int size );
+
+
+
+memHeap_t *mmAddRange( memHeap_t *heap,
+		       int ofs,
+		       int size );
+
+
+/*
+ * Allocate 'size' bytes with 2^align2 bytes alignment,
+ * restrict the search to free memory after 'startSearch'
+ * depth and back buffers should be in different 4mb banks
+ * to get better page hits if possible
+ * input:	size = size of block
+ *       	align2 = 2^align2 bytes alignment
+ *		startSearch = linear offset from start of heap to begin search
+ * return: pointer to the allocated block, 0 if error
+ */
+PMemBlock  mmAllocMem( memHeap_t *heap, int size, int align2, int startSearch );
+
+/*
+ * Free block starts at offset
+ * input: pointer to a block
+ * return: 0 if OK, -1 if error
+ */
+int  mmFreeMem( PMemBlock b );
+
+/*
+ * Reserve 'size' bytes block start at offset
+ * This is used to prevent allocation of memory already used
+ * by the X server for the front buffer, pixmaps, and cursor
+ * input: size, offset
+ * output: 0 if OK, -1 if error
+ */
+int mmReserveMem( memHeap_t *heap, int offset,int size );
+int mmFreeReserved( memHeap_t *heap, int offset );
+
+/*
+ * destroy MM
+ */
+void mmDestroy( memHeap_t *mmInit );
+
+/* For debuging purpose. */
+void mmDumpMemInfo( memHeap_t *mmInit );
+
+#endif
diff -urN linux-2.4.17-pre5/drivers/char/drm/sis_mm.c linux/drivers/char/drm/sis_mm.c
--- linux-2.4.17-pre5/drivers/char/drm/sis_mm.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/char/drm/sis_mm.c	Fri Dec  7 14:53:07 2001
@@ -0,0 +1,307 @@
+/* sis_mm.c -- Private header for Direct Rendering Manager -*- linux-c -*-
+ * Created: Mon Jan  4 10:05:05 1999 by sclin@sis.com.tw
+ *
+ * Copyright 2000 Silicon Integrated Systems Corp, Inc., HsinChu, Taiwan.
+ * All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ * 
+ * Authors:
+ *    Sung-Ching Lin <sclin@sis.com.tw>
+ * 
+ */
+
+#define __NO_VERSION__
+#include "sis.h"
+#include <linux/sisfb.h>
+#include "drmP.h"
+#include "sis_drm.h"
+#include "sis_drv.h"
+#include "sis_ds.h"
+
+#define MAX_CONTEXT 100
+#define VIDEO_TYPE 0 
+#define AGP_TYPE 1
+
+typedef struct {
+  int used;
+  int context;
+  set_t *sets[2]; /* 0 for video, 1 for AGP */
+} sis_context_t;
+
+static sis_context_t global_ppriv[MAX_CONTEXT];
+
+static int add_alloc_set(int context, int type, unsigned int val)
+{
+  int i, retval = 0;
+  
+  for(i = 0; i < MAX_CONTEXT; i++)
+    if(global_ppriv[i].used && global_ppriv[i].context == context){
+      retval = setAdd(global_ppriv[i].sets[type], val);
+      break;
+    }
+  return retval;
+}
+
+static int del_alloc_set(int context, int type, unsigned int val)
+{  
+  int i, retval = 0;
+  for(i = 0; i < MAX_CONTEXT; i++)
+    if(global_ppriv[i].used && global_ppriv[i].context == context){
+      retval = setDel(global_ppriv[i].sets[type], val);
+      break;
+    }
+  return retval;
+}
+
+/* fb management via fb device */ 
+#if 1
+int sis_fb_alloc(struct inode *inode, struct file *filp, unsigned int cmd,
+		  unsigned long arg)
+{
+  drm_sis_mem_t fb;
+  struct sis_memreq req;
+  int retval = 0;
+   
+  if (copy_from_user(&fb, (drm_sis_mem_t *)arg, sizeof(fb)))
+	  return -EFAULT;
+  
+  req.size = fb.size;
+  sis_malloc(&req);
+  if(req.offset){
+    /* TODO */
+    fb.offset = req.offset;
+    fb.free = req.offset;
+    if(!add_alloc_set(fb.context, VIDEO_TYPE, fb.free)){
+      DRM_DEBUG("adding to allocation set fails\n");
+      sis_free(req.offset);
+      retval = -1;
+    }
+  }
+  else{  
+    fb.offset = 0;
+    fb.size = 0;
+    fb.free = 0;
+  }
+   
+  if (copy_to_user((drm_sis_mem_t *)arg, &fb, sizeof(fb))) return -EFAULT;
+
+  DRM_DEBUG("alloc fb, size = %d, offset = %ld\n", fb.size, req.offset);
+
+  return retval;
+}
+
+int sis_fb_free(struct inode *inode, struct file *filp, unsigned int cmd,
+		  unsigned long arg)
+{
+  drm_sis_mem_t fb;
+  int retval = 0;
+    
+  if (copy_from_user(&fb, (drm_sis_mem_t *)arg, sizeof(fb)))
+	  return -EFAULT;
+  
+  if(!fb.free){
+    return -1;
+  }
+
+  sis_free(fb.free);
+  if(!del_alloc_set(fb.context, VIDEO_TYPE, fb.free))
+    retval = -1;
+
+  DRM_DEBUG("free fb, offset = %d\n", fb.free);
+  
+  return retval;
+}
+
+#else
+
+int sis_fb_alloc(struct inode *inode, struct file *filp, unsigned int cmd,
+		  unsigned long arg)
+{
+  return -1;
+}
+
+int sis_fb_free(struct inode *inode, struct file *filp, unsigned int cmd,
+		  unsigned long arg)
+{
+  return 0;
+}
+
+#endif
+
+/* agp memory management */ 
+#if 1
+
+static memHeap_t *AgpHeap = NULL;
+
+int sisp_agp_init(struct inode *inode, struct file *filp, unsigned int cmd,
+		  unsigned long arg)
+{
+  drm_sis_agp_t agp;
+   
+  if (copy_from_user(&agp, (drm_sis_agp_t *)arg, sizeof(agp)))
+	  return -EFAULT;
+
+  AgpHeap = mmInit(agp.offset, agp.size);
+
+  DRM_DEBUG("offset = %u, size = %u", agp.offset, agp.size);
+  
+  return 0;
+}
+
+int sisp_agp_alloc(struct inode *inode, struct file *filp, unsigned int cmd,
+		  unsigned long arg)
+{
+  drm_sis_mem_t agp;
+  PMemBlock block;
+  int retval = 0;
+   
+  if(!AgpHeap)
+    return -1;
+  
+  if (copy_from_user(&agp, (drm_sis_mem_t *)arg, sizeof(agp)))
+	  return -EFAULT;
+  
+  block = mmAllocMem(AgpHeap, agp.size, 0, 0);
+  if(block){
+    /* TODO */
+    agp.offset = block->ofs;
+    agp.free = (unsigned int)block;
+    if(!add_alloc_set(agp.context, AGP_TYPE, agp.free)){
+      DRM_DEBUG("adding to allocation set fails\n");
+      mmFreeMem((PMemBlock)agp.free);
+      retval = -1;
+    }
+  }
+  else{  
+    agp.offset = 0;
+    agp.size = 0;
+    agp.free = 0;
+  }
+   
+  if (copy_to_user((drm_sis_mem_t *)arg, &agp, sizeof(agp))) return -EFAULT;
+
+  DRM_DEBUG("alloc agp, size = %d, offset = %d\n", agp.size, agp.offset);
+
+  return retval;
+}
+
+int sisp_agp_free(struct inode *inode, struct file *filp, unsigned int cmd,
+		  unsigned long arg)
+{
+  drm_sis_mem_t agp;
+  int retval = 0;
+
+  if(!AgpHeap)
+    return -1;
+    
+  if (copy_from_user(&agp, (drm_sis_mem_t *)arg, sizeof(agp)))
+	  return -EFAULT;
+  
+  if(!agp.free){
+    return -1;
+  }
+
+  mmFreeMem((PMemBlock)agp.free);
+  if(!del_alloc_set(agp.context, AGP_TYPE, agp.free))
+    retval = -1;
+
+  DRM_DEBUG("free agp, free = %d\n", agp.free);
+  
+  return retval;
+}
+
+#endif
+
+int sis_init_context(int context)
+{
+	int i;
+	
+	for(i = 0; i < MAX_CONTEXT ; i++)
+	  if(global_ppriv[i].used && (global_ppriv[i].context == context))
+	    break;
+
+	if(i >= MAX_CONTEXT){
+	  for(i = 0; i < MAX_CONTEXT ; i++){
+	    if(!global_ppriv[i].used){
+	      global_ppriv[i].context = context;
+	      global_ppriv[i].used = 1;
+	      global_ppriv[i].sets[0] = setInit();
+	      global_ppriv[i].sets[1] = setInit();
+	      DRM_DEBUG("init allocation set, socket=%d, context = %d\n", 
+	                 i, context);
+	      break;
+	    }	
+	  }
+	  if((i >= MAX_CONTEXT) || (global_ppriv[i].sets[0] == NULL) ||
+	     (global_ppriv[i].sets[1] == NULL)){
+	    return 0;
+	  }
+	}
+	
+	return 1;
+}
+
+int sis_final_context(int context)
+{
+	int i;
+
+	for(i=0; i<MAX_CONTEXT; i++)
+	  if(global_ppriv[i].used && (global_ppriv[i].context == context))
+	    break;
+          
+	if(i < MAX_CONTEXT){
+	  set_t *set;
+	  unsigned int item;
+	  int retval;
+	  
+  	  DRM_DEBUG("find socket %d, context = %d\n", i, context);
+
+	  /* Video Memory */
+	  set = global_ppriv[i].sets[0];
+	  retval = setFirst(set, &item);
+	  while(retval){
+   	    DRM_DEBUG("free video memory 0x%x\n", item);
+            sis_free(item);
+	    retval = setNext(set, &item);
+	  }
+	  setDestroy(set);
+
+	  /* AGP Memory */
+	  set = global_ppriv[i].sets[1];
+	  retval = setFirst(set, &item);
+	  while(retval){
+   	    DRM_DEBUG("free agp memory 0x%x\n", item);
+	    mmFreeMem((PMemBlock)item);
+	    retval = setNext(set, &item);
+	  }
+	  setDestroy(set);
+	  
+	  global_ppriv[i].used = 0;	  
+        }
+
+	/* turn-off auto-flip */
+	/* TODO */
+#if defined(SIS_STEREO)
+	flip_final();
+#endif
+	
+	return 1;
+}
diff -urN linux-2.4.17-pre5/drivers/char/joystick/cs461x.c linux/drivers/char/joystick/cs461x.c
--- linux-2.4.17-pre5/drivers/char/joystick/cs461x.c	Fri Nov  9 13:41:42 2001
+++ linux/drivers/char/joystick/cs461x.c	Fri Dec  7 14:53:07 2001
@@ -313,7 +313,7 @@
         name:           "PCI Gameport",
         id_table:       cs461x_pci_tbl,
         probe:          cs461x_pci_probe,
-        remove:         cs461x_pci_remove,
+        remove:         __devexit_p(cs461x_pci_remove),
 };
 
 int __init js_cs461x_init(void)
diff -urN linux-2.4.17-pre5/drivers/char/joystick/emu10k1-gp.c linux/drivers/char/joystick/emu10k1-gp.c
--- linux-2.4.17-pre5/drivers/char/joystick/emu10k1-gp.c	Fri Nov  9 13:41:42 2001
+++ linux/drivers/char/joystick/emu10k1-gp.c	Fri Dec  7 14:53:07 2001
@@ -108,7 +108,7 @@
         name:           "Emu10k1 Gameport",
         id_table:       emu_tbl,
         probe:          emu_probe,
-        remove:         emu_remove,
+        remove:         __devexit_p(emu_remove),
 };
 
 int __init emu_init(void)
diff -urN linux-2.4.17-pre5/drivers/char/joystick/pcigame.c linux/drivers/char/joystick/pcigame.c
--- linux-2.4.17-pre5/drivers/char/joystick/pcigame.c	Fri Nov  9 13:41:42 2001
+++ linux/drivers/char/joystick/pcigame.c	Fri Dec  7 14:53:07 2001
@@ -180,7 +180,7 @@
 	name:		"pcigame",
 	id_table:	pcigame_id_table,
 	probe:		pcigame_probe,
-	remove:		pcigame_remove,
+	remove:		__devexit_p(pcigame_remove),
 };
 
 int __init pcigame_init(void)
diff -urN linux-2.4.17-pre5/drivers/char/mem.c linux/drivers/char/mem.c
--- linux-2.4.17-pre5/drivers/char/mem.c	Fri Sep 14 14:04:07 2001
+++ linux/drivers/char/mem.c	Fri Dec  7 14:53:07 2001
@@ -272,6 +272,8 @@
  	return virtr + read;
 }
 
+extern long vwrite(char *buf, char *addr, unsigned long count);
+
 /*
  * This function writes to the *virtual* memory as seen by the kernel.
  */
@@ -279,12 +281,46 @@
 			  size_t count, loff_t *ppos)
 {
 	unsigned long p = *ppos;
+	ssize_t wrote = 0;
+	ssize_t virtr = 0;
+	char * kbuf; /* k-addr because vwrite() takes vmlist_lock rwlock */
+
+	if (p < (unsigned long) high_memory) {
+		wrote = count;
+		if (count > (unsigned long) high_memory - p)
+			wrote = (unsigned long) high_memory - p;
+
+		wrote = do_write_mem(file, (void*)p, p, buf, wrote, ppos);
+
+		p += wrote;
+		buf += wrote;
+		count -= wrote;
+	}
+
+	if (count > 0) {
+		kbuf = (char *)__get_free_page(GFP_KERNEL);
+		if (!kbuf)
+			return -ENOMEM;
+		while (count > 0) {
+			int len = count;
+
+			if (len > PAGE_SIZE)
+				len = PAGE_SIZE;
+			if (len && copy_from_user(kbuf, buf, len)) {
+				free_page((unsigned long)kbuf);
+				return -EFAULT;
+			}
+			len = vwrite(kbuf, (char *)p, len);
+			count -= len;
+			buf += len;
+			virtr += len;
+			p += len;
+		}
+		free_page((unsigned long)kbuf);
+	}
 
-	if (p >= (unsigned long) high_memory)
-		return 0;
-	if (count > (unsigned long) high_memory - p)
-		count = (unsigned long) high_memory - p;
-	return do_write_mem(file, (void*)p, p, buf, count, ppos);
+ 	*ppos = p;
+ 	return virtr + wrote;
 }
 
 #if !defined(__mc68000__)
diff -urN linux-2.4.17-pre5/drivers/char/serial.c linux/drivers/char/serial.c
--- linux-2.4.17-pre5/drivers/char/serial.c	Fri Dec  7 14:52:27 2001
+++ linux/drivers/char/serial.c	Fri Dec  7 14:53:07 2001
@@ -4892,7 +4892,7 @@
 static struct pci_driver serial_pci_driver = {
        name:           "serial",
        probe:          serial_init_one,
-       remove:	       serial_remove_one,
+       remove:	       __devexit_p(serial_remove_one),
        id_table:       serial_pci_tbl,
 };
 
diff -urN linux-2.4.17-pre5/drivers/char/sonypi.c linux/drivers/char/sonypi.c
--- linux-2.4.17-pre5/drivers/char/sonypi.c	Mon Oct 15 08:38:31 2001
+++ linux/drivers/char/sonypi.c	Fri Dec  7 14:53:07 2001
@@ -617,8 +617,11 @@
 		goto out3;
 	}
 
+#if !defined(CONFIG_ACPI)
+	/* Enable ACPI mode to get Fn key events */
 	if (fnkeyinit)
 		outb(0xf0, 0xb2);
+#endif
 
 	if (sonypi_device.model == SONYPI_DEVICE_MODEL_TYPE2)
 		sonypi_type2_srs();
@@ -666,6 +669,11 @@
 		sonypi_type2_dis();
 	else
 		sonypi_type1_dis();
+#if !defined(CONFIG_ACPI)
+	/* disable ACPI mode */
+	if (fnkeyinit)
+		outb(0xf1, 0xb2);
+#endif
 	free_irq(sonypi_device.irq, sonypi_irq);
 	release_region(sonypi_device.ioport1, sonypi_device.region_size);
 	misc_deregister(&sonypi_misc_device);
diff -urN linux-2.4.17-pre5/drivers/char/sonypi.h linux/drivers/char/sonypi.h
--- linux-2.4.17-pre5/drivers/char/sonypi.h	Mon Oct 15 08:38:31 2001
+++ linux/drivers/char/sonypi.h	Fri Dec  7 14:53:07 2001
@@ -35,7 +35,7 @@
 #ifdef __KERNEL__
 
 #define SONYPI_DRIVER_MAJORVERSION	1
-#define SONYPI_DRIVER_MINORVERSION	7
+#define SONYPI_DRIVER_MINORVERSION	8
 
 #include <linux/types.h>
 #include <linux/pci.h>
diff -urN linux-2.4.17-pre5/drivers/ieee1394/ohci1394.c linux/drivers/ieee1394/ohci1394.c
--- linux-2.4.17-pre5/drivers/ieee1394/ohci1394.c	Fri Dec  7 14:52:27 2001
+++ linux/drivers/ieee1394/ohci1394.c	Fri Dec  7 14:53:07 2001
@@ -2374,7 +2374,7 @@
 	name:		OHCI1394_DRIVER_NAME,
 	id_table:	ohci1394_pci_tbl,
 	probe:		ohci1394_add_one,
-	remove:		ohci1394_remove_one,
+	remove:		__devexit_p(ohci1394_remove_one),
 };
 
 static void __exit ohci1394_cleanup (void)
diff -urN linux-2.4.17-pre5/drivers/isdn/eicon/common.c linux/drivers/isdn/eicon/common.c
--- linux-2.4.17-pre5/drivers/isdn/eicon/common.c	Sun Sep 30 12:26:05 2001
+++ linux/drivers/isdn/eicon/common.c	Fri Dec  7 14:53:07 2001
@@ -808,7 +808,9 @@
 	
 	while(i--)
 	{
-		DivaDoCardDpc(card++);
+            if (card->state == DIA_RUNNING)
+		DivaDoCardDpc(card);
+            card++;
 	}
 }
 
diff -urN linux-2.4.17-pre5/drivers/isdn/eicon/eicon.h linux/drivers/isdn/eicon/eicon.h
--- linux-2.4.17-pre5/drivers/isdn/eicon/eicon.h	Sun Sep 30 12:26:05 2001
+++ linux/drivers/isdn/eicon/eicon.h	Fri Dec  7 14:53:07 2001
@@ -1,4 +1,4 @@
-/* $Id: eicon.h,v 1.23.6.5 2001/09/23 22:24:37 kai Exp $
+/* $Id: eicon.h,v 1.1.4.1 2001/11/20 14:19:35 kai Exp $
  *
  * ISDN low-level module for Eicon active ISDN-Cards.
  *
diff -urN linux-2.4.17-pre5/drivers/isdn/eicon/eicon_dsp.h linux/drivers/isdn/eicon/eicon_dsp.h
--- linux-2.4.17-pre5/drivers/isdn/eicon/eicon_dsp.h	Sun Sep 30 12:26:05 2001
+++ linux/drivers/isdn/eicon/eicon_dsp.h	Fri Dec  7 14:53:07 2001
@@ -1,4 +1,4 @@
-/* $Id: eicon_dsp.h,v 1.7.6.1 2001/09/23 22:24:37 kai Exp $
+/* $Id: eicon_dsp.h,v 1.1.4.1 2001/11/20 14:19:35 kai Exp $
  *
  * ISDN lowlevel-module for Eicon active cards.
  * DSP definitions
diff -urN linux-2.4.17-pre5/drivers/isdn/eicon/eicon_idi.c linux/drivers/isdn/eicon/eicon_idi.c
--- linux-2.4.17-pre5/drivers/isdn/eicon/eicon_idi.c	Fri Nov  9 13:41:41 2001
+++ linux/drivers/isdn/eicon/eicon_idi.c	Fri Dec  7 14:53:07 2001
@@ -1,4 +1,4 @@
-/* $Id: eicon_idi.c,v 1.41.6.4 2001/11/06 20:58:29 kai Exp $
+/* $Id: eicon_idi.c,v 1.1.4.1 2001/11/20 14:19:35 kai Exp $
  *
  * ISDN lowlevel-module for Eicon active cards.
  * IDI interface 
@@ -25,7 +25,7 @@
 
 #undef EICON_FULL_SERVICE_OKTETT
 
-char *eicon_idi_revision = "$Revision: 1.41.6.4 $";
+char *eicon_idi_revision = "$Revision: 1.1.4.1 $";
 
 eicon_manifbuf *manbuf;
 
diff -urN linux-2.4.17-pre5/drivers/isdn/eicon/eicon_idi.h linux/drivers/isdn/eicon/eicon_idi.h
--- linux-2.4.17-pre5/drivers/isdn/eicon/eicon_idi.h	Sun Sep 30 12:26:05 2001
+++ linux/drivers/isdn/eicon/eicon_idi.h	Fri Dec  7 14:53:07 2001
@@ -1,4 +1,4 @@
-/* $Id: eicon_idi.h,v 1.11.6.1 2001/09/23 22:24:37 kai Exp $
+/* $Id: eicon_idi.h,v 1.1.4.1 2001/11/20 14:19:35 kai Exp $
  *
  * ISDN lowlevel-module for the Eicon active cards.
  * IDI-Interface
diff -urN linux-2.4.17-pre5/drivers/isdn/eicon/eicon_io.c linux/drivers/isdn/eicon/eicon_io.c
--- linux-2.4.17-pre5/drivers/isdn/eicon/eicon_io.c	Sun Sep 30 12:26:05 2001
+++ linux/drivers/isdn/eicon/eicon_io.c	Fri Dec  7 14:53:07 2001
@@ -1,4 +1,4 @@
-/* $Id: eicon_io.c,v 1.13.6.2 2001/09/23 22:24:37 kai Exp $
+/* $Id: eicon_io.c,v 1.1.4.1 2001/11/20 14:19:35 kai Exp $
  *
  * ISDN low-level module for Eicon active ISDN-Cards.
  * Code for communicating with hardware.
diff -urN linux-2.4.17-pre5/drivers/isdn/eicon/eicon_isa.c linux/drivers/isdn/eicon/eicon_isa.c
--- linux-2.4.17-pre5/drivers/isdn/eicon/eicon_isa.c	Fri Nov  9 13:41:41 2001
+++ linux/drivers/isdn/eicon/eicon_isa.c	Fri Dec  7 14:53:07 2001
@@ -1,4 +1,4 @@
-/* $Id: eicon_isa.c,v 1.16.6.2 2001/11/06 20:58:29 kai Exp $
+/* $Id: eicon_isa.c,v 1.1.4.1 2001/11/20 14:19:35 kai Exp $
  *
  * ISDN low-level module for Eicon active ISDN-Cards.
  * Hardware-specific code for old ISA cards.
@@ -20,7 +20,7 @@
 #define release_shmem release_region
 #define request_shmem request_region
 
-char *eicon_isa_revision = "$Revision: 1.16.6.2 $";
+char *eicon_isa_revision = "$Revision: 1.1.4.1 $";
 
 #undef EICON_MCA_DEBUG
 
diff -urN linux-2.4.17-pre5/drivers/isdn/eicon/eicon_isa.h linux/drivers/isdn/eicon/eicon_isa.h
--- linux-2.4.17-pre5/drivers/isdn/eicon/eicon_isa.h	Sun Sep 30 12:26:05 2001
+++ linux/drivers/isdn/eicon/eicon_isa.h	Fri Dec  7 14:53:07 2001
@@ -1,4 +1,4 @@
-/* $Id: eicon_isa.h,v 1.10.6.1 2001/09/23 22:24:37 kai Exp $
+/* $Id: eicon_isa.h,v 1.1.4.1 2001/11/20 14:19:35 kai Exp $
  *
  * ISDN low-level module for Eicon active ISDN-Cards.
  *
diff -urN linux-2.4.17-pre5/drivers/isdn/eicon/eicon_mod.c linux/drivers/isdn/eicon/eicon_mod.c
--- linux-2.4.17-pre5/drivers/isdn/eicon/eicon_mod.c	Sun Sep 30 12:26:05 2001
+++ linux/drivers/isdn/eicon/eicon_mod.c	Fri Dec  7 14:53:07 2001
@@ -1,4 +1,4 @@
-/* $Id: eicon_mod.c,v 1.37.6.6 2001/09/23 22:24:37 kai Exp $
+/* $Id: eicon_mod.c,v 1.1.4.1 2001/11/20 14:19:35 kai Exp $
  *
  * ISDN lowlevel-module for Eicon active cards.
  * 
@@ -44,7 +44,7 @@
 static eicon_card *cards = (eicon_card *) NULL;   /* glob. var , contains
                                                      start of card-list   */
 
-static char *eicon_revision = "$Revision: 1.37.6.6 $";
+static char *eicon_revision = "$Revision: 1.1.4.1 $";
 
 extern char *eicon_pci_revision;
 extern char *eicon_isa_revision;
@@ -1550,7 +1550,7 @@
             	};
 	};
 	/* all adapter flavors checked without match, finito with:            */
-        return ENODEV;
+        return -ENODEV;
 };
 
 
@@ -1597,14 +1597,14 @@
 				membase = cards_membase;
 			} else {
 				if (membase != cards_membase)
-					return ENODEV;
+					return -ENODEV;
 			};
 			cards_irq=irq_array[((adf_pos0 & 0xC)>>2)];
 			if (irq == -1) { 
 				irq = cards_irq;
 			} else {
 				if (irq != cards_irq)
-					return ENODEV;
+					return -ENODEV;
 			};
 			cards_io= 0xC00 + ((adf_pos0>>4)*0x10);
 			type = EICON_CTYPE_ISAPRI; 
@@ -1616,14 +1616,14 @@
 				membase = cards_membase;
 			} else {
 				if (membase != cards_membase)
-					return ENODEV;
+					return -ENODEV;
 			};
 			cards_irq=irq_array[((adf_pos0 & 0xC)>>2)];
 			if (irq == -1) { 
 				irq = cards_irq;
 			} else {
 				if (irq != cards_irq)
-					return ENODEV;
+					return -ENODEV;
 			};
 
 			cards_io= 0xC00 + ((adf_pos0>>4)*0x10);
@@ -1637,12 +1637,12 @@
 				irq = cards_irq;
 			} else {
 				if (irq != cards_irq)
-					return ENODEV;
+					return -ENODEV;
 			};
 			type = 0; 
 			break;
 		default:
-			return  ENODEV;
+			return -ENODEV;
 	};
 	/* matching membase & irq */
 	if ( 1 == eicon_addcard(type, membase, irq, id, 0)) { 
@@ -1661,7 +1661,7 @@
 			cards->mca_slot+1);
 		return  0 ; /* eicon_addcard added a card */
 	} else {
-		return ENODEV;
+		return -ENODEV;
 	};
 };
 #endif /* CONFIG_MCA */
diff -urN linux-2.4.17-pre5/drivers/isdn/eicon/eicon_pci.c linux/drivers/isdn/eicon/eicon_pci.c
--- linux-2.4.17-pre5/drivers/isdn/eicon/eicon_pci.c	Sun Sep 30 12:26:05 2001
+++ linux/drivers/isdn/eicon/eicon_pci.c	Fri Dec  7 14:53:07 2001
@@ -1,4 +1,4 @@
-/* $Id: eicon_pci.c,v 1.15.6.3 2001/09/23 22:24:37 kai Exp $
+/* $Id: eicon_pci.c,v 1.1.4.1 2001/11/20 14:19:35 kai Exp $
  *
  * ISDN low-level module for Eicon active ISDN-Cards.
  * Hardware-specific code for PCI cards.
@@ -24,7 +24,7 @@
 #include "adapter.h"
 #include "uxio.h"
 
-char *eicon_pci_revision = "$Revision: 1.15.6.3 $";
+char *eicon_pci_revision = "$Revision: 1.1.4.1 $";
 
 #if CONFIG_PCI	         /* intire stuff is only for PCI */
 #ifdef CONFIG_ISDN_DRV_EICON_PCI
diff -urN linux-2.4.17-pre5/drivers/isdn/eicon/eicon_pci.h linux/drivers/isdn/eicon/eicon_pci.h
--- linux-2.4.17-pre5/drivers/isdn/eicon/eicon_pci.h	Sun Sep 30 12:26:05 2001
+++ linux/drivers/isdn/eicon/eicon_pci.h	Fri Dec  7 14:53:07 2001
@@ -1,4 +1,4 @@
-/* $Id: eicon_pci.h,v 1.6.6.1 2001/09/23 22:24:37 kai Exp $
+/* $Id: eicon_pci.h,v 1.1.4.1 2001/11/20 14:19:35 kai Exp $
  *
  * ISDN low-level module for Eicon active ISDN-Cards (PCI part).
  *
diff -urN linux-2.4.17-pre5/drivers/isdn/hisax/config.c linux/drivers/isdn/hisax/config.c
--- linux-2.4.17-pre5/drivers/isdn/hisax/config.c	Fri Dec  7 14:52:27 2001
+++ linux/drivers/isdn/hisax/config.c	Fri Dec  7 14:53:07 2001
@@ -485,7 +485,7 @@
 		if (strlen(str) < HISAX_IDSIZE)
 			strcpy(HiSaxID, str);
 		else
-			printk(KERN_WARNING "HiSax: ID too long!")
+			printk(KERN_WARNING "HiSax: ID too long!");
 	} else
 		strcpy(HiSaxID, "HiSax");
 
diff -urN linux-2.4.17-pre5/drivers/isdn/hisax/hisax_fcpcipnp.c linux/drivers/isdn/hisax/hisax_fcpcipnp.c
--- linux-2.4.17-pre5/drivers/isdn/hisax/hisax_fcpcipnp.c	Fri Dec  7 14:52:27 2001
+++ linux/drivers/isdn/hisax/hisax_fcpcipnp.c	Fri Dec  7 14:53:07 2001
@@ -533,7 +533,7 @@
 	dev_kfree_skb_irq(skb);
 }
 
-static void hdlc_irq(struct fritz_bcs *bcs, u32 stat)
+static void hdlc_irq_one(struct fritz_bcs *bcs, u32 stat)
 {
 	DBG(0x10, "ch%d stat %#x", bcs->channel, stat);
 	if (stat & HDLC_INT_RPR) {
@@ -550,7 +550,7 @@
 	}
 }
 
-static inline void hdlc_interrupt(struct fritz_adapter *adapter)
+static inline void hdlc_irq(struct fritz_adapter *adapter)
 {
 	int nr;
 	u32 stat;
@@ -559,7 +559,7 @@
 		stat = adapter->read_hdlc_status(adapter, nr);
 		DBG(0x10, "HDLC %c stat %#x", 'A' + nr, stat);
 		if (stat & HDLC_INT_MASK)
-			hdlc_irq(&adapter->bcs[nr], stat);
+			hdlc_irq_one(&adapter->bcs[nr], stat);
 	}
 }
 
@@ -642,10 +642,10 @@
 		return;
 	DBG(2, "STATUS0 %#x", val);
 	if (val & AVM_STATUS0_IRQ_ISAC)
-		isacsx_interrupt(&adapter->isac);
+		isacsx_irq(&adapter->isac);
 
 	if (val & AVM_STATUS0_IRQ_HDLC)
-		hdlc_interrupt(adapter);
+		hdlc_irq(adapter);
 }
 
 static void fcpci_irq(int intno, void *dev, struct pt_regs *regs)
@@ -659,10 +659,10 @@
 		return;
 	DBG(2, "sval %#x", sval);
 	if (!(sval & AVM_STATUS0_IRQ_ISAC))
-		isac_interrupt(&adapter->isac);
+		isac_irq(&adapter->isac);
 
 	if (!(sval & AVM_STATUS0_IRQ_HDLC))
-		hdlc_interrupt(adapter);
+		hdlc_irq(adapter);
 }
 
 // ----------------------------------------------------------------------
diff -urN linux-2.4.17-pre5/drivers/isdn/hisax/hisax_isac.c linux/drivers/isdn/hisax/hisax_isac.c
--- linux-2.4.17-pre5/drivers/isdn/hisax/hisax_isac.c	Fri Dec  7 14:52:27 2001
+++ linux/drivers/isdn/hisax/hisax_isac.c	Fri Dec  7 14:53:07 2001
@@ -601,7 +601,7 @@
 	}
 }
 
-void isac_interrupt(struct isac *isac)
+void isac_irq(struct isac *isac)
 {
 	unsigned char val;
 
@@ -741,7 +741,7 @@
 	}
 }
 
-void isacsx_interrupt(struct isac *isac)
+void isacsx_irq(struct isac *isac)
 {
 	unsigned char val;
 
@@ -887,10 +887,10 @@
 EXPORT_SYMBOL(isac_d_l2l1);
 
 EXPORT_SYMBOL(isacsx_setup);
-EXPORT_SYMBOL(isacsx_interrupt);
+EXPORT_SYMBOL(isacsx_irq);
 
 EXPORT_SYMBOL(isac_setup);
-EXPORT_SYMBOL(isac_interrupt);
+EXPORT_SYMBOL(isac_irq);
 
 module_init(hisax_isac_init);
 module_exit(hisax_isac_exit);
diff -urN linux-2.4.17-pre5/drivers/isdn/hisax/hisax_isac.h linux/drivers/isdn/hisax/hisax_isac.h
--- linux-2.4.17-pre5/drivers/isdn/hisax/hisax_isac.h	Fri Dec  7 14:52:27 2001
+++ linux/drivers/isdn/hisax/hisax_isac.h	Fri Dec  7 14:53:07 2001
@@ -37,9 +37,9 @@
 void isac_d_l2l1(struct hisax_if *hisax_d_if, int pr, void *arg);
 
 void isac_setup(struct isac *isac);
-void isac_interrupt(struct isac *isac);
+void isac_irq(struct isac *isac);
 
 void isacsx_setup(struct isac *isac);
-void isacsx_interrupt(struct isac *isac);
+void isacsx_irq(struct isac *isac);
 
 #endif
diff -urN linux-2.4.17-pre5/drivers/isdn/hisax/st5481_b.c linux/drivers/isdn/hisax/st5481_b.c
--- linux-2.4.17-pre5/drivers/isdn/hisax/st5481_b.c	Sun Sep 30 12:26:06 2001
+++ linux/drivers/isdn/hisax/st5481_b.c	Fri Dec  7 14:53:07 2001
@@ -275,7 +275,7 @@
 				      usb_b_out_complete, bcs);
 }
 
-static void __devexit st5481_release_b_out(struct st5481_bcs *bcs)
+static void st5481_release_b_out(struct st5481_bcs *bcs)
 {
 	struct st5481_b_out *b_out = &bcs->b_out;
 
@@ -316,7 +316,7 @@
 /*
  * Release buffers and URBs for the B channels
  */
-void __devexit st5481_release_b(struct st5481_bcs *bcs)
+void st5481_release_b(struct st5481_bcs *bcs)
 {
 	DBG(4,"");
 
diff -urN linux-2.4.17-pre5/drivers/isdn/hisax/st5481_d.c linux/drivers/isdn/hisax/st5481_d.c
--- linux-2.4.17-pre5/drivers/isdn/hisax/st5481_d.c	Wed Oct 24 15:34:51 2001
+++ linux/drivers/isdn/hisax/st5481_d.c	Fri Dec  7 14:53:07 2001
@@ -673,7 +673,7 @@
 				      usb_d_out_complete, adapter);
 }
 
-static void __devexit st5481_release_d_out(struct st5481_adapter *adapter)
+static void st5481_release_d_out(struct st5481_adapter *adapter)
 {
 	struct st5481_d_out *d_out = &adapter->d_out;
 
@@ -723,7 +723,7 @@
 	return retval;
 }
 
-void __devexit st5481_release_d(struct st5481_adapter *adapter)
+void st5481_release_d(struct st5481_adapter *adapter)
 {
 	DBG(2,"");
 
diff -urN linux-2.4.17-pre5/drivers/isdn/hisax/st5481_init.c linux/drivers/isdn/hisax/st5481_init.c
--- linux-2.4.17-pre5/drivers/isdn/hisax/st5481_init.c	Sun Sep 30 12:26:06 2001
+++ linux/drivers/isdn/hisax/st5481_init.c	Fri Dec  7 14:53:07 2001
@@ -178,7 +178,7 @@
 static struct usb_driver st5481_usb_driver = {
 	name: "st5481_usb",
 	probe: probe_st5481,
-	disconnect: disconnect_st5481,
+	disconnect: __devexit_p(disconnect_st5481),
 	id_table: st5481_ids,
 };
 
diff -urN linux-2.4.17-pre5/drivers/isdn/hisax/st5481_usb.c linux/drivers/isdn/hisax/st5481_usb.c
--- linux-2.4.17-pre5/drivers/isdn/hisax/st5481_usb.c	Wed Oct 24 15:34:51 2001
+++ linux/drivers/isdn/hisax/st5481_usb.c	Fri Dec  7 14:53:07 2001
@@ -307,7 +307,7 @@
  * Release buffers and URBs for the interrupt and control
  * endpoint.
  */
-void __devexit st5481_release_usb(struct st5481_adapter *adapter)
+void st5481_release_usb(struct st5481_adapter *adapter)
 {
 	struct st5481_intr *intr = &adapter->intr;
 	struct st5481_ctrl *ctrl = &adapter->ctrl;
@@ -443,7 +443,7 @@
 	return retval;
 }
 
-void __devexit st5481_release_isocpipes(struct urb* urb[2])
+void st5481_release_isocpipes(struct urb* urb[2])
 {
 	int j;
 
@@ -547,7 +547,7 @@
 	return retval;
 }
 
-void __devexit st5481_release_in(struct st5481_in *in)
+void st5481_release_in(struct st5481_in *in)
 {
 	DBG(2,"");
 
diff -urN linux-2.4.17-pre5/drivers/isdn/hysdn/hysdn_procfs.c linux/drivers/isdn/hysdn/hysdn_procfs.c
--- linux-2.4.17-pre5/drivers/isdn/hysdn/hysdn_procfs.c	Sun Aug 12 10:38:48 2001
+++ linux/drivers/isdn/hysdn/hysdn_procfs.c	Wed Dec 31 16:00:00 1969
@@ -1,471 +0,0 @@
-/* $Id: hysdn_procfs.c,v 1.1 2000/02/10 19:45:18 werner Exp $
-
- * Linux driver for HYSDN cards, /proc/net filesystem log functions.
- * written by Werner Cornelius (werner@titro.de) for Hypercope GmbH
- *
- * Copyright 1999  by Werner Cornelius (werner@titro.de)
- *
- * 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, 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.
- *
- * $Log: hysdn_procfs.c,v $
- * Revision 1.1  2000/02/10 19:45:18  werner
- *
- * Initial release
- *
- *
- */
-
-#define __NO_VERSION__
-#include <linux/module.h>
-#include <linux/version.h>
-#include <linux/poll.h>
-#include <linux/proc_fs.h>
-#include <linux/pci.h>
-#include <linux/smp_lock.h>
-
-#include "hysdn_defs.h"
-
-static char *hysdn_procfs_revision = "$Revision: 1.1 $";
-
-#define INFO_OUT_LEN 80		/* length of info line including lf */
-
-/*************************************************/
-/* structure keeping ascii log for device output */
-/*************************************************/
-struct log_data {
-	struct log_data *next;
-	ulong usage_cnt;	/* number of files still to work */
-	void *proc_ctrl;	/* pointer to own control procdata structure */
-	char log_start[2];	/* log string start (final len aligned by size) */
-};
-
-/**********************************************/
-/* structure holding proc entrys for one card */
-/**********************************************/
-struct procdata {
-	struct proc_dir_entry *log;	/* log entry */
-	char log_name[15];	/* log filename */
-	struct log_data *log_head, *log_tail;	/* head and tail for queue */
-	int if_used;		/* open count for interface */
-	wait_queue_head_t rd_queue;
-};
-
-/********************************************/
-/* put an log buffer into the log queue.    */
-/* This buffer will be kept until all files */
-/* opened for read got the contents.        */
-/* Flushes buffers not longer in use.       */
-/********************************************/
-void
-put_log_buffer(hysdn_card * card, char *cp)
-{
-	struct log_data *ib;
-	struct procdata *pd = card->procfs;
-	int flags;
-
-	if (!pd)
-		return;
-	if (!cp)
-		return;
-	if (!*cp)
-		return;
-	if (pd->if_used <= 0)
-		return;		/* no open file for read */
-
-	if (!(ib = (struct log_data *) kmalloc(sizeof(struct log_data) + strlen(cp), GFP_ATOMIC)))
-		 return;	/* no memory */
-	strcpy(ib->log_start, cp);	/* set output string */
-	ib->next = NULL;
-	ib->proc_ctrl = pd;	/* point to own control structure */
-	save_flags(flags);
-	cli();
-	ib->usage_cnt = pd->if_used;
-	if (!pd->log_head)
-		pd->log_head = ib;	/* new head */
-	else
-		pd->log_tail->next = ib;	/* follows existing messages */
-	pd->log_tail = ib;	/* new tail */
-	restore_flags(flags);
-
-	/* delete old entrys */
-	while (pd->log_head->next) {
-		if ((pd->log_head->usage_cnt <= 0) &&
-		    (pd->log_head->next->usage_cnt <= 0)) {
-			ib = pd->log_head;
-			pd->log_head = pd->log_head->next;
-			kfree(ib);
-		} else
-			break;
-	}			/* pd->log_head->next */
-	wake_up_interruptible(&(pd->rd_queue));		/* announce new entry */
-}				/* put_log_buffer */
-
-
-/**********************************/
-/* log file operations and tables */
-/**********************************/
-
-/****************************************/
-/* write log file -> set log level bits */
-/****************************************/
-static ssize_t
-hysdn_log_write(struct file *file, const char *buf, size_t count, loff_t * off)
-{
-	int retval;
-	hysdn_card *card = (hysdn_card *) file->private_data;
-
-	if (&file->f_pos != off)	/* fs error check */
-		return (-ESPIPE);
-
-	if ((retval = pof_boot_write(card, buf, count)) < 0)
-		retval = -EFAULT;	/* an error occurred */
-
-	return (retval);
-}				/* hysdn_log_write */
-
-/******************/
-/* read log file */
-/******************/
-static ssize_t
-hysdn_log_read(struct file *file, char *buf, size_t count, loff_t * off)
-{
-	struct log_data *inf;
-	int len;
-	word ino;
-	struct procdata *pd;
-	hysdn_card *card;
-
-	if (!*((struct log_data **) file->private_data)) {
-		if (file->f_flags & O_NONBLOCK)
-			return (-EAGAIN);
-
-		/* sorry, but we need to search the card */
-		ino = file->f_dentry->d_inode->i_ino & 0xFFFF;	/* low-ino */
-		card = card_root;
-		while (card) {
-			pd = card->procfs;
-			if (pd->log->low_ino == ino)
-				break;
-			card = card->next;	/* search next entry */
-		}
-		if (card)
-			interruptible_sleep_on(&(pd->rd_queue));
-		else
-			return (-EAGAIN);
-
-	}
-	if (!(inf = *((struct log_data **) file->private_data)))
-		return (0);
-
-	inf->usage_cnt--;	/* new usage count */
-	(struct log_data **) file->private_data = &inf->next;	/* next structure */
-	if ((len = strlen(inf->log_start)) <= count) {
-		if (copy_to_user(buf, inf->log_start, len))
-			return -EFAULT;
-		file->f_pos += len;
-		return (len);
-	}
-	return (0);
-}				/* hysdn_log_read */
-
-/******************/
-/* open log file */
-/******************/
-static int
-hysdn_log_open(struct inode *ino, struct file *filep)
-{
-	hysdn_card *card;
-	struct procdata *pd;
-	ulong flags;
-
-	lock_kernel();
-	card = card_root;
-	while (card) {
-		pd = card->procfs;
-		if (pd->log->low_ino == (ino->i_ino & 0xFFFF))
-			break;
-		card = card->next;	/* search next entry */
-	}
-	if (!card) {
-		unlock_kernel();
-		return (-ENODEV);	/* device is unknown/invalid */
-	}
-	filep->private_data = card;	/* remember our own card */
-
-	if ((filep->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_WRITE) {
-		/* write only access -> boot pof data */
-		if (pof_boot_open(card)) {
-			unlock_kernel();
-			return (-EPERM);	/* no permission this time */
-		}
-	} else if ((filep->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ) {
-
-		/* read access -> log/debug read */
-		save_flags(flags);
-		cli();
-		pd->if_used++;
-		if (pd->log_head)
-			(struct log_data **) filep->private_data = &(pd->log_tail->next);
-		else
-			(struct log_data **) filep->private_data = &(pd->log_head);
-		restore_flags(flags);
-
-	} else {		/* simultaneous read/write access forbidden ! */
-		unlock_kernel();
-		return (-EPERM);	/* no permission this time */
-	}
-	unlock_kernel();
-	return (0);
-}				/* hysdn_log_open */
-
-/*******************************************************************************/
-/* close a cardlog file. If the file has been opened for exclusive write it is */
-/* assumed as pof data input and the pof loader is noticed about.              */
-/* Otherwise file is handled as log output. In this case the interface usage   */
-/* count is decremented and all buffers are noticed of closing. If this file   */
-/* was the last one to be closed, all buffers are freed.                       */
-/*******************************************************************************/
-static int
-hysdn_log_close(struct inode *ino, struct file *filep)
-{
-	struct log_data *inf;
-	struct procdata *pd;
-	hysdn_card *card;
-	int flags, retval = 0;
-
-	lock_kernel();
-	if ((filep->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_WRITE) {
-		/* write only access -> write debug completely written */
-		retval = 0;	/* success */
-	} else {
-		/* read access -> log/debug read, mark one further file as closed */
-
-		pd = NULL;
-		save_flags(flags);
-		cli();
-		inf = *((struct log_data **) filep->private_data);	/* get first log entry */
-		if (inf)
-			pd = (struct procdata *) inf->proc_ctrl;	/* still entries there */
-		else {
-			/* no info available -> search card */
-			card = card_root;
-			while (card) {
-				pd = card->procfs;
-				if (pd->log->low_ino == (ino->i_ino & 0xFFFF))
-					break;
-				card = card->next;	/* search next entry */
-			}
-			if (card)
-				pd = card->procfs;	/* pointer to procfs ctrl */
-		}
-		if (pd)
-			pd->if_used--;	/* decrement interface usage count by one */
-
-		while (inf) {
-			inf->usage_cnt--;	/* decrement usage count for buffers */
-			inf = inf->next;
-		}
-		restore_flags(flags);
-
-		if (pd)
-			if (pd->if_used <= 0)	/* delete buffers if last file closed */
-				while (pd->log_head) {
-					inf = pd->log_head;
-					pd->log_head = pd->log_head->next;
-					kfree(inf);
-				}
-	}			/* read access */
-
-	unlock_kernel();
-	return (retval);
-}				/* hysdn_log_close */
-
-/*************************************************/
-/* select/poll routine to be able using select() */
-/*************************************************/
-static unsigned int
-hysdn_log_poll(struct file *file, poll_table * wait)
-{
-	unsigned int mask = 0;
-	word ino;
-	hysdn_card *card;
-	struct procdata *pd;
-
-	if ((file->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_WRITE)
-		return (mask);	/* no polling for write supported */
-
-	/* we need to search the card */
-	ino = file->f_dentry->d_inode->i_ino & 0xFFFF;	/* low-ino */
-	card = card_root;
-	while (card) {
-		pd = card->procfs;
-		if (pd->log->low_ino == ino)
-			break;
-		card = card->next;	/* search next entry */
-	}
-	if (!card)
-		return (mask);	/* card not found */
-
-	poll_wait(file, &(pd->rd_queue), wait);
-
-	if (*((struct log_data **) file->private_data))
-		mask |= POLLIN | POLLRDNORM;
-
-	return mask;
-}				/* hysdn_log_poll */
-
-/**************************************************/
-/* table for log filesystem functions defined above. */
-/**************************************************/
-static struct file_operations log_fops =
-{
-	llseek:		no_llseek,
-	read:		hysdn_log_read,
-	write:		hysdn_log_write,
-	poll:		hysdn_log_poll,
-	open:		hysdn_log_open,
-	release:	hysdn_log_close,
-};
-
-/*****************************************/
-/* Output info data to the cardinfo file */
-/*****************************************/
-static int
-info_read(char *buffer, char **start, off_t offset, int length, int *eof, void *data)
-{
-	char tmp[INFO_OUT_LEN * 11 + 2];
-	int i;
-	char *cp;
-	hysdn_card *card;
-
-	sprintf(tmp, "id bus slot type irq iobase plx-mem    dp-mem     boot device");
-	cp = tmp;		/* start of string */
-	while (*cp)
-		cp++;
-	while (((cp - tmp) % (INFO_OUT_LEN + 1)) != INFO_OUT_LEN)
-		*cp++ = ' ';
-	*cp++ = '\n';
-
-	card = card_root;	/* start of list */
-	while (card) {
-		sprintf(cp, "%d  %3d %4d %4d %3d 0x%04x 0x%08x 0x%08x",
-			card->myid,
-			card->bus,
-			PCI_SLOT(card->devfn),
-			card->brdtype,
-			card->irq,
-			card->iobase,
-			card->plxbase,
-			card->membase);
-		card = card->next;
-		while (*cp)
-			cp++;
-		while (((cp - tmp) % (INFO_OUT_LEN + 1)) != INFO_OUT_LEN)
-			*cp++ = ' ';
-		*cp++ = '\n';
-	}
-
-	i = cp - tmp;
-	*start = buffer;
-	if (offset + length > i) {
-		length = i - offset;
-		*eof = 1;
-	} else if (offset > i) {
-		length = 0;
-		*eof = 1;
-	}
-	cp = tmp + offset;
-
-	if (length > 0) {
-		/*   start_bh_atomic(); */
-		memcpy(buffer, cp, length);
-		/* end_bh_atomic(); */
-		return length;
-	}
-	return 0;
-}				/* info_read */
-
-/*****************************/
-/* hysdn subdir in /proc/net */
-/*****************************/
-static struct proc_dir_entry *hysdn_proc_entry = NULL;
-static struct proc_dir_entry *hysdn_info_entry = NULL;
-
-/***************************************************************************************/
-/* hysdn_procfs_init is called when the module is loaded and after the cards have been */
-/* detected. The needed proc dir and card entries are created.                         */
-/***************************************************************************************/
-int
-hysdn_procfs_init(void)
-{
-	struct procdata *pd;
-	hysdn_card *card;
-
-	hysdn_proc_entry = create_proc_entry(PROC_SUBDIR_NAME, S_IFDIR | S_IRUGO | S_IXUGO, proc_net);
-	if (!hysdn_proc_entry) {
-		printk(KERN_ERR "HYSDN: unable to create hysdn subdir\n");
-		return (-1);
-	}
-	hysdn_info_entry = create_proc_entry("cardinfo", 0, hysdn_proc_entry);
-	if (hysdn_info_entry)
-		hysdn_info_entry->read_proc = info_read;	/* read info function */
-
-	/* create all cardlog proc entries */
-
-	card = card_root;	/* start with first card */
-	while (card) {
-		if ((pd = (struct procdata *) kmalloc(sizeof(struct procdata), GFP_KERNEL)) != NULL) {
-			memset(pd, 0, sizeof(struct procdata));
-
-			sprintf(pd->log_name, "%s%d", PROC_LOG_BASENAME, card->myid);
-			if ((pd->log = create_proc_entry(pd->log_name, S_IFREG | S_IRUGO | S_IWUSR, hysdn_proc_entry)) != NULL) {
-				pd->log->proc_fops = &log_fops;	/* set new operations table */
-				pd->log->owner = THIS_MODULE;
-			}
-
-			init_waitqueue_head(&(pd->rd_queue));
-
-			card->procfs = (void *) pd;	/* remember procfs structure */
-		}
-		card = card->next;	/* point to next card */
-	}
-
-	printk(KERN_NOTICE "HYSDN: procfs Rev. %s initialised\n", hysdn_getrev(hysdn_procfs_revision));
-	return (0);
-}				/* hysdn_procfs_init */
-
-/***************************************************************************************/
-/* hysdn_procfs_release is called when the module is unloaded and before the cards     */
-/* resources are released. The module counter is assumed to be 0 !                     */
-/***************************************************************************************/
-void
-hysdn_procfs_release(void)
-{
-	struct procdata *pd;
-	hysdn_card *card;
-
-	card = card_root;	/* start with first card */
-	while (card) {
-		if ((pd = (struct procdata *) card->procfs) != NULL) {
-			if (pd->log)
-				remove_proc_entry(pd->log_name, hysdn_proc_entry);
-			kfree(pd);	/* release memory */
-		}
-		card = card->next;	/* point to next card */
-	}
-
-	remove_proc_entry("cardinfo", hysdn_proc_entry);
-	remove_proc_entry(PROC_SUBDIR_NAME, proc_net);
-}				/* hysdn_procfs_release */
diff -urN linux-2.4.17-pre5/drivers/isdn/tpam/tpam_main.c linux/drivers/isdn/tpam/tpam_main.c
--- linux-2.4.17-pre5/drivers/isdn/tpam/tpam_main.c	Sun Sep 30 12:26:06 2001
+++ linux/drivers/isdn/tpam/tpam_main.c	Fri Dec  7 14:53:07 2001
@@ -254,7 +254,7 @@
 	name:		"tpam",
 	id_table:	tpam_pci_tbl,
 	probe:		tpam_probe,
-	remove:		tpam_remove,
+	remove:		__devexit_p(tpam_remove),
 };
 
 static int __init tpam_init(void) {
diff -urN linux-2.4.17-pre5/drivers/media/radio/radio-gemtek-pci.c linux/drivers/media/radio/radio-gemtek-pci.c
--- linux-2.4.17-pre5/drivers/media/radio/radio-gemtek-pci.c	Sun Sep 30 12:26:06 2001
+++ linux/drivers/media/radio/radio-gemtek-pci.c	Fri Dec  7 14:53:07 2001
@@ -424,7 +424,7 @@
     name:	"gemtek_pci",
 id_table:	gemtek_pci_id,
    probe:	gemtek_pci_probe,
-  remove:	gemtek_pci_remove
+  remove:	__devexit_p(gemtek_pci_remove),
 };
 
 static int __init gemtek_pci_init_module( void )
diff -urN linux-2.4.17-pre5/drivers/media/radio/radio-maxiradio.c linux/drivers/media/radio/radio-maxiradio.c
--- linux-2.4.17-pre5/drivers/media/radio/radio-maxiradio.c	Sun Sep 30 12:26:06 2001
+++ linux/drivers/media/radio/radio-maxiradio.c	Fri Dec  7 14:53:07 2001
@@ -376,7 +376,7 @@
 	name:		"radio-maxiradio",
 	id_table:	maxiradio_pci_tbl,
 	probe:		maxiradio_init_one,
-	remove:		maxiradio_remove_one,
+	remove:		__devexit_p(maxiradio_remove_one),
 };
 
 int __init maxiradio_radio_init(void)
diff -urN linux-2.4.17-pre5/drivers/media/video/bttv-driver.c linux/drivers/media/video/bttv-driver.c
--- linux-2.4.17-pre5/drivers/media/video/bttv-driver.c	Wed Oct 17 14:19:20 2001
+++ linux/drivers/media/video/bttv-driver.c	Fri Dec  7 14:53:07 2001
@@ -3025,7 +3025,7 @@
         name:     "bttv",
         id_table: bttv_pci_tbl,
         probe:    bttv_probe,
-        remove:   bttv_remove,
+        remove:   __devexit_p(bttv_remove),
 };
 
 int bttv_init_module(void)
diff -urN linux-2.4.17-pre5/drivers/media/video/meye.c linux/drivers/media/video/meye.c
--- linux-2.4.17-pre5/drivers/media/video/meye.c	Thu Oct 25 13:53:47 2001
+++ linux/drivers/media/video/meye.c	Fri Dec  7 14:53:07 2001
@@ -1460,7 +1460,7 @@
 	name:		"meye",
 	id_table:	meye_pci_tbl,
 	probe:		meye_probe,
-	remove:		meye_remove,
+	remove:		__devexit_p(meye_remove),
 };
 
 static int __init meye_init_module(void) {
diff -urN linux-2.4.17-pre5/drivers/net/3c59x.c linux/drivers/net/3c59x.c
--- linux-2.4.17-pre5/drivers/net/3c59x.c	Fri Nov  9 13:41:42 2001
+++ linux/drivers/net/3c59x.c	Fri Dec  7 14:53:07 2001
@@ -2919,7 +2919,7 @@
 static struct pci_driver vortex_driver = {
 	name:		"3c59x",
 	probe:		vortex_init_one,
-	remove:		vortex_remove_one,
+	remove:		__devexit_p(vortex_remove_one),
 	id_table:	vortex_pci_tbl,
 #ifdef CONFIG_PM
 	suspend:	vortex_suspend,
diff -urN linux-2.4.17-pre5/drivers/net/8139cp.c linux/drivers/net/8139cp.c
--- linux-2.4.17-pre5/drivers/net/8139cp.c	Mon Nov 19 15:19:42 2001
+++ linux/drivers/net/8139cp.c	Fri Dec  7 14:53:07 2001
@@ -1313,7 +1313,7 @@
 	name:		DRV_NAME,
 	id_table:	cp_pci_tbl,
 	probe:		cp_init_one,
-	remove:		cp_remove_one,
+	remove:		__devexit_p(cp_remove_one),
 };
 
 static int __init cp_init (void)
diff -urN linux-2.4.17-pre5/drivers/net/8139too.c linux/drivers/net/8139too.c
--- linux-2.4.17-pre5/drivers/net/8139too.c	Fri Dec  7 14:52:27 2001
+++ linux/drivers/net/8139too.c	Fri Dec  7 14:53:07 2001
@@ -2494,7 +2494,7 @@
 	name:		DRV_NAME,
 	id_table:	rtl8139_pci_tbl,
 	probe:		rtl8139_init_one,
-	remove:		rtl8139_remove_one,
+	remove:		__devexit_p(rtl8139_remove_one),
 #ifdef CONFIG_PM
 	suspend:	rtl8139_suspend,
 	resume:		rtl8139_resume,
diff -urN linux-2.4.17-pre5/drivers/net/arcnet/com20020-pci.c linux/drivers/net/arcnet/com20020-pci.c
--- linux-2.4.17-pre5/drivers/net/arcnet/com20020-pci.c	Fri Nov  9 13:41:42 2001
+++ linux/drivers/net/arcnet/com20020-pci.c	Fri Dec  7 14:53:07 2001
@@ -160,7 +160,7 @@
 	name:		"com20020",
 	id_table:	com20020pci_id_table,
 	probe:		com20020pci_probe,
-	remove:		com20020pci_remove
+	remove:		__devexit_p(com20020pci_remove),
 };
 
 static int __init com20020pci_init(void)
diff -urN linux-2.4.17-pre5/drivers/net/defxx.c linux/drivers/net/defxx.c
--- linux-2.4.17-pre5/drivers/net/defxx.c	Sun Sep 30 12:26:06 2001
+++ linux/drivers/net/defxx.c	Fri Dec  7 14:53:07 2001
@@ -3360,7 +3360,7 @@
 static struct pci_driver dfx_driver = {
 	name:		"defxx",
 	probe:		dfx_init_one,
-	remove:		dfx_remove_one,
+	remove:		__devexit_p(dfx_remove_one),
 	id_table:	dfx_pci_tbl,
 };
 
diff -urN linux-2.4.17-pre5/drivers/net/dl2k.c linux/drivers/net/dl2k.c
--- linux-2.4.17-pre5/drivers/net/dl2k.c	Mon Nov 19 15:19:42 2001
+++ linux/drivers/net/dl2k.c	Fri Dec  7 14:53:07 2001
@@ -1671,7 +1671,7 @@
 	name:"dl2k",
 	id_table:rio_pci_tbl,
 	probe:rio_probe1,
-	remove:rio_remove1,
+	remove:__devexit_p(rio_remove1),
 };
 
 static int __init
diff -urN linux-2.4.17-pre5/drivers/net/eepro100.c linux/drivers/net/eepro100.c
--- linux-2.4.17-pre5/drivers/net/eepro100.c	Fri Dec  7 14:52:27 2001
+++ linux/drivers/net/eepro100.c	Fri Dec  7 14:53:07 2001
@@ -2297,7 +2297,7 @@
 	name:		"eepro100",
 	id_table:	eepro100_pci_tbl,
 	probe:		eepro100_init_one,
-	remove:		eepro100_remove_one,
+	remove:		__devexit_p(eepro100_remove_one),
 #ifdef CONFIG_PM
 	suspend:	eepro100_suspend,
 	resume:		eepro100_resume,
diff -urN linux-2.4.17-pre5/drivers/net/epic100.c linux/drivers/net/epic100.c
--- linux-2.4.17-pre5/drivers/net/epic100.c	Sun Sep 30 12:26:06 2001
+++ linux/drivers/net/epic100.c	Fri Dec  7 14:53:07 2001
@@ -1507,7 +1507,7 @@
 	name:		DRV_NAME,
 	id_table:	epic_pci_tbl,
 	probe:		epic_init_one,
-	remove:		epic_remove_one,
+	remove:		__devexit_p(epic_remove_one),
 #ifdef CONFIG_PM
 	suspend:	epic_suspend,
 	resume:		epic_resume,
diff -urN linux-2.4.17-pre5/drivers/net/fealnx.c linux/drivers/net/fealnx.c
--- linux-2.4.17-pre5/drivers/net/fealnx.c	Mon Nov 19 15:19:42 2001
+++ linux/drivers/net/fealnx.c	Fri Dec  7 14:53:07 2001
@@ -1858,7 +1858,7 @@
 	name:		"fealnx",
 	id_table:	fealnx_pci_tbl,
 	probe:		fealnx_init_one,
-	remove:		fealnx_remove_one,
+	remove:		__devexit_p(fealnx_remove_one),
 };
 
 static int __init fealnx_init(void)
diff -urN linux-2.4.17-pre5/drivers/net/ioc3-eth.c linux/drivers/net/ioc3-eth.c
--- linux-2.4.17-pre5/drivers/net/ioc3-eth.c	Tue Oct 16 21:56:29 2001
+++ linux/drivers/net/ioc3-eth.c	Fri Dec  7 14:53:07 2001
@@ -1515,7 +1515,7 @@
 	name:		"ioc3-eth",
 	id_table:	ioc3_pci_tbl,
 	probe:		ioc3_probe,
-	remove:		ioc3_remove_one,
+	remove:		__devexit_p(ioc3_remove_one),
 };
 
 static int __init ioc3_init_module(void)
diff -urN linux-2.4.17-pre5/drivers/net/irda/vlsi_ir.c linux/drivers/net/irda/vlsi_ir.c
--- linux-2.4.17-pre5/drivers/net/irda/vlsi_ir.c	Fri Dec  7 14:52:27 2001
+++ linux/drivers/net/irda/vlsi_ir.c	Fri Dec  7 14:53:07 2001
@@ -1291,7 +1291,7 @@
 	name:           drivername,
 	id_table:       vlsi_irda_table,
 	probe:          vlsi_irda_probe,
-	remove:         vlsi_irda_remove,
+	remove:         __devexit_p(vlsi_irda_remove),
 	suspend:        vlsi_irda_suspend,
 	resume:         vlsi_irda_resume,
 };
diff -urN linux-2.4.17-pre5/drivers/net/natsemi.c linux/drivers/net/natsemi.c
--- linux-2.4.17-pre5/drivers/net/natsemi.c	Mon Nov 19 15:19:42 2001
+++ linux/drivers/net/natsemi.c	Fri Dec  7 14:53:07 2001
@@ -2518,7 +2518,7 @@
 	name:		DRV_NAME,
 	id_table:	natsemi_pci_tbl,
 	probe:		natsemi_probe1,
-	remove:		natsemi_remove1,
+	remove:		__devexit_p(natsemi_remove1),
 #ifdef CONFIG_PM
 	suspend:	natsemi_suspend,
 	resume:		natsemi_resume,
diff -urN linux-2.4.17-pre5/drivers/net/ne2k-pci.c linux/drivers/net/ne2k-pci.c
--- linux-2.4.17-pre5/drivers/net/ne2k-pci.c	Sun Sep 30 12:26:07 2001
+++ linux/drivers/net/ne2k-pci.c	Fri Dec  7 14:53:07 2001
@@ -642,7 +642,7 @@
 static struct pci_driver ne2k_driver = {
 	name:		DRV_NAME,
 	probe:		ne2k_pci_init_one,
-	remove:		ne2k_pci_remove_one,
+	remove:		__devexit_p(ne2k_pci_remove_one),
 	id_table:	ne2k_pci_tbl,
 };
 
diff -urN linux-2.4.17-pre5/drivers/net/ns83820.c linux/drivers/net/ns83820.c
--- linux-2.4.17-pre5/drivers/net/ns83820.c	Fri Nov  9 13:45:35 2001
+++ linux/drivers/net/ns83820.c	Fri Dec  7 14:53:07 2001
@@ -1455,7 +1455,7 @@
 	name:		"ns83820",
 	id_table:	ns83820_pci_tbl,
 	probe:		ns83820_init_one,
-	remove:		ns83820_remove_one,
+	remove:		__devexit_p(ns83820_remove_one),
 #if 0	/* FIXME: implement */
 	suspend:	,
 	resume:		,
diff -urN linux-2.4.17-pre5/drivers/net/pci-skeleton.c linux/drivers/net/pci-skeleton.c
--- linux-2.4.17-pre5/drivers/net/pci-skeleton.c	Tue Oct 16 21:56:29 2001
+++ linux/drivers/net/pci-skeleton.c	Fri Dec  7 14:53:07 2001
@@ -1980,7 +1980,7 @@
 	name:		MODNAME,
 	id_table:	netdrv_pci_tbl,
 	probe:		netdrv_init_one,
-	remove:		netdrv_remove_one,
+	remove:		__devexit_p(netdrv_remove_one),
 #ifdef CONFIG_PM
 	suspend:	netdrv_suspend,
 	resume:		netdrv_resume,
diff -urN linux-2.4.17-pre5/drivers/net/pcmcia/xircom_cb.c linux/drivers/net/pcmcia/xircom_cb.c
--- linux-2.4.17-pre5/drivers/net/pcmcia/xircom_cb.c	Fri Nov  9 13:41:42 2001
+++ linux/drivers/net/pcmcia/xircom_cb.c	Fri Dec  7 14:53:07 2001
@@ -170,7 +170,7 @@
 	name:		"xircom_cb", 
 	id_table:	xircom_pci_table, 
 	probe:		xircom_probe, 
-	remove:		xircom_remove, 
+	remove:		__devexit_p(xircom_remove), 
 };
 
 
diff -urN linux-2.4.17-pre5/drivers/net/pcmcia/xircom_tulip_cb.c linux/drivers/net/pcmcia/xircom_tulip_cb.c
--- linux-2.4.17-pre5/drivers/net/pcmcia/xircom_tulip_cb.c	Fri Nov  9 13:41:42 2001
+++ linux/drivers/net/pcmcia/xircom_tulip_cb.c	Fri Dec  7 14:53:07 2001
@@ -1748,7 +1748,7 @@
 	name:		DRV_NAME,
 	id_table:	xircom_pci_table,
 	probe:		xircom_init_one,
-	remove:		xircom_remove_one,
+	remove:		__devexit_p(xircom_remove_one),
 #ifdef CONFIG_PM
 	suspend:	xircom_suspend,
 	resume:		xircom_resume
diff -urN linux-2.4.17-pre5/drivers/net/sis900.c linux/drivers/net/sis900.c
--- linux-2.4.17-pre5/drivers/net/sis900.c	Tue Oct  9 15:13:03 2001
+++ linux/drivers/net/sis900.c	Fri Dec  7 14:53:07 2001
@@ -2098,7 +2098,7 @@
 	name:		SIS900_MODULE_NAME,
 	id_table:	sis900_pci_tbl,
 	probe:		sis900_probe,
-	remove:		sis900_remove,
+	remove:		__devexit_p(sis900_remove),
 };
 
 static int __init sis900_init_module(void)
diff -urN linux-2.4.17-pre5/drivers/net/starfire.c linux/drivers/net/starfire.c
--- linux-2.4.17-pre5/drivers/net/starfire.c	Sun Sep 30 12:26:07 2001
+++ linux/drivers/net/starfire.c	Fri Dec  7 14:53:07 2001
@@ -1963,7 +1963,7 @@
 static struct pci_driver starfire_driver = {
 	name:		DRV_NAME,
 	probe:		starfire_init_one,
-	remove:		starfire_remove_one,
+	remove:		__devexit_p(starfire_remove_one),
 	id_table:	starfire_pci_tbl,
 };
 
diff -urN linux-2.4.17-pre5/drivers/net/sundance.c linux/drivers/net/sundance.c
--- linux-2.4.17-pre5/drivers/net/sundance.c	Fri Oct 19 08:32:28 2001
+++ linux/drivers/net/sundance.c	Fri Dec  7 14:53:07 2001
@@ -1474,7 +1474,7 @@
 	name:		DRV_NAME,
 	id_table:	sundance_pci_tbl,
 	probe:		sundance_probe1,
-	remove:		sundance_remove1,
+	remove:		__devexit_p(sundance_remove1),
 };
 
 static int __init sundance_init(void)
diff -urN linux-2.4.17-pre5/drivers/net/sungem.c linux/drivers/net/sungem.c
--- linux-2.4.17-pre5/drivers/net/sungem.c	Fri Dec  7 14:52:27 2001
+++ linux/drivers/net/sungem.c	Fri Dec  7 14:53:07 2001
@@ -2859,7 +2859,7 @@
 	name:		GEM_MODULE_NAME,
 	id_table:	gem_pci_tbl,
 	probe:		gem_init_one,
-	remove:		gem_remove_one,
+	remove:		__devexit_p(gem_remove_one),
 #ifdef CONFIG_PM
 	suspend:	gem_suspend,
 	resume:		gem_resume,
diff -urN linux-2.4.17-pre5/drivers/net/tlan.c linux/drivers/net/tlan.c
--- linux-2.4.17-pre5/drivers/net/tlan.c	Sun Sep 30 12:26:08 2001
+++ linux/drivers/net/tlan.c	Fri Dec  7 14:53:07 2001
@@ -430,7 +430,7 @@
 	name:		"tlan",
 	id_table:	tlan_pci_tbl,
 	probe:		tlan_init_one,
-	remove:		tlan_remove_one,	
+	remove:		__devexit_p(tlan_remove_one),	
 };
 
 static int __init tlan_probe(void)
diff -urN linux-2.4.17-pre5/drivers/net/tokenring/lanstreamer.c linux/drivers/net/tokenring/lanstreamer.c
--- linux-2.4.17-pre5/drivers/net/tokenring/lanstreamer.c	Sat Nov 10 15:38:59 2001
+++ linux/drivers/net/tokenring/lanstreamer.c	Fri Dec  7 14:53:07 2001
@@ -1812,7 +1812,7 @@
   name:       "lanstreamer",
   id_table:   streamer_pci_tbl,
   probe:      streamer_init_one,
-  remove:     streamer_remove_one,
+  remove:     __devexit_p(streamer_remove_one),
 };
 
 static int __init streamer_init_module(void) {
diff -urN linux-2.4.17-pre5/drivers/net/tokenring/olympic.c linux/drivers/net/tokenring/olympic.c
--- linux-2.4.17-pre5/drivers/net/tokenring/olympic.c	Fri Nov  9 13:46:29 2001
+++ linux/drivers/net/tokenring/olympic.c	Fri Dec  7 14:53:07 2001
@@ -1705,7 +1705,7 @@
 	name:		"olympic",
 	id_table:	olympic_pci_tbl,
 	probe:		olympic_probe,
-	remove:		olympic_remove_one
+	remove:		__devexit_p(olympic_remove_one),
 };
 
 static int __init olympic_pci_init(void) 
diff -urN linux-2.4.17-pre5/drivers/net/tulip/tulip_core.c linux/drivers/net/tulip/tulip_core.c
--- linux-2.4.17-pre5/drivers/net/tulip/tulip_core.c	Mon Nov 19 15:19:42 2001
+++ linux/drivers/net/tulip/tulip_core.c	Fri Dec  7 14:53:07 2001
@@ -1889,7 +1889,7 @@
 	name:		DRV_NAME,
 	id_table:	tulip_pci_tbl,
 	probe:		tulip_init_one,
-	remove:		tulip_remove_one,
+	remove:		__devexit_p(tulip_remove_one),
 #ifdef CONFIG_PM
 	suspend:	tulip_suspend,
 	resume:		tulip_resume,
diff -urN linux-2.4.17-pre5/drivers/net/via-rhine.c linux/drivers/net/via-rhine.c
--- linux-2.4.17-pre5/drivers/net/via-rhine.c	Fri Nov  9 13:45:36 2001
+++ linux/drivers/net/via-rhine.c	Fri Dec  7 14:53:07 2001
@@ -1667,7 +1667,7 @@
 	name:		"via-rhine",
 	id_table:	via_rhine_pci_tbl,
 	probe:		via_rhine_init_one,
-	remove:		via_rhine_remove_one,
+	remove:		__devexit_p(via_rhine_remove_one),
 };
 
 
diff -urN linux-2.4.17-pre5/drivers/net/wan/farsync.c linux/drivers/net/wan/farsync.c
--- linux-2.4.17-pre5/drivers/net/wan/farsync.c	Fri Nov  9 13:41:42 2001
+++ linux/drivers/net/wan/farsync.c	Fri Dec  7 14:53:07 2001
@@ -1810,7 +1810,7 @@
         name:           FST_NAME,
         id_table:       fst_pci_dev_id,
         probe:          fst_add_one,
-        remove:         fst_remove_one,
+        remove:         __devexit_p(fst_remove_one),
         suspend:        NULL,
         resume:         NULL,
 };
diff -urN linux-2.4.17-pre5/drivers/net/winbond-840.c linux/drivers/net/winbond-840.c
--- linux-2.4.17-pre5/drivers/net/winbond-840.c	Tue Oct  9 15:13:02 2001
+++ linux/drivers/net/winbond-840.c	Fri Dec  7 14:53:08 2001
@@ -1697,7 +1697,7 @@
 	name:		DRV_NAME,
 	id_table:	w840_pci_tbl,
 	probe:		w840_probe1,
-	remove:		w840_remove1,
+	remove:		__devexit_p(w840_remove1),
 #ifdef CONFIG_PM
 	suspend:	w840_suspend,
 	resume:		w840_resume,
diff -urN linux-2.4.17-pre5/drivers/net/wireless/airo.c linux/drivers/net/wireless/airo.c
--- linux-2.4.17-pre5/drivers/net/wireless/airo.c	Fri Nov  9 13:41:42 2001
+++ linux/drivers/net/wireless/airo.c	Fri Dec  7 14:53:08 2001
@@ -64,7 +64,7 @@
 	name:     "airo",
 	id_table: card_ids,
 	probe:    airo_pci_probe,
-	remove:   airo_pci_remove,
+	remove:   __devexit_p(airo_pci_remove),
 };
 #endif /* CONFIG_PCI */
 
diff -urN linux-2.4.17-pre5/drivers/net/wireless/orinoco_plx.c linux/drivers/net/wireless/orinoco_plx.c
--- linux-2.4.17-pre5/drivers/net/wireless/orinoco_plx.c	Tue Oct  9 15:13:03 2001
+++ linux/drivers/net/wireless/orinoco_plx.c	Fri Dec  7 14:53:08 2001
@@ -279,7 +279,7 @@
 	name:"orinoco_plx",
 	id_table:orinoco_plx_pci_id_table,
 	probe:orinoco_plx_init_one,
-	remove:orinoco_plx_remove_one,
+	remove:__devexit_p(orinoco_plx_remove_one),
 	suspend:0,
 	resume:0
 };
diff -urN linux-2.4.17-pre5/drivers/net/yellowfin.c linux/drivers/net/yellowfin.c
--- linux-2.4.17-pre5/drivers/net/yellowfin.c	Fri Oct 19 08:32:28 2001
+++ linux/drivers/net/yellowfin.c	Fri Dec  7 14:53:08 2001
@@ -1506,7 +1506,7 @@
 	name:		DRV_NAME,
 	id_table:	yellowfin_pci_tbl,
 	probe:		yellowfin_init_one,
-	remove:		yellowfin_remove_one,
+	remove:		__devexit_p(yellowfin_remove_one),
 };
 
 
diff -urN linux-2.4.17-pre5/drivers/parport/ChangeLog linux/drivers/parport/ChangeLog
--- linux-2.4.17-pre5/drivers/parport/ChangeLog	Fri Dec  7 14:52:27 2001
+++ linux/drivers/parport/ChangeLog	Fri Dec  7 14:53:08 2001
@@ -1,3 +1,27 @@
+2001-12-07  Tim Waugh  <twaugh@redhat.com>
+
+	* ieee1284_ops.c (parport_ieee1284_epp_write_addr,
+	parport_ieee1284_epp_read_addr): Actually do something useful.
+
+2001-12-07  Tim Waugh  <twaugh@redhat.com>
+
+	* parport_pc.c (dmaval): Don't use DMA by default.  It seems to be
+	too buggy at the moment.  Use 'dma=auto' to restore the previous
+	behaviour.
+
+2001-12-03  Rich Liu  <Rich.Liu@ite.com.tw>
+
+	* parport_pc.c (sio_ite_8872_probe): ITE8873 is a single-port
+	serial board, not a serial+parallel.
+
+2001-11-30  Neils Kristian Bech Jensen  <nkbj@image.dk>
+
+	* parport_pc.c: Fix compiler warning.
+
+2001-12-07  Tim Waugh  <twaugh@redhat.com>
+
+	* daisy.c (DEBUG): Undefine.
+
 2001-12-06  Tim Waugh  <twaugh@redhat.com>
 
 	* ieee1284_ops.c (parport_ieee1284_ecp_read_data): Mask off
diff -urN linux-2.4.17-pre5/drivers/parport/daisy.c linux/drivers/parport/daisy.c
--- linux-2.4.17-pre5/drivers/parport/daisy.c	Fri Jul 21 14:21:58 2000
+++ linux/drivers/parport/daisy.c	Fri Dec  7 14:53:08 2001
@@ -23,7 +23,7 @@
 #include <linux/delay.h>
 #include <asm/uaccess.h>
 
-#define DEBUG /* undef me for production */
+#undef DEBUG /* undef me for production */
 
 #ifdef DEBUG
 #define DPRINTK(stuff...) printk (stuff)
diff -urN linux-2.4.17-pre5/drivers/parport/ieee1284_ops.c linux/drivers/parport/ieee1284_ops.c
--- linux-2.4.17-pre5/drivers/parport/ieee1284_ops.c	Fri Dec  7 14:52:27 2001
+++ linux/drivers/parport/ieee1284_ops.c	Fri Dec  7 14:53:08 2001
@@ -824,35 +824,40 @@
 					const void *buffer, size_t len,
 					int flags)
 {
-	/* This is untested */
 	unsigned char *bp = (unsigned char *) buffer;
 	size_t ret = 0;
 
+	/* set EPP idle state (just to make sure) with strobe low */
 	parport_frob_control (port,
 			      PARPORT_CONTROL_STROBE |
+			      PARPORT_CONTROL_AUTOFD |
 			      PARPORT_CONTROL_SELECT |
-			      PARPORT_CONTROL_AUTOFD,
+			      PARPORT_CONTROL_INIT,
 			      PARPORT_CONTROL_STROBE |
-			      PARPORT_CONTROL_SELECT);
+			      PARPORT_CONTROL_INIT);
 	port->ops->data_forward (port);
 	for (; len > 0; len--, bp++) {
-		/* Write data and assert nAStrb. */
+		/* Event 56: Write data and set nAStrb low. */
 		parport_write_data (port, *bp);
 		parport_frob_control (port, PARPORT_CONTROL_SELECT,
 				      PARPORT_CONTROL_SELECT);
 
-		if (parport_poll_peripheral (port, PARPORT_STATUS_BUSY,
-					     PARPORT_STATUS_BUSY, 10))
+		/* Event 58: wait for busy (nWait) to go high */
+		if (parport_poll_peripheral (port, PARPORT_STATUS_BUSY, 0, 10))
 			break;
 
+		/* Event 59: set nAStrb high */
 		parport_frob_control (port, PARPORT_CONTROL_SELECT, 0);
 
-		if (parport_poll_peripheral (port, PARPORT_STATUS_BUSY, 0, 5))
+		/* Event 60: wait for busy (nWait) to go low */
+		if (parport_poll_peripheral (port, PARPORT_STATUS_BUSY,
+					     PARPORT_STATUS_BUSY, 5))
 			break;
 
 		ret++;
 	}
 
+	/* Event 61: set strobe (nWrite) high */
 	parport_frob_control (port, PARPORT_CONTROL_STROBE, 0);
 
 	return ret;
@@ -863,28 +868,36 @@
 				       void *buffer, size_t len,
 				       int flags)
 {
-	/* This is untested. */
 	unsigned char *bp = (unsigned char *) buffer;
 	unsigned ret = 0;
 
+	/* Set EPP idle state (just to make sure) with strobe high */
 	parport_frob_control (port,
 			      PARPORT_CONTROL_STROBE |
-			      PARPORT_CONTROL_AUTOFD, 0);
+			      PARPORT_CONTROL_AUTOFD |
+			      PARPORT_CONTROL_SELECT |
+			      PARPORT_CONTROL_INIT,
+			      PARPORT_CONTROL_INIT);
 	port->ops->data_reverse (port);
 	for (; len > 0; len--, bp++) {
-		parport_frob_control (port, PARPORT_CONTROL_SELECT, 0);
+		/* Event 64: set nSelectIn (nAStrb) low */
+		parport_frob_control (port, PARPORT_CONTROL_SELECT,
+				      PARPORT_CONTROL_SELECT);
 
-		/* Event 58 */
-		if (parport_poll_peripheral (port, PARPORT_STATUS_BUSY,
-					     PARPORT_STATUS_BUSY, 10))
+		/* Event 58: wait for Busy to go high */
+		if (parport_wait_peripheral (port, PARPORT_STATUS_BUSY, 0)) {
 			break;
+		}
 
 		*bp = parport_read_data (port);
 
+		/* Event 59: set nSelectIn (nAStrb) high */
 		parport_frob_control (port, PARPORT_CONTROL_SELECT,
 				      PARPORT_CONTROL_SELECT);
 
-		if (parport_poll_peripheral (port, PARPORT_STATUS_BUSY, 0, 5))
+		/* Event 60: wait for Busy to go low */
+		if (parport_poll_peripheral (port, PARPORT_STATUS_BUSY, 
+					     PARPORT_STATUS_BUSY, 5))
 			break;
 
 		ret++;
diff -urN linux-2.4.17-pre5/drivers/parport/parport_pc.c linux/drivers/parport/parport_pc.c
--- linux-2.4.17-pre5/drivers/parport/parport_pc.c	Mon Nov 12 09:44:58 2001
+++ linux/drivers/parport/parport_pc.c	Fri Dec  7 14:53:08 2001
@@ -91,7 +91,9 @@
 } superios[NR_SUPERIOS] __devinitdata = { {0,},};
 
 static int user_specified __devinitdata = 0;
+#if defined(CONFIG_PARPORT_PC_FIFO) || defined(CONFIG_PARPORT_PC_SUPERIO)
 static int verbose_probing;
+#endif
 static int registered_parport;
 
 /* frob_control, but for ECR */
@@ -1780,6 +1782,7 @@
 	return ok;
 }
 
+#ifdef CONFIG_PARPORT_PC_FIFO
 static int __devinit parport_ECP_supported(struct parport *pb)
 {
 	int i;
@@ -1905,6 +1908,7 @@
 
 	return 1;
 }
+#endif
 
 static int __devinit parport_ECPPS2_supported(struct parport *pb)
 {
@@ -2004,7 +2008,9 @@
 
 /* Don't bother probing for modes we know we won't use. */
 static int __devinit parport_PS2_supported(struct parport *pb) { return 0; }
+#ifdef CONFIG_PARPORT_PC_FIFO
 static int __devinit parport_ECP_supported(struct parport *pb) { return 0; }
+#endif
 static int __devinit parport_EPP_supported(struct parport *pb) { return 0; }
 static int __devinit parport_ECPEPP_supported(struct parport *pb){return 0;}
 static int __devinit parport_ECPPS2_supported(struct parport *pb){return 0;}
@@ -2453,9 +2459,8 @@
 		ite8872set = 0x64e00000;
 		break;
 	case 0x6:
-		printk (KERN_INFO "parport_pc: ITE8873 found (1S1P)\n");
-		ite8872set = 0x64a00000;
-		break;
+		printk (KERN_INFO "parport_pc: ITE8873 found (1S)\n");
+		return 0;
 	case 0x8:
 		DPRINTK (KERN_DEBUG "parport_pc: ITE8874 found (2S)\n");
 		return 0;
@@ -3007,7 +3012,7 @@
 static int io[PARPORT_PC_MAX_PORTS+1] = { [0 ... PARPORT_PC_MAX_PORTS] = 0 };
 static int io_hi[PARPORT_PC_MAX_PORTS+1] =
 	{ [0 ... PARPORT_PC_MAX_PORTS] = PARPORT_IOHI_AUTO };
-static int dmaval[PARPORT_PC_MAX_PORTS] = { [0 ... PARPORT_PC_MAX_PORTS-1] = PARPORT_DMA_AUTO };
+static int dmaval[PARPORT_PC_MAX_PORTS] = { [0 ... PARPORT_PC_MAX_PORTS-1] = PARPORT_DMA_NONE };
 static int irqval[PARPORT_PC_MAX_PORTS] = { [0 ... PARPORT_PC_MAX_PORTS-1] = PARPORT_IRQ_PROBEONLY };
 static const char *irq[PARPORT_PC_MAX_PORTS] = { NULL, };
 static const char *dma[PARPORT_PC_MAX_PORTS] = { NULL, };
@@ -3024,8 +3029,10 @@
 MODULE_PARM(irq, "1-" __MODULE_STRING(PARPORT_PC_MAX_PORTS) "s");
 MODULE_PARM_DESC(dma, "DMA channel");
 MODULE_PARM(dma, "1-" __MODULE_STRING(PARPORT_PC_MAX_PORTS) "s");
-MODULE_PARM(verbose_probing, "i");
+#if defined(CONFIG_PARPORT_PC_FIFO) || defined(CONFIG_PARPORT_PC_SUPERIO)
 MODULE_PARM_DESC(verbose_probing, "Log chit-chat during initialisation");
+MODULE_PARM(verbose_probing, "i");
+#endif
 
 int init_module(void)
 {	
diff -urN linux-2.4.17-pre5/drivers/parport/parport_serial.c linux/drivers/parport/parport_serial.c
--- linux-2.4.17-pre5/drivers/parport/parport_serial.c	Fri Nov  9 14:30:55 2001
+++ linux/drivers/parport/parport_serial.c	Fri Dec  7 14:53:08 2001
@@ -331,7 +331,7 @@
 	name:		"parport_serial",
 	id_table:	parport_serial_pci_tbl,
 	probe:		parport_serial_pci_probe,
-	remove:		parport_serial_pci_remove,
+	remove:		__devexit_p(parport_serial_pci_remove),
 };
 
 
diff -urN linux-2.4.17-pre5/drivers/pcmcia/pci_socket.c linux/drivers/pcmcia/pci_socket.c
--- linux-2.4.17-pre5/drivers/pcmcia/pci_socket.c	Fri Nov  9 13:41:42 2001
+++ linux/drivers/pcmcia/pci_socket.c	Fri Dec  7 14:53:08 2001
@@ -249,7 +249,7 @@
 	name:		"cardbus",
 	id_table:	cardbus_table,
 	probe:		cardbus_probe,
-	remove:		cardbus_remove,
+	remove:		__devexit_p(cardbus_remove),
 	suspend:	cardbus_suspend,
 	resume:		cardbus_resume,
 };
diff -urN linux-2.4.17-pre5/drivers/pcmcia/rsrc_mgr.c linux/drivers/pcmcia/rsrc_mgr.c
--- linux-2.4.17-pre5/drivers/pcmcia/rsrc_mgr.c	Fri Dec  7 14:52:27 2001
+++ linux/drivers/pcmcia/rsrc_mgr.c	Fri Dec  7 14:53:08 2001
@@ -107,17 +107,21 @@
 static struct resource *resource_parent(unsigned long b, unsigned long n,
 					int flags, struct pci_dev *dev)
 {
-	struct resource res;
+#ifdef CONFIG_PCI
+	struct resource res, *pr;
 
-	if (dev == NULL) {
-		if (flags & IORESOURCE_MEM)
-			return &iomem_resource;
-		return &ioport_resource;
+	if (dev != NULL) {
+		res.start = b;
+		res.end = b + n - 1;
+		res.flags = flags;
+		pr = pci_find_parent_resource(dev, &res);
+		if (pr)
+			return pr;
 	}
-	res.start = b;
-	res.end = b + n - 1;
-	res.flags = flags;
-	return pci_find_parent_resource(dev, &res);
+#endif /* CONFIG_PCI */
+	if (flags & IORESOURCE_MEM)
+		return &iomem_resource;
+	return &ioport_resource;
 }
 
 static inline int check_io_resource(unsigned long b, unsigned long n,
diff -urN linux-2.4.17-pre5/drivers/scsi/NCR5380.c linux/drivers/scsi/NCR5380.c
--- linux-2.4.17-pre5/drivers/scsi/NCR5380.c	Fri Dec  7 14:52:27 2001
+++ linux/drivers/scsi/NCR5380.c	Fri Dec  7 14:53:08 2001
@@ -83,8 +83,6 @@
  *     basically, transfer size needs to be reduced by one 
  *     and the last byte read as is done with PSEUDO_DMA.
  * 
- * 3.  Test USLEEP code 
- *
  * 4.  Test SCSI-II tagged queueing (I have no devices which support 
  *      tagged queueing)
  *
@@ -110,6 +108,12 @@
 #define READ_OVERRUNS
 #endif
 
+#ifdef BOARD_REQUIRES_NO_DELAY
+#define io_recovery_delay(x)
+#else
+#define io_recovery_delay(x)	udelay(x)
+#endif
+
 /*
  * Design
  * Issues :
@@ -192,9 +196,8 @@
  * phase goes through the various phases as instructed by the target.
  * if the target goes into MSG IN and sends a DISCONNECT message,
  * the command structure is placed into the per instance disconnected
- * queue, and NCR5380_main tries to find more work.  If USLEEP
- * was defined, and the target is idle for too long, the system
- * will try to sleep.
+ * queue, and NCR5380_main tries to find more work.  If the target is 
+ * idle for too long, the system will try to sleep.
  *
  * If a command has disconnected, eventually an interrupt will trigger,
  * calling NCR5380_intr()  which will in turn call NCR5380_reselect
@@ -244,21 +247,14 @@
  *      rely on phase mismatch and EOP interrupts to determine end 
  *      of phase.
  *
- * SCSI2 - if defined, SCSI-2 tagged queuing is used where possible
- *
  * UNSAFE - leave interrupts enabled during pseudo-DMA transfers.  You
  *          only really want to use this if you're having a problem with
  *          dropped characters during high speed communications, and even
  *          then, you're going to be better off twiddling with transfersize
  *          in the high level code.
  *
- * USLEEP - if defined, on devices that aren't disconnecting from the 
- *      bus, we will go to sleep so that the CPU can get real work done 
- *      when we run a command that won't complete immediately.
- *
- * Defaults for these will be provided if USLEEP is defined, although
- * the user may want to adjust these to allocate CPU resources to 
- * the SCSI driver or "real" code.
+ * Defaults for these will be provided although the user may want to adjust 
+ * these to allocate CPU resources to the SCSI driver or "real" code.
  * 
  * USLEEP_SLEEP - amount of time, in jiffies, to sleep
  *
@@ -322,18 +318,13 @@
 static void do_reset(struct Scsi_Host *host);
 static struct Scsi_Host *first_instance = NULL;
 static Scsi_Host_Template *the_template = NULL;
-
-#ifdef USLEEP
-struct timer_list usleep_timer;
-#endif
+static struct timer_list usleep_timer;
 
 /*
- * Function : void initialize_SCp(Scsi_Cmnd *cmd)
- *
- * Purpose : initialize the saved data pointers for cmd to point to the 
- *      start of the buffer.
+ *	initialize_SCp		-	init the scsi pointer field
+ *	@cmd: command block to set up
  *
- * Inputs : cmd - Scsi_Cmnd structure to have pointers reset.
+ *	Set up the internal fields in the SCSI command.
  */
 
 static __inline__ void initialize_SCp(Scsi_Cmnd * cmd)
@@ -362,46 +353,49 @@
 static struct {
 	unsigned char mask;
 	const char *name;
-} signals[] = { {
-
-SR_DBP, "PARITY"}, {
-SR_RST, "RST"}, {
-SR_BSY, "BSY"}, {
-SR_REQ, "REQ"}, {
-SR_MSG, "MSG"}, {
-SR_CD, "CD"}, {
-SR_IO, "IO"}, {
-SR_SEL, "SEL"}, {
-0, NULL}
-}, basrs[] = { {
-BASR_ATN, "ATN"}, {
-BASR_ACK, "ACK"}, {
-0, NULL}
-}, icrs[] = { {
-ICR_ASSERT_RST, "ASSERT RST"}, {
-ICR_ASSERT_ACK, "ASSERT ACK"}, {
-ICR_ASSERT_BSY, "ASSERT BSY"}, {
-ICR_ASSERT_SEL, "ASSERT SEL"}, {
-ICR_ASSERT_ATN, "ASSERT ATN"}, {
-ICR_ASSERT_DATA, "ASSERT DATA"}, {
-0, NULL}
-}, mrs[] = { {
-MR_BLOCK_DMA_MODE, "MODE BLOCK DMA"}, {
-MR_TARGET, "MODE TARGET"}, {
-MR_ENABLE_PAR_CHECK, "MODE PARITY CHECK"}, {
-MR_ENABLE_PAR_INTR, "MODE PARITY INTR"}, {
-MR_MONITOR_BSY, "MODE MONITOR BSY"}, {
-MR_DMA_MODE, "MODE DMA"}, {
-MR_ARBITRATE, "MODE ARBITRATION"}, {
-0, NULL}
+} signals[] = { 
+	{SR_DBP, "PARITY"}, 
+	{SR_RST, "RST"}, 
+	{SR_BSY, "BSY"}, 
+	{SR_REQ, "REQ"}, 
+	{SR_MSG, "MSG"}, 
+	{SR_CD, "CD"}, 
+	{SR_IO, "IO"}, 
+	{SR_SEL, "SEL"}, 
+	{0, NULL}
+}, 
+basrs[] = {
+	{BASR_ATN, "ATN"}, 
+	{BASR_ACK, "ACK"}, 
+	{0, NULL}
+}, 
+icrs[] = { 
+	{ICR_ASSERT_RST, "ASSERT RST"}, 
+	{ICR_ASSERT_ACK, "ASSERT ACK"}, 
+	{ICR_ASSERT_BSY, "ASSERT BSY"}, 
+	{ICR_ASSERT_SEL, "ASSERT SEL"}, 
+	{ICR_ASSERT_ATN, "ASSERT ATN"}, 
+	{ICR_ASSERT_DATA, "ASSERT DATA"}, 
+	{0, NULL}
+}, 
+mrs[] = { 
+	{MR_BLOCK_DMA_MODE, "MODE BLOCK DMA"}, 
+	{MR_TARGET, "MODE TARGET"}, 
+	{MR_ENABLE_PAR_CHECK, "MODE PARITY CHECK"}, 
+	{MR_ENABLE_PAR_INTR, "MODE PARITY INTR"}, 
+	{MR_MONITOR_BSY, "MODE MONITOR BSY"}, 
+	{MR_DMA_MODE, "MODE DMA"}, 
+	{MR_ARBITRATE, "MODE ARBITRATION"}, 
+	{0, NULL}
 };
 
-/*
- * Function : void NCR5380_print(struct Scsi_Host *instance)
+/**
+ *	NCR5380_print	-	print scsi bus signals
+ *	@instance:	adapter state to dump
  *
- * Purpose : print the SCSI bus signals for debugging purposes
+ *	Print the SCSI bus signals for debugging purposes
  *
- * Input : instance - which NCR5380
+ *	Locks: none
  */
 
 static void NCR5380_print(struct Scsi_Host *instance)
@@ -410,6 +404,7 @@
 	unsigned long flags;
 	unsigned char status, data, basr, mr, icr, i;
 	NCR5380_setup(instance);
+	/* FIXME - this needs proper locking */
 	save_flags(flags);
 	cli();
 	data = NCR5380_read(CURRENT_SCSI_DATA_REG);
@@ -441,23 +436,22 @@
 	unsigned char value;
 	const char *name;
 } phases[] = {
-
-	{
-	PHASE_DATAOUT, "DATAOUT"}, {
-	PHASE_DATAIN, "DATAIN"}, {
-	PHASE_CMDOUT, "CMDOUT"}, {
-	PHASE_STATIN, "STATIN"}, {
-	PHASE_MSGOUT, "MSGOUT"}, {
-	PHASE_MSGIN, "MSGIN"}, {
-	PHASE_UNKNOWN, "UNKNOWN"}
+	{PHASE_DATAOUT, "DATAOUT"}, 
+	{PHASE_DATAIN, "DATAIN"}, 
+	{PHASE_CMDOUT, "CMDOUT"}, 
+	{PHASE_STATIN, "STATIN"}, 
+	{PHASE_MSGOUT, "MSGOUT"}, 
+	{PHASE_MSGIN, "MSGIN"}, 
+	{PHASE_UNKNOWN, "UNKNOWN"}
 };
 
 /* 
- * Function : void NCR5380_print_phase(struct Scsi_Host *instance)
+ *	NCR5380_print_phase	-	show SCSI phase
+ *	@instance: adapter to dump
  *
- * Purpose : print the current SCSI phase for debugging purposes
+ * 	Print the current SCSI phase for debugging purposes
  *
- * Input : instance - which NCR5380
+ *	Locks: none
  */
 
 static void NCR5380_print_phase(struct Scsi_Host *instance)
@@ -496,7 +490,7 @@
  * conditions are possible.
  */
 
-static volatile int main_running = 0;
+static unsigned long main_running = 0;
 
 /* 
  * Function : run_main(void)
@@ -510,14 +504,10 @@
 
 static __inline__ void run_main(void)
 {
-	if (!main_running) {
-		main_running = 1;
+	if (!test_and_set_bit(0, &main_running))
 		NCR5380_main();
-	}
 }
 
-#ifdef USLEEP
-
 /*
  * These need tweaking, and would probably work best as per-device 
  * flags initialized differently for disk, tape, cd, etc devices.
@@ -587,17 +577,15 @@
 
 /*
  * Assumes instance->time_expires has been set in higher level code.
+ *
+ * Locks: Caller must hold io_request_lock
  */
 
 static int NCR5380_set_timer(struct Scsi_Host *instance)
 {
-	unsigned long flags;
 	struct Scsi_Host *tmp, **prev;
 
-	save_flags(flags);
-	cli();
 	if (((struct NCR5380_hostdata *) (instance->hostdata))->next_timer) {
-		restore_flags(flags);
 		return -1;
 	}
 	for (prev = &expires_first, tmp = expires_first; tmp; prev = &(((struct NCR5380_hostdata *) tmp->hostdata)->next_timer), tmp = ((struct NCR5380_hostdata *) tmp->hostdata)->next_timer)
@@ -608,17 +596,28 @@
 	*prev = instance;
 
 	mod_timer(&usleep_timer, ((struct NCR5380_hostdata *) expires_first->hostdata)->time_expires);
-	restore_flags(flags);
 	return 0;
 }
 
-/* Doing something about unwanted reentrancy here might be useful */
-void NCR5380_timer_fn(unsigned long surplus_to_requirements)
+/**
+ *	NCR5380_timer_fn	-	handle polled timeouts
+ *	@unused: unused
+ *
+ *	Walk the list of controllers, find which controllers have exceeded
+ *	their expiry timeout and then schedule the processing co-routine to
+ *	do the real work.
+ *
+ *	Doing something about unwanted reentrancy here might be useful 
+ *
+ *	Locks: disables irqs, takes and frees io_request_lock
+ */
+ 
+void NCR5380_timer_fn(unsigned long unused)
 {
-	unsigned long flags;
 	struct Scsi_Host *instance;
-	save_flags(flags);
-	cli();
+
+	spin_lock_irq(&io_request_lock);
+	
 	for (; expires_first && time_before_eq(((struct NCR5380_hostdata *) expires_first->hostdata)->time_expires, jiffies);) {
 		instance = ((struct NCR5380_hostdata *) expires_first->hostdata)->next_timer;
 		((struct NCR5380_hostdata *) expires_first->hostdata)->next_timer = NULL;
@@ -631,51 +630,56 @@
 		usleep_timer.expires = ((struct NCR5380_hostdata *) expires_first->hostdata)->time_expires;
 		add_timer(&usleep_timer);
 	}
-	restore_flags(flags);
-
-	spin_lock_irqsave(&io_request_lock, flags);
 	run_main();
-	spin_unlock_irqrestore(&io_request_lock, flags);
+	spin_unlock_irq(&io_request_lock);
 }
-#endif				/* def USLEEP */
 
+/**
+ *	NCR5380_all_init	-	global setup
+ *
+ *	Set up the global values and timers needed by the NCR5380 driver
+ */
+ 
 static inline void NCR5380_all_init(void)
 {
 	static int done = 0;
 	if (!done) {
-#if (NDEBUG & NDEBUG_INIT)
-		printk("scsi : NCR5380_all_init()\n");
-#endif
+		dprintk(NDEBUG_INIT, ("scsi : NCR5380_all_init()\n"));
 		done = 1;
-#ifdef USLEEP
 		init_timer(&usleep_timer);
 		usleep_timer.function = NCR5380_timer_fn;
-#endif
 	}
 }
 
-#ifdef AUTOPROBE_IRQ
-/*
- * Function : int NCR5380_probe_irq (struct Scsi_Host *instance, int possible)
- * 
- * Purpose : autoprobe for the IRQ line used by the NCR5380.  
- *
- * Inputs : instance - pointer to this instance of the NCR5380 driver,
- *          possible - bitmask of permissible interrupts.
- *
- * Returns : number of the IRQ selected, IRQ_NONE if no interrupt fired.
- * 
- * XXX no effort is made to deal with spurious interrupts. 
- */
-
 
 static int probe_irq __initdata = 0;
 
+/**
+ *	probe_intr	-	helper for IRQ autoprobe
+ *	@irq: interrupt number
+ *	@dev_id: unused
+ *	@regs: unused
+ *
+ *	Set a flag to indicate the IRQ in question was received. This is
+ *	used by the IRQ probe code.
+ */
+ 
 static void __init probe_intr(int irq, void *dev_id, struct pt_regs *regs)
 {
 	probe_irq = irq;
 }
 
+/**
+ *	NCR5380_probe_irq	-	find the IRQ of an NCR5380
+ *	@instance: NCR5380 controller
+ *	@possible: bitmask of ISA IRQ lines
+ *
+ *	Autoprobe for the IRQ line used by the NCR5380 by triggering an IRQ
+ *	and then looking to see what interrupt actually turned up.
+ *
+ *	Locks: none, irqs must be enabled on entry
+ */
+
 static int __init NCR5380_probe_irq(struct Scsi_Host *instance, int possible)
 {
 	NCR5380_local_declare();
@@ -685,22 +689,21 @@
 	NCR5380_setup(instance);
 
 	for (trying_irqs = i = 0, mask = 1; i < 16; ++i, mask <<= 1)
-		if ((mask & possible) && (request_irq(i, &probe_intr, SA_INTERRUPT, "NCR-probe", NULL)
-					  == 0))
+		if ((mask & possible) && (request_irq(i, &probe_intr, SA_INTERRUPT, "NCR-probe", NULL) == 0))
 			trying_irqs |= mask;
 
 	timeout = jiffies + (250 * HZ / 1000);
 	probe_irq = IRQ_NONE;
 
-/*
- * A interrupt is triggered whenever BSY = false, SEL = true
- * and a bit set in the SELECT_ENABLE_REG is asserted on the 
- * SCSI bus.
- *
- * Note that the bus is only driven when the phase control signals
- * (I/O, C/D, and MSG) match those in the TCR, so we must reset that
- * to zero.
- */
+	/*
+	 * A interrupt is triggered whenever BSY = false, SEL = true
+	 * and a bit set in the SELECT_ENABLE_REG is asserted on the 
+	 * SCSI bus.
+	 *
+	 * Note that the bus is only driven when the phase control signals
+	 * (I/O, C/D, and MSG) match those in the TCR, so we must reset that
+	 * to zero.
+	 */
 
 	NCR5380_write(TARGET_COMMAND_REG, 0);
 	NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
@@ -719,15 +722,16 @@
 
 	return probe_irq;
 }
-#endif				/* AUTOPROBE_IRQ */
 
-/*
- * Function : void NCR58380_print_options (struct Scsi_Host *instance)
+/**
+ *	NCR58380_print_options	-	show options
+ *	@instance: unused for now
+ *
+ *	Called by probe code indicating the NCR5380 driver options that 
+ *	were selected. At some point this will switch to runtime options
+ *	read from the adapter in question
  *
- * Purpose : called by probe code indicating the NCR5380 driver
- *           options that were selected.
- *
- * Inputs : instance, pointer to this instance.  Unused.
+ *	Locks: none
  */
 
 static void __init NCR5380_print_options(struct Scsi_Host *instance)
@@ -754,29 +758,25 @@
 #ifdef PSEUDO_DMA
 	       " PSEUDO DMA"
 #endif
-#ifdef SCSI2
-	       " SCSI-2"
-#endif
 #ifdef UNSAFE
 	       " UNSAFE "
 #endif
 	    );
-#ifdef USLEEP
 	printk(" USLEEP, USLEEP_POLL=%d USLEEP_SLEEP=%d", USLEEP_POLL, USLEEP_SLEEP);
-#endif
 	printk(" generic release=%d", NCR5380_PUBLIC_RELEASE);
 	if (((struct NCR5380_hostdata *) instance->hostdata)->flags & FLAG_NCR53C400) {
 		printk(" ncr53c400 release=%d", NCR53C400_PUBLIC_RELEASE);
 	}
 }
 
-/*
- * Function : void NCR5380_print_status (struct Scsi_Host *instance)
+/**
+ *	NCR5380_print_status 	-	dump controller info
+ *	@instance: controller to dump
  *
- * Purpose : print commands in the various queues, called from
- *      NCR5380_abort and NCR5380_debug to aid debugging.
+ *	Print commands in the various queues, called from NCR5380_abort 
+ *	and NCR5380_debug to aid debugging.
  *
- * Inputs : instance, pointer to this instance.  
+ *	Locks: called functions disable irqs, missing queue lock in proc call
  */
 
 static void NCR5380_print_status(struct Scsi_Host *instance)
@@ -787,10 +787,8 @@
 
 	printk("NCR5380 : coroutine is%s running.\n", main_running ? "" : "n't");
 
-#ifdef NDEBUG
-	NCR5380_print(instance);
-	NCR5380_print_phase(instance);
-#endif
+	NCR5380_dprint(NDEBUG_ANY, instance);
+	NCR5380_dprint_phase(NDEBUG_ANY, instance);
 
 	len = NCR5380_proc_info(pr_bfr, &start, 0, sizeof(pr_bfr), instance->host_no, 0);
 	pr_bfr[len] = 0;
@@ -825,7 +823,6 @@
 #endif
 int NCR5380_proc_info(char *buffer, char **start, off_t offset, int length, int hostno, int inout)
 {
-	unsigned long flags;
 	char *pos = buffer;
 	struct Scsi_Host *instance;
 	struct NCR5380_hostdata *hostdata;
@@ -874,8 +871,7 @@
 #ifdef PAS16_PUBLIC_RELEASE
 	SPRINTF("Highwater I/O busy_spin_counts -- write: %d  read: %d\n", pas_wmaxi, pas_maxi);
 #endif
-	save_flags(flags);
-	cli();
+	spin_lock_irq(&io_request_lock);
 	SPRINTF("NCR5380 : coroutine is%s running.\n", main_running ? "" : "n't");
 	if (!hostdata->connected)
 		SPRINTF("scsi%d: no currently connected command\n", instance->host_no);
@@ -889,7 +885,8 @@
 	for (ptr = (Scsi_Cmnd *) hostdata->disconnected_queue; ptr; ptr = (Scsi_Cmnd *) ptr->host_scribble)
 		pos = lprint_Scsi_Cmnd(ptr, pos, buffer, length);
 
-	restore_flags(flags);
+	spin_unlock_irq(&io_request_lock);
+	
 	*start = buffer;
 	if (pos - buffer < offset)
 		return 0;
@@ -926,17 +923,18 @@
 }
 
 
-/* 
- * Function : void NCR5380_init (struct Scsi_Host *instance, flags)
+/**
+ *	NCR5380_init	-	initialise an NCR5380
+ *	@instance: adapter to configure
+ *	@flags: control flags
  *
- * Purpose : initializes *instance and corresponding 5380 chip,
+ *	Initializes *instance and corresponding 5380 chip,
  *      with flags OR'd into the initial flags value.
  *
- * Inputs : instance - instantiation of the 5380 driver.  
- *
- * Notes : I assume that the host, hostno, and id bits have been
+ *	Notes : I assume that the host, hostno, and id bits have been
  *      set correctly.  I don't care about the irq and other fields. 
- * 
+ *
+ *	Locks: interrupts must be enabled when we are called 
  */
 
 static void __init NCR5380_init(struct Scsi_Host *instance, int flags)
@@ -946,6 +944,8 @@
 	unsigned long timeout;
 	struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *) instance->hostdata;
 
+	if(in_interrupt())
+		printk(KERN_ERR "NCR5380_init called with interrupts off!\n");
 	/* 
 	 * On NCR53C400 boards, NCR5380 registers are mapped 8 past 
 	 * the base address.
@@ -957,7 +957,6 @@
 #endif
 
 	NCR5380_setup(instance);
-
 	NCR5380_all_init();
 
 	hostdata->aborted = 0;
@@ -996,15 +995,13 @@
 		the_template = instance->hostt;
 		first_instance = instance;
 	}
-#ifdef USLEEP
 	hostdata->time_expires = 0;
 	hostdata->next_timer = NULL;
-#endif
 
 #ifndef AUTOSENSE
 	if ((instance->cmd_per_lun > 1) || instance->can_queue > 1)
-		)
-		    printk("scsi%d : WARNING : support for multiple outstanding commands enabled\n" "         without AUTOSENSE option, contingent allegiance conditions may\n" "         be incorrectly cleared.\n", instance->host_no);
+		    printk(KERN_WARNING "scsi%d : WARNING : support for multiple outstanding commands enabled\n" "         without AUTOSENSE option, contingent allegiance conditions may\n"
+		    	   "         be incorrectly cleared.\n", instance->host_no);
 #endif				/* def AUTOSENSE */
 
 	NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
@@ -1053,22 +1050,17 @@
 	}
 }
 
-/* 
- * Function : int NCR5380_queue_command (Scsi_Cmnd *cmd, 
- *      void (*done)(Scsi_Cmnd *)) 
- *
- * Purpose :  enqueues a SCSI command
+/**
+ *	NCR5380_queue_command 		-	queue a command
+ *	@cmd: SCSI command
+ *	@done: completion handler
  *
- * Inputs : cmd - SCSI command, done - function called on completion, with
- *      a pointer to the command descriptor.
- * 
- * Returns : 0
- *
- * Side effects : 
  *      cmd is added to the per instance issue_queue, with minor 
  *      twiddling done to the host specific fields of cmd.  If the 
  *      main coroutine is not running, it is restarted.
  *
+ *	Locks: io_request lock held by caller. Called functions drop and
+ *	retake this lock. Called functions take dma lock.
  */
 
 /* Only make static if a wrapper function is used */
@@ -1092,15 +1084,7 @@
 #endif				/* (NDEBUG & NDEBUG_NO_WRITE) */
 
 #ifdef NCR5380_STATS
-#if 0
-	if (!hostdata->connected && !hostdata->issue_queue && !hostdata->disconnected_queue) {
-		hostdata->timebase = jiffies;
-	}
-#endif
-#ifdef NCR5380_STAT_LIMIT
-	if (cmd->request_bufflen > NCR5380_STAT_LIMIT)
-#endif
-		switch (cmd->cmnd[0]) {
+	switch (cmd->cmnd[0]) {
 		case WRITE:
 		case WRITE_6:
 		case WRITE_10:
@@ -1115,7 +1099,7 @@
 			hostdata->bytes_read[cmd->target] += cmd->request_bufflen;
 			hostdata->pendingr++;
 			break;
-		}
+	}
 #endif
 
 	/* 
@@ -1125,10 +1109,8 @@
 
 	cmd->host_scribble = NULL;
 	cmd->scsi_done = done;
-
 	cmd->result = 0;
 
-
 	/* 
 	 * Insert the cmd into the issue queue. Note that REQUEST SENSE 
 	 * commands are added to the head of the queue since any command will
@@ -1145,25 +1127,24 @@
 		LIST(cmd, tmp);
 		tmp->host_scribble = (unsigned char *) cmd;
 	}
-#if (NDEBUG & NDEBUG_QUEUES)
-	printk("scsi%d : command added to %s of queue\n", instance->host_no, (cmd->cmnd[0] == REQUEST_SENSE) ? "head" : "tail");
-#endif
+	dprintk(NDEBUG_QUEUES, ("scsi%d : command added to %s of queue\n", instance->host_no, (cmd->cmnd[0] == REQUEST_SENSE) ? "head" : "tail"));
 
-/* Run the coroutine if it isn't already running. */
+	/* Run the coroutine if it isn't already running. */
 	run_main();
 	return 0;
 }
 
-/*
- * Function : NCR5380_main (void) 
+/**
+ *	NCR5380_main	-	NCR state machines
  *
- * Purpose : NCR5380_main is a coroutine that runs as long as more work can 
+ *	NCR5380_main is a coroutine that runs as long as more work can 
  *      be done on the NCR5380 host adapters in a system.  Both 
  *      NCR5380_queue_command() and NCR5380_intr() will try to start it 
  *      in case it is not running.
  * 
- * NOTE : NCR5380_main exits with interrupts *disabled*, the caller should 
- *  reenable them.  This prevents reentrancy and kernel stack overflow.
+ *	Locks; The caller must hold the io_request_lock. The lock will still be
+ *	held on return but may be dropped while running. Called functions take
+ *	the DMA lock.
  */
 
 static void NCR5380_main(void) {
@@ -1171,7 +1152,6 @@
 	struct Scsi_Host *instance;
 	struct NCR5380_hostdata *hostdata;
 	int done;
-	unsigned long flags;
 
 	/*
 	 * We run (with interrupts disabled) until we're sure that none of 
@@ -1185,40 +1165,22 @@
 	 * this should prevent any race conditions.
 	 */
 
-	 spin_unlock_irq(&io_request_lock);
-
-	 save_flags(flags);
-
 	do {
-		cli();		/* Freeze request queues */
+		/* Lock held here */
 		done = 1;
 		for (instance = first_instance; instance && instance->hostt == the_template; instance = instance->next) {
 			hostdata = (struct NCR5380_hostdata *) instance->hostdata;
-			cli();
-#ifdef USLEEP
+			/* Lock held here */
 			if (!hostdata->connected && !hostdata->selecting) {
-#else
-			if (!hostdata->connected) {
-#endif
-#if (NDEBUG & NDEBUG_MAIN)
-				printk("scsi%d : not connected\n", instance->host_no);
-#endif
+				dprintk(NDEBUG_MAIN, ("scsi%d : not connected\n", instance->host_no));
 				/*
 				 * Search through the issue_queue for a command destined
 				 * for a target that's not busy.
 				 */
-#if (NDEBUG & NDEBUG_LISTS)
-				for (tmp = (Scsi_Cmnd *) hostdata->issue_queue, prev = NULL; tmp && (tmp != prev); prev = tmp, tmp = (Scsi_Cmnd *) tmp->host_scribble);
-				/*printk("%p  ", tmp); */
-				if ((tmp == prev) && tmp)
-					printk(" LOOP\n");	/* else printk("\n"); */
-#endif
-				for (tmp = (Scsi_Cmnd *) hostdata->issue_queue, prev = NULL; tmp; prev = tmp, tmp = (Scsi_Cmnd *) tmp->host_scribble) {
-
-#if (NDEBUG & NDEBUG_LISTS)
+				for (tmp = (Scsi_Cmnd *) hostdata->issue_queue, prev = NULL; tmp; prev = tmp, tmp = (Scsi_Cmnd *) tmp->host_scribble) 
+				{
 					if (prev != tmp)
-						printk("MAIN tmp=%p   target=%d   busy=%d lun=%d\n", tmp, tmp->target, hostdata->busy[tmp->target], tmp->lun);
-#endif
+						dprintk(NDEBUG_LISTS, ("MAIN tmp=%p   target=%d   busy=%d lun=%d\n", tmp, tmp->target, hostdata->busy[tmp->target], tmp->lun));
 					/*  When we find one, remove it from the issue queue. */
 					if (!(hostdata->busy[tmp->target] & (1 << tmp->lun))) {
 						if (prev) {
@@ -1230,8 +1192,6 @@
 						}
 						tmp->host_scribble = NULL;
 
-						/* reenable interrupts after finding one */
-						restore_flags(flags);
 
 						/* 
 						 * Attempt to establish an I_T_L nexus here. 
@@ -1239,9 +1199,7 @@
 						 * On failure, we must add the command back to the
 						 *   issue queue so we can keep trying. 
 						 */
-#if (NDEBUG & (NDEBUG_MAIN | NDEBUG_QUEUES))
-						printk("scsi%d : main() : command for target %d lun %d removed from issue_queue\n", instance->host_no, tmp->target, tmp->lun);
-#endif
+						dprintk(NDEBUG_MAIN|NDEBUG_QUEUES, ("scsi%d : main() : command for target %d lun %d removed from issue_queue\n", instance->host_no, tmp->target, tmp->lun));
 
 						/*
 						 * A successful selection is defined as one that 
@@ -1253,10 +1211,8 @@
 						 * and see if we can do an information transfer,
 						 * with failures we will restart.
 						 */
-#ifdef USLEEP
-						hostdata->selecting = 0;	/* RvC: have to preset this
-										   to indicate a new command is being performed */
-#endif
+						hostdata->selecting = 0;	
+						/* RvC: have to preset this to indicate a new command is being performed */
 
 						if (!NCR5380_select(instance, tmp,
 								    /* 
@@ -1268,23 +1224,20 @@
 								    (tmp->cmnd[0] == REQUEST_SENSE) ? TAG_NONE : TAG_NEXT)) {
 							break;
 						} else {
-							cli();
 							LIST(tmp, hostdata->issue_queue);
-							tmp->host_scribble = (unsigned char *)
-							    hostdata->issue_queue;
+							tmp->host_scribble = (unsigned char *) hostdata->issue_queue;
 							hostdata->issue_queue = tmp;
 							done = 0;
-							restore_flags(flags);
-#if (NDEBUG & (NDEBUG_MAIN | NDEBUG_QUEUES))
-							printk("scsi%d : main(): select() failed, returned to issue_queue\n", instance->host_no);
-#endif
+							dprintk(NDEBUG_MAIN|NDEBUG_QUEUES, ("scsi%d : main(): select() failed, returned to issue_queue\n", instance->host_no));
 						}
+						/* lock held here still */
 					}	/* if target/lun is not busy */
 				}	/* for */
+				/* exited locked */
 			}	/* if (!hostdata->connected) */
-#ifdef USLEEP
 			if (hostdata->selecting) {
 				tmp = (Scsi_Cmnd *) hostdata->selecting;
+				/* Selection will drop and retake the lock */
 				if (!NCR5380_select(instance, tmp, (tmp->cmnd[0] == REQUEST_SENSE) ? TAG_NONE : TAG_NEXT)) {
 					/* Ok ?? */
 				} else {
@@ -1293,56 +1246,46 @@
 					   do not respond to commands immediately
 					   after a scan */
 					printk(KERN_DEBUG "scsi%d: device %d did not respond in time\n", instance->host_no, tmp->target);
-					cli();
+					//spin_lock_irq(&io_request_lock);
 					LIST(tmp, hostdata->issue_queue);
 					tmp->host_scribble = (unsigned char *) hostdata->issue_queue;
 					hostdata->issue_queue = tmp;
-					restore_flags(flags);
+					//spin_unlock_irq(&io_request_lock);
 
 					hostdata->time_expires = jiffies + USLEEP_WAITLONG;
 					NCR5380_set_timer(instance);
 				}
 			}	/* if hostdata->selecting */
-#endif
 			if (hostdata->connected
 #ifdef REAL_DMA
 			    && !hostdata->dmalen
 #endif
-#ifdef USLEEP
 			    && (!hostdata->time_expires || time_before_eq(hostdata->time_expires, jiffies))
-#endif
 			    ) {
-				restore_flags(flags);
-#if (NDEBUG & NDEBUG_MAIN)
-				printk("scsi%d : main() : performing information transfer\n", instance->host_no);
-#endif
+				dprintk(NDEBUG_MAIN, ("scsi%d : main() : performing information transfer\n", instance->host_no));
 				NCR5380_information_transfer(instance);
-#if (NDEBUG & NDEBUG_MAIN)
-				printk("scsi%d : main() : done set false\n", instance->host_no);
-#endif
+				dprintk(NDEBUG_MAIN, ("scsi%d : main() : done set false\n", instance->host_no));
 				done = 0;
 			} else
 				break;
 		}		/* for instance */
 	} while (!done);
-	spin_lock_irq(&io_request_lock);
-	/*    cli(); */
-	main_running = 0;
+	/* Exit lock held */
+	clear_bit(0, &main_running);
 }
 
 #ifndef DONT_USE_INTR
 #include <linux/blk.h>
 #include <linux/spinlock.h>
 
-/*
- * Function : void NCR5380_intr (int irq)
- * 
- * Purpose : handle interrupts, reestablishing I_T_L or I_T_L_Q nexuses
+/**
+ * 	NCR5380_intr	-	generic NCR5380 irq handler
+ *
+ *	Handle interrupts, reestablishing I_T_L or I_T_L_Q nexuses
  *      from the disconnected queue, and restarting NCR5380_main() 
  *      as required.
  *
- * Inputs : int irq, irq that caused this interrupt.
- *
+ *	Locks: caller must hold the io_request lock.
  */
 
 static void NCR5380_intr(int irq, void *dev_id, struct pt_regs *regs) {
@@ -1350,13 +1293,9 @@
 	struct Scsi_Host *instance;
 	int done;
 	unsigned char basr;
-	unsigned long flags;
 
-	 save_flags(flags);
-	 cli();
-#if (NDEBUG & NDEBUG_INTR)
-	 printk("scsi : NCR5380 irq %d triggered\n", irq);
-#endif
+	dprintk(NDEBUG_INTR, ("scsi : NCR5380 irq %d triggered\n", irq));
+
 	do {
 		done = 1;
 		for (instance = first_instance; instance && (instance->hostt == the_template); instance = instance->next)
@@ -1367,33 +1306,19 @@
 				basr = NCR5380_read(BUS_AND_STATUS_REG);
 				/* XXX dispatch to appropriate routine if found and done=0 */
 				if (basr & BASR_IRQ) {
-#if (NDEBUG & NDEBUG_INTR)
-					NCR5380_print(instance);
-#endif
+					NCR5380_dprint(NDEBUG_INTR, instance);
 					if ((NCR5380_read(STATUS_REG) & (SR_SEL | SR_IO)) == (SR_SEL | SR_IO)) {
 						done = 0;
-						restore_flags(flags);
-#if (NDEBUG & NDEBUG_INTR)
-						printk("scsi%d : SEL interrupt\n", instance->host_no);
-#endif
+						dprintk(NDEBUG_INTR, ("scsi%d : SEL interrupt\n", instance->host_no));
 						NCR5380_reselect(instance);
 						(void) NCR5380_read(RESET_PARITY_INTERRUPT_REG);
 					} else if (basr & BASR_PARITY_ERROR) {
-#if (NDEBUG & NDEBUG_INTR)
-						printk("scsi%d : PARITY interrupt\n", instance->host_no);
-#endif
+						dprintk(NDEBUG_INTR, ("scsi%d : PARITY interrupt\n", instance->host_no));
 						(void) NCR5380_read(RESET_PARITY_INTERRUPT_REG);
 					} else if ((NCR5380_read(STATUS_REG) & SR_RST) == SR_RST) {
-#if (NDEBUG & NDEBUG_INTR)
-						printk("scsi%d : RESET interrupt\n", instance->host_no);
-#endif
+						dprintk(NDEBUG_INTR, ("scsi%d : RESET interrupt\n", instance->host_no));
 						(void) NCR5380_read(RESET_PARITY_INTERRUPT_REG);
 					} else {
-/*  
- * XXX the rest of the interrupt conditions should *only* occur during a 
- * DMA transfer, which I haven't gotten around to fixing yet.
- */
-
 #if defined(REAL_DMA)
 						/*
 						 * We should only get PHASE MISMATCH and EOP interrupts
@@ -1424,7 +1349,7 @@
 								if (time_after_eq(jiffies, timeout))
 									printk("scsi%d: timeout at NCR5380.c:%d\n", host->host_no, __LINE__);
 							}
-#else				/* NCR_TIMEOUT */
+#else /* NCR_TIMEOUT */
 							while (NCR5380_read(BUS_AND_STATUS_REG) & BASR_ACK);
 #endif
 
@@ -1432,9 +1357,7 @@
 							NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
 						}
 #else
-#if (NDEBUG & NDEBUG_INTR)
-						printk("scsi : unknown interrupt, BASR 0x%X, MR 0x%X, SR 0x%x\n", basr, NCR5380_read(MODE_REG), NCR5380_read(STATUS_REG));
-#endif
+						dprintk(NDEBUG_INTR, ("scsi : unknown interrupt, BASR 0x%X, MR 0x%X, SR 0x%x\n", basr, NCR5380_read(MODE_REG), NCR5380_read(STATUS_REG)));
 						(void) NCR5380_read(RESET_PARITY_INTERRUPT_REG);
 #endif
 					}
@@ -1445,6 +1368,17 @@
 	} while (!done);
 }
 
+/**
+ *	do_NCR5380_intr
+ *	@irq: interrupt number
+ *	@dev_id: device info
+ *	@regs: registers (unused)
+ *
+ *	Takes the io_request_lock and invokes the generic NCR5380 interrupt
+ *	handler code
+ *
+ *	Locks: takes and releases the io_request lock
+ */
 
 static void do_NCR5380_intr(int irq, void *dev_id, struct pt_regs *regs) {
 	unsigned long flags;
@@ -1454,26 +1388,37 @@
 	 spin_unlock_irqrestore(&io_request_lock, flags);
 }
 #endif
+
+
+/**
+ *	collect_stats		-	collect stats on a scsi command
+ *	@hostdata: adapter 
+ *	@cmd: command being issued
+ *
+ *	Update the statistical data by parsing the command in question
+ */
+ 
+static void collect_stats(struct NCR5380_hostdata *hostdata, Scsi_Cmnd * cmd) 
+{
 #ifdef NCR5380_STATS
-static void collect_stats(struct NCR5380_hostdata *hostdata, Scsi_Cmnd * cmd) {
-#ifdef NCR5380_STAT_LIMIT
-	if (cmd->request_bufflen > NCR5380_STAT_LIMIT)
+	switch (cmd->cmnd[0]) {
+	case WRITE:
+	case WRITE_6:
+	case WRITE_10:
+		hostdata->time_write[cmd->target] += (jiffies - hostdata->timebase);
+		hostdata->pendingw--;
+		break;
+	case READ:
+	case READ_6:
+	case READ_10:
+		hostdata->time_read[cmd->target] += (jiffies - hostdata->timebase);
+		hostdata->pendingr--;
+		break;
+	}
 #endif
-		switch (cmd->cmnd[0]) {
-		case WRITE:
-		case WRITE_6:
-		case WRITE_10:
-			hostdata->time_write[cmd->target] += (jiffies - hostdata->timebase);
-			/*hostdata->bytes_write[cmd->target] += cmd->request_bufflen; */
-			hostdata->pendingw--;
-			break;
-			case READ:case READ_6:case READ_10:hostdata->time_read[cmd->target] += (jiffies - hostdata->timebase);
-			/*hostdata->bytes_read[cmd->target] += cmd->request_bufflen; */
-			hostdata->pendingr--;
-			break;
-		}
 }
-#endif
+
+
 /* 
  * Function : int NCR5380_select (struct Scsi_Host *instance, Scsi_Cmnd *cmd, 
  *      int tag);
@@ -1503,34 +1448,30 @@
  *
  *      If failed (no target) : cmd->scsi_done() will be called, and the 
  *              cmd->result host byte set to DID_BAD_TARGET.
- */ static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd * cmd, int tag) {
+ *
+ *	Locks: caller holds io_request_lock
+ */
+ 
+static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd * cmd, int tag) 
+{
 	NCR5380_local_declare();
 	struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *) instance->hostdata;
 	unsigned char tmp[3], phase;
 	unsigned char *data;
 	int len;
 	unsigned long timeout;
-	unsigned long flags;
-#ifdef USLEEP
 	unsigned char value;
-#endif
-
-	 NCR5380_setup(instance);
-
-#ifdef USLEEP
+	NCR5380_setup(instance);
 
 	if (hostdata->selecting) {
 		goto part2;	/* RvC: sorry prof. Dijkstra, but it keeps the
 				   rest of the code nearly the same */
 	}
-#endif
+
 	hostdata->restart_select = 0;
-#if defined (NDEBUG) && (NDEBUG & NDEBUG_ARBITRATION)
-	NCR5380_print(instance);
-	printk("scsi%d : starting arbitration, id = %d\n", instance->host_no, instance->this_id);
-#endif
-	save_flags(flags);
-	cli();
+
+	NCR5380_dprint(NDEBUG_ARBITRATION, instance);
+	dprintk(NDEBUG_ARBITRATION, ("scsi%d : starting arbitration, id = %d\n", instance->host_no, instance->this_id));
 
 	/* 
 	 * Set the phase bits to 0, otherwise the NCR5380 won't drive the 
@@ -1539,7 +1480,6 @@
 
 	NCR5380_write(TARGET_COMMAND_REG, 0);
 
-
 	/* 
 	 * Start arbitration.
 	 */
@@ -1547,8 +1487,6 @@
 	NCR5380_write(OUTPUT_DATA_REG, hostdata->id_mask);
 	NCR5380_write(MODE_REG, MR_ARBITRATE);
 
-	restore_flags(flags);
-
 	/* Wait for arbitration logic to complete */
 #if NCR_TIMEOUT
 	{
@@ -1572,11 +1510,7 @@
 	while (!(NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_PROGRESS));
 #endif
 
-#if (NDEBUG & NDEBUG_ARBITRATION)
-	printk("scsi%d : arbitration complete\n", instance->host_no);
-/* Avoid GCC 2.4.5 asm needs to many reloads error */
-	__asm__("nop");
-#endif
+	dprintk(NDEBUG_ARBITRATION, ("scsi%d : arbitration complete\n", instance->host_no));
 
 	/* 
 	 * The arbitration delay is 2.2us, but this is a minimum and there is 
@@ -1590,9 +1524,7 @@
 	/* Check for lost arbitration */
 	if ((NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_LOST) || (NCR5380_read(CURRENT_SCSI_DATA_REG) & hostdata->id_higher_mask) || (NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_LOST)) {
 		NCR5380_write(MODE_REG, MR_BASE);
-#if (NDEBUG & NDEBUG_ARBITRATION)
-		printk("scsi%d : lost arbitration, deasserting MR_ARBITRATE\n", instance->host_no);
-#endif
+		dprintk(NDEBUG_ARBITRATION, ("scsi%d : lost arbitration, deasserting MR_ARBITRATE\n", instance->host_no));
 		return -1;
 	}
 	NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_SEL);
@@ -1605,9 +1537,7 @@
 	    (NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_LOST)) {
 		NCR5380_write(MODE_REG, MR_BASE);
 		NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
-#if (NDEBUG & NDEBUG_ARBITRATION)
-		printk("scsi%d : lost arbitration, deasserting ICR_ASSERT_SEL\n", instance->host_no);
-#endif
+		dprintk(NDEBUG_ARBITRATION, ("scsi%d : lost arbitration, deasserting ICR_ASSERT_SEL\n", instance->host_no));
 		return -1;
 	}
 	/* 
@@ -1617,10 +1547,7 @@
 
 	udelay(2);
 
-#if (NDEBUG & NDEBUG_ARBITRATION)
-	printk("scsi%d : won arbitration\n", instance->host_no);
-#endif
-
+	dprintk(NDEBUG_ARBITRATION, ("scsi%d : won arbitration\n", instance->host_no));
 
 	/* 
 	 * Now that we have won arbitration, start Selection process, asserting 
@@ -1672,9 +1599,7 @@
 
 	udelay(1);
 
-#if (NDEBUG & NDEBUG_SELECTION)
-	printk("scsi%d : selecting target %d\n", instance->host_no, cmd->target);
-#endif
+	dprintk(NDEBUG_SELECTION, ("scsi%d : selecting target %d\n", instance->host_no, cmd->target));
 
 	/* 
 	 * The SCSI specification calls for a 250 ms timeout for the actual 
@@ -1689,11 +1614,10 @@
 	 * and it's detecting as true.  Sigh.
 	 */
 
-#ifdef USLEEP
 	hostdata->select_time = 0;	/* we count the clock ticks at which we polled */
 	hostdata->selecting = cmd;
 
-      part2:
+part2:
 	/* RvC: here we enter after a sleeping period, or immediately after
 	   execution of part 1
 	   we poll only once ech clock tick */
@@ -1710,11 +1634,6 @@
 
 	hostdata->selecting = 0;	/* clear this pointer, because we passed the
 					   waiting period */
-#else
-	spin_unlock_irq(&io_request_lock);
-	while (time_before(jiffies, timeout) && !(NCR5380_read(STATUS_REG) & (SR_BSY | SR_IO)));
-	spin_lock_irq(&io_request_lock);
-#endif
 	if ((NCR5380_read(STATUS_REG) & (SR_SEL | SR_IO)) == (SR_SEL | SR_IO)) {
 		NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
 		NCR5380_reselect(instance);
@@ -1738,21 +1657,15 @@
 			printk("scsi%d : weirdness\n", instance->host_no);
 			if (hostdata->restart_select)
 				printk("\trestart select\n");
-#if (NDEBUG & NDEBUG_SELECTION)
-			NCR5380_print(instance);
-#endif
+			NCR5380_dprint(NDEBUG_SELECTION, instance);
 			NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
 			return -1;
 		}
 		cmd->result = DID_BAD_TARGET << 16;
-#ifdef NCR5380_STATS
 		collect_stats(hostdata, cmd);
-#endif
 		cmd->scsi_done(cmd);
 		NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
-#if (NDEBUG & NDEBUG_SELECTION)
-		printk("scsi%d : target did not respond within 250ms\n", instance->host_no);
-#endif
+		dprintk(NDEBUG_SELECTION, ("scsi%d : target did not respond within 250ms\n", instance->host_no));
 		NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
 		return 0;
 	}
@@ -1792,46 +1705,20 @@
 	while (!(NCR5380_read(STATUS_REG) & SR_REQ));
 #endif				/* def NCR_TIMEOUT */
 
-#if (NDEBUG & NDEBUG_SELECTION)
-	printk("scsi%d : target %d selected, going into MESSAGE OUT phase.\n", instance->host_no, cmd->target);
-#endif
+	dprintk(NDEBUG_SELECTION, ("scsi%d : target %d selected, going into MESSAGE OUT phase.\n", instance->host_no, cmd->target));
 	tmp[0] = IDENTIFY(((instance->irq == IRQ_NONE) ? 0 : 1), cmd->lun);
-#ifdef SCSI2
-	if (cmd->device->tagged_queue && (tag != TAG_NONE)) {
-		tmp[1] = SIMPLE_QUEUE_TAG;
-		if (tag == TAG_NEXT) {
-			/* 0 is TAG_NONE, used to imply no tag for this command */
-			if (cmd->device->current_tag == 0)
-				cmd->device->current_tag = 1;
-
-			cmd->tag = cmd->device->current_tag;
-			cmd->device->current_tag++;
-		} else
-			cmd->tag = (unsigned char) tag;
-
-		tmp[2] = cmd->tag;
-		hostdata->last_message = SIMPLE_QUEUE_TAG;
-		len = 3;
-	} else
-#endif				/* def SCSI2 */
-	{
-		len = 1;
-		cmd->tag = 0;
-	}
+
+	len = 1;
+	cmd->tag = 0;
 
 	/* Send message(s) */
 	data = tmp;
 	phase = PHASE_MSGOUT;
 	NCR5380_transfer_pio(instance, &phase, &len, &data);
-#if (NDEBUG & NDEBUG_SELECTION)
-	printk("scsi%d : nexus established.\n", instance->host_no);
-#endif
+	dprintk(NDEBUG_SELECTION, ("scsi%d : nexus established.\n", instance->host_no));
 	/* XXX need to handle errors here */
 	hostdata->connected = cmd;
-#ifdef SCSI2
-	if (!cmd->device->tagged_queue)
-#endif
-		hostdata->busy[cmd->target] |= (1 << cmd->lun);
+	hostdata->busy[cmd->target] |= (1 << cmd->lun);
 
 	initialize_SCp(cmd);
 
@@ -1866,24 +1753,20 @@
 
 static int NCR5380_transfer_pio(struct Scsi_Host *instance, unsigned char *phase, int *count, unsigned char **data) {
 	NCR5380_local_declare();
-	register unsigned char p = *phase, tmp;
-	register int c = *count;
-	register unsigned char *d = *data;
-#ifdef USLEEP
+	unsigned char p = *phase, tmp;
+	int c = *count;
+	unsigned char *d = *data;
 	/*
 	 *      RvC: some administrative data to process polling time
 	 */
 	int break_allowed = 0;
 	struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *) instance->hostdata;
-#endif
-	 NCR5380_setup(instance);
+	NCR5380_setup(instance);
 
-#if (NDEBUG & NDEBUG_PIO)
 	if (!(p & SR_IO))
-		 printk("scsi%d : pio write %d bytes\n", instance->host_no, c);
+		dprintk(NDEBUG_PIO, ("scsi%d : pio write %d bytes\n", instance->host_no, c));
 	else
-		 printk("scsi%d : pio read %d bytes\n", instance->host_no, c);
-#endif
+		dprintk(NDEBUG_PIO, ("scsi%d : pio read %d bytes\n", instance->host_no, c));
 
 	/* 
 	 * The NCR5380 chip will only drive the SCSI bus when the 
@@ -1893,21 +1776,18 @@
 
 	 NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(p));
 
-#ifdef USLEEP
 	/* RvC: don't know if this is necessary, but other SCSI I/O is short
 	 *      so breaks are not necessary there
 	 */
 	if ((p == PHASE_DATAIN) || (p == PHASE_DATAOUT)) {
 		break_allowed = 1;
 	}
-#endif
 	do {
 		/* 
 		 * Wait for assertion of REQ, after which the phase bits will be 
 		 * valid 
 		 */
 
-#ifdef USLEEP
 		/* RvC: we simply poll once, after that we stop temporarily
 		 *      and let the device buffer fill up
 		 *      if breaking is not allowed, we keep polling as long as needed
@@ -1920,20 +1800,13 @@
 			NCR5380_set_timer(instance);
 			break;
 		}
-#else
-		while (!((tmp = NCR5380_read(STATUS_REG)) & SR_REQ));
-#endif
 
-#if (NDEBUG & NDEBUG_HANDSHAKE)
-		printk("scsi%d : REQ detected\n", instance->host_no);
-#endif
+		dprintk(NDEBUG_HANDSHAKE, ("scsi%d : REQ detected\n", instance->host_no));
 
 		/* Check for phase mismatch */
 		if ((tmp & PHASE_MASK) != p) {
-#if (NDEBUG & NDEBUG_PIO)
-			printk("scsi%d : phase mismatch\n", instance->host_no);
-			NCR5380_print_phase(instance);
-#endif
+			dprintk(NDEBUG_HANDSHAKE, ("scsi%d : phase mismatch\n", instance->host_no));
+			NCR5380_dprint_phase(NDEBUG_HANDSHAKE, instance);
 			break;
 		}
 		/* Do actual transfer from SCSI bus to / from memory */
@@ -1954,29 +1827,21 @@
 		if (!(p & SR_IO)) {
 			if (!((p & SR_MSG) && c > 1)) {
 				NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_DATA);
-#if (NDEBUG & NDEBUG_PIO)
-				NCR5380_print(instance);
-#endif
+				NCR5380_dprint(NDEBUG_PIO, instance);
 				NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_DATA | ICR_ASSERT_ACK);
 			} else {
 				NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_DATA | ICR_ASSERT_ATN);
-#if (NDEBUG & NDEBUG_PIO)
-				NCR5380_print(instance);
-#endif
+				NCR5380_dprint(NDEBUG_PIO, instance);
 				NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_DATA | ICR_ASSERT_ATN | ICR_ASSERT_ACK);
 			}
 		} else {
-#if (NDEBUG & NDEBUG_PIO)
-			NCR5380_print(instance);
-#endif
+			NCR5380_dprint(NDEBUG_PIO, instance);
 			NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ACK);
 		}
 
 		while (NCR5380_read(STATUS_REG) & SR_REQ);
 
-#if (NDEBUG & NDEBUG_HANDSHAKE)
-		printk("scsi%d : req false, handshake complete\n", instance->host_no);
-#endif
+		dprintk(NDEBUG_HANDSHAKE, ("scsi%d : req false, handshake complete\n", instance->host_no));
 
 /*
  * We have several special cases to consider during REQ/ACK handshaking : 
@@ -1997,9 +1862,7 @@
 		}
 	} while (--c);
 
-#if (NDEBUG & NDEBUG_PIO)
-	printk("scsi%d : residual %d\n", instance->host_no, c);
-#endif
+	dprintk(NDEBUG_PIO, ("scsi%d : residual %d\n", instance->host_no, c));
 
 	*count = c;
 	*data = d;
@@ -2015,35 +1878,46 @@
 		return -1;
 }
 
+/**
+ *	do_reset	-	issue a reset command
+ *	@host: adapter to reset
+ *
+ *	Issue a reset sequence to the NCR5380 and try and get the bus
+ *	back into sane shape.
+ *
+ *	Locks: caller holds io_request lock
+ */
+ 
 static void do_reset(struct Scsi_Host *host) {
-	unsigned long flags;
-	 NCR5380_local_declare();
-	 NCR5380_setup(host);
+	NCR5380_local_declare();
+	NCR5380_setup(host);
+
+	NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(NCR5380_read(STATUS_REG) & PHASE_MASK));
+	NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_RST);
+	udelay(25);
+	NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
+}
+
+/*
+ * Function : do_abort (Scsi_Host *host)
+ * 
+ * Purpose : abort the currently established nexus.  Should only be 
+ *      called from a routine which can drop into a 
+ * 
+ * Returns : 0 on success, -1 on failure.
+ *
+ * Locks: io_request lock held by caller
+ */
 
-	 save_flags(flags);
-	 cli();
-	 NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(NCR5380_read(STATUS_REG) & PHASE_MASK));
-	 NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_RST);
-	 udelay(25);
-	 NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
-	 restore_flags(flags);
-}				/*
-
-				 * Function : do_abort (Scsi_Host *host)
-				 * 
-				 * Purpose : abort the currently established nexus.  Should only be 
-				 *      called from a routine which can drop into a 
-				 * 
-				 * Returns : 0 on success, -1 on failure.
-				 */ static int do_abort(struct Scsi_Host *host) {
+static int do_abort(struct Scsi_Host *host) {
 	NCR5380_local_declare();
 	unsigned char tmp, *msgptr, phase;
 	int len;
-	 NCR5380_setup(host);
+	NCR5380_setup(host);
 
 
 	/* Request message out phase */
-	 NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN);
+	NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN);
 
 	/* 
 	 * Wait for the target to indicate a valid phase by asserting 
@@ -2057,7 +1931,7 @@
 
 	while (!(tmp = NCR5380_read(STATUS_REG)) & SR_REQ);
 
-	 NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(tmp));
+	NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(tmp));
 
 	if ((tmp & PHASE_MASK) != PHASE_MSGOUT) {
 		NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN | ICR_ASSERT_ACK);
@@ -2096,6 +1970,7 @@
  *
  *      Also, *phase, *count, *data are modified in place.
  *
+ *	Locks: io_request lock held by caller
  */
 
 
@@ -2105,19 +1980,15 @@
 	register unsigned char p = *phase;
 	register unsigned char *d = *data;
 	unsigned char tmp;
-#if defined(PSEUDO_DMA) && !defined(UNSAFE)
-	unsigned long flags;
-#endif
 	int foo;
 #if defined(REAL_DMA_POLL)
 	int cnt, toPIO;
 	unsigned char saved_data = 0, overrun = 0, residue;
 #endif
 
-	struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *)
-	 instance->hostdata;
+	struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *) instance->hostdata;
 
-	 NCR5380_setup(instance);
+	NCR5380_setup(instance);
 
 	if ((tmp = (NCR5380_read(STATUS_REG) & PHASE_MASK)) != p) {
 		*phase = tmp;
@@ -2129,9 +2000,7 @@
 		c -= 2;
 	}
 #endif
-#if (NDEBUG & NDEBUG_DMA)
-	printk("scsi%d : initializing DMA channel %d for %s, %d bytes %s %0x\n", instance->host_no, instance->dma_channel, (p & SR_IO) ? "reading" : "writing", c, (p & SR_IO) ? "to" : "from", (unsigned) d);
-#endif
+	dprintk(NDEBUG_DMA, ("scsi%d : initializing DMA channel %d for %s, %d bytes %s %0x\n", instance->host_no, instance->dma_channel, (p & SR_IO) ? "reading" : "writing", c, (p & SR_IO) ? "to" : "from", (unsigned) d));
 	hostdata->dma_len = (p & SR_IO) ? NCR5380_dma_read_setup(instance, d, c) : NCR5380_dma_write_setup(instance, d, c);
 #endif
 
@@ -2148,9 +2017,8 @@
 	 * before the setting of DMA mode to after transfer of the last byte.
 	 */
 
-#if defined(PSEUDO_DMA) && !defined(UNSAFE)
-	save_flags(flags);
-	cli();
+#if defined(PSEUDO_DMA) && defined(UNSAFE)
+	spin_unlock_irq(&io_request_lock);
 #endif
 	/* KLL May need eop and parity in 53c400 */
 	if (hostdata->flags & FLAG_NCR53C400)
@@ -2159,36 +2027,22 @@
 		NCR5380_write(MODE_REG, MR_BASE | MR_DMA_MODE);
 #endif				/* def REAL_DMA */
 
-#if (NDEBUG & NDEBUG_DMA) & 0
-	printk("scsi%d : mode reg = 0x%X\n", instance->host_no, NCR5380_read(MODE_REG));
-#endif
+	dprintk(NDEBUG_DMA, ("scsi%d : mode reg = 0x%X\n", instance->host_no, NCR5380_read(MODE_REG)));
 
-/* 
- * FOO stuff. For some UNAPPARENT reason, I'm getting 
- * watchdog timers fired on bootup for NO APPARENT REASON, meaning it's
- * probably a timing problem.
- *
- * Since this is the only place I have back-to-back writes, perhaps this 
- * is the problem?
- */
+	/* 
+	 *	On the PAS16 at least I/O recovery delays are not needed here.
+	 *	Everyone else seems to want them.
+	 */
 
 	if (p & SR_IO) {
-#ifndef FOO
-		udelay(1);
-#endif
+		io_recovery_delay(1);
 		NCR5380_write(START_DMA_INITIATOR_RECEIVE_REG, 0);
 	} else {
-#ifndef FOO
-		udelay(1);
-#endif
+		io_recovery_delay(1);
 		NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_DATA);
-#ifndef FOO
-		udelay(1);
-#endif
+		io_recovery_delay(1);
 		NCR5380_write(START_DMA_SEND_REG, 0);
-#ifndef FOO
-		udelay(1);
-#endif
+		io_recovery_delay(1);
 	}
 
 #if defined(REAL_DMA_POLL)
@@ -2250,10 +2104,7 @@
 		}
 	}
 
-
-#if (NDEBUG & NDEBUG_DMA)
-	printk("scsi%d : polled DMA transfer complete, basr 0x%X, sr 0x%X\n", instance->host_no, tmp, NCR5380_read(STATUS_REG));
-#endif
+	dprintk(NDEBUG_DMA, ("scsi%d : polled DMA transfer complete, basr 0x%X, sr 0x%X\n", instance->host_no, tmp, NCR5380_read(STATUS_REG)));
 
 	NCR5380_write(MODE_REG, MR_BASE);
 	NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
@@ -2267,9 +2118,7 @@
 #ifdef READ_OVERRUNS
 	if (*phase == p && (p & SR_IO) && residue == 0) {
 		if (overrun) {
-#if (NDEBUG & NDEBUG_DMA)
-			printk("Got an input overrun, using saved byte\n");
-#endif
+			dprintk(NDEBUG_DMA, ("Got an input overrun, using saved byte\n"));
 			**data = saved_data;
 			*data += 1;
 			*count -= 1;
@@ -2278,17 +2127,13 @@
 			printk("No overrun??\n");
 			cnt = toPIO = 2;
 		}
-#if (NDEBUG & NDEBUG_DMA)
-		printk("Doing %d-byte PIO to 0x%X\n", cnt, *data);
-#endif
+		dprintk(NDEBUG_DMA, ("Doing %d-byte PIO to 0x%X\n", cnt, *data));
 		NCR5380_transfer_pio(instance, phase, &cnt, data);
 		*count -= toPIO - cnt;
 	}
 #endif
 
-#if (NDEBUG & NDEBUG_DMA)
-	printk("Return with data ptr = 0x%X, count %d, last 0x%X, next 0x%X\n", *data, *count, *(*data + *count - 1), *(*data + *count));
-#endif
+	dprintk(NDEBUG_DMA, ("Return with data ptr = 0x%X, count %d, last 0x%X, next 0x%X\n", *data, *count, *(*data + *count - 1), *(*data + *count)));
 	return 0;
 
 #elif defined(REAL_DMA)
@@ -2338,9 +2183,7 @@
 		foo = NCR5380_pwrite(instance, d, c);
 #else
 		int timeout;
-#if (NDEBUG & NDEBUG_C400_PWRITE)
-		printk("About to pwrite %d bytes\n", c);
-#endif
+		dprintk(NDEBUG_C400_PWRITE, ("About to pwrite %d bytes\n", c));
 		if (!(foo = NCR5380_pwrite(instance, d, c))) {
 			/*
 			 * Wait for the last byte to be sent.  If REQ is being asserted for 
@@ -2350,30 +2193,20 @@
 				timeout = 20000;
 				while (!(NCR5380_read(BUS_AND_STATUS_REG) & BASR_DRQ) && (NCR5380_read(BUS_AND_STATUS_REG) & BASR_PHASE_MATCH));
 
-
-#if (NDEBUG & NDEBUG_LAST_BYTE_SENT)
 				if (!timeout)
-					printk("scsi%d : timed out on last byte\n", instance->host_no);
-#endif
-
+					dprintk(NDEBUG_LAST_BYTE_SENT, ("scsi%d : timed out on last byte\n", instance->host_no));
 
 				if (hostdata->flags & FLAG_CHECK_LAST_BYTE_SENT) {
 					hostdata->flags &= ~FLAG_CHECK_LAST_BYTE_SENT;
 					if (NCR5380_read(TARGET_COMMAND_REG) & TCR_LAST_BYTE_SENT) {
 						hostdata->flags |= FLAG_HAS_LAST_BYTE_SENT;
-#if (NDEBUG & NDEBUG_LAST_BYTE_SENT)
-						printk("scsi%d : last bit sent works\n", instance->host_no);
-#endif
+						dprintk(NDEBUG_LAST_WRITE_SENT, ("scsi%d : last bit sent works\n", instance->host_no));
 					}
 				}
 			} else {
-#if (NDEBUG & NDEBUG_C400_PWRITE)
-				printk("Waiting for LASTBYTE\n");
-#endif
+				dprintk(NDEBUG_C400_PWRITE, ("Waiting for LASTBYTE\n"));
 				while (!(NCR5380_read(TARGET_COMMAND_REG) & TCR_LAST_BYTE_SENT));
-#if (NDEBUG & NDEBUG_C400_PWRITE)
-				printk("Got LASTBYTE\n");
-#endif
+				dprintk(NDEBUG_C400_PWRITE, ("Got LASTBYTE\n"));
 			}
 		}
 #endif
@@ -2382,13 +2215,9 @@
 	NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
 
 	if ((!(p & SR_IO)) && (hostdata->flags & FLAG_NCR53C400)) {
-#if (NDEBUG & NDEBUG_C400_PWRITE)
-		printk("53C400w: Checking for IRQ\n");
-#endif
+		dprintk(NDEBUG_C400_PWRITE, ("53C400w: Checking for IRQ\n"));
 		if (NCR5380_read(BUS_AND_STATUS_REG) & BASR_IRQ) {
-#if (NDEBUG & NDEBUG_C400_PWRITE)
-			printk("53C400w:    got it, reading reset interrupt reg\n");
-#endif
+			dprintk(NDEBUG_C400_PWRITE, ("53C400w:    got it, reading reset interrupt reg\n"));
 			NCR5380_read(RESET_PARITY_INTERRUPT_REG);
 		} else {
 			printk("53C400w:    IRQ NOT THERE!\n");
@@ -2397,11 +2226,8 @@
 	*data = d + c;
 	*count = 0;
 	*phase = NCR5380_read(STATUS_REG) & PHASE_MASK;
-#if 0
-	NCR5380_print_phase(instance);
-#endif
-#if defined(PSEUDO_DMA) && !defined(UNSAFE)
-	restore_flags(flags);
+#if defined(PSEUDO_DMA) && defined(UNSAFE)
+	spin_lock_irq(&io_request_lock);
 #endif				/* defined(REAL_DMA_POLL) */
 	return foo;
 #endif				/* def REAL_DMA */
@@ -2423,12 +2249,13 @@
  *
  * XXX Note : we need to watch for bus free or a reset condition here 
  *      to recover from an unexpected bus free condition.
+ *
+ * Locks: io_request_lock held by caller
  */
 
 static void NCR5380_information_transfer(struct Scsi_Host *instance) {
 	NCR5380_local_declare();
-	struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *)
-	 instance->hostdata;
+	struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *)instance->hostdata;
 	unsigned char msgout = NOP;
 	int sink = 0;
 	int len;
@@ -2438,12 +2265,10 @@
 	unsigned char *data;
 	unsigned char phase, tmp, extended_msg[10], old_phase = 0xff;
 	Scsi_Cmnd *cmd = (Scsi_Cmnd *) hostdata->connected;
-#ifdef USLEEP
 	/* RvC: we need to set the end of the polling time */
 	unsigned long poll_time = jiffies + USLEEP_POLL;
-#endif
 
-	 NCR5380_setup(instance);
+	NCR5380_setup(instance);
 
 	while (1) {
 		tmp = NCR5380_read(STATUS_REG);
@@ -2452,9 +2277,7 @@
 			phase = (tmp & PHASE_MASK);
 			if (phase != old_phase) {
 				old_phase = phase;
-#if (NDEBUG & NDEBUG_INFORMATION)
-				NCR5380_print_phase(instance);
-#endif
+				NCR5380_dprint_phase(NDEBUG_INFORMATION, instance);
 			}
 			if (sink && (phase != PHASE_MSGOUT)) {
 				NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(tmp));
@@ -2486,9 +2309,7 @@
 					--cmd->SCp.buffers_residual;
 					cmd->SCp.this_residual = cmd->SCp.buffer->length;
 					cmd->SCp.ptr = cmd->SCp.buffer->address;
-#if (NDEBUG & NDEBUG_INFORMATION)
-					printk("scsi%d : %d bytes and %d buffers left\n", instance->host_no, cmd->SCp.this_residual, cmd->SCp.buffers_residual);
-#endif
+					dprintk(NDEBUG_INFORMATION, ("scsi%d : %d bytes and %d buffers left\n", instance->host_no, cmd->SCp.this_residual, cmd->SCp.buffers_residual));
 				}
 				/*
 				 * The preferred transfer method is going to be 
@@ -2567,16 +2388,12 @@
 				case LINKED_FLG_CMD_COMPLETE:
 					/* Accept message by clearing ACK */
 					NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
-
-#if (NDEBUG & NDEBUG_LINKED)
-					printk("scsi%d : target %d lun %d linked command complete.\n", instance->host_no, cmd->target, cmd->lun);
-#endif
+					dprintk(NDEBUG_LINKED, ("scsi%d : target %d lun %d linked command complete.\n", instance->host_no, cmd->target, cmd->lun));
 					/* 
 					 * Sanity check : A linked command should only terminate with
 					 * one of these messages if there are more linked commands
 					 * available.
 					 */
-
 					if (!cmd->next_link) {
 						printk("scsi%d : target %d lun %d linked command complete, no next_link\n" instance->host_no, cmd->target, cmd->lun);
 						sink = 1;
@@ -2587,12 +2404,8 @@
 					/* The next command is still part of this process */
 					cmd->next_link->tag = cmd->tag;
 					cmd->result = cmd->SCp.Status | (cmd->SCp.Message << 8);
-#if (NDEBUG & NDEBUG_LINKED)
-					printk("scsi%d : target %d lun %d linked request done, calling scsi_done().\n", instance->host_no, cmd->target, cmd->lun);
-#endif
-#ifdef NCR5380_STATS
+					dprintk(NDEBUG_LINKED, ("scsi%d : target %d lun %d linked request done, calling scsi_done().\n", instance->host_no, cmd->target, cmd->lun));
 					collect_stats(hostdata, cmd);
-#endif
 					cmd->scsi_done(cmd);
 					cmd = hostdata->connected;
 					break;
@@ -2603,9 +2416,7 @@
 					sink = 1;
 					NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
 					hostdata->connected = NULL;
-#if (NDEBUG & NDEBUG_QUEUES)
-					printk("scsi%d : command for target %d, lun %d completed\n", instance->host_no, cmd->target, cmd->lun);
-#endif
+					dprintk(NDEBUG_QUEUES, ("scsi%d : command for target %d, lun %d completed\n", instance->host_no, cmd->target, cmd->lun));
 					hostdata->busy[cmd->target] &= ~(1 << cmd->lun);
 
 					/* 
@@ -2631,10 +2442,7 @@
 
 #ifdef AUTOSENSE
 					if ((cmd->cmnd[0] != REQUEST_SENSE) && (cmd->SCp.Status == CHECK_CONDITION)) {
-						unsigned long flags;
-#if (NDEBUG & NDEBUG_AUTOSENSE)
-						printk("scsi%d : performing request sense\n", instance->host_no);
-#endif
+						dprintk(NDEBUG_AUTOSENSE, ("scsi%d : performing request sense\n", instance->host_no));
 						cmd->cmnd[0] = REQUEST_SENSE;
 						cmd->cmnd[1] &= 0xe0;
 						cmd->cmnd[2] = 0;
@@ -2647,21 +2455,14 @@
 						cmd->SCp.ptr = (char *) cmd->sense_buffer;
 						cmd->SCp.this_residual = sizeof(cmd->sense_buffer);
 
-						save_flags(flags);
-						cli();
 						LIST(cmd, hostdata->issue_queue);
 						cmd->host_scribble = (unsigned char *)
 						    hostdata->issue_queue;
 						hostdata->issue_queue = (Scsi_Cmnd *) cmd;
-						restore_flags(flags);
-#if (NDEBUG & NDEBUG_QUEUES)
-						printk("scsi%d : REQUEST SENSE added to head of issue queue\n", instance->host_no);
-#endif
+						dprintk(NDEBUG_QUEUES, ("scsi%d : REQUEST SENSE added to head of issue queue\n", instance->host_no));
 					} else {
 #endif				/* def AUTOSENSE */
-#ifdef NCR5380_STATS
 						collect_stats(hostdata, cmd);
-#endif
 						cmd->scsi_done(cmd);
 					}
 
@@ -2689,21 +2490,15 @@
 						break;
 					}
 				case DISCONNECT:{
-						unsigned long flags;
 						/* Accept message by clearing ACK */
 						NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
 						cmd->device->disconnect = 1;
-						save_flags(flags);
-						cli();
 						LIST(cmd, hostdata->disconnected_queue);
 						cmd->host_scribble = (unsigned char *)
 						    hostdata->disconnected_queue;
 						hostdata->connected = NULL;
 						hostdata->disconnected_queue = cmd;
-						restore_flags(flags);
-#if (NDEBUG & NDEBUG_QUEUES)
-						printk("scsi%d : command for target %d lun %d was moved from connected to" "  the disconnected_queue\n", instance->host_no, cmd->target, cmd->lun);
-#endif
+						dprintk(NDEBUG_QUEUES, ("scsi%d : command for target %d lun %d was moved from connected to" "  the disconnected_queue\n", instance->host_no, cmd->target, cmd->lun));
 						/* 
 						 * Restore phase bits to 0 so an interrupted selection, 
 						 * arbitration can resume.
@@ -2715,9 +2510,6 @@
 						/* Wait for bus free to avoid nasty timeouts */
 						while ((NCR5380_read(STATUS_REG) & SR_BSY) && !hostdata->connected)
 							barrier();
-#if 0
-						NCR5380_print_status(instance);
-#endif
 						return;
 					}
 					/* 
@@ -2751,19 +2543,14 @@
 					extended_msg[0] = EXTENDED_MESSAGE;
 					/* Accept first byte by clearing ACK */
 					NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
-
-#if (NDEBUG & NDEBUG_EXTENDED)
-					printk("scsi%d : receiving extended message\n", instance->host_no);
-#endif
+					dprintk(NDEBUG_EXTENDED, ("scsi%d : receiving extended message\n", instance->host_no));
 
 					len = 2;
 					data = extended_msg + 1;
 					phase = PHASE_MSGIN;
 					NCR5380_transfer_pio(instance, &phase, &len, &data);
 
-#if (NDEBUG & NDEBUG_EXTENDED)
-					printk("scsi%d : length=%d, code=0x%02x\n", instance->host_no, (int) extended_msg[1], (int) extended_msg[2]);
-#endif
+					dprintk(NDEBUG_EXTENDED, ("scsi%d : length=%d, code=0x%02x\n", instance->host_no, (int) extended_msg[1], (int) extended_msg[2]));
 
 					if (!len && extended_msg[1] <= (sizeof(extended_msg) - 1)) {
 						/* Accept third byte by clearing ACK */
@@ -2773,10 +2560,7 @@
 						phase = PHASE_MSGIN;
 
 						NCR5380_transfer_pio(instance, &phase, &len, &data);
-
-#if (NDEBUG & NDEBUG_EXTENDED)
-						printk("scsi%d : message received, residual %d\n", instance->host_no, len);
-#endif
+						dprintk(NDEBUG_EXTENDED, ("scsi%d : message received, residual %d\n", instance->host_no, len));
 
 						switch (extended_msg[2]) {
 						case EXTENDED_SDTR:
@@ -2822,9 +2606,7 @@
 					hostdata->busy[cmd->target] &= ~(1 << cmd->lun);
 					hostdata->connected = NULL;
 					cmd->result = DID_ERROR << 16;
-#ifdef NCR5380_STATS
 					collect_stats(hostdata, cmd);
-#endif
 					cmd->scsi_done(cmd);
 					NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
 					return;
@@ -2840,16 +2622,12 @@
 				 * use the dma transfer function.  
 				 */
 				NCR5380_transfer_pio(instance, &phase, &len, &data);
-#ifdef USLEEP
 				if (!cmd->device->disconnect && should_disconnect(cmd->cmnd[0])) {
 					hostdata->time_expires = jiffies + USLEEP_SLEEP;
-#if (NDEBUG & NDEBUG_USLEEP)
-					printk("scsi%d : issued command, sleeping until %ul\n", instance->host_no, hostdata->time_expires);
-#endif
+					dprintk(NDEBUG_USLEEP, ("scsi%d : issued command, sleeping until %ul\n", instance->host_no, hostdata->time_expires));
 					NCR5380_set_timer(instance);
 					return;
 				}
-#endif				/* def USLEEP */
 				break;
 			case PHASE_STATIN:
 				len = 1;
@@ -2859,25 +2637,19 @@
 				break;
 			default:
 				printk("scsi%d : unknown phase\n", instance->host_no);
-#ifdef NDEBUG
-				NCR5380_print(instance);
-#endif
+				NCR5380_dprint(NDEBUG_ALL, instance);
 			}	/* switch(phase) */
 		}		/* if (tmp * SR_REQ) */
-#ifdef USLEEP
 		else {
 			/* RvC: go to sleep if polling time expired
 			 */
 			if (!cmd->device->disconnect && time_after_eq(jiffies, poll_time)) {
 				hostdata->time_expires = jiffies + USLEEP_SLEEP;
-#if (NDEBUG & NDEBUG_USLEEP)
-				printk("scsi%d : poll timed out, sleeping until %ul\n", instance->host_no, hostdata->time_expires);
-#endif
+				dprintk(NDEBUG_USLEEP, ("scsi%d : poll timed out, sleeping until %ul\n", instance->host_no, hostdata->time_expires));
 				NCR5380_set_timer(instance);
 				return;
 			}
 		}
-#endif
 	}			/* while (1) */
 }
 
@@ -2890,9 +2662,9 @@
  *      
  * Inputs : instance - this instance of the NCR5380.
  *
+ * Locks: io_request_lock held by caller
  */
 
-
 static void NCR5380_reselect(struct Scsi_Host *instance) {
 	NCR5380_local_declare();
 	struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *)
@@ -2900,28 +2672,22 @@
 	unsigned char target_mask;
 	unsigned char lun, phase;
 	int len;
-#ifdef SCSI2
-	unsigned char tag;
-#endif
 	unsigned char msg[3];
 	unsigned char *data;
 	Scsi_Cmnd *tmp = NULL, *prev;
 	int abort = 0;
-	 NCR5380_setup(instance);
+	NCR5380_setup(instance);
 
 	/*
 	 * Disable arbitration, etc. since the host adapter obviously
 	 * lost, and tell an interrupted NCR5380_select() to restart.
 	 */
 
-	 NCR5380_write(MODE_REG, MR_BASE);
-	 hostdata->restart_select = 1;
-
-	 target_mask = NCR5380_read(CURRENT_SCSI_DATA_REG) & ~(hostdata->id_mask);
+	NCR5380_write(MODE_REG, MR_BASE);
+	hostdata->restart_select = 1;
 
-#if (NDEBUG & NDEBUG_RESELECTION)
-	 printk("scsi%d : reselect\n", instance->host_no);
-#endif
+	target_mask = NCR5380_read(CURRENT_SCSI_DATA_REG) & ~(hostdata->id_mask);
+	dprintk(NDEBUG_SELECTION, ("scsi%d : reselect\n", instance->host_no));
 
 	/* 
 	 * At this point, we have detected that our SCSI ID is on the bus,
@@ -2932,10 +2698,10 @@
 	 * signal.
 	 */
 
-	 NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_BSY);
+	NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_BSY);
 
 	while (NCR5380_read(STATUS_REG) & SR_SEL);
-	 NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
+	NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
 
 	/*
 	 * Wait for target to go into MSGIN.
@@ -2943,11 +2709,10 @@
 
 	while (!(NCR5380_read(STATUS_REG) & SR_REQ));
 
-	 len = 1;
-	 data = msg;
-	 phase = PHASE_MSGIN;
-	 NCR5380_transfer_pio(instance, &phase, &len, &data);
-
+	len = 1;
+	data = msg;
+	phase = PHASE_MSGIN;
+	NCR5380_transfer_pio(instance, &phase, &len, &data);
 
 	if (!msg[0] & 0x80) {
 		printk("scsi%d : expecting IDENTIFY message, got ", instance->host_no);
@@ -2964,10 +2729,6 @@
 		 * nexuses so we can chose to do additional data transfer.
 		 */
 
-#ifdef SCSI2
-#error "SCSI-II tagged queueing is not supported yet"
-#endif
-
 		/* 
 		 * Find the command corresponding to the I_T_L or I_T_L_Q  nexus we 
 		 * just reestablished, and remove it from the disconnected queue.
@@ -2976,9 +2737,6 @@
 
 		for (tmp = (Scsi_Cmnd *) hostdata->disconnected_queue, prev = NULL; tmp; prev = tmp, tmp = (Scsi_Cmnd *) tmp->host_scribble)
 			if ((target_mask == (1 << tmp->target)) && (lun == tmp->lun)
-#ifdef SCSI2
-			    && (tag == tmp->tag)
-#endif
 			    ) {
 				if (prev) {
 					REMOVE(prev, prev->host_scribble, tmp, tmp->host_scribble);
@@ -2991,11 +2749,7 @@
 				break;
 			}
 		if (!tmp) {
-#ifdef SCSI2
-			printk("scsi%d : warning : target bitmask %02x lun %d tag %d not in disconnect_queue.\n", instance->host_no, target_mask, lun, tag);
-#else
 			printk("scsi%d : warning : target bitmask %02x lun %d not in disconnect_queue.\n", instance->host_no, target_mask, lun);
-#endif
 			/* 
 			 * Since we have an established nexus that we can't do anything with,
 			 * we must abort it.  
@@ -3008,9 +2762,7 @@
 		do_abort(instance);
 	} else {
 		hostdata->connected = tmp;
-#if (NDEBUG & NDEBUG_RESELECTION)
-		printk("scsi%d : nexus established, target = %d, lun = %d, tag = %d\n", instance->host_no, tmp->target, tmp->lun, tmp->tag);
-#endif
+		dprintk(NDEBUG_RESELECTION, ("scsi%d : nexus established, target = %d, lun = %d, tag = %d\n", instance->host_no, tmp->target, tmp->lun, tmp->tag));
 	}
 }
 
@@ -3072,10 +2824,12 @@
  *
  * Returns : 0 - success, -1 on failure.
  *
- * XXX - there is no way to abort the command that is currently 
- *       connected, you have to wait for it to complete.  If this is 
- *       a problem, we could implement longjmp() / setjmp(), setjmp()
- *       called where the loop started in NCR5380_main().
+ *	XXX - there is no way to abort the command that is currently 
+ *	connected, you have to wait for it to complete.  If this is 
+ *	a problem, we could implement longjmp() / setjmp(), setjmp()
+ *	called where the loop started in NCR5380_main().
+ *
+ *	Locks: io_request_lock held by caller
  */
 
 #ifndef NCR5380_abort
@@ -3083,10 +2837,8 @@
 #endif
 int NCR5380_abort(Scsi_Cmnd * cmd) {
 	NCR5380_local_declare();
-	unsigned long flags;
 	struct Scsi_Host *instance = cmd->host;
-	struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *)
-	 instance->hostdata;
+	struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *) instance->hostdata;
 	Scsi_Cmnd *tmp, **prev;
 
 	printk("scsi%d : aborting command\n", instance->host_no);
@@ -3099,14 +2851,10 @@
 
 	NCR5380_print_status(instance);
 
-	save_flags(flags);
-	cli();
 	NCR5380_setup(instance);
 
-#if (NDEBUG & NDEBUG_ABORT)
-	printk("scsi%d : abort called\n", instance->host_no);
-	printk("        basr 0x%X, sr 0x%X\n", NCR5380_read(BUS_AND_STATUS_REG), NCR5380_read(STATUS_REG));
-#endif
+	dprintk(NDEBUG_ABORT, ("scsi%d : abort called\n", instance->host_no));
+	dprintk(NDEBUG_ABORT, ("        basr 0x%X, sr 0x%X\n", NCR5380_read(BUS_AND_STATUS_REG), NCR5380_read(STATUS_REG)));
 
 #if 0
 /*
@@ -3116,9 +2864,7 @@
  */
 
 	if (hostdata->connected == cmd) {
-#if (NDEBUG & NDEBUG_ABORT)
-		printk("scsi%d : aborting connected command\n", instance->host_no);
-#endif
+		dprintk(NDEBUG_ABORT, ("scsi%d : aborting connected command\n", instance->host_no));
 		hostdata->aborted = 1;
 /*
  * We should perform BSY checking, and make sure we haven't slipped
@@ -3145,20 +2891,15 @@
  * Case 2 : If the command hasn't been issued yet, we simply remove it 
  *          from the issue queue.
  */
-#if (NDEBUG & NDEBUG_ABORT)
 	/* KLL */
-	printk("scsi%d : abort going into loop.\n", instance->host_no);
-#endif
+	dprintk(NDEBUG_ABORT, ("scsi%d : abort going into loop.\n", instance->host_no));
 	for (prev = (Scsi_Cmnd **) & (hostdata->issue_queue), tmp = (Scsi_Cmnd *) hostdata->issue_queue; tmp; prev = (Scsi_Cmnd **) & (tmp->host_scribble), tmp = (Scsi_Cmnd *) tmp->host_scribble)
 		if (cmd == tmp) {
 			REMOVE(5, *prev, tmp, tmp->host_scribble);
 			(*prev) = (Scsi_Cmnd *) tmp->host_scribble;
 			tmp->host_scribble = NULL;
 			tmp->result = DID_ABORT << 16;
-			restore_flags(flags);
-#if (NDEBUG & NDEBUG_ABORT)
-			printk("scsi%d : abort removed command from issue queue.\n", instance->host_no);
-#endif
+			dprintk(NDEBUG_ABORT, ("scsi%d : abort removed command from issue queue.\n", instance->host_no));
 			tmp->done(tmp);
 			return SCSI_ABORT_SUCCESS;
 		}
@@ -3180,10 +2921,7 @@
  */
 
 	if (hostdata->connected) {
-		restore_flags(flags);
-#if (NDEBUG & NDEBUG_ABORT)
-		printk("scsi%d : abort failed, command connected.\n", instance->host_no);
-#endif
+		dprintk(NDEBUG_ABORT, ("scsi%d : abort failed, command connected.\n", instance->host_no));
 		return SCSI_ABORT_NOT_RUNNING;
 	}
 /*
@@ -3213,28 +2951,20 @@
 
 	for (tmp = (Scsi_Cmnd *) hostdata->disconnected_queue; tmp; tmp = (Scsi_Cmnd *) tmp->host_scribble)
 		if (cmd == tmp) {
-			restore_flags(flags);
-#if (NDEBUG & NDEBUG_ABORT)
-			printk("scsi%d : aborting disconnected command.\n", instance->host_no);
-#endif
+			dprintk(NDEBUG_ABORT, ("scsi%d : aborting disconnected command.\n", instance->host_no));
 
 			if (NCR5380_select(instance, cmd, (int) cmd->tag))
 				return SCSI_ABORT_BUSY;
-
-#if (NDEBUG & NDEBUG_ABORT)
-			printk("scsi%d : nexus reestablished.\n", instance->host_no);
-#endif
+			dprintk(NDEBUG_ABORT, ("scsi%d : nexus reestablished.\n", instance->host_no));
 
 			do_abort(instance);
 
-			cli();
 			for (prev = (Scsi_Cmnd **) & (hostdata->disconnected_queue), tmp = (Scsi_Cmnd *) hostdata->disconnected_queue; tmp; prev = (Scsi_Cmnd **) & (tmp->host_scribble), tmp = (Scsi_Cmnd *) tmp->host_scribble)
 				if (cmd == tmp) {
 					REMOVE(5, *prev, tmp, tmp->host_scribble);
 					*prev = (Scsi_Cmnd *) tmp->host_scribble;
 					tmp->host_scribble = NULL;
 					tmp->result = DID_ABORT << 16;
-					restore_flags(flags);
 					tmp->done(tmp);
 					return SCSI_ABORT_SUCCESS;
 				}
@@ -3248,8 +2978,6 @@
  * so we won't panic, but we will notify the user in case something really
  * broke.
  */
-
-	restore_flags(flags);
 	printk("scsi%d : warning : SCSI command probably completed successfully\n" "         before abortion\n", instance->host_no);
 	return SCSI_ABORT_NOT_RUNNING;
 }
@@ -3262,6 +2990,7 @@
  *
  * Returns : SCSI_RESET_WAKEUP
  *
+ * Locks: io_request_lock held by caller
  */
 
 #ifndef NCR5380_reset
diff -urN linux-2.4.17-pre5/drivers/scsi/NCR5380.h linux/drivers/scsi/NCR5380.h
--- linux-2.4.17-pre5/drivers/scsi/NCR5380.h	Fri Dec  7 14:52:27 2001
+++ linux/drivers/scsi/NCR5380.h	Fri Dec  7 14:53:08 2001
@@ -55,6 +55,8 @@
 #define NDEBUG_C400_PWRITE	0x200000
 #define NDEBUG_LISTS		0x400000
 
+#define NDEBUG_ANY		0xFFFFFFFFUL
+
 /* 
  * The contents of the OUTPUT DATA register are asserted on the bus when
  * either arbitration is occurring or the phase-indicating signals (
@@ -91,10 +93,10 @@
  */
 #define MR_BLOCK_DMA_MODE	0x80	/* rw block mode DMA */
 #define MR_TARGET		0x40	/* rw target mode */
-#define MR_ENABLE_PAR_CHECK   0x20	/* rw enable parity checking */
+#define MR_ENABLE_PAR_CHECK	0x20	/* rw enable parity checking */
 #define MR_ENABLE_PAR_INTR	0x10	/* rw enable bad parity interrupt */
 #define MR_ENABLE_EOP_INTR	0x08	/* rw enable eop interrupt */
-#define MR_MONITOR_BSY	0x04	/* rw enable int on unexpected bsy fail */
+#define MR_MONITOR_BSY		0x04	/* rw enable int on unexpected bsy fail */
 #define MR_DMA_MODE		0x02	/* rw DMA / pseudo DMA mode */
 #define MR_ARBITRATE		0x01	/* rw start arbitration */
 
@@ -245,36 +247,34 @@
 
 #ifndef ASM
 struct NCR5380_hostdata {
-	NCR5380_implementation_fields;	/* implementation specific */
+	NCR5380_implementation_fields;		/* implementation specific */
 	unsigned char id_mask, id_higher_mask;	/* 1 << id, all bits greater */
-	unsigned char targets_present;	/* targets we have connected
-					   to, so we can call a select
-					   failure a retryable condition */
-	volatile unsigned char busy[8];	/* index = target, bit = lun */
+	unsigned char targets_present;		/* targets we have connected
+						   to, so we can call a select
+						   failure a retryable condition */
+	volatile unsigned char busy[8];		/* index = target, bit = lun */
 #if defined(REAL_DMA) || defined(REAL_DMA_POLL)
-	volatile int dma_len;	/* requested length of DMA */
+	volatile int dma_len;			/* requested length of DMA */
 #endif
 	volatile unsigned char last_message;	/* last message OUT */
-	volatile Scsi_Cmnd *connected;	/* currently connected command */
+	volatile Scsi_Cmnd *connected;		/* currently connected command */
 	volatile Scsi_Cmnd *issue_queue;	/* waiting to be issued */
 	volatile Scsi_Cmnd *disconnected_queue;	/* waiting for reconnect */
-	volatile int restart_select;	/* we have disconnected,
-					   used to restart 
-					   NCR5380_select() */
-	volatile unsigned aborted:1;	/* flag, says aborted */
+	volatile int restart_select;		/* we have disconnected,
+						   used to restart 
+						   NCR5380_select() */
+	volatile unsigned aborted:1;		/* flag, says aborted */
 	int flags;
-#ifdef USLEEP
-	unsigned long time_expires;	/* in jiffies, set prior to sleeping */
+	unsigned long time_expires;		/* in jiffies, set prior to sleeping */
 	struct Scsi_Host *next_timer;
-	int select_time;	/* timer in select for target response */
+	int select_time;			/* timer in select for target response */
 	volatile Scsi_Cmnd *selecting;
-#endif
 #ifdef NCR5380_STATS
-	unsigned timebase;	/* Base for time calcs */
-	long time_read[8];	/* time to do reads */
-	long time_write[8];	/* time to do writes */
-	unsigned long bytes_read[8];	/* bytes read */
-	unsigned long bytes_write[8];	/* bytes written */
+	unsigned timebase;			/* Base for time calcs */
+	long time_read[8];			/* time to do reads */
+	long time_write[8];			/* time to do writes */
+	unsigned long bytes_read[8];		/* bytes read */
+	unsigned long bytes_write[8];		/* bytes written */
 	unsigned pendingr;
 	unsigned pendingw;
 #endif
@@ -283,6 +283,10 @@
 #ifdef __KERNEL__
 static struct Scsi_Host *first_instance;	/* linked list of 5380's */
 
+#define dprintk(a,b)			do {} while(0)
+#define NCR5380_dprint(a,b)		do {} while(0)
+#define NCR5380_dprint_phase(a,b)	do {} while(0)
+
 #if defined(AUTOPROBE_IRQ)
 static int NCR5380_probe_irq(struct Scsi_Host *instance, int possible);
 #endif
@@ -321,10 +325,24 @@
 
 #if defined(i386) || defined(__alpha__)
 
+/**
+ *	NCR5380_pc_dma_setup		-	setup ISA DMA
+ *	@instance: adapter to set up
+ *	@ptr: block to transfer (virtual address)
+ *	@count: number of bytes to transfer
+ *	@mode: DMA controller mode to use
+ *
+ *	Program the DMA controller ready to perform an ISA DMA transfer
+ *	on this chip.
+ *
+ *	Locks: takes and releases the ISA DMA lock.
+ */
+ 
 static __inline__ int NCR5380_pc_dma_setup(struct Scsi_Host *instance, unsigned char *ptr, unsigned int count, unsigned char mode)
 {
 	unsigned limit;
 	unsigned long bus_addr = virt_to_bus(ptr);
+	unsigned long flags;
 
 	if (instance->dma_channel <= 3) {
 		if (count > 65536)
@@ -341,34 +359,72 @@
 
 	if ((count & 1) || (bus_addr & 1))
 		panic("scsi%d : attempted unaligned DMA transfer\n", instance->host_no);
-	cli();
+	
+	flags=claim_dma_lock();
 	disable_dma(instance->dma_channel);
 	clear_dma_ff(instance->dma_channel);
 	set_dma_addr(instance->dma_channel, bus_addr);
 	set_dma_count(instance->dma_channel, count);
 	set_dma_mode(instance->dma_channel, mode);
 	enable_dma(instance->dma_channel);
-	sti();
+	release_dma_lock(flags);
+	
 	return count;
 }
 
+/**
+ *	NCR5380_pc_dma_write_setup		-	setup ISA DMA write
+ *	@instance: adapter to set up
+ *	@ptr: block to transfer (virtual address)
+ *	@count: number of bytes to transfer
+ *
+ *	Program the DMA controller ready to perform an ISA DMA write to the
+ *	SCSI controller.
+ *
+ *	Locks: called routines take and release the ISA DMA lock.
+ */
+
 static __inline__ int NCR5380_pc_dma_write_setup(struct Scsi_Host *instance, unsigned char *src, unsigned int count)
 {
 	return NCR5380_pc_dma_setup(instance, src, count, DMA_MODE_WRITE);
 }
 
+/**
+ *	NCR5380_pc_dma_read_setup		-	setup ISA DMA read
+ *	@instance: adapter to set up
+ *	@ptr: block to transfer (virtual address)
+ *	@count: number of bytes to transfer
+ *
+ *	Program the DMA controller ready to perform an ISA DMA read from the
+ *	SCSI controller.
+ *
+ *	Locks: called routines take and release the ISA DMA lock.
+ */
+
 static __inline__ int NCR5380_pc_dma_read_setup(struct Scsi_Host *instance, unsigned char *src, unsigned int count)
 {
 	return NCR5380_pc_dma_setup(instance, src, count, DMA_MODE_READ);
 }
 
+/**
+ *	NCR5380_pc_dma_residual		-	return bytes left 
+ *	@instance: adapter
+ *
+ *	Reports the number of bytes left over after the DMA was terminated.
+ *
+ *	Locks: takes and releases the ISA DMA lock.
+ */
+
 static __inline__ int NCR5380_pc_dma_residual(struct Scsi_Host *instance)
 {
-	register int tmp;
-	cli();
+	unsigned long flags;
+	int tmp;
+
+	flags = claim_dma_lock();
 	clear_dma_ff(instance->dma_channel);
 	tmp = get_dma_residue(instance->dma_channel);
-	sti();
+	release_dma_lock(flags);
+	
 	return tmp;
 }
 #endif				/* defined(i386) || defined(__alpha__) */
diff -urN linux-2.4.17-pre5/drivers/scsi/scsi_scan.c linux/drivers/scsi/scsi_scan.c
--- linux-2.4.17-pre5/drivers/scsi/scsi_scan.c	Fri Dec  7 14:52:27 2001
+++ linux/drivers/scsi/scsi_scan.c	Fri Dec  7 14:53:08 2001
@@ -161,6 +161,8 @@
 	{"SONY", "TSL",       "*", BLIST_FORCELUN},  // DDS3 & DDS4 autoloaders
 	{"DELL", "PERCRAID", "*", BLIST_FORCELUN},
 	{"HP", "NetRAID-4M", "*", BLIST_FORCELUN},
+	{"ADAPTEC", "AACRAID", "*", BLIST_FORCELUN},
+	{"ADAPTEC", "Adaptec 5400S", "*", BLIST_FORCELUN},
 
 	/*
 	 * Must be at end of list...
diff -urN linux-2.4.17-pre5/drivers/sound/Config.in linux/drivers/sound/Config.in
--- linux-2.4.17-pre5/drivers/sound/Config.in	Fri Nov  9 14:06:42 2001
+++ linux/drivers/sound/Config.in	Fri Dec  7 14:53:08 2001
@@ -40,6 +40,9 @@
 dep_tristate '  ESS Maestro, Maestro2, Maestro2E driver' CONFIG_SOUND_MAESTRO $CONFIG_SOUND
 dep_tristate '  ESS Maestro3/Allegro driver (EXPERIMENTAL)' CONFIG_SOUND_MAESTRO3 $CONFIG_SOUND $CONFIG_PCI $CONFIG_EXPERIMENTAL
 dep_tristate '  Intel ICH (i8xx) audio support' CONFIG_SOUND_ICH $CONFIG_PCI
+if [ "$CONFIG_MIPS_ITE8172" = "y" -o "$CONFIG_MIPS_IVR" = "y" ]; then
+    dep_tristate '  IT8172G Sound' CONFIG_SOUND_IT8172 $CONFIG_SOUND
+fi
 dep_tristate '  RME Hammerfall (RME96XX) support' CONFIG_SOUND_RME96XX $CONFIG_SOUND $CONFIG_PCI $CONFIG_EXPERIMENTAL
 dep_tristate '  S3 SonicVibes' CONFIG_SOUND_SONICVIBES $CONFIG_SOUND
 if [ "$CONFIG_VISWS" = "y" ]; then
diff -urN linux-2.4.17-pre5/drivers/sound/Makefile linux/drivers/sound/Makefile
--- linux-2.4.17-pre5/drivers/sound/Makefile	Fri Sep 14 14:04:07 2001
+++ linux/drivers/sound/Makefile	Fri Dec  7 14:53:08 2001
@@ -73,6 +73,7 @@
 obj-$(CONFIG_SOUND_RME96XX)     += rme96xx.o
 obj-$(CONFIG_SOUND_BT878)	+= btaudio.o
 obj-$(CONFIG_SOUND_EMU10K1)	+= ac97_codec.o
+obj-$(CONFIG_SOUND_IT8172)     += ite8172.o ac97_codec.o
 
 ifeq ($(CONFIG_MIDI_EMU10K1),y)
   obj-$(CONFIG_SOUND_EMU10K1)	+= sound.o
diff -urN linux-2.4.17-pre5/drivers/sound/btaudio.c linux/drivers/sound/btaudio.c
--- linux-2.4.17-pre5/drivers/sound/btaudio.c	Wed Oct 17 14:19:20 2001
+++ linux/drivers/sound/btaudio.c	Fri Dec  7 14:53:08 2001
@@ -1030,7 +1030,7 @@
         name:     "btaudio",
         id_table: btaudio_pci_tbl,
         probe:    btaudio_probe,
-        remove:   btaudio_remove,
+        remove:   __devexit_p(btaudio_remove),
 };
 
 int btaudio_init_module(void)
diff -urN linux-2.4.17-pre5/drivers/sound/emu10k1/main.c linux/drivers/sound/emu10k1/main.c
--- linux-2.4.17-pre5/drivers/sound/emu10k1/main.c	Tue Oct  9 10:53:18 2001
+++ linux/drivers/sound/emu10k1/main.c	Fri Dec  7 14:53:08 2001
@@ -1127,7 +1127,7 @@
 	name:		"emu10k1",
 	id_table:	emu10k1_pci_tbl,
 	probe:		emu10k1_probe,
-	remove:		emu10k1_remove,
+	remove:		__devexit_p(emu10k1_remove),
 };
 
 static int __init emu10k1_init_module(void)
diff -urN linux-2.4.17-pre5/drivers/sound/ymfpci.c linux/drivers/sound/ymfpci.c
--- linux-2.4.17-pre5/drivers/sound/ymfpci.c	Fri Dec  7 14:52:27 2001
+++ linux/drivers/sound/ymfpci.c	Fri Dec  7 14:53:08 2001
@@ -1443,13 +1443,14 @@
 {
 	struct ymf_state *state = (struct ymf_state *)file->private_data;
 	struct ymf_dmabuf *dmabuf;
+	int redzone;
 	unsigned long flags;
 	unsigned int mask = 0;
 
 	if (file->f_mode & FMODE_WRITE)
 		poll_wait(file, &state->wpcm.dmabuf.wait, wait);
-	// if (file->f_mode & FMODE_READ)
-	// 	poll_wait(file, &dmabuf->wait, wait);
+	if (file->f_mode & FMODE_READ)
+		poll_wait(file, &state->rpcm.dmabuf.wait, wait);
 
 	spin_lock_irqsave(&state->unit->reg_lock, flags);
 	if (file->f_mode & FMODE_READ) {
@@ -1458,12 +1459,21 @@
 			mask |= POLLIN | POLLRDNORM;
 	}
 	if (file->f_mode & FMODE_WRITE) {
+		redzone = ymf_calc_lend(state->format.rate);
+		redzone <<= state->format.shift;
+		redzone *= 3;
+
 		dmabuf = &state->wpcm.dmabuf;
 		if (dmabuf->mapped) {
 			if (dmabuf->count >= (signed)dmabuf->fragsize)
 				mask |= POLLOUT | POLLWRNORM;
 		} else {
-			if ((signed)dmabuf->dmasize >= dmabuf->count + (signed)dmabuf->fragsize)
+			/*
+			 * Don't select unless a full fragment is available.
+			 * Otherwise artsd does GETOSPACE, sees 0, and loops.
+			 */
+			if (dmabuf->count + redzone + dmabuf->fragsize
+			     <= dmabuf->dmasize)
 				mask |= POLLOUT | POLLWRNORM;
 		}
 	}
@@ -1498,6 +1508,7 @@
 		return -EAGAIN;
 	dmabuf->mapped = 1;
 
+/* P3 */ printk(KERN_INFO "ymfpci: using memory mapped sound, untested!\n");
 	return 0;
 }
 
@@ -2430,6 +2441,7 @@
 static int __devinit ymf_probe_one(struct pci_dev *pcidev, const struct pci_device_id *ent)
 {
 	u16 ctrl;
+	unsigned long base;
 	ymfpci_t *codec;
 
 	int err;
@@ -2438,6 +2450,7 @@
 		printk(KERN_ERR "ymfpci: pci_enable_device failed\n");
 		return err;
 	}
+	base = pci_resource_start(pcidev, 0);
 
 	if ((codec = kmalloc(sizeof(ymfpci_t), GFP_KERNEL)) == NULL) {
 		printk(KERN_ERR "ymfpci: no core\n");
@@ -2452,16 +2465,21 @@
 	codec->pci = pcidev;
 
 	pci_read_config_byte(pcidev, PCI_REVISION_ID, &codec->rev);
-	codec->reg_area_virt = ioremap(pci_resource_start(pcidev, 0), 0x8000);
-	if (codec->reg_area_virt == NULL) {
-		printk(KERN_ERR "ymfpci: unable to map registers\n");
+
+	if (request_mem_region(base, 0x8000, "ymfpci") == NULL) {
+		printk(KERN_ERR "ymfpci: unable to request mem region\n");
 		goto out_free;
 	}
 
+	if ((codec->reg_area_virt = ioremap(base, 0x8000)) == NULL) {
+		printk(KERN_ERR "ymfpci: unable to map registers\n");
+		goto out_release_region;
+	}
+
 	pci_set_master(pcidev);
 
 	printk(KERN_INFO "ymfpci: %s at 0x%lx IRQ %d\n",
-	    (char *)ent->driver_data, pci_resource_start(pcidev, 0), pcidev->irq);
+	    (char *)ent->driver_data, base, pcidev->irq);
 
 	ymfpci_aclink_reset(pcidev);
 	if (ymfpci_codec_ready(codec, 0, 1) < 0)
@@ -2491,8 +2509,7 @@
 
 	/* register /dev/dsp */
 	if ((codec->dev_audio = register_sound_dsp(&ymf_fops, -1)) < 0) {
-		printk(KERN_ERR "ymfpci%d: unable to register dsp\n",
-		    codec->dev_audio);
+		printk(KERN_ERR "ymfpci: unable to register dsp\n");
 		goto out_free_irq;
 	}
 
@@ -2538,6 +2555,8 @@
 	ymfpci_writel(codec, YDSXGR_STATUS, ~0);
  out_unmap:
 	iounmap(codec->reg_area_virt);
+ out_release_region:
+	release_mem_region(pci_resource_start(pcidev, 0), 0x8000);
  out_free:
 	kfree(codec);
 	return -ENODEV;
@@ -2561,6 +2580,7 @@
 	ctrl = ymfpci_readw(codec, YDSXGR_GLOBALCTRL);
 	ymfpci_writew(codec, YDSXGR_GLOBALCTRL, ctrl & ~0x0007);
 	iounmap(codec->reg_area_virt);
+	release_mem_region(pci_resource_start(pcidev, 0), 0x8000);
 #ifdef CONFIG_SOUND_YMFPCI_LEGACY
 	if (codec->iomidi) {
 		unload_uart401(&codec->mpu_data);
@@ -2577,7 +2597,7 @@
 	name:		"ymfpci",
 	id_table:	ymf_id_tbl,
 	probe:		ymf_probe_one,
-	remove:         ymf_remove_one,
+	remove:         __devexit_p(ymf_remove_one),
 	suspend:	ymf_suspend,
 	resume:		ymf_resume
 };
diff -urN linux-2.4.17-pre5/drivers/usb/uhci.c linux/drivers/usb/uhci.c
--- linux-2.4.17-pre5/drivers/usb/uhci.c	Fri Nov  9 13:41:42 2001
+++ linux/drivers/usb/uhci.c	Fri Dec  7 14:53:08 2001
@@ -2990,7 +2990,7 @@
 	id_table:	uhci_pci_ids,
 
 	probe:		uhci_pci_probe,
-	remove:		uhci_pci_remove,
+	remove:		__devexit_p(uhci_pci_remove),
 
 #ifdef	CONFIG_PM
 	suspend:	uhci_pci_suspend,
diff -urN linux-2.4.17-pre5/drivers/usb/usb-ohci.c linux/drivers/usb/usb-ohci.c
--- linux-2.4.17-pre5/drivers/usb/usb-ohci.c	Fri Nov  9 13:41:42 2001
+++ linux/drivers/usb/usb-ohci.c	Fri Dec  7 14:53:08 2001
@@ -2860,7 +2860,7 @@
 	id_table:	&ohci_pci_ids [0],
 
 	probe:		ohci_pci_probe,
-	remove:		ohci_pci_remove,
+	remove:		__devexit_p(ohci_pci_remove),
 
 #ifdef	CONFIG_PM
 	suspend:	ohci_pci_suspend,
diff -urN linux-2.4.17-pre5/drivers/usb/usb-uhci.c linux/drivers/usb/usb-uhci.c
--- linux-2.4.17-pre5/drivers/usb/usb-uhci.c	Fri Nov  9 13:41:42 2001
+++ linux/drivers/usb/usb-uhci.c	Fri Dec  7 14:53:08 2001
@@ -3070,7 +3070,7 @@
 	id_table:	&uhci_pci_ids [0],
 
 	probe:		uhci_pci_probe,
-	remove:		uhci_pci_remove,
+	remove:		__devexit_p(uhci_pci_remove),
 
 #ifdef	CONFIG_PM
 	suspend:	uhci_pci_suspend,
diff -urN linux-2.4.17-pre5/drivers/video/cyber2000fb.c linux/drivers/video/cyber2000fb.c
--- linux-2.4.17-pre5/drivers/video/cyber2000fb.c	Thu Oct 25 13:53:52 2001
+++ linux/drivers/video/cyber2000fb.c	Fri Dec  7 14:53:08 2001
@@ -1683,7 +1683,7 @@
 static struct pci_driver cyberpro_driver = {
 	name:		"CyberPro",
 	probe:		cyberpro_probe,
-	remove:		cyberpro_remove,
+	remove:		__devexit_p(cyberpro_remove),
 	suspend:	cyberpro_suspend,
 	resume:		cyberpro_resume,
 	id_table:	cyberpro_pci_table
diff -urN linux-2.4.17-pre5/drivers/video/imsttfb.c linux/drivers/video/imsttfb.c
--- linux-2.4.17-pre5/drivers/video/imsttfb.c	Wed Nov 14 14:52:20 2001
+++ linux/drivers/video/imsttfb.c	Fri Dec  7 14:53:08 2001
@@ -1643,7 +1643,7 @@
 	name:		"imsttfb",
 	id_table:	imsttfb_pci_tbl,
 	probe:		imsttfb_probe,
-	remove:		imsttfb_remove,
+	remove:		__devexit_p(imsttfb_remove),
 };
 
 static struct fb_ops imsttfb_ops = {
diff -urN linux-2.4.17-pre5/drivers/video/matrox/matroxfb_base.c linux/drivers/video/matrox/matroxfb_base.c
--- linux-2.4.17-pre5/drivers/video/matrox/matroxfb_base.c	Wed Nov 14 14:52:20 2001
+++ linux/drivers/video/matrox/matroxfb_base.c	Fri Dec  7 14:53:08 2001
@@ -108,6 +108,7 @@
 #endif
 
 static void matroxfb_unregister_device(struct matrox_fb_info* minfo);
+int matroxfb_switch(int con, struct fb_info *info);
 
 /* --------------------------------------------------------------------- */
 
diff -urN linux-2.4.17-pre5/drivers/video/radeonfb.c linux/drivers/video/radeonfb.c
--- linux-2.4.17-pre5/drivers/video/radeonfb.c	Wed Nov 14 14:52:20 2001
+++ linux/drivers/video/radeonfb.c	Fri Dec  7 14:53:08 2001
@@ -619,7 +619,7 @@
 	name:		"radeonfb",
 	id_table:	radeonfb_pci_table,
 	probe:		radeonfb_pci_register,
-	remove:		radeonfb_pci_unregister,
+	remove:		__devexit_p(radeonfb_pci_unregister),
 };
 
 
diff -urN linux-2.4.17-pre5/drivers/video/riva/fbdev.c linux/drivers/video/riva/fbdev.c
--- linux-2.4.17-pre5/drivers/video/riva/fbdev.c	Wed Nov 14 14:52:20 2001
+++ linux/drivers/video/riva/fbdev.c	Fri Dec  7 14:53:08 2001
@@ -2082,7 +2082,7 @@
 	name:		"rivafb",
 	id_table:	rivafb_pci_tbl,
 	probe:		rivafb_init_one,
-	remove:		rivafb_remove_one,
+	remove:		__devexit_p(rivafb_remove_one),
 };
 
 
diff -urN linux-2.4.17-pre5/drivers/video/tdfxfb.c linux/drivers/video/tdfxfb.c
--- linux-2.4.17-pre5/drivers/video/tdfxfb.c	Wed Nov 14 14:52:20 2001
+++ linux/drivers/video/tdfxfb.c	Fri Dec  7 14:53:08 2001
@@ -495,7 +495,7 @@
 	name:		"tdfxfb",
 	id_table:	tdfxfb_id_table,
 	probe:		tdfxfb_probe,
-	remove:		tdfxfb_remove,
+	remove:		__devexit_p(tdfxfb_remove),
 };
 
 MODULE_DEVICE_TABLE(pci, tdfxfb_id_table);
diff -urN linux-2.4.17-pre5/fs/binfmt_elf.c linux/fs/binfmt_elf.c
--- linux-2.4.17-pre5/fs/binfmt_elf.c	Sat Oct 20 19:16:59 2001
+++ linux/fs/binfmt_elf.c	Fri Dec  7 14:53:08 2001
@@ -32,7 +32,7 @@
 #include <linux/highuid.h>
 #include <linux/smp_lock.h>
 #include <linux/compiler.h>
-#include <linux/limits.h>
+#include <linux/highmem.h>
 
 #include <asm/uaccess.h>
 #include <asm/param.h>
@@ -1032,6 +1032,25 @@
 	elf_fpregset_t fpu;		/* NT_PRFPREG */
 	struct elf_prpsinfo psinfo;	/* NT_PRPSINFO */
 
+	/* first copy the parameters from user space */
+	memset(&psinfo, 0, sizeof(psinfo));
+	{
+		int i, len;
+
+		len = current->mm->arg_end - current->mm->arg_start;
+		if (len >= ELF_PRARGSZ)
+			len = ELF_PRARGSZ-1;
+		copy_from_user(&psinfo.pr_psargs,
+			      (const char *)current->mm->arg_start, len);
+		for(i = 0; i < len; i++)
+			if (psinfo.pr_psargs[i] == 0)
+				psinfo.pr_psargs[i] = ' ';
+		psinfo.pr_psargs[len] = 0;
+
+	}
+
+	/* now stop all vm operations */
+	down_write(&current->mm->mmap_sem);
 	segs = current->mm->map_count;
 
 #ifdef DEBUG
@@ -1073,7 +1092,6 @@
 	 * Set up the notes in similar form to SVR4 core dumps made
 	 * with info from their /proc.
 	 */
-	memset(&psinfo, 0, sizeof(psinfo));
 	memset(&prstatus, 0, sizeof(prstatus));
 
 	notes[0].name = "CORE";
@@ -1129,23 +1147,6 @@
 	psinfo.pr_flag = current->flags;
 	psinfo.pr_uid = NEW_TO_OLD_UID(current->uid);
 	psinfo.pr_gid = NEW_TO_OLD_GID(current->gid);
-	{
-		int i, len;
-
-		set_fs(fs);
-
-		len = current->mm->arg_end - current->mm->arg_start;
-		if (len >= ELF_PRARGSZ)
-			len = ELF_PRARGSZ-1;
-		copy_from_user(&psinfo.pr_psargs,
-			      (const char *)current->mm->arg_start, len);
-		for(i = 0; i < len; i++)
-			if (psinfo.pr_psargs[i] == 0)
-				psinfo.pr_psargs[i] = ' ';
-		psinfo.pr_psargs[len] = 0;
-
-		set_fs(KERNEL_DS);
-	}
 	strncpy(psinfo.pr_fname, current->comm, sizeof(psinfo.pr_fname));
 
 	notes[2].name = "CORE";
@@ -1217,8 +1218,6 @@
 		if (!writenote(&notes[i], file))
 			goto end_coredump;
 
-	set_fs(fs);
-
 	DUMP_SEEK(dataoff);
 
 	for(vma = current->mm->mmap; vma != NULL; vma = vma->vm_next) {
@@ -1232,22 +1231,24 @@
 		for (addr = vma->vm_start;
 		     addr < vma->vm_end;
 		     addr += PAGE_SIZE) {
-			pgd_t *pgd;
-			pmd_t *pmd;
-			pte_t *pte;
-
-			pgd = pgd_offset(vma->vm_mm, addr);
-			if (pgd_none(*pgd))
-				goto nextpage_coredump;
-			pmd = pmd_offset(pgd, addr);
-			if (pmd_none(*pmd))
-				goto nextpage_coredump;
-			pte = pte_offset(pmd, addr);
-			if (pte_none(*pte)) {
-nextpage_coredump:
+			struct page* page;
+			struct vm_area_struct *vma;
+
+			if (get_user_pages(current, current->mm, addr, 1, 0, 1,
+						&page, &vma) <= 0) {
 				DUMP_SEEK (file->f_pos + PAGE_SIZE);
 			} else {
-				DUMP_WRITE((void*)addr, PAGE_SIZE);
+				if (page == ZERO_PAGE(addr)) {
+					DUMP_SEEK (file->f_pos + PAGE_SIZE);
+				} else {
+					void *kaddr;
+					flush_cache_page(vma, addr);
+					kaddr = kmap(page);
+					DUMP_WRITE(kaddr, PAGE_SIZE);
+					flush_page_to_ram(page);
+					kunmap(page);
+				}
+				put_page(page);
 			}
 		}
 	}
@@ -1260,6 +1261,7 @@
 
  end_coredump:
 	set_fs(fs);
+	up_write(&current->mm->mmap_sem);
 	return has_dumped;
 }
 #endif		/* USE_ELF_CORE_DUMP */
diff -urN linux-2.4.17-pre5/fs/block_dev.c linux/fs/block_dev.c
--- linux-2.4.17-pre5/fs/block_dev.c	Wed Nov 21 14:07:25 2001
+++ linux/fs/block_dev.c	Fri Dec  7 14:53:08 2001
@@ -234,7 +234,7 @@
 #define HASH_SIZE	(1UL << HASH_BITS)
 #define HASH_MASK	(HASH_SIZE-1)
 static struct list_head bdev_hashtable[HASH_SIZE];
-static spinlock_t bdev_lock = SPIN_LOCK_UNLOCKED;
+static spinlock_t bdev_lock __cacheline_aligned_in_smp = SPIN_LOCK_UNLOCKED;
 static kmem_cache_t * bdev_cachep;
 
 #define alloc_bdev() \
diff -urN linux-2.4.17-pre5/fs/buffer.c linux/fs/buffer.c
--- linux-2.4.17-pre5/fs/buffer.c	Fri Dec  7 14:52:27 2001
+++ linux/fs/buffer.c	Fri Dec  7 14:53:08 2001
@@ -73,7 +73,7 @@
 static rwlock_t hash_table_lock = RW_LOCK_UNLOCKED;
 
 static struct buffer_head *lru_list[NR_LIST];
-static spinlock_t lru_list_lock = SPIN_LOCK_UNLOCKED;
+static spinlock_t lru_list_lock __cacheline_aligned_in_smp = SPIN_LOCK_UNLOCKED;
 static int nr_buffers_type[NR_LIST];
 static unsigned long size_buffers_type[NR_LIST];
 
diff -urN linux-2.4.17-pre5/fs/dcache.c linux/fs/dcache.c
--- linux-2.4.17-pre5/fs/dcache.c	Wed Oct  3 22:57:36 2001
+++ linux/fs/dcache.c	Fri Dec  7 14:53:08 2001
@@ -29,7 +29,7 @@
 #define DCACHE_PARANOIA 1
 /* #define DCACHE_DEBUG 1 */
 
-spinlock_t dcache_lock = SPIN_LOCK_UNLOCKED;
+spinlock_t dcache_lock __cacheline_aligned_in_smp = SPIN_LOCK_UNLOCKED;
 
 /* Right now the dcache depends on the kernel lock */
 #define check_lock()	if (!kernel_locked()) BUG()
diff -urN linux-2.4.17-pre5/fs/devpts/root.c linux/fs/devpts/root.c
--- linux-2.4.17-pre5/fs/devpts/root.c	Fri Aug 11 14:29:02 2000
+++ linux/fs/devpts/root.c	Fri Dec  7 14:53:08 2001
@@ -101,7 +101,6 @@
 	int i;
 	const char *p;
 
-	dentry->d_inode = NULL;	/* Assume failure */
 	dentry->d_op    = &devpts_dentry_operations;
 
 	if ( dentry->d_name.len == 1 && dentry->d_name.name[0] == '0' ) {
@@ -127,11 +126,10 @@
 	if ( entry >= sbi->max_ptys )
 		return NULL;
 
-	dentry->d_inode = sbi->inodes[entry];
-	if ( dentry->d_inode )
-		atomic_inc(&dentry->d_inode->i_count);
+	if ( sbi->inodes[entry] )
+		atomic_inc(&sbi->inodes[entry]->i_count);
 	
-	d_add(dentry, dentry->d_inode);
+	d_add(dentry, sbi->inodes[entry]);
 
 	return NULL;
 }
diff -urN linux-2.4.17-pre5/fs/exec.c linux/fs/exec.c
--- linux-2.4.17-pre5/fs/exec.c	Fri Dec  7 14:52:27 2001
+++ linux/fs/exec.c	Fri Dec  7 14:53:08 2001
@@ -973,9 +973,7 @@
 	if (do_truncate(file->f_dentry, 0) != 0)
 		goto close_fail;
 
-	down_read(&current->mm->mmap_sem);
 	retval = binfmt->core_dump(signr, regs, file);
-	up_read(&current->mm->mmap_sem);
 
 close_fail:
 	filp_close(file, NULL);
diff -urN linux-2.4.17-pre5/fs/ext3/Makefile linux/fs/ext3/Makefile
--- linux-2.4.17-pre5/fs/ext3/Makefile	Fri Nov  9 14:25:04 2001
+++ linux/fs/ext3/Makefile	Fri Dec  7 14:53:08 2001
@@ -9,7 +9,7 @@
 
 O_TARGET := ext3.o
 
-obj-y    := acl.o balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o \
+obj-y    := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o \
 		ioctl.o namei.o super.o symlink.o
 obj-m    := $(O_TARGET)
 
diff -urN linux-2.4.17-pre5/fs/ext3/acl.c linux/fs/ext3/acl.c
--- linux-2.4.17-pre5/fs/ext3/acl.c	Fri Nov  9 14:25:04 2001
+++ linux/fs/ext3/acl.c	Wed Dec 31 16:00:00 1969
@@ -1,17 +0,0 @@
-/*
- * linux/fs/ext3/acl.c
- *
- * Copyright (C) 1993, 1994, 1995
- * Remy Card (card@masi.ibp.fr)
- * Laboratoire MASI - Institut Blaise Pascal
- * Universite Pierre et Marie Curie (Paris VI)
- */
-
-#include <linux/fs.h>
-#include <linux/sched.h>
-
-
-/*
- * This file will contain the Access Control Lists management for the
- * second extended file system.
- */
diff -urN linux-2.4.17-pre5/fs/ext3/inode.c linux/fs/ext3/inode.c
--- linux-2.4.17-pre5/fs/ext3/inode.c	Fri Nov  9 14:25:04 2001
+++ linux/fs/ext3/inode.c	Fri Dec  7 14:53:08 2001
@@ -32,7 +32,6 @@
 #include <linux/quotaops.h>
 #include <linux/module.h>
 
-
 /*
  * SEARCH_FROM_ZERO forces each block allocation to search from the start
  * of the filesystem.  This is to force rapid reallocation of recently-freed
@@ -716,6 +715,8 @@
  * reachable from inode.
  *
  * akpm: `handle' can be NULL if create == 0.
+ *
+ * The BKL may not be held on entry here.  Be sure to take it early.
  */
 
 static int ext3_get_block_handle(handle_t *handle, struct inode *inode, 
@@ -823,6 +824,9 @@
 	goto reread;
 }
 
+/*
+ * The BKL is not held on entry here.
+ */
 static int ext3_get_block(struct inode *inode, long iblock,
 			struct buffer_head *bh_result, int create)
 {
@@ -1022,13 +1026,26 @@
 		ret = PTR_ERR(handle);
 		goto out;
 	}
+	unlock_kernel();
 	ret = block_prepare_write(page, from, to, ext3_get_block);
+	lock_kernel();
 	if (ret != 0)
 		goto prepare_write_failed;
 
-	if (ext3_should_journal_data(inode))
+	if (ext3_should_journal_data(inode)) {
 		ret = walk_page_buffers(handle, page->buffers,
 				from, to, NULL, do_journal_get_write_access);
+		if (ret) {
+			/*
+			 * We're going to fail this prepare_write(),
+			 * so commit_write() will not be called.
+			 * We need to undo block_prepare_write()'s kmap().
+			 * AKPM: Do we need to clear PageUptodate?  I don't
+			 * think so.
+			 */
+			kunmap(page);
+		}
+	}
 prepare_write_failed:
 	if (ret)
 		ext3_journal_stop(handle, inode);
@@ -1096,7 +1113,7 @@
 		kunmap(page);
 		if (pos > inode->i_size)
 			inode->i_size = pos;
-		set_bit(EXT3_STATE_JDATA, &inode->u.ext3_i.i_state);
+		EXT3_I(inode)->i_state |= EXT3_STATE_JDATA;
 	} else {
 		if (ext3_should_order_data(inode)) {
 			ret = walk_page_buffers(handle, page->buffers,
@@ -1104,8 +1121,17 @@
 		}
 		/* Be careful here if generic_commit_write becomes a
 		 * required invocation after block_prepare_write. */
-		if (ret == 0)
+		if (ret == 0) {
 			ret = generic_commit_write(file, page, from, to);
+		} else {
+			/*
+			 * block_prepare_write() was called, but we're not
+			 * going to call generic_commit_write().  So we
+			 * need to perform generic_commit_write()'s kunmap
+			 * by hand.
+			 */
+			kunmap(page);
+		}
 	}
 	if (inode->i_size > inode->u.ext3_i.i_disksize) {
 		inode->u.ext3_i.i_disksize = inode->i_size;
@@ -1140,7 +1166,7 @@
 	journal_t *journal;
 	int err;
 	
-	if (test_and_clear_bit(EXT3_STATE_JDATA, &inode->u.ext3_i.i_state)) {
+	if (EXT3_I(inode)->i_state & EXT3_STATE_JDATA) {
 		/* 
 		 * This is a REALLY heavyweight approach, but the use of
 		 * bmap on dirty files is expected to be extremely rare:
@@ -1159,6 +1185,7 @@
 		 * everything they get.
 		 */
 		
+		EXT3_I(inode)->i_state &= ~EXT3_STATE_JDATA;
 		journal = EXT3_JOURNAL(inode);
 		journal_lock_updates(journal);
 		err = journal_flush(journal);
@@ -2203,7 +2230,7 @@
 	/* If we are not tracking these fields in the in-memory inode,
 	 * then preserve them on disk, but still initialise them to zero
 	 * for new inodes. */
-	if (inode->u.ext3_i.i_state & EXT3_STATE_NEW) {
+	if (EXT3_I(inode)->i_state & EXT3_STATE_NEW) {
 		raw_inode->i_faddr = 0;
 		raw_inode->i_frag = 0;
 		raw_inode->i_fsize = 0;
@@ -2249,7 +2276,7 @@
 	rc = ext3_journal_dirty_metadata(handle, bh);
 	if (!err)
 		err = rc;
-	inode->u.ext3_i.i_state &= ~EXT3_STATE_NEW;
+	EXT3_I(inode)->i_state &= ~EXT3_STATE_NEW;
 
 out_brelse:
 	brelse (bh);
@@ -2333,7 +2360,7 @@
 int ext3_setattr(struct dentry *dentry, struct iattr *attr)
 {
 	struct inode *inode = dentry->d_inode;
-	int error, rc;
+	int error, rc = 0;
 
 	error = inode_change_ok(inode, attr);
 	if (error)
@@ -2356,7 +2383,7 @@
 		ext3_journal_stop(handle, inode);
 	}
 	
-	inode_setattr(inode, attr);
+	rc = inode_setattr(inode, attr);
 
 	/* If inode_setattr's call to ext3_truncate failed to get a
 	 * transaction handle at all, we need to clean up the in-core
@@ -2366,7 +2393,9 @@
 
 err_out:
 	ext3_std_error(inode->i_sb, error);
-	return 0;
+	if (!error)
+		error = rc;
+	return error;
 }
 
 
@@ -2667,6 +2696,3 @@
  * here, in ext3_aops_journal_start() to ensure that the forthcoming "see if we
  * need to extend" test in ext3_prepare_write() succeeds.  
  */
-
-
-MODULE_LICENSE("GPL");
diff -urN linux-2.4.17-pre5/fs/ext3/super.c linux/fs/ext3/super.c
--- linux-2.4.17-pre5/fs/ext3/super.c	Fri Nov  9 14:25:04 2001
+++ linux/fs/ext3/super.c	Fri Dec  7 14:53:08 2001
@@ -1257,8 +1257,11 @@
 	}
 
 	journal = journal_init_inode(journal_inode);
-	if (!journal)
+	if (!journal) {
+		printk(KERN_ERR "EXT3-fs: Could not load journal inode\n");
 		iput(journal_inode);
+	}
+	
 	return journal;
 }
 
@@ -1350,7 +1353,7 @@
 	journal_t *journal;
 	int journal_inum = le32_to_cpu(es->s_journal_inum);
 	int journal_dev = le32_to_cpu(es->s_journal_dev);
-	int err;
+	int err = 0;
 	int really_read_only;
 
 	really_read_only = is_read_only(sb->s_dev);
@@ -1400,9 +1403,10 @@
 	}
 
 	if (!EXT3_HAS_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_RECOVER))
-		journal_wipe(journal, !really_read_only);
+		err = journal_wipe(journal, !really_read_only);
+	if (!err)
+		err = journal_load(journal);
 
-	err = journal_load(journal);
 	if (err) {
 		printk(KERN_ERR "EXT3-fs: error loading journal.\n");
 		journal_destroy(journal);
@@ -1740,6 +1744,8 @@
 
 EXPORT_NO_SYMBOLS;
 
+MODULE_AUTHOR("Remy Card, Stephen Tweedie, Andrew Morton, Andreas Dilger, Theodore Ts'o and others");
+MODULE_DESCRIPTION("Second Extended Filesystem with journaling extensions");
 MODULE_LICENSE("GPL");
 module_init(init_ext3_fs)
 module_exit(exit_ext3_fs)
diff -urN linux-2.4.17-pre5/fs/jbd/commit.c linux/fs/jbd/commit.c
--- linux-2.4.17-pre5/fs/jbd/commit.c	Fri Nov  9 14:25:04 2001
+++ linux/fs/jbd/commit.c	Fri Dec  7 14:53:08 2001
@@ -47,7 +47,8 @@
 	struct buffer_head *wbuf[64];
 	int bufs;
 	int flags;
-	int blocknr;
+	int err;
+	unsigned long blocknr;
 	char *tagp = NULL;
 	journal_header_t *header;
 	journal_block_tag_t *tag = NULL;
@@ -352,6 +353,11 @@
 			jbd_debug(4, "JBD: get descriptor\n");
 
 			descriptor = journal_get_descriptor_buffer(journal);
+			if (!descriptor) {
+				__journal_abort_hard(journal);
+				continue;
+			}
+			
 			bh = jh2bh(descriptor);
 			jbd_debug(4, "JBD: got buffer %ld (%p)\n",
 				bh->b_blocknr, bh->b_data);
@@ -375,7 +381,14 @@
 
 		/* Where is the buffer to be written? */
 
-		blocknr = journal_next_log_block(journal);
+		err = journal_next_log_block(journal, &blocknr);
+		/* If the block mapping failed, just abandon the buffer
+		   and repeat this loop: we'll fall into the
+		   refile-on-abort condition above. */
+		if (err) {
+			__journal_abort_hard(journal);
+			continue;
+		}
 
 		/* Bump b_count to prevent truncate from stumbling over
                    the shadowed buffer!  @@@ This can go if we ever get
@@ -554,16 +567,20 @@
 
 	jbd_debug(3, "JBD: commit phase 6\n");
 
+	if (is_journal_aborted(journal))
+		goto skip_commit;
+
 	/* Done it all: now write the commit record.  We should have
 	 * cleaned up our previous buffers by now, so if we are in abort
 	 * mode we can now just skip the rest of the journal write
 	 * entirely. */
 
-	if (is_journal_aborted(journal))
-		goto skip_commit;
-
 	descriptor = journal_get_descriptor_buffer(journal);
-
+	if (!descriptor) {
+		__journal_abort_hard(journal);
+		goto skip_commit;
+	}
+	
 	/* AKPM: buglet - add `i' to tmp! */
 	for (i = 0; i < jh2bh(descriptor)->b_size; i += 512) {
 		journal_header_t *tmp =
diff -urN linux-2.4.17-pre5/fs/jbd/journal.c linux/fs/jbd/journal.c
--- linux-2.4.17-pre5/fs/jbd/journal.c	Fri Nov  9 14:25:04 2001
+++ linux/fs/jbd/journal.c	Fri Dec  7 14:53:08 2001
@@ -70,7 +70,6 @@
 EXPORT_SYMBOL(journal_destroy);
 EXPORT_SYMBOL(journal_recover);
 EXPORT_SYMBOL(journal_update_superblock);
-EXPORT_SYMBOL(__journal_abort);
 EXPORT_SYMBOL(journal_abort);
 EXPORT_SYMBOL(journal_errno);
 EXPORT_SYMBOL(journal_ack_err);
@@ -606,7 +605,7 @@
  * Log buffer allocation routines:
  */
 
-unsigned long journal_next_log_block(journal_t *journal)
+int journal_next_log_block(journal_t *journal, unsigned long *retp)
 {
 	unsigned long blocknr;
 
@@ -617,7 +616,7 @@
 	journal->j_free--;
 	if (journal->j_head == journal->j_last)
 		journal->j_head = journal->j_first;
-	return journal_bmap(journal, blocknr);
+	return journal_bmap(journal, blocknr, retp);
 }
 
 /*
@@ -627,17 +626,28 @@
  * this is a no-op.  If needed, we can use j_blk_offset - everything is
  * ready.
  */
-unsigned long journal_bmap(journal_t *journal, unsigned long blocknr)
+int journal_bmap(journal_t *journal, unsigned long blocknr, 
+		 unsigned long *retp)
 {
+	int err = 0;
 	unsigned long ret;
 
 	if (journal->j_inode) {
 		ret = bmap(journal->j_inode, blocknr);
-		J_ASSERT(ret != 0);
+		if (ret)
+			*retp = ret;
+		else {
+			printk (KERN_ALERT __FUNCTION__ 
+				": journal block not found "
+				"at offset %lu on %s\n",
+				blocknr, bdevname(journal->j_dev));
+			err = -EIO;
+			__journal_abort_soft(journal, err);
+		}
 	} else {
-		ret = blocknr;	 /* +journal->j_blk_offset */
+		*retp = blocknr; /* +journal->j_blk_offset */
 	}
-	return ret;
+	return err;
 }
 
 /*
@@ -649,7 +659,13 @@
 struct journal_head * journal_get_descriptor_buffer(journal_t *journal)
 {
 	struct buffer_head *bh;
-	unsigned long blocknr = journal_next_log_block(journal);
+	unsigned long blocknr;
+	int err;
+
+	err = journal_next_log_block(journal, &blocknr);
+
+	if (err)
+		return NULL;
 
 	bh = getblk(journal->j_dev, blocknr, journal->j_blocksize);
 	bh->b_state |= (1 << BH_Dirty);
@@ -747,7 +763,8 @@
 {
 	struct buffer_head *bh;
 	journal_t *journal = journal_init_common();
-	int blocknr;
+	int err;
+	unsigned long blocknr;
 
 	if (!journal)
 		return NULL;
@@ -757,13 +774,22 @@
 	journal->j_inode = inode;
 	jbd_debug(1,
 		  "journal %p: inode %s/%ld, size %Ld, bits %d, blksize %ld\n",
-		  journal, bdevname(inode->i_dev), inode->i_ino, inode->i_size,
+		  journal, bdevname(inode->i_dev), inode->i_ino, 
+		  (long long) inode->i_size,
 		  inode->i_sb->s_blocksize_bits, inode->i_sb->s_blocksize);
 
 	journal->j_maxlen = inode->i_size >> inode->i_sb->s_blocksize_bits;
 	journal->j_blocksize = inode->i_sb->s_blocksize;
 
-	blocknr = journal_bmap(journal, 0);
+	err = journal_bmap(journal, 0, &blocknr);
+	/* If that failed, give up */
+	if (err) {
+		printk(KERN_ERR __FUNCTION__ ": Cannnot locate journal "
+		       "superblock\n");
+		kfree(journal);
+		return NULL;
+	}
+	
 	bh = getblk(journal->j_dev, blocknr, journal->j_blocksize);
 	J_ASSERT(bh != NULL);
 	journal->j_sb_buffer = bh;
@@ -772,6 +798,18 @@
 	return journal;
 }
 
+/* 
+ * If the journal init or create aborts, we need to mark the journal
+ * superblock as being NULL to prevent the journal destroy from writing
+ * back a bogus superblock. 
+ */
+static void journal_fail_superblock (journal_t *journal)
+{
+	struct buffer_head *bh = journal->j_sb_buffer;
+	brelse(bh);
+	journal->j_sb_buffer = NULL;
+}
+
 /*
  * Given a journal_t structure, initialise the various fields for
  * startup of a new journaling session.  We use this both when creating
@@ -817,14 +855,15 @@
 
 int journal_create (journal_t *journal)
 {
-	int blocknr;
+	unsigned long blocknr;
 	struct buffer_head *bh;
 	journal_superblock_t *sb;
-	int i;
+	int i, err;
 
 	if (journal->j_maxlen < JFS_MIN_JOURNAL_BLOCKS) {
 		printk (KERN_ERR "Journal length (%d blocks) too short.\n",
 			journal->j_maxlen);
+		journal_fail_superblock(journal);
 		return -EINVAL;
 	}
 
@@ -841,7 +880,9 @@
 	   have any blocks on disk beginning with JFS_MAGIC_NUMBER. */
 	jbd_debug(1, "JBD: Zeroing out journal blocks...\n");
 	for (i = 0; i < journal->j_maxlen; i++) {
-		blocknr = journal_bmap(journal, i);
+		err = journal_bmap(journal, i, &blocknr);
+		if (err)
+			return err;
 		bh = getblk(journal->j_dev, blocknr, journal->j_blocksize);
 		wait_on_buffer(bh);
 		memset (bh->b_data, 0, journal->j_blocksize);
@@ -851,6 +892,7 @@
 		mark_buffer_uptodate(bh, 1);
 		__brelse(bh);
 	}
+
 	sync_dev(journal->j_dev);
 	jbd_debug(1, "JBD: journal cleared.\n");
 
@@ -915,7 +957,8 @@
 {
 	struct buffer_head *bh;
 	journal_superblock_t *sb;
-
+	int err = -EIO;
+	
 	bh = journal->j_sb_buffer;
 
 	J_ASSERT(bh != NULL);
@@ -925,16 +968,18 @@
 		if (!buffer_uptodate(bh)) {
 			printk (KERN_ERR
 				"JBD: IO error reading journal superblock\n");
-			return -EIO;
+			goto out;
 		}
 	}
 
 	sb = journal->j_superblock;
 
+	err = -EINVAL;
+	
 	if (sb->s_header.h_magic != htonl(JFS_MAGIC_NUMBER) ||
 	    sb->s_blocksize != htonl(journal->j_blocksize)) {
 		printk(KERN_WARNING "JBD: no valid journal superblock found\n");
-		return -EINVAL;
+		goto out;
 	}
 
 	switch(ntohl(sb->s_header.h_blocktype)) {
@@ -946,17 +991,21 @@
 		break;
 	default:
 		printk(KERN_WARNING "JBD: unrecognised superblock format ID\n");
-		return -EINVAL;
+		goto out;
 	}
 
 	if (ntohl(sb->s_maxlen) < journal->j_maxlen)
 		journal->j_maxlen = ntohl(sb->s_maxlen);
 	else if (ntohl(sb->s_maxlen) > journal->j_maxlen) {
 		printk (KERN_WARNING "JBD: journal file too short\n");
-		return -EINVAL;
+		goto out;
 	}
 
 	return 0;
+
+out:
+	journal_fail_superblock(journal);
+	return err;
 }
 
 /*
@@ -1061,7 +1110,10 @@
 	/* We can now mark the journal as empty. */
 	journal->j_tail = 0;
 	journal->j_tail_sequence = ++journal->j_transaction_sequence;
-	journal_update_superblock(journal, 1);
+	if (journal->j_sb_buffer) {
+		journal_update_superblock(journal, 1);
+		brelse(journal->j_sb_buffer);
+	}
 
 	if (journal->j_inode)
 		iput(journal->j_inode);
@@ -1069,7 +1121,6 @@
 		journal_destroy_revoke(journal);
 
 	unlock_journal(journal);
-	brelse(journal->j_sb_buffer);
 	kfree(journal);
 	MOD_DEC_USE_COUNT;
 }
@@ -1356,11 +1407,16 @@
  * progress).
  */
 
-/* Quick version for internal journal use (doesn't lock the journal) */
-void __journal_abort (journal_t *journal)
+/* Quick version for internal journal use (doesn't lock the journal).
+ * Aborts hard --- we mark the abort as occurred, but do _nothing_ else,
+ * and don't attempt to make any other journal updates. */
+void __journal_abort_hard (journal_t *journal)
 {
 	transaction_t *transaction;
 
+	if (journal->j_flags & JFS_ABORT)
+		return;
+
 	printk (KERN_ERR "Aborting journal on device %s.\n",
 		journal_dev_name(journal));
 
@@ -1370,23 +1426,27 @@
 		log_start_commit(journal, transaction);
 }
 
-/* Full version for external use */
-void journal_abort (journal_t *journal, int errno)
+/* Soft abort: record the abort error status in the journal superblock,
+ * but don't do any other IO. */
+void __journal_abort_soft (journal_t *journal, int errno)
 {
-	lock_journal(journal);
-
 	if (journal->j_flags & JFS_ABORT)
-		goto out;
+		return;
 
 	if (!journal->j_errno)
 		journal->j_errno = errno;
 
-	__journal_abort(journal);
+	__journal_abort_hard(journal);
 
 	if (errno)
 		journal_update_superblock(journal, 1);
+}
 
- out:
+/* Full version for external use */
+void journal_abort (journal_t *journal, int errno)
+{
+	lock_journal(journal);
+	__journal_abort_soft(journal, errno);
 	unlock_journal(journal);
 }
 
diff -urN linux-2.4.17-pre5/fs/jbd/recovery.c linux/fs/jbd/recovery.c
--- linux-2.4.17-pre5/fs/jbd/recovery.c	Fri Nov  9 14:25:04 2001
+++ linux/fs/jbd/recovery.c	Fri Dec  7 14:53:08 2001
@@ -70,7 +70,8 @@
 static int do_readahead(journal_t *journal, unsigned int start)
 {
 	int err;
-	unsigned int max, nbufs, next, blocknr;
+	unsigned int max, nbufs, next;
+	unsigned long blocknr;
 	struct buffer_head *bh;
 	
 	struct buffer_head * bufs[MAXBUF];
@@ -86,12 +87,11 @@
 	nbufs = 0;
 	
 	for (next = start; next < max; next++) {
-		blocknr = journal_bmap(journal, next);
+		err = journal_bmap(journal, next, &blocknr);
 
-		if (!blocknr) {
+		if (err) {
 			printk (KERN_ERR "JBD: bad block at offset %u\n",
 				next);
-			err = -EIO;
 			goto failed;
 		}
 
@@ -132,19 +132,20 @@
 static int jread(struct buffer_head **bhp, journal_t *journal, 
 		 unsigned int offset)
 {
-	unsigned int blocknr;
+	int err;
+	unsigned long blocknr;
 	struct buffer_head *bh;
 
 	*bhp = NULL;
 
 	J_ASSERT (offset < journal->j_maxlen);
 	
-	blocknr = journal_bmap(journal, offset);
+	err = journal_bmap(journal, offset, &blocknr);
 
-	if (!blocknr) {
+	if (err) {
 		printk (KERN_ERR "JBD: bad block at offset %u\n",
 			offset);
-		return -EIO;
+		return err;
 	}
 
 	bh = getblk(journal->j_dev, blocknr, journal->j_blocksize);
diff -urN linux-2.4.17-pre5/fs/jbd/revoke.c linux/fs/jbd/revoke.c
--- linux-2.4.17-pre5/fs/jbd/revoke.c	Fri Nov  9 14:25:04 2001
+++ linux/fs/jbd/revoke.c	Fri Dec  7 14:53:08 2001
@@ -495,6 +495,8 @@
 	
 	if (!descriptor) {
 		descriptor = journal_get_descriptor_buffer(journal);
+		if (!descriptor)
+			return;
 		header = (journal_header_t *) &jh2bh(descriptor)->b_data[0];
 		header->h_magic     = htonl(JFS_MAGIC_NUMBER);
 		header->h_blocktype = htonl(JFS_REVOKE_BLOCK);
diff -urN linux-2.4.17-pre5/fs/jbd/transaction.c linux/fs/jbd/transaction.c
--- linux-2.4.17-pre5/fs/jbd/transaction.c	Fri Nov  9 14:25:04 2001
+++ linux/fs/jbd/transaction.c	Fri Dec  7 14:53:08 2001
@@ -1058,21 +1058,6 @@
 		JBUFFER_TRACE(jh, "not on a transaction");
 		__journal_file_buffer(jh, handle->h_transaction, wanted_jlist);
 	}
-	/*
-	 * We need to mark the buffer dirty and refile it inside the lock to
-	 * protect it from release by journal_try_to_free_buffer()
-	 *
-	 * We set ->b_flushtime to something small enough to typically keep
-	 * kupdate away from the buffer.
-	 *
-	 * We don't need to do a balance_dirty() - __block_commit_write()
-	 * does that.
-	 */
-	if (!async && !atomic_set_buffer_dirty(jh2bh(jh))) {
-		jh2bh(jh)->b_flushtime =
-			jiffies + journal->j_commit_interval + 1 * HZ;
-		refile_buffer(jh2bh(jh));
-	}
 no_journal:
 	spin_unlock(&journal_datalist_lock);
 	if (need_brelse) {
@@ -1604,8 +1589,6 @@
 
 	assert_spin_locked(&journal_datalist_lock);
 
-	if (!buffer_jbd(bh))
-		return 1;
 	jh = bh2jh(bh);
 
 	if (buffer_locked(bh) || buffer_dirty(bh)) {
diff -urN linux-2.4.17-pre5/fs/nfs/nfs3proc.c linux/fs/nfs/nfs3proc.c
--- linux-2.4.17-pre5/fs/nfs/nfs3proc.c	Mon Oct  1 13:45:37 2001
+++ linux/fs/nfs/nfs3proc.c	Fri Dec  7 14:53:08 2001
@@ -17,6 +17,37 @@
 
 #define NFSDBG_FACILITY		NFSDBG_PROC
 
+/* A wrapper to handle the EJUKEBOX error message */
+static int
+nfs3_rpc_wrapper(struct rpc_clnt *clnt, struct rpc_message *msg, int flags)
+{
+	sigset_t oldset;
+	int res;
+	rpc_clnt_sigmask(clnt, &oldset);
+	do {
+		res = rpc_call_sync(clnt, msg, flags);
+		if (res != -EJUKEBOX)
+			break;
+		set_current_state(TASK_INTERRUPTIBLE);
+		schedule_timeout(NFS_JUKEBOX_RETRY_TIME);
+		res = -ERESTARTSYS;
+	} while (!signalled());
+	rpc_clnt_sigunmask(clnt, &oldset);
+	return res;
+}
+
+static inline int
+nfs3_rpc_call_wrapper(struct rpc_clnt *clnt, u32 proc, void *argp, void *resp, int flags)
+{
+	struct rpc_message msg = { proc, argp, resp, NULL };
+	return nfs3_rpc_wrapper(clnt, &msg, flags);
+}
+
+#define rpc_call(clnt, proc, argp, resp, flags) \
+		nfs3_rpc_call_wrapper(clnt, proc, argp, resp, flags)
+#define rpc_call_sync(clnt, msg, flags) \
+		nfs3_rpc_wrapper(clnt, msg, flags)
+
 /*
  * Bare-bones access to getattr: this is for nfs_read_super.
  */
diff -urN linux-2.4.17-pre5/fs/nfs/pagelist.c linux/fs/nfs/pagelist.c
--- linux-2.4.17-pre5/fs/nfs/pagelist.c	Fri Nov  9 14:28:15 2001
+++ linux/fs/nfs/pagelist.c	Fri Dec  7 14:53:08 2001
@@ -187,7 +187,7 @@
 		BUG();
 	}
 #endif
-	for (pos = head->prev; pos != head; pos = pos->prev) {
+	list_for_each_prev(pos, head) {
 		struct nfs_page	*p = nfs_list_entry(pos);
 		if (page_index(p->wb_page) < pg_idx)
 			break;
diff -urN linux-2.4.17-pre5/fs/nfs/read.c linux/fs/nfs/read.c
--- linux-2.4.17-pre5/fs/nfs/read.c	Fri Nov  9 14:28:15 2001
+++ linux/fs/nfs/read.c	Fri Dec  7 14:53:08 2001
@@ -402,6 +402,9 @@
 	dprintk("NFS: %4d nfs_readpage_result, (status %d)\n",
 		task->tk_pid, task->tk_status);
 
+	if (nfs_async_handle_jukebox(task))
+		return;
+
 	nfs_refresh_inode(inode, &data->fattr);
 	while (!list_empty(&data->pages)) {
 		struct nfs_page *req = nfs_list_entry(data->pages.next);
diff -urN linux-2.4.17-pre5/fs/nfs/unlink.c linux/fs/nfs/unlink.c
--- linux-2.4.17-pre5/fs/nfs/unlink.c	Thu Aug 16 09:39:37 2001
+++ linux/fs/nfs/unlink.c	Fri Dec  7 14:53:08 2001
@@ -123,6 +123,8 @@
 	struct dentry		*dir = data->dir;
 	struct inode		*dir_i;
 
+	if (nfs_async_handle_jukebox(task))
+		return;
 	if (!dir)
 		return;
 	dir_i = dir->d_inode;
diff -urN linux-2.4.17-pre5/fs/nfs/write.c linux/fs/nfs/write.c
--- linux-2.4.17-pre5/fs/nfs/write.c	Tue Nov 20 14:18:50 2001
+++ linux/fs/nfs/write.c	Fri Dec  7 14:53:08 2001
@@ -305,18 +305,30 @@
 
 /*
  * Insert a write request into an inode
+ * Note: we sort the list in order to be able to optimize nfs_find_request()
+ *	 & co. for the 'write append' case. For 2.5 we may want to consider
+ *	 some form of hashing so as to perform well on random writes.
  */
 static inline void
 nfs_inode_add_request(struct inode *inode, struct nfs_page *req)
 {
+	struct list_head *pos, *head;
+	unsigned long pg_idx = page_index(req->wb_page);
+
 	if (!list_empty(&req->wb_hash))
 		return;
 	if (!NFS_WBACK_BUSY(req))
 		printk(KERN_ERR "NFS: unlocked request attempted hashed!\n");
-	if (list_empty(&inode->u.nfs_i.writeback))
+	head = &inode->u.nfs_i.writeback;
+	if (list_empty(head))
 		igrab(inode);
+	list_for_each_prev(pos, head) {
+		struct nfs_page *entry = nfs_inode_wb_entry(pos);
+		if (page_index(entry->wb_page) < pg_idx)
+			break;
+	}
 	inode->u.nfs_i.npages++;
-	list_add(&req->wb_hash, &inode->u.nfs_i.writeback);
+	list_add(&req->wb_hash, pos);
 	req->wb_count++;
 }
 
@@ -354,15 +366,18 @@
 static inline struct nfs_page *
 _nfs_find_request(struct inode *inode, struct page *page)
 {
-	struct list_head	*head, *next;
+	struct list_head	*head, *pos;
+	unsigned long pg_idx = page_index(page);
 
 	head = &inode->u.nfs_i.writeback;
-	next = head->next;
-	while (next != head) {
-		struct nfs_page *req = nfs_inode_wb_entry(next);
-		next = next->next;
-		if (page_index(req->wb_page) != page_index(page))
+	list_for_each_prev(pos, head) {
+		struct nfs_page *req = nfs_inode_wb_entry(pos);
+		unsigned long found_idx = page_index(req->wb_page);
+
+		if (pg_idx < found_idx)
 			continue;
+		if (pg_idx != found_idx)
+			break;
 		req->wb_count++;
 		return req;
 	}
@@ -444,20 +459,20 @@
 	else
 		idx_end = idx_start + npages - 1;
 
-	spin_lock(&nfs_wreq_lock);
 	head = &inode->u.nfs_i.writeback;
-	p = head->next;
-	while (p != head) {
+ restart:
+	spin_lock(&nfs_wreq_lock);
+	list_for_each_prev(p, head) {
 		unsigned long pg_idx;
 		struct nfs_page *req = nfs_inode_wb_entry(p);
 
-		p = p->next;
-
 		if (file && req->wb_file != file)
 			continue;
 
 		pg_idx = page_index(req->wb_page);
-		if (pg_idx < idx_start || pg_idx > idx_end)
+		if (pg_idx < idx_start)
+			break;
+		if (pg_idx > idx_end)
 			continue;
 
 		if (!NFS_WBACK_BUSY(req))
@@ -468,9 +483,8 @@
 		nfs_release_request(req);
 		if (error < 0)
 			return error;
-		spin_lock(&nfs_wreq_lock);
-		p = head->next;
 		res++;
+		goto restart;
 	}
 	spin_unlock(&nfs_wreq_lock);
 	return res;
@@ -991,6 +1005,9 @@
 	dprintk("NFS: %4d nfs_writeback_done (status %d)\n",
 		task->tk_pid, task->tk_status);
 
+	if (nfs_async_handle_jukebox(task))
+		return;
+
 	/* We can't handle that yet but we check for it nevertheless */
 	if (resp->count < argp->count && task->tk_status >= 0) {
 		static unsigned long    complain;
@@ -1183,6 +1200,9 @@
 
         dprintk("NFS: %4d nfs_commit_done (status %d)\n",
                                 task->tk_pid, task->tk_status);
+
+	if (nfs_async_handle_jukebox(task))
+		return;
 
 	nfs_write_attributes(inode, resp->fattr);
 	while (!list_empty(&data->pages)) {
diff -urN linux-2.4.17-pre5/include/asm-sparc64/page.h linux/include/asm-sparc64/page.h
--- linux-2.4.17-pre5/include/asm-sparc64/page.h	Fri Dec  7 14:52:27 2001
+++ linux/include/asm-sparc64/page.h	Fri Dec  7 14:53:08 2001
@@ -1,4 +1,4 @@
-/* $Id: page.h,v 1.37 2001/11/17 00:10:48 davem Exp $ */
+/* $Id: page.h,v 1.38 2001/11/30 01:04:10 davem Exp $ */
 
 #ifndef _SPARC64_PAGE_H
 #define _SPARC64_PAGE_H
@@ -31,9 +31,7 @@
 #define PAGE_BUG(page)	BUG()
 
 extern void _clear_page(void *page);
-extern void _copy_page(void *to, void *from);
 #define clear_page(X)	_clear_page((void *)(X))
-#define copy_page(X,Y)	_copy_page((void *)(X), (void *)(Y))
 extern void clear_user_page(void *page, unsigned long vaddr);
 extern void copy_user_page(void *to, void *from, unsigned long vaddr);
 
diff -urN linux-2.4.17-pre5/include/linux/cache.h linux/include/linux/cache.h
--- linux-2.4.17-pre5/include/linux/cache.h	Thu Nov 22 11:46:18 2001
+++ linux/include/linux/cache.h	Fri Dec  7 14:53:08 2001
@@ -34,4 +34,12 @@
 #endif
 #endif /* __cacheline_aligned */
 
+#ifndef __cacheline_aligned_in_smp
+#ifdef CONFIG_SMP
+#define __cacheline_aligned_in_smp __cacheline_aligned
+#else
+#define __cacheline_aligned_in_smp
+#endif /* CONFIG_SMP */
+#endif
+
 #endif /* __LINUX_CACHE_H */
diff -urN linux-2.4.17-pre5/include/linux/ext3_fs.h linux/include/linux/ext3_fs.h
--- linux-2.4.17-pre5/include/linux/ext3_fs.h	Fri Nov  9 14:25:04 2001
+++ linux/include/linux/ext3_fs.h	Fri Dec  7 14:53:08 2001
@@ -36,8 +36,8 @@
 /*
  * The second extended file system version
  */
-#define EXT3FS_DATE		"06 Nov 2001"
-#define EXT3FS_VERSION		"2.4-0.9.15"
+#define EXT3FS_DATE		"02 Dec 2001"
+#define EXT3FS_VERSION		"2.4-0.9.16"
 
 /*
  * Debug code
@@ -577,10 +577,6 @@
 					 ~EXT3_DIR_ROUND)
 
 #ifdef __KERNEL__
-
-/* Filesize hard limits for 64-bit file offsets */
-extern long long ext3_max_sizes[];
-
 /*
  * Describe an inode's exact location on disk and in memory
  */
@@ -603,9 +599,6 @@
 # define ATTRIB_NORET  __attribute__((noreturn))
 # define NORET_AND     noreturn,
 
-/* acl.c */
-extern int ext3_permission (struct inode *, int);
-
 /* balloc.c */
 extern int ext3_bg_has_super(struct super_block *sb, int group);
 extern unsigned long ext3_bg_num_gdb(struct super_block *sb, int group);
@@ -619,16 +612,10 @@
 						    unsigned int block_group,
 						    struct buffer_head ** bh);
 
-/* bitmap.c */
-extern unsigned long ext3_count_free (struct buffer_head *, unsigned);
-
 /* dir.c */
 extern int ext3_check_dir_entry(const char *, struct inode *,
 				struct ext3_dir_entry_2 *, struct buffer_head *,
 				unsigned long);
-
-/* file.c */
-
 /* fsync.c */
 extern int ext3_sync_file (struct file *, struct dentry *, int);
 
@@ -638,9 +625,9 @@
 extern struct inode * ext3_orphan_get (struct super_block *, ino_t);
 extern unsigned long ext3_count_free_inodes (struct super_block *);
 extern void ext3_check_inodes_bitmap (struct super_block *);
+extern unsigned long ext3_count_free (struct buffer_head *, unsigned);
 
 /* inode.c */
-
 extern struct buffer_head * ext3_getblk (handle_t *, struct inode *, long, int, int *);
 extern struct buffer_head * ext3_bread (handle_t *, struct inode *, int, int, int *);
 
@@ -654,13 +641,13 @@
 extern void ext3_discard_prealloc (struct inode *);
 extern void ext3_dirty_inode(struct inode *);
 extern int ext3_change_inode_journal_flag(struct inode *, int);
+extern void ext3_truncate (struct inode *);
 
 /* ioctl.c */
 extern int ext3_ioctl (struct inode *, struct file *, unsigned int,
 		       unsigned long);
 
 /* namei.c */
-extern struct inode_operations ext3_dir_inode_operations;
 extern int ext3_orphan_add(handle_t *, struct inode *);
 extern int ext3_orphan_del(handle_t *, struct inode *);
 
@@ -684,9 +671,6 @@
 extern struct super_block * ext3_read_super (struct super_block *,void *,int);
 extern int ext3_statfs (struct super_block *, struct statfs *);
 
-/* truncate.c */
-extern void ext3_truncate (struct inode *);
-
 #define ext3_std_error(sb, errno)				\
 do {								\
 	if ((errno))						\
@@ -705,10 +689,15 @@
 extern struct inode_operations ext3_file_inode_operations;
 extern struct file_operations ext3_file_operations;
 
+/* inode.c */
+extern struct address_space_operations ext3_aops;
+
+/* namei.c */
+extern struct inode_operations ext3_dir_inode_operations;
+
 /* symlink.c */
 extern struct inode_operations ext3_fast_symlink_inode_operations;
 
-extern struct address_space_operations ext3_aops;
 
 #endif	/* __KERNEL__ */
 
diff -urN linux-2.4.17-pre5/include/linux/ext3_jbd.h linux/include/linux/ext3_jbd.h
--- linux-2.4.17-pre5/include/linux/ext3_jbd.h	Fri Nov  9 14:25:04 2001
+++ linux/include/linux/ext3_jbd.h	Fri Dec  7 14:53:08 2001
@@ -196,9 +196,22 @@
  */
 static inline handle_t *ext3_journal_start(struct inode *inode, int nblocks)
 {
+	journal_t *journal;
+	
 	if (inode->i_sb->s_flags & MS_RDONLY)
 		return ERR_PTR(-EROFS);
-	return journal_start(EXT3_JOURNAL(inode), nblocks);
+
+	/* Special case here: if the journal has aborted behind our
+	 * backs (eg. EIO in the commit thread), then we still need to
+	 * take the FS itself readonly cleanly. */
+	journal = EXT3_JOURNAL(inode);
+	if (is_journal_aborted(journal)) {
+		ext3_abort(inode->i_sb, __FUNCTION__,
+			   "Detected aborted journal");
+		return ERR_PTR(-EROFS);
+	}
+	
+	return journal_start(journal, nblocks);
 }
 
 static inline handle_t *
diff -urN linux-2.4.17-pre5/include/linux/highmem.h linux/include/linux/highmem.h
--- linux-2.4.17-pre5/include/linux/highmem.h	Thu Nov 22 11:46:23 2001
+++ linux/include/linux/highmem.h	Fri Dec  7 14:53:08 2001
@@ -93,15 +93,4 @@
 	kunmap_atomic(vto, KM_USER1);
 }
 
-static inline void copy_highpage(struct page *to, struct page *from)
-{
-	char *vfrom, *vto;
-
-	vfrom = kmap(from);
-	vto = kmap(to);
-	copy_page(vto, vfrom);
-	kunmap(from);
-	kunmap(to);
-}
-
 #endif /* _LINUX_HIGHMEM_H */
diff -urN linux-2.4.17-pre5/include/linux/init.h linux/include/linux/init.h
--- linux-2.4.17-pre5/include/linux/init.h	Thu Nov 22 11:46:18 2001
+++ linux/include/linux/init.h	Fri Dec  7 14:53:08 2001
@@ -111,7 +111,7 @@
  */
 #define module_exit(x)	__exitcall(x);
 
-#else
+#else	/* MODULE */
 
 #define __init
 #define __exit
@@ -141,7 +141,7 @@
 
 #define __setup(str,func) /* nothing */
 
-#endif
+#endif	/* !MODULE */
 
 #ifdef CONFIG_HOTPLUG
 #define __devinit
@@ -153,6 +153,18 @@
 #define __devinitdata __initdata
 #define __devexit __exit
 #define __devexitdata __exitdata
+#endif
+
+/* Functions marked as __devexit may be discarded at kernel link time, depending
+   on config options.  Newer versions of binutils detect references from
+   retained sections to discarded sections and flag an error.  Pointers to
+   __devexit functions must use __devexit_p(function_name), the wrapper will
+   insert either the function_name or NULL, depending on the config options.
+ */
+#if defined(MODULE) || defined(CONFIG_HOTPLUG)
+#define __devexit_p(x) x
+#else
+#define __devexit_p(x) NULL
 #endif
 
 #endif /* _LINUX_INIT_H */
diff -urN linux-2.4.17-pre5/include/linux/jbd.h linux/include/linux/jbd.h
--- linux-2.4.17-pre5/include/linux/jbd.h	Fri Dec  7 14:52:27 2001
+++ linux/include/linux/jbd.h	Fri Dec  7 14:53:08 2001
@@ -564,7 +564,7 @@
 
 /* Log buffer allocation */
 extern struct journal_head * journal_get_descriptor_buffer(journal_t *);
-extern unsigned long journal_next_log_block(journal_t *);
+int journal_next_log_block(journal_t *, unsigned long *);
 
 /* Commit management */
 extern void journal_commit_transaction(journal_t *);
@@ -664,15 +664,16 @@
 extern void	   journal_destroy    (journal_t *);
 extern int	   journal_recover    (journal_t *journal);
 extern int	   journal_wipe       (journal_t *, int);
-extern int	   journal_skip_recovery (journal_t *);
-extern void	   journal_update_superblock (journal_t *, int);
-extern void	   __journal_abort      (journal_t *);
+extern int	   journal_skip_recovery	(journal_t *);
+extern void	   journal_update_superblock	(journal_t *, int);
+extern void	   __journal_abort_hard	(journal_t *);
+extern void	   __journal_abort_soft	(journal_t *, int);
 extern void	   journal_abort      (journal_t *, int);
 extern int	   journal_errno      (journal_t *);
 extern void	   journal_ack_err    (journal_t *);
 extern int	   journal_clear_err  (journal_t *);
-extern unsigned long journal_bmap(journal_t *journal, unsigned long blocknr);
-extern int	    journal_force_commit(journal_t *journal);
+extern int	   journal_bmap(journal_t *, unsigned long, unsigned long *);
+extern int	   journal_force_commit(journal_t *);
 
 /*
  * journal_head management
diff -urN linux-2.4.17-pre5/include/linux/list.h linux/include/linux/list.h
--- linux-2.4.17-pre5/include/linux/list.h	Thu Nov 22 11:46:19 2001
+++ linux/include/linux/list.h	Fri Dec  7 14:53:08 2001
@@ -162,6 +162,16 @@
 	for (pos = (head)->next, n = pos->next; pos != (head); \
 		pos = n, n = pos->next)
 
+/**
+ * list_for_each_prev	-	iterate over a list in reverse order
+ * @pos:	the &struct list_head to use as a loop counter.
+ * @head:	the head for your list.
+ */
+#define list_for_each_prev(pos, head) \
+	for (pos = (head)->prev, prefetch(pos->prev); pos != (head); \
+        	pos = pos->prev, prefetch(pos->prev))
+        	
+
 #endif /* __KERNEL__ || _LVM_H_INCLUDE */
 
 #endif
diff -urN linux-2.4.17-pre5/include/linux/mm.h linux/include/linux/mm.h
--- linux-2.4.17-pre5/include/linux/mm.h	Fri Dec  7 14:52:27 2001
+++ linux/include/linux/mm.h	Fri Dec  7 14:53:08 2001
@@ -422,6 +422,9 @@
 extern void ptrace_disable(struct task_struct *);
 extern int ptrace_check_attach(struct task_struct *task, int kill);
 
+int get_user_pages(struct task_struct *tsk, struct mm_struct *mm, unsigned long start,
+		int len, int write, int force, struct page **pages, struct vm_area_struct **vmas);
+
 /*
  * On a two-level page table, this ends up being trivial. Thus the
  * inlining and the symmetry break with pte_alloc() that does all
diff -urN linux-2.4.17-pre5/include/linux/nfs_fs.h linux/include/linux/nfs_fs.h
--- linux-2.4.17-pre5/include/linux/nfs_fs.h	Thu Nov 22 11:47:00 2001
+++ linux/include/linux/nfs_fs.h	Fri Dec  7 14:53:08 2001
@@ -16,6 +16,7 @@
 
 #include <linux/sunrpc/debug.h>
 #include <linux/sunrpc/auth.h>
+#include <linux/sunrpc/clnt.h>
 
 #include <linux/nfs.h>
 #include <linux/nfs2.h>
@@ -331,6 +332,29 @@
 		wait_event(wq, condition);				\
 	__retval;							\
 })
+
+#ifdef CONFIG_NFS_V3
+
+#define NFS_JUKEBOX_RETRY_TIME (5 * HZ)
+static inline int
+nfs_async_handle_jukebox(struct rpc_task *task)
+{
+	if (task->tk_status != -EJUKEBOX)
+		return 0;
+	task->tk_status = 0;
+	rpc_restart_call(task);
+	rpc_delay(task, NFS_JUKEBOX_RETRY_TIME);
+	return 1;
+}
+
+#else
+
+static inline int
+nfs_async_handle_jukebox(struct rpc_task *task)
+{
+	return 0;
+}
+#endif /* CONFIG_NFS_V3 */
 
 #endif /* __KERNEL__ */
 
diff -urN linux-2.4.17-pre5/kernel/ptrace.c linux/kernel/ptrace.c
--- linux-2.4.17-pre5/kernel/ptrace.c	Wed Nov 21 14:43:01 2001
+++ linux/kernel/ptrace.c	Fri Dec  7 14:53:08 2001
@@ -121,119 +121,17 @@
 }
 
 /*
- * Access another process' address space, one page at a time.
+ * Access another process' address space.
+ * Source/target buffer must be kernel space, 
+ * Do not walk the page table directly, use get_user_pages
  */
-static int access_one_page(struct mm_struct * mm, struct vm_area_struct * vma, unsigned long addr, void *buf, int len, int write)
-{
-	pgd_t * pgdir;
-	pmd_t * pgmiddle;
-	pte_t * pgtable;
-	char *maddr; 
-	struct page *page;
-
-repeat:
-	spin_lock(&mm->page_table_lock);
-	pgdir = pgd_offset(vma->vm_mm, addr);
-	if (pgd_none(*pgdir))
-		goto fault_in_page;
-	if (pgd_bad(*pgdir))
-		goto bad_pgd;
-	pgmiddle = pmd_offset(pgdir, addr);
-	if (pmd_none(*pgmiddle))
-		goto fault_in_page;
-	if (pmd_bad(*pgmiddle))
-		goto bad_pmd;
-	pgtable = pte_offset(pgmiddle, addr);
-	if (!pte_present(*pgtable))
-		goto fault_in_page;
-	if (write && (!pte_write(*pgtable) || !pte_dirty(*pgtable)))
-		goto fault_in_page;
-	page = pte_page(*pgtable);
-
-	/* ZERO_PAGE is special: reads from it are ok even though it's marked reserved */
-	if (page != ZERO_PAGE(addr) || write) {
-		if ((!VALID_PAGE(page)) || PageReserved(page)) {
-			spin_unlock(&mm->page_table_lock);
-			return 0;
-		}
-	}
-	get_page(page);
-	spin_unlock(&mm->page_table_lock);
-	flush_cache_page(vma, addr);
-
-	if (write) {
-		maddr = kmap(page);
-		memcpy(maddr + (addr & ~PAGE_MASK), buf, len);
-		flush_page_to_ram(page);
-		flush_icache_page(vma, page);
-		kunmap(page);
-	} else {
-		maddr = kmap(page);
-		memcpy(buf, maddr + (addr & ~PAGE_MASK), len);
-		flush_page_to_ram(page);
-		kunmap(page);
-	}
-	put_page(page);
-	return len;
-
-fault_in_page:
-	spin_unlock(&mm->page_table_lock);
-	/* -1: out of memory. 0 - unmapped page */
-	if (handle_mm_fault(mm, vma, addr, write) > 0)
-		goto repeat;
-	return 0;
-
-bad_pgd:
-	spin_unlock(&mm->page_table_lock);
-	pgd_ERROR(*pgdir);
-	return 0;
-
-bad_pmd:
-	spin_unlock(&mm->page_table_lock);
-	pmd_ERROR(*pgmiddle);
-	return 0;
-}
-
-static int access_mm(struct mm_struct *mm, struct vm_area_struct * vma, unsigned long addr, void *buf, int len, int write)
-{
-	int copied = 0;
-
-	for (;;) {
-		unsigned long offset = addr & ~PAGE_MASK;
-		int this_len = PAGE_SIZE - offset;
-		int retval;
-
-		if (this_len > len)
-			this_len = len;
-		retval = access_one_page(mm, vma, addr, buf, this_len, write);
-		copied += retval;
-		if (retval != this_len)
-			break;
-
-		len -= retval;
-		if (!len)
-			break;
-
-		addr += retval;
-		buf += retval;
-
-		if (addr < vma->vm_end)
-			continue;	
-		if (!vma->vm_next)
-			break;
-		if (vma->vm_next->vm_start != vma->vm_end)
-			break;
-	
-		vma = vma->vm_next;
-	}
-	return copied;
-}
 
 int access_process_vm(struct task_struct *tsk, unsigned long addr, void *buf, int len, int write)
 {
-	int copied;
 	struct mm_struct *mm;
-	struct vm_area_struct * vma;
+	struct vm_area_struct *vma;
+	struct page *page;
+	void *old_buf = buf;
 
 	/* Worry about races with exit() */
 	task_lock(tsk);
@@ -245,14 +143,41 @@
 		return 0;
 
 	down_read(&mm->mmap_sem);
-	vma = find_extend_vma(mm, addr);
-	copied = 0;
-	if (vma)
-		copied = access_mm(mm, vma, addr, buf, len, write);
+	/* ignore errors, just check how much was sucessfully transfered */
+	while (len) {
+		int bytes, ret, offset;
+		void *maddr;
+
+		ret = get_user_pages(current, mm, addr, 1,
+				write, 1, &page, &vma);
+		if (ret <= 0)
+			break;
+
+		bytes = len;
+		offset = addr & (PAGE_SIZE-1);
+		if (bytes > PAGE_SIZE-offset)
+			bytes = PAGE_SIZE-offset;
 
+		flush_cache_page(vma, addr);
+
+		maddr = kmap(page);
+		if (write) {
+			memcpy(maddr + offset, buf, bytes);
+			flush_page_to_ram(page);
+			flush_icache_page(vma, page);
+		} else {
+			memcpy(buf, maddr + offset, bytes);
+			flush_page_to_ram(page);
+		}
+		kunmap(page);
+		put_page(page);
+		len -= bytes;
+		buf += bytes;
+	}
 	up_read(&mm->mmap_sem);
 	mmput(mm);
-	return copied;
+	
+	return buf - old_buf;
 }
 
 int ptrace_readdata(struct task_struct *tsk, unsigned long src, char *dst, int len)
diff -urN linux-2.4.17-pre5/mm/filemap.c linux/mm/filemap.c
--- linux-2.4.17-pre5/mm/filemap.c	Mon Nov 26 05:29:17 2001
+++ linux/mm/filemap.c	Fri Dec  7 14:53:08 2001
@@ -53,7 +53,7 @@
 EXPORT_SYMBOL(vm_min_readahead);
 
 
-spinlock_t pagecache_lock ____cacheline_aligned_in_smp = SPIN_LOCK_UNLOCKED;
+spinlock_t pagecache_lock __cacheline_aligned_in_smp = SPIN_LOCK_UNLOCKED;
 /*
  * NOTE: to avoid deadlocking you must never acquire the pagemap_lru_lock 
  *	with the pagecache_lock held.
@@ -63,7 +63,7 @@
  *		pagemap_lru_lock ->
  *			pagecache_lock
  */
-spinlock_t pagemap_lru_lock ____cacheline_aligned_in_smp = SPIN_LOCK_UNLOCKED;
+spinlock_t pagemap_lru_lock __cacheline_aligned_in_smp = SPIN_LOCK_UNLOCKED;
 
 #define CLUSTER_PAGES		(1 << page_cluster)
 #define CLUSTER_OFFSET(x)	(((x) >> page_cluster) << page_cluster)
diff -urN linux-2.4.17-pre5/mm/highmem.c linux/mm/highmem.c
--- linux-2.4.17-pre5/mm/highmem.c	Mon Oct 22 15:01:57 2001
+++ linux/mm/highmem.c	Fri Dec  7 14:53:08 2001
@@ -32,7 +32,7 @@
  */
 static int pkmap_count[LAST_PKMAP];
 static unsigned int last_pkmap_nr;
-static spinlock_t kmap_lock = SPIN_LOCK_UNLOCKED;
+static spinlock_t kmap_lock __cacheline_aligned_in_smp = SPIN_LOCK_UNLOCKED;
 
 pte_t * pkmap_page_table;
 
diff -urN linux-2.4.17-pre5/mm/memory.c linux/mm/memory.c
--- linux-2.4.17-pre5/mm/memory.c	Fri Dec  7 14:52:27 2001
+++ linux/mm/memory.c	Fri Dec  7 14:53:08 2001
@@ -397,17 +397,16 @@
 	spin_unlock(&mm->page_table_lock);
 }
 
-
 /*
  * Do a quick page-table lookup for a single page. 
  */
-static struct page * follow_page(unsigned long address, int write) 
+static struct page * follow_page(struct mm_struct *mm, unsigned long address, int write) 
 {
 	pgd_t *pgd;
 	pmd_t *pmd;
 	pte_t *ptep, pte;
 
-	pgd = pgd_offset(current->mm, address);
+	pgd = pgd_offset(mm, address);
 	if (pgd_none(*pgd) || pgd_bad(*pgd))
 		goto out;
 
@@ -443,21 +442,74 @@
 	return page;
 }
 
+int get_user_pages(struct task_struct *tsk, struct mm_struct *mm, unsigned long start,
+		int len, int write, int force, struct page **pages, struct vm_area_struct **vmas)
+{
+	int i = 0;
+
+	do {
+		struct vm_area_struct *	vma;
+
+		vma = find_extend_vma(mm, start);
+
+		if ( !vma ||
+		    (!force &&
+		     	((write && (!(vma->vm_flags & VM_WRITE))) ||
+		    	 (!write && (!(vma->vm_flags & VM_READ))) ) )) {
+			if (i) return i;
+			return -EFAULT;
+		}
+
+		spin_lock(&mm->page_table_lock);
+		do {
+			struct page *map;
+			while (!(map = follow_page(mm, start, write))) {
+				spin_unlock(&mm->page_table_lock);
+				switch (handle_mm_fault(mm, vma, start, write)) {
+				case 1:
+					tsk->min_flt++;
+					break;
+				case 2:
+					tsk->maj_flt++;
+					break;
+				case 0:
+					if (i) return i;
+					return -EFAULT;
+				default:
+					if (i) return i;
+					return -ENOMEM;
+				}
+				spin_lock(&mm->page_table_lock);
+			}
+			if (pages) {
+				pages[i] = get_page_map(map);
+				/* FIXME: call the correct function,
+				 * depending on the type of the found page
+				 */
+				if (pages[i])
+					page_cache_get(pages[i]);
+			}
+			if (vmas)
+				vmas[i] = vma;
+			i++;
+			start += PAGE_SIZE;
+			len--;
+		} while(len && start < vma->vm_end);
+		spin_unlock(&mm->page_table_lock);
+	} while(len);
+	return i;
+}
+
 /*
  * Force in an entire range of pages from the current process's user VA,
  * and pin them in physical memory.  
  */
-
 #define dprintk(x...)
+
 int map_user_kiobuf(int rw, struct kiobuf *iobuf, unsigned long va, size_t len)
 {
-	unsigned long		ptr, end;
-	int			err;
+	int pgcount, err;
 	struct mm_struct *	mm;
-	struct vm_area_struct *	vma = 0;
-	struct page *		map;
-	int			i;
-	int			datain = (rw == READ);
 	
 	/* Make sure the iobuf is not already mapped somewhere. */
 	if (iobuf->nr_pages)
@@ -466,79 +518,37 @@
 	mm = current->mm;
 	dprintk ("map_user_kiobuf: begin\n");
 	
-	ptr = va & PAGE_MASK;
-	end = (va + len + PAGE_SIZE - 1) & PAGE_MASK;
-	err = expand_kiobuf(iobuf, (end - ptr) >> PAGE_SHIFT);
+	pgcount = (va + len + PAGE_SIZE - 1)/PAGE_SIZE - va/PAGE_SIZE;
+	/* mapping 0 bytes is not permitted */
+	if (!pgcount) BUG();
+	err = expand_kiobuf(iobuf, pgcount);
 	if (err)
 		return err;
 
-	down_read(&mm->mmap_sem);
-
-	err = -EFAULT;
 	iobuf->locked = 0;
-	iobuf->offset = va & ~PAGE_MASK;
+	iobuf->offset = va & (PAGE_SIZE-1);
 	iobuf->length = len;
 	
-	i = 0;
-	
-	/* 
-	 * First of all, try to fault in all of the necessary pages
-	 */
-	while (ptr < end) {
-		if (!vma || ptr >= vma->vm_end) {
-			vma = find_vma(current->mm, ptr);
-			if (!vma) 
-				goto out_unlock;
-			if (vma->vm_start > ptr) {
-				if (!(vma->vm_flags & VM_GROWSDOWN))
-					goto out_unlock;
-				if (expand_stack(vma, ptr))
-					goto out_unlock;
-			}
-			if (((datain) && (!(vma->vm_flags & VM_WRITE))) ||
-					(!(vma->vm_flags & VM_READ))) {
-				err = -EACCES;
-				goto out_unlock;
-			}
-		}
-		spin_lock(&mm->page_table_lock);
-		while (!(map = follow_page(ptr, datain))) {
-			int ret;
-
-			spin_unlock(&mm->page_table_lock);
-			ret = handle_mm_fault(current->mm, vma, ptr, datain);
-			if (ret <= 0) {
-				if (!ret)
-					goto out_unlock;
-				else {
-					err = -ENOMEM;
-					goto out_unlock;
-				}
-			}
-			spin_lock(&mm->page_table_lock);
-		}			
-		map = get_page_map(map);
-		if (map) {
-			flush_dcache_page(map);
-			page_cache_get(map);
-		} else
-			printk (KERN_INFO "Mapped page missing [%d]\n", i);
-		spin_unlock(&mm->page_table_lock);
-		iobuf->maplist[i] = map;
-		iobuf->nr_pages = ++i;
-		
-		ptr += PAGE_SIZE;
-	}
-
+	/* Try to fault in all of the necessary pages */
+	down_read(&mm->mmap_sem);
+	/* rw==READ means read from disk, write into memory area */
+	err = get_user_pages(current, mm, va, pgcount,
+			(rw==READ), 0, iobuf->maplist, NULL);
 	up_read(&mm->mmap_sem);
+	if (err < 0) {
+		unmap_kiobuf(iobuf);
+		dprintk ("map_user_kiobuf: end %d\n", err);
+		return err;
+	}
+	iobuf->nr_pages = err;
+	while (pgcount--) {
+		/* FIXME: flush superflous for rw==READ,
+		 * probably wrong function for rw==WRITE
+		 */
+		flush_dcache_page(iobuf->maplist[pgcount]);
+	}
 	dprintk ("map_user_kiobuf: end OK\n");
 	return 0;
-
- out_unlock:
-	up_read(&mm->mmap_sem);
-	unmap_kiobuf(iobuf);
-	dprintk ("map_user_kiobuf: end %d\n", err);
-	return err;
 }
 
 /*
@@ -588,6 +598,9 @@
 		if (map) {
 			if (iobuf->locked)
 				UnlockPage(map);
+			/* FIXME: cache flush missing for rw==READ
+			 * FIXME: call the correct reference counting function
+			 */
 			page_cache_release(map);
 		}
 	}
@@ -1220,7 +1233,7 @@
 		struct page * page = alloc_page(GFP_HIGHUSER);
 		if (!page)
 			return -1;
-		copy_highpage(page, new_page);
+		copy_user_highpage(page, new_page, address);
 		page_cache_release(new_page);
 		lru_cache_add(page);
 		new_page = page;
@@ -1409,23 +1422,19 @@
 	return pte_offset(pmd, address);
 }
 
-/*
- * Simplistic page force-in..
- */
 int make_pages_present(unsigned long addr, unsigned long end)
 {
-	int write;
-	struct mm_struct *mm = current->mm;
+	int ret, len, write;
 	struct vm_area_struct * vma;
 
-	vma = find_vma(mm, addr);
+	vma = find_vma(current->mm, addr);
 	write = (vma->vm_flags & VM_WRITE) != 0;
 	if (addr >= end)
 		BUG();
-	do {
-		if (handle_mm_fault(mm, vma, addr, write) < 0)
-			return -1;
-		addr += PAGE_SIZE;
-	} while (addr < end);
-	return 0;
+	if (end > vma->vm_end)
+		BUG();
+	len = (end+PAGE_SIZE-1)/PAGE_SIZE-addr/PAGE_SIZE;
+	ret = get_user_pages(current, current->mm, addr,
+			len, write, 0, NULL, NULL);
+	return ret == len ? 0 : -1;
 }
diff -urN linux-2.4.17-pre5/mm/vmalloc.c linux/mm/vmalloc.c
--- linux-2.4.17-pre5/mm/vmalloc.c	Mon Sep 17 13:16:31 2001
+++ linux/mm/vmalloc.c	Fri Dec  7 14:53:08 2001
@@ -6,6 +6,7 @@
  *  SMP-safe vmalloc/vfree/ioremap, Tigran Aivazian <tigran@veritas.com>, May 2000
  */
 
+#include <linux/config.h>
 #include <linux/slab.h>
 #include <linux/vmalloc.h>
 #include <linux/spinlock.h>
@@ -273,6 +274,43 @@
 			if (count == 0)
 				goto finished;
 			*buf = *addr;
+			buf++;
+			addr++;
+			count--;
+		} while (--n > 0);
+	}
+finished:
+	read_unlock(&vmlist_lock);
+	return buf - buf_start;
+}
+
+long vwrite(char *buf, char *addr, unsigned long count)
+{
+	struct vm_struct *tmp;
+	char *vaddr, *buf_start = buf;
+	unsigned long n;
+
+	/* Don't allow overflow */
+	if ((unsigned long) addr + count < count)
+		count = -(unsigned long) addr;
+
+	read_lock(&vmlist_lock);
+	for (tmp = vmlist; tmp; tmp = tmp->next) {
+		vaddr = (char *) tmp->addr;
+		if (addr >= vaddr + tmp->size - PAGE_SIZE)
+			continue;
+		while (addr < vaddr) {
+			if (count == 0)
+				goto finished;
+			buf++;
+			addr++;
+			count--;
+		}
+		n = vaddr + tmp->size - PAGE_SIZE - addr;
+		do {
+			if (count == 0)
+				goto finished;
+			*addr = *buf;
 			buf++;
 			addr++;
 			count--;
