diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/CREDITS linux-2.4.28-pre3/CREDITS
--- linux-2.4.27/CREDITS	2004-08-07 23:26:04.000000000 +0000
+++ linux-2.4.28-pre3/CREDITS	2004-09-10 19:35:58.000000000 +0000
@@ -2130,14 +2130,13 @@ S: 7546 JA  Enschede
 S: Netherlands
 
 N: David S. Miller
-E: davem@redhat.com
+E: davem@davemloft.net
 D: Sparc and blue box hacker
 D: Vger Linux mailing list co-maintainer
 D: Linux Emacs elf/qmagic support + other libc/gcc things
 D: Yee bore de yee bore! ;-)
-S: 750 N. Shoreline Blvd.
-S: Apt. #111
-S: Mountain View, California 94043
+S: 575 Harrison St. #103
+S: San Francisco, California 94105
 S: USA
 
 N: Rick Miller
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/Documentation/Configure.help linux-2.4.28-pre3/Documentation/Configure.help
--- linux-2.4.27/Documentation/Configure.help	2004-08-07 23:26:04.000000000 +0000
+++ linux-2.4.28-pre3/Documentation/Configure.help	2004-09-10 19:36:53.000000000 +0000
@@ -696,6 +696,24 @@ CONFIG_BLK_DEV_IDE
   could say N here, and select the "Old hard disk driver" below
   instead to save about 13 KB of memory in the kernel.
 
+Support for SATA (deprecated; conflicts with libata SATA driver)
+CONFIG_BLK_DEV_IDE_SATA
+  There are two drivers for Serial ATA controllers.
+
+  The main driver, "libata", exists inside the SCSI subsystem
+  and supports most modern SATA controllers.
+
+  The IDE driver (which you are currently configuring) supports
+  a few first-generation SATA controllers.
+
+  In order to eliminate conflicts between the two subsystems,
+  this config option enables the IDE driver's SATA support.
+  Normally this is disabled, as it is preferred that libata
+  supports SATA controllers, and this (IDE) driver supports
+  PATA controllers.
+
+  If unsure, say N.
+
 Old hard disk (MFM/RLL/IDE) driver
 CONFIG_BLK_DEV_HD_ONLY
   There are two drivers for MFM/RLL/IDE hard disks. Most people use
@@ -4678,12 +4696,6 @@ CONFIG_BINFMT_ELF
   ld.so (check the file <file:Documentation/Changes> for location and
   latest version).
 
-  If you want to compile this as a module ( = code which can be
-  inserted in and removed from the running kernel whenever you want),
-  say M here and read <file:Documentation/modules.txt>.  The module
-  will be called binfmt_elf.o. Saying M or N here is dangerous because
-  some crucial programs on your system might be in ELF format.
-
 Kernel support for a.out binaries
 CONFIG_BINFMT_AOUT
   A.out (Assembler.OUTput) is a set of formats for libraries and
@@ -7953,7 +7965,7 @@ CONFIG_SCSI_LOGGING
 QDIO base support for IBM S/390 and zSeries
 CONFIG_QDIO
   This driver provides the Queued Direct I/O base support for the
-  IBM S/390 (G5 and G6) and eServer zSeries (z800 and z900).
+  IBM S/390 (G5 and G6) and eServer zSeries (z800, z900 and z990).
 
   For details please refer to the documentation provided by IBM at
   <http://www10.software.ibm.com/developerworks/opensource/linux390>
@@ -7971,6 +7983,37 @@ CONFIG_QDIO_PERF_STATS
 
   If unsure, say N.
 
+IBM S/390 and zSeries OSA-Express and HiperSockets device driver
+CONFIG_QETH
+  This driver supports the IBM S/390 and zSeries OSA Express adapters
+  in QDIO mode (all media types), HiperSockets interfaces and VM GuestLAN
+  interfaces in QDIO and HIPER mode.
+
+  For details please refer to the documentation provided by IBM at
+  <http://www10.software.ibm.com/developerworks/opensource/linux390>
+
+  This driver is also available as a module (code which can be
+  inserted in and removed from the running kernel whenever you
+  want). If you want to compile it as a module, say 'M' here and
+  read file Documentation/modules.txt.
+
+IPv6 support for qeth
+CONFIG_QETH_IPV6
+  If CONFIG_QETH is switched on, this option will include IPv6
+  support in the qeth device driver.
+
+IEEE 802.1q VLAN support for qeth
+CONFIG_QETH_VLAN
+  If CONFIG_QETH is switched on, this option will include IEEE
+  802.1q VLAN support in the qeth device driver.
+
+Performance statistics for the qeth drivers
+CONFIG_QETH_PERF_STATS
+  When switched on, this option will add a file in the proc-fs
+  (/proc/qeth_perf_stats) containing performance statistics. It
+  may slightly impact performance, so this is only recommended for
+  internal tuning of the device driver.
+
 SGI WD93C93 SCSI Driver
 CONFIG_SCSI_SGIWD93
   Say Y here to support the on-board WD93C93 SCSI controller found (a)
@@ -9281,6 +9324,16 @@ CONFIG_SCSI_SATA_SVW
 
   If unsure, say N.
 
+CONFIG_SCSI_ATA_PIIX
+  This option enables support for ICH5 Serial ATA.
+
+  If unsure, say N.
+
+CONFIG_SCSI_SATA_NV
+  This option enables support for NVIDIA Serial ATA.
+
+  If unsure, say N.
+
 CONFIG_SCSI_SATA_PROMISE
   This option enables support for Promise Serial ATA TX2/TX4.
 
@@ -10077,6 +10130,49 @@ CONFIG_AIRONET4500_CS
   compile it as a module, say M here and read
   <file:Documentation/modules.txt>.
 
+Intersil 802.11(a/b/g) Prism GT/Duette/Indigo support
+CONFIG_PRISM54
+  Enable PCI and Cardbus support for the following chipset based cards:
+
+  ISL3880 - Prism GT		802.11 b/g
+  ISL3877 - Prism Indigo	802.11 a
+  ISL3890 - Prism Duette	802.11 a/b/g
+  
+  For a complete list of supported cards visit <http://prism54.org>.
+  Here is the latest confirmed list of supported cards:
+
+  3com OfficeConnect 11g Cardbus Card aka 3CRWE154G72
+  Allnet ALL0271 PCI Card
+  Compex WL54G Cardbus Card
+  Corega CG-WLCB54GT Cardbus Card
+  D-Link Air Plus Xtreme G A1 Cardbus Card aka DWL-g650
+  I-O Data WN-G54/CB Cardbus Card
+  Kobishi XG-300 aka Z-Com Cardbus Card
+  Netgear WG511 Cardbus Card
+  Ovislink WL-5400PCI PCI Card
+  Peabird WLG-PCI PCI Card
+  Sitecom WL-100i Cardbus Card
+  Sitecom WL-110i PCI Card
+  SMC2802W - EZ Connect g 2.4GHz 54 Mbps Wireless PCI Card
+  SMC2835W - EZ Connect g 2.4GHz 54 Mbps Wireless Cardbus Card
+  Z-Com XG-900 PCI Card
+  Zyxel G-100 Cardbus Card
+
+  If you enable this, you require a firmware file as well.
+  You will need to copy this to /usr/lib/hotplug/firmware/isl3890.
+  You can get this non-GPL'd firmware file from the Prism54 project page:
+  <http://prism54.org>.
+  You will also need the /etc/hotplug/firmware.agent script from
+  a current hotplug package.
+
+
+  Note: You need a motherboard with DMA support to use any of these cards 
+  
+  If you want to compile the driver as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want),
+  say M here and read <file:Documentation/modules.txt>.  The module
+  will be called prism54.o.
+
 Aironet 4500/4800 PROC interface
 CONFIG_AIRONET4500_PROC
   If you say Y here (and to the "/proc file system" below), you will
@@ -17211,10 +17307,11 @@ CONFIG_NFSD_V3
   If you would like to include the NFSv3 server as well as the NFSv2
   server, say Y here.  If unsure, say Y.
 
-Provide NFS over TCP server support EXPERIMENTAL
+Provide NFS over TCP server support
 CONFIG_NFSD_TCP
-  Enable NFS service over TCP connections.  This the officially
-  still experimental, but seems to work well.
+  If you want your NFS server to support TCP connections, say Y here.
+  TCP connections usually perform better than the default UDP when
+  the network is lossy or congested.  If unsure, say Y.
 
 OS/2 HPFS file system support
 CONFIG_HPFS_FS
@@ -25344,13 +25441,13 @@ CONFIG_S390_PARTITION
 Support for DASD hard disks
 CONFIG_DASD
   Enable this option if you want to access DASDs directly utilizing
-  S/390s channel subsystem commands. This is necessary for running
+  S/390's or zSeries' channel subsystem commands. This is necessary for running
   natively on a single image or an LPAR.
 
 Support for ECKD hard disks
 CONFIG_DASD_ECKD
   ECKD (Extended Count Key Data) devices are the most commonly used 
-  devices on S/390s. You should enable this option unless you are 
+  devices on zSeries and S/390. You should enable this option unless you are
   very sure you have no ECKD device.
 
 ECKD demand loading
@@ -28864,6 +28961,18 @@ CONFIG_CRYPTO_SHA512
   This code also includes SHA-384, a 384 bit hash with 192 bits
   of security against collision attacks.
 
+CONFIG_CRYPTO_WHIRLPOOL
+  Whirlpool hash algorithm.
+
+  Whirlpool is part of the NESSIE cryptographic primtives.
+  Whirlpool works on messages shorter than 2^256 bits and
+  produces a 512 bit hash.
+
+  Whirlpool will be part of the ISO/IEC 10118-3:2003(E) standard
+
+  See also:
+  http://planeta.terra.com.br/informatica/paulobarreto/WhirlpoolPage.html
+
 CONFIG_CRYPTO_DES
   DES cipher algorithm (FIPS 46-2), and Triple DES EDE (FIPS 46-3).
 
@@ -28932,7 +29041,7 @@ CONFIG_CRYPTO_TEA
   many rounds for security.  It is very fast and uses
   little memory.
 
-  Xtendend Tiny Encryption Algorithm is a modifcation to
+  Xtendend Tiny Encryption Algorithm is a modification to
   the TEA algorithm to address a potential key weakness
   in the TEA algorithm.
 
@@ -28944,6 +29053,16 @@ CONFIG_CRYPTO_ARC4
   WEP, but it should not be for other purposes because of the
   weakness of the algorithm.
 
+CONFIG_CRYPTO_KHAZAD
+  Khazad cipher algorithm.
+
+  Khazad was a finalist in the initial NESSIE competition.  It is
+  an algorithm optimized for 64-bit processors with good performance
+  on 32-bit processors.  Khazad uses an 128 bit key size.
+
+  See also:
+  http://planeta.terra.com.br/informatica/paulobarreto/KhazadPage.html
+
 CONFIG_CRYPTO_DEFLATE
   This is the Deflate algorithm (RFC1951), specified for use in
   IPSec with the IPCOMP protocol (RFC3173, RFC2394).
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/Documentation/crypto/api-intro.txt linux-2.4.28-pre3/Documentation/crypto/api-intro.txt
--- linux-2.4.27/Documentation/crypto/api-intro.txt	2004-08-07 23:26:04.000000000 +0000
+++ linux-2.4.28-pre3/Documentation/crypto/api-intro.txt	2004-09-10 19:37:20.000000000 +0000
@@ -219,6 +219,15 @@ AES algorithm contributors:
 CAST5/CAST6 algorithm contributors:
   Kartikey Mahendra Bhatt (original developers unknown, FSF copyright).
 
+TEA/XTEA algorithm contributors:
+  Aaron Grothe
+
+Khazad algorithm contributors:
+  Aaron Grothe
+
+Whirlpool algorithm contributors:
+  Aaron Grothe
+
 Generic scatterwalk code by Adam J. Richter <adam@yggdrasil.com>
 
 Please send any credits updates or corrections to:
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/Documentation/filesystems/xfs.txt linux-2.4.28-pre3/Documentation/filesystems/xfs.txt
--- linux-2.4.27/Documentation/filesystems/xfs.txt	2004-08-07 23:26:04.000000000 +0000
+++ linux-2.4.28-pre3/Documentation/filesystems/xfs.txt	2004-09-10 19:33:06.000000000 +0000
@@ -120,19 +120,19 @@ The following sysctls are available for 
 
   fs.xfs.stats_clear		(Min: 0  Default: 0  Max: 1)
 	Setting this to "1" clears accumulated XFS statistics 
-	in /proc/fs/xfs/stat.  It then immediately reset to "0".
+	in /proc/fs/xfs/stat.  It then immediately resets to "0".
   	
-  fs.xfs.sync_interval		(Min: HZ  Default: 30*HZ  Max: 60*HZ)
+  fs.xfs.xfssyncd_centisecs	(Min: 100  Default: 3000  Max: 6000)
 	The interval at which the xfssyncd thread flushes metadata
 	out to disk.  This thread will flush log activity out, and
 	do some processing on unlinked inodes.
 
-  fs.xfs.age_buffer             (Min: 1*HZ  Default: 15*HZ  Max: 300*HZ)
-	The age at which xfsbufd flushes dirty metadata buffers to disk.
-
-  fs.xfs.flush_interval         (Min: HZ/2  Default: HZ  Max: 30*HZ)
+  fs.xfs.xfsbufd_centisecs	(Min: 50  Default: 100  Max: 3000)
 	The interval at which xfsbufd scans the dirty metadata buffers list.
 
+  fs.xfs.age_buffer_centisecs	(Min: 100  Default: 1500  Max: 30000)
+	The age at which xfsbufd flushes dirty metadata buffers to disk.
+
   fs.xfs.error_level		(Min: 0  Default: 3  Max: 11)
 	A volume knob for error reporting when internal errors occur.
 	This will generate detailed messages & backtraces for filesystem
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/Documentation/ftape.txt linux-2.4.28-pre3/Documentation/ftape.txt
--- linux-2.4.27/Documentation/ftape.txt	1999-11-06 18:38:40.000000000 +0000
+++ linux-2.4.28-pre3/Documentation/ftape.txt	2004-09-10 19:32:23.000000000 +0000
@@ -15,7 +15,7 @@ as a feature or bug of zftape).
 
 ftape has a home page at
 
-http://www-math.math.rwth-aachen.de/~LBFM/claus/ftape
+http://www.instmath.rwth-aachen.de/~heine/ftape/
 
 which contains further information about ftape. Please cross check
 this WWW address against the address given (if any) in the MAINTAINERS
@@ -58,7 +58,7 @@ changed. Up to date documentation as wel
 versions of ftape and useful links to related topics can be found at
 the ftape home page at
 
-http://www-math.math.rwth-aachen.de/~LBFM/claus/ftape
+http://www.instmath.rwth-aachen.de/~heine/ftape/
 
 *******************************************************************************
 
@@ -132,7 +132,7 @@ A. Changes
 
    or from the ftape home page at
 
-   http://www-math.math.rwth-aachen.de/~LBFM/claus/ftape
+   http://www.instmath.rwth-aachen.de/~heine/ftape/
 
    `ftformat' is contained in the `./contrib/' subdirectory of that
    separate ftape package.
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/Documentation/isdn/CREDITS linux-2.4.28-pre3/Documentation/isdn/CREDITS
--- linux-2.4.27/Documentation/isdn/CREDITS	2000-02-15 19:40:42.000000000 +0000
+++ linux-2.4.28-pre3/Documentation/isdn/CREDITS	2004-09-10 19:32:41.000000000 +0000
@@ -37,7 +37,7 @@ Michael Knigge (knick@cove.han.de)
 Andreas Kool (akool@Kool.f.EUnet.de)
   For contribution of the isdnlog/isdnrep-tool
 
-Pedro Roque Marques (roque@di.fc.ul.pt)
+Pedro Roque Marques (pedro_m@yahoo.com)
   For lot of new ideas and the pcbit driver.
 
 Eberhard Moenkeberg (emoenke@gwdg.de)
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/Documentation/isdn/README.pcbit linux-2.4.28-pre3/Documentation/isdn/README.pcbit
--- linux-2.4.27/Documentation/isdn/README.pcbit	1999-11-08 00:34:00.000000000 +0000
+++ linux-2.4.28-pre3/Documentation/isdn/README.pcbit	2004-09-10 19:36:31.000000000 +0000
@@ -37,4 +37,4 @@ mailing list (isdn4linux@listserv.isdn4l
 regards,
   Pedro.
 		
-<roque@di.fc.ul.pt>
+<pedro_m@yahoo.com>
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/MAINTAINERS linux-2.4.28-pre3/MAINTAINERS
--- linux-2.4.27/MAINTAINERS	2004-08-07 23:26:04.000000000 +0000
+++ linux-2.4.28-pre3/MAINTAINERS	2004-09-10 19:35:28.000000000 +0000
@@ -177,10 +177,8 @@ S:	Maintained
 
 AD1816 SOUND DRIVER
 P:	Thorsten Knabe
-M:	Thorsten Knabe <tek@rbg.informatik.tu-darmstadt.de>
-M:	Thorsten Knabe <tek01@hrzpub.tu-darmstadt.de>
-W:	http://www.student.informatik.tu-darmstadt.de/~tek/projects/linux.html
-W:	http://www.tu-darmstadt.de/~tek01/projects/linux.html
+M:	Thorsten Knabe <linux@thorsten-knabe.de>
+W:	http://linux.thorsten-knabe.de
 S:	Maintained
 
 ADVANSYS SCSI DRIVER
@@ -456,14 +454,20 @@ L:	omnibook@zurich.ai.mit.edu
 S:      Maintained
 
 
+HP 66Mhz FIBRE CHANNEL DRIVER
+P:	Chirag Kantharia
+M:	chirag.kantharia@hp.com
+L:	iss_storagedev@hp.com
+S:	Maintained
+
 HP SMART2 RAID DRIVER
-P:     Francis Wiran
-M:     francis.wiran@hp.com
+P:	Chirag Kantharia
+M:	chirag.kantharia@hp.com
 L:     iss_storagedev@hp.com
-S:	Odd Fixes
+S:	Maintained
 
-HP SMART CISS RAID DRIVER
-P:     Mike Miller, Michael Ni
+HP SMART ARRAY CISS RAID DRIVER (cciss)
+P:	Mike Miller
 M:     mike.miller@hp.com
 L:     iss_storagedev@hp.com
 S:	Supported
@@ -530,15 +534,7 @@ CRYPTO API
 P:	James Morris
 M:	jmorris@intercode.com.au
 P:	David S. Miller
-M:	davem@redhat.com
-MARVELL YUKON / SYSKONNECT DRIVER
-P:	Mirko Lindner
-M: 	mlindner@syskonnect.de
-P:	Ralph Roesler
-M: 	rroesler@syskonnect.de
-W: 	http://www.syskonnect.com
-S: 	Supported
-M:	davem@redhat.com
+M:	davem@davemloft.net
 W	http://samba.org/~jamesm/crypto/
 L:	linux-kernel@vger.kernel.org
 S:	Maintained
@@ -1188,6 +1184,14 @@ L:	linux-mips@linux-mips.org
 L:	netdev@oss.sgi.com
 S:	Supported
 
+MARVELL YUKON / SYSKONNECT DRIVER
+P:	Mirko Lindner
+M: 	mlindner@syskonnect.de
+P:	Ralph Roesler
+M: 	rroesler@syskonnect.de
+W: 	http://www.syskonnect.com
+S: 	Supported
+
 MATROX FRAMEBUFFER DRIVER
 P:	Petr Vandrovec
 M:	vandrove@vc.cvut.cz
@@ -1312,7 +1316,7 @@ S:	Maintained
 
 NETWORKING [IPv4/IPv6]
 P:	David S. Miller
-M:	davem@redhat.com
+M:	davem@davemloft.net
 P:	Alexey Kuznetsov
 M:	kuznet@ms2.inr.ac.ru
 P:	Pekka Savola (ipv6)
@@ -1448,9 +1452,8 @@ L:	linux-kernel@vger.kernel.org
 S:	Odd Fixes
 
 PCI HOTPLUG CORE
-P:	Greg Kroah-Hartman
-M:	greg@kroah.com
-M:	gregkh@us.ibm.com
+P:	Gary Hade
+M:	garyhade@us.ibm.com
 S:	Supported
 
 PCI HOTPLUG COMPAQ DRIVER
@@ -1723,7 +1726,7 @@ S:	Maintained
 
 UltraSPARC (sparc64):
 P:	David S. Miller
-M:	davem@redhat.com
+M:	davem@davemloft.net
 P:	Eddie C. Dost
 M:	ecd@skynet.be
 P:	Jakub Jelinek
@@ -1735,8 +1738,8 @@ L:	ultralinux@vger.kernel.org
 S:	Maintained
 
 SPARC (sparc32):
-P:	Keith M. Wesolowski
-M:	wesolows@foobazco.org
+P:	William L. Irwin
+M:	wli@holomorphy.com
 L:	sparclinux@vger.kernel.org
 S:	Maintained
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/Makefile linux-2.4.28-pre3/Makefile
--- linux-2.4.27/Makefile	2004-08-07 23:26:07.000000000 +0000
+++ linux-2.4.28-pre3/Makefile	2004-09-10 19:35:43.000000000 +0000
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 4
-SUBLEVEL = 27
-EXTRAVERSION =
+SUBLEVEL = 28
+EXTRAVERSION = -pre3
 
 KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/alpha/config.in linux-2.4.28-pre3/arch/alpha/config.in
--- linux-2.4.27/arch/alpha/config.in	2004-02-18 13:36:30.000000000 +0000
+++ linux-2.4.28-pre3/arch/alpha/config.in	2004-09-10 19:33:17.000000000 +0000
@@ -314,7 +314,7 @@ if [ "$CONFIG_BINFMT_AOUT" != "n" ]; the
 	bool '  OSF/1 v4 readv/writev compatibility' CONFIG_OSF4_COMPAT
 fi
 
-tristate 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF
+bool 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF
 tristate 'Kernel support for MISC binaries' CONFIG_BINFMT_MISC
 tristate 'Kernel support for Linux/Intel ELF binaries' CONFIG_BINFMT_EM86
 source drivers/parport/Config.in
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/arm/config.in linux-2.4.28-pre3/arch/arm/config.in
--- linux-2.4.27/arch/arm/config.in	2004-02-18 13:36:30.000000000 +0000
+++ linux-2.4.28-pre3/arch/arm/config.in	2004-09-10 19:33:04.000000000 +0000
@@ -498,7 +498,7 @@ choice 'Kernel core (/proc/kcore) format
 	"ELF		CONFIG_KCORE_ELF	\
 	 A.OUT		CONFIG_KCORE_AOUT" ELF
 tristate 'Kernel support for a.out binaries' CONFIG_BINFMT_AOUT
-tristate 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF
+bool 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF
 tristate 'Kernel support for MISC binaries' CONFIG_BINFMT_MISC
 dep_bool 'Power Management support (experimental)' CONFIG_PM $CONFIG_EXPERIMENTAL
 dep_tristate 'RISC OS personality' CONFIG_ARTHUR $CONFIG_CPU_32
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/cris/config.in linux-2.4.28-pre3/arch/cris/config.in
--- linux-2.4.27/arch/cris/config.in	2004-02-18 13:36:30.000000000 +0000
+++ linux-2.4.28-pre3/arch/cris/config.in	2004-09-10 19:35:17.000000000 +0000
@@ -30,7 +30,7 @@ bool 'System V IPC' CONFIG_SYSVIPC
 bool 'BSD Process Accounting' CONFIG_BSD_PROCESS_ACCT
 bool 'Sysctl support' CONFIG_SYSCTL
 
-tristate 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF
+bool 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF
 
 string 'Kernel command line' CONFIG_ETRAX_CMDLINE "root=/dev/mtdblock3"
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/i386/Makefile linux-2.4.28-pre3/arch/i386/Makefile
--- linux-2.4.27/arch/i386/Makefile	2003-06-13 14:51:29.000000000 +0000
+++ linux-2.4.28-pre3/arch/i386/Makefile	2004-09-10 19:34:00.000000000 +0000
@@ -94,6 +94,10 @@ ifdef CONFIG_MVIAC3_2
 CFLAGS += $(call check_gcc,-march=c3-2,-march=i686)
 endif
 
+# Disable unit-at-a-time mode, it makes gcc use a lot more stack
+# due to the lack of sharing of stacklots.
+CFLAGS += $(call check_gcc,-fno-unit-at-a-time,)
+
 HEAD := arch/i386/kernel/head.o arch/i386/kernel/init_task.o
 
 SUBDIRS += arch/i386/kernel arch/i386/mm arch/i386/lib
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/i386/boot/compressed/misc.c linux-2.4.28-pre3/arch/i386/boot/compressed/misc.c
--- linux-2.4.27/arch/i386/boot/compressed/misc.c	2003-08-25 11:44:39.000000000 +0000
+++ linux-2.4.28-pre3/arch/i386/boot/compressed/misc.c	2004-09-10 19:35:24.000000000 +0000
@@ -104,7 +104,7 @@ static unsigned long output_ptr = 0;
 static void *malloc(int size);
 static void free(void *where);
 
-static void puts(const char *);
+static void putstr(const char *);
 
 extern int end;
 static long free_mem_ptr = (long)&end;
@@ -165,7 +165,7 @@ static void scroll(void)
 		vidmem[i] = ' ';
 }
 
-static void puts(const char *s)
+static void putstr(const char *s)
 {
 	int x,y,pos;
 	char c;
@@ -283,9 +283,9 @@ static void flush_window(void)
 
 static void error(char *x)
 {
-	puts("\n\n");
-	puts(x);
-	puts("\n\n -- System halted");
+	putstr("\n\n");
+	putstr(x);
+	putstr("\n\n -- System halted");
 
 	while(1);	/* Halt */
 }
@@ -369,9 +369,9 @@ asmlinkage int decompress_kernel(struct 
 	else setup_output_buffer_if_we_run_high(mv);
 
 	makecrc();
-	puts("Uncompressing Linux... ");
+	putstr("Uncompressing Linux... ");
 	gunzip();
-	puts("Ok, booting the kernel.\n");
+	putstr("Ok, booting the kernel.\n");
 	if (high_loaded) close_output_buffer_if_we_run_high(mv);
 	return high_loaded;
 }
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/i386/config.in linux-2.4.28-pre3/arch/i386/config.in
--- linux-2.4.27/arch/i386/config.in	2004-02-18 13:36:30.000000000 +0000
+++ linux-2.4.28-pre3/arch/i386/config.in	2004-09-10 19:33:44.000000000 +0000
@@ -326,7 +326,7 @@ if [ "$CONFIG_PROC_FS" = "y" ]; then
 	 A.OUT		CONFIG_KCORE_AOUT" ELF
 fi
 tristate 'Kernel support for a.out binaries' CONFIG_BINFMT_AOUT
-tristate 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF
+bool 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF
 tristate 'Kernel support for MISC binaries' CONFIG_BINFMT_MISC
 bool 'Select task to kill on out of memory condition' CONFIG_OOM_KILLER
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/i386/defconfig linux-2.4.28-pre3/arch/i386/defconfig
--- linux-2.4.27/arch/i386/defconfig	2004-08-07 23:26:04.000000000 +0000
+++ linux-2.4.28-pre3/arch/i386/defconfig	2004-09-10 19:32:41.000000000 +0000
@@ -758,7 +758,7 @@ CONFIG_NFS_FS=y
 # CONFIG_ROOT_NFS is not set
 CONFIG_NFSD=y
 # CONFIG_NFSD_V3 is not set
-# CONFIG_NFSD_TCP is not set
+CONFIG_NFSD_TCP=y
 CONFIG_SUNRPC=y
 CONFIG_LOCKD=y
 # CONFIG_SMB_FS is not set
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/i386/kernel/dmi_scan.c linux-2.4.28-pre3/arch/i386/kernel/dmi_scan.c
--- linux-2.4.27/arch/i386/kernel/dmi_scan.c	2004-04-14 13:05:25.000000000 +0000
+++ linux-2.4.28-pre3/arch/i386/kernel/dmi_scan.c	2004-09-10 19:34:06.000000000 +0000
@@ -459,6 +459,22 @@ static __init int fix_broken_hp_bios_irq
 }
 
 /*
+ * Work around broken Acer TravelMate 360 Notebooks which assign Cardbus to
+ * IRQ 11 even though it is actually wired to IRQ 10
+ */
+static __init int fix_acer_tm360_irqrouting(struct dmi_blacklist *d)
+{
+#ifdef CONFIG_PCI
+	extern int acer_tm360_irqrouting;
+	if (acer_tm360_irqrouting == 0) {
+		acer_tm360_irqrouting = 1;
+		printk(KERN_INFO "%s detected - fixing broken IRQ routing\n", d->ident);
+	}
+#endif
+	return 0;
+}
+
+/*
  *	Exploding PnPBIOS. Don't yet know if its the BIOS or us for
  *	some entries
  */
@@ -820,6 +836,12 @@ static __initdata struct dmi_blacklist d
 			MATCH(DMI_BOARD_VERSION, "OmniBook N32N-736")
 			} },
 
+	{ fix_acer_tm360_irqrouting, "Acer TravelMate 36x Laptop", {
+			MATCH(DMI_SYS_VENDOR, "Acer"),
+			MATCH(DMI_PRODUCT_NAME, "TravelMate 360"),
+			NO_MATCH, NO_MATCH
+			} },
+ 
 	/*
 	 *	Generic per vendor APM settings
 	 */
@@ -935,6 +957,13 @@ static __initdata struct dmi_blacklist d
 			/* newer BIOS, Revision 1011, does work */
 			MATCH(DMI_BIOS_VERSION, "ASUS A7V ACPI BIOS Revision 1007"),
 			NO_MATCH }},
+
+	{ disable_acpi_pci, "Acer TravelMate 36x Laptop", {
+			MATCH(DMI_SYS_VENDOR, "Acer"),
+			MATCH(DMI_PRODUCT_NAME, "TravelMate 360"),
+			NO_MATCH, NO_MATCH
+			} },
+ 
 #endif	/* CONFIG_ACPI_PCI */
 
 	{ NULL, }
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/i386/kernel/io_apic.c linux-2.4.28-pre3/arch/i386/kernel/io_apic.c
--- linux-2.4.27/arch/i386/kernel/io_apic.c	2004-08-07 23:26:04.000000000 +0000
+++ linux-2.4.28-pre3/arch/i386/kernel/io_apic.c	2004-09-10 19:33:48.000000000 +0000
@@ -1349,7 +1349,7 @@ static void mask_and_ack_level_ioapic_ir
 
 #ifndef CONFIG_SMP
 
-void send_IPI_self(int vector)
+void fastcall send_IPI_self(int vector)
 {
 	unsigned int cfg;
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/i386/kernel/pci-irq.c linux-2.4.28-pre3/arch/i386/kernel/pci-irq.c
--- linux-2.4.27/arch/i386/kernel/pci-irq.c	2004-08-07 23:26:04.000000000 +0000
+++ linux-2.4.28-pre3/arch/i386/kernel/pci-irq.c	2004-09-10 19:37:18.000000000 +0000
@@ -23,6 +23,7 @@
 #define PIRQ_VERSION 0x0100
 
 int broken_hp_bios_irq9;
+int acer_tm360_irqrouting;
 
 static struct irq_routing_table *pirq_table;
 
@@ -894,6 +895,14 @@ static int pcibios_lookup_irq(struct pci
 		r->set(pirq_router_dev, dev, pirq, 11);
 	}
 
+	/* same for Acer Travelmate 360, but with CB and irq 11 -> 10 */
+	if (acer_tm360_irqrouting && dev->irq == 11 && dev->vendor == PCI_VENDOR_ID_O2) {
+		pirq = 0x68;
+		mask = 0x400;
+		dev->irq = r->get(pirq_router_dev, dev, pirq);
+		pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
+ 	}
+
 	/*
 	 * Find the best IRQ to assign: use the one
 	 * reported by the device if possible.
@@ -1103,10 +1112,6 @@ void pcibios_enable_irq(struct pci_dev *
 				}
 				dev = temp_dev;
 				if (irq >= 0) {
-#ifdef CONFIG_PCI_USE_VECTOR
-					if (!platform_legacy_irq(irq))
-						irq = IO_APIC_VECTOR(irq);
-#endif
 					printk(KERN_INFO "PCI->APIC IRQ transform: (B%d,I%d,P%d) -> %d\n",
 						dev->bus->number, PCI_SLOT(dev->devfn), pin, irq);
 					dev->irq = irq;
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/i386/kernel/pci-pc.c linux-2.4.28-pre3/arch/i386/kernel/pci-pc.c
--- linux-2.4.27/arch/i386/kernel/pci-pc.c	2004-08-07 23:26:04.000000000 +0000
+++ linux-2.4.28-pre3/arch/i386/kernel/pci-pc.c	2004-09-10 19:34:17.000000000 +0000
@@ -177,6 +177,7 @@ static struct pci_ops pci_direct_mq_conf
 };
 
 #endif /* !CONFIG_MULTIQUAD */
+#undef PCI_CONF1_ADDRESS
 #define PCI_CONF1_ADDRESS(bus, dev, fn, reg) \
 	(0x80000000 | (bus << 16) | (dev << 11) | (fn << 8) | (reg & ~3))
 
@@ -1017,11 +1018,13 @@ struct irq_routing_table * __devinit pci
 		"1:"
 		: "=a" (ret),
 		  "=b" (map),
-		  "+m" (opt)
+		  "=m" (opt)
 		: "0" (PCIBIOS_GET_ROUTING_OPTIONS),
 		  "1" (0),
 		  "D" ((long) &opt),
-		  "S" (&pci_indirect));
+		  "S" (&pci_indirect),
+		  "m" (opt)
+		: "memory");
 	DBG("OK  ret=%d, size=%d, map=%x\n", ret, opt.size, map);
 	if (ret & 0xff00)
 		printk(KERN_ERR "PCI: Error %02x when fetching IRQ routing table.\n", (ret >> 8) & 0xff);
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/i386/kernel/process.c linux-2.4.28-pre3/arch/i386/kernel/process.c
--- linux-2.4.27/arch/i386/kernel/process.c	2004-02-18 13:36:30.000000000 +0000
+++ linux-2.4.28-pre3/arch/i386/kernel/process.c	2004-09-10 19:31:49.000000000 +0000
@@ -644,7 +644,7 @@ void dump_thread(struct pt_regs * regs, 
  * More important, however, is the fact that this allows us much
  * more flexibility.
  */
-void __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
+void fastcall __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
 {
 	struct thread_struct *prev = &prev_p->thread,
 				 *next = &next_p->thread;
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/i386/kernel/signal.c linux-2.4.28-pre3/arch/i386/kernel/signal.c
--- linux-2.4.27/arch/i386/kernel/signal.c	2002-08-03 00:39:42.000000000 +0000
+++ linux-2.4.28-pre3/arch/i386/kernel/signal.c	2004-09-10 19:34:37.000000000 +0000
@@ -581,7 +581,7 @@ handle_signal(unsigned long sig, struct 
  * want to handle. Thus you cannot kill init even with a SIGKILL even by
  * mistake.
  */
-int do_signal(struct pt_regs *regs, sigset_t *oldset)
+int fastcall do_signal(struct pt_regs *regs, sigset_t *oldset)
 {
 	siginfo_t info;
 	struct k_sigaction *ka;
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/i386/kernel/smp.c linux-2.4.28-pre3/arch/i386/kernel/smp.c
--- linux-2.4.27/arch/i386/kernel/smp.c	2003-06-13 14:51:29.000000000 +0000
+++ linux-2.4.28-pre3/arch/i386/kernel/smp.c	2004-09-10 19:32:31.000000000 +0000
@@ -150,7 +150,7 @@ static inline void __send_IPI_shortcut(u
 	apic_write_around(APIC_ICR, cfg);
 }
 
-void send_IPI_self(int vector)
+void fastcall send_IPI_self(int vector)
 {
 	__send_IPI_shortcut(APIC_DEST_SELF, vector);
 }
@@ -497,7 +497,7 @@ void flush_tlb_all(void)
  * anything. Worst case is that we lose a reschedule ...
  */
 
-void smp_send_reschedule(int cpu)
+void fastcall smp_send_reschedule(int cpu)
 {
 	send_IPI_mask(1 << cpu, RESCHEDULE_VECTOR);
 }
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/i386/kernel/vm86.c linux-2.4.28-pre3/arch/i386/kernel/vm86.c
--- linux-2.4.27/arch/i386/kernel/vm86.c	2003-08-25 11:44:39.000000000 +0000
+++ linux-2.4.28-pre3/arch/i386/kernel/vm86.c	2004-09-10 19:32:38.000000000 +0000
@@ -91,7 +91,7 @@
 #define VM86_REGS_SIZE2 (sizeof(struct kernel_vm86_regs) - VM86_REGS_SIZE1)
 
 struct pt_regs * FASTCALL(save_v86_state(struct kernel_vm86_regs * regs));
-struct pt_regs * save_v86_state(struct kernel_vm86_regs * regs)
+struct pt_regs * fastcall save_v86_state(struct kernel_vm86_regs * regs)
 {
 	struct tss_struct *tss;
 	struct pt_regs *ret;
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/ia64/config.in linux-2.4.28-pre3/arch/ia64/config.in
--- linux-2.4.27/arch/ia64/config.in	2004-02-18 13:36:30.000000000 +0000
+++ linux-2.4.28-pre3/arch/ia64/config.in	2004-09-10 19:37:29.000000000 +0000
@@ -123,7 +123,7 @@ bool 'Networking support' CONFIG_NET
 bool 'System V IPC' CONFIG_SYSVIPC
 bool 'BSD Process Accounting' CONFIG_BSD_PROCESS_ACCT
 bool 'Sysctl support' CONFIG_SYSCTL
-tristate 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF
+bool 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF
 tristate 'Kernel support for MISC binaries' CONFIG_BINFMT_MISC
 
 if [ "$CONFIG_IA64_HP_SIM" = "n" ]; then
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/ia64/defconfig linux-2.4.28-pre3/arch/ia64/defconfig
--- linux-2.4.27/arch/ia64/defconfig	2004-08-07 23:26:04.000000000 +0000
+++ linux-2.4.28-pre3/arch/ia64/defconfig	2004-09-10 19:32:31.000000000 +0000
@@ -755,7 +755,7 @@ CONFIG_NFS_V3=y
 # CONFIG_ROOT_NFS is not set
 CONFIG_NFSD=y
 CONFIG_NFSD_V3=y
-# CONFIG_NFSD_TCP is not set
+CONFIG_NFSD_TCP=y
 CONFIG_SUNRPC=y
 CONFIG_LOCKD=y
 CONFIG_LOCKD_V4=y
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/m68k/config.in linux-2.4.28-pre3/arch/m68k/config.in
--- linux-2.4.27/arch/m68k/config.in	2004-02-18 13:36:30.000000000 +0000
+++ linux-2.4.28-pre3/arch/m68k/config.in	2004-09-10 19:36:05.000000000 +0000
@@ -98,7 +98,7 @@ if [ "$CONFIG_PROC_FS" = "y" ]; then
 	 A.OUT		CONFIG_KCORE_AOUT" ELF
 fi
 tristate 'Kernel support for a.out binaries' CONFIG_BINFMT_AOUT
-tristate 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF
+bool 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF
 tristate 'Kernel support for MISC binaries' CONFIG_BINFMT_MISC
 
 if [ "$CONFIG_AMIGA" = "y" ]; then
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/mips/config-shared.in linux-2.4.28-pre3/arch/mips/config-shared.in
--- linux-2.4.27/arch/mips/config-shared.in	2004-02-18 13:36:30.000000000 +0000
+++ linux-2.4.28-pre3/arch/mips/config-shared.in	2004-09-10 19:35:04.000000000 +0000
@@ -943,7 +943,7 @@ bool 'Sysctl support' CONFIG_SYSCTL
 define_bool CONFIG_KCORE_ELF y
 define_bool CONFIG_KCORE_AOUT n
 define_bool CONFIG_BINFMT_AOUT n
-tristate 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF
+bool 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF
 dep_bool 'Kernel support for Linux/MIPS 32-bit binary compatibility' CONFIG_MIPS32_COMPAT $CONFIG_MIPS64
 dep_bool 'Kernel support for o32 binaries' CONFIG_MIPS32_O32 $CONFIG_MIPS32_COMPAT
 dep_bool 'Kernel support for n32 binaries' CONFIG_MIPS32_N32 $CONFIG_MIPS32_COMPAT
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/mips/defconfig linux-2.4.28-pre3/arch/mips/defconfig
--- linux-2.4.27/arch/mips/defconfig	2004-02-18 13:36:30.000000000 +0000
+++ linux-2.4.28-pre3/arch/mips/defconfig	2004-09-10 19:32:45.000000000 +0000
@@ -607,7 +607,7 @@ CONFIG_NFS_FS=y
 CONFIG_ROOT_NFS=y
 CONFIG_NFSD=y
 # CONFIG_NFSD_V3 is not set
-# CONFIG_NFSD_TCP is not set
+CONFIG_NFSD_TCP=y
 CONFIG_SUNRPC=y
 CONFIG_LOCKD=y
 # CONFIG_SMB_FS is not set
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/mips64/defconfig linux-2.4.28-pre3/arch/mips64/defconfig
--- linux-2.4.27/arch/mips64/defconfig	2004-02-18 13:36:30.000000000 +0000
+++ linux-2.4.28-pre3/arch/mips64/defconfig	2004-09-10 19:33:10.000000000 +0000
@@ -563,7 +563,7 @@ CONFIG_NFS_V3=y
 CONFIG_ROOT_NFS=y
 # CONFIG_NFSD is not set
 # CONFIG_NFSD_V3 is not set
-# CONFIG_NFSD_TCP is not set
+CONFIG_NFSD_TCP=y
 CONFIG_SUNRPC=y
 CONFIG_LOCKD=y
 CONFIG_LOCKD_V4=y
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/parisc/config.in linux-2.4.28-pre3/arch/parisc/config.in
--- linux-2.4.27/arch/parisc/config.in	2004-02-18 13:36:30.000000000 +0000
+++ linux-2.4.28-pre3/arch/parisc/config.in	2004-09-10 19:37:18.000000000 +0000
@@ -88,7 +88,7 @@ bool 'System V IPC' CONFIG_SYSVIPC
 bool 'BSD Process Accounting' CONFIG_BSD_PROCESS_ACCT
 bool 'Sysctl support' CONFIG_SYSCTL
 define_bool CONFIG_KCORE_ELF y
-tristate 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF
+bool 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF
 tristate 'Kernel support for SOM binaries' CONFIG_BINFMT_SOM
 tristate 'Kernel support for MISC binaries' CONFIG_BINFMT_MISC
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/ppc/defconfig linux-2.4.28-pre3/arch/ppc/defconfig
--- linux-2.4.27/arch/ppc/defconfig	2004-02-18 13:36:30.000000000 +0000
+++ linux-2.4.28-pre3/arch/ppc/defconfig	2004-09-10 19:36:28.000000000 +0000
@@ -812,7 +812,7 @@ CONFIG_NFS_FS=y
 # CONFIG_ROOT_NFS is not set
 CONFIG_NFSD=y
 # CONFIG_NFSD_V3 is not set
-# CONFIG_NFSD_TCP is not set
+CONFIG_NFSD_TCP=y
 CONFIG_SUNRPC=y
 CONFIG_LOCKD=y
 # CONFIG_SMB_FS is not set
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/ppc/kernel/ppc_htab.c linux-2.4.28-pre3/arch/ppc/kernel/ppc_htab.c
--- linux-2.4.27/arch/ppc/kernel/ppc_htab.c	2004-08-07 23:26:04.000000000 +0000
+++ linux-2.4.28-pre3/arch/ppc/kernel/ppc_htab.c	2004-09-10 19:32:19.000000000 +0000
@@ -489,7 +489,7 @@ int proc_dol2crvec(ctl_table *table, int
 				if (!isspace(c))
 					break;
 				left--;
-				((char *) buffer)++;
+				buffer++;
 			}
 			if (!left)
 				break;
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/ppc64/defconfig linux-2.4.28-pre3/arch/ppc64/defconfig
--- linux-2.4.27/arch/ppc64/defconfig	2004-02-18 13:36:30.000000000 +0000
+++ linux-2.4.28-pre3/arch/ppc64/defconfig	2004-09-10 19:34:39.000000000 +0000
@@ -668,7 +668,7 @@ CONFIG_NFS_V3=y
 # CONFIG_ROOT_NFS is not set
 CONFIG_NFSD=y
 CONFIG_NFSD_V3=y
-# CONFIG_NFSD_TCP is not set
+CONFIG_NFSD_TCP=y
 CONFIG_SUNRPC=y
 CONFIG_LOCKD=y
 CONFIG_LOCKD_V4=y
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/s390/config.in linux-2.4.28-pre3/arch/s390/config.in
--- linux-2.4.27/arch/s390/config.in	2003-11-28 18:26:19.000000000 +0000
+++ linux-2.4.28-pre3/arch/s390/config.in	2004-09-10 19:36:19.000000000 +0000
@@ -57,7 +57,7 @@ bool 'System V IPC' CONFIG_SYSVIPC
 bool 'BSD Process Accounting' CONFIG_BSD_PROCESS_ACCT
 bool 'Sysctl support' CONFIG_SYSCTL
 define_bool CONFIG_KCORE_ELF y
-tristate 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF
+bool 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF
 tristate 'Kernel support for MISC binaries' CONFIG_BINFMT_MISC
 bool 'Show crashed user process info' CONFIG_PROCESS_DEBUG
 bool 'Pseudo page fault support' CONFIG_PFAULT
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/s390/defconfig linux-2.4.28-pre3/arch/s390/defconfig
--- linux-2.4.27/arch/s390/defconfig	2004-02-18 13:36:30.000000000 +0000
+++ linux-2.4.28-pre3/arch/s390/defconfig	2004-09-10 19:36:34.000000000 +0000
@@ -129,6 +129,14 @@ CONFIG_FDDI=y
 #
 CONFIG_CHANDEV=y
 CONFIG_HOTPLUG=y
+CONFIG_QETH=m
+
+#
+# Gigabit Ethernet default settings
+#
+CONFIG_QETH_IPV6=y
+CONFIG_QETH_VLAN=y
+# CONFIG_QETH_PERF_STATS is not set
 CONFIG_CTC=m
 CONFIG_IUCV=m
 
@@ -242,7 +250,6 @@ CONFIG_IP6_NF_TARGET_MARK=m
 #
 #    SCTP Configuration (EXPERIMENTAL)
 #
-CONFIG_IPV6_SCTP__=m
 # CONFIG_IP_SCTP is not set
 # CONFIG_ATM is not set
 CONFIG_VLAN_8021Q=m
@@ -351,7 +358,7 @@ CONFIG_NFS_V3=y
 # CONFIG_ROOT_NFS is not set
 CONFIG_NFSD=y
 CONFIG_NFSD_V3=y
-# CONFIG_NFSD_TCP is not set
+CONFIG_NFSD_TCP=y
 CONFIG_SUNRPC=y
 CONFIG_LOCKD=y
 CONFIG_LOCKD_V4=y
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/s390/kernel/entry.S linux-2.4.28-pre3/arch/s390/kernel/entry.S
--- linux-2.4.27/arch/s390/kernel/entry.S	2003-06-13 14:51:32.000000000 +0000
+++ linux-2.4.28-pre3/arch/s390/kernel/entry.S	2004-09-10 19:32:58.000000000 +0000
@@ -690,7 +690,12 @@ pgm_tracesys:
 io_int_handler:
 	SAVE_ALL_BASE
         SAVE_ALL __LC_IO_OLD_PSW,0
+	mc 0,0
         GET_CURRENT               # load pointer to task_struct to R9
+	stck	__LC_INT_CLOCK
+	clc	__LC_INT_CLOCK(8),__LC_JIFFY_TIMER
+	bhe	BASED(io_handle_tick)
+io_call_handler:
         l       %r1,BASED(.Ldo_IRQ)        # load address of do_IRQ
         la      %r2,SP_PTREGS(%r15) # address of register-save area
         sr      %r3,%r3
@@ -725,6 +730,15 @@ io_leave:
         RESTORE_ALL 0
 
 #
+# account tick
+#
+io_handle_tick:
+	l	%r1,BASED(.Laccount_ticks)
+	la	%r2,SP_PTREGS(%r15)    # address of register-save area
+	la	%r14,BASED(io_call_handler)
+	br	%r1
+
+#
 # call do_softirq
 #
 io_handle_bottom_half:
@@ -758,8 +772,13 @@ io_signal_return:     
 ext_int_handler:
 	SAVE_ALL_BASE
         SAVE_ALL __LC_EXT_OLD_PSW,0
-        GET_CURRENT                    # load pointer to task_struct to R9
+	mc 0, 0
+	GET_CURRENT                    # load pointer to task_struct to R9
 	lh	%r6,__LC_EXT_INT_CODE  # get interruption code
+	stck	__LC_INT_CLOCK
+	clc	__LC_INT_CLOCK(8),__LC_JIFFY_TIMER
+	bhe	BASED(ext_handle_tick)
+ext_call_handler:
 	lr	%r1,%r6		       # calculate index = code & 0xff
 	n	%r1,BASED(.Lc0xff)
 	sll	%r1,2
@@ -770,7 +789,8 @@ ext_int_handler:
 ext_int_loop:
 	ch	%r6,8(%r7)	       # compare external interrupt code
 	bne	BASED(ext_int_next)
-	l	%r1,4(%r7)	       # get handler address
+	icm	%r1,15,4(%r7)	       # get handler address
+	bz	BASED(ext_int_next)
 	la	%r2,SP_PTREGS(%r15)    # address of register-save area
 	lr	%r3,%r6		       # interruption code
 	basr	%r14,%r1	       # call handler
@@ -779,6 +799,15 @@ ext_int_next:
 	bnz	BASED(ext_int_loop)
 	b	BASED(io_return)
 
+#
+# account tick
+#
+ext_handle_tick:
+	l	%r1,BASED(.Laccount_ticks)
+	la	%r2,SP_PTREGS(%r15)    # address of register-save area
+	la	%r14,BASED(ext_call_handler)
+	br	%r1
+
 /*
  * Machine check handler routines
  */
@@ -787,6 +816,7 @@ ext_int_next:
 mcck_int_handler:
 	SAVE_ALL_BASE
         SAVE_ALL __LC_MCK_OLD_PSW,0
+	mc 0, 0
 	l       %r1,BASED(.Ls390_mcck)
 	basr    %r14,%r1	  # call machine check handler
 mcck_return:
@@ -869,4 +899,4 @@ restart_go:
 .Lvfork:       .long  sys_vfork
 
 .Lschedtail:   .long  schedule_tail
-
+.Laccount_ticks:.long account_ticks
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/s390/kernel/s390_ksyms.c linux-2.4.28-pre3/arch/s390/kernel/s390_ksyms.c
--- linux-2.4.27/arch/s390/kernel/s390_ksyms.c	2004-02-18 13:36:30.000000000 +0000
+++ linux-2.4.28-pre3/arch/s390/kernel/s390_ksyms.c	2004-09-10 19:35:32.000000000 +0000
@@ -7,6 +7,7 @@
 #include <linux/module.h>
 #include <linux/smp.h>
 #include <asm/checksum.h>
+#include <asm/cpcmd.h>
 #include <asm/delay.h>
 #include <asm/setup.h>
 #include <asm/softirq.h>
@@ -66,3 +67,7 @@ EXPORT_SYMBOL(pfix_get_page_addr);
 EXPORT_SYMBOL(get_storage_key);
 EXPORT_SYMBOL_NOVERS(do_call_softirq);
 EXPORT_SYMBOL(sys_wait4);
+EXPORT_SYMBOL(smp_call_function_on);
+EXPORT_SYMBOL(show_trace);
+EXPORT_SYMBOL(cpcmd);
+
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/s390/kernel/smp.c linux-2.4.28-pre3/arch/s390/kernel/smp.c
--- linux-2.4.27/arch/s390/kernel/smp.c	2002-11-28 23:53:11.000000000 +0000
+++ linux-2.4.28-pre3/arch/s390/kernel/smp.c	2004-09-10 19:31:55.000000000 +0000
@@ -92,7 +92,7 @@ extern char vmpoff_cmd[];
 
 extern void reipl(unsigned long devno);
 
-static sigp_ccode smp_ext_bitcall(int, ec_bit_sig);
+static void smp_ext_bitcall(int, ec_bit_sig);
 static void smp_ext_bitcall_others(ec_bit_sig);
 
 /*
@@ -131,7 +131,7 @@ static void do_call_function(void)
  * in the system.
  */
 
-int smp_call_function (void (*func) (void *info), void *info, int nonatomic,
+int smp_call_function(void (*func) (void *info), void *info, int nonatomic,
 			int wait)
 /*
  * [SUMMARY] Run a function on all other CPUs.
@@ -162,7 +162,7 @@ int smp_call_function (void (*func) (voi
 	spin_lock_bh(&call_lock);
 	call_data = &data;
 	/* Send a message to all other CPUs and wait for them to respond */
-        smp_ext_bitcall_others(ec_call_function);
+	smp_ext_bitcall_others(ec_call_function);
 
 	/* Wait for response */
 	while (atomic_read(&data.started) != cpus)
@@ -176,9 +176,54 @@ int smp_call_function (void (*func) (voi
 	return 0;
 }
 
+/*
+ * Call a function on one CPU
+ * cpu : the CPU the function should be executed on
+ *
+ * You must not call this function with disabled interrupts or from a
+ * hardware interrupt handler, you may call it from a bottom half handler.
+ */
+int smp_call_function_on(void (*func) (void *info), void *info,
+                         int nonatomic, int wait, int cpu)
+{
+	struct call_data_struct data;
+
+	if (!atomic_read(&smp_commenced))
+		return 0;
+
+	if (smp_processor_id() == cpu) {
+		/* direct call to function */
+		func(info);
+		return 0;
+	}
+
+	data.func = func;
+	data.info = info;
+
+	atomic_set(&data.started, 0);
+	data.wait = wait;
+	if (wait)
+		atomic_set(&data.finished, 0);
+
+	spin_lock_bh(&call_lock);
+	call_data = &data;
+	smp_ext_bitcall(cpu, ec_call_function);
+
+	/* Wait for response */
+	while (atomic_read(&data.started) != 1)
+		barrier();
+
+	if (wait)
+		while (atomic_read(&data.finished) != 1)
+			barrier();
+
+	spin_unlock_bh(&call_lock);
+	return 0;
+}
+
 static inline void do_send_stop(void)
 {
-        u32 dummy;
+        unsigned long dummy;
         int i;
 
         /* stop all processors */
@@ -199,7 +244,7 @@ static inline void do_send_stop(void)
 static inline void do_store_status(void)
 {
         unsigned long low_core_addr;
-        u32 dummy;
+        unsigned long dummy;
         int i;
 
         /* store status of all processors in their lowcores (real 0) */
@@ -328,42 +373,41 @@ void do_ext_call_interrupt(struct pt_reg
 }
 
 /*
- * Send an external call sigp to another cpu and return without waiting
+ * Send an external call sigp to another cpu and wait
  * for its completion.
  */
-static sigp_ccode smp_ext_bitcall(int cpu, ec_bit_sig sig)
+static void smp_ext_bitcall(int cpu, ec_bit_sig sig)
 {
-        struct _lowcore *lowcore = get_cpu_lowcore(cpu);
-        sigp_ccode ccode;
+	struct _lowcore *lowcore = get_cpu_lowcore(cpu);
 
-        /*
-         * Set signaling bit in lowcore of target cpu and kick it
-         */
-        atomic_set_mask(1<<sig, &lowcore->ext_call_fast);
-        ccode = signal_processor(cpu, sigp_external_call);
-        return ccode;
+	/*
+	 * Set signaling bit in lowcore of target cpu and kick it
+	 */
+	atomic_set_mask(1<<sig, &lowcore->ext_call_fast);
+	while(signal_processor(cpu, sigp_external_call) == sigp_busy)
+		udelay(10);
 }
 
 /*
  * Send an external call sigp to every other cpu in the system and
- * return without waiting for its completion.
+ * wait for its completion.
  */
 static void smp_ext_bitcall_others(ec_bit_sig sig)
 {
-        struct _lowcore *lowcore;
-        int i;
+	struct _lowcore *lowcore;
+	int i;
 
-        for (i = 0; i < smp_num_cpus; i++) {
-                if (smp_processor_id() == i)
-                        continue;
-                lowcore = get_cpu_lowcore(i);
-                /*
-                 * Set signaling bit in lowcore of target cpu and kick it
-                 */
-                atomic_set_mask(1<<sig, &lowcore->ext_call_fast);
-                while (signal_processor(i, sigp_external_call) == sigp_busy)
+	for (i = 0; i < smp_num_cpus; i++) {
+		if (smp_processor_id() == i)
+			continue;
+		lowcore = get_cpu_lowcore(i);
+		/*
+		 * Set signaling bit in lowcore of target cpu and kick it
+		 */
+		atomic_set_mask(1<<sig, &lowcore->ext_call_fast);
+		while (signal_processor(i, sigp_external_call) == sigp_busy)
 			udelay(10);
-        }
+	}
 }
 
 /*
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/s390/kernel/time.c linux-2.4.28-pre3/arch/s390/kernel/time.c
--- linux-2.4.27/arch/s390/kernel/time.c	2003-06-13 14:51:32.000000000 +0000
+++ linux-2.4.28-pre3/arch/s390/kernel/time.c	2004-09-10 19:31:59.000000000 +0000
@@ -34,13 +34,20 @@
 #include <asm/irq.h>
 
 /* change this if you have some constant time drift */
-#define USECS_PER_JIFFY     ((unsigned long) 1000000/HZ)
 #define CLK_TICKS_PER_JIFFY ((unsigned long) USECS_PER_JIFFY << 12)
 
+/*
+ * Create a small time difference between the timer interrupts
+ * on the different cpus to avoid lock contention.
+ */
+#define USECS_PER_JIFFY     ((unsigned long) 1000000/HZ)
+#define CPU_DEVIATION       (smp_processor_id() << 12)
+
 #define TICK_SIZE tick
 
 static ext_int_info_t ext_int_info_timer;
-static uint64_t init_timer_cc;
+static u64 init_timer_cc;
+static u64 xtime_cc;
 
 extern rwlock_t xtime_lock;
 extern unsigned long wall_jiffies;
@@ -83,7 +90,7 @@ static inline unsigned long do_gettimeof
 {
 	__u64 now;
 
-	asm ("STCK 0(%0)" : : "a" (&now) : "memory", "cc");
+	asm volatile ("STCK 0(%0)" : : "a" (&now) : "memory", "cc");
         now = (now - init_timer_cc) >> 12;
 	/* We require the offset from the latest update of xtime */
 	now -= (__u64) wall_jiffies*USECS_PER_JIFFY;
@@ -137,41 +144,72 @@ void do_settimeofday(struct timeval *tv)
 	write_unlock_irq(&xtime_lock);
 }
 
+static inline __u32 div64_32(__u64 dividend, __u32 divisor)
+{
+	register_pair rp;
+
+	rp.pair = dividend;
+	asm ("dr %0,%1" : "+d" (rp) : "d" (divisor));
+	return rp.subreg.odd;
+}
+
 /*
  * timer_interrupt() needs to keep up the real-time clock,
  * as well as call the "do_timer()" routine every clocktick
  */
-
-#ifdef CONFIG_SMP
-extern __u16 boot_cpu_addr;
-#endif
-
-static void do_comparator_interrupt(struct pt_regs *regs, __u16 error_code)
+void account_ticks(struct pt_regs *regs)
 {
 	int cpu = smp_processor_id();
+	__u64 tmp;
+	__u32 ticks;
+
+	/* Calculate how many ticks have passed. */
+	tmp = S390_lowcore.int_clock - S390_lowcore.jiffy_timer;
+	if (tmp >= 2*CLK_TICKS_PER_JIFFY) {
+		ticks = div64_32(tmp >> 1, CLK_TICKS_PER_JIFFY >> 1) + 1;
+		S390_lowcore.jiffy_timer +=
+			CLK_TICKS_PER_JIFFY * (__u64) ticks;
+	} else if (tmp > CLK_TICKS_PER_JIFFY) {
+		ticks = 2;
+		S390_lowcore.jiffy_timer += 2*CLK_TICKS_PER_JIFFY;
+	} else {
+		ticks = 1;
+		S390_lowcore.jiffy_timer += CLK_TICKS_PER_JIFFY;
+	}
+
+	/* set clock comparator for next tick */
+	tmp = S390_lowcore.jiffy_timer + CPU_DEVIATION;
+	asm volatile ("SCKC %0" : : "m" (tmp));
 
 	irq_enter(cpu, 0);
 
+#ifdef CONFIG_SMP
 	/*
-	 * set clock comparator for next tick
+	 * Do not rely on the boot cpu to do the calls to do_timer.
+	 * Spread it over all cpus instead.
 	 */
-        S390_lowcore.jiffy_timer += CLK_TICKS_PER_JIFFY;
-        asm volatile ("SCKC %0" : : "m" (S390_lowcore.jiffy_timer));
-
-#ifdef CONFIG_SMP
-	if (S390_lowcore.cpu_data.cpu_addr == boot_cpu_addr)
-		write_lock(&xtime_lock);
-
-	update_process_times(user_mode(regs));
-
-	if (S390_lowcore.cpu_data.cpu_addr == boot_cpu_addr) {
-		do_timer(regs);
-		write_unlock(&xtime_lock);
+	write_lock(&xtime_lock);
+	if (S390_lowcore.jiffy_timer > xtime_cc) {
+		__u32 xticks;
+
+		tmp = S390_lowcore.jiffy_timer - xtime_cc;
+		if (tmp >= 2*CLK_TICKS_PER_JIFFY) {
+			xticks = div64_32(tmp >> 1, CLK_TICKS_PER_JIFFY >> 1);
+			xtime_cc += (__u64) xticks * CLK_TICKS_PER_JIFFY;
+		} else {
+			xticks = 1;
+			xtime_cc += CLK_TICKS_PER_JIFFY;
+		}
+		while (xticks--)
+			do_timer(regs);
 	}
+	write_unlock(&xtime_lock);
+	while (ticks--)
+		update_process_times(user_mode(regs));
 #else
-	do_timer(regs);
+	while (ticks--)
+		do_timer(regs);
 #endif
-
 	irq_exit(cpu, 0);
 }
 
@@ -180,11 +218,13 @@ static void do_comparator_interrupt(stru
  */
 void init_cpu_timer(void)
 {
-	unsigned long cr0;
+        unsigned long cr0;
+	__u64 timer;
 
-	S390_lowcore.jiffy_timer = (__u64) jiffies * CLK_TICKS_PER_JIFFY;
-	S390_lowcore.jiffy_timer += init_timer_cc + CLK_TICKS_PER_JIFFY;
-	asm volatile ("SCKC %0" : : "m" (S390_lowcore.jiffy_timer));
+        timer = init_timer_cc + (__u64) jiffies * CLK_TICKS_PER_JIFFY;
+        S390_lowcore.jiffy_timer = timer + CLK_TICKS_PER_JIFFY;
+        timer += CLK_TICKS_PER_JIFFY + CPU_DEVIATION;
+        asm volatile ("SCKC %0" : : "m" (timer));
         /* allow clock comparator timer interrupt */
         asm volatile ("STCTL 0,0,%0" : "=m" (cr0) : : "memory");
         cr0 |= 0x800;
@@ -220,12 +260,13 @@ void __init time_init(void)
         }
 
 	/* set xtime */
+	xtime_cc = init_timer_cc + CLK_TICKS_PER_JIFFY;
         set_time_cc = init_timer_cc - 0x8126d60e46000000LL +
                       (0x3c26700LL*1000000*4096);
         tod_to_timeval(set_time_cc, &xtime);
 
         /* request the 0x1004 external interrupt */
-        if (register_early_external_interrupt(0x1004, do_comparator_interrupt,
+        if (register_early_external_interrupt(0x1004, NULL,
 					      &ext_int_info_timer) != 0)
                 panic("Couldn't request external interrupt 0x1004");
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/s390x/config.in linux-2.4.28-pre3/arch/s390x/config.in
--- linux-2.4.27/arch/s390x/config.in	2003-11-28 18:26:19.000000000 +0000
+++ linux-2.4.28-pre3/arch/s390x/config.in	2004-09-10 19:32:37.000000000 +0000
@@ -60,7 +60,7 @@ bool 'System V IPC' CONFIG_SYSVIPC
 bool 'BSD Process Accounting' CONFIG_BSD_PROCESS_ACCT
 bool 'Sysctl support' CONFIG_SYSCTL
 define_bool CONFIG_KCORE_ELF y
-tristate 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF
+bool 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF
 tristate 'Kernel support for MISC binaries' CONFIG_BINFMT_MISC
 bool 'Show crashed user process info' CONFIG_PROCESS_DEBUG
 bool 'Pseudo page fault support' CONFIG_PFAULT
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/s390x/defconfig linux-2.4.28-pre3/arch/s390x/defconfig
--- linux-2.4.27/arch/s390x/defconfig	2004-02-18 13:36:30.000000000 +0000
+++ linux-2.4.28-pre3/arch/s390x/defconfig	2004-09-10 19:31:52.000000000 +0000
@@ -129,6 +129,14 @@ CONFIG_FDDI=y
 #
 CONFIG_CHANDEV=y
 CONFIG_HOTPLUG=y
+CONFIG_QETH=m
+
+#
+# Gigabit Ethernet default settings
+#
+CONFIG_QETH_IPV6=y
+CONFIG_QETH_VLAN=y
+# CONFIG_QETH_PERF_STATS is not set
 CONFIG_CTC=m
 CONFIG_IUCV=m
 
@@ -291,7 +299,7 @@ CONFIG_NFS_V3=y
 # CONFIG_ROOT_NFS is not set
 CONFIG_NFSD=y
 CONFIG_NFSD_V3=y
-# CONFIG_NFSD_TCP is not set
+CONFIG_NFSD_TCP=y
 CONFIG_SUNRPC=y
 CONFIG_LOCKD=y
 CONFIG_LOCKD_V4=y
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/s390x/kernel/entry.S linux-2.4.28-pre3/arch/s390x/kernel/entry.S
--- linux-2.4.27/arch/s390x/kernel/entry.S	2003-08-25 11:44:40.000000000 +0000
+++ linux-2.4.28-pre3/arch/s390x/kernel/entry.S	2004-09-10 19:33:22.000000000 +0000
@@ -722,7 +722,12 @@ pgm_tracesys:
         .globl io_int_handler
 io_int_handler:
         SAVE_ALL __LC_IO_OLD_PSW,0
+	mc 0, 0
         GET_CURRENT                    # load pointer to task_struct to R9
+	stck	__LC_INT_CLOCK
+	clc	__LC_INT_CLOCK(8),__LC_JIFFY_TIMER
+	jhe	io_handle_tick
+io_call_handler:
         la      %r2,SP_PTREGS(%r15)    # address of register-save area
 	llgh    %r3,__LC_SUBCHANNEL_NR # load subchannel number
         llgf    %r4,__LC_IO_INT_PARM   # load interuption parm
@@ -780,14 +785,27 @@ io_signal_return:     
 	larl    %r14,io_leave
         jg      do_signal           # return point is io_leave
 
+#
+# account tick
+#
+io_handle_tick:
+	la	%r2,SP_PTREGS(%r15)    # address of register-save area
+	larl	%r14,io_call_handler
+	jg	account_ticks
+
 /*
  * External interrupt handler routine
  */
         .globl  ext_int_handler
 ext_int_handler:
         SAVE_ALL __LC_EXT_OLD_PSW,0
+	mc 0, 0
         GET_CURRENT                    # load pointer to task_struct to R9
 	llgh	%r6,__LC_EXT_INT_CODE  # get interruption code
+	stck	__LC_INT_CLOCK
+	clc	__LC_INT_CLOCK(8),__LC_JIFFY_TIMER
+	jhe	ext_handle_tick
+ext_call_handler:
 	lgr	%r1,%r6		       # calculate index = code & 0xff
 	nill	%r1,0xff
 	sll	%r1,3
@@ -799,6 +817,8 @@ ext_int_loop:
 	ch	%r6,16(%r7)	       # compare external interrupt code
 	jne	ext_int_next
 	lg	%r1,8(%r7)	       # get handler address
+	ltgr	%r1,%r1
+	jz	ext_int_next
 	la	%r2,SP_PTREGS(%r15)    # address of register-save area
 	lgr	%r3,%r6		       # interruption code
 	basr	%r14,%r1	       # call handler
@@ -808,12 +828,21 @@ ext_int_next:
 	jnz	ext_int_loop
 	j	io_return
 
+#
+# account tick
+#
+ext_handle_tick:
+	la	%r2,SP_PTREGS(%r15)    # address of register-save area
+	larl	%r14,ext_call_handler
+	jg	account_ticks
+
 /*
  * Machine check handler routines
  */
         .globl mcck_int_handler
 mcck_int_handler:
         SAVE_ALL __LC_MCK_OLD_PSW,0
+	mc 0, 0
 	brasl   %r14,s390_do_machine_check
 mcck_return:
         RESTORE_ALL 0
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/s390x/kernel/ioctl32.c linux-2.4.28-pre3/arch/s390x/kernel/ioctl32.c
--- linux-2.4.27/arch/s390x/kernel/ioctl32.c	2003-08-25 11:44:40.000000000 +0000
+++ linux-2.4.28-pre3/arch/s390x/kernel/ioctl32.c	2004-09-10 19:36:54.000000000 +0000
@@ -34,6 +34,7 @@
 #include <asm/uaccess.h>
 #include <asm/dasd.h>
 #include <asm/sockios.h>
+#include "../../../drivers/s390/char/tubio.h"
 
 #include "linux32.h"
 
@@ -535,6 +536,12 @@ static struct ioctl32_list ioctl32_handl
 
 	IOCTL32_HANDLER(HDIO_GETGEO, hd_geometry_ioctl),
 
+	IOCTL32_DEFAULT(TUBICMD),
+	IOCTL32_DEFAULT(TUBOCMD),
+	IOCTL32_DEFAULT(TUBGETI),
+	IOCTL32_DEFAULT(TUBGETO),
+	IOCTL32_DEFAULT(TUBSETMOD),
+	IOCTL32_DEFAULT(TUBGETMOD),
 	IOCTL32_DEFAULT(TCGETA),
 	IOCTL32_DEFAULT(TCSETA),
 	IOCTL32_DEFAULT(TCSETAW),
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/s390x/kernel/linux32.c linux-2.4.28-pre3/arch/s390x/kernel/linux32.c
--- linux-2.4.27/arch/s390x/kernel/linux32.c	2004-02-18 13:36:30.000000000 +0000
+++ linux-2.4.28-pre3/arch/s390x/kernel/linux32.c	2004-09-10 19:36:02.000000000 +0000
@@ -4427,7 +4427,7 @@ asmlinkage long sys32_stat64(char * file
     ret = sys_newstat(tmp, &s);
     set_fs (old_fs);
     putname(tmp);
-    if (putstat64 (statbuf, &s)) 
+    if (!ret && putstat64 (statbuf, &s))
 	    return -EFAULT;
     return ret;
 }
@@ -4451,7 +4451,7 @@ asmlinkage long sys32_lstat64(char * fil
     ret = sys_newlstat(tmp, &s);
     set_fs (old_fs);
     putname(tmp);
-    if (putstat64 (statbuf, &s)) 
+    if (!ret && putstat64 (statbuf, &s))
 	    return -EFAULT;
     return ret;
 }
@@ -4467,7 +4467,7 @@ asmlinkage long sys32_fstat64(unsigned l
     set_fs (KERNEL_DS);
     ret = sys_newfstat(fd, &s);
     set_fs (old_fs);
-    if (putstat64 (statbuf, &s))
+    if (!ret && putstat64 (statbuf, &s))
 	    return -EFAULT;
     return ret;
 }
@@ -4507,7 +4507,7 @@ static inline long do_mmap2(
 	error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
 	if (!IS_ERR((void *) error) && error + len >= 0x80000000ULL) {
 		/* Result is out of bounds.  */
-		do_munmap(current->mm, addr, len);
+		do_munmap(current->mm, error, len);
 		error = -ENOMEM;
 	}
 	up_write(&current->mm->mmap_sem);
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/s390x/kernel/s390_ksyms.c linux-2.4.28-pre3/arch/s390x/kernel/s390_ksyms.c
--- linux-2.4.27/arch/s390x/kernel/s390_ksyms.c	2004-02-18 13:36:30.000000000 +0000
+++ linux-2.4.28-pre3/arch/s390x/kernel/s390_ksyms.c	2004-09-10 19:36:30.000000000 +0000
@@ -9,6 +9,7 @@
 #include <linux/mm.h>
 #include <linux/smp.h>
 #include <asm/checksum.h>
+#include <asm/cpcmd.h>
 #include <asm/delay.h>
 #include <asm/pgalloc.h>
 #include <asm/setup.h>
@@ -83,3 +84,7 @@ EXPORT_SYMBOL(console_mode);
 EXPORT_SYMBOL(console_device);
 EXPORT_SYMBOL_NOVERS(do_call_softirq);
 EXPORT_SYMBOL(sys_wait4);
+EXPORT_SYMBOL(smp_call_function_on);
+EXPORT_SYMBOL(show_trace);
+EXPORT_SYMBOL(cpcmd);
+
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/s390x/kernel/smp.c linux-2.4.28-pre3/arch/s390x/kernel/smp.c
--- linux-2.4.27/arch/s390x/kernel/smp.c	2003-06-13 14:51:32.000000000 +0000
+++ linux-2.4.28-pre3/arch/s390x/kernel/smp.c	2004-09-10 19:35:00.000000000 +0000
@@ -92,7 +92,7 @@ extern char vmpoff_cmd[];
 
 extern void reipl(unsigned long devno);
 
-static sigp_ccode smp_ext_bitcall(int, ec_bit_sig);
+static void smp_ext_bitcall(int, ec_bit_sig);
 static void smp_ext_bitcall_others(ec_bit_sig);
 
 /*
@@ -131,7 +131,7 @@ static void do_call_function(void)
  * in the system.
  */
 
-int smp_call_function (void (*func) (void *info), void *info, int nonatomic,
+int smp_call_function(void (*func) (void *info), void *info, int nonatomic,
 			int wait)
 /*
  * [SUMMARY] Run a function on all other CPUs.
@@ -176,46 +176,92 @@ int smp_call_function (void (*func) (voi
 	return 0;
 }
 
+/*
+ * Call a function only on one CPU
+ * cpu : the CPU the function should be executed on
+ *
+ * You must not call this function with disabled interrupts or from a
+ * hardware interrupt handler, you may call it from a bottom half handler.
+ */
+int smp_call_function_on(void (*func) (void *info), void *info,
+			 int nonatomic, int wait, int cpu)
+{
+	struct call_data_struct data;
+
+	if (!atomic_read(&smp_commenced))
+		return 0;
+
+	if (smp_processor_id() == cpu) {
+		/* direct call to function */
+		func(info);
+		return 0;
+	}
+
+	data.func = func;
+	data.info = info;
+
+	atomic_set(&data.started, 0);
+	data.wait = wait;
+	if (wait)
+		atomic_set(&data.finished, 0);
+
+	spin_lock_bh(&call_lock);
+	call_data = &data;
+	smp_ext_bitcall(cpu, ec_call_function);
+
+	/* Wait for response */
+	while (atomic_read(&data.started) != 1)
+		barrier();
+
+	if (wait)
+		while (atomic_read(&data.finished) != 1)
+			barrier();
+
+	spin_unlock_bh(&call_lock);
+	return 0;
+}
+
+
 static inline void do_send_stop(void)
 {
-        u32 dummy;
-        int i;
+	unsigned long dummy;
+	int i;
 
-        /* stop all processors */
-        for (i =  0; i < smp_num_cpus; i++) {
-                if (smp_processor_id() != i) {
-                        int ccode;
-                        do {
-                                ccode = signal_processor_ps(
-                                   &dummy,
-                                   0,
-                                   i,
-                                   sigp_stop);
-                        } while(ccode == sigp_busy);
-                }
-        }
+	/* stop all processors */
+	for (i =  0; i < smp_num_cpus; i++) {
+		if (smp_processor_id() != i) {
+			int ccode;
+			do {
+				ccode = signal_processor_ps(
+				   &dummy,
+				   0,
+				   i,
+				   sigp_stop);
+			} while(ccode == sigp_busy);
+		}
+	}
 }
 
 static inline void do_store_status(void)
 {
-        unsigned long low_core_addr;
-        u32 dummy;
-        int i;
+	unsigned long low_core_addr;
+	unsigned long dummy;
+	int i;
 
-        /* store status of all processors in their lowcores (real 0) */
-        for (i =  0; i < smp_num_cpus; i++) {
-                if (smp_processor_id() != i) {
-                        int ccode;
-                        low_core_addr = (unsigned long)get_cpu_lowcore(i);
-                        do {
-                                ccode = signal_processor_ps(
-                                   &dummy,
-                                   low_core_addr,
-                                   i,
-                                   sigp_store_status_at_address);
-                        } while(ccode == sigp_busy);
-                }
-        }
+	/* store status of all processors in their lowcores (real 0) */
+	for (i =  0; i < smp_num_cpus; i++) {
+		if (smp_processor_id() != i) {
+			int ccode;
+			low_core_addr = (unsigned long)get_cpu_lowcore(i);
+			do {
+				ccode = signal_processor_ps(
+				   &dummy,
+				   low_core_addr,
+				   i,
+				   sigp_store_status_at_address);
+			} while(ccode == sigp_busy);
+		}
+	}
 }
 
 /*
@@ -224,8 +270,8 @@ static inline void do_store_status(void)
  */
 void smp_send_stop(void)
 {
-        /* write magic number to zero page (absolute 0) */
-        get_cpu_lowcore(smp_processor_id())->panic_magic = __PANIC_MAGIC;
+	/* write magic number to zero page (absolute 0) */
+	get_cpu_lowcore(smp_processor_id())->panic_magic = __PANIC_MAGIC;
 
 	/* stop other processors. */
 	do_send_stop();
@@ -263,7 +309,7 @@ static void do_machine_restart(void * __
 void machine_restart_smp(char * __unused) 
 {
 	cpu_restart_map = cpu_online_map;
-        smp_call_function(do_machine_restart, NULL, 0, 0);
+	smp_call_function(do_machine_restart, NULL, 0, 0);
 	do_machine_restart(NULL);
 }
 
@@ -282,7 +328,7 @@ static void do_machine_halt(void * __unu
 
 void machine_halt_smp(void)
 {
-        smp_call_function(do_machine_halt, NULL, 0, 0);
+	smp_call_function(do_machine_halt, NULL, 0, 0);
 	do_machine_halt(NULL);
 }
 
@@ -301,7 +347,7 @@ static void do_machine_power_off(void * 
 
 void machine_power_off_smp(void)
 {
-        smp_call_function(do_machine_power_off, NULL, 0, 0);
+	smp_call_function(do_machine_power_off, NULL, 0, 0);
 	do_machine_power_off(NULL);
 }
 
@@ -312,55 +358,52 @@ void machine_power_off_smp(void)
 
 void do_ext_call_interrupt(struct pt_regs *regs, __u16 code)
 {
-        unsigned long bits;
+	unsigned long bits;
 
-        /*
-         * handle bit signal external calls
-         *
-         * For the ec_schedule signal we have to do nothing. All the work
-         * is done automatically when we return from the interrupt.
-         */
+	/*
+	 * handle bit signal external calls
+	 *
+	 * For the ec_schedule signal we have to do nothing. All the work
+	 * is done automatically when we return from the interrupt.
+	 */
 	bits = xchg(&S390_lowcore.ext_call_fast, 0);
 
-        if (test_bit(ec_call_function, &bits))
+	if (test_bit(ec_call_function, &bits))
 		do_call_function();
 }
 
 /*
- * Send an external call sigp to another cpu and return without waiting
+ * Send an external call sigp to another cpu and wait
  * for its completion.
  */
-static sigp_ccode smp_ext_bitcall(int cpu, ec_bit_sig sig)
+static void smp_ext_bitcall(int cpu, ec_bit_sig sig)
 {
-        sigp_ccode ccode;
-
-        /*
-         * Set signaling bit in lowcore of target cpu and kick it
-         */
+	/*
+	 * Set signaling bit in lowcore of target cpu and kick it
+	 */
 	set_bit(sig, &(get_cpu_lowcore(cpu)->ext_call_fast));
-        ccode = signal_processor(cpu, sigp_external_call);
-        return ccode;
+	while (signal_processor(cpu, sigp_external_call) == sigp_busy)
+		udelay(10);
 }
 
 /*
  * Send an external call sigp to every other cpu in the system and
- * return without waiting for its completion.
+ * wait for its completion.
  */
 static void smp_ext_bitcall_others(ec_bit_sig sig)
 {
-        sigp_ccode ccode;
-        int i;
+	int i;
 
-        for (i = 0; i < smp_num_cpus; i++) {
-                if (smp_processor_id() == i)
-                        continue;
-                /*
-                 * Set signaling bit in lowcore of target cpu and kick it
-                 */
+	for (i = 0; i < smp_num_cpus; i++) {
+		if (smp_processor_id() == i)
+			continue;
+		/*
+		 * Set signaling bit in lowcore of target cpu and kick it
+		 */
 		set_bit(sig, &(get_cpu_lowcore(i)->ext_call_fast));
-                while (signal_processor(i, sigp_external_call) == sigp_busy)
+		while (signal_processor(i, sigp_external_call) == sigp_busy)
 			udelay(10);
-        }
+	}
 }
 
 /*
@@ -650,3 +693,4 @@ EXPORT_SYMBOL(smp_ctl_set_bit);
 EXPORT_SYMBOL(smp_ctl_clear_bit);
 EXPORT_SYMBOL(smp_num_cpus);
 EXPORT_SYMBOL(smp_call_function);
+
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/s390x/kernel/time.c linux-2.4.28-pre3/arch/s390x/kernel/time.c
--- linux-2.4.27/arch/s390x/kernel/time.c	2003-06-13 14:51:32.000000000 +0000
+++ linux-2.4.28-pre3/arch/s390x/kernel/time.c	2004-09-10 19:36:30.000000000 +0000
@@ -37,10 +37,17 @@
 #define USECS_PER_JIFFY     ((unsigned long) 1000000/HZ)
 #define CLK_TICKS_PER_JIFFY ((unsigned long) USECS_PER_JIFFY << 12)
 
+/*
+ * Create a small time difference between the timer interrupts
+ * on the different cpus to avoid lock contention.
+ */
+#define CPU_DEVIATION       (smp_processor_id() << 12)
+
 #define TICK_SIZE tick
 
 static ext_int_info_t ext_int_info_timer;
-static uint64_t init_timer_cc;
+static u64 init_timer_cc;
+static u64 xtime_cc;
 
 extern rwlock_t xtime_lock;
 extern unsigned long wall_jiffies;
@@ -56,7 +63,7 @@ static inline unsigned long do_gettimeof
 {
 	__u64 now;
 
-	asm ("STCK 0(%0)" : : "a" (&now) : "memory", "cc");
+	asm volatile ("STCK 0(%0)" : : "a" (&now) : "memory", "cc");
         now = (now - init_timer_cc) >> 12;
 	/* We require the offset from the latest update of xtime */
 	now -= (__u64) wall_jiffies*USECS_PER_JIFFY;
@@ -114,35 +121,58 @@ void do_settimeofday(struct timeval *tv)
  * timer_interrupt() needs to keep up the real-time clock,
  * as well as call the "do_timer()" routine every clocktick
  */
-
-#ifdef CONFIG_SMP
-extern __u16 boot_cpu_addr;
-#endif
-
-static void do_comparator_interrupt(struct pt_regs *regs, __u16 error_code)
+void account_ticks(struct pt_regs *regs)
 {
 	int cpu = smp_processor_id();
+	__u64 tmp;
+	__u32 ticks;
+
+	/* Calculate how many ticks have passed. */
+	tmp = S390_lowcore.int_clock - S390_lowcore.jiffy_timer;
+	if (tmp >= 2*CLK_TICKS_PER_JIFFY) {  /* more than one tick ? */
+		ticks = tmp / CLK_TICKS_PER_JIFFY + 1;
+		S390_lowcore.jiffy_timer +=
+			CLK_TICKS_PER_JIFFY * (__u64) ticks;
+	} else if (tmp > CLK_TICKS_PER_JIFFY) {
+		ticks = 2;
+		S390_lowcore.jiffy_timer += 2*CLK_TICKS_PER_JIFFY;
+	} else {
+		ticks = 1;
+		S390_lowcore.jiffy_timer += CLK_TICKS_PER_JIFFY;
+	}
+
+	/* set clock comparator for next tick */
+	tmp = S390_lowcore.jiffy_timer + CPU_DEVIATION;
+	asm volatile ("SCKC %0" : : "m" (tmp));
 
 	irq_enter(cpu, 0);
 
+#ifdef CONFIG_SMP
 	/*
-	 * set clock comparator for next tick
+	 * Do not rely on the boot cpu to do the calls to do_timer.
+	 * Spread it over all cpus instead.
 	 */
-        S390_lowcore.jiffy_timer += CLK_TICKS_PER_JIFFY;
-        asm volatile ("SCKC %0" : : "m" (S390_lowcore.jiffy_timer));
-
-#ifdef CONFIG_SMP
-	if (S390_lowcore.cpu_data.cpu_addr == boot_cpu_addr)
-		write_lock(&xtime_lock);
-
-	update_process_times(user_mode(regs));
-
-	if (S390_lowcore.cpu_data.cpu_addr == boot_cpu_addr) {
-		do_timer(regs);
-		write_unlock(&xtime_lock);
+	write_lock(&xtime_lock);
+	if (S390_lowcore.jiffy_timer > xtime_cc) {
+		__u32 xticks;
+
+		tmp = S390_lowcore.jiffy_timer - xtime_cc;
+		if (tmp >= 2*CLK_TICKS_PER_JIFFY) {
+			xticks = tmp / CLK_TICKS_PER_JIFFY;
+			xtime_cc += (__u64) xticks * CLK_TICKS_PER_JIFFY;
+		} else {
+			xticks = 1;
+			xtime_cc += CLK_TICKS_PER_JIFFY;
+		}
+		while (xticks--)
+			do_timer(regs);
 	}
+	write_unlock(&xtime_lock);
+	while (ticks--)
+		update_process_times(user_mode(regs));
 #else
-	do_timer(regs);
+	while (ticks--)
+		do_timer(regs);
 #endif
 
 	irq_exit(cpu, 0);
@@ -153,11 +183,13 @@ static void do_comparator_interrupt(stru
  */
 void init_cpu_timer(void)
 {
-	unsigned long cr0;
+        unsigned long cr0;
+	__u64 timer;
 
-	S390_lowcore.jiffy_timer = (__u64) jiffies * CLK_TICKS_PER_JIFFY;
-	S390_lowcore.jiffy_timer += init_timer_cc + CLK_TICKS_PER_JIFFY;
-	asm volatile ("SCKC %0" : : "m" (S390_lowcore.jiffy_timer));
+        timer = init_timer_cc + (__u64) jiffies * CLK_TICKS_PER_JIFFY;
+        S390_lowcore.jiffy_timer = timer + CLK_TICKS_PER_JIFFY;
+        timer += CLK_TICKS_PER_JIFFY + CPU_DEVIATION;
+        asm volatile ("SCKC %0" : : "m" (timer));
         /* allow clock comparator timer interrupt */
         asm volatile ("STCTG 0,0,%0" : "=m" (cr0) : : "memory");
         cr0 |= 0x800;
@@ -193,12 +225,13 @@ void __init time_init(void)
         }
 
 	/* set xtime */
+	xtime_cc = init_timer_cc + CLK_TICKS_PER_JIFFY;
         set_time_cc = init_timer_cc - 0x8126d60e46000000LL +
                       (0x3c26700LL*1000000*4096);
         tod_to_timeval(set_time_cc, &xtime);
 
         /* request the 0x1004 external interrupt */
-        if (register_early_external_interrupt(0x1004, do_comparator_interrupt,
+        if (register_early_external_interrupt(0x1004, NULL,
 					      &ext_int_info_timer) != 0)
                 panic("Couldn't request external interrupt 0x1004");
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/sh/config.in linux-2.4.28-pre3/arch/sh/config.in
--- linux-2.4.27/arch/sh/config.in	2004-02-18 13:36:30.000000000 +0000
+++ linux-2.4.28-pre3/arch/sh/config.in	2004-09-10 19:34:57.000000000 +0000
@@ -282,7 +282,7 @@ if [ "$CONFIG_PROC_FS" = "y" ]; then
 	"ELF		CONFIG_KCORE_ELF	\
 	 A.OUT		CONFIG_KCORE_AOUT" ELF
 fi
-tristate 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF
+bool 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF
 tristate 'Kernel support for MISC binaries' CONFIG_BINFMT_MISC
 
 bool 'Select task to kill on out of memory condition' CONFIG_OOM_KILLER
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/sh64/config.in linux-2.4.28-pre3/arch/sh64/config.in
--- linux-2.4.27/arch/sh64/config.in	2004-08-07 23:26:04.000000000 +0000
+++ linux-2.4.28-pre3/arch/sh64/config.in	2004-09-10 19:37:23.000000000 +0000
@@ -150,7 +150,7 @@ if [ "$CONFIG_PROC_FS" = "y" ]; then
 	"ELF		CONFIG_KCORE_ELF	\
 	 A.OUT		CONFIG_KCORE_AOUT" ELF
 fi
-tristate 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF
+bool 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF
 tristate 'Kernel support for MISC binaries' CONFIG_BINFMT_MISC
 
 bool 'Select task to kill on out of memory condition' CONFIG_OOM_KILLER
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/sh64/defconfig linux-2.4.28-pre3/arch/sh64/defconfig
--- linux-2.4.27/arch/sh64/defconfig	2004-08-07 23:26:04.000000000 +0000
+++ linux-2.4.28-pre3/arch/sh64/defconfig	2004-09-10 19:36:59.000000000 +0000
@@ -386,7 +386,7 @@ CONFIG_NFS_V3=y
 CONFIG_ROOT_NFS=y
 # CONFIG_NFSD is not set
 # CONFIG_NFSD_V3 is not set
-# CONFIG_NFSD_TCP is not set
+CONFIG_NFSD_TCP=y
 CONFIG_SUNRPC=y
 CONFIG_LOCKD=y
 CONFIG_LOCKD_V4=y
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/sparc/config.in linux-2.4.28-pre3/arch/sparc/config.in
--- linux-2.4.27/arch/sparc/config.in	2004-02-18 13:36:30.000000000 +0000
+++ linux-2.4.28-pre3/arch/sparc/config.in	2004-09-10 19:32:23.000000000 +0000
@@ -73,7 +73,7 @@ if [ "$CONFIG_PROC_FS" = "y" ]; then
    define_bool CONFIG_KCORE_ELF y
 fi
 tristate 'Kernel support for a.out binaries' CONFIG_BINFMT_AOUT
-tristate 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF
+bool 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF
 tristate 'Kernel support for MISC binaries' CONFIG_BINFMT_MISC
 bool 'SunOS binary emulation' CONFIG_SUNOS_EMUL
 bool 'Select task to kill on out of memory condition' CONFIG_OOM_KILLER
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/sparc/lib/copy_user.S linux-2.4.28-pre3/arch/sparc/lib/copy_user.S
--- linux-2.4.27/arch/sparc/lib/copy_user.S	2003-11-28 18:26:19.000000000 +0000
+++ linux-2.4.28-pre3/arch/sparc/lib/copy_user.S	2004-09-10 19:35:12.000000000 +0000
@@ -65,52 +65,52 @@
 
 /* Both these macros have to start with exactly the same insn */
 #define MOVE_BIGCHUNK(src, dst, offset, t0, t1, t2, t3, t4, t5, t6, t7) \
-	ldd	[%src + offset + 0x00], %t0; \
-	ldd	[%src + offset + 0x08], %t2; \
-	ldd	[%src + offset + 0x10], %t4; \
-	ldd	[%src + offset + 0x18], %t6; \
-	st	%t0, [%dst + offset + 0x00]; \
-	st	%t1, [%dst + offset + 0x04]; \
-	st	%t2, [%dst + offset + 0x08]; \
-	st	%t3, [%dst + offset + 0x0c]; \
-	st	%t4, [%dst + offset + 0x10]; \
-	st	%t5, [%dst + offset + 0x14]; \
-	st	%t6, [%dst + offset + 0x18]; \
-	st	%t7, [%dst + offset + 0x1c];
+	ldd	[%src + (offset) + 0x00], %t0; \
+	ldd	[%src + (offset) + 0x08], %t2; \
+	ldd	[%src + (offset) + 0x10], %t4; \
+	ldd	[%src + (offset) + 0x18], %t6; \
+	st	%t0, [%dst + (offset) + 0x00]; \
+	st	%t1, [%dst + (offset) + 0x04]; \
+	st	%t2, [%dst + (offset) + 0x08]; \
+	st	%t3, [%dst + (offset) + 0x0c]; \
+	st	%t4, [%dst + (offset) + 0x10]; \
+	st	%t5, [%dst + (offset) + 0x14]; \
+	st	%t6, [%dst + (offset) + 0x18]; \
+	st	%t7, [%dst + (offset) + 0x1c];
 
 #define MOVE_BIGALIGNCHUNK(src, dst, offset, t0, t1, t2, t3, t4, t5, t6, t7) \
-	ldd	[%src + offset + 0x00], %t0; \
-	ldd	[%src + offset + 0x08], %t2; \
-	ldd	[%src + offset + 0x10], %t4; \
-	ldd	[%src + offset + 0x18], %t6; \
-	std	%t0, [%dst + offset + 0x00]; \
-	std	%t2, [%dst + offset + 0x08]; \
-	std	%t4, [%dst + offset + 0x10]; \
-	std	%t6, [%dst + offset + 0x18];
+	ldd	[%src + (offset) + 0x00], %t0; \
+	ldd	[%src + (offset) + 0x08], %t2; \
+	ldd	[%src + (offset) + 0x10], %t4; \
+	ldd	[%src + (offset) + 0x18], %t6; \
+	std	%t0, [%dst + (offset) + 0x00]; \
+	std	%t2, [%dst + (offset) + 0x08]; \
+	std	%t4, [%dst + (offset) + 0x10]; \
+	std	%t6, [%dst + (offset) + 0x18];
 
 #define MOVE_LASTCHUNK(src, dst, offset, t0, t1, t2, t3) \
-	ldd	[%src - offset - 0x10], %t0; \
-	ldd	[%src - offset - 0x08], %t2; \
-	st	%t0, [%dst - offset - 0x10]; \
-	st	%t1, [%dst - offset - 0x0c]; \
-	st	%t2, [%dst - offset - 0x08]; \
-	st	%t3, [%dst - offset - 0x04];
+	ldd	[%src - (offset) - 0x10], %t0; \
+	ldd	[%src - (offset) - 0x08], %t2; \
+	st	%t0, [%dst - (offset) - 0x10]; \
+	st	%t1, [%dst - (offset) - 0x0c]; \
+	st	%t2, [%dst - (offset) - 0x08]; \
+	st	%t3, [%dst - (offset) - 0x04];
 
 #define MOVE_HALFCHUNK(src, dst, offset, t0, t1, t2, t3) \
-	lduh	[%src + offset + 0x00], %t0; \
-	lduh	[%src + offset + 0x02], %t1; \
-	lduh	[%src + offset + 0x04], %t2; \
-	lduh	[%src + offset + 0x06], %t3; \
-	sth	%t0, [%dst + offset + 0x00]; \
-	sth	%t1, [%dst + offset + 0x02]; \
-	sth	%t2, [%dst + offset + 0x04]; \
-	sth	%t3, [%dst + offset + 0x06];
+	lduh	[%src + (offset) + 0x00], %t0; \
+	lduh	[%src + (offset) + 0x02], %t1; \
+	lduh	[%src + (offset) + 0x04], %t2; \
+	lduh	[%src + (offset) + 0x06], %t3; \
+	sth	%t0, [%dst + (offset) + 0x00]; \
+	sth	%t1, [%dst + (offset) + 0x02]; \
+	sth	%t2, [%dst + (offset) + 0x04]; \
+	sth	%t3, [%dst + (offset) + 0x06];
 
 #define MOVE_SHORTCHUNK(src, dst, offset, t0, t1) \
-	ldub	[%src - offset - 0x02], %t0; \
-	ldub	[%src - offset - 0x01], %t1; \
-	stb	%t0, [%dst - offset - 0x02]; \
-	stb	%t1, [%dst - offset - 0x01];
+	ldub	[%src - (offset) - 0x02], %t0; \
+	ldub	[%src - (offset) - 0x01], %t1; \
+	stb	%t0, [%dst - (offset) - 0x02]; \
+	stb	%t1, [%dst - (offset) - 0x01];
 
 	.text
 	.align	4
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/sparc64/config.in linux-2.4.28-pre3/arch/sparc64/config.in
--- linux-2.4.27/arch/sparc64/config.in	2004-08-07 23:26:04.000000000 +0000
+++ linux-2.4.28-pre3/arch/sparc64/config.in	2004-09-10 19:33:39.000000000 +0000
@@ -78,7 +78,7 @@ if [ "$CONFIG_SPARC32_COMPAT" != "n" ]; 
    tristate '  Kernel support for 32-bit ELF binaries' CONFIG_BINFMT_ELF32
    bool '  Kernel support for 32-bit (ie. SunOS) a.out binaries' CONFIG_BINFMT_AOUT32
 fi
-tristate 'Kernel support for 64-bit ELF binaries' CONFIG_BINFMT_ELF
+bool 'Kernel support for 64-bit ELF binaries' CONFIG_BINFMT_ELF
 tristate 'Kernel support for MISC binaries' CONFIG_BINFMT_MISC
 bool 'SunOS binary emulation' CONFIG_SUNOS_EMUL
 if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/sparc64/defconfig linux-2.4.28-pre3/arch/sparc64/defconfig
--- linux-2.4.27/arch/sparc64/defconfig	2004-08-07 23:26:04.000000000 +0000
+++ linux-2.4.28-pre3/arch/sparc64/defconfig	2004-09-10 19:33:49.000000000 +0000
@@ -375,7 +375,7 @@ CONFIG_NET_SCH_SFQ=m
 CONFIG_NET_SCH_TEQL=m
 CONFIG_NET_SCH_TBF=m
 CONFIG_NET_SCH_GRED=m
-CONFIG_NET_SCH_DELAY=m
+CONFIG_NET_SCH_NETEM=m
 CONFIG_NET_SCH_DSMARK=m
 CONFIG_NET_SCH_INGRESS=m
 CONFIG_NET_QOS=y
@@ -410,6 +410,7 @@ CONFIG_BLK_DEV_IDE=y
 #
 # CONFIG_BLK_DEV_HD_IDE is not set
 # CONFIG_BLK_DEV_HD is not set
+# CONFIG_BLK_DEV_IDE_SATA is not set
 CONFIG_BLK_DEV_IDEDISK=y
 # CONFIG_IDEDISK_MULTI_MODE is not set
 # CONFIG_IDEDISK_STROKE is not set
@@ -1134,6 +1135,8 @@ CONFIG_CRYPTO_SERPENT=m
 CONFIG_CRYPTO_AES=m
 CONFIG_CRYPTO_CAST5=m
 CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_TEA=m
+CONFIG_CRYPTO_KHAZAD=m
 CONFIG_CRYPTO_ARC4=m
 CONFIG_CRYPTO_DEFLATE=y
 CONFIG_CRYPTO_MICHAEL_MIC=m
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/sparc64/kernel/head.S linux-2.4.28-pre3/arch/sparc64/kernel/head.S
--- linux-2.4.27/arch/sparc64/kernel/head.S	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.28-pre3/arch/sparc64/kernel/head.S	2004-09-10 19:34:07.000000000 +0000
@@ -50,7 +50,7 @@ bootup_user_stack:
  */
         .global root_flags, ram_flags, root_dev
         .global sparc_ramdisk_image, sparc_ramdisk_size
-	.globl	silo_args
+	.global sparc_ramdisk_image64
 
         .ascii  "HdrS"
         .word   LINUX_VERSION_CODE
@@ -61,7 +61,7 @@ bootup_user_stack:
 	 * 0x0202 : Supports kernel params string
 	 * 0x0201 : Supports reboot_command
 	 */
-	.half   0x0300          /* HdrS version */
+	.half   0x0301          /* HdrS version */
 
 root_flags:
         .half   1
@@ -75,6 +75,8 @@ sparc_ramdisk_size:
         .word   0
         .xword  reboot_command
 	.xword	bootstr_info
+sparc_ramdisk_image64:
+	.xword	0
 	.word	_end
 
 	/* We must be careful, 32-bit OpenBOOT will get confused if it
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/sparc64/kernel/ioctl32.c linux-2.4.28-pre3/arch/sparc64/kernel/ioctl32.c
--- linux-2.4.27/arch/sparc64/kernel/ioctl32.c	2004-08-07 23:26:04.000000000 +0000
+++ linux-2.4.28-pre3/arch/sparc64/kernel/ioctl32.c	2004-09-10 19:36:44.000000000 +0000
@@ -2948,7 +2948,7 @@ static int do_lvm_ioctl(unsigned int fd,
 	case LV_REMOVE:
 	case LV_RENAME:
 	case LV_STATUS_BYNAME:
-	        err = copy_from_user(&u.pv_status, arg, sizeof(u.pv_status.pv_name));
+	        err = copy_from_user(&u.lv_req, arg, sizeof(u.lv_req.lv_name));
 		if (err)
 			return -EFAULT;
 		if (cmd != LV_REMOVE) {
@@ -2991,7 +2991,7 @@ static int do_lvm_ioctl(unsigned int fd,
 
 	case PV_CHANGE:
 	case PV_STATUS:
-		err = copy_from_user(&u.pv_status, arg, sizeof(u.lv_req.lv_name));
+		err = copy_from_user(&u.pv_status, arg, sizeof(u.pv_status.pv_name));
 		if (err)
 			return -EFAULT;
 		err = __get_user(ptr, &((pv_status_req32_t *)arg)->pv);
@@ -3063,7 +3063,7 @@ static int do_lvm_ioctl(unsigned int fd,
 	        if (u.lv_bydev.lv) {
 			if (!err)
 				err = copy_lv_t(ptr, u.lv_bydev.lv);
-			put_lv_t(u.lv_byindex.lv);
+			put_lv_t(u.lv_bydev.lv);
 	        }
 	        break;
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/sparc64/kernel/itlb_base.S linux-2.4.28-pre3/arch/sparc64/kernel/itlb_base.S
--- linux-2.4.27/arch/sparc64/kernel/itlb_base.S	2003-06-13 14:51:32.000000000 +0000
+++ linux-2.4.28-pre3/arch/sparc64/kernel/itlb_base.S	2004-09-10 19:32:39.000000000 +0000
@@ -41,6 +41,9 @@
 	CREATE_VPTE_OFFSET2(%g4, %g6)			! Create VPTE offset
 	ldxa		[%g3 + %g6] ASI_P, %g5		! Load VPTE
 1:	brgez,pn	%g5, 3f				! Not valid, branch out
+	 sethi		%hi(_PAGE_EXEC), %g4		! Delay-slot
+	andcc		%g5, %g4, %g0			! Executable?
+	be,pn		%xcc, 3f			! Nope, branch.
 	 nop						! Delay-slot
 2:	stxa		%g5, [%g0] ASI_ITLB_DATA_IN	! Load PTE into TLB
 	retry						! Trap return
@@ -73,9 +76,6 @@ winfix_trampoline:
 	nop
 	nop
 	nop
-	nop
-	nop
-	nop
 	CREATE_VPTE_NOP
 
 #undef CREATE_VPTE_OFFSET1
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/sparc64/kernel/pci_iommu.c linux-2.4.28-pre3/arch/sparc64/kernel/pci_iommu.c
--- linux-2.4.27/arch/sparc64/kernel/pci_iommu.c	2003-11-28 18:26:19.000000000 +0000
+++ linux-2.4.28-pre3/arch/sparc64/kernel/pci_iommu.c	2004-09-10 19:32:45.000000000 +0000
@@ -56,6 +56,39 @@ static void __iommu_flushall(struct pci_
 	}
 }
 
+#define IOPTE_CONSISTENT(CTX) \
+	(IOPTE_VALID | IOPTE_CACHE | \
+	 (((CTX) << 47) & IOPTE_CONTEXT))
+
+#define IOPTE_STREAMING(CTX) \
+	(IOPTE_CONSISTENT(CTX) | IOPTE_STBUF)
+
+/* Existing mappings are never marked invalid, instead they
+ * are pointed to a dummy page.
+ */
+#define IOPTE_IS_DUMMY(iommu, iopte)	\
+	((iopte_val(*iopte) & IOPTE_PAGE) == (iommu)->dummy_page_pa)
+
+static void inline iopte_make_dummy(struct pci_iommu *iommu, iopte_t *iopte)
+{
+	unsigned long val = iopte_val(*iopte);
+
+	val &= ~IOPTE_PAGE;
+	val |= iommu->dummy_page_pa;
+
+	iopte_val(*iopte) = val;
+}
+
+void pci_iommu_table_init(struct pci_iommu *iommu, int tsbsize)
+{
+	int i;
+
+	tsbsize /= sizeof(iopte_t);
+
+	for (i = 0; i < tsbsize; i++)
+		iopte_make_dummy(iommu, &iommu->page_table[i]);
+}
+
 static iopte_t *alloc_streaming_cluster(struct pci_iommu *iommu, unsigned long npages)
 {
 	iopte_t *iopte, *limit, *first;
@@ -79,7 +112,7 @@ static iopte_t *alloc_streaming_cluster(
 	
 	first = iopte;
 	for (;;) {
-		if (iopte_val(*iopte) == 0UL) {
+		if (IOPTE_IS_DUMMY(iommu, iopte)) {
 			if ((iopte + (1 << cnum)) >= limit)
 				ent = 0;
 			else
@@ -142,12 +175,12 @@ static iopte_t *alloc_consistent_cluster
 	iopte = iommu->page_table + (1 << (iommu->page_table_sz_bits - PBM_LOGCLUSTERS));
 	while (iopte > iommu->page_table) {
 		iopte--;
-		if (!(iopte_val(*iopte) & IOPTE_VALID)) {
+		if (IOPTE_IS_DUMMY(iommu, iopte)) {
 			unsigned long tmp = npages;
 
 			while (--tmp) {
 				iopte--;
-				if (iopte_val(*iopte) & IOPTE_VALID)
+				if (!IOPTE_IS_DUMMY(iommu, iopte))
 					break;
 			}
 			if (tmp == 0) {
@@ -162,15 +195,6 @@ static iopte_t *alloc_consistent_cluster
 	return NULL;
 }
 
-#define IOPTE_CONSISTENT(CTX) \
-	(IOPTE_VALID | IOPTE_CACHE | \
-	 (((CTX) << 47) & IOPTE_CONTEXT))
-
-#define IOPTE_STREAMING(CTX) \
-	(IOPTE_CONSISTENT(CTX) | IOPTE_STBUF)
-
-#define IOPTE_INVALID	0UL
-
 /* Allocate and map kernel buffer of size SIZE using consistent mode
  * DMA for PCI device PDEV.  Return non-NULL cpu-side address if
  * successful and set *DMA_ADDRP to the PCI side dma address.
@@ -261,7 +285,7 @@ void pci_free_consistent(struct pci_dev 
 		limit = (iommu->page_table +
 			 (1 << (iommu->page_table_sz_bits - PBM_LOGCLUSTERS)));
 		while (walk < limit) {
-			if (iopte_val(*walk) != IOPTE_INVALID)
+			if (!IOPTE_IS_DUMMY(iommu, walk))
 				break;
 			walk++;
 		}
@@ -280,7 +304,7 @@ void pci_free_consistent(struct pci_dev 
 		ctx = (iopte_val(*iopte) & IOPTE_CONTEXT) >> 47UL;
 
 	for (i = 0; i < npages; i++, iopte++)
-		iopte_val(*iopte) = IOPTE_INVALID;
+		iopte_make_dummy(iommu, iopte);
 
 	if (iommu->iommu_ctxflush) {
 		pci_iommu_write(iommu->iommu_ctxflush, ctx);
@@ -377,7 +401,7 @@ void pci_unmap_single(struct pci_dev *pd
 	base = iommu->page_table +
 		((bus_addr - iommu->page_table_map_base) >> IO_PAGE_SHIFT);
 #ifdef DEBUG_PCI_IOMMU
-	if (iopte_val(*base) == IOPTE_INVALID)
+	if (IOPTE_IS_DUMMY(iommu, base))
 		printk("pci_unmap_single called on non-mapped region %08x,%08x from %016lx\n",
 		       bus_addr, sz, __builtin_return_address(0));
 #endif
@@ -416,7 +440,7 @@ void pci_unmap_single(struct pci_dev *pd
 	}
 
 	/* Step 2: Clear out first TSB entry. */
-	iopte_val(*base) = IOPTE_INVALID;
+	iopte_make_dummy(iommu, base);
 
 	free_streaming_cluster(iommu, bus_addr - iommu->page_table_map_base,
 			       npages, ctx);
@@ -617,7 +641,7 @@ void pci_unmap_sg(struct pci_dev *pdev, 
 		((bus_addr - iommu->page_table_map_base) >> IO_PAGE_SHIFT);
 
 #ifdef DEBUG_PCI_IOMMU
-	if (iopte_val(*base) == IOPTE_INVALID)
+	if (IOPTE_IS_DUMMY(iommu, base))
 		printk("pci_unmap_sg called on non-mapped region %016lx,%d from %016lx\n", sglist->dma_address, nelems, __builtin_return_address(0));
 #endif
 
@@ -654,7 +678,7 @@ void pci_unmap_sg(struct pci_dev *pdev, 
 	}
 
 	/* Step 2: Clear out first TSB entry. */
-	iopte_val(*base) = IOPTE_INVALID;
+	iopte_make_dummy(iommu, base);
 
 	free_streaming_cluster(iommu, bus_addr - iommu->page_table_map_base,
 			       npages, ctx);
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/sparc64/kernel/pci_psycho.c linux-2.4.28-pre3/arch/sparc64/kernel/pci_psycho.c
--- linux-2.4.27/arch/sparc64/kernel/pci_psycho.c	2003-11-28 18:26:19.000000000 +0000
+++ linux-2.4.28-pre3/arch/sparc64/kernel/pci_psycho.c	2004-09-10 19:35:22.000000000 +0000
@@ -1373,6 +1373,14 @@ static void __init psycho_iommu_init(str
 	 * in pci_iommu.c
 	 */
 
+	iommu->dummy_page = __get_free_pages(GFP_KERNEL, 0);
+	if (!iommu->dummy_page) {
+		prom_printf("PSYCHO_IOMMU: Error, gfp(dummy_page) failed.\n");
+		prom_halt();
+	}
+	memset((void *)iommu->dummy_page, 0, PAGE_SIZE);
+	iommu->dummy_page_pa = (unsigned long) __pa(iommu->dummy_page);
+
 	/* Using assumed page size 8K with 128K entries we need 1MB iommu page
 	 * table (128K ioptes * 8 bytes per iopte).  This is
 	 * page order 7 on UltraSparc.
@@ -1386,7 +1394,7 @@ static void __init psycho_iommu_init(str
 	iommu->page_table_sz_bits = 17;
 	iommu->page_table_map_base = 0xc0000000;
 	iommu->dma_addr_mask = 0xffffffff;
-	memset((char *)tsbbase, 0, IO_TSB_SIZE);
+	pci_iommu_table_init(iommu, IO_TSB_SIZE);
 
 	/* We start with no consistent mappings. */
 	iommu->lowest_consistent_map =
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/sparc64/kernel/pci_sabre.c linux-2.4.28-pre3/arch/sparc64/kernel/pci_sabre.c
--- linux-2.4.27/arch/sparc64/kernel/pci_sabre.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.28-pre3/arch/sparc64/kernel/pci_sabre.c	2004-09-10 19:34:33.000000000 +0000
@@ -1315,6 +1315,14 @@ static void __init sabre_iommu_init(stru
 	 * in pci_iommu.c
 	 */
 
+	iommu->dummy_page = __get_free_pages(GFP_KERNEL, 0);
+	if (!iommu->dummy_page) {
+		prom_printf("PSYCHO_IOMMU: Error, gfp(dummy_page) failed.\n");
+		prom_halt();
+	}
+	memset((void *)iommu->dummy_page, 0, PAGE_SIZE);
+	iommu->dummy_page_pa = (unsigned long) __pa(iommu->dummy_page);
+
 	tsbbase = __get_free_pages(GFP_KERNEL, order = get_order(tsbsize * 1024 * 8));
 	if (!tsbbase) {
 		prom_printf("SABRE_IOMMU: Error, gfp(tsb) failed.\n");
@@ -1323,7 +1331,7 @@ static void __init sabre_iommu_init(stru
 	iommu->page_table = (iopte_t *)tsbbase;
 	iommu->page_table_map_base = dvma_offset;
 	iommu->dma_addr_mask = dma_mask;
-	memset((char *)tsbbase, 0, PAGE_SIZE << order);
+	pci_iommu_table_init(iommu, PAGE_SIZE << order);
 
 	sabre_write(p->pbm_A.controller_regs + SABRE_IOMMU_TSBBASE, __pa(tsbbase));
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/sparc64/kernel/pci_schizo.c linux-2.4.28-pre3/arch/sparc64/kernel/pci_schizo.c
--- linux-2.4.27/arch/sparc64/kernel/pci_schizo.c	2003-11-28 18:26:19.000000000 +0000
+++ linux-2.4.28-pre3/arch/sparc64/kernel/pci_schizo.c	2004-09-10 19:32:41.000000000 +0000
@@ -1843,6 +1843,14 @@ static void schizo_pbm_iommu_init(struct
 	 * in pci_iommu.c
 	 */
 
+	iommu->dummy_page = __get_free_pages(GFP_KERNEL, 0);
+	if (!iommu->dummy_page) {
+		prom_printf("PSYCHO_IOMMU: Error, gfp(dummy_page) failed.\n");
+		prom_halt();
+	}
+	memset((void *)iommu->dummy_page, 0, PAGE_SIZE);
+	iommu->dummy_page_pa = (unsigned long) __pa(iommu->dummy_page);
+
 	/* Using assumed page size 8K with 128K entries we need 1MB iommu page
 	 * table (128K ioptes * 8 bytes per iopte).  This is
 	 * page order 7 on UltraSparc.
@@ -1857,7 +1865,7 @@ static void schizo_pbm_iommu_init(struct
 	iommu->page_table = (iopte_t *)tsbbase;
 	iommu->page_table_map_base = vdma[0];
 	iommu->dma_addr_mask = dma_mask;
-	memset((char *)tsbbase, 0, PAGE_SIZE << order);
+	pci_iommu_table_init(iommu, PAGE_SIZE << order);
 
 	switch (tsbsize) {
 	case 64:
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/sparc64/kernel/process.c linux-2.4.28-pre3/arch/sparc64/kernel/process.c
--- linux-2.4.27/arch/sparc64/kernel/process.c	2004-08-07 23:26:04.000000000 +0000
+++ linux-2.4.28-pre3/arch/sparc64/kernel/process.c	2004-09-10 19:34:24.000000000 +0000
@@ -503,7 +503,7 @@ static unsigned long clone_stackframe(un
 
 	distance = fp - psp;
 	rval = (csp - distance);
-	if (copy_in_user(rval, psp, distance))
+	if (copy_in_user((void *)rval, (void *)psp, distance))
 		rval = 0;
 	else if (current->thread.flags & SPARC_FLAG_32BIT) {
 		if (put_user(((u32)csp), &(((struct reg_window32 *)rval)->ins[6])))
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/sparc64/kernel/sbus.c linux-2.4.28-pre3/arch/sparc64/kernel/sbus.c
--- linux-2.4.27/arch/sparc64/kernel/sbus.c	2002-08-03 00:39:43.000000000 +0000
+++ linux-2.4.28-pre3/arch/sparc64/kernel/sbus.c	2004-09-10 19:37:20.000000000 +0000
@@ -27,10 +27,10 @@
  *
  * On SYSIO, using an 8K page size we have 1GB of SBUS
  * DMA space mapped.  We divide this space into equally
- * sized clusters.  Currently we allow clusters up to a
- * size of 1MB.  If anything begins to generate DMA
- * mapping requests larger than this we will need to
- * increase things a bit.
+ * sized clusters. We allocate a DMA mapping from the
+ * cluster that matches the order of the allocation, or
+ * if the order is greater than the number of clusters,
+ * we try to allocate from the last cluster.
  */
 
 #define NCLUSTERS	8UL
@@ -133,12 +133,17 @@ static void strbuf_flush(struct sbus_iom
 
 static iopte_t *alloc_streaming_cluster(struct sbus_iommu *iommu, unsigned long npages)
 {
-	iopte_t *iopte, *limit, *first;
-	unsigned long cnum, ent, flush_point;
+	iopte_t *iopte, *limit, *first, *cluster;
+	unsigned long cnum, ent, nent, flush_point, found;
 
 	cnum = 0;
+	nent = 1;
 	while ((1UL << cnum) < npages)
 		cnum++;
+	if(cnum >= NCLUSTERS) {
+		nent = 1UL << (cnum - NCLUSTERS);
+		cnum = NCLUSTERS - 1;
+	}
 	iopte  = iommu->page_table + (cnum * CLUSTER_NPAGES);
 
 	if (cnum == 0)
@@ -151,22 +156,31 @@ static iopte_t *alloc_streaming_cluster(
 	flush_point = iommu->alloc_info[cnum].flush;
 
 	first = iopte;
+	cluster = NULL;
+	found = 0;
 	for (;;) {
 		if (iopte_val(*iopte) == 0UL) {
-			if ((iopte + (1 << cnum)) >= limit)
-				ent = 0;
-			else
-				ent = ent + 1;
-			iommu->alloc_info[cnum].next = ent;
-			if (ent == flush_point)
-				__iommu_flushall(iommu);
-			break;
+			found++;
+			if (!cluster)
+				cluster = iopte;
+		} else {
+			/* Used cluster in the way */
+			cluster = NULL;
+			found = 0;
 		}
+
+		if (found == nent)
+			break;
+
 		iopte += (1 << cnum);
 		ent++;
 		if (iopte >= limit) {
 			iopte = (iommu->page_table + (cnum * CLUSTER_NPAGES));
 			ent = 0;
+
+			/* Multiple cluster allocations must not wrap */
+			cluster = NULL;
+			found = 0;
 		}
 		if (ent == flush_point)
 			__iommu_flushall(iommu);
@@ -174,8 +188,19 @@ static iopte_t *alloc_streaming_cluster(
 			goto bad;
 	}
 
+	/* ent/iopte points to the last cluster entry we're going to use,
+	 * so save our place for the next allocation.
+	 */
+	if ((iopte + (1 << cnum)) >= limit)
+		ent = 0;
+	else
+		ent = ent + 1;
+	iommu->alloc_info[cnum].next = ent;
+	if (ent == flush_point)
+		__iommu_flushall(iommu);
+
 	/* I've got your streaming cluster right here buddy boy... */
-	return iopte;
+	return cluster;
 
 bad:
 	printk(KERN_EMERG "sbus: alloc_streaming_cluster of npages(%ld) failed!\n",
@@ -185,15 +210,23 @@ bad:
 
 static void free_streaming_cluster(struct sbus_iommu *iommu, u32 base, unsigned long npages)
 {
-	unsigned long cnum, ent;
+	unsigned long cnum, ent, nent;
 	iopte_t *iopte;
 
 	cnum = 0;
+	nent = 1;
 	while ((1UL << cnum) < npages)
 		cnum++;
+	if(cnum >= NCLUSTERS) {
+		nent = 1UL << (cnum - NCLUSTERS);
+		cnum = NCLUSTERS - 1;
+	}
 	ent = (base & CLUSTER_MASK) >> (IO_PAGE_SHIFT + cnum);
 	iopte = iommu->page_table + ((base - MAP_BASE) >> IO_PAGE_SHIFT);
-	iopte_val(*iopte) = 0UL;
+	do {
+		iopte_val(*iopte) = 0UL;
+		iopte += 1 << cnum;
+	} while(--nent);
 
 	/* If the global flush might not have caught this entry,
 	 * adjust the flush point such that we will flush before
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/sparc64/kernel/signal.c linux-2.4.28-pre3/arch/sparc64/kernel/signal.c
--- linux-2.4.27/arch/sparc64/kernel/signal.c	2003-08-25 11:44:40.000000000 +0000
+++ linux-2.4.28-pre3/arch/sparc64/kernel/signal.c	2004-09-10 19:35:20.000000000 +0000
@@ -116,8 +116,8 @@ asmlinkage void sparc64_set_context(stru
 	regs->tnpc = npc;
 	err |= __get_user(regs->y, &((*grp)[MC_Y]));
 	err |= __get_user(tstate, &((*grp)[MC_TSTATE]));
-	regs->tstate &= ~(TSTATE_ICC | TSTATE_XCC);
-	regs->tstate |= (tstate & (TSTATE_ICC | TSTATE_XCC));
+	regs->tstate &= ~(TSTATE_ASI | TSTATE_ICC | TSTATE_XCC);
+	regs->tstate |= (tstate & (TSTATE_ASI | TSTATE_ICC | TSTATE_XCC));
 	err |= __get_user(regs->u_regs[UREG_G1], (&(*grp)[MC_G1]));
 	err |= __get_user(regs->u_regs[UREG_G2], (&(*grp)[MC_G2]));
 	err |= __get_user(regs->u_regs[UREG_G3], (&(*grp)[MC_G3]));
@@ -437,9 +437,9 @@ void do_rt_sigreturn(struct pt_regs *reg
 	err |= __get_user(tstate, &sf->regs.tstate);
 	err |= copy_from_user(regs->u_regs, sf->regs.u_regs, sizeof(regs->u_regs));
 
-	/* User can only change condition codes in %tstate. */
-	regs->tstate &= ~(TSTATE_ICC | TSTATE_XCC);
-	regs->tstate |= (tstate & (TSTATE_ICC | TSTATE_XCC));
+	/* User can only change condition codes and %asi in %tstate. */
+	regs->tstate &= ~(TSTATE_ASI | TSTATE_ICC | TSTATE_XCC);
+	regs->tstate |= (tstate & (TSTATE_ASI | TSTATE_ICC | TSTATE_XCC));
 
 	err |= __get_user(fpu_save, &sf->fpu_save);
 	if (fpu_save)
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/sparc64/kernel/signal32.c linux-2.4.28-pre3/arch/sparc64/kernel/signal32.c
--- linux-2.4.27/arch/sparc64/kernel/signal32.c	2004-08-07 23:26:04.000000000 +0000
+++ linux-2.4.28-pre3/arch/sparc64/kernel/signal32.c	2004-09-10 19:31:52.000000000 +0000
@@ -62,6 +62,16 @@ struct signal_sframe32 {
 	unsigned extramask[_NSIG_WORDS32 - 1];
 };
 
+/* This magic should be in g_upper[0] for all upper parts
+ * to be valid.
+ */
+#define SIGINFO_EXTRA_V8PLUS_MAGIC	0x130e269
+typedef struct {
+	unsigned int g_upper[8];
+	unsigned int o_upper[8];
+	unsigned int asi;
+} siginfo_extra_v8plus_t;
+
 /* 
  * And the new one, intended to be used for Linux applications only
  * (we have enough in there to work with clone).
@@ -292,8 +302,13 @@ void do_new_sigreturn32(struct pt_regs *
 	if ((psr & (PSR_VERS|PSR_IMPL)) == PSR_V8PLUS) {
 		err |= __get_user(i, &sf->v8plus.g_upper[0]);
 		if (i == SIGINFO_EXTRA_V8PLUS_MAGIC) {
+			unsigned long asi;
+
 			for (i = UREG_G1; i <= UREG_I7; i++)
 				err |= __get_user(((u32 *)regs->u_regs)[2*i], &sf->v8plus.g_upper[i]);
+			err |= __get_user(asi, &sf->v8plus.asi);
+			regs->tstate &= ~TSTATE_ASI;
+			regs->tstate |= ((asi & 0xffUL) << 24UL);
 		}
 	}
 
@@ -431,8 +446,13 @@ asmlinkage void do_rt_sigreturn32(struct
 	if ((psr & (PSR_VERS|PSR_IMPL)) == PSR_V8PLUS) {
 		err |= __get_user(i, &sf->v8plus.g_upper[0]);
 		if (i == SIGINFO_EXTRA_V8PLUS_MAGIC) {
+			unsigned long asi;
+
 			for (i = UREG_G1; i <= UREG_I7; i++)
 				err |= __get_user(((u32 *)regs->u_regs)[2*i], &sf->v8plus.g_upper[i]);
+			err |= __get_user(asi, &sf->v8plus.asi);
+			regs->tstate &= ~TSTATE_ASI;
+			regs->tstate |= ((asi & 0xffUL) << 24UL);
 		}
 	}
 
@@ -728,7 +748,10 @@ static inline void new_setup_frame32(str
 	err |= __put_user(sizeof(siginfo_extra_v8plus_t), &sf->extra_size);
 	err |= __put_user(SIGINFO_EXTRA_V8PLUS_MAGIC, &sf->v8plus.g_upper[0]);
 	for (i = 1; i < 16; i++)
-		err |= __put_user(((u32 *)regs->u_regs)[2*i], &sf->v8plus.g_upper[i]);
+		err |= __put_user(((u32 *)regs->u_regs)[2*i],
+				  &sf->v8plus.g_upper[i]);
+	err |= __put_user((regs->tstate & TSTATE_ASI) >> 24UL,
+			  &sf->v8plus.asi);
 
 	if (psr & PSR_EF) {
 		err |= save_fpu_state32(regs, &sf->fpu_state);
@@ -1175,7 +1198,10 @@ static inline void setup_rt_frame32(stru
 	err |= __put_user(sizeof(siginfo_extra_v8plus_t), &sf->extra_size);
 	err |= __put_user(SIGINFO_EXTRA_V8PLUS_MAGIC, &sf->v8plus.g_upper[0]);
 	for (i = 1; i < 16; i++)
-		err |= __put_user(((u32 *)regs->u_regs)[2*i], &sf->v8plus.g_upper[i]);
+		err |= __put_user(((u32 *)regs->u_regs)[2*i],
+				  &sf->v8plus.g_upper[i]);
+	err |= __put_user((regs->tstate & TSTATE_ASI) >> 24UL,
+			  &sf->v8plus.asi);
 
 	if (psr & PSR_EF) {
 		err |= save_fpu_state32(regs, &sf->fpu_state);
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/sparc64/kernel/sparc64_ksyms.c linux-2.4.28-pre3/arch/sparc64/kernel/sparc64_ksyms.c
--- linux-2.4.27/arch/sparc64/kernel/sparc64_ksyms.c	2004-08-07 23:26:04.000000000 +0000
+++ linux-2.4.28-pre3/arch/sparc64/kernel/sparc64_ksyms.c	2004-09-10 19:36:30.000000000 +0000
@@ -324,8 +324,6 @@ EXPORT_SYMBOL(sparc32_open);
 #endif
 
 /* Special internal versions of library functions. */
-EXPORT_SYMBOL(__memcpy);
-EXPORT_SYMBOL(__memset);
 EXPORT_SYMBOL(_clear_page);
 EXPORT_SYMBOL(clear_user_page);
 EXPORT_SYMBOL(copy_user_page);
@@ -334,14 +332,17 @@ EXPORT_SYMBOL(__memscan_zero);
 EXPORT_SYMBOL(__memscan_generic);
 EXPORT_SYMBOL(__memcmp);
 EXPORT_SYMBOL(__strncmp);
-EXPORT_SYMBOL(__memmove);
+EXPORT_SYMBOL(__memset);
 
 EXPORT_SYMBOL(csum_partial_copy_sparc64);
 
 /* Moving data to/from userspace. */
-EXPORT_SYMBOL(__copy_to_user);
-EXPORT_SYMBOL(__copy_from_user);
-EXPORT_SYMBOL(__strncpy_from_user);
+EXPORT_SYMBOL(___copy_to_user);
+EXPORT_SYMBOL(___copy_from_user);
+EXPORT_SYMBOL(___copy_in_user);
+EXPORT_SYMBOL(copy_to_user_fixup);
+EXPORT_SYMBOL(copy_from_user_fixup);
+EXPORT_SYMBOL(copy_in_user_fixup);
 EXPORT_SYMBOL(__bzero_noasi);
 
 /* Various address conversion macros use this. */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/sparc64/kernel/time.c linux-2.4.28-pre3/arch/sparc64/kernel/time.c
--- linux-2.4.27/arch/sparc64/kernel/time.c	2003-11-28 18:26:19.000000000 +0000
+++ linux-2.4.28-pre3/arch/sparc64/kernel/time.c	2004-09-10 19:34:52.000000000 +0000
@@ -432,18 +432,12 @@ void sparc64_do_profile(unsigned long pc
 		extern int _stext;
 		extern int rwlock_impl_begin, rwlock_impl_end;
 		extern int atomic_impl_begin, atomic_impl_end;
-		extern int __memcpy_begin, __memcpy_end;
-		extern int __bzero_begin, __bzero_end;
 		extern int __bitops_begin, __bitops_end;
 
 		if ((pc >= (unsigned long) &atomic_impl_begin &&
 		     pc < (unsigned long) &atomic_impl_end) ||
 		    (pc >= (unsigned long) &rwlock_impl_begin &&
 		     pc < (unsigned long) &rwlock_impl_end) ||
-		    (pc >= (unsigned long) &__memcpy_begin &&
-		     pc < (unsigned long) &__memcpy_end) ||
-		    (pc >= (unsigned long) &__bzero_begin &&
-		     pc < (unsigned long) &__bzero_end) ||
 		    (pc >= (unsigned long) &__bitops_begin &&
 		     pc < (unsigned long) &__bitops_end))
 			pc = o7;
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/sparc64/lib/Makefile linux-2.4.28-pre3/arch/sparc64/lib/Makefile
--- linux-2.4.27/arch/sparc64/lib/Makefile	2002-08-03 00:39:43.000000000 +0000
+++ linux-2.4.28-pre3/arch/sparc64/lib/Makefile	2004-09-10 19:32:22.000000000 +0000
@@ -8,9 +8,11 @@ EXTRA_AFLAGS := -ansi
 L_TARGET = lib.a
 obj-y := PeeCeeI.o blockops.o debuglocks.o strlen.o strncmp.o \
 	 memscan.o strncpy_from_user.o strlen_user.o memcmp.o checksum.o \
-	 VIScopy.o VISbzero.o VISmemset.o VIScsum.o VIScsumcopy.o \
+	 VISbzero.o VISmemset.o VIScsum.o VIScsumcopy.o \
 	 VIScsumcopyusr.o VISsave.o atomic.o rwlock.o bitops.o \
-	 dec_and_lock.o U3memcpy.o U3copy_from_user.o U3copy_to_user.o \
-	 U3copy_in_user.o mcount.o
+	 U1memcpy.o U1copy_from_user.o U1copy_to_user.o \
+	 U3memcpy.o U3copy_from_user.o U3copy_to_user.o U3patch.o \
+	 copy_in_user.o user_fixup.o memmove.o \
+	 dec_and_lock.o mcount.o
 
 include $(TOPDIR)/Rules.make
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/sparc64/lib/U1copy_from_user.S linux-2.4.28-pre3/arch/sparc64/lib/U1copy_from_user.S
--- linux-2.4.27/arch/sparc64/lib/U1copy_from_user.S	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.28-pre3/arch/sparc64/lib/U1copy_from_user.S	2004-09-10 19:33:27.000000000 +0000
@@ -0,0 +1,33 @@
+/* U1copy_from_user.S: UltraSparc-I/II/IIi/IIe optimized copy from userspace.
+ *
+ * Copyright (C) 1999, 2000, 2004 David S. Miller (davem@redhat.com)
+ */
+
+#define EX_LD(x)		\
+98:	x;			\
+	.section .fixup;	\
+	.align 4;		\
+99:	retl;			\
+	 mov	1, %o0;		\
+	.section __ex_table;	\
+	.align 4;		\
+	.word 98b, 99b;		\
+	.text;			\
+	.align 4;
+
+#define FUNC_NAME		___copy_from_user
+#define LOAD(type,addr,dest)	type##a [addr] %asi, dest
+#define LOAD_BLK(addr,dest)	ldda [addr] ASI_BLK_AIUS, dest
+#define EX_RETVAL(x)		0
+
+	/* Writing to %asi is _expensive_ so we hardcode it.
+	 * Reading %asi to check for KERNEL_DS is comparatively
+	 * cheap.
+	 */
+#define PREAMBLE					\
+	rd		%asi, %g1;			\
+	cmp		%g1, ASI_AIUS;			\
+	bne,pn		%icc, memcpy_user_stub;		\
+	 nop;						\
+
+#include "U1memcpy.S"
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/sparc64/lib/U1copy_to_user.S linux-2.4.28-pre3/arch/sparc64/lib/U1copy_to_user.S
--- linux-2.4.27/arch/sparc64/lib/U1copy_to_user.S	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.28-pre3/arch/sparc64/lib/U1copy_to_user.S	2004-09-10 19:35:13.000000000 +0000
@@ -0,0 +1,33 @@
+/* U1copy_to_user.S: UltraSparc-I/II/IIi/IIe optimized copy to userspace.
+ *
+ * Copyright (C) 1999, 2000, 2004 David S. Miller (davem@redhat.com)
+ */
+
+#define EX_ST(x)		\
+98:	x;			\
+	.section .fixup;	\
+	.align 4;		\
+99:	retl;			\
+	 mov	1, %o0;		\
+	.section __ex_table;	\
+	.align 4;		\
+	.word 98b, 99b;		\
+	.text;			\
+	.align 4;
+
+#define FUNC_NAME		___copy_to_user
+#define STORE(type,src,addr)	type##a src, [addr] ASI_AIUS
+#define STORE_BLK(src,addr)	stda src, [addr] ASI_BLK_AIUS
+#define EX_RETVAL(x)		0
+
+	/* Writing to %asi is _expensive_ so we hardcode it.
+	 * Reading %asi to check for KERNEL_DS is comparatively
+	 * cheap.
+	 */
+#define PREAMBLE					\
+	rd		%asi, %g1;			\
+	cmp		%g1, ASI_AIUS;			\
+	bne,pn		%icc, memcpy_user_stub;		\
+	 nop;						\
+
+#include "U1memcpy.S"
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/sparc64/lib/U1memcpy.S linux-2.4.28-pre3/arch/sparc64/lib/U1memcpy.S
--- linux-2.4.27/arch/sparc64/lib/U1memcpy.S	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.28-pre3/arch/sparc64/lib/U1memcpy.S	2004-09-10 19:36:46.000000000 +0000
@@ -0,0 +1,552 @@
+/* U1memcpy.S: UltraSPARC-I/II/IIi/IIe optimized memcpy.
+ *
+ * Copyright (C) 1997, 2004 David S. Miller (davem@redhat.com)
+ * Copyright (C) 1996, 1997, 1998, 1999 Jakub Jelinek (jj@ultra.linux.cz)
+ */
+
+#ifdef __KERNEL__
+#include <asm/visasm.h>
+#include <asm/asi.h>
+#else
+#define ASI_BLK_P 0xf0
+#define FPRS_FEF  0x04
+#ifdef MEMCPY_DEBUG
+#define VISEntry rd %fprs, %o5; wr %g0, FPRS_FEF, %fprs; \
+		 clr %g1; clr %g2; clr %g3; subcc %g0, %g0, %g0;
+#define VISExit and %o5, FPRS_FEF, %o5; wr %o5, 0x0, %fprs
+#else
+#define VISEntry rd %fprs, %o5; wr %g0, FPRS_FEF, %fprs
+#define VISExit and %o5, FPRS_FEF, %o5; wr %o5, 0x0, %fprs
+#endif
+#endif
+
+#ifndef EX_LD
+#define EX_LD(x)	x
+#endif
+
+#ifndef EX_ST
+#define EX_ST(x)	x
+#endif
+
+#ifndef EX_RETVAL
+#define EX_RETVAL(x)	x
+#endif
+
+#ifndef LOAD
+#define LOAD(type,addr,dest)	type [addr], dest
+#endif
+
+#ifndef LOAD_BLK
+#define LOAD_BLK(addr,dest)	ldda [addr] ASI_BLK_P, dest
+#endif
+
+#ifndef STORE
+#define STORE(type,src,addr)	type src, [addr]
+#endif
+
+#ifndef STORE_BLK
+#define STORE_BLK(src,addr)	stda src, [addr] ASI_BLK_P
+#endif
+
+#ifndef FUNC_NAME
+#define FUNC_NAME	memcpy
+#endif
+
+#ifndef PREAMBLE
+#define PREAMBLE
+#endif
+
+#ifndef XCC
+#define XCC xcc
+#endif
+
+#define FREG_FROB(f1, f2, f3, f4, f5, f6, f7, f8, f9)		\
+	faligndata		%f1, %f2, %f48;			\
+	faligndata		%f2, %f3, %f50;			\
+	faligndata		%f3, %f4, %f52;			\
+	faligndata		%f4, %f5, %f54;			\
+	faligndata		%f5, %f6, %f56;			\
+	faligndata		%f6, %f7, %f58;			\
+	faligndata		%f7, %f8, %f60;			\
+	faligndata		%f8, %f9, %f62;
+
+#define MAIN_LOOP_CHUNK(src, dest, fdest, fsrc, len, jmptgt)	\
+	EX_LD(LOAD_BLK(%src, %fdest));				\
+	EX_ST(STORE_BLK(%fsrc, %dest));				\
+	add			%src, 0x40, %src;		\
+	subcc			%len, 0x40, %len;		\
+	be,pn			%xcc, jmptgt;			\
+	 add			%dest, 0x40, %dest;		\
+
+#define LOOP_CHUNK1(src, dest, len, branch_dest)		\
+	MAIN_LOOP_CHUNK(src, dest, f0,  f48, len, branch_dest)
+#define LOOP_CHUNK2(src, dest, len, branch_dest)		\
+	MAIN_LOOP_CHUNK(src, dest, f16, f48, len, branch_dest)
+#define LOOP_CHUNK3(src, dest, len, branch_dest)		\
+	MAIN_LOOP_CHUNK(src, dest, f32, f48, len, branch_dest)
+
+#define STORE_SYNC(dest, fsrc)				\
+	EX_ST(STORE_BLK(%fsrc, %dest));			\
+	add			%dest, 0x40, %dest;
+
+#define STORE_JUMP(dest, fsrc, target)			\
+	EX_ST(STORE_BLK(%fsrc, %dest));			\
+	add			%dest, 0x40, %dest;	\
+	ba,pt			%xcc, target;
+
+#define FINISH_VISCHUNK(dest, f0, f1, left)	\
+	subcc			%left, 8, %left;\
+	bl,pn			%xcc, 95f;	\
+	 faligndata		%f0, %f1, %f48;	\
+	EX_ST(STORE(std, %f48, %dest));		\
+	add			%dest, 8, %dest;
+
+#define UNEVEN_VISCHUNK_LAST(dest, f0, f1, left)	\
+	subcc			%left, 8, %left;	\
+	bl,pn			%xcc, 95f;		\
+	 fsrc1			%f0, %f1;
+
+#define UNEVEN_VISCHUNK(dest, f0, f1, left)		\
+	UNEVEN_VISCHUNK_LAST(dest, f0, f1, left)	\
+	ba,a,pt			%xcc, 93f;
+
+	.register	%g2,#scratch
+	.register	%g3,#scratch
+
+	.text
+	.align		64
+
+	.globl		FUNC_NAME
+FUNC_NAME:		/* %o0=dst, %o1=src, %o2=len */
+	PREAMBLE
+	mov		%o0, %g5
+	cmp		%o2, 0
+	be,pn		%XCC, 85f
+	 or		%o0, %o1, %o3
+	cmp		%o2, 16
+	blu,a,pn	%XCC, 80f
+	 or		%o3, %o2, %o3
+
+	cmp		%o2, (5 * 64)
+	blu,pt		%XCC, 70f
+	 andcc		%o3, 0x7, %g0
+
+	/* Clobbers o5/g1/g2/g3/g7/icc/xcc.  */
+	VISEntry
+
+	/* Is 'dst' already aligned on an 64-byte boundary? */
+	andcc		%o0, 0x3f, %g2
+	be,pt		%XCC, 2f
+
+	/* Compute abs((dst & 0x3f) - 0x40) into %g2.  This is the number
+	 * of bytes to copy to make 'dst' 64-byte aligned.  We pre-
+	 * subtract this from 'len'.
+	 */
+	 sub		%o0, %o1, %o4
+	sub		%g2, 0x40, %g2
+	sub		%g0, %g2, %g2
+	sub		%o2, %g2, %o2
+	andcc		%g2, 0x7, %g1
+	be,pt		%icc, 2f
+	 and		%g2, 0x38, %g2
+
+1:	subcc		%g1, 0x1, %g1
+	EX_LD(LOAD(ldub, %o1 + 0x00, %o3))
+	EX_ST(STORE(stb, %o3, %o1 + %o4))
+	bgu,pt		%XCC, 1b
+	 add		%o1, 0x1, %o1
+
+	add		%o1, %o4, %o0
+
+2:	cmp		%g2, 0x0
+	and		%o1, 0x7, %g1
+	be,pt		%icc, 3f
+	 alignaddr	%o1, %g0, %o1
+
+	EX_LD(LOAD(ldd, %o1, %f4))
+1:	EX_LD(LOAD(ldd, %o1 + 0x8, %f6))
+	add		%o1, 0x8, %o1
+	subcc		%g2, 0x8, %g2
+	faligndata	%f4, %f6, %f0
+	EX_ST(STORE(std, %f0, %o0))
+	be,pn		%icc, 3f
+	 add		%o0, 0x8, %o0
+
+	EX_LD(LOAD(ldd, %o1 + 0x8, %f4))
+	add		%o1, 0x8, %o1
+	subcc		%g2, 0x8, %g2
+	faligndata	%f6, %f4, %f0
+	EX_ST(STORE(std, %f0, %o0))
+	bne,pt		%icc, 1b
+	 add		%o0, 0x8, %o0
+
+	/* Destination is 64-byte aligned.  */
+3:	
+	membar		  #LoadStore | #StoreStore | #StoreLoad
+
+	subcc		%o2, 0x40, %o4
+	add		%o1, %g1, %g1
+	andncc		%o4, (0x40 - 1), %o4
+	srl		%g1, 3, %g2
+	sub		%o2, %o4, %g3
+	andn		%o1, (0x40 - 1), %o1
+	and		%g2, 7, %g2
+	andncc		%g3, 0x7, %g3
+	fmovd		%f0, %f2
+	sub		%g3, 0x8, %g3
+	sub		%o2, %o4, %o2
+
+	add		%g1, %o4, %g1
+	subcc		%o2, %g3, %o2
+
+	EX_LD(LOAD_BLK(%o1, %f0))
+	add		%o1, 0x40, %o1
+	add		%g1, %g3, %g1
+	EX_LD(LOAD_BLK(%o1, %f16))
+	add		%o1, 0x40, %o1
+	sub		%o4, 0x80, %o4
+	EX_LD(LOAD_BLK(%o1, %f32))
+	add		%o1, 0x40, %o1
+
+	/* There are 8 instances of the unrolled loop,
+	 * one for each possible alignment of the
+	 * source buffer.  Each loop instance is 452
+	 * bytes.
+	 */
+	sll		%g2, 3, %o3
+	sub		%o3, %g2, %o3
+	sllx		%o3, 4, %o3
+	add		%o3, %g2, %o3
+	sllx		%o3, 2, %g2
+1:	rd		%pc, %o3
+	add		%o3, %lo(1f - 1b), %o3
+	jmpl		%o3 + %g2, %g0
+	 nop
+
+	.align		64
+1:	FREG_FROB(f0, f2, f4, f6, f8, f10,f12,f14,f16)
+	LOOP_CHUNK1(o1, o0, o4, 1f)
+	FREG_FROB(f16,f18,f20,f22,f24,f26,f28,f30,f32)
+	LOOP_CHUNK2(o1, o0, o4, 2f)
+	FREG_FROB(f32,f34,f36,f38,f40,f42,f44,f46,f0)
+	LOOP_CHUNK3(o1, o0, o4, 3f)
+	ba,pt		%xcc, 1b+4
+	 faligndata	%f0, %f2, %f48
+1:	FREG_FROB(f16,f18,f20,f22,f24,f26,f28,f30,f32)
+	STORE_SYNC(o0, f48) membar #Sync
+	FREG_FROB(f32,f34,f36,f38,f40,f42,f44,f46,f0)
+	STORE_JUMP(o0, f48, 40f) membar #Sync
+2:	FREG_FROB(f32,f34,f36,f38,f40,f42,f44,f46,f0)
+	STORE_SYNC(o0, f48) membar #Sync
+	FREG_FROB(f0, f2, f4, f6, f8, f10,f12,f14,f16)
+	STORE_JUMP(o0, f48, 48f) membar #Sync
+3:	FREG_FROB(f0, f2, f4, f6, f8, f10,f12,f14,f16)
+	STORE_SYNC(o0, f48) membar #Sync
+	FREG_FROB(f16,f18,f20,f22,f24,f26,f28,f30,f32)
+	STORE_JUMP(o0, f48, 56f) membar #Sync
+
+1:	FREG_FROB(f2, f4, f6, f8, f10,f12,f14,f16,f18)
+	LOOP_CHUNK1(o1, o0, o4, 1f)
+	FREG_FROB(f18,f20,f22,f24,f26,f28,f30,f32,f34)
+	LOOP_CHUNK2(o1, o0, o4, 2f)
+	FREG_FROB(f34,f36,f38,f40,f42,f44,f46,f0, f2)
+	LOOP_CHUNK3(o1, o0, o4, 3f)
+	ba,pt		%xcc, 1b+4
+	 faligndata	%f2, %f4, %f48
+1:	FREG_FROB(f18,f20,f22,f24,f26,f28,f30,f32,f34)
+	STORE_SYNC(o0, f48) membar #Sync
+	FREG_FROB(f34,f36,f38,f40,f42,f44,f46,f0, f2)
+	STORE_JUMP(o0, f48, 41f) membar #Sync
+2:	FREG_FROB(f34,f36,f38,f40,f42,f44,f46,f0, f2)
+	STORE_SYNC(o0, f48) membar #Sync
+	FREG_FROB(f2, f4, f6, f8, f10,f12,f14,f16,f18)
+	STORE_JUMP(o0, f48, 49f) membar #Sync
+3:	FREG_FROB(f2, f4, f6, f8, f10,f12,f14,f16,f18)
+	STORE_SYNC(o0, f48) membar #Sync
+	FREG_FROB(f18,f20,f22,f24,f26,f28,f30,f32,f34)
+	STORE_JUMP(o0, f48, 57f) membar #Sync
+
+1:	FREG_FROB(f4, f6, f8, f10,f12,f14,f16,f18,f20)
+	LOOP_CHUNK1(o1, o0, o4, 1f)
+	FREG_FROB(f20,f22,f24,f26,f28,f30,f32,f34,f36)
+	LOOP_CHUNK2(o1, o0, o4, 2f)
+	FREG_FROB(f36,f38,f40,f42,f44,f46,f0, f2, f4)
+	LOOP_CHUNK3(o1, o0, o4, 3f)
+	ba,pt		%xcc, 1b+4
+	 faligndata	%f4, %f6, %f48
+1:	FREG_FROB(f20,f22,f24,f26,f28,f30,f32,f34,f36)
+	STORE_SYNC(o0, f48) membar #Sync
+	FREG_FROB(f36,f38,f40,f42,f44,f46,f0, f2, f4)
+	STORE_JUMP(o0, f48, 42f) membar #Sync
+2:	FREG_FROB(f36,f38,f40,f42,f44,f46,f0, f2, f4)
+	STORE_SYNC(o0, f48) membar #Sync
+	FREG_FROB(f4, f6, f8, f10,f12,f14,f16,f18,f20)
+	STORE_JUMP(o0, f48, 50f) membar #Sync
+3:	FREG_FROB(f4, f6, f8, f10,f12,f14,f16,f18,f20)
+	STORE_SYNC(o0, f48) membar #Sync
+	FREG_FROB(f20,f22,f24,f26,f28,f30,f32,f34,f36)
+	STORE_JUMP(o0, f48, 58f) membar #Sync
+
+1:	FREG_FROB(f6, f8, f10,f12,f14,f16,f18,f20,f22)
+	LOOP_CHUNK1(o1, o0, o4, 1f)
+	FREG_FROB(f22,f24,f26,f28,f30,f32,f34,f36,f38)
+	LOOP_CHUNK2(o1, o0, o4, 2f)
+	FREG_FROB(f38,f40,f42,f44,f46,f0, f2, f4, f6) 
+	LOOP_CHUNK3(o1, o0, o4, 3f)
+	ba,pt		%xcc, 1b+4
+	 faligndata	%f6, %f8, %f48
+1:	FREG_FROB(f22,f24,f26,f28,f30,f32,f34,f36,f38)
+	STORE_SYNC(o0, f48) membar #Sync
+	FREG_FROB(f38,f40,f42,f44,f46,f0, f2, f4, f6)
+	STORE_JUMP(o0, f48, 43f) membar #Sync
+2:	FREG_FROB(f38,f40,f42,f44,f46,f0, f2, f4, f6)
+	STORE_SYNC(o0, f48) membar #Sync
+	FREG_FROB(f6, f8, f10,f12,f14,f16,f18,f20,f22)
+	STORE_JUMP(o0, f48, 51f) membar #Sync
+3:	FREG_FROB(f6, f8, f10,f12,f14,f16,f18,f20,f22)
+	STORE_SYNC(o0, f48) membar #Sync
+	FREG_FROB(f22,f24,f26,f28,f30,f32,f34,f36,f38)
+	STORE_JUMP(o0, f48, 59f) membar #Sync
+
+1:	FREG_FROB(f8, f10,f12,f14,f16,f18,f20,f22,f24)
+	LOOP_CHUNK1(o1, o0, o4, 1f)
+	FREG_FROB(f24,f26,f28,f30,f32,f34,f36,f38,f40)
+	LOOP_CHUNK2(o1, o0, o4, 2f)
+	FREG_FROB(f40,f42,f44,f46,f0, f2, f4, f6, f8)
+	LOOP_CHUNK3(o1, o0, o4, 3f)
+	ba,pt		%xcc, 1b+4
+	 faligndata	%f8, %f10, %f48
+1:	FREG_FROB(f24,f26,f28,f30,f32,f34,f36,f38,f40)
+	STORE_SYNC(o0, f48) membar #Sync
+	FREG_FROB(f40,f42,f44,f46,f0, f2, f4, f6, f8)
+	STORE_JUMP(o0, f48, 44f) membar #Sync
+2:	FREG_FROB(f40,f42,f44,f46,f0, f2, f4, f6, f8)
+	STORE_SYNC(o0, f48) membar #Sync
+	FREG_FROB(f8, f10,f12,f14,f16,f18,f20,f22,f24)
+	STORE_JUMP(o0, f48, 52f) membar #Sync
+3:	FREG_FROB(f8, f10,f12,f14,f16,f18,f20,f22,f24)
+	STORE_SYNC(o0, f48) membar #Sync
+	FREG_FROB(f24,f26,f28,f30,f32,f34,f36,f38,f40)
+	STORE_JUMP(o0, f48, 60f) membar #Sync
+
+1:	FREG_FROB(f10,f12,f14,f16,f18,f20,f22,f24,f26)
+	LOOP_CHUNK1(o1, o0, o4, 1f)
+	FREG_FROB(f26,f28,f30,f32,f34,f36,f38,f40,f42)
+	LOOP_CHUNK2(o1, o0, o4, 2f)
+	FREG_FROB(f42,f44,f46,f0, f2, f4, f6, f8, f10)
+	LOOP_CHUNK3(o1, o0, o4, 3f)
+	ba,pt		%xcc, 1b+4
+	 faligndata	%f10, %f12, %f48
+1:	FREG_FROB(f26,f28,f30,f32,f34,f36,f38,f40,f42)
+	STORE_SYNC(o0, f48) membar #Sync
+	FREG_FROB(f42,f44,f46,f0, f2, f4, f6, f8, f10)
+	STORE_JUMP(o0, f48, 45f) membar #Sync
+2:	FREG_FROB(f42,f44,f46,f0, f2, f4, f6, f8, f10)
+	STORE_SYNC(o0, f48) membar #Sync
+	FREG_FROB(f10,f12,f14,f16,f18,f20,f22,f24,f26)
+	STORE_JUMP(o0, f48, 53f) membar #Sync
+3:	FREG_FROB(f10,f12,f14,f16,f18,f20,f22,f24,f26)
+	STORE_SYNC(o0, f48) membar #Sync
+	FREG_FROB(f26,f28,f30,f32,f34,f36,f38,f40,f42)
+	STORE_JUMP(o0, f48, 61f) membar #Sync
+
+1:	FREG_FROB(f12,f14,f16,f18,f20,f22,f24,f26,f28)
+	LOOP_CHUNK1(o1, o0, o4, 1f)
+	FREG_FROB(f28,f30,f32,f34,f36,f38,f40,f42,f44)
+	LOOP_CHUNK2(o1, o0, o4, 2f)
+	FREG_FROB(f44,f46,f0, f2, f4, f6, f8, f10,f12)
+	LOOP_CHUNK3(o1, o0, o4, 3f)
+	ba,pt		%xcc, 1b+4
+	 faligndata	%f12, %f14, %f48
+1:	FREG_FROB(f28,f30,f32,f34,f36,f38,f40,f42,f44)
+	STORE_SYNC(o0, f48) membar #Sync
+	FREG_FROB(f44,f46,f0, f2, f4, f6, f8, f10,f12)
+	STORE_JUMP(o0, f48, 46f) membar #Sync
+2:	FREG_FROB(f44,f46,f0, f2, f4, f6, f8, f10,f12)
+	STORE_SYNC(o0, f48) membar #Sync
+	FREG_FROB(f12,f14,f16,f18,f20,f22,f24,f26,f28)
+	STORE_JUMP(o0, f48, 54f) membar #Sync
+3:	FREG_FROB(f12,f14,f16,f18,f20,f22,f24,f26,f28)
+	STORE_SYNC(o0, f48) membar #Sync
+	FREG_FROB(f28,f30,f32,f34,f36,f38,f40,f42,f44)
+	STORE_JUMP(o0, f48, 62f) membar #Sync
+
+1:	FREG_FROB(f14,f16,f18,f20,f22,f24,f26,f28,f30)
+	LOOP_CHUNK1(o1, o0, o4, 1f)
+	FREG_FROB(f30,f32,f34,f36,f38,f40,f42,f44,f46)
+	LOOP_CHUNK2(o1, o0, o4, 2f)
+	FREG_FROB(f46,f0, f2, f4, f6, f8, f10,f12,f14)
+	LOOP_CHUNK3(o1, o0, o4, 3f)
+	ba,pt		%xcc, 1b+4
+	 faligndata	%f14, %f16, %f48
+1:	FREG_FROB(f30,f32,f34,f36,f38,f40,f42,f44,f46)
+	STORE_SYNC(o0, f48) membar #Sync
+	FREG_FROB(f46,f0, f2, f4, f6, f8, f10,f12,f14)
+	STORE_JUMP(o0, f48, 47f) membar #Sync
+2:	FREG_FROB(f46,f0, f2, f4, f6, f8, f10,f12,f14)
+	STORE_SYNC(o0, f48) membar #Sync
+	FREG_FROB(f14,f16,f18,f20,f22,f24,f26,f28,f30)
+	STORE_JUMP(o0, f48, 55f) membar #Sync
+3:	FREG_FROB(f14,f16,f18,f20,f22,f24,f26,f28,f30)
+	STORE_SYNC(o0, f48) membar #Sync
+	FREG_FROB(f30,f32,f34,f36,f38,f40,f42,f44,f46)
+	STORE_JUMP(o0, f48, 63f) membar #Sync
+
+40:	FINISH_VISCHUNK(o0, f0,  f2,  g3)
+41:	FINISH_VISCHUNK(o0, f2,  f4,  g3)
+42:	FINISH_VISCHUNK(o0, f4,  f6,  g3)
+43:	FINISH_VISCHUNK(o0, f6,  f8,  g3)
+44:	FINISH_VISCHUNK(o0, f8,  f10, g3)
+45:	FINISH_VISCHUNK(o0, f10, f12, g3)
+46:	FINISH_VISCHUNK(o0, f12, f14, g3)
+47:	UNEVEN_VISCHUNK(o0, f14, f0,  g3)
+48:	FINISH_VISCHUNK(o0, f16, f18, g3)
+49:	FINISH_VISCHUNK(o0, f18, f20, g3)
+50:	FINISH_VISCHUNK(o0, f20, f22, g3)
+51:	FINISH_VISCHUNK(o0, f22, f24, g3)
+52:	FINISH_VISCHUNK(o0, f24, f26, g3)
+53:	FINISH_VISCHUNK(o0, f26, f28, g3)
+54:	FINISH_VISCHUNK(o0, f28, f30, g3)
+55:	UNEVEN_VISCHUNK(o0, f30, f0,  g3)
+56:	FINISH_VISCHUNK(o0, f32, f34, g3)
+57:	FINISH_VISCHUNK(o0, f34, f36, g3)
+58:	FINISH_VISCHUNK(o0, f36, f38, g3)
+59:	FINISH_VISCHUNK(o0, f38, f40, g3)
+60:	FINISH_VISCHUNK(o0, f40, f42, g3)
+61:	FINISH_VISCHUNK(o0, f42, f44, g3)
+62:	FINISH_VISCHUNK(o0, f44, f46, g3)
+63:	UNEVEN_VISCHUNK_LAST(o0, f46, f0,  g3)
+
+93:	EX_LD(LOAD(ldd, %o1, %f2))
+	add		%o1, 8, %o1
+	subcc		%g3, 8, %g3
+	faligndata	%f0, %f2, %f8
+	EX_ST(STORE(std, %f8, %o0))
+	bl,pn		%xcc, 95f
+	 add		%o0, 8, %o0
+	EX_LD(LOAD(ldd, %o1, %f0))
+	add		%o1, 8, %o1
+	subcc		%g3, 8, %g3
+	faligndata	%f2, %f0, %f8
+	EX_ST(STORE(std, %f8, %o0))
+	bge,pt		%xcc, 93b
+	 add		%o0, 8, %o0
+
+95:	brz,pt		%o2, 2f
+	 mov		%g1, %o1
+
+1:	EX_LD(LOAD(ldub, %o1, %o3))
+	add		%o1, 1, %o1
+	subcc		%o2, 1, %o2
+	EX_ST(STORE(stb, %o3, %o0))
+	bne,pt		%xcc, 1b
+	 add		%o0, 1, %o0
+
+2:	membar		#StoreLoad | #StoreStore
+	VISExit
+	retl
+	 mov		EX_RETVAL(%g5), %o0
+
+	.align		64
+70:	/* 16 < len <= (5 * 64) */
+	bne,pn		%XCC, 75f
+	 sub		%o0, %o1, %o3
+
+72:	andn		%o2, 0xf, %o4
+	and		%o2, 0xf, %o2
+1:	EX_LD(LOAD(ldx, %o1 + 0x00, %o5))
+	EX_LD(LOAD(ldx, %o1 + 0x08, %g1))
+	subcc		%o4, 0x10, %o4
+	EX_ST(STORE(stx, %o5, %o1 + %o3))
+	add		%o1, 0x8, %o1
+	EX_ST(STORE(stx, %g1, %o1 + %o3))
+	bgu,pt		%XCC, 1b
+	 add		%o1, 0x8, %o1
+73:	andcc		%o2, 0x8, %g0
+	be,pt		%XCC, 1f
+	 nop
+	EX_LD(LOAD(ldx, %o1, %o5))
+	sub		%o2, 0x8, %o2
+	EX_ST(STORE(stx, %o5, %o1 + %o3))
+	add		%o1, 0x8, %o1
+1:	andcc		%o2, 0x4, %g0
+	be,pt		%XCC, 1f
+	 nop
+	EX_LD(LOAD(lduw, %o1, %o5))
+	sub		%o2, 0x4, %o2
+	EX_ST(STORE(stw, %o5, %o1 + %o3))
+	add		%o1, 0x4, %o1
+1:	cmp		%o2, 0
+	be,pt		%XCC, 85f
+	 nop
+	ba,pt		%xcc, 90f
+	 nop
+
+75:	andcc		%o0, 0x7, %g1
+	sub		%g1, 0x8, %g1
+	be,pn		%icc, 2f
+	 sub		%g0, %g1, %g1
+	sub		%o2, %g1, %o2
+
+1:	EX_LD(LOAD(ldub, %o1, %o5))
+	subcc		%g1, 1, %g1
+	EX_ST(STORE(stb, %o5, %o1 + %o3))
+	bgu,pt		%icc, 1b
+	 add		%o1, 1, %o1
+
+2:	add		%o1, %o3, %o0
+	andcc		%o1, 0x7, %g1
+	bne,pt		%icc, 8f
+	 sll		%g1, 3, %g1
+
+	cmp		%o2, 16
+	bgeu,pt		%icc, 72b
+	 nop
+	ba,a,pt		%xcc, 73b
+
+8:	mov		64, %o3
+	andn		%o1, 0x7, %o1
+	EX_LD(LOAD(ldx, %o1, %g2))
+	sub		%o3, %g1, %o3
+	andn		%o2, 0x7, %o4
+	sllx		%g2, %g1, %g2
+1:	EX_LD(LOAD(ldx, %o1 + 0x8, %g3))
+	subcc		%o4, 0x8, %o4
+	add		%o1, 0x8, %o1
+	srlx		%g3, %o3, %o5
+	or		%o5, %g2, %o5
+	EX_ST(STORE(stx, %o5, %o0))
+	add		%o0, 0x8, %o0
+	bgu,pt		%icc, 1b
+	 sllx		%g3, %g1, %g2
+
+	srl		%g1, 3, %g1
+	andcc		%o2, 0x7, %o2
+	be,pn		%icc, 85f
+	 add		%o1, %g1, %o1
+	ba,pt		%xcc, 90f
+	 sub		%o0, %o1, %o3
+
+	.align		64
+80:	/* 0 < len <= 16 */
+	andcc		%o3, 0x3, %g0
+	bne,pn		%XCC, 90f
+	 sub		%o0, %o1, %o3
+
+1:	EX_LD(LOAD(lduw, %o1, %g1))
+	subcc		%o2, 4, %o2
+	EX_ST(STORE(stw, %g1, %o1 + %o3))
+	bgu,pt		%XCC, 1b
+	 add		%o1, 4, %o1
+
+85:	retl
+	 mov		EX_RETVAL(%g5), %o0
+
+	.align		32
+90:	EX_LD(LOAD(ldub, %o1, %g1))
+	subcc		%o2, 1, %o2
+	EX_ST(STORE(stb, %g1, %o1 + %o3))
+	bgu,pt		%XCC, 90b
+	 add		%o1, 1, %o1
+	retl
+	 mov		EX_RETVAL(%g5), %o0
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/sparc64/lib/U3copy_from_user.S linux-2.4.28-pre3/arch/sparc64/lib/U3copy_from_user.S
--- linux-2.4.27/arch/sparc64/lib/U3copy_from_user.S	2002-11-28 23:53:12.000000000 +0000
+++ linux-2.4.28-pre3/arch/sparc64/lib/U3copy_from_user.S	2004-09-10 19:33:03.000000000 +0000
@@ -1,519 +1,22 @@
-/* $Id: U3copy_from_user.S,v 1.3.2.1 2002/01/15 07:17:47 davem Exp $
- * U3memcpy.S: UltraSparc-III optimized copy from userspace.
+/* U3copy_from_user.S: UltraSparc-III optimized copy from userspace.
  *
- * Copyright (C) 1999, 2000 David S. Miller (davem@redhat.com)
+ * Copyright (C) 1999, 2000, 2004 David S. Miller (davem@redhat.com)
  */
 
-#ifdef __KERNEL__
-#include <asm/visasm.h>
-#include <asm/asi.h>
-#include <asm/dcu.h>
-#include <asm/spitfire.h>
-#undef SMALL_COPY_USES_FPU
-#define EXNV(x,y,a,b)			\
-98:	x,y;				\
-	.section .fixup;		\
-	.align 4;			\
-99:	VISExitHalf;			\
-	ba U3cfu_fixup;			\
-	 a, b, %o1;			\
-	.section __ex_table;		\
-	.align 4;			\
-	.word 98b, 99b;			\
-	.text;				\
+#define EX_LD(x)		\
+98:	x;			\
+	.section .fixup;	\
+	.align 4;		\
+99:	retl;			\
+	 mov	1, %o0;		\
+	.section __ex_table;	\
+	.align 4;		\
+	.word 98b, 99b;		\
+	.text;			\
 	.align 4;
-#define EX(x,y,a,b)			\
-98:	x,y;				\
-	.section .fixup;		\
-	.align 4;			\
-99:	VISExitHalf;			\
-	ba U3cfu_fixup;			\
-	 a, b, %o1;			\
-	.section __ex_table;		\
-	.align 4;			\
-	.word 98b, 99b;			\
-	.text;				\
-	.align 4;
-#define EX2(x,y)			\
-98:	x,y;				\
-	.section .fixup;		\
-	.align 4;			\
-99:	VISExitHalf;			\
-	and %o2, (0x40 - 1), %o1;	\
-	add %o1, %o4, %o1;		\
-	ba U3cfu_fixup;			\
-	 add %o1, 0x1c0, %o1;		\
-	.section __ex_table;		\
-	.align 4;			\
-	.word 98b, 99b;			\
-	.text;				\
-	.align 4;
-#define EX3(x,y)			\
-98:	x,y;				\
-	.section .fixup;		\
-	.align 4;			\
-99:	VISExitHalf;			\
-	and %o2, (0x40 - 1), %o1;	\
-	sll %g3, 6, %g3;		\
-	add %o1, 0x80, %o1;		\
-	ba U3cfu_fixup;			\
-	 add %o1, %g3, %o1;		\
-	.section __ex_table;		\
-	.align 4;			\
-	.word 98b, 99b;			\
-	.text;				\
-	.align 4;
-#define EX4(x,y)			\
-98:	x,y;				\
-	.section .fixup;		\
-	.align 4;			\
-99:	VISExitHalf;			\
-	and %o2, (0x40 - 1), %o1;	\
-	add %o1, 0x40, %o1;		\
-	ba U3cfu_fixup;			\
-	 add %o1, %g3, %o1;		\
-	.section __ex_table;		\
-	.align 4;			\
-	.word 98b, 99b;			\
-	.text;				\
-	.align 4;
-#else
-#define ASI_BLK_P 0xf0
-#define FPRS_FEF  0x04
-#define VISEntryHalf rd %fprs, %o5; wr %g0, FPRS_FEF, %fprs
-#define VISExitHalf and %o5, FPRS_FEF, %o5; wr %o5, 0x0, %fprs
-#define SMALL_COPY_USES_FPU
-#define EXNV(x,y,a,b)	x,y;
-#define EX(x,y,a,b)	x,y;
-#define EX2(x,y)	x,y;
-#define EX3(x,y)	x,y;
-#define EX4(x,y)	x,y;
-#endif
-
-	/* Special/non-trivial issues of this code:
-	 *
-	 * 1) %o5 is preserved from VISEntryHalf to VISExitHalf
-	 * 2) Only low 32 FPU registers are used so that only the
-	 *    lower half of the FPU register set is dirtied by this
-	 *    code.  This is especially important in the kernel.
-	 * 3) This code never prefetches cachelines past the end
-	 *    of the source buffer.
-	 */
-
-	.text
-	.align	32
-
-	/* The cheetah's flexible spine, oversized liver, enlarged heart,
-	 * slender muscular body, and claws make it the swiftest hunter
-	 * in Africa and the fastest animal on land.  Can reach speeds
-	 * of up to 2.4GB per second.
-	 */
-
-	.globl		U3copy_from_user
-U3copy_from_user: /* %o0=dst, %o1=src, %o2=len */
-#ifndef __KERNEL__
-	/* Save away original 'dst' for memcpy return value. */
-	mov		%o0, %g3			! A0	Group
-#endif
-	/* Anything to copy at all? */
-	cmp		%o2, 0				! A1
-	ble,pn		%icc, U3copy_from_user_short_ret! BR
-
-	/* Extremely small copy? */
-	 cmp		%o2, 31				! A0	Group
-	ble,pn		%icc, U3copy_from_user_short	! BR
-
-	/* Large enough to use unrolled prefetch loops? */
-	 cmp		%o2, 0x100			! A1
-	bge,a,pt	%icc, U3copy_from_user_enter	! BR	Group
-	 andcc		%o0, 0x3f, %g2			! A0
-
-	ba,pt		%xcc, U3copy_from_user_toosmall	! BR	Group
-	 andcc		%o0, 0x7, %g2			! A0
-
-	.align		32
-U3copy_from_user_short:
-	/* Copy %o2 bytes from src to dst, one byte at a time. */
-	EXNV(lduba [%o1 + 0x00] %asi, %o3, add %o2, %g0)! MS	Group
-	add		%o1, 0x1, %o1			! A0
-	add		%o0, 0x1, %o0			! A1
-	subcc		%o2, 1, %o2			! A0	Group
-
-	bg,pt		%icc, U3copy_from_user_short	! BR
-	 stb		%o3, [%o0 + -1]			! MS	Group (1-cycle stall)
-
-U3copy_from_user_short_ret:
-#ifdef __KERNEL__
-	retl						! BR	Group (0-4 cycle stall)
-	 clr		%o0				! A0
-#else
-	retl						! BR	Group (0-4 cycle stall)
-	 mov		%g3, %o0			! A0
-#endif
-
-	/* Here len >= (6 * 64) and condition codes reflect execution
-	 * of "andcc %o0, 0x7, %g2", done by caller.
-	 */
-	.align		64
-U3copy_from_user_enter:
-	/* Is 'dst' already aligned on an 64-byte boundary? */
-	be,pt		%xcc, 2f			! BR
-
-	/* Compute abs((dst & 0x3f) - 0x40) into %g2.  This is the number
-	 * of bytes to copy to make 'dst' 64-byte aligned.  We pre-
-	 * subtract this from 'len'.
-	 */
-	 sub		%g2, 0x40, %g2			! A0	Group
-	sub		%g0, %g2, %g2			! A0	Group
-	sub		%o2, %g2, %o2			! A0	Group
-
-	/* Copy %g2 bytes from src to dst, one byte at a time. */
-1:	EXNV(lduba [%o1 + 0x00] %asi, %o3, add %o2, %g2)! MS	(Group)
-	add		%o1, 0x1, %o1			! A1
-	add		%o0, 0x1, %o0			! A0	Group
-	subcc		%g2, 0x1, %g2			! A1
-
-	bg,pt		%icc, 1b			! BR	Group
-	 stb		%o3, [%o0 + -1]			! MS	Group
-
-2:	VISEntryHalf					! MS+MS
-	and		%o1, 0x7, %g1			! A1
-	ba,pt		%xcc, U3copy_from_user_begin		! BR
-	 alignaddr	%o1, %g0, %o1			! MS	      (Break-after)
-
-	.align		64
-U3copy_from_user_begin:
-#ifdef __KERNEL__
-	.globl		U3copy_from_user_nop_1_6
-U3copy_from_user_nop_1_6:
-	ldxa		[%g0] ASI_DCU_CONTROL_REG, %g3
-	sethi		%uhi(DCU_PE), %o3
-	sllx		%o3, 32, %o3
-	or		%g3, %o3, %o3
-	stxa		%o3, [%g0] ASI_DCU_CONTROL_REG	! Enable P-cache
-	membar		#Sync
-#endif
-	prefetcha	[%o1 + 0x000] %asi, #one_read	! MS	Group1
-	prefetcha	[%o1 + 0x040] %asi, #one_read	! MS	Group2
-	andn		%o2, (0x40 - 1), %o4		! A0
-	prefetcha	[%o1 + 0x080] %asi, #one_read	! MS	Group3
-	cmp		%o4, 0x140			! A0
-	prefetcha	[%o1 + 0x0c0] %asi, #one_read	! MS	Group4
-	EX(ldda [%o1 + 0x000] %asi, %f0, add %o2, %g0)	! MS	Group5 (%f0 results at G8)
-	bge,a,pt	%icc, 1f			! BR
-
-	prefetcha	[%o1 + 0x100] %asi, #one_read	! MS	Group6
-1:	EX(ldda [%o1 + 0x008] %asi, %f2, add %o2, %g0)	! AX	       (%f2 results at G9)
-	cmp		%o4, 0x180			! A1
-	bge,a,pt	%icc, 1f			! BR
-	 prefetcha	[%o1 + 0x140] %asi, #one_read	! MS	Group7
-1:	EX(ldda [%o1 + 0x010] %asi, %f4, add %o2, %g0)	! AX	       (%f4 results at G10)
-	cmp		%o4, 0x1c0			! A1
-	bge,a,pt	%icc, 1f			! BR
-
-	 prefetcha	[%o1 + 0x180] %asi, #one_read	! MS	Group8
-1:	faligndata	%f0, %f2, %f16			! FGA	Group9 (%f16 at G12)
-	EX(ldda [%o1 + 0x018] %asi, %f6, add %o2, %g0)	! AX	       (%f6 results at G12)
-	faligndata	%f2, %f4, %f18			! FGA	Group10 (%f18 results at G13)
-	EX(ldda [%o1 + 0x020] %asi, %f8, add %o2, %g0)	! MS	        (%f8 results at G13)
-	faligndata	%f4, %f6, %f20			! FGA	Group12	(1-cycle stall,%f20 at G15)
-	EX(ldda [%o1 + 0x028] %asi, %f10, add %o2, %g0)	! MS		(%f10 results at G15)
-	faligndata	%f6, %f8, %f22			! FGA	Group13 (%f22 results at G16)
-
-	EX(ldda [%o1 + 0x030] %asi, %f12, add %o2, %g0)	! MS		(%f12 results at G16)
-	faligndata	%f8, %f10, %f24			! FGA	Group15 (1-cycle stall,%f24 at G18)
-	EX(ldda [%o1 + 0x038] %asi, %f14, add %o2, %g0)	! MS		(%f14 results at G18)
-	faligndata	%f10, %f12, %f26		! FGA	Group16 (%f26 results at G19)
-	EX(ldda [%o1 + 0x040] %asi, %f0, add %o2, %g0)	! MS		(%f0 results at G19)
-
-	/* We only use the first loop if len > (7 * 64). */
-	subcc		%o4, 0x1c0, %o4			! A0	Group17
-	bg,pt		%icc, U3copy_from_user_loop1	! BR
-	 add		%o1, 0x40, %o1			! A1
-
-	add		%o4, 0x140, %o4			! A0	Group18
-	ba,pt		%xcc, U3copy_from_user_loop2	! BR
-	 srl		%o4, 6, %o3			! A0	Group19
-	nop
-	nop
-	nop
-	nop
-	nop
-
-	nop
-	nop
-
-	/* This loop performs the copy and queues new prefetches.
-	 * We drop into the second loop when len <= (5 * 64).  Note
-	 * that this (5 * 64) factor has been subtracted from len
-	 * already.
-	 */
-U3copy_from_user_loop1:
-	EX2(ldda [%o1 + 0x008] %asi, %f2)		! MS	Group2	(%f2 results at G5)
-	faligndata	%f12, %f14, %f28		! FGA		(%f28 results at G5)
-	EX2(ldda [%o1 + 0x010] %asi, %f4)		! MS	Group3	(%f4 results at G6)
-	faligndata	%f14, %f0, %f30			! FGA	Group4	(1-cycle stall, %f30 at G7)
-	stda		%f16, [%o0] ASI_BLK_P		! MS
-	EX2(ldda [%o1 + 0x018] %asi, %f6)		! AX		(%f6 results at G7)
-
-	faligndata	%f0, %f2, %f16			! FGA	Group12 (7-cycle stall)
-	EX2(ldda [%o1 + 0x020] %asi, %f8)		! MS	        (%f8 results at G15)
-	faligndata	%f2, %f4, %f18			! FGA	Group13	(%f18 results at G16)
-	EX2(ldda [%o1 + 0x028] %asi, %f10)		! MS		(%f10 results at G16)
-	faligndata	%f4, %f6, %f20			! FGA	Group14	(%f20 results at G17)
-	EX2(ldda [%o1 + 0x030] %asi, %f12)		! MS		(%f12 results at G17)
-	faligndata	%f6, %f8, %f22			! FGA	Group15	(%f22 results at G18)
-	EX2(ldda [%o1 + 0x038] %asi, %f14)		! MS		(%f14 results at G18)
-
-	faligndata	%f8, %f10, %f24			! FGA	Group16	(%f24 results at G19)
-	EX2(ldda [%o1 + 0x040] %asi, %f0)		! AX		(%f0 results at G19)
-	prefetcha	[%o1 + 0x180] %asi, #one_read	! MS
-	faligndata	%f10, %f12, %f26		! FGA	Group17	(%f26 results at G20)
-	subcc		%o4, 0x40, %o4			! A0
-	add		%o1, 0x40, %o1			! A1
-	bg,pt		%xcc, U3copy_from_user_loop1	! BR
-	 add		%o0, 0x40, %o0			! A0	Group18
-
-U3copy_from_user_loop2_enter:
-	mov		5, %o3				! A1
-
-	/* This loop performs on the copy, no new prefetches are
-	 * queued.  We do things this way so that we do not perform
-	 * any spurious prefetches past the end of the src buffer.
-	 */
-U3copy_from_user_loop2:
-	EX3(ldda [%o1 + 0x008] %asi, %f2)		! MS
-	faligndata	%f12, %f14, %f28		! FGA	Group2
-	EX3(ldda [%o1 + 0x010] %asi, %f4)		! MS
-	faligndata	%f14, %f0, %f30			! FGA	Group4	(1-cycle stall)
-	stda		%f16, [%o0] ASI_BLK_P		! MS
-	EX3(ldda [%o1 + 0x018] %asi, %f6)		! AX
-	faligndata	%f0, %f2, %f16			! FGA	Group12 (7-cycle stall)
-
-	EX3(ldda [%o1 + 0x020] %asi, %f8)		! MS
-	faligndata	%f2, %f4, %f18			! FGA	Group13
-	EX3(ldda [%o1 + 0x028] %asi, %f10)		! MS
-	faligndata	%f4, %f6, %f20			! FGA	Group14
-	EX3(ldda [%o1 + 0x030] %asi, %f12)		! MS
-	faligndata	%f6, %f8, %f22			! FGA	Group15
-	EX3(ldda [%o1 + 0x038] %asi, %f14)		! MS
-	faligndata	%f8, %f10, %f24			! FGA	Group16
-
-	EX3(ldda [%o1 + 0x040] %asi, %f0)		! AX
-	faligndata	%f10, %f12, %f26		! FGA	Group17
-	subcc		%o3, 0x01, %o3			! A0
-	add		%o1, 0x40, %o1			! A1
-	bg,pt		%xcc, U3copy_from_user_loop2	! BR
-	 add		%o0, 0x40, %o0			! A0	Group18
-
-	/* Finally we copy the last full 64-byte block. */
-U3copy_from_user_loopfini:
-	EX3(ldda [%o1 + 0x008] %asi, %f2)		! MS
-	faligndata	%f12, %f14, %f28		! FGA
-	EX3(ldda [%o1 + 0x010] %asi, %f4)		! MS	Group19
-	faligndata	%f14, %f0, %f30			! FGA
-	stda		%f16, [%o0] ASI_BLK_P		! MS	Group20
-	EX3(ldda [%o1 + 0x018] %asi, %f6)		! AX
-	faligndata	%f0, %f2, %f16			! FGA	Group11 (7-cycle stall)
-	EX3(ldda [%o1 + 0x020] %asi, %f8)		! MS
-	faligndata	%f2, %f4, %f18			! FGA	Group12
-	EX3(ldda [%o1 + 0x028] %asi, %f10)		! MS
-	faligndata	%f4, %f6, %f20			! FGA	Group13
-	EX3(ldda [%o1 + 0x030] %asi, %f12)		! MS
-	faligndata	%f6, %f8, %f22			! FGA	Group14
-	EX3(ldda [%o1 + 0x038] %asi, %f14)		! MS
-	faligndata	%f8, %f10, %f24			! FGA	Group15
-	cmp		%g1, 0				! A0
-	be,pt		%icc, 1f			! BR
-	 add		%o0, 0x40, %o0			! A1
-	EX4(ldda [%o1 + 0x040] %asi, %f0)		! MS
-1:	faligndata	%f10, %f12, %f26		! FGA	Group16
-	faligndata	%f12, %f14, %f28		! FGA	Group17
-	faligndata	%f14, %f0, %f30			! FGA	Group18
-	stda		%f16, [%o0] ASI_BLK_P		! MS
-	add		%o0, 0x40, %o0			! A0
-	add		%o1, 0x40, %o1			! A1
-#ifdef __KERNEL__
-	.globl		U3copy_from_user_nop_2_3
-U3copy_from_user_nop_2_3:
-	mov		PRIMARY_CONTEXT, %o3
-	stxa		%g0, [%o3] ASI_DMMU		! Flush P-cache
-	stxa		%g3, [%g0] ASI_DCU_CONTROL_REG	! Disable P-cache
-#endif
-	membar		#Sync				! MS	Group26 (7-cycle stall)
-
-	/* Now we copy the (len modulo 64) bytes at the end.
-	 * Note how we borrow the %f0 loaded above.
-	 *
-	 * Also notice how this code is careful not to perform a
-	 * load past the end of the src buffer just like similar
-	 * code found in U3copy_from_user_toosmall processing.
-	 */
-U3copy_from_user_loopend:
-	and		%o2, 0x3f, %o2			! A0	Group
-	andcc		%o2, 0x38, %g2			! A0	Group
-	be,pn		%icc, U3copy_from_user_endcruft	! BR
-	 subcc		%g2, 0x8, %g2			! A1
-	be,pn		%icc, U3copy_from_user_endcruft	! BR	Group
-	 cmp		%g1, 0				! A0
-
-	be,a,pt		%icc, 1f			! BR	Group
-	 EX(ldda [%o1 + 0x00] %asi, %f0, add %o2, %g0)	! MS
-
-1:	EX(ldda [%o1 + 0x08] %asi, %f2, add %o2, %g0)	! MS	Group
-	add		%o1, 0x8, %o1			! A0
-	sub		%o2, 0x8, %o2			! A1
-	subcc		%g2, 0x8, %g2			! A0	Group
-	faligndata	%f0, %f2, %f8			! FGA	Group
-	std		%f8, [%o0 + 0x00]		! MS	(XXX does it stall here? XXX)
-	be,pn		%icc, U3copy_from_user_endcruft	! BR
-	 add		%o0, 0x8, %o0			! A0
-	EX(ldda [%o1 + 0x08] %asi, %f0, add %o2, %g0)	! MS	Group
-	add		%o1, 0x8, %o1			! A0
-	sub		%o2, 0x8, %o2			! A1
-	subcc		%g2, 0x8, %g2			! A0	Group
-	faligndata	%f2, %f0, %f8			! FGA
-	std		%f8, [%o0 + 0x00]		! MS	(XXX does it stall here? XXX)
-	bne,pn		%icc, 1b			! BR
-	 add		%o0, 0x8, %o0			! A0	Group
-
-	/* If anything is left, we copy it one byte at a time.
-	 * Note that %g1 is (src & 0x3) saved above before the
-	 * alignaddr was performed.
-	 */
-U3copy_from_user_endcruft:
-	cmp		%o2, 0
-	add		%o1, %g1, %o1
-	VISExitHalf
-	be,pn		%icc, U3copy_from_user_short_ret
-	 nop
-	ba,a,pt		%xcc, U3copy_from_user_short
-
-	/* If we get here, then 32 <= len < (6 * 64) */
-U3copy_from_user_toosmall:
-
-#ifdef SMALL_COPY_USES_FPU
-
-	/* Is 'dst' already aligned on an 8-byte boundary? */
-	be,pt		%xcc, 2f			! BR	Group
-
-	/* Compute abs((dst & 7) - 8) into %g2.  This is the number
-	 * of bytes to copy to make 'dst' 8-byte aligned.  We pre-
-	 * subtract this from 'len'.
-	 */
-	 sub		%g2, 0x8, %g2			! A0
-	sub		%g0, %g2, %g2			! A0	Group (reg-dep)
-	sub		%o2, %g2, %o2			! A0	Group (reg-dep)
-
-	/* Copy %g2 bytes from src to dst, one byte at a time. */
-1:	EXNV(lduba [%o1 + 0x00] %asi, %o3, add %o2, %g2)! MS	(Group) (%o3 in 3 cycles)
-	add		%o1, 0x1, %o1			! A1
-	add		%o0, 0x1, %o0			! A0	Group
-	subcc		%g2, 0x1, %g2			! A1
-
-	bg,pt		%icc, 1b			! BR	Group
-	 stb		%o3, [%o0 + -1]			! MS	Group
-
-2:	VISEntryHalf					! MS+MS
-
-	/* Compute (len - (len % 8)) into %g2.  This is guarenteed
-	 * to be nonzero.
-	 */
-	andn		%o2, 0x7, %g2			! A0	Group
-
-	/* You may read this and believe that it allows reading
-	 * one 8-byte longword past the end of src.  It actually
-	 * does not, as %g2 is subtracted as loads are done from
-	 * src, so we always stop before running off the end.
-	 * Also, we are guarenteed to have at least 0x10 bytes
-	 * to move here.
-	 */
-	sub		%g2, 0x8, %g2			! A0	Group (reg-dep)
-	alignaddr	%o1, %g0, %g1			! MS	      (Break-after)
-	EX(ldda [%g1 + 0x00] %asi, %f0, add %o2, %g0)	! MS	Group (1-cycle stall)
-	add		%g1, 0x8, %g1			! A0
-
-1:	EX(ldda [%g1 + 0x00] %asi, %f2, add %o2, %g0)	! MS	Group
-	add		%g1, 0x8, %g1			! A0
-	sub		%o2, 0x8, %o2			! A1
-	subcc		%g2, 0x8, %g2			! A0	Group
-
-	faligndata	%f0, %f2, %f8			! FGA	Group (1-cycle stall)
-	std		%f8, [%o0 + 0x00]		! MS	Group (2-cycle stall)
-	add		%o1, 0x8, %o1			! A0
-	be,pn		%icc, 2f			! BR
-
-	 add		%o0, 0x8, %o0			! A1
-	EX(ldda [%g1 + 0x00] %asi, %f0, add %o2, %g0)	! MS	Group
-	add		%g1, 0x8, %g1			! A0
-	sub		%o2, 0x8, %o2			! A1
-
-	subcc		%g2, 0x8, %g2			! A0	Group
-	faligndata	%f2, %f0, %f8			! FGA	Group (1-cycle stall)
-	std		%f8, [%o0 + 0x00]		! MS	Group (2-cycle stall)
-	add		%o1, 0x8, %o1			! A0
-
-	bne,pn		%icc, 1b			! BR
-	 add		%o0, 0x8, %o0			! A1
-
-	/* Nothing left to copy? */
-2:	cmp		%o2, 0				! A0	Group
-	VISExitHalf					! A0+MS
-	be,pn		%icc, U3copy_from_user_short_ret! BR	Group
-	 nop						! A0
-	ba,a,pt		%xcc, U3copy_from_user_short	! BR	Group
-
-#else /* !(SMALL_COPY_USES_FPU) */
-
-	xor		%o1, %o0, %g2
-	andcc		%g2, 0x7, %g0
-	bne,pn		%icc, U3copy_from_user_short
-	 andcc		%o1, 0x7, %g2
-
-	be,pt		%xcc, 2f
-	 sub		%g2, 0x8, %g2
-	sub		%g0, %g2, %g2
-	sub		%o2, %g2, %o2
-
-1:	EXNV(lduba [%o1 + 0x00] %asi, %o3, add %o2, %g2)
-	add		%o1, 0x1, %o1
-	add		%o0, 0x1, %o0
-	subcc		%g2, 0x1, %g2
-	bg,pt		%icc, 1b
-	 stb		%o3, [%o0 + -1]
-
-2:	andn		%o2, 0x7, %g2
-	sub		%o2, %g2, %o2
-
-3:	EXNV(ldxa [%o1 + 0x00] %asi, %o3, add %o2, %g2)
-	add		%o1, 0x8, %o1
-	add		%o0, 0x8, %o0
-	subcc		%g2, 0x8, %g2
-	bg,pt		%icc, 3b
-	 stx		%o3, [%o0 + -8]
-
-	cmp		%o2, 0
-	bne,pn		%icc, U3copy_from_user_short
-	 nop
-	ba,a,pt		%xcc, U3copy_from_user_short_ret
-
-#endif /* !(SMALL_COPY_USES_FPU) */
-
-#ifdef __KERNEL__
-	.globl		U3cfu_fixup
-U3cfu_fixup:
-	/* Since this is copy_from_user(), zero out the rest of the
-	 * kernel buffer.
-	 */
-	cmp		%o1, 0
-	ble,pn		%icc, 2f
-	 mov		%o1, %g2
 
-1:	subcc		%g2, 1, %g2
-	stb		%g0, [%o0]
-	bne,pt		%icc, 1b
-	 add		%o0, 1, %o0
+#define FUNC_NAME		U3copy_from_user
+#define LOAD(type,addr,dest)	type##a [addr] %asi, dest
+#define EX_RETVAL(x)		0
 
-2:	retl
-	 mov		%o1, %o0
-#endif
+#include "U3memcpy.S"
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/sparc64/lib/U3copy_in_user.S linux-2.4.28-pre3/arch/sparc64/lib/U3copy_in_user.S
--- linux-2.4.27/arch/sparc64/lib/U3copy_in_user.S	2001-03-26 02:14:21.000000000 +0000
+++ linux-2.4.28-pre3/arch/sparc64/lib/U3copy_in_user.S	1970-01-01 00:00:00.000000000 +0000
@@ -1,531 +0,0 @@
-/* $Id: U3copy_in_user.S,v 1.4 2001/03/21 05:58:47 davem Exp $
- * U3memcpy.S: UltraSparc-III optimized copy within userspace.
- *
- * Copyright (C) 1999, 2000 David S. Miller (davem@redhat.com)
- */
-
-#ifdef __KERNEL__
-#include <asm/visasm.h>
-#include <asm/asi.h>
-#undef SMALL_COPY_USES_FPU
-#define EXNV(x,y,a,b)	\
-98:	x,y;				\
-	.section .fixup;		\
-	.align 4;			\
-99:	retl;				\
-	 a, b, %o0;			\
-	.section __ex_table;		\
-	.align 4;			\
-	.word 98b, 99b;			\
-	.text;				\
-	.align 4;
-#define EXNV2(x,y,a,b)	\
-98:	x,y;				\
-	.section .fixup;		\
-	.align 4;			\
-99:	a, b, %o0;			\
-	retl;				\
-	 add %o0, 1, %o0;		\
-	.section __ex_table;		\
-	.align 4;			\
-	.word 98b, 99b;			\
-	.text;				\
-	.align 4;
-#define EXNV3(x,y,a,b)	\
-98:	x,y;				\
-	.section .fixup;		\
-	.align 4;			\
-99:	a, b, %o0;			\
-	retl;				\
-	 add %o0, 8, %o0;		\
-	.section __ex_table;		\
-	.align 4;			\
-	.word 98b, 99b;			\
-	.text;				\
-	.align 4;
-#define EX(x,y,a,b)			\
-98:	x,y;				\
-	.section .fixup;		\
-	.align 4;			\
-99:	VISExitHalf;			\
-	retl;				\
-	 a, b, %o0;			\
-	.section __ex_table;		\
-	.align 4;			\
-	.word 98b, 99b;			\
-	.text;				\
-	.align 4;
-#define EXBLK1(x,y)			\
-98:	x,y;				\
-	.section .fixup;		\
-	.align 4;			\
-99:	VISExitHalf;			\
-	add %o4, 0x1c0, %o1;		\
-	and %o2, (0x40 - 1), %o2;	\
-	retl;				\
-	 add %o1, %o2, %o0;		\
-	.section __ex_table;		\
-	.align 4;			\
-	.word 98b, 99b;			\
-	.text;				\
-	.align 4;
-#define EXBLK2(x,y)			\
-98:	x,y;				\
-	.section .fixup;		\
-	.align 4;			\
-99:	VISExitHalf;			\
-	sll %o3, 6, %o3;		\
-	and %o2, (0x40 - 1), %o2;	\
-	add %o3, 0x80, %o1;		\
-	retl;				\
-	 add %o1, %o2, %o0;		\
-	.section __ex_table;		\
-	.align 4;			\
-	.word 98b, 99b;			\
-	.text;				\
-	.align 4;
-#define EXBLK3(x,y)			\
-98:	x,y;				\
-	.section .fixup;		\
-	.align 4;			\
-99:	VISExitHalf;			\
-	and %o2, (0x40 - 1), %o2;	\
-	retl;				\
-	 add %o2, 0x80, %o0;		\
-	.section __ex_table;		\
-	.align 4;			\
-	.word 98b, 99b;			\
-	.text;				\
-	.align 4;
-#define EXBLK4(x,y)			\
-98:	x,y;				\
-	.section .fixup;		\
-	.align 4;			\
-99:	VISExitHalf;			\
-	and %o2, (0x40 - 1), %o2;	\
-	retl;				\
-	 add %o2, 0x40, %o0;		\
-	.section __ex_table;		\
-	.align 4;			\
-	.word 98b, 99b;			\
-	.text;				\
-	.align 4;
-#else
-#define ASI_AIUS 0x80
-#define ASI_BLK_AIUS 0xf0
-#define FPRS_FEF  0x04
-#define VISEntryHalf rd %fprs, %o5; wr %g0, FPRS_FEF, %fprs
-#define VISExitHalf and %o5, FPRS_FEF, %o5; wr %o5, 0x0, %fprs
-#define SMALL_COPY_USES_FPU
-#define EXNV(x,y,a,b)	x,y;
-#define EXNV2(x,y,a,b)	x,y;
-#define EXNV3(x,y,a,b)	x,y;
-#define EX(x,y,a,b)	x,y;
-#define EXBLK1(x,y)	x,y;
-#define EXBLK2(x,y)	x,y;
-#define EXBLK3(x,y)	x,y;
-#define EXBLK4(x,y)	x,y;
-#endif
-
-	/* Special/non-trivial issues of this code:
-	 *
-	 * 1) %o5 is preserved from VISEntryHalf to VISExitHalf
-	 * 2) Only low 32 FPU registers are used so that only the
-	 *    lower half of the FPU register set is dirtied by this
-	 *    code.  This is especially important in the kernel.
-	 * 3) This code never prefetches cachelines past the end
-	 *    of the source buffer.
-	 *
-	 *    XXX Actually, Cheetah can buffer up to 8 concurrent
-	 *    XXX prefetches, revisit this...
-	 */
-
-	.text
-	.align	32
-
-	/* The cheetah's flexible spine, oversized liver, enlarged heart,
-	 * slender muscular body, and claws make it the swiftest hunter
-	 * in Africa and the fastest animal on land.  Can reach speeds
-	 * of up to 2.4GB per second.
-	 */
-
-	.globl		U3copy_in_user
-U3copy_in_user: /* %o0=dst, %o1=src, %o2=len */
-	/* Writing to %asi is _expensive_ so we hardcode it.
-	 * Reading %asi to check for KERNEL_DS is comparatively
-	 * cheap.
-	 */
-	rd		%asi, %g1			! MS	Group	(4 cycles)
-	cmp		%g1, ASI_AIUS			! A0	Group
-	bne		U3memcpy			! BR
-	 nop						! A1
-#ifndef __KERNEL__
-	/* Save away original 'dst' for memcpy return value. */
-	mov		%o0, %g3			! A0	Group
-#endif
-	/* Anything to copy at all? */
-	cmp		%o2, 0				! A1
-	ble,pn		%icc, U3copy_in_user_short_ret	! BR
-
-	/* Extremely small copy? */
-	 cmp		%o2, 31				! A0	Group
-	ble,pn		%icc, U3copy_in_user_short	! BR
-
-	/* Large enough to use unrolled prefetch loops? */
-	 cmp		%o2, 0x100			! A1
-	bge,a,pt	%icc, U3copy_in_user_enter	! BR	Group
-	 andcc		%o0, 0x3f, %g2			! A0
-
-	ba,pt		%xcc, U3copy_in_user_toosmall	! BR	Group
-	 andcc		%o0, 0x7, %g2			! A0
-
-	.align		32
-U3copy_in_user_short:
-	/* Copy %o2 bytes from src to dst, one byte at a time. */
-	EXNV(lduba [%o1 + 0x00] %asi, %o3, add %o2, %g0)! MS	Group
-	add		%o1, 0x1, %o1			! A0
-	add		%o0, 0x1, %o0			! A1
-	subcc		%o2, 1, %o2			! A0	Group
-
-	bg,pt		%icc, U3copy_in_user_short	! BR
-	 EXNV(stba %o3, [%o0 + -1] %asi, add %o2, 1)	! MS	Group (1-cycle stall)
-
-U3copy_in_user_short_ret:
-#ifdef __KERNEL__
-	retl						! BR	Group (0-4 cycle stall)
-	 clr		%o0				! A0
-#else
-	retl						! BR	Group (0-4 cycle stall)
-	 mov		%g3, %o0			! A0
-#endif
-
-	/* Here len >= (6 * 64) and condition codes reflect execution
-	 * of "andcc %o0, 0x7, %g2", done by caller.
-	 */
-	.align		64
-U3copy_in_user_enter:
-	/* Is 'dst' already aligned on an 64-byte boundary? */
-	be,pt		%xcc, 2f			! BR
-
-	/* Compute abs((dst & 0x3f) - 0x40) into %g2.  This is the number
-	 * of bytes to copy to make 'dst' 64-byte aligned.  We pre-
-	 * subtract this from 'len'.
-	 */
-	 sub		%g2, 0x40, %g2			! A0	Group
-	sub		%g0, %g2, %g2			! A0	Group
-	sub		%o2, %g2, %o2			! A0	Group
-
-	/* Copy %g2 bytes from src to dst, one byte at a time. */
-1:	EXNV(lduba [%o1 + 0x00] %asi, %o3, add %o2, %g2)! MS	(Group)
-	add		%o1, 0x1, %o1			! A1
-	add		%o0, 0x1, %o0			! A0	Group
-	subcc		%g2, 0x1, %g2			! A1
-
-	bg,pt		%icc, 1b			! BR	Group
-	 EXNV2(stba %o3, [%o0 + -1] %asi, add %o2, %g2)	! MS	Group
-
-2:	VISEntryHalf					! MS+MS
-	and		%o1, 0x7, %g1			! A1
-	ba,pt		%xcc, U3copy_in_user_begin	! BR
-	 alignaddr	%o1, %g0, %o1			! MS	      (Break-after)
-
-	.align		64
-U3copy_in_user_begin:
-	prefetcha	[%o1 + 0x000] %asi, #one_read	! MS	Group1
-	prefetcha	[%o1 + 0x040] %asi, #one_read	! MS	Group2
-	andn		%o2, (0x40 - 1), %o4		! A0
-	prefetcha	[%o1 + 0x080] %asi, #one_read	! MS	Group3
-	cmp		%o4, 0x140			! A0
-	prefetcha	[%o1 + 0x0c0] %asi, #one_read	! MS	Group4
-	EX(ldda [%o1 + 0x000] %asi, %f0, add %o2, %g0)	! MS	Group5 (%f0 results at G8)
-	bge,a,pt	%icc, 1f			! BR
-
-	 prefetcha	[%o1 + 0x100] %asi, #one_read	! MS	Group6
-1:	EX(ldda [%o1 + 0x008] %asi, %f2, add %o2, %g0)	! AX	       (%f2 results at G9)
-	cmp		%o4, 0x180			! A1
-	bge,a,pt	%icc, 1f			! BR
-	 prefetcha	[%o1 + 0x140] %asi, #one_read	! MS	Group7
-1:	EX(ldda [%o1 + 0x010] %asi, %f4, add %o2, %g0)	! AX	       (%f4 results at G10)
-	cmp		%o4, 0x1c0			! A1
-	bge,a,pt	%icc, 1f			! BR
-
-	 prefetcha	[%o1 + 0x180] %asi, #one_read	! MS	Group8
-1:	faligndata	%f0, %f2, %f16			! FGA	Group9 (%f16 at G12)
-	EX(ldda [%o1 + 0x018] %asi, %f6, add %o2, %g0)	! AX	       (%f6 results at G12)
-	faligndata	%f2, %f4, %f18			! FGA	Group10 (%f18 results at G13)
-	EX(ldda [%o1 + 0x020] %asi, %f8, add %o2, %g0)	! MS	        (%f8 results at G13)
-	faligndata	%f4, %f6, %f20			! FGA	Group12	(1-cycle stall,%f20 at G15)
-	EX(ldda [%o1 + 0x028] %asi, %f10, add %o2, %g0)	! MS		(%f10 results at G15)
-	faligndata	%f6, %f8, %f22			! FGA	Group13 (%f22 results at G16)
-	
-	EX(ldda [%o1 + 0x030] %asi, %f12, add %o2, %g0)	! MS		(%f12 results at G16)
-	faligndata	%f8, %f10, %f24			! FGA	Group15 (1-cycle stall,%f24 at G18)
-	EX(ldda [%o1 + 0x038] %asi, %f14, add %o2, %g0)	! MS		(%f14 results at G18)
-	faligndata	%f10, %f12, %f26		! FGA	Group16 (%f26 results at G19)
-	EX(ldda [%o1 + 0x040] %asi, %f0, add %o2, %g0)	! MS		(%f0 results at G19)
-
-	/* We only use the first loop if len > (7 * 64). */
-	subcc		%o4, 0x1c0, %o4			! A0	Group17
-	bg,pt		%icc, U3copy_in_user_loop1	! BR
-	 add		%o1, 0x40, %o1			! A1
-
-	add		%o4, 0x140, %o4			! A0	Group18
-	ba,pt		%xcc, U3copy_in_user_loop2	! BR
-	 srl		%o4, 6, %o3			! A0	Group19
-	nop
-	nop
-	nop
-	nop
-	nop
-
-	nop
-	nop
-
-	/* This loop performs the copy and queues new prefetches.
-	 * We drop into the second loop when len <= (5 * 64).  Note
-	 * that this (5 * 64) factor has been subtracted from len
-	 * already.
-	 */
-U3copy_in_user_loop1:
-	EXBLK1(ldda [%o1 + 0x008] %asi, %f2)		! MS	Group2	(%f2 results at G5)
-	faligndata	%f12, %f14, %f28		! FGA		(%f28 results at G5)
-	EXBLK1(ldda [%o1 + 0x010] %asi, %f4)		! MS	Group3	(%f4 results at G6)
-	faligndata	%f14, %f0, %f30			! FGA	Group4	(1-cycle stall, %f30 at G7)
-	EXBLK1(stda %f16, [%o0] ASI_BLK_AIUS)		! MS
-	EXBLK1(ldda [%o1 + 0x018] %asi, %f6)		! AX		(%f6 results at G7)
-
-	faligndata	%f0, %f2, %f16			! FGA	Group12 (7-cycle stall)
-	EXBLK1(ldda [%o1 + 0x020] %asi, %f8)		! MS	        (%f8 results at G15)
-	faligndata	%f2, %f4, %f18			! FGA	Group13	(%f18 results at G16)
-	EXBLK1(ldda [%o1 + 0x028] %asi, %f10)		! MS		(%f10 results at G16)
-	faligndata	%f4, %f6, %f20			! FGA	Group14	(%f20 results at G17)
-	EXBLK1(ldda [%o1 + 0x030] %asi, %f12)		! MS		(%f12 results at G17)
-	faligndata	%f6, %f8, %f22			! FGA	Group15	(%f22 results at G18)
-	EXBLK1(ldda [%o1 + 0x038] %asi, %f14)		! MS		(%f14 results at G18)
-
-	faligndata	%f8, %f10, %f24			! FGA	Group16	(%f24 results at G19)
-	EXBLK1(ldda [%o1 + 0x040] %asi, %f0)		! AX		(%f0 results at G19)
-	prefetcha	[%o1 + 0x180] %asi, #one_read	! MS
-	faligndata	%f10, %f12, %f26		! FGA	Group17	(%f26 results at G20)
-	subcc		%o4, 0x40, %o4			! A0
-	add		%o1, 0x40, %o1			! A1
-	bg,pt		%xcc, U3copy_in_user_loop1		! BR
-	 add		%o0, 0x40, %o0			! A0	Group18
-
-U3copy_in_user_loop2_enter:
-	mov		5, %o3				! A1
-
-	/* This loop performs on the copy, no new prefetches are
-	 * queued.  We do things this way so that we do not perform
-	 * any spurious prefetches past the end of the src buffer.
-	 */
-U3copy_in_user_loop2:
-	EXBLK2(ldda [%o1 + 0x008] %asi, %f2)		! MS
-	faligndata	%f12, %f14, %f28		! FGA	Group2
-	EXBLK2(ldda [%o1 + 0x010] %asi, %f4)		! MS
-	faligndata	%f14, %f0, %f30			! FGA	Group4	(1-cycle stall)
-	EXBLK2(stda %f16, [%o0] ASI_BLK_AIUS)		! MS
-	EXBLK2(ldda [%o1 + 0x018] %asi, %f6)		! AX
-	faligndata	%f0, %f2, %f16			! FGA	Group12 (7-cycle stall)
-
-	EXBLK2(ldda [%o1 + 0x020] %asi, %f8)		! MS
-	faligndata	%f2, %f4, %f18			! FGA	Group13
-	EXBLK2(ldda [%o1 + 0x028] %asi, %f10)		! MS
-	faligndata	%f4, %f6, %f20			! FGA	Group14
-	EXBLK2(ldda [%o1 + 0x030] %asi, %f12)		! MS
-	faligndata	%f6, %f8, %f22			! FGA	Group15
-	EXBLK2(ldda [%o1 + 0x038] %asi, %f14)		! MS
-	faligndata	%f8, %f10, %f24			! FGA	Group16
-
-	EXBLK2(ldda [%o1 + 0x040] %asi, %f0)		! AX
-	faligndata	%f10, %f12, %f26		! FGA	Group17
-	subcc		%o3, 0x01, %o3			! A0
-	add		%o1, 0x40, %o1			! A1
-	bg,pt		%xcc, U3copy_in_user_loop2	! BR
-	 add		%o0, 0x40, %o0			! A0	Group18
-
-	/* Finally we copy the last full 64-byte block. */
-U3copy_in_user_loopfini:
-	EXBLK3(ldda [%o1 + 0x008] %asi, %f2)		! MS
-	faligndata	%f12, %f14, %f28		! FGA
-	EXBLK3(ldda [%o1 + 0x010] %asi, %f4)		! MS	Group19
-	faligndata	%f14, %f0, %f30			! FGA
-	EXBLK3(stda %f16, [%o0] ASI_BLK_AIUS)		! MS	Group20
-	EXBLK4(ldda [%o1 + 0x018] %asi, %f6)		! AX
-	faligndata	%f0, %f2, %f16			! FGA	Group11 (7-cycle stall)
-	EXBLK4(ldda [%o1 + 0x020] %asi, %f8)		! MS
-	faligndata	%f2, %f4, %f18			! FGA	Group12
-	EXBLK4(ldda [%o1 + 0x028] %asi, %f10)		! MS
-	faligndata	%f4, %f6, %f20			! FGA	Group13
-	EXBLK4(ldda [%o1 + 0x030] %asi, %f12)		! MS
-	faligndata	%f6, %f8, %f22			! FGA	Group14
-	EXBLK4(ldda [%o1 + 0x038] %asi, %f14)		! MS
-	faligndata	%f8, %f10, %f24			! FGA	Group15
-	cmp		%g1, 0				! A0
-	be,pt		%icc, 1f			! BR
-	 add		%o0, 0x40, %o0			! A1
-	EXBLK4(ldda [%o1 + 0x040] %asi, %f0)		! MS
-1:	faligndata	%f10, %f12, %f26		! FGA	Group16
-	faligndata	%f12, %f14, %f28		! FGA	Group17
-	faligndata	%f14, %f0, %f30			! FGA	Group18
-	EXBLK4(stda %f16, [%o0] ASI_BLK_AIUS)		! MS
-	add		%o0, 0x40, %o0			! A0
-	add		%o1, 0x40, %o1			! A1
-	membar		#Sync				! MS	Group26 (7-cycle stall)
-
-	/* Now we copy the (len modulo 64) bytes at the end.
-	 * Note how we borrow the %f0 loaded above.
-	 *
-	 * Also notice how this code is careful not to perform a
-	 * load past the end of the src buffer just like similar
-	 * code found in U3copy_in_user_toosmall processing.
-	 */
-U3copy_in_user_loopend:
-	and		%o2, 0x3f, %o2			! A0	Group
-	andcc		%o2, 0x38, %g2			! A0	Group
-	be,pn		%icc, U3copy_in_user_endcruft	! BR
-	 subcc		%g2, 0x8, %g2			! A1
-	be,pn		%icc, U3copy_in_user_endcruft	! BR	Group
-	 cmp		%g1, 0				! A0
-
-	be,a,pt		%icc, 1f			! BR	Group
-	 EX(ldda [%o1 + 0x00] %asi, %f0, add %o2, %g0)	! MS
-
-1:	EX(ldda [%o1 + 0x08] %asi, %f2, add %o2, %g0)	! MS	Group
-	add		%o1, 0x8, %o1			! A0
-	sub		%o2, 0x8, %o2			! A1
-	subcc		%g2, 0x8, %g2			! A0	Group
-	faligndata	%f0, %f2, %f8			! FGA	Group
-	EX(stda %f8, [%o0 + 0x00] %asi, add %o2, 0x8)	! MS	(XXX does it stall here? XXX)
-	be,pn		%icc, U3copy_in_user_endcruft	! BR
-	 add		%o0, 0x8, %o0			! A0
-	EX(ldda [%o1 + 0x08] %asi, %f0, add %o2, %g0)	! MS	Group
-	add		%o1, 0x8, %o1			! A0
-	sub		%o2, 0x8, %o2			! A1
-	subcc		%g2, 0x8, %g2			! A0	Group
-	faligndata	%f2, %f0, %f8			! FGA
-	EX(stda %f8, [%o0 + 0x00] %asi, add %o2, 0x8)	! MS	(XXX does it stall here? XXX)
-	bne,pn		%icc, 1b			! BR
-	 add		%o0, 0x8, %o0			! A0	Group
-
-	/* If anything is left, we copy it one byte at a time.
-	 * Note that %g1 is (src & 0x3) saved above before the
-	 * alignaddr was performed.
-	 */
-U3copy_in_user_endcruft:
-	cmp		%o2, 0
-	add		%o1, %g1, %o1
-	VISExitHalf
-	be,pn		%icc, U3copy_in_user_short_ret
-	 nop
-	ba,a,pt		%xcc, U3copy_in_user_short
-
-	/* If we get here, then 32 <= len < (6 * 64) */
-U3copy_in_user_toosmall:
-
-#ifdef SMALL_COPY_USES_FPU
-
-	/* Is 'dst' already aligned on an 8-byte boundary? */
-	be,pt		%xcc, 2f			! BR	Group
-
-	/* Compute abs((dst & 7) - 8) into %g2.  This is the number
-	 * of bytes to copy to make 'dst' 8-byte aligned.  We pre-
-	 * subtract this from 'len'.
-	 */
-	 sub		%g2, 0x8, %g2			! A0
-	sub		%g0, %g2, %g2			! A0	Group (reg-dep)
-	sub		%o2, %g2, %o2			! A0	Group (reg-dep)
-
-	/* Copy %g2 bytes from src to dst, one byte at a time. */
-1:	EXNV2(lduba [%o1 + 0x00] %asi, %o3, add %o2, %g2)! MS	(Group) (%o3 in 3 cycles)
-	add		%o1, 0x1, %o1			! A1
-	add		%o0, 0x1, %o0			! A0	Group
-	subcc		%g2, 0x1, %g2			! A1
-
-	bg,pt		%icc, 1b			! BR	Group
-	 EXNV2(stba %o3, [%o0 + -1] %asi, add %o2, %g2)	! MS	Group
-
-2:	VISEntryHalf					! MS+MS
-
-	/* Compute (len - (len % 8)) into %g2.  This is guarenteed
-	 * to be nonzero.
-	 */
-	andn		%o2, 0x7, %g2			! A0	Group
-
-	/* You may read this and believe that it allows reading
-	 * one 8-byte longword past the end of src.  It actually
-	 * does not, as %g2 is subtracted as loads are done from
-	 * src, so we always stop before running off the end.
-	 * Also, we are guarenteed to have at least 0x10 bytes
-	 * to move here.
-	 */
-	sub		%g2, 0x8, %g2			! A0	Group (reg-dep)
-	alignaddr	%o1, %g0, %g1			! MS	      (Break-after)
-	EX(ldda [%g1 + 0x00] %asi, %f0, add %o2, %g0)	! MS	Group (1-cycle stall)
-	add		%g1, 0x8, %g1			! A0
-
-1:	EX(ldda [%g1 + 0x00] %asi, %f2, add %o2, %g0)	! MS	Group
-	add		%g1, 0x8, %g1			! A0
-	sub		%o2, 0x8, %o2			! A1
-	subcc		%g2, 0x8, %g2			! A0	Group
-
-	faligndata	%f0, %f2, %f8			! FGA	Group (1-cycle stall)
-	EX(stda %f8, [%o0 + 0x00] %asi, add %o2, 0x8)	! MS	Group (2-cycle stall)
-	add		%o1, 0x8, %o1			! A0
-	be,pn		%icc, 2f			! BR
-
-	 add		%o0, 0x8, %o0			! A1
-	EX(ldda [%g1 + 0x00] %asi, %f0, add %o2, %g0)	! MS	Group
-	add		%g1, 0x8, %g1			! A0
-	sub		%o2, 0x8, %o2			! A1
-
-	subcc		%g2, 0x8, %g2			! A0	Group
-	faligndata	%f2, %f0, %f8			! FGA	Group (1-cycle stall)
-	EX(stda %f8, [%o0 + 0x00] %asi, add %o2, 0x8)	! MS	Group (2-cycle stall)
-	add		%o1, 0x8, %o1			! A0
-
-	bne,pn		%icc, 1b			! BR
-	 add		%o0, 0x8, %o0			! A1
-
-	/* Nothing left to copy? */
-2:	cmp		%o2, 0				! A0	Group
-	VISExitHalf					! A0+MS
-	be,pn		%icc, U3copy_in_user_short_ret	! BR	Group
-	 nop						! A0
-	ba,a,pt		%xcc, U3copy_in_user_short	! BR	Group
-
-#else /* !(SMALL_COPY_USES_FPU) */
-
-	xor		%o1, %o0, %g2
-	andcc		%g2, 0x7, %g0
-	bne,pn		%icc, U3copy_in_user_short
-	 andcc		%o1, 0x7, %g2
-
-	be,pt		%xcc, 2f
-	 sub		%g2, 0x8, %g2
-	sub		%g0, %g2, %g2
-	sub		%o2, %g2, %o2
-
-1:	EXNV2(lduba [%o1 + 0x00] %asi, %o3, add %o2, %g2)
-	add		%o1, 0x1, %o1
-	add		%o0, 0x1, %o0
-	subcc		%g2, 0x1, %g2
-	bg,pt		%icc, 1b
-	 EXNV2(stba %o3, [%o0 + -1] %asi, add %o2, %g2)
-
-2:	andn		%o2, 0x7, %g2
-	sub		%o2, %g2, %o2
-
-3:	EXNV3(ldxa [%o1 + 0x00] %asi, %o3, add %o2, %g2)
-	add		%o1, 0x8, %o1
-	add		%o0, 0x8, %o0
-	subcc		%g2, 0x8, %g2
-	bg,pt		%icc, 3b
-	 EXNV3(stxa %o3, [%o0 + -8] %asi, add %o2, %g2)
-
-	cmp		%o2, 0
-	bne,pn		%icc, U3copy_in_user_short
-	 nop
-	ba,a,pt		%xcc, U3copy_in_user_short_ret
-
-#endif /* !(SMALL_COPY_USES_FPU) */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/sparc64/lib/U3copy_to_user.S linux-2.4.28-pre3/arch/sparc64/lib/U3copy_to_user.S
--- linux-2.4.27/arch/sparc64/lib/U3copy_to_user.S	2002-11-28 23:53:12.000000000 +0000
+++ linux-2.4.28-pre3/arch/sparc64/lib/U3copy_to_user.S	2004-09-10 19:31:50.000000000 +0000
@@ -1,547 +1,33 @@
-/* $Id: U3copy_to_user.S,v 1.3 2000/11/01 09:29:19 davem Exp $
- * U3memcpy.S: UltraSparc-III optimized copy to userspace.
+/* U3copy_to_user.S: UltraSparc-III optimized copy to userspace.
  *
- * Copyright (C) 1999, 2000 David S. Miller (davem@redhat.com)
+ * Copyright (C) 1999, 2000, 2004 David S. Miller (davem@redhat.com)
  */
 
-#ifdef __KERNEL__
-#include <asm/visasm.h>
-#include <asm/asi.h>
-#include <asm/dcu.h>
-#include <asm/spitfire.h>
-#undef SMALL_COPY_USES_FPU
-#define EXNV(x,y,a,b)	\
-98:	x,y;				\
-	.section .fixup;		\
-	.align 4;			\
-99:	retl;				\
-	 a, b, %o0;			\
-	.section __ex_table;		\
-	.align 4;			\
-	.word 98b, 99b;			\
-	.text;				\
-	.align 4;
-#define EXNV2(x,y,a,b)	\
-98:	x,y;				\
-	.section .fixup;		\
-	.align 4;			\
-99:	a, b, %o0;			\
-	retl;				\
-	 add %o0, 1, %o0;		\
-	.section __ex_table;		\
-	.align 4;			\
-	.word 98b, 99b;			\
-	.text;				\
-	.align 4;
-#define EXNV3(x,y,a,b)	\
-98:	x,y;				\
-	.section .fixup;		\
-	.align 4;			\
-99:	a, b, %o0;			\
-	retl;				\
-	 add %o0, 8, %o0;		\
-	.section __ex_table;		\
-	.align 4;			\
-	.word 98b, 99b;			\
-	.text;				\
-	.align 4;
-#define EX(x,y,a,b)			\
-98:	x,y;				\
-	.section .fixup;		\
-	.align 4;			\
-99:	VISExitHalf;			\
-	retl;				\
-	 a, b, %o0;			\
-	.section __ex_table;		\
-	.align 4;			\
-	.word 98b, 99b;			\
-	.text;				\
-	.align 4;
-#define EXBLK1(x,y)			\
-98:	x,y;				\
-	.section .fixup;		\
-	.align 4;			\
-99:	VISExitHalf;			\
-	add %o4, 0x1c0, %o1;		\
-	and %o2, (0x40 - 1), %o2;	\
-	retl;				\
-	 add %o1, %o2, %o0;		\
-	.section __ex_table;		\
-	.align 4;			\
-	.word 98b, 99b;			\
-	.text;				\
-	.align 4;
-#define EXBLK2(x,y)			\
-98:	x,y;				\
-	.section .fixup;		\
-	.align 4;			\
-99:	VISExitHalf;			\
-	sll %o3, 6, %o3;		\
-	and %o2, (0x40 - 1), %o2;	\
-	add %o3, 0x80, %o1;		\
-	retl;				\
-	 add %o1, %o2, %o0;		\
-	.section __ex_table;		\
-	.align 4;			\
-	.word 98b, 99b;			\
-	.text;				\
-	.align 4;
-#define EXBLK3(x,y)			\
-98:	x,y;				\
-	.section .fixup;		\
-	.align 4;			\
-99:	VISExitHalf;			\
-	and %o2, (0x40 - 1), %o2;	\
-	retl;				\
-	 add %o2, 0x80, %o0;		\
-	.section __ex_table;		\
-	.align 4;			\
-	.word 98b, 99b;			\
-	.text;				\
-	.align 4;
-#define EXBLK4(x,y)			\
-98:	x,y;				\
-	.section .fixup;		\
-	.align 4;			\
-99:	VISExitHalf;			\
-	and %o2, (0x40 - 1), %o2;	\
-	retl;				\
-	 add %o2, 0x40, %o0;		\
-	.section __ex_table;		\
-	.align 4;			\
-	.word 98b, 99b;			\
-	.text;				\
-	.align 4;
-#else
-#define ASI_AIUS 0x80
-#define ASI_BLK_AIUS 0xf0
-#define FPRS_FEF  0x04
-#define VISEntryHalf rd %fprs, %o5; wr %g0, FPRS_FEF, %fprs
-#define VISExitHalf and %o5, FPRS_FEF, %o5; wr %o5, 0x0, %fprs
-#define SMALL_COPY_USES_FPU
-#define EXNV(x,y,a,b)	x,y;
-#define EXNV2(x,y,a,b)	x,y;
-#define EXNV3(x,y,a,b)	x,y;
-#define EX(x,y,a,b)	x,y;
-#define EXBLK1(x,y)	x,y;
-#define EXBLK2(x,y)	x,y;
-#define EXBLK3(x,y)	x,y;
-#define EXBLK4(x,y)	x,y;
-#endif
-
-	/* Special/non-trivial issues of this code:
-	 *
-	 * 1) %o5 is preserved from VISEntryHalf to VISExitHalf
-	 * 2) Only low 32 FPU registers are used so that only the
-	 *    lower half of the FPU register set is dirtied by this
-	 *    code.  This is especially important in the kernel.
-	 * 3) This code never prefetches cachelines past the end
-	 *    of the source buffer.
-	 */
+#define EX_ST(x)		\
+98:	x;			\
+	.section .fixup;	\
+	.align 4;		\
+99:	retl;			\
+	 mov	1, %o0;		\
+	.section __ex_table;	\
+	.align 4;		\
+	.word 98b, 99b;		\
+	.text;			\
+	.align 4;
+
+#define FUNC_NAME		U3copy_to_user
+#define STORE(type,src,addr)	type##a src, [addr] ASI_AIUS
+#define STORE_BLK(src,addr)	stda src, [addr] ASI_BLK_AIUS
+#define EX_RETVAL(x)		0
 
-	.text
-	.align	32
-
-	/* The cheetah's flexible spine, oversized liver, enlarged heart,
-	 * slender muscular body, and claws make it the swiftest hunter
-	 * in Africa and the fastest animal on land.  Can reach speeds
-	 * of up to 2.4GB per second.
-	 */
-
-	.globl		U3copy_to_user
-U3copy_to_user: /* %o0=dst, %o1=src, %o2=len */
 	/* Writing to %asi is _expensive_ so we hardcode it.
 	 * Reading %asi to check for KERNEL_DS is comparatively
 	 * cheap.
 	 */
-	rd		%asi, %g1			! MS	Group	(4 cycles)
-	cmp		%g1, ASI_AIUS			! A0	Group
-	bne		U3memcpy			! BR
-	 nop						! A1
-#ifndef __KERNEL__
-	/* Save away original 'dst' for memcpy return value. */
-	mov		%o0, %g3			! A0	Group
-#endif
-	/* Anything to copy at all? */
-	cmp		%o2, 0				! A1
-	ble,pn		%icc, U3copy_to_user_short_ret	! BR
-
-	/* Extremely small copy? */
-	 cmp		%o2, 31				! A0	Group
-	ble,pn		%icc, U3copy_to_user_short	! BR
-
-	/* Large enough to use unrolled prefetch loops? */
-	 cmp		%o2, 0x100			! A1
-	bge,a,pt	%icc, U3copy_to_user_enter	! BR	Group
-	 andcc		%o0, 0x3f, %g2			! A0
-
-	ba,pt		%xcc, U3copy_to_user_toosmall	! BR	Group
-	 andcc		%o0, 0x7, %g2			! A0
-
-	.align		32
-U3copy_to_user_short:
-	/* Copy %o2 bytes from src to dst, one byte at a time. */
-	ldub		[%o1 + 0x00], %o3		! MS	Group
-	add		%o1, 0x1, %o1			! A0
-	add		%o0, 0x1, %o0			! A1
-	subcc		%o2, 1, %o2			! A0	Group
-
-	bg,pt		%icc, U3copy_to_user_short	! BR
-	 EXNV(stba %o3, [%o0 + -1] %asi, add %o2, 1)	! MS	Group (1-cycle stall)
-
-U3copy_to_user_short_ret:
-#ifdef __KERNEL__
-	retl						! BR	Group (0-4 cycle stall)
-	 clr		%o0				! A0
-#else
-	retl						! BR	Group (0-4 cycle stall)
-	 mov		%g3, %o0			! A0
-#endif
-
-	/* Here len >= (6 * 64) and condition codes reflect execution
-	 * of "andcc %o0, 0x7, %g2", done by caller.
-	 */
-	.align		64
-U3copy_to_user_enter:
-	/* Is 'dst' already aligned on an 64-byte boundary? */
-	be,pt		%xcc, 2f			! BR
-
-	/* Compute abs((dst & 0x3f) - 0x40) into %g2.  This is the number
-	 * of bytes to copy to make 'dst' 64-byte aligned.  We pre-
-	 * subtract this from 'len'.
-	 */
-	 sub		%g2, 0x40, %g2			! A0	Group
-	sub		%g0, %g2, %g2			! A0	Group
-	sub		%o2, %g2, %o2			! A0	Group
-
-	/* Copy %g2 bytes from src to dst, one byte at a time. */
-1:	ldub		[%o1 + 0x00], %o3		! MS	(Group)
-	add		%o1, 0x1, %o1			! A1
-	add		%o0, 0x1, %o0			! A0	Group
-	subcc		%g2, 0x1, %g2			! A1
-
-	bg,pt		%icc, 1b			! BR	Group
-	 EXNV2(stba %o3, [%o0 + -1] %asi, add %o2, %g2)	! MS	Group
-
-2:	VISEntryHalf					! MS+MS
-	and		%o1, 0x7, %g1			! A1
-	ba,pt		%xcc, U3copy_to_user_begin	! BR
-	 alignaddr	%o1, %g0, %o1			! MS	      (Break-after)
-
-	.align		64
-U3copy_to_user_begin:
-#ifdef __KERNEL__
-	.globl		U3copy_to_user_nop_1_6
-U3copy_to_user_nop_1_6:
-	ldxa		[%g0] ASI_DCU_CONTROL_REG, %g3
-	sethi		%uhi(DCU_PE), %o3
-	sllx		%o3, 32, %o3
-	or		%g3, %o3, %o3
-	stxa		%o3, [%g0] ASI_DCU_CONTROL_REG	! Enable P-cache
-	membar		#Sync
-#endif
-	prefetch	[%o1 + 0x000], #one_read	! MS	Group1
-	prefetch	[%o1 + 0x040], #one_read	! MS	Group2
-	andn		%o2, (0x40 - 1), %o4		! A0
-	prefetch	[%o1 + 0x080], #one_read	! MS	Group3
-	cmp		%o4, 0x140			! A0
-	prefetch	[%o1 + 0x0c0], #one_read	! MS	Group4
-	ldd		[%o1 + 0x000], %f0		! MS	Group5 (%f0 results at G8)
-	bge,a,pt	%icc, 1f			! BR
-
-	 prefetch	[%o1 + 0x100], #one_read	! MS	Group6
-1:	ldd		[%o1 + 0x008], %f2		! AX	       (%f2 results at G9)
-	cmp		%o4, 0x180			! A1
-	bge,a,pt	%icc, 1f			! BR
-	 prefetch	[%o1 + 0x140], #one_read	! MS	Group7
-1:	ldd		[%o1 + 0x010], %f4		! AX	       (%f4 results at G10)
-	cmp		%o4, 0x1c0			! A1
-	bge,a,pt	%icc, 1f			! BR
-
-	 prefetch	[%o1 + 0x180], #one_read	! MS	Group8
-1:	faligndata	%f0, %f2, %f16			! FGA	Group9 (%f16 at G12)
-	ldd		[%o1 + 0x018], %f6		! AX	       (%f6 results at G12)
-	faligndata	%f2, %f4, %f18			! FGA	Group10 (%f18 results at G13)
-	ldd		[%o1 + 0x020], %f8		! MS	        (%f8 results at G13)
-	faligndata	%f4, %f6, %f20			! FGA	Group12	(1-cycle stall,%f20 at G15)
-	ldd		[%o1 + 0x028], %f10		! MS		(%f10 results at G15)
-	faligndata	%f6, %f8, %f22			! FGA	Group13 (%f22 results at G16)
-	
-	ldd		[%o1 + 0x030], %f12		! MS		(%f12 results at G16)
-	faligndata	%f8, %f10, %f24			! FGA	Group15 (1-cycle stall,%f24 at G18)
-	ldd		[%o1 + 0x038], %f14		! MS		(%f14 results at G18)
-	faligndata	%f10, %f12, %f26		! FGA	Group16 (%f26 results at G19)
-	ldd		[%o1 + 0x040], %f0		! MS		(%f0 results at G19)
-
-	/* We only use the first loop if len > (7 * 64). */
-	subcc		%o4, 0x1c0, %o4			! A0	Group17
-	bg,pt		%icc, U3copy_to_user_loop1	! BR
-	 add		%o1, 0x40, %o1			! A1
-
-	add		%o4, 0x140, %o4			! A0	Group18
-	ba,pt		%xcc, U3copy_to_user_loop2	! BR
-	 srl		%o4, 6, %o3			! A0	Group19
-	nop
-	nop
-	nop
-	nop
-	nop
-
-	nop
-	nop
-
-	/* This loop performs the copy and queues new prefetches.
-	 * We drop into the second loop when len <= (5 * 64).  Note
-	 * that this (5 * 64) factor has been subtracted from len
-	 * already.
-	 */
-U3copy_to_user_loop1:
-	ldd		[%o1 + 0x008], %f2		! MS	Group2	(%f2 results at G5)
-	faligndata	%f12, %f14, %f28		! FGA		(%f28 results at G5)
-	ldd		[%o1 + 0x010], %f4		! MS	Group3	(%f4 results at G6)
-	faligndata	%f14, %f0, %f30			! FGA	Group4	(1-cycle stall, %f30 at G7)
-	EXBLK1(stda %f16, [%o0] ASI_BLK_AIUS)		! MS
-	ldd		[%o1 + 0x018], %f6		! AX		(%f6 results at G7)
-
-	faligndata	%f0, %f2, %f16			! FGA	Group12 (7-cycle stall)
-	ldd		[%o1 + 0x020], %f8		! MS	        (%f8 results at G15)
-	faligndata	%f2, %f4, %f18			! FGA	Group13	(%f18 results at G16)
-	ldd		[%o1 + 0x028], %f10		! MS		(%f10 results at G16)
-	faligndata	%f4, %f6, %f20			! FGA	Group14	(%f20 results at G17)
-	ldd		[%o1 + 0x030], %f12		! MS		(%f12 results at G17)
-	faligndata	%f6, %f8, %f22			! FGA	Group15	(%f22 results at G18)
-	ldd		[%o1 + 0x038], %f14		! MS		(%f14 results at G18)
-
-	faligndata	%f8, %f10, %f24			! FGA	Group16	(%f24 results at G19)
-	ldd		[%o1 + 0x040], %f0		! AX		(%f0 results at G19)
-	prefetch	[%o1 + 0x180], #one_read	! MS
-	faligndata	%f10, %f12, %f26		! FGA	Group17	(%f26 results at G20)
-	subcc		%o4, 0x40, %o4			! A0
-	add		%o1, 0x40, %o1			! A1
-	bg,pt		%xcc, U3copy_to_user_loop1		! BR
-	 add		%o0, 0x40, %o0			! A0	Group18
-
-U3copy_to_user_loop2_enter:
-	mov		5, %o3				! A1
-
-	/* This loop performs on the copy, no new prefetches are
-	 * queued.  We do things this way so that we do not perform
-	 * any spurious prefetches past the end of the src buffer.
-	 */
-U3copy_to_user_loop2:
-	ldd		[%o1 + 0x008], %f2		! MS
-	faligndata	%f12, %f14, %f28		! FGA	Group2
-	ldd		[%o1 + 0x010], %f4		! MS
-	faligndata	%f14, %f0, %f30			! FGA	Group4	(1-cycle stall)
-	EXBLK2(stda %f16, [%o0] ASI_BLK_AIUS)		! MS
-	ldd		[%o1 + 0x018], %f6		! AX
-	faligndata	%f0, %f2, %f16			! FGA	Group12 (7-cycle stall)
-
-	ldd		[%o1 + 0x020], %f8		! MS
-	faligndata	%f2, %f4, %f18			! FGA	Group13
-	ldd		[%o1 + 0x028], %f10		! MS
-	faligndata	%f4, %f6, %f20			! FGA	Group14
-	ldd		[%o1 + 0x030], %f12		! MS
-	faligndata	%f6, %f8, %f22			! FGA	Group15
-	ldd		[%o1 + 0x038], %f14		! MS
-	faligndata	%f8, %f10, %f24			! FGA	Group16
-
-	ldd		[%o1 + 0x040], %f0		! AX
-	faligndata	%f10, %f12, %f26		! FGA	Group17
-	subcc		%o3, 0x01, %o3			! A0
-	add		%o1, 0x40, %o1			! A1
-	bg,pt		%xcc, U3copy_to_user_loop2	! BR
-	 add		%o0, 0x40, %o0			! A0	Group18
-
-	/* Finally we copy the last full 64-byte block. */
-U3copy_to_user_loopfini:
-	ldd		[%o1 + 0x008], %f2		! MS
-	faligndata	%f12, %f14, %f28		! FGA
-	ldd		[%o1 + 0x010], %f4		! MS	Group19
-	faligndata	%f14, %f0, %f30			! FGA
-	EXBLK3(stda %f16, [%o0] ASI_BLK_AIUS)		! MS	Group20
-	ldd		[%o1 + 0x018], %f6		! AX
-	faligndata	%f0, %f2, %f16			! FGA	Group11 (7-cycle stall)
-	ldd		[%o1 + 0x020], %f8		! MS
-	faligndata	%f2, %f4, %f18			! FGA	Group12
-	ldd		[%o1 + 0x028], %f10		! MS
-	faligndata	%f4, %f6, %f20			! FGA	Group13
-	ldd		[%o1 + 0x030], %f12		! MS
-	faligndata	%f6, %f8, %f22			! FGA	Group14
-	ldd		[%o1 + 0x038], %f14		! MS
-	faligndata	%f8, %f10, %f24			! FGA	Group15
-	cmp		%g1, 0				! A0
-	be,pt		%icc, 1f			! BR
-	 add		%o0, 0x40, %o0			! A1
-	ldd		[%o1 + 0x040], %f0		! MS
-1:	faligndata	%f10, %f12, %f26		! FGA	Group16
-	faligndata	%f12, %f14, %f28		! FGA	Group17
-	faligndata	%f14, %f0, %f30			! FGA	Group18
-	EXBLK4(stda %f16, [%o0] ASI_BLK_AIUS)		! MS
-	add		%o0, 0x40, %o0			! A0
-	add		%o1, 0x40, %o1			! A1
-#ifdef __KERNEL__
-	.globl		U3copy_to_user_nop_2_3
-U3copy_to_user_nop_2_3:
-	mov		PRIMARY_CONTEXT, %o3
-	stxa		%g0, [%o3] ASI_DMMU		! Flush P-cache
-	stxa		%g3, [%g0] ASI_DCU_CONTROL_REG	! Disable P-cache
-#endif
-	membar		#Sync				! MS	Group26 (7-cycle stall)
-
-	/* Now we copy the (len modulo 64) bytes at the end.
-	 * Note how we borrow the %f0 loaded above.
-	 *
-	 * Also notice how this code is careful not to perform a
-	 * load past the end of the src buffer just like similar
-	 * code found in U3copy_to_user_toosmall processing.
-	 */
-U3copy_to_user_loopend:
-	and		%o2, 0x3f, %o2			! A0	Group
-	andcc		%o2, 0x38, %g2			! A0	Group
-	be,pn		%icc, U3copy_to_user_endcruft	! BR
-	 subcc		%g2, 0x8, %g2			! A1
-	be,pn		%icc, U3copy_to_user_endcruft	! BR	Group
-	 cmp		%g1, 0				! A0
-
-	be,a,pt		%icc, 1f			! BR	Group
-	 ldd		[%o1 + 0x00], %f0		! MS
-
-1:	ldd		[%o1 + 0x08], %f2		! MS	Group
-	add		%o1, 0x8, %o1			! A0
-	sub		%o2, 0x8, %o2			! A1
-	subcc		%g2, 0x8, %g2			! A0	Group
-	faligndata	%f0, %f2, %f8			! FGA	Group
-	EX(stda %f8, [%o0 + 0x00] %asi, add %o2, 0x8)	! MS	(XXX does it stall here? XXX)
-	be,pn		%icc, U3copy_to_user_endcruft	! BR
-	 add		%o0, 0x8, %o0			! A0
-	ldd		[%o1 + 0x08], %f0		! MS	Group
-	add		%o1, 0x8, %o1			! A0
-	sub		%o2, 0x8, %o2			! A1
-	subcc		%g2, 0x8, %g2			! A0	Group
-	faligndata	%f2, %f0, %f8			! FGA
-	EX(stda %f8, [%o0 + 0x00] %asi, add %o2, 0x8)	! MS	(XXX does it stall here? XXX)
-	bne,pn		%icc, 1b			! BR
-	 add		%o0, 0x8, %o0			! A0	Group
-
-	/* If anything is left, we copy it one byte at a time.
-	 * Note that %g1 is (src & 0x3) saved above before the
-	 * alignaddr was performed.
-	 */
-U3copy_to_user_endcruft:
-	cmp		%o2, 0
-	add		%o1, %g1, %o1
-	VISExitHalf
-	be,pn		%icc, U3copy_to_user_short_ret
-	 nop
-	ba,a,pt		%xcc, U3copy_to_user_short
-
-	/* If we get here, then 32 <= len < (6 * 64) */
-U3copy_to_user_toosmall:
-
-#ifdef SMALL_COPY_USES_FPU
-
-	/* Is 'dst' already aligned on an 8-byte boundary? */
-	be,pt		%xcc, 2f			! BR	Group
-
-	/* Compute abs((dst & 7) - 8) into %g2.  This is the number
-	 * of bytes to copy to make 'dst' 8-byte aligned.  We pre-
-	 * subtract this from 'len'.
-	 */
-	 sub		%g2, 0x8, %g2			! A0
-	sub		%g0, %g2, %g2			! A0	Group (reg-dep)
-	sub		%o2, %g2, %o2			! A0	Group (reg-dep)
-
-	/* Copy %g2 bytes from src to dst, one byte at a time. */
-1:	ldub		[%o1 + 0x00], %o3		! MS	(Group) (%o3 in 3 cycles)
-	add		%o1, 0x1, %o1			! A1
-	add		%o0, 0x1, %o0			! A0	Group
-	subcc		%g2, 0x1, %g2			! A1
-
-	bg,pt		%icc, 1b			! BR	Group
-	 EXNV2(stba %o3, [%o0 + -1] %asi, add %o2, %g2)	! MS	Group
-
-2:	VISEntryHalf					! MS+MS
-
-	/* Compute (len - (len % 8)) into %g2.  This is guarenteed
-	 * to be nonzero.
-	 */
-	andn		%o2, 0x7, %g2			! A0	Group
-
-	/* You may read this and believe that it allows reading
-	 * one 8-byte longword past the end of src.  It actually
-	 * does not, as %g2 is subtracted as loads are done from
-	 * src, so we always stop before running off the end.
-	 * Also, we are guarenteed to have at least 0x10 bytes
-	 * to move here.
-	 */
-	sub		%g2, 0x8, %g2			! A0	Group (reg-dep)
-	alignaddr	%o1, %g0, %g1			! MS	      (Break-after)
-	ldd		[%g1 + 0x00], %f0		! MS	Group (1-cycle stall)
-	add		%g1, 0x8, %g1			! A0
-
-1:	ldd		[%g1 + 0x00], %f2		! MS	Group
-	add		%g1, 0x8, %g1			! A0
-	sub		%o2, 0x8, %o2			! A1
-	subcc		%g2, 0x8, %g2			! A0	Group
-
-	faligndata	%f0, %f2, %f8			! FGA	Group (1-cycle stall)
-	EX(stda %f8, [%o0 + 0x00] %asi, add %o2, 0x8)	! MS	Group (2-cycle stall)
-	add		%o1, 0x8, %o1			! A0
-	be,pn		%icc, 2f			! BR
-
-	 add		%o0, 0x8, %o0			! A1
-	ldd		[%g1 + 0x00], %f0		! MS	Group
-	add		%g1, 0x8, %g1			! A0
-	sub		%o2, 0x8, %o2			! A1
-
-	subcc		%g2, 0x8, %g2			! A0	Group
-	faligndata	%f2, %f0, %f8			! FGA	Group (1-cycle stall)
-	EX(stda %f8, [%o0 + 0x00] %asi, add %o2, 0x8)	! MS	Group (2-cycle stall)
-	add		%o1, 0x8, %o1			! A0
-
-	bne,pn		%icc, 1b			! BR
-	 add		%o0, 0x8, %o0			! A1
-
-	/* Nothing left to copy? */
-2:	cmp		%o2, 0				! A0	Group
-	VISExitHalf					! A0+MS
-	be,pn		%icc, U3copy_to_user_short_ret	! BR	Group
-	 nop						! A0
-	ba,a,pt		%xcc, U3copy_to_user_short	! BR	Group
-
-#else /* !(SMALL_COPY_USES_FPU) */
-
-	xor		%o1, %o0, %g2
-	andcc		%g2, 0x7, %g0
-	bne,pn		%icc, U3copy_to_user_short
-	 andcc		%o1, 0x7, %g2
-
-	be,pt		%xcc, 2f
-	 sub		%g2, 0x8, %g2
-	sub		%g0, %g2, %g2
-	sub		%o2, %g2, %o2
-
-1:	ldub		[%o1 + 0x00], %o3
-	add		%o1, 0x1, %o1
-	add		%o0, 0x1, %o0
-	subcc		%g2, 0x1, %g2
-	bg,pt		%icc, 1b
-	 EXNV2(stba %o3, [%o0 + -1] %asi, add %o2, %g2)
-
-2:	andn		%o2, 0x7, %g2
-	sub		%o2, %g2, %o2
-
-3:	ldx		[%o1 + 0x00], %o3
-	add		%o1, 0x8, %o1
-	add		%o0, 0x8, %o0
-	subcc		%g2, 0x8, %g2
-	bg,pt		%icc, 3b
-	 EXNV3(stxa %o3, [%o0 + -8] %asi, add %o2, %g2)
-
-	cmp		%o2, 0
-	bne,pn		%icc, U3copy_to_user_short
-	 nop
-	ba,a,pt		%xcc, U3copy_to_user_short_ret
+#define PREAMBLE					\
+	rd		%asi, %g1;			\
+	cmp		%g1, ASI_AIUS;			\
+	bne,pn		%icc, memcpy_user_stub;		\
+	 nop;						\
 
-#endif /* !(SMALL_COPY_USES_FPU) */
+#include "U3memcpy.S"
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/sparc64/lib/U3memcpy.S linux-2.4.28-pre3/arch/sparc64/lib/U3memcpy.S
--- linux-2.4.27/arch/sparc64/lib/U3memcpy.S	2002-11-28 23:53:12.000000000 +0000
+++ linux-2.4.28-pre3/arch/sparc64/lib/U3memcpy.S	2004-09-10 19:37:24.000000000 +0000
@@ -1,23 +1,63 @@
-/* $Id: U3memcpy.S,v 1.2 2000/11/01 09:29:19 davem Exp $
- * U3memcpy.S: UltraSparc-III optimized memcpy.
+/* U3memcpy.S: UltraSparc-III optimized memcpy.
  *
- * Copyright (C) 1999, 2000 David S. Miller (davem@redhat.com)
+ * Copyright (C) 1999, 2000, 2004 David S. Miller (davem@redhat.com)
  */
 
 #ifdef __KERNEL__
 #include <asm/visasm.h>
 #include <asm/asi.h>
-#include <asm/dcu.h>
-#include <asm/spitfire.h>
-#undef SMALL_COPY_USES_FPU
 #else
 #define ASI_BLK_P 0xf0
 #define FPRS_FEF  0x04
+#ifdef MEMCPY_DEBUG
+#define VISEntryHalf rd %fprs, %o5; wr %g0, FPRS_FEF, %fprs; \
+		     clr %g1; clr %g2; clr %g3; subcc %g0, %g0, %g0;
+#define VISExitHalf and %o5, FPRS_FEF, %o5; wr %o5, 0x0, %fprs
+#else
 #define VISEntryHalf rd %fprs, %o5; wr %g0, FPRS_FEF, %fprs
 #define VISExitHalf and %o5, FPRS_FEF, %o5; wr %o5, 0x0, %fprs
-#define SMALL_COPY_USES_FPU
+#endif
+#endif
+
+#ifndef EX_LD
+#define EX_LD(x)	x
+#endif
+
+#ifndef EX_ST
+#define EX_ST(x)	x
+#endif
+
+#ifndef EX_RETVAL
+#define EX_RETVAL(x)	x
 #endif
 
+#ifndef LOAD
+#define LOAD(type,addr,dest)	type [addr], dest
+#endif
+
+#ifndef STORE
+#define STORE(type,src,addr)	type src, [addr]
+#endif
+
+#ifndef STORE_BLK
+#define STORE_BLK(src,addr)	stda src, [addr] ASI_BLK_P
+#endif
+
+#ifndef FUNC_NAME
+#define FUNC_NAME	U3memcpy
+#endif
+
+#ifndef PREAMBLE
+#define PREAMBLE
+#endif
+
+#ifndef XCC
+#define XCC xcc
+#endif
+
+	.register	%g2,#scratch
+	.register	%g3,#scratch
+
 	/* Special/non-trivial issues of this code:
 	 *
 	 * 1) %o5 is preserved from VISEntryHalf to VISExitHalf
@@ -29,7 +69,7 @@
 	 */
 
 	.text
-	.align	32
+	.align		64
 
 	/* The cheetah's flexible spine, oversized liver, enlarged heart,
 	 * slender muscular body, and claws make it the swiftest hunter
@@ -37,392 +77,338 @@
 	 * of up to 2.4GB per second.
 	 */
 
-	.globl		U3memcpy
-U3memcpy: /* %o0=dst, %o1=src, %o2=len */
-#ifndef __KERNEL__
-	/* Save away original 'dst' for memcpy return value. */
-	mov		%o0, %g3			! A0	Group
-#endif
-	/* Anything to copy at all? */
-	cmp		%o2, 0				! A1
-	ble,pn		%icc, U3memcpy_short_ret	! BR
-
-	/* Extremely small copy? */
-	 cmp		%o2, 31				! A0	Group
-	ble,pn		%icc, U3memcpy_short		! BR
-
-	/* Large enough to use unrolled prefetch loops? */
-	 cmp		%o2, 0x100			! A1
-	bge,a,pt	%icc, U3memcpy_enter		! BR	Group
-	 andcc		%o0, 0x3f, %g2			! A0
-
-	ba,pt		%xcc, U3memcpy_toosmall		! BR	Group
-	 andcc		%o0, 0x7, %g2			! A0
-
-	.align		32
-U3memcpy_short:
-	/* Copy %o2 bytes from src to dst, one byte at a time. */
-	ldub		[%o1 + 0x00], %o3		! MS	Group
-	add		%o1, 0x1, %o1			! A0
-	add		%o0, 0x1, %o0			! A1
-	subcc		%o2, 1, %o2			! A0	Group
-
-	bg,pt		%icc, U3memcpy_short		! BR
-	 stb		%o3, [%o0 + -1]			! MS	Group (1-cycle stall)
-
-U3memcpy_short_ret:
-#ifdef __KERNEL__
-	retl						! BR	Group (0-4 cycle stall)
-	 clr		%o0				! A0
-#else
-	retl						! BR	Group (0-4 cycle stall)
-	 mov		%g3, %o0			! A0
-#endif
+	.globl	FUNC_NAME
+FUNC_NAME:	/* %o0=dst, %o1=src, %o2=len */
+	PREAMBLE
+	mov		%o0, %g5
+	cmp		%o2, 0
+	be,pn		%XCC, 85f
+	 or		%o0, %o1, %o3
+	cmp		%o2, 16
+	blu,a,pn	%XCC, 80f
+	 or		%o3, %o2, %o3
+
+	cmp		%o2, (3 * 64)
+	blu,pt		%XCC, 70f
+	 andcc		%o3, 0x7, %g0
 
-	/* Here len >= (6 * 64) and condition codes reflect execution
-	 * of "andcc %o0, 0x7, %g2", done by caller.
+	/* Clobbers o5/g1/g2/g3/g7/icc/xcc.  We must preserve
+	 * o5 from here until we hit VISExitHalf.
 	 */
-	.align		64
-U3memcpy_enter:
+	VISEntryHalf
+
 	/* Is 'dst' already aligned on an 64-byte boundary? */
-	be,pt		%xcc, 2f			! BR
+	andcc		%o0, 0x3f, %g2
+	be,pt		%XCC, 2f
 
 	/* Compute abs((dst & 0x3f) - 0x40) into %g2.  This is the number
 	 * of bytes to copy to make 'dst' 64-byte aligned.  We pre-
 	 * subtract this from 'len'.
 	 */
-	 sub		%g2, 0x40, %g2			! A0	Group
-	sub		%g0, %g2, %g2			! A0	Group
-	sub		%o2, %g2, %o2			! A0	Group
-
-	/* Copy %g2 bytes from src to dst, one byte at a time. */
-1:	ldub		[%o1 + 0x00], %o3		! MS	(Group)
-	add		%o1, 0x1, %o1			! A1
-	add		%o0, 0x1, %o0			! A0	Group
-	subcc		%g2, 0x1, %g2			! A1
-
-	bg,pt		%icc, 1b			! BR	Group
-	 stb		%o3, [%o0 + -1]			! MS	Group
-
-2:	VISEntryHalf					! MS+MS
-	and		%o1, 0x7, %g1			! A1
-	ba,pt		%xcc, U3memcpy_begin		! BR
-	 alignaddr	%o1, %g0, %o1			! MS	      (Break-after)
+	 sub		%o0, %o1, %o4
+	sub		%g2, 0x40, %g2
+	sub		%g0, %g2, %g2
+	sub		%o2, %g2, %o2
+	andcc		%g2, 0x7, %g1
+	be,pt		%icc, 2f
+	 and		%g2, 0x38, %g2
+
+1:	subcc		%g1, 0x1, %g1
+	EX_LD(LOAD(ldub, %o1 + 0x00, %o3))
+	EX_ST(STORE(stb, %o3, %o1 + %o4))
+	bgu,pt		%XCC, 1b
+	 add		%o1, 0x1, %o1
+
+	add		%o1, %o4, %o0
+
+2:	cmp		%g2, 0x0
+	and		%o1, 0x7, %g1
+	be,pt		%icc, 3f
+	 alignaddr	%o1, %g0, %o1
+
+	EX_LD(LOAD(ldd, %o1, %f4))
+1:	EX_LD(LOAD(ldd, %o1 + 0x8, %f6))
+	add		%o1, 0x8, %o1
+	subcc		%g2, 0x8, %g2
+	faligndata	%f4, %f6, %f0
+	EX_ST(STORE(std, %f0, %o0))
+	be,pn		%icc, 3f
+	 add		%o0, 0x8, %o0
+
+	EX_LD(LOAD(ldd, %o1 + 0x8, %f4))
+	add		%o1, 0x8, %o1
+	subcc		%g2, 0x8, %g2
+	faligndata	%f6, %f4, %f2
+	EX_ST(STORE(std, %f2, %o0))
+	bne,pt		%icc, 1b
+	 add		%o0, 0x8, %o0
+
+3:	LOAD(prefetch, %o1 + 0x000, #one_read)
+	LOAD(prefetch, %o1 + 0x040, #one_read)
+	andn		%o2, (0x40 - 1), %o4
+	LOAD(prefetch, %o1 + 0x080, #one_read)
+	LOAD(prefetch, %o1 + 0x0c0, #one_read)
+	LOAD(prefetch, %o1 + 0x100, #one_read)
+	EX_LD(LOAD(ldd, %o1 + 0x000, %f0))
+	LOAD(prefetch, %o1 + 0x140, #one_read)
+	EX_LD(LOAD(ldd, %o1 + 0x008, %f2))
+	LOAD(prefetch, %o1 + 0x180, #one_read)
+	EX_LD(LOAD(ldd, %o1 + 0x010, %f4))
+	LOAD(prefetch, %o1 + 0x1c0, #one_read)
+	faligndata	%f0, %f2, %f16
+	EX_LD(LOAD(ldd, %o1 + 0x018, %f6))
+	faligndata	%f2, %f4, %f18
+	EX_LD(LOAD(ldd, %o1 + 0x020, %f8))
+	faligndata	%f4, %f6, %f20
+	EX_LD(LOAD(ldd, %o1 + 0x028, %f10))
+	faligndata	%f6, %f8, %f22
+
+	EX_LD(LOAD(ldd, %o1 + 0x030, %f12))
+	faligndata	%f8, %f10, %f24
+	EX_LD(LOAD(ldd, %o1 + 0x038, %f14))
+	faligndata	%f10, %f12, %f26
+	EX_LD(LOAD(ldd, %o1 + 0x040, %f0))
+
+	subcc		%o4, 0x80, %o4
+	add		%o1, 0x40, %o1
+	bgu,pt		%XCC, 1f
+	 srl		%o4, 6, %o3
+	ba,pt		%xcc, 2f
+	 nop
 
 	.align		64
-U3memcpy_begin:
-#ifdef __KERNEL__
-	.globl		U3memcpy_nop_1_6
-U3memcpy_nop_1_6:
-	ldxa		[%g0] ASI_DCU_CONTROL_REG, %g3
-	sethi		%uhi(DCU_PE), %o3
-	sllx		%o3, 32, %o3
-	or		%g3, %o3, %o3
-	stxa		%o3, [%g0] ASI_DCU_CONTROL_REG	! Enable P-cache
-	membar		#Sync
-#endif
-	prefetch	[%o1 + 0x000], #one_read	! MS	Group1
-	prefetch	[%o1 + 0x040], #one_read	! MS	Group2
-	andn		%o2, (0x40 - 1), %o4		! A0
-	prefetch	[%o1 + 0x080], #one_read	! MS	Group3
-	cmp		%o4, 0x140			! A0
-	prefetch	[%o1 + 0x0c0], #one_read	! MS	Group4
-	ldd		[%o1 + 0x000], %f0		! MS	Group5 (%f0 results at G8)
-	bge,a,pt	%icc, 1f			! BR
-
-	 prefetch	[%o1 + 0x100], #one_read	! MS	Group6
-1:	ldd		[%o1 + 0x008], %f2		! AX	       (%f2 results at G9)
-	cmp		%o4, 0x180			! A1
-	bge,a,pt	%icc, 1f			! BR
-	 prefetch	[%o1 + 0x140], #one_read	! MS	Group7
-1:	ldd		[%o1 + 0x010], %f4		! AX	       (%f4 results at G10)
-	cmp		%o4, 0x1c0			! A1
-	bge,a,pt	%icc, 1f			! BR
-
-	 prefetch	[%o1 + 0x180], #one_read	! MS	Group8
-1:	faligndata	%f0, %f2, %f16			! FGA	Group9 (%f16 at G12)
-	ldd		[%o1 + 0x018], %f6		! AX	       (%f6 results at G12)
-	faligndata	%f2, %f4, %f18			! FGA	Group10 (%f18 results at G13)
-	ldd		[%o1 + 0x020], %f8		! MS	        (%f8 results at G13)
-	faligndata	%f4, %f6, %f20			! FGA	Group12	(1-cycle stall,%f20 at G15)
-	ldd		[%o1 + 0x028], %f10		! MS		(%f10 results at G15)
-	faligndata	%f6, %f8, %f22			! FGA	Group13 (%f22 results at G16)
-
-	ldd		[%o1 + 0x030], %f12		! MS		(%f12 results at G16)
-	faligndata	%f8, %f10, %f24			! FGA	Group15 (1-cycle stall,%f24 at G18)
-	ldd		[%o1 + 0x038], %f14		! MS		(%f14 results at G18)
-	faligndata	%f10, %f12, %f26		! FGA	Group16 (%f26 results at G19)
-	ldd		[%o1 + 0x040], %f0		! MS		(%f0 results at G19)
-
-	/* We only use the first loop if len > (7 * 64). */
-	subcc		%o4, 0x1c0, %o4			! A0	Group17
-	bg,pt		%icc, U3memcpy_loop1		! BR
-	 add		%o1, 0x40, %o1			! A1
-
-	add		%o4, 0x140, %o4			! A0	Group18
-	ba,pt		%xcc, U3memcpy_loop2		! BR
-	 srl		%o4, 6, %o3			! A0	Group19
-	nop
-	nop
-	nop
-	nop
-	nop
-
-	nop
-	nop
-
-	/* This loop performs the copy and queues new prefetches.
-	 * We drop into the second loop when len <= (5 * 64).  Note
-	 * that this (5 * 64) factor has been subtracted from len
-	 * already.
-	 */
-U3memcpy_loop1:
-	ldd		[%o1 + 0x008], %f2		! MS	Group2	(%f2 results at G5)
-	faligndata	%f12, %f14, %f28		! FGA		(%f28 results at G5)
-	ldd		[%o1 + 0x010], %f4		! MS	Group3	(%f4 results at G6)
-	faligndata	%f14, %f0, %f30			! FGA	Group4	(1-cycle stall, %f30 at G7)
-	stda		%f16, [%o0] ASI_BLK_P		! MS
-	ldd		[%o1 + 0x018], %f6		! AX		(%f6 results at G7)
-
-	faligndata	%f0, %f2, %f16			! FGA	Group12 (7-cycle stall)
-	ldd		[%o1 + 0x020], %f8		! MS	        (%f8 results at G15)
-	faligndata	%f2, %f4, %f18			! FGA	Group13	(%f18 results at G16)
-	ldd		[%o1 + 0x028], %f10		! MS		(%f10 results at G16)
-	faligndata	%f4, %f6, %f20			! FGA	Group14	(%f20 results at G17)
-	ldd		[%o1 + 0x030], %f12		! MS		(%f12 results at G17)
-	faligndata	%f6, %f8, %f22			! FGA	Group15	(%f22 results at G18)
-	ldd		[%o1 + 0x038], %f14		! MS		(%f14 results at G18)
-
-	faligndata	%f8, %f10, %f24			! FGA	Group16	(%f24 results at G19)
-	ldd		[%o1 + 0x040], %f0		! AX		(%f0 results at G19)
-	prefetch	[%o1 + 0x180], #one_read	! MS
-	faligndata	%f10, %f12, %f26		! FGA	Group17	(%f26 results at G20)
-	subcc		%o4, 0x40, %o4			! A0
-	add		%o1, 0x40, %o1			! A1
-	bg,pt		%xcc, U3memcpy_loop1		! BR
-	 add		%o0, 0x40, %o0			! A0	Group18
-
-U3memcpy_loop2_enter:
-	mov		5, %o3				! A1
-
-	/* This loop performs on the copy, no new prefetches are
-	 * queued.  We do things this way so that we do not perform
-	 * any spurious prefetches past the end of the src buffer.
-	 */
-U3memcpy_loop2:
-	ldd		[%o1 + 0x008], %f2		! MS
-	faligndata	%f12, %f14, %f28		! FGA	Group2
-	ldd		[%o1 + 0x010], %f4		! MS
-	faligndata	%f14, %f0, %f30			! FGA	Group4	(1-cycle stall)
-	stda		%f16, [%o0] ASI_BLK_P		! MS
-	ldd		[%o1 + 0x018], %f6		! AX
-	faligndata	%f0, %f2, %f16			! FGA	Group12 (7-cycle stall)
-
-	ldd		[%o1 + 0x020], %f8		! MS
-	faligndata	%f2, %f4, %f18			! FGA	Group13
-	ldd		[%o1 + 0x028], %f10		! MS
-	faligndata	%f4, %f6, %f20			! FGA	Group14
-	ldd		[%o1 + 0x030], %f12		! MS
-	faligndata	%f6, %f8, %f22			! FGA	Group15
-	ldd		[%o1 + 0x038], %f14		! MS
-	faligndata	%f8, %f10, %f24			! FGA	Group16
-
-	ldd		[%o1 + 0x040], %f0		! AX
-	faligndata	%f10, %f12, %f26		! FGA	Group17
-	subcc		%o3, 0x01, %o3			! A0
-	add		%o1, 0x40, %o1			! A1
-	bg,pt		%xcc, U3memcpy_loop2		! BR
-	 add		%o0, 0x40, %o0			! A0	Group18
+1:
+	EX_LD(LOAD(ldd, %o1 + 0x008, %f2))
+	faligndata	%f12, %f14, %f28
+	EX_LD(LOAD(ldd, %o1 + 0x010, %f4))
+	faligndata	%f14, %f0, %f30
+	EX_ST(STORE_BLK(%f16, %o0))
+	EX_LD(LOAD(ldd, %o1 + 0x018, %f6))
+	faligndata	%f0, %f2, %f16
+	add		%o0, 0x40, %o0
+
+	EX_LD(LOAD(ldd, %o1 + 0x020, %f8))
+	faligndata	%f2, %f4, %f18
+	EX_LD(LOAD(ldd, %o1 + 0x028, %f10))
+	faligndata	%f4, %f6, %f20
+	EX_LD(LOAD(ldd, %o1 + 0x030, %f12))
+	subcc		%o3, 0x01, %o3
+	faligndata	%f6, %f8, %f22
+	EX_LD(LOAD(ldd, %o1 + 0x038, %f14))
+
+	faligndata	%f8, %f10, %f24
+	EX_LD(LOAD(ldd, %o1 + 0x040, %f0))
+	LOAD(prefetch, %o1 + 0x1c0, #one_read)
+	faligndata	%f10, %f12, %f26
+	bg,pt		%XCC, 1b
+	 add		%o1, 0x40, %o1
 
 	/* Finally we copy the last full 64-byte block. */
-U3memcpy_loopfini:
-	ldd		[%o1 + 0x008], %f2		! MS
-	faligndata	%f12, %f14, %f28		! FGA
-	ldd		[%o1 + 0x010], %f4		! MS	Group19
-	faligndata	%f14, %f0, %f30			! FGA
-	stda		%f16, [%o0] ASI_BLK_P		! MS	Group20
-	ldd		[%o1 + 0x018], %f6		! AX
-	faligndata	%f0, %f2, %f16			! FGA	Group11 (7-cycle stall)
-	ldd		[%o1 + 0x020], %f8		! MS
-	faligndata	%f2, %f4, %f18			! FGA	Group12
-	ldd		[%o1 + 0x028], %f10		! MS
-	faligndata	%f4, %f6, %f20			! FGA	Group13
-	ldd		[%o1 + 0x030], %f12		! MS
-	faligndata	%f6, %f8, %f22			! FGA	Group14
-	ldd		[%o1 + 0x038], %f14		! MS
-	faligndata	%f8, %f10, %f24			! FGA	Group15
-	cmp		%g1, 0				! A0
-	be,pt		%icc, 1f			! BR
-	 add		%o0, 0x40, %o0			! A1
-	ldd		[%o1 + 0x040], %f0		! MS
-1:	faligndata	%f10, %f12, %f26		! FGA	Group16
-	faligndata	%f12, %f14, %f28		! FGA	Group17
-	faligndata	%f14, %f0, %f30			! FGA	Group18
-	stda		%f16, [%o0] ASI_BLK_P		! MS
-	add		%o0, 0x40, %o0			! A0
-	add		%o1, 0x40, %o1			! A1
-#ifdef __KERNEL__
-	.globl		U3memcpy_nop_2_3
-U3memcpy_nop_2_3:
-	mov		PRIMARY_CONTEXT, %o3
-	stxa		%g0, [%o3] ASI_DMMU		! Flush P-cache
-	stxa		%g3, [%g0] ASI_DCU_CONTROL_REG	! Disable P-cache
-#endif
-	membar		#Sync				! MS	Group26 (7-cycle stall)
+2:
+	EX_LD(LOAD(ldd, %o1 + 0x008, %f2))
+	faligndata	%f12, %f14, %f28
+	EX_LD(LOAD(ldd, %o1 + 0x010, %f4))
+	faligndata	%f14, %f0, %f30
+	EX_ST(STORE_BLK(%f16, %o0))
+	EX_LD(LOAD(ldd, %o1 + 0x018, %f6))
+	faligndata	%f0, %f2, %f16
+	EX_LD(LOAD(ldd, %o1 + 0x020, %f8))
+	faligndata	%f2, %f4, %f18
+	EX_LD(LOAD(ldd, %o1 + 0x028, %f10))
+	faligndata	%f4, %f6, %f20
+	EX_LD(LOAD(ldd, %o1 + 0x030, %f12))
+	faligndata	%f6, %f8, %f22
+	EX_LD(LOAD(ldd, %o1 + 0x038, %f14))
+	faligndata	%f8, %f10, %f24
+	cmp		%g1, 0
+	be,pt		%XCC, 1f
+	 add		%o0, 0x40, %o0
+	EX_LD(LOAD(ldd, %o1 + 0x040, %f0))
+1:	faligndata	%f10, %f12, %f26
+	faligndata	%f12, %f14, %f28
+	faligndata	%f14, %f0, %f30
+	EX_ST(STORE_BLK(%f16, %o0))
+	add		%o0, 0x40, %o0
+	add		%o1, 0x40, %o1
+	membar		#Sync
 
 	/* Now we copy the (len modulo 64) bytes at the end.
 	 * Note how we borrow the %f0 loaded above.
 	 *
 	 * Also notice how this code is careful not to perform a
-	 * load past the end of the src buffer just like similar
-	 * code found in U3memcpy_toosmall processing.
+	 * load past the end of the src buffer.
 	 */
-U3memcpy_loopend:
-	and		%o2, 0x3f, %o2			! A0	Group
-	andcc		%o2, 0x38, %g2			! A0	Group
-	be,pn		%icc, U3memcpy_endcruft		! BR
-	 subcc		%g2, 0x8, %g2			! A1
-	be,pn		%icc, U3memcpy_endcruft		! BR	Group
-	 cmp		%g1, 0				! A0
-
-	be,a,pt		%icc, 1f			! BR	Group
-	 ldd		[%o1 + 0x00], %f0		! MS
-
-1:	ldd		[%o1 + 0x08], %f2		! MS	Group
-	add		%o1, 0x8, %o1			! A0
-	sub		%o2, 0x8, %o2			! A1
-	subcc		%g2, 0x8, %g2			! A0	Group
-	faligndata	%f0, %f2, %f8			! FGA	Group
-	std		%f8, [%o0 + 0x00]		! MS	(XXX does it stall here? XXX)
-	be,pn		%icc, U3memcpy_endcruft		! BR
-	 add		%o0, 0x8, %o0			! A0
-	ldd		[%o1 + 0x08], %f0		! MS	Group
-	add		%o1, 0x8, %o1			! A0
-	sub		%o2, 0x8, %o2			! A1
-	subcc		%g2, 0x8, %g2			! A0	Group
-	faligndata	%f2, %f0, %f8			! FGA
-	std		%f8, [%o0 + 0x00]		! MS	(XXX does it stall here? XXX)
-	bne,pn		%icc, 1b			! BR
-	 add		%o0, 0x8, %o0			! A0	Group
+	and		%o2, 0x3f, %o2
+	andcc		%o2, 0x38, %g2
+	be,pn		%XCC, 2f
+	 subcc		%g2, 0x8, %g2
+	be,pn		%XCC, 2f
+	 cmp		%g1, 0
+
+	sub		%o2, %g2, %o2
+	be,a,pt		%XCC, 1f
+	 EX_LD(LOAD(ldd, %o1 + 0x00, %f0))
+
+1:	EX_LD(LOAD(ldd, %o1 + 0x08, %f2))
+	add		%o1, 0x8, %o1
+	subcc		%g2, 0x8, %g2
+	faligndata	%f0, %f2, %f8
+	EX_ST(STORE(std, %f8, %o0))
+	be,pn		%XCC, 2f
+	 add		%o0, 0x8, %o0
+	EX_LD(LOAD(ldd, %o1 + 0x08, %f0))
+	add		%o1, 0x8, %o1
+	subcc		%g2, 0x8, %g2
+	faligndata	%f2, %f0, %f8
+	EX_ST(STORE(std, %f8, %o0))
+	bne,pn		%XCC, 1b
+	 add		%o0, 0x8, %o0
 
 	/* If anything is left, we copy it one byte at a time.
 	 * Note that %g1 is (src & 0x3) saved above before the
 	 * alignaddr was performed.
 	 */
-U3memcpy_endcruft:
+2:
 	cmp		%o2, 0
 	add		%o1, %g1, %o1
 	VISExitHalf
-	be,pn		%icc, U3memcpy_short_ret
-	 nop
-	ba,a,pt		%xcc, U3memcpy_short
-
-	/* If we get here, then 32 <= len < (6 * 64) */
-U3memcpy_toosmall:
+	be,pn		%XCC, 85f
+	 sub		%o0, %o1, %o3
 
-#ifdef SMALL_COPY_USES_FPU
-
-	/* Is 'dst' already aligned on an 8-byte boundary? */
-	be,pt		%xcc, 2f			! BR	Group
-
-	/* Compute abs((dst & 7) - 8) into %g2.  This is the number
-	 * of bytes to copy to make 'dst' 8-byte aligned.  We pre-
-	 * subtract this from 'len'.
-	 */
-	 sub		%g2, 0x8, %g2			! A0
-	sub		%g0, %g2, %g2			! A0	Group (reg-dep)
-	sub		%o2, %g2, %o2			! A0	Group (reg-dep)
-
-	/* Copy %g2 bytes from src to dst, one byte at a time. */
-1:	ldub		[%o1 + 0x00], %o3		! MS	(Group) (%o3 in 3 cycles)
-	add		%o1, 0x1, %o1			! A1
-	add		%o0, 0x1, %o0			! A0	Group
-	subcc		%g2, 0x1, %g2			! A1
-
-	bg,pt		%icc, 1b			! BR	Group
-	 stb		%o3, [%o0 + -1]			! MS	Group
+	andcc		%g1, 0x7, %g0
+	bne,pn		%icc, 90f
+	 andcc		%o2, 0x8, %g0
+	be,pt		%icc, 1f
+	 nop
+	EX_LD(LOAD(ldx, %o1, %o5))
+	EX_ST(STORE(stx, %o5, %o1 + %o3))
+	add		%o1, 0x8, %o1
 
-2:	VISEntryHalf					! MS+MS
+1:	andcc		%o2, 0x4, %g0
+	be,pt		%icc, 1f
+	 nop
+	EX_LD(LOAD(lduw, %o1, %o5))
+	EX_ST(STORE(stw, %o5, %o1 + %o3))
+	add		%o1, 0x4, %o1
 
-	/* Compute (len - (len % 8)) into %g2.  This is guarenteed
-	 * to be nonzero.
-	 */
-	andn		%o2, 0x7, %g2			! A0	Group
+1:	andcc		%o2, 0x2, %g0
+	be,pt		%icc, 1f
+	 nop
+	EX_LD(LOAD(lduh, %o1, %o5))
+	EX_ST(STORE(sth, %o5, %o1 + %o3))
+	add		%o1, 0x2, %o1
 
-	/* You may read this and believe that it allows reading
-	 * one 8-byte longword past the end of src.  It actually
-	 * does not, as %g2 is subtracted as loads are done from
-	 * src, so we always stop before running off the end.
-	 * Also, we are guarenteed to have at least 0x10 bytes
-	 * to move here.
-	 */
-	sub		%g2, 0x8, %g2			! A0	Group (reg-dep)
-	alignaddr	%o1, %g0, %g1			! MS	      (Break-after)
-	ldd		[%g1 + 0x00], %f0		! MS	Group (1-cycle stall)
-	add		%g1, 0x8, %g1			! A0
-
-1:	ldd		[%g1 + 0x00], %f2		! MS	Group
-	add		%g1, 0x8, %g1			! A0
-	sub		%o2, 0x8, %o2			! A1
-	subcc		%g2, 0x8, %g2			! A0	Group
-
-	faligndata	%f0, %f2, %f8			! FGA	Group (1-cycle stall)
-	std		%f8, [%o0 + 0x00]		! MS	Group (2-cycle stall)
-	add		%o1, 0x8, %o1			! A0
-	be,pn		%icc, 2f			! BR
-
-	 add		%o0, 0x8, %o0			! A1
-	ldd		[%g1 + 0x00], %f0		! MS	Group
-	add		%g1, 0x8, %g1			! A0
-	sub		%o2, 0x8, %o2			! A1
-
-	subcc		%g2, 0x8, %g2			! A0	Group
-	faligndata	%f2, %f0, %f8			! FGA	Group (1-cycle stall)
-	std		%f8, [%o0 + 0x00]		! MS	Group (2-cycle stall)
-	add		%o1, 0x8, %o1			! A0
-
-	bne,pn		%icc, 1b			! BR
-	 add		%o0, 0x8, %o0			! A1
-
-	/* Nothing left to copy? */
-2:	cmp		%o2, 0				! A0	Group
-	VISExitHalf					! A0+MS
-	be,pn		%icc, U3memcpy_short_ret	! BR	Group
-	 nop						! A0
-	ba,a,pt		%xcc, U3memcpy_short		! BR	Group
-
-#else /* !(SMALL_COPY_USES_FPU) */
-
-	xor		%o1, %o0, %g2
-	andcc		%g2, 0x7, %g0
-	bne,pn		%icc, U3memcpy_short
-	 andcc		%o1, 0x7, %g2
+1:	andcc		%o2, 0x1, %g0
+	be,pt		%icc, 85f
+	 nop
+	EX_LD(LOAD(ldub, %o1, %o5))
+	ba,pt		%xcc, 85f
+	 EX_ST(STORE(stb, %o5, %o1 + %o3))
 
-	be,pt		%xcc, 2f
-	 sub		%g2, 0x8, %g2
-	sub		%g0, %g2, %g2
-	sub		%o2, %g2, %o2
+	.align		64
+70: /* 16 < len <= 64 */
+	bne,pn		%XCC, 75f
+	 sub		%o0, %o1, %o3
+
+72:
+	andn		%o2, 0xf, %o4
+	and		%o2, 0xf, %o2
+1:	subcc		%o4, 0x10, %o4
+	EX_LD(LOAD(ldx, %o1 + 0x00, %o5))
+	EX_LD(LOAD(ldx, %o1 + 0x08, %g1))
+	EX_ST(STORE(stx, %o5, %o1 + %o3))
+	add		%o1, 0x8, %o1
+	EX_ST(STORE(stx, %g1, %o1 + %o3))
+	bgu,pt		%XCC, 1b
+	 add		%o1, 0x8, %o1
+73:	andcc		%o2, 0x8, %g0
+	be,pt		%XCC, 1f
+	 nop
+	sub		%o2, 0x8, %o2
+	EX_LD(LOAD(ldx, %o1, %o5))
+	EX_ST(STORE(stx, %o5, %o1 + %o3))
+	add		%o1, 0x8, %o1
+1:	andcc		%o2, 0x4, %g0
+	be,pt		%XCC, 1f
+	 nop
+	sub		%o2, 0x4, %o2
+	EX_LD(LOAD(lduw, %o1, %o5))
+	EX_ST(STORE(stw, %o5, %o1 + %o3))
+	add		%o1, 0x4, %o1
+1:	cmp		%o2, 0
+	be,pt		%XCC, 85f
+	 nop
+	ba,pt		%xcc, 90f
+	 nop
 
-1:	ldub		[%o1 + 0x00], %o3
-	add		%o1, 0x1, %o1
-	add		%o0, 0x1, %o0
-	subcc		%g2, 0x1, %g2
-	bg,pt		%icc, 1b
-	 stb		%o3, [%o0 + -1]
+75:
+	andcc		%o0, 0x7, %g1
+	sub		%g1, 0x8, %g1
+	be,pn		%icc, 2f
+	 sub		%g0, %g1, %g1
+	sub		%o2, %g1, %o2
+
+1:	subcc		%g1, 1, %g1
+	EX_LD(LOAD(ldub, %o1, %o5))
+	EX_ST(STORE(stb, %o5, %o1 + %o3))
+	bgu,pt		%icc, 1b
+	 add		%o1, 1, %o1
+
+2:	add		%o1, %o3, %o0
+	andcc		%o1, 0x7, %g1
+	bne,pt		%icc, 8f
+	 sll		%g1, 3, %g1
 
-2:	andn		%o2, 0x7, %g2
-	sub		%o2, %g2, %o2
+	cmp		%o2, 16
+	bgeu,pt		%icc, 72b
+	 nop
+	ba,a,pt		%xcc, 73b
 
-3:	ldx		[%o1 + 0x00], %o3
+8:	mov		64, %o3
+	andn		%o1, 0x7, %o1
+	EX_LD(LOAD(ldx, %o1, %g2))
+	sub		%o3, %g1, %o3
+	andn		%o2, 0x7, %o4
+	sllx		%g2, %g1, %g2
+1:	EX_LD(LOAD(ldx, %o1 + 0x8, %g3))
+	subcc		%o4, 0x8, %o4
 	add		%o1, 0x8, %o1
+	srlx		%g3, %o3, %o5
+	or		%o5, %g2, %o5
+	EX_ST(STORE(stx, %o5, %o0))
 	add		%o0, 0x8, %o0
-	subcc		%g2, 0x8, %g2
-	bg,pt		%icc, 3b
-	 stx		%o3, [%o0 + -8]
+	bgu,pt		%icc, 1b
+	 sllx		%g3, %g1, %g2
 
-	cmp		%o2, 0
-	bne,pn		%icc, U3memcpy_short
-	 nop
-	ba,a,pt		%xcc, U3memcpy_short_ret
+	srl		%g1, 3, %g1
+	andcc		%o2, 0x7, %o2
+	be,pn		%icc, 85f
+	 add		%o1, %g1, %o1
+	ba,pt		%xcc, 90f
+	 sub		%o0, %o1, %o3
+
+	.align		64
+80: /* 0 < len <= 16 */
+	andcc		%o3, 0x3, %g0
+	bne,pn		%XCC, 90f
+	 sub		%o0, %o1, %o3
+
+1:
+	subcc		%o2, 4, %o2
+	EX_LD(LOAD(lduw, %o1, %g1))
+	EX_ST(STORE(stw, %g1, %o1 + %o3))
+	bgu,pt		%XCC, 1b
+	 add		%o1, 4, %o1
 
-#endif /* !(SMALL_COPY_USES_FPU) */
+85:	retl
+	 mov		EX_RETVAL(%g5), %o0
+
+	.align		32
+90:
+	subcc		%o2, 1, %o2
+	EX_LD(LOAD(ldub, %o1, %g1))
+	EX_ST(STORE(stb, %g1, %o1 + %o3))
+	bgu,pt		%XCC, 90b
+	 add		%o1, 1, %o1
+	retl
+	 mov		EX_RETVAL(%g5), %o0
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/sparc64/lib/U3patch.S linux-2.4.28-pre3/arch/sparc64/lib/U3patch.S
--- linux-2.4.27/arch/sparc64/lib/U3patch.S	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.28-pre3/arch/sparc64/lib/U3patch.S	2004-09-10 19:36:16.000000000 +0000
@@ -0,0 +1,30 @@
+/* U3patch.S: Patch Ultra-I routines with Ultra-III variant.
+ *
+ * Copyright (C) 2004 David S. Miller <davem@redhat.com>
+ */
+
+#define BRANCH_ALWAYS	0x10680000
+#define NOP		0x01000000
+#define ULTRA3_DO_PATCH(OLD, NEW)	\
+	sethi	%hi(NEW), %g1; \
+	or	%g1, %lo(NEW), %g1; \
+	sethi	%hi(OLD), %g2; \
+	or	%g2, %lo(OLD), %g2; \
+	sub	%g1, %g2, %g1; \
+	sethi	%hi(BRANCH_ALWAYS), %g3; \
+	srl	%g1, 2, %g1; \
+	or	%g3, %lo(BRANCH_ALWAYS), %g3; \
+	or	%g3, %g1, %g3; \
+	stw	%g3, [%g2]; \
+	sethi	%hi(NOP), %g3; \
+	or	%g3, %lo(NOP), %g3; \
+	stw	%g3, [%g2 + 0x4]; \
+	flush	%g2;
+
+	.globl	cheetah_patch_copyops
+cheetah_patch_copyops:
+	ULTRA3_DO_PATCH(memcpy, U3memcpy)
+	ULTRA3_DO_PATCH(___copy_from_user, U3copy_from_user)
+	ULTRA3_DO_PATCH(___copy_to_user, U3copy_to_user)
+	retl
+	 nop
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/sparc64/lib/VIScopy.S linux-2.4.28-pre3/arch/sparc64/lib/VIScopy.S
--- linux-2.4.27/arch/sparc64/lib/VIScopy.S	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.28-pre3/arch/sparc64/lib/VIScopy.S	1970-01-01 00:00:00.000000000 +0000
@@ -1,1187 +0,0 @@
-/* $Id: VIScopy.S,v 1.26 2001/09/27 04:36:24 kanoj Exp $
- * VIScopy.S: High speed copy operations utilizing the UltraSparc
- *            Visual Instruction Set.
- *
- * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
- * Copyright (C) 1996, 1997, 1998, 1999 Jakub Jelinek (jj@ultra.linux.cz)
- */
-
-#include "VIS.h"
-
-	/* VIS code can be used for numerous copy/set operation variants.
-	 * It can be made to work in the kernel, one single instance,
-	 * for all of memcpy, copy_to_user, and copy_from_user by setting
-	 * the ASI src/dest globals correctly.  Furthermore it can
-	 * be used for kernel-->kernel page copies as well, a hook label
-	 * is put in here just for this purpose.
-	 *
-	 * For userland, compiling this without __KERNEL__ defined makes
-	 * it work just fine as a generic libc bcopy and memcpy.
-	 * If for userland it is compiled with a 32bit gcc (but you need
-	 * -Wa,-Av9a for as), the code will just rely on lower 32bits of
-	 * IEU registers, if you compile it with 64bit gcc (ie. define
-	 * __sparc_v9__), the code will use full 64bit.
-	 */
-	 
-#ifdef __KERNEL__
-
-#include <asm/visasm.h>
-#include <asm/asm_offsets.h>
-
-#define FPU_CLEAN_RETL								\
-	ldub		[%g6 + AOFF_task_thread + AOFF_thread_current_ds], %o1;	\
-	VISExit									\
-	clr		%o0;							\
-	retl;									\
-	 wr		%o1, %g0, %asi;
-#define FPU_RETL								\
-	ldub		[%g6 + AOFF_task_thread + AOFF_thread_current_ds], %o1;	\
-	VISExit									\
-	clr		%o0;							\
-	retl;									\
-	 wr		%o1, %g0, %asi;
-#define NORMAL_RETL								\
-	ldub		[%g6 + AOFF_task_thread + AOFF_thread_current_ds], %o1;	\
-	clr		%o0;							\
-	retl;									\
-	 wr		%o1, %g0, %asi;
-#define EX(x,y,a,b) 				\
-98: 	x,y;					\
-	.section .fixup;			\
-	.align	4;				\
-99:	ba	VIScopyfixup_ret;		\
-	 a, b, %o1;				\
-	.section __ex_table;			\
-	.align	4;				\
-	.word	98b, 99b;			\
-	.text;					\
-	.align	4;
-#define EX2(x,y,c,d,e,a,b) 			\
-98: 	x,y;					\
-	.section .fixup;			\
-	.align	4;				\
-99:	c, d, e;				\
-	ba	VIScopyfixup_ret;		\
-	 a, b, %o1;				\
-	.section __ex_table;			\
-	.align	4;				\
-	.word	98b, 99b;			\
-	.text;					\
-	.align	4;
-#define EXO2(x,y) 				\
-98: 	x,y;					\
-	.section __ex_table;			\
-	.align	4;				\
-	.word	98b, VIScopyfixup_reto2;	\
-	.text;					\
-	.align	4;
-#define EXVISN(x,y,n) 				\
-98: 	x,y;					\
-	.section __ex_table;			\
-	.align	4;				\
-	.word	98b, VIScopyfixup_vis##n;	\
-	.text;					\
-	.align	4;
-#define EXT(start,end,handler) 			\
-	.section __ex_table;			\
-	.align	4;				\
-	.word	start, 0, end, handler;		\
-	.text;					\
-	.align	4;
-#else
-#ifdef REGS_64BIT
-#define FPU_CLEAN_RETL				\
-	retl;					\
-	 mov	%g6, %o0;
-#define FPU_RETL				\
-	retl;					\
-	 mov	%g6, %o0;
-#else
-#define FPU_CLEAN_RETL				\
-	wr	%g0, FPRS_FEF, %fprs;		\
-	retl;					\
-	 mov	%g6, %o0;
-#define FPU_RETL				\
-	wr	%g0, FPRS_FEF, %fprs;		\
-	retl;					\
-	 mov	%g6, %o0;
-#endif
-#define NORMAL_RETL	\
-	retl;		\
-	 mov	%g6, %o0;
-#define EX(x,y,a,b)		x,y
-#define EX2(x,y,c,d,e,a,b)	x,y
-#define EXO2(x,y)		x,y
-#define EXVISN(x,y,n)		x,y
-#define EXT(a,b,c)
-#endif
-#define EXVIS(x,y) EXVISN(x,y,0)
-#define EXVIS1(x,y) EXVISN(x,y,1)
-#define EXVIS2(x,y) EXVISN(x,y,2)
-#define EXVIS3(x,y) EXVISN(x,y,3)
-#define EXVIS4(x,y) EXVISN(x,y,4)
-
-#define FREG_FROB(f1, f2, f3, f4, f5, f6, f7, f8, f9)		\
-	faligndata		%f1, %f2, %f48;			\
-	faligndata		%f2, %f3, %f50;			\
-	faligndata		%f3, %f4, %f52;			\
-	faligndata		%f4, %f5, %f54;			\
-	faligndata		%f5, %f6, %f56;			\
-	faligndata		%f6, %f7, %f58;			\
-	faligndata		%f7, %f8, %f60;			\
-	faligndata		%f8, %f9, %f62;
-
-#define MAIN_LOOP_CHUNK(src, dest, fdest, fsrc, len, jmptgt)	\
-	EXVIS(LDBLK		[%src] ASIBLK, %fdest);		\
-	ASI_SETDST_BLK						\
-	EXVIS(STBLK		%fsrc, [%dest] ASIBLK);		\
-	add			%src, 0x40, %src;		\
-	subcc			%len, 0x40, %len;		\
-	be,pn			%xcc, jmptgt;			\
-	 add			%dest, 0x40, %dest;		\
-	ASI_SETSRC_BLK
-
-#define LOOP_CHUNK1(src, dest, len, branch_dest)		\
-	MAIN_LOOP_CHUNK(src, dest, f0,  f48, len, branch_dest)
-#define LOOP_CHUNK2(src, dest, len, branch_dest)		\
-	MAIN_LOOP_CHUNK(src, dest, f16, f48, len, branch_dest)
-#define LOOP_CHUNK3(src, dest, len, branch_dest)		\
-	MAIN_LOOP_CHUNK(src, dest, f32, f48, len, branch_dest)
-
-#define STORE_SYNC(dest, fsrc)					\
-	EXVIS(STBLK		%fsrc, [%dest] ASIBLK);		\
-	add			%dest, 0x40, %dest;
-
-#ifdef __KERNEL__
-#define STORE_JUMP(dest, fsrc, target)				\
-	srl			asi_dest, 3, %g5;		\
-	EXVIS2(STBLK		%fsrc, [%dest] ASIBLK);		\
-	xor		       asi_dest, ASI_BLK_XOR1, asi_dest;\
-	add			%dest, 0x40, %dest;		\
-	xor			asi_dest, %g5, asi_dest;	\
-	ba,pt			%xcc, target;
-#else
-#define STORE_JUMP(dest, fsrc, target)				\
-	EXVIS2(STBLK		%fsrc, [%dest] ASIBLK);		\
-	add			%dest, 0x40, %dest;		\
-	ba,pt			%xcc, target;
-#endif
-
-#ifndef __KERNEL__
-#define VISLOOP_PAD nop; nop; nop; nop; \
-		    nop; nop; nop; nop; \
-		    nop; nop; nop; nop; \
-		    nop; nop; nop;
-#else
-#define VISLOOP_PAD
-#endif
-
-#define FINISH_VISCHUNK(dest, f0, f1, left)			\
-	ASI_SETDST_NOBLK					\
-	subcc			%left, 8, %left;		\
-	bl,pn			%xcc, vis_out;			\
-	 faligndata		%f0, %f1, %f48;			\
-	EXVIS3(STDF		%f48, [%dest] ASINORMAL);	\
-	add			%dest, 8, %dest;
-
-#define UNEVEN_VISCHUNK_LAST(dest, f0, f1, left)		\
-	subcc			%left, 8, %left;		\
-	bl,pn			%xcc, vis_out;			\
-	 fsrc1			%f0, %f1;
-#define UNEVEN_VISCHUNK(dest, f0, f1, left)			\
-	UNEVEN_VISCHUNK_LAST(dest, f0, f1, left)		\
-	ba,a,pt			%xcc, vis_out_slk;
-
-	/* Macros for non-VIS memcpy code. */
-#ifdef REGS_64BIT
-
-#define MOVE_BIGCHUNK(src, dst, offset, t0, t1, t2, t3)			\
-	ASI_SETSRC_NOBLK						\
-	LDX			[%src + offset + 0x00] ASINORMAL, %t0; 	\
-	LDX			[%src + offset + 0x08] ASINORMAL, %t1; 	\
-	LDX			[%src + offset + 0x10] ASINORMAL, %t2; 	\
-	LDX			[%src + offset + 0x18] ASINORMAL, %t3; 	\
-	ASI_SETDST_NOBLK						\
-	STW			%t0, [%dst + offset + 0x04] ASINORMAL; 	\
-	srlx			%t0, 32, %t0;				\
-	STW			%t0, [%dst + offset + 0x00] ASINORMAL; 	\
-	STW			%t1, [%dst + offset + 0x0c] ASINORMAL; 	\
-	srlx			%t1, 32, %t1;				\
-	STW			%t1, [%dst + offset + 0x08] ASINORMAL; 	\
-	STW			%t2, [%dst + offset + 0x14] ASINORMAL; 	\
-	srlx			%t2, 32, %t2;				\
-	STW			%t2, [%dst + offset + 0x10] ASINORMAL; 	\
-	STW			%t3, [%dst + offset + 0x1c] ASINORMAL;	\
-	srlx			%t3, 32, %t3;				\
-	STW			%t3, [%dst + offset + 0x18] ASINORMAL;
-
-#define MOVE_BIGALIGNCHUNK(src, dst, offset, t0, t1, t2, t3)		\
-	ASI_SETSRC_NOBLK						\
-	LDX			[%src + offset + 0x00] ASINORMAL, %t0; 	\
-	LDX			[%src + offset + 0x08] ASINORMAL, %t1; 	\
-	LDX			[%src + offset + 0x10] ASINORMAL, %t2; 	\
-	LDX			[%src + offset + 0x18] ASINORMAL, %t3; 	\
-	ASI_SETDST_NOBLK						\
-	STX			%t0, [%dst + offset + 0x00] ASINORMAL; 	\
-	STX			%t1, [%dst + offset + 0x08] ASINORMAL; 	\
-	STX			%t2, [%dst + offset + 0x10] ASINORMAL; 	\
-	STX			%t3, [%dst + offset + 0x18] ASINORMAL; 	\
-	ASI_SETSRC_NOBLK						\
-	LDX			[%src + offset + 0x20] ASINORMAL, %t0; 	\
-	LDX			[%src + offset + 0x28] ASINORMAL, %t1; 	\
-	LDX			[%src + offset + 0x30] ASINORMAL, %t2; 	\
-	LDX			[%src + offset + 0x38] ASINORMAL, %t3; 	\
-	ASI_SETDST_NOBLK						\
-	STX			%t0, [%dst + offset + 0x20] ASINORMAL; 	\
-	STX			%t1, [%dst + offset + 0x28] ASINORMAL; 	\
-	STX			%t2, [%dst + offset + 0x30] ASINORMAL; 	\
-	STX			%t3, [%dst + offset + 0x38] ASINORMAL;
-
-#define MOVE_LASTCHUNK(src, dst, offset, t0, t1, t2, t3)		\
-	ASI_SETSRC_NOBLK						\
-	LDX			[%src - offset - 0x10] ASINORMAL, %t0;	\
-	LDX			[%src - offset - 0x08] ASINORMAL, %t1; 	\
-	ASI_SETDST_NOBLK						\
-	STW			%t0, [%dst - offset - 0x0c] ASINORMAL; 	\
-	srlx			%t0, 32, %t2;				\
-	STW			%t2, [%dst - offset - 0x10] ASINORMAL; 	\
-	STW			%t1, [%dst - offset - 0x04] ASINORMAL; 	\
-	srlx			%t1, 32, %t3;				\
-	STW			%t3, [%dst - offset - 0x08] ASINORMAL;
-
-#define MOVE_LASTALIGNCHUNK(src, dst, offset, t0, t1)			\
-	ASI_SETSRC_NOBLK						\
-	LDX			[%src - offset - 0x10] ASINORMAL, %t0; 	\
-	LDX			[%src - offset - 0x08] ASINORMAL, %t1; 	\
-	ASI_SETDST_NOBLK						\
-	STX			%t0, [%dst - offset - 0x10] ASINORMAL; 	\
-	STX			%t1, [%dst - offset - 0x08] ASINORMAL;
-
-#else /* !REGS_64BIT */
-
-#define MOVE_BIGCHUNK(src, dst, offset, t0, t1, t2, t3)			\
-	lduw			[%src + offset + 0x00], %t0; 		\
-	lduw			[%src + offset + 0x04], %t1; 		\
-	lduw			[%src + offset + 0x08], %t2; 		\
-	lduw			[%src + offset + 0x0c], %t3; 		\
-	stw			%t0, [%dst + offset + 0x00]; 		\
-	stw			%t1, [%dst + offset + 0x04]; 		\
-	stw			%t2, [%dst + offset + 0x08]; 		\
-	stw			%t3, [%dst + offset + 0x0c]; 		\
-	lduw			[%src + offset + 0x10], %t0; 		\
-	lduw			[%src + offset + 0x14], %t1; 		\
-	lduw			[%src + offset + 0x18], %t2; 		\
-	lduw			[%src + offset + 0x1c], %t3; 		\
-	stw			%t0, [%dst + offset + 0x10]; 		\
-	stw			%t1, [%dst + offset + 0x14]; 		\
-	stw			%t2, [%dst + offset + 0x18]; 		\
-	stw			%t3, [%dst + offset + 0x1c];
-
-#define MOVE_LASTCHUNK(src, dst, offset, t0, t1, t2, t3)		\
-	lduw			[%src - offset - 0x10], %t0; 		\
-	lduw			[%src - offset - 0x0c], %t1; 		\
-	lduw			[%src - offset - 0x08], %t2; 		\
-	lduw			[%src - offset - 0x04], %t3; 		\
-	stw			%t0, [%dst - offset - 0x10]; 		\
-	stw			%t1, [%dst - offset - 0x0c]; 		\
-	stw			%t2, [%dst - offset - 0x08]; 		\
-	stw			%t3, [%dst - offset - 0x04];
-
-#endif /* !REGS_64BIT */
-
-#ifdef __KERNEL__
-		.section	__ex_table,#alloc
-		.section	.fixup,#alloc,#execinstr
-#endif
-
-		.text
-		.align			32
-		.globl			memcpy
-		.type			memcpy,@function
-
-		.globl			bcopy
-		.type			bcopy,@function
-
-#ifdef __KERNEL__
-		.globl			__memcpy_begin
-__memcpy_begin:
-
-		.globl			__memcpy
-		.type			__memcpy,@function
-
-memcpy_private:
-__memcpy:
-memcpy:		mov		ASI_P, asi_src			! IEU0	Group
-		brnz,pt		%o2, __memcpy_entry		! CTI
-		 mov		ASI_P, asi_dest			! IEU1
-		retl
-		 clr		%o0
-
-		.align			32
-		.globl			__copy_from_user
-		.type			__copy_from_user,@function
-__copy_from_user:rd		%asi, asi_src			! IEU0	Group
-		brnz,pt		%o2, __memcpy_entry		! CTI
-		 mov		ASI_P, asi_dest			! IEU1
-
-		.globl			__copy_to_user
-		.type			__copy_to_user,@function
-__copy_to_user:	mov		ASI_P, asi_src			! IEU0	Group
-		brnz,pt		%o2, __memcpy_entry		! CTI
-		 rd		%asi, asi_dest			! IEU1
-		retl						! CTI	Group
-		 clr		%o0				! IEU0	Group
-
-		.globl			__copy_in_user
-		.type			__copy_in_user,@function
-__copy_in_user:	rd		%asi, asi_src			! IEU0	Group
-		brnz,pt		%o2, __memcpy_entry		! CTI
-		 mov		asi_src, asi_dest		! IEU1
-		retl						! CTI	Group
-		 clr		%o0				! IEU0	Group
-#endif
-
-bcopy:		or		%o0, 0, %g3			! IEU0	Group
-		addcc		%o1, 0, %o0			! IEU1
-		brgez,pt	%o2, memcpy_private		! CTI
-		 or		%g3, 0, %o1			! IEU0	Group
-		retl						! CTI	Group brk forced
-		 clr		%o0				! IEU0
-
-
-#ifdef __KERNEL__
-#define BRANCH_ALWAYS	0x10680000
-#define NOP		0x01000000
-#define ULTRA3_DO_PATCH(OLD, NEW)	\
-	sethi	%hi(NEW), %g1; \
-	or	%g1, %lo(NEW), %g1; \
-	sethi	%hi(OLD), %g2; \
-	or	%g2, %lo(OLD), %g2; \
-	sub	%g1, %g2, %g1; \
-	sethi	%hi(BRANCH_ALWAYS), %g3; \
-	srl	%g1, 2, %g1; \
-	or	%g3, %lo(BRANCH_ALWAYS), %g3; \
-	or	%g3, %g1, %g3; \
-	stw	%g3, [%g2]; \
-	sethi	%hi(NOP), %g3; \
-	or	%g3, %lo(NOP), %g3; \
-	stw	%g3, [%g2 + 0x4]; \
-	flush	%g2;
-#define ULTRA3_PCACHE_DO_NOP(symbol)	\
-	sethi	%hi(symbol##_nop_1_6), %g1; \
-	or	%g1, %lo(symbol##_nop_1_6), %g1; \
-	sethi	%hi(NOP), %g2; \
-	stw	%g2, [%g1 + 0x00]; \
-	stw	%g2, [%g1 + 0x04]; \
-	flush	%g1 + 0x00; \
-	stw	%g2, [%g1 + 0x08]; \
-	stw	%g2, [%g1 + 0x0c]; \
-	flush	%g1 + 0x08; \
-	stw	%g2, [%g1 + 0x10]; \
-	stw	%g2, [%g1 + 0x04]; \
-	flush	%g1 + 0x10; \
-	sethi	%hi(symbol##_nop_2_3), %g1; \
-	or	%g1, %lo(symbol##_nop_2_3), %g1; \
-	stw	%g2, [%g1 + 0x00]; \
-	stw	%g2, [%g1 + 0x04]; \
-	flush	%g1 + 0x00; \
-	stw	%g2, [%g1 + 0x08]; \
-	flush	%g1 + 0x08;
-
-#include <asm/dcu.h>
-
-	.globl	cheetah_patch_copyops
-cheetah_patch_copyops:
-	ULTRA3_DO_PATCH(memcpy, U3memcpy)
-	ULTRA3_DO_PATCH(__copy_from_user, U3copy_from_user)
-	ULTRA3_DO_PATCH(__copy_to_user, U3copy_to_user)
-	ULTRA3_DO_PATCH(__copy_in_user, U3copy_in_user)
-#if 0 /* Causes data corruption, nop out the optimization
-       * for now -DaveM
-       */
-	ldxa			[%g0] ASI_DCU_CONTROL_REG, %g3
-	sethi			%uhi(DCU_PE), %o3
-	sllx			%o3, 32, %o3
-	andcc			%g3, %o3, %g0
-	be,pn			%xcc, pcache_disabled
-	 nop
-#endif
-	ULTRA3_PCACHE_DO_NOP(U3memcpy)
-	ULTRA3_PCACHE_DO_NOP(U3copy_from_user)
-	ULTRA3_PCACHE_DO_NOP(U3copy_to_user)
-	ULTRA3_PCACHE_DO_NOP(cheetah_copy_user_page)
-#if 0
-pcache_disabled:
-#endif
-	retl
-	 nop
-#undef BRANCH_ALWAYS
-#undef NOP
-#undef ULTRA3_DO_PATCH
-#endif /* __KERNEL__ */
-
-	.align			32
-#ifdef __KERNEL__
-	andcc			%o0, 7, %g2			! IEU1	Group
-#endif
-VIS_enter:
-	be,pt			%xcc, dest_is_8byte_aligned	! CTI
-#ifdef __KERNEL__
-	 nop							! IEU0	Group
-#else
-	 andcc			%o0, 0x38, %g5			! IEU1	Group
-#endif
-do_dest_8byte_align:
-	mov			8, %g1				! IEU0
-	sub			%g1, %g2, %g2			! IEU0	Group
-	andcc			%o0, 1, %g0			! IEU1
-	be,pt			%icc, 2f			! CTI
-	 sub			%o2, %g2, %o2			! IEU0	Group
-1:	ASI_SETSRC_NOBLK					! LSU	Group
-	EX(LDUB			[%o1] ASINORMAL, %o5, 
-				add %o2, %g2)			! Load	Group
-	add			%o1, 1, %o1			! IEU0
-	add			%o0, 1, %o0			! IEU1
-	ASI_SETDST_NOBLK					! LSU	Group
-	subcc			%g2, 1, %g2			! IEU1	Group
-	be,pn			%xcc, 3f			! CTI
-	 EX2(STB		%o5, [%o0 - 1] ASINORMAL,
-				add %g2, 1, %g2,
-				add %o2, %g2)			! Store
-2:	ASI_SETSRC_NOBLK					! LSU	Group
-	EX(LDUB			[%o1] ASINORMAL, %o5, 
-				add %o2, %g2)			! Load	Group
-	add			%o0, 2, %o0			! IEU0
-	EX2(LDUB		[%o1 + 1] ASINORMAL, %g3,
-				sub %o0, 2, %o0,
-				add %o2, %g2)			! Load	Group
-	ASI_SETDST_NOBLK					! LSU	Group
-	subcc			%g2, 2, %g2			! IEU1	Group
-	EX2(STB			%o5, [%o0 - 2] ASINORMAL,
-				add %g2, 2, %g2,
-				add %o2, %g2)			! Store
-	add			%o1, 2, %o1			! IEU0
-	bne,pt			%xcc, 2b			! CTI	Group
-	 EX2(STB		%g3, [%o0 - 1] ASINORMAL,
-				add %g2, 1, %g2,
-				add %o2, %g2)			! Store
-#ifdef __KERNEL__
-3:
-dest_is_8byte_aligned:
-	VISEntry
-	andcc			%o0, 0x38, %g5			! IEU1	Group
-#else
-3:	andcc			%o0, 0x38, %g5			! IEU1	Group
-dest_is_8byte_aligned:
-#endif
-	be,pt			%icc, dest_is_64byte_aligned	! CTI
-	 mov			64, %g1				! IEU0
-	fmovd			%f0, %f2			! FPU
-	sub			%g1, %g5, %g5			! IEU0	Group
-	ASI_SETSRC_NOBLK					! LSU	Group
-	alignaddr		%o1, %g0, %g1			! GRU	Group
-	EXO2(LDDF		[%g1] ASINORMAL, %f4)		! Load	Group
-	sub			%o2, %g5, %o2			! IEU0
-1:	EX(LDDF			[%g1 + 0x8] ASINORMAL, %f6,
-				add %o2, %g5)			! Load	Group
-	add			%g1, 0x8, %g1			! IEU0	Group
-	subcc			%g5, 8, %g5			! IEU1
-	ASI_SETDST_NOBLK					! LSU	Group
-	faligndata		%f4, %f6, %f0			! GRU	Group
-	EX2(STDF		%f0, [%o0] ASINORMAL,
-				add %g5, 8, %g5,
-				add %o2, %g5)			! Store
-	add			%o1, 8, %o1			! IEU0	Group
-	be,pn			%xcc, dest_is_64byte_aligned	! CTI
-	 add			%o0, 8, %o0			! IEU1
-	ASI_SETSRC_NOBLK					! LSU	Group
-	EX(LDDF			[%g1 + 0x8] ASINORMAL, %f4,
-				add %o2, %g5)			! Load	Group
-	add			%g1, 8, %g1			! IEU0
-	subcc			%g5, 8, %g5			! IEU1
-	ASI_SETDST_NOBLK					! LSU	Group
-	faligndata		%f6, %f4, %f0			! GRU	Group
-	EX2(STDF		%f0, [%o0] ASINORMAL,
-				add %g5, 8, %g5,
-				add %o2, %g5)			! Store
-	add			%o1, 8, %o1			! IEU0
-	ASI_SETSRC_NOBLK					! LSU	Group
-	bne,pt			%xcc, 1b			! CTI	Group
-	 add			%o0, 8, %o0			! IEU0
-dest_is_64byte_aligned:
-	membar		  #LoadStore | #StoreStore | #StoreLoad	! LSU	Group
-#ifndef __KERNEL__
-	wr			%g0, ASI_BLK_P, %asi		! LSU	Group
-#endif
-	subcc			%o2, 0x40, %g7			! IEU1	Group
-	mov			%o1, %g1			! IEU0
-	andncc			%g7, (0x40 - 1), %g7		! IEU1	Group
-	srl			%g1, 3, %g2			! IEU0
-	sub			%o2, %g7, %g3			! IEU0	Group
-	andn			%o1, (0x40 - 1), %o1		! IEU1
-	and			%g2, 7, %g2			! IEU0	Group
-	andncc			%g3, 0x7, %g3			! IEU1
-	fmovd			%f0, %f2			! FPU
-	sub			%g3, 0x10, %g3			! IEU0	Group
-	sub			%o2, %g7, %o2			! IEU1
-#ifdef __KERNEL__
-	or			asi_src, ASI_BLK_OR, asi_src	! IEU0	Group
-	or			asi_dest, ASI_BLK_OR, asi_dest	! IEU1
-#endif
-	alignaddr		%g1, %g0, %g0			! GRU	Group
-	add			%g1, %g7, %g1			! IEU0	Group
-	subcc			%o2, %g3, %o2			! IEU1
-	ASI_SETSRC_BLK						! LSU	Group
-	EXVIS1(LDBLK		[%o1 + 0x00] ASIBLK, %f0)	! LSU	Group
-	add			%g1, %g3, %g1			! IEU0
-	EXVIS1(LDBLK		[%o1 + 0x40] ASIBLK, %f16)	! LSU	Group
-	sub			%g7, 0x80, %g7			! IEU0
-	EXVIS(LDBLK		[%o1 + 0x80] ASIBLK, %f32)	! LSU	Group
-#ifdef __KERNEL__
-vispc:	sll			%g2, 9, %g2			! IEU0	Group
-	sethi			%hi(vis00), %g5			! IEU1
-	or			%g5, %lo(vis00), %g5		! IEU0	Group
-	jmpl			%g5 + %g2, %g0			! CTI	Group brk forced
-	 addcc			%o1, 0xc0, %o1			! IEU1	Group
-#else
-								! Clk1	Group 8-(
-								! Clk2	Group 8-(
-								! Clk3	Group 8-(
-								! Clk4	Group 8-(
-vispc:	rd			%pc, %g5			! PDU	Group 8-(
-	addcc			%g5, %lo(vis00 - vispc), %g5	! IEU1	Group
-	sll			%g2, 9, %g2			! IEU0
-	jmpl			%g5 + %g2, %g0			! CTI	Group brk forced
-	 addcc			%o1, 0xc0, %o1			! IEU1	Group
-#endif
-	.align			512		/* OK, here comes the fun part... */
-vis00:FREG_FROB(f0, f2, f4, f6, f8, f10,f12,f14,f16) LOOP_CHUNK1(o1, o0, g7, vis01)
-      FREG_FROB(f16,f18,f20,f22,f24,f26,f28,f30,f32) LOOP_CHUNK2(o1, o0, g7, vis02)
-      FREG_FROB(f32,f34,f36,f38,f40,f42,f44,f46,f0)  LOOP_CHUNK3(o1, o0, g7, vis03)
-      b,pt			%xcc, vis00+4; faligndata %f0, %f2, %f48
-vis01:FREG_FROB(f16,f18,f20,f22,f24,f26,f28,f30,f32) STORE_SYNC(o0, f48) membar #Sync
-      FREG_FROB(f32,f34,f36,f38,f40,f42,f44,f46,f0)  STORE_JUMP(o0, f48, finish_f0) membar #Sync
-vis02:FREG_FROB(f32,f34,f36,f38,f40,f42,f44,f46,f0)  STORE_SYNC(o0, f48) membar #Sync
-      FREG_FROB(f0, f2, f4, f6, f8, f10,f12,f14,f16) STORE_JUMP(o0, f48, finish_f16) membar #Sync
-vis03:FREG_FROB(f0, f2, f4, f6, f8, f10,f12,f14,f16) STORE_SYNC(o0, f48) membar #Sync
-      FREG_FROB(f16,f18,f20,f22,f24,f26,f28,f30,f32) STORE_JUMP(o0, f48, finish_f32) membar #Sync
-      VISLOOP_PAD
-vis10:FREG_FROB(f2, f4, f6, f8, f10,f12,f14,f16,f18) LOOP_CHUNK1(o1, o0, g7, vis11)
-      FREG_FROB(f18,f20,f22,f24,f26,f28,f30,f32,f34) LOOP_CHUNK2(o1, o0, g7, vis12)
-      FREG_FROB(f34,f36,f38,f40,f42,f44,f46,f0, f2)  LOOP_CHUNK3(o1, o0, g7, vis13)
-      b,pt			%xcc, vis10+4; faligndata %f2, %f4, %f48
-vis11:FREG_FROB(f18,f20,f22,f24,f26,f28,f30,f32,f34) STORE_SYNC(o0, f48) membar #Sync
-      FREG_FROB(f34,f36,f38,f40,f42,f44,f46,f0, f2)  STORE_JUMP(o0, f48, finish_f2) membar #Sync
-vis12:FREG_FROB(f34,f36,f38,f40,f42,f44,f46,f0, f2)  STORE_SYNC(o0, f48) membar #Sync
-      FREG_FROB(f2, f4, f6, f8, f10,f12,f14,f16,f18) STORE_JUMP(o0, f48, finish_f18) membar #Sync
-vis13:FREG_FROB(f2, f4, f6, f8, f10,f12,f14,f16,f18) STORE_SYNC(o0, f48) membar #Sync
-      FREG_FROB(f18,f20,f22,f24,f26,f28,f30,f32,f34) STORE_JUMP(o0, f48, finish_f34) membar #Sync
-      VISLOOP_PAD
-vis20:FREG_FROB(f4, f6, f8, f10,f12,f14,f16,f18,f20) LOOP_CHUNK1(o1, o0, g7, vis21)
-      FREG_FROB(f20,f22,f24,f26,f28,f30,f32,f34,f36) LOOP_CHUNK2(o1, o0, g7, vis22)
-      FREG_FROB(f36,f38,f40,f42,f44,f46,f0, f2, f4)  LOOP_CHUNK3(o1, o0, g7, vis23)
-      b,pt			%xcc, vis20+4; faligndata %f4, %f6, %f48
-vis21:FREG_FROB(f20,f22,f24,f26,f28,f30,f32,f34,f36) STORE_SYNC(o0, f48) membar #Sync
-      FREG_FROB(f36,f38,f40,f42,f44,f46,f0, f2, f4)  STORE_JUMP(o0, f48, finish_f4) membar #Sync
-vis22:FREG_FROB(f36,f38,f40,f42,f44,f46,f0, f2, f4)  STORE_SYNC(o0, f48) membar #Sync
-      FREG_FROB(f4, f6, f8, f10,f12,f14,f16,f18,f20) STORE_JUMP(o0, f48, finish_f20) membar #Sync
-vis23:FREG_FROB(f4, f6, f8, f10,f12,f14,f16,f18,f20) STORE_SYNC(o0, f48) membar #Sync
-      FREG_FROB(f20,f22,f24,f26,f28,f30,f32,f34,f36) STORE_JUMP(o0, f48, finish_f36) membar #Sync
-      VISLOOP_PAD
-vis30:FREG_FROB(f6, f8, f10,f12,f14,f16,f18,f20,f22) LOOP_CHUNK1(o1, o0, g7, vis31)
-      FREG_FROB(f22,f24,f26,f28,f30,f32,f34,f36,f38) LOOP_CHUNK2(o1, o0, g7, vis32)
-      FREG_FROB(f38,f40,f42,f44,f46,f0, f2, f4, f6)  LOOP_CHUNK3(o1, o0, g7, vis33)
-      b,pt			%xcc, vis30+4; faligndata %f6, %f8, %f48
-vis31:FREG_FROB(f22,f24,f26,f28,f30,f32,f34,f36,f38) STORE_SYNC(o0, f48) membar #Sync
-      FREG_FROB(f38,f40,f42,f44,f46,f0, f2, f4, f6)  STORE_JUMP(o0, f48, finish_f6) membar #Sync
-vis32:FREG_FROB(f38,f40,f42,f44,f46,f0, f2, f4, f6)  STORE_SYNC(o0, f48) membar #Sync
-      FREG_FROB(f6, f8, f10,f12,f14,f16,f18,f20,f22) STORE_JUMP(o0, f48, finish_f22) membar #Sync
-vis33:FREG_FROB(f6, f8, f10,f12,f14,f16,f18,f20,f22) STORE_SYNC(o0, f48) membar #Sync
-      FREG_FROB(f22,f24,f26,f28,f30,f32,f34,f36,f38) STORE_JUMP(o0, f48, finish_f38) membar #Sync
-      VISLOOP_PAD
-vis40:FREG_FROB(f8, f10,f12,f14,f16,f18,f20,f22,f24) LOOP_CHUNK1(o1, o0, g7, vis41)
-      FREG_FROB(f24,f26,f28,f30,f32,f34,f36,f38,f40) LOOP_CHUNK2(o1, o0, g7, vis42)
-      FREG_FROB(f40,f42,f44,f46,f0, f2, f4, f6, f8)  LOOP_CHUNK3(o1, o0, g7, vis43)
-      b,pt			%xcc, vis40+4; faligndata %f8, %f10, %f48
-vis41:FREG_FROB(f24,f26,f28,f30,f32,f34,f36,f38,f40) STORE_SYNC(o0, f48) membar #Sync
-      FREG_FROB(f40,f42,f44,f46,f0, f2, f4, f6, f8)  STORE_JUMP(o0, f48, finish_f8) membar #Sync
-vis42:FREG_FROB(f40,f42,f44,f46,f0, f2, f4, f6, f8)  STORE_SYNC(o0, f48) membar #Sync
-      FREG_FROB(f8, f10,f12,f14,f16,f18,f20,f22,f24) STORE_JUMP(o0, f48, finish_f24) membar #Sync
-vis43:FREG_FROB(f8, f10,f12,f14,f16,f18,f20,f22,f24) STORE_SYNC(o0, f48) membar #Sync
-      FREG_FROB(f24,f26,f28,f30,f32,f34,f36,f38,f40) STORE_JUMP(o0, f48, finish_f40) membar #Sync
-      VISLOOP_PAD
-vis50:FREG_FROB(f10,f12,f14,f16,f18,f20,f22,f24,f26) LOOP_CHUNK1(o1, o0, g7, vis51)
-      FREG_FROB(f26,f28,f30,f32,f34,f36,f38,f40,f42) LOOP_CHUNK2(o1, o0, g7, vis52)
-      FREG_FROB(f42,f44,f46,f0, f2, f4, f6, f8, f10) LOOP_CHUNK3(o1, o0, g7, vis53)
-      b,pt			%xcc, vis50+4; faligndata %f10, %f12, %f48
-vis51:FREG_FROB(f26,f28,f30,f32,f34,f36,f38,f40,f42) STORE_SYNC(o0, f48) membar #Sync
-      FREG_FROB(f42,f44,f46,f0, f2, f4, f6, f8, f10) STORE_JUMP(o0, f48, finish_f10) membar #Sync
-vis52:FREG_FROB(f42,f44,f46,f0, f2, f4, f6, f8, f10) STORE_SYNC(o0, f48) membar #Sync
-      FREG_FROB(f10,f12,f14,f16,f18,f20,f22,f24,f26) STORE_JUMP(o0, f48, finish_f26) membar #Sync
-vis53:FREG_FROB(f10,f12,f14,f16,f18,f20,f22,f24,f26) STORE_SYNC(o0, f48) membar #Sync
-      FREG_FROB(f26,f28,f30,f32,f34,f36,f38,f40,f42) STORE_JUMP(o0, f48, finish_f42) membar #Sync
-      VISLOOP_PAD
-vis60:FREG_FROB(f12,f14,f16,f18,f20,f22,f24,f26,f28) LOOP_CHUNK1(o1, o0, g7, vis61)
-      FREG_FROB(f28,f30,f32,f34,f36,f38,f40,f42,f44) LOOP_CHUNK2(o1, o0, g7, vis62)
-      FREG_FROB(f44,f46,f0, f2, f4, f6, f8, f10,f12) LOOP_CHUNK3(o1, o0, g7, vis63)
-      b,pt			%xcc, vis60+4; faligndata %f12, %f14, %f48
-vis61:FREG_FROB(f28,f30,f32,f34,f36,f38,f40,f42,f44) STORE_SYNC(o0, f48) membar #Sync
-      FREG_FROB(f44,f46,f0, f2, f4, f6, f8, f10,f12) STORE_JUMP(o0, f48, finish_f12) membar #Sync
-vis62:FREG_FROB(f44,f46,f0, f2, f4, f6, f8, f10,f12) STORE_SYNC(o0, f48) membar #Sync
-      FREG_FROB(f12,f14,f16,f18,f20,f22,f24,f26,f28) STORE_JUMP(o0, f48, finish_f28) membar #Sync
-vis63:FREG_FROB(f12,f14,f16,f18,f20,f22,f24,f26,f28) STORE_SYNC(o0, f48) membar #Sync
-      FREG_FROB(f28,f30,f32,f34,f36,f38,f40,f42,f44) STORE_JUMP(o0, f48, finish_f44) membar #Sync
-      VISLOOP_PAD
-vis70:FREG_FROB(f14,f16,f18,f20,f22,f24,f26,f28,f30) LOOP_CHUNK1(o1, o0, g7, vis71)
-      FREG_FROB(f30,f32,f34,f36,f38,f40,f42,f44,f46) LOOP_CHUNK2(o1, o0, g7, vis72)
-      FREG_FROB(f46,f0, f2, f4, f6, f8, f10,f12,f14) LOOP_CHUNK3(o1, o0, g7, vis73)
-      b,pt			%xcc, vis70+4; faligndata %f14, %f16, %f48
-vis71:FREG_FROB(f30,f32,f34,f36,f38,f40,f42,f44,f46) STORE_SYNC(o0, f48) membar #Sync
-      FREG_FROB(f46,f0, f2, f4, f6, f8, f10,f12,f14) STORE_JUMP(o0, f48, finish_f14) membar #Sync
-vis72:FREG_FROB(f46,f0, f2, f4, f6, f8, f10,f12,f14) STORE_SYNC(o0, f48) membar #Sync
-      FREG_FROB(f14,f16,f18,f20,f22,f24,f26,f28,f30) STORE_JUMP(o0, f48, finish_f30) membar #Sync
-vis73:FREG_FROB(f14,f16,f18,f20,f22,f24,f26,f28,f30) STORE_SYNC(o0, f48) membar #Sync
-      FREG_FROB(f30,f32,f34,f36,f38,f40,f42,f44,f46) STORE_JUMP(o0, f48, finish_f46) membar #Sync
-      VISLOOP_PAD
-finish_f0:	FINISH_VISCHUNK(o0, f0,  f2,  g3)
-finish_f2:	FINISH_VISCHUNK(o0, f2,  f4,  g3)
-finish_f4:	FINISH_VISCHUNK(o0, f4,  f6,  g3)
-finish_f6:	FINISH_VISCHUNK(o0, f6,  f8,  g3)
-finish_f8:	FINISH_VISCHUNK(o0, f8,  f10, g3)
-finish_f10:	FINISH_VISCHUNK(o0, f10, f12, g3)
-finish_f12:	FINISH_VISCHUNK(o0, f12, f14, g3)
-finish_f14:	UNEVEN_VISCHUNK(o0, f14, f0,  g3)
-finish_f16:	FINISH_VISCHUNK(o0, f16, f18, g3)
-finish_f18:	FINISH_VISCHUNK(o0, f18, f20, g3)
-finish_f20:	FINISH_VISCHUNK(o0, f20, f22, g3)
-finish_f22:	FINISH_VISCHUNK(o0, f22, f24, g3)
-finish_f24:	FINISH_VISCHUNK(o0, f24, f26, g3)
-finish_f26:	FINISH_VISCHUNK(o0, f26, f28, g3)
-finish_f28:	FINISH_VISCHUNK(o0, f28, f30, g3)
-finish_f30:	UNEVEN_VISCHUNK(o0, f30, f0,  g3)
-finish_f32:	FINISH_VISCHUNK(o0, f32, f34, g3)
-finish_f34:	FINISH_VISCHUNK(o0, f34, f36, g3)
-finish_f36:	FINISH_VISCHUNK(o0, f36, f38, g3)
-finish_f38:	FINISH_VISCHUNK(o0, f38, f40, g3)
-finish_f40:	FINISH_VISCHUNK(o0, f40, f42, g3)
-finish_f42:	FINISH_VISCHUNK(o0, f42, f44, g3)
-finish_f44:	FINISH_VISCHUNK(o0, f44, f46, g3)
-finish_f46:	UNEVEN_VISCHUNK_LAST(o0, f46, f0,  g3)
-vis_out_slk:
-#ifdef __KERNEL__
-	srl		asi_src, 3, %g5				! IEU0	Group
-	xor		asi_src, ASI_BLK_XOR1, asi_src		! IEU1
-	xor		asi_src, %g5, asi_src			! IEU0	Group
-#endif
-vis_slk:ASI_SETSRC_NOBLK					! LSU	Group
-	EXVIS3(LDDF	[%o1] ASINORMAL, %f2)			! Load	Group
-	add		%o1, 8, %o1				! IEU0
-	subcc		%g3, 8, %g3				! IEU1
-	ASI_SETDST_NOBLK					! LSU	Group
-	faligndata	%f0, %f2, %f8				! GRU	Group
-	EXVIS4(STDF	%f8, [%o0] ASINORMAL)			! Store
-	bl,pn		%xcc, vis_out_slp			! CTI
-	 add		%o0, 8, %o0				! IEU0	Group
-	ASI_SETSRC_NOBLK					! LSU	Group
-	EXVIS3(LDDF	[%o1] ASINORMAL, %f0)			! Load	Group
-	add		%o1, 8, %o1				! IEU0
-	subcc		%g3, 8, %g3				! IEU1
-	ASI_SETDST_NOBLK					! LSU	Group
-	faligndata	%f2, %f0, %f8				! GRU	Group
-	EXVIS4(STDF	%f8, [%o0] ASINORMAL)			! Store
-	bge,pt		%xcc, vis_slk				! CTI
-	 add		%o0, 8, %o0				! IEU0	Group
-vis_out_slp:
-#ifdef __KERNEL__
-	brz,pt		%o2, vis_ret				! CTI	Group
-	 mov		%g1, %o1				! IEU0
-	ba,pt		%xcc, vis_slp+4				! CTI	Group
-	 ASI_SETSRC_NOBLK					! LSU	Group
-#endif
-vis_out:brz,pt		%o2, vis_ret				! CTI	Group
-	 mov		%g1, %o1				! IEU0
-#ifdef __KERNEL__
-	srl		asi_src, 3, %g5				! IEU0	Group
-	xor		asi_src, ASI_BLK_XOR1, asi_src		! IEU1
-	xor		asi_src, %g5, asi_src			! IEU0	Group
-#endif
-vis_slp:ASI_SETSRC_NOBLK					! LSU	Group
-	EXO2(LDUB	[%o1] ASINORMAL, %g5)			! LOAD
-	add		%o1, 1, %o1				! IEU0
-	add		%o0, 1, %o0				! IEU1
-	ASI_SETDST_NOBLK					! LSU	Group
-	subcc		%o2, 1, %o2				! IEU1
-	bne,pt		%xcc, vis_slp				! CTI
-	 EX(STB		%g5, [%o0 - 1] ASINORMAL,
-			add %o2, 1)				! Store	Group
-vis_ret:membar		#StoreLoad | #StoreStore		! LSU	Group
-	FPU_CLEAN_RETL
-
-
-__memcpy_short:
-	andcc		%o2, 1, %g0				! IEU1	Group
-	be,pt		%icc, 2f				! CTI
-1:	 ASI_SETSRC_NOBLK					! LSU	Group
-	EXO2(LDUB	[%o1] ASINORMAL, %g5)			! LOAD	Group
-	add		%o1, 1, %o1				! IEU0
-	add		%o0, 1, %o0				! IEU1
-	ASI_SETDST_NOBLK					! LSU	Group
-	subcc		%o2, 1, %o2				! IEU1	Group
-	be,pn		%xcc, short_ret				! CTI
-	 EX(STB		%g5, [%o0 - 1] ASINORMAL,
-			add %o2, 1)				! Store
-2:	ASI_SETSRC_NOBLK					! LSU	Group
-	EXO2(LDUB	[%o1] ASINORMAL, %g5)			! LOAD	Group
-	add		%o0, 2, %o0				! IEU0
-	EX2(LDUB	[%o1 + 1] ASINORMAL, %o5,
-			sub %o0, 2, %o0,
-			add %o2, %g0)				! LOAD	Group
-	add		%o1, 2, %o1				! IEU0
-	ASI_SETDST_NOBLK					! LSU	Group
-	subcc		%o2, 2, %o2				! IEU1	Group
-	EX(STB		%g5, [%o0 - 2] ASINORMAL,
-			add %o2, 2)				! Store
-	bne,pt		%xcc, 2b				! CTI
-	 EX(STB		%o5, [%o0 - 1] ASINORMAL,
-			add %o2, 1)				! Store
-short_ret:
-	NORMAL_RETL
-
-#ifndef __KERNEL__
-memcpy_private:
-memcpy:
-#ifndef REGS_64BIT
-	srl		%o2, 0, %o2				! IEU1	Group
-#endif	
-	brz,pn		%o2, short_ret				! CTI	Group
-	 mov		%o0, %g6				! IEU0
-#endif
-__memcpy_entry:
-	cmp		%o2, 15					! IEU1	Group
-	bleu,pn		%xcc, __memcpy_short			! CTI
-	 cmp		%o2, (64 * 6)				! IEU1	Group
-	bgeu,pn		%xcc, VIS_enter				! CTI
-	 andcc		%o0, 7, %g2				! IEU1	Group
-	sub		%o0, %o1, %g5				! IEU0
-	andcc		%g5, 3, %o5				! IEU1	Group
-	bne,pn		%xcc, memcpy_noVIS_misaligned		! CTI
-	 andcc		%o1, 3, %g0				! IEU1	Group
-#ifdef REGS_64BIT
-	be,a,pt		%xcc, 3f				! CTI
-	 andcc		%o1, 4, %g0				! IEU1	Group
-	andcc		%o1, 1, %g0				! IEU1	Group
-#else /* !REGS_64BIT */
-	be,pt		%xcc, 5f				! CTI
-	 andcc		%o1, 1, %g0				! IEU1	Group
-#endif /* !REGS_64BIT */
-	be,pn		%xcc, 4f				! CTI
-	 andcc		%o1, 2, %g0				! IEU1	Group
-	ASI_SETSRC_NOBLK					! LSU	Group
-	EXO2(LDUB	[%o1] ASINORMAL, %g2)			! Load	Group
-	add		%o1, 1, %o1				! IEU0
-	add		%o0, 1, %o0				! IEU1
-	sub		%o2, 1, %o2				! IEU0	Group
-	ASI_SETDST_NOBLK					! LSU	Group
-	bne,pn		%xcc, 5f				! CTI	Group
-	 EX(STB		%g2, [%o0 - 1] ASINORMAL,
-			add %o2, 1)				! Store
-4:	ASI_SETSRC_NOBLK					! LSU	Group
-	EXO2(LDUH	[%o1] ASINORMAL, %g2)			! Load	Group
-	add		%o1, 2, %o1				! IEU0
-	add		%o0, 2, %o0				! IEU1
-	ASI_SETDST_NOBLK					! LSU	Group
-	sub		%o2, 2, %o2				! IEU0
-	EX(STH		%g2, [%o0 - 2] ASINORMAL,
-			add %o2, 2)				! Store	Group + bubble
-#ifdef REGS_64BIT
-5:	andcc		%o1, 4, %g0				! IEU1
-3:	be,a,pn		%xcc, 2f				! CTI
-	 andcc		%o2, -128, %g7				! IEU1	Group
-	ASI_SETSRC_NOBLK					! LSU	Group
-	EXO2(LDUW	[%o1] ASINORMAL, %g5)			! Load	Group
-	add		%o1, 4, %o1				! IEU0
-	add		%o0, 4, %o0				! IEU1
-	ASI_SETDST_NOBLK					! LSU	Group
-	sub		%o2, 4, %o2				! IEU0	Group
-	EX(STW		%g5, [%o0 - 4] ASINORMAL,
-			add %o2, 4)				! Store
-	andcc		%o2, -128, %g7				! IEU1	Group
-2:	be,pn		%xcc, 3f				! CTI
-	 andcc		%o0, 4, %g0				! IEU1	Group
-	be,pn		%xcc, 82f + 4				! CTI	Group
-#else /* !REGS_64BIT */
-5:	andcc		%o2, -128, %g7				! IEU1
-	be,a,pn		%xcc, 41f				! CTI
-	 andcc		%o2, 0x70, %g7				! IEU1	Group
-#endif /* !REGS_64BIT */
-5:	MOVE_BIGCHUNK(o1, o0, 0x00, g1, g3, g5, o5)
-	MOVE_BIGCHUNK(o1, o0, 0x20, g1, g3, g5, o5)
-	MOVE_BIGCHUNK(o1, o0, 0x40, g1, g3, g5, o5)
-	MOVE_BIGCHUNK(o1, o0, 0x60, g1, g3, g5, o5)
-	EXT(5b,35f,VIScopyfixup1)
-35:	subcc		%g7, 128, %g7				! IEU1	Group
-	add		%o1, 128, %o1				! IEU0
-	bne,pt		%xcc, 5b				! CTI
-	 add		%o0, 128, %o0				! IEU0	Group
-3:	andcc		%o2, 0x70, %g7				! IEU1	Group
-41:	be,pn		%xcc, 80f				! CTI
-	 andcc		%o2, 8, %g0				! IEU1	Group
-#ifdef __KERNEL__
-79:	sethi		%hi(80f), %o5				! IEU0
-	sll		%g7, 1, %g5				! IEU0	Group
-	add		%o1, %g7, %o1				! IEU1
-	srl		%g7, 1, %g2				! IEU0  Group
-	sub		%o5, %g5, %o5				! IEU1
-	sub		%o5, %g2, %o5				! IEU0  Group
-	jmpl		%o5 + %lo(80f), %g0			! CTI	Group brk forced
-	 add		%o0, %g7, %o0				! IEU0	Group
-#else
-								! Clk1 8-(
-								! Clk2 8-(
-								! Clk3 8-(
-								! Clk4 8-(
-79:	rd		%pc, %o5				! PDU	Group
-	sll		%g7, 1, %g5				! IEU0	Group
-	add		%o1, %g7, %o1				! IEU1
-	sub		%o5, %g5, %o5				! IEU0  Group
-	jmpl		%o5 + %lo(80f - 79b), %g0		! CTI	Group brk forced
-	 add		%o0, %g7, %o0				! IEU0	Group
-#endif
-36:	MOVE_LASTCHUNK(o1, o0, 0x60, g2, g3, g5, o5)
-	MOVE_LASTCHUNK(o1, o0, 0x50, g2, g3, g5, o5)
-	MOVE_LASTCHUNK(o1, o0, 0x40, g2, g3, g5, o5)
-	MOVE_LASTCHUNK(o1, o0, 0x30, g2, g3, g5, o5)
-	MOVE_LASTCHUNK(o1, o0, 0x20, g2, g3, g5, o5)
-	MOVE_LASTCHUNK(o1, o0, 0x10, g2, g3, g5, o5)
-	MOVE_LASTCHUNK(o1, o0, 0x00, g2, g3, g5, o5)
-	EXT(36b,80f,VIScopyfixup2)
-80:	be,pt		%xcc, 81f				! CTI
-	 andcc		%o2, 4, %g0				! IEU1
-#ifdef REGS_64BIT
-	ASI_SETSRC_NOBLK					! LSU	Group
-	EX(LDX		[%o1] ASINORMAL, %g2,
-			and %o2, 0xf)				! Load	Group
-	add		%o0, 8, %o0				! IEU0
-	ASI_SETDST_NOBLK					! LSU	Group
-	EX(STW		%g2, [%o0 - 0x4] ASINORMAL,
-			and %o2, 0xf)				! Store	Group
-	add		%o1, 8, %o1				! IEU1
-	srlx		%g2, 32, %g2				! IEU0	Group
-	EX2(STW		%g2, [%o0 - 0x8] ASINORMAL,
-			and %o2, 0xf, %o2,
-			sub %o2, 4)				! Store
-#else /* !REGS_64BIT */
-	lduw		[%o1], %g2				! Load	Group
-	add		%o0, 8, %o0				! IEU0
-	lduw		[%o1 + 0x4], %g3			! Load	Group
-	add		%o1, 8, %o1				! IEU0
-	stw		%g2, [%o0 - 0x8]			! Store	Group
-	stw		%g3, [%o0 - 0x4]			! Store	Group
-#endif /* !REGS_64BIT */
-81:	be,pt		%xcc, 1f				! CTI
-	 andcc		%o2, 2, %g0				! IEU1	Group
-	ASI_SETSRC_NOBLK					! LSU	Group
-	EX(LDUW		[%o1] ASINORMAL, %g2,
-			and %o2, 0x7)				! Load	Group
-	add		%o1, 4, %o1				! IEU0
-	ASI_SETDST_NOBLK					! LSU	Group
-	EX(STW		%g2, [%o0] ASINORMAL,
-			and %o2, 0x7)				! Store	Group
-	add		%o0, 4, %o0				! IEU0
-1:	be,pt		%xcc, 1f				! CTI
-	 andcc		%o2, 1, %g0				! IEU1	Group
-	ASI_SETSRC_NOBLK					! LSU	Group
-	EX(LDUH		[%o1] ASINORMAL, %g2,
-			and %o2, 0x3)				! Load	Group
-	add		%o1, 2, %o1				! IEU0
-	ASI_SETDST_NOBLK					! LSU	Group
-	EX(STH		%g2, [%o0] ASINORMAL,
-			and %o2, 0x3)				! Store	Group
-	add		%o0, 2, %o0				! IEU0
-1:	be,pt		%xcc, normal_retl			! CTI
-	 nop							! IEU1
-	ASI_SETSRC_NOBLK					! LSU	Group
-	EX(LDUB		[%o1] ASINORMAL, %g2,
-			add %g0, 1)				! Load	Group
-	ASI_SETDST_NOBLK					! LSU	Group
-	EX(STB		%g2, [%o0] ASINORMAL,
-			add %g0, 1)				! Store	Group + bubble
-normal_retl:
-	NORMAL_RETL
-
-#ifdef REGS_64BIT
-82:	MOVE_BIGALIGNCHUNK(o1, o0, 0x00, g1, g3, g5, o5)
-	MOVE_BIGALIGNCHUNK(o1, o0, 0x40, g1, g3, g5, o5)
-	EXT(82b,37f,VIScopyfixup3)
-37:	subcc		%g7, 128, %g7				! IEU1	Group
-	add		%o1, 128, %o1				! IEU0
-	bne,pt		%xcc, 82b				! CTI
-	 add		%o0, 128, %o0				! IEU0	Group
-	andcc		%o2, 0x70, %g7				! IEU1
-	be,pn		%xcc, 84f				! CTI
-	 andcc		%o2, 8, %g0				! IEU1	Group
-#ifdef __KERNEL__
-83:	srl		%g7, 1, %g5				! IEU0
-	sethi		%hi(84f), %o5				! IEU0	Group
-	add		%g7, %g5, %g5				! IEU1
-	add		%o1, %g7, %o1				! IEU0	Group
-	sub		%o5, %g5, %o5				! IEU1
-	jmpl		%o5 + %lo(84f), %g0			! CTI	Group brk forced
-	 add		%o0, %g7, %o0				! IEU0	Group
-#else
-								! Clk1 8-(
-								! Clk2 8-(
-								! Clk3 8-(
-								! Clk4 8-(
-83:	rd		%pc, %o5				! PDU	Group
-	add		%o1, %g7, %o1				! IEU0	Group
-	sub		%o5, %g7, %o5				! IEU1
-	jmpl		%o5 + %lo(84f - 83b), %g0		! CTI	Group brk forced
-	 add		%o0, %g7, %o0				! IEU0	Group
-#endif
-38:	MOVE_LASTALIGNCHUNK(o1, o0, 0x60, g2, g3)
-	MOVE_LASTALIGNCHUNK(o1, o0, 0x50, g2, g3)
-	MOVE_LASTALIGNCHUNK(o1, o0, 0x40, g2, g3)
-	MOVE_LASTALIGNCHUNK(o1, o0, 0x30, g2, g3)
-	MOVE_LASTALIGNCHUNK(o1, o0, 0x20, g2, g3)
-	MOVE_LASTALIGNCHUNK(o1, o0, 0x10, g2, g3)
-	MOVE_LASTALIGNCHUNK(o1, o0, 0x00, g2, g3)
-	EXT(38b,84f,VIScopyfixup4)
-84:	be,pt		%xcc, 85f				! CTI	Group
-	 andcc		%o2, 4, %g0				! IEU1
-	ASI_SETSRC_NOBLK					! LSU	Group
-	EX(LDX		[%o1] ASINORMAL, %g2,
-			and %o2, 0xf)				! Load	Group
-	add		%o0, 8, %o0				! IEU0
-	ASI_SETDST_NOBLK					! LSU	Group
-	add		%o1, 8, %o1				! IEU0	Group
-	EX(STX		%g2, [%o0 - 0x8] ASINORMAL,
-			and %o2, 0xf)				! Store
-85:	be,pt		%xcc, 1f				! CTI
-	 andcc		%o2, 2, %g0				! IEU1	Group
-	ASI_SETSRC_NOBLK					! LSU	Group
-	EX(LDUW		[%o1] ASINORMAL, %g2,
-			and %o2, 0x7)				! Load	Group
-	add		%o0, 4, %o0				! IEU0
-	ASI_SETDST_NOBLK					! LSU	Group
-	add		%o1, 4, %o1				! IEU0	Group
-	EX(STW		%g2, [%o0 - 0x4] ASINORMAL,
-			and %o2, 0x7)				! Store
-1:	be,pt		%xcc, 1f				! CTI
-	 andcc		%o2, 1, %g0				! IEU1	Group
-	ASI_SETSRC_NOBLK					! LSU	Group
-	EX(LDUH		[%o1] ASINORMAL, %g2,
-			and %o2, 0x3)				! Load	Group
-	add		%o0, 2, %o0				! IEU0
-	ASI_SETDST_NOBLK					! LSU	Group
-	add		%o1, 2, %o1				! IEU0	Group
-	EX(STH		%g2, [%o0 - 0x2] ASINORMAL,
-			and %o2, 0x3)				! Store
-1:	be,pt		%xcc, 1f				! CTI
-	 nop							! IEU0	Group
-	ASI_SETSRC_NOBLK					! LSU	Group
-	EX(LDUB		[%o1] ASINORMAL, %g2,
-			add %g0, 1)				! Load	Group
-	ASI_SETDST_NOBLK					! LSU	Group
-	EX(STB		%g2, [%o0] ASINORMAL,
-			add %g0, 1)				! Store	Group + bubble
-1:	NORMAL_RETL
-#endif	/* REGS_64BIT */
-
-memcpy_noVIS_misaligned:
-	brz,pt			%g2, 2f				! CTI	Group
-	 mov			8, %g1				! IEU0
-	sub			%g1, %g2, %g2			! IEU0	Group
-	sub			%o2, %g2, %o2			! IEU0	Group
-1:	ASI_SETSRC_NOBLK					! LSU	Group
-	EX(LDUB			[%o1] ASINORMAL, %g5,
-				add %o2, %g2)			! Load	Group
-	add			%o1, 1, %o1			! IEU0
-	add			%o0, 1, %o0			! IEU1
-	ASI_SETDST_NOBLK					! LSU	Group
-	subcc			%g2, 1, %g2			! IEU1	Group
-	bne,pt			%xcc, 1b			! CTI
-	 EX2(STB		%g5, [%o0 - 1] ASINORMAL,
-				add %o2, %g2, %o2,
-				add %o2, 1)			! Store
-2:
-#ifdef __KERNEL__
-	VISEntry
-#endif
-	andn			%o2, 7, %g5 			! IEU0	Group
-	and			%o2, 7, %o2			! IEU1
-	fmovd			%f0, %f2			! FPU
-	ASI_SETSRC_NOBLK					! LSU	Group
-	alignaddr		%o1, %g0, %g1			! GRU	Group
-	EXO2(LDDF		[%g1] ASINORMAL, %f4)		! Load	Group
-1:	EX(LDDF			[%g1 + 0x8] ASINORMAL, %f6,
-				add %o2, %g5)			! Load	Group
-	add			%g1, 0x8, %g1			! IEU0	Group
-	subcc			%g5, 8, %g5			! IEU1
-	ASI_SETDST_NOBLK					! LSU	Group
-	faligndata		%f4, %f6, %f0			! GRU	Group
-	EX2(STDF		%f0, [%o0] ASINORMAL,
-				add %o2, %g5, %o2,
-				add %o2, 8)			! Store
-	add			%o1, 8, %o1			! IEU0	Group
-	be,pn			%xcc, end_cruft			! CTI
-	 add			%o0, 8, %o0			! IEU1
-	ASI_SETSRC_NOBLK					! LSU	Group
-	EX(LDDF			[%g1 + 0x8] ASINORMAL, %f4,
-				add %o2, %g5)			! Load	Group
-	add			%g1, 8, %g1			! IEU0
-	subcc			%g5, 8, %g5			! IEU1
-	ASI_SETDST_NOBLK					! LSU	Group
-	faligndata		%f6, %f4, %f0			! GRU	Group
-	EX2(STDF		%f0, [%o0] ASINORMAL,
-				add %o2, %g5, %o2,
-				add %o2, 8)			! Store
-	add			%o1, 8, %o1			! IEU0
-	ASI_SETSRC_NOBLK					! LSU	Group
-	bne,pn			%xcc, 1b			! CTI	Group
-	 add			%o0, 8, %o0			! IEU0
-end_cruft:
-	brz,pn			%o2, fpu_retl			! CTI	Group
-#ifndef __KERNEL__
-	 nop							! IEU0
-#else
-	 ASI_SETSRC_NOBLK					! LSU	Group
-#endif
-	EXO2(LDUB	[%o1] ASINORMAL, %g5)			! LOAD
-	add		%o1, 1, %o1				! IEU0
-	add		%o0, 1, %o0				! IEU1
-	ASI_SETDST_NOBLK					! LSU	Group
-	subcc		%o2, 1, %o2				! IEU1
-	bne,pt		%xcc, vis_slp				! CTI
-	 EX(STB		%g5, [%o0 - 1] ASINORMAL,
-			add %o2, 1)				! Store	Group
-fpu_retl:
-	FPU_RETL
-
-#ifdef __KERNEL__
-	.globl		__memcpy_end
-__memcpy_end:
-
-		.section	.fixup
-		.align		4
-VIScopyfixup_reto2:
-		mov		%o2, %o1
-VIScopyfixup_ret:
-		/* If this is copy_from_user(), zero out the rest of the
-		 * kernel buffer.
-		 */
-		ldub		[%g6 + AOFF_task_thread + AOFF_thread_current_ds], %o4
-		andcc		asi_src, 0x1, %g0
-		be,pt		%icc, 1f
-		 VISExit
-		andcc		asi_dest, 0x1, %g0
-		bne,pn		%icc, 1f
-		 nop
-		save		%sp, -160, %sp
-		mov		%i0, %o0
-		call		__bzero
-		 mov		%i1, %o1
-		restore
-1:		mov		%o1, %o0
-		retl
-		 wr		%o4, %g0, %asi
-VIScopyfixup1:	subcc		%g2, 18, %g2
-		add		%o0, 32, %o0
-		bgeu,a,pt	%icc, VIScopyfixup1
-		 sub		%g7, 32, %g7
-		sub		%o0, 32, %o0
-		rd		%pc, %g5
-		add		%g2, (18 + 16), %g2
-		ldub		[%g5 + %g2], %g2
-		ba,a,pt		%xcc, 2f
-.byte		0, 0, 0, 0, 0, 0, 0, 4, 4, 8, 12, 12, 16, 20, 20, 24, 28, 28
-		.align		4
-VIScopyfixup2:	mov		(7 * 16), %g7
-1:		subcc		%g2, 10, %g2
-		bgeu,a,pt	%icc, 1b
-		 sub		%g7, 16, %g7
-		sub		%o0, %g7, %o0
-		rd		%pc, %g5
-		add		%g2, (10 + 16), %g2
-		ldub		[%g5 + %g2], %g2
-		ba,a,pt		%xcc, 4f
-.byte		0, 0, 0, 0, 0, 4, 4, 8, 12, 12
-		.align		4
-VIScopyfixup3:	subcc		%g2, 10, %g2
-		add		%o0, 32, %o0
-		bgeu,a,pt	%icc, VIScopyfixup3
-		 sub		%g7, 32, %g7
-		sub		%o0, 32, %o0
-		rd		%pc, %g5
-		add		%g2, (10 + 16), %g2
-		ldub		[%g5 + %g2], %g2
-		ba,a,pt		%xcc, 2f
-.byte		0, 0, 0, 0, 0, 0, 0, 8, 16, 24
-		.align		4
-2:		and		%o2, 0x7f, %o2
-		sub		%g7, %g2, %g7
-		ba,pt		%xcc, VIScopyfixup_ret
-		 add		%g7, %o2, %o1
-VIScopyfixup4:	mov		(7 * 16), %g7
-3:		subcc		%g2, 6, %g2
-		bgeu,a,pt	%icc, 3b
-		 sub		%g7, 16, %g7
-		sub		%o0, %g7, %o0
-		rd		%pc, %g5
-		add		%g2, (6 + 16), %g2
-		ldub		[%g5 + %g2], %g2
-		ba,a,pt		%xcc, 4f
-.byte		0, 0, 0, 0, 0, 8
-		.align		4
-4:		and		%o2, 0xf, %o2
-		sub		%g7, %g2, %g7
-		ba,pt		%xcc, VIScopyfixup_ret
-		 add		%g7, %o2, %o1
-VIScopyfixup_vis2:
-		sub		%o2, 0x40, %o2
-VIScopyfixup_vis0:
-		add		%o2, 0x80, %o2
-VIScopyfixup_vis1:
-		add		%g7, %g3, %g7
-		ba,pt		%xcc, VIScopyfixup_ret
-		 add		%o2, %g7, %o1
-VIScopyfixup_vis4:
-		add		%g3, 8, %g3
-VIScopyfixup_vis3:
-		add		%g3, 8, %g3
-		ba,pt		%xcc, VIScopyfixup_ret
-		 add		%o2, %g3, %o1
-#endif
-
-#ifdef __KERNEL__
-		.text
-		.align		32
-
-		.globl		__memmove
-		.type		__memmove,@function
-
-		.globl		memmove
-		.type		memmove,@function
-
-memmove:
-__memmove:	cmp		%o0, %o1
-		blu,pt		%xcc, memcpy_private
-		 sub		%o0, %o1, %g5
-		add		%o1, %o2, %g3
-		cmp		%g3, %o0
-		bleu,pt		%xcc, memcpy_private
-		 add		%o1, %o2, %g5
-		add		%o0, %o2, %o5
-
-		sub		%g5, 1, %o1
-		sub		%o5, 1, %o0
-1:		ldub		[%o1], %g5
-		subcc		%o2, 1, %o2
-		sub		%o1, 1, %o1
-		stb		%g5, [%o0]
-		bne,pt		%icc, 1b
-		 sub		%o0, 1, %o0
-
-		retl
-		 clr		%o0
-#endif
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/sparc64/lib/copy_in_user.S linux-2.4.28-pre3/arch/sparc64/lib/copy_in_user.S
--- linux-2.4.27/arch/sparc64/lib/copy_in_user.S	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.28-pre3/arch/sparc64/lib/copy_in_user.S	2004-09-10 19:34:57.000000000 +0000
@@ -0,0 +1,114 @@
+/* copy_in_user.S: Copy from userspace to userspace.
+ *
+ * Copyright (C) 1999, 2000, 2004 David S. Miller (davem@redhat.com)
+ */
+
+#include <asm/asi.h>
+
+#define XCC xcc
+
+#define EX(x,y)			\
+98:	x,y;			\
+	.section .fixup;	\
+	.align 4;		\
+99:	retl;			\
+	 mov 1, %o0;		\
+	.section __ex_table;	\
+	.align 4;		\
+	.word 98b, 99b;		\
+	.text;			\
+	.align 4;
+
+	.register	%g2,#scratch
+	.register	%g3,#scratch
+
+	.text
+	.align	32
+
+	/* Don't try to get too fancy here, just nice and
+	 * simple.  This is predominantly used for well aligned
+	 * small copies in the compat layer.  It is also used
+	 * to copy register windows around during thread cloning.
+	 */
+
+	.globl	___copy_in_user
+___copy_in_user:	/* %o0=dst, %o1=src, %o2=len */
+	/* Writing to %asi is _expensive_ so we hardcode it.
+	 * Reading %asi to check for KERNEL_DS is comparatively
+	 * cheap.
+	 */
+	rd		%asi, %g1
+	cmp		%g1, ASI_AIUS
+	bne,pn		%icc, memcpy_user_stub
+	 nop
+
+	cmp		%o2, 0
+	be,pn		%XCC, 85f
+	 or		%o0, %o1, %o3
+	cmp		%o2, 16
+	bleu,a,pn	%XCC, 80f
+	 or		%o3, %o2, %o3
+
+	/* 16 < len <= 64 */
+	andcc		%o3, 0x7, %g0
+	bne,pn		%XCC, 90f
+	 sub		%o0, %o1, %o3
+
+	andn		%o2, 0x7, %o4
+	and		%o2, 0x7, %o2
+1:	subcc		%o4, 0x8, %o4
+	EX(ldxa [%o1] %asi, %o5)
+	EX(stxa %o5, [%o1 + %o3] ASI_AIUS)
+	bgu,pt		%XCC, 1b
+	 add		%o1, 0x8, %o1
+	andcc		%o2, 0x4, %g0
+	be,pt		%XCC, 1f
+	 nop
+	sub		%o2, 0x4, %o2
+	EX(lduwa [%o1] %asi, %o5)
+	EX(stwa %o5, [%o1 + %o3] ASI_AIUS)
+	add		%o1, 0x4, %o1
+1:	cmp		%o2, 0
+	be,pt		%XCC, 85f
+	 nop
+	ba,pt		%xcc, 90f
+	 nop
+
+80:	/* 0 < len <= 16 */
+	andcc		%o3, 0x3, %g0
+	bne,pn		%XCC, 90f
+	 sub		%o0, %o1, %o3
+
+82:
+	subcc		%o2, 4, %o2
+	EX(lduwa [%o1] %asi, %g1)
+	EX(stwa %g1, [%o1 + %o3] ASI_AIUS)
+	bgu,pt		%XCC, 82b
+	 add		%o1, 4, %o1
+
+85:	retl
+	 clr		%o0
+
+	.align	32
+90:
+	subcc		%o2, 1, %o2
+	EX(lduba [%o1] %asi, %g1)
+	EX(stba %g1, [%o1 + %o3] ASI_AIUS)
+	bgu,pt		%XCC, 90b
+	 add		%o1, 1, %o1
+	retl
+	 clr		%o0
+
+	/* Act like copy_{to,in}_user(), ie. return zero instead
+	 * of original destination pointer.  This is invoked when
+	 * copy_{to,in}_user() finds that %asi is kernel space.
+	 */
+	.globl		memcpy_user_stub
+memcpy_user_stub:
+	save		%sp, -192, %sp
+	mov		%i0, %o0
+	mov		%i1, %o1
+	call		memcpy
+	 mov		%i2, %o2
+	ret
+	 restore	%g0, %g0, %o0
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/sparc64/lib/memmove.S linux-2.4.28-pre3/arch/sparc64/lib/memmove.S
--- linux-2.4.27/arch/sparc64/lib/memmove.S	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.28-pre3/arch/sparc64/lib/memmove.S	2004-09-10 19:37:12.000000000 +0000
@@ -0,0 +1,31 @@
+/* memmove.S: Simple memmove implementation.
+ *
+ * Copyright (C) 1997, 2004 David S. Miller (davem@redhat.com)
+ * Copyright (C) 1996, 1997, 1998, 1999 Jakub Jelinek (jj@ultra.linux.cz)
+ */
+
+	.text
+	.align	32
+	.globl	memmove
+memmove:
+	mov		%o0, %g1
+	cmp		%o0, %o1
+	blu,pt		%xcc, memcpy
+	 sub		%o0, %o1, %g5
+	add		%o1, %o2, %g3
+	cmp		%g3, %o0
+	bleu,pt		%xcc, memcpy
+	 add		%o1, %o2, %g5
+	add		%o0, %o2, %o5
+
+	sub		%g5, 1, %o1
+	sub		%o5, 1, %o0
+1:	ldub		[%o1], %g5
+	subcc		%o2, 1, %o2
+	sub		%o1, 1, %o1
+	stb		%g5, [%o0]
+	bne,pt		%icc, 1b
+	 sub		%o0, 1, %o0
+
+	retl
+	 mov		%g1, %o0
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/sparc64/lib/user_fixup.c linux-2.4.28-pre3/arch/sparc64/lib/user_fixup.c
--- linux-2.4.27/arch/sparc64/lib/user_fixup.c	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.28-pre3/arch/sparc64/lib/user_fixup.c	2004-09-10 19:36:14.000000000 +0000
@@ -0,0 +1,68 @@
+/* user_fixup.c: Fix up user copy faults.
+ *
+ * Copyright (C) 2004 David S. Miller <davem@redhat.com>
+ */
+
+#include <linux/compiler.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <asm/uaccess.h>
+
+/* Calculating the exact fault address when using
+ * block loads and stores can be very complicated.
+ * Instead of trying to be clever and handling all
+ * of the cases, just fix things up simply here.
+ */
+
+unsigned long copy_from_user_fixup(void *to, const void __user *from, unsigned long size)
+{
+	char *dst = to;
+	const char __user *src = from;
+
+	while (size--) {
+		if (__get_user(*dst, src))
+			break;
+		dst++;
+		src++;
+	}
+
+	if (size)
+		memset(dst, 0, size);
+
+	return size;
+}
+
+unsigned long copy_to_user_fixup(void __user *to, const void *from, unsigned long size)
+{
+	char __user *dst = to;
+	const char *src = from;
+
+	while (size--) {
+		if (__put_user(*src, dst))
+			break;
+		dst++;
+		src++;
+	}
+
+	return size;
+}
+
+unsigned long copy_in_user_fixup(void __user *to, void __user *from, unsigned long size)
+{
+	char __user *dst = to;
+	char __user *src = from;
+
+	while (size--) {
+		char tmp;
+
+		if (__get_user(tmp, src))
+			break;
+		if (__put_user(tmp, dst))
+			break;
+		dst++;
+		src++;
+	}
+
+	return size;
+}
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/sparc64/mm/fault.c linux-2.4.28-pre3/arch/sparc64/mm/fault.c
--- linux-2.4.27/arch/sparc64/mm/fault.c	2004-08-07 23:26:04.000000000 +0000
+++ linux-2.4.28-pre3/arch/sparc64/mm/fault.c	2004-09-10 19:37:06.000000000 +0000
@@ -253,7 +253,7 @@ static void do_kernel_fault(struct pt_re
 	 * in that case.
 	 */
 
-	if (!(fault_code & FAULT_CODE_WRITE) &&
+	if (!(fault_code & (FAULT_CODE_WRITE|FAULT_CODE_ITLB)) &&
 	    (insn & 0xc0800000) == 0xc0800000) {
 		if (insn & 0x2000)
 			asi = (regs->tstate >> 24);
@@ -404,6 +404,16 @@ continue_fault:
 	 */
 good_area:
 	si_code = SEGV_ACCERR;
+
+	/* If we took a ITLB miss on a non-executable page, catch
+	 * that here.
+	 */
+	if ((fault_code & FAULT_CODE_ITLB) && !(vma->vm_flags & VM_EXEC)) {
+		BUG_ON(address != regs->tpc);
+		BUG_ON(regs->tstate & TSTATE_PRIV);
+		goto bad_area;
+	}
+
 	if (fault_code & FAULT_CODE_WRITE) {
 		if (!(vma->vm_flags & VM_WRITE))
 			goto bad_area;
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/sparc64/mm/init.c linux-2.4.28-pre3/arch/sparc64/mm/init.c
--- linux-2.4.27/arch/sparc64/mm/init.c	2004-08-07 23:26:04.000000000 +0000
+++ linux-2.4.28-pre3/arch/sparc64/mm/init.c	2004-09-10 19:34:04.000000000 +0000
@@ -63,6 +63,7 @@ unsigned long tlb_context_cache = CTX_FI
 unsigned long mmu_context_bmap[CTX_BMAP_SLOTS];
 
 /* Initial ramdisk setup */
+extern unsigned long sparc_ramdisk_image64;
 extern unsigned int sparc_ramdisk_image;
 extern unsigned int sparc_ramdisk_size;
 
@@ -1251,10 +1252,12 @@ unsigned long __init bootmem_init(unsign
 
 #ifdef CONFIG_BLK_DEV_INITRD
 	/* Now have to check initial ramdisk, so that bootmap does not overwrite it */
-	if (sparc_ramdisk_image) {
-		if (sparc_ramdisk_image >= (unsigned long)&_end - 2 * PAGE_SIZE)
-			sparc_ramdisk_image -= KERNBASE;
-		initrd_start = sparc_ramdisk_image + phys_base;
+	if (sparc_ramdisk_image || sparc_ramdisk_image64) {
+		unsigned long ramdisk_image = sparc_ramdisk_image ?
+			sparc_ramdisk_image : sparc_ramdisk_image64;
+		if (ramdisk_image >= (unsigned long)&_end - 2 * PAGE_SIZE)
+			ramdisk_image -= KERNBASE;
+		initrd_start = ramdisk_image + phys_base;
 		initrd_end = initrd_start + sparc_ramdisk_size;
 		if (initrd_end > end_of_phys_memory) {
 			printk(KERN_CRIT "initrd extends beyond end of memory "
@@ -1300,6 +1303,10 @@ unsigned long __init bootmem_init(unsign
 			    initrd_start, size);
 #endif
 		/* Resert the initrd image area. */
+#ifdef CONFIG_DEBUG_BOOTMEM
+		prom_printf("reserve_bootmem(initrd): base[%llx] size[%lx]\n",
+			initrd_start, initrd_end);
+#endif
 		reserve_bootmem(initrd_start, size);
 		*pages_avail -= PAGE_ALIGN(size) >> PAGE_SHIFT;
 
@@ -1353,7 +1360,7 @@ void __init paging_init(void)
 	if ((real_end > ((unsigned long)KERNBASE + 0x400000)))
 		bigkernel = 1;
 #ifdef CONFIG_BLK_DEV_INITRD
-	if (sparc_ramdisk_image)
+	if (sparc_ramdisk_image || sparc_ramdisk_image64)
 		real_end = (PAGE_ALIGN(real_end) + PAGE_ALIGN(sparc_ramdisk_size));
 #endif
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/x86_64/boot/compressed/misc.c linux-2.4.28-pre3/arch/x86_64/boot/compressed/misc.c
--- linux-2.4.27/arch/x86_64/boot/compressed/misc.c	2003-06-13 14:51:32.000000000 +0000
+++ linux-2.4.28-pre3/arch/x86_64/boot/compressed/misc.c	2004-09-10 19:33:29.000000000 +0000
@@ -96,7 +96,7 @@ static void error(char *m);
 static void gzip_mark(void **);
 static void gzip_release(void **);
  
-static void puts(const char *);
+static void putstr(const char *);
   
 extern int end;
 static long free_mem_ptr = (long)&end;
@@ -157,7 +157,7 @@ static void scroll(void)
 		vidmem[i] = ' ';
 }
 
-static void puts(const char *s)
+static void putstr(const char *s)
 {
 	int x,y,pos;
 	char c;
@@ -275,9 +275,9 @@ static void flush_window(void)
 
 static void error(char *x)
 {
-	puts("\n\n");
-	puts(x);
-	puts("\n\n -- System halted");
+	putstr("\n\n");
+	putstr(x);
+	putstr("\n\n -- System halted");
 
 	while(1);
 }
@@ -351,9 +351,9 @@ int decompress_kernel(struct moveparams 
 	else setup_output_buffer_if_we_run_high(mv);
 
 	makecrc();
-	puts(".\nDecompressing Linux...");
+	putstr(".\nDecompressing Linux...");
 	gunzip();
-	puts("done.\nBooting the kernel.\n");
+	putstr("done.\nBooting the kernel.\n");
 	if (high_loaded) close_output_buffer_if_we_run_high(mv);
 	return high_loaded;
 }
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/x86_64/config.in linux-2.4.28-pre3/arch/x86_64/config.in
--- linux-2.4.27/arch/x86_64/config.in	2004-04-14 13:05:28.000000000 +0000
+++ linux-2.4.28-pre3/arch/x86_64/config.in	2004-09-10 19:35:57.000000000 +0000
@@ -117,7 +117,7 @@ if [ "$CONFIG_PROC_FS" = "y" ]; then
    define_bool CONFIG_KCORE_ELF y
 fi
 #tristate 'Kernel support for a.out binaries' CONFIG_BINFMT_AOUT
-tristate 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF
+bool 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF
 tristate 'Kernel support for MISC binaries' CONFIG_BINFMT_MISC
 
 bool 'Power Management support' CONFIG_PM
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/x86_64/ia32/ia32_ioctl.c linux-2.4.28-pre3/arch/x86_64/ia32/ia32_ioctl.c
--- linux-2.4.27/arch/x86_64/ia32/ia32_ioctl.c	2004-04-14 13:05:28.000000000 +0000
+++ linux-2.4.28-pre3/arch/x86_64/ia32/ia32_ioctl.c	2004-09-10 19:36:33.000000000 +0000
@@ -1171,6 +1171,7 @@ static int fd_ioctl_trans(unsigned int f
 		case FDDEFPRM32:
 		case FDGETPRM32:
 		{
+			u32 name;
 			struct floppy_struct *f;
 
 			f = karg = kmalloc(sizeof(struct floppy_struct), GFP_KERNEL);
@@ -1187,7 +1188,8 @@ static int fd_ioctl_trans(unsigned int f
 			err |= __get_user(f->rate, &((struct floppy_struct32 *)arg)->rate);
 			err |= __get_user(f->spec1, &((struct floppy_struct32 *)arg)->spec1);
 			err |= __get_user(f->fmt_gap, &((struct floppy_struct32 *)arg)->fmt_gap);
-			err |= __get_user((u64)f->name, &((struct floppy_struct32 *)arg)->name);
+			err |= __get_user(name, &((struct floppy_struct32 *)arg)->name);
+			f->name = (void*)(u64)name;
 			if (err) {
 				err = -EFAULT;
 				goto out;
@@ -2726,13 +2728,15 @@ static int blkpg_ioctl_trans(unsigned in
 {
 	struct blkpg_ioctl_arg a;
 	struct blkpg_partition p;
+	u32 udata;
 	int err;
 	mm_segment_t old_fs = get_fs();
 
 	err = get_user(a.op, &arg->op);
 	err |= __get_user(a.flags, &arg->flags);
 	err |= __get_user(a.datalen, &arg->datalen);
-	err |= __get_user((long)a.data, &arg->data);
+	err |= __get_user(udata, &arg->data);
+	a.data = (void*)(u64)udata;
 	if (err) return err;
 	switch (a.op) {
 	case BLKPG_ADD_PARTITION:
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/x86_64/ia32/sys_ia32.c linux-2.4.28-pre3/arch/x86_64/ia32/sys_ia32.c
--- linux-2.4.27/arch/x86_64/ia32/sys_ia32.c	2004-04-14 13:05:28.000000000 +0000
+++ linux-2.4.28-pre3/arch/x86_64/ia32/sys_ia32.c	2004-09-10 19:36:38.000000000 +0000
@@ -384,12 +384,16 @@ sys32_rt_sigaction(int sig, struct sigac
 		return -EINVAL;
 
 	if (act) {
+		u32 handler, restorer;
+
 		if (verify_area(VERIFY_READ, act, sizeof(*act)) ||
-		    __get_user((long)new_ka.sa.sa_handler, &act->sa_handler) ||
+		    __get_user(handler, &act->sa_handler) ||
 		    __get_user(new_ka.sa.sa_flags, &act->sa_flags) ||
-		    __get_user((long)new_ka.sa.sa_restorer, &act->sa_restorer)||
+		    __get_user(restorer, &act->sa_restorer)||
 		    __copy_from_user(&set32, &act->sa_mask, sizeof(sigset32_t)))
 			return -EFAULT;
+		new_ka.sa.sa_handler = (void*)(u64)handler;
+		new_ka.sa.sa_restorer = (void*)(u64)restorer;
 
 		/* FIXME: here we rely on _IA32_NSIG_WORS to be >= than _NSIG_WORDS << 1 */
 		switch (_NSIG_WORDS) {
@@ -441,13 +445,16 @@ sys32_sigaction (int sig, struct old_sig
 
         if (act) {
 		old_sigset32_t mask;
+		u32 handler, restorer;
 
 		if (verify_area(VERIFY_READ, act, sizeof(*act)) ||
-		    __get_user((long)new_ka.sa.sa_handler, &act->sa_handler) ||
+		    __get_user(handler, &act->sa_handler) ||
 		    __get_user(new_ka.sa.sa_flags, &act->sa_flags) ||
-		    __get_user((long)new_ka.sa.sa_restorer, &act->sa_restorer) ||
+		    __get_user(restorer, &act->sa_restorer) ||
 		    __get_user(mask, &act->sa_mask))
 			return -EFAULT;
+		new_ka.sa.sa_handler = (void*)(u64)handler;
+		new_ka.sa.sa_restorer = (void*)(u64)restorer;
 		siginitset(&new_ka.sa.sa_mask, mask);
         }
 
@@ -778,7 +785,7 @@ filldir32 (void *__buf, const char *name
 	put_user(reclen, &dirent->d_reclen);
 	copy_to_user(dirent->d_name, name, namlen);
 	put_user(0, dirent->d_name + namlen);
-	((char *) dirent) += reclen;
+	dirent = ((void *)dirent) + reclen;
 	buf->current_dir = dirent;
 	buf->count -= reclen;
 	return 0;
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/x86_64/kernel/x8664_ksyms.c linux-2.4.28-pre3/arch/x86_64/kernel/x8664_ksyms.c
--- linux-2.4.27/arch/x86_64/kernel/x8664_ksyms.c	2004-04-14 13:05:28.000000000 +0000
+++ linux-2.4.28-pre3/arch/x86_64/kernel/x8664_ksyms.c	2004-09-10 19:35:33.000000000 +0000
@@ -157,7 +157,7 @@ extern void * memset(void *,int,__kernel
 extern __kernel_size_t strlen(const char *);
 extern int strcmp(const char *,const char *);
 extern char * strcpy(char *,const char *);
-extern char * bcopy(const char * src, char * dest, int count);
+extern void bcopy(const void * src, void * dest, size_t count);
 
 EXPORT_SYMBOL_NOVERS(memcpy);
 EXPORT_SYMBOL_NOVERS(__memcpy);
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/arch/x86_64/lib/usercopy.c linux-2.4.28-pre3/arch/x86_64/lib/usercopy.c
--- linux-2.4.27/arch/x86_64/lib/usercopy.c	2004-04-14 13:05:28.000000000 +0000
+++ linux-2.4.28-pre3/arch/x86_64/lib/usercopy.c	2004-09-10 19:35:20.000000000 +0000
@@ -88,7 +88,7 @@ unsigned long __clear_user(void *addr, u
 		"	.quad 1b,2b\n"
 		".previous"
 		: [size8] "=c"(size), [dst] "=&D" (__d0)
-		: [size1] "r"(size & 7), "[size8]" (size / 8), "[dst] "(addr),
+		: [size1] "r"(size & 7), "[size8]" (size / 8), "[dst]"(addr),
 		  [zero] "r" (0UL), [eight] "r" (8UL));
 	return size;
 }
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/crypto/Config.in linux-2.4.28-pre3/crypto/Config.in
--- linux-2.4.27/crypto/Config.in	2004-08-07 23:26:04.000000000 +0000
+++ linux-2.4.28-pre3/crypto/Config.in	2004-09-10 19:36:44.000000000 +0000
@@ -58,6 +58,7 @@ if [ "$CONFIG_CRYPTO" = "y" ]; then
   fi
   tristate       '  SHA256 digest algorithm' CONFIG_CRYPTO_SHA256
   tristate       '  SHA384 and SHA512 digest algorithms' CONFIG_CRYPTO_SHA512
+  tristate       '  Whirlpool digest algorithm' CONFIG_CRYPTO_WHIRLPOOL
   if [ "$CONFIG_INET_ESP" = "y" -o \
        "$CONFIG_INET_ESP" = "m" -o \
        "$CONFIG_INET6_ESP" = "y" -o \
@@ -73,6 +74,7 @@ if [ "$CONFIG_CRYPTO" = "y" ]; then
   tristate       '  CAST5 (CAST-128) cipher algorithm' CONFIG_CRYPTO_CAST5
   tristate       '  CAST6 (CAST-256) cipher algorithm' CONFIG_CRYPTO_CAST6
   tristate       '  TEA and XTEA cipher algorithms' CONFIG_CRYPTO_TEA
+  tristate       '  Khazad cipher algorithm' CONFIG_CRYPTO_KHAZAD
   tristate       '  ARC4 cipher algorithm' CONFIG_CRYPTO_ARC4
   if [ "$CONFIG_INET_IPCOMP" = "y" -o \
        "$CONFIG_INET_IPCOMP" = "m" -o \
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/crypto/Makefile linux-2.4.28-pre3/crypto/Makefile
--- linux-2.4.27/crypto/Makefile	2004-08-07 23:26:04.000000000 +0000
+++ linux-2.4.28-pre3/crypto/Makefile	2004-09-10 19:33:26.000000000 +0000
@@ -19,6 +19,7 @@ obj-$(CONFIG_CRYPTO_MD5) += md5.o
 obj-$(CONFIG_CRYPTO_SHA1) += sha1.o
 obj-$(CONFIG_CRYPTO_SHA256) += sha256.o
 obj-$(CONFIG_CRYPTO_SHA512) += sha512.o
+obj-$(CONFIG_CRYPTO_WHIRLPOOL) += whirlpool.o
 obj-$(CONFIG_CRYPTO_DES) += des.o
 obj-$(CONFIG_CRYPTO_BLOWFISH) += blowfish.o
 obj-$(CONFIG_CRYPTO_TWOFISH) += twofish.o
@@ -28,6 +29,7 @@ obj-$(CONFIG_CRYPTO_CAST5) += cast5.o
 obj-$(CONFIG_CRYPTO_CAST6) += cast6.o
 obj-$(CONFIG_CRYPTO_ARC4) += arc4.o
 obj-$(CONFIG_CRYPTO_TEA) += tea.o
+obj-$(CONFIG_CRYPTO_KHAZAD) += khazad.o
 obj-$(CONFIG_CRYPTO_DEFLATE) += deflate.o
 obj-$(CONFIG_CRYPTO_MICHAEL_MIC) += michael_mic.o
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/crypto/aes.c linux-2.4.28-pre3/crypto/aes.c
--- linux-2.4.27/crypto/aes.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.28-pre3/crypto/aes.c	2004-09-10 19:33:05.000000000 +0000
@@ -160,7 +160,7 @@ gen_tabs (void)
 	u8 p, q;
 
 	/* log and power tables for GF(2**8) finite field with
-	   0x011b as modular polynomial - the simplest prmitive
+	   0x011b as modular polynomial - the simplest primitive
 	   root is 0x03, used here to generate the tables */
 
 	for (i = 0, p = 1; i < 256; ++i) {
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/crypto/arc4.c linux-2.4.28-pre3/crypto/arc4.c
--- linux-2.4.27/crypto/arc4.c	2004-04-14 13:05:28.000000000 +0000
+++ linux-2.4.28-pre3/crypto/arc4.c	2004-09-10 19:34:57.000000000 +0000
@@ -3,7 +3,7 @@
  *
  * ARC4 Cipher Algorithm
  *
- * Jon Oberheide <jon@focalhost.com>
+ * Jon Oberheide <jon@oberheide.org>
  *
  * 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
@@ -100,4 +100,4 @@ module_exit(arc4_exit);
 
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("ARC4 Cipher Algorithm");
-MODULE_AUTHOR("Jon Oberheide <jon@focalhost.com>");
+MODULE_AUTHOR("Jon Oberheide <jon@oberheide.org>");
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/crypto/blowfish.c linux-2.4.28-pre3/crypto/blowfish.c
--- linux-2.4.27/crypto/blowfish.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.28-pre3/crypto/blowfish.c	2004-09-10 19:35:48.000000000 +0000
@@ -3,9 +3,9 @@
  *
  * Blowfish Cipher Algorithm, by Bruce Schneier.
  * http://www.counterpane.com/blowfish.html
- * 
- * Adapated from Kerneli implementation.
- * 
+ *
+ * Adapted from Kerneli implementation.
+ *
  * Copyright (c) Herbert Valerio Riedel <hvr@hvrlab.org>
  * Copyright (c) Kyle McMartin <kyle@debian.org>
  * Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/crypto/khazad.c linux-2.4.28-pre3/crypto/khazad.c
--- linux-2.4.27/crypto/khazad.c	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.28-pre3/crypto/khazad.c	2004-09-10 19:35:59.000000000 +0000
@@ -0,0 +1,915 @@
+/*
+ * Cryptographic API.
+ *
+ * Khazad Algorithm
+ *
+ * The Khazad algorithm was developed by Paulo S. L. M. Barreto and
+ * Vincent Rijmen.  It was a finalist in the NESSIE encryption contest.
+ *
+ * The original authors have disclaimed all copyright interest in this
+ * code and thus put it in the public domain. The subsequent authors
+ * have put this under the GNU General Public License.
+ *
+ * By Aaron Grothe ajgrothe@yahoo.com, August 1, 2004
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/mm.h>
+#include <asm/scatterlist.h>
+#include <linux/crypto.h>
+
+#define KHAZAD_KEY_SIZE		16
+#define KHAZAD_BLOCK_SIZE	8
+#define KHAZAD_ROUNDS		8
+
+struct khazad_ctx {
+	u64 E[KHAZAD_ROUNDS + 1];
+	u64 D[KHAZAD_ROUNDS + 1];
+};
+
+static const u64 T0[256] = {
+	0xbad3d268bbb96a01ULL, 0x54fc4d19e59a66b1ULL, 0x2f71bc93e26514cdULL,
+	0x749ccdb925871b51ULL, 0x53f55102f7a257a4ULL, 0xd3686bb8d0d6be03ULL,
+	0xd26b6fbdd6deb504ULL, 0x4dd72964b35285feULL, 0x50f05d0dfdba4aadULL,
+	0xace98a26cf09e063ULL, 0x8d8a0e83091c9684ULL, 0xbfdcc679a5914d1aULL,
+	0x7090ddad3da7374dULL, 0x52f65507f1aa5ca3ULL, 0x9ab352c87ba417e1ULL,
+	0x4cd42d61b55a8ef9ULL, 0xea238f65460320acULL, 0xd56273a6c4e68411ULL,
+	0x97a466f155cc68c2ULL, 0xd16e63b2dcc6a80dULL, 0x3355ccffaa85d099ULL,
+	0x51f35908fbb241aaULL, 0x5bed712ac7e20f9cULL, 0xa6f7a204f359ae55ULL,
+	0xde7f5f81febec120ULL, 0x48d83d75ad7aa2e5ULL, 0xa8e59a32d729cc7fULL,
+	0x99b65ec771bc0ae8ULL, 0xdb704b90e096e63bULL, 0x3256c8faac8ddb9eULL,
+	0xb7c4e65195d11522ULL, 0xfc19d72b32b3aaceULL, 0xe338ab48704b7393ULL,
+	0x9ebf42dc63843bfdULL, 0x91ae7eef41fc52d0ULL, 0x9bb056cd7dac1ce6ULL,
+	0xe23baf4d76437894ULL, 0xbbd0d66dbdb16106ULL, 0x41c319589b32f1daULL,
+	0x6eb2a5cb7957e517ULL, 0xa5f2ae0bf941b35cULL, 0xcb400bc08016564bULL,
+	0x6bbdb1da677fc20cULL, 0x95a26efb59dc7eccULL, 0xa1febe1fe1619f40ULL,
+	0xf308eb1810cbc3e3ULL, 0xb1cefe4f81e12f30ULL, 0x0206080a0c10160eULL,
+	0xcc4917db922e675eULL, 0xc45137f3a26e3f66ULL, 0x1d2774694ee8cf53ULL,
+	0x143c504478a09c6cULL, 0xc3582be8b0560e73ULL, 0x63a591f2573f9a34ULL,
+	0xda734f95e69eed3cULL, 0x5de76934d3d2358eULL, 0x5fe1613edfc22380ULL,
+	0xdc79578bf2aed72eULL, 0x7d87e99413cf486eULL, 0xcd4a13de94266c59ULL,
+	0x7f81e19e1fdf5e60ULL, 0x5aee752fc1ea049bULL, 0x6cb4adc17547f319ULL,
+	0x5ce46d31d5da3e89ULL, 0xf704fb0c08ebefffULL, 0x266a98bed42d47f2ULL,
+	0xff1cdb2438abb7c7ULL, 0xed2a937e543b11b9ULL, 0xe825876f4a1336a2ULL,
+	0x9dba4ed3699c26f4ULL, 0x6fb1a1ce7f5fee10ULL, 0x8e8f028c03048b8dULL,
+	0x192b647d56c8e34fULL, 0xa0fdba1ae7699447ULL, 0xf00de7171ad3deeaULL,
+	0x89861e97113cba98ULL, 0x0f113c332278692dULL, 0x07091c1b12383115ULL,
+	0xafec8629c511fd6aULL, 0xfb10cb30208b9bdbULL, 0x0818202830405838ULL,
+	0x153f54417ea8976bULL, 0x0d1734392e687f23ULL, 0x040c101418202c1cULL,
+	0x0103040506080b07ULL, 0x64ac8de94507ab21ULL, 0xdf7c5b84f8b6ca27ULL,
+	0x769ac5b329970d5fULL, 0x798bf9800bef6472ULL, 0xdd7a538ef4a6dc29ULL,
+	0x3d47f4c98ef5b2b3ULL, 0x163a584e74b08a62ULL, 0x3f41fcc382e5a4bdULL,
+	0x3759dcebb2a5fc85ULL, 0x6db7a9c4734ff81eULL, 0x3848e0d890dd95a8ULL,
+	0xb9d6de67b1a17708ULL, 0x7395d1a237bf2a44ULL, 0xe926836a4c1b3da5ULL,
+	0x355fd4e1beb5ea8bULL, 0x55ff491ce3926db6ULL, 0x7193d9a83baf3c4aULL,
+	0x7b8df18a07ff727cULL, 0x8c890a860f149d83ULL, 0x7296d5a731b72143ULL,
+	0x88851a921734b19fULL, 0xf607ff090ee3e4f8ULL, 0x2a7ea882fc4d33d6ULL,
+	0x3e42f8c684edafbaULL, 0x5ee2653bd9ca2887ULL, 0x27699cbbd2254cf5ULL,
+	0x46ca0543890ac0cfULL, 0x0c14303c28607424ULL, 0x65af89ec430fa026ULL,
+	0x68b8bdd56d67df05ULL, 0x61a399f85b2f8c3aULL, 0x03050c0f0a181d09ULL,
+	0xc15e23e2bc46187dULL, 0x57f94116ef827bb8ULL, 0xd6677fa9cefe9918ULL,
+	0xd976439aec86f035ULL, 0x58e87d25cdfa1295ULL, 0xd875479fea8efb32ULL,
+	0x66aa85e34917bd2fULL, 0xd7647bacc8f6921fULL, 0x3a4ee8d29ccd83a6ULL,
+	0xc84507cf8a0e4b42ULL, 0x3c44f0cc88fdb9b4ULL, 0xfa13cf35268390dcULL,
+	0x96a762f453c463c5ULL, 0xa7f4a601f551a552ULL, 0x98b55ac277b401efULL,
+	0xec29977b52331abeULL, 0xb8d5da62b7a97c0fULL, 0xc7543bfca876226fULL,
+	0xaeef822cc319f66dULL, 0x69bbb9d06b6fd402ULL, 0x4bdd317aa762bfecULL,
+	0xabe0963ddd31d176ULL, 0xa9e69e37d121c778ULL, 0x67a981e64f1fb628ULL,
+	0x0a1e28223c504e36ULL, 0x47c901468f02cbc8ULL, 0xf20bef1d16c3c8e4ULL,
+	0xb5c2ee5b99c1032cULL, 0x226688aacc0d6beeULL, 0xe532b356647b4981ULL,
+	0xee2f9f715e230cb0ULL, 0xbedfc27ca399461dULL, 0x2b7dac87fa4538d1ULL,
+	0x819e3ebf217ce2a0ULL, 0x1236485a6c90a67eULL, 0x839836b52d6cf4aeULL,
+	0x1b2d6c775ad8f541ULL, 0x0e1238362470622aULL, 0x23658cafca0560e9ULL,
+	0xf502f30604fbf9f1ULL, 0x45cf094c8312ddc6ULL, 0x216384a5c61576e7ULL,
+	0xce4f1fd19e3e7150ULL, 0x49db3970ab72a9e2ULL, 0x2c74b09ce87d09c4ULL,
+	0xf916c33a2c9b8dd5ULL, 0xe637bf596e635488ULL, 0xb6c7e25493d91e25ULL,
+	0x2878a088f05d25d8ULL, 0x17395c4b72b88165ULL, 0x829b32b02b64ffa9ULL,
+	0x1a2e68725cd0fe46ULL, 0x8b80169d1d2cac96ULL, 0xfe1fdf213ea3bcc0ULL,
+	0x8a8312981b24a791ULL, 0x091b242d3648533fULL, 0xc94603ca8c064045ULL,
+	0x879426a1354cd8b2ULL, 0x4ed2256bb94a98f7ULL, 0xe13ea3427c5b659dULL,
+	0x2e72b896e46d1fcaULL, 0xe431b75362734286ULL, 0xe03da7477a536e9aULL,
+	0xeb208b60400b2babULL, 0x90ad7aea47f459d7ULL, 0xa4f1aa0eff49b85bULL,
+	0x1e22786644f0d25aULL, 0x85922eab395ccebcULL, 0x60a09dfd5d27873dULL,
+	0x0000000000000000ULL, 0x256f94b1de355afbULL, 0xf401f70302f3f2f6ULL,
+	0xf10ee3121cdbd5edULL, 0x94a16afe5fd475cbULL, 0x0b1d2c273a584531ULL,
+	0xe734bb5c686b5f8fULL, 0x759fc9bc238f1056ULL, 0xef2c9b74582b07b7ULL,
+	0x345cd0e4b8bde18cULL, 0x3153c4f5a695c697ULL, 0xd46177a3c2ee8f16ULL,
+	0xd06d67b7dacea30aULL, 0x869722a43344d3b5ULL, 0x7e82e59b19d75567ULL,
+	0xadea8e23c901eb64ULL, 0xfd1ad32e34bba1c9ULL, 0x297ba48df6552edfULL,
+	0x3050c0f0a09dcd90ULL, 0x3b4decd79ac588a1ULL, 0x9fbc46d9658c30faULL,
+	0xf815c73f2a9386d2ULL, 0xc6573ff9ae7e2968ULL, 0x13354c5f6a98ad79ULL,
+	0x060a181e14303a12ULL, 0x050f14111e28271bULL, 0xc55233f6a4663461ULL,
+	0x113344556688bb77ULL, 0x7799c1b62f9f0658ULL, 0x7c84ed9115c74369ULL,
+	0x7a8ef58f01f7797bULL, 0x7888fd850de76f75ULL, 0x365ad8eeb4adf782ULL,
+	0x1c24706c48e0c454ULL, 0x394be4dd96d59eafULL, 0x59eb7920cbf21992ULL,
+	0x1828607850c0e848ULL, 0x56fa4513e98a70bfULL, 0xb3c8f6458df1393eULL,
+	0xb0cdfa4a87e92437ULL, 0x246c90b4d83d51fcULL, 0x206080a0c01d7de0ULL,
+	0xb2cbf2408bf93239ULL, 0x92ab72e04be44fd9ULL, 0xa3f8b615ed71894eULL,
+	0xc05d27e7ba4e137aULL, 0x44cc0d49851ad6c1ULL, 0x62a695f751379133ULL,
+	0x103040506080b070ULL, 0xb4c1ea5e9fc9082bULL, 0x84912aae3f54c5bbULL,
+	0x43c511529722e7d4ULL, 0x93a876e54dec44deULL, 0xc25b2fedb65e0574ULL,
+	0x4ade357fa16ab4ebULL, 0xbddace73a9815b14ULL, 0x8f8c0689050c808aULL,
+	0x2d77b499ee7502c3ULL, 0xbcd9ca76af895013ULL, 0x9cb94ad66f942df3ULL,
+	0x6abeb5df6177c90bULL, 0x40c01d5d9d3afaddULL, 0xcf4c1bd498367a57ULL,
+	0xa2fbb210eb798249ULL, 0x809d3aba2774e9a7ULL, 0x4fd1216ebf4293f0ULL,
+	0x1f217c6342f8d95dULL, 0xca430fc5861e5d4cULL, 0xaae39238db39da71ULL,
+	0x42c61557912aecd3ULL
+};
+
+static const u64 T1[256] = {
+	0xd3ba68d2b9bb016aULL, 0xfc54194d9ae5b166ULL, 0x712f93bc65e2cd14ULL,
+	0x9c74b9cd8725511bULL, 0xf5530251a2f7a457ULL, 0x68d3b86bd6d003beULL,
+	0x6bd2bd6fded604b5ULL, 0xd74d642952b3fe85ULL, 0xf0500d5dbafdad4aULL,
+	0xe9ac268a09cf63e0ULL, 0x8a8d830e1c098496ULL, 0xdcbf79c691a51a4dULL,
+	0x9070addda73d4d37ULL, 0xf6520755aaf1a35cULL, 0xb39ac852a47be117ULL,
+	0xd44c612d5ab5f98eULL, 0x23ea658f0346ac20ULL, 0x62d5a673e6c41184ULL,
+	0xa497f166cc55c268ULL, 0x6ed1b263c6dc0da8ULL, 0x5533ffcc85aa99d0ULL,
+	0xf3510859b2fbaa41ULL, 0xed5b2a71e2c79c0fULL, 0xf7a604a259f355aeULL,
+	0x7fde815fbefe20c1ULL, 0xd848753d7aade5a2ULL, 0xe5a8329a29d77fccULL,
+	0xb699c75ebc71e80aULL, 0x70db904b96e03be6ULL, 0x5632fac88dac9edbULL,
+	0xc4b751e6d1952215ULL, 0x19fc2bd7b332ceaaULL, 0x38e348ab4b709373ULL,
+	0xbf9edc428463fd3bULL, 0xae91ef7efc41d052ULL, 0xb09bcd56ac7de61cULL,
+	0x3be24daf43769478ULL, 0xd0bb6dd6b1bd0661ULL, 0xc3415819329bdaf1ULL,
+	0xb26ecba5577917e5ULL, 0xf2a50bae41f95cb3ULL, 0x40cbc00b16804b56ULL,
+	0xbd6bdab17f670cc2ULL, 0xa295fb6edc59cc7eULL, 0xfea11fbe61e1409fULL,
+	0x08f318ebcb10e3c3ULL, 0xceb14ffee181302fULL, 0x06020a08100c0e16ULL,
+	0x49ccdb172e925e67ULL, 0x51c4f3376ea2663fULL, 0x271d6974e84e53cfULL,
+	0x3c144450a0786c9cULL, 0x58c3e82b56b0730eULL, 0xa563f2913f57349aULL,
+	0x73da954f9ee63cedULL, 0xe75d3469d2d38e35ULL, 0xe15f3e61c2df8023ULL,
+	0x79dc8b57aef22ed7ULL, 0x877d94e9cf136e48ULL, 0x4acdde132694596cULL,
+	0x817f9ee1df1f605eULL, 0xee5a2f75eac19b04ULL, 0xb46cc1ad477519f3ULL,
+	0xe45c316ddad5893eULL, 0x04f70cfbeb08ffefULL, 0x6a26be982dd4f247ULL,
+	0x1cff24dbab38c7b7ULL, 0x2aed7e933b54b911ULL, 0x25e86f87134aa236ULL,
+	0xba9dd34e9c69f426ULL, 0xb16fcea15f7f10eeULL, 0x8f8e8c0204038d8bULL,
+	0x2b197d64c8564fe3ULL, 0xfda01aba69e74794ULL, 0x0df017e7d31aeadeULL,
+	0x8689971e3c1198baULL, 0x110f333c78222d69ULL, 0x09071b1c38121531ULL,
+	0xecaf298611c56afdULL, 0x10fb30cb8b20db9bULL, 0x1808282040303858ULL,
+	0x3f154154a87e6b97ULL, 0x170d3934682e237fULL, 0x0c04141020181c2cULL,
+	0x030105040806070bULL, 0xac64e98d074521abULL, 0x7cdf845bb6f827caULL,
+	0x9a76b3c597295f0dULL, 0x8b7980f9ef0b7264ULL, 0x7add8e53a6f429dcULL,
+	0x473dc9f4f58eb3b2ULL, 0x3a164e58b074628aULL, 0x413fc3fce582bda4ULL,
+	0x5937ebdca5b285fcULL, 0xb76dc4a94f731ef8ULL, 0x4838d8e0dd90a895ULL,
+	0xd6b967dea1b10877ULL, 0x9573a2d1bf37442aULL, 0x26e96a831b4ca53dULL,
+	0x5f35e1d4b5be8beaULL, 0xff551c4992e3b66dULL, 0x9371a8d9af3b4a3cULL,
+	0x8d7b8af1ff077c72ULL, 0x898c860a140f839dULL, 0x9672a7d5b7314321ULL,
+	0x8588921a34179fb1ULL, 0x07f609ffe30ef8e4ULL, 0x7e2a82a84dfcd633ULL,
+	0x423ec6f8ed84baafULL, 0xe25e3b65cad98728ULL, 0x6927bb9c25d2f54cULL,
+	0xca4643050a89cfc0ULL, 0x140c3c3060282474ULL, 0xaf65ec890f4326a0ULL,
+	0xb868d5bd676d05dfULL, 0xa361f8992f5b3a8cULL, 0x05030f0c180a091dULL,
+	0x5ec1e22346bc7d18ULL, 0xf957164182efb87bULL, 0x67d6a97ffece1899ULL,
+	0x76d99a4386ec35f0ULL, 0xe858257dfacd9512ULL, 0x75d89f478eea32fbULL,
+	0xaa66e38517492fbdULL, 0x64d7ac7bf6c81f92ULL, 0x4e3ad2e8cd9ca683ULL,
+	0x45c8cf070e8a424bULL, 0x443cccf0fd88b4b9ULL, 0x13fa35cf8326dc90ULL,
+	0xa796f462c453c563ULL, 0xf4a701a651f552a5ULL, 0xb598c25ab477ef01ULL,
+	0x29ec7b973352be1aULL, 0xd5b862daa9b70f7cULL, 0x54c7fc3b76a86f22ULL,
+	0xefae2c8219c36df6ULL, 0xbb69d0b96f6b02d4ULL, 0xdd4b7a3162a7ecbfULL,
+	0xe0ab3d9631dd76d1ULL, 0xe6a9379e21d178c7ULL, 0xa967e6811f4f28b6ULL,
+	0x1e0a2228503c364eULL, 0xc9474601028fc8cbULL, 0x0bf21defc316e4c8ULL,
+	0xc2b55beec1992c03ULL, 0x6622aa880dccee6bULL, 0x32e556b37b648149ULL,
+	0x2fee719f235eb00cULL, 0xdfbe7cc299a31d46ULL, 0x7d2b87ac45fad138ULL,
+	0x9e81bf3e7c21a0e2ULL, 0x36125a48906c7ea6ULL, 0x9883b5366c2daef4ULL,
+	0x2d1b776cd85a41f5ULL, 0x120e363870242a62ULL, 0x6523af8c05cae960ULL,
+	0x02f506f3fb04f1f9ULL, 0xcf454c091283c6ddULL, 0x6321a58415c6e776ULL,
+	0x4fced11f3e9e5071ULL, 0xdb49703972abe2a9ULL, 0x742c9cb07de8c409ULL,
+	0x16f93ac39b2cd58dULL, 0x37e659bf636e8854ULL, 0xc7b654e2d993251eULL,
+	0x782888a05df0d825ULL, 0x39174b5cb8726581ULL, 0x9b82b032642ba9ffULL,
+	0x2e1a7268d05c46feULL, 0x808b9d162c1d96acULL, 0x1ffe21dfa33ec0bcULL,
+	0x838a9812241b91a7ULL, 0x1b092d2448363f53ULL, 0x46c9ca03068c4540ULL,
+	0x9487a1264c35b2d8ULL, 0xd24e6b254ab9f798ULL, 0x3ee142a35b7c9d65ULL,
+	0x722e96b86de4ca1fULL, 0x31e453b773628642ULL, 0x3de047a7537a9a6eULL,
+	0x20eb608b0b40ab2bULL, 0xad90ea7af447d759ULL, 0xf1a40eaa49ff5bb8ULL,
+	0x221e6678f0445ad2ULL, 0x9285ab2e5c39bcceULL, 0xa060fd9d275d3d87ULL,
+	0x0000000000000000ULL, 0x6f25b19435defb5aULL, 0x01f403f7f302f6f2ULL,
+	0x0ef112e3db1cedd5ULL, 0xa194fe6ad45fcb75ULL, 0x1d0b272c583a3145ULL,
+	0x34e75cbb6b688f5fULL, 0x9f75bcc98f235610ULL, 0x2cef749b2b58b707ULL,
+	0x5c34e4d0bdb88ce1ULL, 0x5331f5c495a697c6ULL, 0x61d4a377eec2168fULL,
+	0x6dd0b767ceda0aa3ULL, 0x9786a4224433b5d3ULL, 0x827e9be5d7196755ULL,
+	0xeaad238e01c964ebULL, 0x1afd2ed3bb34c9a1ULL, 0x7b298da455f6df2eULL,
+	0x5030f0c09da090cdULL, 0x4d3bd7ecc59aa188ULL, 0xbc9fd9468c65fa30ULL,
+	0x15f83fc7932ad286ULL, 0x57c6f93f7eae6829ULL, 0x35135f4c986a79adULL,
+	0x0a061e183014123aULL, 0x0f051114281e1b27ULL, 0x52c5f63366a46134ULL,
+	0x33115544886677bbULL, 0x9977b6c19f2f5806ULL, 0x847c91edc7156943ULL,
+	0x8e7a8ff5f7017b79ULL, 0x887885fde70d756fULL, 0x5a36eed8adb482f7ULL,
+	0x241c6c70e04854c4ULL, 0x4b39dde4d596af9eULL, 0xeb592079f2cb9219ULL,
+	0x28187860c05048e8ULL, 0xfa5613458ae9bf70ULL, 0xc8b345f6f18d3e39ULL,
+	0xcdb04afae9873724ULL, 0x6c24b4903dd8fc51ULL, 0x6020a0801dc0e07dULL,
+	0xcbb240f2f98b3932ULL, 0xab92e072e44bd94fULL, 0xf8a315b671ed4e89ULL,
+	0x5dc0e7274eba7a13ULL, 0xcc44490d1a85c1d6ULL, 0xa662f79537513391ULL,
+	0x30105040806070b0ULL, 0xc1b45eeac99f2b08ULL, 0x9184ae2a543fbbc5ULL,
+	0xc54352112297d4e7ULL, 0xa893e576ec4dde44ULL, 0x5bc2ed2f5eb67405ULL,
+	0xde4a7f356aa1ebb4ULL, 0xdabd73ce81a9145bULL, 0x8c8f89060c058a80ULL,
+	0x772d99b475eec302ULL, 0xd9bc76ca89af1350ULL, 0xb99cd64a946ff32dULL,
+	0xbe6adfb577610bc9ULL, 0xc0405d1d3a9dddfaULL, 0x4ccfd41b3698577aULL,
+	0xfba210b279eb4982ULL, 0x9d80ba3a7427a7e9ULL, 0xd14f6e2142bff093ULL,
+	0x211f637cf8425dd9ULL, 0x43cac50f1e864c5dULL, 0xe3aa389239db71daULL,
+	0xc64257152a91d3ecULL
+};
+
+static const u64 T2[256] = {
+	0xd268bad36a01bbb9ULL, 0x4d1954fc66b1e59aULL, 0xbc932f7114cde265ULL,
+	0xcdb9749c1b512587ULL, 0x510253f557a4f7a2ULL, 0x6bb8d368be03d0d6ULL,
+	0x6fbdd26bb504d6deULL, 0x29644dd785feb352ULL, 0x5d0d50f04aadfdbaULL,
+	0x8a26ace9e063cf09ULL, 0x0e838d8a9684091cULL, 0xc679bfdc4d1aa591ULL,
+	0xddad7090374d3da7ULL, 0x550752f65ca3f1aaULL, 0x52c89ab317e17ba4ULL,
+	0x2d614cd48ef9b55aULL, 0x8f65ea2320ac4603ULL, 0x73a6d5628411c4e6ULL,
+	0x66f197a468c255ccULL, 0x63b2d16ea80ddcc6ULL, 0xccff3355d099aa85ULL,
+	0x590851f341aafbb2ULL, 0x712a5bed0f9cc7e2ULL, 0xa204a6f7ae55f359ULL,
+	0x5f81de7fc120febeULL, 0x3d7548d8a2e5ad7aULL, 0x9a32a8e5cc7fd729ULL,
+	0x5ec799b60ae871bcULL, 0x4b90db70e63be096ULL, 0xc8fa3256db9eac8dULL,
+	0xe651b7c4152295d1ULL, 0xd72bfc19aace32b3ULL, 0xab48e3387393704bULL,
+	0x42dc9ebf3bfd6384ULL, 0x7eef91ae52d041fcULL, 0x56cd9bb01ce67dacULL,
+	0xaf4de23b78947643ULL, 0xd66dbbd06106bdb1ULL, 0x195841c3f1da9b32ULL,
+	0xa5cb6eb2e5177957ULL, 0xae0ba5f2b35cf941ULL, 0x0bc0cb40564b8016ULL,
+	0xb1da6bbdc20c677fULL, 0x6efb95a27ecc59dcULL, 0xbe1fa1fe9f40e161ULL,
+	0xeb18f308c3e310cbULL, 0xfe4fb1ce2f3081e1ULL, 0x080a0206160e0c10ULL,
+	0x17dbcc49675e922eULL, 0x37f3c4513f66a26eULL, 0x74691d27cf534ee8ULL,
+	0x5044143c9c6c78a0ULL, 0x2be8c3580e73b056ULL, 0x91f263a59a34573fULL,
+	0x4f95da73ed3ce69eULL, 0x69345de7358ed3d2ULL, 0x613e5fe12380dfc2ULL,
+	0x578bdc79d72ef2aeULL, 0xe9947d87486e13cfULL, 0x13decd4a6c599426ULL,
+	0xe19e7f815e601fdfULL, 0x752f5aee049bc1eaULL, 0xadc16cb4f3197547ULL,
+	0x6d315ce43e89d5daULL, 0xfb0cf704efff08ebULL, 0x98be266a47f2d42dULL,
+	0xdb24ff1cb7c738abULL, 0x937eed2a11b9543bULL, 0x876fe82536a24a13ULL,
+	0x4ed39dba26f4699cULL, 0xa1ce6fb1ee107f5fULL, 0x028c8e8f8b8d0304ULL,
+	0x647d192be34f56c8ULL, 0xba1aa0fd9447e769ULL, 0xe717f00ddeea1ad3ULL,
+	0x1e978986ba98113cULL, 0x3c330f11692d2278ULL, 0x1c1b070931151238ULL,
+	0x8629afecfd6ac511ULL, 0xcb30fb109bdb208bULL, 0x2028081858383040ULL,
+	0x5441153f976b7ea8ULL, 0x34390d177f232e68ULL, 0x1014040c2c1c1820ULL,
+	0x040501030b070608ULL, 0x8de964acab214507ULL, 0x5b84df7cca27f8b6ULL,
+	0xc5b3769a0d5f2997ULL, 0xf980798b64720befULL, 0x538edd7adc29f4a6ULL,
+	0xf4c93d47b2b38ef5ULL, 0x584e163a8a6274b0ULL, 0xfcc33f41a4bd82e5ULL,
+	0xdceb3759fc85b2a5ULL, 0xa9c46db7f81e734fULL, 0xe0d8384895a890ddULL,
+	0xde67b9d67708b1a1ULL, 0xd1a273952a4437bfULL, 0x836ae9263da54c1bULL,
+	0xd4e1355fea8bbeb5ULL, 0x491c55ff6db6e392ULL, 0xd9a871933c4a3bafULL,
+	0xf18a7b8d727c07ffULL, 0x0a868c899d830f14ULL, 0xd5a77296214331b7ULL,
+	0x1a928885b19f1734ULL, 0xff09f607e4f80ee3ULL, 0xa8822a7e33d6fc4dULL,
+	0xf8c63e42afba84edULL, 0x653b5ee22887d9caULL, 0x9cbb27694cf5d225ULL,
+	0x054346cac0cf890aULL, 0x303c0c1474242860ULL, 0x89ec65afa026430fULL,
+	0xbdd568b8df056d67ULL, 0x99f861a38c3a5b2fULL, 0x0c0f03051d090a18ULL,
+	0x23e2c15e187dbc46ULL, 0x411657f97bb8ef82ULL, 0x7fa9d6679918cefeULL,
+	0x439ad976f035ec86ULL, 0x7d2558e81295cdfaULL, 0x479fd875fb32ea8eULL,
+	0x85e366aabd2f4917ULL, 0x7bacd764921fc8f6ULL, 0xe8d23a4e83a69ccdULL,
+	0x07cfc8454b428a0eULL, 0xf0cc3c44b9b488fdULL, 0xcf35fa1390dc2683ULL,
+	0x62f496a763c553c4ULL, 0xa601a7f4a552f551ULL, 0x5ac298b501ef77b4ULL,
+	0x977bec291abe5233ULL, 0xda62b8d57c0fb7a9ULL, 0x3bfcc754226fa876ULL,
+	0x822caeeff66dc319ULL, 0xb9d069bbd4026b6fULL, 0x317a4bddbfeca762ULL,
+	0x963dabe0d176dd31ULL, 0x9e37a9e6c778d121ULL, 0x81e667a9b6284f1fULL,
+	0x28220a1e4e363c50ULL, 0x014647c9cbc88f02ULL, 0xef1df20bc8e416c3ULL,
+	0xee5bb5c2032c99c1ULL, 0x88aa22666beecc0dULL, 0xb356e5324981647bULL,
+	0x9f71ee2f0cb05e23ULL, 0xc27cbedf461da399ULL, 0xac872b7d38d1fa45ULL,
+	0x3ebf819ee2a0217cULL, 0x485a1236a67e6c90ULL, 0x36b58398f4ae2d6cULL,
+	0x6c771b2df5415ad8ULL, 0x38360e12622a2470ULL, 0x8caf236560e9ca05ULL,
+	0xf306f502f9f104fbULL, 0x094c45cfddc68312ULL, 0x84a5216376e7c615ULL,
+	0x1fd1ce4f71509e3eULL, 0x397049dba9e2ab72ULL, 0xb09c2c7409c4e87dULL,
+	0xc33af9168dd52c9bULL, 0xbf59e63754886e63ULL, 0xe254b6c71e2593d9ULL,
+	0xa088287825d8f05dULL, 0x5c4b1739816572b8ULL, 0x32b0829bffa92b64ULL,
+	0x68721a2efe465cd0ULL, 0x169d8b80ac961d2cULL, 0xdf21fe1fbcc03ea3ULL,
+	0x12988a83a7911b24ULL, 0x242d091b533f3648ULL, 0x03cac94640458c06ULL,
+	0x26a18794d8b2354cULL, 0x256b4ed298f7b94aULL, 0xa342e13e659d7c5bULL,
+	0xb8962e721fcae46dULL, 0xb753e43142866273ULL, 0xa747e03d6e9a7a53ULL,
+	0x8b60eb202bab400bULL, 0x7aea90ad59d747f4ULL, 0xaa0ea4f1b85bff49ULL,
+	0x78661e22d25a44f0ULL, 0x2eab8592cebc395cULL, 0x9dfd60a0873d5d27ULL,
+	0x0000000000000000ULL, 0x94b1256f5afbde35ULL, 0xf703f401f2f602f3ULL,
+	0xe312f10ed5ed1cdbULL, 0x6afe94a175cb5fd4ULL, 0x2c270b1d45313a58ULL,
+	0xbb5ce7345f8f686bULL, 0xc9bc759f1056238fULL, 0x9b74ef2c07b7582bULL,
+	0xd0e4345ce18cb8bdULL, 0xc4f53153c697a695ULL, 0x77a3d4618f16c2eeULL,
+	0x67b7d06da30adaceULL, 0x22a48697d3b53344ULL, 0xe59b7e82556719d7ULL,
+	0x8e23adeaeb64c901ULL, 0xd32efd1aa1c934bbULL, 0xa48d297b2edff655ULL,
+	0xc0f03050cd90a09dULL, 0xecd73b4d88a19ac5ULL, 0x46d99fbc30fa658cULL,
+	0xc73ff81586d22a93ULL, 0x3ff9c6572968ae7eULL, 0x4c5f1335ad796a98ULL,
+	0x181e060a3a121430ULL, 0x1411050f271b1e28ULL, 0x33f6c5523461a466ULL,
+	0x44551133bb776688ULL, 0xc1b6779906582f9fULL, 0xed917c84436915c7ULL,
+	0xf58f7a8e797b01f7ULL, 0xfd8578886f750de7ULL, 0xd8ee365af782b4adULL,
+	0x706c1c24c45448e0ULL, 0xe4dd394b9eaf96d5ULL, 0x792059eb1992cbf2ULL,
+	0x60781828e84850c0ULL, 0x451356fa70bfe98aULL, 0xf645b3c8393e8df1ULL,
+	0xfa4ab0cd243787e9ULL, 0x90b4246c51fcd83dULL, 0x80a020607de0c01dULL,
+	0xf240b2cb32398bf9ULL, 0x72e092ab4fd94be4ULL, 0xb615a3f8894eed71ULL,
+	0x27e7c05d137aba4eULL, 0x0d4944ccd6c1851aULL, 0x95f762a691335137ULL,
+	0x40501030b0706080ULL, 0xea5eb4c1082b9fc9ULL, 0x2aae8491c5bb3f54ULL,
+	0x115243c5e7d49722ULL, 0x76e593a844de4decULL, 0x2fedc25b0574b65eULL,
+	0x357f4adeb4eba16aULL, 0xce73bdda5b14a981ULL, 0x06898f8c808a050cULL,
+	0xb4992d7702c3ee75ULL, 0xca76bcd95013af89ULL, 0x4ad69cb92df36f94ULL,
+	0xb5df6abec90b6177ULL, 0x1d5d40c0fadd9d3aULL, 0x1bd4cf4c7a579836ULL,
+	0xb210a2fb8249eb79ULL, 0x3aba809de9a72774ULL, 0x216e4fd193f0bf42ULL,
+	0x7c631f21d95d42f8ULL, 0x0fc5ca435d4c861eULL, 0x9238aae3da71db39ULL,
+	0x155742c6ecd3912aULL
+};
+
+static const u64 T3[256] = {
+	0x68d2d3ba016ab9bbULL, 0x194dfc54b1669ae5ULL, 0x93bc712fcd1465e2ULL,
+	0xb9cd9c74511b8725ULL, 0x0251f553a457a2f7ULL, 0xb86b68d303bed6d0ULL,
+	0xbd6f6bd204b5ded6ULL, 0x6429d74dfe8552b3ULL, 0x0d5df050ad4abafdULL,
+	0x268ae9ac63e009cfULL, 0x830e8a8d84961c09ULL, 0x79c6dcbf1a4d91a5ULL,
+	0xaddd90704d37a73dULL, 0x0755f652a35caaf1ULL, 0xc852b39ae117a47bULL,
+	0x612dd44cf98e5ab5ULL, 0x658f23eaac200346ULL, 0xa67362d51184e6c4ULL,
+	0xf166a497c268cc55ULL, 0xb2636ed10da8c6dcULL, 0xffcc553399d085aaULL,
+	0x0859f351aa41b2fbULL, 0x2a71ed5b9c0fe2c7ULL, 0x04a2f7a655ae59f3ULL,
+	0x815f7fde20c1befeULL, 0x753dd848e5a27aadULL, 0x329ae5a87fcc29d7ULL,
+	0xc75eb699e80abc71ULL, 0x904b70db3be696e0ULL, 0xfac856329edb8dacULL,
+	0x51e6c4b72215d195ULL, 0x2bd719fcceaab332ULL, 0x48ab38e393734b70ULL,
+	0xdc42bf9efd3b8463ULL, 0xef7eae91d052fc41ULL, 0xcd56b09be61cac7dULL,
+	0x4daf3be294784376ULL, 0x6dd6d0bb0661b1bdULL, 0x5819c341daf1329bULL,
+	0xcba5b26e17e55779ULL, 0x0baef2a55cb341f9ULL, 0xc00b40cb4b561680ULL,
+	0xdab1bd6b0cc27f67ULL, 0xfb6ea295cc7edc59ULL, 0x1fbefea1409f61e1ULL,
+	0x18eb08f3e3c3cb10ULL, 0x4ffeceb1302fe181ULL, 0x0a0806020e16100cULL,
+	0xdb1749cc5e672e92ULL, 0xf33751c4663f6ea2ULL, 0x6974271d53cfe84eULL,
+	0x44503c146c9ca078ULL, 0xe82b58c3730e56b0ULL, 0xf291a563349a3f57ULL,
+	0x954f73da3ced9ee6ULL, 0x3469e75d8e35d2d3ULL, 0x3e61e15f8023c2dfULL,
+	0x8b5779dc2ed7aef2ULL, 0x94e9877d6e48cf13ULL, 0xde134acd596c2694ULL,
+	0x9ee1817f605edf1fULL, 0x2f75ee5a9b04eac1ULL, 0xc1adb46c19f34775ULL,
+	0x316de45c893edad5ULL, 0x0cfb04f7ffefeb08ULL, 0xbe986a26f2472dd4ULL,
+	0x24db1cffc7b7ab38ULL, 0x7e932aedb9113b54ULL, 0x6f8725e8a236134aULL,
+	0xd34eba9df4269c69ULL, 0xcea1b16f10ee5f7fULL, 0x8c028f8e8d8b0403ULL,
+	0x7d642b194fe3c856ULL, 0x1abafda0479469e7ULL, 0x17e70df0eaded31aULL,
+	0x971e868998ba3c11ULL, 0x333c110f2d697822ULL, 0x1b1c090715313812ULL,
+	0x2986ecaf6afd11c5ULL, 0x30cb10fbdb9b8b20ULL, 0x2820180838584030ULL,
+	0x41543f156b97a87eULL, 0x3934170d237f682eULL, 0x14100c041c2c2018ULL,
+	0x05040301070b0806ULL, 0xe98dac6421ab0745ULL, 0x845b7cdf27cab6f8ULL,
+	0xb3c59a765f0d9729ULL, 0x80f98b797264ef0bULL, 0x8e537add29dca6f4ULL,
+	0xc9f4473db3b2f58eULL, 0x4e583a16628ab074ULL, 0xc3fc413fbda4e582ULL,
+	0xebdc593785fca5b2ULL, 0xc4a9b76d1ef84f73ULL, 0xd8e04838a895dd90ULL,
+	0x67ded6b90877a1b1ULL, 0xa2d19573442abf37ULL, 0x6a8326e9a53d1b4cULL,
+	0xe1d45f358beab5beULL, 0x1c49ff55b66d92e3ULL, 0xa8d993714a3caf3bULL,
+	0x8af18d7b7c72ff07ULL, 0x860a898c839d140fULL, 0xa7d596724321b731ULL,
+	0x921a85889fb13417ULL, 0x09ff07f6f8e4e30eULL, 0x82a87e2ad6334dfcULL,
+	0xc6f8423ebaafed84ULL, 0x3b65e25e8728cad9ULL, 0xbb9c6927f54c25d2ULL,
+	0x4305ca46cfc00a89ULL, 0x3c30140c24746028ULL, 0xec89af6526a00f43ULL,
+	0xd5bdb86805df676dULL, 0xf899a3613a8c2f5bULL, 0x0f0c0503091d180aULL,
+	0xe2235ec17d1846bcULL, 0x1641f957b87b82efULL, 0xa97f67d61899feceULL,
+	0x9a4376d935f086ecULL, 0x257de8589512facdULL, 0x9f4775d832fb8eeaULL,
+	0xe385aa662fbd1749ULL, 0xac7b64d71f92f6c8ULL, 0xd2e84e3aa683cd9cULL,
+	0xcf0745c8424b0e8aULL, 0xccf0443cb4b9fd88ULL, 0x35cf13fadc908326ULL,
+	0xf462a796c563c453ULL, 0x01a6f4a752a551f5ULL, 0xc25ab598ef01b477ULL,
+	0x7b9729ecbe1a3352ULL, 0x62dad5b80f7ca9b7ULL, 0xfc3b54c76f2276a8ULL,
+	0x2c82efae6df619c3ULL, 0xd0b9bb6902d46f6bULL, 0x7a31dd4becbf62a7ULL,
+	0x3d96e0ab76d131ddULL, 0x379ee6a978c721d1ULL, 0xe681a96728b61f4fULL,
+	0x22281e0a364e503cULL, 0x4601c947c8cb028fULL, 0x1def0bf2e4c8c316ULL,
+	0x5beec2b52c03c199ULL, 0xaa886622ee6b0dccULL, 0x56b332e581497b64ULL,
+	0x719f2feeb00c235eULL, 0x7cc2dfbe1d4699a3ULL, 0x87ac7d2bd13845faULL,
+	0xbf3e9e81a0e27c21ULL, 0x5a4836127ea6906cULL, 0xb5369883aef46c2dULL,
+	0x776c2d1b41f5d85aULL, 0x3638120e2a627024ULL, 0xaf8c6523e96005caULL,
+	0x06f302f5f1f9fb04ULL, 0x4c09cf45c6dd1283ULL, 0xa5846321e77615c6ULL,
+	0xd11f4fce50713e9eULL, 0x7039db49e2a972abULL, 0x9cb0742cc4097de8ULL,
+	0x3ac316f9d58d9b2cULL, 0x59bf37e68854636eULL, 0x54e2c7b6251ed993ULL,
+	0x88a07828d8255df0ULL, 0x4b5c39176581b872ULL, 0xb0329b82a9ff642bULL,
+	0x72682e1a46fed05cULL, 0x9d16808b96ac2c1dULL, 0x21df1ffec0bca33eULL,
+	0x9812838a91a7241bULL, 0x2d241b093f534836ULL, 0xca0346c94540068cULL,
+	0xa1269487b2d84c35ULL, 0x6b25d24ef7984ab9ULL, 0x42a33ee19d655b7cULL,
+	0x96b8722eca1f6de4ULL, 0x53b731e486427362ULL, 0x47a73de09a6e537aULL,
+	0x608b20ebab2b0b40ULL, 0xea7aad90d759f447ULL, 0x0eaaf1a45bb849ffULL,
+	0x6678221e5ad2f044ULL, 0xab2e9285bcce5c39ULL, 0xfd9da0603d87275dULL,
+	0x0000000000000000ULL, 0xb1946f25fb5a35deULL, 0x03f701f4f6f2f302ULL,
+	0x12e30ef1edd5db1cULL, 0xfe6aa194cb75d45fULL, 0x272c1d0b3145583aULL,
+	0x5cbb34e78f5f6b68ULL, 0xbcc99f7556108f23ULL, 0x749b2cefb7072b58ULL,
+	0xe4d05c348ce1bdb8ULL, 0xf5c4533197c695a6ULL, 0xa37761d4168feec2ULL,
+	0xb7676dd00aa3cedaULL, 0xa4229786b5d34433ULL, 0x9be5827e6755d719ULL,
+	0x238eeaad64eb01c9ULL, 0x2ed31afdc9a1bb34ULL, 0x8da47b29df2e55f6ULL,
+	0xf0c0503090cd9da0ULL, 0xd7ec4d3ba188c59aULL, 0xd946bc9ffa308c65ULL,
+	0x3fc715f8d286932aULL, 0xf93f57c668297eaeULL, 0x5f4c351379ad986aULL,
+	0x1e180a06123a3014ULL, 0x11140f051b27281eULL, 0xf63352c5613466a4ULL,
+	0x5544331177bb8866ULL, 0xb6c1997758069f2fULL, 0x91ed847c6943c715ULL,
+	0x8ff58e7a7b79f701ULL, 0x85fd8878756fe70dULL, 0xeed85a3682f7adb4ULL,
+	0x6c70241c54c4e048ULL, 0xdde44b39af9ed596ULL, 0x2079eb599219f2cbULL,
+	0x7860281848e8c050ULL, 0x1345fa56bf708ae9ULL, 0x45f6c8b33e39f18dULL,
+	0x4afacdb03724e987ULL, 0xb4906c24fc513dd8ULL, 0xa0806020e07d1dc0ULL,
+	0x40f2cbb23932f98bULL, 0xe072ab92d94fe44bULL, 0x15b6f8a34e8971edULL,
+	0xe7275dc07a134ebaULL, 0x490dcc44c1d61a85ULL, 0xf795a66233913751ULL,
+	0x5040301070b08060ULL, 0x5eeac1b42b08c99fULL, 0xae2a9184bbc5543fULL,
+	0x5211c543d4e72297ULL, 0xe576a893de44ec4dULL, 0xed2f5bc274055eb6ULL,
+	0x7f35de4aebb46aa1ULL, 0x73cedabd145b81a9ULL, 0x89068c8f8a800c05ULL,
+	0x99b4772dc30275eeULL, 0x76cad9bc135089afULL, 0xd64ab99cf32d946fULL,
+	0xdfb5be6a0bc97761ULL, 0x5d1dc040ddfa3a9dULL, 0xd41b4ccf577a3698ULL,
+	0x10b2fba2498279ebULL, 0xba3a9d80a7e97427ULL, 0x6e21d14ff09342bfULL,
+	0x637c211f5dd9f842ULL, 0xc50f43ca4c5d1e86ULL, 0x3892e3aa71da39dbULL,
+	0x5715c642d3ec2a91ULL
+};
+
+static const u64 T4[256] = {
+	0xbbb96a01bad3d268ULL, 0xe59a66b154fc4d19ULL, 0xe26514cd2f71bc93ULL,
+	0x25871b51749ccdb9ULL, 0xf7a257a453f55102ULL, 0xd0d6be03d3686bb8ULL,
+	0xd6deb504d26b6fbdULL, 0xb35285fe4dd72964ULL, 0xfdba4aad50f05d0dULL,
+	0xcf09e063ace98a26ULL, 0x091c96848d8a0e83ULL, 0xa5914d1abfdcc679ULL,
+	0x3da7374d7090ddadULL, 0xf1aa5ca352f65507ULL, 0x7ba417e19ab352c8ULL,
+	0xb55a8ef94cd42d61ULL, 0x460320acea238f65ULL, 0xc4e68411d56273a6ULL,
+	0x55cc68c297a466f1ULL, 0xdcc6a80dd16e63b2ULL, 0xaa85d0993355ccffULL,
+	0xfbb241aa51f35908ULL, 0xc7e20f9c5bed712aULL, 0xf359ae55a6f7a204ULL,
+	0xfebec120de7f5f81ULL, 0xad7aa2e548d83d75ULL, 0xd729cc7fa8e59a32ULL,
+	0x71bc0ae899b65ec7ULL, 0xe096e63bdb704b90ULL, 0xac8ddb9e3256c8faULL,
+	0x95d11522b7c4e651ULL, 0x32b3aacefc19d72bULL, 0x704b7393e338ab48ULL,
+	0x63843bfd9ebf42dcULL, 0x41fc52d091ae7eefULL, 0x7dac1ce69bb056cdULL,
+	0x76437894e23baf4dULL, 0xbdb16106bbd0d66dULL, 0x9b32f1da41c31958ULL,
+	0x7957e5176eb2a5cbULL, 0xf941b35ca5f2ae0bULL, 0x8016564bcb400bc0ULL,
+	0x677fc20c6bbdb1daULL, 0x59dc7ecc95a26efbULL, 0xe1619f40a1febe1fULL,
+	0x10cbc3e3f308eb18ULL, 0x81e12f30b1cefe4fULL, 0x0c10160e0206080aULL,
+	0x922e675ecc4917dbULL, 0xa26e3f66c45137f3ULL, 0x4ee8cf531d277469ULL,
+	0x78a09c6c143c5044ULL, 0xb0560e73c3582be8ULL, 0x573f9a3463a591f2ULL,
+	0xe69eed3cda734f95ULL, 0xd3d2358e5de76934ULL, 0xdfc223805fe1613eULL,
+	0xf2aed72edc79578bULL, 0x13cf486e7d87e994ULL, 0x94266c59cd4a13deULL,
+	0x1fdf5e607f81e19eULL, 0xc1ea049b5aee752fULL, 0x7547f3196cb4adc1ULL,
+	0xd5da3e895ce46d31ULL, 0x08ebeffff704fb0cULL, 0xd42d47f2266a98beULL,
+	0x38abb7c7ff1cdb24ULL, 0x543b11b9ed2a937eULL, 0x4a1336a2e825876fULL,
+	0x699c26f49dba4ed3ULL, 0x7f5fee106fb1a1ceULL, 0x03048b8d8e8f028cULL,
+	0x56c8e34f192b647dULL, 0xe7699447a0fdba1aULL, 0x1ad3deeaf00de717ULL,
+	0x113cba9889861e97ULL, 0x2278692d0f113c33ULL, 0x1238311507091c1bULL,
+	0xc511fd6aafec8629ULL, 0x208b9bdbfb10cb30ULL, 0x3040583808182028ULL,
+	0x7ea8976b153f5441ULL, 0x2e687f230d173439ULL, 0x18202c1c040c1014ULL,
+	0x06080b0701030405ULL, 0x4507ab2164ac8de9ULL, 0xf8b6ca27df7c5b84ULL,
+	0x29970d5f769ac5b3ULL, 0x0bef6472798bf980ULL, 0xf4a6dc29dd7a538eULL,
+	0x8ef5b2b33d47f4c9ULL, 0x74b08a62163a584eULL, 0x82e5a4bd3f41fcc3ULL,
+	0xb2a5fc853759dcebULL, 0x734ff81e6db7a9c4ULL, 0x90dd95a83848e0d8ULL,
+	0xb1a17708b9d6de67ULL, 0x37bf2a447395d1a2ULL, 0x4c1b3da5e926836aULL,
+	0xbeb5ea8b355fd4e1ULL, 0xe3926db655ff491cULL, 0x3baf3c4a7193d9a8ULL,
+	0x07ff727c7b8df18aULL, 0x0f149d838c890a86ULL, 0x31b721437296d5a7ULL,
+	0x1734b19f88851a92ULL, 0x0ee3e4f8f607ff09ULL, 0xfc4d33d62a7ea882ULL,
+	0x84edafba3e42f8c6ULL, 0xd9ca28875ee2653bULL, 0xd2254cf527699cbbULL,
+	0x890ac0cf46ca0543ULL, 0x286074240c14303cULL, 0x430fa02665af89ecULL,
+	0x6d67df0568b8bdd5ULL, 0x5b2f8c3a61a399f8ULL, 0x0a181d0903050c0fULL,
+	0xbc46187dc15e23e2ULL, 0xef827bb857f94116ULL, 0xcefe9918d6677fa9ULL,
+	0xec86f035d976439aULL, 0xcdfa129558e87d25ULL, 0xea8efb32d875479fULL,
+	0x4917bd2f66aa85e3ULL, 0xc8f6921fd7647bacULL, 0x9ccd83a63a4ee8d2ULL,
+	0x8a0e4b42c84507cfULL, 0x88fdb9b43c44f0ccULL, 0x268390dcfa13cf35ULL,
+	0x53c463c596a762f4ULL, 0xf551a552a7f4a601ULL, 0x77b401ef98b55ac2ULL,
+	0x52331abeec29977bULL, 0xb7a97c0fb8d5da62ULL, 0xa876226fc7543bfcULL,
+	0xc319f66daeef822cULL, 0x6b6fd40269bbb9d0ULL, 0xa762bfec4bdd317aULL,
+	0xdd31d176abe0963dULL, 0xd121c778a9e69e37ULL, 0x4f1fb62867a981e6ULL,
+	0x3c504e360a1e2822ULL, 0x8f02cbc847c90146ULL, 0x16c3c8e4f20bef1dULL,
+	0x99c1032cb5c2ee5bULL, 0xcc0d6bee226688aaULL, 0x647b4981e532b356ULL,
+	0x5e230cb0ee2f9f71ULL, 0xa399461dbedfc27cULL, 0xfa4538d12b7dac87ULL,
+	0x217ce2a0819e3ebfULL, 0x6c90a67e1236485aULL, 0x2d6cf4ae839836b5ULL,
+	0x5ad8f5411b2d6c77ULL, 0x2470622a0e123836ULL, 0xca0560e923658cafULL,
+	0x04fbf9f1f502f306ULL, 0x8312ddc645cf094cULL, 0xc61576e7216384a5ULL,
+	0x9e3e7150ce4f1fd1ULL, 0xab72a9e249db3970ULL, 0xe87d09c42c74b09cULL,
+	0x2c9b8dd5f916c33aULL, 0x6e635488e637bf59ULL, 0x93d91e25b6c7e254ULL,
+	0xf05d25d82878a088ULL, 0x72b8816517395c4bULL, 0x2b64ffa9829b32b0ULL,
+	0x5cd0fe461a2e6872ULL, 0x1d2cac968b80169dULL, 0x3ea3bcc0fe1fdf21ULL,
+	0x1b24a7918a831298ULL, 0x3648533f091b242dULL, 0x8c064045c94603caULL,
+	0x354cd8b2879426a1ULL, 0xb94a98f74ed2256bULL, 0x7c5b659de13ea342ULL,
+	0xe46d1fca2e72b896ULL, 0x62734286e431b753ULL, 0x7a536e9ae03da747ULL,
+	0x400b2babeb208b60ULL, 0x47f459d790ad7aeaULL, 0xff49b85ba4f1aa0eULL,
+	0x44f0d25a1e227866ULL, 0x395ccebc85922eabULL, 0x5d27873d60a09dfdULL,
+	0x0000000000000000ULL, 0xde355afb256f94b1ULL, 0x02f3f2f6f401f703ULL,
+	0x1cdbd5edf10ee312ULL, 0x5fd475cb94a16afeULL, 0x3a5845310b1d2c27ULL,
+	0x686b5f8fe734bb5cULL, 0x238f1056759fc9bcULL, 0x582b07b7ef2c9b74ULL,
+	0xb8bde18c345cd0e4ULL, 0xa695c6973153c4f5ULL, 0xc2ee8f16d46177a3ULL,
+	0xdacea30ad06d67b7ULL, 0x3344d3b5869722a4ULL, 0x19d755677e82e59bULL,
+	0xc901eb64adea8e23ULL, 0x34bba1c9fd1ad32eULL, 0xf6552edf297ba48dULL,
+	0xa09dcd903050c0f0ULL, 0x9ac588a13b4decd7ULL, 0x658c30fa9fbc46d9ULL,
+	0x2a9386d2f815c73fULL, 0xae7e2968c6573ff9ULL, 0x6a98ad7913354c5fULL,
+	0x14303a12060a181eULL, 0x1e28271b050f1411ULL, 0xa4663461c55233f6ULL,
+	0x6688bb7711334455ULL, 0x2f9f06587799c1b6ULL, 0x15c743697c84ed91ULL,
+	0x01f7797b7a8ef58fULL, 0x0de76f757888fd85ULL, 0xb4adf782365ad8eeULL,
+	0x48e0c4541c24706cULL, 0x96d59eaf394be4ddULL, 0xcbf2199259eb7920ULL,
+	0x50c0e84818286078ULL, 0xe98a70bf56fa4513ULL, 0x8df1393eb3c8f645ULL,
+	0x87e92437b0cdfa4aULL, 0xd83d51fc246c90b4ULL, 0xc01d7de0206080a0ULL,
+	0x8bf93239b2cbf240ULL, 0x4be44fd992ab72e0ULL, 0xed71894ea3f8b615ULL,
+	0xba4e137ac05d27e7ULL, 0x851ad6c144cc0d49ULL, 0x5137913362a695f7ULL,
+	0x6080b07010304050ULL, 0x9fc9082bb4c1ea5eULL, 0x3f54c5bb84912aaeULL,
+	0x9722e7d443c51152ULL, 0x4dec44de93a876e5ULL, 0xb65e0574c25b2fedULL,
+	0xa16ab4eb4ade357fULL, 0xa9815b14bddace73ULL, 0x050c808a8f8c0689ULL,
+	0xee7502c32d77b499ULL, 0xaf895013bcd9ca76ULL, 0x6f942df39cb94ad6ULL,
+	0x6177c90b6abeb5dfULL, 0x9d3afadd40c01d5dULL, 0x98367a57cf4c1bd4ULL,
+	0xeb798249a2fbb210ULL, 0x2774e9a7809d3abaULL, 0xbf4293f04fd1216eULL,
+	0x42f8d95d1f217c63ULL, 0x861e5d4cca430fc5ULL, 0xdb39da71aae39238ULL,
+	0x912aecd342c61557ULL
+};
+
+static const u64 T5[256] = {
+	0xb9bb016ad3ba68d2ULL, 0x9ae5b166fc54194dULL, 0x65e2cd14712f93bcULL,
+	0x8725511b9c74b9cdULL, 0xa2f7a457f5530251ULL, 0xd6d003be68d3b86bULL,
+	0xded604b56bd2bd6fULL, 0x52b3fe85d74d6429ULL, 0xbafdad4af0500d5dULL,
+	0x09cf63e0e9ac268aULL, 0x1c0984968a8d830eULL, 0x91a51a4ddcbf79c6ULL,
+	0xa73d4d379070adddULL, 0xaaf1a35cf6520755ULL, 0xa47be117b39ac852ULL,
+	0x5ab5f98ed44c612dULL, 0x0346ac2023ea658fULL, 0xe6c4118462d5a673ULL,
+	0xcc55c268a497f166ULL, 0xc6dc0da86ed1b263ULL, 0x85aa99d05533ffccULL,
+	0xb2fbaa41f3510859ULL, 0xe2c79c0fed5b2a71ULL, 0x59f355aef7a604a2ULL,
+	0xbefe20c17fde815fULL, 0x7aade5a2d848753dULL, 0x29d77fcce5a8329aULL,
+	0xbc71e80ab699c75eULL, 0x96e03be670db904bULL, 0x8dac9edb5632fac8ULL,
+	0xd1952215c4b751e6ULL, 0xb332ceaa19fc2bd7ULL, 0x4b70937338e348abULL,
+	0x8463fd3bbf9edc42ULL, 0xfc41d052ae91ef7eULL, 0xac7de61cb09bcd56ULL,
+	0x437694783be24dafULL, 0xb1bd0661d0bb6dd6ULL, 0x329bdaf1c3415819ULL,
+	0x577917e5b26ecba5ULL, 0x41f95cb3f2a50baeULL, 0x16804b5640cbc00bULL,
+	0x7f670cc2bd6bdab1ULL, 0xdc59cc7ea295fb6eULL, 0x61e1409ffea11fbeULL,
+	0xcb10e3c308f318ebULL, 0xe181302fceb14ffeULL, 0x100c0e1606020a08ULL,
+	0x2e925e6749ccdb17ULL, 0x6ea2663f51c4f337ULL, 0xe84e53cf271d6974ULL,
+	0xa0786c9c3c144450ULL, 0x56b0730e58c3e82bULL, 0x3f57349aa563f291ULL,
+	0x9ee63ced73da954fULL, 0xd2d38e35e75d3469ULL, 0xc2df8023e15f3e61ULL,
+	0xaef22ed779dc8b57ULL, 0xcf136e48877d94e9ULL, 0x2694596c4acdde13ULL,
+	0xdf1f605e817f9ee1ULL, 0xeac19b04ee5a2f75ULL, 0x477519f3b46cc1adULL,
+	0xdad5893ee45c316dULL, 0xeb08ffef04f70cfbULL, 0x2dd4f2476a26be98ULL,
+	0xab38c7b71cff24dbULL, 0x3b54b9112aed7e93ULL, 0x134aa23625e86f87ULL,
+	0x9c69f426ba9dd34eULL, 0x5f7f10eeb16fcea1ULL, 0x04038d8b8f8e8c02ULL,
+	0xc8564fe32b197d64ULL, 0x69e74794fda01abaULL, 0xd31aeade0df017e7ULL,
+	0x3c1198ba8689971eULL, 0x78222d69110f333cULL, 0x3812153109071b1cULL,
+	0x11c56afdecaf2986ULL, 0x8b20db9b10fb30cbULL, 0x4030385818082820ULL,
+	0xa87e6b973f154154ULL, 0x682e237f170d3934ULL, 0x20181c2c0c041410ULL,
+	0x0806070b03010504ULL, 0x074521abac64e98dULL, 0xb6f827ca7cdf845bULL,
+	0x97295f0d9a76b3c5ULL, 0xef0b72648b7980f9ULL, 0xa6f429dc7add8e53ULL,
+	0xf58eb3b2473dc9f4ULL, 0xb074628a3a164e58ULL, 0xe582bda4413fc3fcULL,
+	0xa5b285fc5937ebdcULL, 0x4f731ef8b76dc4a9ULL, 0xdd90a8954838d8e0ULL,
+	0xa1b10877d6b967deULL, 0xbf37442a9573a2d1ULL, 0x1b4ca53d26e96a83ULL,
+	0xb5be8bea5f35e1d4ULL, 0x92e3b66dff551c49ULL, 0xaf3b4a3c9371a8d9ULL,
+	0xff077c728d7b8af1ULL, 0x140f839d898c860aULL, 0xb73143219672a7d5ULL,
+	0x34179fb18588921aULL, 0xe30ef8e407f609ffULL, 0x4dfcd6337e2a82a8ULL,
+	0xed84baaf423ec6f8ULL, 0xcad98728e25e3b65ULL, 0x25d2f54c6927bb9cULL,
+	0x0a89cfc0ca464305ULL, 0x60282474140c3c30ULL, 0x0f4326a0af65ec89ULL,
+	0x676d05dfb868d5bdULL, 0x2f5b3a8ca361f899ULL, 0x180a091d05030f0cULL,
+	0x46bc7d185ec1e223ULL, 0x82efb87bf9571641ULL, 0xfece189967d6a97fULL,
+	0x86ec35f076d99a43ULL, 0xfacd9512e858257dULL, 0x8eea32fb75d89f47ULL,
+	0x17492fbdaa66e385ULL, 0xf6c81f9264d7ac7bULL, 0xcd9ca6834e3ad2e8ULL,
+	0x0e8a424b45c8cf07ULL, 0xfd88b4b9443cccf0ULL, 0x8326dc9013fa35cfULL,
+	0xc453c563a796f462ULL, 0x51f552a5f4a701a6ULL, 0xb477ef01b598c25aULL,
+	0x3352be1a29ec7b97ULL, 0xa9b70f7cd5b862daULL, 0x76a86f2254c7fc3bULL,
+	0x19c36df6efae2c82ULL, 0x6f6b02d4bb69d0b9ULL, 0x62a7ecbfdd4b7a31ULL,
+	0x31dd76d1e0ab3d96ULL, 0x21d178c7e6a9379eULL, 0x1f4f28b6a967e681ULL,
+	0x503c364e1e0a2228ULL, 0x028fc8cbc9474601ULL, 0xc316e4c80bf21defULL,
+	0xc1992c03c2b55beeULL, 0x0dccee6b6622aa88ULL, 0x7b64814932e556b3ULL,
+	0x235eb00c2fee719fULL, 0x99a31d46dfbe7cc2ULL, 0x45fad1387d2b87acULL,
+	0x7c21a0e29e81bf3eULL, 0x906c7ea636125a48ULL, 0x6c2daef49883b536ULL,
+	0xd85a41f52d1b776cULL, 0x70242a62120e3638ULL, 0x05cae9606523af8cULL,
+	0xfb04f1f902f506f3ULL, 0x1283c6ddcf454c09ULL, 0x15c6e7766321a584ULL,
+	0x3e9e50714fced11fULL, 0x72abe2a9db497039ULL, 0x7de8c409742c9cb0ULL,
+	0x9b2cd58d16f93ac3ULL, 0x636e885437e659bfULL, 0xd993251ec7b654e2ULL,
+	0x5df0d825782888a0ULL, 0xb872658139174b5cULL, 0x642ba9ff9b82b032ULL,
+	0xd05c46fe2e1a7268ULL, 0x2c1d96ac808b9d16ULL, 0xa33ec0bc1ffe21dfULL,
+	0x241b91a7838a9812ULL, 0x48363f531b092d24ULL, 0x068c454046c9ca03ULL,
+	0x4c35b2d89487a126ULL, 0x4ab9f798d24e6b25ULL, 0x5b7c9d653ee142a3ULL,
+	0x6de4ca1f722e96b8ULL, 0x7362864231e453b7ULL, 0x537a9a6e3de047a7ULL,
+	0x0b40ab2b20eb608bULL, 0xf447d759ad90ea7aULL, 0x49ff5bb8f1a40eaaULL,
+	0xf0445ad2221e6678ULL, 0x5c39bcce9285ab2eULL, 0x275d3d87a060fd9dULL,
+	0x0000000000000000ULL, 0x35defb5a6f25b194ULL, 0xf302f6f201f403f7ULL,
+	0xdb1cedd50ef112e3ULL, 0xd45fcb75a194fe6aULL, 0x583a31451d0b272cULL,
+	0x6b688f5f34e75cbbULL, 0x8f2356109f75bcc9ULL, 0x2b58b7072cef749bULL,
+	0xbdb88ce15c34e4d0ULL, 0x95a697c65331f5c4ULL, 0xeec2168f61d4a377ULL,
+	0xceda0aa36dd0b767ULL, 0x4433b5d39786a422ULL, 0xd7196755827e9be5ULL,
+	0x01c964ebeaad238eULL, 0xbb34c9a11afd2ed3ULL, 0x55f6df2e7b298da4ULL,
+	0x9da090cd5030f0c0ULL, 0xc59aa1884d3bd7ecULL, 0x8c65fa30bc9fd946ULL,
+	0x932ad28615f83fc7ULL, 0x7eae682957c6f93fULL, 0x986a79ad35135f4cULL,
+	0x3014123a0a061e18ULL, 0x281e1b270f051114ULL, 0x66a4613452c5f633ULL,
+	0x886677bb33115544ULL, 0x9f2f58069977b6c1ULL, 0xc7156943847c91edULL,
+	0xf7017b798e7a8ff5ULL, 0xe70d756f887885fdULL, 0xadb482f75a36eed8ULL,
+	0xe04854c4241c6c70ULL, 0xd596af9e4b39dde4ULL, 0xf2cb9219eb592079ULL,
+	0xc05048e828187860ULL, 0x8ae9bf70fa561345ULL, 0xf18d3e39c8b345f6ULL,
+	0xe9873724cdb04afaULL, 0x3dd8fc516c24b490ULL, 0x1dc0e07d6020a080ULL,
+	0xf98b3932cbb240f2ULL, 0xe44bd94fab92e072ULL, 0x71ed4e89f8a315b6ULL,
+	0x4eba7a135dc0e727ULL, 0x1a85c1d6cc44490dULL, 0x37513391a662f795ULL,
+	0x806070b030105040ULL, 0xc99f2b08c1b45eeaULL, 0x543fbbc59184ae2aULL,
+	0x2297d4e7c5435211ULL, 0xec4dde44a893e576ULL, 0x5eb674055bc2ed2fULL,
+	0x6aa1ebb4de4a7f35ULL, 0x81a9145bdabd73ceULL, 0x0c058a808c8f8906ULL,
+	0x75eec302772d99b4ULL, 0x89af1350d9bc76caULL, 0x946ff32db99cd64aULL,
+	0x77610bc9be6adfb5ULL, 0x3a9dddfac0405d1dULL, 0x3698577a4ccfd41bULL,
+	0x79eb4982fba210b2ULL, 0x7427a7e99d80ba3aULL, 0x42bff093d14f6e21ULL,
+	0xf8425dd9211f637cULL, 0x1e864c5d43cac50fULL, 0x39db71dae3aa3892ULL,
+	0x2a91d3ecc6425715ULL
+};
+
+static const u64 T6[256] = {
+	0x6a01bbb9d268bad3ULL, 0x66b1e59a4d1954fcULL, 0x14cde265bc932f71ULL,
+	0x1b512587cdb9749cULL, 0x57a4f7a2510253f5ULL, 0xbe03d0d66bb8d368ULL,
+	0xb504d6de6fbdd26bULL, 0x85feb35229644dd7ULL, 0x4aadfdba5d0d50f0ULL,
+	0xe063cf098a26ace9ULL, 0x9684091c0e838d8aULL, 0x4d1aa591c679bfdcULL,
+	0x374d3da7ddad7090ULL, 0x5ca3f1aa550752f6ULL, 0x17e17ba452c89ab3ULL,
+	0x8ef9b55a2d614cd4ULL, 0x20ac46038f65ea23ULL, 0x8411c4e673a6d562ULL,
+	0x68c255cc66f197a4ULL, 0xa80ddcc663b2d16eULL, 0xd099aa85ccff3355ULL,
+	0x41aafbb2590851f3ULL, 0x0f9cc7e2712a5bedULL, 0xae55f359a204a6f7ULL,
+	0xc120febe5f81de7fULL, 0xa2e5ad7a3d7548d8ULL, 0xcc7fd7299a32a8e5ULL,
+	0x0ae871bc5ec799b6ULL, 0xe63be0964b90db70ULL, 0xdb9eac8dc8fa3256ULL,
+	0x152295d1e651b7c4ULL, 0xaace32b3d72bfc19ULL, 0x7393704bab48e338ULL,
+	0x3bfd638442dc9ebfULL, 0x52d041fc7eef91aeULL, 0x1ce67dac56cd9bb0ULL,
+	0x78947643af4de23bULL, 0x6106bdb1d66dbbd0ULL, 0xf1da9b32195841c3ULL,
+	0xe5177957a5cb6eb2ULL, 0xb35cf941ae0ba5f2ULL, 0x564b80160bc0cb40ULL,
+	0xc20c677fb1da6bbdULL, 0x7ecc59dc6efb95a2ULL, 0x9f40e161be1fa1feULL,
+	0xc3e310cbeb18f308ULL, 0x2f3081e1fe4fb1ceULL, 0x160e0c10080a0206ULL,
+	0x675e922e17dbcc49ULL, 0x3f66a26e37f3c451ULL, 0xcf534ee874691d27ULL,
+	0x9c6c78a05044143cULL, 0x0e73b0562be8c358ULL, 0x9a34573f91f263a5ULL,
+	0xed3ce69e4f95da73ULL, 0x358ed3d269345de7ULL, 0x2380dfc2613e5fe1ULL,
+	0xd72ef2ae578bdc79ULL, 0x486e13cfe9947d87ULL, 0x6c59942613decd4aULL,
+	0x5e601fdfe19e7f81ULL, 0x049bc1ea752f5aeeULL, 0xf3197547adc16cb4ULL,
+	0x3e89d5da6d315ce4ULL, 0xefff08ebfb0cf704ULL, 0x47f2d42d98be266aULL,
+	0xb7c738abdb24ff1cULL, 0x11b9543b937eed2aULL, 0x36a24a13876fe825ULL,
+	0x26f4699c4ed39dbaULL, 0xee107f5fa1ce6fb1ULL, 0x8b8d0304028c8e8fULL,
+	0xe34f56c8647d192bULL, 0x9447e769ba1aa0fdULL, 0xdeea1ad3e717f00dULL,
+	0xba98113c1e978986ULL, 0x692d22783c330f11ULL, 0x311512381c1b0709ULL,
+	0xfd6ac5118629afecULL, 0x9bdb208bcb30fb10ULL, 0x5838304020280818ULL,
+	0x976b7ea85441153fULL, 0x7f232e6834390d17ULL, 0x2c1c18201014040cULL,
+	0x0b07060804050103ULL, 0xab2145078de964acULL, 0xca27f8b65b84df7cULL,
+	0x0d5f2997c5b3769aULL, 0x64720beff980798bULL, 0xdc29f4a6538edd7aULL,
+	0xb2b38ef5f4c93d47ULL, 0x8a6274b0584e163aULL, 0xa4bd82e5fcc33f41ULL,
+	0xfc85b2a5dceb3759ULL, 0xf81e734fa9c46db7ULL, 0x95a890dde0d83848ULL,
+	0x7708b1a1de67b9d6ULL, 0x2a4437bfd1a27395ULL, 0x3da54c1b836ae926ULL,
+	0xea8bbeb5d4e1355fULL, 0x6db6e392491c55ffULL, 0x3c4a3bafd9a87193ULL,
+	0x727c07fff18a7b8dULL, 0x9d830f140a868c89ULL, 0x214331b7d5a77296ULL,
+	0xb19f17341a928885ULL, 0xe4f80ee3ff09f607ULL, 0x33d6fc4da8822a7eULL,
+	0xafba84edf8c63e42ULL, 0x2887d9ca653b5ee2ULL, 0x4cf5d2259cbb2769ULL,
+	0xc0cf890a054346caULL, 0x74242860303c0c14ULL, 0xa026430f89ec65afULL,
+	0xdf056d67bdd568b8ULL, 0x8c3a5b2f99f861a3ULL, 0x1d090a180c0f0305ULL,
+	0x187dbc4623e2c15eULL, 0x7bb8ef82411657f9ULL, 0x9918cefe7fa9d667ULL,
+	0xf035ec86439ad976ULL, 0x1295cdfa7d2558e8ULL, 0xfb32ea8e479fd875ULL,
+	0xbd2f491785e366aaULL, 0x921fc8f67bacd764ULL, 0x83a69ccde8d23a4eULL,
+	0x4b428a0e07cfc845ULL, 0xb9b488fdf0cc3c44ULL, 0x90dc2683cf35fa13ULL,
+	0x63c553c462f496a7ULL, 0xa552f551a601a7f4ULL, 0x01ef77b45ac298b5ULL,
+	0x1abe5233977bec29ULL, 0x7c0fb7a9da62b8d5ULL, 0x226fa8763bfcc754ULL,
+	0xf66dc319822caeefULL, 0xd4026b6fb9d069bbULL, 0xbfeca762317a4bddULL,
+	0xd176dd31963dabe0ULL, 0xc778d1219e37a9e6ULL, 0xb6284f1f81e667a9ULL,
+	0x4e363c5028220a1eULL, 0xcbc88f02014647c9ULL, 0xc8e416c3ef1df20bULL,
+	0x032c99c1ee5bb5c2ULL, 0x6beecc0d88aa2266ULL, 0x4981647bb356e532ULL,
+	0x0cb05e239f71ee2fULL, 0x461da399c27cbedfULL, 0x38d1fa45ac872b7dULL,
+	0xe2a0217c3ebf819eULL, 0xa67e6c90485a1236ULL, 0xf4ae2d6c36b58398ULL,
+	0xf5415ad86c771b2dULL, 0x622a247038360e12ULL, 0x60e9ca058caf2365ULL,
+	0xf9f104fbf306f502ULL, 0xddc68312094c45cfULL, 0x76e7c61584a52163ULL,
+	0x71509e3e1fd1ce4fULL, 0xa9e2ab72397049dbULL, 0x09c4e87db09c2c74ULL,
+	0x8dd52c9bc33af916ULL, 0x54886e63bf59e637ULL, 0x1e2593d9e254b6c7ULL,
+	0x25d8f05da0882878ULL, 0x816572b85c4b1739ULL, 0xffa92b6432b0829bULL,
+	0xfe465cd068721a2eULL, 0xac961d2c169d8b80ULL, 0xbcc03ea3df21fe1fULL,
+	0xa7911b2412988a83ULL, 0x533f3648242d091bULL, 0x40458c0603cac946ULL,
+	0xd8b2354c26a18794ULL, 0x98f7b94a256b4ed2ULL, 0x659d7c5ba342e13eULL,
+	0x1fcae46db8962e72ULL, 0x42866273b753e431ULL, 0x6e9a7a53a747e03dULL,
+	0x2bab400b8b60eb20ULL, 0x59d747f47aea90adULL, 0xb85bff49aa0ea4f1ULL,
+	0xd25a44f078661e22ULL, 0xcebc395c2eab8592ULL, 0x873d5d279dfd60a0ULL,
+	0x0000000000000000ULL, 0x5afbde3594b1256fULL, 0xf2f602f3f703f401ULL,
+	0xd5ed1cdbe312f10eULL, 0x75cb5fd46afe94a1ULL, 0x45313a582c270b1dULL,
+	0x5f8f686bbb5ce734ULL, 0x1056238fc9bc759fULL, 0x07b7582b9b74ef2cULL,
+	0xe18cb8bdd0e4345cULL, 0xc697a695c4f53153ULL, 0x8f16c2ee77a3d461ULL,
+	0xa30adace67b7d06dULL, 0xd3b5334422a48697ULL, 0x556719d7e59b7e82ULL,
+	0xeb64c9018e23adeaULL, 0xa1c934bbd32efd1aULL, 0x2edff655a48d297bULL,
+	0xcd90a09dc0f03050ULL, 0x88a19ac5ecd73b4dULL, 0x30fa658c46d99fbcULL,
+	0x86d22a93c73ff815ULL, 0x2968ae7e3ff9c657ULL, 0xad796a984c5f1335ULL,
+	0x3a121430181e060aULL, 0x271b1e281411050fULL, 0x3461a46633f6c552ULL,
+	0xbb77668844551133ULL, 0x06582f9fc1b67799ULL, 0x436915c7ed917c84ULL,
+	0x797b01f7f58f7a8eULL, 0x6f750de7fd857888ULL, 0xf782b4add8ee365aULL,
+	0xc45448e0706c1c24ULL, 0x9eaf96d5e4dd394bULL, 0x1992cbf2792059ebULL,
+	0xe84850c060781828ULL, 0x70bfe98a451356faULL, 0x393e8df1f645b3c8ULL,
+	0x243787e9fa4ab0cdULL, 0x51fcd83d90b4246cULL, 0x7de0c01d80a02060ULL,
+	0x32398bf9f240b2cbULL, 0x4fd94be472e092abULL, 0x894eed71b615a3f8ULL,
+	0x137aba4e27e7c05dULL, 0xd6c1851a0d4944ccULL, 0x9133513795f762a6ULL,
+	0xb070608040501030ULL, 0x082b9fc9ea5eb4c1ULL, 0xc5bb3f542aae8491ULL,
+	0xe7d49722115243c5ULL, 0x44de4dec76e593a8ULL, 0x0574b65e2fedc25bULL,
+	0xb4eba16a357f4adeULL, 0x5b14a981ce73bddaULL, 0x808a050c06898f8cULL,
+	0x02c3ee75b4992d77ULL, 0x5013af89ca76bcd9ULL, 0x2df36f944ad69cb9ULL,
+	0xc90b6177b5df6abeULL, 0xfadd9d3a1d5d40c0ULL, 0x7a5798361bd4cf4cULL,
+	0x8249eb79b210a2fbULL, 0xe9a727743aba809dULL, 0x93f0bf42216e4fd1ULL,
+	0xd95d42f87c631f21ULL, 0x5d4c861e0fc5ca43ULL, 0xda71db399238aae3ULL,
+	0xecd3912a155742c6ULL
+};
+
+static const u64 T7[256] = {
+	0x016ab9bb68d2d3baULL, 0xb1669ae5194dfc54ULL, 0xcd1465e293bc712fULL,
+	0x511b8725b9cd9c74ULL, 0xa457a2f70251f553ULL, 0x03bed6d0b86b68d3ULL,
+	0x04b5ded6bd6f6bd2ULL, 0xfe8552b36429d74dULL, 0xad4abafd0d5df050ULL,
+	0x63e009cf268ae9acULL, 0x84961c09830e8a8dULL, 0x1a4d91a579c6dcbfULL,
+	0x4d37a73daddd9070ULL, 0xa35caaf10755f652ULL, 0xe117a47bc852b39aULL,
+	0xf98e5ab5612dd44cULL, 0xac200346658f23eaULL, 0x1184e6c4a67362d5ULL,
+	0xc268cc55f166a497ULL, 0x0da8c6dcb2636ed1ULL, 0x99d085aaffcc5533ULL,
+	0xaa41b2fb0859f351ULL, 0x9c0fe2c72a71ed5bULL, 0x55ae59f304a2f7a6ULL,
+	0x20c1befe815f7fdeULL, 0xe5a27aad753dd848ULL, 0x7fcc29d7329ae5a8ULL,
+	0xe80abc71c75eb699ULL, 0x3be696e0904b70dbULL, 0x9edb8dacfac85632ULL,
+	0x2215d19551e6c4b7ULL, 0xceaab3322bd719fcULL, 0x93734b7048ab38e3ULL,
+	0xfd3b8463dc42bf9eULL, 0xd052fc41ef7eae91ULL, 0xe61cac7dcd56b09bULL,
+	0x947843764daf3be2ULL, 0x0661b1bd6dd6d0bbULL, 0xdaf1329b5819c341ULL,
+	0x17e55779cba5b26eULL, 0x5cb341f90baef2a5ULL, 0x4b561680c00b40cbULL,
+	0x0cc27f67dab1bd6bULL, 0xcc7edc59fb6ea295ULL, 0x409f61e11fbefea1ULL,
+	0xe3c3cb1018eb08f3ULL, 0x302fe1814ffeceb1ULL, 0x0e16100c0a080602ULL,
+	0x5e672e92db1749ccULL, 0x663f6ea2f33751c4ULL, 0x53cfe84e6974271dULL,
+	0x6c9ca07844503c14ULL, 0x730e56b0e82b58c3ULL, 0x349a3f57f291a563ULL,
+	0x3ced9ee6954f73daULL, 0x8e35d2d33469e75dULL, 0x8023c2df3e61e15fULL,
+	0x2ed7aef28b5779dcULL, 0x6e48cf1394e9877dULL, 0x596c2694de134acdULL,
+	0x605edf1f9ee1817fULL, 0x9b04eac12f75ee5aULL, 0x19f34775c1adb46cULL,
+	0x893edad5316de45cULL, 0xffefeb080cfb04f7ULL, 0xf2472dd4be986a26ULL,
+	0xc7b7ab3824db1cffULL, 0xb9113b547e932aedULL, 0xa236134a6f8725e8ULL,
+	0xf4269c69d34eba9dULL, 0x10ee5f7fcea1b16fULL, 0x8d8b04038c028f8eULL,
+	0x4fe3c8567d642b19ULL, 0x479469e71abafda0ULL, 0xeaded31a17e70df0ULL,
+	0x98ba3c11971e8689ULL, 0x2d697822333c110fULL, 0x153138121b1c0907ULL,
+	0x6afd11c52986ecafULL, 0xdb9b8b2030cb10fbULL, 0x3858403028201808ULL,
+	0x6b97a87e41543f15ULL, 0x237f682e3934170dULL, 0x1c2c201814100c04ULL,
+	0x070b080605040301ULL, 0x21ab0745e98dac64ULL, 0x27cab6f8845b7cdfULL,
+	0x5f0d9729b3c59a76ULL, 0x7264ef0b80f98b79ULL, 0x29dca6f48e537addULL,
+	0xb3b2f58ec9f4473dULL, 0x628ab0744e583a16ULL, 0xbda4e582c3fc413fULL,
+	0x85fca5b2ebdc5937ULL, 0x1ef84f73c4a9b76dULL, 0xa895dd90d8e04838ULL,
+	0x0877a1b167ded6b9ULL, 0x442abf37a2d19573ULL, 0xa53d1b4c6a8326e9ULL,
+	0x8beab5bee1d45f35ULL, 0xb66d92e31c49ff55ULL, 0x4a3caf3ba8d99371ULL,
+	0x7c72ff078af18d7bULL, 0x839d140f860a898cULL, 0x4321b731a7d59672ULL,
+	0x9fb13417921a8588ULL, 0xf8e4e30e09ff07f6ULL, 0xd6334dfc82a87e2aULL,
+	0xbaafed84c6f8423eULL, 0x8728cad93b65e25eULL, 0xf54c25d2bb9c6927ULL,
+	0xcfc00a894305ca46ULL, 0x247460283c30140cULL, 0x26a00f43ec89af65ULL,
+	0x05df676dd5bdb868ULL, 0x3a8c2f5bf899a361ULL, 0x091d180a0f0c0503ULL,
+	0x7d1846bce2235ec1ULL, 0xb87b82ef1641f957ULL, 0x1899fecea97f67d6ULL,
+	0x35f086ec9a4376d9ULL, 0x9512facd257de858ULL, 0x32fb8eea9f4775d8ULL,
+	0x2fbd1749e385aa66ULL, 0x1f92f6c8ac7b64d7ULL, 0xa683cd9cd2e84e3aULL,
+	0x424b0e8acf0745c8ULL, 0xb4b9fd88ccf0443cULL, 0xdc90832635cf13faULL,
+	0xc563c453f462a796ULL, 0x52a551f501a6f4a7ULL, 0xef01b477c25ab598ULL,
+	0xbe1a33527b9729ecULL, 0x0f7ca9b762dad5b8ULL, 0x6f2276a8fc3b54c7ULL,
+	0x6df619c32c82efaeULL, 0x02d46f6bd0b9bb69ULL, 0xecbf62a77a31dd4bULL,
+	0x76d131dd3d96e0abULL, 0x78c721d1379ee6a9ULL, 0x28b61f4fe681a967ULL,
+	0x364e503c22281e0aULL, 0xc8cb028f4601c947ULL, 0xe4c8c3161def0bf2ULL,
+	0x2c03c1995beec2b5ULL, 0xee6b0dccaa886622ULL, 0x81497b6456b332e5ULL,
+	0xb00c235e719f2feeULL, 0x1d4699a37cc2dfbeULL, 0xd13845fa87ac7d2bULL,
+	0xa0e27c21bf3e9e81ULL, 0x7ea6906c5a483612ULL, 0xaef46c2db5369883ULL,
+	0x41f5d85a776c2d1bULL, 0x2a6270243638120eULL, 0xe96005caaf8c6523ULL,
+	0xf1f9fb0406f302f5ULL, 0xc6dd12834c09cf45ULL, 0xe77615c6a5846321ULL,
+	0x50713e9ed11f4fceULL, 0xe2a972ab7039db49ULL, 0xc4097de89cb0742cULL,
+	0xd58d9b2c3ac316f9ULL, 0x8854636e59bf37e6ULL, 0x251ed99354e2c7b6ULL,
+	0xd8255df088a07828ULL, 0x6581b8724b5c3917ULL, 0xa9ff642bb0329b82ULL,
+	0x46fed05c72682e1aULL, 0x96ac2c1d9d16808bULL, 0xc0bca33e21df1ffeULL,
+	0x91a7241b9812838aULL, 0x3f5348362d241b09ULL, 0x4540068cca0346c9ULL,
+	0xb2d84c35a1269487ULL, 0xf7984ab96b25d24eULL, 0x9d655b7c42a33ee1ULL,
+	0xca1f6de496b8722eULL, 0x8642736253b731e4ULL, 0x9a6e537a47a73de0ULL,
+	0xab2b0b40608b20ebULL, 0xd759f447ea7aad90ULL, 0x5bb849ff0eaaf1a4ULL,
+	0x5ad2f0446678221eULL, 0xbcce5c39ab2e9285ULL, 0x3d87275dfd9da060ULL,
+	0x0000000000000000ULL, 0xfb5a35deb1946f25ULL, 0xf6f2f30203f701f4ULL,
+	0xedd5db1c12e30ef1ULL, 0xcb75d45ffe6aa194ULL, 0x3145583a272c1d0bULL,
+	0x8f5f6b685cbb34e7ULL, 0x56108f23bcc99f75ULL, 0xb7072b58749b2cefULL,
+	0x8ce1bdb8e4d05c34ULL, 0x97c695a6f5c45331ULL, 0x168feec2a37761d4ULL,
+	0x0aa3cedab7676dd0ULL, 0xb5d34433a4229786ULL, 0x6755d7199be5827eULL,
+	0x64eb01c9238eeaadULL, 0xc9a1bb342ed31afdULL, 0xdf2e55f68da47b29ULL,
+	0x90cd9da0f0c05030ULL, 0xa188c59ad7ec4d3bULL, 0xfa308c65d946bc9fULL,
+	0xd286932a3fc715f8ULL, 0x68297eaef93f57c6ULL, 0x79ad986a5f4c3513ULL,
+	0x123a30141e180a06ULL, 0x1b27281e11140f05ULL, 0x613466a4f63352c5ULL,
+	0x77bb886655443311ULL, 0x58069f2fb6c19977ULL, 0x6943c71591ed847cULL,
+	0x7b79f7018ff58e7aULL, 0x756fe70d85fd8878ULL, 0x82f7adb4eed85a36ULL,
+	0x54c4e0486c70241cULL, 0xaf9ed596dde44b39ULL, 0x9219f2cb2079eb59ULL,
+	0x48e8c05078602818ULL, 0xbf708ae91345fa56ULL, 0x3e39f18d45f6c8b3ULL,
+	0x3724e9874afacdb0ULL, 0xfc513dd8b4906c24ULL, 0xe07d1dc0a0806020ULL,
+	0x3932f98b40f2cbb2ULL, 0xd94fe44be072ab92ULL, 0x4e8971ed15b6f8a3ULL,
+	0x7a134ebae7275dc0ULL, 0xc1d61a85490dcc44ULL, 0x33913751f795a662ULL,
+	0x70b0806050403010ULL, 0x2b08c99f5eeac1b4ULL, 0xbbc5543fae2a9184ULL,
+	0xd4e722975211c543ULL, 0xde44ec4de576a893ULL, 0x74055eb6ed2f5bc2ULL,
+	0xebb46aa17f35de4aULL, 0x145b81a973cedabdULL, 0x8a800c0589068c8fULL,
+	0xc30275ee99b4772dULL, 0x135089af76cad9bcULL, 0xf32d946fd64ab99cULL,
+	0x0bc97761dfb5be6aULL, 0xddfa3a9d5d1dc040ULL, 0x577a3698d41b4ccfULL,
+	0x498279eb10b2fba2ULL, 0xa7e97427ba3a9d80ULL, 0xf09342bf6e21d14fULL,
+	0x5dd9f842637c211fULL, 0x4c5d1e86c50f43caULL, 0x71da39db3892e3aaULL,
+	0xd3ec2a915715c642ULL
+};
+
+static const u64 c[KHAZAD_ROUNDS + 1] = {
+	0xba542f7453d3d24dULL, 0x50ac8dbf70529a4cULL, 0xead597d133515ba6ULL,
+	0xde48a899db32b7fcULL, 0xe39e919be2bb416eULL, 0xa5cb6b95a1f3b102ULL,
+	0xccc41d14c363da5dULL, 0x5fdc7dcd7f5a6c5cULL, 0xf726ffede89d6f8eULL
+};
+
+static int khazad_setkey(void *ctx_arg, const u8 *in_key,
+                       unsigned int key_len, u32 *flags)
+{
+
+	struct khazad_ctx *ctx = ctx_arg;
+	int r;
+	const u64 *S = T7;
+	u64 K2, K1;
+	
+	if (key_len != 16)
+	{
+		*flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
+		return -EINVAL;
+	}
+
+	K2 = ((u64)in_key[ 0] << 56) ^
+	     ((u64)in_key[ 1] << 48) ^
+	     ((u64)in_key[ 2] << 40) ^
+	     ((u64)in_key[ 3] << 32) ^
+	     ((u64)in_key[ 4] << 24) ^
+	     ((u64)in_key[ 5] << 16) ^
+	     ((u64)in_key[ 6] <<  8) ^
+	     ((u64)in_key[ 7]      );
+	K1 = ((u64)in_key[ 8] << 56) ^
+	     ((u64)in_key[ 9] << 48) ^
+	     ((u64)in_key[10] << 40) ^
+	     ((u64)in_key[11] << 32) ^
+	     ((u64)in_key[12] << 24) ^
+	     ((u64)in_key[13] << 16) ^
+	     ((u64)in_key[14] <<  8) ^
+	     ((u64)in_key[15]      );
+
+	/* setup the encrypt key */
+	for (r = 0; r <= KHAZAD_ROUNDS; r++) {
+		ctx->E[r] = T0[(int)(K1 >> 56)       ] ^
+			    T1[(int)(K1 >> 48) & 0xff] ^
+			    T2[(int)(K1 >> 40) & 0xff] ^
+			    T3[(int)(K1 >> 32) & 0xff] ^
+			    T4[(int)(K1 >> 24) & 0xff] ^
+			    T5[(int)(K1 >> 16) & 0xff] ^
+			    T6[(int)(K1 >>  8) & 0xff] ^
+			    T7[(int)(K1      ) & 0xff] ^
+			    c[r] ^ K2;
+		K2 = K1; 
+		K1 = ctx->E[r];
+	}
+	/* Setup the decrypt key */
+	ctx->D[0] = ctx->E[KHAZAD_ROUNDS];
+	for (r = 1; r < KHAZAD_ROUNDS; r++) {
+		K1 = ctx->E[KHAZAD_ROUNDS - r];
+		ctx->D[r] = T0[(int)S[(int)(K1 >> 56)       ] & 0xff] ^
+			    T1[(int)S[(int)(K1 >> 48) & 0xff] & 0xff] ^
+			    T2[(int)S[(int)(K1 >> 40) & 0xff] & 0xff] ^
+			    T3[(int)S[(int)(K1 >> 32) & 0xff] & 0xff] ^
+			    T4[(int)S[(int)(K1 >> 24) & 0xff] & 0xff] ^
+			    T5[(int)S[(int)(K1 >> 16) & 0xff] & 0xff] ^
+			    T6[(int)S[(int)(K1 >>  8) & 0xff] & 0xff] ^
+			    T7[(int)S[(int)(K1      ) & 0xff] & 0xff];
+	}
+	ctx->D[KHAZAD_ROUNDS] = ctx->E[0];
+
+	return 0;
+
+}
+
+static void khazad_crypt(const u64 roundKey[KHAZAD_ROUNDS + 1],
+		u8 *ciphertext, const u8 *plaintext)
+{
+
+	int r;
+	u64 state;
+
+	state = ((u64)plaintext[0] << 56) ^
+		((u64)plaintext[1] << 48) ^
+		((u64)plaintext[2] << 40) ^
+		((u64)plaintext[3] << 32) ^
+		((u64)plaintext[4] << 24) ^
+		((u64)plaintext[5] << 16) ^
+		((u64)plaintext[6] <<  8) ^
+		((u64)plaintext[7]      ) ^
+		roundKey[0];
+
+	for (r = 1; r < KHAZAD_ROUNDS; r++) {
+		state = T0[(int)(state >> 56)       ] ^
+			T1[(int)(state >> 48) & 0xff] ^
+			T2[(int)(state >> 40) & 0xff] ^
+			T3[(int)(state >> 32) & 0xff] ^
+			T4[(int)(state >> 24) & 0xff] ^
+			T5[(int)(state >> 16) & 0xff] ^
+			T6[(int)(state >>  8) & 0xff] ^
+			T7[(int)(state      ) & 0xff] ^
+			roundKey[r];
+    	}
+
+	state = (T0[(int)(state >> 56)       ] & 0xff00000000000000ULL) ^
+		(T1[(int)(state >> 48) & 0xff] & 0x00ff000000000000ULL) ^
+		(T2[(int)(state >> 40) & 0xff] & 0x0000ff0000000000ULL) ^
+		(T3[(int)(state >> 32) & 0xff] & 0x000000ff00000000ULL) ^
+		(T4[(int)(state >> 24) & 0xff] & 0x00000000ff000000ULL) ^
+		(T5[(int)(state >> 16) & 0xff] & 0x0000000000ff0000ULL) ^
+		(T6[(int)(state >>  8) & 0xff] & 0x000000000000ff00ULL) ^
+		(T7[(int)(state      ) & 0xff] & 0x00000000000000ffULL) ^
+		roundKey[KHAZAD_ROUNDS];
+
+	ciphertext[0] = (u8)(state >> 56);
+	ciphertext[1] = (u8)(state >> 48);
+	ciphertext[2] = (u8)(state >> 40);
+	ciphertext[3] = (u8)(state >> 32);
+	ciphertext[4] = (u8)(state >> 24);
+	ciphertext[5] = (u8)(state >> 16);
+	ciphertext[6] = (u8)(state >>  8);
+	ciphertext[7] = (u8)(state      );
+
+}
+
+static void khazad_encrypt(void *ctx_arg, u8 *dst, const u8 *src)
+{
+	struct khazad_ctx *ctx = ctx_arg;
+	khazad_crypt(ctx->E, dst, src);
+}
+
+static void khazad_decrypt(void *ctx_arg, u8 *dst, const u8 *src)
+{
+	struct khazad_ctx *ctx = ctx_arg;
+	khazad_crypt(ctx->D, dst, src);
+}
+
+static struct crypto_alg khazad_alg = {
+	.cra_name		=	"khazad",
+	.cra_flags		=	CRYPTO_ALG_TYPE_CIPHER,
+	.cra_blocksize		=	KHAZAD_BLOCK_SIZE,
+	.cra_ctxsize		=	sizeof (struct khazad_ctx),
+	.cra_module		=	THIS_MODULE,
+	.cra_list		=	LIST_HEAD_INIT(khazad_alg.cra_list),
+	.cra_u			=	{ .cipher = {
+	.cia_min_keysize	=	KHAZAD_KEY_SIZE,
+	.cia_max_keysize	=	KHAZAD_KEY_SIZE,
+	.cia_setkey		= 	khazad_setkey,
+	.cia_encrypt		=	khazad_encrypt,
+	.cia_decrypt		=	khazad_decrypt } }
+};
+
+static int __init init(void)
+{
+	int ret = 0;
+	
+	ret = crypto_register_alg(&khazad_alg);
+	return ret;
+}
+
+static void __exit fini(void)
+{
+	crypto_unregister_alg(&khazad_alg);
+}
+
+
+module_init(init);
+module_exit(fini);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Khazad Cryptographic Algorithm");
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/crypto/scatterwalk.c linux-2.4.28-pre3/crypto/scatterwalk.c
--- linux-2.4.27/crypto/scatterwalk.c	2004-04-14 13:05:28.000000000 +0000
+++ linux-2.4.28-pre3/crypto/scatterwalk.c	2004-09-10 19:31:55.000000000 +0000
@@ -70,7 +70,7 @@ static void scatterwalk_pagedone(struct 
 {
 	/* walk->data may be pointing the first byte of the next page;
 	   however, we know we transfered at least one byte.  So,
-	   walk->data - 1 will be a virutual address in the mapped page. */
+	   walk->data - 1 will be a virtual address in the mapped page. */
 
 	if (out)
 		flush_dcache_page(walk->page);
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/crypto/tcrypt.c linux-2.4.28-pre3/crypto/tcrypt.c
--- linux-2.4.27/crypto/tcrypt.c	2004-08-07 23:26:04.000000000 +0000
+++ linux-2.4.28-pre3/crypto/tcrypt.c	2004-09-10 19:35:38.000000000 +0000
@@ -63,7 +63,7 @@ static char *tvmem;
 static char *check[] = {
 	"des", "md5", "des3_ede", "rot13", "sha1", "sha256", "blowfish",
 	"twofish", "serpent", "sha384", "sha512", "md4", "aes", "cast6", 
-	"arc4", "michael_mic", "deflate", "tea", "xtea", NULL
+	"arc4", "michael_mic", "deflate", "tea", "xtea", "whirlpool", NULL
 };
 
 static void
@@ -575,8 +575,13 @@ do_test(void)
 		test_cipher ("xtea", MODE_ECB, ENCRYPT, xtea_enc_tv_template, XTEA_ENC_TEST_VECTORS);
 		test_cipher ("xtea", MODE_ECB, DECRYPT, xtea_dec_tv_template, XTEA_DEC_TEST_VECTORS);
 
+		//KHAZAD
+		test_cipher ("khazad", MODE_ECB, ENCRYPT, khazad_enc_tv_template, KHAZAD_ENC_TEST_VECTORS);
+		test_cipher ("khazad", MODE_ECB, DECRYPT, khazad_dec_tv_template, KHAZAD_DEC_TEST_VECTORS);
+
 		test_hash("sha384", sha384_tv_template, SHA384_TEST_VECTORS);
 		test_hash("sha512", sha512_tv_template, SHA512_TEST_VECTORS);
+		test_hash("whirlpool", whirlpool_tv_template, WHIRLPOOL_TEST_VECTORS);
 		test_deflate();		
 #ifdef CONFIG_CRYPTO_HMAC
 		test_hmac("md5", hmac_md5_tv_template, HMAC_MD5_TEST_VECTORS);
@@ -678,6 +683,14 @@ do_test(void)
 		test_cipher ("xtea", MODE_ECB, DECRYPT, xtea_dec_tv_template, XTEA_DEC_TEST_VECTORS);
 		break;
 
+	case 21:
+		test_cipher ("khazad", MODE_ECB, ENCRYPT, khazad_enc_tv_template, KHAZAD_ENC_TEST_VECTORS);
+		test_cipher ("khazad", MODE_ECB, DECRYPT, khazad_dec_tv_template, KHAZAD_DEC_TEST_VECTORS);
+		break;
+	case 22:
+		test_hash("whirlpool", whirlpool_tv_template, WHIRLPOOL_TEST_VECTORS);
+		break;
+
 #ifdef CONFIG_CRYPTO_HMAC
 	case 100:
 		test_hmac("md5", hmac_md5_tv_template, HMAC_MD5_TEST_VECTORS);
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/crypto/tcrypt.h linux-2.4.28-pre3/crypto/tcrypt.h
--- linux-2.4.27/crypto/tcrypt.h	2004-08-07 23:26:04.000000000 +0000
+++ linux-2.4.28-pre3/crypto/tcrypt.h	2004-09-10 19:37:06.000000000 +0000
@@ -551,6 +551,109 @@ struct hmac_testvec hmac_sha256_tv_templ
 #endif	/* CONFIG_CRYPTO_HMAC */
 
 /*
+ * WHIRLPOOL test vectors from Whirlpool package 
+ * by Vincent Rijmen and Paulo S. L. M. Barreto as part of the NESSIE
+ * submission
+ */
+#define WHIRLPOOL_TEST_VECTORS	8
+
+struct hash_testvec whirlpool_tv_template[] = {
+	{ 
+		.plaintext = "",
+		.psize	= 0,
+		.digest	= { 0x19, 0xFA, 0x61, 0xD7, 0x55, 0x22, 0xA4, 0x66,
+			    0x9B, 0x44, 0xE3, 0x9C, 0x1D, 0x2E, 0x17, 0x26,
+			    0xC5, 0x30, 0x23, 0x21, 0x30, 0xD4, 0x07, 0xF8,
+			    0x9A, 0xFE, 0xE0, 0x96, 0x49, 0x97, 0xF7, 0xA7,
+			    0x3E, 0x83, 0xBE, 0x69, 0x8B, 0x28, 0x8F, 0xEB,
+			    0xCF, 0x88, 0xE3, 0xE0, 0x3C, 0x4F, 0x07, 0x57,
+			    0xEA, 0x89, 0x64, 0xE5, 0x9B, 0x63, 0xD9, 0x37,
+			    0x08, 0xB1, 0x38, 0xCC, 0x42, 0xA6, 0x6E, 0xB3 },
+
+
+	}, {
+		.plaintext = "a",
+		.psize	= 1,
+		.digest	= { 0x8A, 0xCA, 0x26, 0x02, 0x79, 0x2A, 0xEC, 0x6F,
+			    0x11, 0xA6, 0x72, 0x06, 0x53, 0x1F, 0xB7, 0xD7,
+			    0xF0, 0xDF, 0xF5, 0x94, 0x13, 0x14, 0x5E, 0x69,
+			    0x73, 0xC4, 0x50, 0x01, 0xD0, 0x08, 0x7B, 0x42,
+			    0xD1, 0x1B, 0xC6, 0x45, 0x41, 0x3A, 0xEF, 0xF6,
+			    0x3A, 0x42, 0x39, 0x1A, 0x39, 0x14, 0x5A, 0x59,
+			    0x1A, 0x92, 0x20, 0x0D, 0x56, 0x01, 0x95, 0xE5,
+			    0x3B, 0x47, 0x85, 0x84, 0xFD, 0xAE, 0x23, 0x1A },
+	}, {
+		.plaintext = "abc",
+		.psize	= 3,
+		.digest	= { 0x4E, 0x24, 0x48, 0xA4, 0xC6, 0xF4, 0x86, 0xBB,
+			    0x16, 0xB6, 0x56, 0x2C, 0x73, 0xB4, 0x02, 0x0B,
+			    0xF3, 0x04, 0x3E, 0x3A, 0x73, 0x1B, 0xCE, 0x72,
+			    0x1A, 0xE1, 0xB3, 0x03, 0xD9, 0x7E, 0x6D, 0x4C,
+			    0x71, 0x81, 0xEE, 0xBD, 0xB6, 0xC5, 0x7E, 0x27,
+			    0x7D, 0x0E, 0x34, 0x95, 0x71, 0x14, 0xCB, 0xD6,
+			    0xC7, 0x97, 0xFC, 0x9D, 0x95, 0xD8, 0xB5, 0x82,
+			    0xD2, 0x25, 0x29, 0x20, 0x76, 0xD4, 0xEE, 0xF5 },
+	}, {
+		.plaintext = "message digest",
+		.psize	= 14,
+		.digest	= { 0x37, 0x8C, 0x84, 0xA4, 0x12, 0x6E, 0x2D, 0xC6, 
+			    0xE5, 0x6D, 0xCC, 0x74, 0x58, 0x37, 0x7A, 0xAC, 
+			    0x83, 0x8D, 0x00, 0x03, 0x22, 0x30, 0xF5, 0x3C, 
+			    0xE1, 0xF5, 0x70, 0x0C, 0x0F, 0xFB, 0x4D, 0x3B, 
+			    0x84, 0x21, 0x55, 0x76, 0x59, 0xEF, 0x55, 0xC1, 
+			    0x06, 0xB4, 0xB5, 0x2A, 0xC5, 0xA4, 0xAA, 0xA6, 
+			    0x92, 0xED, 0x92, 0x00, 0x52, 0x83, 0x8F, 0x33, 
+			    0x62, 0xE8, 0x6D, 0xBD, 0x37, 0xA8, 0x90, 0x3E },
+	}, {
+		.plaintext = "abcdefghijklmnopqrstuvwxyz",
+		.psize	= 26,
+		.digest	= { 0xF1, 0xD7, 0x54, 0x66, 0x26, 0x36, 0xFF, 0xE9,
+			    0x2C, 0x82, 0xEB, 0xB9, 0x21, 0x2A, 0x48, 0x4A,
+			    0x8D, 0x38, 0x63, 0x1E, 0xAD, 0x42, 0x38, 0xF5,
+			    0x44, 0x2E, 0xE1, 0x3B, 0x80, 0x54, 0xE4, 0x1B,
+			    0x08, 0xBF, 0x2A, 0x92, 0x51, 0xC3, 0x0B, 0x6A,
+			    0x0B, 0x8A, 0xAE, 0x86, 0x17, 0x7A, 0xB4, 0xA6,
+			    0xF6, 0x8F, 0x67, 0x3E, 0x72, 0x07, 0x86, 0x5D,
+			    0x5D, 0x98, 0x19, 0xA3, 0xDB, 0xA4, 0xEB, 0x3B },
+	}, {
+		.plaintext = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+			     "abcdefghijklmnopqrstuvwxyz0123456789",
+		.psize	= 62,
+		.digest	= { 0xDC, 0x37, 0xE0, 0x08, 0xCF, 0x9E, 0xE6, 0x9B,
+			    0xF1, 0x1F, 0x00, 0xED, 0x9A, 0xBA, 0x26, 0x90,
+			    0x1D, 0xD7, 0xC2, 0x8C, 0xDE, 0xC0, 0x66, 0xCC,
+			    0x6A, 0xF4, 0x2E, 0x40, 0xF8, 0x2F, 0x3A, 0x1E,
+			    0x08, 0xEB, 0xA2, 0x66, 0x29, 0x12, 0x9D, 0x8F,
+			    0xB7, 0xCB, 0x57, 0x21, 0x1B, 0x92, 0x81, 0xA6,
+			    0x55, 0x17, 0xCC, 0x87, 0x9D, 0x7B, 0x96, 0x21,
+			    0x42, 0xC6, 0x5F, 0x5A, 0x7A, 0xF0, 0x14, 0x67 },
+	}, {
+		.plaintext = "1234567890123456789012345678901234567890"
+			     "1234567890123456789012345678901234567890",
+		.psize	= 80,
+		.digest	= { 0x46, 0x6E, 0xF1, 0x8B, 0xAB, 0xB0, 0x15, 0x4D,
+			    0x25, 0xB9, 0xD3, 0x8A, 0x64, 0x14, 0xF5, 0xC0,
+			    0x87, 0x84, 0x37, 0x2B, 0xCC, 0xB2, 0x04, 0xD6,
+			    0x54, 0x9C, 0x4A, 0xFA, 0xDB, 0x60, 0x14, 0x29,
+			    0x4D, 0x5B, 0xD8, 0xDF, 0x2A, 0x6C, 0x44, 0xE5,
+			    0x38, 0xCD, 0x04, 0x7B, 0x26, 0x81, 0xA5, 0x1A,
+			    0x2C, 0x60, 0x48, 0x1E, 0x88, 0xC5, 0xA2, 0x0B,
+			    0x2C, 0x2A, 0x80, 0xCF, 0x3A, 0x9A, 0x08, 0x3B },
+	}, {
+		.plaintext = "abcdbcdecdefdefgefghfghighijhijk",
+		.psize	= 32,
+		.digest	= { 0x2A, 0x98, 0x7E, 0xA4, 0x0F, 0x91, 0x70, 0x61, 
+			    0xF5, 0xD6, 0xF0, 0xA0, 0xE4, 0x64, 0x4F, 0x48,
+			    0x8A, 0x7A, 0x5A, 0x52, 0xDE, 0xEE, 0x65, 0x62,
+			    0x07, 0xC5, 0x62, 0xF9, 0x88, 0xE9, 0x5C, 0x69,
+			    0x16, 0xBD, 0xC8, 0x03, 0x1B, 0xC5, 0xBE, 0x1B,
+			    0x7B, 0x94, 0x76, 0x39, 0xFE, 0x05, 0x0B, 0x56,
+			    0x93, 0x9B, 0xAA, 0xA0, 0xAD, 0xFF, 0x9A, 0xE6,
+			    0x74, 0x5B, 0x7B, 0x18, 0x1C, 0x3B, 0xE3, 0xFD },
+	},
+};
+
+/*
  * DES test vectors.
  */
 #define DES_ENC_TEST_VECTORS		10
@@ -1186,7 +1289,7 @@ struct cipher_testvec tf_cbc_dec_tv_temp
 
 /*
  * Serpent test vectors.  These are backwards because Serpent writes
- * octect sequences in right-to-left mode.
+ * octet sequences in right-to-left mode.
  */
 #define SERPENT_ENC_TEST_VECTORS	4
 #define SERPENT_DEC_TEST_VECTORS	4
@@ -1818,7 +1921,103 @@ struct cipher_testvec xtea_dec_tv_templa
 	}
 };
 
+/*
+ * KHAZAD test vectors.
+ */
+#define KHAZAD_ENC_TEST_VECTORS 5
+#define KHAZAD_DEC_TEST_VECTORS 5
+
+struct cipher_testvec khazad_enc_tv_template[] = { 
+	{ 
+		.key	= { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+		.klen	= 16,
+		.input	= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+		.ilen	= 8,
+		.result	= { 0x49, 0xa4, 0xce, 0x32, 0xac, 0x19, 0x0e, 0x3f },
+		.rlen	= 8,
+	}, {
+		.key	= { 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38,
+			    0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38 },
+		.klen	= 16,
+		.input	= { 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38 },
+		.ilen	= 8,
+		.result	= { 0x7e, 0x82, 0x12, 0xa1, 0Xd9, 0X5b, 0Xe4, 0Xf9 },
+		.rlen	= 8,
+	}, {
+		.key	= { 0Xa2, 0Xa2, 0Xa2, 0Xa2, 0Xa2, 0Xa2, 0Xa2, 0Xa2,
+			    0Xa2, 0Xa2, 0Xa2, 0Xa2, 0Xa2, 0Xa2, 0Xa2, 0Xa2 },
+		.klen	= 16,
+		.input	= { 0Xa2, 0Xa2, 0Xa2, 0Xa2, 0Xa2, 0Xa2, 0Xa2, 0Xa2 },
+		.ilen	= 8,
+		.result	= { 0Xaa, 0Xbe, 0Xc1, 0X95, 0Xc5, 0X94, 0X1a, 0X9c },
+		.rlen	= 8,
+	}, {
+		.key	= { 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f,
+			    0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f },
+		.klen	= 16,
+		.input	= { 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f },
+		.ilen	= 8,
+		.result = { 0X04, 0X74, 0Xf5, 0X70, 0X50, 0X16, 0Xd3, 0Xb8 },
+		.rlen	= 8,
+	}, {
+		.key	= { 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f,
+			    0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f },
+		.klen	= 16,
+		.input	= { 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f ,
+			    0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f },
+		.ilen	= 16,
+		.result = { 0X04, 0X74, 0Xf5, 0X70, 0X50, 0X16, 0Xd3, 0Xb8 ,
+			    0X04, 0X74, 0Xf5, 0X70, 0X50, 0X16, 0Xd3, 0Xb8 },
+		.rlen	= 16,
+	},
+};
 
+struct cipher_testvec khazad_dec_tv_template[] = { 
+	{
+		.key	= { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+		.klen	= 16,
+		.input	= { 0X49, 0Xa4, 0Xce, 0X32, 0Xac, 0X19, 0X0e, 0X3f },
+		.ilen	= 8,
+		.result	= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+		.rlen	= 8,
+	}, {
+		.key	= { 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38,
+			    0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38 },
+		.klen	= 16,
+		.input	= { 0X7e, 0X82, 0X12, 0Xa1, 0Xd9, 0X5b, 0Xe4, 0Xf9 },
+		.ilen	= 8,
+		.result	= { 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38 },
+		.rlen	= 8,
+	}, {
+		.key	= { 0Xa2, 0Xa2, 0Xa2, 0Xa2, 0Xa2, 0Xa2, 0Xa2, 0Xa2,
+			    0Xa2, 0Xa2, 0Xa2, 0Xa2, 0Xa2, 0Xa2, 0Xa2, 0Xa2 },
+		.klen	= 16,
+		.input	= { 0Xaa, 0Xbe, 0Xc1, 0X95, 0Xc5, 0X94, 0X1a, 0X9c },
+		.ilen	= 8,
+		.result	= { 0Xa2, 0Xa2, 0Xa2, 0Xa2, 0Xa2, 0Xa2, 0Xa2, 0Xa2 },
+		.rlen	= 8,
+	}, {
+		.key	= { 0x2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f,
+			    0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f },
+		.klen	= 16,
+		.input = { 0X04, 0X74, 0Xf5, 0X70, 0X50, 0X16, 0Xd3, 0Xb8 },
+		.ilen	= 8,
+		.result	= { 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f },
+		.rlen	= 8,
+	}, {
+		.key	= { 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f,
+			    0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f },
+		.klen	= 16,
+		.input = { 0X04, 0X74, 0Xf5, 0X70, 0X50, 0X16, 0Xd3, 0Xb8 ,
+			    0X04, 0X74, 0Xf5, 0X70, 0X50, 0X16, 0Xd3, 0Xb8 },
+		.ilen	= 16,
+		.result	= { 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f ,
+			    0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f, 0X2f },
+		.rlen	= 16,
+	},
+};
 
 /*
  * Compression stuff.
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/crypto/twofish.c linux-2.4.28-pre3/crypto/twofish.c
--- linux-2.4.27/crypto/twofish.c	2004-08-07 23:26:04.000000000 +0000
+++ linux-2.4.28-pre3/crypto/twofish.c	2004-09-10 19:32:40.000000000 +0000
@@ -1,7 +1,7 @@
 /*
  * Twofish for CryptoAPI
  *
- * Originaly Twofish for GPG
+ * Originally Twofish for GPG
  * By Matthew Skala <mskala@ansuz.sooke.bc.ca>, July 26, 1998
  * 256-bit key length added March 20, 1999
  * Some modifications to reduce the text size by Werner Koch, April, 1998
@@ -514,7 +514,7 @@ static const u8 calc_sb_tbl[512] = {
  * preprocessed through q0 and q1 respectively; for longer keys they are the
  * output of previous stages.  j is the index of the first key byte to use.
  * CALC_K computes a pair of subkeys for 128-bit Twofish, by calling CALC_K_2
- * twice, doing the Psuedo-Hadamard Transform, and doing the necessary
+ * twice, doing the Pseudo-Hadamard Transform, and doing the necessary
  * rotations.  Its parameters are: a, the array to write the results into,
  * j, the index of the first output entry, k and l, the preprocessed indices
  * for index 2i, and m and n, the preprocessed indices for index 2i+1.
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/crypto/whirlpool.c linux-2.4.28-pre3/crypto/whirlpool.c
--- linux-2.4.27/crypto/whirlpool.c	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.28-pre3/crypto/whirlpool.c	2004-09-10 19:37:30.000000000 +0000
@@ -0,0 +1,1131 @@
+/*
+ * Cryptographic API.
+ *
+ * Whirlpool hashing Algorithm
+ *
+ * The Whirlpool algorithm was developed by Paulo S. L. M. Barreto and
+ * Vincent Rijmen.  It has been selected as one of cryptographic
+ * primitives by the NESSIE project http://www.cryptonessie.org/
+ *
+ * The original authors have disclaimed all copyright interest in this
+ * code and thus put it in the public domain. The subsequent authors
+ * have put this under the GNU General Public License.
+ *
+ * By Aaron Grothe ajgrothe@yahoo.com, August 23, 2004
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ */
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/mm.h>
+#include <asm/scatterlist.h>
+#include <linux/crypto.h>
+
+#define WHIRLPOOL_DIGEST_SIZE 64
+#define WHIRLPOOL_BLOCK_SIZE  64
+#define WHIRLPOOL_LENGTHBYTES 32
+
+#define WHIRLPOOL_ROUNDS 10
+
+struct whirlpool_ctx {
+	u8  bitLength[WHIRLPOOL_LENGTHBYTES];
+	u8  buffer[WHIRLPOOL_BLOCK_SIZE];
+	int bufferBits;
+	int bufferPos;
+	u64 hash[WHIRLPOOL_DIGEST_SIZE/8];
+};
+
+/*
+ * Though Whirlpool is endianness-neutral, the encryption tables are listed
+ * in BIG-ENDIAN format, which is adopted throughout this implementation
+ * (but little-endian notation would be equally suitable if consistently
+ * employed).
+ */
+
+static const u64 C0[256] = {
+	0x18186018c07830d8ULL, 0x23238c2305af4626ULL, 0xc6c63fc67ef991b8ULL,
+	0xe8e887e8136fcdfbULL, 0x878726874ca113cbULL, 0xb8b8dab8a9626d11ULL,
+	0x0101040108050209ULL, 0x4f4f214f426e9e0dULL, 0x3636d836adee6c9bULL,
+	0xa6a6a2a6590451ffULL, 0xd2d26fd2debdb90cULL, 0xf5f5f3f5fb06f70eULL,
+	0x7979f979ef80f296ULL, 0x6f6fa16f5fcede30ULL, 0x91917e91fcef3f6dULL,
+	0x52525552aa07a4f8ULL, 0x60609d6027fdc047ULL, 0xbcbccabc89766535ULL,
+	0x9b9b569baccd2b37ULL, 0x8e8e028e048c018aULL, 0xa3a3b6a371155bd2ULL,
+	0x0c0c300c603c186cULL, 0x7b7bf17bff8af684ULL, 0x3535d435b5e16a80ULL,
+	0x1d1d741de8693af5ULL, 0xe0e0a7e05347ddb3ULL, 0xd7d77bd7f6acb321ULL,
+	0xc2c22fc25eed999cULL, 0x2e2eb82e6d965c43ULL, 0x4b4b314b627a9629ULL,
+	0xfefedffea321e15dULL, 0x575741578216aed5ULL, 0x15155415a8412abdULL,
+	0x7777c1779fb6eee8ULL, 0x3737dc37a5eb6e92ULL, 0xe5e5b3e57b56d79eULL,
+	0x9f9f469f8cd92313ULL, 0xf0f0e7f0d317fd23ULL, 0x4a4a354a6a7f9420ULL,
+	0xdada4fda9e95a944ULL, 0x58587d58fa25b0a2ULL, 0xc9c903c906ca8fcfULL,
+	0x2929a429558d527cULL, 0x0a0a280a5022145aULL, 0xb1b1feb1e14f7f50ULL,
+	0xa0a0baa0691a5dc9ULL, 0x6b6bb16b7fdad614ULL, 0x85852e855cab17d9ULL,
+	0xbdbdcebd8173673cULL, 0x5d5d695dd234ba8fULL, 0x1010401080502090ULL,
+	0xf4f4f7f4f303f507ULL, 0xcbcb0bcb16c08bddULL, 0x3e3ef83eedc67cd3ULL,
+	0x0505140528110a2dULL, 0x676781671fe6ce78ULL, 0xe4e4b7e47353d597ULL,
+	0x27279c2725bb4e02ULL, 0x4141194132588273ULL, 0x8b8b168b2c9d0ba7ULL,
+	0xa7a7a6a7510153f6ULL, 0x7d7de97dcf94fab2ULL, 0x95956e95dcfb3749ULL,
+	0xd8d847d88e9fad56ULL, 0xfbfbcbfb8b30eb70ULL, 0xeeee9fee2371c1cdULL,
+	0x7c7ced7cc791f8bbULL, 0x6666856617e3cc71ULL, 0xdddd53dda68ea77bULL,
+	0x17175c17b84b2eafULL, 0x4747014702468e45ULL, 0x9e9e429e84dc211aULL,
+	0xcaca0fca1ec589d4ULL, 0x2d2db42d75995a58ULL, 0xbfbfc6bf9179632eULL,
+	0x07071c07381b0e3fULL, 0xadad8ead012347acULL, 0x5a5a755aea2fb4b0ULL,
+	0x838336836cb51befULL, 0x3333cc3385ff66b6ULL, 0x636391633ff2c65cULL,
+	0x02020802100a0412ULL, 0xaaaa92aa39384993ULL, 0x7171d971afa8e2deULL,
+	0xc8c807c80ecf8dc6ULL, 0x19196419c87d32d1ULL, 0x494939497270923bULL,
+	0xd9d943d9869aaf5fULL, 0xf2f2eff2c31df931ULL, 0xe3e3abe34b48dba8ULL,
+	0x5b5b715be22ab6b9ULL, 0x88881a8834920dbcULL, 0x9a9a529aa4c8293eULL,
+	0x262698262dbe4c0bULL, 0x3232c8328dfa64bfULL, 0xb0b0fab0e94a7d59ULL,
+	0xe9e983e91b6acff2ULL, 0x0f0f3c0f78331e77ULL, 0xd5d573d5e6a6b733ULL,
+	0x80803a8074ba1df4ULL, 0xbebec2be997c6127ULL, 0xcdcd13cd26de87ebULL,
+	0x3434d034bde46889ULL, 0x48483d487a759032ULL, 0xffffdbffab24e354ULL,
+	0x7a7af57af78ff48dULL, 0x90907a90f4ea3d64ULL, 0x5f5f615fc23ebe9dULL,
+	0x202080201da0403dULL, 0x6868bd6867d5d00fULL, 0x1a1a681ad07234caULL,
+	0xaeae82ae192c41b7ULL, 0xb4b4eab4c95e757dULL, 0x54544d549a19a8ceULL,
+	0x93937693ece53b7fULL, 0x222288220daa442fULL, 0x64648d6407e9c863ULL,
+	0xf1f1e3f1db12ff2aULL, 0x7373d173bfa2e6ccULL, 0x12124812905a2482ULL,
+	0x40401d403a5d807aULL, 0x0808200840281048ULL, 0xc3c32bc356e89b95ULL,
+	0xecec97ec337bc5dfULL, 0xdbdb4bdb9690ab4dULL, 0xa1a1bea1611f5fc0ULL,
+	0x8d8d0e8d1c830791ULL, 0x3d3df43df5c97ac8ULL, 0x97976697ccf1335bULL,
+	0x0000000000000000ULL, 0xcfcf1bcf36d483f9ULL, 0x2b2bac2b4587566eULL,
+	0x7676c57697b3ece1ULL, 0x8282328264b019e6ULL, 0xd6d67fd6fea9b128ULL,
+	0x1b1b6c1bd87736c3ULL, 0xb5b5eeb5c15b7774ULL, 0xafaf86af112943beULL,
+	0x6a6ab56a77dfd41dULL, 0x50505d50ba0da0eaULL, 0x45450945124c8a57ULL,
+	0xf3f3ebf3cb18fb38ULL, 0x3030c0309df060adULL, 0xefef9bef2b74c3c4ULL,
+	0x3f3ffc3fe5c37edaULL, 0x55554955921caac7ULL, 0xa2a2b2a2791059dbULL,
+	0xeaea8fea0365c9e9ULL, 0x656589650fecca6aULL, 0xbabad2bab9686903ULL,
+	0x2f2fbc2f65935e4aULL, 0xc0c027c04ee79d8eULL, 0xdede5fdebe81a160ULL,
+	0x1c1c701ce06c38fcULL, 0xfdfdd3fdbb2ee746ULL, 0x4d4d294d52649a1fULL,
+	0x92927292e4e03976ULL, 0x7575c9758fbceafaULL, 0x06061806301e0c36ULL,
+	0x8a8a128a249809aeULL, 0xb2b2f2b2f940794bULL, 0xe6e6bfe66359d185ULL,
+	0x0e0e380e70361c7eULL, 0x1f1f7c1ff8633ee7ULL, 0x6262956237f7c455ULL,
+	0xd4d477d4eea3b53aULL, 0xa8a89aa829324d81ULL, 0x96966296c4f43152ULL,
+	0xf9f9c3f99b3aef62ULL, 0xc5c533c566f697a3ULL, 0x2525942535b14a10ULL,
+	0x59597959f220b2abULL, 0x84842a8454ae15d0ULL, 0x7272d572b7a7e4c5ULL,
+	0x3939e439d5dd72ecULL, 0x4c4c2d4c5a619816ULL, 0x5e5e655eca3bbc94ULL,
+	0x7878fd78e785f09fULL, 0x3838e038ddd870e5ULL, 0x8c8c0a8c14860598ULL,
+	0xd1d163d1c6b2bf17ULL, 0xa5a5aea5410b57e4ULL, 0xe2e2afe2434dd9a1ULL,
+	0x616199612ff8c24eULL, 0xb3b3f6b3f1457b42ULL, 0x2121842115a54234ULL,
+	0x9c9c4a9c94d62508ULL, 0x1e1e781ef0663ceeULL, 0x4343114322528661ULL,
+	0xc7c73bc776fc93b1ULL, 0xfcfcd7fcb32be54fULL, 0x0404100420140824ULL,
+	0x51515951b208a2e3ULL, 0x99995e99bcc72f25ULL, 0x6d6da96d4fc4da22ULL,
+	0x0d0d340d68391a65ULL, 0xfafacffa8335e979ULL, 0xdfdf5bdfb684a369ULL,
+	0x7e7ee57ed79bfca9ULL, 0x242490243db44819ULL, 0x3b3bec3bc5d776feULL,
+	0xabab96ab313d4b9aULL, 0xcece1fce3ed181f0ULL, 0x1111441188552299ULL,
+	0x8f8f068f0c890383ULL, 0x4e4e254e4a6b9c04ULL, 0xb7b7e6b7d1517366ULL,
+	0xebeb8beb0b60cbe0ULL, 0x3c3cf03cfdcc78c1ULL, 0x81813e817cbf1ffdULL,
+	0x94946a94d4fe3540ULL, 0xf7f7fbf7eb0cf31cULL, 0xb9b9deb9a1676f18ULL,
+	0x13134c13985f268bULL, 0x2c2cb02c7d9c5851ULL, 0xd3d36bd3d6b8bb05ULL,
+	0xe7e7bbe76b5cd38cULL, 0x6e6ea56e57cbdc39ULL, 0xc4c437c46ef395aaULL,
+	0x03030c03180f061bULL, 0x565645568a13acdcULL, 0x44440d441a49885eULL,
+	0x7f7fe17fdf9efea0ULL, 0xa9a99ea921374f88ULL, 0x2a2aa82a4d825467ULL,
+	0xbbbbd6bbb16d6b0aULL, 0xc1c123c146e29f87ULL, 0x53535153a202a6f1ULL,
+	0xdcdc57dcae8ba572ULL, 0x0b0b2c0b58271653ULL, 0x9d9d4e9d9cd32701ULL,
+	0x6c6cad6c47c1d82bULL, 0x3131c43195f562a4ULL, 0x7474cd7487b9e8f3ULL,
+	0xf6f6fff6e309f115ULL, 0x464605460a438c4cULL, 0xacac8aac092645a5ULL,
+	0x89891e893c970fb5ULL, 0x14145014a04428b4ULL, 0xe1e1a3e15b42dfbaULL,
+	0x16165816b04e2ca6ULL, 0x3a3ae83acdd274f7ULL, 0x6969b9696fd0d206ULL,
+	0x09092409482d1241ULL, 0x7070dd70a7ade0d7ULL, 0xb6b6e2b6d954716fULL,
+	0xd0d067d0ceb7bd1eULL, 0xeded93ed3b7ec7d6ULL, 0xcccc17cc2edb85e2ULL,
+	0x424215422a578468ULL, 0x98985a98b4c22d2cULL, 0xa4a4aaa4490e55edULL,
+	0x2828a0285d885075ULL, 0x5c5c6d5cda31b886ULL, 0xf8f8c7f8933fed6bULL,
+	0x8686228644a411c2ULL,
+};
+
+static const u64 C1[256] = {
+	0xd818186018c07830ULL, 0x2623238c2305af46ULL, 0xb8c6c63fc67ef991ULL,
+	0xfbe8e887e8136fcdULL, 0xcb878726874ca113ULL, 0x11b8b8dab8a9626dULL,
+	0x0901010401080502ULL, 0x0d4f4f214f426e9eULL, 0x9b3636d836adee6cULL,
+	0xffa6a6a2a6590451ULL, 0x0cd2d26fd2debdb9ULL, 0x0ef5f5f3f5fb06f7ULL,
+	0x967979f979ef80f2ULL, 0x306f6fa16f5fcedeULL, 0x6d91917e91fcef3fULL,
+	0xf852525552aa07a4ULL, 0x4760609d6027fdc0ULL, 0x35bcbccabc897665ULL,
+	0x379b9b569baccd2bULL, 0x8a8e8e028e048c01ULL, 0xd2a3a3b6a371155bULL,
+	0x6c0c0c300c603c18ULL, 0x847b7bf17bff8af6ULL, 0x803535d435b5e16aULL,
+	0xf51d1d741de8693aULL, 0xb3e0e0a7e05347ddULL, 0x21d7d77bd7f6acb3ULL,
+	0x9cc2c22fc25eed99ULL, 0x432e2eb82e6d965cULL, 0x294b4b314b627a96ULL,
+	0x5dfefedffea321e1ULL, 0xd5575741578216aeULL, 0xbd15155415a8412aULL,
+	0xe87777c1779fb6eeULL, 0x923737dc37a5eb6eULL, 0x9ee5e5b3e57b56d7ULL,
+	0x139f9f469f8cd923ULL, 0x23f0f0e7f0d317fdULL, 0x204a4a354a6a7f94ULL,
+	0x44dada4fda9e95a9ULL, 0xa258587d58fa25b0ULL, 0xcfc9c903c906ca8fULL,
+	0x7c2929a429558d52ULL, 0x5a0a0a280a502214ULL, 0x50b1b1feb1e14f7fULL,
+	0xc9a0a0baa0691a5dULL, 0x146b6bb16b7fdad6ULL, 0xd985852e855cab17ULL,
+	0x3cbdbdcebd817367ULL, 0x8f5d5d695dd234baULL, 0x9010104010805020ULL,
+	0x07f4f4f7f4f303f5ULL, 0xddcbcb0bcb16c08bULL, 0xd33e3ef83eedc67cULL,
+	0x2d0505140528110aULL, 0x78676781671fe6ceULL, 0x97e4e4b7e47353d5ULL,
+	0x0227279c2725bb4eULL, 0x7341411941325882ULL, 0xa78b8b168b2c9d0bULL,
+	0xf6a7a7a6a7510153ULL, 0xb27d7de97dcf94faULL, 0x4995956e95dcfb37ULL,
+	0x56d8d847d88e9fadULL, 0x70fbfbcbfb8b30ebULL, 0xcdeeee9fee2371c1ULL,
+	0xbb7c7ced7cc791f8ULL, 0x716666856617e3ccULL, 0x7bdddd53dda68ea7ULL,
+	0xaf17175c17b84b2eULL, 0x454747014702468eULL, 0x1a9e9e429e84dc21ULL,
+	0xd4caca0fca1ec589ULL, 0x582d2db42d75995aULL, 0x2ebfbfc6bf917963ULL,
+	0x3f07071c07381b0eULL, 0xacadad8ead012347ULL, 0xb05a5a755aea2fb4ULL,
+	0xef838336836cb51bULL, 0xb63333cc3385ff66ULL, 0x5c636391633ff2c6ULL,
+	0x1202020802100a04ULL, 0x93aaaa92aa393849ULL, 0xde7171d971afa8e2ULL,
+	0xc6c8c807c80ecf8dULL, 0xd119196419c87d32ULL, 0x3b49493949727092ULL,
+	0x5fd9d943d9869aafULL, 0x31f2f2eff2c31df9ULL, 0xa8e3e3abe34b48dbULL,
+	0xb95b5b715be22ab6ULL, 0xbc88881a8834920dULL, 0x3e9a9a529aa4c829ULL,
+	0x0b262698262dbe4cULL, 0xbf3232c8328dfa64ULL, 0x59b0b0fab0e94a7dULL,
+	0xf2e9e983e91b6acfULL, 0x770f0f3c0f78331eULL, 0x33d5d573d5e6a6b7ULL,
+	0xf480803a8074ba1dULL, 0x27bebec2be997c61ULL, 0xebcdcd13cd26de87ULL,
+	0x893434d034bde468ULL, 0x3248483d487a7590ULL, 0x54ffffdbffab24e3ULL,
+	0x8d7a7af57af78ff4ULL, 0x6490907a90f4ea3dULL, 0x9d5f5f615fc23ebeULL,
+	0x3d202080201da040ULL, 0x0f6868bd6867d5d0ULL, 0xca1a1a681ad07234ULL,
+	0xb7aeae82ae192c41ULL, 0x7db4b4eab4c95e75ULL, 0xce54544d549a19a8ULL,
+	0x7f93937693ece53bULL, 0x2f222288220daa44ULL, 0x6364648d6407e9c8ULL,
+	0x2af1f1e3f1db12ffULL, 0xcc7373d173bfa2e6ULL, 0x8212124812905a24ULL,
+	0x7a40401d403a5d80ULL, 0x4808082008402810ULL, 0x95c3c32bc356e89bULL,
+	0xdfecec97ec337bc5ULL, 0x4ddbdb4bdb9690abULL, 0xc0a1a1bea1611f5fULL,
+	0x918d8d0e8d1c8307ULL, 0xc83d3df43df5c97aULL, 0x5b97976697ccf133ULL,
+	0x0000000000000000ULL, 0xf9cfcf1bcf36d483ULL, 0x6e2b2bac2b458756ULL,
+	0xe17676c57697b3ecULL, 0xe68282328264b019ULL, 0x28d6d67fd6fea9b1ULL,
+	0xc31b1b6c1bd87736ULL, 0x74b5b5eeb5c15b77ULL, 0xbeafaf86af112943ULL,
+	0x1d6a6ab56a77dfd4ULL, 0xea50505d50ba0da0ULL, 0x5745450945124c8aULL,
+	0x38f3f3ebf3cb18fbULL, 0xad3030c0309df060ULL, 0xc4efef9bef2b74c3ULL,
+	0xda3f3ffc3fe5c37eULL, 0xc755554955921caaULL, 0xdba2a2b2a2791059ULL,
+	0xe9eaea8fea0365c9ULL, 0x6a656589650feccaULL, 0x03babad2bab96869ULL,
+	0x4a2f2fbc2f65935eULL, 0x8ec0c027c04ee79dULL, 0x60dede5fdebe81a1ULL,
+	0xfc1c1c701ce06c38ULL, 0x46fdfdd3fdbb2ee7ULL, 0x1f4d4d294d52649aULL,
+	0x7692927292e4e039ULL, 0xfa7575c9758fbceaULL, 0x3606061806301e0cULL,
+	0xae8a8a128a249809ULL, 0x4bb2b2f2b2f94079ULL, 0x85e6e6bfe66359d1ULL,
+	0x7e0e0e380e70361cULL, 0xe71f1f7c1ff8633eULL, 0x556262956237f7c4ULL,
+	0x3ad4d477d4eea3b5ULL, 0x81a8a89aa829324dULL, 0x5296966296c4f431ULL,
+	0x62f9f9c3f99b3aefULL, 0xa3c5c533c566f697ULL, 0x102525942535b14aULL,
+	0xab59597959f220b2ULL, 0xd084842a8454ae15ULL, 0xc57272d572b7a7e4ULL,
+	0xec3939e439d5dd72ULL, 0x164c4c2d4c5a6198ULL, 0x945e5e655eca3bbcULL,
+	0x9f7878fd78e785f0ULL, 0xe53838e038ddd870ULL, 0x988c8c0a8c148605ULL,
+	0x17d1d163d1c6b2bfULL, 0xe4a5a5aea5410b57ULL, 0xa1e2e2afe2434dd9ULL,
+	0x4e616199612ff8c2ULL, 0x42b3b3f6b3f1457bULL, 0x342121842115a542ULL,
+	0x089c9c4a9c94d625ULL, 0xee1e1e781ef0663cULL, 0x6143431143225286ULL,
+	0xb1c7c73bc776fc93ULL, 0x4ffcfcd7fcb32be5ULL, 0x2404041004201408ULL,
+	0xe351515951b208a2ULL, 0x2599995e99bcc72fULL, 0x226d6da96d4fc4daULL,
+	0x650d0d340d68391aULL, 0x79fafacffa8335e9ULL, 0x69dfdf5bdfb684a3ULL,
+	0xa97e7ee57ed79bfcULL, 0x19242490243db448ULL, 0xfe3b3bec3bc5d776ULL,
+	0x9aabab96ab313d4bULL, 0xf0cece1fce3ed181ULL, 0x9911114411885522ULL,
+	0x838f8f068f0c8903ULL, 0x044e4e254e4a6b9cULL, 0x66b7b7e6b7d15173ULL,
+	0xe0ebeb8beb0b60cbULL, 0xc13c3cf03cfdcc78ULL, 0xfd81813e817cbf1fULL,
+	0x4094946a94d4fe35ULL, 0x1cf7f7fbf7eb0cf3ULL, 0x18b9b9deb9a1676fULL,
+	0x8b13134c13985f26ULL, 0x512c2cb02c7d9c58ULL, 0x05d3d36bd3d6b8bbULL,
+	0x8ce7e7bbe76b5cd3ULL, 0x396e6ea56e57cbdcULL, 0xaac4c437c46ef395ULL,
+	0x1b03030c03180f06ULL, 0xdc565645568a13acULL, 0x5e44440d441a4988ULL,
+	0xa07f7fe17fdf9efeULL, 0x88a9a99ea921374fULL, 0x672a2aa82a4d8254ULL,
+	0x0abbbbd6bbb16d6bULL, 0x87c1c123c146e29fULL, 0xf153535153a202a6ULL,
+	0x72dcdc57dcae8ba5ULL, 0x530b0b2c0b582716ULL, 0x019d9d4e9d9cd327ULL,
+	0x2b6c6cad6c47c1d8ULL, 0xa43131c43195f562ULL, 0xf37474cd7487b9e8ULL,
+	0x15f6f6fff6e309f1ULL, 0x4c464605460a438cULL, 0xa5acac8aac092645ULL,
+	0xb589891e893c970fULL, 0xb414145014a04428ULL, 0xbae1e1a3e15b42dfULL,
+	0xa616165816b04e2cULL, 0xf73a3ae83acdd274ULL, 0x066969b9696fd0d2ULL,
+	0x4109092409482d12ULL, 0xd77070dd70a7ade0ULL, 0x6fb6b6e2b6d95471ULL,
+	0x1ed0d067d0ceb7bdULL, 0xd6eded93ed3b7ec7ULL, 0xe2cccc17cc2edb85ULL,
+	0x68424215422a5784ULL, 0x2c98985a98b4c22dULL, 0xeda4a4aaa4490e55ULL,
+	0x752828a0285d8850ULL, 0x865c5c6d5cda31b8ULL, 0x6bf8f8c7f8933fedULL,
+	0xc28686228644a411ULL,
+};
+
+static const u64 C2[256] = {
+	0x30d818186018c078ULL, 0x462623238c2305afULL, 0x91b8c6c63fc67ef9ULL,
+	0xcdfbe8e887e8136fULL, 0x13cb878726874ca1ULL, 0x6d11b8b8dab8a962ULL,
+	0x0209010104010805ULL, 0x9e0d4f4f214f426eULL, 0x6c9b3636d836adeeULL,
+	0x51ffa6a6a2a65904ULL, 0xb90cd2d26fd2debdULL, 0xf70ef5f5f3f5fb06ULL,
+	0xf2967979f979ef80ULL, 0xde306f6fa16f5fceULL, 0x3f6d91917e91fcefULL,
+	0xa4f852525552aa07ULL, 0xc04760609d6027fdULL, 0x6535bcbccabc8976ULL,
+	0x2b379b9b569baccdULL, 0x018a8e8e028e048cULL, 0x5bd2a3a3b6a37115ULL,
+	0x186c0c0c300c603cULL, 0xf6847b7bf17bff8aULL, 0x6a803535d435b5e1ULL,
+	0x3af51d1d741de869ULL, 0xddb3e0e0a7e05347ULL, 0xb321d7d77bd7f6acULL,
+	0x999cc2c22fc25eedULL, 0x5c432e2eb82e6d96ULL, 0x96294b4b314b627aULL,
+	0xe15dfefedffea321ULL, 0xaed5575741578216ULL, 0x2abd15155415a841ULL,
+	0xeee87777c1779fb6ULL, 0x6e923737dc37a5ebULL, 0xd79ee5e5b3e57b56ULL,
+	0x23139f9f469f8cd9ULL, 0xfd23f0f0e7f0d317ULL, 0x94204a4a354a6a7fULL,
+	0xa944dada4fda9e95ULL, 0xb0a258587d58fa25ULL, 0x8fcfc9c903c906caULL,
+	0x527c2929a429558dULL, 0x145a0a0a280a5022ULL, 0x7f50b1b1feb1e14fULL,
+	0x5dc9a0a0baa0691aULL, 0xd6146b6bb16b7fdaULL, 0x17d985852e855cabULL,
+	0x673cbdbdcebd8173ULL, 0xba8f5d5d695dd234ULL, 0x2090101040108050ULL,
+	0xf507f4f4f7f4f303ULL, 0x8bddcbcb0bcb16c0ULL, 0x7cd33e3ef83eedc6ULL,
+	0x0a2d050514052811ULL, 0xce78676781671fe6ULL, 0xd597e4e4b7e47353ULL,
+	0x4e0227279c2725bbULL, 0x8273414119413258ULL, 0x0ba78b8b168b2c9dULL,
+	0x53f6a7a7a6a75101ULL, 0xfab27d7de97dcf94ULL, 0x374995956e95dcfbULL,
+	0xad56d8d847d88e9fULL, 0xeb70fbfbcbfb8b30ULL, 0xc1cdeeee9fee2371ULL,
+	0xf8bb7c7ced7cc791ULL, 0xcc716666856617e3ULL, 0xa77bdddd53dda68eULL,
+	0x2eaf17175c17b84bULL, 0x8e45474701470246ULL, 0x211a9e9e429e84dcULL,
+	0x89d4caca0fca1ec5ULL, 0x5a582d2db42d7599ULL, 0x632ebfbfc6bf9179ULL,
+	0x0e3f07071c07381bULL, 0x47acadad8ead0123ULL, 0xb4b05a5a755aea2fULL,
+	0x1bef838336836cb5ULL, 0x66b63333cc3385ffULL, 0xc65c636391633ff2ULL,
+	0x041202020802100aULL, 0x4993aaaa92aa3938ULL, 0xe2de7171d971afa8ULL,
+	0x8dc6c8c807c80ecfULL, 0x32d119196419c87dULL, 0x923b494939497270ULL,
+	0xaf5fd9d943d9869aULL, 0xf931f2f2eff2c31dULL, 0xdba8e3e3abe34b48ULL,
+	0xb6b95b5b715be22aULL, 0x0dbc88881a883492ULL, 0x293e9a9a529aa4c8ULL,
+	0x4c0b262698262dbeULL, 0x64bf3232c8328dfaULL, 0x7d59b0b0fab0e94aULL,
+	0xcff2e9e983e91b6aULL, 0x1e770f0f3c0f7833ULL, 0xb733d5d573d5e6a6ULL,
+	0x1df480803a8074baULL, 0x6127bebec2be997cULL, 0x87ebcdcd13cd26deULL,
+	0x68893434d034bde4ULL, 0x903248483d487a75ULL, 0xe354ffffdbffab24ULL,
+	0xf48d7a7af57af78fULL, 0x3d6490907a90f4eaULL, 0xbe9d5f5f615fc23eULL,
+	0x403d202080201da0ULL, 0xd00f6868bd6867d5ULL, 0x34ca1a1a681ad072ULL,
+	0x41b7aeae82ae192cULL, 0x757db4b4eab4c95eULL, 0xa8ce54544d549a19ULL,
+	0x3b7f93937693ece5ULL, 0x442f222288220daaULL, 0xc86364648d6407e9ULL,
+	0xff2af1f1e3f1db12ULL, 0xe6cc7373d173bfa2ULL, 0x248212124812905aULL,
+	0x807a40401d403a5dULL, 0x1048080820084028ULL, 0x9b95c3c32bc356e8ULL,
+	0xc5dfecec97ec337bULL, 0xab4ddbdb4bdb9690ULL, 0x5fc0a1a1bea1611fULL,
+	0x07918d8d0e8d1c83ULL, 0x7ac83d3df43df5c9ULL, 0x335b97976697ccf1ULL,
+	0x0000000000000000ULL, 0x83f9cfcf1bcf36d4ULL, 0x566e2b2bac2b4587ULL,
+	0xece17676c57697b3ULL, 0x19e68282328264b0ULL, 0xb128d6d67fd6fea9ULL,
+	0x36c31b1b6c1bd877ULL, 0x7774b5b5eeb5c15bULL, 0x43beafaf86af1129ULL,
+	0xd41d6a6ab56a77dfULL, 0xa0ea50505d50ba0dULL, 0x8a5745450945124cULL,
+	0xfb38f3f3ebf3cb18ULL, 0x60ad3030c0309df0ULL, 0xc3c4efef9bef2b74ULL,
+	0x7eda3f3ffc3fe5c3ULL, 0xaac755554955921cULL, 0x59dba2a2b2a27910ULL,
+	0xc9e9eaea8fea0365ULL, 0xca6a656589650fecULL, 0x6903babad2bab968ULL,
+	0x5e4a2f2fbc2f6593ULL, 0x9d8ec0c027c04ee7ULL, 0xa160dede5fdebe81ULL,
+	0x38fc1c1c701ce06cULL, 0xe746fdfdd3fdbb2eULL, 0x9a1f4d4d294d5264ULL,
+	0x397692927292e4e0ULL, 0xeafa7575c9758fbcULL, 0x0c3606061806301eULL,
+	0x09ae8a8a128a2498ULL, 0x794bb2b2f2b2f940ULL, 0xd185e6e6bfe66359ULL,
+	0x1c7e0e0e380e7036ULL, 0x3ee71f1f7c1ff863ULL, 0xc4556262956237f7ULL,
+	0xb53ad4d477d4eea3ULL, 0x4d81a8a89aa82932ULL, 0x315296966296c4f4ULL,
+	0xef62f9f9c3f99b3aULL, 0x97a3c5c533c566f6ULL, 0x4a102525942535b1ULL,
+	0xb2ab59597959f220ULL, 0x15d084842a8454aeULL, 0xe4c57272d572b7a7ULL,
+	0x72ec3939e439d5ddULL, 0x98164c4c2d4c5a61ULL, 0xbc945e5e655eca3bULL,
+	0xf09f7878fd78e785ULL, 0x70e53838e038ddd8ULL, 0x05988c8c0a8c1486ULL,
+	0xbf17d1d163d1c6b2ULL, 0x57e4a5a5aea5410bULL, 0xd9a1e2e2afe2434dULL,
+	0xc24e616199612ff8ULL, 0x7b42b3b3f6b3f145ULL, 0x42342121842115a5ULL,
+	0x25089c9c4a9c94d6ULL, 0x3cee1e1e781ef066ULL, 0x8661434311432252ULL,
+	0x93b1c7c73bc776fcULL, 0xe54ffcfcd7fcb32bULL, 0x0824040410042014ULL,
+	0xa2e351515951b208ULL, 0x2f2599995e99bcc7ULL, 0xda226d6da96d4fc4ULL,
+	0x1a650d0d340d6839ULL, 0xe979fafacffa8335ULL, 0xa369dfdf5bdfb684ULL,
+	0xfca97e7ee57ed79bULL, 0x4819242490243db4ULL, 0x76fe3b3bec3bc5d7ULL,
+	0x4b9aabab96ab313dULL, 0x81f0cece1fce3ed1ULL, 0x2299111144118855ULL,
+	0x03838f8f068f0c89ULL, 0x9c044e4e254e4a6bULL, 0x7366b7b7e6b7d151ULL,
+	0xcbe0ebeb8beb0b60ULL, 0x78c13c3cf03cfdccULL, 0x1ffd81813e817cbfULL,
+	0x354094946a94d4feULL, 0xf31cf7f7fbf7eb0cULL, 0x6f18b9b9deb9a167ULL,
+	0x268b13134c13985fULL, 0x58512c2cb02c7d9cULL, 0xbb05d3d36bd3d6b8ULL,
+	0xd38ce7e7bbe76b5cULL, 0xdc396e6ea56e57cbULL, 0x95aac4c437c46ef3ULL,
+	0x061b03030c03180fULL, 0xacdc565645568a13ULL, 0x885e44440d441a49ULL,
+	0xfea07f7fe17fdf9eULL, 0x4f88a9a99ea92137ULL, 0x54672a2aa82a4d82ULL,
+	0x6b0abbbbd6bbb16dULL, 0x9f87c1c123c146e2ULL, 0xa6f153535153a202ULL,
+	0xa572dcdc57dcae8bULL, 0x16530b0b2c0b5827ULL, 0x27019d9d4e9d9cd3ULL,
+	0xd82b6c6cad6c47c1ULL, 0x62a43131c43195f5ULL, 0xe8f37474cd7487b9ULL,
+	0xf115f6f6fff6e309ULL, 0x8c4c464605460a43ULL, 0x45a5acac8aac0926ULL,
+	0x0fb589891e893c97ULL, 0x28b414145014a044ULL, 0xdfbae1e1a3e15b42ULL,
+	0x2ca616165816b04eULL, 0x74f73a3ae83acdd2ULL, 0xd2066969b9696fd0ULL,
+	0x124109092409482dULL, 0xe0d77070dd70a7adULL, 0x716fb6b6e2b6d954ULL,
+	0xbd1ed0d067d0ceb7ULL, 0xc7d6eded93ed3b7eULL, 0x85e2cccc17cc2edbULL,
+	0x8468424215422a57ULL, 0x2d2c98985a98b4c2ULL, 0x55eda4a4aaa4490eULL,
+	0x50752828a0285d88ULL, 0xb8865c5c6d5cda31ULL, 0xed6bf8f8c7f8933fULL,
+	0x11c28686228644a4ULL,
+};
+
+static const u64 C3[256] = {
+	0x7830d818186018c0ULL, 0xaf462623238c2305ULL, 0xf991b8c6c63fc67eULL,
+	0x6fcdfbe8e887e813ULL, 0xa113cb878726874cULL, 0x626d11b8b8dab8a9ULL,
+	0x0502090101040108ULL, 0x6e9e0d4f4f214f42ULL, 0xee6c9b3636d836adULL,
+	0x0451ffa6a6a2a659ULL, 0xbdb90cd2d26fd2deULL, 0x06f70ef5f5f3f5fbULL,
+	0x80f2967979f979efULL, 0xcede306f6fa16f5fULL, 0xef3f6d91917e91fcULL,
+	0x07a4f852525552aaULL, 0xfdc04760609d6027ULL, 0x766535bcbccabc89ULL,
+	0xcd2b379b9b569bacULL, 0x8c018a8e8e028e04ULL, 0x155bd2a3a3b6a371ULL,
+	0x3c186c0c0c300c60ULL, 0x8af6847b7bf17bffULL, 0xe16a803535d435b5ULL,
+	0x693af51d1d741de8ULL, 0x47ddb3e0e0a7e053ULL, 0xacb321d7d77bd7f6ULL,
+	0xed999cc2c22fc25eULL, 0x965c432e2eb82e6dULL, 0x7a96294b4b314b62ULL,
+	0x21e15dfefedffea3ULL, 0x16aed55757415782ULL, 0x412abd15155415a8ULL,
+	0xb6eee87777c1779fULL, 0xeb6e923737dc37a5ULL, 0x56d79ee5e5b3e57bULL,
+	0xd923139f9f469f8cULL, 0x17fd23f0f0e7f0d3ULL, 0x7f94204a4a354a6aULL,
+	0x95a944dada4fda9eULL, 0x25b0a258587d58faULL, 0xca8fcfc9c903c906ULL,
+	0x8d527c2929a42955ULL, 0x22145a0a0a280a50ULL, 0x4f7f50b1b1feb1e1ULL,
+	0x1a5dc9a0a0baa069ULL, 0xdad6146b6bb16b7fULL, 0xab17d985852e855cULL,
+	0x73673cbdbdcebd81ULL, 0x34ba8f5d5d695dd2ULL, 0x5020901010401080ULL,
+	0x03f507f4f4f7f4f3ULL, 0xc08bddcbcb0bcb16ULL, 0xc67cd33e3ef83eedULL,
+	0x110a2d0505140528ULL, 0xe6ce78676781671fULL, 0x53d597e4e4b7e473ULL,
+	0xbb4e0227279c2725ULL, 0x5882734141194132ULL, 0x9d0ba78b8b168b2cULL,
+	0x0153f6a7a7a6a751ULL, 0x94fab27d7de97dcfULL, 0xfb374995956e95dcULL,
+	0x9fad56d8d847d88eULL, 0x30eb70fbfbcbfb8bULL, 0x71c1cdeeee9fee23ULL,
+	0x91f8bb7c7ced7cc7ULL, 0xe3cc716666856617ULL, 0x8ea77bdddd53dda6ULL,
+	0x4b2eaf17175c17b8ULL, 0x468e454747014702ULL, 0xdc211a9e9e429e84ULL,
+	0xc589d4caca0fca1eULL, 0x995a582d2db42d75ULL, 0x79632ebfbfc6bf91ULL,
+	0x1b0e3f07071c0738ULL, 0x2347acadad8ead01ULL, 0x2fb4b05a5a755aeaULL,
+	0xb51bef838336836cULL, 0xff66b63333cc3385ULL, 0xf2c65c636391633fULL,
+	0x0a04120202080210ULL, 0x384993aaaa92aa39ULL, 0xa8e2de7171d971afULL,
+	0xcf8dc6c8c807c80eULL, 0x7d32d119196419c8ULL, 0x70923b4949394972ULL,
+	0x9aaf5fd9d943d986ULL, 0x1df931f2f2eff2c3ULL, 0x48dba8e3e3abe34bULL,
+	0x2ab6b95b5b715be2ULL, 0x920dbc88881a8834ULL, 0xc8293e9a9a529aa4ULL,
+	0xbe4c0b262698262dULL, 0xfa64bf3232c8328dULL, 0x4a7d59b0b0fab0e9ULL,
+	0x6acff2e9e983e91bULL, 0x331e770f0f3c0f78ULL, 0xa6b733d5d573d5e6ULL,
+	0xba1df480803a8074ULL, 0x7c6127bebec2be99ULL, 0xde87ebcdcd13cd26ULL,
+	0xe468893434d034bdULL, 0x75903248483d487aULL, 0x24e354ffffdbffabULL,
+	0x8ff48d7a7af57af7ULL, 0xea3d6490907a90f4ULL, 0x3ebe9d5f5f615fc2ULL,
+	0xa0403d202080201dULL, 0xd5d00f6868bd6867ULL, 0x7234ca1a1a681ad0ULL,
+	0x2c41b7aeae82ae19ULL, 0x5e757db4b4eab4c9ULL, 0x19a8ce54544d549aULL,
+	0xe53b7f93937693ecULL, 0xaa442f222288220dULL, 0xe9c86364648d6407ULL,
+	0x12ff2af1f1e3f1dbULL, 0xa2e6cc7373d173bfULL, 0x5a24821212481290ULL,
+	0x5d807a40401d403aULL, 0x2810480808200840ULL, 0xe89b95c3c32bc356ULL,
+	0x7bc5dfecec97ec33ULL, 0x90ab4ddbdb4bdb96ULL, 0x1f5fc0a1a1bea161ULL,
+	0x8307918d8d0e8d1cULL, 0xc97ac83d3df43df5ULL, 0xf1335b97976697ccULL,
+	0x0000000000000000ULL, 0xd483f9cfcf1bcf36ULL, 0x87566e2b2bac2b45ULL,
+	0xb3ece17676c57697ULL, 0xb019e68282328264ULL, 0xa9b128d6d67fd6feULL,
+	0x7736c31b1b6c1bd8ULL, 0x5b7774b5b5eeb5c1ULL, 0x2943beafaf86af11ULL,
+	0xdfd41d6a6ab56a77ULL, 0x0da0ea50505d50baULL, 0x4c8a574545094512ULL,
+	0x18fb38f3f3ebf3cbULL, 0xf060ad3030c0309dULL, 0x74c3c4efef9bef2bULL,
+	0xc37eda3f3ffc3fe5ULL, 0x1caac75555495592ULL, 0x1059dba2a2b2a279ULL,
+	0x65c9e9eaea8fea03ULL, 0xecca6a656589650fULL, 0x686903babad2bab9ULL,
+	0x935e4a2f2fbc2f65ULL, 0xe79d8ec0c027c04eULL, 0x81a160dede5fdebeULL,
+	0x6c38fc1c1c701ce0ULL, 0x2ee746fdfdd3fdbbULL, 0x649a1f4d4d294d52ULL,
+	0xe0397692927292e4ULL, 0xbceafa7575c9758fULL, 0x1e0c360606180630ULL,
+	0x9809ae8a8a128a24ULL, 0x40794bb2b2f2b2f9ULL, 0x59d185e6e6bfe663ULL,
+	0x361c7e0e0e380e70ULL, 0x633ee71f1f7c1ff8ULL, 0xf7c4556262956237ULL,
+	0xa3b53ad4d477d4eeULL, 0x324d81a8a89aa829ULL, 0xf4315296966296c4ULL,
+	0x3aef62f9f9c3f99bULL, 0xf697a3c5c533c566ULL, 0xb14a102525942535ULL,
+	0x20b2ab59597959f2ULL, 0xae15d084842a8454ULL, 0xa7e4c57272d572b7ULL,
+	0xdd72ec3939e439d5ULL, 0x6198164c4c2d4c5aULL, 0x3bbc945e5e655ecaULL,
+	0x85f09f7878fd78e7ULL, 0xd870e53838e038ddULL, 0x8605988c8c0a8c14ULL,
+	0xb2bf17d1d163d1c6ULL, 0x0b57e4a5a5aea541ULL, 0x4dd9a1e2e2afe243ULL,
+	0xf8c24e616199612fULL, 0x457b42b3b3f6b3f1ULL, 0xa542342121842115ULL,
+	0xd625089c9c4a9c94ULL, 0x663cee1e1e781ef0ULL, 0x5286614343114322ULL,
+	0xfc93b1c7c73bc776ULL, 0x2be54ffcfcd7fcb3ULL, 0x1408240404100420ULL,
+	0x08a2e351515951b2ULL, 0xc72f2599995e99bcULL, 0xc4da226d6da96d4fULL,
+	0x391a650d0d340d68ULL, 0x35e979fafacffa83ULL, 0x84a369dfdf5bdfb6ULL,
+	0x9bfca97e7ee57ed7ULL, 0xb44819242490243dULL, 0xd776fe3b3bec3bc5ULL,
+	0x3d4b9aabab96ab31ULL, 0xd181f0cece1fce3eULL, 0x5522991111441188ULL,
+	0x8903838f8f068f0cULL, 0x6b9c044e4e254e4aULL, 0x517366b7b7e6b7d1ULL,
+	0x60cbe0ebeb8beb0bULL, 0xcc78c13c3cf03cfdULL, 0xbf1ffd81813e817cULL,
+	0xfe354094946a94d4ULL, 0x0cf31cf7f7fbf7ebULL, 0x676f18b9b9deb9a1ULL,
+	0x5f268b13134c1398ULL, 0x9c58512c2cb02c7dULL, 0xb8bb05d3d36bd3d6ULL,
+	0x5cd38ce7e7bbe76bULL, 0xcbdc396e6ea56e57ULL, 0xf395aac4c437c46eULL,
+	0x0f061b03030c0318ULL, 0x13acdc565645568aULL, 0x49885e44440d441aULL,
+	0x9efea07f7fe17fdfULL, 0x374f88a9a99ea921ULL, 0x8254672a2aa82a4dULL,
+	0x6d6b0abbbbd6bbb1ULL, 0xe29f87c1c123c146ULL, 0x02a6f153535153a2ULL,
+	0x8ba572dcdc57dcaeULL, 0x2716530b0b2c0b58ULL, 0xd327019d9d4e9d9cULL,
+	0xc1d82b6c6cad6c47ULL, 0xf562a43131c43195ULL, 0xb9e8f37474cd7487ULL,
+	0x09f115f6f6fff6e3ULL, 0x438c4c464605460aULL, 0x2645a5acac8aac09ULL,
+	0x970fb589891e893cULL, 0x4428b414145014a0ULL, 0x42dfbae1e1a3e15bULL,
+	0x4e2ca616165816b0ULL, 0xd274f73a3ae83acdULL, 0xd0d2066969b9696fULL,
+	0x2d12410909240948ULL, 0xade0d77070dd70a7ULL, 0x54716fb6b6e2b6d9ULL,
+	0xb7bd1ed0d067d0ceULL, 0x7ec7d6eded93ed3bULL, 0xdb85e2cccc17cc2eULL,
+	0x578468424215422aULL, 0xc22d2c98985a98b4ULL, 0x0e55eda4a4aaa449ULL,
+	0x8850752828a0285dULL, 0x31b8865c5c6d5cdaULL, 0x3fed6bf8f8c7f893ULL,
+	0xa411c28686228644ULL,
+};
+
+static const u64 C4[256] = {
+	0xc07830d818186018ULL, 0x05af462623238c23ULL, 0x7ef991b8c6c63fc6ULL,
+	0x136fcdfbe8e887e8ULL, 0x4ca113cb87872687ULL, 0xa9626d11b8b8dab8ULL,
+	0x0805020901010401ULL, 0x426e9e0d4f4f214fULL, 0xadee6c9b3636d836ULL,
+	0x590451ffa6a6a2a6ULL, 0xdebdb90cd2d26fd2ULL, 0xfb06f70ef5f5f3f5ULL,
+	0xef80f2967979f979ULL, 0x5fcede306f6fa16fULL, 0xfcef3f6d91917e91ULL,
+	0xaa07a4f852525552ULL, 0x27fdc04760609d60ULL, 0x89766535bcbccabcULL,
+	0xaccd2b379b9b569bULL, 0x048c018a8e8e028eULL, 0x71155bd2a3a3b6a3ULL,
+	0x603c186c0c0c300cULL, 0xff8af6847b7bf17bULL, 0xb5e16a803535d435ULL,
+	0xe8693af51d1d741dULL, 0x5347ddb3e0e0a7e0ULL, 0xf6acb321d7d77bd7ULL,
+	0x5eed999cc2c22fc2ULL, 0x6d965c432e2eb82eULL, 0x627a96294b4b314bULL,
+	0xa321e15dfefedffeULL, 0x8216aed557574157ULL, 0xa8412abd15155415ULL,
+	0x9fb6eee87777c177ULL, 0xa5eb6e923737dc37ULL, 0x7b56d79ee5e5b3e5ULL,
+	0x8cd923139f9f469fULL, 0xd317fd23f0f0e7f0ULL, 0x6a7f94204a4a354aULL,
+	0x9e95a944dada4fdaULL, 0xfa25b0a258587d58ULL, 0x06ca8fcfc9c903c9ULL,
+	0x558d527c2929a429ULL, 0x5022145a0a0a280aULL, 0xe14f7f50b1b1feb1ULL,
+	0x691a5dc9a0a0baa0ULL, 0x7fdad6146b6bb16bULL, 0x5cab17d985852e85ULL,
+	0x8173673cbdbdcebdULL, 0xd234ba8f5d5d695dULL, 0x8050209010104010ULL,
+	0xf303f507f4f4f7f4ULL, 0x16c08bddcbcb0bcbULL, 0xedc67cd33e3ef83eULL,
+	0x28110a2d05051405ULL, 0x1fe6ce7867678167ULL, 0x7353d597e4e4b7e4ULL,
+	0x25bb4e0227279c27ULL, 0x3258827341411941ULL, 0x2c9d0ba78b8b168bULL,
+	0x510153f6a7a7a6a7ULL, 0xcf94fab27d7de97dULL, 0xdcfb374995956e95ULL,
+	0x8e9fad56d8d847d8ULL, 0x8b30eb70fbfbcbfbULL, 0x2371c1cdeeee9feeULL,
+	0xc791f8bb7c7ced7cULL, 0x17e3cc7166668566ULL, 0xa68ea77bdddd53ddULL,
+	0xb84b2eaf17175c17ULL, 0x02468e4547470147ULL, 0x84dc211a9e9e429eULL,
+	0x1ec589d4caca0fcaULL, 0x75995a582d2db42dULL, 0x9179632ebfbfc6bfULL,
+	0x381b0e3f07071c07ULL, 0x012347acadad8eadULL, 0xea2fb4b05a5a755aULL,
+	0x6cb51bef83833683ULL, 0x85ff66b63333cc33ULL, 0x3ff2c65c63639163ULL,
+	0x100a041202020802ULL, 0x39384993aaaa92aaULL, 0xafa8e2de7171d971ULL,
+	0x0ecf8dc6c8c807c8ULL, 0xc87d32d119196419ULL, 0x7270923b49493949ULL,
+	0x869aaf5fd9d943d9ULL, 0xc31df931f2f2eff2ULL, 0x4b48dba8e3e3abe3ULL,
+	0xe22ab6b95b5b715bULL, 0x34920dbc88881a88ULL, 0xa4c8293e9a9a529aULL,
+	0x2dbe4c0b26269826ULL, 0x8dfa64bf3232c832ULL, 0xe94a7d59b0b0fab0ULL,
+	0x1b6acff2e9e983e9ULL, 0x78331e770f0f3c0fULL, 0xe6a6b733d5d573d5ULL,
+	0x74ba1df480803a80ULL, 0x997c6127bebec2beULL, 0x26de87ebcdcd13cdULL,
+	0xbde468893434d034ULL, 0x7a75903248483d48ULL, 0xab24e354ffffdbffULL,
+	0xf78ff48d7a7af57aULL, 0xf4ea3d6490907a90ULL, 0xc23ebe9d5f5f615fULL,
+	0x1da0403d20208020ULL, 0x67d5d00f6868bd68ULL, 0xd07234ca1a1a681aULL,
+	0x192c41b7aeae82aeULL, 0xc95e757db4b4eab4ULL, 0x9a19a8ce54544d54ULL,
+	0xece53b7f93937693ULL, 0x0daa442f22228822ULL, 0x07e9c86364648d64ULL,
+	0xdb12ff2af1f1e3f1ULL, 0xbfa2e6cc7373d173ULL, 0x905a248212124812ULL,
+	0x3a5d807a40401d40ULL, 0x4028104808082008ULL, 0x56e89b95c3c32bc3ULL,
+	0x337bc5dfecec97ecULL, 0x9690ab4ddbdb4bdbULL, 0x611f5fc0a1a1bea1ULL,
+	0x1c8307918d8d0e8dULL, 0xf5c97ac83d3df43dULL, 0xccf1335b97976697ULL,
+	0x0000000000000000ULL, 0x36d483f9cfcf1bcfULL, 0x4587566e2b2bac2bULL,
+	0x97b3ece17676c576ULL, 0x64b019e682823282ULL, 0xfea9b128d6d67fd6ULL,
+	0xd87736c31b1b6c1bULL, 0xc15b7774b5b5eeb5ULL, 0x112943beafaf86afULL,
+	0x77dfd41d6a6ab56aULL, 0xba0da0ea50505d50ULL, 0x124c8a5745450945ULL,
+	0xcb18fb38f3f3ebf3ULL, 0x9df060ad3030c030ULL, 0x2b74c3c4efef9befULL,
+	0xe5c37eda3f3ffc3fULL, 0x921caac755554955ULL, 0x791059dba2a2b2a2ULL,
+	0x0365c9e9eaea8feaULL, 0x0fecca6a65658965ULL, 0xb9686903babad2baULL,
+	0x65935e4a2f2fbc2fULL, 0x4ee79d8ec0c027c0ULL, 0xbe81a160dede5fdeULL,
+	0xe06c38fc1c1c701cULL, 0xbb2ee746fdfdd3fdULL, 0x52649a1f4d4d294dULL,
+	0xe4e0397692927292ULL, 0x8fbceafa7575c975ULL, 0x301e0c3606061806ULL,
+	0x249809ae8a8a128aULL, 0xf940794bb2b2f2b2ULL, 0x6359d185e6e6bfe6ULL,
+	0x70361c7e0e0e380eULL, 0xf8633ee71f1f7c1fULL, 0x37f7c45562629562ULL,
+	0xeea3b53ad4d477d4ULL, 0x29324d81a8a89aa8ULL, 0xc4f4315296966296ULL,
+	0x9b3aef62f9f9c3f9ULL, 0x66f697a3c5c533c5ULL, 0x35b14a1025259425ULL,
+	0xf220b2ab59597959ULL, 0x54ae15d084842a84ULL, 0xb7a7e4c57272d572ULL,
+	0xd5dd72ec3939e439ULL, 0x5a6198164c4c2d4cULL, 0xca3bbc945e5e655eULL,
+	0xe785f09f7878fd78ULL, 0xddd870e53838e038ULL, 0x148605988c8c0a8cULL,
+	0xc6b2bf17d1d163d1ULL, 0x410b57e4a5a5aea5ULL, 0x434dd9a1e2e2afe2ULL,
+	0x2ff8c24e61619961ULL, 0xf1457b42b3b3f6b3ULL, 0x15a5423421218421ULL,
+	0x94d625089c9c4a9cULL, 0xf0663cee1e1e781eULL, 0x2252866143431143ULL,
+	0x76fc93b1c7c73bc7ULL, 0xb32be54ffcfcd7fcULL, 0x2014082404041004ULL,
+	0xb208a2e351515951ULL, 0xbcc72f2599995e99ULL, 0x4fc4da226d6da96dULL,
+	0x68391a650d0d340dULL, 0x8335e979fafacffaULL, 0xb684a369dfdf5bdfULL,
+	0xd79bfca97e7ee57eULL, 0x3db4481924249024ULL, 0xc5d776fe3b3bec3bULL,
+	0x313d4b9aabab96abULL, 0x3ed181f0cece1fceULL, 0x8855229911114411ULL,
+	0x0c8903838f8f068fULL, 0x4a6b9c044e4e254eULL, 0xd1517366b7b7e6b7ULL,
+	0x0b60cbe0ebeb8bebULL, 0xfdcc78c13c3cf03cULL, 0x7cbf1ffd81813e81ULL,
+	0xd4fe354094946a94ULL, 0xeb0cf31cf7f7fbf7ULL, 0xa1676f18b9b9deb9ULL,
+	0x985f268b13134c13ULL, 0x7d9c58512c2cb02cULL, 0xd6b8bb05d3d36bd3ULL,
+	0x6b5cd38ce7e7bbe7ULL, 0x57cbdc396e6ea56eULL, 0x6ef395aac4c437c4ULL,
+	0x180f061b03030c03ULL, 0x8a13acdc56564556ULL, 0x1a49885e44440d44ULL,
+	0xdf9efea07f7fe17fULL, 0x21374f88a9a99ea9ULL, 0x4d8254672a2aa82aULL,
+	0xb16d6b0abbbbd6bbULL, 0x46e29f87c1c123c1ULL, 0xa202a6f153535153ULL,
+	0xae8ba572dcdc57dcULL, 0x582716530b0b2c0bULL, 0x9cd327019d9d4e9dULL,
+	0x47c1d82b6c6cad6cULL, 0x95f562a43131c431ULL, 0x87b9e8f37474cd74ULL,
+	0xe309f115f6f6fff6ULL, 0x0a438c4c46460546ULL, 0x092645a5acac8aacULL,
+	0x3c970fb589891e89ULL, 0xa04428b414145014ULL, 0x5b42dfbae1e1a3e1ULL,
+	0xb04e2ca616165816ULL, 0xcdd274f73a3ae83aULL, 0x6fd0d2066969b969ULL,
+	0x482d124109092409ULL, 0xa7ade0d77070dd70ULL, 0xd954716fb6b6e2b6ULL,
+	0xceb7bd1ed0d067d0ULL, 0x3b7ec7d6eded93edULL, 0x2edb85e2cccc17ccULL,
+	0x2a57846842421542ULL, 0xb4c22d2c98985a98ULL, 0x490e55eda4a4aaa4ULL,
+	0x5d8850752828a028ULL, 0xda31b8865c5c6d5cULL, 0x933fed6bf8f8c7f8ULL,
+	0x44a411c286862286ULL,
+};
+
+static const u64 C5[256] = {
+	0x18c07830d8181860ULL, 0x2305af462623238cULL, 0xc67ef991b8c6c63fULL,
+	0xe8136fcdfbe8e887ULL, 0x874ca113cb878726ULL, 0xb8a9626d11b8b8daULL,
+	0x0108050209010104ULL, 0x4f426e9e0d4f4f21ULL, 0x36adee6c9b3636d8ULL,
+	0xa6590451ffa6a6a2ULL, 0xd2debdb90cd2d26fULL, 0xf5fb06f70ef5f5f3ULL,
+	0x79ef80f2967979f9ULL, 0x6f5fcede306f6fa1ULL, 0x91fcef3f6d91917eULL,
+	0x52aa07a4f8525255ULL, 0x6027fdc04760609dULL, 0xbc89766535bcbccaULL,
+	0x9baccd2b379b9b56ULL, 0x8e048c018a8e8e02ULL, 0xa371155bd2a3a3b6ULL,
+	0x0c603c186c0c0c30ULL, 0x7bff8af6847b7bf1ULL, 0x35b5e16a803535d4ULL,
+	0x1de8693af51d1d74ULL, 0xe05347ddb3e0e0a7ULL, 0xd7f6acb321d7d77bULL,
+	0xc25eed999cc2c22fULL, 0x2e6d965c432e2eb8ULL, 0x4b627a96294b4b31ULL,
+	0xfea321e15dfefedfULL, 0x578216aed5575741ULL, 0x15a8412abd151554ULL,
+	0x779fb6eee87777c1ULL, 0x37a5eb6e923737dcULL, 0xe57b56d79ee5e5b3ULL,
+	0x9f8cd923139f9f46ULL, 0xf0d317fd23f0f0e7ULL, 0x4a6a7f94204a4a35ULL,
+	0xda9e95a944dada4fULL, 0x58fa25b0a258587dULL, 0xc906ca8fcfc9c903ULL,
+	0x29558d527c2929a4ULL, 0x0a5022145a0a0a28ULL, 0xb1e14f7f50b1b1feULL,
+	0xa0691a5dc9a0a0baULL, 0x6b7fdad6146b6bb1ULL, 0x855cab17d985852eULL,
+	0xbd8173673cbdbdceULL, 0x5dd234ba8f5d5d69ULL, 0x1080502090101040ULL,
+	0xf4f303f507f4f4f7ULL, 0xcb16c08bddcbcb0bULL, 0x3eedc67cd33e3ef8ULL,
+	0x0528110a2d050514ULL, 0x671fe6ce78676781ULL, 0xe47353d597e4e4b7ULL,
+	0x2725bb4e0227279cULL, 0x4132588273414119ULL, 0x8b2c9d0ba78b8b16ULL,
+	0xa7510153f6a7a7a6ULL, 0x7dcf94fab27d7de9ULL, 0x95dcfb374995956eULL,
+	0xd88e9fad56d8d847ULL, 0xfb8b30eb70fbfbcbULL, 0xee2371c1cdeeee9fULL,
+	0x7cc791f8bb7c7cedULL, 0x6617e3cc71666685ULL, 0xdda68ea77bdddd53ULL,
+	0x17b84b2eaf17175cULL, 0x4702468e45474701ULL, 0x9e84dc211a9e9e42ULL,
+	0xca1ec589d4caca0fULL, 0x2d75995a582d2db4ULL, 0xbf9179632ebfbfc6ULL,
+	0x07381b0e3f07071cULL, 0xad012347acadad8eULL, 0x5aea2fb4b05a5a75ULL,
+	0x836cb51bef838336ULL, 0x3385ff66b63333ccULL, 0x633ff2c65c636391ULL,
+	0x02100a0412020208ULL, 0xaa39384993aaaa92ULL, 0x71afa8e2de7171d9ULL,
+	0xc80ecf8dc6c8c807ULL, 0x19c87d32d1191964ULL, 0x497270923b494939ULL,
+	0xd9869aaf5fd9d943ULL, 0xf2c31df931f2f2efULL, 0xe34b48dba8e3e3abULL,
+	0x5be22ab6b95b5b71ULL, 0x8834920dbc88881aULL, 0x9aa4c8293e9a9a52ULL,
+	0x262dbe4c0b262698ULL, 0x328dfa64bf3232c8ULL, 0xb0e94a7d59b0b0faULL,
+	0xe91b6acff2e9e983ULL, 0x0f78331e770f0f3cULL, 0xd5e6a6b733d5d573ULL,
+	0x8074ba1df480803aULL, 0xbe997c6127bebec2ULL, 0xcd26de87ebcdcd13ULL,
+	0x34bde468893434d0ULL, 0x487a75903248483dULL, 0xffab24e354ffffdbULL,
+	0x7af78ff48d7a7af5ULL, 0x90f4ea3d6490907aULL, 0x5fc23ebe9d5f5f61ULL,
+	0x201da0403d202080ULL, 0x6867d5d00f6868bdULL, 0x1ad07234ca1a1a68ULL,
+	0xae192c41b7aeae82ULL, 0xb4c95e757db4b4eaULL, 0x549a19a8ce54544dULL,
+	0x93ece53b7f939376ULL, 0x220daa442f222288ULL, 0x6407e9c86364648dULL,
+	0xf1db12ff2af1f1e3ULL, 0x73bfa2e6cc7373d1ULL, 0x12905a2482121248ULL,
+	0x403a5d807a40401dULL, 0x0840281048080820ULL, 0xc356e89b95c3c32bULL,
+	0xec337bc5dfecec97ULL, 0xdb9690ab4ddbdb4bULL, 0xa1611f5fc0a1a1beULL,
+	0x8d1c8307918d8d0eULL, 0x3df5c97ac83d3df4ULL, 0x97ccf1335b979766ULL,
+	0x0000000000000000ULL, 0xcf36d483f9cfcf1bULL, 0x2b4587566e2b2bacULL,
+	0x7697b3ece17676c5ULL, 0x8264b019e6828232ULL, 0xd6fea9b128d6d67fULL,
+	0x1bd87736c31b1b6cULL, 0xb5c15b7774b5b5eeULL, 0xaf112943beafaf86ULL,
+	0x6a77dfd41d6a6ab5ULL, 0x50ba0da0ea50505dULL, 0x45124c8a57454509ULL,
+	0xf3cb18fb38f3f3ebULL, 0x309df060ad3030c0ULL, 0xef2b74c3c4efef9bULL,
+	0x3fe5c37eda3f3ffcULL, 0x55921caac7555549ULL, 0xa2791059dba2a2b2ULL,
+	0xea0365c9e9eaea8fULL, 0x650fecca6a656589ULL, 0xbab9686903babad2ULL,
+	0x2f65935e4a2f2fbcULL, 0xc04ee79d8ec0c027ULL, 0xdebe81a160dede5fULL,
+	0x1ce06c38fc1c1c70ULL, 0xfdbb2ee746fdfdd3ULL, 0x4d52649a1f4d4d29ULL,
+	0x92e4e03976929272ULL, 0x758fbceafa7575c9ULL, 0x06301e0c36060618ULL,
+	0x8a249809ae8a8a12ULL, 0xb2f940794bb2b2f2ULL, 0xe66359d185e6e6bfULL,
+	0x0e70361c7e0e0e38ULL, 0x1ff8633ee71f1f7cULL, 0x6237f7c455626295ULL,
+	0xd4eea3b53ad4d477ULL, 0xa829324d81a8a89aULL, 0x96c4f43152969662ULL,
+	0xf99b3aef62f9f9c3ULL, 0xc566f697a3c5c533ULL, 0x2535b14a10252594ULL,
+	0x59f220b2ab595979ULL, 0x8454ae15d084842aULL, 0x72b7a7e4c57272d5ULL,
+	0x39d5dd72ec3939e4ULL, 0x4c5a6198164c4c2dULL, 0x5eca3bbc945e5e65ULL,
+	0x78e785f09f7878fdULL, 0x38ddd870e53838e0ULL, 0x8c148605988c8c0aULL,
+	0xd1c6b2bf17d1d163ULL, 0xa5410b57e4a5a5aeULL, 0xe2434dd9a1e2e2afULL,
+	0x612ff8c24e616199ULL, 0xb3f1457b42b3b3f6ULL, 0x2115a54234212184ULL,
+	0x9c94d625089c9c4aULL, 0x1ef0663cee1e1e78ULL, 0x4322528661434311ULL,
+	0xc776fc93b1c7c73bULL, 0xfcb32be54ffcfcd7ULL, 0x0420140824040410ULL,
+	0x51b208a2e3515159ULL, 0x99bcc72f2599995eULL, 0x6d4fc4da226d6da9ULL,
+	0x0d68391a650d0d34ULL, 0xfa8335e979fafacfULL, 0xdfb684a369dfdf5bULL,
+	0x7ed79bfca97e7ee5ULL, 0x243db44819242490ULL, 0x3bc5d776fe3b3becULL,
+	0xab313d4b9aabab96ULL, 0xce3ed181f0cece1fULL, 0x1188552299111144ULL,
+	0x8f0c8903838f8f06ULL, 0x4e4a6b9c044e4e25ULL, 0xb7d1517366b7b7e6ULL,
+	0xeb0b60cbe0ebeb8bULL, 0x3cfdcc78c13c3cf0ULL, 0x817cbf1ffd81813eULL,
+	0x94d4fe354094946aULL, 0xf7eb0cf31cf7f7fbULL, 0xb9a1676f18b9b9deULL,
+	0x13985f268b13134cULL, 0x2c7d9c58512c2cb0ULL, 0xd3d6b8bb05d3d36bULL,
+	0xe76b5cd38ce7e7bbULL, 0x6e57cbdc396e6ea5ULL, 0xc46ef395aac4c437ULL,
+	0x03180f061b03030cULL, 0x568a13acdc565645ULL, 0x441a49885e44440dULL,
+	0x7fdf9efea07f7fe1ULL, 0xa921374f88a9a99eULL, 0x2a4d8254672a2aa8ULL,
+	0xbbb16d6b0abbbbd6ULL, 0xc146e29f87c1c123ULL, 0x53a202a6f1535351ULL,
+	0xdcae8ba572dcdc57ULL, 0x0b582716530b0b2cULL, 0x9d9cd327019d9d4eULL,
+	0x6c47c1d82b6c6cadULL, 0x3195f562a43131c4ULL, 0x7487b9e8f37474cdULL,
+	0xf6e309f115f6f6ffULL, 0x460a438c4c464605ULL, 0xac092645a5acac8aULL,
+	0x893c970fb589891eULL, 0x14a04428b4141450ULL, 0xe15b42dfbae1e1a3ULL,
+	0x16b04e2ca6161658ULL, 0x3acdd274f73a3ae8ULL, 0x696fd0d2066969b9ULL,
+	0x09482d1241090924ULL, 0x70a7ade0d77070ddULL, 0xb6d954716fb6b6e2ULL,
+	0xd0ceb7bd1ed0d067ULL, 0xed3b7ec7d6eded93ULL, 0xcc2edb85e2cccc17ULL,
+	0x422a578468424215ULL, 0x98b4c22d2c98985aULL, 0xa4490e55eda4a4aaULL,
+	0x285d8850752828a0ULL, 0x5cda31b8865c5c6dULL, 0xf8933fed6bf8f8c7ULL,
+	0x8644a411c2868622ULL,
+};
+
+static const u64 C6[256] = {
+	0x6018c07830d81818ULL, 0x8c2305af46262323ULL, 0x3fc67ef991b8c6c6ULL,
+	0x87e8136fcdfbe8e8ULL, 0x26874ca113cb8787ULL, 0xdab8a9626d11b8b8ULL,
+	0x0401080502090101ULL, 0x214f426e9e0d4f4fULL, 0xd836adee6c9b3636ULL,
+	0xa2a6590451ffa6a6ULL, 0x6fd2debdb90cd2d2ULL, 0xf3f5fb06f70ef5f5ULL,
+	0xf979ef80f2967979ULL, 0xa16f5fcede306f6fULL, 0x7e91fcef3f6d9191ULL,
+	0x5552aa07a4f85252ULL, 0x9d6027fdc0476060ULL, 0xcabc89766535bcbcULL,
+	0x569baccd2b379b9bULL, 0x028e048c018a8e8eULL, 0xb6a371155bd2a3a3ULL,
+	0x300c603c186c0c0cULL, 0xf17bff8af6847b7bULL, 0xd435b5e16a803535ULL,
+	0x741de8693af51d1dULL, 0xa7e05347ddb3e0e0ULL, 0x7bd7f6acb321d7d7ULL,
+	0x2fc25eed999cc2c2ULL, 0xb82e6d965c432e2eULL, 0x314b627a96294b4bULL,
+	0xdffea321e15dfefeULL, 0x41578216aed55757ULL, 0x5415a8412abd1515ULL,
+	0xc1779fb6eee87777ULL, 0xdc37a5eb6e923737ULL, 0xb3e57b56d79ee5e5ULL,
+	0x469f8cd923139f9fULL, 0xe7f0d317fd23f0f0ULL, 0x354a6a7f94204a4aULL,
+	0x4fda9e95a944dadaULL, 0x7d58fa25b0a25858ULL, 0x03c906ca8fcfc9c9ULL,
+	0xa429558d527c2929ULL, 0x280a5022145a0a0aULL, 0xfeb1e14f7f50b1b1ULL,
+	0xbaa0691a5dc9a0a0ULL, 0xb16b7fdad6146b6bULL, 0x2e855cab17d98585ULL,
+	0xcebd8173673cbdbdULL, 0x695dd234ba8f5d5dULL, 0x4010805020901010ULL,
+	0xf7f4f303f507f4f4ULL, 0x0bcb16c08bddcbcbULL, 0xf83eedc67cd33e3eULL,
+	0x140528110a2d0505ULL, 0x81671fe6ce786767ULL, 0xb7e47353d597e4e4ULL,
+	0x9c2725bb4e022727ULL, 0x1941325882734141ULL, 0x168b2c9d0ba78b8bULL,
+	0xa6a7510153f6a7a7ULL, 0xe97dcf94fab27d7dULL, 0x6e95dcfb37499595ULL,
+	0x47d88e9fad56d8d8ULL, 0xcbfb8b30eb70fbfbULL, 0x9fee2371c1cdeeeeULL,
+	0xed7cc791f8bb7c7cULL, 0x856617e3cc716666ULL, 0x53dda68ea77bddddULL,
+	0x5c17b84b2eaf1717ULL, 0x014702468e454747ULL, 0x429e84dc211a9e9eULL,
+	0x0fca1ec589d4cacaULL, 0xb42d75995a582d2dULL, 0xc6bf9179632ebfbfULL,
+	0x1c07381b0e3f0707ULL, 0x8ead012347acadadULL, 0x755aea2fb4b05a5aULL,
+	0x36836cb51bef8383ULL, 0xcc3385ff66b63333ULL, 0x91633ff2c65c6363ULL,
+	0x0802100a04120202ULL, 0x92aa39384993aaaaULL, 0xd971afa8e2de7171ULL,
+	0x07c80ecf8dc6c8c8ULL, 0x6419c87d32d11919ULL, 0x39497270923b4949ULL,
+	0x43d9869aaf5fd9d9ULL, 0xeff2c31df931f2f2ULL, 0xabe34b48dba8e3e3ULL,
+	0x715be22ab6b95b5bULL, 0x1a8834920dbc8888ULL, 0x529aa4c8293e9a9aULL,
+	0x98262dbe4c0b2626ULL, 0xc8328dfa64bf3232ULL, 0xfab0e94a7d59b0b0ULL,
+	0x83e91b6acff2e9e9ULL, 0x3c0f78331e770f0fULL, 0x73d5e6a6b733d5d5ULL,
+	0x3a8074ba1df48080ULL, 0xc2be997c6127bebeULL, 0x13cd26de87ebcdcdULL,
+	0xd034bde468893434ULL, 0x3d487a7590324848ULL, 0xdbffab24e354ffffULL,
+	0xf57af78ff48d7a7aULL, 0x7a90f4ea3d649090ULL, 0x615fc23ebe9d5f5fULL,
+	0x80201da0403d2020ULL, 0xbd6867d5d00f6868ULL, 0x681ad07234ca1a1aULL,
+	0x82ae192c41b7aeaeULL, 0xeab4c95e757db4b4ULL, 0x4d549a19a8ce5454ULL,
+	0x7693ece53b7f9393ULL, 0x88220daa442f2222ULL, 0x8d6407e9c8636464ULL,
+	0xe3f1db12ff2af1f1ULL, 0xd173bfa2e6cc7373ULL, 0x4812905a24821212ULL,
+	0x1d403a5d807a4040ULL, 0x2008402810480808ULL, 0x2bc356e89b95c3c3ULL,
+	0x97ec337bc5dfececULL, 0x4bdb9690ab4ddbdbULL, 0xbea1611f5fc0a1a1ULL,
+	0x0e8d1c8307918d8dULL, 0xf43df5c97ac83d3dULL, 0x6697ccf1335b9797ULL,
+	0x0000000000000000ULL, 0x1bcf36d483f9cfcfULL, 0xac2b4587566e2b2bULL,
+	0xc57697b3ece17676ULL, 0x328264b019e68282ULL, 0x7fd6fea9b128d6d6ULL,
+	0x6c1bd87736c31b1bULL, 0xeeb5c15b7774b5b5ULL, 0x86af112943beafafULL,
+	0xb56a77dfd41d6a6aULL, 0x5d50ba0da0ea5050ULL, 0x0945124c8a574545ULL,
+	0xebf3cb18fb38f3f3ULL, 0xc0309df060ad3030ULL, 0x9bef2b74c3c4efefULL,
+	0xfc3fe5c37eda3f3fULL, 0x4955921caac75555ULL, 0xb2a2791059dba2a2ULL,
+	0x8fea0365c9e9eaeaULL, 0x89650fecca6a6565ULL, 0xd2bab9686903babaULL,
+	0xbc2f65935e4a2f2fULL, 0x27c04ee79d8ec0c0ULL, 0x5fdebe81a160dedeULL,
+	0x701ce06c38fc1c1cULL, 0xd3fdbb2ee746fdfdULL, 0x294d52649a1f4d4dULL,
+	0x7292e4e039769292ULL, 0xc9758fbceafa7575ULL, 0x1806301e0c360606ULL,
+	0x128a249809ae8a8aULL, 0xf2b2f940794bb2b2ULL, 0xbfe66359d185e6e6ULL,
+	0x380e70361c7e0e0eULL, 0x7c1ff8633ee71f1fULL, 0x956237f7c4556262ULL,
+	0x77d4eea3b53ad4d4ULL, 0x9aa829324d81a8a8ULL, 0x6296c4f431529696ULL,
+	0xc3f99b3aef62f9f9ULL, 0x33c566f697a3c5c5ULL, 0x942535b14a102525ULL,
+	0x7959f220b2ab5959ULL, 0x2a8454ae15d08484ULL, 0xd572b7a7e4c57272ULL,
+	0xe439d5dd72ec3939ULL, 0x2d4c5a6198164c4cULL, 0x655eca3bbc945e5eULL,
+	0xfd78e785f09f7878ULL, 0xe038ddd870e53838ULL, 0x0a8c148605988c8cULL,
+	0x63d1c6b2bf17d1d1ULL, 0xaea5410b57e4a5a5ULL, 0xafe2434dd9a1e2e2ULL,
+	0x99612ff8c24e6161ULL, 0xf6b3f1457b42b3b3ULL, 0x842115a542342121ULL,
+	0x4a9c94d625089c9cULL, 0x781ef0663cee1e1eULL, 0x1143225286614343ULL,
+	0x3bc776fc93b1c7c7ULL, 0xd7fcb32be54ffcfcULL, 0x1004201408240404ULL,
+	0x5951b208a2e35151ULL, 0x5e99bcc72f259999ULL, 0xa96d4fc4da226d6dULL,
+	0x340d68391a650d0dULL, 0xcffa8335e979fafaULL, 0x5bdfb684a369dfdfULL,
+	0xe57ed79bfca97e7eULL, 0x90243db448192424ULL, 0xec3bc5d776fe3b3bULL,
+	0x96ab313d4b9aababULL, 0x1fce3ed181f0ceceULL, 0x4411885522991111ULL,
+	0x068f0c8903838f8fULL, 0x254e4a6b9c044e4eULL, 0xe6b7d1517366b7b7ULL,
+	0x8beb0b60cbe0ebebULL, 0xf03cfdcc78c13c3cULL, 0x3e817cbf1ffd8181ULL,
+	0x6a94d4fe35409494ULL, 0xfbf7eb0cf31cf7f7ULL, 0xdeb9a1676f18b9b9ULL,
+	0x4c13985f268b1313ULL, 0xb02c7d9c58512c2cULL, 0x6bd3d6b8bb05d3d3ULL,
+	0xbbe76b5cd38ce7e7ULL, 0xa56e57cbdc396e6eULL, 0x37c46ef395aac4c4ULL,
+	0x0c03180f061b0303ULL, 0x45568a13acdc5656ULL, 0x0d441a49885e4444ULL,
+	0xe17fdf9efea07f7fULL, 0x9ea921374f88a9a9ULL, 0xa82a4d8254672a2aULL,
+	0xd6bbb16d6b0abbbbULL, 0x23c146e29f87c1c1ULL, 0x5153a202a6f15353ULL,
+	0x57dcae8ba572dcdcULL, 0x2c0b582716530b0bULL, 0x4e9d9cd327019d9dULL,
+	0xad6c47c1d82b6c6cULL, 0xc43195f562a43131ULL, 0xcd7487b9e8f37474ULL,
+	0xfff6e309f115f6f6ULL, 0x05460a438c4c4646ULL, 0x8aac092645a5acacULL,
+	0x1e893c970fb58989ULL, 0x5014a04428b41414ULL, 0xa3e15b42dfbae1e1ULL,
+	0x5816b04e2ca61616ULL, 0xe83acdd274f73a3aULL, 0xb9696fd0d2066969ULL,
+	0x2409482d12410909ULL, 0xdd70a7ade0d77070ULL, 0xe2b6d954716fb6b6ULL,
+	0x67d0ceb7bd1ed0d0ULL, 0x93ed3b7ec7d6ededULL, 0x17cc2edb85e2ccccULL,
+	0x15422a5784684242ULL, 0x5a98b4c22d2c9898ULL, 0xaaa4490e55eda4a4ULL,
+	0xa0285d8850752828ULL, 0x6d5cda31b8865c5cULL, 0xc7f8933fed6bf8f8ULL,
+	0x228644a411c28686ULL,
+};
+
+static const u64 C7[256] = {
+	0x186018c07830d818ULL, 0x238c2305af462623ULL, 0xc63fc67ef991b8c6ULL,
+	0xe887e8136fcdfbe8ULL, 0x8726874ca113cb87ULL, 0xb8dab8a9626d11b8ULL,
+	0x0104010805020901ULL, 0x4f214f426e9e0d4fULL, 0x36d836adee6c9b36ULL,
+	0xa6a2a6590451ffa6ULL, 0xd26fd2debdb90cd2ULL, 0xf5f3f5fb06f70ef5ULL,
+	0x79f979ef80f29679ULL, 0x6fa16f5fcede306fULL, 0x917e91fcef3f6d91ULL,
+	0x525552aa07a4f852ULL, 0x609d6027fdc04760ULL, 0xbccabc89766535bcULL,
+	0x9b569baccd2b379bULL, 0x8e028e048c018a8eULL, 0xa3b6a371155bd2a3ULL,
+	0x0c300c603c186c0cULL, 0x7bf17bff8af6847bULL, 0x35d435b5e16a8035ULL,
+	0x1d741de8693af51dULL, 0xe0a7e05347ddb3e0ULL, 0xd77bd7f6acb321d7ULL,
+	0xc22fc25eed999cc2ULL, 0x2eb82e6d965c432eULL, 0x4b314b627a96294bULL,
+	0xfedffea321e15dfeULL, 0x5741578216aed557ULL, 0x155415a8412abd15ULL,
+	0x77c1779fb6eee877ULL, 0x37dc37a5eb6e9237ULL, 0xe5b3e57b56d79ee5ULL,
+	0x9f469f8cd923139fULL, 0xf0e7f0d317fd23f0ULL, 0x4a354a6a7f94204aULL,
+	0xda4fda9e95a944daULL, 0x587d58fa25b0a258ULL, 0xc903c906ca8fcfc9ULL,
+	0x29a429558d527c29ULL, 0x0a280a5022145a0aULL, 0xb1feb1e14f7f50b1ULL,
+	0xa0baa0691a5dc9a0ULL, 0x6bb16b7fdad6146bULL, 0x852e855cab17d985ULL,
+	0xbdcebd8173673cbdULL, 0x5d695dd234ba8f5dULL, 0x1040108050209010ULL,
+	0xf4f7f4f303f507f4ULL, 0xcb0bcb16c08bddcbULL, 0x3ef83eedc67cd33eULL,
+	0x05140528110a2d05ULL, 0x6781671fe6ce7867ULL, 0xe4b7e47353d597e4ULL,
+	0x279c2725bb4e0227ULL, 0x4119413258827341ULL, 0x8b168b2c9d0ba78bULL,
+	0xa7a6a7510153f6a7ULL, 0x7de97dcf94fab27dULL, 0x956e95dcfb374995ULL,
+	0xd847d88e9fad56d8ULL, 0xfbcbfb8b30eb70fbULL, 0xee9fee2371c1cdeeULL,
+	0x7ced7cc791f8bb7cULL, 0x66856617e3cc7166ULL, 0xdd53dda68ea77bddULL,
+	0x175c17b84b2eaf17ULL, 0x47014702468e4547ULL, 0x9e429e84dc211a9eULL,
+	0xca0fca1ec589d4caULL, 0x2db42d75995a582dULL, 0xbfc6bf9179632ebfULL,
+	0x071c07381b0e3f07ULL, 0xad8ead012347acadULL, 0x5a755aea2fb4b05aULL,
+	0x8336836cb51bef83ULL, 0x33cc3385ff66b633ULL, 0x6391633ff2c65c63ULL,
+	0x020802100a041202ULL, 0xaa92aa39384993aaULL, 0x71d971afa8e2de71ULL,
+	0xc807c80ecf8dc6c8ULL, 0x196419c87d32d119ULL, 0x4939497270923b49ULL,
+	0xd943d9869aaf5fd9ULL, 0xf2eff2c31df931f2ULL, 0xe3abe34b48dba8e3ULL,
+	0x5b715be22ab6b95bULL, 0x881a8834920dbc88ULL, 0x9a529aa4c8293e9aULL,
+	0x2698262dbe4c0b26ULL, 0x32c8328dfa64bf32ULL, 0xb0fab0e94a7d59b0ULL,
+	0xe983e91b6acff2e9ULL, 0x0f3c0f78331e770fULL, 0xd573d5e6a6b733d5ULL,
+	0x803a8074ba1df480ULL, 0xbec2be997c6127beULL, 0xcd13cd26de87ebcdULL,
+	0x34d034bde4688934ULL, 0x483d487a75903248ULL, 0xffdbffab24e354ffULL,
+	0x7af57af78ff48d7aULL, 0x907a90f4ea3d6490ULL, 0x5f615fc23ebe9d5fULL,
+	0x2080201da0403d20ULL, 0x68bd6867d5d00f68ULL, 0x1a681ad07234ca1aULL,
+	0xae82ae192c41b7aeULL, 0xb4eab4c95e757db4ULL, 0x544d549a19a8ce54ULL,
+	0x937693ece53b7f93ULL, 0x2288220daa442f22ULL, 0x648d6407e9c86364ULL,
+	0xf1e3f1db12ff2af1ULL, 0x73d173bfa2e6cc73ULL, 0x124812905a248212ULL,
+	0x401d403a5d807a40ULL, 0x0820084028104808ULL, 0xc32bc356e89b95c3ULL,
+	0xec97ec337bc5dfecULL, 0xdb4bdb9690ab4ddbULL, 0xa1bea1611f5fc0a1ULL,
+	0x8d0e8d1c8307918dULL, 0x3df43df5c97ac83dULL, 0x976697ccf1335b97ULL,
+	0x0000000000000000ULL, 0xcf1bcf36d483f9cfULL, 0x2bac2b4587566e2bULL,
+	0x76c57697b3ece176ULL, 0x82328264b019e682ULL, 0xd67fd6fea9b128d6ULL,
+	0x1b6c1bd87736c31bULL, 0xb5eeb5c15b7774b5ULL, 0xaf86af112943beafULL,
+	0x6ab56a77dfd41d6aULL, 0x505d50ba0da0ea50ULL, 0x450945124c8a5745ULL,
+	0xf3ebf3cb18fb38f3ULL, 0x30c0309df060ad30ULL, 0xef9bef2b74c3c4efULL,
+	0x3ffc3fe5c37eda3fULL, 0x554955921caac755ULL, 0xa2b2a2791059dba2ULL,
+	0xea8fea0365c9e9eaULL, 0x6589650fecca6a65ULL, 0xbad2bab9686903baULL,
+	0x2fbc2f65935e4a2fULL, 0xc027c04ee79d8ec0ULL, 0xde5fdebe81a160deULL,
+	0x1c701ce06c38fc1cULL, 0xfdd3fdbb2ee746fdULL, 0x4d294d52649a1f4dULL,
+	0x927292e4e0397692ULL, 0x75c9758fbceafa75ULL, 0x061806301e0c3606ULL,
+	0x8a128a249809ae8aULL, 0xb2f2b2f940794bb2ULL, 0xe6bfe66359d185e6ULL,
+	0x0e380e70361c7e0eULL, 0x1f7c1ff8633ee71fULL, 0x62956237f7c45562ULL,
+	0xd477d4eea3b53ad4ULL, 0xa89aa829324d81a8ULL, 0x966296c4f4315296ULL,
+	0xf9c3f99b3aef62f9ULL, 0xc533c566f697a3c5ULL, 0x25942535b14a1025ULL,
+	0x597959f220b2ab59ULL, 0x842a8454ae15d084ULL, 0x72d572b7a7e4c572ULL,
+	0x39e439d5dd72ec39ULL, 0x4c2d4c5a6198164cULL, 0x5e655eca3bbc945eULL,
+	0x78fd78e785f09f78ULL, 0x38e038ddd870e538ULL, 0x8c0a8c148605988cULL,
+	0xd163d1c6b2bf17d1ULL, 0xa5aea5410b57e4a5ULL, 0xe2afe2434dd9a1e2ULL,
+	0x6199612ff8c24e61ULL, 0xb3f6b3f1457b42b3ULL, 0x21842115a5423421ULL,
+	0x9c4a9c94d625089cULL, 0x1e781ef0663cee1eULL, 0x4311432252866143ULL,
+	0xc73bc776fc93b1c7ULL, 0xfcd7fcb32be54ffcULL, 0x0410042014082404ULL,
+	0x515951b208a2e351ULL, 0x995e99bcc72f2599ULL, 0x6da96d4fc4da226dULL,
+	0x0d340d68391a650dULL, 0xfacffa8335e979faULL, 0xdf5bdfb684a369dfULL,
+	0x7ee57ed79bfca97eULL, 0x2490243db4481924ULL, 0x3bec3bc5d776fe3bULL,
+	0xab96ab313d4b9aabULL, 0xce1fce3ed181f0ceULL, 0x1144118855229911ULL,
+	0x8f068f0c8903838fULL, 0x4e254e4a6b9c044eULL, 0xb7e6b7d1517366b7ULL,
+	0xeb8beb0b60cbe0ebULL, 0x3cf03cfdcc78c13cULL, 0x813e817cbf1ffd81ULL,
+	0x946a94d4fe354094ULL, 0xf7fbf7eb0cf31cf7ULL, 0xb9deb9a1676f18b9ULL,
+	0x134c13985f268b13ULL, 0x2cb02c7d9c58512cULL, 0xd36bd3d6b8bb05d3ULL,
+	0xe7bbe76b5cd38ce7ULL, 0x6ea56e57cbdc396eULL, 0xc437c46ef395aac4ULL,
+	0x030c03180f061b03ULL, 0x5645568a13acdc56ULL, 0x440d441a49885e44ULL,
+	0x7fe17fdf9efea07fULL, 0xa99ea921374f88a9ULL, 0x2aa82a4d8254672aULL,
+	0xbbd6bbb16d6b0abbULL, 0xc123c146e29f87c1ULL, 0x535153a202a6f153ULL,
+	0xdc57dcae8ba572dcULL, 0x0b2c0b582716530bULL, 0x9d4e9d9cd327019dULL,
+	0x6cad6c47c1d82b6cULL, 0x31c43195f562a431ULL, 0x74cd7487b9e8f374ULL,
+	0xf6fff6e309f115f6ULL, 0x4605460a438c4c46ULL, 0xac8aac092645a5acULL,
+	0x891e893c970fb589ULL, 0x145014a04428b414ULL, 0xe1a3e15b42dfbae1ULL,
+	0x165816b04e2ca616ULL, 0x3ae83acdd274f73aULL, 0x69b9696fd0d20669ULL,
+	0x092409482d124109ULL, 0x70dd70a7ade0d770ULL, 0xb6e2b6d954716fb6ULL,
+	0xd067d0ceb7bd1ed0ULL, 0xed93ed3b7ec7d6edULL, 0xcc17cc2edb85e2ccULL,
+	0x4215422a57846842ULL, 0x985a98b4c22d2c98ULL, 0xa4aaa4490e55eda4ULL,
+	0x28a0285d88507528ULL, 0x5c6d5cda31b8865cULL, 0xf8c7f8933fed6bf8ULL,
+	0x86228644a411c286ULL,
+};
+
+static const u64 rc[WHIRLPOOL_ROUNDS + 1] = {
+	0x0000000000000000ULL, 0x1823c6e887b8014fULL, 0x36a6d2f5796f9152ULL,
+	0x60bc9b8ea30c7b35ULL, 0x1de0d7c22e4bfe57ULL, 0x157737e59ff04adaULL,
+	0x58c9290ab1a06b85ULL, 0xbd5d10f4cb3e0567ULL, 0xe427418ba77d95d8ULL,
+	0xfbee7c66dd17479eULL, 0xca2dbf07ad5a8333ULL,
+};
+
+/**
+ * The core Whirlpool transform.
+ */
+
+static void whirlpool_process_buffer(struct whirlpool_ctx *wctx) {
+	int i, r;
+	u64 K[8];        /* the round key */
+	u64 block[8];    /* mu(buffer) */
+	u64 state[8];    /* the cipher state */
+	u64 L[8];
+	u8 *buffer = wctx->buffer;
+
+	for (i = 0; i < 8; i++, buffer += 8) {
+		block[i] =
+		(((u64)buffer[0]        ) << 56) ^
+		(((u64)buffer[1] & 0xffL) << 48) ^
+		(((u64)buffer[2] & 0xffL) << 40) ^
+		(((u64)buffer[3] & 0xffL) << 32) ^
+		(((u64)buffer[4] & 0xffL) << 24) ^
+		(((u64)buffer[5] & 0xffL) << 16) ^
+		(((u64)buffer[6] & 0xffL) <<  8) ^
+		(((u64)buffer[7] & 0xffL)      );
+	}
+
+	state[0] = block[0] ^ (K[0] = wctx->hash[0]);
+	state[1] = block[1] ^ (K[1] = wctx->hash[1]);
+	state[2] = block[2] ^ (K[2] = wctx->hash[2]);
+	state[3] = block[3] ^ (K[3] = wctx->hash[3]);
+	state[4] = block[4] ^ (K[4] = wctx->hash[4]);
+	state[5] = block[5] ^ (K[5] = wctx->hash[5]);
+	state[6] = block[6] ^ (K[6] = wctx->hash[6]);
+	state[7] = block[7] ^ (K[7] = wctx->hash[7]);
+
+	for (r = 1; r <= WHIRLPOOL_ROUNDS; r++) {
+
+		L[0] = C0[(int)(K[0] >> 56)       ] ^
+			   C1[(int)(K[7] >> 48) & 0xff] ^
+			   C2[(int)(K[6] >> 40) & 0xff] ^
+			   C3[(int)(K[5] >> 32) & 0xff] ^
+			   C4[(int)(K[4] >> 24) & 0xff] ^
+			   C5[(int)(K[3] >> 16) & 0xff] ^
+			   C6[(int)(K[2] >>  8) & 0xff] ^
+			   C7[(int)(K[1]      ) & 0xff] ^
+			   rc[r];
+
+		L[1] = C0[(int)(K[1] >> 56)       ] ^
+			   C1[(int)(K[0] >> 48) & 0xff] ^
+			   C2[(int)(K[7] >> 40) & 0xff] ^
+			   C3[(int)(K[6] >> 32) & 0xff] ^
+			   C4[(int)(K[5] >> 24) & 0xff] ^
+			   C5[(int)(K[4] >> 16) & 0xff] ^
+			   C6[(int)(K[3] >>  8) & 0xff] ^
+			   C7[(int)(K[2]      ) & 0xff];
+
+		L[2] = C0[(int)(K[2] >> 56)       ] ^
+			   C1[(int)(K[1] >> 48) & 0xff] ^
+			   C2[(int)(K[0] >> 40) & 0xff] ^
+			   C3[(int)(K[7] >> 32) & 0xff] ^
+			   C4[(int)(K[6] >> 24) & 0xff] ^
+			   C5[(int)(K[5] >> 16) & 0xff] ^
+			   C6[(int)(K[4] >>  8) & 0xff] ^
+			   C7[(int)(K[3]      ) & 0xff];
+
+		L[3] = C0[(int)(K[3] >> 56)       ] ^
+			   C1[(int)(K[2] >> 48) & 0xff] ^
+			   C2[(int)(K[1] >> 40) & 0xff] ^
+			   C3[(int)(K[0] >> 32) & 0xff] ^
+			   C4[(int)(K[7] >> 24) & 0xff] ^
+			   C5[(int)(K[6] >> 16) & 0xff] ^
+			   C6[(int)(K[5] >>  8) & 0xff] ^
+			   C7[(int)(K[4]      ) & 0xff];
+
+		L[4] = C0[(int)(K[4] >> 56)       ] ^
+			   C1[(int)(K[3] >> 48) & 0xff] ^
+			   C2[(int)(K[2] >> 40) & 0xff] ^
+			   C3[(int)(K[1] >> 32) & 0xff] ^
+			   C4[(int)(K[0] >> 24) & 0xff] ^
+			   C5[(int)(K[7] >> 16) & 0xff] ^
+			   C6[(int)(K[6] >>  8) & 0xff] ^
+			   C7[(int)(K[5]      ) & 0xff];
+
+		L[5] = C0[(int)(K[5] >> 56)       ] ^
+			   C1[(int)(K[4] >> 48) & 0xff] ^
+			   C2[(int)(K[3] >> 40) & 0xff] ^
+			   C3[(int)(K[2] >> 32) & 0xff] ^
+			   C4[(int)(K[1] >> 24) & 0xff] ^
+			   C5[(int)(K[0] >> 16) & 0xff] ^
+			   C6[(int)(K[7] >>  8) & 0xff] ^
+			   C7[(int)(K[6]      ) & 0xff];
+
+		L[6] = C0[(int)(K[6] >> 56)       ] ^
+			   C1[(int)(K[5] >> 48) & 0xff] ^
+			   C2[(int)(K[4] >> 40) & 0xff] ^
+			   C3[(int)(K[3] >> 32) & 0xff] ^
+			   C4[(int)(K[2] >> 24) & 0xff] ^
+			   C5[(int)(K[1] >> 16) & 0xff] ^
+			   C6[(int)(K[0] >>  8) & 0xff] ^
+			   C7[(int)(K[7]      ) & 0xff];
+
+		L[7] = C0[(int)(K[7] >> 56)       ] ^
+			   C1[(int)(K[6] >> 48) & 0xff] ^
+			   C2[(int)(K[5] >> 40) & 0xff] ^
+			   C3[(int)(K[4] >> 32) & 0xff] ^
+			   C4[(int)(K[3] >> 24) & 0xff] ^
+			   C5[(int)(K[2] >> 16) & 0xff] ^
+			   C6[(int)(K[1] >>  8) & 0xff] ^
+			   C7[(int)(K[0]      ) & 0xff];
+
+		K[0] = L[0];
+		K[1] = L[1];
+		K[2] = L[2];
+		K[3] = L[3];
+		K[4] = L[4];
+		K[5] = L[5];
+		K[6] = L[6];
+		K[7] = L[7];
+
+		L[0] = C0[(int)(state[0] >> 56)       ] ^
+			   C1[(int)(state[7] >> 48) & 0xff] ^
+			   C2[(int)(state[6] >> 40) & 0xff] ^
+			   C3[(int)(state[5] >> 32) & 0xff] ^
+			   C4[(int)(state[4] >> 24) & 0xff] ^
+			   C5[(int)(state[3] >> 16) & 0xff] ^
+			   C6[(int)(state[2] >>  8) & 0xff] ^
+			   C7[(int)(state[1]      ) & 0xff] ^
+			   K[0];
+
+		L[1] = C0[(int)(state[1] >> 56)       ] ^
+			   C1[(int)(state[0] >> 48) & 0xff] ^
+			   C2[(int)(state[7] >> 40) & 0xff] ^
+			   C3[(int)(state[6] >> 32) & 0xff] ^
+			   C4[(int)(state[5] >> 24) & 0xff] ^
+			   C5[(int)(state[4] >> 16) & 0xff] ^
+			   C6[(int)(state[3] >>  8) & 0xff] ^
+			   C7[(int)(state[2]      ) & 0xff] ^
+			   K[1];
+
+		L[2] = C0[(int)(state[2] >> 56)       ] ^
+			   C1[(int)(state[1] >> 48) & 0xff] ^
+			   C2[(int)(state[0] >> 40) & 0xff] ^
+			   C3[(int)(state[7] >> 32) & 0xff] ^
+			   C4[(int)(state[6] >> 24) & 0xff] ^
+			   C5[(int)(state[5] >> 16) & 0xff] ^
+			   C6[(int)(state[4] >>  8) & 0xff] ^
+			   C7[(int)(state[3]      ) & 0xff] ^
+			   K[2];
+
+		L[3] = C0[(int)(state[3] >> 56)       ] ^
+			   C1[(int)(state[2] >> 48) & 0xff] ^
+			   C2[(int)(state[1] >> 40) & 0xff] ^
+			   C3[(int)(state[0] >> 32) & 0xff] ^
+			   C4[(int)(state[7] >> 24) & 0xff] ^
+			   C5[(int)(state[6] >> 16) & 0xff] ^
+			   C6[(int)(state[5] >>  8) & 0xff] ^
+			   C7[(int)(state[4]      ) & 0xff] ^
+			   K[3];
+
+		L[4] = C0[(int)(state[4] >> 56)       ] ^
+			   C1[(int)(state[3] >> 48) & 0xff] ^
+			   C2[(int)(state[2] >> 40) & 0xff] ^
+			   C3[(int)(state[1] >> 32) & 0xff] ^
+			   C4[(int)(state[0] >> 24) & 0xff] ^
+			   C5[(int)(state[7] >> 16) & 0xff] ^
+			   C6[(int)(state[6] >>  8) & 0xff] ^
+			   C7[(int)(state[5]      ) & 0xff] ^
+			   K[4];
+
+		L[5] = C0[(int)(state[5] >> 56)       ] ^
+			   C1[(int)(state[4] >> 48) & 0xff] ^
+			   C2[(int)(state[3] >> 40) & 0xff] ^
+			   C3[(int)(state[2] >> 32) & 0xff] ^
+			   C4[(int)(state[1] >> 24) & 0xff] ^
+			   C5[(int)(state[0] >> 16) & 0xff] ^
+			   C6[(int)(state[7] >>  8) & 0xff] ^
+			   C7[(int)(state[6]      ) & 0xff] ^
+			   K[5];
+
+		L[6] = C0[(int)(state[6] >> 56)       ] ^
+			   C1[(int)(state[5] >> 48) & 0xff] ^
+			   C2[(int)(state[4] >> 40) & 0xff] ^
+			   C3[(int)(state[3] >> 32) & 0xff] ^
+			   C4[(int)(state[2] >> 24) & 0xff] ^
+			   C5[(int)(state[1] >> 16) & 0xff] ^
+			   C6[(int)(state[0] >>  8) & 0xff] ^
+			   C7[(int)(state[7]      ) & 0xff] ^
+			   K[6];
+
+		L[7] = C0[(int)(state[7] >> 56)       ] ^
+			   C1[(int)(state[6] >> 48) & 0xff] ^
+			   C2[(int)(state[5] >> 40) & 0xff] ^
+			   C3[(int)(state[4] >> 32) & 0xff] ^
+			   C4[(int)(state[3] >> 24) & 0xff] ^
+			   C5[(int)(state[2] >> 16) & 0xff] ^
+			   C6[(int)(state[1] >>  8) & 0xff] ^
+			   C7[(int)(state[0]      ) & 0xff] ^
+			   K[7];
+
+		state[0] = L[0];
+		state[1] = L[1];
+		state[2] = L[2];
+		state[3] = L[3];
+		state[4] = L[4];
+		state[5] = L[5];
+		state[6] = L[6];
+		state[7] = L[7];
+	}
+	/*
+	* apply the Miyaguchi-Preneel compression function:
+	*/
+	wctx->hash[0] ^= state[0] ^ block[0];
+	wctx->hash[1] ^= state[1] ^ block[1];
+	wctx->hash[2] ^= state[2] ^ block[2];
+	wctx->hash[3] ^= state[3] ^ block[3];
+	wctx->hash[4] ^= state[4] ^ block[4];
+	wctx->hash[5] ^= state[5] ^ block[5];
+	wctx->hash[6] ^= state[6] ^ block[6];
+	wctx->hash[7] ^= state[7] ^ block[7];
+
+}
+
+static void whirlpool_init (void *ctx) {
+	int i;
+	struct whirlpool_ctx *wctx = ctx;
+
+	memset(wctx->bitLength, 0, 32);
+	wctx->bufferBits = wctx->bufferPos = 0;
+	wctx->buffer[0] = 0;
+	for (i = 0; i < 8; i++) {
+		wctx->hash[i] = 0L;
+	}
+}
+
+static void whirlpool_update(void *ctx, const u8 *source, unsigned int len)
+{
+
+	struct whirlpool_ctx *wctx = ctx;
+	int sourcePos    = 0;
+	unsigned int bits_len = len * 8; // convert to number of bits
+	int sourceGap    = (8 - ((int)bits_len & 7)) & 7;
+	int bufferRem    = wctx->bufferBits & 7;
+	int i;
+	u32 b, carry;
+	u8 *buffer       = wctx->buffer;
+	u8 *bitLength    = wctx->bitLength;
+	int bufferBits   = wctx->bufferBits;
+	int bufferPos    = wctx->bufferPos;
+
+	u64 value = bits_len;
+	for (i = 31, carry = 0; i >= 0 && (carry != 0 || value != 0ULL); i--) {
+		carry += bitLength[i] + ((u32)value & 0xff);
+		bitLength[i] = (u8)carry;
+		carry >>= 8;
+		value >>= 8;
+	}
+	while (bits_len > 8) {
+		b = ((source[sourcePos] << sourceGap) & 0xff) |
+		((source[sourcePos + 1] & 0xff) >> (8 - sourceGap));
+		buffer[bufferPos++] |= (u8)(b >> bufferRem);
+		bufferBits += 8 - bufferRem;
+		if (bufferBits == WHIRLPOOL_DIGEST_SIZE * 8) {
+			whirlpool_process_buffer(wctx);
+			bufferBits = bufferPos = 0;
+		}
+		buffer[bufferPos] = b << (8 - bufferRem);
+		bufferBits += bufferRem;
+		bits_len -= 8;
+		sourcePos++;
+	}
+	if (bits_len > 0) {
+		b = (source[sourcePos] << sourceGap) & 0xff;
+		buffer[bufferPos] |= b >> bufferRem;
+	} else {
+		b = 0;
+	}
+	if (bufferRem + bits_len < 8) {
+		bufferBits += bits_len;
+	} else {
+		bufferPos++;
+		bufferBits += 8 - bufferRem;
+		bits_len -= 8 - bufferRem;
+		if (bufferBits == WHIRLPOOL_DIGEST_SIZE * 8) {
+			whirlpool_process_buffer(wctx);
+			bufferBits = bufferPos = 0;
+		}
+		buffer[bufferPos] = b << (8 - bufferRem);
+		bufferBits += (int)bits_len;
+	}
+
+	wctx->bufferBits   = bufferBits;
+	wctx->bufferPos    = bufferPos;
+
+}
+
+static void whirlpool_final(void *ctx, u8 *out)
+{
+	struct whirlpool_ctx *wctx = ctx;
+	int i;
+   	u8 *buffer      = wctx->buffer;
+   	u8 *bitLength   = wctx->bitLength;
+   	int bufferBits  = wctx->bufferBits;
+   	int bufferPos   = wctx->bufferPos;
+   	u8 *digest      = out;
+
+   	buffer[bufferPos] |= 0x80U >> (bufferBits & 7);
+   	bufferPos++;
+   	if (bufferPos > WHIRLPOOL_BLOCK_SIZE - WHIRLPOOL_LENGTHBYTES) {
+   		if (bufferPos < WHIRLPOOL_BLOCK_SIZE) {
+	   	memset(&buffer[bufferPos], 0, WHIRLPOOL_BLOCK_SIZE - bufferPos);
+   		}
+   		whirlpool_process_buffer(wctx);
+   		bufferPos = 0;
+   	}
+   	if (bufferPos < WHIRLPOOL_BLOCK_SIZE - WHIRLPOOL_LENGTHBYTES) {
+   		memset(&buffer[bufferPos], 0,
+			  (WHIRLPOOL_BLOCK_SIZE - WHIRLPOOL_LENGTHBYTES) - bufferPos);
+   	}
+   	bufferPos = WHIRLPOOL_BLOCK_SIZE - WHIRLPOOL_LENGTHBYTES;
+   	memcpy(&buffer[WHIRLPOOL_BLOCK_SIZE - WHIRLPOOL_LENGTHBYTES],
+		   bitLength, WHIRLPOOL_LENGTHBYTES);
+   	whirlpool_process_buffer(wctx);
+   	for (i = 0; i < WHIRLPOOL_DIGEST_SIZE/8; i++) {
+		digest[0] = (u8)(wctx->hash[i] >> 56);
+		digest[1] = (u8)(wctx->hash[i] >> 48);
+		digest[2] = (u8)(wctx->hash[i] >> 40);
+		digest[3] = (u8)(wctx->hash[i] >> 32);
+		digest[4] = (u8)(wctx->hash[i] >> 24);
+		digest[5] = (u8)(wctx->hash[i] >> 16);
+		digest[6] = (u8)(wctx->hash[i] >>  8);
+		digest[7] = (u8)(wctx->hash[i]      );
+		digest += 8;
+   	}
+   	wctx->bufferBits   = bufferBits;
+   	wctx->bufferPos    = bufferPos;
+}
+
+static struct crypto_alg alg = {
+	.cra_name	=	"whirlpool",
+	.cra_flags	=	CRYPTO_ALG_TYPE_DIGEST,
+	.cra_blocksize	=	WHIRLPOOL_BLOCK_SIZE,
+	.cra_ctxsize	=	sizeof(struct whirlpool_ctx),
+	.cra_module	=	THIS_MODULE,
+	.cra_list       =       LIST_HEAD_INIT(alg.cra_list),	
+	.cra_u		=	{ .digest = {
+	.dia_digestsize	=	WHIRLPOOL_DIGEST_SIZE,
+	.dia_init   	= 	whirlpool_init,
+	.dia_update 	=	whirlpool_update,
+	.dia_final  	=	whirlpool_final } }
+};
+
+static int __init init(void)
+{
+	return crypto_register_alg(&alg);
+}
+
+static void __exit fini(void)
+{
+	crypto_unregister_alg(&alg);
+}
+
+module_init(init);
+module_exit(fini);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Whirlpool Message Digest Algorithm");
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/atm/eni.c linux-2.4.28-pre3/drivers/atm/eni.c
--- linux-2.4.27/drivers/atm/eni.c	2003-11-28 18:26:19.000000000 +0000
+++ linux-2.4.28-pre3/drivers/atm/eni.c	2004-09-10 19:33:15.000000000 +0000
@@ -1879,7 +1879,7 @@ static void eni_close(struct atm_vcc *vc
 	DPRINTK("eni_close: done waiting\n");
 	/* deallocate memory */
 	kfree(ENI_VCC(vcc));
-	ENI_VCC(vcc) = NULL;
+	vcc->dev_data = NULL;
 	clear_bit(ATM_VF_ADDR,&vcc->flags);
 	/*foo();*/
 }
@@ -1951,7 +1951,7 @@ static int eni_open(struct atm_vcc *vcc,
 
 	DPRINTK(">eni_open\n");
 	EVENT("eni_open\n",0,0);
-	if (!test_bit(ATM_VF_PARTIAL,&vcc->flags)) ENI_VCC(vcc) = NULL;
+	if (!test_bit(ATM_VF_PARTIAL,&vcc->flags)) vcc->dev_data = NULL;
 	eni_dev = ENI_DEV(vcc->dev);
 	error = get_ci(vcc,&vpi,&vci);
 	if (error) return error;
@@ -1966,7 +1966,7 @@ static int eni_open(struct atm_vcc *vcc,
 	if (!test_bit(ATM_VF_PARTIAL,&vcc->flags)) {
 		eni_vcc = kmalloc(sizeof(struct eni_vcc),GFP_KERNEL);
 		if (!eni_vcc) return -ENOMEM;
-		ENI_VCC(vcc) = eni_vcc;
+		vcc->dev_data = eni_vcc;
 		eni_vcc->tx = NULL; /* for eni_close after open_rx */
 		if ((error = open_rx_first(vcc))) {
 			eni_close(vcc);
@@ -2302,7 +2302,7 @@ static int __devinit eni_init_one(struct
 	if (!dev) goto out2;
 	pci_set_drvdata(pci_dev, dev);
 	eni_dev->pci_dev = pci_dev;
-	ENI_DEV(dev) = eni_dev;
+	dev->dev_data = eni_dev;
 	eni_dev->asic = ent->driver_data;
 	error = eni_do_init(dev);
 	if (error) goto out3;
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/atm/fore200e.c linux-2.4.28-pre3/drivers/atm/fore200e.c
--- linux-2.4.27/drivers/atm/fore200e.c	2004-08-07 23:26:04.000000000 +0000
+++ linux-2.4.28-pre3/drivers/atm/fore200e.c	2004-09-10 19:37:16.000000000 +0000
@@ -101,6 +101,7 @@
 
 
 #if 1
+#undef ASSERT
 #define ASSERT(expr)     if (!(expr)) { \
                              printk(FORE200E "assertion failed! %s[%d]: %s\n", \
 			            __FUNCTION__, __LINE__, #expr); \
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/atm/suni.c linux-2.4.28-pre3/drivers/atm/suni.c
--- linux-2.4.27/drivers/atm/suni.c	2003-06-13 14:51:32.000000000 +0000
+++ linux-2.4.28-pre3/drivers/atm/suni.c	2004-09-10 19:36:25.000000000 +0000
@@ -230,7 +230,7 @@ static int suni_start(struct atm_dev *de
 	unsigned long flags;
 	int first;
 
-	if (!(PRIV(dev) = kmalloc(sizeof(struct suni_priv),GFP_KERNEL)))
+	if (!(dev->phy_data = kmalloc(sizeof(struct suni_priv),GFP_KERNEL)))
 		return -ENOMEM;
 
 	PRIV(dev)->dev = dev;
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/block/cciss.c linux-2.4.28-pre3/drivers/block/cciss.c
--- linux-2.4.27/drivers/block/cciss.c	2004-08-07 23:26:04.000000000 +0000
+++ linux-2.4.28-pre3/drivers/block/cciss.c	2004-09-10 19:37:07.000000000 +0000
@@ -80,7 +80,7 @@ const struct pci_device_id cciss_pci_dev
                         0x0E11, 0x4091, 0, 0, 0},
 	{ PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_CISSC,
                         0x0E11, 0x409E, 0, 0, 0},
-	{ PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_CISSC,
+	{ PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISS,
                         0x103C, 0x3211, 0, 0, 0},
 	{0,}
 };
@@ -125,7 +125,7 @@ static struct board_type products[] = {
 /* Originally cciss driver only supports 8 major number */
 #define MAX_CTLR_ORIG  COMPAQ_CISS_MAJOR7 - COMPAQ_CISS_MAJOR + 1
 
-#define CCISS_DMA_MASK 0xFFFFFFFFFFFFFFFF /* 64 bit DMA */
+#define CCISS_DMA_MASK 0xFFFFFFFFFFFFFFFFULL /* 64 bit DMA */
 
 #ifdef CONFIG_CISS_MONITOR_THREAD
 static int cciss_monitor(void *ctlr);
@@ -168,6 +168,35 @@ static int cciss_proc_get_info(char *buf
 static void cciss_procinit(int i) {}
 #endif /* CONFIG_PROC_FS */
 
+/*
+ * Enqueuing and dequeuing functions for cmdlists.
+ */
+static inline void addQ(CommandList_struct **Qptr, CommandList_struct *c)
+{
+        if (*Qptr == NULL) {
+                *Qptr = c;
+                c->next = c->prev = c;
+        } else {
+                c->prev = (*Qptr)->prev;
+                c->next = (*Qptr);
+                (*Qptr)->prev->next = c;
+                (*Qptr)->prev = c;
+        }
+}
+
+static inline CommandList_struct *removeQ(CommandList_struct **Qptr, 
+						CommandList_struct *c)
+{
+        if (c && c->next != c) {
+                if (*Qptr == c) *Qptr = c->next;
+                c->prev->next = c->next;
+                c->next->prev = c->prev;
+        } else {
+                *Qptr = NULL;
+        }
+        return c;
+}
+
 static struct block_device_operations cciss_fops  = {
 	owner:			THIS_MODULE,
 	open:			cciss_open, 
@@ -592,7 +621,7 @@ int cciss_ioctl32_passthru(unsigned int 
 	set_fs(old_fs);
 	if (err)
 		return err;
-	err |= copy_to_user(&arg32->error_info, &arg64.error_info, sizeof(&arg32->error_info));
+	err |= copy_to_user(&arg32->error_info, &arg64.error_info, sizeof(arg32->error_info));
 	if (err) 
 		return -EFAULT; 
 	return err;
@@ -620,7 +649,7 @@ int cciss_ioctl32_big_passthru(unsigned 
 	set_fs(old_fs);
 	if (err)
 		return err;
-	err |= copy_to_user(&arg32->error_info, &arg64.error_info, sizeof(&arg32->error_info));
+	err |= copy_to_user(&arg32->error_info, &arg64.error_info, sizeof(arg32->error_info));
 	if (err) 
 		return -EFAULT; 
 	return err;
@@ -629,6 +658,7 @@ int cciss_ioctl32_big_passthru(unsigned 
 static inline void register_cciss_ioctl32(void) {}
 static inline void unregister_cciss_ioctl32(void) {}
 #endif
+
 /*
  * ioctl 
  */
@@ -942,6 +972,8 @@ static int cciss_ioctl(struct inode *ino
 			{
 				kfree(buff);
 				return -EFAULT;
+			} else {
+				memset(buff, 0, iocommand.buf_size);
 			}
 		}
 		if ((c = cmd_alloc(h , 0)) == NULL) {
@@ -1060,12 +1092,15 @@ static int cciss_ioctl(struct inode *ino
 					goto cleanup1;
 				}
 				if (iocommand.Request.Type.Direction == 
-						XFER_WRITE)
+						XFER_WRITE) {
 				   /* Copy the data into the buffer created */
 				   if (copy_from_user(buff[sg_used], data_ptr, 
 						buff_size[sg_used])) {
 					status = -ENOMEM;
 					goto cleanup1;			
+				   } else {
+					memset(buff[sg_used], 0, buff_size[sg_used]);
+				   }
 				   }
 				size_left_alloc -= buff_size[sg_used];
 				data_ptr += buff_size[sg_used];
@@ -2129,35 +2164,6 @@ static ulong remap_pci_mem(ulong base, u
         return (ulong) (page_remapped ? (page_remapped + page_offs) : 0UL);
 }
 
-/*
- * Enqueuing and dequeuing functions for cmdlists.
- */
-static inline void addQ(CommandList_struct **Qptr, CommandList_struct *c)
-{
-        if (*Qptr == NULL) {
-                *Qptr = c;
-                c->next = c->prev = c;
-        } else {
-                c->prev = (*Qptr)->prev;
-                c->next = (*Qptr);
-                (*Qptr)->prev->next = c;
-                (*Qptr)->prev = c;
-        }
-}
-
-static inline CommandList_struct *removeQ(CommandList_struct **Qptr, 
-						CommandList_struct *c)
-{
-        if (c && c->next != c) {
-                if (*Qptr == c) *Qptr = c->next;
-                c->prev->next = c->next;
-                c->next->prev = c->prev;
-        } else {
-                *Qptr = NULL;
-        }
-        return c;
-}
-
 /* 
  * Takes jobs of the Q and sends them to the hardware, then puts it on 
  * the Q to wait for completion. 
@@ -2671,7 +2677,7 @@ static int find_PCI_BAR_index(struct pci
 static int cciss_pci_init(ctlr_info_t *c, struct pci_dev *pdev)
 {
 	ushort subsystem_vendor_id, subsystem_device_id, command;
-	unchar irq = pdev->irq, ready = 0;
+	int ready = 0;
 	__u32 board_id, scratchpad;
 	__u64 cfg_offset;
 	__u32 cfg_base_addr;
@@ -2727,11 +2733,11 @@ static int cciss_pci_init(ctlr_info_t *c
 
 #ifdef CCISS_DEBUG
 	printk("command = %x\n", command);
-	printk("irq = %x\n", irq);
+	printk("irq = %x\n", pdev->irq);
 	printk("board_id = %x\n", board_id);
 #endif /* CCISS_DEBUG */ 
 
-	c->intr = irq;
+	c->intr = pdev->irq;
 
 	/*
 	 * Memory base addr is first addr , the second points to the config
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/block/cciss.h linux-2.4.28-pre3/drivers/block/cciss.h
--- linux-2.4.27/drivers/block/cciss.h	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.28-pre3/drivers/block/cciss.h	2004-09-10 19:31:54.000000000 +0000
@@ -51,7 +51,7 @@ struct ctlr_info 
 	unsigned long io_mem_addr;
 	unsigned long io_mem_length;
 	CfgTable_struct *cfgtable;
-	int	intr;
+	unsigned int	intr;
 	int	interrupts_enabled;
 	int 	max_commands;
 	int	commands_outstanding;
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/block/cpqarray.c linux-2.4.28-pre3/drivers/block/cpqarray.c
--- linux-2.4.27/drivers/block/cpqarray.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.28-pre3/drivers/block/cpqarray.c	2004-09-10 19:32:46.000000000 +0000
@@ -960,6 +960,20 @@ static inline cmdlist_t *removeQ(cmdlist
 	return c;
 }
 
+static inline void complete_buffers(struct buffer_head *bh, int ok)
+{
+	struct buffer_head *xbh;
+	while(bh) {
+		xbh = bh->b_reqnext;
+		bh->b_reqnext = NULL;
+		
+		blk_finished_io(bh->b_size >> 9);
+		bh->b_end_io(bh, ok);
+
+		bh = xbh;
+	}
+}
+
 /*
  * Get a request and submit it to the controller.
  * This routine needs to grab all the requests it possibly can from the
@@ -1094,19 +1108,6 @@ static void start_io(ctlr_info_t *h)
 	}
 }
 
-static inline void complete_buffers(struct buffer_head *bh, int ok)
-{
-	struct buffer_head *xbh;
-	while(bh) {
-		xbh = bh->b_reqnext;
-		bh->b_reqnext = NULL;
-		
-		blk_finished_io(bh->b_size >> 9);
-		bh->b_end_io(bh, ok);
-
-		bh = xbh;
-	}
-}
 /*
  * Mark all buffers that cmd was responsible for
  */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/block/ll_rw_blk.c linux-2.4.28-pre3/drivers/block/ll_rw_blk.c
--- linux-2.4.27/drivers/block/ll_rw_blk.c	2004-04-14 13:05:29.000000000 +0000
+++ linux-2.4.28-pre3/drivers/block/ll_rw_blk.c	2004-09-10 19:32:38.000000000 +0000
@@ -132,7 +132,7 @@ static inline int get_max_sectors(kdev_t
 	return max_sectors[MAJOR(dev)][MINOR(dev)];
 }
 
-inline request_queue_t *blk_get_queue(kdev_t dev)
+static inline request_queue_t *__blk_get_queue(kdev_t dev)
 {
 	struct blk_dev_struct *bdev = blk_dev + MAJOR(dev);
 
@@ -142,6 +142,11 @@ inline request_queue_t *blk_get_queue(kd
 		return &blk_dev[MAJOR(dev)].request_queue;
 }
 
+request_queue_t *blk_get_queue(kdev_t dev)
+{
+	return __blk_get_queue(dev);
+}
+
 static int __blk_cleanup_queue(struct request_list *list)
 {
 	struct list_head *head = &list->free;
@@ -303,7 +308,7 @@ void blk_queue_bounce_limit(request_queu
 /*
  * can we merge the two segments, or do we need to start a new one?
  */
-inline int blk_seg_merge_ok(struct buffer_head *bh, struct buffer_head *nxt)
+static inline int __blk_seg_merge_ok(struct buffer_head *bh, struct buffer_head *nxt)
 {
 	/*
 	 * if bh and nxt are contigous and don't cross a 4g boundary, it's ok
@@ -314,6 +319,11 @@ inline int blk_seg_merge_ok(struct buffe
 	return 0;
 }
 
+int blk_seg_merge_ok(struct buffer_head *bh, struct buffer_head *nxt)
+{
+	return __blk_seg_merge_ok(bh, nxt);
+}
+
 static inline int ll_new_segment(request_queue_t *q, struct request *req, int max_segments)
 {
 	if (req->nr_segments < max_segments) {
@@ -326,7 +336,7 @@ static inline int ll_new_segment(request
 static int ll_back_merge_fn(request_queue_t *q, struct request *req, 
 			    struct buffer_head *bh, int max_segments)
 {
-	if (blk_seg_merge_ok(req->bhtail, bh))
+	if (__blk_seg_merge_ok(req->bhtail, bh))
 		return 1;
 
 	return ll_new_segment(q, req, max_segments);
@@ -335,7 +345,7 @@ static int ll_back_merge_fn(request_queu
 static int ll_front_merge_fn(request_queue_t *q, struct request *req, 
 			     struct buffer_head *bh, int max_segments)
 {
-	if (blk_seg_merge_ok(bh, req->bh))
+	if (__blk_seg_merge_ok(bh, req->bh))
 		return 1;
 
 	return ll_new_segment(q, req, max_segments);
@@ -346,7 +356,7 @@ static int ll_merge_requests_fn(request_
 {
 	int total_segments = req->nr_segments + next->nr_segments;
 
-	if (blk_seg_merge_ok(req->bhtail, next->bh))
+	if (__blk_seg_merge_ok(req->bhtail, next->bh))
 		total_segments--;
 
 	if (total_segments > max_segments)
@@ -1255,7 +1265,7 @@ void generic_make_request (int rw, struc
 	 * Stacking drivers are expected to know what they are doing.
 	 */
 	do {
-		q = blk_get_queue(bh->b_rdev);
+		q = __blk_get_queue(bh->b_rdev);
 		if (!q) {
 			printk(KERN_ERR
 			       "generic_make_request: Trying to access "
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/char/agp/agp.h linux-2.4.28-pre3/drivers/char/agp/agp.h
--- linux-2.4.27/drivers/char/agp/agp.h	2004-08-07 23:26:04.000000000 +0000
+++ linux-2.4.28-pre3/drivers/char/agp/agp.h	2004-09-10 19:34:22.000000000 +0000
@@ -211,6 +211,12 @@ struct agp_bridge_data {
 #ifndef PCI_DEVICE_ID_INTEL_865_G_1
 #define PCI_DEVICE_ID_INTEL_865_G_1	0x2572
 #endif
+#ifndef PCI_DEVICE_ID_INTEL_915_G_0
+#define PCI_DEVICE_ID_INTEL_915_G_0	0x2580
+#endif
+#ifndef PCI_DEVICE_ID_INTEL_915_G_1
+#define PCI_DEVICE_ID_INTEL_915_G_1	0x2582
+#endif
 #ifndef PCI_DEVICE_ID_INTEL_820_0
 #define PCI_DEVICE_ID_INTEL_820_0       0x2500
 #endif
@@ -441,6 +447,12 @@ struct agp_bridge_data {
 #define I810_DRAM_ROW_0        0x00000001
 #define I810_DRAM_ROW_0_SDRAM  0x00000001
 
+/* intel I915 registers */
+#define I915_GMADDR 0x18
+#define I915_MMADDR 0x10
+#define I915_PTEADDR 0x1C
+#define I915_GMCH_GMS_STOLEN_48M    (0x6 << 4)
+#define I915_GMCH_GMS_STOLEN_64M    (0x7 << 4)
 
 
 /* VIA register */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/char/agp/agpgart_be.c linux-2.4.28-pre3/drivers/char/agp/agpgart_be.c
--- linux-2.4.27/drivers/char/agp/agpgart_be.c	2004-08-07 23:26:04.000000000 +0000
+++ linux-2.4.28-pre3/drivers/char/agp/agpgart_be.c	2004-09-10 19:32:47.000000000 +0000
@@ -794,7 +794,29 @@ static unsigned long agp_generic_alloc_p
 	}
 #endif
 	get_page(page);
-	LockPage(page);
+	set_bit(PG_locked, &page->flags);
+	atomic_inc(&agp_bridge.current_memory_agp);
+	return (unsigned long)page_address(page);
+}
+
+/* Exists to support ARGB cursors */
+static unsigned long i830_alloc_pages(void)
+{
+	struct page * page;
+	
+	page = alloc_pages(GFP_KERNEL, 2);
+	if (page == NULL) {
+		return 0;
+	}
+
+#ifdef CONFIG_X86
+	if (change_page_attr(page, 4, PAGE_KERNEL_NOCACHE) < 0) {
+		__free_page(page); 
+		return 0;
+	}
+#endif
+	get_page(page);
+	set_bit(PG_locked, &page->flags);
 	atomic_inc(&agp_bridge.current_memory_agp);
 	return (unsigned long)page_address(page);
 }
@@ -818,6 +840,25 @@ static void agp_generic_destroy_page(uns
 	atomic_dec(&agp_bridge.current_memory_agp);
 }
 
+static void i830_destroy_pages(unsigned long addr)
+{
+	void *pt = (void *) addr;
+	struct page *page;
+
+	if (pt == NULL) {
+		return;
+	}
+	
+	page = virt_to_page(pt);
+#ifdef CONFIG_X86
+	change_page_attr(page, 4, PAGE_KERNEL); 
+#endif	
+	put_page(page);
+	UnlockPage(page);
+	free_pages((unsigned long) pt, 2);
+	atomic_dec(&agp_bridge.current_memory_agp);
+}
+
 /* End Basic Page Allocation Routines */
 
 void agp_enable(u32 mode)
@@ -1022,33 +1063,49 @@ static agp_memory *intel_i810_alloc_by_t
 		return new;
 	}
 	if(type == AGP_PHYS_MEMORY) {
+		unsigned long physical;
+
 		/* The I810 requires a physical address to program
 		 * it's mouse pointer into hardware.  However the
 		 * Xserver still writes to it through the agp
 		 * aperture
 		 */
-	   	if (pg_count != 1) {
-		   	return NULL;
-		}
-	   	new = agp_create_memory(1);
+		if (pg_count != 1 && pg_count != 4) return(NULL);
 
-		if (new == NULL) {
-			return NULL;
+		new = agp_create_memory(pg_count);
+
+		if (new == NULL) return(NULL);
+
+		MOD_INC_USE_COUNT;
+		if (pg_count == 1)
+			new->memory[0] = agp_bridge.agp_alloc_page();
+		else {
+			/* kludge to get 4 physical pages for ARGB cursor */
+			new->memory[0] = i830_alloc_pages();
+			new->memory[1] = new->memory[0] + PAGE_SIZE;
+			new->memory[2] = new->memory[1] + PAGE_SIZE;
+			new->memory[3] = new->memory[2] + PAGE_SIZE;
 		}
-	   	MOD_INC_USE_COUNT;
-		new->memory[0] = agp_bridge.agp_alloc_page();
 
 		if (new->memory[0] == 0) {
 			/* Free this structure */
 			agp_free_memory(new);
 			return NULL;
 		}
+		physical = new->memory[0];
+
 		new->memory[0] = virt_to_phys((void *) new->memory[0]);
-		new->page_count = 1;
-	   	new->num_scratch_pages = 1;
-	   	new->type = AGP_PHYS_MEMORY;
-	        new->physical = virt_to_phys((void *) new->memory[0]);
-	   	return new;
+		if (pg_count == 4) {
+			/* kludge to enable 4 physical pages for ARGB cursor */
+			new->memory[1] = virt_to_phys((void *) new->memory[1]);
+			new->memory[2] = virt_to_phys((void *) new->memory[2]);
+			new->memory[3] = virt_to_phys((void *) new->memory[3]);
+		}
+		new->page_count = pg_count;
+		new->num_scratch_pages = pg_count;
+		new->type = AGP_PHYS_MEMORY;
+		new->physical = virt_to_phys((void *) physical);
+		return(new);
 	}
    
 	return NULL;
@@ -1058,7 +1115,11 @@ static void intel_i810_free_by_type(agp_
 {
 	agp_free_key(curr->key);
    	if(curr->type == AGP_PHYS_MEMORY) {
-	   	agp_bridge.agp_destroy_page((unsigned long)
+		if (curr->page_count == 4)
+			i830_destroy_pages((unsigned long)
+				 phys_to_virt(curr->memory[0]));
+		else
+	   		agp_bridge.agp_destroy_page((unsigned long)
 				 phys_to_virt(curr->memory[0]));
 		vfree(curr->memory);
 	}
@@ -1108,15 +1169,20 @@ static aper_size_info_fixed intel_i830_s
 {
 	{128, 32768, 5},
 	/* The 64M mode still requires a 128k gatt */
-	{64, 16384, 5}
+	{64, 16384, 5},
+	/* For I915G */
+	{256, 65536, 6}
 };
 
 static struct _intel_i830_private {
 	struct pci_dev *i830_dev;   /* device one */
 	volatile u8 *registers;
+	volatile u32 *gtt;	/* I915G */
 	int gtt_entries;
 } intel_i830_private;
 
+static int intel_i830_fetch_size(void);
+
 static void intel_i830_init_gtt_entries(void)
 {
 	u16 gmch_ctrl;
@@ -1124,26 +1190,47 @@ static void intel_i830_init_gtt_entries(
 	u8 rdct;
 	int local = 0;
 	static const int ddt[4] = { 0, 16, 32, 64 };
+        int size;
+ 
 
 	pci_read_config_word(agp_bridge.dev,I830_GMCH_CTRL,&gmch_ctrl);
 
+	/* We obtain the size of the GTT, which is also stored (for some
+	 * reason) at the top of stolen memory. Then we add 4KB to that
+  	 * for the video BIOS popup, which is also stored in there. */
+	size = intel_i830_fetch_size() + 4;
+
 	if (agp_bridge.dev->device != PCI_DEVICE_ID_INTEL_830_M_0 &&
 	    agp_bridge.dev->device != PCI_DEVICE_ID_INTEL_845_G_0) {
 		switch (gmch_ctrl & I855_GMCH_GMS_MASK) {
 		case I855_GMCH_GMS_STOLEN_1M:
-			gtt_entries = MB(1) - KB(132);
+			gtt_entries = MB(1) - KB(size);
 			break;
 		case I855_GMCH_GMS_STOLEN_4M:
-			gtt_entries = MB(4) - KB(132);
+			gtt_entries = MB(4) - KB(size);
 			break;
 		case I855_GMCH_GMS_STOLEN_8M:
-			gtt_entries = MB(8) - KB(132);
+			gtt_entries = MB(8) - KB(size);
 			break;
 		case I855_GMCH_GMS_STOLEN_16M:
-			gtt_entries = MB(16) - KB(132);
+			gtt_entries = MB(16) - KB(size);
 			break;
 		case I855_GMCH_GMS_STOLEN_32M:
-			gtt_entries = MB(32) - KB(132);
+			gtt_entries = MB(32) - KB(size);
+			break;
+		case I915_GMCH_GMS_STOLEN_48M:
+			/* Check it's really I915 */
+			if (agp_bridge.dev->device == PCI_DEVICE_ID_INTEL_915_G_0)
+				gtt_entries = MB(48) - KB(size);
+			else
+				gtt_entries = 0;
+			break;
+		case I915_GMCH_GMS_STOLEN_64M:
+			/* Check it's really I915 */
+			if (agp_bridge.dev->device == PCI_DEVICE_ID_INTEL_915_G_0)
+				gtt_entries = MB(64) - KB(size);
+			else
+				gtt_entries = 0;
 			break;
 		default:
 			gtt_entries = 0;
@@ -1153,13 +1240,13 @@ static void intel_i830_init_gtt_entries(
 	{
 		switch (gmch_ctrl & I830_GMCH_GMS_MASK) {
 		case I830_GMCH_GMS_STOLEN_512:
-			gtt_entries = KB(512) - KB(132);
+			gtt_entries = KB(512) - KB(size);
 			break;
 		case I830_GMCH_GMS_STOLEN_1024:
-			gtt_entries = MB(1) - KB(132);
+			gtt_entries = MB(1) - KB(size);
 			break;
 		case I830_GMCH_GMS_STOLEN_8192:
-			gtt_entries = MB(8) - KB(132);
+			gtt_entries = MB(8) - KB(size);
 			break;
 		case I830_GMCH_GMS_LOCAL:
 			rdct = INREG8(intel_i830_private.registers,
@@ -1193,14 +1280,24 @@ static int intel_i830_create_gatt_table(
 	int page_order;
 	aper_size_info_fixed *size;
 	int num_entries;
-	u32 temp;
+	u32 temp, temp2;
 
 	size = agp_bridge.current_size;
 	page_order = size->page_order;
 	num_entries = size->num_entries;
 	agp_bridge.gatt_table_real = 0;
 
-	pci_read_config_dword(intel_i830_private.i830_dev,I810_MMADDR,&temp);
+	if (agp_bridge.dev->device == PCI_DEVICE_ID_INTEL_915_G_0) {
+		pci_read_config_dword(intel_i830_private.i830_dev,
+							I915_MMADDR,&temp);
+		pci_read_config_dword(intel_i830_private.i830_dev,
+							I915_PTEADDR,&temp2);
+		intel_i830_private.gtt = (volatile u32 *) ioremap(temp2, 256 * 1024);
+		if (!intel_i830_private.gtt) return (-ENOMEM);
+	} else
+		pci_read_config_dword(intel_i830_private.i830_dev,	
+							I810_MMADDR,&temp);
+
 	temp &= 0xfff80000;
 
 	intel_i830_private.registers = (volatile u8 *) ioremap(temp,128 * 4096);
@@ -1234,6 +1331,20 @@ static int intel_i830_fetch_size(void)
 
 	values = A_SIZE_FIX(agp_bridge.aperture_sizes);
 
+	if (agp_bridge.dev->device == PCI_DEVICE_ID_INTEL_915_G_0) {
+		u32 temp, offset = 0;
+		pci_read_config_dword(intel_i830_private.i830_dev,
+							I915_GMADDR,&temp);
+#define I915_256MB_ADDRESS_MASK (1<<27)
+		if (temp & I915_256MB_ADDRESS_MASK)
+			offset = 0;	/* 128MB aperture */
+		else
+			offset = 2;	/* 256MB aperture */
+		agp_bridge.previous_size = agp_bridge.current_size = (void *)(values + offset);
+		agp_bridge.aperture_size_idx = offset;
+		return(values[offset].size);
+	}
+
 	if (agp_bridge.dev->device != PCI_DEVICE_ID_INTEL_830_M_0 &&
 	    agp_bridge.dev->device != PCI_DEVICE_ID_INTEL_845_G_0) {
 		agp_bridge.previous_size = agp_bridge.current_size = (void *) values;
@@ -1247,7 +1358,7 @@ static int intel_i830_fetch_size(void)
 		agp_bridge.aperture_size_idx = 0;
 		return(values[0].size);
 	} else {
-		agp_bridge.previous_size = agp_bridge.current_size = (void *) values;
+		agp_bridge.previous_size = agp_bridge.current_size = (void *)(values + 1);
 		agp_bridge.aperture_size_idx = 1;
 		return(values[1].size);
 	}
@@ -1264,7 +1375,13 @@ static int intel_i830_configure(void)
 
 	current_size = A_SIZE_FIX(agp_bridge.current_size);
 
-	pci_read_config_dword(intel_i830_private.i830_dev,I810_GMADDR,&temp);
+	if (agp_bridge.dev->device == PCI_DEVICE_ID_INTEL_915_G_0)
+		pci_read_config_dword(intel_i830_private.i830_dev,
+							I915_GMADDR,&temp);
+	else
+		pci_read_config_dword(intel_i830_private.i830_dev,
+							I810_GMADDR,&temp);
+
 	agp_bridge.gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
 
 	pci_read_config_word(agp_bridge.dev,I830_GMCH_CTRL,&gmch_ctrl);
@@ -1274,15 +1391,24 @@ static int intel_i830_configure(void)
 	OUTREG32(intel_i830_private.registers,I810_PGETBL_CTL,agp_bridge.gatt_bus_addr | I810_PGETBL_ENABLED);
 	CACHE_FLUSH();
 
-	if (agp_bridge.needs_scratch_page == TRUE)
-		for (i = intel_i830_private.gtt_entries; i < current_size->num_entries; i++)
-			OUTREG32(intel_i830_private.registers,I810_PTE_BASE + (i * 4),agp_bridge.scratch_page);
+	if (agp_bridge.needs_scratch_page == TRUE) {
+		if (agp_bridge.dev->device == PCI_DEVICE_ID_INTEL_915_G_0) {
+			for (i = intel_i830_private.gtt_entries; i < current_size->num_entries; i++)
+				OUTREG32(intel_i830_private.gtt, i, agp_bridge.scratch_page);
+		} else {
+			for (i = intel_i830_private.gtt_entries; i < current_size->num_entries; i++)
+				OUTREG32(intel_i830_private.registers,I810_PTE_BASE + (i * 4),agp_bridge.scratch_page);
+		}
+	}
 
 	return (0);
 }
 
 static void intel_i830_cleanup(void)
 {
+	if (agp_bridge.dev->device == PCI_DEVICE_ID_INTEL_915_G_0)
+		iounmap((void *)intel_i830_private.gtt);
+
 	iounmap((void *) intel_i830_private.registers);
 }
 
@@ -1315,9 +1441,13 @@ static int intel_i830_insert_entries(agp
 
 	CACHE_FLUSH();
 
-	for (i = 0, j = pg_start; i < mem->page_count; i++, j++)
-		OUTREG32(intel_i830_private.registers,I810_PTE_BASE + (j * 4),
-			 agp_bridge.mask_memory(mem->memory[i], mem->type));
+	if (agp_bridge.dev->device == PCI_DEVICE_ID_INTEL_915_G_0) {
+		for (i = 0, j = pg_start; i < mem->page_count; i++, j++)
+			OUTREG32(intel_i830_private.gtt, j, agp_bridge.mask_memory(mem->memory[i], mem->type));
+	} else {
+		for (i = 0, j = pg_start; i < mem->page_count; i++, j++)
+			OUTREG32(intel_i830_private.registers,I810_PTE_BASE + (j * 4),agp_bridge.mask_memory(mem->memory[i], mem->type));
+	}
 
 	CACHE_FLUSH();
 
@@ -1337,8 +1467,13 @@ static int intel_i830_remove_entries(agp
 		return (-EINVAL);
 	}
 
-	for (i = pg_start; i < (mem->page_count + pg_start); i++)
-		OUTREG32(intel_i830_private.registers,I810_PTE_BASE + (i * 4),agp_bridge.scratch_page);
+	if (agp_bridge.dev->device == PCI_DEVICE_ID_INTEL_915_G_0) {
+		for (i = pg_start; i < (mem->page_count + pg_start); i++)
+			OUTREG32(intel_i830_private.gtt, i, agp_bridge.scratch_page);
+	} else {
+		for (i = pg_start; i < (mem->page_count + pg_start); i++)
+			OUTREG32(intel_i830_private.registers,I810_PTE_BASE + (i * 4),agp_bridge.scratch_page);
+	}
 
 	CACHE_FLUSH();
 
@@ -1363,24 +1498,40 @@ static agp_memory *intel_i830_alloc_by_t
 		 * aperture
 		 */
 
-		if (pg_count != 1) return(NULL);
+		if (pg_count != 1 && pg_count != 4) return(NULL);
 
-		nw = agp_create_memory(1);
+		nw = agp_create_memory(pg_count);
 
 		if (nw == NULL) return(NULL);
 
 		MOD_INC_USE_COUNT;
-		nw->memory[0] = agp_bridge.agp_alloc_page();
-		physical = nw->memory[0];
+		if (pg_count == 1)
+			nw->memory[0] = agp_bridge.agp_alloc_page();
+		else {
+			/* kludge to get 4 physical pages for ARGB cursor */
+			nw->memory[0] = i830_alloc_pages();
+			nw->memory[1] = nw->memory[0] + PAGE_SIZE;
+			nw->memory[2] = nw->memory[1] + PAGE_SIZE;
+			nw->memory[3] = nw->memory[2] + PAGE_SIZE;
+		}
+
 		if (nw->memory[0] == 0) {
 			/* free this structure */
 			agp_free_memory(nw);
 			return(NULL);
 		}
 
+		physical = nw->memory[0];
+
 		nw->memory[0] = virt_to_phys((void *) nw->memory[0]);
-		nw->page_count = 1;
-		nw->num_scratch_pages = 1;
+		if (pg_count == 4) {
+			/* kludge to enable 4 physical pages for ARGB cursor */
+			nw->memory[1] = virt_to_phys((void *) nw->memory[1]);
+			nw->memory[2] = virt_to_phys((void *) nw->memory[2]);
+			nw->memory[3] = virt_to_phys((void *) nw->memory[3]);
+		}
+		nw->page_count = pg_count;
+		nw->num_scratch_pages = pg_count;
 		nw->type = AGP_PHYS_MEMORY;
 		nw->physical = virt_to_phys((void *) physical);
 		return(nw);
@@ -3447,9 +3598,9 @@ static int x86_64_insert_memory(agp_memo
 	for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
 		tmp = agp_bridge.mask_memory(mem->memory[i], mem->type);
 
-		BUG_ON(tmp & 0xffffff0000000ffc);
-		pte = (tmp & 0x000000ff00000000) >> 28;
-		pte |=(tmp & 0x00000000fffff000);
+		BUG_ON(tmp & 0xffffff0000000ffcULL);
+		pte = (tmp & 0x000000ff00000000ULL) >> 28;
+		pte |=(tmp & 0x00000000fffff000ULL);
 		pte |= 1<<1|1<<0;
 
 		agp_bridge.gatt_table[j] = pte;
@@ -6112,6 +6263,13 @@ static struct {
 		"865G",
 		 intel_845_setup },
 
+	{ PCI_DEVICE_ID_INTEL_915_G_0,
+		PCI_VENDOR_ID_INTEL,
+		INTEL_I915_G,
+		"Intel(R)",
+		"915G",
+		 intel_845_setup },
+
 	{ PCI_DEVICE_ID_INTEL_840_0,
 		PCI_VENDOR_ID_INTEL,
 		INTEL_I840,
@@ -6835,6 +6993,34 @@ static int __init agp_init_one(struct pc
 				   "865G Chipset.\n");
 			agp_bridge.type = INTEL_I810;
 			return intel_i830_setup(i810_dev);
+
+		case PCI_DEVICE_ID_INTEL_915_G_0:
+			i810_dev = pci_find_device(PCI_VENDOR_ID_INTEL,
+					PCI_DEVICE_ID_INTEL_915_G_1, NULL);
+			if(i810_dev && PCI_FUNC(i810_dev->devfn) != 0) {
+				i810_dev = pci_find_device(PCI_VENDOR_ID_INTEL,
+					PCI_DEVICE_ID_INTEL_915_G_1, i810_dev);
+			}
+
+			if (i810_dev == NULL) {
+                                /* 
+                                 * We probably have a 915G chipset
+                                 * with an external graphics
+                                 * card. It will be initialized later 
+                                 */
+				printk(KERN_ERR PFX "Detected an "
+				       "Intel(R) 915G, but could not"
+				       " find the"
+				       " secondary device. Assuming a "
+				       "non-integrated video card.\n");
+				agp_bridge.type = INTEL_I915_G;
+				break;
+			}
+			printk(KERN_INFO PFX "Detected an Intel(R) "
+				   "915G Chipset.\n");
+			agp_bridge.type = INTEL_I810;
+			return intel_i830_setup(i810_dev);
+
 		default:
 			break;
 		}
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/char/applicom.c linux-2.4.28-pre3/drivers/char/applicom.c
--- linux-2.4.27/drivers/char/applicom.c	2002-08-03 00:39:43.000000000 +0000
+++ linux-2.4.28-pre3/drivers/char/applicom.c	2004-09-10 19:36:55.000000000 +0000
@@ -222,6 +222,7 @@ int __init applicom_init(void)
 
 		if (!RamIO) {
 			printk(KERN_INFO "ac.o: Failed to ioremap PCI memory space at 0x%lx\n", PCI_BASE_ADDRESS(dev));
+			pci_disable_device(dev);
 			return -EIO;
 		}
 
@@ -233,12 +234,14 @@ int __init applicom_init(void)
 						  (unsigned long)RamIO,0))) {
 			printk(KERN_INFO "ac.o: PCI Applicom device doesn't have correct signature.\n");
 			iounmap(RamIO);
+			pci_disable_device(dev);
 			continue;
 		}
 
 		if (request_irq(dev->irq, &ac_interrupt, SA_SHIRQ, "Applicom PCI", &dummy)) {
 			printk(KERN_INFO "Could not allocate IRQ %d for PCI Applicom device.\n", dev->irq);
 			iounmap(RamIO);
+			pci_disable_device(dev);
 			apbs[boardno - 1].RamIO = 0;
 			continue;
 		}
@@ -265,12 +268,6 @@ int __init applicom_init(void)
 
 	/* Now try the specified ISA cards */
 
-#warning "LEAK"
-	RamIO = ioremap(mem, LEN_RAM_IO * MAX_ISA_BOARD);
-
-	if (!RamIO) 
-		printk(KERN_INFO "ac.o: Failed to ioremap ISA memory space at 0x%lx\n", mem);
-
 	for (i = 0; i < MAX_ISA_BOARD; i++) {
 		RamIO = ioremap(mem + (LEN_RAM_IO * i), LEN_RAM_IO);
 
@@ -293,7 +290,8 @@ int __init applicom_init(void)
 				iounmap((void *) RamIO);
 				apbs[boardno - 1].RamIO = 0;
 			}
-			apbs[boardno - 1].irq = irq;
+			else
+				apbs[boardno - 1].irq = irq;
 		}
 		else
 			apbs[boardno - 1].irq = 0;
@@ -368,7 +366,7 @@ static ssize_t ac_write(struct file *fil
 	if (count != sizeof(struct st_ram_io) + sizeof(struct mailbox)) {
 		static int warncount = 5;
 		if (warncount) {
-			printk(KERN_INFO "Hmmm. write() of Applicom card, length %d != expected %d\n",
+			printk(KERN_INFO "Hmmm. write() of Applicom card, length %zd != expected %zd\n",
 			       count, sizeof(struct st_ram_io) + sizeof(struct mailbox));
 			warncount--;
 		}
@@ -476,18 +474,17 @@ static ssize_t ac_write(struct file *fil
 	return 0;
 }
 
-static int do_ac_read(int IndexCard, char *buf)
+static int do_ac_read(int IndexCard, char *buf,
+		struct st_ram_io *st_loc, struct mailbox *mailbox)
 {
-	struct st_ram_io st_loc;
-	struct mailbox tmpmailbox;	/* bounce buffer - can't copy to user space with cli() */
 	unsigned long from = (unsigned long)apbs[IndexCard].RamIO + RAM_TO_PC;
-	unsigned char *to = (unsigned char *)&tmpmailbox;
+	unsigned char *to = (unsigned char *)&mailbox;
 #ifdef DEBUG
 	int c;
 #endif
 
-	st_loc.tic_owner_to_pc = readb(apbs[IndexCard].RamIO + TIC_OWNER_TO_PC);
-	st_loc.numcard_owner_to_pc = readb(apbs[IndexCard].RamIO + NUMCARD_OWNER_TO_PC);
+	st_loc->tic_owner_to_pc = readb(apbs[IndexCard].RamIO + TIC_OWNER_TO_PC);
+	st_loc->numcard_owner_to_pc = readb(apbs[IndexCard].RamIO + NUMCARD_OWNER_TO_PC);
 
 
 	{
@@ -510,32 +507,24 @@ static int do_ac_read(int IndexCard, cha
 		printk("Read from applicom card #%d. struct st_ram_io follows:", NumCard);
 
 		for (c = 0; c < sizeof(struct st_ram_io);) {
-			printk("\n%5.5X: %2.2X", c, ((unsigned char *) &st_loc)[c]);
+			printk("\n%5.5X: %2.2X", c, ((unsigned char *)st_loc)[c]);
 
 			for (c++; c % 8 && c < sizeof(struct st_ram_io); c++) {
-				printk(" %2.2X", ((unsigned char *) &st_loc)[c]);
+				printk(" %2.2X", ((unsigned char *)st_loc)[c]);
 			}
 		}
 
 		printk("\nstruct mailbox follows:");
 
 		for (c = 0; c < sizeof(struct mailbox);) {
-			printk("\n%5.5X: %2.2X", c, ((unsigned char *) &tmpmailbox)[c]);
+			printk("\n%5.5X: %2.2X", c, ((unsigned char *)mailbox)[c]);
 
 			for (c++; c % 8 && c < sizeof(struct mailbox); c++) {
-				printk(" %2.2X", ((unsigned char *) &tmpmailbox)[c]);
+				printk(" %2.2X", ((unsigned char *)mailbox)[c]);
 			}
 		}
 		printk("\n");
 #endif
-
-#warning "Je suis stupide. DW. - copy*user in cli"
-
-	if (copy_to_user(buf, &st_loc, sizeof(struct st_ram_io)))
-		return -EFAULT;
-	if (copy_to_user(&buf[sizeof(struct st_ram_io)], &tmpmailbox, sizeof(struct mailbox)))
-		return -EFAULT;
-
 	return (sizeof(struct st_ram_io) + sizeof(struct mailbox));
 }
 
@@ -551,7 +540,7 @@ static ssize_t ac_read (struct file *fil
 #endif
 	/* No need to ratelimit this. Only root can trigger it anyway */
 	if (count != sizeof(struct st_ram_io) + sizeof(struct mailbox)) {
-		printk( KERN_WARNING "Hmmm. read() of Applicom card, length %d != expected %d\n",
+		printk( KERN_WARNING "Hmmm. read() of Applicom card, length %zd != expected %zd\n",
 			count,sizeof(struct st_ram_io) + sizeof(struct mailbox));
 		return -EINVAL;
 	}
@@ -570,11 +559,19 @@ static ssize_t ac_read (struct file *fil
 			tmp = readb(apbs[i].RamIO + DATA_TO_PC_READY);
 			
 			if (tmp == 2) {
+				struct st_ram_io st_loc;
+				struct mailbox mailbox;
+
 				/* Got a packet for us */
-				ret = do_ac_read(i, buf);
+				ret = do_ac_read(i, buf, &st_loc, &mailbox);
 				spin_unlock_irqrestore(&apbs[i].mutex, flags);
 				set_current_state(TASK_RUNNING);
 				remove_wait_queue(&FlagSleepRec, &wait);
+
+				if (copy_to_user(buf, &st_loc, sizeof(st_loc)))
+					return -EFAULT;
+				if (copy_to_user(buf + sizeof(st_loc), &mailbox, sizeof(mailbox)))
+					return -EFAULT;
 				return tmp;
 			}
 			
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/char/drm/drm_dma.h linux-2.4.28-pre3/drivers/char/drm/drm_dma.h
--- linux-2.4.27/drivers/char/drm/drm_dma.h	2003-11-28 18:26:20.000000000 +0000
+++ linux-2.4.28-pre3/drivers/char/drm/drm_dma.h	2004-09-10 19:35:35.000000000 +0000
@@ -648,7 +648,7 @@ int DRM(wait_vblank)(struct inode *inode
 		 * for the same vblank sequence number; nothing to be done in
 		 * that case
 		 */
-		list_for_each( ( (struct list_head *) vbl_sig ), &dev->vbl_sigs.head ) {
+		list_for_each_entry( vbl_sig, &dev->vbl_sigs.head, head ) {
 			if (vbl_sig->sequence == vblwait.request.sequence
 			    && vbl_sig->info.si_signo == vblwait.request.signal
 			    && vbl_sig->task == current)
@@ -699,19 +699,20 @@ done:
 
 void DRM(vbl_send_signals)( drm_device_t *dev )
 {
-	struct list_head *tmp;
+	struct list_head *list, *tmp;
 	drm_vbl_sig_t *vbl_sig;
 	unsigned int vbl_seq = atomic_read( &dev->vbl_received );
 	unsigned long flags;
 
 	spin_lock_irqsave( &dev->vbl_lock, flags );
 
-	list_for_each_safe( ( (struct list_head *) vbl_sig ), tmp, &dev->vbl_sigs.head ) {
+	list_for_each_safe( list, tmp, &dev->vbl_sigs.head ) {
+		vbl_sig = list_entry( list, drm_vbl_sig_t, head );
 		if ( ( vbl_seq - vbl_sig->sequence ) <= (1<<23) ) {
 			vbl_sig->info.si_code = vbl_seq;
 			send_sig_info( vbl_sig->info.si_signo, &vbl_sig->info, vbl_sig->task );
 
-			list_del( (struct list_head *) vbl_sig );
+			list_del( list );
 
 
 			kfree( vbl_sig );
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/char/drm/radeon_state.c linux-2.4.28-pre3/drivers/char/drm/radeon_state.c
--- linux-2.4.27/drivers/char/drm/radeon_state.c	2003-11-28 18:26:20.000000000 +0000
+++ linux-2.4.28-pre3/drivers/char/drm/radeon_state.c	2004-09-10 19:36:31.000000000 +0000
@@ -1223,7 +1223,7 @@ static int radeon_cp_dispatch_texture( d
 		/* Update the input parameters for next time */
 		image->y += height;
 		image->height -= height;
-		(const u8 *)image->data += size;
+		image->data = (const u8 *)image->data + size;
 	} while (image->height > 0);
 
 	/* Flush the pixel cache after the blit completes.  This ensures
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/char/ftape/lowlevel/ftape-bsm.c linux-2.4.28-pre3/drivers/char/ftape/lowlevel/ftape-bsm.c
--- linux-2.4.27/drivers/char/ftape/lowlevel/ftape-bsm.c	2000-10-16 19:58:51.000000000 +0000
+++ linux-2.4.28-pre3/drivers/char/ftape/lowlevel/ftape-bsm.c	2004-09-10 19:33:21.000000000 +0000
@@ -203,6 +203,7 @@ static void print_bad_sector_map(void)
 	    ft_format_code == fmt_1100ft) {
 		SectorCount *ptr = (SectorCount *)bad_sector_map;
 		unsigned int sector;
+		__u16 *ptr16;
 
 		while((sector = get_sector(ptr++)) != 0) {
 			if ((ft_format_code == fmt_big || 
@@ -218,9 +219,10 @@ static void print_bad_sector_map(void)
 		}
 		/*  Display old ftape's end-of-file marks
 		 */
-		while ((sector = get_unaligned(((__u16*)ptr)++)) != 0) {
+		ptr16 = (__u16*)ptr;
+		while ((sector = get_unaligned(ptr16++)) != 0) {
 			TRACE(ft_t_noise, "Old ftape eof mark: %4d/%2d",
-			      sector, get_unaligned(((__u16*)ptr)++));
+			      sector, get_unaligned(ptr16++));
 		}
 	} else { /* fixed size format */
 		for (i = ft_first_data_segment;
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/char/ftape/lowlevel/ftape-bsm.h linux-2.4.28-pre3/drivers/char/ftape/lowlevel/ftape-bsm.h
--- linux-2.4.27/drivers/char/ftape/lowlevel/ftape-bsm.h	1997-11-25 22:45:27.000000000 +0000
+++ linux-2.4.28-pre3/drivers/char/ftape/lowlevel/ftape-bsm.h	2004-09-10 19:31:49.000000000 +0000
@@ -47,7 +47,7 @@ typedef __u32 SectorMap;
  */
 typedef struct NewSectorMap {          
 	__u8 bytes[3];
-} SectorCount __attribute__((packed));
+} __attribute__((packed)) SectorCount;
 
 
 /*
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/char/ftape/zftape/zftape-eof.c linux-2.4.28-pre3/drivers/char/ftape/zftape/zftape-eof.c
--- linux-2.4.27/drivers/char/ftape/zftape/zftape-eof.c	1999-11-23 18:29:15.000000000 +0000
+++ linux-2.4.28-pre3/drivers/char/ftape/zftape/zftape-eof.c	2004-09-10 19:37:30.000000000 +0000
@@ -123,7 +123,7 @@ static __u8 * find_end_of_eof_list(__u8 
 	while (ptr + 3 < limit) {
 
 		if (get_unaligned((__u32*)ptr)) {
-			++(__u32*)ptr;
+			ptr += sizeof(__u32);
 		} else {
 			return ptr;
 		}
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/char/ib700wdt.c linux-2.4.28-pre3/drivers/char/ib700wdt.c
--- linux-2.4.27/drivers/char/ib700wdt.c	2002-11-28 23:53:12.000000000 +0000
+++ linux-2.4.28-pre3/drivers/char/ib700wdt.c	2004-09-10 19:36:48.000000000 +0000
@@ -133,7 +133,7 @@ static void
 ibwdt_ping(void)
 {
 	/* Write a watchdog value */
-	outb_p(wd_times[wd_margin], WDT_START);
+	outb_p(wd_margin, WDT_START);
 }
 
 static ssize_t
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/char/ip2main.c linux-2.4.28-pre3/drivers/char/ip2main.c
--- linux-2.4.27/drivers/char/ip2main.c	2003-11-28 18:26:20.000000000 +0000
+++ linux-2.4.28-pre3/drivers/char/ip2main.c	2004-09-10 19:37:27.000000000 +0000
@@ -282,8 +282,8 @@ static void ip2_interrupt_bh(i2eBordStrP
 static void ip2_interrupt(int irq, void *dev_id, struct pt_regs * regs);
 static void ip2_poll(unsigned long arg);
 static inline void service_all_boards(void);
-static inline void do_input(i2ChanStrPtr pCh);
-static inline void do_status(i2ChanStrPtr pCh);
+static void do_input(i2ChanStrPtr pCh);
+static void do_status(i2ChanStrPtr pCh);
 
 static void ip2_wait_until_sent(PTTY,int);
 
@@ -1433,7 +1433,7 @@ ip2_poll(unsigned long arg)
 	ip2trace (ITRC_NO_PORT, ITRC_INTR, ITRC_RETURN, 0 );
 }
 
-static inline void 
+static void 
 do_input( i2ChanStrPtr pCh )
 {
 	unsigned long flags;
@@ -1468,7 +1468,7 @@ isig(int sig, struct tty_struct *tty, in
 	}
 }
 
-static inline void
+static void
 do_status( i2ChanStrPtr pCh )
 {
 	int status;
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/char/istallion.c linux-2.4.28-pre3/drivers/char/istallion.c
--- linux-2.4.27/drivers/char/istallion.c	2004-08-07 23:26:04.000000000 +0000
+++ linux-2.4.28-pre3/drivers/char/istallion.c	2004-09-10 19:35:31.000000000 +0000
@@ -4546,6 +4546,26 @@ static inline int stli_eisamemprobe(stli
 /*****************************************************************************/
 
 /*
+ *	Find the next available board number that is free.
+ */
+
+static inline int stli_getbrdnr()
+{
+	int	i;
+
+	for (i = 0; (i < STL_MAXBRDS); i++) {
+		if (stli_brds[i] == (stlibrd_t *) NULL) {
+			if (i >= stli_nrbrds)
+				stli_nrbrds = i + 1;
+			return(i);
+		}
+	}
+	return(-1);
+}
+
+/*****************************************************************************/
+
+/*
  *	Probe around and try to find any EISA boards in system. The biggest
  *	problem here is finding out what memory address is associated with
  *	an EISA board after it is found. The registers of the ECPE and
@@ -4625,26 +4645,6 @@ static inline int stli_findeisabrds()
 
 /*****************************************************************************/
 
-/*
- *	Find the next available board number that is free.
- */
-
-static inline int stli_getbrdnr()
-{
-	int	i;
-
-	for (i = 0; (i < STL_MAXBRDS); i++) {
-		if (stli_brds[i] == (stlibrd_t *) NULL) {
-			if (i >= stli_nrbrds)
-				stli_nrbrds = i + 1;
-			return(i);
-		}
-	}
-	return(-1);
-}
-
-/*****************************************************************************/
-
 #ifdef	CONFIG_PCI
 
 /*
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/char/mxser.c linux-2.4.28-pre3/drivers/char/mxser.c
--- linux-2.4.27/drivers/char/mxser.c	2002-11-28 23:53:12.000000000 +0000
+++ linux-2.4.28-pre3/drivers/char/mxser.c	2004-09-10 19:35:52.000000000 +0000
@@ -1385,66 +1385,6 @@ void mxser_hangup(struct tty_struct *tty
 	wake_up_interruptible(&info->open_wait);
 }
 
-/*
- * This is the serial driver's generic interrupt routine
- */
-static void mxser_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-{
-	int status, i;
-	struct mxser_struct *info;
-	struct mxser_struct *port;
-	int max, irqbits, bits, msr;
-	int pass_counter = 0;
-
-	port = 0;
-	for (i = 0; i < MXSER_BOARDS; i++) {
-		if (dev_id == &(mxvar_table[i * MXSER_PORTS_PER_BOARD])) {
-			port = dev_id;
-			break;
-		}
-	}
-
-	if (i == MXSER_BOARDS)
-		return;
-	if (port == 0)
-		return;
-	max = mxser_numports[mxsercfg[i].board_type];
-
-	while (1) {
-		irqbits = inb(port->vector) & port->vectormask;
-		if (irqbits == port->vectormask)
-			break;
-		for (i = 0, bits = 1; i < max; i++, irqbits |= bits, bits <<= 1) {
-			if (irqbits == port->vectormask)
-				break;
-			if (bits & irqbits)
-				continue;
-			info = port + i;
-			if (!info->tty ||
-			  (inb(info->base + UART_IIR) & UART_IIR_NO_INT))
-				continue;
-			status = inb(info->base + UART_LSR) & info->read_status_mask;
-			if (status & UART_LSR_DR)
-				mxser_receive_chars(info, &status);
-			msr = inb(info->base + UART_MSR);
-			if (msr & UART_MSR_ANY_DELTA)
-				mxser_check_modem_status(info, msr);
-			if (status & UART_LSR_THRE) {
-/* 8-2-99 by William
-   if ( info->x_char || (info->xmit_cnt > 0) )
- */
-				mxser_transmit_chars(info);
-			}
-		}
-		if (pass_counter++ > MXSER_ISR_PASS_LIMIT) {
-#if 0
-			printk("MOXA Smartio/Indusrtio family driver interrupt loop break\n");
-#endif
-			break;	/* Prevent infinite loops */
-		}
-	}
-}
-
 static inline void mxser_receive_chars(struct mxser_struct *info,
 					 int *status)
 {
@@ -1487,44 +1427,6 @@ static inline void mxser_receive_chars(s
 
 }
 
-static inline void mxser_transmit_chars(struct mxser_struct *info)
-{
-	int count, cnt;
-
-	if (info->x_char) {
-		outb(info->x_char, info->base + UART_TX);
-		info->x_char = 0;
-		mxvar_log.txcnt[info->port]++;
-		return;
-	}
-	if ((info->xmit_cnt <= 0) || info->tty->stopped ||
-	    info->tty->hw_stopped) {
-		info->IER &= ~UART_IER_THRI;
-		outb(info->IER, info->base + UART_IER);
-		return;
-	}
-	cnt = info->xmit_cnt;
-	count = info->xmit_fifo_size;
-	do {
-		outb(info->xmit_buf[info->xmit_tail++], info->base + UART_TX);
-		info->xmit_tail = info->xmit_tail & (SERIAL_XMIT_SIZE - 1);
-		if (--info->xmit_cnt <= 0)
-			break;
-	} while (--count > 0);
-	mxvar_log.txcnt[info->port] += (cnt - info->xmit_cnt);
-
-	if (info->xmit_cnt < WAKEUP_CHARS) {
-		set_bit(MXSER_EVENT_TXLOW, &info->event);
-		MOD_INC_USE_COUNT;
-		if (schedule_task(&info->tqueue) == 0)
-		    MOD_DEC_USE_COUNT;
-	}
-	if (info->xmit_cnt <= 0) {
-		info->IER &= ~UART_IER_THRI;
-		outb(info->IER, info->base + UART_IER);
-	}
-}
-
 static inline void mxser_check_modem_status(struct mxser_struct *info,
 					      int status)
 {
@@ -1572,6 +1474,104 @@ static inline void mxser_check_modem_sta
 	}
 }
 
+static inline void mxser_transmit_chars(struct mxser_struct *info)
+{
+	int count, cnt;
+
+	if (info->x_char) {
+		outb(info->x_char, info->base + UART_TX);
+		info->x_char = 0;
+		mxvar_log.txcnt[info->port]++;
+		return;
+	}
+	if ((info->xmit_cnt <= 0) || info->tty->stopped ||
+	    info->tty->hw_stopped) {
+		info->IER &= ~UART_IER_THRI;
+		outb(info->IER, info->base + UART_IER);
+		return;
+	}
+	cnt = info->xmit_cnt;
+	count = info->xmit_fifo_size;
+	do {
+		outb(info->xmit_buf[info->xmit_tail++], info->base + UART_TX);
+		info->xmit_tail = info->xmit_tail & (SERIAL_XMIT_SIZE - 1);
+		if (--info->xmit_cnt <= 0)
+			break;
+	} while (--count > 0);
+	mxvar_log.txcnt[info->port] += (cnt - info->xmit_cnt);
+
+	if (info->xmit_cnt < WAKEUP_CHARS) {
+		set_bit(MXSER_EVENT_TXLOW, &info->event);
+		MOD_INC_USE_COUNT;
+		if (schedule_task(&info->tqueue) == 0)
+		    MOD_DEC_USE_COUNT;
+	}
+	if (info->xmit_cnt <= 0) {
+		info->IER &= ~UART_IER_THRI;
+		outb(info->IER, info->base + UART_IER);
+	}
+}
+
+/*
+ * This is the serial driver's generic interrupt routine
+ */
+static void mxser_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+	int status, i;
+	struct mxser_struct *info;
+	struct mxser_struct *port;
+	int max, irqbits, bits, msr;
+	int pass_counter = 0;
+
+	port = 0;
+	for (i = 0; i < MXSER_BOARDS; i++) {
+		if (dev_id == &(mxvar_table[i * MXSER_PORTS_PER_BOARD])) {
+			port = dev_id;
+			break;
+		}
+	}
+
+	if (i == MXSER_BOARDS)
+		return;
+	if (port == 0)
+		return;
+	max = mxser_numports[mxsercfg[i].board_type];
+
+	while (1) {
+		irqbits = inb(port->vector) & port->vectormask;
+		if (irqbits == port->vectormask)
+			break;
+		for (i = 0, bits = 1; i < max; i++, irqbits |= bits, bits <<= 1) {
+			if (irqbits == port->vectormask)
+				break;
+			if (bits & irqbits)
+				continue;
+			info = port + i;
+			if (!info->tty ||
+			  (inb(info->base + UART_IIR) & UART_IIR_NO_INT))
+				continue;
+			status = inb(info->base + UART_LSR) & info->read_status_mask;
+			if (status & UART_LSR_DR)
+				mxser_receive_chars(info, &status);
+			msr = inb(info->base + UART_MSR);
+			if (msr & UART_MSR_ANY_DELTA)
+				mxser_check_modem_status(info, msr);
+			if (status & UART_LSR_THRE) {
+/* 8-2-99 by William
+   if ( info->x_char || (info->xmit_cnt > 0) )
+ */
+				mxser_transmit_chars(info);
+			}
+		}
+		if (pass_counter++ > MXSER_ISR_PASS_LIMIT) {
+#if 0
+			printk("MOXA Smartio/Indusrtio family driver interrupt loop break\n");
+#endif
+			break;	/* Prevent infinite loops */
+		}
+	}
+}
+
 static int mxser_block_til_ready(struct tty_struct *tty, struct file *filp,
 				 struct mxser_struct *info)
 {
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/char/nwflash.c linux-2.4.28-pre3/drivers/char/nwflash.c
--- linux-2.4.27/drivers/char/nwflash.c	2004-08-07 23:26:04.000000000 +0000
+++ linux-2.4.28-pre3/drivers/char/nwflash.c	2004-09-10 19:37:23.000000000 +0000
@@ -159,7 +159,8 @@ static ssize_t flash_read(struct file *f
 		if (ret == 0) {
 			ret = count;
 			*ppos = p + count;
-		}
+		} else
+			ret = -EFAULT;
 		up(&nwflash_sem);
 	}
 	return ret;
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/char/random.c linux-2.4.28-pre3/drivers/char/random.c
--- linux-2.4.27/drivers/char/random.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.28-pre3/drivers/char/random.c	2004-09-10 19:32:28.000000000 +0000
@@ -750,6 +750,11 @@ static void add_timer_randomness(struct 
 	__u32 high;
 	rdtsc(time, high);
 	num ^= high;
+#elif defined (__sparc_v9__)
+	unsigned long tick = tick_ops->get_tick();
+
+	time = (unsigned int) tick;
+	num ^= (tick >> 32UL);
 #else
 	time = jiffies;
 #endif
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/char/synclinkmp.c linux-2.4.28-pre3/drivers/char/synclinkmp.c
--- linux-2.4.27/drivers/char/synclinkmp.c	2003-11-28 18:26:20.000000000 +0000
+++ linux-2.4.28-pre3/drivers/char/synclinkmp.c	2004-09-10 19:34:41.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * $Id: synclinkmp.c,v 3.22 2003/09/05 14:04:26 paulkf Exp $
+ * $Id: synclinkmp.c,v 3.23 2004/08/24 19:49:48 paulkf Exp $
  *
  * Device driver for Microgate SyncLink Multiport
  * high speed multiprotocol serial adapter.
@@ -504,7 +504,7 @@ MODULE_PARM(maxframe,"1-" __MODULE_STRIN
 MODULE_PARM(dosyncppp,"1-" __MODULE_STRING(MAX_DEVICES) "i");
 
 static char *driver_name = "SyncLink MultiPort driver";
-static char *driver_version = "$Revision: 3.22 $";
+static char *driver_version = "$Revision: 3.23 $";
 
 static int __devinit synclinkmp_init_one(struct pci_dev *dev,const struct pci_device_id *ent);
 static void __devexit synclinkmp_remove_one(struct pci_dev *dev);
@@ -681,7 +681,7 @@ static unsigned char tx_active_fifo_leve
 static unsigned char tx_negate_fifo_level = 32;	// tx request FIFO negation level in bytes
 
 static u32 misc_ctrl_value = 0x007e4040;
-static u32 lcr1_brdr_value = 0x0080002d;
+static u32 lcr1_brdr_value = 0x00800029;
 
 static u32 read_ahead_count = 8;
 
@@ -2036,16 +2036,15 @@ void isr_rxint(SLMP_INFO * info)
 {
  	struct tty_struct *tty = info->tty;
  	struct	mgsl_icount *icount = &info->icount;
-	unsigned char status = read_reg(info, SR1);
-	unsigned char status2 = read_reg(info, SR2);
+	unsigned char status = read_reg(info, SR1) & info->ie1_value & (FLGD + IDLD + CDCD + BRKD);
+	unsigned char status2 = read_reg(info, SR2) & info->ie2_value & OVRN;
 
 	/* clear status bits */
-	if ( status & (FLGD + IDLD + CDCD + BRKD) )
-		write_reg(info, SR1, 
-				(unsigned char)(status & (FLGD + IDLD + CDCD + BRKD)));
+	if (status)
+		write_reg(info, SR1, status);
 
-	if ( status2 & OVRN )
-		write_reg(info, SR2, (unsigned char)(status2 & OVRN));
+	if (status2)
+		write_reg(info, SR2, status2);
 	
 	if ( debug_level >= DEBUG_LEVEL_ISR )
 		printk("%s(%d):%s isr_rxint status=%02X %02x\n",
@@ -2182,15 +2181,22 @@ void isr_txeom(SLMP_INFO * info, unsigne
 		printk("%s(%d):%s isr_txeom status=%02x\n",
 			__FILE__,__LINE__,info->device_name,status);
 
-	/* disable and clear MSCI interrupts */
-	info->ie1_value &= ~(IDLE + UDRN);
-	write_reg(info, IE1, info->ie1_value);
-	write_reg(info, SR1, (unsigned char)(UDRN + IDLE));
-
 	write_reg(info, TXDMA + DIR, 0x00); /* disable Tx DMA IRQs */
 	write_reg(info, TXDMA + DSR, 0xc0); /* clear IRQs and disable DMA */
 	write_reg(info, TXDMA + DCMD, SWABORT);	/* reset/init DMA channel */
 
+	if (status & UDRN) {
+		write_reg(info, CMD, TXRESET);
+		write_reg(info, CMD, TXENABLE);
+	} else
+		write_reg(info, CMD, TXBUFCLR);
+
+	/* disable and clear tx interrupts */
+	info->ie0_value &= ~TXRDYE;
+	info->ie1_value &= ~(IDLE + UDRN);
+	write_reg16(info, IE0, (unsigned short)((info->ie1_value << 8) + info->ie0_value));
+	write_reg(info, SR1, (unsigned char)(UDRN + IDLE));
+
 	if ( info->tx_active ) {
 		if (info->params.mode != MGSL_MODE_ASYNC) {
 			if (status & UDRN)
@@ -2231,10 +2237,10 @@ void isr_txeom(SLMP_INFO * info, unsigne
  */
 void isr_txint(SLMP_INFO * info)
 {
-	unsigned char status = read_reg(info, SR1);
+	unsigned char status = read_reg(info, SR1) & info->ie1_value & (UDRN + IDLE + CCTS);
 
 	/* clear status bits */
-	write_reg(info, SR1, (unsigned char)(status & (UDRN + IDLE + CCTS)));
+	write_reg(info, SR1, status);
 
 	if ( debug_level >= DEBUG_LEVEL_ISR )
 		printk("%s(%d):%s isr_txint status=%02x\n",
@@ -2263,6 +2269,14 @@ void isr_txrdy(SLMP_INFO * info)
 		printk("%s(%d):%s isr_txrdy() tx_count=%d\n",
 			__FILE__,__LINE__,info->device_name,info->tx_count);
 
+	if (info->params.mode != MGSL_MODE_ASYNC) {
+		/* disable TXRDY IRQ, enable IDLE IRQ */
+		info->ie0_value &= ~TXRDYE;
+		info->ie1_value |= IDLE;
+		write_reg16(info, IE0, (unsigned short)((info->ie1_value << 8) + info->ie0_value));
+		return;
+	}
+
 	if (info->tty && (info->tty->stopped || info->tty->hw_stopped)) {
 		tx_stop(info);
 		return;
@@ -2317,13 +2331,6 @@ void isr_rxdmaerror(SLMP_INFO * info)
 
 void isr_txdmaok(SLMP_INFO * info)
 {
-	/* BIT7 = EOT (end of transfer, used for async mode)
-	 * BIT6 = EOM (end of message/frame, used for sync mode)
-	 *
-	 * We don't look at DMA status because only EOT is enabled
-	 * and we always clear and disable all tx DMA IRQs.
-	 */
-//	unsigned char dma_status = read_reg(info,TXDMA + DSR) & 0xc0;
 	unsigned char status_reg1 = read_reg(info, SR1);
 
 	write_reg(info, TXDMA + DIR, 0x00);	/* disable Tx DMA IRQs */
@@ -2334,19 +2341,10 @@ void isr_txdmaok(SLMP_INFO * info)
 		printk("%s(%d):%s isr_txdmaok(), status=%02x\n",
 			__FILE__,__LINE__,info->device_name,status_reg1);
 
-	/* If transmitter already idle, do end of frame processing,
-	 * otherwise enable interrupt for tx IDLE.
-	 */
-	if (status_reg1 & IDLE)
-		isr_txeom(info, IDLE);
-	else {
-		/* disable and clear underrun IRQ, enable IDLE interrupt */
-		info->ie1_value |= IDLE;
-		info->ie1_value &= ~UDRN;
-		write_reg(info, IE1, info->ie1_value);
-
-		write_reg(info, SR1, UDRN);
-	}
+	/* program TXRDY as FIFO empty flag, enable TXRDY IRQ */
+	write_reg16(info, TRC0, 0);
+	info->ie0_value |= TXRDYE;
+	write_reg(info, IE0, info->ie0_value);
 }
 
 void isr_txdmaerror(SLMP_INFO * info)
@@ -3037,7 +3035,7 @@ static int wait_mgsl_event(SLMP_INFO * i
 		unsigned char oldval = info->ie1_value;
 		unsigned char newval = oldval +
 			 (mask & MgslEvent_ExitHuntMode ? FLGD:0) +
-			 (mask & MgslEvent_IdleReceived ? IDLE:0);
+			 (mask & MgslEvent_IdleReceived ? IDLD:0);
 		if ( oldval != newval ) {
 			info->ie1_value = newval;
 			write_reg(info, IE1, info->ie1_value);
@@ -3104,7 +3102,7 @@ static int wait_mgsl_event(SLMP_INFO * i
 		spin_lock_irqsave(&info->lock,flags);
 		if (!waitqueue_active(&info->event_wait_q)) {
 			/* disable enable exit hunt mode/idle rcvd IRQs */
-			info->ie1_value &= ~(FLGD|IDLE);
+			info->ie1_value &= ~(FLGD|IDLD);
 			write_reg(info, IE1, info->ie1_value);
 		}
 		spin_unlock_irqrestore(&info->lock,flags);
@@ -3554,9 +3552,10 @@ void free_tmp_rx_buf(SLMP_INFO *info)
 
 int claim_resources(SLMP_INFO *info)
 {
-	if (request_mem_region(info->phys_memory_base,0x40000,"synclinkmp") == NULL) {
+	if (request_mem_region(info->phys_memory_base,SCA_MEM_SIZE,"synclinkmp") == NULL) {
 		printk( "%s(%d):%s mem addr conflict, Addr=%08X\n",
 			__FILE__,__LINE__,info->device_name, info->phys_memory_base);
+		info->init_error = DiagStatus_AddressConflict;
 		goto errout;
 	}
 	else
@@ -3565,22 +3564,25 @@ int claim_resources(SLMP_INFO *info)
 	if (request_mem_region(info->phys_lcr_base + info->lcr_offset,128,"synclinkmp") == NULL) {
 		printk( "%s(%d):%s lcr mem addr conflict, Addr=%08X\n",
 			__FILE__,__LINE__,info->device_name, info->phys_lcr_base);
+		info->init_error = DiagStatus_AddressConflict;
 		goto errout;
 	}
 	else
 		info->lcr_mem_requested = 1;
 
-	if (request_mem_region(info->phys_sca_base + info->sca_offset,512,"synclinkmp") == NULL) {
+	if (request_mem_region(info->phys_sca_base + info->sca_offset,SCA_BASE_SIZE,"synclinkmp") == NULL) {
 		printk( "%s(%d):%s sca mem addr conflict, Addr=%08X\n",
 			__FILE__,__LINE__,info->device_name, info->phys_sca_base);
+		info->init_error = DiagStatus_AddressConflict;
 		goto errout;
 	}
 	else
 		info->sca_base_requested = 1;
 
-	if (request_mem_region(info->phys_statctrl_base + info->statctrl_offset,16,"synclinkmp") == NULL) {
+	if (request_mem_region(info->phys_statctrl_base + info->statctrl_offset,SCA_REG_SIZE,"synclinkmp") == NULL) {
 		printk( "%s(%d):%s stat/ctrl mem addr conflict, Addr=%08X\n",
 			__FILE__,__LINE__,info->device_name, info->phys_statctrl_base);
+		info->init_error = DiagStatus_AddressConflict;
 		goto errout;
 	}
 	else
@@ -3590,33 +3592,41 @@ int claim_resources(SLMP_INFO *info)
 	if (!info->memory_base) {
 		printk( "%s(%d):%s Cant map shared memory, MemAddr=%08X\n",
 			__FILE__,__LINE__,info->device_name, info->phys_memory_base );
+		info->init_error = DiagStatus_CantAssignPciResources;
 		goto errout;
 	}
 
-	if ( !memory_test(info) ) {
-		printk( "%s(%d):Shared Memory Test failed for device %s MemAddr=%08X\n",
-			__FILE__,__LINE__,info->device_name, info->phys_memory_base );
-		goto errout;
-	}
-
-	info->lcr_base = ioremap(info->phys_lcr_base,PAGE_SIZE) + info->lcr_offset;
+	info->lcr_base = ioremap(info->phys_lcr_base,PAGE_SIZE);
 	if (!info->lcr_base) {
 		printk( "%s(%d):%s Cant map LCR memory, MemAddr=%08X\n",
 			__FILE__,__LINE__,info->device_name, info->phys_lcr_base );
+		info->init_error = DiagStatus_CantAssignPciResources;
 		goto errout;
 	}
+	info->lcr_base += info->lcr_offset;
 
-	info->sca_base = ioremap(info->phys_sca_base,PAGE_SIZE) + info->sca_offset;
+	info->sca_base = ioremap(info->phys_sca_base,PAGE_SIZE);
 	if (!info->sca_base) {
 		printk( "%s(%d):%s Cant map SCA memory, MemAddr=%08X\n",
 			__FILE__,__LINE__,info->device_name, info->phys_sca_base );
+		info->init_error = DiagStatus_CantAssignPciResources;
 		goto errout;
 	}
+	info->sca_base += info->sca_offset;
 
-	info->statctrl_base = ioremap(info->phys_statctrl_base,PAGE_SIZE) + info->statctrl_offset;
+	info->statctrl_base = ioremap(info->phys_statctrl_base,PAGE_SIZE);
 	if (!info->statctrl_base) {
 		printk( "%s(%d):%s Cant map SCA Status/Control memory, MemAddr=%08X\n",
 			__FILE__,__LINE__,info->device_name, info->phys_statctrl_base );
+		info->init_error = DiagStatus_CantAssignPciResources;
+		goto errout;
+	}
+	info->statctrl_base += info->statctrl_offset;
+
+	if ( !memory_test(info) ) {
+		printk( "%s(%d):Shared Memory Test failed for device %s MemAddr=%08X\n",
+			__FILE__,__LINE__,info->device_name, info->phys_memory_base );
+		info->init_error = DiagStatus_MemoryError;
 		goto errout;
 	}
 
@@ -3639,7 +3649,7 @@ void release_resources(SLMP_INFO *info)
 	}
 
 	if ( info->shared_mem_requested ) {
-		release_mem_region(info->phys_memory_base,0x40000);
+		release_mem_region(info->phys_memory_base,SCA_MEM_SIZE);
 		info->shared_mem_requested = 0;
 	}
 	if ( info->lcr_mem_requested ) {
@@ -3647,11 +3657,11 @@ void release_resources(SLMP_INFO *info)
 		info->lcr_mem_requested = 0;
 	}
 	if ( info->sca_base_requested ) {
-		release_mem_region(info->phys_sca_base + info->sca_offset,512);
+		release_mem_region(info->phys_sca_base + info->sca_offset,SCA_BASE_SIZE);
 		info->sca_base_requested = 0;
 	}
 	if ( info->sca_statctrl_requested ) {
-		release_mem_region(info->phys_statctrl_base + info->statctrl_offset,16);
+		release_mem_region(info->phys_statctrl_base + info->statctrl_offset,SCA_REG_SIZE);
 		info->sca_statctrl_requested = 0;
 	}
 
@@ -3982,34 +3992,25 @@ static void __exit synclinkmp_exit(void)
 		       __FILE__,__LINE__,rc);
 	restore_flags(flags);
 
+	/* reset devices */
 	info = synclinkmp_device_list;
 	while(info) {
-#ifdef CONFIG_SYNCLINK_SYNCPPP
-		if (info->dosyncppp)
-			sppp_delete(info);
-#endif
 		reset_port(info);
-		if ( info->port_num == 0 ) {
-			if ( info->irq_requested ) {
-				free_irq(info->irq_level, info);
-				info->irq_requested = 0;
-			}
-		}
 		info = info->next_device;
 	}
 
-	/* port 0 of each adapter originally claimed
-	 * all resources, release those now
-	 */
+	/* release devices */
 	info = synclinkmp_device_list;
 	while(info) {
+#ifdef CONFIG_SYNCLINK_SYNCPPP
+		if (info->dosyncppp)
+			sppp_delete(info);
+#endif
 		free_dma_bufs(info);
 		free_tmp_rx_buf(info);
 		if ( info->port_num == 0 ) {
-			spin_lock_irqsave(&info->lock,flags);
-			reset_adapter(info);
-			write_reg(info, LPR, 1);		/* set low power mode */
-			spin_unlock_irqrestore(&info->lock,flags);
+			if (info->sca_base)
+				write_reg(info, LPR, 1); /* set low power mode */
 			release_resources(info);
 		}
 		tmp = info;
@@ -4229,6 +4230,9 @@ void tx_start(SLMP_INFO *info)
 				}
 			}
 
+			write_reg16(info, TRC0,
+				(unsigned short)(((tx_negate_fifo_level-1)<<8) + tx_active_fifo_level));
+
 			write_reg(info, TXDMA + DSR, 0); 		/* disable DMA channel */
 			write_reg(info, TXDMA + DCMD, SWABORT);	/* reset/init DMA channel */
 	
@@ -4240,11 +4244,10 @@ void tx_start(SLMP_INFO *info)
 			write_reg16(info, TXDMA + EDA,
 				info->tx_buf_list_ex[info->last_tx_buf].phys_entry);
 	
-			/* clear IDLE and UDRN status bit */
-			info->ie1_value &= ~(IDLE + UDRN);
-			if (info->params.mode != MGSL_MODE_ASYNC)
-				info->ie1_value |= UDRN;     		/* HDLC, IRQ on underrun */
-			write_reg(info, IE1, info->ie1_value);	/* enable MSCI interrupts */
+			/* enable underrun IRQ */
+			info->ie1_value &= ~IDLE;
+			info->ie1_value |= UDRN;
+			write_reg(info, IE1, info->ie1_value);
 			write_reg(info, SR1, (unsigned char)(IDLE + UDRN));
 	
 			write_reg(info, TXDMA + DIR, 0x40);		/* enable Tx DMA interrupts (EOM) */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/char/vc_screen.c linux-2.4.28-pre3/drivers/char/vc_screen.c
--- linux-2.4.27/drivers/char/vc_screen.c	2004-08-07 23:26:04.000000000 +0000
+++ linux-2.4.28-pre3/drivers/char/vc_screen.c	2004-09-10 19:33:32.000000000 +0000
@@ -136,10 +136,12 @@ vcs_read(struct file *file, char *buf, s
 	if (!vc_cons_allocated(currcons))
 		goto unlock_out;
 
-	read = 0;
-	ret = 0;
+	ret = -EINVAL;
 	if (pos != n)
 		goto unlock_out;
+
+	read = 0;
+	ret = 0;
 	while (count) {
 		char *con_buf0, *con_buf_start;
 		long this_round, size;
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/fc4/fc.c linux-2.4.28-pre3/drivers/fc4/fc.c
--- linux-2.4.27/drivers/fc4/fc.c	2001-09-14 21:04:08.000000000 +0000
+++ linux-2.4.28-pre3/drivers/fc4/fc.c	2004-09-10 19:35:20.000000000 +0000
@@ -1155,3 +1155,5 @@ int fc_do_prli(fc_channel *fc, unsigned 
 	kfree(p);
 	return status;
 }
+
+MODULE_LICENSE("GPL");
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/hotplug/cpqphp_ctrl.c linux-2.4.28-pre3/drivers/hotplug/cpqphp_ctrl.c
--- linux-2.4.27/drivers/hotplug/cpqphp_ctrl.c	2003-11-28 18:26:20.000000000 +0000
+++ linux-2.4.28-pre3/drivers/hotplug/cpqphp_ctrl.c	2004-09-10 19:33:58.000000000 +0000
@@ -1726,7 +1726,14 @@ static int event_thread(void* data)
 	
 	//  New name
 	strcpy(current->comm, "phpd_event");
-	
+
+	/* avoid getting signals */
+	spin_lock_irq(&current->sigmask_lock);
+	flush_signals(current);
+	sigfillset(&current->blocked);
+	recalc_sigpending(current);
+	spin_unlock_irq(&current->sigmask_lock);
+
 	unlock_kernel();
 
 	while (1) {
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/hotplug/ibmphp_res.c linux-2.4.28-pre3/drivers/hotplug/ibmphp_res.c
--- linux-2.4.27/drivers/hotplug/ibmphp_res.c	2003-11-28 18:26:20.000000000 +0000
+++ linux-2.4.28-pre3/drivers/hotplug/ibmphp_res.c	2004-09-10 19:37:02.000000000 +0000
@@ -42,7 +42,7 @@ static int remove_ranges (struct bus_nod
 static int update_bridge_ranges (struct bus_node **);
 static int add_range (int type, struct range_node *, struct bus_node *);
 static void fix_resources (struct bus_node *);
-static inline struct bus_node *find_bus_wprev (u8, struct bus_node **, u8);
+static struct bus_node *find_bus_wprev (u8, struct bus_node **, u8);
 
 static LIST_HEAD(gbuses);
 LIST_HEAD(ibmphp_res_head);
@@ -1757,7 +1757,7 @@ struct bus_node *ibmphp_find_res_bus (u8
 	return find_bus_wprev (bus_number, NULL, 0);
 }
 
-static inline struct bus_node *find_bus_wprev (u8 bus_number, struct bus_node **prev, u8 flag)
+static struct bus_node *find_bus_wprev (u8 bus_number, struct bus_node **prev, u8 flag)
 {
 	struct bus_node *bus_cur;
 	struct list_head *tmp;
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/hotplug/pciehp.h linux-2.4.28-pre3/drivers/hotplug/pciehp.h
--- linux-2.4.27/drivers/hotplug/pciehp.h	2004-08-07 23:26:04.000000000 +0000
+++ linux-2.4.28-pre3/drivers/hotplug/pciehp.h	2004-09-10 19:37:20.000000000 +0000
@@ -45,8 +45,6 @@ extern int pciehp_poll_mode;
 extern int pciehp_poll_time;
 extern int pciehp_debug;
 
-extern int pciehp_msi_quirk;
-
 /*#define dbg(format, arg...) do { if (pciehp_debug) printk(KERN_DEBUG "%s: " format, MY_NAME , ## arg); } while (0)*/
 #define dbg(format, arg...) do { if (pciehp_debug) printk("%s: " format, MY_NAME , ## arg); } while (0)
 #define err(format, arg...) printk(KERN_ERR "%s: " format, MY_NAME , ## arg)
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/hotplug/pciehp_ctrl.c linux-2.4.28-pre3/drivers/hotplug/pciehp_ctrl.c
--- linux-2.4.27/drivers/hotplug/pciehp_ctrl.c	2004-08-07 23:26:04.000000000 +0000
+++ linux-2.4.28-pre3/drivers/hotplug/pciehp_ctrl.c	2004-09-10 19:32:47.000000000 +0000
@@ -1053,6 +1053,34 @@ static int is_bridge(struct pci_func * f
    hotplug controller logic
  */
 
+static void set_slot_off(struct controller *ctrl, struct slot * pslot)
+{
+	/* Wait for exclusive access to hardware */
+	down(&ctrl->crit_sect);
+
+	/* turn off slot, turn on Amber LED, turn off Green LED */
+	if (pslot->hpc_ops->power_off_slot(pslot)) {   
+		err("%s: Issue of Slot Power Off command failed\n", __FUNCTION__);
+		up(&ctrl->crit_sect);
+		return;
+	}
+	wait_for_ctrl_irq (ctrl);
+
+	pslot->hpc_ops->green_led_off(pslot);   
+	
+	wait_for_ctrl_irq (ctrl);
+
+	/* turn on Amber LED */
+	if (pslot->hpc_ops->set_attention_status(pslot, 1)) {   
+		err("%s: Issue of Set Attention Led command failed\n", __FUNCTION__);
+		up(&ctrl->crit_sect);
+		return;
+	}
+	wait_for_ctrl_irq (ctrl);
+
+	/* Done with exclusive hardware access */
+	up(&ctrl->crit_sect);
+}
 
 /**
  * board_added - Called after a board has been added to the system.
@@ -1066,7 +1094,7 @@ static u32 board_added(struct pci_func *
 	u8 hp_slot;
 	int index;
 	u32 temp_register = 0xFFFFFFFF;
-	u32 retval, rc = 0;
+	u32 rc = 0;
 	struct pci_func *new_func = NULL;
 	struct slot *p_slot;
 	struct resource_lists res_lists;
@@ -1082,8 +1110,10 @@ static u32 board_added(struct pci_func *
 	
 	/* Power on slot */
 	rc = p_slot->hpc_ops->power_on_slot(p_slot);
-	if (rc)
+	if (rc) {
+		up(&ctrl->crit_sect);
 		return -1;
+	}
 
 	/* Wait for the command to complete */
 	wait_for_ctrl_irq(ctrl);
@@ -1105,10 +1135,11 @@ static u32 board_added(struct pci_func *
 	dbg("%s: afterlong_delay\n", __FUNCTION__);
 
 	dbg("%s: before check link status", __FUNCTION__);
-	/*  Make this to check for link training status */
+	/*  Check link training status */
 	rc = p_slot->hpc_ops->check_lnk_status(ctrl);  
 	if (rc) {
 		err("%s: Failed to check link status\n", __FUNCTION__);
+		set_slot_off(ctrl, p_slot);
 		return -1;
 	}
 
@@ -1161,36 +1192,7 @@ static u32 board_added(struct pci_func *
 		pciehp_resource_sort_and_combine(&(ctrl->bus_head));
 
 		if (rc) {
-			/* Wait for exclusive access to hardware */
-			down(&ctrl->crit_sect);
-
-			/* Turn off slot, turn on Amber LED, turn off Green LED */
-			retval = p_slot->hpc_ops->power_off_slot(p_slot);   
-			/* In PCI Express, just power off slot */
-			if (retval) {
-				err("%s: Issue of Slot Power Off command failed\n", __FUNCTION__);
-				return retval;
-			}
-			/* Wait for the command to complete */
-			wait_for_ctrl_irq(ctrl);
-
-			p_slot->hpc_ops->green_led_off(p_slot);   
-			
-			/* Wait for the command to complete */
-			wait_for_ctrl_irq(ctrl);
-
-			/* Turn on Amber LED */
-			retval = p_slot->hpc_ops->set_attention_status(p_slot, 1);   
-			if (retval) {
-				err("%s: Issue of Set Attention Led command failed\n", __FUNCTION__);
-				return retval;
-			}
-			/* Wait for the command to complete */
-			wait_for_ctrl_irq(ctrl);
-
-			/* Done with exclusive hardware access */
-			up(&ctrl->crit_sect);
-
+			set_slot_off(ctrl, p_slot);
 			return(rc);
 		}
 		pciehp_save_slot_config(ctrl, func);
@@ -1220,42 +1222,12 @@ static u32 board_added(struct pci_func *
 		/* Wait for the command to complete */
 		wait_for_ctrl_irq(ctrl);
 
-
 		/* Done with exclusive hardware access */
 		up(&ctrl->crit_sect);
 
 	} else {
-		/* Wait for exclusive access to hardware */
-		down(&ctrl->crit_sect);
-
-		/* Turn off slot, turn on Amber LED, turn off Green LED */
-		retval = p_slot->hpc_ops->power_off_slot(p_slot);   
-		/* In PCI Express, just power off slot */
-		if (retval) {
-			err("%s: Issue of Slot Power Off command failed\n", __FUNCTION__);
-			return retval;
-		}
-		/* Wait for the command to complete */
-		wait_for_ctrl_irq(ctrl);
-
-		p_slot->hpc_ops->green_led_off(p_slot);   
-		
-		/* Wait for the command to complete */
-		wait_for_ctrl_irq(ctrl);
-
-		/* Turn on Amber LED */
-		retval = p_slot->hpc_ops->set_attention_status(p_slot, 1);   
-		if (retval) {
-			err("%s: Issue of Set Attention Led command failed\n", __FUNCTION__);
-			return retval;
-		}
-		/* Wait for the command to complete */
-		wait_for_ctrl_irq(ctrl);
-
-		/* Done with exclusive hardware access */
-		up(&ctrl->crit_sect);
-
-		return(rc);
+		set_slot_off(ctrl, p_slot);
+		return -1;
 	}
 	return 0;
 }
@@ -1323,6 +1295,7 @@ static u32 remove_board(struct pci_func 
 	rc = p_slot->hpc_ops->power_off_slot(p_slot);
 	if (rc) {
 		err("%s: Issue of Slot Disable command failed\n", __FUNCTION__);
+		up(&ctrl->crit_sect);
 		return rc;
 	}
 	/* Wait for the command to complete */
@@ -1592,7 +1565,10 @@ static void interrupt_event_handler(stru
 					down(&ctrl->crit_sect);
 
 					p_slot->hpc_ops->set_attention_status(p_slot, 1);
+					wait_for_ctrl_irq(ctrl);
+
 					p_slot->hpc_ops->green_led_off(p_slot);
+					wait_for_ctrl_irq(ctrl);
 
 					/* Done with exclusive hardware access */
 					up(&ctrl->crit_sect);
@@ -1624,7 +1600,6 @@ void pciehp_pushbutton_thread (unsigned 
 {
 	struct slot *p_slot = (struct slot *) slot;
 	u8 getstatus;
-	int rc;
 	
 	pushbutton_pending = 0;
 
@@ -1638,23 +1613,7 @@ void pciehp_pushbutton_thread (unsigned 
 		p_slot->state = POWEROFF_STATE;
 		dbg("In power_down_board, b:d(%x:%x)\n", p_slot->bus, p_slot->device);
 
-		if (pciehp_disable_slot(p_slot)) {
-			/* Wait for exclusive access to hardware */
-			down(&p_slot->ctrl->crit_sect);
-
-			/* Turn on the Attention LED */
-			rc = p_slot->hpc_ops->set_attention_status(p_slot, 1);
-			if (rc) {
-				err("%s: Issue of Set Atten Indicator On command failed\n", __FUNCTION__);
-				return;
-			}
-	
-			/* Wait for the command to complete */
-			wait_for_ctrl_irq (p_slot->ctrl);
-
-			/* Done with exclusive hardware access */
-			up(&p_slot->ctrl->crit_sect);
-		}
+		pciehp_disable_slot(p_slot);
 		p_slot->state = STATIC_STATE;
 	} else {
 		p_slot->state = POWERON_STATE;
@@ -1664,15 +1623,6 @@ void pciehp_pushbutton_thread (unsigned 
 			/* Wait for exclusive access to hardware */
 			down(&p_slot->ctrl->crit_sect);
 
-			/* Turn off the green LED */
-			rc = p_slot->hpc_ops->set_attention_status(p_slot, 1);
-			if (rc) {
-				err("%s: Issue of Set Attn Indicator On command failed\n", __FUNCTION__);
-				return;
-			}
-			/* Wait for the command to complete */
-			wait_for_ctrl_irq (p_slot->ctrl);
-			
 			p_slot->hpc_ops->green_led_off(p_slot);
 
 			/* Wait for the command to complete */
@@ -1706,21 +1656,21 @@ int pciehp_enable_slot (struct slot *p_s
 	if (rc || !getstatus) {
 		info("%s: no adapter on slot(%x)\n", __FUNCTION__, p_slot->number);
 		up(&p_slot->ctrl->crit_sect);
-		return (0);
+		return (1);
 	}
 
 	rc = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
 	if (rc || getstatus) {
 		info("%s: latch open on slot(%x)\n", __FUNCTION__, p_slot->number);
 		up(&p_slot->ctrl->crit_sect);
-		return (0);
+		return (1);
 	}
 
 	rc = p_slot->hpc_ops->get_power_status(p_slot, &getstatus);
 	if (rc || getstatus) {
 		info("%s: already enabled on slot(%x)\n", __FUNCTION__, p_slot->number);
 		up(&p_slot->ctrl->crit_sect);
-		return (0);
+		return (1);
 	}
 	up(&p_slot->ctrl->crit_sect);
 
@@ -1793,21 +1743,21 @@ int pciehp_disable_slot (struct slot *p_
 	if (ret || !getstatus) {
 		info("%s: no adapter on slot(%x)\n", __FUNCTION__, p_slot->number);
 		up(&p_slot->ctrl->crit_sect);
-		return (0);
+		return (1);
 	}
 
 	ret = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
 	if (ret || getstatus) {
 		info("%s: latch open on slot(%x)\n", __FUNCTION__, p_slot->number);
 		up(&p_slot->ctrl->crit_sect);
-		return (0);
+		return (1);
 	}
 
 	ret = p_slot->hpc_ops->get_power_status(p_slot, &getstatus);
 	if (ret || !getstatus) {
 		info("%s: already disabled slot(%x)\n", __FUNCTION__, p_slot->number);
 		up(&p_slot->ctrl->crit_sect);
-		return (0);
+		return (1);
 	}
 	up(&p_slot->ctrl->crit_sect);
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/hotplug/pciehp_hpc.c linux-2.4.28-pre3/drivers/hotplug/pciehp_hpc.c
--- linux-2.4.27/drivers/hotplug/pciehp_hpc.c	2004-08-07 23:26:04.000000000 +0000
+++ linux-2.4.28-pre3/drivers/hotplug/pciehp_hpc.c	2004-09-10 19:34:15.000000000 +0000
@@ -346,10 +346,11 @@ static int hpc_check_lnk_status(struct c
 		return retval;
 	}
 
-	if ( (lnk_status & (LNK_TRN | LNK_TRN_ERR)) == 0x0C00) {
+	dbg("%s: lnk_status = %x\n", __FUNCTION__, lnk_status);
+	if ( (lnk_status & LNK_TRN) || (lnk_status & LNK_TRN_ERR) || 
+		!(lnk_status & NEG_LINK_WD)) {
 		err("%s : Link Training Error occurs \n", __FUNCTION__);
-		retval = -1;
-		return retval;
+		return -1;
 	}
 
 	DBG_LEAVE_ROUTINE 
@@ -911,7 +912,6 @@ static void pcie_isr(int IRQ, void *dev_
 		err("%s : hp_register_read_word SLOT_STATUS failed\n", __FUNCTION__);
 		return;
 	}
-	/* dbg("%s: hp_register_read_word SLOT_STATUS with value %x\n", __FUNCTION__, slot_status); */
 
 	intr_detect = ( ATTN_BUTTN_PRESSED | PWR_FAULT_DETECTED | MRL_SENS_CHANGED |
 					PRSN_DETECT_CHANGED | CMD_COMPLETED );
@@ -932,8 +932,6 @@ static void pcie_isr(int IRQ, void *dev_
 			return;
 		}
 
-		dbg("%s: Set Mask Hot-plug Interrupt Enable\n", __FUNCTION__);
-		dbg("%s: hp_register_read_word SLOT_CTRL with value %x\n", __FUNCTION__, temp_word);
 		temp_word = (temp_word & ~HP_INTR_ENABLE & ~CMD_CMPL_INTR_ENABLE) | 0x00;
 
 		rc = hp_register_write_word(php_ctlr->pci_dev, SLOT_CTRL, temp_word);
@@ -941,14 +939,12 @@ static void pcie_isr(int IRQ, void *dev_
 			err("%s : hp_register_write_word SLOT_CTRL failed\n", __FUNCTION__);
 			return;
 		}
-		dbg("%s: hp_register_write_word SLOT_CTRL with value %x\n", __FUNCTION__, temp_word);
 		
 		rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS, slot_status);
 		if (rc) {
 			err("%s : hp_register_read_word SLOT_STATUS failed\n", __FUNCTION__);
 			return;
 		}
-		dbg("%s: hp_register_read_word SLOT_STATUS with value %x\n", __FUNCTION__, slot_status); 
 		
 		/* Clear command complete interrupt caused by this write */
 		temp_word = 0x1f;
@@ -957,7 +953,6 @@ static void pcie_isr(int IRQ, void *dev_
 			err("%s : hp_register_write_word SLOT_STATUS failed\n", __FUNCTION__);
 			return;
 		}
-		dbg("%s: hp_register_write_word SLOT_STATUS with value %x\n", __FUNCTION__, temp_word); 	
 	}
 
 	if (intr_loc & CMD_COMPLETED) {
@@ -995,8 +990,6 @@ static void pcie_isr(int IRQ, void *dev_
 			err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__);
 			return;
 		}
-		dbg("%s: Unmask Hot-plug Interrupt Enable\n", __FUNCTION__);
-		dbg("%s: hp_register_read_word SLOT_CTRL with value %x\n", __FUNCTION__, temp_word);
 		temp_word = (temp_word & ~HP_INTR_ENABLE) | HP_INTR_ENABLE;
 
 		rc = hp_register_write_word(php_ctlr->pci_dev, SLOT_CTRL, temp_word);
@@ -1004,14 +997,12 @@ static void pcie_isr(int IRQ, void *dev_
 			err("%s : hp_register_write_word SLOT_CTRL failed\n", __FUNCTION__);
 			return;
 		}	
-		dbg("%s: hp_register_write_word SLOT_CTRL with value %x\n", __FUNCTION__, temp_word); 	
 	
 		rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS, slot_status);
 		if (rc) {
 			err("%s : hp_register_read_word SLOT_STATUS failed\n", __FUNCTION__);
 			return;
 		}
-		dbg("%s: hp_register_read_word SLOT_STATUS with value %x\n", __FUNCTION__, slot_status); 
 		
 		/* Clear command complete interrupt caused by this write */
 		temp_word = 0x1F;
@@ -1020,7 +1011,6 @@ static void pcie_isr(int IRQ, void *dev_
 			err("%s : hp_register_write_word SLOT_STATUS failed\n", __FUNCTION__);
 			return;
 		}
-		dbg("%s: hp_register_write_word SLOT_STATUS with value %x\n", __FUNCTION__, temp_word); 	
 	}
 	return;
 }
@@ -1409,17 +1399,6 @@ int pcie_init(struct controller * ctrl,
 		start_int_poll_timer( php_ctlr, 10 );   /* start with 10 second delay */
 	} else {
 		/* Installs the interrupt handler */
-#ifdef CONFIG_PCI_USE_VECTOR 
-		if (!pciehp_msi_quirk) {	
-			rc = pci_enable_msi(pdev);
-			if (rc) {
-				info("Can't get msi for the hotplug controller\n");
-				info("Use INTx for the hotplug controller\n");
-				dbg("%s: rc = %x\n", __FUNCTION__, rc);
-			} else
-				php_ctlr->irq = pdev->irq;
-		}
-#endif
 		rc = request_irq(php_ctlr->irq, pcie_isr, SA_SHIRQ, MY_NAME, (void *) ctrl);
 		dbg("%s: request_irq %d for hpc%d (returns %d)\n", __FUNCTION__, php_ctlr->irq, ctlr_seq_num, rc);
 		if (rc) {
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/hotplug/pciehp_pci.c linux-2.4.28-pre3/drivers/hotplug/pciehp_pci.c
--- linux-2.4.27/drivers/hotplug/pciehp_pci.c	2004-08-07 23:26:04.000000000 +0000
+++ linux-2.4.28-pre3/drivers/hotplug/pciehp_pci.c	2004-09-10 19:35:56.000000000 +0000
@@ -117,9 +117,7 @@ static int configure_visit_pci_dev (stru
 			temp_func->pci_dev->bus->number, temp_func->pci_dev->devfn); 
 		dbg("%s: PCI_SLOT_NAME=%s\n", __FUNCTION__, 
 			temp_func->pci_dev->slot_name);
-		//pci_enable_device(temp_func->pci_dev);
-		//dbg("%s: after calling pci_enable_device, irq = %x\n", 
-		//	__FUNCTION__, temp_func->pci_dev->irq); 
+		pci_enable_device(temp_func->pci_dev);
 		pci_proc_attach_device(temp_func->pci_dev);
 		pci_announce_device_to_drivers(temp_func->pci_dev);
 	}
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/hotplug/pciehprm_acpi.c linux-2.4.28-pre3/drivers/hotplug/pciehprm_acpi.c
--- linux-2.4.27/drivers/hotplug/pciehprm_acpi.c	2004-08-07 23:26:04.000000000 +0000
+++ linux-2.4.28-pre3/drivers/hotplug/pciehprm_acpi.c	2004-09-10 19:36:44.000000000 +0000
@@ -217,6 +217,10 @@ static void acpi_get__hpp ( struct acpi_
 	}
 
 	ab->_hpp = kmalloc (sizeof (struct acpi__hpp), GFP_KERNEL);
+	if (!ab->_hpp) {
+		err ("acpi_pciehprm:%s alloc for _HPP failed\n", path_name);
+		goto free_and_return;
+	}
 	memset(ab->_hpp, 0, sizeof(struct acpi__hpp));
 
 	ab->_hpp->cache_line_size	= nui[0];
@@ -1392,7 +1396,7 @@ static int configure_existing_function(
 
 static int bind_pci_resources_to_slots ( struct controller *ctrl)
 {
-	struct pci_func *func;
+	struct pci_func *func, new_func;
 	int busn = ctrl->slot_bus;
 	int devn, funn;
 	u32	vid;
@@ -1411,11 +1415,19 @@ static int bind_pci_resources_to_slots (
 			if (vid != 0xFFFFFFFF) {
 				dbg("%s: vid = %x\n", __FUNCTION__, vid);
 				func = pciehp_slot_find(busn, devn, funn);
-				if (!func)
-					continue;
-				configure_existing_function(ctrl, func);
+				if (!func) {
+					memset(&new_func, 0, sizeof(struct pci_func));
+					new_func.bus = busn;
+					new_func.device = devn;
+					new_func.function = funn;
+					new_func.is_a_board = 1;
+					configure_existing_function(ctrl, &new_func);
+					pciehprm_dump_func_res(&new_func);
+				} else {
+					configure_existing_function(ctrl, func);
+					pciehprm_dump_func_res(func);
+				}
 				dbg("aCCF:existing PCI 0x%x Func ResourceDump\n", ctrl->bus);
-				pciehprm_dump_func_res(func);
 			}
 		}
 	}
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/hotplug/pciehprm_nonacpi.c linux-2.4.28-pre3/drivers/hotplug/pciehprm_nonacpi.c
--- linux-2.4.27/drivers/hotplug/pciehprm_nonacpi.c	2004-08-07 23:26:04.000000000 +0000
+++ linux-2.4.28-pre3/drivers/hotplug/pciehprm_nonacpi.c	2004-09-10 19:32:27.000000000 +0000
@@ -281,7 +281,7 @@ static int pciehprm_delete_resource(
 
 static int bind_pci_resources_to_slots ( struct controller *ctrl)
 {
-	struct pci_func *func;
+	struct pci_func *func, new_func;
 	int busn = ctrl->slot_bus;
 	int devn, funn;
 	u32	vid;
@@ -301,11 +301,19 @@ static int bind_pci_resources_to_slots (
 				vid, busn, devn, funn);
 				func = pciehp_slot_find(busn, devn, funn);
 				dbg("%s: func = %p\n", __FUNCTION__,func);
-				if (!func)
-					continue;
-				configure_existing_function(ctrl, func);
+				if (!func) {
+					memset(&new_func, 0, sizeof(struct pci_func));
+					new_func.bus = busn;
+					new_func.device = devn;
+					new_func.function = funn;
+					new_func.is_a_board = 1;
+					configure_existing_function(ctrl, &new_func);
+					phprm_dump_func_res(&new_func);
+				} else {
+					configure_existing_function(ctrl, func);
+					phprm_dump_func_res(func);
+				}
 				dbg("aCCF:existing PCI 0x%x Func ResourceDump\n", ctrl->bus);
-				phprm_dump_func_res(func);
 			}
 		}
 	}
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/hotplug/shpchp.h linux-2.4.28-pre3/drivers/hotplug/shpchp.h
--- linux-2.4.27/drivers/hotplug/shpchp.h	2004-08-07 23:26:04.000000000 +0000
+++ linux-2.4.28-pre3/drivers/hotplug/shpchp.h	2004-09-10 19:34:01.000000000 +0000
@@ -61,6 +61,7 @@ struct pci_func {
 	u8 configured;
 	u8 switch_save;
 	u8 presence_save;
+	u8 pwr_save;
 	u32 base_length[0x06];
 	u8 base_type[0x06];
 	u16 reserved2;
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/hotplug/shpchp_ctrl.c linux-2.4.28-pre3/drivers/hotplug/shpchp_ctrl.c
--- linux-2.4.27/drivers/hotplug/shpchp_ctrl.c	2004-08-07 23:26:04.000000000 +0000
+++ linux-2.4.28-pre3/drivers/hotplug/shpchp_ctrl.c	2004-09-10 19:37:00.000000000 +0000
@@ -137,6 +137,8 @@ u8 shpchp_handle_switch_change(u8 hp_slo
 	p_slot = shpchp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
 	p_slot->hpc_ops->get_adapter_status(p_slot, &(func->presence_save));
 	p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
+	dbg("%s: Card present %x Power status %x\n", __FUNCTION__,
+		func->presence_save, func->pwr_save);
 
 	if (getstatus) {
 		/*
@@ -145,6 +147,10 @@ u8 shpchp_handle_switch_change(u8 hp_slo
 		info("Latch open on Slot(%d)\n", ctrl->first_slot + hp_slot);
 		func->switch_save = 0;
 		taskInfo->event_type = INT_SWITCH_OPEN;
+		if (func->pwr_save && func->presence_save) {
+			taskInfo->event_type = INT_POWER_FAULT;
+			err("Surprise Removal of card\n");
+		}
 	} else {
 		/*
 		 *  Switch closed
@@ -1431,6 +1437,7 @@ static u32 board_added(struct pci_func *
 					rc = p_slot->hpc_ops->set_bus_speed_mode(p_slot, adapter_speed);
 					if (rc) {
 						err("%s: Issue of set bus speed mode command failed\n", __FUNCTION__);
+						up(&ctrl->crit_sect);
 						return WRONG_BUS_FREQUENCY;
 					}
 				
@@ -1442,6 +1449,7 @@ static u32 board_added(struct pci_func *
 						err("%s: Can't set bus speed/mode in the case of adapter & bus mismatch\n",
 								  __FUNCTION__);
 						err("%s: Error code (%d)\n", __FUNCTION__, rc);
+						up(&ctrl->crit_sect);
 						return WRONG_BUS_FREQUENCY;
 					}
 					/* Done with exclusive hardware access */
@@ -1592,7 +1600,8 @@ static u32 board_added(struct pci_func *
 		func->status = 0;
 		func->switch_save = 0x10;
 		func->is_a_board = 0x01;
-
+		func->pwr_save = 1;
+	
 		/* Next, we will instantiate the linux pci_dev structures 
 		 * (with appropriate driver notification, if already present) 
 		 */
@@ -1785,6 +1794,7 @@ static u32 remove_board(struct pci_func 
 		func->function = 0;
 		func->configured = 0;
 		func->switch_save = 0x10;
+		func->pwr_save = 0;
 		func->is_a_board = 0;
 	}
 
@@ -2038,7 +2048,6 @@ void shpchp_pushbutton_thread (unsigned 
 {
 	struct slot *p_slot = (struct slot *) slot;
 	u8 getstatus;
-	int rc;
 	
 	pushbutton_pending = 0;
 
@@ -2052,23 +2061,7 @@ void shpchp_pushbutton_thread (unsigned 
 		p_slot->state = POWEROFF_STATE;
 		dbg("In power_down_board, b:d(%x:%x)\n", p_slot->bus, p_slot->device);
 
-		if (shpchp_disable_slot(p_slot)) {
-			/* Wait for exclusive access to hardware */
-			down(&p_slot->ctrl->crit_sect);
-
-			/* Turn on the Attention LED */
-			rc = p_slot->hpc_ops->set_attention_status(p_slot, 1);
-			if (rc) {
-				err("%s: Issue of Set Atten Indicator On command failed\n", __FUNCTION__);
-				return;
-			}
-	
-			/* Wait for the command to complete */
-			wait_for_ctrl_irq(p_slot->ctrl);
-
-			/* Done with exclusive hardware access */
-			up(&p_slot->ctrl->crit_sect);
-		}
+		shpchp_disable_slot(p_slot);
 		p_slot->state = STATIC_STATE;
 	} else {
 		p_slot->state = POWERON_STATE;
@@ -2078,15 +2071,6 @@ void shpchp_pushbutton_thread (unsigned 
 			/* Wait for exclusive access to hardware */
 			down(&p_slot->ctrl->crit_sect);
 
-			/* Turn off the green LED */
-			rc = p_slot->hpc_ops->set_attention_status(p_slot, 1);
-			if (rc) {
-				err("%s: Issue of Set Atten Indicator On command failed\n", __FUNCTION__);
-				return;
-			}
-			/* Wait for the command to complete */
-			wait_for_ctrl_irq(p_slot->ctrl);
-			
 			p_slot->hpc_ops->green_led_off(p_slot);
 
 			/* Wait for the command to complete */
@@ -2120,19 +2104,19 @@ int shpchp_enable_slot (struct slot *p_s
 	if (rc || !getstatus) {
 		info("%s: no adapter on slot(%x)\n", __FUNCTION__, p_slot->number);
 		up(&p_slot->ctrl->crit_sect);
-		return (0);
+		return (1);
 	}
 	rc = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
 	if (rc || getstatus) {
 		info("%s: latch open on slot(%x)\n", __FUNCTION__, p_slot->number);
 		up(&p_slot->ctrl->crit_sect);
-		return (0);
+		return (1);
 	}
 	rc = p_slot->hpc_ops->get_power_status(p_slot, &getstatus);
 	if (rc || getstatus) {
 		info("%s: already enabled on slot(%x)\n", __FUNCTION__, p_slot->number);
 		up(&p_slot->ctrl->crit_sect);
-		return (0);
+		return (1);
 	}
 	up(&p_slot->ctrl->crit_sect);
 
@@ -2150,6 +2134,8 @@ int shpchp_enable_slot (struct slot *p_s
 
 	/* We have to save the presence info for these slots */
 	p_slot->hpc_ops->get_adapter_status(p_slot, &(func->presence_save));
+	p_slot->hpc_ops->get_power_status(p_slot, &(func->pwr_save));
+	dbg("%s: func->pwr_save %x\n", __FUNCTION__, func->pwr_save);
 	p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
 	func->switch_save = !getstatus? 0x10:0;
 
@@ -2205,19 +2191,19 @@ int shpchp_disable_slot (struct slot *p_
 	if (ret || !getstatus) {
 		info("%s: no adapter on slot(%x)\n", __FUNCTION__, p_slot->number);
 		up(&p_slot->ctrl->crit_sect);
-		return (0);
+		return (1);
 	}
 	ret = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
 	if (ret || getstatus) {
 		info("%s: latch open on slot(%x)\n", __FUNCTION__, p_slot->number);
 		up(&p_slot->ctrl->crit_sect);
-		return (0);
+		return (1);
 	}
 	ret = p_slot->hpc_ops->get_power_status(p_slot, &getstatus);
 	if (ret || !getstatus) {
 		info("%s: already disabled slot(%x)\n", __FUNCTION__, p_slot->number);
 		up(&p_slot->ctrl->crit_sect);
-		return (0);
+		return (1);
 	}
 	up(&p_slot->ctrl->crit_sect);
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/hotplug/shpchp_hpc.c linux-2.4.28-pre3/drivers/hotplug/shpchp_hpc.c
--- linux-2.4.27/drivers/hotplug/shpchp_hpc.c	2004-08-07 23:26:04.000000000 +0000
+++ linux-2.4.28-pre3/drivers/hotplug/shpchp_hpc.c	2004-09-10 19:34:33.000000000 +0000
@@ -1547,15 +1547,6 @@ int shpc_init(struct controller * ctrl,
 		start_int_poll_timer( php_ctlr, 10 );   /* start with 10 second delay */
 	} else {
 		/* Installs the interrupt handler */
-#ifdef CONFIG_PCI_USE_VECTOR 
-		rc = pci_enable_msi(pdev);
-		if (rc) {
-			info("Can't get msi for the hotplug controller\n");
-			info("Use INTx for the hotplug controller\n");
-			dbg("%s: rc = %x\n", __FUNCTION__, rc);
-		} else
-			php_ctlr->irq = pdev->irq;
-#endif		
 		rc = request_irq(php_ctlr->irq, shpc_isr, SA_SHIRQ, MY_NAME, (void *) ctrl);
 		dbg("%s: request_irq %d for hpc%d (returns %d)\n", __FUNCTION__, php_ctlr->irq, 
 			ctlr_seq_num, rc);
@@ -1563,7 +1554,6 @@ int shpc_init(struct controller * ctrl,
 			err("Can't get irq %d for the hotplug controller\n", php_ctlr->irq);
 			goto abort_free_ctlr;
 		}
-		/* Execute OSHP method here */
 	}
 	dbg("%s: Before adding HPC to HPC list\n", __FUNCTION__);
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/hotplug/shpchp_pci.c linux-2.4.28-pre3/drivers/hotplug/shpchp_pci.c
--- linux-2.4.27/drivers/hotplug/shpchp_pci.c	2004-08-07 23:26:04.000000000 +0000
+++ linux-2.4.28-pre3/drivers/hotplug/shpchp_pci.c	2004-09-10 19:33:11.000000000 +0000
@@ -481,6 +481,7 @@ int shpchp_save_config(struct controller
 				new_slot->function = (u8) function;
 				new_slot->is_a_board = 1;
 				new_slot->switch_save = 0x10;
+				new_slot->pwr_save = 1;
 				/* In case of unsupported board */
 				new_slot->status = DevError;
 				new_slot->pci_dev = pci_find_slot(new_slot->bus, (new_slot->device << 3) | new_slot->function);
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/hotplug/shpchprm_acpi.c linux-2.4.28-pre3/drivers/hotplug/shpchprm_acpi.c
--- linux-2.4.27/drivers/hotplug/shpchprm_acpi.c	2004-08-07 23:26:04.000000000 +0000
+++ linux-2.4.28-pre3/drivers/hotplug/shpchprm_acpi.c	2004-09-10 19:37:30.000000000 +0000
@@ -217,6 +217,10 @@ static void acpi_get__hpp ( struct acpi_
 	}
 
 	ab->_hpp = kmalloc (sizeof (struct acpi__hpp), GFP_KERNEL);
+	if (!ab->_hpp) {
+		err ("acpi_shpchprm:%s alloc for _HPP failed\n", path_name);
+		goto free_and_return;
+	}
 	memset(ab->_hpp, 0, sizeof(struct acpi__hpp));
 
 	ab->_hpp->cache_line_size	= nui[0];
@@ -1387,7 +1391,7 @@ static int configure_existing_function(
 
 static int bind_pci_resources_to_slots ( struct controller *ctrl)
 {
-	struct pci_func *func;
+	struct pci_func *func, new_func;
 	int busn = ctrl->bus;
 	int devn, funn;
 	u32	vid;
@@ -1402,11 +1406,19 @@ static int bind_pci_resources_to_slots (
 
 			if (vid != 0xFFFFFFFF) {
 				func = shpchp_slot_find(busn, devn, funn);
-				if (!func)
-					continue;
-				configure_existing_function(ctrl, func);
+				if (!func) {
+					memset(&new_func, 0, sizeof(struct pci_func));
+					new_func.bus = busn;
+					new_func.device = devn;
+					new_func.function = funn;
+					new_func.is_a_board = 1;
+					configure_existing_function(ctrl, &new_func);
+					shpchprm_dump_func_res(&new_func);
+				} else {
+					configure_existing_function(ctrl, func);
+					shpchprm_dump_func_res(func);
+				}
 				dbg("aCCF:existing PCI 0x%x Func ResourceDump\n", ctrl->bus);
-				shpchprm_dump_func_res(func);
 			}
 		}
 	}
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/hotplug/shpchprm_nonacpi.c linux-2.4.28-pre3/drivers/hotplug/shpchprm_nonacpi.c
--- linux-2.4.27/drivers/hotplug/shpchprm_nonacpi.c	2004-08-07 23:26:04.000000000 +0000
+++ linux-2.4.28-pre3/drivers/hotplug/shpchprm_nonacpi.c	2004-09-10 19:35:00.000000000 +0000
@@ -213,7 +213,7 @@ static int configure_existing_function(
 
 static int bind_pci_resources_to_slots ( struct controller *ctrl)
 {
-	struct pci_func *func;
+	struct pci_func *func, new_func;
 	int busn = ctrl->slot_bus;
 	int devn, funn;
 	u32	vid;
@@ -230,11 +230,19 @@ static int bind_pci_resources_to_slots (
 
 			if (vid != 0xFFFFFFFF) {
 				func = shpchp_slot_find(busn, devn, funn);
-				if (!func)
-					continue;
-				configure_existing_function(ctrl, func);
+				if (!func) {
+					memset(&new_func, 0, sizeof(struct pci_func));
+					new_func.bus = busn;
+					new_func.device = devn;
+					new_func.function = funn;
+					new_func.is_a_board = 1;
+					configure_existing_function(ctrl, &new_func);
+					phprm_dump_func_res(&new_func);
+				} else {
+					configure_existing_function(ctrl, func);
+					phprm_dump_func_res(func);
+				}
 				dbg("aCCF:existing PCI 0x%x Func ResourceDump\n", ctrl->bus);
-				phprm_dump_func_res(func);
 			}
 		}
 	}
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/ide/Config.in linux-2.4.28-pre3/drivers/ide/Config.in
--- linux-2.4.27/drivers/ide/Config.in	2004-08-07 23:26:04.000000000 +0000
+++ linux-2.4.28-pre3/drivers/ide/Config.in	2004-09-10 19:36:49.000000000 +0000
@@ -12,6 +12,7 @@ if [ "$CONFIG_BLK_DEV_IDE" != "n" ]; the
    dep_bool '  Use old disk-only driver on primary interface' CONFIG_BLK_DEV_HD_IDE $CONFIG_X86
    define_bool CONFIG_BLK_DEV_HD $CONFIG_BLK_DEV_HD_IDE
 
+   dep_mbool '  Support for SATA (deprecated; conflicts with libata SATA driver)' CONFIG_BLK_DEV_IDE_SATA $CONFIG_BLK_DEV_IDE
    dep_tristate '  Include IDE/ATA-2 DISK support' CONFIG_BLK_DEV_IDEDISK $CONFIG_BLK_DEV_IDE
    dep_mbool '    Use multi-mode by default' CONFIG_IDEDISK_MULTI_MODE $CONFIG_BLK_DEV_IDEDISK
    dep_mbool '    Auto-Geometry Resizing support' CONFIG_IDEDISK_STROKE $CONFIG_BLK_DEV_IDEDISK
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/ide/pci/amd74xx.c linux-2.4.28-pre3/drivers/ide/pci/amd74xx.c
--- linux-2.4.27/drivers/ide/pci/amd74xx.c	2004-08-07 23:26:04.000000000 +0000
+++ linux-2.4.28-pre3/drivers/ide/pci/amd74xx.c	2004-09-10 19:35:20.000000000 +0000
@@ -70,11 +70,7 @@ static struct amd_ide_chip {
 	{ PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA,	0x50, AMD_UDMA_133 },
 	{ PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA2,	0x50, AMD_UDMA_133 },
 	{ PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_IDE,	0x50, AMD_UDMA_133 },
-	{ PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_SATA,	0x50, AMD_UDMA_133 },
-	{ PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_SATA2,	0x50, AMD_UDMA_133 },
 	{ PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_IDE,	0x50, AMD_UDMA_133 },
-	{ PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_SATA,	0x50, AMD_UDMA_133 },
-	{ PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_SATA2,	0x50, AMD_UDMA_133 },
 	{ 0 }
 };
 
@@ -466,17 +462,17 @@ static struct pci_device_id amd74xx_pci_
 	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_IDE,	PCI_ANY_ID, PCI_ANY_ID, 0, 0,  5 },
 	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE2_IDE,	PCI_ANY_ID, PCI_ANY_ID, 0, 0,  6 },
 	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE2S_IDE,	PCI_ANY_ID, PCI_ANY_ID, 0, 0,  7 },
+#ifdef CONFIG_BLK_DEV_IDE_SATA
 	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE2S_SATA,	PCI_ANY_ID, PCI_ANY_ID, 0, 0,  8 },
+#endif
 	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE3_IDE,	PCI_ANY_ID, PCI_ANY_ID, 0, 0,  9 },
 	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE3S_IDE,	PCI_ANY_ID, PCI_ANY_ID, 0, 0, 10 },
+#ifdef CONFIG_BLK_DEV_IDE_SATA
 	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA,	PCI_ANY_ID, PCI_ANY_ID, 0, 0, 11 },
 	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA2,	PCI_ANY_ID, PCI_ANY_ID, 0, 0, 12 },
+#endif
 	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_IDE,	PCI_ANY_ID, PCI_ANY_ID, 0, 0, 13 },
-	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_SATA,	PCI_ANY_ID, PCI_ANY_ID, 0, 0, 14 },
-	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_SATA2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 15 },
-	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_IDE,	PCI_ANY_ID, PCI_ANY_ID, 0, 0, 16 },
-	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_SATA,	PCI_ANY_ID, PCI_ANY_ID, 0, 0, 17 },
-	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_SATA2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 18 },
+	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_IDE,	PCI_ANY_ID, PCI_ANY_ID, 0, 0, 14 },
 	{ 0, },
 };
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/ide/pci/amd74xx.h linux-2.4.28-pre3/drivers/ide/pci/amd74xx.h
--- linux-2.4.27/drivers/ide/pci/amd74xx.h	2004-08-07 23:26:04.000000000 +0000
+++ linux-2.4.28-pre3/drivers/ide/pci/amd74xx.h	2004-09-10 19:36:48.000000000 +0000
@@ -188,28 +188,6 @@ static ide_pci_device_t amd74xx_chipsets
 	},
 	{	/* 14 */
 		.vendor		= PCI_VENDOR_ID_NVIDIA,
-		.device		= PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_SATA,
-		.name		= "NFORCE-CK804-SATA",
-		.init_chipset	= init_chipset_amd74xx,
-		.init_hwif	= init_hwif_amd74xx,
-		.channels	= 2,
-		.autodma	= AUTODMA,
-		.enablebits	= {{0x50,0x02,0x02}, {0x50,0x01,0x01}},
-		.bootable	= ON_BOARD,
-	},
-	{	/* 15 */
-		.vendor		= PCI_VENDOR_ID_NVIDIA,
-		.device		= PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_SATA2,
-		.name		= "NFORCE-CK804-SATA2",
-		.init_chipset	= init_chipset_amd74xx,
-		.init_hwif	= init_hwif_amd74xx,
-		.channels	= 2,
-		.autodma	= AUTODMA,
-		.enablebits	= {{0x50,0x02,0x02}, {0x50,0x01,0x01}},
-		.bootable	= ON_BOARD,
-	},
-	{	/* 16 */
-		.vendor		= PCI_VENDOR_ID_NVIDIA,
 		.device		= PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_IDE,
 		.name		= "NFORCE-MCP04",
 		.init_chipset	= init_chipset_amd74xx,
@@ -219,28 +197,6 @@ static ide_pci_device_t amd74xx_chipsets
 		.enablebits	= {{0x50,0x02,0x02}, {0x50,0x01,0x01}},
 		.bootable	= ON_BOARD,
 	},
-	{	/* 17 */
-		.vendor		= PCI_VENDOR_ID_NVIDIA,
-		.device		= PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_SATA,
-		.name		= "NFORCE-MCP04-SATA",
-		.init_chipset	= init_chipset_amd74xx,
-		.init_hwif	= init_hwif_amd74xx,
-		.channels	= 2,
-		.autodma	= AUTODMA,
-		.enablebits	= {{0x50,0x02,0x02}, {0x50,0x01,0x01}},
-		.bootable	= ON_BOARD,
-	},
-	{	/* 18 */
-		.vendor		= PCI_VENDOR_ID_NVIDIA,
-		.device		= PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_SATA2,
-		.name		= "NFORCE-MCP04-SATA2",
-		.init_chipset	= init_chipset_amd74xx,
-		.init_hwif	= init_hwif_amd74xx,
-		.channels	= 2,
-		.autodma	= AUTODMA,
-		.enablebits	= {{0x50,0x02,0x02}, {0x50,0x01,0x01}},
-		.bootable	= ON_BOARD,
-	},
 	{
 		.vendor		= 0,
 		.device		= 0,
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/ide/pci/piix.c linux-2.4.28-pre3/drivers/ide/pci/piix.c
--- linux-2.4.27/drivers/ide/pci/piix.c	2004-08-07 23:26:04.000000000 +0000
+++ linux-2.4.28-pre3/drivers/ide/pci/piix.c	2004-09-10 19:36:56.000000000 +0000
@@ -49,9 +49,9 @@
  * pci_read_config_word(HWIF(drive)->pci_dev, 0x40, &reg40);
  * pci_read_config_word(HWIF(drive)->pci_dev, 0x42, &reg42);
  * pci_read_config_word(HWIF(drive)->pci_dev, 0x44, &reg44);
- * pci_read_config_word(HWIF(drive)->pci_dev, 0x48, &reg48);
+ * pci_read_config_byte(HWIF(drive)->pci_dev, 0x48, &reg48);
  * pci_read_config_word(HWIF(drive)->pci_dev, 0x4a, &reg4a);
- * pci_read_config_word(HWIF(drive)->pci_dev, 0x54, &reg54);
+ * pci_read_config_byte(HWIF(drive)->pci_dev, 0x54, &reg54);
  *
  * Documentation
  *	Publically available from Intel web site. Errata documentation
@@ -433,15 +433,14 @@ static int piix_tune_chipset (ide_drive_
 	int w_flag		= 0x10 << drive->dn;
 	int u_speed		= 0;
 	int			sitre;
-	u16			reg4042, reg44, reg48, reg4a, reg54;
-	u8			reg55;
+	u16			reg4042, reg4a;
+	u8			reg48, reg54, reg55;
 
 	pci_read_config_word(dev, maslave, &reg4042);
 	sitre = (reg4042 & 0x4000) ? 1 : 0;
-	pci_read_config_word(dev, 0x44, &reg44);
-	pci_read_config_word(dev, 0x48, &reg48);
+	pci_read_config_byte(dev, 0x48, &reg48);
 	pci_read_config_word(dev, 0x4a, &reg4a);
-	pci_read_config_word(dev, 0x54, &reg54);
+	pci_read_config_byte(dev, 0x54, &reg54);
 	pci_read_config_byte(dev, 0x55, &reg55);
 
 	switch(speed) {
@@ -463,30 +462,26 @@ static int piix_tune_chipset (ide_drive_
 
 	if (speed >= XFER_UDMA_0) {
 		if (!(reg48 & u_flag))
-			pci_write_config_word(dev, 0x48, reg48|u_flag);
+			pci_write_config_byte(dev, 0x48, reg48 | u_flag);
 		if (speed == XFER_UDMA_5) {
 			pci_write_config_byte(dev, 0x55, (u8) reg55|w_flag);
 		} else {
 			pci_write_config_byte(dev, 0x55, (u8) reg55 & ~w_flag);
 		}
-		if (!(reg4a & u_speed)) {
-			pci_write_config_word(dev, 0x4a, reg4a & ~a_speed);
-			pci_write_config_word(dev, 0x4a, reg4a|u_speed);
-		}
+		if ((reg4a & a_speed) != u_speed)
+			pci_write_config_word(dev, 0x4a, (reg4a & ~a_speed) | u_speed);
 		if (speed > XFER_UDMA_2) {
-			if (!(reg54 & v_flag)) {
-				pci_write_config_word(dev, 0x54, reg54|v_flag);
-			}
-		} else {
-			pci_write_config_word(dev, 0x54, reg54 & ~v_flag);
-		}
+			if (!(reg54 & v_flag))
+				pci_write_config_byte(dev, 0x54, reg54 | v_flag);
+		} else
+			pci_write_config_byte(dev, 0x54, reg54 & ~v_flag);
 	} else {
 		if (reg48 & u_flag)
-			pci_write_config_word(dev, 0x48, reg48 & ~u_flag);
+			pci_write_config_byte(dev, 0x48, reg48 & ~u_flag);
 		if (reg4a & a_speed)
 			pci_write_config_word(dev, 0x4a, reg4a & ~a_speed);
 		if (reg54 & v_flag)
-			pci_write_config_word(dev, 0x54, reg54 & ~v_flag);
+			pci_write_config_byte(dev, 0x54, reg54 & ~v_flag);
 		if (reg55 & w_flag)
 			pci_write_config_byte(dev, 0x55, (u8) reg55 & ~w_flag);
 	}
@@ -882,7 +877,9 @@ static struct pci_device_id piix_pci_tbl
 	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_11,PCI_ANY_ID, PCI_ANY_ID, 0, 0, 15},
 	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801E_11, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 16},
 	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_10,PCI_ANY_ID, PCI_ANY_ID, 0, 0, 17},
+#ifdef CONFIG_BLK_DEV_IDE_SATA
  	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 18},
+#endif
 	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB_2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 19},
 	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 20},
 	{ 0, },
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/ide/pci/sc1200.c linux-2.4.28-pre3/drivers/ide/pci/sc1200.c
--- linux-2.4.27/drivers/ide/pci/sc1200.c	2003-06-13 14:51:33.000000000 +0000
+++ linux-2.4.28-pre3/drivers/ide/pci/sc1200.c	2004-09-10 19:35:31.000000000 +0000
@@ -418,7 +418,7 @@ printk("SC1200: save_state(%u)\n", state
 			ss = kmalloc(sizeof(sc1200_saved_state_t), GFP_KERNEL);
 			if (ss == NULL)
 				return -ENOMEM;
-			(sc1200_saved_state_t *)hwif->config_data = ss;
+			hwif->config_data = (unsigned long)ss;
 		}
 		ss = (sc1200_saved_state_t *)hwif->config_data;
 		//
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/ide/pci/siimage.c linux-2.4.28-pre3/drivers/ide/pci/siimage.c
--- linux-2.4.27/drivers/ide/pci/siimage.c	2004-08-07 23:26:04.000000000 +0000
+++ linux-2.4.28-pre3/drivers/ide/pci/siimage.c	2004-09-10 19:36:30.000000000 +0000
@@ -1194,8 +1194,10 @@ static int __devinit siimage_init_one(st
 
 static struct pci_device_id siimage_pci_tbl[] __devinitdata = {
 	{ PCI_VENDOR_ID_CMD, PCI_DEVICE_ID_SII_680,  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+#ifdef CONFIG_BLK_DEV_IDE_SATA
 	{ PCI_VENDOR_ID_CMD, PCI_DEVICE_ID_SII_3112, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1},
 	{ PCI_VENDOR_ID_CMD, PCI_DEVICE_ID_SII_1210SA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 2},
+#endif
 	{ 0, },
 };
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/ide/pci/triflex.c linux-2.4.28-pre3/drivers/ide/pci/triflex.c
--- linux-2.4.27/drivers/ide/pci/triflex.c	2003-06-13 14:51:33.000000000 +0000
+++ linux-2.4.28-pre3/drivers/ide/pci/triflex.c	2004-09-10 19:34:15.000000000 +0000
@@ -44,15 +44,17 @@
 #include "ide_modes.h"
 #include "triflex.h"
 
-static struct pci_dev *triflex_dev;
+#ifdef CONFIG_PROC_FS
+static u8 triflex_proc;
 
-static int triflex_get_info(char *buf, char **addr, off_t offset, int count)
-{
-	char *p = buf;
-	int len;
+#define TRIFLEX_MAX_DEVS	2
+static struct pci_dev *triflex_devs[TRIFLEX_MAX_DEVS];
+static unsigned int n_triflex_devs;
 
-	struct pci_dev *dev	= triflex_dev;
+static int triflex_info(char *buffer, struct pci_dev *dev)
+{
 	unsigned long bibma = pci_resource_start(dev, 4);
+	char *p = buffer;
 	u8  c0 = 0, c1 = 0;
 	u32 pri_timing, sec_timing;
 
@@ -87,11 +89,23 @@ static int triflex_get_info(char *buf, c
 	p += sprintf(p, "DMA\n");
 	p += sprintf(p, "PIO\n");
 
+	return p - buffer;
+}
+
+static int triflex_get_info(char *buf, char **addr, off_t offset, int count)
+{
+	char *p = buf;
+	unsigned int i, len;
+
+	for (i = 0; i < n_triflex_devs; i++)
+		buf += triflex_info(buf, triflex_devs[i]);
+
 	len = (p - buf) - offset;
 	*addr = buf + offset;
-	
+
 	return len > count ? count : len;
 }
+#endif
 
 static int triflex_tune_chipset(ide_drive_t *drive, u8 xferspeed)
 {
@@ -211,9 +225,13 @@ static unsigned int __init init_chipset_
 		const char *name) 
 {
 #ifdef CONFIG_PROC_FS
-	ide_pci_register_host_proc(&triflex_proc);
+	triflex_devs[n_triflex_devs++] = dev;
+	if (!triflex_proc) {
+		triflex_proc = 1;
+		ide_pci_register_host_proc(&triflex_procs);
+	}
 #endif
-	return 0;	
+	return 0;
 }
 
 static int __devinit triflex_init_one(struct pci_dev *dev, 
@@ -222,11 +240,10 @@ static int __devinit triflex_init_one(st
 	ide_pci_device_t *d = &triflex_devices[id->driver_data];
 	if (dev->device != d->device)
 		BUG();
-	
+
 	ide_setup_pci_device(dev, d);
-	triflex_dev = dev;
 	MOD_INC_USE_COUNT;
-	
+
 	return 0;
 }
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/ide/pci/triflex.h linux-2.4.28-pre3/drivers/ide/pci/triflex.h
--- linux-2.4.27/drivers/ide/pci/triflex.h	2003-06-13 14:51:33.000000000 +0000
+++ linux-2.4.28-pre3/drivers/ide/pci/triflex.h	2004-09-10 19:35:32.000000000 +0000
@@ -14,7 +14,6 @@
 
 static unsigned int __devinit init_chipset_triflex(struct pci_dev *, const char *);
 static void init_hwif_triflex(ide_hwif_t *);
-static int triflex_get_info(char *, char **, off_t, int);
 
 static ide_pci_device_t triflex_devices[] __devinitdata = {
 	{
@@ -34,7 +33,9 @@ static ide_pci_device_t triflex_devices[
 };
 
 #ifdef CONFIG_PROC_FS
-static ide_pci_host_proc_t triflex_proc __initdata = {
+static int triflex_get_info(char *, char **, off_t, int);
+
+static ide_pci_host_proc_t triflex_procs __initdata = {
 	.name		= "triflex",
 	.set		= 1,
 	.get_info 	= triflex_get_info,
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/ieee1394/eth1394.c linux-2.4.28-pre3/drivers/ieee1394/eth1394.c
--- linux-2.4.27/drivers/ieee1394/eth1394.c	2003-11-28 18:26:20.000000000 +0000
+++ linux-2.4.28-pre3/drivers/ieee1394/eth1394.c	2004-09-10 19:36:19.000000000 +0000
@@ -149,6 +149,20 @@ MODULE_PARM_DESC(max_partial_datagrams,
 		 "(default = 25).");
 static int max_partial_datagrams = 25;
 
+static inline void purge_partial_datagram(struct list_head *old)
+{
+	struct partial_datagram *pd = list_entry(old, struct partial_datagram, list);
+	struct list_head *lh, *n;
+
+	list_for_each_safe(lh, n, &pd->frag_info) {
+		struct fragment_info *fi = list_entry(lh, struct fragment_info, list);
+		list_del(lh);
+		kfree(fi);
+	}
+	list_del(old);
+	kfree_skb(pd->skb);
+	kfree(pd);
+}
 
 static int ether1394_header(struct sk_buff *skb, struct net_device *dev,
 			    unsigned short type, void *daddr, void *saddr,
@@ -885,21 +899,6 @@ static inline int update_partial_datagra
 	return 0;
 }
 
-static inline void purge_partial_datagram(struct list_head *old)
-{
-	struct partial_datagram *pd = list_entry(old, struct partial_datagram, list);
-	struct list_head *lh, *n;
-
-	list_for_each_safe(lh, n, &pd->frag_info) {
-		struct fragment_info *fi = list_entry(lh, struct fragment_info, list);
-		list_del(lh);
-		kfree(fi);
-	}
-	list_del(old);
-	kfree_skb(pd->skb);
-	kfree(pd);
-}
-
 static inline int is_datagram_complete(struct list_head *lh, int dg_size)
 {
 	struct partial_datagram *pd = list_entry(lh, struct partial_datagram, list);
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/isdn/divert/divert_procfs.c linux-2.4.28-pre3/drivers/isdn/divert/divert_procfs.c
--- linux-2.4.27/drivers/isdn/divert/divert_procfs.c	2004-08-07 23:26:04.000000000 +0000
+++ linux-2.4.28-pre3/drivers/isdn/divert/divert_procfs.c	2004-09-10 19:36:55.000000000 +0000
@@ -92,7 +92,7 @@ isdn_divert_read(struct file *file, char
 		return (0);
 
 	inf->usage_cnt--;	/* new usage count */
-	(struct divert_info **) file->private_data = &inf->next;	/* next structure */
+	file->private_data = &inf->next;	/* next structure */
 	if ((len = strlen(inf->info_start)) <= count) {
 		if (copy_to_user(buf, inf->info_start, len))
 			return -EFAULT;
@@ -141,9 +141,9 @@ isdn_divert_open(struct inode *ino, stru
 	cli();
 	if_used++;
 	if (divert_info_head)
-		(struct divert_info **) filep->private_data = &(divert_info_tail->next);
+		filep->private_data = &(divert_info_tail->next);
 	else
-		(struct divert_info **) filep->private_data = &divert_info_head;
+		filep->private_data = &divert_info_head;
 	restore_flags(flags);
 	/*  start_divert(); */
 	unlock_kernel();
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/isdn/hisax/callc.c linux-2.4.28-pre3/drivers/isdn/hisax/callc.c
--- linux-2.4.27/drivers/isdn/hisax/callc.c	2001-12-21 17:41:54.000000000 +0000
+++ linux-2.4.28-pre3/drivers/isdn/hisax/callc.c	2004-09-10 19:34:58.000000000 +0000
@@ -925,7 +925,7 @@ static void stat_redir_result(struct Isd
 	ic.driver = cs->myid;
 	ic.command = ISDN_STAT_REDIR;
 	ic.arg = chan; 
-	(ulong)(ic.parm.num[0]) = result;
+	ic.parm.num[0] = result;
 	cs->iif.statcallb(&ic);
 } /* stat_redir_result */
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/isdn/hisax/isar.c linux-2.4.28-pre3/drivers/isdn/hisax/isar.c
--- linux-2.4.27/drivers/isdn/hisax/isar.c	2003-06-13 14:51:34.000000000 +0000
+++ linux-2.4.28-pre3/drivers/isdn/hisax/isar.c	2004-09-10 19:34:22.000000000 +0000
@@ -428,6 +428,21 @@ reterror:
 	return(ret);
 }
 
+static inline void
+ll_deliver_faxstat(struct BCState *bcs, u_char status)
+{
+        isdn_ctrl ic;
+	struct Channel *chanp = (struct Channel *) bcs->st->lli.userdata;
+ 
+	if (bcs->cs->debug & L1_DEB_HSCX)
+		debugl1(bcs->cs, "HL->LL FAXIND %x", status);
+	ic.driver = bcs->cs->myid;
+	ic.command = ISDN_STAT_FAXIND;
+	ic.arg = chanp->chan;
+	ic.parm.aux.cmd = status;
+	bcs->cs->iif.statcallb(&ic);
+}
+
 extern void BChannel_bh(struct BCState *);
 #define B_LL_NOCARRIER	8
 #define B_LL_CONNECT	9
@@ -962,21 +977,6 @@ isar_pump_statev_modem(struct BCState *b
 	}
 }
 
-static inline void
-ll_deliver_faxstat(struct BCState *bcs, u_char status)
-{
-        isdn_ctrl ic;
-	struct Channel *chanp = (struct Channel *) bcs->st->lli.userdata;
- 
-	if (bcs->cs->debug & L1_DEB_HSCX)
-		debugl1(bcs->cs, "HL->LL FAXIND %x", status);
-	ic.driver = bcs->cs->myid;
-	ic.command = ISDN_STAT_FAXIND;
-	ic.arg = chanp->chan;
-	ic.parm.aux.cmd = status;
-	bcs->cs->iif.statcallb(&ic);
-}
-
 static void
 isar_pump_statev_fax(struct BCState *bcs, u_char devt) {
 	struct IsdnCardState *cs = bcs->cs;
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/isdn/hisax/st5481.h linux-2.4.28-pre3/drivers/isdn/hisax/st5481.h
--- linux-2.4.27/drivers/isdn/hisax/st5481.h	2003-06-13 14:51:34.000000000 +0000
+++ linux-2.4.28-pre3/drivers/isdn/hisax/st5481.h	2004-09-10 19:35:46.000000000 +0000
@@ -219,13 +219,13 @@ enum {
 #define L1_EVENT_COUNT (EV_TIMER3 + 1)
 
 #define ERR(format, arg...) \
-printk(KERN_ERR __FILE__ ": " __FUNCTION__ ": " format "\n" , ## arg)
+printk(KERN_ERR "%s:%s: " format "\n" , __FILE__,  __FUNCTION__ , ## arg)
 
 #define WARN(format, arg...) \
-printk(KERN_WARNING __FILE__ ": " __FUNCTION__ ": " format "\n" , ## arg)
+printk(KERN_WARNING "%s:%s: " format "\n" , __FILE__,  __FUNCTION__ , ## arg)
 
 #define INFO(format, arg...) \
-printk(KERN_INFO __FILE__ ": " __FUNCTION__ ": " format "\n" , ## arg)
+printk(KERN_INFO "%s:%s: " format "\n" , __FILE__,  __FUNCTION__ , ## arg)
 
 #include "isdnhdlc.h"
 #include "fsm.h"
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/isdn/hysdn/hysdn_procconf.c linux-2.4.28-pre3/drivers/isdn/hysdn/hysdn_procconf.c
--- linux-2.4.27/drivers/isdn/hysdn/hysdn_procconf.c	2004-08-07 23:26:04.000000000 +0000
+++ linux-2.4.28-pre3/drivers/isdn/hysdn/hysdn_procconf.c	2004-09-10 19:32:47.000000000 +0000
@@ -219,20 +219,25 @@ hysdn_conf_read(struct file *file, char 
 	if (off != &file->f_pos)	/* fs error check */
 		return -ESPIPE;
 
+	if (!(file->f_mode & FMODE_READ))
+		return -EPERM;
+
 	if (!(cp = file->private_data))
 		return (-EFAULT);	/* should never happen */
+
 	i = strlen(cp);	/* get total string length */
-	if (pos == (unsigned)pos && pos < i) {
-		/* still bytes to transfer */
-		cp += pos;	/* point to desired data offset */
-		i -= pos;	/* remaining length */
-		if (i > count)
-			i = count;	/* limit length to transfer */
-		if (copy_to_user(buf, cp, i))
-			return (-EFAULT);	/* copy error */
-		*off = pos + i;	/* adjust offset */
-	} else
-		return (0);
+
+	if (pos != (unsigned)pos || pos >= i)
+		return 0;
+
+	/* still bytes to transfer */
+	cp += pos;	/* point to desired data offset */
+	i -= pos;	/* remaining length */
+	if (i > count)
+		i = count;	/* limit length to transfer */
+	if (copy_to_user(buf, cp, i))
+		return (-EFAULT);	/* copy error */
+	*off = pos + i;	/* adjust offset */
 
 	return (i);
 }				/* hysdn_conf_read */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/isdn/pcbit/callbacks.c linux-2.4.28-pre3/drivers/isdn/pcbit/callbacks.c
--- linux-2.4.27/drivers/isdn/pcbit/callbacks.c	2001-09-30 19:26:06.000000000 +0000
+++ linux-2.4.28-pre3/drivers/isdn/pcbit/callbacks.c	2004-09-10 19:37:19.000000000 +0000
@@ -3,7 +3,7 @@
  *
  * Copyright (C) 1996 Universidade de Lisboa
  * 
- * Written by Pedro Roque Marques (roque@di.fc.ul.pt)
+ * Written by Pedro Roque Marques (pedro_m@yahoo.com)
  *
  * This software may be used and distributed according to the terms of 
  * the GNU General Public License, incorporated herein by reference.
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/isdn/pcbit/callbacks.h linux-2.4.28-pre3/drivers/isdn/pcbit/callbacks.h
--- linux-2.4.27/drivers/isdn/pcbit/callbacks.h	2001-09-30 19:26:06.000000000 +0000
+++ linux-2.4.28-pre3/drivers/isdn/pcbit/callbacks.h	2004-09-10 19:31:51.000000000 +0000
@@ -3,7 +3,7 @@
  *
  * Copyright (C) 1996 Universidade de Lisboa
  * 
- * Written by Pedro Roque Marques (roque@di.fc.ul.pt)
+ * Written by Pedro Roque Marques (pedro_m@yahoo.com)
  *
  * This software may be used and distributed according to the terms of 
  * the GNU General Public License, incorporated herein by reference.
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/isdn/pcbit/capi.c linux-2.4.28-pre3/drivers/isdn/pcbit/capi.c
--- linux-2.4.27/drivers/isdn/pcbit/capi.c	2001-09-30 19:26:06.000000000 +0000
+++ linux-2.4.28-pre3/drivers/isdn/pcbit/capi.c	2004-09-10 19:36:03.000000000 +0000
@@ -4,7 +4,7 @@
  *
  * Copyright (C) 1996 Universidade de Lisboa
  * 
- * Written by Pedro Roque Marques (roque@di.fc.ul.pt)
+ * Written by Pedro Roque Marques (pedro_m@yahoo.com)
  *
  * This software may be used and distributed according to the terms of 
  * the GNU General Public License, incorporated herein by reference.
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/isdn/pcbit/capi.h linux-2.4.28-pre3/drivers/isdn/pcbit/capi.h
--- linux-2.4.27/drivers/isdn/pcbit/capi.h	2002-08-03 00:39:44.000000000 +0000
+++ linux-2.4.28-pre3/drivers/isdn/pcbit/capi.h	2004-09-10 19:36:50.000000000 +0000
@@ -3,7 +3,7 @@
  *
  * Copyright (C) 1996 Universidade de Lisboa
  * 
- * Written by Pedro Roque Marques (roque@di.fc.ul.pt)
+ * Written by Pedro Roque Marques (pedro_m@yahoo.com)
  *
  * This software may be used and distributed according to the terms of 
  * the GNU General Public License, incorporated herein by reference.
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/isdn/pcbit/drv.c linux-2.4.28-pre3/drivers/isdn/pcbit/drv.c
--- linux-2.4.27/drivers/isdn/pcbit/drv.c	2002-11-28 23:53:13.000000000 +0000
+++ linux-2.4.28-pre3/drivers/isdn/pcbit/drv.c	2004-09-10 19:36:02.000000000 +0000
@@ -3,7 +3,7 @@
  *
  * Copyright (C) 1996 Universidade de Lisboa
  * 
- * Written by Pedro Roque Marques (roque@di.fc.ul.pt)
+ * Written by Pedro Roque Marques (pedro_m@yahoo.com)
  *
  * This software may be used and distributed according to the terms of 
  * the GNU General Public License, incorporated herein by reference.
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/isdn/pcbit/edss1.c linux-2.4.28-pre3/drivers/isdn/pcbit/edss1.c
--- linux-2.4.27/drivers/isdn/pcbit/edss1.c	2001-09-30 19:26:06.000000000 +0000
+++ linux-2.4.28-pre3/drivers/isdn/pcbit/edss1.c	2004-09-10 19:32:27.000000000 +0000
@@ -4,7 +4,7 @@
  *
  * Copyright (C) 1996 Universidade de Lisboa
  * 
- * Written by Pedro Roque Marques (roque@di.fc.ul.pt)
+ * Written by Pedro Roque Marques (pedro_m@yahoo.com)
  *
  * This software may be used and distributed according to the terms of 
  * the GNU General Public License, incorporated herein by reference.
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/isdn/pcbit/edss1.h linux-2.4.28-pre3/drivers/isdn/pcbit/edss1.h
--- linux-2.4.27/drivers/isdn/pcbit/edss1.h	2001-09-30 19:26:06.000000000 +0000
+++ linux-2.4.28-pre3/drivers/isdn/pcbit/edss1.h	2004-09-10 19:33:22.000000000 +0000
@@ -3,7 +3,7 @@
  *
  * Copyright (C) 1996 Universidade de Lisboa
  * 
- * Written by Pedro Roque Marques (roque@di.fc.ul.pt)
+ * Written by Pedro Roque Marques (pedro_m@yahoo.com)
  *
  * This software may be used and distributed according to the terms of 
  * the GNU General Public License, incorporated herein by reference.
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/isdn/pcbit/layer2.c linux-2.4.28-pre3/drivers/isdn/pcbit/layer2.c
--- linux-2.4.27/drivers/isdn/pcbit/layer2.c	2001-09-30 19:26:06.000000000 +0000
+++ linux-2.4.28-pre3/drivers/isdn/pcbit/layer2.c	2004-09-10 19:36:06.000000000 +0000
@@ -3,7 +3,7 @@
  *
  * Copyright (C) 1996 Universidade de Lisboa
  *
- * Written by Pedro Roque Marques (roque@di.fc.ul.pt)
+ * Written by Pedro Roque Marques (pedro_m@yahoo.com)
  *
  * This software may be used and distributed according to the terms of
  * the GNU General Public License, incorporated herein by reference.
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/isdn/pcbit/layer2.h linux-2.4.28-pre3/drivers/isdn/pcbit/layer2.h
--- linux-2.4.27/drivers/isdn/pcbit/layer2.h	2001-09-30 19:26:06.000000000 +0000
+++ linux-2.4.28-pre3/drivers/isdn/pcbit/layer2.h	2004-09-10 19:32:40.000000000 +0000
@@ -3,7 +3,7 @@
  *
  * Copyright (C) 1996 Universidade de Lisboa
  * 
- * Written by Pedro Roque Marques (roque@di.fc.ul.pt)
+ * Written by Pedro Roque Marques (pedro_m@yahoo.com)
  *
  * This software may be used and distributed according to the terms of 
  * the GNU General Public License, incorporated herein by reference.
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/isdn/pcbit/module.c linux-2.4.28-pre3/drivers/isdn/pcbit/module.c
--- linux-2.4.27/drivers/isdn/pcbit/module.c	2001-09-30 19:26:06.000000000 +0000
+++ linux-2.4.28-pre3/drivers/isdn/pcbit/module.c	2004-09-10 19:35:42.000000000 +0000
@@ -3,7 +3,7 @@
  *
  * Copyright (C) 1996 Universidade de Lisboa
  * 
- * Written by Pedro Roque Marques (roque@di.fc.ul.pt)
+ * Written by Pedro Roque Marques (pedro_m@yahoo.com)
  *
  * This software may be used and distributed according to the terms of 
  * the GNU General Public License, incorporated herein by reference.
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/isdn/pcbit/pcbit.h linux-2.4.28-pre3/drivers/isdn/pcbit/pcbit.h
--- linux-2.4.27/drivers/isdn/pcbit/pcbit.h	2001-09-30 19:26:06.000000000 +0000
+++ linux-2.4.28-pre3/drivers/isdn/pcbit/pcbit.h	2004-09-10 19:32:38.000000000 +0000
@@ -3,7 +3,7 @@
  *
  * Copyright (C) 1996 Universidade de Lisboa
  * 
- * Written by Pedro Roque Marques (roque@di.fc.ul.pt)
+ * Written by Pedro Roque Marques (pedro_m@yahoo.com)
  *
  * This software may be used and distributed according to the terms of 
  * the GNU General Public License, incorporated herein by reference.
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/md/lvm.c linux-2.4.28-pre3/drivers/md/lvm.c
--- linux-2.4.27/drivers/md/lvm.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.28-pre3/drivers/md/lvm.c	2004-09-10 19:35:28.000000000 +0000
@@ -2689,6 +2689,10 @@ static int lvm_do_lv_status_byname(vg_t 
 			    (&lv_status_byname_req.lv->lv_current_pe,
 			     &saved_ptr1, sizeof(void *)) != 0)
 				return -EFAULT;
+			if (copy_to_user
+			    (&lv_status_byname_req.lv->lv_block_exception,
+			     &saved_ptr2, sizeof(void *)) != 0)
+				return -EFAULT;
 			return 0;
 		}
 	}
@@ -2743,6 +2747,10 @@ static int lvm_do_lv_status_byindex(vg_t
 	    (&lv_status_byindex_req.lv->lv_current_pe, &saved_ptr1,
 	     sizeof(void *)) != 0)
 		return -EFAULT;
+	if (copy_to_user
+	    (&lv_status_byindex_req.lv->lv_block_exception, &saved_ptr2,
+	     sizeof(void *)) != 0)
+		return -EFAULT;
 
 	return 0;
 }				/* lvm_do_lv_status_byindex() */
@@ -2801,6 +2809,10 @@ static int lvm_do_lv_status_bydev(vg_t *
 	    (&lv_status_bydev_req.lv->lv_current_pe, &saved_ptr1,
 	     sizeof(void *)) != 0)
 		return -EFAULT;
+	if (copy_to_user
+	    (&lv_status_bydev_req.lv->lv_block_exception, &saved_ptr2,
+	     sizeof(void *)) != 0)
+		return -EFAULT;
 
 	return 0;
 }				/* lvm_do_lv_status_bydev() */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/media/radio/radio-maestro.c linux-2.4.28-pre3/drivers/media/radio/radio-maestro.c
--- linux-2.4.27/drivers/media/radio/radio-maestro.c	2001-09-30 19:26:06.000000000 +0000
+++ linux-2.4.28-pre3/drivers/media/radio/radio-maestro.c	2004-09-10 19:35:29.000000000 +0000
@@ -307,30 +307,6 @@ void __exit maestro_radio_exit(void)
 	video_unregister_device(&maestro_radio);
 }
 
-int __init maestro_radio_init(void)
-{
-	register __u16 found=0;
-	struct pci_dev *pcidev = NULL;
-	if(!pci_present())
-		return -ENODEV;
-	while(!found && (pcidev = pci_find_device(PCI_VENDOR_ESS, 
-						  PCI_DEVICE_ID_ESS_ESS1968,
-						  pcidev)))
-		found |= radio_install(pcidev);
-	while(!found && (pcidev = pci_find_device(PCI_VENDOR_ESS,
-						  PCI_DEVICE_ID_ESS_ESS1978, 
-						  pcidev)))
-		found |= radio_install(pcidev);
-	if(!found) {
-		printk(KERN_INFO "radio-maestro: no devices found.\n");
-		return -ENODEV;
-	}
-	return 0;
-}
-
-module_init(maestro_radio_init);
-module_exit(maestro_radio_exit);
-
 inline static __u16 radio_power_on(struct radio_device *dev)
 {
 	register __u16 io=dev->io;
@@ -378,3 +354,27 @@ inline static __u16 radio_install(struct
 		return 0;   
 }
 
+int __init maestro_radio_init(void)
+{
+	register __u16 found=0;
+	struct pci_dev *pcidev = NULL;
+	if(!pci_present())
+		return -ENODEV;
+	while(!found && (pcidev = pci_find_device(PCI_VENDOR_ESS, 
+						  PCI_DEVICE_ID_ESS_ESS1968,
+						  pcidev)))
+		found |= radio_install(pcidev);
+	while(!found && (pcidev = pci_find_device(PCI_VENDOR_ESS,
+						  PCI_DEVICE_ID_ESS_ESS1978, 
+						  pcidev)))
+		found |= radio_install(pcidev);
+	if(!found) {
+		printk(KERN_INFO "radio-maestro: no devices found.\n");
+		return -ENODEV;
+	}
+	return 0;
+}
+
+module_init(maestro_radio_init);
+module_exit(maestro_radio_exit);
+
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/media/video/bttv-driver.c linux-2.4.28-pre3/drivers/media/video/bttv-driver.c
--- linux-2.4.27/drivers/media/video/bttv-driver.c	2003-11-28 18:26:20.000000000 +0000
+++ linux-2.4.28-pre3/drivers/media/video/bttv-driver.c	2004-09-10 19:36:12.000000000 +0000
@@ -558,7 +558,7 @@ static struct tvnorm tvnorms[] = {
 		.sram           = -1,
 	},{
 		/* PAL-N */
-		.Fsc             35468950,
+		.Fsc            = 35468950,
 		.swidth         = 768,
 		.sheight        = 576,
 		.totalwidth     = 1135,
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/media/video/w9966.c linux-2.4.28-pre3/drivers/media/video/w9966.c
--- linux-2.4.27/drivers/media/video/w9966.c	2003-06-13 14:51:34.000000000 +0000
+++ linux-2.4.28-pre3/drivers/media/video/w9966.c	2004-09-10 19:33:19.000000000 +0000
@@ -691,6 +691,14 @@ static inline void w9966_i2c_setsda(stru
 	udelay(W9966_I2C_UDELAY);
 }
 
+// Get peripheral clock line
+// Expects a claimed pdev.
+static inline int w9966_i2c_getscl(struct w9966_dev* cam)
+{
+	const u8 pins = w9966_rreg(cam, 0x18);
+	return ((pins & W9966_I2C_R_CLOCK) > 0);
+}
+
 // Sets the clock line on the i2c bus.
 // Expects a claimed pdev.
 // 1 on success, else 0
@@ -723,14 +731,6 @@ static inline int w9966_i2c_getsda(struc
 	return ((pins & W9966_I2C_R_DATA) > 0);
 }
 
-// Get peripheral clock line
-// Expects a claimed pdev.
-static inline int w9966_i2c_getscl(struct w9966_dev* cam)
-{
-	const u8 pins = w9966_rreg(cam, 0x18);
-	return ((pins & W9966_I2C_R_CLOCK) > 0);
-}
-
 // Write a byte with ack to the i2c bus.
 // Expects a claimed pdev.
 // 1 on success, else 0
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/message/i2o/i2o_pci.c linux-2.4.28-pre3/drivers/message/i2o/i2o_pci.c
--- linux-2.4.27/drivers/message/i2o/i2o_pci.c	2002-11-28 23:53:13.000000000 +0000
+++ linux-2.4.28-pre3/drivers/message/i2o/i2o_pci.c	2004-09-10 19:32:51.000000000 +0000
@@ -390,4 +390,3 @@ MODULE_PARM(dpt, "i");
 MODULE_PARM_DESC(dpt, "Set this if you want to drive DPT cards normally handled by dpt_i2o");
 module_init(i2o_pci_core_attach);
 module_exit(i2o_pci_core_detach);
- 
\ No newline at end of file
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/mtd/chips/cfi_cmdset_0002.c linux-2.4.28-pre3/drivers/mtd/chips/cfi_cmdset_0002.c
--- linux-2.4.27/drivers/mtd/chips/cfi_cmdset_0002.c	2003-06-13 14:51:34.000000000 +0000
+++ linux-2.4.28-pre3/drivers/mtd/chips/cfi_cmdset_0002.c	2004-09-10 19:34:24.000000000 +0000
@@ -461,7 +461,6 @@ static int do_write_oneword(struct map_i
 	unsigned int dq6, dq5;	
 	struct cfi_private *cfi = map->fldrv_priv;
 	DECLARE_WAITQUEUE(wait, current);
-	int ret = 0;
 
  retry:
 	cfi_spin_lock(chip->mutex);
@@ -554,7 +553,7 @@ static int do_write_oneword(struct map_i
 			wake_up(&chip->wq);
 			cfi_spin_unlock(chip->mutex);
 			DISABLE_VPP(map);
-			ret = -EIO;
+			return -EIO;
 		}
 	}
 
@@ -563,7 +562,7 @@ static int do_write_oneword(struct map_i
 	wake_up(&chip->wq);
 	cfi_spin_unlock(chip->mutex);
 
-	return ret;
+	return 0;
 }
 
 static int cfi_amdstd_write (struct mtd_info *mtd, loff_t to , size_t len, size_t *retlen, const u_char *buf)
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/mtd/devices/doc1000.c linux-2.4.28-pre3/drivers/mtd/devices/doc1000.c
--- linux-2.4.27/drivers/mtd/devices/doc1000.c	2003-06-13 14:51:34.000000000 +0000
+++ linux-2.4.28-pre3/drivers/mtd/devices/doc1000.c	2004-09-10 19:35:47.000000000 +0000
@@ -137,6 +137,119 @@ int flashcard_erase (struct mtd_info *mt
 	return 0;
 }
 
+static inline int suspend_erase(volatile u_char *addr)
+{
+	__u16 status;
+	u_long i = 0;
+	
+	writew(IF_ERASE_SUSPEND, addr);
+	writew(IF_READ_CSR, addr);
+	
+	do {
+		status = readw(addr);
+		if ((status & CSR_WR_READY) == CSR_WR_READY)
+			return 0;
+		i++;
+	} while(i < max_tries);
+
+	printk(KERN_NOTICE "flashcard: suspend_erase timed out, status 0x%x\n", status);
+	return -EIO;
+
+}
+
+static inline void resume_erase(volatile u_char *addr)
+{
+	__u16 status;
+	
+	writew(IF_READ_CSR, addr);
+	status = readw(addr);
+	
+	/* Only give resume signal if the erase is really suspended */
+	if (status & CSR_ERA_SUSPEND)
+		writew(IF_CONFIRM, addr);
+}
+
+static inline int byte_write (volatile u_char *addr, u_char byte)
+{
+	register u_char status;
+	register u_short i = 0;
+
+	do {
+		status = readb(addr);
+		if (status & CSR_WR_READY)
+		{
+			writeb(IF_WRITE & 0xff, addr);
+			writeb(byte, addr);
+			return 0;
+		}
+		i++;
+	} while(i < max_tries);
+
+		
+	printk(KERN_NOTICE "flashcard: byte_write timed out, status 0x%x\n",status);
+	return -EIO;
+}
+
+static inline int word_write (volatile u_char *addr, __u16 word)
+{
+	register u_short status;
+	register u_short i = 0;
+	
+	do {
+		status = readw(addr);
+		if ((status & CSR_WR_READY) == CSR_WR_READY)
+		{
+			writew(IF_WRITE, addr);
+			writew(word, addr);
+			return 0;
+		}
+		i++;
+	} while(i < max_tries);
+		
+	printk(KERN_NOTICE "flashcard: word_write timed out at %p, status 0x%x\n", addr, status);
+	return -EIO;
+}
+
+static inline void reset_block(volatile u_char *addr)
+{
+	u_short i;
+	__u16 status;
+
+	writew(IF_CLEAR_CSR, addr);
+
+	for (i = 0; i < 100; i++) {
+		writew(IF_READ_CSR, addr);
+		status = readw(addr);
+		if (status != 0xffff) break;
+		udelay(1000);
+	}
+
+	writew(IF_READ_CSR, addr);
+}
+
+static inline int check_write(volatile u_char *addr)
+{
+	u_short status, i = 0;
+	
+	writew(IF_READ_CSR, addr);
+	
+	do {
+		status = readw(addr);
+		if (status & (CSR_WR_ERR | CSR_VPP_LOW))
+		{
+			printk(KERN_NOTICE "flashcard: write failure at %p, status 0x%x\n", addr, status);
+			reset_block(addr);
+			return -EIO;
+		}
+		if ((status & CSR_WR_READY) == CSR_WR_READY)
+			return 0;
+		i++;
+	} while (i < max_tries);
+
+	printk(KERN_NOTICE "flashcard: write timed out at %p, status 0x%x\n", addr, status);
+	return -EIO;
+}
+
 
 int flashcard_read (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf)
 {
@@ -281,47 +394,6 @@ int flashcard_write (struct mtd_info *mt
 
 /*====================================================================*/
 
-static inline int byte_write (volatile u_char *addr, u_char byte)
-{
-	register u_char status;
-	register u_short i = 0;
-
-	do {
-		status = readb(addr);
-		if (status & CSR_WR_READY)
-		{
-			writeb(IF_WRITE & 0xff, addr);
-			writeb(byte, addr);
-			return 0;
-		}
-		i++;
-	} while(i < max_tries);
-
-		
-	printk(KERN_NOTICE "flashcard: byte_write timed out, status 0x%x\n",status);
-	return -EIO;
-}
-
-static inline int word_write (volatile u_char *addr, __u16 word)
-{
-	register u_short status;
-	register u_short i = 0;
-	
-	do {
-		status = readw(addr);
-		if ((status & CSR_WR_READY) == CSR_WR_READY)
-		{
-			writew(IF_WRITE, addr);
-			writew(word, addr);
-			return 0;
-		}
-		i++;
-	} while(i < max_tries);
-		
-	printk(KERN_NOTICE "flashcard: word_write timed out at %p, status 0x%x\n", addr, status);
-	return -EIO;
-}
-
 static inline void block_erase (volatile u_char *addr)
 {
 	writew(IF_BLOCK_ERASE, addr);
@@ -350,79 +422,6 @@ static inline int check_erase(volatile u
 	return 0;
 }
 
-static inline int suspend_erase(volatile u_char *addr)
-{
-	__u16 status;
-	u_long i = 0;
-	
-	writew(IF_ERASE_SUSPEND, addr);
-	writew(IF_READ_CSR, addr);
-	
-	do {
-		status = readw(addr);
-		if ((status & CSR_WR_READY) == CSR_WR_READY)
-			return 0;
-		i++;
-	} while(i < max_tries);
-
-	printk(KERN_NOTICE "flashcard: suspend_erase timed out, status 0x%x\n", status);
-	return -EIO;
-
-}
-
-static inline void resume_erase(volatile u_char *addr)
-{
-	__u16 status;
-	
-	writew(IF_READ_CSR, addr);
-	status = readw(addr);
-	
-	/* Only give resume signal if the erase is really suspended */
-	if (status & CSR_ERA_SUSPEND)
-		writew(IF_CONFIRM, addr);
-}
-
-static inline void reset_block(volatile u_char *addr)
-{
-	u_short i;
-	__u16 status;
-
-	writew(IF_CLEAR_CSR, addr);
-
-	for (i = 0; i < 100; i++) {
-		writew(IF_READ_CSR, addr);
-		status = readw(addr);
-		if (status != 0xffff) break;
-		udelay(1000);
-	}
-
-	writew(IF_READ_CSR, addr);
-}
-
-static inline int check_write(volatile u_char *addr)
-{
-	u_short status, i = 0;
-	
-	writew(IF_READ_CSR, addr);
-	
-	do {
-		status = readw(addr);
-		if (status & (CSR_WR_ERR | CSR_VPP_LOW))
-		{
-			printk(KERN_NOTICE "flashcard: write failure at %p, status 0x%x\n", addr, status);
-			reset_block(addr);
-			return -EIO;
-		}
-		if ((status & CSR_WR_READY) == CSR_WR_READY)
-			return 0;
-		i++;
-	} while (i < max_tries);
-
-	printk(KERN_NOTICE "flashcard: write timed out at %p, status 0x%x\n", addr, status);
-	return -EIO;
-}
-
-
 /*====================================================================*/
 
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/mtd/maps/amd76xrom.c linux-2.4.28-pre3/drivers/mtd/maps/amd76xrom.c
--- linux-2.4.27/drivers/mtd/maps/amd76xrom.c	2003-06-13 14:51:34.000000000 +0000
+++ linux-2.4.28-pre3/drivers/mtd/maps/amd76xrom.c	2004-09-10 19:33:44.000000000 +0000
@@ -178,7 +178,7 @@ err_out_iounmap:
 	iounmap((void *)(info->window_addr));
 err_out_free_mmio_region:
 	release_mem_region(window->start, window->size);
-err_out_none:
+//err_out_none:
 	return -ENODEV;
 }
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/net/8139too.c linux-2.4.28-pre3/drivers/net/8139too.c
--- linux-2.4.27/drivers/net/8139too.c	2004-08-07 23:26:04.000000000 +0000
+++ linux-2.4.28-pre3/drivers/net/8139too.c	2004-09-10 19:31:49.000000000 +0000
@@ -614,7 +614,7 @@ static int rtl8139_open (struct net_devi
 static int mdio_read (struct net_device *dev, int phy_id, int location);
 static void mdio_write (struct net_device *dev, int phy_id, int location,
 			int val);
-static inline void rtl8139_start_thread(struct net_device *dev);
+static void rtl8139_start_thread(struct net_device *dev);
 static void rtl8139_tx_timeout (struct net_device *dev);
 static void rtl8139_init_ring (struct net_device *dev);
 static int rtl8139_start_xmit (struct sk_buff *skb,
@@ -1626,7 +1626,7 @@ static int rtl8139_thread (void *data)
 	complete_and_exit (&tp->thr_exited, 0);
 }
 
-static inline void rtl8139_start_thread(struct net_device *dev)
+static void rtl8139_start_thread(struct net_device *dev)
 {
 	struct rtl8139_private *tp = dev->priv;
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/net/dmfe.c linux-2.4.28-pre3/drivers/net/dmfe.c
--- linux-2.4.27/drivers/net/dmfe.c	2003-11-28 18:26:20.000000000 +0000
+++ linux-2.4.28-pre3/drivers/net/dmfe.c	2004-09-10 19:36:43.000000000 +0000
@@ -863,6 +863,20 @@ static void dmfe_free_tx_pkt(struct DEVI
 
 
 /*
+ *	Calculate the CRC valude of the Rx packet
+ *	flag = 	1 : return the reverse CRC (for the received packet CRC)
+ *		0 : return the normal CRC (for Hash Table index)
+ */
+
+static inline u32 cal_CRC(unsigned char * Data, unsigned int Len, u8 flag)
+{
+	u32 crc = ether_crc_le(Len, Data);
+	if (flag) crc = ~crc;
+	return crc;
+}
+
+
+/*
  *	Receive the come packet and pass to upper layer
  */
 
@@ -1753,20 +1767,6 @@ static u16 phy_read_1bit(unsigned long i
 
 
 /*
- *	Calculate the CRC valude of the Rx packet
- *	flag = 	1 : return the reverse CRC (for the received packet CRC)
- *		0 : return the normal CRC (for Hash Table index)
- */
-
-static inline u32 cal_CRC(unsigned char * Data, unsigned int Len, u8 flag)
-{
-	u32 crc = ether_crc_le(Len, Data);
-	if (flag) crc = ~crc;
-	return crc;
-}
-
-
-/*
  *	Parser SROM and media mode
  */
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/net/e100/e100_main.c linux-2.4.28-pre3/drivers/net/e100/e100_main.c
--- linux-2.4.27/drivers/net/e100/e100_main.c	2004-08-07 23:26:05.000000000 +0000
+++ linux-2.4.28-pre3/drivers/net/e100/e100_main.c	2004-09-10 19:32:37.000000000 +0000
@@ -1073,6 +1073,116 @@ e100_change_mtu(struct net_device *dev, 
 	return 0;
 }
 
+/**
+ * e100_prepare_xmit_buff - prepare a buffer for transmission
+ * @bdp: atapter's private data struct
+ * @skb: skb to send
+ *
+ * This routine prepare a buffer for transmission. It checks
+ * the message length for the appropiate size. It picks up a
+ * free tcb from the TCB pool and sets up the corresponding
+ * TBD's. If the number of fragments are more than the number
+ * of TBD/TCB it copies all the fragments in a coalesce buffer.
+ * It returns a pointer to the prepared TCB.
+ */
+static inline tcb_t *
+e100_prepare_xmit_buff(struct e100_private *bdp, struct sk_buff *skb)
+{
+	tcb_t *tcb, *prev_tcb;
+
+	tcb = bdp->tcb_pool.data;
+	tcb += TCB_TO_USE(bdp->tcb_pool);
+
+	if (bdp->flags & USE_IPCB) {
+		tcb->tcbu.ipcb.ip_activation_high = IPCB_IP_ACTIVATION_DEFAULT;
+		tcb->tcbu.ipcb.ip_schedule &= ~IPCB_TCP_PACKET;
+		tcb->tcbu.ipcb.ip_schedule &= ~IPCB_TCPUDP_CHECKSUM_ENABLE;
+	}
+
+	if(bdp->vlgrp && vlan_tx_tag_present(skb)) {
+		(tcb->tcbu).ipcb.ip_activation_high |= IPCB_INSERTVLAN_ENABLE;
+		(tcb->tcbu).ipcb.vlan = cpu_to_be16(vlan_tx_tag_get(skb));
+	}
+	
+	tcb->tcb_hdr.cb_status = 0;
+	tcb->tcb_thrshld = bdp->tx_thld;
+	tcb->tcb_hdr.cb_cmd |= __constant_cpu_to_le16(CB_S_BIT);
+
+	/* Set I (Interrupt) bit on every (TX_FRAME_CNT)th packet */
+	if (!(++bdp->tx_count % TX_FRAME_CNT))
+		tcb->tcb_hdr.cb_cmd |= __constant_cpu_to_le16(CB_I_BIT);
+	else
+		/* Clear I bit on other packets */
+		tcb->tcb_hdr.cb_cmd &= ~__constant_cpu_to_le16(CB_I_BIT);
+
+	tcb->tcb_skb = skb;
+
+	if (skb->ip_summed == CHECKSUM_HW) {
+		const struct iphdr *ip = skb->nh.iph;
+
+		if ((ip->protocol == IPPROTO_TCP) ||
+		    (ip->protocol == IPPROTO_UDP)) {
+
+			tcb->tcbu.ipcb.ip_activation_high |=
+				IPCB_HARDWAREPARSING_ENABLE;
+			tcb->tcbu.ipcb.ip_schedule |=
+				IPCB_TCPUDP_CHECKSUM_ENABLE;
+
+			if (ip->protocol == IPPROTO_TCP)
+				tcb->tcbu.ipcb.ip_schedule |= IPCB_TCP_PACKET;
+		}
+	}
+
+	if (!skb_shinfo(skb)->nr_frags) {
+		(tcb->tbd_ptr)->tbd_buf_addr =
+			cpu_to_le32(pci_map_single(bdp->pdev, skb->data,
+						   skb->len, PCI_DMA_TODEVICE));
+		(tcb->tbd_ptr)->tbd_buf_cnt = cpu_to_le16(skb->len);
+		tcb->tcb_tbd_num = 1;
+		tcb->tcb_tbd_ptr = tcb->tcb_tbd_dflt_ptr;
+	} else {
+		int i;
+		void *addr;
+		tbd_t *tbd_arr_ptr = &(tcb->tbd_ptr[1]);
+		skb_frag_t *frag = &skb_shinfo(skb)->frags[0];
+
+		(tcb->tbd_ptr)->tbd_buf_addr =
+			cpu_to_le32(pci_map_single(bdp->pdev, skb->data,
+						   skb_headlen(skb),
+						   PCI_DMA_TODEVICE));
+		(tcb->tbd_ptr)->tbd_buf_cnt =
+			cpu_to_le16(skb_headlen(skb));
+
+		for (i = 0; i < skb_shinfo(skb)->nr_frags;
+		     i++, tbd_arr_ptr++, frag++) {
+
+			addr = ((void *) page_address(frag->page) +
+				frag->page_offset);
+
+			tbd_arr_ptr->tbd_buf_addr =
+				cpu_to_le32(pci_map_single(bdp->pdev,
+							   addr, frag->size,
+							   PCI_DMA_TODEVICE));
+			tbd_arr_ptr->tbd_buf_cnt = cpu_to_le16(frag->size);
+		}
+		tcb->tcb_tbd_num = skb_shinfo(skb)->nr_frags + 1;
+		tcb->tcb_tbd_ptr = tcb->tcb_tbd_expand_ptr;
+	}
+
+	/* clear the S-BIT on the previous tcb */
+	prev_tcb = bdp->tcb_pool.data;
+	prev_tcb += PREV_TCB_USED(bdp->tcb_pool);
+	prev_tcb->tcb_hdr.cb_cmd &= __constant_cpu_to_le16((u16) ~CB_S_BIT);
+
+	bdp->tcb_pool.tail = NEXT_TCB_TOUSE(bdp->tcb_pool.tail);
+
+	wmb();
+
+	e100_start_cu(bdp, tcb);
+
+	return tcb;
+}
+
 static int
 e100_xmit_frame(struct sk_buff *skb, struct net_device *dev)
 {
@@ -1605,6 +1715,32 @@ e100_alloc_tcb_pool(struct e100_private 
 	return 1;
 }
 
+/**
+ * e100_tx_skb_free - free TX skbs resources
+ * @bdp: atapter's private data struct
+ * @tcb: associated tcb of the freed skb
+ *
+ * This routine frees resources of TX skbs.
+ */
+static inline void
+e100_tx_skb_free(struct e100_private *bdp, tcb_t *tcb)
+{
+	if (tcb->tcb_skb) {
+		int i;
+		tbd_t *tbd_arr = tcb->tbd_ptr;
+		int frags = skb_shinfo(tcb->tcb_skb)->nr_frags;
+
+		for (i = 0; i <= frags; i++, tbd_arr++) {
+			pci_unmap_single(bdp->pdev,
+					 le32_to_cpu(tbd_arr->tbd_buf_addr),
+					 le16_to_cpu(tbd_arr->tbd_buf_cnt),
+					 PCI_DMA_TODEVICE);
+		}
+		dev_kfree_skb_irq(tcb->tcb_skb);
+		tcb->tcb_skb = NULL;
+	}
+}
+
 void
 e100_free_tcb_pool(struct e100_private *bdp)
 {
@@ -1910,32 +2046,6 @@ e100intr(int irq, void *dev_inst, struct
 }
 
 /**
- * e100_tx_skb_free - free TX skbs resources
- * @bdp: atapter's private data struct
- * @tcb: associated tcb of the freed skb
- *
- * This routine frees resources of TX skbs.
- */
-static inline void
-e100_tx_skb_free(struct e100_private *bdp, tcb_t *tcb)
-{
-	if (tcb->tcb_skb) {
-		int i;
-		tbd_t *tbd_arr = tcb->tbd_ptr;
-		int frags = skb_shinfo(tcb->tcb_skb)->nr_frags;
-
-		for (i = 0; i <= frags; i++, tbd_arr++) {
-			pci_unmap_single(bdp->pdev,
-					 le32_to_cpu(tbd_arr->tbd_buf_addr),
-					 le16_to_cpu(tbd_arr->tbd_buf_cnt),
-					 PCI_DMA_TODEVICE);
-		}
-		dev_kfree_skb_irq(tcb->tcb_skb);
-		tcb->tcb_skb = NULL;
-	}
-}
-
-/**
  * e100_tx_srv - service TX queues
  * @bdp: atapter's private data struct
  *
@@ -2155,116 +2265,6 @@ e100_refresh_txthld(struct e100_private 
 	}			/* end underrun check */
 }
 
-/**
- * e100_prepare_xmit_buff - prepare a buffer for transmission
- * @bdp: atapter's private data struct
- * @skb: skb to send
- *
- * This routine prepare a buffer for transmission. It checks
- * the message length for the appropiate size. It picks up a
- * free tcb from the TCB pool and sets up the corresponding
- * TBD's. If the number of fragments are more than the number
- * of TBD/TCB it copies all the fragments in a coalesce buffer.
- * It returns a pointer to the prepared TCB.
- */
-static inline tcb_t *
-e100_prepare_xmit_buff(struct e100_private *bdp, struct sk_buff *skb)
-{
-	tcb_t *tcb, *prev_tcb;
-
-	tcb = bdp->tcb_pool.data;
-	tcb += TCB_TO_USE(bdp->tcb_pool);
-
-	if (bdp->flags & USE_IPCB) {
-		tcb->tcbu.ipcb.ip_activation_high = IPCB_IP_ACTIVATION_DEFAULT;
-		tcb->tcbu.ipcb.ip_schedule &= ~IPCB_TCP_PACKET;
-		tcb->tcbu.ipcb.ip_schedule &= ~IPCB_TCPUDP_CHECKSUM_ENABLE;
-	}
-
-	if(bdp->vlgrp && vlan_tx_tag_present(skb)) {
-		(tcb->tcbu).ipcb.ip_activation_high |= IPCB_INSERTVLAN_ENABLE;
-		(tcb->tcbu).ipcb.vlan = cpu_to_be16(vlan_tx_tag_get(skb));
-	}
-	
-	tcb->tcb_hdr.cb_status = 0;
-	tcb->tcb_thrshld = bdp->tx_thld;
-	tcb->tcb_hdr.cb_cmd |= __constant_cpu_to_le16(CB_S_BIT);
-
-	/* Set I (Interrupt) bit on every (TX_FRAME_CNT)th packet */
-	if (!(++bdp->tx_count % TX_FRAME_CNT))
-		tcb->tcb_hdr.cb_cmd |= __constant_cpu_to_le16(CB_I_BIT);
-	else
-		/* Clear I bit on other packets */
-		tcb->tcb_hdr.cb_cmd &= ~__constant_cpu_to_le16(CB_I_BIT);
-
-	tcb->tcb_skb = skb;
-
-	if (skb->ip_summed == CHECKSUM_HW) {
-		const struct iphdr *ip = skb->nh.iph;
-
-		if ((ip->protocol == IPPROTO_TCP) ||
-		    (ip->protocol == IPPROTO_UDP)) {
-
-			tcb->tcbu.ipcb.ip_activation_high |=
-				IPCB_HARDWAREPARSING_ENABLE;
-			tcb->tcbu.ipcb.ip_schedule |=
-				IPCB_TCPUDP_CHECKSUM_ENABLE;
-
-			if (ip->protocol == IPPROTO_TCP)
-				tcb->tcbu.ipcb.ip_schedule |= IPCB_TCP_PACKET;
-		}
-	}
-
-	if (!skb_shinfo(skb)->nr_frags) {
-		(tcb->tbd_ptr)->tbd_buf_addr =
-			cpu_to_le32(pci_map_single(bdp->pdev, skb->data,
-						   skb->len, PCI_DMA_TODEVICE));
-		(tcb->tbd_ptr)->tbd_buf_cnt = cpu_to_le16(skb->len);
-		tcb->tcb_tbd_num = 1;
-		tcb->tcb_tbd_ptr = tcb->tcb_tbd_dflt_ptr;
-	} else {
-		int i;
-		void *addr;
-		tbd_t *tbd_arr_ptr = &(tcb->tbd_ptr[1]);
-		skb_frag_t *frag = &skb_shinfo(skb)->frags[0];
-
-		(tcb->tbd_ptr)->tbd_buf_addr =
-			cpu_to_le32(pci_map_single(bdp->pdev, skb->data,
-						   skb_headlen(skb),
-						   PCI_DMA_TODEVICE));
-		(tcb->tbd_ptr)->tbd_buf_cnt =
-			cpu_to_le16(skb_headlen(skb));
-
-		for (i = 0; i < skb_shinfo(skb)->nr_frags;
-		     i++, tbd_arr_ptr++, frag++) {
-
-			addr = ((void *) page_address(frag->page) +
-				frag->page_offset);
-
-			tbd_arr_ptr->tbd_buf_addr =
-				cpu_to_le32(pci_map_single(bdp->pdev,
-							   addr, frag->size,
-							   PCI_DMA_TODEVICE));
-			tbd_arr_ptr->tbd_buf_cnt = cpu_to_le16(frag->size);
-		}
-		tcb->tcb_tbd_num = skb_shinfo(skb)->nr_frags + 1;
-		tcb->tcb_tbd_ptr = tcb->tcb_tbd_expand_ptr;
-	}
-
-	/* clear the S-BIT on the previous tcb */
-	prev_tcb = bdp->tcb_pool.data;
-	prev_tcb += PREV_TCB_USED(bdp->tcb_pool);
-	prev_tcb->tcb_hdr.cb_cmd &= __constant_cpu_to_le16((u16) ~CB_S_BIT);
-
-	bdp->tcb_pool.tail = NEXT_TCB_TOUSE(bdp->tcb_pool.tail);
-
-	wmb();
-
-	e100_start_cu(bdp, tcb);
-
-	return tcb;
-}
-
 /* Changed for 82558 enhancement */
 /**
  * e100_start_cu - start the adapter's CU
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/net/e1000/e1000_main.c linux-2.4.28-pre3/drivers/net/e1000/e1000_main.c
--- linux-2.4.27/drivers/net/e1000/e1000_main.c	2004-08-07 23:26:05.000000000 +0000
+++ linux-2.4.28-pre3/drivers/net/e1000/e1000_main.c	2004-09-10 19:34:20.000000000 +0000
@@ -248,6 +248,34 @@ e1000_exit_module(void)
 module_exit(e1000_exit_module);
 
 
+/**
+ * e1000_irq_enable - Enable default interrupt generation settings
+ * @adapter: board private structure
+ **/
+
+static inline void
+e1000_irq_enable(struct e1000_adapter *adapter)
+{
+	if(atomic_dec_and_test(&adapter->irq_sem)) {
+		E1000_WRITE_REG(&adapter->hw, IMS, IMS_ENABLE_MASK);
+		E1000_WRITE_FLUSH(&adapter->hw);
+	}
+}
+
+/**
+ * e1000_irq_disable - Mask off interrupt generation on the NIC
+ * @adapter: board private structure
+ **/
+
+static inline void
+e1000_irq_disable(struct e1000_adapter *adapter)
+{
+	atomic_inc(&adapter->irq_sem);
+	E1000_WRITE_REG(&adapter->hw, IMC, ~0);
+	E1000_WRITE_FLUSH(&adapter->hw);
+	synchronize_irq();
+}
+
 int
 e1000_up(struct e1000_adapter *adapter)
 {
@@ -2055,34 +2083,6 @@ e1000_update_stats(struct e1000_adapter 
 }
 
 /**
- * e1000_irq_disable - Mask off interrupt generation on the NIC
- * @adapter: board private structure
- **/
-
-static inline void
-e1000_irq_disable(struct e1000_adapter *adapter)
-{
-	atomic_inc(&adapter->irq_sem);
-	E1000_WRITE_REG(&adapter->hw, IMC, ~0);
-	E1000_WRITE_FLUSH(&adapter->hw);
-	synchronize_irq();
-}
-
-/**
- * e1000_irq_enable - Enable default interrupt generation settings
- * @adapter: board private structure
- **/
-
-static inline void
-e1000_irq_enable(struct e1000_adapter *adapter)
-{
-	if(atomic_dec_and_test(&adapter->irq_sem)) {
-		E1000_WRITE_REG(&adapter->hw, IMS, IMS_ENABLE_MASK);
-		E1000_WRITE_FLUSH(&adapter->hw);
-	}
-}
-
-/**
  * e1000_intr - Interrupt Handler
  * @irq: interrupt number
  * @data: pointer to a network interface device structure
@@ -2227,6 +2227,41 @@ e1000_clean_tx_irq(struct e1000_adapter 
 }
 
 /**
+ * e1000_rx_checksum - Receive Checksum Offload for 82543
+ * @adapter: board private structure
+ * @rx_desc: receive descriptor
+ * @sk_buff: socket buffer with received data
+ **/
+
+static inline void
+e1000_rx_checksum(struct e1000_adapter *adapter,
+                  struct e1000_rx_desc *rx_desc,
+                  struct sk_buff *skb)
+{
+	/* 82543 or newer only */
+	if((adapter->hw.mac_type < e1000_82543) ||
+	/* Ignore Checksum bit is set */
+	(rx_desc->status & E1000_RXD_STAT_IXSM) ||
+	/* TCP Checksum has not been calculated */
+	(!(rx_desc->status & E1000_RXD_STAT_TCPCS))) {
+		skb->ip_summed = CHECKSUM_NONE;
+		return;
+	}
+
+	/* At this point we know the hardware did the TCP checksum */
+	/* now look at the TCP checksum error bit */
+	if(rx_desc->errors & E1000_RXD_ERR_TCPE) {
+		/* let the stack verify checksum errors */
+		skb->ip_summed = CHECKSUM_NONE;
+		adapter->hw_csum_err++;
+	} else {
+	/* TCP checksum is good */
+		skb->ip_summed = CHECKSUM_UNNECESSARY;
+		adapter->hw_csum_good++;
+	}
+}
+
+/**
  * e1000_clean_rx_irq - Send received data up the network stack,
  * @adapter: board private structure
  **/
@@ -2581,41 +2616,6 @@ e1000_mii_ioctl(struct net_device *netde
 	return E1000_SUCCESS;
 }
 
-/**
- * e1000_rx_checksum - Receive Checksum Offload for 82543
- * @adapter: board private structure
- * @rx_desc: receive descriptor
- * @sk_buff: socket buffer with received data
- **/
-
-static inline void
-e1000_rx_checksum(struct e1000_adapter *adapter,
-                  struct e1000_rx_desc *rx_desc,
-                  struct sk_buff *skb)
-{
-	/* 82543 or newer only */
-	if((adapter->hw.mac_type < e1000_82543) ||
-	/* Ignore Checksum bit is set */
-	(rx_desc->status & E1000_RXD_STAT_IXSM) ||
-	/* TCP Checksum has not been calculated */
-	(!(rx_desc->status & E1000_RXD_STAT_TCPCS))) {
-		skb->ip_summed = CHECKSUM_NONE;
-		return;
-	}
-
-	/* At this point we know the hardware did the TCP checksum */
-	/* now look at the TCP checksum error bit */
-	if(rx_desc->errors & E1000_RXD_ERR_TCPE) {
-		/* let the stack verify checksum errors */
-		skb->ip_summed = CHECKSUM_NONE;
-		adapter->hw_csum_err++;
-	} else {
-	/* TCP checksum is good */
-		skb->ip_summed = CHECKSUM_UNNECESSARY;
-		adapter->hw_csum_good++;
-	}
-}
-
 void
 e1000_pci_set_mwi(struct e1000_hw *hw)
 {
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/net/e1000/e1000_param.c linux-2.4.28-pre3/drivers/net/e1000/e1000_param.c
--- linux-2.4.27/drivers/net/e1000/e1000_param.c	2004-08-07 23:26:05.000000000 +0000
+++ linux-2.4.28-pre3/drivers/net/e1000/e1000_param.c	2004-09-10 19:32:44.000000000 +0000
@@ -212,7 +212,7 @@ E1000_PARAM(InterruptThrottleRate, "Inte
 #define MAX_TXABSDELAY            0xFFFF
 #define MIN_TXABSDELAY                 0
 
-#define DEFAULT_ITR                    1
+#define DEFAULT_ITR                 8000
 #define MAX_ITR                   100000
 #define MIN_ITR                      100
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/net/eql.c linux-2.4.28-pre3/drivers/net/eql.c
--- linux-2.4.27/drivers/net/eql.c	2004-08-07 23:26:05.000000000 +0000
+++ linux-2.4.28-pre3/drivers/net/eql.c	2004-09-10 19:33:46.000000000 +0000
@@ -335,6 +335,152 @@ static int eql_ioctl(struct net_device *
 }
 
 
+static inline int eql_number_slaves(slave_queue_t *queue)
+{
+	return queue->num_slaves;
+}
+
+
+static inline int eql_is_empty(slave_queue_t *queue)
+{
+	if (eql_number_slaves (queue) == 0)
+		return 1;
+	return 0;
+}
+
+static inline int eql_is_full(slave_queue_t *queue)
+{
+	equalizer_t *eql = (equalizer_t *) queue->master_dev->priv;
+
+	if (eql_number_slaves (queue) == eql->max_slaves)
+		return 1;
+	return 0;
+}
+
+static inline slave_t *eql_first_slave(slave_queue_t *queue)
+{
+	return queue->head->next;
+}
+
+
+static inline slave_t *eql_next_slave(slave_queue_t *queue, slave_t *slave)
+{
+	return slave->next;
+}
+
+static inline void eql_set_best_slave(slave_queue_t *queue, slave_t *slave)
+{
+	queue->best_slave = slave;
+}
+
+static inline void eql_schedule_slaves(slave_queue_t *queue)
+{
+	struct net_device *master_dev = queue->master_dev;
+	slave_t *best_slave = 0;
+	slave_t *slave_corpse = 0;
+
+#ifdef EQL_DEBUG
+	if (eql_debug >= 100)
+		printk ("%s: schedule %d slaves\n", 
+			master_dev->name, eql_number_slaves (queue));
+#endif
+	if ( eql_is_empty (queue) )
+	{
+		/*
+		 *	No slaves to play with 
+		 */
+		eql_set_best_slave (queue, (slave_t *) 0);
+		return;
+	}
+	else
+	{		
+		/*
+		 *	Make a pass to set the best slave 
+		 */
+		unsigned long best_load = (unsigned long) ULONG_MAX;
+		slave_t *slave = 0;
+		unsigned long flags;
+		int i;
+
+		save_flags(flags);
+		cli ();
+		for (i = 1, slave = eql_first_slave (queue);
+			i <= eql_number_slaves (queue);
+			i++, slave = eql_next_slave (queue, slave))
+		{
+			/*
+			 *	Go through the slave list once, updating best_slave 
+			 *      whenever a new best_load is found, whenever a dead
+			 *	slave is found, it is marked to be pulled out of the 
+			 *	queue 
+			 */
+		
+			unsigned long slave_load;
+			unsigned long bytes_queued; 
+			unsigned long priority_Bps; 
+	  	
+	  		if (slave != 0)
+			{
+				bytes_queued = slave->bytes_queued;
+				priority_Bps = slave->priority_Bps;    
+				if ( slave->dev != 0)
+				{
+					if ((slave->dev->flags & IFF_UP) == IFF_UP )
+					{
+						slave_load = (ULONG_MAX - (ULONG_MAX / 2)) - 
+							(priority_Bps) + bytes_queued * 8;
+
+		      				if (slave_load < best_load)
+						{
+							best_load = slave_load;
+							best_slave = slave;
+						}
+					}
+					else		/* we found a dead slave */
+					{
+						/* 
+						 *	We only bury one slave at a time, if more than
+						 *	one slave dies, we will bury him on the next 
+						 *	reschedule. slaves don't die all at once that 
+						 *	much anyway 
+						 */
+						slave_corpse = slave;
+					}
+				}
+			}
+		} /* for */
+		restore_flags(flags);
+		eql_set_best_slave (queue, best_slave);
+	} /* else */
+	if (slave_corpse != 0)
+	{
+		printk ("eql: scheduler found dead slave, burying...\n");
+		eql_delete_slave (eql_remove_slave (queue, slave_corpse));
+	}
+	return;
+}
+
+
+static inline struct net_device *eql_best_slave_dev(slave_queue_t *queue)
+{
+	if (queue->best_slave != 0)
+	{
+		if (queue->best_slave->dev != 0)
+			return queue->best_slave->dev;
+		else
+			return 0;
+	}
+	else
+		return 0;
+}
+
+
+static inline slave_t *eql_best_slave(slave_queue_t *queue)
+{
+	return queue->best_slave;
+}
+
+
 static int eql_slave_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	equalizer_t *eql = (equalizer_t *) dev->priv;
@@ -383,6 +529,28 @@ static struct net_device_stats * eql_get
 	return eql->stats;
 }
 
+static inline int eql_is_slave(struct net_device *dev)
+{
+	if (dev)
+	{
+		if ((dev->flags & IFF_SLAVE) == IFF_SLAVE)
+			return 1;
+	}
+	return 0;
+}
+
+
+static inline int eql_is_master(struct net_device *dev)
+{
+	if (dev)
+	{
+		if ((dev->flags & IFF_MASTER) == IFF_MASTER)
+		return 1;
+	}
+	return 0;
+}
+
+
 /*
  *	Private ioctl functions
  */
@@ -597,28 +765,6 @@ static int eql_s_master_cfg(struct net_d
  *	Private device support functions
  */
 
-static inline int eql_is_slave(struct net_device *dev)
-{
-	if (dev)
-	{
-		if ((dev->flags & IFF_SLAVE) == IFF_SLAVE)
-			return 1;
-	}
-	return 0;
-}
-
-
-static inline int eql_is_master(struct net_device *dev)
-{
-	if (dev)
-	{
-		if ((dev->flags & IFF_MASTER) == IFF_MASTER)
-		return 1;
-	}
-	return 0;
-}
-
-
 static slave_t *eql_new_slave(void)
 {
 	slave_t *slave;
@@ -650,27 +796,6 @@ static long slave_bps(slave_t *slave)
 
 #endif
 
-static inline int eql_number_slaves(slave_queue_t *queue)
-{
-	return queue->num_slaves;
-}
-
-static inline int eql_is_empty(slave_queue_t *queue)
-{
-	if (eql_number_slaves (queue) == 0)
-		return 1;
-	return 0;
-}
-
-static inline int eql_is_full(slave_queue_t *queue)
-{
-	equalizer_t *eql = (equalizer_t *) queue->master_dev->priv;
-
-	if (eql_number_slaves (queue) == eql->max_slaves)
-		return 1;
-	return 0;
-}
-
 static slave_queue_t *eql_new_slave_queue(struct net_device *dev)
 {
 	slave_queue_t *queue;
@@ -817,113 +942,6 @@ static int eql_remove_slave_dev(slave_qu
 }
 
 
-static inline struct net_device *eql_best_slave_dev(slave_queue_t *queue)
-{
-	if (queue->best_slave != 0)
-	{
-		if (queue->best_slave->dev != 0)
-			return queue->best_slave->dev;
-		else
-			return 0;
-	}
-	else
-		return 0;
-}
-
-
-static inline slave_t *eql_best_slave(slave_queue_t *queue)
-{
-	return queue->best_slave;
-}
-
-static inline void eql_schedule_slaves(slave_queue_t *queue)
-{
-	struct net_device *master_dev = queue->master_dev;
-	slave_t *best_slave = 0;
-	slave_t *slave_corpse = 0;
-
-#ifdef EQL_DEBUG
-	if (eql_debug >= 100)
-		printk ("%s: schedule %d slaves\n", 
-			master_dev->name, eql_number_slaves (queue));
-#endif
-	if ( eql_is_empty (queue) )
-	{
-		/*
-		 *	No slaves to play with 
-		 */
-		eql_set_best_slave (queue, (slave_t *) 0);
-		return;
-	}
-	else
-	{		
-		/*
-		 *	Make a pass to set the best slave 
-		 */
-		unsigned long best_load = (unsigned long) ULONG_MAX;
-		slave_t *slave = 0;
-		unsigned long flags;
-		int i;
-
-		save_flags(flags);
-		cli ();
-		for (i = 1, slave = eql_first_slave (queue);
-			i <= eql_number_slaves (queue);
-			i++, slave = eql_next_slave (queue, slave))
-		{
-			/*
-			 *	Go through the slave list once, updating best_slave 
-			 *      whenever a new best_load is found, whenever a dead
-			 *	slave is found, it is marked to be pulled out of the 
-			 *	queue 
-			 */
-		
-			unsigned long slave_load;
-			unsigned long bytes_queued; 
-			unsigned long priority_Bps; 
-	  	
-	  		if (slave != 0)
-			{
-				bytes_queued = slave->bytes_queued;
-				priority_Bps = slave->priority_Bps;    
-				if ( slave->dev != 0)
-				{
-					if ((slave->dev->flags & IFF_UP) == IFF_UP )
-					{
-						slave_load = (ULONG_MAX - (ULONG_MAX / 2)) - 
-							(priority_Bps) + bytes_queued * 8;
-
-		      				if (slave_load < best_load)
-						{
-							best_load = slave_load;
-							best_slave = slave;
-						}
-					}
-					else		/* we found a dead slave */
-					{
-						/* 
-						 *	We only bury one slave at a time, if more than
-						 *	one slave dies, we will bury him on the next 
-						 *	reschedule. slaves don't die all at once that 
-						 *	much anyway 
-						 */
-						slave_corpse = slave;
-					}
-				}
-			}
-		} /* for */
-		restore_flags(flags);
-		eql_set_best_slave (queue, best_slave);
-	} /* else */
-	if (slave_corpse != 0)
-	{
-		printk ("eql: scheduler found dead slave, burying...\n");
-		eql_delete_slave (eql_remove_slave (queue, slave_corpse));
-	}
-	return;
-}
-
-
 static slave_t * eql_find_slave_dev(slave_queue_t *queue, struct net_device *dev)
 {
 	slave_t *slave = 0;
@@ -943,22 +961,6 @@ static slave_t * eql_find_slave_dev(slav
 }
 
 
-static inline slave_t *eql_first_slave(slave_queue_t *queue)
-{
-	return queue->head->next;
-}
-
-
-static inline slave_t *eql_next_slave(slave_queue_t *queue, slave_t *slave)
-{
-	return slave->next;
-}
-
-static inline void eql_set_best_slave(slave_queue_t *queue, slave_t *slave)
-{
-	queue->best_slave = slave;
-}
-
 static void eql_timer(unsigned long param)
 {
 	equalizer_t *eql = (equalizer_t *) param;
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/net/fc/iph5526.c linux-2.4.28-pre3/drivers/net/fc/iph5526.c
--- linux-2.4.27/drivers/net/fc/iph5526.c	2003-06-13 14:51:34.000000000 +0000
+++ linux-2.4.28-pre3/drivers/net/fc/iph5526.c	2004-09-10 19:33:16.000000000 +0000
@@ -689,8 +689,8 @@ int index, no_of_entries = 0;
 			prev_IMQ_index = current_IMQ_index;
 		}
 	} /*end of for loop*/		
-	return;
 	LEAVE("tachyon_interrupt");
+       return;
 }
 
 
@@ -2933,7 +2933,7 @@ static void iph5526_timeout(struct net_d
 {
 	struct fc_info *fi = (struct fc_info*)dev->priv;
 	printk(KERN_WARNING "%s: timed out on send.\n", dev->name);
-	fi->fc_stats.rx_dropped++;
+	fi->fc_stats.tx_dropped++;
 	dev->trans_start = jiffies;
 	netif_wake_queue(dev);
 }
@@ -2976,7 +2976,7 @@ static int iph5526_send_packet(struct sk
 		fi->fc_stats.tx_packets++;
 	}
 	else
-		fi->fc_stats.rx_dropped++;
+		fi->fc_stats.tx_dropped++;
 	dev->trans_start = jiffies;
 	/* We free up the IP buffers in the OCI_interrupt handler.
 	 * status == 0 implies that the frame was not transmitted. So the
@@ -3374,8 +3374,8 @@ u_int s_id;
 		q = q->next;
 	}
 	DPRINTK1("Port Name does not match. Txing LOGO.");
-	return 0;
 	LEAVE("validate_login");
+       return 0;
 }
 
 static void add_to_address_cache(struct fc_info *fi, u_int *base_ptr)
@@ -3758,8 +3758,10 @@ struct pci_dev *pdev = NULL;
 		sprintf(fi->name, "fc%d", count);
 
 		host = scsi_register(tmpt, sizeof(struct iph5526_hostdata));
-		if(host==NULL)
+		if(host==NULL) {
+			kfree(fc[count]);
 			return no_of_hosts;
+		}
 			
 		hostdata = (struct iph5526_hostdata *)host->hostdata;
 		memset(hostdata, 0 , sizeof(struct iph5526_hostdata));
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/net/fealnx.c linux-2.4.28-pre3/drivers/net/fealnx.c
--- linux-2.4.27/drivers/net/fealnx.c	2004-08-07 23:26:05.000000000 +0000
+++ linux-2.4.28-pre3/drivers/net/fealnx.c	2004-09-10 19:35:57.000000000 +0000
@@ -1796,7 +1796,7 @@ static void set_rx_mode(struct net_devic
 	unsigned long flags;
 	spin_lock_irqsave(lp, flags);
 	__set_rx_mode(dev);
-	spin_unlock_irqrestore(&lp, flags);
+	spin_unlock_irqrestore(lp, flags);
 }
 
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/net/hamachi.c linux-2.4.28-pre3/drivers/net/hamachi.c
--- linux-2.4.27/drivers/net/hamachi.c	2003-06-13 14:51:34.000000000 +0000
+++ linux-2.4.28-pre3/drivers/net/hamachi.c	2004-09-10 19:37:19.000000000 +0000
@@ -1369,109 +1369,6 @@ static int hamachi_start_xmit(struct sk_
 	return 0;
 }
 
-/* The interrupt handler does all of the Rx thread work and cleans up
-   after the Tx thread. */
-static void hamachi_interrupt(int irq, void *dev_instance, struct pt_regs *rgs)
-{
-	struct net_device *dev = dev_instance;
-	struct hamachi_private *hmp;
-	long ioaddr, boguscnt = max_interrupt_work;
-
-#ifndef final_version			/* Can never occur. */
-	if (dev == NULL) {
-		printk (KERN_ERR "hamachi_interrupt(): irq %d for unknown device.\n", irq);
-		return;
-	}
-#endif
-
-	ioaddr = dev->base_addr;
-	hmp = dev->priv;
-	spin_lock(&hmp->lock);
-
-	do {
-		u32 intr_status = readl(ioaddr + InterruptClear);
-
-		if (hamachi_debug > 4)
-			printk(KERN_DEBUG "%s: Hamachi interrupt, status %4.4x.\n",
-				   dev->name, intr_status);
-
-		if (intr_status == 0)
-			break;
-
-		if (intr_status & IntrRxDone)
-			hamachi_rx(dev);
-
-		if (intr_status & IntrTxDone){
-			/* This code should RARELY need to execute. After all, this is
-			 * a gigabit link, it should consume packets as fast as we put
-			 * them in AND we clear the Tx ring in hamachi_start_xmit().
-			 */ 
-			if (hmp->tx_full){
-				for (; hmp->cur_tx - hmp->dirty_tx > 0; hmp->dirty_tx++){
-					int entry = hmp->dirty_tx % TX_RING_SIZE;
-					struct sk_buff *skb;
-
-					if (hmp->tx_ring[entry].status_n_length & cpu_to_le32(DescOwn)) 
-						break;
-					skb = hmp->tx_skbuff[entry];
-					/* Free the original skb. */
-					if (skb){
-						pci_unmap_single(hmp->pci_dev, 
-							hmp->tx_ring[entry].addr, 
-							skb->len,
-							PCI_DMA_TODEVICE);
-						dev_kfree_skb_irq(skb);
-						hmp->tx_skbuff[entry] = 0;
-					}
-					hmp->tx_ring[entry].status_n_length = 0;
-					if (entry >= TX_RING_SIZE-1)  
-						hmp->tx_ring[TX_RING_SIZE-1].status_n_length |= 
-							cpu_to_le32(DescEndRing);
-					hmp->stats.tx_packets++;
-				}
-				if (hmp->cur_tx - hmp->dirty_tx < TX_RING_SIZE - 4){
-					/* The ring is no longer full */
-					hmp->tx_full = 0;
-					netif_wake_queue(dev);
-				}
-			} else {
-				netif_wake_queue(dev);
-			}
-		}
-
-
-		/* Abnormal error summary/uncommon events handlers. */
-		if (intr_status &
-			(IntrTxPCIFault | IntrTxPCIErr | IntrRxPCIFault | IntrRxPCIErr |
-			 LinkChange | NegotiationChange | StatsMax))
-			hamachi_error(dev, intr_status);
-
-		if (--boguscnt < 0) {
-			printk(KERN_WARNING "%s: Too much work at interrupt, status=0x%4.4x.\n",
-				   dev->name, intr_status);
-			break;
-		}
-	} while (1);
-
-	if (hamachi_debug > 3)
-		printk(KERN_DEBUG "%s: exiting interrupt, status=%#4.4x.\n",
-			   dev->name, readl(ioaddr + IntrStatus));
-
-#ifndef final_version
-	/* Code that should never be run!  Perhaps remove after testing.. */
-	{
-		static int stopit = 10;
-		if (dev->start == 0  &&  --stopit < 0) {
-			printk(KERN_ERR "%s: Emergency stop, looping startup interrupt.\n",
-				   dev->name);
-			free_irq(irq, dev);
-		}
-	}
-#endif
-
-	spin_unlock(&hmp->lock);
-}
-
 /* This routine is logically part of the interrupt handler, but seperated
    for clarity and better register allocation. */
 static int hamachi_rx(struct net_device *dev)
@@ -1677,6 +1574,109 @@ static int hamachi_rx(struct net_device 
 	return 0;
 }
 
+/* The interrupt handler does all of the Rx thread work and cleans up
+   after the Tx thread. */
+static void hamachi_interrupt(int irq, void *dev_instance, struct pt_regs *rgs)
+{
+	struct net_device *dev = dev_instance;
+	struct hamachi_private *hmp;
+	long ioaddr, boguscnt = max_interrupt_work;
+
+#ifndef final_version			/* Can never occur. */
+	if (dev == NULL) {
+		printk (KERN_ERR "hamachi_interrupt(): irq %d for unknown device.\n", irq);
+		return;
+	}
+#endif
+
+	ioaddr = dev->base_addr;
+	hmp = dev->priv;
+	spin_lock(&hmp->lock);
+
+	do {
+		u32 intr_status = readl(ioaddr + InterruptClear);
+
+		if (hamachi_debug > 4)
+			printk(KERN_DEBUG "%s: Hamachi interrupt, status %4.4x.\n",
+				   dev->name, intr_status);
+
+		if (intr_status == 0)
+			break;
+
+		if (intr_status & IntrRxDone)
+			hamachi_rx(dev);
+
+		if (intr_status & IntrTxDone){
+			/* This code should RARELY need to execute. After all, this is
+			 * a gigabit link, it should consume packets as fast as we put
+			 * them in AND we clear the Tx ring in hamachi_start_xmit().
+			 */ 
+			if (hmp->tx_full){
+				for (; hmp->cur_tx - hmp->dirty_tx > 0; hmp->dirty_tx++){
+					int entry = hmp->dirty_tx % TX_RING_SIZE;
+					struct sk_buff *skb;
+
+					if (hmp->tx_ring[entry].status_n_length & cpu_to_le32(DescOwn)) 
+						break;
+					skb = hmp->tx_skbuff[entry];
+					/* Free the original skb. */
+					if (skb){
+						pci_unmap_single(hmp->pci_dev, 
+							hmp->tx_ring[entry].addr, 
+							skb->len,
+							PCI_DMA_TODEVICE);
+						dev_kfree_skb_irq(skb);
+						hmp->tx_skbuff[entry] = 0;
+					}
+					hmp->tx_ring[entry].status_n_length = 0;
+					if (entry >= TX_RING_SIZE-1)  
+						hmp->tx_ring[TX_RING_SIZE-1].status_n_length |= 
+							cpu_to_le32(DescEndRing);
+					hmp->stats.tx_packets++;
+				}
+				if (hmp->cur_tx - hmp->dirty_tx < TX_RING_SIZE - 4){
+					/* The ring is no longer full */
+					hmp->tx_full = 0;
+					netif_wake_queue(dev);
+				}
+			} else {
+				netif_wake_queue(dev);
+			}
+		}
+
+
+		/* Abnormal error summary/uncommon events handlers. */
+		if (intr_status &
+			(IntrTxPCIFault | IntrTxPCIErr | IntrRxPCIFault | IntrRxPCIErr |
+			 LinkChange | NegotiationChange | StatsMax))
+			hamachi_error(dev, intr_status);
+
+		if (--boguscnt < 0) {
+			printk(KERN_WARNING "%s: Too much work at interrupt, status=0x%4.4x.\n",
+				   dev->name, intr_status);
+			break;
+		}
+	} while (1);
+
+	if (hamachi_debug > 3)
+		printk(KERN_DEBUG "%s: exiting interrupt, status=%#4.4x.\n",
+			   dev->name, readl(ioaddr + IntrStatus));
+
+#ifndef final_version
+	/* Code that should never be run!  Perhaps remove after testing.. */
+	{
+		static int stopit = 10;
+		if (dev->start == 0  &&  --stopit < 0) {
+			printk(KERN_ERR "%s: Emergency stop, looping startup interrupt.\n",
+				   dev->name);
+			free_irq(irq, dev);
+		}
+	}
+#endif
+
+	spin_unlock(&hmp->lock);
+}
+
 /* This is more properly named "uncommon interrupt events", as it covers more
    than just errors. */
 static void hamachi_error(struct net_device *dev, int intr_status)
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/net/hamradio/dmascc.c linux-2.4.28-pre3/drivers/net/hamradio/dmascc.c
--- linux-2.4.27/drivers/net/hamradio/dmascc.c	2002-02-25 19:37:59.000000000 +0000
+++ linux-2.4.28-pre3/drivers/net/hamradio/dmascc.c	2004-09-10 19:34:29.000000000 +0000
@@ -356,6 +356,12 @@ void __init dmascc_setup(char *str, int 
 
 #endif
 
+static inline unsigned char random(void) {
+  /* See "Numerical Recipes in C", second edition, p. 284 */
+  rand = rand * 1664525L + 1013904223L;
+  return (unsigned char) (rand >> 24);
+}
+
 
 /* Initialization functions */
 
@@ -950,6 +956,34 @@ static int scc_set_mac_address(struct ne
 }
 
 
+static inline void z8530_isr(struct scc_info *info) {
+  int is, i = 100;
+
+  while ((is = read_scc(&info->priv[0], R3)) && i--) {
+    if (is & CHARxIP) {
+      rx_isr(&info->priv[0]);
+    } else if (is & CHATxIP) {
+      tx_isr(&info->priv[0]);
+    } else if (is & CHAEXT) {
+      es_isr(&info->priv[0]);
+    } else if (is & CHBRxIP) {
+      rx_isr(&info->priv[1]);
+    } else if (is & CHBTxIP) {
+      tx_isr(&info->priv[1]);
+    } else {
+      es_isr(&info->priv[1]);
+    }
+    write_scc(&info->priv[0], R0, RES_H_IUS);
+    i++;
+  }
+  if (i < 0) {
+    printk("dmascc: stuck in ISR with RR3=0x%02x.\n", is);
+  }
+  /* Ok, no interrupts pending from this 8530. The INT line should
+     be inactive now. */
+}
+
+
 static void scc_isr(int irq, void *dev_id, struct pt_regs * regs) {
   struct scc_info *info = dev_id;
 
@@ -983,34 +1017,6 @@ static void scc_isr(int irq, void *dev_i
 }
 
 
-static inline void z8530_isr(struct scc_info *info) {
-  int is, i = 100;
-
-  while ((is = read_scc(&info->priv[0], R3)) && i--) {
-    if (is & CHARxIP) {
-      rx_isr(&info->priv[0]);
-    } else if (is & CHATxIP) {
-      tx_isr(&info->priv[0]);
-    } else if (is & CHAEXT) {
-      es_isr(&info->priv[0]);
-    } else if (is & CHBRxIP) {
-      rx_isr(&info->priv[1]);
-    } else if (is & CHBTxIP) {
-      tx_isr(&info->priv[1]);
-    } else {
-      es_isr(&info->priv[1]);
-    }
-    write_scc(&info->priv[0], R0, RES_H_IUS);
-    i++;
-  }
-  if (i < 0) {
-    printk("dmascc: stuck in ISR with RR3=0x%02x.\n", is);
-  }
-  /* Ok, no interrupts pending from this 8530. The INT line should
-     be inactive now. */
-}
-
-
 static void rx_isr(struct scc_priv *priv) {
   if (priv->param.dma >= 0) {
     /* Check special condition and perform error reset. See 2.4.7.5. */
@@ -1160,6 +1166,90 @@ static void tx_isr(struct scc_priv *priv
 }
 
 
+static inline void tx_on(struct scc_priv *priv) {
+  int i, n;
+  unsigned long flags;
+
+  if (priv->param.dma >= 0) {
+    n = (priv->chip == Z85230) ? 3 : 1;
+    /* Program DMA controller */
+    flags = claim_dma_lock();
+    set_dma_mode(priv->param.dma, DMA_MODE_WRITE);
+    set_dma_addr(priv->param.dma, (int) priv->tx_buf[priv->tx_tail]+n);
+    set_dma_count(priv->param.dma, priv->tx_len[priv->tx_tail]-n);
+    release_dma_lock(flags);
+    /* Enable TX underrun interrupt */
+    write_scc(priv, R15, TxUIE);
+    /* Configure DREQ */
+    if (priv->type == TYPE_TWIN)
+      outb((priv->param.dma == 1) ? TWIN_DMA_HDX_T1 : TWIN_DMA_HDX_T3,
+	   priv->card_base + TWIN_DMA_CFG);
+    else
+      write_scc(priv, R1, EXT_INT_ENAB | WT_FN_RDYFN | WT_RDY_ENAB);
+    /* Write first byte(s) */
+    save_flags(flags);
+    cli();
+    for (i = 0; i < n; i++)
+      write_scc_data(priv, priv->tx_buf[priv->tx_tail][i], 1);
+    enable_dma(priv->param.dma);
+    restore_flags(flags);
+  } else {
+    write_scc(priv, R15, TxUIE);
+    write_scc(priv, R1, EXT_INT_ENAB | WT_FN_RDYFN | TxINT_ENAB);
+    tx_isr(priv);
+  }
+  /* Reset EOM latch if we do not have the AUTOEOM feature */
+  if (priv->chip == Z8530) write_scc(priv, R0, RES_EOM_L);
+}
+
+
+static inline void rx_on(struct scc_priv *priv) {
+  unsigned long flags;
+
+  /* Clear RX FIFO */
+  while (read_scc(priv, R0) & Rx_CH_AV) read_scc_data(priv);
+  priv->rx_over = 0;
+  if (priv->param.dma >= 0) {
+    /* Program DMA controller */
+    flags = claim_dma_lock();
+    set_dma_mode(priv->param.dma, DMA_MODE_READ);
+    set_dma_addr(priv->param.dma, (int) priv->rx_buf[priv->rx_head]);
+    set_dma_count(priv->param.dma, BUF_SIZE);
+    release_dma_lock(flags);
+    enable_dma(priv->param.dma);
+    /* Configure PackeTwin DMA */
+    if (priv->type == TYPE_TWIN) {
+      outb((priv->param.dma == 1) ? TWIN_DMA_HDX_R1 : TWIN_DMA_HDX_R3,
+	   priv->card_base + TWIN_DMA_CFG);
+    }
+    /* Sp. cond. intr. only, ext int enable, RX DMA enable */
+    write_scc(priv, R1, EXT_INT_ENAB | INT_ERR_Rx |
+	      WT_RDY_RT | WT_FN_RDYFN | WT_RDY_ENAB);
+  } else {
+    /* Reset current frame */
+    priv->rx_ptr = 0;
+    /* Intr. on all Rx characters and Sp. cond., ext int enable */
+    write_scc(priv, R1, EXT_INT_ENAB | INT_ALL_Rx | WT_RDY_RT |
+	      WT_FN_RDYFN);
+  }
+  write_scc(priv, R0, ERR_RES);
+  write_scc(priv, R3, RxENABLE | Rx8 | RxCRC_ENAB);
+}
+
+
+static inline void rx_off(struct scc_priv *priv) {
+  /* Disable receiver */
+  write_scc(priv, R3, Rx8);
+  /* Disable DREQ / RX interrupt */
+  if (priv->param.dma >= 0 && priv->type == TYPE_TWIN)
+    outb(0, priv->card_base + TWIN_DMA_CFG);
+  else
+    write_scc(priv, R1, EXT_INT_ENAB | WT_FN_RDYFN);
+  /* Disable DMA */
+  if (priv->param.dma >= 0) disable_dma(priv->param.dma);
+}
+
+
 static void es_isr(struct scc_priv *priv) {
   int i, rr0, drr0, res;
   unsigned long flags;
@@ -1301,90 +1391,6 @@ static void tm_isr(struct scc_priv *priv
 }
 
 
-static inline void tx_on(struct scc_priv *priv) {
-  int i, n;
-  unsigned long flags;
-
-  if (priv->param.dma >= 0) {
-    n = (priv->chip == Z85230) ? 3 : 1;
-    /* Program DMA controller */
-    flags = claim_dma_lock();
-    set_dma_mode(priv->param.dma, DMA_MODE_WRITE);
-    set_dma_addr(priv->param.dma, (int) priv->tx_buf[priv->tx_tail]+n);
-    set_dma_count(priv->param.dma, priv->tx_len[priv->tx_tail]-n);
-    release_dma_lock(flags);
-    /* Enable TX underrun interrupt */
-    write_scc(priv, R15, TxUIE);
-    /* Configure DREQ */
-    if (priv->type == TYPE_TWIN)
-      outb((priv->param.dma == 1) ? TWIN_DMA_HDX_T1 : TWIN_DMA_HDX_T3,
-	   priv->card_base + TWIN_DMA_CFG);
-    else
-      write_scc(priv, R1, EXT_INT_ENAB | WT_FN_RDYFN | WT_RDY_ENAB);
-    /* Write first byte(s) */
-    save_flags(flags);
-    cli();
-    for (i = 0; i < n; i++)
-      write_scc_data(priv, priv->tx_buf[priv->tx_tail][i], 1);
-    enable_dma(priv->param.dma);
-    restore_flags(flags);
-  } else {
-    write_scc(priv, R15, TxUIE);
-    write_scc(priv, R1, EXT_INT_ENAB | WT_FN_RDYFN | TxINT_ENAB);
-    tx_isr(priv);
-  }
-  /* Reset EOM latch if we do not have the AUTOEOM feature */
-  if (priv->chip == Z8530) write_scc(priv, R0, RES_EOM_L);
-}
-
-
-static inline void rx_on(struct scc_priv *priv) {
-  unsigned long flags;
-
-  /* Clear RX FIFO */
-  while (read_scc(priv, R0) & Rx_CH_AV) read_scc_data(priv);
-  priv->rx_over = 0;
-  if (priv->param.dma >= 0) {
-    /* Program DMA controller */
-    flags = claim_dma_lock();
-    set_dma_mode(priv->param.dma, DMA_MODE_READ);
-    set_dma_addr(priv->param.dma, (int) priv->rx_buf[priv->rx_head]);
-    set_dma_count(priv->param.dma, BUF_SIZE);
-    release_dma_lock(flags);
-    enable_dma(priv->param.dma);
-    /* Configure PackeTwin DMA */
-    if (priv->type == TYPE_TWIN) {
-      outb((priv->param.dma == 1) ? TWIN_DMA_HDX_R1 : TWIN_DMA_HDX_R3,
-	   priv->card_base + TWIN_DMA_CFG);
-    }
-    /* Sp. cond. intr. only, ext int enable, RX DMA enable */
-    write_scc(priv, R1, EXT_INT_ENAB | INT_ERR_Rx |
-	      WT_RDY_RT | WT_FN_RDYFN | WT_RDY_ENAB);
-  } else {
-    /* Reset current frame */
-    priv->rx_ptr = 0;
-    /* Intr. on all Rx characters and Sp. cond., ext int enable */
-    write_scc(priv, R1, EXT_INT_ENAB | INT_ALL_Rx | WT_RDY_RT |
-	      WT_FN_RDYFN);
-  }
-  write_scc(priv, R0, ERR_RES);
-  write_scc(priv, R3, RxENABLE | Rx8 | RxCRC_ENAB);
-}
-
-
-static inline void rx_off(struct scc_priv *priv) {
-  /* Disable receiver */
-  write_scc(priv, R3, Rx8);
-  /* Disable DREQ / RX interrupt */
-  if (priv->param.dma >= 0 && priv->type == TYPE_TWIN)
-    outb(0, priv->card_base + TWIN_DMA_CFG);
-  else
-    write_scc(priv, R1, EXT_INT_ENAB | WT_FN_RDYFN);
-  /* Disable DMA */
-  if (priv->param.dma >= 0) disable_dma(priv->param.dma);
-}
-
-
 static void start_timer(struct scc_priv *priv, int t, int r15) {
   unsigned long flags;
 
@@ -1404,10 +1410,3 @@ static void start_timer(struct scc_priv 
   }
 }
 
-
-static inline unsigned char random(void) {
-  /* See "Numerical Recipes in C", second edition, p. 284 */
-  rand = rand * 1664525L + 1013904223L;
-  return (unsigned char) (rand >> 24);
-}
-
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/net/irda/ma600.c linux-2.4.28-pre3/drivers/net/irda/ma600.c
--- linux-2.4.27/drivers/net/irda/ma600.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.28-pre3/drivers/net/irda/ma600.c	2004-09-10 19:33:27.000000000 +0000
@@ -48,7 +48,7 @@
 	#undef IRDA_DEBUG
 	#define IRDA_DEBUG(n, args...) (printk(KERN_DEBUG args))
 
-	#undef ASSERT(expr, func)
+	#undef ASSERT
 	#define ASSERT(expr, func) \
 	if(!(expr)) { \
 		printk( "Assertion failed! %s,%s,%s,line=%d\n",\
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/net/irda/nsc-ircc.c linux-2.4.28-pre3/drivers/net/irda/nsc-ircc.c
--- linux-2.4.27/drivers/net/irda/nsc-ircc.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.28-pre3/drivers/net/irda/nsc-ircc.c	2004-09-10 19:31:52.000000000 +0000
@@ -6,8 +6,8 @@
  * Status:        Stable.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Sat Nov  7 21:43:15 1998
- * Modified at:   Wed Mar  1 11:29:34 2000
- * Modified by:   Dag Brattli <dagb@cs.uit.no>
+ * Modified at:   Sat Aug 14 04:14:57 2004
+ * Modified by:   Maik Broemme <mbroemme@plusserver.de>
  * 
  *     Copyright (c) 1998-2000 Dag Brattli <dagb@cs.uit.no>
  *     Copyright (c) 1998 Lichen Wang, <lwang@actisys.com>
@@ -369,15 +369,22 @@ static int nsc_ircc_open(int i, chipio_t
 	}
 	MESSAGE("IrDA: Registered device %s\n", dev->name);
 
-	/* Check if user has supplied the dongle id or not */
+	/* Check if user has supplied the dongle id and if it is in the range of available ids or not. */
 	if (!dongle_id) {
 		dongle_id = nsc_ircc_read_dongle_id(self->io.fir_base);
 		
 		MESSAGE("%s, Found dongle: %s\n", driver_name,
 			dongle_types[dongle_id]);
 	} else {
-		MESSAGE("%s, Using dongle: %s\n", driver_name,
-			dongle_types[dongle_id]);
+		if (dongle_id < sizeof(dongle_types) / sizeof(dongle_types[0])) {
+			MESSAGE("%s, Using dongle: %s\n", driver_name,
+				dongle_types[dongle_id]);
+		} else {
+			MESSAGE("%s, dongle id %i out of range, start autodetect.\n", driver_name, dongle_id);
+			dongle_id = nsc_ircc_read_dongle_id(self->io.fir_base);
+			MESSAGE("%s, Found dongle: %s\n", driver_name,
+				dongle_types[dongle_id]);
+		}
 	}
 	
 	self->io.dongle_id = dongle_id;
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/net/ne2k-pci.c linux-2.4.28-pre3/drivers/net/ne2k-pci.c
--- linux-2.4.27/drivers/net/ne2k-pci.c	2004-04-14 13:05:30.000000000 +0000
+++ linux-2.4.28-pre3/drivers/net/ne2k-pci.c	2004-09-10 19:33:14.000000000 +0000
@@ -505,8 +505,12 @@ static void ne2k_pci_block_input(struct 
 		insl(NE_BASE + NE_DATAPORT, buf, count>>2);
 		if (count & 3) {
 			buf += count & ~3;
-			if (count & 2)
-				*((u16*)buf)++ = le16_to_cpu(inw(NE_BASE + NE_DATAPORT));
+			if (count & 2) {
+				u16 *b = (u16 *)buf;
+
+				*b++ = le16_to_cpu(inw(NE_BASE + NE_DATAPORT));
+				buf = (char *)b;
+			}
 			if (count & 1)
 				*buf = inb(NE_BASE + NE_DATAPORT);
 		}
@@ -566,8 +570,12 @@ static void ne2k_pci_block_output(struct
 		outsl(NE_BASE + NE_DATAPORT, buf, count>>2);
 		if (count & 3) {
 			buf += count & ~3;
-			if (count & 2)
-				outw(cpu_to_le16(*((u16*)buf)++), NE_BASE + NE_DATAPORT);
+			if (count & 2) {
+				u16 *b = (u16 *)buf;
+
+				outw(cpu_to_le16(*b++), NE_BASE + NE_DATAPORT);
+				buf = (char *)b;
+			}
 		}
 	}
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/net/ns83820.c linux-2.4.28-pre3/drivers/net/ns83820.c
--- linux-2.4.27/drivers/net/ns83820.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.28-pre3/drivers/net/ns83820.c	2004-09-10 19:37:07.000000000 +0000
@@ -587,7 +587,7 @@ static inline int rx_refill(struct ns838
 }
 
 static void FASTCALL(rx_refill_atomic(struct ns83820 *dev));
-static void rx_refill_atomic(struct ns83820 *dev)
+static void fastcall rx_refill_atomic(struct ns83820 *dev)
 {
 	rx_refill(dev, GFP_ATOMIC);
 }
@@ -608,7 +608,7 @@ static inline void clear_rx_desc(struct 
 }
 
 static void FASTCALL(phy_intr(struct ns83820 *dev));
-static void phy_intr(struct ns83820 *dev)
+static void fastcall phy_intr(struct ns83820 *dev)
 {
 	static char *speeds[] = { "10", "100", "1000", "1000(?)", "1000F" };
 	u32 cfg, new_cfg;
@@ -793,7 +793,7 @@ static void ns83820_cleanup_rx(struct ns
 }
 
 static void FASTCALL(ns83820_rx_kick(struct ns83820 *dev));
-static void ns83820_rx_kick(struct ns83820 *dev)
+static void fastcall ns83820_rx_kick(struct ns83820 *dev)
 {
 	/*if (nr_rx_empty(dev) >= NR_RX_DESC/4)*/ {
 		if (dev->rx_info.up) {
@@ -814,7 +814,7 @@ static void ns83820_rx_kick(struct ns838
  *	
  */
 static void FASTCALL(rx_irq(struct ns83820 *dev));
-static void rx_irq(struct ns83820 *dev)
+static void fastcall rx_irq(struct ns83820 *dev)
 {
 	struct rx_info *info = &dev->rx_info;
 	unsigned next_rx;
@@ -1585,6 +1585,7 @@ static void ns83820_run_bist(struct ns83
 	dprintk("%s: done %s in %d loops\n", dev->net_dev.name, name, loops);
 }
 
+#ifdef PHY_CODE_IS_FINISHED
 static void ns83820_mii_write_bit(struct ns83820 *dev, int bit)
 {
 	/* drive MDC low */
@@ -1757,6 +1758,7 @@ static void ns83820_probe_phy(struct ns8
 		dprintk("version: 0x%04x 0x%04x\n", a, b);
 	}
 }
+#endif
 
 static int __devinit ns83820_init_one(struct pci_dev *pci_dev, const struct pci_device_id *id)
 {
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/net/smc9194.c linux-2.4.28-pre3/drivers/net/smc9194.c
--- linux-2.4.27/drivers/net/smc9194.c	2003-06-13 14:51:35.000000000 +0000
+++ linux-2.4.28-pre3/drivers/net/smc9194.c	2004-09-10 19:36:12.000000000 +0000
@@ -1132,131 +1132,6 @@ static void smc_timeout(struct net_devic
 	netif_wake_queue(dev);
 }
 
-/*--------------------------------------------------------------------
- .
- . This is the main routine of the driver, to handle the device when
- . it needs some attention.
- .
- . So:
- .   first, save state of the chipset
- .   branch off into routines to handle each case, and acknowledge
- .	    each to the interrupt register
- .   and finally restore state.
- .
- ---------------------------------------------------------------------*/
-
-static void smc_interrupt(int irq, void * dev_id,  struct pt_regs * regs)
-{
-	struct net_device *dev 	= dev_id;
-	int ioaddr 		= dev->base_addr;
-	struct smc_local *lp 	= (struct smc_local *)dev->priv;
-
-	byte	status;
-	word	card_stats;
-	byte	mask;
-	int	timeout;
-	/* state registers */
-	word	saved_bank;
-	word	saved_pointer;
-
-
-
-	PRINTK3((CARDNAME": SMC interrupt started \n"));
-
-	saved_bank = inw( ioaddr + BANK_SELECT );
-
-	SMC_SELECT_BANK(2);
-	saved_pointer = inw( ioaddr + POINTER );
-
-	mask = inb( ioaddr + INT_MASK );
-	/* clear all interrupts */
-	outb( 0, ioaddr + INT_MASK );
-
-
-	/* set a timeout value, so I don't stay here forever */
-	timeout = 4;
-
-	PRINTK2((KERN_WARNING CARDNAME ": MASK IS %x \n", mask ));
-	do {
-		/* read the status flag, and mask it */
-		status = inb( ioaddr + INTERRUPT ) & mask;
-		if (!status )
-			break;
-
-		PRINTK3((KERN_WARNING CARDNAME
-			": Handling interrupt status %x \n", status ));
-
-		if (status & IM_RCV_INT) {
-			/* Got a packet(s). */
-			PRINTK2((KERN_WARNING CARDNAME
-				": Receive Interrupt\n"));
-			smc_rcv(dev);
-		} else if (status & IM_TX_INT ) {
-			PRINTK2((KERN_WARNING CARDNAME
-				": TX ERROR handled\n"));
-			smc_tx(dev);
-			outb(IM_TX_INT, ioaddr + INTERRUPT );
-		} else if (status & IM_TX_EMPTY_INT ) {
-			/* update stats */
-			SMC_SELECT_BANK( 0 );
-			card_stats = inw( ioaddr + COUNTER );
-			/* single collisions */
-			lp->stats.collisions += card_stats & 0xF;
-			card_stats >>= 4;
-			/* multiple collisions */
-			lp->stats.collisions += card_stats & 0xF;
-
-			/* these are for when linux supports these statistics */
-
-			SMC_SELECT_BANK( 2 );
-			PRINTK2((KERN_WARNING CARDNAME
-				": TX_BUFFER_EMPTY handled\n"));
-			outb( IM_TX_EMPTY_INT, ioaddr + INTERRUPT );
-			mask &= ~IM_TX_EMPTY_INT;
-			lp->stats.tx_packets += lp->packets_waiting;
-			lp->packets_waiting = 0;
-
-		} else if (status & IM_ALLOC_INT ) {
-			PRINTK2((KERN_DEBUG CARDNAME
-				": Allocation interrupt \n"));
-			/* clear this interrupt so it doesn't happen again */
-			mask &= ~IM_ALLOC_INT;
-
-			smc_hardware_send_packet( dev );
-
-			/* enable xmit interrupts based on this */
-			mask |= ( IM_TX_EMPTY_INT | IM_TX_INT );
-
-			/* and let the card send more packets to me */
-			netif_wake_queue(dev);
-			
-			PRINTK2((CARDNAME": Handoff done successfully.\n"));
-		} else if (status & IM_RX_OVRN_INT ) {
-			lp->stats.rx_errors++;
-			lp->stats.rx_fifo_errors++;
-			outb( IM_RX_OVRN_INT, ioaddr + INTERRUPT );
-		} else if (status & IM_EPH_INT ) {
-			PRINTK((CARDNAME ": UNSUPPORTED: EPH INTERRUPT \n"));
-		} else if (status & IM_ERCV_INT ) {
-			PRINTK((CARDNAME ": UNSUPPORTED: ERCV INTERRUPT \n"));
-			outb( IM_ERCV_INT, ioaddr + INTERRUPT );
-		}
-	} while ( timeout -- );
-
-
-	/* restore state register */
-	SMC_SELECT_BANK( 2 );
-	outb( mask, ioaddr + INT_MASK );
-
-	PRINTK3(( KERN_WARNING CARDNAME ": MASK is now %x \n", mask ));
-	outw( saved_pointer, ioaddr + POINTER );
-
-	SMC_SELECT_BANK( saved_bank );
-
-	PRINTK3((CARDNAME ": Interrupt done\n"));
-	return;
-}
-
 /*-------------------------------------------------------------
  .
  . smc_rcv -  receive a packet from the card
@@ -1448,6 +1323,131 @@ static void smc_tx( struct net_device * 
 	return;
 }
 
+/*--------------------------------------------------------------------
+ .
+ . This is the main routine of the driver, to handle the device when
+ . it needs some attention.
+ .
+ . So:
+ .   first, save state of the chipset
+ .   branch off into routines to handle each case, and acknowledge
+ .	    each to the interrupt register
+ .   and finally restore state.
+ .
+ ---------------------------------------------------------------------*/
+
+static void smc_interrupt(int irq, void * dev_id,  struct pt_regs * regs)
+{
+	struct net_device *dev 	= dev_id;
+	int ioaddr 		= dev->base_addr;
+	struct smc_local *lp 	= (struct smc_local *)dev->priv;
+
+	byte	status;
+	word	card_stats;
+	byte	mask;
+	int	timeout;
+	/* state registers */
+	word	saved_bank;
+	word	saved_pointer;
+
+
+
+	PRINTK3((CARDNAME": SMC interrupt started \n"));
+
+	saved_bank = inw( ioaddr + BANK_SELECT );
+
+	SMC_SELECT_BANK(2);
+	saved_pointer = inw( ioaddr + POINTER );
+
+	mask = inb( ioaddr + INT_MASK );
+	/* clear all interrupts */
+	outb( 0, ioaddr + INT_MASK );
+
+
+	/* set a timeout value, so I don't stay here forever */
+	timeout = 4;
+
+	PRINTK2((KERN_WARNING CARDNAME ": MASK IS %x \n", mask ));
+	do {
+		/* read the status flag, and mask it */
+		status = inb( ioaddr + INTERRUPT ) & mask;
+		if (!status )
+			break;
+
+		PRINTK3((KERN_WARNING CARDNAME
+			": Handling interrupt status %x \n", status ));
+
+		if (status & IM_RCV_INT) {
+			/* Got a packet(s). */
+			PRINTK2((KERN_WARNING CARDNAME
+				": Receive Interrupt\n"));
+			smc_rcv(dev);
+		} else if (status & IM_TX_INT ) {
+			PRINTK2((KERN_WARNING CARDNAME
+				": TX ERROR handled\n"));
+			smc_tx(dev);
+			outb(IM_TX_INT, ioaddr + INTERRUPT );
+		} else if (status & IM_TX_EMPTY_INT ) {
+			/* update stats */
+			SMC_SELECT_BANK( 0 );
+			card_stats = inw( ioaddr + COUNTER );
+			/* single collisions */
+			lp->stats.collisions += card_stats & 0xF;
+			card_stats >>= 4;
+			/* multiple collisions */
+			lp->stats.collisions += card_stats & 0xF;
+
+			/* these are for when linux supports these statistics */
+
+			SMC_SELECT_BANK( 2 );
+			PRINTK2((KERN_WARNING CARDNAME
+				": TX_BUFFER_EMPTY handled\n"));
+			outb( IM_TX_EMPTY_INT, ioaddr + INTERRUPT );
+			mask &= ~IM_TX_EMPTY_INT;
+			lp->stats.tx_packets += lp->packets_waiting;
+			lp->packets_waiting = 0;
+
+		} else if (status & IM_ALLOC_INT ) {
+			PRINTK2((KERN_DEBUG CARDNAME
+				": Allocation interrupt \n"));
+			/* clear this interrupt so it doesn't happen again */
+			mask &= ~IM_ALLOC_INT;
+
+			smc_hardware_send_packet( dev );
+
+			/* enable xmit interrupts based on this */
+			mask |= ( IM_TX_EMPTY_INT | IM_TX_INT );
+
+			/* and let the card send more packets to me */
+			netif_wake_queue(dev);
+			
+			PRINTK2((CARDNAME": Handoff done successfully.\n"));
+		} else if (status & IM_RX_OVRN_INT ) {
+			lp->stats.rx_errors++;
+			lp->stats.rx_fifo_errors++;
+			outb( IM_RX_OVRN_INT, ioaddr + INTERRUPT );
+		} else if (status & IM_EPH_INT ) {
+			PRINTK((CARDNAME ": UNSUPPORTED: EPH INTERRUPT \n"));
+		} else if (status & IM_ERCV_INT ) {
+			PRINTK((CARDNAME ": UNSUPPORTED: ERCV INTERRUPT \n"));
+			outb( IM_ERCV_INT, ioaddr + INTERRUPT );
+		}
+	} while ( timeout -- );
+
+
+	/* restore state register */
+	SMC_SELECT_BANK( 2 );
+	outb( mask, ioaddr + INT_MASK );
+
+	PRINTK3(( KERN_WARNING CARDNAME ": MASK is now %x \n", mask ));
+	outw( saved_pointer, ioaddr + POINTER );
+
+	SMC_SELECT_BANK( saved_bank );
+
+	PRINTK3((CARDNAME ": Interrupt done\n"));
+	return;
+}
+
 /*----------------------------------------------------
  . smc_close
  .
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/net/sungem.c linux-2.4.28-pre3/drivers/net/sungem.c
--- linux-2.4.27/drivers/net/sungem.c	2004-04-14 13:05:30.000000000 +0000
+++ linux-2.4.28-pre3/drivers/net/sungem.c	2004-09-10 19:37:02.000000000 +0000
@@ -2920,7 +2920,7 @@ static int __devinit gem_init_one(struct
 	 */
 	if (pdev->vendor == PCI_VENDOR_ID_SUN &&
 	    pdev->device == PCI_DEVICE_ID_SUN_GEM &&
-	    !pci_set_dma_mask(pdev, (u64) 0xffffffffffffffff)) {
+	    !pci_set_dma_mask(pdev, (u64) 0xffffffffffffffffULL)) {
 		pci_using_dac = 1;
 	} else {
 		err = pci_set_dma_mask(pdev, (u64) 0xffffffff);
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/net/sungem.h linux-2.4.28-pre3/drivers/net/sungem.h
--- linux-2.4.27/drivers/net/sungem.h	2002-08-03 00:39:44.000000000 +0000
+++ linux-2.4.28-pre3/drivers/net/sungem.h	2004-09-10 19:35:17.000000000 +0000
@@ -805,14 +805,14 @@ struct gem_txd {
 	u64	buffer;
 };
 
-#define TXDCTRL_BUFSZ	0x0000000000007fff	/* Buffer Size		*/
-#define TXDCTRL_CSTART	0x00000000001f8000	/* CSUM Start Offset	*/
-#define TXDCTRL_COFF	0x000000001fe00000	/* CSUM Stuff Offset	*/
-#define TXDCTRL_CENAB	0x0000000020000000	/* CSUM Enable		*/
-#define TXDCTRL_EOF	0x0000000040000000	/* End of Frame		*/
-#define TXDCTRL_SOF	0x0000000080000000	/* Start of Frame	*/
-#define TXDCTRL_INTME	0x0000000100000000	/* "Interrupt Me"	*/
-#define TXDCTRL_NOCRC	0x0000000200000000	/* No CRC Present	*/
+#define TXDCTRL_BUFSZ	0x0000000000007fffULL	/* Buffer Size		*/
+#define TXDCTRL_CSTART	0x00000000001f8000ULL	/* CSUM Start Offset	*/
+#define TXDCTRL_COFF	0x000000001fe00000ULL	/* CSUM Stuff Offset	*/
+#define TXDCTRL_CENAB	0x0000000020000000ULL	/* CSUM Enable		*/
+#define TXDCTRL_EOF	0x0000000040000000ULL	/* End of Frame		*/
+#define TXDCTRL_SOF	0x0000000080000000ULL	/* Start of Frame	*/
+#define TXDCTRL_INTME	0x0000000100000000ULL	/* "Interrupt Me"	*/
+#define TXDCTRL_NOCRC	0x0000000200000000ULL	/* No CRC Present	*/
 
 /* GEM requires that RX descriptors are provided four at a time,
  * aligned.  Also, the RX ring may not wrap around.  This means that
@@ -840,13 +840,13 @@ struct gem_rxd {
 	u64	buffer;
 };
 
-#define RXDCTRL_TCPCSUM	0x000000000000ffff	/* TCP Pseudo-CSUM	*/
-#define RXDCTRL_BUFSZ	0x000000007fff0000	/* Buffer Size		*/
-#define RXDCTRL_OWN	0x0000000080000000	/* GEM owns this entry	*/
-#define RXDCTRL_HASHVAL	0x0ffff00000000000	/* Hash Value		*/
-#define RXDCTRL_HPASS	0x1000000000000000	/* Passed Hash Filter	*/
-#define RXDCTRL_ALTMAC	0x2000000000000000	/* Matched ALT MAC	*/
-#define RXDCTRL_BAD	0x4000000000000000	/* Frame has bad CRC	*/
+#define RXDCTRL_TCPCSUM	0x000000000000ffffULL	/* TCP Pseudo-CSUM	*/
+#define RXDCTRL_BUFSZ	0x000000007fff0000ULL	/* Buffer Size		*/
+#define RXDCTRL_OWN	0x0000000080000000ULL	/* GEM owns this entry	*/
+#define RXDCTRL_HASHVAL	0x0ffff00000000000ULL	/* Hash Value		*/
+#define RXDCTRL_HPASS	0x1000000000000000ULL	/* Passed Hash Filter	*/
+#define RXDCTRL_ALTMAC	0x2000000000000000ULL	/* Matched ALT MAC	*/
+#define RXDCTRL_BAD	0x4000000000000000ULL	/* Frame has bad CRC	*/
 
 #define RXDCTRL_FRESH(gp)	\
 	((((RX_BUF_ALLOC_SIZE(gp) - RX_OFFSET) << 16) & RXDCTRL_BUFSZ) | \
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/net/tg3.c linux-2.4.28-pre3/drivers/net/tg3.c
--- linux-2.4.27/drivers/net/tg3.c	2004-08-07 23:26:05.000000000 +0000
+++ linux-2.4.28-pre3/drivers/net/tg3.c	2004-09-10 19:34:21.000000000 +0000
@@ -4,6 +4,9 @@
  * Copyright (C) 2001, 2002, 2003, 2004 David S. Miller (davem@redhat.com)
  * Copyright (C) 2001, 2002, 2003 Jeff Garzik (jgarzik@pobox.com)
  * Copyright (C) 2004 Sun Microsystems Inc.
+ *
+ * Firmware is:
+ * 	Copyright (C) 2000-2003 Broadcom Corporation.
  */
 
 #include <linux/config.h>
@@ -56,8 +59,8 @@
 
 #define DRV_MODULE_NAME		"tg3"
 #define PFX DRV_MODULE_NAME	": "
-#define DRV_MODULE_VERSION	"3.8"
-#define DRV_MODULE_RELDATE	"July 14, 2004"
+#define DRV_MODULE_VERSION	"3.9"
+#define DRV_MODULE_RELDATE	"August 30, 2004"
 
 #define TG3_DEF_MAC_MODE	0
 #define TG3_DEF_RX_MODE		0
@@ -441,9 +444,14 @@ static void tg3_switch_clocks(struct tg3
 		       0x1f);
 	tp->pci_clock_ctrl = clock_ctrl;
 
-	if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705 &&
-	    GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5750 &&
-	    (orig_clock_ctrl & CLOCK_CTRL_44MHZ_CORE) != 0) {
+	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 ||
+	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750) {
+		if (orig_clock_ctrl & CLOCK_CTRL_625_CORE) {
+			tw32_f(TG3PCI_CLOCK_CTRL,
+			       clock_ctrl | CLOCK_CTRL_625_CORE);
+			udelay(40);
+		}
+	} else if ((orig_clock_ctrl & CLOCK_CTRL_44MHZ_CORE) != 0) {
 		tw32_f(TG3PCI_CLOCK_CTRL,
 		     clock_ctrl |
 		     (CLOCK_CTRL_44MHZ_CORE | CLOCK_CTRL_ALTCLK));
@@ -979,7 +987,7 @@ static int tg3_set_power_state(struct tg
 		tp->link_config.orig_autoneg = tp->link_config.autoneg;
 	}
 
-	if (tp->phy_id != PHY_ID_SERDES) {
+	if (!(tp->tg3_flags2 & TG3_FLG2_PHY_SERDES)) {
 		tp->link_config.speed = SPEED_10;
 		tp->link_config.duplex = DUPLEX_HALF;
 		tp->link_config.autoneg = AUTONEG_ENABLE;
@@ -991,7 +999,7 @@ static int tg3_set_power_state(struct tg
 	if (tp->tg3_flags & TG3_FLAG_WOL_ENABLE) {
 		u32 mac_mode;
 
-		if (tp->phy_id != PHY_ID_SERDES) {
+		if (!(tp->tg3_flags2 & TG3_FLG2_PHY_SERDES)) {
 			tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x5a);
 			udelay(40);
 
@@ -1486,6 +1494,18 @@ static int tg3_setup_copper_phy(struct t
 	current_speed = SPEED_INVALID;
 	current_duplex = DUPLEX_INVALID;
 
+	if (tp->tg3_flags2 & TG3_FLG2_CAPACITIVE_COUPLING) {
+		u32 val;
+
+		tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x4007);
+		tg3_readphy(tp, MII_TG3_AUX_CTRL, &val);
+		if (!(val & (1 << 10))) {
+			val |= (1 << 10);
+			tg3_writephy(tp, MII_TG3_AUX_CTRL, val);
+			goto relink;
+		}
+	}
+
 	bmsr = 0;
 	for (i = 0; i < 100; i++) {
 		tg3_readphy(tp, MII_BMSR, &bmsr);
@@ -1565,7 +1585,7 @@ static int tg3_setup_copper_phy(struct t
 			tg3_setup_flow_control(tp, local_adv, remote_adv);
 		}
 	}
-
+relink:
 	if (current_link_up == 0) {
 		u32 tmp;
 
@@ -1615,7 +1635,7 @@ static int tg3_setup_copper_phy(struct t
 	tw32_f(MAC_MODE, tp->mac_mode);
 	udelay(40);
 
-	if (tp->tg3_flags & (TG3_FLAG_USE_LINKCHG_REG | TG3_FLAG_POLL_SERDES)) {
+	if (tp->tg3_flags & TG3_FLAG_USE_LINKCHG_REG) {
 		/* Polled via timer. */
 		tw32_f(MAC_EVENT, 0);
 	} else {
@@ -1964,62 +1984,264 @@ static int tg3_fiber_aneg_smachine(struc
 static int fiber_autoneg(struct tg3 *tp, u32 *flags)
 {
 	int res = 0;
+	struct tg3_fiber_aneginfo aninfo;
+	int status = ANEG_FAILED;
+	unsigned int tick;
+	u32 tmp;
 
-	if (tp->tg3_flags2 & TG3_FLG2_HW_AUTONEG) {
-		u32 dig_status;
+	tw32_f(MAC_TX_AUTO_NEG, 0);
 
-		dig_status = tr32(SG_DIG_STATUS);
-		*flags = 0;
-		if (dig_status & SG_DIG_PARTNER_ASYM_PAUSE)
-			*flags |= MR_LP_ADV_ASYM_PAUSE;
-		if (dig_status & SG_DIG_PARTNER_PAUSE_CAPABLE)
-			*flags |= MR_LP_ADV_SYM_PAUSE;
-
-		if ((dig_status & SG_DIG_AUTONEG_COMPLETE) &&
-		    !(dig_status & (SG_DIG_AUTONEG_ERROR |
-				    SG_DIG_PARTNER_FAULT_MASK)))
-			res = 1;
-	} else {
-		struct tg3_fiber_aneginfo aninfo;
-		int status = ANEG_FAILED;
-		unsigned int tick;
-		u32 tmp;
+	tmp = tp->mac_mode & ~MAC_MODE_PORT_MODE_MASK;
+	tw32_f(MAC_MODE, tmp | MAC_MODE_PORT_MODE_GMII);
+	udelay(40);
 
-		tw32_f(MAC_TX_AUTO_NEG, 0);
+	tw32_f(MAC_MODE, tp->mac_mode | MAC_MODE_SEND_CONFIGS);
+	udelay(40);
 
-		tmp = tp->mac_mode & ~MAC_MODE_PORT_MODE_MASK;
-		tw32_f(MAC_MODE, tmp | MAC_MODE_PORT_MODE_GMII);
-		udelay(40);
+	memset(&aninfo, 0, sizeof(aninfo));
+	aninfo.flags |= MR_AN_ENABLE;
+	aninfo.state = ANEG_STATE_UNKNOWN;
+	aninfo.cur_time = 0;
+	tick = 0;
+	while (++tick < 195000) {
+		status = tg3_fiber_aneg_smachine(tp, &aninfo);
+		if (status == ANEG_DONE || status == ANEG_FAILED)
+			break;
 
-		tw32_f(MAC_MODE, tp->mac_mode | MAC_MODE_SEND_CONFIGS);
-		udelay(40);
+		udelay(1);
+	}
 
-		memset(&aninfo, 0, sizeof(aninfo));
-		aninfo.flags |= MR_AN_ENABLE;
-		aninfo.state = ANEG_STATE_UNKNOWN;
-		aninfo.cur_time = 0;
-		tick = 0;
-		while (++tick < 195000) {
-			status = tg3_fiber_aneg_smachine(tp, &aninfo);
-			if (status == ANEG_DONE || status == ANEG_FAILED)
-				break;
+	tp->mac_mode &= ~MAC_MODE_SEND_CONFIGS;
+	tw32_f(MAC_MODE, tp->mac_mode);
+	udelay(40);
 
-			udelay(1);
+	*flags = aninfo.flags;
+
+	if (status == ANEG_DONE &&
+	    (aninfo.flags & (MR_AN_COMPLETE | MR_LINK_OK |
+			     MR_LP_ADV_FULL_DUPLEX)))
+		res = 1;
+
+	return res;
+}
+
+static void tg3_init_bcm8002(struct tg3 *tp)
+{
+	u32 mac_status = tr32(MAC_STATUS);
+	int i;
+
+	/* Reset when initting first time or we have a link. */
+	if ((tp->tg3_flags & TG3_FLAG_INIT_COMPLETE) &&
+	    !(mac_status & MAC_STATUS_PCS_SYNCED))
+		return;
+
+	/* Set PLL lock range. */
+	tg3_writephy(tp, 0x16, 0x8007);
+
+	/* SW reset */
+	tg3_writephy(tp, MII_BMCR, BMCR_RESET);
+
+	/* Wait for reset to complete. */
+	/* XXX schedule_timeout() ... */
+	for (i = 0; i < 500; i++)
+		udelay(10);
+
+	/* Config mode; select PMA/Ch 1 regs. */
+	tg3_writephy(tp, 0x10, 0x8411);
+
+	/* Enable auto-lock and comdet, select txclk for tx. */
+	tg3_writephy(tp, 0x11, 0x0a10);
+
+	tg3_writephy(tp, 0x18, 0x00a0);
+	tg3_writephy(tp, 0x16, 0x41ff);
+
+	/* Assert and deassert POR. */
+	tg3_writephy(tp, 0x13, 0x0400);
+	udelay(40);
+	tg3_writephy(tp, 0x13, 0x0000);
+
+	tg3_writephy(tp, 0x11, 0x0a50);
+	udelay(40);
+	tg3_writephy(tp, 0x11, 0x0a10);
+
+	/* Wait for signal to stabilize */
+	/* XXX schedule_timeout() ... */
+	for (i = 0; i < 15000; i++)
+		udelay(10);
+
+	/* Deselect the channel register so we can read the PHYID
+	 * later.
+	 */
+	tg3_writephy(tp, 0x10, 0x8011);
+}
+
+static int tg3_setup_fiber_hw_autoneg(struct tg3 *tp, u32 mac_status)
+{
+	u32 sg_dig_ctrl, sg_dig_status;
+	u32 serdes_cfg, expected_sg_dig_ctrl;
+	int workaround, port_a;
+	int current_link_up;
+
+	serdes_cfg = 0;
+	expected_sg_dig_ctrl = 0;
+	workaround = 0;
+	port_a = 1;
+	current_link_up = 0;
+
+	if (tp->pci_chip_rev_id != CHIPREV_ID_5704_A0 &&
+	    tp->pci_chip_rev_id != CHIPREV_ID_5704_A1) {
+		workaround = 1;
+		if (tr32(TG3PCI_DUAL_MAC_CTRL) & DUAL_MAC_CTRL_ID)
+			port_a = 0;
+
+		serdes_cfg = tr32(MAC_SERDES_CFG) &
+			((1 << 23) | (1 << 22) | (1 << 21) | (1 << 20));
+	}
+
+	sg_dig_ctrl = tr32(SG_DIG_CTRL);
+
+	if (tp->link_config.autoneg != AUTONEG_ENABLE) {
+		if (sg_dig_ctrl & (1 << 31)) {
+			if (workaround) {
+				u32 val = serdes_cfg;
+
+				if (port_a)
+					val |= 0xc010880;
+				else
+					val |= 0x4010880;
+				tw32_f(MAC_SERDES_CFG, val);
+			}
+			tw32_f(SG_DIG_CTRL, 0x01388400);
 		}
+		if (mac_status & MAC_STATUS_PCS_SYNCED) {
+			tg3_setup_flow_control(tp, 0, 0);
+			current_link_up = 1;
+		}
+		goto out;
+	}
 
-		tp->mac_mode &= ~MAC_MODE_SEND_CONFIGS;
-		tw32_f(MAC_MODE, tp->mac_mode);
-		udelay(40);
+	/* Want auto-negotiation.  */
+	expected_sg_dig_ctrl = 0x81388400;
+
+	/* Pause capability */
+	expected_sg_dig_ctrl |= (1 << 11);
 
-		*flags = aninfo.flags;
+	/* Asymettric pause */
+	expected_sg_dig_ctrl |= (1 << 12);
 
-		if (status == ANEG_DONE &&
-		    (aninfo.flags & (MR_AN_COMPLETE | MR_LINK_OK |
-				     MR_LP_ADV_FULL_DUPLEX)))
-			res = 1;
+	if (sg_dig_ctrl != expected_sg_dig_ctrl) {
+		if (workaround)
+			tw32_f(MAC_SERDES_CFG, serdes_cfg | 0xc011880);
+		tw32_f(SG_DIG_CTRL, expected_sg_dig_ctrl | (1 << 30));
+		udelay(5);
+		tw32_f(SG_DIG_CTRL, expected_sg_dig_ctrl);
+
+		tp->tg3_flags2 |= TG3_FLG2_PHY_JUST_INITTED;
+	} else if (mac_status & (MAC_STATUS_PCS_SYNCED |
+				 MAC_STATUS_SIGNAL_DET)) {
+		sg_dig_status = tr32(SG_DIG_STATUS);
+
+		if ((sg_dig_status & (1 << 1)) &&
+		    (mac_status & MAC_STATUS_PCS_SYNCED)) {
+			u32 local_adv, remote_adv;
+
+			local_adv = ADVERTISE_PAUSE_CAP;
+			remote_adv = 0;
+			if (sg_dig_status & (1 << 19))
+				remote_adv |= LPA_PAUSE_CAP;
+			if (sg_dig_status & (1 << 20))
+				remote_adv |= LPA_PAUSE_ASYM;
+
+			tg3_setup_flow_control(tp, local_adv, remote_adv);
+			current_link_up = 1;
+			tp->tg3_flags2 &= ~TG3_FLG2_PHY_JUST_INITTED;
+		} else if (!(sg_dig_status & (1 << 1))) {
+			if (tp->tg3_flags2 & TG3_FLG2_PHY_JUST_INITTED)
+				tp->tg3_flags2 &= ~TG3_FLG2_PHY_JUST_INITTED;
+			else {
+				if (workaround) {
+					u32 val = serdes_cfg;
+
+					if (port_a)
+						val |= 0xc010880;
+					else
+						val |= 0x4010880;
+
+					tw32_f(MAC_SERDES_CFG, serdes_cfg);
+				}
+
+				tw32_f(SG_DIG_CTRL, 0x01388400);
+				udelay(40);
+
+				mac_status = tr32(MAC_STATUS);
+				if (mac_status & MAC_STATUS_PCS_SYNCED) {
+					tg3_setup_flow_control(tp, 0, 0);
+					current_link_up = 1;
+				}
+			}
+		}
 	}
 
-	return res;
+out:
+	return current_link_up;
+}
+
+static int tg3_setup_fiber_by_hand(struct tg3 *tp, u32 mac_status)
+{
+	int current_link_up = 0;
+
+ 	if (!(mac_status & MAC_STATUS_PCS_SYNCED)) {
+		tp->tg3_flags &= ~TG3_FLAG_GOT_SERDES_FLOWCTL;
+		goto out;
+	}
+
+	if (tp->link_config.autoneg == AUTONEG_ENABLE) {
+		u32 flags;
+		int i;
+  
+		if (fiber_autoneg(tp, &flags)) {
+			u32 local_adv, remote_adv;
+
+			local_adv = ADVERTISE_PAUSE_CAP;
+			remote_adv = 0;
+			if (flags & MR_LP_ADV_SYM_PAUSE)
+				remote_adv |= LPA_PAUSE_CAP;
+			if (flags & MR_LP_ADV_ASYM_PAUSE)
+				remote_adv |= LPA_PAUSE_ASYM;
+
+			tg3_setup_flow_control(tp, local_adv, remote_adv);
+
+			tp->tg3_flags |= TG3_FLAG_GOT_SERDES_FLOWCTL;
+			current_link_up = 1;
+		}
+		for (i = 0; i < 30; i++) {
+			udelay(20);
+			tw32_f(MAC_STATUS,
+			       (MAC_STATUS_SYNC_CHANGED |
+				MAC_STATUS_CFG_CHANGED));
+			udelay(40);
+			if ((tr32(MAC_STATUS) &
+			     (MAC_STATUS_SYNC_CHANGED |
+			      MAC_STATUS_CFG_CHANGED)) == 0)
+				break;
+		}
+
+		mac_status = tr32(MAC_STATUS);
+		if (current_link_up == 0 &&
+		    (mac_status & MAC_STATUS_PCS_SYNCED) &&
+		    !(mac_status & MAC_STATUS_RCVD_CFG))
+			current_link_up = 1;
+	} else {
+		/* Forcing 1000FD link up. */
+		current_link_up = 1;
+		tp->tg3_flags |= TG3_FLAG_GOT_SERDES_FLOWCTL;
+
+		tw32_f(MAC_MODE, (tp->mac_mode | MAC_MODE_SEND_CONFIGS));
+		udelay(40);
+	}
+
+out:
+	return current_link_up;
 }
 
 static int tg3_setup_fiber_phy(struct tg3 *tp, int force_reset)
@@ -2027,6 +2249,7 @@ static int tg3_setup_fiber_phy(struct tg
 	u32 orig_pause_cfg;
 	u16 orig_active_speed;
 	u8 orig_active_duplex;
+	u32 mac_status;
 	int current_link_up;
 	int i;
 
@@ -2036,118 +2259,43 @@ static int tg3_setup_fiber_phy(struct tg
 	orig_active_speed = tp->link_config.active_speed;
 	orig_active_duplex = tp->link_config.active_duplex;
 
-	tp->mac_mode &= ~(MAC_MODE_PORT_MODE_MASK | MAC_MODE_HALF_DUPLEX);
-	tp->mac_mode |= MAC_MODE_PORT_MODE_TBI;
-	tw32_f(MAC_MODE, tp->mac_mode);
-	udelay(40);
-
-	if (tp->tg3_flags2 & TG3_FLG2_HW_AUTONEG) {
-		/* Allow time for the hardware to auto-negotiate (195ms) */
-		unsigned int tick = 0;
-
-		while (++tick < 195000) { 
-			if (tr32(SG_DIG_STATUS) & SG_DIG_AUTONEG_COMPLETE)
-				break;
-			udelay(1);
+	if (!(tp->tg3_flags2 & TG3_FLG2_HW_AUTONEG) &&
+	    netif_carrier_ok(tp->dev) &&
+	    (tp->tg3_flags & TG3_FLAG_INIT_COMPLETE)) {
+		mac_status = tr32(MAC_STATUS);
+		mac_status &= (MAC_STATUS_PCS_SYNCED |
+			       MAC_STATUS_SIGNAL_DET |
+			       MAC_STATUS_CFG_CHANGED |
+			       MAC_STATUS_RCVD_CFG);
+		if (mac_status == (MAC_STATUS_PCS_SYNCED |
+				   MAC_STATUS_SIGNAL_DET)) {
+			tw32_f(MAC_STATUS, (MAC_STATUS_SYNC_CHANGED |
+					    MAC_STATUS_CFG_CHANGED));
+			return 0;
 		}
-		if (tick >= 195000)
-			printk(KERN_INFO PFX "%s: HW autoneg failed !\n",
-			    tp->dev->name);
 	}
 
-	/* Reset when initting first time or we have a link. */
-	if (!(tp->tg3_flags & TG3_FLAG_INIT_COMPLETE) ||
-	    (tr32(MAC_STATUS) & MAC_STATUS_PCS_SYNCED)) {
-		/* Set PLL lock range. */
-		tg3_writephy(tp, 0x16, 0x8007);
-
-		/* SW reset */
-		tg3_writephy(tp, MII_BMCR, BMCR_RESET);
-
-		/* Wait for reset to complete. */
-		/* XXX schedule_timeout() ... */
-		for (i = 0; i < 500; i++)
-			udelay(10);
-
-		/* Config mode; select PMA/Ch 1 regs. */
-		tg3_writephy(tp, 0x10, 0x8411);
-
-		/* Enable auto-lock and comdet, select txclk for tx. */
-		tg3_writephy(tp, 0x11, 0x0a10);
-
-		tg3_writephy(tp, 0x18, 0x00a0);
-		tg3_writephy(tp, 0x16, 0x41ff);
-
-		/* Assert and deassert POR. */
-		tg3_writephy(tp, 0x13, 0x0400);
-		udelay(40);
-		tg3_writephy(tp, 0x13, 0x0000);
+	tw32_f(MAC_TX_AUTO_NEG, 0);
 
-		tg3_writephy(tp, 0x11, 0x0a50);
-		udelay(40);
-		tg3_writephy(tp, 0x11, 0x0a10);
+	tp->mac_mode &= ~(MAC_MODE_PORT_MODE_MASK | MAC_MODE_HALF_DUPLEX);
+	tp->mac_mode |= MAC_MODE_PORT_MODE_TBI;
+	tw32_f(MAC_MODE, tp->mac_mode);
+	udelay(40);
 
-		/* Wait for signal to stabilize */
-		/* XXX schedule_timeout() ... */
-		for (i = 0; i < 15000; i++)
-			udelay(10);
+	if (tp->phy_id == PHY_ID_BCM8002)
+		tg3_init_bcm8002(tp);
 
-		/* Deselect the channel register so we can read the PHYID
-		 * later.
-		 */
-		tg3_writephy(tp, 0x10, 0x8011);
-	}
-
-	/* Enable link change interrupt unless serdes polling.  */
-	if (!(tp->tg3_flags & TG3_FLAG_POLL_SERDES))
-		tw32_f(MAC_EVENT, MAC_EVENT_LNKSTATE_CHANGED);
-	else
-		tw32_f(MAC_EVENT, 0);
+	/* Enable link change event even when serdes polling.  */
+	tw32_f(MAC_EVENT, MAC_EVENT_LNKSTATE_CHANGED);
 	udelay(40);
 
 	current_link_up = 0;
- 	if (tr32(MAC_STATUS) & MAC_STATUS_PCS_SYNCED) {
-		if (tp->link_config.autoneg == AUTONEG_ENABLE) {
-			u32 flags;
-  
-			if (fiber_autoneg(tp, &flags)) {
-				u32 local_adv, remote_adv;
-
-				local_adv = ADVERTISE_PAUSE_CAP;
-				remote_adv = 0;
-				if (flags & MR_LP_ADV_SYM_PAUSE)
-  					remote_adv |= LPA_PAUSE_CAP;
-				if (flags & MR_LP_ADV_ASYM_PAUSE)
-					remote_adv |= LPA_PAUSE_ASYM;
+	mac_status = tr32(MAC_STATUS);
 
-				tg3_setup_flow_control(tp, local_adv, remote_adv);
-
-				tp->tg3_flags |=
-					TG3_FLAG_GOT_SERDES_FLOWCTL;
-				current_link_up = 1;
-			}
-			for (i = 0; i < 60; i++) {
-				udelay(20);
-				tw32_f(MAC_STATUS,
-				     (MAC_STATUS_SYNC_CHANGED |
-				      MAC_STATUS_CFG_CHANGED));
-				udelay(40);
-				if ((tr32(MAC_STATUS) &
-				     (MAC_STATUS_SYNC_CHANGED |
-				      MAC_STATUS_CFG_CHANGED)) == 0)
-					break;
-			}
-			if (current_link_up == 0 &&
-			    (tr32(MAC_STATUS) & MAC_STATUS_PCS_SYNCED)) {
-				current_link_up = 1;
-			}
-		} else {
-			/* Forcing 1000FD link up. */
-			current_link_up = 1;
-			tp->tg3_flags |= TG3_FLAG_GOT_SERDES_FLOWCTL;
-		}
-	} else
-		tp->tg3_flags &= ~TG3_FLAG_GOT_SERDES_FLOWCTL;
+	if (tp->tg3_flags2 & TG3_FLG2_HW_AUTONEG)
+		current_link_up = tg3_setup_fiber_hw_autoneg(tp, mac_status);
+	else
+		current_link_up = tg3_setup_fiber_by_hand(tp, mac_status);
 
 	tp->mac_mode &= ~MAC_MODE_LINK_POLARITY;
 	tw32_f(MAC_MODE, tp->mac_mode);
@@ -2158,19 +2306,24 @@ static int tg3_setup_fiber_phy(struct tg
 		 (tp->hw_status->status & ~SD_STATUS_LINK_CHG));
 
 	for (i = 0; i < 100; i++) {
-		udelay(20);
-		tw32_f(MAC_STATUS,
-		     (MAC_STATUS_SYNC_CHANGED |
-		      MAC_STATUS_CFG_CHANGED));
-		udelay(40);
-		if ((tr32(MAC_STATUS) &
-		     (MAC_STATUS_SYNC_CHANGED |
-		      MAC_STATUS_CFG_CHANGED)) == 0)
+		tw32_f(MAC_STATUS, (MAC_STATUS_SYNC_CHANGED |
+				    MAC_STATUS_CFG_CHANGED));
+		udelay(5);
+		if ((tr32(MAC_STATUS) & (MAC_STATUS_SYNC_CHANGED |
+					 MAC_STATUS_CFG_CHANGED)) == 0)
 			break;
 	}
 
-	if ((tr32(MAC_STATUS) & MAC_STATUS_PCS_SYNCED) == 0)
+	mac_status = tr32(MAC_STATUS);
+	if ((mac_status & MAC_STATUS_PCS_SYNCED) == 0) {
 		current_link_up = 0;
+		if (tp->link_config.autoneg == AUTONEG_ENABLE) {
+			tw32_f(MAC_MODE, (tp->mac_mode |
+					  MAC_MODE_SEND_CONFIGS));
+			udelay(1);
+			tw32_f(MAC_MODE, tp->mac_mode);
+		}
+	}
 
 	if (current_link_up == 1) {
 		tp->link_config.active_speed = SPEED_1000;
@@ -2202,15 +2355,6 @@ static int tg3_setup_fiber_phy(struct tg
 			tg3_link_report(tp);
 	}
 
-	if ((tr32(MAC_STATUS) & MAC_STATUS_PCS_SYNCED) == 0) {
-		tw32_f(MAC_MODE, tp->mac_mode | MAC_MODE_LINK_POLARITY);
-		udelay(40);
-		if (tp->tg3_flags & TG3_FLAG_INIT_COMPLETE) {
-			tw32_f(MAC_MODE, tp->mac_mode);
-			udelay(40);
-		}
-	}
-
 	return 0;
 }
 
@@ -2218,7 +2362,7 @@ static int tg3_setup_phy(struct tg3 *tp,
 {
 	int err;
 
-	if (tp->phy_id == PHY_ID_SERDES) {
+	if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) {
 		err = tg3_setup_fiber_phy(tp, force_reset);
 	} else {
 		err = tg3_setup_copper_phy(tp, force_reset);
@@ -2736,11 +2880,11 @@ static void tg3_reset_task(void *_data)
 	tg3_halt(tp);
 	tg3_init_hw(tp);
 
+	tg3_netif_start(tp);
+
 	spin_unlock(&tp->tx_lock);
 	spin_unlock_irq(&tp->lock);
 
-	tg3_netif_start(tp);
-
 	if (restart_timer)
 		mod_timer(&tp->timer, jiffies + 1);
 }
@@ -3100,9 +3244,10 @@ static int tg3_change_mtu(struct net_dev
 
 	tg3_init_hw(tp);
 
+	tg3_netif_start(tp);
+
 	spin_unlock(&tp->tx_lock);
 	spin_unlock_irq(&tp->lock);
-	tg3_netif_start(tp);
 
 	return 0;
 }
@@ -3593,6 +3738,8 @@ static void tg3_write_sig_legacy(struct 
 	}
 }
 
+static void tg3_stop_fw(struct tg3 *);
+
 /* tp->lock is held. */
 static int tg3_chip_reset(struct tg3 *tp)
 {
@@ -3695,6 +3842,11 @@ static int tg3_chip_reset(struct tg3 *tp
 
 	tw32(MEMARB_MODE, MEMARB_MODE_ENABLE);
 
+	if (tp->pci_chip_rev_id == CHIPREV_ID_5750_A3) {
+		tg3_stop_fw(tp);
+		tw32(0x5000, 0x400);
+	}
+
 	tw32(GRC_MODE, tp->grc_mode);
 
 	if (tp->pci_chip_rev_id == CHIPREV_ID_5705_A0) {
@@ -3711,7 +3863,7 @@ static int tg3_chip_reset(struct tg3 *tp
 		tw32(TG3PCI_CLOCK_CTRL, tp->pci_clock_ctrl);
 	}
 
-	if (tp->phy_id == PHY_ID_SERDES) {
+	if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) {
 		tp->mac_mode = MAC_MODE_PORT_MODE_TBI;
 		tw32_f(MAC_MODE, tp->mac_mode);
 	} else
@@ -5241,14 +5393,14 @@ static int tg3_reset_hw(struct tg3 *tp)
 	tw32(MAC_LED_CTRL, tp->led_ctrl);
 
 	tw32(MAC_MI_STAT, MAC_MI_STAT_LNKSTAT_ATTN_ENAB);
-	if (tp->phy_id == PHY_ID_SERDES) {
+	if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) {
 		tw32_f(MAC_RX_MODE, RX_MODE_RESET);
 		udelay(10);
 	}
 	tw32_f(MAC_RX_MODE, tp->rx_mode);
 	udelay(10);
 
-	if (tp->phy_id == PHY_ID_SERDES) {
+	if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) {
 		if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) {
 			/* Set drive transmission level to 1.2V  */
 			val = tr32(MAC_SERDES_CFG);
@@ -5266,22 +5418,8 @@ static int tg3_reset_hw(struct tg3 *tp)
 	tw32_f(MAC_LOW_WMARK_MAX_RX_FRAME, 2);
 
 	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704 &&
-	    tp->phy_id == PHY_ID_SERDES) {
-		/* Enable hardware link auto-negotiation */
-		u32 digctrl, txctrl;
-
-		digctrl = SG_DIG_USING_HW_AUTONEG | SG_DIG_CRC16_CLEAR_N |
-		    SG_DIG_LOCAL_DUPLEX_STATUS | SG_DIG_LOCAL_LINK_STATUS |
-		    (2 << SG_DIG_SPEED_STATUS_SHIFT) | SG_DIG_FIBER_MODE |
-		    SG_DIG_GBIC_ENABLE;
-
-		txctrl = tr32(MAC_SERDES_CFG);
-		tw32_f(MAC_SERDES_CFG, txctrl | MAC_SERDES_CFG_EDGE_SELECT);
-		tw32_f(SG_DIG_CTRL, digctrl | SG_DIG_SOFT_RESET);
-		tr32(SG_DIG_CTRL);
-		udelay(5);
-		tw32_f(SG_DIG_CTRL, digctrl);
-
+	    (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES)) {
+		/* Use hardware link auto-negotiation */
 		tp->tg3_flags2 |= TG3_FLG2_HW_AUTONEG;
 	}
 
@@ -5289,7 +5427,7 @@ static int tg3_reset_hw(struct tg3 *tp)
 	if (err)
 		return err;
 
-	if (tp->phy_id != PHY_ID_SERDES) {
+	if (!(tp->tg3_flags2 & TG3_FLG2_PHY_SERDES)) {
 		u32 tmp;
 
 		/* Clear CRC stats. */
@@ -5481,7 +5619,8 @@ static void tg3_timer(unsigned long __op
 				need_setup = 1;
 			}
 			if (! netif_carrier_ok(tp->dev) &&
-			    (mac_stat & MAC_STATUS_PCS_SYNCED)) {
+			    (mac_stat & (MAC_STATUS_PCS_SYNCED |
+					 MAC_STATUS_SIGNAL_DET))) {
 				need_setup = 1;
 			}
 			if (need_setup) {
@@ -5877,7 +6016,7 @@ static unsigned long calc_crc_errors(str
 {
 	struct tg3_hw_stats *hw_stats = tp->hw_stats;
 
-	if (tp->phy_id != PHY_ID_SERDES &&
+	if (!(tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) &&
 	    (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 ||
 	     GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701)) {
 		unsigned long flags;
@@ -6308,7 +6447,7 @@ static int tg3_get_settings(struct net_d
 		cmd->supported |= (SUPPORTED_1000baseT_Half |
 				   SUPPORTED_1000baseT_Full);
 
-	if (tp->phy_id != PHY_ID_SERDES)
+	if (!(tp->tg3_flags2 & TG3_FLG2_PHY_SERDES))
 		cmd->supported |= (SUPPORTED_100baseT_Half |
 				  SUPPORTED_100baseT_Full |
 				  SUPPORTED_10baseT_Half |
@@ -6337,7 +6476,7 @@ static int tg3_set_settings(struct net_d
 	    tp->link_config.phy_is_low_power)
 		return -EAGAIN;
 
-	if (tp->phy_id == PHY_ID_SERDES) {
+	if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) {
 		/* These are the only valid advertisement bits allowed.  */
 		if (cmd->autoneg == AUTONEG_ENABLE &&
 		    (cmd->advertising & ~(ADVERTISED_1000baseT_Half |
@@ -6395,7 +6534,7 @@ static int tg3_set_wol(struct net_device
 	if (wol->wolopts & ~WAKE_MAGIC)
 		return -EINVAL;
 	if ((wol->wolopts & WAKE_MAGIC) &&
-	    tp->phy_id == PHY_ID_SERDES &&
+	    tp->tg3_flags2 & TG3_FLG2_PHY_SERDES &&
 	    !(tp->tg3_flags & TG3_FLAG_SERDES_WOL_CAP))
 		return -EINVAL;
   
@@ -6491,10 +6630,9 @@ static int tg3_set_ringparam(struct net_
 
 	tg3_halt(tp);
 	tg3_init_hw(tp);
-	netif_wake_queue(tp->dev);
+	tg3_netif_start(tp);
 	spin_unlock(&tp->tx_lock);
 	spin_unlock_irq(&tp->lock);
-	tg3_netif_start(tp);
   
 	return 0;
 }
@@ -6529,9 +6667,9 @@ static int tg3_set_pauseparam(struct net
 		tp->tg3_flags &= ~TG3_FLAG_PAUSE_TX;
 	tg3_halt(tp);
 	tg3_init_hw(tp);
+	tg3_netif_start(tp);
 	spin_unlock(&tp->tx_lock);
 	spin_unlock_irq(&tp->lock);
-	tg3_netif_start(tp);
   
 	return 0;
 }
@@ -6618,7 +6756,7 @@ static int tg3_ioctl(struct net_device *
 	case SIOCGMIIREG: {
 		u32 mii_regval;
 
-		if (tp->phy_id == PHY_ID_SERDES)
+		if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES)
 			break;			/* We have no PHY */
 
 		spin_lock_irq(&tp->lock);
@@ -6631,7 +6769,7 @@ static int tg3_ioctl(struct net_device *
 	}
 
 	case SIOCSMIIREG:
-		if (tp->phy_id == PHY_ID_SERDES)
+		if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES)
 			break;			/* We have no PHY */
 
 		if (!capable(CAP_NET_ADMIN))
@@ -6868,10 +7006,10 @@ static struct subsys_tbl_ent subsys_id_t
 	{ PCI_VENDOR_ID_BROADCOM, 0x1644, PHY_ID_BCM5401 }, /* BCM95700A6 */
 	{ PCI_VENDOR_ID_BROADCOM, 0x0001, PHY_ID_BCM5701 }, /* BCM95701A5 */
 	{ PCI_VENDOR_ID_BROADCOM, 0x0002, PHY_ID_BCM8002 }, /* BCM95700T6 */
-	{ PCI_VENDOR_ID_BROADCOM, 0x0003, PHY_ID_SERDES  }, /* BCM95700A9 */
+	{ PCI_VENDOR_ID_BROADCOM, 0x0003, 0 },		    /* BCM95700A9 */
 	{ PCI_VENDOR_ID_BROADCOM, 0x0005, PHY_ID_BCM5701 }, /* BCM95701T1 */
 	{ PCI_VENDOR_ID_BROADCOM, 0x0006, PHY_ID_BCM5701 }, /* BCM95701T8 */
-	{ PCI_VENDOR_ID_BROADCOM, 0x0007, PHY_ID_SERDES  }, /* BCM95701A7 */
+	{ PCI_VENDOR_ID_BROADCOM, 0x0007, 0 },		    /* BCM95701A7 */
 	{ PCI_VENDOR_ID_BROADCOM, 0x0008, PHY_ID_BCM5701 }, /* BCM95701A10 */
 	{ PCI_VENDOR_ID_BROADCOM, 0x8008, PHY_ID_BCM5701 }, /* BCM95701A12 */
 	{ PCI_VENDOR_ID_BROADCOM, 0x0009, PHY_ID_BCM5703 }, /* BCM95703Ax1 */
@@ -6880,7 +7018,7 @@ static struct subsys_tbl_ent subsys_id_t
 	/* 3com boards. */
 	{ PCI_VENDOR_ID_3COM, 0x1000, PHY_ID_BCM5401 }, /* 3C996T */
 	{ PCI_VENDOR_ID_3COM, 0x1006, PHY_ID_BCM5701 }, /* 3C996BT */
-	{ PCI_VENDOR_ID_3COM, 0x1004, PHY_ID_SERDES  }, /* 3C996SX */
+	{ PCI_VENDOR_ID_3COM, 0x1004, 0 },		/* 3C996SX */
 	{ PCI_VENDOR_ID_3COM, 0x1007, PHY_ID_BCM5701 }, /* 3C1000T */
 	{ PCI_VENDOR_ID_3COM, 0x1008, PHY_ID_BCM5701 }, /* 3C940BR01 */
 
@@ -6893,37 +7031,43 @@ static struct subsys_tbl_ent subsys_id_t
 	/* Compaq boards. */
 	{ PCI_VENDOR_ID_COMPAQ, 0x007c, PHY_ID_BCM5701 }, /* BANSHEE */
 	{ PCI_VENDOR_ID_COMPAQ, 0x009a, PHY_ID_BCM5701 }, /* BANSHEE_2 */
-	{ PCI_VENDOR_ID_COMPAQ, 0x007d, PHY_ID_SERDES  }, /* CHANGELING */
+	{ PCI_VENDOR_ID_COMPAQ, 0x007d, 0 },		  /* CHANGELING */
 	{ PCI_VENDOR_ID_COMPAQ, 0x0085, PHY_ID_BCM5701 }, /* NC7780 */
 	{ PCI_VENDOR_ID_COMPAQ, 0x0099, PHY_ID_BCM5701 }, /* NC7780_2 */
 
 	/* IBM boards. */
-	{ PCI_VENDOR_ID_IBM, 0x0281, PHY_ID_SERDES } /* IBM??? */
+	{ PCI_VENDOR_ID_IBM, 0x0281, 0 } /* IBM??? */
 };
 
-static int __devinit tg3_phy_probe(struct tg3 *tp)
+static inline struct subsys_tbl_ent *lookup_by_subsys(struct tg3 *tp)
 {
-	u32 eeprom_phy_id, hw_phy_id_1, hw_phy_id_2;
-	u32 hw_phy_id, hw_phy_id_masked;
-	u32 val;
-	int i, eeprom_signature_found, err;
+	int i;
 
-	tp->phy_id = PHY_ID_INVALID;
 	for (i = 0; i < ARRAY_SIZE(subsys_id_to_phy_id); i++) {
 		if ((subsys_id_to_phy_id[i].subsys_vendor ==
 		     tp->pdev->subsystem_vendor) &&
 		    (subsys_id_to_phy_id[i].subsys_devid ==
-		     tp->pdev->subsystem_device)) {
-			tp->phy_id = subsys_id_to_phy_id[i].phy_id;
-			break;
-		}
+		     tp->pdev->subsystem_device))
+			return &subsys_id_to_phy_id[i];
 	}
+	return NULL;
+}
+
+static int __devinit tg3_phy_probe(struct tg3 *tp)
+{
+	u32 eeprom_phy_id, hw_phy_id_1, hw_phy_id_2;
+	u32 hw_phy_id, hw_phy_id_masked;
+	u32 val;
+	int eeprom_signature_found, eeprom_phy_serdes, err;
 
+	tp->phy_id = PHY_ID_INVALID;
 	eeprom_phy_id = PHY_ID_INVALID;
+	eeprom_phy_serdes = 0;
 	eeprom_signature_found = 0;
 	tg3_read_mem(tp, NIC_SRAM_DATA_SIG, &val);
 	if (val == NIC_SRAM_DATA_SIG_MAGIC) {
 		u32 nic_cfg, led_cfg;
+		u32 nic_phy_id, cfg2;
 
 		tg3_read_mem(tp, NIC_SRAM_DATA_CFG, &nic_cfg);
 		tp->nic_sram_data_cfg = nic_cfg;
@@ -6931,21 +7075,19 @@ static int __devinit tg3_phy_probe(struc
 		eeprom_signature_found = 1;
 
 		if ((nic_cfg & NIC_SRAM_DATA_CFG_PHY_TYPE_MASK) ==
-		    NIC_SRAM_DATA_CFG_PHY_TYPE_FIBER) {
-			eeprom_phy_id = PHY_ID_SERDES;
-		} else {
-			u32 nic_phy_id;
+		    NIC_SRAM_DATA_CFG_PHY_TYPE_FIBER)
+			eeprom_phy_serdes = 1;
 
-			tg3_read_mem(tp, NIC_SRAM_DATA_PHY_ID, &nic_phy_id);
-			if (nic_phy_id != 0) {
-				u32 id1 = nic_phy_id & NIC_SRAM_DATA_PHY_ID1_MASK;
-				u32 id2 = nic_phy_id & NIC_SRAM_DATA_PHY_ID2_MASK;
-
-				eeprom_phy_id  = (id1 >> 16) << 10;
-				eeprom_phy_id |= (id2 & 0xfc00) << 16;
-				eeprom_phy_id |= (id2 & 0x03ff) <<  0;
-			}
-		}
+		tg3_read_mem(tp, NIC_SRAM_DATA_PHY_ID, &nic_phy_id);
+		if (nic_phy_id != 0) {
+			u32 id1 = nic_phy_id & NIC_SRAM_DATA_PHY_ID1_MASK;
+			u32 id2 = nic_phy_id & NIC_SRAM_DATA_PHY_ID2_MASK;
+
+			eeprom_phy_id  = (id1 >> 16) << 10;
+			eeprom_phy_id |= (id2 & 0xfc00) << 16;
+			eeprom_phy_id |= (id2 & 0x03ff) <<  0;
+		} else
+			eeprom_phy_id = 0;
 
 		if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750) {
 			tg3_read_mem(tp, NIC_SRAM_DATA_CFG_2, &led_cfg);
@@ -7007,6 +7149,10 @@ static int __devinit tg3_phy_probe(struc
 		}
 		if (nic_cfg & NIC_SRAM_DATA_CFG_FIBER_WOL)
 			tp->tg3_flags |= TG3_FLAG_SERDES_WOL_CAP;
+
+		tg3_read_mem(tp, NIC_SRAM_DATA_PHY_ID, &cfg2);
+		if (cfg2 & (1 << 17))
+			tp->tg3_flags2 |= TG3_FLG2_CAPACITIVE_COUPLING;
 	}
 
 	/* Reading the PHY ID register can conflict with ASF
@@ -7033,20 +7179,31 @@ static int __devinit tg3_phy_probe(struc
 
 	if (!err && KNOWN_PHY_ID(hw_phy_id_masked)) {
 		tp->phy_id = hw_phy_id;
+		if (hw_phy_id_masked == PHY_ID_BCM8002)
+			tp->tg3_flags2 |= TG3_FLG2_PHY_SERDES;
 	} else {
-		/* phy_id currently holds the value found in the
-		 * subsys_id_to_phy_id[] table or PHY_ID_INVALID
-		 * if a match was not found there.
-		 */
-		if (tp->phy_id == PHY_ID_INVALID) {
-			if (!eeprom_signature_found ||
-			    !KNOWN_PHY_ID(eeprom_phy_id & PHY_ID_MASK))
-				return -ENODEV;
+		if (eeprom_signature_found) {
 			tp->phy_id = eeprom_phy_id;
+			if (eeprom_phy_serdes)
+				tp->tg3_flags2 |= TG3_FLG2_PHY_SERDES;
+		} else {
+			struct subsys_tbl_ent *p;
+
+			/* No eeprom signature?  Try the hardcoded
+			 * subsys device table.
+			 */
+			p = lookup_by_subsys(tp);
+			if (!p)
+				return -ENODEV;
+
+			tp->phy_id = p->phy_id;
+			if (!tp->phy_id ||
+			    tp->phy_id == PHY_ID_BCM8002)
+				tp->tg3_flags2 |= TG3_FLG2_PHY_SERDES;
 		}
 	}
 
-	if (tp->phy_id != PHY_ID_SERDES &&
+	if (!(tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) &&
 	    !(tp->tg3_flags & TG3_FLAG_ENABLE_ASF)) {
 		u32 bmsr, adv_reg, tg3_ctrl;
 
@@ -7103,7 +7260,7 @@ skip_phy_reset:
 	if (!eeprom_signature_found)
 		tp->led_ctrl = LED_CTRL_MODE_PHY_1;
 
-	if (tp->phy_id == PHY_ID_SERDES)
+	if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES)
 		tp->link_config.advertising =
 			(ADVERTISED_1000baseT_Half |
 			 ADVERTISED_1000baseT_Full |
@@ -7490,12 +7647,14 @@ static int __devinit tg3_get_invariants(
 	grc_misc_cfg = tr32(GRC_MISC_CFG);
 	grc_misc_cfg &= GRC_MISC_CFG_BOARD_ID_MASK;
 
+	/* Broadcom's driver says that CIOBE multisplit has a bug */
+#if 0
 	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704 &&
 	    grc_misc_cfg == GRC_MISC_CFG_BOARD_ID_5704CIOBE) {
 		tp->tg3_flags |= TG3_FLAG_SPLIT_MODE;
 		tp->split_mode_max_reqs = SPLIT_MODE_5704_MAX_REQ;
 	}
-
+#endif
 	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 &&
 	    (grc_misc_cfg == GRC_MISC_CFG_BOARD_ID_5788 ||
 	     grc_misc_cfg == GRC_MISC_CFG_BOARD_ID_5788M))
@@ -7522,7 +7681,7 @@ static int __devinit tg3_get_invariants(
 
 	tg3_read_partno(tp);
 
-	if (tp->phy_id == PHY_ID_SERDES) {
+	if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) {
 		tp->tg3_flags &= ~TG3_FLAG_USE_MI_INTERRUPT;
 	} else {
 		if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700)
@@ -7545,13 +7704,13 @@ static int __devinit tg3_get_invariants(
 	 * upon subsystem IDs.
 	 */
 	if (tp->pdev->subsystem_vendor == PCI_VENDOR_ID_DELL &&
-	    tp->phy_id != PHY_ID_SERDES) {
+	    !(tp->tg3_flags2 & TG3_FLG2_PHY_SERDES)) {
 		tp->tg3_flags |= (TG3_FLAG_USE_MI_INTERRUPT |
 				  TG3_FLAG_USE_LINKCHG_REG);
 	}
 
 	/* For all SERDES we poll the MAC status register. */
-	if (tp->phy_id == PHY_ID_SERDES)
+	if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES)
 		tp->tg3_flags |= TG3_FLAG_POLL_SERDES;
 	else
 		tp->tg3_flags &= ~TG3_FLAG_POLL_SERDES;
@@ -7987,8 +8146,8 @@ static char * __devinit tg3_phy_string(s
 	case PHY_ID_BCM5704:	return "5704";
 	case PHY_ID_BCM5705:	return "5705";
 	case PHY_ID_BCM5750:	return "5750";
-	case PHY_ID_BCM8002:	return "8002";
-	case PHY_ID_SERDES:	return "serdes";
+	case PHY_ID_BCM8002:	return "8002/serdes";
+	case 0:			return "serdes";
 	default:		return "unknown";
 	};
 }
@@ -8363,11 +8522,11 @@ static int tg3_suspend(struct pci_dev *p
 		tp->timer.expires = jiffies + tp->timer_offset;
 		add_timer(&tp->timer);
 
-		spin_unlock(&tp->tx_lock);
-		spin_unlock_irq(&tp->lock);
-
 		netif_device_attach(dev);
 		tg3_netif_start(tp);
+
+		spin_unlock(&tp->tx_lock);
+		spin_unlock_irq(&tp->lock);
 	}
 
 	return err;
@@ -8400,11 +8559,11 @@ static int tg3_resume(struct pci_dev *pd
 
 	tg3_enable_ints(tp);
 
+	tg3_netif_start(tp);
+
 	spin_unlock(&tp->tx_lock);
 	spin_unlock_irq(&tp->lock);
 
-	tg3_netif_start(tp);
-
 	return 0;
 }
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/net/tg3.h linux-2.4.28-pre3/drivers/net/tg3.h
--- linux-2.4.27/drivers/net/tg3.h	2004-08-07 23:26:05.000000000 +0000
+++ linux-2.4.28-pre3/drivers/net/tg3.h	2004-09-10 19:35:30.000000000 +0000
@@ -124,6 +124,7 @@
 #define  CHIPREV_ID_5705_A3		 0x3003
 #define  CHIPREV_ID_5750_A0		 0x4000
 #define  CHIPREV_ID_5750_A1		 0x4001
+#define  CHIPREV_ID_5750_A3		 0x4003
 #define  GET_ASIC_REV(CHIP_REV_ID)	((CHIP_REV_ID) >> 12)
 #define   ASIC_REV_5700			 0x07
 #define   ASIC_REV_5701			 0x00
@@ -2089,6 +2090,9 @@ struct tg3 {
 #define TG3_FLG2_PCI_EXPRESS		0x00000200
 #define TG3_FLG2_ASF_NEW_HANDSHAKE	0x00000400
 #define TG3_FLG2_HW_AUTONEG		0x00000800
+#define TG3_FLG2_PHY_JUST_INITTED	0x00001000
+#define TG3_FLG2_PHY_SERDES		0x00002000
+#define TG3_FLG2_CAPACITIVE_COUPLING	0x00004000
 
 	u32				split_mode_max_reqs;
 #define SPLIT_MODE_5704_MAX_REQ		3
@@ -2136,7 +2140,6 @@ struct tg3 {
 #define PHY_ID_BCM5705			0x600081a0
 #define PHY_ID_BCM5750			0x60008180
 #define PHY_ID_BCM8002			0x60010140
-#define PHY_ID_SERDES			0xfeedbee0
 #define PHY_ID_INVALID			0xffffffff
 #define PHY_ID_REV_MASK			0x0000000f
 #define PHY_REV_BCM5401_B0		0x1
@@ -2159,7 +2162,7 @@ struct tg3 {
 	 (X) == PHY_ID_BCM5411 || (X) == PHY_ID_BCM5701 || \
 	 (X) == PHY_ID_BCM5703 || (X) == PHY_ID_BCM5704 || \
 	 (X) == PHY_ID_BCM5705 || (X) == PHY_ID_BCM5750 || \
-	 (X) == PHY_ID_BCM8002 || (X) == PHY_ID_SERDES)
+	 (X) == PHY_ID_BCM8002)
 
 	struct tg3_hw_stats		*hw_stats;
 	dma_addr_t			stats_mapping;
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/net/wan/dscc4.c linux-2.4.28-pre3/drivers/net/wan/dscc4.c
--- linux-2.4.27/drivers/net/wan/dscc4.c	2003-11-28 18:26:20.000000000 +0000
+++ linux-2.4.28-pre3/drivers/net/wan/dscc4.c	2004-09-10 19:33:22.000000000 +0000
@@ -351,8 +351,8 @@ struct dscc4_dev_priv {
 #endif
 
 /* Functions prototypes */
-static inline void dscc4_rx_irq(struct dscc4_pci_priv *, struct dscc4_dev_priv *);
-static inline void dscc4_tx_irq(struct dscc4_pci_priv *, struct dscc4_dev_priv *);
+static void dscc4_rx_irq(struct dscc4_pci_priv *, struct dscc4_dev_priv *);
+static void dscc4_tx_irq(struct dscc4_pci_priv *, struct dscc4_dev_priv *);
 static int dscc4_found1(struct pci_dev *, unsigned long ioaddr);
 static int dscc4_init_one(struct pci_dev *, const struct pci_device_id *ent);
 static int dscc4_open(struct net_device *);
@@ -366,7 +366,6 @@ static void dscc4_tx_timeout(struct net_
 static void dscc4_irq(int irq, void *dev_id, struct pt_regs *ptregs);
 static int dscc4_hdlc_attach(hdlc_device *, unsigned short, unsigned short);
 static int dscc4_set_iface(struct dscc4_dev_priv *, struct net_device *);
-static inline int dscc4_set_quartz(struct dscc4_dev_priv *, int);
 #ifdef DSCC4_POLLING
 static int dscc4_tx_poll(struct dscc4_dev_priv *, struct net_device *);
 #endif
@@ -857,6 +856,18 @@ static void dscc4_init_registers(struct 
 	//scc_writel(0x00250008 & ~RxActivate, dpriv, dev, CCR2);
 }
 
+static inline int dscc4_set_quartz(struct dscc4_dev_priv *dpriv, int hz)
+{
+	int ret = 0;
+
+	if ((hz < 0) || (hz > DSCC4_HZ_MAX))
+		ret = -EOPNOTSUPP;
+	else
+		dpriv->pci_priv->xtal_hz = hz;
+
+	return ret;
+}
+
 static int dscc4_found1(struct pci_dev *pdev, unsigned long ioaddr)
 {
 	struct dscc4_pci_priv *ppriv;
@@ -1325,18 +1336,6 @@ static int dscc4_ioctl(struct net_device
 	return ret;
 }
 
-static inline int dscc4_set_quartz(struct dscc4_dev_priv *dpriv, int hz)
-{
-	int ret = 0;
-
-	if ((hz < 0) || (hz > DSCC4_HZ_MAX))
-		ret = -EOPNOTSUPP;
-	else
-		dpriv->pci_priv->xtal_hz = hz;
-
-	return ret;
-}
-
 static int dscc4_match(struct thingie *p, int value)
 {
 	int i;
@@ -1512,7 +1511,7 @@ out:
 	spin_unlock_irqrestore(&priv->lock, flags);
 }
 
-static inline void dscc4_tx_irq(struct dscc4_pci_priv *ppriv,
+static void dscc4_tx_irq(struct dscc4_pci_priv *ppriv,
 				struct dscc4_dev_priv *dpriv)
 {
 	struct net_device *dev = hdlc_to_dev(&dpriv->hdlc);
@@ -1681,7 +1680,7 @@ try:
 	goto try;
 }
 
-static inline void dscc4_rx_irq(struct dscc4_pci_priv *priv,
+static void dscc4_rx_irq(struct dscc4_pci_priv *priv,
 				    struct dscc4_dev_priv *dpriv)
 {
 	struct net_device *dev = hdlc_to_dev(&dpriv->hdlc);
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/net/wan/hd6457x.c linux-2.4.28-pre3/drivers/net/wan/hd6457x.c
--- linux-2.4.27/drivers/net/wan/hd6457x.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.28-pre3/drivers/net/wan/hd6457x.c	2004-09-10 19:33:06.000000000 +0000
@@ -452,8 +452,8 @@ static void sca_set_port(port_t *port)
 			brv >>= 1; /* brv = 2^9 = 512 max in specs */
 
 			/* Baud Rate = CLOCK_BASE / TMC / 2^BR */
-			tmc = CLOCK_BASE / (brv * port->settings.clock_rate);
-		}while(br > 1 && tmc <= 128);
+			tmc = CLOCK_BASE / brv / port->settings.clock_rate;
+		}while (br > 1 && tmc <= 128);
 
 		if (tmc < 1) {
 			tmc = 1;
@@ -462,7 +462,7 @@ static void sca_set_port(port_t *port)
 		} else if (tmc > 255)
 			tmc = 256; /* tmc=0 means 256 - low baud rates */
 
-		port->settings.clock_rate = CLOCK_BASE / (brv * tmc);
+		port->settings.clock_rate = CLOCK_BASE / brv / tmc;
 	} else {
 		br = 9; /* Minimum clock rate */
 		tmc = 256;	/* 8bit = 0 */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/net/wan/lmc/lmc_debug.c linux-2.4.28-pre3/drivers/net/wan/lmc/lmc_debug.c
--- linux-2.4.27/drivers/net/wan/lmc/lmc_debug.c	2002-08-03 00:39:44.000000000 +0000
+++ linux-2.4.28-pre3/drivers/net/wan/lmc/lmc_debug.c	2004-09-10 19:33:40.000000000 +0000
@@ -66,7 +66,7 @@ void lmcEventLog (u_int32_t EventNum, u_
 #endif
 }
 
-inline void lmc_trace(struct net_device *dev, char *msg){
+void lmc_trace(struct net_device *dev, char *msg){
 #ifdef LMC_TRACE
     unsigned long j = jiffies + 3; /* Wait for 50 ms */
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/net/wan/lmc/lmc_debug.h linux-2.4.28-pre3/drivers/net/wan/lmc/lmc_debug.h
--- linux-2.4.27/drivers/net/wan/lmc/lmc_debug.h	2000-04-21 23:08:45.000000000 +0000
+++ linux-2.4.28-pre3/drivers/net/wan/lmc/lmc_debug.h	2004-09-10 19:32:00.000000000 +0000
@@ -47,6 +47,6 @@ extern u_int32_t lmcEventLogBuf[LMC_EVEN
 
 void lmcConsoleLog(char *type, unsigned char *ucData, int iLen);
 void lmcEventLog (u_int32_t EventNum, u_int32_t arg2, u_int32_t arg3);
-inline void lmc_trace(struct net_device *dev, char *msg);
+void lmc_trace(struct net_device *dev, char *msg);
 
 #endif
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/net/wan/pc300_tty.c linux-2.4.28-pre3/drivers/net/wan/pc300_tty.c
--- linux-2.4.27/drivers/net/wan/pc300_tty.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.28-pre3/drivers/net/wan/pc300_tty.c	2004-09-10 19:34:06.000000000 +0000
@@ -702,7 +702,7 @@ static void cpc_tty_rx_task(void * data)
 															
 				if (cpc_tty->tty && (cpc_tty->tty->ldisc.receive_buf)) { 
 					CPC_TTY_DBG("%s: call line disc. receive_buf\n",cpc_tty->name);
-					cpc_tty->tty->ldisc.receive_buf(cpc_tty->tty, buf->data, 
+					cpc_tty->tty->ldisc.receive_buf(cpc_tty->tty, (const unsigned char *)buf->data, 
 													&flags, buf->size);
 				}	
 				cpc_tty->buf_rx.first = cpc_tty->buf_rx.first->next;
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/net/wireless/Config.in linux-2.4.28-pre3/drivers/net/wireless/Config.in
--- linux-2.4.27/drivers/net/wireless/Config.in	2004-04-14 13:05:30.000000000 +0000
+++ linux-2.4.28-pre3/drivers/net/wireless/Config.in	2004-09-10 19:33:35.000000000 +0000
@@ -27,6 +27,15 @@ if [ "$CONFIG_PCMCIA" != "n" ]; then
    dep_tristate '  Atmel at76c502/at76c504 PCMCIA cards' CONFIG_PCMCIA_ATMEL $CONFIG_FW_LOADER
 fi
 
+# If PCI enabled, allow for prism54 driver. CONFIG_FW_LOADER required
+comment 'Prism54 PCI/PCMCIA GT/Duette Driver - 802.11(a/b/g)'
+dep_tristate 'Intersil Prism GT/Duette/Indigo PCI/PCMCIA' CONFIG_PRISM54 $CONFIG_EXPERIMENTAL $CONFIG_PCI $CONFIG_HOTPLUG
+if [ "$CONFIG_PRISM54" != "n" ]; then
+ if [ "$CONFIG_FW_LOADER" != "y" ]; then
+  define_tristate CONFIG_FW_LOADER $CONFIG_PRISM54
+ fi
+fi
+
 # yes, this works even when no drivers are selected
 if [ "$CONFIG_ISA" = "y" -o "$CONFIG_PCI" = "y" -o \
      "$CONFIG_ALL_PPC" = "y" -o "$CONFIG_PCMCIA" != "n" ]; then
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/net/wireless/Makefile linux-2.4.28-pre3/drivers/net/wireless/Makefile
--- linux-2.4.27/drivers/net/wireless/Makefile	2004-04-14 13:05:30.000000000 +0000
+++ linux-2.4.28-pre3/drivers/net/wireless/Makefile	2004-09-10 19:37:30.000000000 +0000
@@ -25,4 +25,9 @@ obj-$(CONFIG_AIRO)		+= airo.o
 obj-$(CONFIG_AIRO_CS)		+= airo_cs.o airo.o
 obj-$(CONFIG_PCMCIA_ATMEL)	+= atmel_cs.o atmel.o
 
+ifeq ($(CONFIG_PRISM54),y)
+obj-$(CONFIG_PRISM54)		+= prism54/prism54.o
+endif
+subdir-$(CONFIG_PRISM54)	+= prism54
+
 include $(TOPDIR)/Rules.make
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/net/wireless/prism54/Makefile linux-2.4.28-pre3/drivers/net/wireless/prism54/Makefile
--- linux-2.4.27/drivers/net/wireless/prism54/Makefile	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.28-pre3/drivers/net/wireless/prism54/Makefile	2004-09-10 19:37:02.000000000 +0000
@@ -0,0 +1,12 @@
+
+O_TARGET := prism54.o
+
+EXTRA_CFLAGS += -DPRISM54_COMPAT24
+
+obj-y		:= isl_38xx.o islpci_dev.o islpci_eth.o \
+		   islpci_mgt.o islpci_hotplug.o isl_ioctl.o \
+		   oid_mgt.o
+
+obj-m		+= prism54.o
+
+include $(TOPDIR)/Rules.make
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/net/wireless/prism54/isl_38xx.c linux-2.4.28-pre3/drivers/net/wireless/prism54/isl_38xx.c
--- linux-2.4.27/drivers/net/wireless/prism54/isl_38xx.c	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.28-pre3/drivers/net/wireless/prism54/isl_38xx.c	2004-09-10 19:37:25.000000000 +0000
@@ -0,0 +1,265 @@
+/*
+ *  
+ *  Copyright (C) 2002 Intersil Americas Inc.
+ *  Copyright (C) 2003-2004 Luis R. Rodriguez <mcgrof@ruslug.rutgers.edu>_
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License
+ *
+ *  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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/delay.h>
+
+#include <asm/uaccess.h>
+#include <asm/io.h>
+
+#include "prismcompat.h"
+#include "isl_38xx.h"
+#include "islpci_dev.h"
+#include "islpci_mgt.h"
+
+/******************************************************************************
+    Device Interface & Control functions
+******************************************************************************/
+
+/**
+ * isl38xx_disable_interrupts - disable all interrupts
+ * @device: pci memory base address
+ *
+ *  Instructs the device to disable all interrupt reporting by asserting 
+ *  the IRQ line. New events may still show up in the interrupt identification
+ *  register located at offset %ISL38XX_INT_IDENT_REG.
+ */
+void
+isl38xx_disable_interrupts(void *device)
+{
+	isl38xx_w32_flush(device, 0x00000000, ISL38XX_INT_EN_REG);
+	udelay(ISL38XX_WRITEIO_DELAY);
+}
+
+void
+isl38xx_handle_sleep_request(isl38xx_control_block *control_block,
+			     int *powerstate, void *device_base)
+{
+	/* device requests to go into sleep mode
+	 * check whether the transmit queues for data and management are empty */
+	if (isl38xx_in_queue(control_block, ISL38XX_CB_TX_DATA_LQ))
+		/* data tx queue not empty */
+		return;
+
+	if (isl38xx_in_queue(control_block, ISL38XX_CB_TX_MGMTQ))
+		/* management tx queue not empty */
+		return;
+
+	/* check also whether received frames are pending */
+	if (isl38xx_in_queue(control_block, ISL38XX_CB_RX_DATA_LQ))
+		/* data rx queue not empty */
+		return;
+
+	if (isl38xx_in_queue(control_block, ISL38XX_CB_RX_MGMTQ))
+		/* management rx queue not empty */
+		return;
+
+#if VERBOSE > SHOW_ERROR_MESSAGES
+	DEBUG(SHOW_TRACING, "Device going to sleep mode\n");
+#endif
+
+	/* all queues are empty, allow the device to go into sleep mode */
+	*powerstate = ISL38XX_PSM_POWERSAVE_STATE;
+
+	/* assert the Sleep interrupt in the Device Interrupt Register */
+	isl38xx_w32_flush(device_base, ISL38XX_DEV_INT_SLEEP,
+			  ISL38XX_DEV_INT_REG);
+	udelay(ISL38XX_WRITEIO_DELAY);
+}
+
+void
+isl38xx_handle_wakeup(isl38xx_control_block *control_block,
+		      int *powerstate, void *device_base)
+{
+	/* device is in active state, update the powerstate flag */
+	*powerstate = ISL38XX_PSM_ACTIVE_STATE;
+
+	/* now check whether there are frames pending for the card */
+	if (!isl38xx_in_queue(control_block, ISL38XX_CB_TX_DATA_LQ)
+	    && !isl38xx_in_queue(control_block, ISL38XX_CB_TX_MGMTQ))
+		return;
+
+#if VERBOSE > SHOW_ERROR_MESSAGES
+	DEBUG(SHOW_ANYTHING, "Wake up handler trigger the device\n");
+#endif
+
+	/* either data or management transmit queue has a frame pending
+	 * trigger the device by setting the Update bit in the Device Int reg */
+	isl38xx_w32_flush(device_base, ISL38XX_DEV_INT_UPDATE,
+			  ISL38XX_DEV_INT_REG);
+	udelay(ISL38XX_WRITEIO_DELAY);
+}
+
+void
+isl38xx_trigger_device(int asleep, void *device_base)
+{
+	struct timeval current_time;
+	u32 reg, counter = 0;
+
+#if VERBOSE > SHOW_ERROR_MESSAGES
+	DEBUG(SHOW_FUNCTION_CALLS, "isl38xx trigger device\n");
+#endif
+
+	/* check whether the device is in power save mode */
+	if (asleep) {
+		/* device is in powersave, trigger the device for wakeup */
+#if VERBOSE > SHOW_ERROR_MESSAGES
+		do_gettimeofday(&current_time);
+		DEBUG(SHOW_TRACING, "%08li.%08li Device wakeup triggered\n",
+		      current_time.tv_sec, current_time.tv_usec);
+#endif
+
+		DEBUG(SHOW_TRACING, "%08li.%08li Device register read %08x\n",
+		      current_time.tv_sec, current_time.tv_usec,
+		      readl(device_base + ISL38XX_CTRL_STAT_REG));
+		udelay(ISL38XX_WRITEIO_DELAY);
+
+		if (reg = readl(device_base + ISL38XX_INT_IDENT_REG),
+		    reg == 0xabadface) {
+#if VERBOSE > SHOW_ERROR_MESSAGES
+			do_gettimeofday(&current_time);
+			DEBUG(SHOW_TRACING,
+			      "%08li.%08li Device register abadface\n",
+			      current_time.tv_sec, current_time.tv_usec);
+#endif
+			/* read the Device Status Register until Sleepmode bit is set */
+			while (reg = readl(device_base + ISL38XX_CTRL_STAT_REG),
+			       (reg & ISL38XX_CTRL_STAT_SLEEPMODE) == 0) {
+				udelay(ISL38XX_WRITEIO_DELAY);
+				counter++;
+			}
+
+			DEBUG(SHOW_TRACING,
+			      "%08li.%08li Device register read %08x\n",
+			      current_time.tv_sec, current_time.tv_usec,
+			      readl(device_base + ISL38XX_CTRL_STAT_REG));
+			udelay(ISL38XX_WRITEIO_DELAY);
+
+#if VERBOSE > SHOW_ERROR_MESSAGES
+			do_gettimeofday(&current_time);
+			DEBUG(SHOW_TRACING,
+			      "%08li.%08li Device asleep counter %i\n",
+			      current_time.tv_sec, current_time.tv_usec,
+			      counter);
+#endif
+		}
+		/* assert the Wakeup interrupt in the Device Interrupt Register */
+		isl38xx_w32_flush(device_base, ISL38XX_DEV_INT_WAKEUP,
+				  ISL38XX_DEV_INT_REG);
+		udelay(ISL38XX_WRITEIO_DELAY);
+
+		/* perform another read on the Device Status Register */
+		reg = readl(device_base + ISL38XX_CTRL_STAT_REG);
+		udelay(ISL38XX_WRITEIO_DELAY);
+
+#if VERBOSE > SHOW_ERROR_MESSAGES
+		do_gettimeofday(&current_time);
+		DEBUG(SHOW_TRACING, "%08li.%08li Device register read %08x\n",
+		      current_time.tv_sec, current_time.tv_usec, reg);
+#endif
+	} else {
+		/* device is (still) awake  */
+#if VERBOSE > SHOW_ERROR_MESSAGES
+		DEBUG(SHOW_TRACING, "Device is in active state\n");
+#endif
+		/* trigger the device by setting the Update bit in the Device Int reg */
+
+		isl38xx_w32_flush(device_base, ISL38XX_DEV_INT_UPDATE,
+				  ISL38XX_DEV_INT_REG);
+		udelay(ISL38XX_WRITEIO_DELAY);
+	}
+}
+
+void
+isl38xx_interface_reset(void *device_base, dma_addr_t host_address)
+{
+	u32 reg;
+
+#if VERBOSE > SHOW_ERROR_MESSAGES
+	DEBUG(SHOW_FUNCTION_CALLS, "isl38xx_interface_reset \n");
+#endif
+
+	/* load the address of the control block in the device */
+	isl38xx_w32_flush(device_base, host_address, ISL38XX_CTRL_BLK_BASE_REG);
+	udelay(ISL38XX_WRITEIO_DELAY);
+
+	/* set the reset bit in the Device Interrupt Register */
+	isl38xx_w32_flush(device_base, ISL38XX_DEV_INT_RESET,
+			  ISL38XX_DEV_INT_REG);
+	udelay(ISL38XX_WRITEIO_DELAY);
+
+	/* enable the interrupt for detecting initialization */
+
+	/* Note: Do not enable other interrupts here. We want the
+	 * device to have come up first 100% before allowing any other 
+	 * interrupts. */
+	reg = ISL38XX_INT_IDENT_INIT;
+
+	isl38xx_w32_flush(device_base, reg, ISL38XX_INT_EN_REG);
+	udelay(ISL38XX_WRITEIO_DELAY);  /* allow complete full reset */
+}
+
+void
+isl38xx_enable_common_interrupts(void *device_base) {
+	u32 reg;
+	reg = ( ISL38XX_INT_IDENT_UPDATE | 
+			ISL38XX_INT_IDENT_SLEEP | ISL38XX_INT_IDENT_WAKEUP);
+	isl38xx_w32_flush(device_base, reg, ISL38XX_INT_EN_REG);
+	udelay(ISL38XX_WRITEIO_DELAY);
+}
+
+int
+isl38xx_in_queue(isl38xx_control_block *cb, int queue)
+{
+	const s32 delta = (le32_to_cpu(cb->driver_curr_frag[queue]) -
+			   le32_to_cpu(cb->device_curr_frag[queue]));
+
+	/* determine the amount of fragments in the queue depending on the type
+	 * of the queue, either transmit or receive */
+
+	BUG_ON(delta < 0);	/* driver ptr must be ahead of device ptr */
+
+	switch (queue) {
+		/* send queues */
+	case ISL38XX_CB_TX_MGMTQ:
+		BUG_ON(delta > ISL38XX_CB_MGMT_QSIZE);
+	case ISL38XX_CB_TX_DATA_LQ:
+	case ISL38XX_CB_TX_DATA_HQ:
+		BUG_ON(delta > ISL38XX_CB_TX_QSIZE);
+		return delta;
+		break;
+
+		/* receive queues */
+	case ISL38XX_CB_RX_MGMTQ:
+		BUG_ON(delta > ISL38XX_CB_MGMT_QSIZE);
+		return ISL38XX_CB_MGMT_QSIZE - delta;
+		break;
+
+	case ISL38XX_CB_RX_DATA_LQ:
+	case ISL38XX_CB_RX_DATA_HQ:
+		BUG_ON(delta > ISL38XX_CB_RX_QSIZE);
+		return ISL38XX_CB_RX_QSIZE - delta;
+		break;
+	}
+	BUG();
+	return 0;
+}
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/net/wireless/prism54/isl_38xx.h linux-2.4.28-pre3/drivers/net/wireless/prism54/isl_38xx.h
--- linux-2.4.27/drivers/net/wireless/prism54/isl_38xx.h	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.28-pre3/drivers/net/wireless/prism54/isl_38xx.h	2004-09-10 19:36:20.000000000 +0000
@@ -0,0 +1,169 @@
+/*
+ *  
+ *  Copyright (C) 2002 Intersil Americas Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License
+ *
+ *  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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef _ISL_38XX_H
+#define _ISL_38XX_H
+
+#include <linux/version.h>
+#include <asm/io.h>
+#include <asm/byteorder.h>
+
+#define ISL38XX_CB_RX_QSIZE                     8
+#define ISL38XX_CB_TX_QSIZE                     32
+
+/* ISL38XX Access Point Specific definitions */
+#define ISL38XX_MAX_WDS_LINKS                   8
+
+/* ISL38xx Client Specific definitions */
+#define ISL38XX_PSM_ACTIVE_STATE                0
+#define ISL38XX_PSM_POWERSAVE_STATE             1
+
+/* ISL38XX Host Interface Definitions */
+#define ISL38XX_PCI_MEM_SIZE                    0x02000
+#define ISL38XX_MEMORY_WINDOW_SIZE              0x01000
+#define ISL38XX_DEV_FIRMWARE_ADDRES             0x20000
+#define ISL38XX_WRITEIO_DELAY                   10	/* in us */
+#define ISL38XX_RESET_DELAY                     50	/* in ms */
+#define ISL38XX_WAIT_CYCLE                      10	/* in 10ms */
+#define ISL38XX_MAX_WAIT_CYCLES                 10
+
+/* PCI Memory Area */
+#define ISL38XX_HARDWARE_REG                    0x0000
+#define ISL38XX_CARDBUS_CIS                     0x0800
+#define ISL38XX_DIRECT_MEM_WIN                  0x1000
+
+/* Hardware registers */
+#define ISL38XX_DEV_INT_REG                     0x0000
+#define ISL38XX_INT_IDENT_REG                   0x0010
+#define ISL38XX_INT_ACK_REG                     0x0014
+#define ISL38XX_INT_EN_REG                      0x0018
+#define ISL38XX_GEN_PURP_COM_REG_1              0x0020
+#define ISL38XX_GEN_PURP_COM_REG_2              0x0024
+#define ISL38XX_CTRL_BLK_BASE_REG               ISL38XX_GEN_PURP_COM_REG_1
+#define ISL38XX_DIR_MEM_BASE_REG                0x0030
+#define ISL38XX_CTRL_STAT_REG                   0x0078
+
+/* High end mobos queue up pci writes, the following
+ * is used to "read" from after a write to force flush */
+#define ISL38XX_PCI_POSTING_FLUSH		ISL38XX_INT_EN_REG
+
+/**
+ * isl38xx_w32_flush - PCI iomem write helper
+ * @base: (host) memory base address of the device
+ * @val: 32bit value (host order) to write
+ * @offset: byte offset into @base to write value to
+ * 
+ *  This helper takes care of writing a 32bit datum to the
+ *  specified offset into the device's pci memory space, and making sure 
+ *  the pci memory buffers get flushed by performing one harmless read 
+ *  from the %ISL38XX_PCI_POSTING_FLUSH offset.
+ */
+static inline void
+isl38xx_w32_flush(void *base, u32 val, unsigned long offset)
+{
+	writel(val, base + offset);
+	(void) readl(base + ISL38XX_PCI_POSTING_FLUSH);
+}
+
+/* Device Interrupt register bits */
+#define ISL38XX_DEV_INT_RESET                   0x0001
+#define ISL38XX_DEV_INT_UPDATE                  0x0002
+#define ISL38XX_DEV_INT_WAKEUP                  0x0008
+#define ISL38XX_DEV_INT_SLEEP                   0x0010
+
+/* Interrupt Identification/Acknowledge/Enable register bits */
+#define ISL38XX_INT_IDENT_UPDATE                0x0002
+#define ISL38XX_INT_IDENT_INIT                  0x0004
+#define ISL38XX_INT_IDENT_WAKEUP                0x0008
+#define ISL38XX_INT_IDENT_SLEEP                 0x0010
+#define ISL38XX_INT_SOURCES                     0x001E
+
+/* Control/Status register bits */
+#define ISL38XX_CTRL_STAT_SLEEPMODE             0x00000200
+#define	ISL38XX_CTRL_STAT_CLKRUN		0x00800000
+#define ISL38XX_CTRL_STAT_RESET                 0x10000000
+#define ISL38XX_CTRL_STAT_RAMBOOT               0x20000000
+#define ISL38XX_CTRL_STAT_STARTHALTED           0x40000000
+#define ISL38XX_CTRL_STAT_HOST_OVERRIDE         0x80000000
+
+/* Control Block definitions */
+#define ISL38XX_CB_RX_DATA_LQ                   0
+#define ISL38XX_CB_TX_DATA_LQ                   1
+#define ISL38XX_CB_RX_DATA_HQ                   2
+#define ISL38XX_CB_TX_DATA_HQ                   3
+#define ISL38XX_CB_RX_MGMTQ                     4
+#define ISL38XX_CB_TX_MGMTQ                     5
+#define ISL38XX_CB_QCOUNT                       6
+#define ISL38XX_CB_MGMT_QSIZE                   4
+#define ISL38XX_MIN_QTHRESHOLD                  4	/* fragments */
+
+/* Memory Manager definitions */
+#define MGMT_FRAME_SIZE                         1500	/* >= size struct obj_bsslist */
+#define MGMT_TX_FRAME_COUNT                     24	/* max 4 + spare 4 + 8 init */
+#define MGMT_RX_FRAME_COUNT                     24	/* 4*4 + spare 8 */
+#define MGMT_FRAME_COUNT                        (MGMT_TX_FRAME_COUNT + MGMT_RX_FRAME_COUNT)
+#define CONTROL_BLOCK_SIZE                      1024	/* should be enough */
+#define PSM_FRAME_SIZE                          1536
+#define PSM_MINIMAL_STATION_COUNT               64
+#define PSM_FRAME_COUNT                         PSM_MINIMAL_STATION_COUNT
+#define PSM_BUFFER_SIZE                         PSM_FRAME_SIZE * PSM_FRAME_COUNT
+#define MAX_TRAP_RX_QUEUE                       4
+#define HOST_MEM_BLOCK                          CONTROL_BLOCK_SIZE + PSM_BUFFER_SIZE
+
+/* Fragment package definitions */
+#define FRAGMENT_FLAG_MF                        0x0001
+#define MAX_FRAGMENT_SIZE                       1536
+
+/* In monitor mode frames have a header. I don't know exactly how big those
+ * frame can be but I've never seen any frame bigger than 1584... :
+ */
+#define MAX_FRAGMENT_SIZE_RX	                1600
+
+typedef struct {
+	u32 address;		/* physical address on host */
+	u16 size;		/* packet size */
+	u16 flags;		/* set of bit-wise flags */
+} isl38xx_fragment;
+
+struct isl38xx_cb {
+	u32 driver_curr_frag[ISL38XX_CB_QCOUNT];
+	u32 device_curr_frag[ISL38XX_CB_QCOUNT];
+	isl38xx_fragment rx_data_low[ISL38XX_CB_RX_QSIZE];
+	isl38xx_fragment tx_data_low[ISL38XX_CB_TX_QSIZE];
+	isl38xx_fragment rx_data_high[ISL38XX_CB_RX_QSIZE];
+	isl38xx_fragment tx_data_high[ISL38XX_CB_TX_QSIZE];
+	isl38xx_fragment rx_data_mgmt[ISL38XX_CB_MGMT_QSIZE];
+	isl38xx_fragment tx_data_mgmt[ISL38XX_CB_MGMT_QSIZE];
+};
+
+typedef struct isl38xx_cb isl38xx_control_block;
+
+/* determine number of entries currently in queue */
+int isl38xx_in_queue(isl38xx_control_block *cb, int queue);
+
+void isl38xx_disable_interrupts(void *);
+void isl38xx_enable_common_interrupts(void *);
+
+void isl38xx_handle_sleep_request(isl38xx_control_block *, int *,
+				  void *);
+void isl38xx_handle_wakeup(isl38xx_control_block *, int *, void *);
+void isl38xx_trigger_device(int, void *);
+void isl38xx_interface_reset(void *, dma_addr_t);
+
+#endif				/* _ISL_38XX_H */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/net/wireless/prism54/isl_ioctl.c linux-2.4.28-pre3/drivers/net/wireless/prism54/isl_ioctl.c
--- linux-2.4.27/drivers/net/wireless/prism54/isl_ioctl.c	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.28-pre3/drivers/net/wireless/prism54/isl_ioctl.c	2004-09-10 19:36:01.000000000 +0000
@@ -0,0 +1,2269 @@
+/*
+ *  
+ *  Copyright (C) 2002 Intersil Americas Inc.
+ *            (C) 2003,2004 Aurelien Alleaume <slts@free.fr>
+ *            (C) 2003 Herbert Valerio Riedel <hvr@gnu.org>
+ *            (C) 2003 Luis R. Rodriguez <mcgrof@ruslug.rutgers.edu>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License
+ *
+ *  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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/if_arp.h>
+#include <linux/pci.h>
+
+#include <asm/uaccess.h>
+
+#include "prismcompat.h"
+#include "isl_ioctl.h"
+#include "islpci_mgt.h"
+#include "isl_oid.h"		/* additional types and defs for isl38xx fw */
+#include "oid_mgt.h"
+
+#include <net/iw_handler.h>	/* New driver API */
+
+static int init_mode = CARD_DEFAULT_IW_MODE;
+static int init_channel = CARD_DEFAULT_CHANNEL;
+static int init_wep = CARD_DEFAULT_WEP;
+static int init_filter = CARD_DEFAULT_FILTER;
+static int init_authen = CARD_DEFAULT_AUTHEN;
+static int init_dot1x = CARD_DEFAULT_DOT1X;
+static int init_conformance = CARD_DEFAULT_CONFORMANCE;
+static int init_mlme = CARD_DEFAULT_MLME_MODE;
+
+module_param(init_mode, int, 0);
+MODULE_PARM_DESC(init_mode,
+		 "Set card mode:\n0: Auto\n1: Ad-Hoc\n2: Managed Client (Default)\n3: Master / Access Point\n4: Repeater (Not supported yet)\n5: Secondary (Not supported yet)\n6: Monitor");
+
+module_param(init_channel, int, 0);
+MODULE_PARM_DESC(init_channel,
+		 "Check `iwpriv ethx channel` for available channels");
+
+module_param(init_wep, int, 0);
+module_param(init_filter, int, 0);
+
+module_param(init_authen, int, 0);
+MODULE_PARM_DESC(init_authen,
+		 "Authentication method. Can be of seven types:\n0 0x0000: None\n1 0x0001: DOT11_AUTH_OS (Default)\n2 0x0002: DOT11_AUTH_SK\n3 0x0003: DOT11_AUTH_BOTH");
+
+module_param(init_dot1x, int, 0);
+MODULE_PARM_DESC(init_dot1x,
+		 "\n0: None/not set	(Default)\n1: DOT11_DOT1X_AUTHENABLED\n2: DOT11_DOT1X_KEYTXENABLED");
+
+module_param(init_mlme, int, 0);
+MODULE_PARM_DESC(init_mlme,
+		 "Sets the MAC layer management entity (MLME) mode of operation,\n0: DOT11_MLME_AUTO (Default)\n1: DOT11_MLME_INTERMEDIATE\n2: DOT11_MLME_EXTENDED");
+
+/**
+ * prism54_mib_mode_helper - MIB change mode helper function
+ * @mib: the &struct islpci_mib object to modify
+ * @iw_mode: new mode (%IW_MODE_*)
+ * 
+ *  This is a helper function, hence it does not lock. Make sure
+ *  caller deals with locking *if* necessary. This function sets the 
+ *  mode-dependent mib values and does the mapping of the Linux 
+ *  Wireless API modes to Device firmware modes. It also checks for 
+ *  correct valid Linux wireless modes. 
+ */
+int
+prism54_mib_mode_helper(islpci_private *priv, u32 iw_mode)
+{
+	u32 config = INL_CONFIG_MANUALRUN;
+	u32 mode, bsstype;
+
+	/* For now, just catch early the Repeater and Secondary modes here */
+	if (iw_mode == IW_MODE_REPEAT || iw_mode == IW_MODE_SECOND) {
+		printk(KERN_DEBUG
+		       "%s(): Sorry, Repeater mode and Secondary mode "
+		       "are not yet supported by this driver.\n", __FUNCTION__);
+		return -EINVAL;
+	}
+
+	priv->iw_mode = iw_mode;
+
+	switch (iw_mode) {
+	case IW_MODE_AUTO:
+		mode = INL_MODE_CLIENT;
+		bsstype = DOT11_BSSTYPE_ANY;
+		break;
+	case IW_MODE_ADHOC:
+		mode = INL_MODE_CLIENT;
+		bsstype = DOT11_BSSTYPE_IBSS;
+		break;
+	case IW_MODE_INFRA:
+		mode = INL_MODE_CLIENT;
+		bsstype = DOT11_BSSTYPE_INFRA;
+		break;
+	case IW_MODE_MASTER:
+		mode = INL_MODE_AP;
+		bsstype = DOT11_BSSTYPE_INFRA;
+		break;
+	case IW_MODE_MONITOR:
+		mode = INL_MODE_PROMISCUOUS;
+		bsstype = DOT11_BSSTYPE_ANY;
+		config |= INL_CONFIG_RXANNEX;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	if (init_wds)
+		config |= INL_CONFIG_WDS;
+	mgt_set(priv, DOT11_OID_BSSTYPE, &bsstype);
+	mgt_set(priv, OID_INL_CONFIG, &config);
+	mgt_set(priv, OID_INL_MODE, &mode);
+
+	return 0;
+}
+
+/**
+ * prism54_mib_init - fill MIB cache with defaults
+ *
+ *  this function initializes the struct given as @mib with defaults,
+ *  of which many are retrieved from the global module parameter
+ *  variables.  
+ */
+
+void
+prism54_mib_init(islpci_private *priv)
+{
+	u32 t;
+	struct obj_buffer psm_buffer = {
+		.size = PSM_BUFFER_SIZE,
+		.addr = priv->device_psm_buffer
+	};
+
+	mgt_set(priv, DOT11_OID_CHANNEL, &init_channel);
+	mgt_set(priv, DOT11_OID_AUTHENABLE, &init_authen);
+	mgt_set(priv, DOT11_OID_PRIVACYINVOKED, &init_wep);
+
+	mgt_set(priv, DOT11_OID_PSMBUFFER, &psm_buffer);
+	mgt_set(priv, DOT11_OID_EXUNENCRYPTED, &init_filter);
+	mgt_set(priv, DOT11_OID_DOT1XENABLE, &init_dot1x);
+	mgt_set(priv, DOT11_OID_MLMEAUTOLEVEL, &init_mlme);
+	mgt_set(priv, OID_INL_DOT11D_CONFORMANCE, &init_conformance);
+
+	t = 127;
+	mgt_set(priv, OID_INL_OUTPUTPOWER, &t);
+
+	/* Important: we are setting a default wireless mode and we are 
+	 * forcing a valid one, so prism54_mib_mode_helper should just set
+	 * mib values depending on what the wireless mode given is. No need
+	 * for it save old values */
+	if (init_mode > IW_MODE_MONITOR || init_mode < IW_MODE_AUTO) {
+		printk(KERN_DEBUG "%s(): You passed a non-valid init_mode. "
+		       "Using default mode\n", __FUNCTION__);
+		init_mode = CARD_DEFAULT_IW_MODE;
+	}
+	/* This sets all of the mode-dependent values */
+	prism54_mib_mode_helper(priv, init_mode);
+}
+
+/* this will be executed outside of atomic context thanks to
+ * schedule_work(), thus we can as well use sleeping semaphore
+ * locking */
+void
+prism54_update_stats(islpci_private *priv)
+{
+	char *data;
+	int j;
+	struct obj_bss bss, *bss2;
+	union oid_res_t r;
+
+	if (down_interruptible(&priv->stats_sem))
+		return;
+
+/* Noise floor.
+ * I'm not sure if the unit is dBm.
+ * Note : If we are not connected, this value seems to be irrelevant. */
+
+	mgt_get_request(priv, DOT11_OID_NOISEFLOOR, 0, NULL, &r);
+	priv->local_iwstatistics.qual.noise = r.u;
+
+/* Get the rssi of the link. To do this we need to retrieve a bss. */
+
+	/* First get the MAC address of the AP we are associated with. */
+	mgt_get_request(priv, DOT11_OID_BSSID, 0, NULL, &r);
+	data = r.ptr;
+
+	/* copy this MAC to the bss */
+	memcpy(bss.address, data, 6);
+	kfree(data);
+
+	/* now ask for the corresponding bss */
+	j = mgt_get_request(priv, DOT11_OID_BSSFIND, 0, (void *) &bss, &r);
+	bss2 = r.ptr;
+	/* report the rssi and use it to calculate
+	 *  link quality through a signal-noise
+	 *  ratio */
+	priv->local_iwstatistics.qual.level = bss2->rssi;
+	priv->local_iwstatistics.qual.qual =
+	    bss2->rssi - priv->iwstatistics.qual.noise;
+
+	kfree(bss2);
+
+	/* report that the stats are new */
+	priv->local_iwstatistics.qual.updated = 0x7;
+
+/* Rx : unable to decrypt the MPDU */
+	mgt_get_request(priv, DOT11_OID_PRIVRXFAILED, 0, NULL, &r);
+	priv->local_iwstatistics.discard.code = r.u;
+
+/* Tx : Max MAC retries num reached */
+	mgt_get_request(priv, DOT11_OID_MPDUTXFAILED, 0, NULL, &r);
+	priv->local_iwstatistics.discard.retries = r.u;
+
+	up(&priv->stats_sem);
+
+	return;
+}
+
+struct iw_statistics *
+prism54_get_wireless_stats(struct net_device *ndev)
+{
+	islpci_private *priv = netdev_priv(ndev);
+
+	/* If the stats are being updated return old data */
+	if (down_trylock(&priv->stats_sem) == 0) {
+		memcpy(&priv->iwstatistics, &priv->local_iwstatistics,
+		       sizeof (struct iw_statistics));
+		/* They won't be marked updated for the next time */
+		priv->local_iwstatistics.qual.updated = 0;
+		up(&priv->stats_sem);
+	} else
+		priv->iwstatistics.qual.updated = 0;
+
+	/* Update our wireless stats, but do not schedule to often 
+	 * (max 1 HZ) */
+	if ((priv->stats_timestamp == 0) ||
+	    time_after(jiffies, priv->stats_timestamp + 1 * HZ)) {
+		schedule_work(&priv->stats_work);
+		priv->stats_timestamp = jiffies;
+	}
+
+	return &priv->iwstatistics;
+}
+
+static int
+prism54_commit(struct net_device *ndev, struct iw_request_info *info,
+	       char *cwrq, char *extra)
+{
+	islpci_private *priv = netdev_priv(ndev);
+
+	/* simply re-set the last set SSID, this should commit most stuff */
+
+	/* Commit in Monitor mode is not necessary, also setting essid
+	 * in Monitor mode does not make sense and isn't allowed for this
+	 * device's firmware */
+	if (priv->iw_mode != IW_MODE_MONITOR)
+		return mgt_set_request(priv, DOT11_OID_SSID, 0, NULL);
+	return 0;
+}
+
+static int
+prism54_get_name(struct net_device *ndev, struct iw_request_info *info,
+		 char *cwrq, char *extra)
+{
+	islpci_private *priv = netdev_priv(ndev);
+	char *capabilities;
+	union oid_res_t r;
+	int rvalue;
+
+	if (islpci_get_state(priv) < PRV_STATE_INIT) {
+		strncpy(cwrq, "NOT READY!", IFNAMSIZ);
+		return 0;
+	}
+	rvalue = mgt_get_request(priv, OID_INL_PHYCAPABILITIES, 0, NULL, &r);
+
+	switch (r.u) {
+	case INL_PHYCAP_5000MHZ:
+		capabilities = "IEEE 802.11a/b/g";
+		break;
+	case INL_PHYCAP_FAA:
+		capabilities = "IEEE 802.11b/g - FAA Support";
+		break;
+	case INL_PHYCAP_2400MHZ:
+	default:
+		capabilities = "IEEE 802.11b/g";	/* Default */
+		break;
+	}
+	strncpy(cwrq, capabilities, IFNAMSIZ);
+	return rvalue;
+}
+
+static int
+prism54_set_freq(struct net_device *ndev, struct iw_request_info *info,
+		 struct iw_freq *fwrq, char *extra)
+{
+	islpci_private *priv = netdev_priv(ndev);
+	int rvalue;
+	u32 c;
+
+	if (fwrq->m < 1000)
+		/* we have a channel number */
+		c = fwrq->m;
+	else
+		c = (fwrq->e == 1) ? channel_of_freq(fwrq->m / 100000) : 0;
+
+	rvalue = c ? mgt_set_request(priv, DOT11_OID_CHANNEL, 0, &c) : -EINVAL;
+
+	/* Call commit handler */
+	return (rvalue ? rvalue : -EINPROGRESS);
+}
+
+static int
+prism54_get_freq(struct net_device *ndev, struct iw_request_info *info,
+		 struct iw_freq *fwrq, char *extra)
+{
+	islpci_private *priv = netdev_priv(ndev);
+	union oid_res_t r;
+	int rvalue;
+
+	rvalue = mgt_get_request(priv, DOT11_OID_CHANNEL, 0, NULL, &r);
+	fwrq->i = r.u;
+	rvalue |= mgt_get_request(priv, DOT11_OID_FREQUENCY, 0, NULL, &r);
+	fwrq->m = r.u;
+	fwrq->e = 3;
+
+	return rvalue;
+}
+
+static int
+prism54_set_mode(struct net_device *ndev, struct iw_request_info *info,
+		 __u32 * uwrq, char *extra)
+{
+	islpci_private *priv = netdev_priv(ndev);
+	u32 mlmeautolevel = CARD_DEFAULT_MLME_MODE;
+
+	/* Let's see if the user passed a valid Linux Wireless mode */
+	if (*uwrq > IW_MODE_MONITOR || *uwrq < IW_MODE_AUTO) {
+		printk(KERN_DEBUG
+		       "%s: %s() You passed a non-valid init_mode.\n",
+		       priv->ndev->name, __FUNCTION__);
+		return -EINVAL;
+	}
+
+	down_write(&priv->mib_sem);
+
+	if (prism54_mib_mode_helper(priv, *uwrq)) {
+		up_write(&priv->mib_sem);
+		return -EOPNOTSUPP;
+	}
+
+	/* the ACL code needs an intermediate mlmeautolevel. The wpa stuff an
+	 * extended one.
+	 */
+	if ((*uwrq == IW_MODE_MASTER) && (priv->acl.policy != MAC_POLICY_OPEN))
+		mlmeautolevel = DOT11_MLME_INTERMEDIATE;
+	if (priv->wpa)
+		mlmeautolevel = DOT11_MLME_EXTENDED;
+
+	mgt_set(priv, DOT11_OID_MLMEAUTOLEVEL, &mlmeautolevel);
+
+	mgt_commit(priv);
+	priv->ndev->type = (priv->iw_mode == IW_MODE_MONITOR)
+	    ? priv->monitor_type : ARPHRD_ETHER;
+	up_write(&priv->mib_sem);
+
+	return 0;
+}
+
+/* Use mib cache */
+static int
+prism54_get_mode(struct net_device *ndev, struct iw_request_info *info,
+		 __u32 * uwrq, char *extra)
+{
+	islpci_private *priv = netdev_priv(ndev);
+
+	BUG_ON((priv->iw_mode < IW_MODE_AUTO) || (priv->iw_mode >
+						  IW_MODE_MONITOR));
+	*uwrq = priv->iw_mode;
+
+	return 0;
+}
+
+/* we use DOT11_OID_EDTHRESHOLD. From what I guess the card will not try to
+ * emit data if (sensitivity > rssi - noise) (in dBm).
+ * prism54_set_sens does not seem to work.
+ */
+
+static int
+prism54_set_sens(struct net_device *ndev, struct iw_request_info *info,
+		 struct iw_param *vwrq, char *extra)
+{
+	islpci_private *priv = netdev_priv(ndev);
+	u32 sens;
+
+	/* by default  the card sets this to 20. */
+	sens = vwrq->disabled ? 20 : vwrq->value;
+
+	return mgt_set_request(priv, DOT11_OID_EDTHRESHOLD, 0, &sens);
+}
+
+static int
+prism54_get_sens(struct net_device *ndev, struct iw_request_info *info,
+		 struct iw_param *vwrq, char *extra)
+{
+	islpci_private *priv = netdev_priv(ndev);
+	union oid_res_t r;
+	int rvalue;
+
+	rvalue = mgt_get_request(priv, DOT11_OID_EDTHRESHOLD, 0, NULL, &r);
+
+	vwrq->value = r.u;
+	vwrq->disabled = (vwrq->value == 0);
+	vwrq->fixed = 1;
+
+	return rvalue;
+}
+
+static int
+prism54_get_range(struct net_device *ndev, struct iw_request_info *info,
+		  struct iw_point *dwrq, char *extra)
+{
+	struct iw_range *range = (struct iw_range *) extra;
+	islpci_private *priv = netdev_priv(ndev);
+	u8 *data;
+	int i, m, rvalue;
+	struct obj_frequencies *freq;
+	union oid_res_t r;
+
+	memset(range, 0, sizeof (struct iw_range));
+	dwrq->length = sizeof (struct iw_range);
+
+	/* set the wireless extension version number */
+	range->we_version_source = SUPPORTED_WIRELESS_EXT;
+	range->we_version_compiled = WIRELESS_EXT;
+
+	/* Now the encoding capabilities */
+	range->num_encoding_sizes = 3;
+	/* 64(40) bits WEP */
+	range->encoding_size[0] = 5;
+	/* 128(104) bits WEP */
+	range->encoding_size[1] = 13;
+	/* 256 bits for WPA-PSK */
+	range->encoding_size[2] = 32;
+	/* 4 keys are allowed */
+	range->max_encoding_tokens = 4;
+
+	/* we don't know the quality range... */
+	range->max_qual.level = 0;
+	range->max_qual.noise = 0;
+	range->max_qual.qual = 0;
+	/* these value describe an average quality. Needs more tweaking... */
+	range->avg_qual.level = -80;	/* -80 dBm */
+	range->avg_qual.noise = 0;	/* don't know what to put here */
+	range->avg_qual.qual = 0;
+
+	range->sensitivity = 200;
+
+	/* retry limit capabilities */
+	range->retry_capa = IW_RETRY_LIMIT | IW_RETRY_LIFETIME;
+	range->retry_flags = IW_RETRY_LIMIT;
+	range->r_time_flags = IW_RETRY_LIFETIME;
+
+	/* I don't know the range. Put stupid things here */
+	range->min_retry = 1;
+	range->max_retry = 65535;
+	range->min_r_time = 1024;
+	range->max_r_time = 65535 * 1024;
+
+	/* txpower is supported in dBm's */
+	range->txpower_capa = IW_TXPOW_DBM;
+
+	if (islpci_get_state(priv) < PRV_STATE_INIT)
+		return 0;
+
+	/* Request the device for the supported frequencies
+	 * not really relevant since some devices will report the 5 GHz band
+	 * frequencies even if they don't support them.
+	 */
+	rvalue =
+	    mgt_get_request(priv, DOT11_OID_SUPPORTEDFREQUENCIES, 0, NULL, &r);
+	freq = r.ptr;
+
+	range->num_channels = freq->nr;
+	range->num_frequency = freq->nr;
+
+	m = min(IW_MAX_FREQUENCIES, (int) freq->nr);
+	for (i = 0; i < m; i++) {
+		range->freq[i].m = freq->mhz[i];
+		range->freq[i].e = 6;
+		range->freq[i].i = channel_of_freq(freq->mhz[i]);
+	}
+	kfree(freq);
+
+	rvalue |= mgt_get_request(priv, DOT11_OID_SUPPORTEDRATES, 0, NULL, &r);
+	data = r.ptr;
+
+	/* We got an array of char. It is NULL terminated. */
+	i = 0;
+	while ((i < IW_MAX_BITRATES) && (*data != 0)) {
+		/*       the result must be in bps. The card gives us 500Kbps */
+		range->bitrate[i] = *data * 500000;
+		i++;
+		data++;
+	}
+	range->num_bitrates = i;
+	kfree(r.ptr);
+
+	return rvalue;
+}
+
+/* Set AP address*/
+
+static int
+prism54_set_wap(struct net_device *ndev, struct iw_request_info *info,
+		struct sockaddr *awrq, char *extra)
+{
+	islpci_private *priv = netdev_priv(ndev);
+	char bssid[6];
+	int rvalue;
+
+	if (awrq->sa_family != ARPHRD_ETHER)
+		return -EINVAL;
+
+	/* prepare the structure for the set object */
+	memcpy(&bssid[0], awrq->sa_data, 6);
+
+	/* set the bssid -- does this make sense when in AP mode? */
+	rvalue = mgt_set_request(priv, DOT11_OID_BSSID, 0, &bssid);
+
+	return (rvalue ? rvalue : -EINPROGRESS);	/* Call commit handler */
+}
+
+/* get AP address*/
+
+static int
+prism54_get_wap(struct net_device *ndev, struct iw_request_info *info,
+		struct sockaddr *awrq, char *extra)
+{
+	islpci_private *priv = netdev_priv(ndev);
+	union oid_res_t r;
+	int rvalue;
+
+	rvalue = mgt_get_request(priv, DOT11_OID_BSSID, 0, NULL, &r);
+	memcpy(awrq->sa_data, r.ptr, 6);
+	awrq->sa_family = ARPHRD_ETHER;
+	kfree(r.ptr);
+
+	return rvalue;
+}
+
+static int
+prism54_set_scan(struct net_device *dev, struct iw_request_info *info,
+		 struct iw_param *vwrq, char *extra)
+{
+	/* hehe the device does this automagicaly */
+	return 0;
+}
+
+/* a little helper that will translate our data into a card independent
+ * format that the Wireless Tools will understand. This was inspired by
+ * the "Aironet driver for 4500 and 4800 series cards" (GPL)
+ */
+
+static char *
+prism54_translate_bss(struct net_device *ndev, char *current_ev,
+		      char *end_buf, struct obj_bss *bss, char noise)
+{
+	struct iw_event iwe;	/* Temporary buffer */
+	short cap;
+	islpci_private *priv = netdev_priv(ndev);
+
+	/* The first entry must be the MAC address */
+	memcpy(iwe.u.ap_addr.sa_data, bss->address, 6);
+	iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
+	iwe.cmd = SIOCGIWAP;
+	current_ev =
+	    iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_ADDR_LEN);
+
+	/* The following entries will be displayed in the same order we give them */
+
+	/* The ESSID. */
+	iwe.u.data.length = bss->ssid.length;
+	iwe.u.data.flags = 1;
+	iwe.cmd = SIOCGIWESSID;
+	current_ev = iwe_stream_add_point(current_ev, end_buf,
+					  &iwe, bss->ssid.octets);
+
+	/* Capabilities */
+#define CAP_ESS 0x01
+#define CAP_IBSS 0x02
+#define CAP_CRYPT 0x10
+
+	/* Mode */
+	cap = bss->capinfo;
+	iwe.u.mode = 0;
+	if (cap & CAP_ESS)
+		iwe.u.mode = IW_MODE_MASTER;
+	else if (cap & CAP_IBSS)
+		iwe.u.mode = IW_MODE_ADHOC;
+	iwe.cmd = SIOCGIWMODE;
+	if (iwe.u.mode)
+		current_ev =
+		    iwe_stream_add_event(current_ev, end_buf, &iwe,
+					 IW_EV_UINT_LEN);
+
+	/* Encryption capability */
+	if (cap & CAP_CRYPT)
+		iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
+	else
+		iwe.u.data.flags = IW_ENCODE_DISABLED;
+	iwe.u.data.length = 0;
+	iwe.cmd = SIOCGIWENCODE;
+	current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, NULL);
+
+	/* Add frequency. (short) bss->channel is the frequency in MHz */
+	iwe.u.freq.m = channel_of_freq(bss->channel);
+	iwe.u.freq.e = 0;
+	iwe.cmd = SIOCGIWFREQ;
+	current_ev =
+	    iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_FREQ_LEN);
+
+	/* Add quality statistics */
+	iwe.u.qual.level = bss->rssi;
+	iwe.u.qual.noise = noise;
+	/* do a simple SNR for quality */
+	iwe.u.qual.qual = bss->rssi - noise;
+	iwe.cmd = IWEVQUAL;
+	current_ev =
+	    iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_QUAL_LEN);
+
+	if (priv->wpa) {
+		u8 wpa_ie[MAX_WPA_IE_LEN];
+		char *buf, *p;
+		size_t wpa_ie_len;
+		int i;
+
+		wpa_ie_len = prism54_wpa_ie_get(priv, bss->address, wpa_ie);
+		if (wpa_ie_len > 0 &&
+		    (buf = kmalloc(wpa_ie_len * 2 + 10, GFP_ATOMIC))) {
+			p = buf;
+			p += sprintf(p, "wpa_ie=");
+			for (i = 0; i < wpa_ie_len; i++) {
+				p += sprintf(p, "%02x", wpa_ie[i]);
+			}
+			memset(&iwe, 0, sizeof (iwe));
+			iwe.cmd = IWEVCUSTOM;
+			iwe.u.data.length = strlen(buf);
+			current_ev = iwe_stream_add_point(current_ev, end_buf,
+							  &iwe, buf);
+			kfree(buf);
+		}
+	}
+	return current_ev;
+}
+
+int
+prism54_get_scan(struct net_device *ndev, struct iw_request_info *info,
+		 struct iw_point *dwrq, char *extra)
+{
+	islpci_private *priv = netdev_priv(ndev);
+	int i, rvalue;
+	struct obj_bsslist *bsslist;
+	u32 noise = 0;
+	char *current_ev = extra;
+	union oid_res_t r;
+
+	if (islpci_get_state(priv) < PRV_STATE_INIT) {
+		/* device is not ready, fail gently */
+		dwrq->length = 0;
+		return 0;
+	}
+
+	/* first get the noise value. We will use it to report the link quality */
+	rvalue = mgt_get_request(priv, DOT11_OID_NOISEFLOOR, 0, NULL, &r);
+	noise = r.u;
+
+	/* Ask the device for a list of known bss. We can report at most
+	 * IW_MAX_AP=64 to the range struct. But the device won't repport anything
+	 * if you change the value of IWMAX_BSS=24.
+	 */
+	rvalue |= mgt_get_request(priv, DOT11_OID_BSSLIST, 0, NULL, &r);
+	bsslist = r.ptr;
+
+	/* ok now, scan the list and translate its info */
+	for (i = 0; i < min(IW_MAX_AP, (int) bsslist->nr); i++)
+		current_ev = prism54_translate_bss(ndev, current_ev,
+						   extra + IW_SCAN_MAX_DATA,
+						   &(bsslist->bsslist[i]),
+						   noise);
+	kfree(bsslist);
+	dwrq->length = (current_ev - extra);
+	dwrq->flags = 0;	/* todo */
+
+	return rvalue;
+}
+
+static int
+prism54_set_essid(struct net_device *ndev, struct iw_request_info *info,
+		  struct iw_point *dwrq, char *extra)
+{
+	islpci_private *priv = netdev_priv(ndev);
+	struct obj_ssid essid;
+
+	memset(essid.octets, 0, 33);
+
+	/* Check if we were asked for `any' */
+	if (dwrq->flags && dwrq->length) {
+		if (dwrq->length > min(33, IW_ESSID_MAX_SIZE + 1))
+			return -E2BIG;
+		essid.length = dwrq->length - 1;
+		memcpy(essid.octets, extra, dwrq->length);
+	} else
+		essid.length = 0;
+
+	if (priv->iw_mode != IW_MODE_MONITOR)
+		return mgt_set_request(priv, DOT11_OID_SSID, 0, &essid);
+
+	/* If in monitor mode, just save to mib */
+	mgt_set(priv, DOT11_OID_SSID, &essid);
+	return 0;
+
+}
+
+static int
+prism54_get_essid(struct net_device *ndev, struct iw_request_info *info,
+		  struct iw_point *dwrq, char *extra)
+{
+	islpci_private *priv = netdev_priv(ndev);
+	struct obj_ssid *essid;
+	union oid_res_t r;
+	int rvalue;
+
+	rvalue = mgt_get_request(priv, DOT11_OID_SSID, 0, NULL, &r);
+	essid = r.ptr;
+
+	if (essid->length) {
+		dwrq->flags = 1;	/* set ESSID to ON for Wireless Extensions */
+		/* if it is to big, trunk it */
+		dwrq->length = min(IW_ESSID_MAX_SIZE, essid->length + 1);
+	} else {
+		dwrq->flags = 0;
+		dwrq->length = 0;
+	}
+	essid->octets[essid->length] = '\0';
+	memcpy(extra, essid->octets, dwrq->length);
+	kfree(essid);
+
+	return rvalue;
+}
+
+/* Provides no functionality, just completes the ioctl. In essence this is a 
+ * just a cosmetic ioctl.
+ */
+static int
+prism54_set_nick(struct net_device *ndev, struct iw_request_info *info,
+		 struct iw_point *dwrq, char *extra)
+{
+	islpci_private *priv = netdev_priv(ndev);
+
+	if (dwrq->length > IW_ESSID_MAX_SIZE)
+		return -E2BIG;
+
+	down_write(&priv->mib_sem);
+	memset(priv->nickname, 0, sizeof (priv->nickname));
+	memcpy(priv->nickname, extra, dwrq->length);
+	up_write(&priv->mib_sem);
+
+	return 0;
+}
+
+static int
+prism54_get_nick(struct net_device *ndev, struct iw_request_info *info,
+		 struct iw_point *dwrq, char *extra)
+{
+	islpci_private *priv = netdev_priv(ndev);
+
+	dwrq->length = 0;
+
+	down_read(&priv->mib_sem);
+	dwrq->length = strlen(priv->nickname) + 1;
+	memcpy(extra, priv->nickname, dwrq->length);
+	up_read(&priv->mib_sem);
+
+	return 0;
+}
+
+/* Set the allowed Bitrates */
+
+static int
+prism54_set_rate(struct net_device *ndev,
+		 struct iw_request_info *info,
+		 struct iw_param *vwrq, char *extra)
+{
+
+	islpci_private *priv = netdev_priv(ndev);
+	u32 rate, profile;
+	char *data;
+	int ret, i;
+	union oid_res_t r;
+
+	if (vwrq->value == -1) {
+		/* auto mode. No limit. */
+		profile = 1;
+		return mgt_set_request(priv, DOT11_OID_PROFILES, 0, &profile);
+	}
+
+	ret = mgt_get_request(priv, DOT11_OID_SUPPORTEDRATES, 0, NULL, &r);
+	if (ret) {
+		kfree(r.ptr);
+		return ret;
+	}
+
+	rate = (u32) (vwrq->value / 500000);
+	data = r.ptr;
+	i = 0;
+
+	while (data[i]) {
+		if (rate && (data[i] == rate)) {
+			break;
+		}
+		if (vwrq->value == i) {
+			break;
+		}
+		data[i] |= 0x80;
+		i++;
+	}
+
+	if (!data[i]) {
+		kfree(r.ptr);
+		return -EINVAL;
+	}
+
+	data[i] |= 0x80;
+	data[i + 1] = 0;
+
+	/* Now, check if we want a fixed or auto value */
+	if (vwrq->fixed) {
+		data[0] = data[i];
+		data[1] = 0;
+	}
+
+/*
+	i = 0;
+	printk("prism54 rate: ");
+	while(data[i]) {
+		printk("%u ", data[i]);
+		i++;
+	}
+	printk("0\n");
+*/
+	profile = -1;
+	ret = mgt_set_request(priv, DOT11_OID_PROFILES, 0, &profile);
+	ret |= mgt_set_request(priv, DOT11_OID_EXTENDEDRATES, 0, data);
+	ret |= mgt_set_request(priv, DOT11_OID_RATES, 0, data);
+
+	kfree(r.ptr);
+
+	return ret;
+}
+
+/* Get the current bit rate */
+static int
+prism54_get_rate(struct net_device *ndev,
+		 struct iw_request_info *info,
+		 struct iw_param *vwrq, char *extra)
+{
+	islpci_private *priv = netdev_priv(ndev);
+	int rvalue;
+	char *data;
+	union oid_res_t r;
+
+	/* Get the current bit rate */
+	if ((rvalue = mgt_get_request(priv, GEN_OID_LINKSTATE, 0, NULL, &r)))
+		return rvalue;
+	vwrq->value = r.u * 500000;
+
+	/* request the device for the enabled rates */
+	rvalue = mgt_get_request(priv, DOT11_OID_RATES, 0, NULL, &r);
+	if (rvalue) {
+		kfree(r.ptr);
+		return rvalue;
+	}
+	data = r.ptr;
+	vwrq->fixed = (data[0] != 0) && (data[1] == 0);
+	kfree(r.ptr);
+
+	return 0;
+}
+
+static int
+prism54_set_rts(struct net_device *ndev, struct iw_request_info *info,
+		struct iw_param *vwrq, char *extra)
+{
+	islpci_private *priv = netdev_priv(ndev);
+
+	return mgt_set_request(priv, DOT11_OID_RTSTHRESH, 0, &vwrq->value);
+}
+
+static int
+prism54_get_rts(struct net_device *ndev, struct iw_request_info *info,
+		struct iw_param *vwrq, char *extra)
+{
+	islpci_private *priv = netdev_priv(ndev);
+	union oid_res_t r;
+	int rvalue;
+
+	/* get the rts threshold */
+	rvalue = mgt_get_request(priv, DOT11_OID_RTSTHRESH, 0, NULL, &r);
+	vwrq->value = r.u;
+
+	return rvalue;
+}
+
+static int
+prism54_set_frag(struct net_device *ndev, struct iw_request_info *info,
+		 struct iw_param *vwrq, char *extra)
+{
+	islpci_private *priv = netdev_priv(ndev);
+
+	return mgt_set_request(priv, DOT11_OID_FRAGTHRESH, 0, &vwrq->value);
+}
+
+static int
+prism54_get_frag(struct net_device *ndev, struct iw_request_info *info,
+		 struct iw_param *vwrq, char *extra)
+{
+	islpci_private *priv = netdev_priv(ndev);
+	union oid_res_t r;
+	int rvalue;
+
+	rvalue = mgt_get_request(priv, DOT11_OID_FRAGTHRESH, 0, NULL, &r);
+	vwrq->value = r.u;
+
+	return rvalue;
+}
+
+/* Here we have (min,max) = max retries for (small frames, big frames). Where
+ * big frame <=>  bigger than the rts threshold
+ * small frame <=>  smaller than the rts threshold
+ * This is not really the behavior expected by the wireless tool but it seems
+ * to be a common behavior in other drivers.
+ */
+
+static int
+prism54_set_retry(struct net_device *ndev, struct iw_request_info *info,
+		  struct iw_param *vwrq, char *extra)
+{
+	islpci_private *priv = netdev_priv(ndev);
+	u32 slimit = 0, llimit = 0;	/* short and long limit */
+	u32 lifetime = 0;
+	int rvalue = 0;
+
+	if (vwrq->disabled)
+		/* we cannot disable this feature */
+		return -EINVAL;
+
+	if (vwrq->flags & IW_RETRY_LIMIT) {
+		if (vwrq->flags & IW_RETRY_MIN)
+			slimit = vwrq->value;
+		else if (vwrq->flags & IW_RETRY_MAX)
+			llimit = vwrq->value;
+		else {
+			/* we are asked to set both */
+			slimit = vwrq->value;
+			llimit = vwrq->value;
+		}
+	}
+	if (vwrq->flags & IW_RETRY_LIFETIME)
+		/* Wireless tools use us unit while the device uses 1024 us unit */
+		lifetime = vwrq->value / 1024;
+
+	/* now set what is requested */
+	if (slimit)
+		rvalue =
+		    mgt_set_request(priv, DOT11_OID_SHORTRETRIES, 0, &slimit);
+	if (llimit)
+		rvalue |=
+		    mgt_set_request(priv, DOT11_OID_LONGRETRIES, 0, &llimit);
+	if (lifetime)
+		rvalue |=
+		    mgt_set_request(priv, DOT11_OID_MAXTXLIFETIME, 0,
+				    &lifetime);
+	return rvalue;
+}
+
+static int
+prism54_get_retry(struct net_device *ndev, struct iw_request_info *info,
+		  struct iw_param *vwrq, char *extra)
+{
+	islpci_private *priv = netdev_priv(ndev);
+	union oid_res_t r;
+	int rvalue = 0;
+	vwrq->disabled = 0;	/* It cannot be disabled */
+
+	if ((vwrq->flags & IW_RETRY_TYPE) == IW_RETRY_LIFETIME) {
+		/* we are asked for the life time */
+		rvalue =
+		    mgt_get_request(priv, DOT11_OID_MAXTXLIFETIME, 0, NULL, &r);
+		vwrq->value = r.u * 1024;
+		vwrq->flags = IW_RETRY_LIFETIME;
+	} else if ((vwrq->flags & IW_RETRY_MAX)) {
+		/* we are asked for the long retry limit */
+		rvalue |=
+		    mgt_get_request(priv, DOT11_OID_LONGRETRIES, 0, NULL, &r);
+		vwrq->value = r.u;
+		vwrq->flags = IW_RETRY_LIMIT | IW_RETRY_MAX;
+	} else {
+		/* default. get the  short retry limit */
+		rvalue |=
+		    mgt_get_request(priv, DOT11_OID_SHORTRETRIES, 0, NULL, &r);
+		vwrq->value = r.u;
+		vwrq->flags = IW_RETRY_LIMIT | IW_RETRY_MIN;
+	}
+
+	return rvalue;
+}
+
+static int
+prism54_set_encode(struct net_device *ndev, struct iw_request_info *info,
+		   struct iw_point *dwrq, char *extra)
+{
+	islpci_private *priv = netdev_priv(ndev);
+	int rvalue = 0, force = 0;
+	int authen = DOT11_AUTH_OS, invoke = 0, exunencrypt = 0;
+	union oid_res_t r;
+
+	/* with the new API, it's impossible to get a NULL pointer.
+	 * New version of iwconfig set the IW_ENCODE_NOKEY flag
+	 * when no key is given, but older versions don't. */
+
+	if (dwrq->length > 0) {
+		/* we have a key to set */
+		int index = (dwrq->flags & IW_ENCODE_INDEX) - 1;
+		int current_index;
+		struct obj_key key = { DOT11_PRIV_WEP, 0, "" };
+
+		/* get the current key index */
+		rvalue = mgt_get_request(priv, DOT11_OID_DEFKEYID, 0, NULL, &r);
+		current_index = r.u;
+		/* Verify that the key is not marked as invalid */
+		if (!(dwrq->flags & IW_ENCODE_NOKEY)) {
+			key.length = dwrq->length > sizeof (key.key) ?
+			    sizeof (key.key) : dwrq->length;
+			memcpy(key.key, extra, key.length);
+			if (key.length == 32)
+				/* we want WPA-PSK */
+				key.type = DOT11_PRIV_TKIP;
+			if ((index < 0) || (index > 3))
+				/* no index provided use the current one */
+				index = current_index;
+
+			/* now send the key to the card  */
+			rvalue |=
+			    mgt_set_request(priv, DOT11_OID_DEFKEYX, index,
+					    &key);
+		}
+		/*
+		 * If a valid key is set, encryption should be enabled 
+		 * (user may turn it off later).
+		 * This is also how "iwconfig ethX key on" works
+		 */
+		if ((index == current_index) && (key.length > 0))
+			force = 1;
+	} else {
+		int index = (dwrq->flags & IW_ENCODE_INDEX) - 1;
+		if ((index >= 0) && (index <= 3)) {
+			/* we want to set the key index */
+			rvalue |=
+			    mgt_set_request(priv, DOT11_OID_DEFKEYID, 0,
+					    &index);
+		} else {
+			if (!dwrq->flags & IW_ENCODE_MODE) {
+				/* we cannot do anything. Complain. */
+				return -EINVAL;
+			}
+		}
+	}
+	/* now read the flags */
+	if (dwrq->flags & IW_ENCODE_DISABLED) {
+		/* Encoding disabled, 
+		 * authen = DOT11_AUTH_OS;
+		 * invoke = 0;
+		 * exunencrypt = 0; */
+	}
+	if (dwrq->flags & IW_ENCODE_OPEN)
+		/* Encode but accept non-encoded packets. No auth */
+		invoke = 1;
+	if ((dwrq->flags & IW_ENCODE_RESTRICTED) || force) {
+		/* Refuse non-encoded packets. Auth */
+		authen = DOT11_AUTH_BOTH;
+		invoke = 1;
+		exunencrypt = 1;
+	}
+	/* do the change if requested  */
+	if ((dwrq->flags & IW_ENCODE_MODE) || force) {
+		rvalue |=
+		    mgt_set_request(priv, DOT11_OID_AUTHENABLE, 0, &authen);
+		rvalue |=
+		    mgt_set_request(priv, DOT11_OID_PRIVACYINVOKED, 0, &invoke);
+		rvalue |=
+		    mgt_set_request(priv, DOT11_OID_EXUNENCRYPTED, 0,
+				    &exunencrypt);
+	}
+	return rvalue;
+}
+
+static int
+prism54_get_encode(struct net_device *ndev, struct iw_request_info *info,
+		   struct iw_point *dwrq, char *extra)
+{
+	islpci_private *priv = netdev_priv(ndev);
+	struct obj_key *key;
+	u32 devindex, index = (dwrq->flags & IW_ENCODE_INDEX) - 1;
+	u32 authen = 0, invoke = 0, exunencrypt = 0;
+	int rvalue;
+	union oid_res_t r;
+
+	/* first get the flags */
+	rvalue = mgt_get_request(priv, DOT11_OID_AUTHENABLE, 0, NULL, &r);
+	authen = r.u;
+	rvalue |= mgt_get_request(priv, DOT11_OID_PRIVACYINVOKED, 0, NULL, &r);
+	invoke = r.u;
+	rvalue |= mgt_get_request(priv, DOT11_OID_EXUNENCRYPTED, 0, NULL, &r);
+	exunencrypt = r.u;
+
+	if (invoke && (authen == DOT11_AUTH_BOTH) && exunencrypt)
+		dwrq->flags = IW_ENCODE_RESTRICTED;
+	else if ((authen == DOT11_AUTH_OS) && !exunencrypt) {
+		if (invoke)
+			dwrq->flags = IW_ENCODE_OPEN;
+		else
+			dwrq->flags = IW_ENCODE_DISABLED;
+	} else
+		/* The card should not work in this state */
+		dwrq->flags = 0;
+
+	/* get the current device key index */
+	rvalue |= mgt_get_request(priv, DOT11_OID_DEFKEYID, 0, NULL, &r);
+	devindex = r.u;
+	/* Now get the key, return it */
+	if ((index < 0) || (index > 3))
+		/* no index provided, use the current one */
+		index = devindex;
+	rvalue |= mgt_get_request(priv, DOT11_OID_DEFKEYX, index, NULL, &r);
+	key = r.ptr;
+	dwrq->length = key->length;
+	memcpy(extra, key->key, dwrq->length);
+	kfree(key);
+	/* return the used key index */
+	dwrq->flags |= devindex + 1;
+
+	return rvalue;
+}
+
+static int
+prism54_get_txpower(struct net_device *ndev, struct iw_request_info *info,
+		    struct iw_param *vwrq, char *extra)
+{
+	islpci_private *priv = netdev_priv(ndev);
+	union oid_res_t r;
+	int rvalue;
+
+	rvalue = mgt_get_request(priv, OID_INL_OUTPUTPOWER, 0, NULL, &r);
+	/* intersil firmware operates in 0.25 dBm (1/4 dBm) */
+	vwrq->value = (s32) r.u / 4;
+	vwrq->fixed = 1;
+	/* radio is not turned of
+	 * btw: how is possible to turn off only the radio 
+	 */
+	vwrq->disabled = 0;
+
+	return rvalue;
+}
+
+static int
+prism54_set_txpower(struct net_device *ndev, struct iw_request_info *info,
+		    struct iw_param *vwrq, char *extra)
+{
+	islpci_private *priv = netdev_priv(ndev);
+	s32 u = vwrq->value;
+
+	/* intersil firmware operates in 0.25 dBm (1/4) */
+	u *= 4;
+	if (vwrq->disabled) {
+		/* don't know how to disable radio */
+		printk(KERN_DEBUG
+		       "%s: %s() disabling radio is not yet supported.\n",
+		       priv->ndev->name, __FUNCTION__);
+		return -ENOTSUPP;
+	} else if (vwrq->fixed)
+		/* currently only fixed value is supported */
+		return mgt_set_request(priv, OID_INL_OUTPUTPOWER, 0, &u);
+	else {
+		printk(KERN_DEBUG
+		       "%s: %s() auto power will be implemented later.\n",
+		       priv->ndev->name, __FUNCTION__);
+		return -ENOTSUPP;
+	}
+}
+
+static int
+prism54_reset(struct net_device *ndev, struct iw_request_info *info,
+	      __u32 * uwrq, char *extra)
+{
+	islpci_reset(netdev_priv(ndev), 0);
+
+	return 0;
+}
+
+static int
+prism54_get_oid(struct net_device *ndev, struct iw_request_info *info,
+		struct iw_point *dwrq, char *extra)
+{
+	union oid_res_t r;
+	int rvalue;
+	enum oid_num_t n = dwrq->flags;
+
+	rvalue = mgt_get_request((islpci_private *) ndev->priv, n, 0, NULL, &r);
+	dwrq->length = mgt_response_to_str(n, &r, extra);
+	if ((isl_oid[n].flags & OID_FLAG_TYPE) != OID_TYPE_U32)
+		kfree(r.ptr);
+	return rvalue;
+}
+
+static int
+prism54_set_u32(struct net_device *ndev, struct iw_request_info *info,
+		__u32 * uwrq, char *extra)
+{
+	u32 oid = uwrq[0], u = uwrq[1];
+
+	return mgt_set_request((islpci_private *) ndev->priv, oid, 0, &u);
+}
+
+static int
+prism54_set_raw(struct net_device *ndev, struct iw_request_info *info,
+		struct iw_point *dwrq, char *extra)
+{
+	u32 oid = dwrq->flags;
+
+	return mgt_set_request((islpci_private *) ndev->priv, oid, 0, extra);
+}
+
+void
+prism54_acl_init(struct islpci_acl *acl)
+{
+	sema_init(&acl->sem, 1);
+	INIT_LIST_HEAD(&acl->mac_list);
+	acl->size = 0;
+	acl->policy = MAC_POLICY_OPEN;
+}
+
+static void
+prism54_clear_mac(struct islpci_acl *acl)
+{
+	struct list_head *ptr, *next;
+	struct mac_entry *entry;
+
+	if (down_interruptible(&acl->sem))
+		return;
+
+	if (acl->size == 0) {
+		up(&acl->sem);
+		return;
+	}
+
+	for (ptr = acl->mac_list.next, next = ptr->next;
+	     ptr != &acl->mac_list; ptr = next, next = ptr->next) {
+		entry = list_entry(ptr, struct mac_entry, _list);
+		list_del(ptr);
+		kfree(entry);
+	}
+	acl->size = 0;
+	up(&acl->sem);
+}
+
+void
+prism54_acl_clean(struct islpci_acl *acl)
+{
+	prism54_clear_mac(acl);
+}
+
+static int
+prism54_add_mac(struct net_device *ndev, struct iw_request_info *info,
+		struct sockaddr *awrq, char *extra)
+{
+	islpci_private *priv = netdev_priv(ndev);
+	struct islpci_acl *acl = &priv->acl;
+	struct mac_entry *entry;
+	struct sockaddr *addr = (struct sockaddr *) extra;
+
+	if (addr->sa_family != ARPHRD_ETHER)
+		return -EOPNOTSUPP;
+
+	entry = kmalloc(sizeof (struct mac_entry), GFP_KERNEL);
+	if (entry == NULL)
+		return -ENOMEM;
+
+	memcpy(entry->addr, addr->sa_data, ETH_ALEN);
+
+	if (down_interruptible(&acl->sem)) {
+		kfree(entry);
+		return -ERESTARTSYS;
+	}
+	list_add_tail(&entry->_list, &acl->mac_list);
+	acl->size++;
+	up(&acl->sem);
+
+	return 0;
+}
+
+static int
+prism54_del_mac(struct net_device *ndev, struct iw_request_info *info,
+		struct sockaddr *awrq, char *extra)
+{
+	islpci_private *priv = netdev_priv(ndev);
+	struct islpci_acl *acl = &priv->acl;
+	struct mac_entry *entry;
+	struct list_head *ptr;
+	struct sockaddr *addr = (struct sockaddr *) extra;
+
+	if (addr->sa_family != ARPHRD_ETHER)
+		return -EOPNOTSUPP;
+
+	if (down_interruptible(&acl->sem))
+		return -ERESTARTSYS;
+	for (ptr = acl->mac_list.next; ptr != &acl->mac_list; ptr = ptr->next) {
+		entry = list_entry(ptr, struct mac_entry, _list);
+
+		if (memcmp(entry->addr, addr->sa_data, ETH_ALEN) == 0) {
+			list_del(ptr);
+			acl->size--;
+			kfree(entry);
+			up(&acl->sem);
+			return 0;
+		}
+	}
+	up(&acl->sem);
+	return -EINVAL;
+}
+
+static int
+prism54_get_mac(struct net_device *ndev, struct iw_request_info *info,
+		struct iw_point *dwrq, char *extra)
+{
+	islpci_private *priv = netdev_priv(ndev);
+	struct islpci_acl *acl = &priv->acl;
+	struct mac_entry *entry;
+	struct list_head *ptr;
+	struct sockaddr *dst = (struct sockaddr *) extra;
+
+	dwrq->length = 0;
+
+	if (down_interruptible(&acl->sem))
+		return -ERESTARTSYS;
+
+	for (ptr = acl->mac_list.next; ptr != &acl->mac_list; ptr = ptr->next) {
+		entry = list_entry(ptr, struct mac_entry, _list);
+
+		memcpy(dst->sa_data, entry->addr, ETH_ALEN);
+		dst->sa_family = ARPHRD_ETHER;
+		dwrq->length++;
+		dst++;
+	}
+	up(&acl->sem);
+	return 0;
+}
+
+/* Setting policy also clears the MAC acl, even if we don't change the defaut
+ * policy
+ */
+
+static int
+prism54_set_policy(struct net_device *ndev, struct iw_request_info *info,
+		   __u32 * uwrq, char *extra)
+{
+	islpci_private *priv = netdev_priv(ndev);
+	struct islpci_acl *acl = &priv->acl;
+	u32 mlmeautolevel;
+
+	prism54_clear_mac(acl);
+
+	if ((*uwrq < MAC_POLICY_OPEN) || (*uwrq > MAC_POLICY_REJECT))
+		return -EINVAL;
+
+	down_write(&priv->mib_sem);
+
+	acl->policy = *uwrq;
+
+	/* the ACL code needs an intermediate mlmeautolevel */
+	if ((priv->iw_mode == IW_MODE_MASTER) &&
+	    (acl->policy != MAC_POLICY_OPEN))
+		mlmeautolevel = DOT11_MLME_INTERMEDIATE;
+	else
+		mlmeautolevel = CARD_DEFAULT_MLME_MODE;
+	if (priv->wpa)
+		mlmeautolevel = DOT11_MLME_EXTENDED;
+	mgt_set(priv, DOT11_OID_MLMEAUTOLEVEL, &mlmeautolevel);
+	/* restart the card with our new policy */
+	mgt_commit(priv);
+	up_write(&priv->mib_sem);
+
+	return 0;
+}
+
+static int
+prism54_get_policy(struct net_device *ndev, struct iw_request_info *info,
+		   __u32 * uwrq, char *extra)
+{
+	islpci_private *priv = netdev_priv(ndev);
+	struct islpci_acl *acl = &priv->acl;
+
+	*uwrq = acl->policy;
+
+	return 0;
+}
+
+/* Return 1 only if client should be accepted. */
+
+static int
+prism54_mac_accept(struct islpci_acl *acl, char *mac)
+{
+	struct list_head *ptr;
+	struct mac_entry *entry;
+	int res = 0;
+
+	if (down_interruptible(&acl->sem))
+		return -ERESTARTSYS;
+
+	if (acl->policy == MAC_POLICY_OPEN) {
+		up(&acl->sem);
+		return 1;
+	}
+
+	for (ptr = acl->mac_list.next; ptr != &acl->mac_list; ptr = ptr->next) {
+		entry = list_entry(ptr, struct mac_entry, _list);
+		if (memcmp(entry->addr, mac, ETH_ALEN) == 0) {
+			res = 1;
+			break;
+		}
+	}
+	res = (acl->policy == MAC_POLICY_ACCEPT) ? !res : res;
+	up(&acl->sem);
+
+	return res;
+}
+
+static int
+prism54_kick_all(struct net_device *ndev, struct iw_request_info *info,
+		 struct iw_point *dwrq, char *extra)
+{
+	struct obj_mlme *mlme;
+	int rvalue;
+
+	mlme = kmalloc(sizeof (struct obj_mlme), GFP_KERNEL);
+	if (mlme == NULL)
+		return -ENOMEM;
+
+	/* Tell the card to kick every client */
+	mlme->id = 0;
+	rvalue =
+	    mgt_set_request(netdev_priv(ndev), DOT11_OID_DISASSOCIATE, 0, mlme);
+	kfree(mlme);
+
+	return rvalue;
+}
+
+static int
+prism54_kick_mac(struct net_device *ndev, struct iw_request_info *info,
+		 struct sockaddr *awrq, char *extra)
+{
+	struct obj_mlme *mlme;
+	struct sockaddr *addr = (struct sockaddr *) extra;
+	int rvalue;
+
+	if (addr->sa_family != ARPHRD_ETHER)
+		return -EOPNOTSUPP;
+
+	mlme = kmalloc(sizeof (struct obj_mlme), GFP_KERNEL);
+	if (mlme == NULL)
+		return -ENOMEM;
+
+	/* Tell the card to only kick the corresponding bastard */
+	memcpy(mlme->address, addr->sa_data, ETH_ALEN);
+	mlme->id = -1;
+	rvalue =
+	    mgt_set_request(netdev_priv(ndev), DOT11_OID_DISASSOCIATE, 0, mlme);
+
+	kfree(mlme);
+
+	return rvalue;
+}
+
+/* Translate a TRAP oid into a wireless event. Called in islpci_mgt_receive. */
+
+static void
+format_event(islpci_private *priv, char *dest, const char *str,
+	     const struct obj_mlme *mlme, u16 *length, int error)
+{
+	const u8 *a = mlme->address;
+	int n = snprintf(dest, IW_CUSTOM_MAX,
+			 "%s %s %2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X %s (%2.2X)",
+			 str,
+			 ((priv->iw_mode == IW_MODE_MASTER) ? "from" : "to"),
+			 a[0], a[1], a[2], a[3], a[4], a[5],
+			 (error ? (mlme->code ? " : REJECTED " : " : ACCEPTED ")
+			  : ""), mlme->code);
+	BUG_ON(n > IW_CUSTOM_MAX);
+	*length = n;
+}
+
+static void
+send_formatted_event(islpci_private *priv, const char *str,
+		     const struct obj_mlme *mlme, int error)
+{
+	union iwreq_data wrqu;
+
+	wrqu.data.pointer = kmalloc(IW_CUSTOM_MAX, GFP_KERNEL);
+	if (!wrqu.data.pointer)
+		return;
+	wrqu.data.length = 0;
+	format_event(priv, wrqu.data.pointer, str, mlme, &wrqu.data.length,
+		     error);
+	wireless_send_event(priv->ndev, IWEVCUSTOM, &wrqu, wrqu.data.pointer);
+	kfree(wrqu.data.pointer);
+}
+
+static void
+send_simple_event(islpci_private *priv, const char *str)
+{
+	union iwreq_data wrqu;
+	int n = strlen(str);
+
+	wrqu.data.pointer = kmalloc(IW_CUSTOM_MAX, GFP_KERNEL);
+	if (!wrqu.data.pointer)
+		return;
+	BUG_ON(n > IW_CUSTOM_MAX);
+	wrqu.data.length = n;
+	strcpy(wrqu.data.pointer, str);
+	wireless_send_event(priv->ndev, IWEVCUSTOM, &wrqu, wrqu.data.pointer);
+	kfree(wrqu.data.pointer);
+}
+
+static void
+link_changed(struct net_device *ndev, u32 bitrate)
+{
+	islpci_private *priv = netdev_priv(ndev);
+
+	if (bitrate) {
+		if (priv->iw_mode == IW_MODE_INFRA) {
+			union iwreq_data uwrq;
+			prism54_get_wap(ndev, NULL, (struct sockaddr *) &uwrq,
+					NULL);
+			wireless_send_event(ndev, SIOCGIWAP, &uwrq, NULL);
+		} else
+			send_simple_event(netdev_priv(ndev),
+					  "Link established");
+	} else
+		send_simple_event(netdev_priv(ndev), "Link lost");
+}
+
+/* Beacon/ProbeResp payload header */
+struct ieee80211_beacon_phdr {
+	u8 timestamp[8];
+	u16 beacon_int;
+	u16 capab_info;
+} __attribute__ ((packed));
+
+#define WLAN_EID_GENERIC 0xdd
+static u8 wpa_oid[4] = { 0x00, 0x50, 0xf2, 1 };
+
+#define MAC2STR(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5]
+#define MACSTR "%02x:%02x:%02x:%02x:%02x:%02x"
+
+void
+prism54_wpa_ie_add(islpci_private *priv, u8 *bssid,
+		   u8 *wpa_ie, size_t wpa_ie_len)
+{
+	struct list_head *ptr;
+	struct islpci_bss_wpa_ie *bss = NULL;
+
+	if (wpa_ie_len > MAX_WPA_IE_LEN)
+		wpa_ie_len = MAX_WPA_IE_LEN;
+
+	if (down_interruptible(&priv->wpa_sem))
+		return;
+
+	/* try to use existing entry */
+	list_for_each(ptr, &priv->bss_wpa_list) {
+		bss = list_entry(ptr, struct islpci_bss_wpa_ie, list);
+		if (memcmp(bss->bssid, bssid, ETH_ALEN) == 0) {
+			list_move(&bss->list, &priv->bss_wpa_list);
+			break;
+		}
+		bss = NULL;
+	}
+
+	if (bss == NULL) {
+		/* add a new BSS entry; if max number of entries is already
+		 * reached, replace the least recently updated */
+		if (priv->num_bss_wpa >= MAX_BSS_WPA_IE_COUNT) {
+			bss = list_entry(priv->bss_wpa_list.prev,
+					 struct islpci_bss_wpa_ie, list);
+			list_del(&bss->list);
+		} else {
+			bss = kmalloc(sizeof (*bss), GFP_ATOMIC);
+			if (bss != NULL) {
+				priv->num_bss_wpa++;
+				memset(bss, 0, sizeof (*bss));
+			}
+		}
+		if (bss != NULL) {
+			memcpy(bss->bssid, bssid, ETH_ALEN);
+			list_add(&bss->list, &priv->bss_wpa_list);
+		}
+	}
+
+	if (bss != NULL) {
+		memcpy(bss->wpa_ie, wpa_ie, wpa_ie_len);
+		bss->wpa_ie_len = wpa_ie_len;
+		bss->last_update = jiffies;
+	} else {
+		printk(KERN_DEBUG "Failed to add BSS WPA entry for " MACSTR
+		       "\n", MAC2STR(bssid));
+	}
+
+	/* expire old entries from WPA list */
+	while (priv->num_bss_wpa > 0) {
+		bss = list_entry(priv->bss_wpa_list.prev,
+				 struct islpci_bss_wpa_ie, list);
+		if (!time_after(jiffies, bss->last_update + 60 * HZ))
+			break;
+
+		list_del(&bss->list);
+		priv->num_bss_wpa--;
+		kfree(bss);
+	}
+
+	up(&priv->wpa_sem);
+}
+
+size_t
+prism54_wpa_ie_get(islpci_private *priv, u8 *bssid, u8 *wpa_ie)
+{
+	struct list_head *ptr;
+	struct islpci_bss_wpa_ie *bss = NULL;
+	size_t len = 0;
+
+	if (down_interruptible(&priv->wpa_sem))
+		return 0;
+
+	list_for_each(ptr, &priv->bss_wpa_list) {
+		bss = list_entry(ptr, struct islpci_bss_wpa_ie, list);
+		if (memcmp(bss->bssid, bssid, ETH_ALEN) == 0)
+			break;
+		bss = NULL;
+	}
+	if (bss) {
+		len = bss->wpa_ie_len;
+		memcpy(wpa_ie, bss->wpa_ie, len);
+	}
+	up(&priv->wpa_sem);
+
+	return len;
+}
+
+void
+prism54_wpa_ie_init(islpci_private *priv)
+{
+	INIT_LIST_HEAD(&priv->bss_wpa_list);
+	sema_init(&priv->wpa_sem, 1);
+}
+
+void
+prism54_wpa_ie_clean(islpci_private *priv)
+{
+	struct list_head *ptr, *n;
+
+	list_for_each_safe(ptr, n, &priv->bss_wpa_list) {
+		struct islpci_bss_wpa_ie *bss;
+		bss = list_entry(ptr, struct islpci_bss_wpa_ie, list);
+		kfree(bss);
+	}
+}
+
+static void
+prism54_process_bss_data(islpci_private *priv, u32 oid, u8 *addr,
+			 u8 *payload, size_t len)
+{
+	struct ieee80211_beacon_phdr *hdr;
+	u8 *pos, *end;
+
+	if (!priv->wpa)
+		return;
+
+	hdr = (struct ieee80211_beacon_phdr *) payload;
+	pos = (u8 *) (hdr + 1);
+	end = payload + len;
+	while (pos < end) {
+		if (pos + 2 + pos[1] > end) {
+			printk(KERN_DEBUG "Parsing Beacon/ProbeResp failed "
+			       "for " MACSTR "\n", MAC2STR(addr));
+			return;
+		}
+		if (pos[0] == WLAN_EID_GENERIC && pos[1] >= 4 &&
+		    memcmp(pos + 2, wpa_oid, 4) == 0) {
+			prism54_wpa_ie_add(priv, addr, pos, pos[1] + 2);
+			return;
+		}
+		pos += 2 + pos[1];
+	}
+}
+
+static void
+handle_request(islpci_private *priv, struct obj_mlme *mlme, enum oid_num_t oid)
+{
+	if (((mlme->state == DOT11_STATE_AUTHING) ||
+	     (mlme->state == DOT11_STATE_ASSOCING))
+	    && mgt_mlme_answer(priv)) {
+		/* Someone is requesting auth and we must respond. Just send back
+		 * the trap with error code set accordingly.
+		 */
+		mlme->code = prism54_mac_accept(&priv->acl,
+						mlme->address) ? 0 : 1;
+		mgt_set_request(priv, oid, 0, mlme);
+	}
+}
+
+int
+prism54_process_trap_helper(islpci_private *priv, enum oid_num_t oid,
+			    char *data)
+{
+	struct obj_mlme *mlme = (struct obj_mlme *) data;
+	size_t len;
+	u8 *payload, *pos = (u8 *) (mlme + 1);
+
+	len = pos[0] | (pos[1] << 8);	/* little endian data length */
+	payload = pos + 2;
+
+	/* I think all trapable objects are listed here.
+	 * Some oids have a EX version. The difference is that they are emitted
+	 * in DOT11_MLME_EXTENDED mode (set with DOT11_OID_MLMEAUTOLEVEL)
+	 * with more info.
+	 * The few events already defined by the wireless tools are not really
+	 * suited. We use the more flexible custom event facility.
+	 */
+
+	/* I fear prism54_process_bss_data won't work with big endian data */
+	if ((oid == DOT11_OID_BEACON) || (oid == DOT11_OID_PROBE))
+		prism54_process_bss_data(priv, oid, mlme->address,
+					 payload, len);
+
+	mgt_le_to_cpu(isl_oid[oid].flags & OID_FLAG_TYPE, (void *) mlme);
+
+	switch (oid) {
+
+	case GEN_OID_LINKSTATE:
+		link_changed(priv->ndev, (u32) *data);
+		break;
+
+	case DOT11_OID_MICFAILURE:
+		send_simple_event(priv, "Mic failure");
+		break;
+
+	case DOT11_OID_DEAUTHENTICATE:
+		send_formatted_event(priv, "DeAuthenticate request", mlme, 0);
+		break;
+
+	case DOT11_OID_AUTHENTICATE:
+		handle_request(priv, mlme, oid);
+		send_formatted_event(priv, "Authenticate request", mlme, 1);
+		break;
+
+	case DOT11_OID_DISASSOCIATE:
+		send_formatted_event(priv, "Disassociate request", mlme, 0);
+		break;
+
+	case DOT11_OID_ASSOCIATE:
+		handle_request(priv, mlme, oid);
+		send_formatted_event(priv, "Associate request", mlme, 1);
+		break;
+
+	case DOT11_OID_REASSOCIATE:
+		handle_request(priv, mlme, oid);
+		send_formatted_event(priv, "ReAssociate request", mlme, 1);
+		break;
+
+	case DOT11_OID_BEACON:
+		send_formatted_event(priv,
+				     "Received a beacon from an unkown AP",
+				     mlme, 0);
+		break;
+
+	case DOT11_OID_PROBE:
+		/* we received a probe from a client. */
+		send_formatted_event(priv, "Received a probe from client", mlme,
+				     0);
+		break;
+
+		/* Note : "mlme" is actually a "struct obj_mlmeex *" here, but this
+		 * is backward compatible layout-wise with "struct obj_mlme".
+		 */
+
+	case DOT11_OID_DEAUTHENTICATEEX:
+		send_formatted_event(priv, "DeAuthenticate request", mlme, 0);
+		break;
+
+	case DOT11_OID_AUTHENTICATEEX:
+		handle_request(priv, mlme, oid);
+		send_formatted_event(priv, "Authenticate request", mlme, 1);
+		break;
+
+	case DOT11_OID_DISASSOCIATEEX:
+		send_formatted_event(priv, "Disassociate request", mlme, 0);
+		break;
+
+	case DOT11_OID_ASSOCIATEEX:
+		handle_request(priv, mlme, oid);
+		send_formatted_event(priv, "Associate request", mlme, 1);
+		break;
+
+	case DOT11_OID_REASSOCIATEEX:
+		handle_request(priv, mlme, oid);
+		send_formatted_event(priv, "Reassociate request", mlme, 1);
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+/*
+ * Process a device trap.  This is called via schedule_work(), outside of
+ * interrupt context, no locks held.
+ */
+void
+prism54_process_trap(void *data)
+{
+	struct islpci_mgmtframe *frame = data;
+	struct net_device *ndev = frame->ndev;
+	enum oid_num_t n = mgt_oidtonum(frame->header->oid);
+
+	if (n != OID_NUM_LAST)
+		prism54_process_trap_helper(netdev_priv(ndev), n, frame->data);
+	islpci_mgt_release(frame);
+}
+
+int
+prism54_set_mac_address(struct net_device *ndev, void *addr)
+{
+	islpci_private *priv = netdev_priv(ndev);
+	int ret;
+
+	if (ndev->addr_len != 6)
+		return -EINVAL;
+	ret = mgt_set_request(priv, GEN_OID_MACADDRESS, 0,
+			      &((struct sockaddr *) addr)->sa_data);
+	if (!ret)
+		memcpy(priv->ndev->dev_addr,
+		       &((struct sockaddr *) addr)->sa_data, 6);
+
+	return ret;
+}
+
+int
+prism54_set_wpa(struct net_device *ndev, struct iw_request_info *info,
+		__u32 * uwrq, char *extra)
+{
+	islpci_private *priv = netdev_priv(ndev);
+
+	down_write(&priv->mib_sem);
+
+	priv->wpa = *uwrq;
+	if (priv->wpa) {
+		u32 l = DOT11_MLME_EXTENDED;
+		mgt_set(priv, DOT11_OID_MLMEAUTOLEVEL, &l);
+	}
+	/* restart the card with new level. Needed ? */
+	mgt_commit(priv);
+	up_write(&priv->mib_sem);
+
+	return 0;
+}
+
+int
+prism54_get_wpa(struct net_device *ndev, struct iw_request_info *info,
+		__u32 * uwrq, char *extra)
+{
+	islpci_private *priv = netdev_priv(ndev);
+	*uwrq = priv->wpa;
+	return 0;
+}
+
+int
+prism54_set_prismhdr(struct net_device *ndev, struct iw_request_info *info,
+		     __u32 * uwrq, char *extra)
+{
+	islpci_private *priv = netdev_priv(ndev);
+	priv->monitor_type =
+	    (*uwrq ? ARPHRD_IEEE80211_PRISM : ARPHRD_IEEE80211);
+	if (priv->iw_mode == IW_MODE_MONITOR)
+		priv->ndev->type = priv->monitor_type;
+
+	return 0;
+}
+
+int
+prism54_get_prismhdr(struct net_device *ndev, struct iw_request_info *info,
+		     __u32 * uwrq, char *extra)
+{
+	islpci_private *priv = netdev_priv(ndev);
+	*uwrq = (priv->monitor_type == ARPHRD_IEEE80211_PRISM);
+	return 0;
+}
+
+int
+prism54_debug_oid(struct net_device *ndev, struct iw_request_info *info,
+		  __u32 * uwrq, char *extra)
+{
+	islpci_private *priv = netdev_priv(ndev);
+
+	priv->priv_oid = *uwrq;
+	printk("%s: oid 0x%08X\n", ndev->name, *uwrq);
+
+	return 0;
+}
+
+int
+prism54_debug_get_oid(struct net_device *ndev, struct iw_request_info *info,
+		      struct iw_point *data, char *extra)
+{
+	islpci_private *priv = netdev_priv(ndev);
+	struct islpci_mgmtframe *response = NULL;
+	int ret = -EIO;
+
+	printk("%s: get_oid 0x%08X\n", ndev->name, priv->priv_oid);
+	data->length = 0;
+
+	if (islpci_get_state(priv) >= PRV_STATE_INIT) {
+		ret =
+		    islpci_mgt_transaction(priv->ndev, PIMFOR_OP_GET,
+					   priv->priv_oid, extra, 256,
+					   &response);
+		printk("%s: ret: %i\n", ndev->name, ret);
+		if (ret || !response
+		    || response->header->operation == PIMFOR_OP_ERROR) {
+			if (response) {
+				islpci_mgt_release(response);
+			}
+			printk("%s: EIO\n", ndev->name);
+			ret = -EIO;
+		}
+		if (!ret) {
+			data->length = response->header->length;
+			memcpy(extra, response->data, data->length);
+			islpci_mgt_release(response);
+			printk("%s: len: %i\n", ndev->name, data->length);
+		}
+	}
+
+	return ret;
+}
+
+int
+prism54_debug_set_oid(struct net_device *ndev, struct iw_request_info *info,
+		      struct iw_point *data, char *extra)
+{
+	islpci_private *priv = netdev_priv(ndev);
+	struct islpci_mgmtframe *response = NULL;
+	int ret = 0, response_op = PIMFOR_OP_ERROR;
+
+	printk("%s: set_oid 0x%08X\tlen: %d\n", ndev->name, priv->priv_oid,
+	       data->length);
+
+	if (islpci_get_state(priv) >= PRV_STATE_INIT) {
+		ret =
+		    islpci_mgt_transaction(priv->ndev, PIMFOR_OP_SET,
+					   priv->priv_oid, extra, data->length,
+					   &response);
+		printk("%s: ret: %i\n", ndev->name, ret);
+		if (ret || !response
+		    || response->header->operation == PIMFOR_OP_ERROR) {
+			if (response) {
+				islpci_mgt_release(response);
+			}
+			printk("%s: EIO\n", ndev->name);
+			ret = -EIO;
+		}
+		if (!ret) {
+			response_op = response->header->operation;
+			printk("%s: response_op: %i\n", ndev->name,
+			       response_op);
+			islpci_mgt_release(response);
+		}
+	}
+
+	return (ret ? ret : -EINPROGRESS);
+}
+
+static int
+prism54_set_spy(struct net_device *ndev,
+		struct iw_request_info *info,
+		union iwreq_data *uwrq, char *extra)
+{
+	islpci_private *priv = netdev_priv(ndev);
+	u32 u, oid = OID_INL_CONFIG;
+
+	down_write(&priv->mib_sem);
+	mgt_get(priv, OID_INL_CONFIG, &u);
+
+	if ((uwrq->data.length == 0) && (priv->spy_data.spy_number > 0))
+		/* disable spy */
+		u &= ~INL_CONFIG_RXANNEX;
+	else if ((uwrq->data.length > 0) && (priv->spy_data.spy_number == 0))
+		/* enable spy */
+		u |= INL_CONFIG_RXANNEX;
+
+	mgt_set(priv, OID_INL_CONFIG, &u);
+	mgt_commit_list(priv, &oid, 1);
+	up_write(&priv->mib_sem);
+
+	return iw_handler_set_spy(ndev, info, uwrq, extra);
+}
+
+static const iw_handler prism54_handler[] = {
+	(iw_handler) prism54_commit,	/* SIOCSIWCOMMIT */
+	(iw_handler) prism54_get_name,	/* SIOCGIWNAME */
+	(iw_handler) NULL,	/* SIOCSIWNWID */
+	(iw_handler) NULL,	/* SIOCGIWNWID */
+	(iw_handler) prism54_set_freq,	/* SIOCSIWFREQ */
+	(iw_handler) prism54_get_freq,	/* SIOCGIWFREQ */
+	(iw_handler) prism54_set_mode,	/* SIOCSIWMODE */
+	(iw_handler) prism54_get_mode,	/* SIOCGIWMODE */
+	(iw_handler) prism54_set_sens,	/* SIOCSIWSENS */
+	(iw_handler) prism54_get_sens,	/* SIOCGIWSENS */
+	(iw_handler) NULL,	/* SIOCSIWRANGE */
+	(iw_handler) prism54_get_range,	/* SIOCGIWRANGE */
+	(iw_handler) NULL,	/* SIOCSIWPRIV */
+	(iw_handler) NULL,	/* SIOCGIWPRIV */
+	(iw_handler) NULL,	/* SIOCSIWSTATS */
+	(iw_handler) NULL,	/* SIOCGIWSTATS */
+	prism54_set_spy,	/* SIOCSIWSPY */
+	iw_handler_get_spy,	/* SIOCGIWSPY */
+	iw_handler_set_thrspy,	/* SIOCSIWTHRSPY */
+	iw_handler_get_thrspy,	/* SIOCGIWTHRSPY */
+	(iw_handler) prism54_set_wap,	/* SIOCSIWAP */
+	(iw_handler) prism54_get_wap,	/* SIOCGIWAP */
+	(iw_handler) NULL,	/* -- hole -- */
+	(iw_handler) NULL,	/* SIOCGIWAPLIST depreciated */
+	(iw_handler) prism54_set_scan,	/* SIOCSIWSCAN */
+	(iw_handler) prism54_get_scan,	/* SIOCGIWSCAN */
+	(iw_handler) prism54_set_essid,	/* SIOCSIWESSID */
+	(iw_handler) prism54_get_essid,	/* SIOCGIWESSID */
+	(iw_handler) prism54_set_nick,	/* SIOCSIWNICKN */
+	(iw_handler) prism54_get_nick,	/* SIOCGIWNICKN */
+	(iw_handler) NULL,	/* -- hole -- */
+	(iw_handler) NULL,	/* -- hole -- */
+	(iw_handler) prism54_set_rate,	/* SIOCSIWRATE */
+	(iw_handler) prism54_get_rate,	/* SIOCGIWRATE */
+	(iw_handler) prism54_set_rts,	/* SIOCSIWRTS */
+	(iw_handler) prism54_get_rts,	/* SIOCGIWRTS */
+	(iw_handler) prism54_set_frag,	/* SIOCSIWFRAG */
+	(iw_handler) prism54_get_frag,	/* SIOCGIWFRAG */
+	(iw_handler) prism54_set_txpower,	/* SIOCSIWTXPOW */
+	(iw_handler) prism54_get_txpower,	/* SIOCGIWTXPOW */
+	(iw_handler) prism54_set_retry,	/* SIOCSIWRETRY */
+	(iw_handler) prism54_get_retry,	/* SIOCGIWRETRY */
+	(iw_handler) prism54_set_encode,	/* SIOCSIWENCODE */
+	(iw_handler) prism54_get_encode,	/* SIOCGIWENCODE */
+	(iw_handler) NULL,	/* SIOCSIWPOWER */
+	(iw_handler) NULL,	/* SIOCGIWPOWER */
+};
+
+/* The low order bit identify a SET (0) or a GET (1) ioctl.  */
+
+#define PRISM54_RESET		SIOCIWFIRSTPRIV
+#define PRISM54_GET_POLICY	SIOCIWFIRSTPRIV+1
+#define PRISM54_SET_POLICY	SIOCIWFIRSTPRIV+2
+#define PRISM54_GET_MAC		SIOCIWFIRSTPRIV+3
+#define PRISM54_ADD_MAC		SIOCIWFIRSTPRIV+4
+
+#define PRISM54_DEL_MAC		SIOCIWFIRSTPRIV+6
+
+#define PRISM54_KICK_MAC	SIOCIWFIRSTPRIV+8
+
+#define PRISM54_KICK_ALL	SIOCIWFIRSTPRIV+10
+
+#define PRISM54_GET_WPA		SIOCIWFIRSTPRIV+11
+#define PRISM54_SET_WPA		SIOCIWFIRSTPRIV+12
+
+#define PRISM54_DBG_OID		SIOCIWFIRSTPRIV+14
+#define PRISM54_DBG_GET_OID	SIOCIWFIRSTPRIV+15
+#define PRISM54_DBG_SET_OID	SIOCIWFIRSTPRIV+16
+
+#define PRISM54_GET_OID		SIOCIWFIRSTPRIV+17
+#define PRISM54_SET_OID_U32	SIOCIWFIRSTPRIV+18
+#define	PRISM54_SET_OID_STR	SIOCIWFIRSTPRIV+20
+#define	PRISM54_SET_OID_ADDR	SIOCIWFIRSTPRIV+22
+
+#define PRISM54_GET_PRISMHDR	SIOCIWFIRSTPRIV+23
+#define PRISM54_SET_PRISMHDR	SIOCIWFIRSTPRIV+24
+
+#define IWPRIV_SET_U32(n,x)	{ n, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "s_"x }
+#define IWPRIV_SET_SSID(n,x)	{ n, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | 1, 0, "s_"x }
+#define IWPRIV_SET_ADDR(n,x)	{ n, IW_PRIV_TYPE_ADDR | IW_PRIV_SIZE_FIXED | 1, 0, "s_"x }
+#define IWPRIV_GET(n,x)	{ n, 0, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | PRIV_STR_SIZE, "g_"x }
+
+#define IWPRIV_U32(n,x)		IWPRIV_SET_U32(n,x), IWPRIV_GET(n,x)
+#define IWPRIV_SSID(n,x)	IWPRIV_SET_SSID(n,x), IWPRIV_GET(n,x)
+#define IWPRIV_ADDR(n,x)	IWPRIV_SET_ADDR(n,x), IWPRIV_GET(n,x)
+
+/* Note : limited to 128 private ioctls (wireless tools 26) */
+
+static const struct iw_priv_args prism54_private_args[] = {
+/*{ cmd, set_args, get_args, name } */
+	{PRISM54_RESET, 0, 0, "reset"},
+	{PRISM54_GET_PRISMHDR, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+	 "get_prismhdr"},
+	{PRISM54_SET_PRISMHDR, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0,
+	 "set_prismhdr"},
+	{PRISM54_GET_POLICY, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+	 "getPolicy"},
+	{PRISM54_SET_POLICY, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0,
+	 "setPolicy"},
+	{PRISM54_GET_MAC, 0, IW_PRIV_TYPE_ADDR | 64, "getMac"},
+	{PRISM54_ADD_MAC, IW_PRIV_TYPE_ADDR | IW_PRIV_SIZE_FIXED | 1, 0,
+	 "addMac"},
+	{PRISM54_DEL_MAC, IW_PRIV_TYPE_ADDR | IW_PRIV_SIZE_FIXED | 1, 0,
+	 "delMac"},
+	{PRISM54_KICK_MAC, IW_PRIV_TYPE_ADDR | IW_PRIV_SIZE_FIXED | 1, 0,
+	 "kickMac"},
+	{PRISM54_KICK_ALL, 0, 0, "kickAll"},
+	{PRISM54_GET_WPA, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+	 "get_wpa"},
+	{PRISM54_SET_WPA, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0,
+	 "set_wpa"},
+	{PRISM54_DBG_OID, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0,
+	 "dbg_oid"},
+	{PRISM54_DBG_GET_OID, 0, IW_PRIV_TYPE_BYTE | 256, "dbg_get_oid"},
+	{PRISM54_DBG_SET_OID, IW_PRIV_TYPE_BYTE | 256, 0, "dbg_set_oid"},
+	/* --- sub-ioctls handlers --- */
+	{PRISM54_GET_OID,
+	 0, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | PRIV_STR_SIZE, ""},
+	{PRISM54_SET_OID_U32,
+	 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, ""},
+	{PRISM54_SET_OID_STR,
+	 IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | 1, 0, ""},
+	{PRISM54_SET_OID_ADDR,
+	 IW_PRIV_TYPE_ADDR | IW_PRIV_SIZE_FIXED | 1, 0, ""},
+	/* --- sub-ioctls definitions --- */
+	IWPRIV_ADDR(GEN_OID_MACADDRESS, "addr"),
+	IWPRIV_GET(GEN_OID_LINKSTATE, "linkstate"),
+	IWPRIV_U32(DOT11_OID_BSSTYPE, "bsstype"),
+	IWPRIV_ADDR(DOT11_OID_BSSID, "bssid"),
+	IWPRIV_U32(DOT11_OID_STATE, "state"),
+	IWPRIV_U32(DOT11_OID_AID, "aid"),
+
+	IWPRIV_SSID(DOT11_OID_SSIDOVERRIDE, "ssidoverride"),
+
+	IWPRIV_U32(DOT11_OID_MEDIUMLIMIT, "medlimit"),
+	IWPRIV_U32(DOT11_OID_BEACONPERIOD, "beacon"),
+	IWPRIV_U32(DOT11_OID_DTIMPERIOD, "dtimperiod"),
+
+	IWPRIV_U32(DOT11_OID_AUTHENABLE, "authenable"),
+	IWPRIV_U32(DOT11_OID_PRIVACYINVOKED, "privinvok"),
+	IWPRIV_U32(DOT11_OID_EXUNENCRYPTED, "exunencrypt"),
+
+	IWPRIV_U32(DOT11_OID_REKEYTHRESHOLD, "rekeythresh"),
+
+	IWPRIV_U32(DOT11_OID_MAXTXLIFETIME, "maxtxlife"),
+	IWPRIV_U32(DOT11_OID_MAXRXLIFETIME, "maxrxlife"),
+	IWPRIV_U32(DOT11_OID_ALOFT_FIXEDRATE, "fixedrate"),
+	IWPRIV_U32(DOT11_OID_MAXFRAMEBURST, "frameburst"),
+	IWPRIV_U32(DOT11_OID_PSM, "psm"),
+
+	IWPRIV_U32(DOT11_OID_BRIDGELOCAL, "bridge"),
+	IWPRIV_U32(DOT11_OID_CLIENTS, "clients"),
+	IWPRIV_U32(DOT11_OID_CLIENTSASSOCIATED, "clientassoc"),
+	IWPRIV_U32(DOT11_OID_DOT1XENABLE, "dot1xenable"),
+	IWPRIV_U32(DOT11_OID_ANTENNARX, "rxant"),
+	IWPRIV_U32(DOT11_OID_ANTENNATX, "txant"),
+	IWPRIV_U32(DOT11_OID_ANTENNADIVERSITY, "antdivers"),
+	IWPRIV_U32(DOT11_OID_EDTHRESHOLD, "edthresh"),
+	IWPRIV_U32(DOT11_OID_PREAMBLESETTINGS, "preamble"),
+	IWPRIV_GET(DOT11_OID_RATES, "rates"),
+	IWPRIV_U32(DOT11_OID_OUTPUTPOWER, ".11outpower"),
+	IWPRIV_GET(DOT11_OID_SUPPORTEDRATES, "supprates"),
+	IWPRIV_GET(DOT11_OID_SUPPORTEDFREQUENCIES, "suppfreq"),
+
+	IWPRIV_U32(DOT11_OID_NOISEFLOOR, "noisefloor"),
+	IWPRIV_GET(DOT11_OID_FREQUENCYACTIVITY, "freqactivity"),
+	IWPRIV_U32(DOT11_OID_NONERPPROTECTION, "nonerpprotec"),
+	IWPRIV_U32(DOT11_OID_PROFILES, "profile"),
+	IWPRIV_GET(DOT11_OID_EXTENDEDRATES, "extrates"),
+	IWPRIV_U32(DOT11_OID_MLMEAUTOLEVEL, "mlmelevel"),
+
+	IWPRIV_GET(DOT11_OID_BSSS, "bsss"),
+	IWPRIV_GET(DOT11_OID_BSSLIST, "bsslist"),
+	IWPRIV_U32(OID_INL_MODE, "mode"),
+	IWPRIV_U32(OID_INL_CONFIG, "config"),
+	IWPRIV_U32(OID_INL_DOT11D_CONFORMANCE, ".11dconform"),
+	IWPRIV_GET(OID_INL_PHYCAPABILITIES, "phycapa"),
+	IWPRIV_U32(OID_INL_OUTPUTPOWER, "outpower"),
+};
+
+static const iw_handler prism54_private_handler[] = {
+	(iw_handler) prism54_reset,
+	(iw_handler) prism54_get_policy,
+	(iw_handler) prism54_set_policy,
+	(iw_handler) prism54_get_mac,
+	(iw_handler) prism54_add_mac,
+	(iw_handler) NULL,
+	(iw_handler) prism54_del_mac,
+	(iw_handler) NULL,
+	(iw_handler) prism54_kick_mac,
+	(iw_handler) NULL,
+	(iw_handler) prism54_kick_all,
+	(iw_handler) prism54_get_wpa,
+	(iw_handler) prism54_set_wpa,
+	(iw_handler) NULL,
+	(iw_handler) prism54_debug_oid,
+	(iw_handler) prism54_debug_get_oid,
+	(iw_handler) prism54_debug_set_oid,
+	(iw_handler) prism54_get_oid,
+	(iw_handler) prism54_set_u32,
+	(iw_handler) NULL,
+	(iw_handler) prism54_set_raw,
+	(iw_handler) NULL,
+	(iw_handler) prism54_set_raw,
+	(iw_handler) prism54_get_prismhdr,
+	(iw_handler) prism54_set_prismhdr,
+};
+
+const struct iw_handler_def prism54_handler_def = {
+	.num_standard = sizeof (prism54_handler) / sizeof (iw_handler),
+	.num_private = sizeof (prism54_private_handler) / sizeof (iw_handler),
+	.num_private_args =
+	    sizeof (prism54_private_args) / sizeof (struct iw_priv_args),
+	.standard = (iw_handler *) prism54_handler,
+	.private = (iw_handler *) prism54_private_handler,
+	.private_args = (struct iw_priv_args *) prism54_private_args,
+	.spy_offset = offsetof(islpci_private, spy_data),
+};
+
+/* For ioctls that don't work with the new API */
+
+int
+prism54_ioctl(struct net_device *ndev, struct ifreq *rq, int cmd)
+{
+
+	return -EOPNOTSUPP;
+}
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/net/wireless/prism54/isl_ioctl.h linux-2.4.28-pre3/drivers/net/wireless/prism54/isl_ioctl.h
--- linux-2.4.27/drivers/net/wireless/prism54/isl_ioctl.h	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.28-pre3/drivers/net/wireless/prism54/isl_ioctl.h	2004-09-10 19:36:06.000000000 +0000
@@ -0,0 +1,54 @@
+/*
+ *  
+ *  Copyright (C) 2002 Intersil Americas Inc.
+ *            (C) 2003 Aurelien Alleaume <slts@free.fr>
+ *            (C) 2003 Luis R. Rodriguez <mcgrof@ruslug.rutgers.edu>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License
+ *
+ *  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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef _ISL_IOCTL_H
+#define _ISL_IOCTL_H
+
+#include "islpci_mgt.h"
+#include "islpci_dev.h"
+
+#include <net/iw_handler.h>	/* New driver API */
+
+#define SUPPORTED_WIRELESS_EXT                  16
+
+void prism54_mib_init(islpci_private *);
+
+struct iw_statistics *prism54_get_wireless_stats(struct net_device *);
+void prism54_update_stats(islpci_private *);
+
+void prism54_acl_init(struct islpci_acl *);
+void prism54_acl_clean(struct islpci_acl *);
+
+void prism54_process_trap(void *);
+
+void prism54_wpa_ie_init(islpci_private *priv);
+void prism54_wpa_ie_clean(islpci_private *priv);
+void prism54_wpa_ie_add(islpci_private *priv, u8 *bssid,
+			u8 *wpa_ie, size_t wpa_ie_len);
+size_t prism54_wpa_ie_get(islpci_private *priv, u8 *bssid, u8 *wpa_ie);
+
+int prism54_set_mac_address(struct net_device *, void *);
+
+int prism54_ioctl(struct net_device *, struct ifreq *, int);
+
+extern const struct iw_handler_def prism54_handler_def;
+
+#endif				/* _ISL_IOCTL_H */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/net/wireless/prism54/isl_oid.h linux-2.4.28-pre3/drivers/net/wireless/prism54/isl_oid.h
--- linux-2.4.27/drivers/net/wireless/prism54/isl_oid.h	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.28-pre3/drivers/net/wireless/prism54/isl_oid.h	2004-09-10 19:35:32.000000000 +0000
@@ -0,0 +1,498 @@
+/*
+ *
+ *  
+ *  Copyright (C) 2003 Herbert Valerio Riedel <hvr@gnu.org>
+ *  Copyright (C) 2004 Luis R. Rodriguez <mcgrof@ruslug.rutgers.edu>
+ *  Copyright (C) 2004 Aurelien Alleaume <slts@free.fr>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License
+ *
+ *  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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#if !defined(_ISL_OID_H)
+#define _ISL_OID_H
+
+/* 
+ * MIB related constant and structure definitions for communicating
+ * with the device firmware
+ */
+
+struct obj_ssid {
+	u8 length;
+	char octets[33];
+} __attribute__ ((packed));
+
+struct obj_key {
+	u8 type;		/* dot11_priv_t */
+	u8 length;
+	char key[32];
+} __attribute__ ((packed));
+
+struct obj_mlme {
+	u8 address[6];
+	u16 id;
+	u16 state;
+	u16 code;
+} __attribute__ ((packed));
+
+struct obj_mlmeex {
+	u8 address[6];
+	u16 id;
+	u16 state;
+	u16 code;
+	u16 size;
+	u8 data[0];
+} __attribute__ ((packed));
+
+struct obj_buffer {
+	u32 size;
+	u32 addr;		/* 32bit bus address */
+} __attribute__ ((packed));
+
+struct obj_bss {
+	u8 address[6];
+	int:16;			/* padding */
+
+	char state;
+	char reserved;
+	short age;
+
+	char quality;
+	char rssi;
+
+	struct obj_ssid ssid;
+	short channel;
+	char beacon_period;
+	char dtim_period;
+	short capinfo;
+	short rates;
+	short basic_rates;
+	int:16;			/* padding */
+} __attribute__ ((packed));
+
+struct obj_bsslist {
+	u32 nr;
+	struct obj_bss bsslist[0];
+} __attribute__ ((packed));
+
+struct obj_frequencies {
+	u16 nr;
+	u16 mhz[0];
+} __attribute__ ((packed));
+
+/* 
+ * in case everything's ok, the inlined function below will be
+ * optimized away by the compiler...
+ */
+static inline void
+__bug_on_wrong_struct_sizes(void)
+{
+	BUG_ON(sizeof (struct obj_ssid) != 34);
+	BUG_ON(sizeof (struct obj_key) != 34);
+	BUG_ON(sizeof (struct obj_mlme) != 12);
+	BUG_ON(sizeof (struct obj_mlmeex) != 14);
+	BUG_ON(sizeof (struct obj_buffer) != 8);
+	BUG_ON(sizeof (struct obj_bss) != 60);
+	BUG_ON(sizeof (struct obj_bsslist) != 4);
+	BUG_ON(sizeof (struct obj_frequencies) != 2);
+}
+
+enum dot11_state_t {
+	DOT11_STATE_NONE = 0,
+	DOT11_STATE_AUTHING = 1,
+	DOT11_STATE_AUTH = 2,
+	DOT11_STATE_ASSOCING = 3,
+
+	DOT11_STATE_ASSOC = 5,
+	DOT11_STATE_IBSS = 6,
+	DOT11_STATE_WDS = 7
+};
+
+enum dot11_bsstype_t {
+	DOT11_BSSTYPE_NONE = 0,
+	DOT11_BSSTYPE_INFRA = 1,
+	DOT11_BSSTYPE_IBSS = 2,
+	DOT11_BSSTYPE_ANY = 3
+};
+
+enum dot11_auth_t {
+	DOT11_AUTH_NONE = 0,
+	DOT11_AUTH_OS = 1,
+	DOT11_AUTH_SK = 2,
+	DOT11_AUTH_BOTH = 3
+};
+
+enum dot11_mlme_t {
+	DOT11_MLME_AUTO = 0,
+	DOT11_MLME_INTERMEDIATE = 1,
+	DOT11_MLME_EXTENDED = 2
+};
+
+enum dot11_priv_t {
+	DOT11_PRIV_WEP = 0,
+	DOT11_PRIV_TKIP = 1
+};
+
+/* Prism "Nitro" / Frameburst / "Packet Frame Grouping"
+ * Value is in microseconds. Represents the # microseconds
+ * the firmware will take to group frames before sending out then out 
+ * together with a CSMA contention. Without this all frames are
+ * sent with a CSMA contention. 
+ * Bibliography: 
+ * http://www.hpl.hp.com/personal/Jean_Tourrilhes/Papers/Packet.Frame.Grouping.html
+ */
+enum dot11_maxframeburst_t { 
+	/* Values for DOT11_OID_MAXFRAMEBURST */
+	DOT11_MAXFRAMEBURST_OFF = 0, /* Card firmware default */
+	DOT11_MAXFRAMEBURST_MIXED_SAFE = 650, /* 802.11 a,b,g safe */
+	DOT11_MAXFRAMEBURST_IDEAL = 1300, /* Theoretical ideal level */
+	DOT11_MAXFRAMEBURST_MAX = 5000, /* Use this as max,
+		* Note: firmware allows for greater values. This is a
+		* recommended max. I'll update this as I find
+		* out what the real MAX is. Also note that you don't necessarily
+		* get better results with a greater value here.
+		*/
+};
+
+/* Support for 802.11 long and short frame preambles.
+ * Long	 preamble uses 128-bit sync field, 8-bit  CRC
+ * Short preamble uses 56-bit  sync field, 16-bit CRC
+ * 
+ * 802.11a -- not sure, both optionally ?
+ * 802.11b supports long and optionally short 
+ * 802.11g supports both */
+enum dot11_preamblesettings_t {
+	DOT11_PREAMBLESETTING_LONG = 0,
+		/* Allows *only* long 802.11 preambles */
+	DOT11_PREAMBLESETTING_SHORT = 1,
+		/* Allows *only* short 802.11 preambles */
+	DOT11_PREAMBLESETTING_DYNAMIC = 2
+		/* AutomatiGically set */
+};
+
+/* Support for 802.11 slot timing (time between packets).
+ *
+ * Long uses 802.11a slot timing  (9 usec ?)
+ * Short uses 802.11b slot timing (20 use ?) */
+enum dot11_slotsettings_t {
+	DOT11_SLOTSETTINGS_LONG = 0, 
+		/* Allows *only* long 802.11b slot timing */
+	DOT11_SLOTSETTINGS_SHORT = 1,
+		/* Allows *only* long 802.11a slot timing */
+	DOT11_SLOTSETTINGS_DYNAMIC = 2
+		/* AutomatiGically set */
+};
+
+/* All you need to know, ERP is "Extended Rate PHY".
+ * An Extended Rate PHY (ERP) STA or AP shall support three different 
+ * preamble and header formats:
+ * Long  preamble (refer to above)
+ * Short preamble (refer to above)
+ * OFDM  preamble ( ? )
+ *
+ * I'm assuming here Protection tells the AP
+ * to be careful, a STA which cannot handle the long pre-amble
+ * has joined.
+ */
+enum do11_nonerpstatus_t {
+	DOT11_ERPSTAT_NONEPRESENT = 0,
+	DOT11_ERPSTAT_USEPROTECTION = 1
+};
+
+/* (ERP is "Extended Rate PHY") Way to read NONERP is NON-ERP-*
+ * The key here is DOT11 NON ERP NEVER protects against
+ * NON ERP STA's. You *don't* want this unless
+ * you know what you are doing. It means you will only 
+ * get Extended Rate capabilities */
+enum dot11_nonerpprotection_t {
+	DOT11_NONERP_NEVER = 0,
+	DOT11_NONERP_ALWAYS = 1,
+	DOT11_NONERP_DYNAMIC = 2
+};
+
+/* Preset OID configuration for 802.11 modes 
+ * Note: DOT11_OID_CW[MIN|MAX] hold the values of the 
+ * DCS MIN|MAX backoff used */
+enum dot11_profile_t { /* And set/allowed values */
+	/* Allowed values for DOT11_OID_PROFILES */
+	DOT11_PROFILE_B_ONLY = 0,
+		/* DOT11_OID_RATES: 1, 2, 5.5, 11Mbps 
+		 * DOT11_OID_PREAMBLESETTINGS: DOT11_PREAMBLESETTING_DYNAMIC
+		 * DOT11_OID_CWMIN: 31
+		 * DOT11_OID_NONEPROTECTION: DOT11_NOERP_DYNAMIC
+		 * DOT11_OID_SLOTSETTINGS: DOT11_SLOTSETTINGS_LONG
+		 */
+	DOT11_PROFILE_MIXED_G_WIFI = 1,
+		/* DOT11_OID_RATES: 1, 2, 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54Mbs
+		 * DOT11_OID_PREAMBLESETTINGS: DOT11_PREAMBLESETTING_DYNAMIC
+		 * DOT11_OID_CWMIN: 15
+		 * DOT11_OID_NONEPROTECTION: DOT11_NOERP_DYNAMIC
+		 * DOT11_OID_SLOTSETTINGS: DOT11_SLOTSETTINGS_DYNAMIC
+		 */
+	DOT11_PROFILE_MIXED_LONG = 2, /* "Long range" */
+		/* Same as Profile MIXED_G_WIFI */
+	DOT11_PROFILE_G_ONLY = 3,
+		/* Same as Profile MIXED_G_WIFI */
+	DOT11_PROFILE_TEST = 4,
+		/* Same as Profile MIXED_G_WIFI except:
+		 * DOT11_OID_PREAMBLESETTINGS: DOT11_PREAMBLESETTING_SHORT
+		 * DOT11_OID_NONEPROTECTION: DOT11_NOERP_NEVER
+		 * DOT11_OID_SLOTSETTINGS: DOT11_SLOTSETTINGS_SHORT
+		 */
+	DOT11_PROFILE_B_WIFI = 5,
+		/* Same as Profile B_ONLY */
+	DOT11_PROFILE_A_ONLY = 6,
+		/* Same as Profile MIXED_G_WIFI except:
+		 * DOT11_OID_RATES: 6, 9, 12, 18, 24, 36, 48, 54Mbs
+		 */
+	DOT11_PROFILE_MIXED_SHORT = 7
+		/* Same as MIXED_G_WIFI */
+};
+
+
+/* The dot11d conformance level configures the 802.11d conformance levels.
+ * The following conformance levels exist:*/
+enum oid_inl_conformance_t {
+	OID_INL_CONFORMANCE_NONE = 0,	/* Perform active scanning */
+	OID_INL_CONFORMANCE_STRICT = 1,	/* Strictly adhere to 802.11d */
+	OID_INL_CONFORMANCE_FLEXIBLE = 2,	/* Use passed 802.11d info to
+		* determine channel AND/OR just make assumption that active 
+		* channels are valid  channels */
+};
+
+enum oid_inl_mode_t {
+	INL_MODE_NONE = -1,
+	INL_MODE_PROMISCUOUS = 0,
+	INL_MODE_CLIENT = 1,
+	INL_MODE_AP = 2,
+	INL_MODE_SNIFFER = 3
+};
+
+enum oid_inl_config_t {
+	INL_CONFIG_NOTHING = 0x00,
+	INL_CONFIG_MANUALRUN = 0x01,
+	INL_CONFIG_FRAMETRAP = 0x02,
+	INL_CONFIG_RXANNEX = 0x04,
+	INL_CONFIG_TXANNEX = 0x08,
+	INL_CONFIG_WDS = 0x10
+};
+
+enum oid_inl_phycap_t {
+	INL_PHYCAP_2400MHZ = 1,
+	INL_PHYCAP_5000MHZ = 2,
+	INL_PHYCAP_FAA = 0x80000000,	/* Means card supports the FAA switch */
+};
+
+
+enum oid_num_t {
+	GEN_OID_MACADDRESS = 0,
+	GEN_OID_LINKSTATE,
+	GEN_OID_WATCHDOG,
+	GEN_OID_MIBOP,
+	GEN_OID_OPTIONS,
+	GEN_OID_LEDCONFIG,
+
+	/* 802.11 */
+	DOT11_OID_BSSTYPE,
+	DOT11_OID_BSSID,
+	DOT11_OID_SSID,
+	DOT11_OID_STATE,
+	DOT11_OID_AID,
+	DOT11_OID_COUNTRYSTRING,
+	DOT11_OID_SSIDOVERRIDE,
+
+	DOT11_OID_MEDIUMLIMIT,
+	DOT11_OID_BEACONPERIOD,
+	DOT11_OID_DTIMPERIOD,
+	DOT11_OID_ATIMWINDOW,
+	DOT11_OID_LISTENINTERVAL,
+	DOT11_OID_CFPPERIOD,
+	DOT11_OID_CFPDURATION,
+
+	DOT11_OID_AUTHENABLE,
+	DOT11_OID_PRIVACYINVOKED,
+	DOT11_OID_EXUNENCRYPTED,
+	DOT11_OID_DEFKEYID,
+	DOT11_OID_DEFKEYX,	/* DOT11_OID_DEFKEY1,...DOT11_OID_DEFKEY4 */
+	DOT11_OID_STAKEY,
+	DOT11_OID_REKEYTHRESHOLD,
+	DOT11_OID_STASC,
+
+	DOT11_OID_PRIVTXREJECTED,
+	DOT11_OID_PRIVRXPLAIN,
+	DOT11_OID_PRIVRXFAILED,
+	DOT11_OID_PRIVRXNOKEY,
+
+	DOT11_OID_RTSTHRESH,
+	DOT11_OID_FRAGTHRESH,
+	DOT11_OID_SHORTRETRIES,
+	DOT11_OID_LONGRETRIES,
+	DOT11_OID_MAXTXLIFETIME,
+	DOT11_OID_MAXRXLIFETIME,
+	DOT11_OID_AUTHRESPTIMEOUT,
+	DOT11_OID_ASSOCRESPTIMEOUT,
+
+	DOT11_OID_ALOFT_TABLE,
+	DOT11_OID_ALOFT_CTRL_TABLE,
+	DOT11_OID_ALOFT_RETREAT,
+	DOT11_OID_ALOFT_PROGRESS,
+	DOT11_OID_ALOFT_FIXEDRATE,
+	DOT11_OID_ALOFT_RSSIGRAPH,
+	DOT11_OID_ALOFT_CONFIG,
+
+	DOT11_OID_VDCFX,
+	DOT11_OID_MAXFRAMEBURST,
+
+	DOT11_OID_PSM,
+	DOT11_OID_CAMTIMEOUT,
+	DOT11_OID_RECEIVEDTIMS,
+	DOT11_OID_ROAMPREFERENCE,
+
+	DOT11_OID_BRIDGELOCAL,
+	DOT11_OID_CLIENTS,
+	DOT11_OID_CLIENTSASSOCIATED,
+	DOT11_OID_CLIENTX,	/* DOT11_OID_CLIENTX,...DOT11_OID_CLIENT2007 */
+
+	DOT11_OID_CLIENTFIND,
+	DOT11_OID_WDSLINKADD,
+	DOT11_OID_WDSLINKREMOVE,
+	DOT11_OID_EAPAUTHSTA,
+	DOT11_OID_EAPUNAUTHSTA,
+	DOT11_OID_DOT1XENABLE,
+	DOT11_OID_MICFAILURE,
+	DOT11_OID_REKEYINDICATE,
+
+	DOT11_OID_MPDUTXSUCCESSFUL,
+	DOT11_OID_MPDUTXONERETRY,
+	DOT11_OID_MPDUTXMULTIPLERETRIES,
+	DOT11_OID_MPDUTXFAILED,
+	DOT11_OID_MPDURXSUCCESSFUL,
+	DOT11_OID_MPDURXDUPS,
+	DOT11_OID_RTSSUCCESSFUL,
+	DOT11_OID_RTSFAILED,
+	DOT11_OID_ACKFAILED,
+	DOT11_OID_FRAMERECEIVES,
+	DOT11_OID_FRAMEERRORS,
+	DOT11_OID_FRAMEABORTS,
+	DOT11_OID_FRAMEABORTSPHY,
+
+	DOT11_OID_SLOTTIME,
+	DOT11_OID_CWMIN, /* MIN DCS backoff */
+	DOT11_OID_CWMAX, /* MAX DCS backoff */
+	DOT11_OID_ACKWINDOW,
+	DOT11_OID_ANTENNARX,
+	DOT11_OID_ANTENNATX,
+	DOT11_OID_ANTENNADIVERSITY,
+	DOT11_OID_CHANNEL,
+	DOT11_OID_EDTHRESHOLD,
+	DOT11_OID_PREAMBLESETTINGS,
+	DOT11_OID_RATES,
+	DOT11_OID_CCAMODESUPPORTED,
+	DOT11_OID_CCAMODE,
+	DOT11_OID_RSSIVECTOR,
+	DOT11_OID_OUTPUTPOWERTABLE,
+	DOT11_OID_OUTPUTPOWER,
+	DOT11_OID_SUPPORTEDRATES,
+	DOT11_OID_FREQUENCY,
+	DOT11_OID_SUPPORTEDFREQUENCIES,
+	DOT11_OID_NOISEFLOOR,
+	DOT11_OID_FREQUENCYACTIVITY,
+	DOT11_OID_IQCALIBRATIONTABLE,
+	DOT11_OID_NONERPPROTECTION,
+	DOT11_OID_SLOTSETTINGS,
+	DOT11_OID_NONERPTIMEOUT,
+	DOT11_OID_PROFILES,
+	DOT11_OID_EXTENDEDRATES,
+
+	DOT11_OID_DEAUTHENTICATE,
+	DOT11_OID_AUTHENTICATE,
+	DOT11_OID_DISASSOCIATE,
+	DOT11_OID_ASSOCIATE,
+	DOT11_OID_SCAN,
+	DOT11_OID_BEACON,
+	DOT11_OID_PROBE,
+	DOT11_OID_DEAUTHENTICATEEX,
+	DOT11_OID_AUTHENTICATEEX,
+	DOT11_OID_DISASSOCIATEEX,
+	DOT11_OID_ASSOCIATEEX,
+	DOT11_OID_REASSOCIATE,
+	DOT11_OID_REASSOCIATEEX,
+
+	DOT11_OID_NONERPSTATUS,
+
+	DOT11_OID_STATIMEOUT,
+	DOT11_OID_MLMEAUTOLEVEL,
+	DOT11_OID_BSSTIMEOUT,
+	DOT11_OID_ATTACHMENT,
+	DOT11_OID_PSMBUFFER,
+
+	DOT11_OID_BSSS,
+	DOT11_OID_BSSX,		/*DOT11_OID_BSS1,...,DOT11_OID_BSS64 */
+	DOT11_OID_BSSFIND,
+	DOT11_OID_BSSLIST,
+
+	OID_INL_TUNNEL,
+	OID_INL_MEMADDR,
+	OID_INL_MEMORY,
+	OID_INL_MODE,
+	OID_INL_COMPONENT_NR,
+	OID_INL_VERSION,
+	OID_INL_INTERFACE_ID,
+	OID_INL_COMPONENT_ID,
+	OID_INL_CONFIG,
+	OID_INL_DOT11D_CONFORMANCE,
+	OID_INL_PHYCAPABILITIES,
+	OID_INL_OUTPUTPOWER,
+
+	OID_NUM_LAST
+};
+
+#define OID_FLAG_CACHED		0x80
+#define OID_FLAG_TYPE		0x7f
+
+#define OID_TYPE_U32		0x01
+#define OID_TYPE_SSID		0x02
+#define OID_TYPE_KEY		0x03
+#define OID_TYPE_BUFFER		0x04
+#define OID_TYPE_BSS		0x05
+#define OID_TYPE_BSSLIST	0x06
+#define OID_TYPE_FREQUENCIES	0x07
+#define OID_TYPE_MLME		0x08
+#define OID_TYPE_MLMEEX		0x09
+#define OID_TYPE_ADDR		0x0A
+#define OID_TYPE_RAW		0x0B
+
+/* OID_TYPE_MLMEEX is special because of a variable size field when sending.
+ * Not yet implemented (not used in driver anyway).
+ */
+
+struct oid_t {
+	enum oid_num_t oid;
+	short range;		/* to define a range of oid */
+	short size;		/* max size of the associated data */
+	char flags;
+};
+
+union oid_res_t {
+	void *ptr;
+	u32 u;
+};
+
+#define	IWMAX_BITRATES	20
+#define	IWMAX_BSS	24
+#define IWMAX_FREQ	30
+#define PRIV_STR_SIZE	1024
+
+#endif				/* !defined(_ISL_OID_H) */
+/* EOF */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/net/wireless/prism54/islpci_dev.c linux-2.4.28-pre3/drivers/net/wireless/prism54/islpci_dev.c
--- linux-2.4.27/drivers/net/wireless/prism54/islpci_dev.c	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.28-pre3/drivers/net/wireless/prism54/islpci_dev.c	2004-09-10 19:37:09.000000000 +0000
@@ -0,0 +1,940 @@
+/*
+ *  
+ *  Copyright (C) 2002 Intersil Americas Inc.
+ *  Copyright (C) 2003 Herbert Valerio Riedel <hvr@gnu.org>
+ *  Copyright (C) 2003 Luis R. Rodriguez <mcgrof@ruslug.rutgers.edu>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License
+ *
+ *  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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include <linux/version.h>
+#include <linux/module.h>
+
+#include <linux/netdevice.h>
+#include <linux/pci.h>
+#include <linux/etherdevice.h>
+#include <linux/delay.h>
+#include <linux/if_arp.h>
+
+#include <asm/io.h>
+
+#include "prismcompat.h"
+#include "isl_38xx.h"
+#include "isl_ioctl.h"
+#include "islpci_dev.h"
+#include "islpci_mgt.h"
+#include "islpci_eth.h"
+#include "oid_mgt.h"
+
+#define ISL3877_IMAGE_FILE	"isl3877"
+#define ISL3886_IMAGE_FILE	"isl3886"
+#define ISL3890_IMAGE_FILE	"isl3890"
+
+static int prism54_bring_down(islpci_private *);
+static int islpci_alloc_memory(islpci_private *);
+
+/* Temporary dummy MAC address to use until firmware is loaded.
+ * The idea there is that some tools (such as nameif) may query
+ * the MAC address before the netdev is 'open'. By using a valid
+ * OUI prefix, they can process the netdev properly.
+ * Of course, this is not the final/real MAC address. It doesn't
+ * matter, as you are suppose to be able to change it anytime via
+ * ndev->set_mac_address. Jean II */
+const unsigned char	dummy_mac[6] = { 0x00, 0x30, 0xB4, 0x00, 0x00, 0x00 };
+
+static int
+isl_upload_firmware(islpci_private *priv)
+{
+	u32 reg, rc;
+	void *device_base = priv->device_base;
+
+	/* clear the RAMBoot and the Reset bit */
+	reg = readl(device_base + ISL38XX_CTRL_STAT_REG);
+	reg &= ~ISL38XX_CTRL_STAT_RESET;
+	reg &= ~ISL38XX_CTRL_STAT_RAMBOOT;
+	writel(reg, device_base + ISL38XX_CTRL_STAT_REG);
+	wmb();
+	udelay(ISL38XX_WRITEIO_DELAY);
+
+	/* set the Reset bit without reading the register ! */
+	reg |= ISL38XX_CTRL_STAT_RESET;
+	writel(reg, device_base + ISL38XX_CTRL_STAT_REG);
+	wmb();
+	udelay(ISL38XX_WRITEIO_DELAY);
+
+	/* clear the Reset bit */
+	reg &= ~ISL38XX_CTRL_STAT_RESET;
+	writel(reg, device_base + ISL38XX_CTRL_STAT_REG);
+	wmb();
+
+	/* wait a while for the device to reboot */
+	mdelay(50);
+
+	{
+		const struct firmware *fw_entry = NULL;
+		long fw_len;
+		const u32 *fw_ptr;
+
+		rc = request_firmware(&fw_entry, priv->firmware, PRISM_FW_PDEV);
+		if (rc) {
+			printk(KERN_ERR
+			       "%s: request_firmware() failed for '%s'\n",
+			       "prism54", priv->firmware);
+			return rc;
+		}
+		/* prepare the Direct Memory Base register */
+		reg = ISL38XX_DEV_FIRMWARE_ADDRES;
+
+		fw_ptr = (u32 *) fw_entry->data;
+		fw_len = fw_entry->size;
+
+		if (fw_len % 4) {
+			printk(KERN_ERR
+			       "%s: firmware '%s' size is not multiple of 32bit, aborting!\n",
+			       "prism54", priv->firmware);
+			release_firmware(fw_entry);
+			return EILSEQ; /* Illegal byte sequence  */;
+		}
+
+		while (fw_len > 0) {
+			long _fw_len =
+			    (fw_len >
+			     ISL38XX_MEMORY_WINDOW_SIZE) ?
+			    ISL38XX_MEMORY_WINDOW_SIZE : fw_len;
+			u32 *dev_fw_ptr = device_base + ISL38XX_DIRECT_MEM_WIN;
+
+			/* set the cards base address for writting the data */
+			isl38xx_w32_flush(device_base, reg,
+					  ISL38XX_DIR_MEM_BASE_REG);
+			wmb();	/* be paranoid */
+
+			/* increment the write address for next iteration */
+			reg += _fw_len;
+			fw_len -= _fw_len;
+
+			/* write the data to the Direct Memory Window 32bit-wise */
+			/* memcpy_toio() doesn't guarantee 32bit writes :-| */
+			while (_fw_len > 0) {
+				/* use non-swapping writel() */
+				__raw_writel(*fw_ptr, dev_fw_ptr);
+				fw_ptr++, dev_fw_ptr++;
+				_fw_len -= 4;
+			}
+
+			/* flush PCI posting */
+			(void) readl(device_base + ISL38XX_PCI_POSTING_FLUSH);
+			wmb();	/* be paranoid again */
+
+			BUG_ON(_fw_len != 0);
+		}
+
+		BUG_ON(fw_len != 0);
+
+		release_firmware(fw_entry);
+	}
+
+	/* now reset the device
+	 * clear the Reset & ClkRun bit, set the RAMBoot bit */
+	reg = readl(device_base + ISL38XX_CTRL_STAT_REG);
+	reg &= ~ISL38XX_CTRL_STAT_CLKRUN;
+	reg &= ~ISL38XX_CTRL_STAT_RESET;
+	reg |= ISL38XX_CTRL_STAT_RAMBOOT;
+	isl38xx_w32_flush(device_base, reg, ISL38XX_CTRL_STAT_REG);
+	wmb();
+	udelay(ISL38XX_WRITEIO_DELAY);
+
+	/* set the reset bit latches the host override and RAMBoot bits
+	 * into the device for operation when the reset bit is reset */
+	reg |= ISL38XX_CTRL_STAT_RESET;
+	writel(reg, device_base + ISL38XX_CTRL_STAT_REG);
+	/* don't do flush PCI posting here! */
+	wmb();
+	udelay(ISL38XX_WRITEIO_DELAY);
+
+	/* clear the reset bit should start the whole circus */
+	reg &= ~ISL38XX_CTRL_STAT_RESET;
+	writel(reg, device_base + ISL38XX_CTRL_STAT_REG);
+	/* don't do flush PCI posting here! */
+	wmb();
+	udelay(ISL38XX_WRITEIO_DELAY);
+
+	return 0;
+}
+
+/******************************************************************************
+    Device Interrupt Handler
+******************************************************************************/
+
+irqreturn_t
+islpci_interrupt(int irq, void *config, struct pt_regs *regs)
+{
+	u32 reg;
+	islpci_private *priv = config;
+	struct net_device *ndev = priv->ndev;
+	void *device = priv->device_base;
+	int powerstate = ISL38XX_PSM_POWERSAVE_STATE;
+
+	/* lock the interrupt handler */
+	spin_lock(&priv->slock);
+
+	/* received an interrupt request on a shared IRQ line
+	 * first check whether the device is in sleep mode */
+	reg = readl(device + ISL38XX_CTRL_STAT_REG);
+	if (reg & ISL38XX_CTRL_STAT_SLEEPMODE)
+		/* device is in sleep mode, IRQ was generated by someone else */
+	{
+#if VERBOSE > SHOW_ERROR_MESSAGES
+		DEBUG(SHOW_TRACING, "Assuming someone else called the IRQ\n");
+#endif
+		spin_unlock(&priv->slock);
+		return IRQ_NONE;
+	}
+
+
+	/* check whether there is any source of interrupt on the device */
+	reg = readl(device + ISL38XX_INT_IDENT_REG);
+
+	/* also check the contents of the Interrupt Enable Register, because this
+	 * will filter out interrupt sources from other devices on the same irq ! */
+	reg &= readl(device + ISL38XX_INT_EN_REG);
+	reg &= ISL38XX_INT_SOURCES;
+
+	if (reg != 0) {
+		if (islpci_get_state(priv) != PRV_STATE_SLEEP)
+			powerstate = ISL38XX_PSM_ACTIVE_STATE;
+
+		/* reset the request bits in the Identification register */
+		isl38xx_w32_flush(device, reg, ISL38XX_INT_ACK_REG);
+
+#if VERBOSE > SHOW_ERROR_MESSAGES
+		DEBUG(SHOW_FUNCTION_CALLS,
+		      "IRQ: Identification register 0x%p 0x%x \n", device, reg);
+#endif
+
+		/* check for each bit in the register separately */
+		if (reg & ISL38XX_INT_IDENT_UPDATE) {
+#if VERBOSE > SHOW_ERROR_MESSAGES
+			/* Queue has been updated */
+			DEBUG(SHOW_TRACING, "IRQ: Update flag \n");
+
+			DEBUG(SHOW_QUEUE_INDEXES,
+			      "CB drv Qs: [%i][%i][%i][%i][%i][%i]\n",
+			      le32_to_cpu(priv->control_block->
+					  driver_curr_frag[0]),
+			      le32_to_cpu(priv->control_block->
+					  driver_curr_frag[1]),
+			      le32_to_cpu(priv->control_block->
+					  driver_curr_frag[2]),
+			      le32_to_cpu(priv->control_block->
+					  driver_curr_frag[3]),
+			      le32_to_cpu(priv->control_block->
+					  driver_curr_frag[4]),
+			      le32_to_cpu(priv->control_block->
+					  driver_curr_frag[5])
+			    );
+
+			DEBUG(SHOW_QUEUE_INDEXES,
+			      "CB dev Qs: [%i][%i][%i][%i][%i][%i]\n",
+			      le32_to_cpu(priv->control_block->
+					  device_curr_frag[0]),
+			      le32_to_cpu(priv->control_block->
+					  device_curr_frag[1]),
+			      le32_to_cpu(priv->control_block->
+					  device_curr_frag[2]),
+			      le32_to_cpu(priv->control_block->
+					  device_curr_frag[3]),
+			      le32_to_cpu(priv->control_block->
+					  device_curr_frag[4]),
+			      le32_to_cpu(priv->control_block->
+					  device_curr_frag[5])
+			    );
+#endif
+
+			/* cleanup the data low transmit queue */
+			islpci_eth_cleanup_transmit(priv, priv->control_block);
+
+			/* device is in active state, update the
+			 * powerstate flag if necessary */
+			powerstate = ISL38XX_PSM_ACTIVE_STATE;
+
+			/* check all three queues in priority order
+			 * call the PIMFOR receive function until the
+			 * queue is empty */
+			if (isl38xx_in_queue(priv->control_block,
+						ISL38XX_CB_RX_MGMTQ) != 0) {
+#if VERBOSE > SHOW_ERROR_MESSAGES
+				DEBUG(SHOW_TRACING,
+				      "Received frame in Management Queue\n");
+#endif
+				islpci_mgt_receive(ndev);
+
+				islpci_mgt_cleanup_transmit(ndev);
+
+				/* Refill slots in receive queue */
+				islpci_mgmt_rx_fill(ndev);
+
+				/* no need to trigger the device, next
+                                   islpci_mgt_transaction does it */
+			}
+
+			while (isl38xx_in_queue(priv->control_block,
+						ISL38XX_CB_RX_DATA_LQ) != 0) {
+#if VERBOSE > SHOW_ERROR_MESSAGES
+				DEBUG(SHOW_TRACING,
+				      "Received frame in Data Low Queue \n");
+#endif
+				islpci_eth_receive(priv);
+			}
+
+			/* check whether the data transmit queues were full */
+			if (priv->data_low_tx_full) {
+				/* check whether the transmit is not full anymore */
+				if (ISL38XX_CB_TX_QSIZE -
+				    isl38xx_in_queue(priv->control_block,
+						     ISL38XX_CB_TX_DATA_LQ) >=
+				    ISL38XX_MIN_QTHRESHOLD) {
+					/* nope, the driver is ready for more network frames */
+					netif_wake_queue(priv->ndev);
+
+					/* reset the full flag */
+					priv->data_low_tx_full = 0;
+				}
+			}
+		}
+
+		if (reg & ISL38XX_INT_IDENT_INIT) {
+			/* Device has been initialized */
+#if VERBOSE > SHOW_ERROR_MESSAGES
+			DEBUG(SHOW_TRACING,
+			      "IRQ: Init flag, device initialized \n");
+#endif
+			wake_up(&priv->reset_done);
+		}
+
+		if (reg & ISL38XX_INT_IDENT_SLEEP) {
+			/* Device intends to move to powersave state */
+#if VERBOSE > SHOW_ERROR_MESSAGES
+			DEBUG(SHOW_TRACING, "IRQ: Sleep flag \n");
+#endif
+			isl38xx_handle_sleep_request(priv->control_block,
+						     &powerstate,
+						     priv->device_base);
+		}
+
+		if (reg & ISL38XX_INT_IDENT_WAKEUP) {
+			/* Device has been woken up to active state */
+#if VERBOSE > SHOW_ERROR_MESSAGES
+			DEBUG(SHOW_TRACING, "IRQ: Wakeup flag \n");
+#endif
+
+			isl38xx_handle_wakeup(priv->control_block,
+					      &powerstate, priv->device_base);
+		}
+	} else {
+#if VERBOSE > SHOW_ERROR_MESSAGES
+		DEBUG(SHOW_TRACING, "Assuming someone else called the IRQ\n");
+#endif
+		spin_unlock(&priv->slock);
+		return IRQ_NONE;
+	}
+
+	/* sleep -> ready */
+	if (islpci_get_state(priv) == PRV_STATE_SLEEP
+	    && powerstate == ISL38XX_PSM_ACTIVE_STATE)
+		islpci_set_state(priv, PRV_STATE_READY);
+
+	/* !sleep -> sleep */
+	if (islpci_get_state(priv) != PRV_STATE_SLEEP
+	    && powerstate == ISL38XX_PSM_POWERSAVE_STATE)
+		islpci_set_state(priv, PRV_STATE_SLEEP);
+
+	/* unlock the interrupt handler */
+	spin_unlock(&priv->slock);
+
+	return IRQ_HANDLED;
+}
+
+/******************************************************************************
+    Network Interface Control & Statistical functions
+******************************************************************************/
+static int
+islpci_open(struct net_device *ndev)
+{
+	u32 rc;
+	islpci_private *priv = netdev_priv(ndev);
+
+	printk(KERN_DEBUG "%s: islpci_open()\n", ndev->name);
+
+	/* reset data structures, upload firmware and reset device */
+	rc = islpci_reset(priv,1);
+	if (rc) {
+		prism54_bring_down(priv);
+		return rc; /* Returns informative message */
+	}
+
+	netif_start_queue(ndev);
+/*      netif_mark_up( ndev ); */
+
+	return 0;
+}
+
+static int
+islpci_close(struct net_device *ndev)
+{
+	islpci_private *priv = netdev_priv(ndev);
+
+	printk(KERN_DEBUG "%s: islpci_close ()\n", ndev->name);
+
+	netif_stop_queue(ndev);
+
+	return prism54_bring_down(priv);
+}
+
+static int
+prism54_bring_down(islpci_private *priv)
+{
+	void *device_base = priv->device_base;
+	u32 reg;
+	/* we are going to shutdown the device */
+	islpci_set_state(priv, PRV_STATE_PREBOOT);
+
+	/* disable all device interrupts in case they weren't */
+	isl38xx_disable_interrupts(priv->device_base);  
+
+	/* For safety reasons, we may want to ensure that no DMA transfer is
+	 * currently in progress by emptying the TX and RX queues. */
+
+	/* wait until interrupts have finished executing on other CPUs */
+	prism54_synchronize_irq(priv->pdev->irq);
+
+	reg = readl(device_base + ISL38XX_CTRL_STAT_REG);
+	reg &= ~(ISL38XX_CTRL_STAT_RESET | ISL38XX_CTRL_STAT_RAMBOOT);
+	writel(reg, device_base + ISL38XX_CTRL_STAT_REG);
+	wmb();
+	udelay(ISL38XX_WRITEIO_DELAY);
+
+	reg |= ISL38XX_CTRL_STAT_RESET;
+	writel(reg, device_base + ISL38XX_CTRL_STAT_REG);
+	wmb();
+	udelay(ISL38XX_WRITEIO_DELAY);
+
+	/* clear the Reset bit */
+	reg &= ~ISL38XX_CTRL_STAT_RESET;
+	writel(reg, device_base + ISL38XX_CTRL_STAT_REG);
+	wmb();
+
+	/* wait a while for the device to reset */
+	set_current_state(TASK_UNINTERRUPTIBLE);
+	schedule_timeout(50*HZ/1000);
+
+	return 0;
+}
+
+static int
+islpci_upload_fw(islpci_private *priv)
+{
+	islpci_state_t old_state;
+	u32 rc;
+
+	old_state = islpci_set_state(priv, PRV_STATE_BOOT);
+
+	printk(KERN_DEBUG "%s: uploading firmware...\n", priv->ndev->name);
+
+	rc = isl_upload_firmware(priv);
+	if (rc) {
+		/* error uploading the firmware */
+		printk(KERN_ERR "%s: could not upload firmware ('%s')\n",
+		       priv->ndev->name, priv->firmware);
+
+		islpci_set_state(priv, old_state);
+		return rc;
+	}
+
+	printk(KERN_DEBUG
+	       "%s: firmware uploaded done, now triggering reset...\n",
+	       priv->ndev->name);
+
+	islpci_set_state(priv, PRV_STATE_POSTBOOT);
+
+	return 0;
+}
+
+static int
+islpci_reset_if(islpci_private *priv)
+{
+	long remaining;
+	int result = -ETIME;
+	int count;
+
+	DEFINE_WAIT(wait);
+	prepare_to_wait(&priv->reset_done, &wait, TASK_UNINTERRUPTIBLE);
+	
+	/* now the last step is to reset the interface */
+	isl38xx_interface_reset(priv->device_base, priv->device_host_address);
+	islpci_set_state(priv, PRV_STATE_PREINIT);
+
+        for(count = 0; count < 2 && result; count++) {
+		/* The software reset acknowledge needs about 220 msec here.
+		 * Be conservative and wait for up to one second. */
+	
+		remaining = schedule_timeout(HZ);
+
+		if(remaining > 0) {
+			result = 0;
+			break;
+		}
+
+		/* If we're here it's because our IRQ hasn't yet gone through. 
+		 * Retry a bit more...
+		 */
+		 printk(KERN_ERR "%s: device soft reset timed out\n",
+		       priv->ndev->name);
+
+	}
+
+	finish_wait(&priv->reset_done, &wait);
+
+	if(result)
+		return result;
+
+	islpci_set_state(priv, PRV_STATE_INIT);
+
+	/* Now that the device is 100% up, let's allow
+	 * for the other interrupts --
+	 * NOTE: this is not *yet* true since we've only allowed the 
+	 * INIT interrupt on the IRQ line. We can perhaps poll
+	 * the IRQ line until we know for sure the reset went through */
+	isl38xx_enable_common_interrupts(priv->device_base);
+
+	down_write(&priv->mib_sem);
+	mgt_commit(priv);
+	up_write(&priv->mib_sem);
+
+	islpci_set_state(priv, PRV_STATE_READY);
+
+	return 0;
+}
+
+int
+islpci_reset(islpci_private *priv, int reload_firmware)
+{
+	isl38xx_control_block *cb =    /* volatile not needed */
+		(isl38xx_control_block *) priv->control_block;
+	unsigned counter;
+	int rc;
+
+	if (reload_firmware)
+		islpci_set_state(priv, PRV_STATE_PREBOOT);
+	else
+		islpci_set_state(priv, PRV_STATE_POSTBOOT);
+
+	printk(KERN_DEBUG "%s: resetting device...\n", priv->ndev->name);
+
+	/* disable all device interrupts in case they weren't */
+	isl38xx_disable_interrupts(priv->device_base);
+
+	/* flush all management queues */
+	priv->index_mgmt_tx = 0;
+	priv->index_mgmt_rx = 0;
+
+	/* clear the indexes in the frame pointer */
+	for (counter = 0; counter < ISL38XX_CB_QCOUNT; counter++) {
+		cb->driver_curr_frag[counter] = cpu_to_le32(0);
+		cb->device_curr_frag[counter] = cpu_to_le32(0);
+	}
+
+	/* reset the mgmt receive queue */
+	for (counter = 0; counter < ISL38XX_CB_MGMT_QSIZE; counter++) {
+		isl38xx_fragment *frag = &cb->rx_data_mgmt[counter];
+		frag->size = cpu_to_le16(MGMT_FRAME_SIZE);
+		frag->flags = 0;
+		frag->address = cpu_to_le32(priv->mgmt_rx[counter].pci_addr);
+	}
+
+	for (counter = 0; counter < ISL38XX_CB_RX_QSIZE; counter++) {
+		cb->rx_data_low[counter].address =
+		    cpu_to_le32((u32) priv->pci_map_rx_address[counter]);
+	}
+
+	/* since the receive queues are filled with empty fragments, now we can
+	 * set the corresponding indexes in the Control Block */
+	priv->control_block->driver_curr_frag[ISL38XX_CB_RX_DATA_LQ] =
+	    cpu_to_le32(ISL38XX_CB_RX_QSIZE);
+	priv->control_block->driver_curr_frag[ISL38XX_CB_RX_MGMTQ] =
+	    cpu_to_le32(ISL38XX_CB_MGMT_QSIZE);
+
+	/* reset the remaining real index registers and full flags */
+	priv->free_data_rx = 0;
+	priv->free_data_tx = 0;
+	priv->data_low_tx_full = 0;
+
+	if (reload_firmware) { /* Should we load the firmware ? */
+	/* now that the data structures are cleaned up, upload
+	 * firmware and reset interface */
+		rc = islpci_upload_fw(priv);
+		if (rc) 
+			return rc;
+	}
+
+	/* finally reset interface */
+	rc = islpci_reset_if(priv);
+	if (!rc) /* If successful */
+		return rc;
+	
+	printk(KERN_DEBUG  "prism54: Your card/socket may be faulty, or IRQ line too busy :(\n");
+	return rc;
+
+}
+
+struct net_device_stats *
+islpci_statistics(struct net_device *ndev)
+{
+	islpci_private *priv = netdev_priv(ndev);
+
+#if VERBOSE > SHOW_ERROR_MESSAGES
+	DEBUG(SHOW_FUNCTION_CALLS, "islpci_statistics \n");
+#endif
+
+	return &priv->statistics;
+}
+
+/******************************************************************************
+    Network device configuration functions
+******************************************************************************/
+static int
+islpci_alloc_memory(islpci_private *priv)
+{
+	int counter;
+
+#if VERBOSE > SHOW_ERROR_MESSAGES
+	printk(KERN_DEBUG "islpci_alloc_memory\n");
+#endif
+
+	/* remap the PCI device base address to accessable */
+	if (!(priv->device_base =
+	      ioremap(pci_resource_start(priv->pdev, 0),
+		      ISL38XX_PCI_MEM_SIZE))) {
+		/* error in remapping the PCI device memory address range */
+		printk(KERN_ERR "PCI memory remapping failed \n");
+		return -1;
+	}
+
+	/* memory layout for consistent DMA region:
+	 *
+	 * Area 1: Control Block for the device interface
+	 * Area 2: Power Save Mode Buffer for temporary frame storage. Be aware that
+	 *         the number of supported stations in the AP determines the minimal
+	 *         size of the buffer !
+	 */
+
+	/* perform the allocation */
+	priv->driver_mem_address = pci_alloc_consistent(priv->pdev,
+							HOST_MEM_BLOCK,
+							&priv->
+							device_host_address);
+
+	if (!priv->driver_mem_address) {
+		/* error allocating the block of PCI memory */
+		printk(KERN_ERR "%s: could not allocate DMA memory, aborting!",
+		       "prism54");
+		return -1;
+	}
+
+	/* assign the Control Block to the first address of the allocated area */
+	priv->control_block =
+	    (isl38xx_control_block *) priv->driver_mem_address;
+
+	/* set the Power Save Buffer pointer directly behind the CB */
+	priv->device_psm_buffer =
+		priv->device_host_address + CONTROL_BLOCK_SIZE;
+
+	/* make sure all buffer pointers are initialized */
+	for (counter = 0; counter < ISL38XX_CB_QCOUNT; counter++) {
+		priv->control_block->driver_curr_frag[counter] = cpu_to_le32(0);
+		priv->control_block->device_curr_frag[counter] = cpu_to_le32(0);
+	}
+
+	priv->index_mgmt_rx = 0;
+	memset(priv->mgmt_rx, 0, sizeof(priv->mgmt_rx));
+	memset(priv->mgmt_tx, 0, sizeof(priv->mgmt_tx));
+
+	/* allocate rx queue for management frames */
+	if (islpci_mgmt_rx_fill(priv->ndev) < 0)
+		goto out_free;
+
+	/* now get the data rx skb's */
+	memset(priv->data_low_rx, 0, sizeof (priv->data_low_rx));
+	memset(priv->pci_map_rx_address, 0, sizeof (priv->pci_map_rx_address));
+
+	for (counter = 0; counter < ISL38XX_CB_RX_QSIZE; counter++) {
+		struct sk_buff *skb;
+
+		/* allocate an sk_buff for received data frames storage
+		 * each frame on receive size consists of 1 fragment
+		 * include any required allignment operations */
+		if (!(skb = dev_alloc_skb(MAX_FRAGMENT_SIZE_RX + 2))) {
+			/* error allocating an sk_buff structure elements */
+			printk(KERN_ERR "Error allocating skb.\n");
+			skb = NULL;
+			goto out_free;
+		}
+		skb_reserve(skb, (4 - (long) skb->data) & 0x03);
+		/* add the new allocated sk_buff to the buffer array */
+		priv->data_low_rx[counter] = skb;
+
+		/* map the allocated skb data area to pci */
+		priv->pci_map_rx_address[counter] =
+		    pci_map_single(priv->pdev, (void *) skb->data,
+				   MAX_FRAGMENT_SIZE_RX + 2,
+				   PCI_DMA_FROMDEVICE);
+		if (!priv->pci_map_rx_address[counter]) {
+			/* error mapping the buffer to device
+			   accessable memory address */
+			printk(KERN_ERR "failed to map skb DMA'able\n");
+			goto out_free;
+		}
+	}
+
+	prism54_acl_init(&priv->acl);
+	prism54_wpa_ie_init(priv);
+	if (mgt_init(priv)) 
+		goto out_free;
+
+	return 0;
+ out_free:
+	islpci_free_memory(priv);
+	return -1;
+}
+
+int
+islpci_free_memory(islpci_private *priv)
+{
+	int counter;
+
+	if (priv->device_base)
+		iounmap(priv->device_base);
+	priv->device_base = NULL;
+
+	/* free consistent DMA area... */
+	if (priv->driver_mem_address)
+		pci_free_consistent(priv->pdev, HOST_MEM_BLOCK,
+				    priv->driver_mem_address,
+				    priv->device_host_address);
+
+	/* clear some dangling pointers */
+	priv->driver_mem_address = NULL;
+	priv->device_host_address = 0;
+	priv->device_psm_buffer = 0;
+	priv->control_block = NULL;
+
+        /* clean up mgmt rx buffers */
+        for (counter = 0; counter < ISL38XX_CB_MGMT_QSIZE; counter++) {
+		struct islpci_membuf *buf = &priv->mgmt_rx[counter];
+		if (buf->pci_addr)
+			pci_unmap_single(priv->pdev, buf->pci_addr,
+					 buf->size, PCI_DMA_FROMDEVICE);
+		buf->pci_addr = 0;
+		if (buf->mem)
+			kfree(buf->mem);
+		buf->size = 0;
+		buf->mem = NULL;
+        }
+
+	/* clean up data rx buffers */
+	for (counter = 0; counter < ISL38XX_CB_RX_QSIZE; counter++) {
+		if (priv->pci_map_rx_address[counter])
+			pci_unmap_single(priv->pdev,
+					 priv->pci_map_rx_address[counter],
+					 MAX_FRAGMENT_SIZE_RX + 2,
+					 PCI_DMA_FROMDEVICE);
+		priv->pci_map_rx_address[counter] = 0;
+
+		if (priv->data_low_rx[counter])
+			dev_kfree_skb(priv->data_low_rx[counter]);
+		priv->data_low_rx[counter] = NULL;
+	}
+
+	/* Free the acces control list and the WPA list */
+	prism54_acl_clean(&priv->acl);
+	prism54_wpa_ie_clean(priv);
+	mgt_clean(priv);
+
+	return 0;
+}
+
+#if 0
+static void
+islpci_set_multicast_list(struct net_device *dev)
+{
+	/* put device into promisc mode and let network layer handle it */
+}
+#endif
+
+struct net_device *
+islpci_setup(struct pci_dev *pdev)
+{
+	islpci_private *priv;
+	struct net_device *ndev = alloc_etherdev(sizeof (islpci_private));
+
+	if (!ndev)
+		return ndev;
+
+	SET_MODULE_OWNER(ndev);
+	pci_set_drvdata(pdev, ndev);
+#if defined(SET_NETDEV_DEV)
+	SET_NETDEV_DEV(ndev, &pdev->dev);
+#endif
+
+	/* setup the structure members */
+	ndev->base_addr = pci_resource_start(pdev, 0);
+	ndev->irq = pdev->irq;
+
+	/* initialize the function pointers */
+	ndev->open = &islpci_open;
+	ndev->stop = &islpci_close;
+	ndev->get_stats = &islpci_statistics;
+	ndev->get_wireless_stats = &prism54_get_wireless_stats;
+	ndev->do_ioctl = &prism54_ioctl;
+	ndev->wireless_handlers =
+	    (struct iw_handler_def *) &prism54_handler_def;
+
+	ndev->hard_start_xmit = &islpci_eth_transmit;
+	/* ndev->set_multicast_list = &islpci_set_multicast_list; */
+	ndev->addr_len = ETH_ALEN;
+	ndev->set_mac_address = &prism54_set_mac_address;
+	/* Get a non-zero dummy MAC address for nameif. Jean II */
+	memcpy(ndev->dev_addr, dummy_mac, 6);
+
+#ifdef HAVE_TX_TIMEOUT
+	ndev->watchdog_timeo = ISLPCI_TX_TIMEOUT;
+	ndev->tx_timeout = &islpci_eth_tx_timeout;
+#endif
+
+	/* allocate a private device structure to the network device  */
+	priv = netdev_priv(ndev);
+	priv->ndev = ndev;
+	priv->pdev = pdev;
+	priv->monitor_type = ARPHRD_IEEE80211;
+	priv->ndev->type = (priv->iw_mode == IW_MODE_MONITOR) ?
+		priv->monitor_type : ARPHRD_ETHER;
+
+	/* save the start and end address of the PCI memory area */
+	ndev->mem_start = (unsigned long) priv->device_base;
+	ndev->mem_end = ndev->mem_start + ISL38XX_PCI_MEM_SIZE;
+
+#if VERBOSE > SHOW_ERROR_MESSAGES
+	DEBUG(SHOW_TRACING, "PCI Memory remapped to 0x%p\n", priv->device_base);
+#endif
+
+	init_waitqueue_head(&priv->reset_done);
+
+	/* init the queue read locks, process wait counter */
+	sema_init(&priv->mgmt_sem, 1);
+	priv->mgmt_received = NULL;
+	init_waitqueue_head(&priv->mgmt_wqueue);
+	sema_init(&priv->stats_sem, 1);
+	spin_lock_init(&priv->slock);
+
+	/* init state machine with off#1 state */
+	priv->state = PRV_STATE_OFF;
+	priv->state_off = 1;
+
+	/* initialize workqueue's */
+	INIT_WORK(&priv->stats_work,
+		  (void (*)(void *)) prism54_update_stats, priv);
+	priv->stats_timestamp = 0;
+
+	INIT_WORK(&priv->reset_task, islpci_do_reset_and_wake, priv);
+	priv->reset_task_pending = 0;
+
+	/* allocate various memory areas */
+	if (islpci_alloc_memory(priv))
+		goto do_free_netdev;
+
+	/* select the firmware file depending on the device id */
+	switch (pdev->device) {
+	case 0x3877:
+		strcpy(priv->firmware, ISL3877_IMAGE_FILE);
+		break;
+
+	case 0x3886:
+		strcpy(priv->firmware, ISL3886_IMAGE_FILE);
+		break;
+
+	default:
+		strcpy(priv->firmware, ISL3890_IMAGE_FILE);
+		break;
+	}
+
+	if (register_netdev(ndev)) {
+		DEBUG(SHOW_ERROR_MESSAGES,
+		      "ERROR: register_netdev() failed \n");
+		goto do_islpci_free_memory;
+	}
+
+	return ndev;
+
+      do_islpci_free_memory:
+	islpci_free_memory(priv);
+      do_free_netdev:
+	pci_set_drvdata(pdev, NULL);
+	free_netdev(ndev);
+	priv = NULL;
+	return NULL;
+}
+
+islpci_state_t
+islpci_set_state(islpci_private *priv, islpci_state_t new_state)
+{
+	islpci_state_t old_state;
+
+	/* lock */
+	old_state = priv->state;
+
+	/* this means either a race condition or some serious error in
+	 * the driver code */
+	switch (new_state) {
+	case PRV_STATE_OFF:
+		priv->state_off++;
+	default:
+		priv->state = new_state;
+		break;
+
+	case PRV_STATE_PREBOOT:
+		/* there are actually many off-states, enumerated by
+		 * state_off */
+		if (old_state == PRV_STATE_OFF)
+			priv->state_off--;
+
+		/* only if hw_unavailable is zero now it means we either
+		 * were in off#1 state, or came here from
+		 * somewhere else */
+		if (!priv->state_off)
+			priv->state = new_state;
+		break;
+	};
+#if 0
+	printk(KERN_DEBUG "%s: state transition %d -> %d (off#%d)\n",
+	       priv->ndev->name, old_state, new_state, priv->state_off);
+#endif
+
+	/* invariants */
+	BUG_ON(priv->state_off < 0);
+	BUG_ON(priv->state_off && (priv->state != PRV_STATE_OFF));
+	BUG_ON(!priv->state_off && (priv->state == PRV_STATE_OFF));
+
+	/* unlock */
+	return old_state;
+}
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/net/wireless/prism54/islpci_dev.h linux-2.4.28-pre3/drivers/net/wireless/prism54/islpci_dev.h
--- linux-2.4.27/drivers/net/wireless/prism54/islpci_dev.h	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.28-pre3/drivers/net/wireless/prism54/islpci_dev.h	2004-09-10 19:33:55.000000000 +0000
@@ -0,0 +1,215 @@
+/*
+ *  
+ *  Copyright (C) 2002 Intersil Americas Inc. 
+ *  Copyright (C) 2003 Herbert Valerio Riedel <hvr@gnu.org>
+ *  Copyright (C) 2003 Luis R. Rodriguez <mcgrof@ruslug.rutgers.edu>
+ *  Copyright (C) 2003 Aurelien Alleaume <slts@free.fr>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License
+ *
+ *  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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef _ISLPCI_DEV_H
+#define _ISLPCI_DEV_H
+
+#include <linux/version.h>
+#include <linux/netdevice.h>
+#include <linux/wireless.h>
+#include <net/iw_handler.h>
+#include <linux/list.h>
+
+#include "isl_38xx.h"
+#include "isl_oid.h"
+#include "islpci_mgt.h"
+
+/* some states might not be superflous and may be removed when
+   design is finalized (hvr) */
+typedef enum {
+	PRV_STATE_OFF = 0,	/* this means hw_unavailable is != 0 */
+	PRV_STATE_PREBOOT,	/* we are in a pre-boot state (empty RAM) */
+	PRV_STATE_BOOT,		/* boot state (fw upload, run fw) */
+	PRV_STATE_POSTBOOT,	/* after boot state, need reset now */
+	PRV_STATE_PREINIT,	/* pre-init state */
+	PRV_STATE_INIT,		/* init state (restore MIB backup to device) */
+	PRV_STATE_READY,	/* driver&device are in operational state */
+	PRV_STATE_SLEEP		/* device in sleep mode */
+} islpci_state_t;
+
+/* ACL using MAC address */
+struct mac_entry {
+   struct list_head _list;
+   char addr[ETH_ALEN];
+};
+
+struct islpci_acl {
+   enum { MAC_POLICY_OPEN=0, MAC_POLICY_ACCEPT=1, MAC_POLICY_REJECT=2 } policy;
+   struct list_head mac_list;  /* a list of mac_entry */
+   int size;   /* size of queue */
+   struct semaphore sem;   /* accessed in ioctls and trap_work */
+};
+
+struct islpci_membuf {
+	int size;                   /* size of memory */
+	void *mem;                  /* address of memory as seen by CPU */
+	dma_addr_t pci_addr;        /* address of memory as seen by device */
+};
+
+#define MAX_BSS_WPA_IE_COUNT 64
+#define MAX_WPA_IE_LEN 64
+struct islpci_bss_wpa_ie {
+	struct list_head list;
+	unsigned long last_update;
+	u8 bssid[ETH_ALEN];
+	u8 wpa_ie[MAX_WPA_IE_LEN];
+	size_t wpa_ie_len;
+	
+};
+
+typedef struct {
+	spinlock_t slock;	/* generic spinlock; */
+	
+	u32 priv_oid;
+
+	/* our mib cache */
+	u32 iw_mode;
+        struct rw_semaphore mib_sem;
+	void **mib;
+	char nickname[IW_ESSID_MAX_SIZE+1];
+	
+	/* Take care of the wireless stats */
+	struct work_struct stats_work;
+	struct semaphore stats_sem;
+	/* remember when we last updated the stats */
+	unsigned long stats_timestamp;
+	/* The first is accessed under semaphore locking.
+	 * The second is the clean one we return to iwconfig.
+	 */
+	struct iw_statistics local_iwstatistics;
+	struct iw_statistics iwstatistics;
+
+	struct iw_spy_data spy_data; /* iwspy support */
+
+	int monitor_type; /* ARPHRD_IEEE80211 or ARPHRD_IEEE80211_PRISM */
+
+	struct islpci_acl acl;
+
+	/* PCI bus allocation & configuration members */
+	struct pci_dev *pdev;	/* PCI structure information */
+	u32 pci_state[16];	/* used for suspend/resume */
+	char firmware[33];
+
+	void *device_base;	/* ioremapped device base address */
+
+	/* consistent DMA region */
+	void *driver_mem_address;	/* base DMA address */
+	dma_addr_t device_host_address;	/* base DMA address (bus address) */
+	dma_addr_t device_psm_buffer;	/* host memory for PSM buffering (bus address) */
+
+	/* our network_device structure  */
+	struct net_device *ndev;
+
+	/* device queue interface members */
+	struct isl38xx_cb *control_block;	/* device control block 
+							   (== driver_mem_address!) */
+
+	/* Each queue has three indexes:
+	 *   free/index_mgmt/data_rx/tx (called index, see below),
+	 *   driver_curr_frag, and device_curr_frag (in the control block)
+	 * All indexes are ever-increasing, but interpreted modulo the
+	 * device queue size when used.
+	 *   index <= device_curr_frag <= driver_curr_frag  at all times
+	 * For rx queues, [index, device_curr_frag) contains fragments
+	 * that the interrupt processing needs to handle (owned by driver).
+	 * [device_curr_frag, driver_curr_frag) is the free space in the
+	 * rx queue, waiting for data (owned by device).  The driver
+	 * increments driver_curr_frag to indicate to the device that more
+	 * buffers are available.
+	 * If device_curr_frag == driver_curr_frag, no more rx buffers are
+	 * available, and the rx DMA engine of the device is halted.
+	 * For tx queues, [index, device_curr_frag) contains fragments
+	 * where tx is done; they need to be freed (owned by driver).
+	 * [device_curr_frag, driver_curr_frag) contains the frames
+	 * that are being transferred (owned by device).  The driver
+	 * increments driver_curr_frag to indicate that more tx work
+	 * needs to be done.
+	 */
+	u32 index_mgmt_rx;              /* real index mgmt rx queue */
+	u32 index_mgmt_tx;              /* read index mgmt tx queue */
+	u32 free_data_rx;	/* free pointer data rx queue */
+	u32 free_data_tx;	/* free pointer data tx queue */
+	u32 data_low_tx_full;	/* full detected flag */
+
+	/* frame memory buffers for the device queues */
+	struct islpci_membuf mgmt_tx[ISL38XX_CB_MGMT_QSIZE];
+	struct islpci_membuf mgmt_rx[ISL38XX_CB_MGMT_QSIZE];
+	struct sk_buff *data_low_tx[ISL38XX_CB_TX_QSIZE];
+	struct sk_buff *data_low_rx[ISL38XX_CB_RX_QSIZE];
+	dma_addr_t pci_map_tx_address[ISL38XX_CB_TX_QSIZE];
+	dma_addr_t pci_map_rx_address[ISL38XX_CB_RX_QSIZE];
+
+	/* driver network interface members */
+	struct net_device_stats statistics;
+
+	/* wait for a reset interrupt */
+	wait_queue_head_t reset_done;
+
+	/* used by islpci_mgt_transaction */
+	struct semaphore mgmt_sem; /* serialize access to mailbox and wqueue */
+	struct islpci_mgmtframe *mgmt_received;	  /* mbox for incoming frame */
+	wait_queue_head_t mgmt_wqueue;            /* waitqueue for mbox */
+
+	/* state machine */
+	islpci_state_t state;
+	int state_off;		/* enumeration of off-state, if 0 then
+				 * we're not in any off-state */
+
+	/* WPA stuff */
+	int wpa; /* WPA mode enabled */
+	struct list_head bss_wpa_list;
+	int num_bss_wpa;
+	struct semaphore wpa_sem;
+
+	struct work_struct reset_task;
+	int reset_task_pending;
+} islpci_private;
+
+static inline islpci_state_t
+islpci_get_state(islpci_private *priv)
+{
+	/* lock */
+	return priv->state;
+	/* unlock */
+}
+
+islpci_state_t islpci_set_state(islpci_private *priv, islpci_state_t new_state);
+
+#define ISLPCI_TX_TIMEOUT               (2*HZ)
+
+irqreturn_t islpci_interrupt(int, void *, struct pt_regs *);
+
+int prism54_post_setup(islpci_private *, int);
+int islpci_reset(islpci_private *, int);
+
+static inline void
+islpci_trigger(islpci_private *priv)
+{
+	isl38xx_trigger_device(islpci_get_state(priv) == PRV_STATE_SLEEP,
+			       priv->device_base);
+}
+
+struct net_device_stats *islpci_statistics(struct net_device *);
+
+int islpci_free_memory(islpci_private *);
+struct net_device *islpci_setup(struct pci_dev *);
+#endif				/* _ISLPCI_DEV_H */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/net/wireless/prism54/islpci_eth.c linux-2.4.28-pre3/drivers/net/wireless/prism54/islpci_eth.c
--- linux-2.4.27/drivers/net/wireless/prism54/islpci_eth.c	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.28-pre3/drivers/net/wireless/prism54/islpci_eth.c	2004-09-10 19:33:05.000000000 +0000
@@ -0,0 +1,518 @@
+/*
+ *  
+ *  Copyright (C) 2002 Intersil Americas Inc.
+ *  Copyright (C) 2004 Aurelien Alleaume <slts@free.fr>
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License
+ *
+ *  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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include <linux/version.h>
+#include <linux/module.h>
+
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/if_arp.h>
+
+#include "prismcompat.h"
+#include "isl_38xx.h"
+#include "islpci_eth.h"
+#include "islpci_mgt.h"
+#include "oid_mgt.h"
+
+/******************************************************************************
+    Network Interface functions
+******************************************************************************/
+void
+islpci_eth_cleanup_transmit(islpci_private *priv,
+			    isl38xx_control_block *control_block)
+{
+	struct sk_buff *skb;
+	u32 index;
+
+	/* compare the control block read pointer with the free pointer */
+	while (priv->free_data_tx !=
+	       le32_to_cpu(control_block->
+			   device_curr_frag[ISL38XX_CB_TX_DATA_LQ])) {
+		/* read the index of the first fragment to be freed */
+		index = priv->free_data_tx % ISL38XX_CB_TX_QSIZE;
+
+		/* check for holes in the arrays caused by multi fragment frames 
+		 * searching for the last fragment of a frame */
+		if (priv->pci_map_tx_address[index] != (dma_addr_t) NULL) {
+			/* entry is the last fragment of a frame
+			 * free the skb structure and unmap pci memory */
+			skb = priv->data_low_tx[index];
+
+#if VERBOSE > SHOW_ERROR_MESSAGES
+			DEBUG(SHOW_TRACING,
+			      "cleanup skb %p skb->data %p skb->len %u truesize %u\n ",
+			      skb, skb->data, skb->len, skb->truesize);
+#endif
+
+			pci_unmap_single(priv->pdev,
+					 priv->pci_map_tx_address[index],
+					 skb->len, PCI_DMA_TODEVICE);
+			dev_kfree_skb_irq(skb);
+			skb = NULL;
+		}
+		/* increment the free data low queue pointer */
+		priv->free_data_tx++;
+	}
+}
+
+int
+islpci_eth_transmit(struct sk_buff *skb, struct net_device *ndev)
+{
+	islpci_private *priv = netdev_priv(ndev);
+	isl38xx_control_block *cb = priv->control_block;
+	u32 index;
+	dma_addr_t pci_map_address;
+	int frame_size;
+	isl38xx_fragment *fragment;
+	int offset;
+	struct sk_buff *newskb;
+	int newskb_offset;
+	unsigned long flags;
+	unsigned char wds_mac[6];
+	u32 curr_frag;
+	int err = 0;
+
+#if VERBOSE > SHOW_ERROR_MESSAGES
+	DEBUG(SHOW_FUNCTION_CALLS, "islpci_eth_transmit \n");
+#endif
+
+	/* lock the driver code */
+	spin_lock_irqsave(&priv->slock, flags);
+
+	/* determine the amount of fragments needed to store the frame */
+
+	frame_size = skb->len < ETH_ZLEN ? ETH_ZLEN : skb->len;
+	if (init_wds)
+		frame_size += 6;
+
+	/* check whether the destination queue has enough fragments for the frame */
+	curr_frag = le32_to_cpu(cb->driver_curr_frag[ISL38XX_CB_TX_DATA_LQ]);
+	if (unlikely(curr_frag - priv->free_data_tx >= ISL38XX_CB_TX_QSIZE)) {
+		printk(KERN_ERR "%s: transmit device queue full when awake\n",
+		       ndev->name);
+		netif_stop_queue(ndev);
+
+		/* trigger the device */
+		isl38xx_w32_flush(priv->device_base, ISL38XX_DEV_INT_UPDATE,
+				  ISL38XX_DEV_INT_REG);
+		udelay(ISL38XX_WRITEIO_DELAY);
+
+		err = -EBUSY;
+		goto drop_free;
+	}
+	/* Check alignment and WDS frame formatting. The start of the packet should
+	 * be aligned on a 4-byte boundary. If WDS is enabled add another 6 bytes
+	 * and add WDS address information */
+	if (likely(((long) skb->data & 0x03) | init_wds)) {
+		/* get the number of bytes to add and re-allign */
+		offset = (4 - (long) skb->data) & 0x03;
+		offset += init_wds ? 6 : 0;
+
+		/* check whether the current skb can be used  */
+		if (!skb_cloned(skb) && (skb_tailroom(skb) >= offset)) {
+			unsigned char *src = skb->data;
+
+#if VERBOSE > SHOW_ERROR_MESSAGES
+			DEBUG(SHOW_TRACING, "skb offset %i wds %i\n", offset,
+			      init_wds);
+#endif
+
+			/* align the buffer on 4-byte boundary */
+			skb_reserve(skb, (4 - (long) skb->data) & 0x03);
+			if (init_wds) {
+				/* wds requires an additional address field of 6 bytes */
+				skb_put(skb, 6);
+#ifdef ISLPCI_ETH_DEBUG
+				printk("islpci_eth_transmit:wds_mac\n");
+#endif
+				memmove(skb->data + 6, src, skb->len);
+				memcpy(skb->data, wds_mac, 6);
+			} else {
+				memmove(skb->data, src, skb->len);
+			}
+
+#if VERBOSE > SHOW_ERROR_MESSAGES
+			DEBUG(SHOW_TRACING, "memmove %p %p %i \n", skb->data,
+			      src, skb->len);
+#endif
+		} else {
+			newskb =
+			    dev_alloc_skb(init_wds ? skb->len + 6 : skb->len);
+			if (unlikely(newskb == NULL)) {
+				printk(KERN_ERR "%s: Cannot allocate skb\n",
+				       ndev->name);
+				err = -ENOMEM;
+				goto drop_free;
+			}
+			newskb_offset = (4 - (long) newskb->data) & 0x03;
+
+			/* Check if newskb->data is aligned */
+			if (newskb_offset)
+				skb_reserve(newskb, newskb_offset);
+
+			skb_put(newskb, init_wds ? skb->len + 6 : skb->len);
+			if (init_wds) {
+				memcpy(newskb->data + 6, skb->data, skb->len);
+				memcpy(newskb->data, wds_mac, 6);
+#ifdef ISLPCI_ETH_DEBUG
+				printk("islpci_eth_transmit:wds_mac\n");
+#endif
+			} else
+				memcpy(newskb->data, skb->data, skb->len);
+
+#if VERBOSE > SHOW_ERROR_MESSAGES
+			DEBUG(SHOW_TRACING, "memcpy %p %p %i wds %i\n",
+			      newskb->data, skb->data, skb->len, init_wds);
+#endif
+
+			newskb->dev = skb->dev;
+			dev_kfree_skb(skb);
+			skb = newskb;
+		}
+	}
+	/* display the buffer contents for debugging */
+#if VERBOSE > SHOW_ERROR_MESSAGES
+	DEBUG(SHOW_BUFFER_CONTENTS, "\ntx %p ", skb->data);
+	display_buffer((char *) skb->data, skb->len);
+#endif
+
+	/* map the skb buffer to pci memory for DMA operation */
+	pci_map_address = pci_map_single(priv->pdev,
+					 (void *) skb->data, skb->len,
+					 PCI_DMA_TODEVICE);
+	if (unlikely(pci_map_address == 0)) {
+		printk(KERN_WARNING "%s: cannot map buffer to PCI\n",
+		       ndev->name);
+
+		err = -EIO;
+		goto drop_free;
+	}
+	/* Place the fragment in the control block structure. */
+	index = curr_frag % ISL38XX_CB_TX_QSIZE;
+	fragment = &cb->tx_data_low[index];
+
+	priv->pci_map_tx_address[index] = pci_map_address;
+	/* store the skb address for future freeing  */
+	priv->data_low_tx[index] = skb;
+	/* set the proper fragment start address and size information */
+	fragment->size = cpu_to_le16(frame_size);
+	fragment->flags = cpu_to_le16(0);	/* set to 1 if more fragments */
+	fragment->address = cpu_to_le32(pci_map_address);
+	curr_frag++;
+
+	/* The fragment address in the control block must have been
+	 * written before announcing the frame buffer to device. */
+	wmb();
+	cb->driver_curr_frag[ISL38XX_CB_TX_DATA_LQ] = cpu_to_le32(curr_frag);
+
+	if (curr_frag - priv->free_data_tx + ISL38XX_MIN_QTHRESHOLD
+	    > ISL38XX_CB_TX_QSIZE) {
+		/* stop sends from upper layers */
+		netif_stop_queue(ndev);
+
+		/* set the full flag for the transmission queue */
+		priv->data_low_tx_full = 1;
+	}
+
+	/* trigger the device */
+	islpci_trigger(priv);
+
+	/* unlock the driver code */
+	spin_unlock_irqrestore(&priv->slock, flags);
+
+	/* set the transmission time */
+	ndev->trans_start = jiffies;
+	priv->statistics.tx_packets++;
+	priv->statistics.tx_bytes += skb->len;
+
+	return 0;
+
+      drop_free:
+	/* free the skbuf structure before aborting */
+	dev_kfree_skb(skb);
+	skb = NULL;
+
+	priv->statistics.tx_dropped++;
+	spin_unlock_irqrestore(&priv->slock, flags);
+	return err;
+}
+
+static inline int
+islpci_monitor_rx(islpci_private *priv, struct sk_buff **skb)
+{
+	/* The card reports full 802.11 packets but with a 20 bytes
+	 * header and without the FCS. But there a is a bit that
+	 * indicates if the packet is corrupted :-) */
+	struct rfmon_header *hdr = (struct rfmon_header *) (*skb)->data;
+	if (hdr->flags & 0x01)
+		/* This one is bad. Drop it ! */
+		return -1;
+	if (priv->ndev->type == ARPHRD_IEEE80211_PRISM) {
+		struct avs_80211_1_header *avs;
+		/* extract the relevant data from the header */
+		u32 clock = le32_to_cpu(hdr->clock);
+		u8 rate = hdr->rate;
+		u16 freq = le16_to_cpu(hdr->freq);
+		u8 rssi = hdr->rssi;
+
+		skb_pull(*skb, sizeof (struct rfmon_header));
+
+		if (skb_headroom(*skb) < sizeof (struct avs_80211_1_header)) {
+			struct sk_buff *newskb = skb_copy_expand(*skb,
+								 sizeof (struct
+									 avs_80211_1_header),
+								 0, GFP_ATOMIC);
+			if (newskb) {
+				dev_kfree_skb_irq(*skb);
+				*skb = newskb;
+			} else
+				return -1;
+			/* This behavior is not very subtile... */
+		}
+
+		/* make room for the new header and fill it. */
+		avs =
+		    (struct avs_80211_1_header *) skb_push(*skb,
+							   sizeof (struct
+								   avs_80211_1_header));
+		
+		avs->version = cpu_to_be32(P80211CAPTURE_VERSION);
+		avs->length = cpu_to_be32(sizeof (struct avs_80211_1_header));
+		avs->mactime = cpu_to_be64(le64_to_cpu(clock));
+		avs->hosttime = cpu_to_be64(jiffies);
+		avs->phytype = cpu_to_be32(6);	/*OFDM: 6 for (g), 8 for (a) */
+		avs->channel = cpu_to_be32(channel_of_freq(freq));
+		avs->datarate = cpu_to_be32(rate * 5);
+		avs->antenna = cpu_to_be32(0);	/*unknown */
+		avs->priority = cpu_to_be32(0);	/*unknown */
+		avs->ssi_type = cpu_to_be32(3);	/*2: dBm, 3: raw RSSI */
+		avs->ssi_signal = cpu_to_be32(rssi & 0x7f);
+		avs->ssi_noise = cpu_to_be32(priv->local_iwstatistics.qual.noise);	/*better than 'undefined', I assume */
+		avs->preamble = cpu_to_be32(0);	/*unknown */
+		avs->encoding = cpu_to_be32(0);	/*unknown */
+	} else
+		skb_pull(*skb, sizeof (struct rfmon_header));
+
+	(*skb)->protocol = htons(ETH_P_802_2);
+	(*skb)->mac.raw = (*skb)->data;
+	(*skb)->pkt_type = PACKET_OTHERHOST;
+
+	return 0;
+}
+
+int
+islpci_eth_receive(islpci_private *priv)
+{
+	struct net_device *ndev = priv->ndev;
+	isl38xx_control_block *control_block = priv->control_block;
+	struct sk_buff *skb;
+	u16 size;
+	u32 index, offset;
+	unsigned char *src;
+	int discard = 0;
+
+#if VERBOSE > SHOW_ERROR_MESSAGES
+	DEBUG(SHOW_FUNCTION_CALLS, "islpci_eth_receive \n");
+#endif
+
+	/* the device has written an Ethernet frame in the data area
+	 * of the sk_buff without updating the structure, do it now */
+	index = priv->free_data_rx % ISL38XX_CB_RX_QSIZE;
+	size = le16_to_cpu(control_block->rx_data_low[index].size);
+	skb = priv->data_low_rx[index];
+	offset = ((unsigned long)
+		  le32_to_cpu(control_block->rx_data_low[index].address) -
+		  (unsigned long) skb->data) & 3;
+
+#if VERBOSE > SHOW_ERROR_MESSAGES
+	DEBUG(SHOW_TRACING,
+	      "frq->addr %x skb->data %p skb->len %u offset %u truesize %u\n ",
+	      control_block->rx_data_low[priv->free_data_rx].address, skb->data,
+	      skb->len, offset, skb->truesize);
+#endif
+
+	/* delete the streaming DMA mapping before processing the skb */
+	pci_unmap_single(priv->pdev,
+			 priv->pci_map_rx_address[index],
+			 MAX_FRAGMENT_SIZE_RX + 2, PCI_DMA_FROMDEVICE);
+
+	/* update the skb structure and allign the buffer */
+	skb_put(skb, size);
+	if (offset) {
+		/* shift the buffer allocation offset bytes to get the right frame */
+		skb_pull(skb, 2);
+		skb_put(skb, 2);
+	}
+#if VERBOSE > SHOW_ERROR_MESSAGES
+	/* display the buffer contents for debugging */
+	DEBUG(SHOW_BUFFER_CONTENTS, "\nrx %p ", skb->data);
+	display_buffer((char *) skb->data, skb->len);
+#endif
+
+	/* check whether WDS is enabled and whether the data frame is a WDS frame */
+
+	if (init_wds) {
+		/* WDS enabled, check for the wds address on the first 6 bytes of the buffer */
+		src = skb->data + 6;
+		memmove(skb->data, src, skb->len - 6);
+		skb_trim(skb, skb->len - 6);
+	}
+#if VERBOSE > SHOW_ERROR_MESSAGES
+	DEBUG(SHOW_TRACING, "Fragment size %i in skb at %p\n", size, skb);
+	DEBUG(SHOW_TRACING, "Skb data at %p, length %i\n", skb->data, skb->len);
+
+	/* display the buffer contents for debugging */
+	DEBUG(SHOW_BUFFER_CONTENTS, "\nrx %p ", skb->data);
+	display_buffer((char *) skb->data, skb->len);
+#endif
+
+	/* do some additional sk_buff and network layer parameters */
+	skb->dev = ndev;
+
+	/* take care of monitor mode and spy monitoring. */
+	if (unlikely(priv->iw_mode == IW_MODE_MONITOR))
+		discard = islpci_monitor_rx(priv, &skb);
+	else {
+		if (unlikely(skb->data[2 * ETH_ALEN] == 0)) {
+			/* The packet has a rx_annex. Read it for spy monitoring, Then
+			 * remove it, while keeping the 2 leading MAC addr.
+			 */
+			struct iw_quality wstats;
+			struct rx_annex_header *annex =
+			    (struct rx_annex_header *) skb->data;
+			wstats.level = annex->rfmon.rssi;
+			/* The noise value can be a bit outdated if nobody's 
+			 * reading wireless stats... */
+			wstats.noise = priv->local_iwstatistics.qual.noise;
+			wstats.qual = wstats.level - wstats.noise;
+			wstats.updated = 0x07;
+			/* Update spy records */
+			wireless_spy_update(ndev, annex->addr2, &wstats);
+
+			memcpy(skb->data + sizeof (struct rfmon_header),
+			       skb->data, 2 * ETH_ALEN);
+			skb_pull(skb, sizeof (struct rfmon_header));
+		}
+		skb->protocol = eth_type_trans(skb, ndev);
+	}
+	skb->ip_summed = CHECKSUM_NONE;
+	priv->statistics.rx_packets++;
+	priv->statistics.rx_bytes += size;
+
+	/* deliver the skb to the network layer */
+#ifdef ISLPCI_ETH_DEBUG
+	printk
+	    ("islpci_eth_receive:netif_rx %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X\n",
+	     skb->data[0], skb->data[1], skb->data[2], skb->data[3],
+	     skb->data[4], skb->data[5]);
+#endif
+	if (unlikely(discard)) {
+		dev_kfree_skb_irq(skb);
+		skb = NULL;
+	} else
+		netif_rx(skb);
+
+	/* increment the read index for the rx data low queue */
+	priv->free_data_rx++;
+
+	/* add one or more sk_buff structures */
+	while (index =
+	       le32_to_cpu(control_block->
+			   driver_curr_frag[ISL38XX_CB_RX_DATA_LQ]),
+	       index - priv->free_data_rx < ISL38XX_CB_RX_QSIZE) {
+		/* allocate an sk_buff for received data frames storage
+		 * include any required allignment operations */
+		skb = dev_alloc_skb(MAX_FRAGMENT_SIZE_RX + 2);
+		if (unlikely(skb == NULL)) {
+			/* error allocating an sk_buff structure elements */
+			DEBUG(SHOW_ERROR_MESSAGES, "Error allocating skb \n");
+			break;
+		}
+		skb_reserve(skb, (4 - (long) skb->data) & 0x03);
+		/* store the new skb structure pointer */
+		index = index % ISL38XX_CB_RX_QSIZE;
+		priv->data_low_rx[index] = skb;
+
+#if VERBOSE > SHOW_ERROR_MESSAGES
+		DEBUG(SHOW_TRACING,
+		      "new alloc skb %p skb->data %p skb->len %u index %u truesize %u\n ",
+		      skb, skb->data, skb->len, index, skb->truesize);
+#endif
+
+		/* set the streaming DMA mapping for proper PCI bus operation */
+		priv->pci_map_rx_address[index] =
+		    pci_map_single(priv->pdev, (void *) skb->data,
+				   MAX_FRAGMENT_SIZE_RX + 2,
+				   PCI_DMA_FROMDEVICE);
+		if (unlikely(priv->pci_map_rx_address[index] == (dma_addr_t) NULL)) {
+			/* error mapping the buffer to device accessable memory address */
+			DEBUG(SHOW_ERROR_MESSAGES,
+			      "Error mapping DMA address\n");
+
+			/* free the skbuf structure before aborting */
+			dev_kfree_skb_irq((struct sk_buff *) skb);
+			skb = NULL;
+			break;
+		}
+		/* update the fragment address */
+		control_block->rx_data_low[index].address = cpu_to_le32((u32)
+									priv->
+									pci_map_rx_address
+									[index]);
+		wmb();
+
+		/* increment the driver read pointer */
+		add_le32p((u32 *) &control_block->
+			  driver_curr_frag[ISL38XX_CB_RX_DATA_LQ], 1);
+	}
+
+	/* trigger the device */
+	islpci_trigger(priv);
+
+	return 0;
+}
+
+void
+islpci_do_reset_and_wake(void *data)
+{
+	islpci_private *priv = (islpci_private *) data;
+	islpci_reset(priv, 1);
+	netif_wake_queue(priv->ndev);
+	priv->reset_task_pending = 0;
+}
+
+void
+islpci_eth_tx_timeout(struct net_device *ndev)
+{
+	islpci_private *priv = netdev_priv(ndev);
+	struct net_device_stats *statistics = &priv->statistics;
+
+	/* increment the transmit error counter */
+	statistics->tx_errors++;
+
+	if (!priv->reset_task_pending) {
+		priv->reset_task_pending = 1;
+		netif_stop_queue(ndev);
+		schedule_work(&priv->reset_task);
+	}
+
+	return;
+}
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/net/wireless/prism54/islpci_eth.h linux-2.4.28-pre3/drivers/net/wireless/prism54/islpci_eth.h
--- linux-2.4.27/drivers/net/wireless/prism54/islpci_eth.h	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.28-pre3/drivers/net/wireless/prism54/islpci_eth.h	2004-09-10 19:35:30.000000000 +0000
@@ -0,0 +1,73 @@
+/*
+ *  
+ *  Copyright (C) 2002 Intersil Americas Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License
+ *
+ *  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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef _ISLPCI_ETH_H
+#define _ISLPCI_ETH_H
+
+#include "isl_38xx.h"
+#include "islpci_dev.h"
+
+struct rfmon_header {
+	u16 unk0;		/* = 0x0000 */
+	u16 length;		/* = 0x1400 */
+	u32 clock;		/* 1MHz clock */
+	u8 flags;
+	u8 unk1;
+	u8 rate;
+	u8 unk2;
+	u16 freq;
+	u16 unk3;
+	u8 rssi;
+	u8 padding[3];
+} __attribute__ ((packed));
+
+struct rx_annex_header {
+	u8 addr1[ETH_ALEN];
+	u8 addr2[ETH_ALEN];
+	struct rfmon_header rfmon;
+} __attribute__ ((packed));
+
+/* wlan-ng (and hopefully others) AVS header, version one.  Fields in
+ * network byte order. */
+#define P80211CAPTURE_VERSION 0x80211001
+
+struct avs_80211_1_header {
+	uint32_t version;
+	uint32_t length;
+	uint64_t mactime;
+	uint64_t hosttime;
+	uint32_t phytype;
+	uint32_t channel;
+	uint32_t datarate;
+	uint32_t antenna;
+	uint32_t priority;
+	uint32_t ssi_type;
+	int32_t ssi_signal;
+	int32_t ssi_noise;
+	uint32_t preamble;
+	uint32_t encoding;
+};
+
+void islpci_eth_cleanup_transmit(islpci_private *, isl38xx_control_block *);
+int islpci_eth_transmit(struct sk_buff *, struct net_device *);
+int islpci_eth_receive(islpci_private *);
+void islpci_eth_tx_timeout(struct net_device *);
+void islpci_do_reset_and_wake(void *data);
+
+#endif				/* _ISL_GEN_H */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/net/wireless/prism54/islpci_hotplug.c linux-2.4.28-pre3/drivers/net/wireless/prism54/islpci_hotplug.c
--- linux-2.4.27/drivers/net/wireless/prism54/islpci_hotplug.c	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.28-pre3/drivers/net/wireless/prism54/islpci_hotplug.c	2004-09-10 19:33:21.000000000 +0000
@@ -0,0 +1,340 @@
+/*
+ *  
+ *  Copyright (C) 2002 Intersil Americas Inc.
+ *  Copyright (C) 2003 Herbert Valerio Riedel <hvr@gnu.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License
+ *
+ *  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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/init.h> /* For __init, __exit */
+
+#include "prismcompat.h"
+#include "islpci_dev.h"
+#include "islpci_mgt.h"		/* for pc_debug */
+#include "isl_oid.h"
+
+#define DRV_NAME	"prism54"
+#define DRV_VERSION	"1.2"
+
+MODULE_AUTHOR("[Intersil] R.Bastings and W.Termorshuizen, The prism54.org Development Team <prism54-devel@prism54.org>");
+MODULE_DESCRIPTION("The Prism54 802.11 Wireless LAN adapter");
+MODULE_LICENSE("GPL");
+
+static int	init_pcitm = 0;
+module_param(init_pcitm, int, 0);
+
+/* In this order: vendor, device, subvendor, subdevice, class, class_mask,
+ * driver_data 
+ * If you have an update for this please contact prism54-devel@prism54.org 
+ * The latest list can be found at http://prism54.org/supported_cards.php */
+static const struct pci_device_id prism54_id_tbl[] = {
+	/* Intersil PRISM Duette/Prism GT Wireless LAN adapter */
+	{
+	 0x1260, 0x3890,
+	 PCI_ANY_ID, PCI_ANY_ID,
+	 0, 0, 0
+	},
+
+	/* 3COM 3CRWE154G72 Wireless LAN adapter */
+	{
+	 0x10b7, 0x6001,
+	 PCI_ANY_ID, PCI_ANY_ID,
+	 0, 0, 0
+	},
+
+	/* Intersil PRISM Indigo Wireless LAN adapter */
+	{
+	 0x1260, 0x3877,
+	 PCI_ANY_ID, PCI_ANY_ID,
+	 0, 0, 0
+	},
+
+	/* Intersil PRISM Javelin/Xbow Wireless LAN adapter */
+	{
+	 0x1260, 0x3886,
+	 PCI_ANY_ID, PCI_ANY_ID,
+	 0, 0, 0
+	},
+
+	/* End of list */
+	{0,0,0,0,0,0,0}
+};
+
+/* register the device with the Hotplug facilities of the kernel */
+MODULE_DEVICE_TABLE(pci, prism54_id_tbl);
+
+static int prism54_probe(struct pci_dev *, const struct pci_device_id *);
+static void prism54_remove(struct pci_dev *);
+static int prism54_suspend(struct pci_dev *, u32 state);
+static int prism54_resume(struct pci_dev *);
+
+static struct pci_driver prism54_driver = {
+	.name = DRV_NAME,
+	.id_table = prism54_id_tbl,
+	.probe = prism54_probe,
+	.remove = prism54_remove,
+	.suspend = prism54_suspend,
+	.resume = prism54_resume,
+	/* .enable_wake ; we don't support this yet */
+};
+
+/******************************************************************************
+    Module initialization functions
+******************************************************************************/
+
+int
+prism54_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+{
+	struct net_device *ndev;
+	u8 latency_tmr;
+	u32 mem_addr;
+	islpci_private *priv;
+	int rvalue;
+
+	/* TRACE(DRV_NAME); */
+	
+	
+	/* Enable the pci device */
+	if (pci_enable_device(pdev)) {
+		printk(KERN_ERR "%s: pci_enable_device() failed.\n", DRV_NAME);
+		return -ENODEV;
+	}
+
+	/* check whether the latency timer is set correctly */
+	pci_read_config_byte(pdev, PCI_LATENCY_TIMER, &latency_tmr);
+#if VERBOSE > SHOW_ERROR_MESSAGES
+	DEBUG(SHOW_TRACING, "latency timer: %x\n", latency_tmr);
+#endif
+	if (latency_tmr < PCIDEVICE_LATENCY_TIMER_MIN) {
+		/* set the latency timer */
+		pci_write_config_byte(pdev, PCI_LATENCY_TIMER,
+				      PCIDEVICE_LATENCY_TIMER_VAL);
+	}
+
+	/* enable PCI DMA */
+	if (pci_set_dma_mask(pdev, 0xffffffff)) {
+		printk(KERN_ERR "%s: 32-bit PCI DMA not supported", DRV_NAME);
+		goto do_pci_disable_device;
+        }
+
+	/* 0x40 is the programmable timer to configure the response timeout (TRDY_TIMEOUT)
+	 * 0x41 is the programmable timer to configure the retry timeout (RETRY_TIMEOUT)
+	 * 	The RETRY_TIMEOUT is used to set the number of retries that the core, as a
+	 * 	Master, will perform before abandoning a cycle. The default value for
+	 * 	RETRY_TIMEOUT is 0x80, which far exceeds the PCI 2.1 requirement for new
+	 * 	devices. A write of zero to the RETRY_TIMEOUT register disables this
+	 * 	function to allow use with any non-compliant legacy devices that may
+	 * 	execute more retries.
+	 *
+	 * 	Writing zero to both these two registers will disable both timeouts and
+	 * 	*can* solve problems caused by devices that are slow to respond.
+	 *	Make this configurable - MSW
+	 */
+	if ( init_pcitm >= 0 ) {
+		pci_write_config_byte(pdev, 0x40, (u8)init_pcitm);
+		pci_write_config_byte(pdev, 0x41, (u8)init_pcitm);
+	} else {
+		printk(KERN_INFO "PCI TRDY/RETRY unchanged\n");
+	}
+
+	/* request the pci device I/O regions */
+	rvalue = pci_request_regions(pdev, DRV_NAME);
+	if (rvalue) {
+		printk(KERN_ERR "%s: pci_request_regions failure (rc=%d)\n",
+		       DRV_NAME, rvalue);
+		goto do_pci_disable_device;
+	}
+
+	/* check if the memory window is indeed set */
+	rvalue = pci_read_config_dword(pdev, PCI_BASE_ADDRESS_0, &mem_addr);
+	if (rvalue || !mem_addr) {
+		printk(KERN_ERR "%s: PCI device memory region not configured; fix your BIOS or CardBus bridge/drivers\n",
+		       DRV_NAME);
+		goto do_pci_disable_device;
+	}
+
+	/* enable PCI bus-mastering */
+	DEBUG(SHOW_TRACING, "%s: pci_set_master(pdev)\n", DRV_NAME);
+	pci_set_master(pdev);
+
+	/* enable MWI */
+	pci_set_mwi(pdev);
+
+	/* setup the network device interface and its structure */
+	if (!(ndev = islpci_setup(pdev))) {
+		/* error configuring the driver as a network device */
+		printk(KERN_ERR "%s: could not configure network device\n",
+		       DRV_NAME);
+		goto do_pci_release_regions;
+	}
+
+	priv = netdev_priv(ndev);
+	islpci_set_state(priv, PRV_STATE_PREBOOT); /* we are attempting to boot */
+
+	/* card is in unknown state yet, might have some interrupts pending */
+	isl38xx_disable_interrupts(priv->device_base);
+
+	/* request for the interrupt before uploading the firmware */
+	rvalue = request_irq(pdev->irq, &islpci_interrupt,
+			     SA_SHIRQ, ndev->name, priv);
+
+	if (rvalue) {
+		/* error, could not hook the handler to the irq */
+		printk(KERN_ERR "%s: could not install IRQ handler\n",
+		       ndev->name);
+		goto do_unregister_netdev;
+	}
+
+	/* firmware upload is triggered in islpci_open */
+
+	return 0;
+
+      do_unregister_netdev:
+	unregister_netdev(ndev);
+	islpci_free_memory(priv);
+	pci_set_drvdata(pdev, NULL);
+	free_netdev(ndev);
+	priv = NULL;
+      do_pci_release_regions:
+	pci_release_regions(pdev);
+      do_pci_disable_device:
+	pci_disable_device(pdev);
+	return -EIO;
+}
+
+/* set by cleanup_module */
+static volatile int __in_cleanup_module = 0;
+
+/* this one removes one(!!) instance only */
+void
+prism54_remove(struct pci_dev *pdev)
+{
+	struct net_device *ndev = pci_get_drvdata(pdev);
+	islpci_private *priv = ndev ? netdev_priv(ndev) : NULL;
+	BUG_ON(!priv);
+
+	if (!__in_cleanup_module) {
+		printk(KERN_DEBUG "%s: hot unplug detected\n", ndev->name);
+		islpci_set_state(priv, PRV_STATE_OFF);
+	}
+
+	printk(KERN_DEBUG "%s: removing device\n", ndev->name);
+
+	unregister_netdev(ndev);
+
+	/* free the interrupt request */
+
+	if (islpci_get_state(priv) != PRV_STATE_OFF) {
+		isl38xx_disable_interrupts(priv->device_base);
+		islpci_set_state(priv, PRV_STATE_OFF);
+		/* This bellow causes a lockup at rmmod time. It might be
+		 * because some interrupts still linger after rmmod time, 
+		 * see bug #17 */
+		/* pci_set_power_state(pdev, 3);*/	/* try to power-off */
+	}
+
+	free_irq(pdev->irq, priv);
+
+	/* free the PCI memory and unmap the remapped page */
+	islpci_free_memory(priv);
+
+	pci_set_drvdata(pdev, NULL);
+	free_netdev(ndev);
+	priv = NULL;
+
+	pci_release_regions(pdev);
+
+	pci_disable_device(pdev);
+}
+
+int
+prism54_suspend(struct pci_dev *pdev, u32 state)
+{
+	struct net_device *ndev = pci_get_drvdata(pdev);
+	islpci_private *priv = ndev ? netdev_priv(ndev) : NULL;
+	BUG_ON(!priv);
+
+	printk(KERN_NOTICE "%s: got suspend request (state %d)\n",
+	       ndev->name, state);
+
+	pci_save_state(pdev, priv->pci_state);
+
+	/* tell the device not to trigger interrupts for now... */
+	isl38xx_disable_interrupts(priv->device_base);
+
+	/* from now on assume the hardware was already powered down
+	   and don't touch it anymore */
+	islpci_set_state(priv, PRV_STATE_OFF);
+
+	netif_stop_queue(ndev);
+	netif_device_detach(ndev);
+
+	return 0;
+}
+
+int
+prism54_resume(struct pci_dev *pdev)
+{
+	struct net_device *ndev = pci_get_drvdata(pdev);
+	islpci_private *priv = ndev ? netdev_priv(ndev) : NULL;
+	BUG_ON(!priv);
+
+	printk(KERN_NOTICE "%s: got resume request\n", ndev->name);
+
+	pci_restore_state(pdev, priv->pci_state);
+
+	/* alright let's go into the PREBOOT state */
+	islpci_reset(priv, 1);
+
+	netif_device_attach(ndev);
+	netif_start_queue(ndev);
+
+	return 0;
+}
+
+static int __init
+prism54_module_init(void)
+{
+	printk(KERN_INFO "Loaded %s driver, version %s\n",
+	       DRV_NAME, DRV_VERSION);
+
+	__bug_on_wrong_struct_sizes ();
+
+	return pci_module_init(&prism54_driver);
+}
+
+/* by the time prism54_module_exit() terminates, as a postcondition
+ * all instances will have been destroyed by calls to
+ * prism54_remove() */
+static void __exit
+prism54_module_exit(void)
+{
+	__in_cleanup_module = 1;
+
+	pci_unregister_driver(&prism54_driver);
+
+	printk(KERN_INFO "Unloaded %s driver\n", DRV_NAME);
+
+	__in_cleanup_module = 0;
+}
+
+/* register entry points */
+module_init(prism54_module_init);
+module_exit(prism54_module_exit);
+/* EOF */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/net/wireless/prism54/islpci_mgt.c linux-2.4.28-pre3/drivers/net/wireless/prism54/islpci_mgt.c
--- linux-2.4.27/drivers/net/wireless/prism54/islpci_mgt.c	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.28-pre3/drivers/net/wireless/prism54/islpci_mgt.c	2004-09-10 19:32:28.000000000 +0000
@@ -0,0 +1,510 @@
+/*
+ *  
+ *  Copyright (C) 2002 Intersil Americas Inc.
+ *  Copyright 2004 Jens Maurer <Jens.Maurer@gmx.net>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License
+ *
+ *  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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/netdevice.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+
+#include <asm/io.h>
+#include <asm/system.h>
+#include <linux/if_arp.h>
+
+#include "prismcompat.h"
+#include "isl_38xx.h"
+#include "islpci_mgt.h"
+#include "isl_oid.h"		/* additional types and defs for isl38xx fw */
+#include "isl_ioctl.h"
+
+#include <net/iw_handler.h>
+
+/******************************************************************************
+        Global variable definition section
+******************************************************************************/
+int pc_debug = VERBOSE;
+module_param(pc_debug, int, 0);
+
+/******************************************************************************
+    Driver general functions
+******************************************************************************/
+void
+display_buffer(char *buffer, int length)
+{
+	if ((pc_debug & SHOW_BUFFER_CONTENTS) == 0)
+		return;
+
+	while (length > 0) {
+		printk("[%02x]", *buffer & 255);
+		length--;
+		buffer++;
+	}
+
+	printk("\n");
+}
+
+/*****************************************************************************
+    Queue handling for management frames
+******************************************************************************/
+
+/*
+ * Helper function to create a PIMFOR management frame header.
+ */
+static void
+pimfor_encode_header(int operation, u32 oid, u32 length, pimfor_header_t *h)
+{
+	h->version = PIMFOR_VERSION;
+	h->operation = operation;
+	h->device_id = PIMFOR_DEV_ID_MHLI_MIB;
+	h->flags = 0;
+	h->oid = cpu_to_be32(oid);
+	h->length = cpu_to_be32(length);
+}
+
+/*
+ * Helper function to analyze a PIMFOR management frame header.
+ */
+static pimfor_header_t *
+pimfor_decode_header(void *data, int len)
+{
+	pimfor_header_t *h = data;
+
+	while ((void *) h < data + len) {
+		if (h->flags & PIMFOR_FLAG_LITTLE_ENDIAN) {
+			le32_to_cpus(&h->oid);
+			le32_to_cpus(&h->length);
+		} else {
+			be32_to_cpus(&h->oid);
+			be32_to_cpus(&h->length);
+		}
+		if (h->oid != OID_INL_TUNNEL)
+			return h;
+		h++;
+	}
+	return NULL;
+}
+
+/*
+ * Fill the receive queue for management frames with fresh buffers.
+ */
+int
+islpci_mgmt_rx_fill(struct net_device *ndev)
+{
+	islpci_private *priv = netdev_priv(ndev);
+	isl38xx_control_block *cb =	/* volatile not needed */
+	    (isl38xx_control_block *) priv->control_block;
+	u32 curr = le32_to_cpu(cb->driver_curr_frag[ISL38XX_CB_RX_MGMTQ]);
+
+#if VERBOSE > SHOW_ERROR_MESSAGES
+	DEBUG(SHOW_FUNCTION_CALLS, "islpci_mgmt_rx_fill \n");
+#endif
+
+	while (curr - priv->index_mgmt_rx < ISL38XX_CB_MGMT_QSIZE) {
+		u32 index = curr % ISL38XX_CB_MGMT_QSIZE;
+		struct islpci_membuf *buf = &priv->mgmt_rx[index];
+		isl38xx_fragment *frag = &cb->rx_data_mgmt[index];
+
+		if (buf->mem == NULL) {
+			buf->mem = kmalloc(MGMT_FRAME_SIZE, GFP_ATOMIC);
+			if (!buf->mem) {
+				printk(KERN_WARNING
+				       "Error allocating management frame.\n");
+				return -ENOMEM;
+			}
+			buf->size = MGMT_FRAME_SIZE;
+		}
+		if (buf->pci_addr == 0) {
+			buf->pci_addr = pci_map_single(priv->pdev, buf->mem,
+						       MGMT_FRAME_SIZE,
+						       PCI_DMA_FROMDEVICE);
+			if (!buf->pci_addr) {
+				printk(KERN_WARNING
+				       "Failed to make memory DMA'able\n.");
+				return -ENOMEM;
+			}
+		}
+
+		/* be safe: always reset control block information */
+		frag->size = cpu_to_le16(MGMT_FRAME_SIZE);
+		frag->flags = 0;
+		frag->address = cpu_to_le32(buf->pci_addr);
+		curr++;
+
+		/* The fragment address in the control block must have
+		 * been written before announcing the frame buffer to
+		 * device */
+		wmb();
+		cb->driver_curr_frag[ISL38XX_CB_RX_MGMTQ] = cpu_to_le32(curr);
+	}
+	return 0;
+}
+
+/*
+ * Create and transmit a management frame using "operation" and "oid",
+ * with arguments data/length.
+ * We either return an error and free the frame, or we return 0 and
+ * islpci_mgt_cleanup_transmit() frees the frame in the tx-done
+ * interrupt.
+ */
+static int
+islpci_mgt_transmit(struct net_device *ndev, int operation, unsigned long oid,
+		    void *data, int length)
+{
+	islpci_private *priv = netdev_priv(ndev);
+	isl38xx_control_block *cb =
+	    (isl38xx_control_block *) priv->control_block;
+	void *p;
+	int err = -EINVAL;
+	unsigned long flags;
+	isl38xx_fragment *frag;
+	struct islpci_membuf buf;
+	u32 curr_frag;
+	int index;
+	int frag_len = length + PIMFOR_HEADER_SIZE;
+
+#if VERBOSE > SHOW_ERROR_MESSAGES
+	DEBUG(SHOW_FUNCTION_CALLS, "islpci_mgt_transmit\n");
+#endif
+
+	if (frag_len > MGMT_FRAME_SIZE) {
+		printk(KERN_DEBUG "%s: mgmt frame too large %d\n",
+		       ndev->name, frag_len);
+		goto error;
+	}
+
+	err = -ENOMEM;
+	p = buf.mem = kmalloc(frag_len, GFP_KERNEL);
+	if (!buf.mem) {
+		printk(KERN_DEBUG "%s: cannot allocate mgmt frame\n",
+		       ndev->name);
+		goto error;
+	}
+	buf.size = frag_len;
+
+	/* create the header directly in the fragment data area */
+	pimfor_encode_header(operation, oid, length, (pimfor_header_t *) p);
+	p += PIMFOR_HEADER_SIZE;
+
+	if (data)
+		memcpy(p, data, length);
+	else
+		memset(p, 0, length);
+
+#if VERBOSE > SHOW_ERROR_MESSAGES
+	{
+		pimfor_header_t *h = buf.mem;
+		DEBUG(SHOW_PIMFOR_FRAMES,
+		      "PIMFOR: op %i, oid 0x%08lx, device %i, flags 0x%x length 0x%x \n",
+		      h->operation, oid, h->device_id, h->flags, length);
+
+		/* display the buffer contents for debugging */
+		display_buffer((char *) h, sizeof (pimfor_header_t));
+		display_buffer(p, length);
+	}
+#endif
+
+	err = -ENOMEM;
+	buf.pci_addr = pci_map_single(priv->pdev, buf.mem, frag_len,
+				      PCI_DMA_TODEVICE);
+	if (!buf.pci_addr) {
+		printk(KERN_WARNING "%s: cannot map PCI memory for mgmt\n",
+		       ndev->name);
+		goto error_free;
+	}
+
+	/* Protect the control block modifications against interrupts. */
+	spin_lock_irqsave(&priv->slock, flags);
+	curr_frag = le32_to_cpu(cb->driver_curr_frag[ISL38XX_CB_TX_MGMTQ]);
+	if (curr_frag - priv->index_mgmt_tx >= ISL38XX_CB_MGMT_QSIZE) {
+		printk(KERN_WARNING "%s: mgmt tx queue is still full\n",
+		       ndev->name);
+		goto error_unlock;
+	}
+
+	/* commit the frame to the tx device queue */
+	index = curr_frag % ISL38XX_CB_MGMT_QSIZE;
+	priv->mgmt_tx[index] = buf;
+	frag = &cb->tx_data_mgmt[index];
+	frag->size = cpu_to_le16(frag_len);
+	frag->flags = 0;	/* for any other than the last fragment, set to 1 */
+	frag->address = cpu_to_le32(buf.pci_addr);
+
+	/* The fragment address in the control block must have
+	 * been written before announcing the frame buffer to
+	 * device */
+	wmb();
+	cb->driver_curr_frag[ISL38XX_CB_TX_MGMTQ] = cpu_to_le32(curr_frag + 1);
+	spin_unlock_irqrestore(&priv->slock, flags);
+
+	/* trigger the device */
+	islpci_trigger(priv);
+	return 0;
+
+      error_unlock:
+	spin_unlock_irqrestore(&priv->slock, flags);
+      error_free:
+	kfree(buf.mem);
+      error:
+	return err;
+}
+
+/*
+ * Receive a management frame from the device.
+ * This can be an arbitrary number of traps, and at most one response
+ * frame for a previous request sent via islpci_mgt_transmit().
+ */
+int
+islpci_mgt_receive(struct net_device *ndev)
+{
+	islpci_private *priv = netdev_priv(ndev);
+	isl38xx_control_block *cb =
+	    (isl38xx_control_block *) priv->control_block;
+	u32 curr_frag;
+
+#if VERBOSE > SHOW_ERROR_MESSAGES
+	DEBUG(SHOW_FUNCTION_CALLS, "islpci_mgt_receive \n");
+#endif
+
+	/* Only once per interrupt, determine fragment range to
+	 * process.  This avoids an endless loop (i.e. lockup) if
+	 * frames come in faster than we can process them. */
+	curr_frag = le32_to_cpu(cb->device_curr_frag[ISL38XX_CB_RX_MGMTQ]);
+	barrier();
+
+	for (; priv->index_mgmt_rx < curr_frag; priv->index_mgmt_rx++) {
+		pimfor_header_t *header;
+		u32 index = priv->index_mgmt_rx % ISL38XX_CB_MGMT_QSIZE;
+		struct islpci_membuf *buf = &priv->mgmt_rx[index];
+		u16 frag_len;
+		int size;
+		struct islpci_mgmtframe *frame;
+
+		/* I have no idea (and no documentation) if flags != 0
+		 * is possible.  Drop the frame, reuse the buffer. */
+		if (le16_to_cpu(cb->rx_data_mgmt[index].flags) != 0) {
+			printk(KERN_WARNING "%s: unknown flags 0x%04x\n",
+			       ndev->name,
+			       le16_to_cpu(cb->rx_data_mgmt[index].flags));
+			continue;
+		}
+
+		/* The device only returns the size of the header(s) here. */
+		frag_len = le16_to_cpu(cb->rx_data_mgmt[index].size);
+
+		/*
+		 * We appear to have no way to tell the device the
+		 * size of a receive buffer.  Thus, if this check
+		 * triggers, we likely have kernel heap corruption. */
+		if (frag_len > MGMT_FRAME_SIZE) {
+			printk(KERN_WARNING
+				"%s: Bogus packet size of %d (%#x).\n",
+				ndev->name, frag_len, frag_len);
+			frag_len = MGMT_FRAME_SIZE;
+		}
+
+		/* Ensure the results of device DMA are visible to the CPU. */
+		pci_dma_sync_single(priv->pdev, buf->pci_addr,
+				    buf->size, PCI_DMA_FROMDEVICE);
+
+		/* Perform endianess conversion for PIMFOR header in-place. */
+		header = pimfor_decode_header(buf->mem, frag_len);
+		if (!header) {
+			printk(KERN_WARNING "%s: no PIMFOR header found\n",
+			       ndev->name);
+			continue;
+		}
+
+		/* The device ID from the PIMFOR packet received from
+		 * the MVC is always 0.  We forward a sensible device_id.
+		 * Not that anyone upstream would care... */
+		header->device_id = priv->ndev->ifindex;
+
+#if VERBOSE > SHOW_ERROR_MESSAGES
+		DEBUG(SHOW_PIMFOR_FRAMES,
+		      "PIMFOR: op %i, oid 0x%08x, device %i, flags 0x%x length 0x%x \n",
+		      header->operation, header->oid, header->device_id,
+		      header->flags, header->length);
+
+		/* display the buffer contents for debugging */
+		display_buffer((char *) header, PIMFOR_HEADER_SIZE);
+		display_buffer((char *) header + PIMFOR_HEADER_SIZE,
+			       header->length);
+#endif
+
+		/* nobody sends these */
+		if (header->flags & PIMFOR_FLAG_APPLIC_ORIGIN) {
+			printk(KERN_DEBUG
+			       "%s: errant PIMFOR application frame\n",
+			       ndev->name);
+			continue;
+		}
+
+		/* Determine frame size, skipping OID_INL_TUNNEL headers. */
+		size = PIMFOR_HEADER_SIZE + header->length;
+		frame = kmalloc(sizeof (struct islpci_mgmtframe) + size,
+				GFP_ATOMIC);
+		if (!frame) {
+			printk(KERN_WARNING
+			       "%s: Out of memory, cannot handle oid 0x%08x\n",
+			       ndev->name, header->oid);
+			continue;
+		}
+		frame->ndev = ndev;
+		memcpy(&frame->buf, header, size);
+		frame->header = (pimfor_header_t *) frame->buf;
+		frame->data = frame->buf + PIMFOR_HEADER_SIZE;
+
+#if VERBOSE > SHOW_ERROR_MESSAGES
+		DEBUG(SHOW_PIMFOR_FRAMES,
+		      "frame: header: %p, data: %p, size: %d\n",
+		      frame->header, frame->data, size);
+#endif
+
+		if (header->operation == PIMFOR_OP_TRAP) {
+#if VERBOSE > SHOW_ERROR_MESSAGES
+			printk(KERN_DEBUG
+			       "TRAP: oid 0x%x, device %i, flags 0x%x length %i\n",
+			       header->oid, header->device_id, header->flags,
+			       header->length);
+#endif
+
+			/* Create work to handle trap out of interrupt
+			 * context. */
+			INIT_WORK(&frame->ws, prism54_process_trap, frame);
+			schedule_work(&frame->ws);
+
+		} else {
+			/* Signal the one waiting process that a response
+			 * has been received. */
+			if ((frame = xchg(&priv->mgmt_received, frame)) != NULL) {
+				printk(KERN_WARNING
+				       "%s: mgmt response not collected\n",
+				       ndev->name);
+				kfree(frame);
+			}
+#if VERBOSE > SHOW_ERROR_MESSAGES
+			DEBUG(SHOW_TRACING, "Wake up Mgmt Queue\n");
+#endif
+			wake_up(&priv->mgmt_wqueue);
+		}
+
+	}
+
+	return 0;
+}
+
+/*
+ * Cleanup the transmit queue by freeing all frames handled by the device.
+ */
+void
+islpci_mgt_cleanup_transmit(struct net_device *ndev)
+{
+	islpci_private *priv = netdev_priv(ndev);
+	isl38xx_control_block *cb =	/* volatile not needed */
+	    (isl38xx_control_block *) priv->control_block;
+	u32 curr_frag;
+
+#if VERBOSE > SHOW_ERROR_MESSAGES
+	DEBUG(SHOW_FUNCTION_CALLS, "islpci_mgt_cleanup_transmit\n");
+#endif
+
+	/* Only once per cleanup, determine fragment range to
+	 * process.  This avoids an endless loop (i.e. lockup) if
+	 * the device became confused, incrementing device_curr_frag
+	 * rapidly. */
+	curr_frag = le32_to_cpu(cb->device_curr_frag[ISL38XX_CB_TX_MGMTQ]);
+	barrier();
+
+	for (; priv->index_mgmt_tx < curr_frag; priv->index_mgmt_tx++) {
+		int index = priv->index_mgmt_tx % ISL38XX_CB_MGMT_QSIZE;
+		struct islpci_membuf *buf = &priv->mgmt_tx[index];
+		pci_unmap_single(priv->pdev, buf->pci_addr, buf->size,
+				 PCI_DMA_TODEVICE);
+		buf->pci_addr = 0;
+		kfree(buf->mem);
+		buf->mem = NULL;
+		buf->size = 0;
+	}
+}
+
+/*
+ * Perform one request-response transaction to the device.
+ */
+int
+islpci_mgt_transaction(struct net_device *ndev,
+		       int operation, unsigned long oid,
+		       void *senddata, int sendlen,
+		       struct islpci_mgmtframe **recvframe)
+{
+	islpci_private *priv = netdev_priv(ndev);
+	const long wait_cycle_jiffies = (ISL38XX_WAIT_CYCLE * 10 * HZ) / 1000;
+	long timeout_left = ISL38XX_MAX_WAIT_CYCLES * wait_cycle_jiffies;
+	int err;
+	DEFINE_WAIT(wait);
+
+	*recvframe = NULL;
+
+	if (down_interruptible(&priv->mgmt_sem))
+		return -ERESTARTSYS;
+
+	prepare_to_wait(&priv->mgmt_wqueue, &wait, TASK_UNINTERRUPTIBLE);
+	err = islpci_mgt_transmit(ndev, operation, oid, senddata, sendlen);
+	if (err)
+		goto out;
+
+	err = -ETIMEDOUT;
+	while (timeout_left > 0) {
+		int timeleft;
+		struct islpci_mgmtframe *frame;
+
+		timeleft = schedule_timeout(wait_cycle_jiffies);
+		frame = xchg(&priv->mgmt_received, NULL);
+		if (frame) {
+			if (frame->header->oid == oid) {
+				*recvframe = frame;
+				err = 0;
+				goto out;
+			} else {
+				printk(KERN_DEBUG
+				       "%s: expecting oid 0x%x, received 0x%x.\n",
+				       ndev->name, (unsigned int) oid,
+				       frame->header->oid);
+				kfree(frame);
+				frame = NULL;
+			}
+		}
+		if (timeleft == 0) {
+			printk(KERN_DEBUG
+				"%s: timeout waiting for mgmt response %lu, "
+				"triggering device\n",
+				ndev->name, timeout_left);
+			islpci_trigger(priv);
+		}
+		timeout_left += timeleft - wait_cycle_jiffies;
+	}
+	printk(KERN_WARNING "%s: timeout waiting for mgmt response\n",
+	       ndev->name);
+
+	/* TODO: we should reset the device here */     
+ out:
+	finish_wait(&priv->mgmt_wqueue, &wait);
+	up(&priv->mgmt_sem);
+	return err;
+}
+
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/net/wireless/prism54/islpci_mgt.h linux-2.4.28-pre3/drivers/net/wireless/prism54/islpci_mgt.h
--- linux-2.4.27/drivers/net/wireless/prism54/islpci_mgt.h	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.28-pre3/drivers/net/wireless/prism54/islpci_mgt.h	2004-09-10 19:36:59.000000000 +0000
@@ -0,0 +1,147 @@
+/*
+ *  
+ *  Copyright (C) 2002 Intersil Americas Inc.
+ *  Copyright (C) 2003 Luis R. Rodriguez <mcgrof@ruslug.rutgers.edu>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License
+ *
+ *  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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef _ISLPCI_MGT_H
+#define _ISLPCI_MGT_H
+
+#include <linux/wireless.h>
+#include <linux/skbuff.h>
+
+/*
+ *  Function definitions
+ */
+
+#define K_DEBUG(f, m, args...) do { if(f & m) printk(KERN_DEBUG args); } while(0)
+#define DEBUG(f, args...) K_DEBUG(f, pc_debug, args)
+
+#define TRACE(devname)   K_DEBUG(SHOW_TRACING, VERBOSE, "%s:  -> " __FUNCTION__ "()\n", devname)
+
+extern int pc_debug;
+#define init_wds 0	/* help compiler optimize away dead code */
+
+
+/* General driver definitions */
+#define PCIDEVICE_LATENCY_TIMER_MIN 		0x40
+#define PCIDEVICE_LATENCY_TIMER_VAL 		0x50
+
+/* Debugging verbose definitions */
+#define SHOW_NOTHING                            0x00	/* overrules everything */
+#define SHOW_ANYTHING                           0xFF
+#define SHOW_ERROR_MESSAGES                     0x01
+#define SHOW_TRAPS                              0x02
+#define SHOW_FUNCTION_CALLS                     0x04
+#define SHOW_TRACING                            0x08
+#define SHOW_QUEUE_INDEXES                      0x10
+#define SHOW_PIMFOR_FRAMES                      0x20
+#define SHOW_BUFFER_CONTENTS                    0x40
+#define VERBOSE                                 0x01
+
+/* Default card definitions */
+#define CARD_DEFAULT_CHANNEL                    6
+#define CARD_DEFAULT_MODE                       INL_MODE_CLIENT
+#define CARD_DEFAULT_IW_MODE			IW_MODE_INFRA
+#define CARD_DEFAULT_BSSTYPE                    DOT11_BSSTYPE_INFRA
+#define CARD_DEFAULT_CLIENT_SSID		""
+#define CARD_DEFAULT_AP_SSID			"default"
+#define CARD_DEFAULT_KEY1                       "default_key_1"
+#define CARD_DEFAULT_KEY2                       "default_key_2"
+#define CARD_DEFAULT_KEY3                       "default_key_3"
+#define CARD_DEFAULT_KEY4                       "default_key_4"
+#define CARD_DEFAULT_WEP                        0
+#define CARD_DEFAULT_FILTER                     0
+#define CARD_DEFAULT_WDS                        0
+#define	CARD_DEFAULT_AUTHEN                     DOT11_AUTH_OS
+#define	CARD_DEFAULT_DOT1X			0
+#define CARD_DEFAULT_MLME_MODE			DOT11_MLME_AUTO
+#define CARD_DEFAULT_CONFORMANCE                OID_INL_CONFORMANCE_NONE
+#define CARD_DEFAULT_PROFILE			DOT11_PROFILE_MIXED_G_WIFI
+#define CARD_DEFAULT_MAXFRAMEBURST		DOT11_MAXFRAMEBURST_MIXED_SAFE
+
+/* PIMFOR package definitions */
+#define PIMFOR_ETHERTYPE                        0x8828
+#define PIMFOR_HEADER_SIZE                      12
+#define PIMFOR_VERSION                          1
+#define PIMFOR_OP_GET                           0
+#define PIMFOR_OP_SET                           1
+#define PIMFOR_OP_RESPONSE                      2
+#define PIMFOR_OP_ERROR                         3
+#define PIMFOR_OP_TRAP                          4
+#define PIMFOR_OP_RESERVED                      5	/* till 255 */
+#define PIMFOR_DEV_ID_MHLI_MIB                  0
+#define PIMFOR_FLAG_APPLIC_ORIGIN               0x01
+#define PIMFOR_FLAG_LITTLE_ENDIAN               0x02
+
+static inline void
+add_le32p(u32 * le_number, u32 add)
+{
+	*le_number = cpu_to_le32(le32_to_cpup(le_number) + add);
+}
+
+void display_buffer(char *, int);
+
+/*
+ *  Type definition section
+ *
+ *  the structure defines only the header allowing copyless
+ *  frame handling
+ */
+typedef struct {
+	u8 version;
+	u8 operation;
+	u32 oid;
+	u8 device_id;
+	u8 flags;
+	u32 length;
+} __attribute__ ((packed))
+pimfor_header_t;
+
+/* A received and interrupt-processed management frame, either for
+ * schedule_work(prism54_process_trap) or for priv->mgmt_received,
+ * processed by islpci_mgt_transaction(). */
+struct islpci_mgmtframe {
+	struct net_device *ndev;      /* pointer to network device */
+	pimfor_header_t *header;      /* payload header, points into buf */
+	void *data;		      /* payload ex header, points into buf */
+        struct work_struct ws;	      /* argument for schedule_work() */
+	char buf[0];		      /* fragment buffer */
+};
+
+int
+islpci_mgt_receive(struct net_device *ndev);
+
+int
+islpci_mgmt_rx_fill(struct net_device *ndev);
+
+void
+islpci_mgt_cleanup_transmit(struct net_device *ndev);
+
+int
+islpci_mgt_transaction(struct net_device *ndev,
+                       int operation, unsigned long oid,
+		       void *senddata, int sendlen,
+		       struct islpci_mgmtframe **recvframe);
+
+static inline void
+islpci_mgt_release(struct islpci_mgmtframe *frame)
+{
+        kfree(frame);
+}
+
+#endif				/* _ISLPCI_MGT_H */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/net/wireless/prism54/oid_mgt.c linux-2.4.28-pre3/drivers/net/wireless/prism54/oid_mgt.c
--- linux-2.4.27/drivers/net/wireless/prism54/oid_mgt.c	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.28-pre3/drivers/net/wireless/prism54/oid_mgt.c	2004-09-10 19:34:09.000000000 +0000
@@ -0,0 +1,811 @@
+/*   
+ *  Copyright (C) 2003,2004 Aurelien Alleaume <slts@free.fr>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License
+ *
+ *  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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include "prismcompat.h"
+#include "islpci_dev.h"
+#include "islpci_mgt.h"
+#include "isl_oid.h"
+#include "oid_mgt.h"
+#include "isl_ioctl.h"
+
+/* to convert between channel and freq */
+const int frequency_list_bg[] = { 2412, 2417, 2422, 2427, 2432, 2437, 2442,
+	2447, 2452, 2457, 2462, 2467, 2472, 2484
+};
+
+int
+channel_of_freq(int f)
+{
+	int c = 0;
+
+	if ((f >= 2412) && (f <= 2484)) {
+		while ((c < 14) && (f != frequency_list_bg[c]))
+			c++;
+		return (c >= 14) ? 0 : ++c;
+	} else if ((f >= (int) 5000) && (f <= (int) 6000)) {
+		return ( (f - 5000) / 5 );
+	} else
+		return 0;
+}
+
+#define OID_STRUCT(name,oid,s,t) [name] = {oid, 0, sizeof(s), t}
+#define OID_STRUCT_C(name,oid,s,t) OID_STRUCT(name,oid,s,t | OID_FLAG_CACHED)
+#define OID_U32(name,oid) OID_STRUCT(name,oid,u32,OID_TYPE_U32)
+#define OID_U32_C(name,oid) OID_STRUCT_C(name,oid,u32,OID_TYPE_U32)
+#define OID_STRUCT_MLME(name,oid) OID_STRUCT(name,oid,struct obj_mlme,OID_TYPE_MLME)
+#define OID_STRUCT_MLMEEX(name,oid) OID_STRUCT(name,oid,struct obj_mlmeex,OID_TYPE_MLMEEX)
+
+#define OID_UNKNOWN(name,oid) OID_STRUCT(name,oid,0,0)
+
+struct oid_t isl_oid[] = {
+	OID_STRUCT(GEN_OID_MACADDRESS, 0x00000000, u8[6], OID_TYPE_ADDR),
+	OID_U32(GEN_OID_LINKSTATE, 0x00000001),
+	OID_UNKNOWN(GEN_OID_WATCHDOG, 0x00000002),
+	OID_UNKNOWN(GEN_OID_MIBOP, 0x00000003),
+	OID_UNKNOWN(GEN_OID_OPTIONS, 0x00000004),
+	OID_UNKNOWN(GEN_OID_LEDCONFIG, 0x00000005),
+
+	/* 802.11 */
+	OID_U32_C(DOT11_OID_BSSTYPE, 0x10000000),
+	OID_STRUCT_C(DOT11_OID_BSSID, 0x10000001, u8[6], OID_TYPE_RAW),
+	OID_STRUCT_C(DOT11_OID_SSID, 0x10000002, struct obj_ssid,
+		     OID_TYPE_SSID),
+	OID_U32(DOT11_OID_STATE, 0x10000003),
+	OID_U32(DOT11_OID_AID, 0x10000004),
+	OID_STRUCT(DOT11_OID_COUNTRYSTRING, 0x10000005, u8[4], OID_TYPE_RAW),
+	OID_STRUCT_C(DOT11_OID_SSIDOVERRIDE, 0x10000006, struct obj_ssid,
+		     OID_TYPE_SSID),
+
+	OID_U32(DOT11_OID_MEDIUMLIMIT, 0x11000000),
+	OID_U32_C(DOT11_OID_BEACONPERIOD, 0x11000001),
+	OID_U32(DOT11_OID_DTIMPERIOD, 0x11000002),
+	OID_U32(DOT11_OID_ATIMWINDOW, 0x11000003),
+	OID_U32(DOT11_OID_LISTENINTERVAL, 0x11000004),
+	OID_U32(DOT11_OID_CFPPERIOD, 0x11000005),
+	OID_U32(DOT11_OID_CFPDURATION, 0x11000006),
+
+	OID_U32_C(DOT11_OID_AUTHENABLE, 0x12000000),
+	OID_U32_C(DOT11_OID_PRIVACYINVOKED, 0x12000001),
+	OID_U32_C(DOT11_OID_EXUNENCRYPTED, 0x12000002),
+	OID_U32_C(DOT11_OID_DEFKEYID, 0x12000003),
+	[DOT11_OID_DEFKEYX] = {0x12000004, 3, sizeof (struct obj_key),
+			       OID_FLAG_CACHED | OID_TYPE_KEY},	/* DOT11_OID_DEFKEY1,...DOT11_OID_DEFKEY4 */
+	OID_UNKNOWN(DOT11_OID_STAKEY, 0x12000008),
+	OID_U32(DOT11_OID_REKEYTHRESHOLD, 0x12000009),
+	OID_UNKNOWN(DOT11_OID_STASC, 0x1200000a),
+
+	OID_U32(DOT11_OID_PRIVTXREJECTED, 0x1a000000),
+	OID_U32(DOT11_OID_PRIVRXPLAIN, 0x1a000001),
+	OID_U32(DOT11_OID_PRIVRXFAILED, 0x1a000002),
+	OID_U32(DOT11_OID_PRIVRXNOKEY, 0x1a000003),
+
+	OID_U32_C(DOT11_OID_RTSTHRESH, 0x13000000),
+	OID_U32_C(DOT11_OID_FRAGTHRESH, 0x13000001),
+	OID_U32_C(DOT11_OID_SHORTRETRIES, 0x13000002),
+	OID_U32_C(DOT11_OID_LONGRETRIES, 0x13000003),
+	OID_U32_C(DOT11_OID_MAXTXLIFETIME, 0x13000004),
+	OID_U32(DOT11_OID_MAXRXLIFETIME, 0x13000005),
+	OID_U32(DOT11_OID_AUTHRESPTIMEOUT, 0x13000006),
+	OID_U32(DOT11_OID_ASSOCRESPTIMEOUT, 0x13000007),
+
+	OID_UNKNOWN(DOT11_OID_ALOFT_TABLE, 0x1d000000),
+	OID_UNKNOWN(DOT11_OID_ALOFT_CTRL_TABLE, 0x1d000001),
+	OID_UNKNOWN(DOT11_OID_ALOFT_RETREAT, 0x1d000002),
+	OID_UNKNOWN(DOT11_OID_ALOFT_PROGRESS, 0x1d000003),
+	OID_U32(DOT11_OID_ALOFT_FIXEDRATE, 0x1d000004),
+	OID_UNKNOWN(DOT11_OID_ALOFT_RSSIGRAPH, 0x1d000005),
+	OID_UNKNOWN(DOT11_OID_ALOFT_CONFIG, 0x1d000006),
+
+	[DOT11_OID_VDCFX] = {0x1b000000, 7, 0, 0},
+	OID_U32(DOT11_OID_MAXFRAMEBURST, 0x1b000008),
+
+	OID_U32(DOT11_OID_PSM, 0x14000000),
+	OID_U32(DOT11_OID_CAMTIMEOUT, 0x14000001),
+	OID_U32(DOT11_OID_RECEIVEDTIMS, 0x14000002),
+	OID_U32(DOT11_OID_ROAMPREFERENCE, 0x14000003),
+
+	OID_U32(DOT11_OID_BRIDGELOCAL, 0x15000000),
+	OID_U32(DOT11_OID_CLIENTS, 0x15000001),
+	OID_U32(DOT11_OID_CLIENTSASSOCIATED, 0x15000002),
+	[DOT11_OID_CLIENTX] = {0x15000003, 2006, 0, 0},	/* DOT11_OID_CLIENTX,...DOT11_OID_CLIENT2007 */
+
+	OID_STRUCT(DOT11_OID_CLIENTFIND, 0x150007DB, u8[6], OID_TYPE_ADDR),
+	OID_STRUCT(DOT11_OID_WDSLINKADD, 0x150007DC, u8[6], OID_TYPE_ADDR),
+	OID_STRUCT(DOT11_OID_WDSLINKREMOVE, 0x150007DD, u8[6], OID_TYPE_ADDR),
+	OID_STRUCT(DOT11_OID_EAPAUTHSTA, 0x150007DE, u8[6], OID_TYPE_ADDR),
+	OID_STRUCT(DOT11_OID_EAPUNAUTHSTA, 0x150007DF, u8[6], OID_TYPE_ADDR),
+	OID_U32_C(DOT11_OID_DOT1XENABLE, 0x150007E0),
+	OID_UNKNOWN(DOT11_OID_MICFAILURE, 0x150007E1),
+	OID_UNKNOWN(DOT11_OID_REKEYINDICATE, 0x150007E2),
+
+	OID_U32(DOT11_OID_MPDUTXSUCCESSFUL, 0x16000000),
+	OID_U32(DOT11_OID_MPDUTXONERETRY, 0x16000001),
+	OID_U32(DOT11_OID_MPDUTXMULTIPLERETRIES, 0x16000002),
+	OID_U32(DOT11_OID_MPDUTXFAILED, 0x16000003),
+	OID_U32(DOT11_OID_MPDURXSUCCESSFUL, 0x16000004),
+	OID_U32(DOT11_OID_MPDURXDUPS, 0x16000005),
+	OID_U32(DOT11_OID_RTSSUCCESSFUL, 0x16000006),
+	OID_U32(DOT11_OID_RTSFAILED, 0x16000007),
+	OID_U32(DOT11_OID_ACKFAILED, 0x16000008),
+	OID_U32(DOT11_OID_FRAMERECEIVES, 0x16000009),
+	OID_U32(DOT11_OID_FRAMEERRORS, 0x1600000A),
+	OID_U32(DOT11_OID_FRAMEABORTS, 0x1600000B),
+	OID_U32(DOT11_OID_FRAMEABORTSPHY, 0x1600000C),
+
+	OID_U32(DOT11_OID_SLOTTIME, 0x17000000),
+	OID_U32(DOT11_OID_CWMIN, 0x17000001),
+	OID_U32(DOT11_OID_CWMAX, 0x17000002),
+	OID_U32(DOT11_OID_ACKWINDOW, 0x17000003),
+	OID_U32(DOT11_OID_ANTENNARX, 0x17000004),
+	OID_U32(DOT11_OID_ANTENNATX, 0x17000005),
+	OID_U32(DOT11_OID_ANTENNADIVERSITY, 0x17000006),
+	OID_U32_C(DOT11_OID_CHANNEL, 0x17000007),
+	OID_U32_C(DOT11_OID_EDTHRESHOLD, 0x17000008),
+	OID_U32(DOT11_OID_PREAMBLESETTINGS, 0x17000009),
+	OID_STRUCT(DOT11_OID_RATES, 0x1700000A, u8[IWMAX_BITRATES + 1],
+		   OID_TYPE_RAW),
+	OID_U32(DOT11_OID_CCAMODESUPPORTED, 0x1700000B),
+	OID_U32(DOT11_OID_CCAMODE, 0x1700000C),
+	OID_UNKNOWN(DOT11_OID_RSSIVECTOR, 0x1700000D),
+	OID_UNKNOWN(DOT11_OID_OUTPUTPOWERTABLE, 0x1700000E),
+	OID_U32(DOT11_OID_OUTPUTPOWER, 0x1700000F),
+	OID_STRUCT(DOT11_OID_SUPPORTEDRATES, 0x17000010,
+		   u8[IWMAX_BITRATES + 1], OID_TYPE_RAW),
+	OID_U32_C(DOT11_OID_FREQUENCY, 0x17000011),
+	[DOT11_OID_SUPPORTEDFREQUENCIES] =
+	    {0x17000012, 0, sizeof (struct obj_frequencies)
+	     + sizeof (u16) * IWMAX_FREQ, OID_TYPE_FREQUENCIES},
+
+	OID_U32(DOT11_OID_NOISEFLOOR, 0x17000013),
+	OID_STRUCT(DOT11_OID_FREQUENCYACTIVITY, 0x17000014, u8[IWMAX_FREQ + 1],
+		   OID_TYPE_RAW),
+	OID_UNKNOWN(DOT11_OID_IQCALIBRATIONTABLE, 0x17000015),
+	OID_U32(DOT11_OID_NONERPPROTECTION, 0x17000016),
+	OID_U32(DOT11_OID_SLOTSETTINGS, 0x17000017),
+	OID_U32(DOT11_OID_NONERPTIMEOUT, 0x17000018),
+	OID_U32(DOT11_OID_PROFILES, 0x17000019),
+	OID_STRUCT(DOT11_OID_EXTENDEDRATES, 0x17000020,
+		   u8[IWMAX_BITRATES + 1], OID_TYPE_RAW),
+
+	OID_STRUCT_MLME(DOT11_OID_DEAUTHENTICATE, 0x18000000),
+	OID_STRUCT_MLME(DOT11_OID_AUTHENTICATE, 0x18000001),
+	OID_STRUCT_MLME(DOT11_OID_DISASSOCIATE, 0x18000002),
+	OID_STRUCT_MLME(DOT11_OID_ASSOCIATE, 0x18000003),
+	OID_UNKNOWN(DOT11_OID_SCAN, 0x18000004),
+	OID_STRUCT_MLMEEX(DOT11_OID_BEACON, 0x18000005),
+	OID_STRUCT_MLMEEX(DOT11_OID_PROBE, 0x18000006),
+	OID_STRUCT_MLMEEX(DOT11_OID_DEAUTHENTICATEEX, 0x18000007),
+	OID_STRUCT_MLMEEX(DOT11_OID_AUTHENTICATEEX, 0x18000008),
+	OID_STRUCT_MLMEEX(DOT11_OID_DISASSOCIATEEX, 0x18000009),
+	OID_STRUCT_MLMEEX(DOT11_OID_ASSOCIATEEX, 0x1800000A),
+	OID_STRUCT_MLMEEX(DOT11_OID_REASSOCIATE, 0x1800000B),
+	OID_STRUCT_MLMEEX(DOT11_OID_REASSOCIATEEX, 0x1800000C),
+
+	OID_U32(DOT11_OID_NONERPSTATUS, 0x1E000000),
+
+	OID_U32(DOT11_OID_STATIMEOUT, 0x19000000),
+	OID_U32_C(DOT11_OID_MLMEAUTOLEVEL, 0x19000001),
+	OID_U32(DOT11_OID_BSSTIMEOUT, 0x19000002),
+	OID_UNKNOWN(DOT11_OID_ATTACHMENT, 0x19000003),
+	OID_STRUCT_C(DOT11_OID_PSMBUFFER, 0x19000004, struct obj_buffer,
+		     OID_TYPE_BUFFER),
+
+	OID_U32(DOT11_OID_BSSS, 0x1C000000),
+	[DOT11_OID_BSSX] = {0x1C000001, 63, sizeof (struct obj_bss),
+			    OID_TYPE_BSS},	/*DOT11_OID_BSS1,...,DOT11_OID_BSS64 */
+	OID_STRUCT(DOT11_OID_BSSFIND, 0x1C000042, struct obj_bss, OID_TYPE_BSS),
+	[DOT11_OID_BSSLIST] = {0x1C000043, 0, sizeof (struct
+						      obj_bsslist) +
+			       sizeof (struct obj_bss[IWMAX_BSS]),
+			       OID_TYPE_BSSLIST},
+
+	OID_UNKNOWN(OID_INL_TUNNEL, 0xFF020000),
+	OID_UNKNOWN(OID_INL_MEMADDR, 0xFF020001),
+	OID_UNKNOWN(OID_INL_MEMORY, 0xFF020002),
+	OID_U32_C(OID_INL_MODE, 0xFF020003),
+	OID_UNKNOWN(OID_INL_COMPONENT_NR, 0xFF020004),
+	OID_STRUCT(OID_INL_VERSION, 0xFF020005, u8[8], OID_TYPE_RAW),
+	OID_UNKNOWN(OID_INL_INTERFACE_ID, 0xFF020006),
+	OID_UNKNOWN(OID_INL_COMPONENT_ID, 0xFF020007),
+	OID_U32_C(OID_INL_CONFIG, 0xFF020008),
+	OID_U32_C(OID_INL_DOT11D_CONFORMANCE, 0xFF02000C),
+	OID_U32(OID_INL_PHYCAPABILITIES, 0xFF02000D),
+	OID_U32_C(OID_INL_OUTPUTPOWER, 0xFF02000F),
+
+};
+
+int
+mgt_init(islpci_private *priv)
+{
+	int i;
+
+	priv->mib = kmalloc(OID_NUM_LAST * sizeof (void *), GFP_KERNEL);
+	if (!priv->mib)
+		return -ENOMEM;
+
+	memset(priv->mib, 0, OID_NUM_LAST * sizeof (void *));
+
+	/* Alloc the cache */
+	for (i = 0; i < OID_NUM_LAST; i++) {
+		if (isl_oid[i].flags & OID_FLAG_CACHED) {
+			priv->mib[i] = kmalloc(isl_oid[i].size *
+					       (isl_oid[i].range + 1),
+					       GFP_KERNEL);
+			if (!priv->mib[i])
+				return -ENOMEM;
+			memset(priv->mib[i], 0,
+			       isl_oid[i].size * (isl_oid[i].range + 1));
+		} else
+			priv->mib[i] = NULL;
+	}
+
+	init_rwsem(&priv->mib_sem);
+	prism54_mib_init(priv);
+
+	return 0;
+}
+
+void
+mgt_clean(islpci_private *priv)
+{
+	int i;
+
+	if (!priv->mib)
+		return;
+	for (i = 0; i < OID_NUM_LAST; i++)
+		if (priv->mib[i]) {
+			kfree(priv->mib[i]);
+			priv->mib[i] = NULL;
+		}
+	kfree(priv->mib);
+	priv->mib = NULL;
+}
+
+void
+mgt_le_to_cpu(int type, void *data)
+{
+	switch (type) {
+	case OID_TYPE_U32:
+		*(u32 *) data = le32_to_cpu(*(u32 *) data);
+		break;
+	case OID_TYPE_BUFFER:{
+			struct obj_buffer *buff = data;
+			buff->size = le32_to_cpu(buff->size);
+			buff->addr = le32_to_cpu(buff->addr);
+			break;
+		}
+	case OID_TYPE_BSS:{
+			struct obj_bss *bss = data;
+			bss->age = le16_to_cpu(bss->age);
+			bss->channel = le16_to_cpu(bss->channel);
+			bss->capinfo = le16_to_cpu(bss->capinfo);
+			bss->rates = le16_to_cpu(bss->rates);
+			bss->basic_rates = le16_to_cpu(bss->basic_rates);
+			break;
+		}
+	case OID_TYPE_BSSLIST:{
+			struct obj_bsslist *list = data;
+			int i;
+			list->nr = le32_to_cpu(list->nr);
+			for (i = 0; i < list->nr; i++)
+				mgt_le_to_cpu(OID_TYPE_BSS, &list->bsslist[i]);
+			break;
+		}
+	case OID_TYPE_FREQUENCIES:{
+			struct obj_frequencies *freq = data;
+			int i;
+			freq->nr = le16_to_cpu(freq->nr);
+			for (i = 0; i < freq->nr; i++)
+				freq->mhz[i] = le16_to_cpu(freq->mhz[i]);
+			break;
+		}
+	case OID_TYPE_MLME:{
+			struct obj_mlme *mlme = data;
+			mlme->id = le16_to_cpu(mlme->id);
+			mlme->state = le16_to_cpu(mlme->state);
+			mlme->code = le16_to_cpu(mlme->code);
+			break;
+		}
+	case OID_TYPE_MLMEEX:{
+			struct obj_mlmeex *mlme = data;
+			mlme->id = le16_to_cpu(mlme->id);
+			mlme->state = le16_to_cpu(mlme->state);
+			mlme->code = le16_to_cpu(mlme->code);
+			mlme->size = le16_to_cpu(mlme->size);
+			break;
+		}
+	case OID_TYPE_SSID:
+	case OID_TYPE_KEY:
+	case OID_TYPE_ADDR:
+	case OID_TYPE_RAW:
+		break;
+	default:
+		BUG();
+	}
+}
+
+static void
+mgt_cpu_to_le(int type, void *data)
+{
+	switch (type) {
+	case OID_TYPE_U32:
+		*(u32 *) data = cpu_to_le32(*(u32 *) data);
+		break;
+	case OID_TYPE_BUFFER:{
+			struct obj_buffer *buff = data;
+			buff->size = cpu_to_le32(buff->size);
+			buff->addr = cpu_to_le32(buff->addr);
+			break;
+		}
+	case OID_TYPE_BSS:{
+			struct obj_bss *bss = data;
+			bss->age = cpu_to_le16(bss->age);
+			bss->channel = cpu_to_le16(bss->channel);
+			bss->capinfo = cpu_to_le16(bss->capinfo);
+			bss->rates = cpu_to_le16(bss->rates);
+			bss->basic_rates = cpu_to_le16(bss->basic_rates);
+			break;
+		}
+	case OID_TYPE_BSSLIST:{
+			struct obj_bsslist *list = data;
+			int i;
+			list->nr = cpu_to_le32(list->nr);
+			for (i = 0; i < list->nr; i++)
+				mgt_cpu_to_le(OID_TYPE_BSS, &list->bsslist[i]);
+			break;
+		}
+	case OID_TYPE_FREQUENCIES:{
+			struct obj_frequencies *freq = data;
+			int i;
+			freq->nr = cpu_to_le16(freq->nr);
+			for (i = 0; i < freq->nr; i++)
+				freq->mhz[i] = cpu_to_le16(freq->mhz[i]);
+			break;
+		}
+	case OID_TYPE_MLME:{
+			struct obj_mlme *mlme = data;
+			mlme->id = cpu_to_le16(mlme->id);
+			mlme->state = cpu_to_le16(mlme->state);
+			mlme->code = cpu_to_le16(mlme->code);
+			break;
+		}
+	case OID_TYPE_MLMEEX:{
+			struct obj_mlmeex *mlme = data;
+			mlme->id = cpu_to_le16(mlme->id);
+			mlme->state = cpu_to_le16(mlme->state);
+			mlme->code = cpu_to_le16(mlme->code);
+			mlme->size = cpu_to_le16(mlme->size);
+			break;
+		}
+	case OID_TYPE_SSID:
+	case OID_TYPE_KEY:
+	case OID_TYPE_ADDR:
+	case OID_TYPE_RAW:
+		break;
+	default:
+		BUG();
+	}
+}
+
+/* Note : data is modified during this function */
+
+int
+mgt_set_request(islpci_private *priv, enum oid_num_t n, int extra, void *data)
+{
+	int ret = 0;
+	struct islpci_mgmtframe *response = NULL;
+	int response_op = PIMFOR_OP_ERROR;
+	int dlen;
+	void *cache, *_data = data;
+	u32 oid;
+
+	BUG_ON(OID_NUM_LAST <= n);
+	BUG_ON(extra > isl_oid[n].range);
+
+	if (!priv->mib)
+		/* memory has been freed */
+		return -1;
+
+	dlen = isl_oid[n].size;
+	cache = priv->mib[n];
+	cache += (cache ? extra * dlen : 0);
+	oid = isl_oid[n].oid + extra;
+
+	if (_data == NULL)
+		/* we are requested to re-set a cached value */
+		_data = cache;
+	else
+		mgt_cpu_to_le(isl_oid[n].flags & OID_FLAG_TYPE, _data);
+	/* If we are going to write to the cache, we don't want anyone to read
+	 * it -> acquire write lock.
+	 * Else we could acquire a read lock to be sure we don't bother the
+	 * commit process (which takes a write lock). But I'm not sure if it's
+	 * needed.
+	 */
+	if (cache)
+		down_write(&priv->mib_sem);
+
+	if (islpci_get_state(priv) >= PRV_STATE_READY) {
+		ret = islpci_mgt_transaction(priv->ndev, PIMFOR_OP_SET, oid,
+					     _data, dlen, &response);
+		if (!ret) {
+			response_op = response->header->operation;
+			islpci_mgt_release(response);
+		}
+		if (ret || response_op == PIMFOR_OP_ERROR)
+			ret = -EIO;
+	} else if (!cache)
+		ret = -EIO;
+
+	if (cache) {
+		if (!ret && data)
+			memcpy(cache, _data, dlen);
+		up_write(&priv->mib_sem);
+	}
+
+	/* re-set given data to what it was */
+	if (data)
+		mgt_le_to_cpu(isl_oid[n].flags & OID_FLAG_TYPE, data);
+
+	return ret;
+}
+
+int
+mgt_get_request(islpci_private *priv, enum oid_num_t n, int extra, void *data,
+		union oid_res_t *res)
+{
+
+	int ret = -EIO;
+	int reslen = 0;
+	struct islpci_mgmtframe *response = NULL;
+
+	int dlen;
+	void *cache, *_res = NULL;
+	u32 oid;
+
+	BUG_ON(OID_NUM_LAST <= n);
+	BUG_ON(extra > isl_oid[n].range);
+
+	res->ptr = NULL;
+
+	if (!priv->mib)
+		/* memory has been freed */
+		return -1;
+
+	dlen = isl_oid[n].size;
+	cache = priv->mib[n];
+	cache += cache ? extra * dlen : 0;
+	oid = isl_oid[n].oid + extra;
+	reslen = dlen;
+
+	if (cache)
+		down_read(&priv->mib_sem);
+
+	if (islpci_get_state(priv) >= PRV_STATE_READY) {
+		ret = islpci_mgt_transaction(priv->ndev, PIMFOR_OP_GET,
+					     oid, data, dlen, &response);
+		if (ret || !response ||
+		    response->header->operation == PIMFOR_OP_ERROR) {
+			if (response)
+				islpci_mgt_release(response);
+			ret = -EIO;
+		}
+		if (!ret) {
+			_res = response->data;
+			reslen = response->header->length;
+		}
+	} else if (cache) {
+		_res = cache;
+		ret = 0;
+	}
+	if ((isl_oid[n].flags & OID_FLAG_TYPE) == OID_TYPE_U32)
+		res->u = ret ? 0 : le32_to_cpu(*(u32 *) _res);
+	else {
+		res->ptr = kmalloc(reslen, GFP_KERNEL);
+		BUG_ON(res->ptr == NULL);
+		if (ret)
+			memset(res->ptr, 0, reslen);
+		else {
+			memcpy(res->ptr, _res, reslen);
+			mgt_le_to_cpu(isl_oid[n].flags & OID_FLAG_TYPE,
+				      res->ptr);
+		}
+	}
+	if (cache)
+		up_read(&priv->mib_sem);
+
+	if (response && !ret)
+		islpci_mgt_release(response);
+
+	if (reslen > isl_oid[n].size)
+		printk(KERN_DEBUG
+		       "mgt_get_request(0x%x): received data length was bigger "
+		       "than expected (%d > %d). Memory is probably corrupted...",
+		       oid, reslen, isl_oid[n].size);
+
+	return ret;
+}
+
+/* lock outside */
+int
+mgt_commit_list(islpci_private *priv, enum oid_num_t *l, int n)
+{
+	int i, ret = 0;
+	struct islpci_mgmtframe *response;
+
+	for (i = 0; i < n; i++) {
+		struct oid_t *t = &(isl_oid[l[i]]);
+		void *data = priv->mib[l[i]];
+		int j = 0;
+		u32 oid = t->oid;
+		BUG_ON(data == NULL);
+		while (j <= t->range) {
+			response = NULL;
+			ret |= islpci_mgt_transaction(priv->ndev, PIMFOR_OP_SET,
+						      oid, data, t->size,
+						      &response);
+			if (response) {
+				ret |= (response->header->operation ==
+					PIMFOR_OP_ERROR);
+				islpci_mgt_release(response);
+			}
+			j++;
+			oid++;
+			data += t->size;
+		}
+	}
+	return ret;
+}
+
+/* Lock outside */
+
+void
+mgt_set(islpci_private *priv, enum oid_num_t n, void *data)
+{
+	BUG_ON(OID_NUM_LAST <= n);
+	BUG_ON(priv->mib[n] == NULL);
+
+	memcpy(priv->mib[n], data, isl_oid[n].size);
+	mgt_cpu_to_le(isl_oid[n].flags & OID_FLAG_TYPE, priv->mib[n]);
+}
+
+void
+mgt_get(islpci_private *priv, enum oid_num_t n, void *res)
+{
+	BUG_ON(OID_NUM_LAST <= n);
+	BUG_ON(priv->mib[n] == NULL);
+	BUG_ON(res == NULL);
+
+	memcpy(res, priv->mib[n], isl_oid[n].size);
+	mgt_le_to_cpu(isl_oid[n].flags & OID_FLAG_TYPE, res);
+}
+
+/* Commits the cache. Lock outside. */
+
+static enum oid_num_t commit_part1[] = {
+	OID_INL_CONFIG,
+	OID_INL_MODE,
+	DOT11_OID_BSSTYPE,
+	DOT11_OID_CHANNEL,
+	DOT11_OID_MLMEAUTOLEVEL
+};
+
+static enum oid_num_t commit_part2[] = {
+	DOT11_OID_SSID,
+	DOT11_OID_PSMBUFFER,
+	DOT11_OID_AUTHENABLE,
+	DOT11_OID_PRIVACYINVOKED,
+	DOT11_OID_EXUNENCRYPTED,
+	DOT11_OID_DEFKEYX,	/* MULTIPLE */
+	DOT11_OID_DEFKEYID,
+	DOT11_OID_DOT1XENABLE,
+	OID_INL_DOT11D_CONFORMANCE,
+	/* Do not initialize this - fw < 1.0.4.3 rejects it
+	OID_INL_OUTPUTPOWER,
+	*/
+};
+
+/* update the MAC addr. */
+static int
+mgt_update_addr(islpci_private *priv)
+{
+	struct islpci_mgmtframe *res = NULL;
+	int ret;
+
+	ret = islpci_mgt_transaction(priv->ndev, PIMFOR_OP_GET,
+				     isl_oid[GEN_OID_MACADDRESS].oid, NULL,
+				     isl_oid[GEN_OID_MACADDRESS].size, &res);
+
+	if ((ret == 0) && res && (res->header->operation != PIMFOR_OP_ERROR))
+		memcpy(priv->ndev->dev_addr, res->data, 6);
+	else
+		ret = -EIO;
+	if (res)
+		islpci_mgt_release(res);
+
+	return ret;
+}
+
+void
+mgt_commit(islpci_private *priv)
+{
+	int rvalue;
+	u32 u;
+
+	if (islpci_get_state(priv) < PRV_STATE_INIT)
+		return;
+
+	rvalue = mgt_commit_list(priv, commit_part1,
+				 sizeof (commit_part1) /
+				 sizeof (commit_part1[0]));
+
+	if (priv->iw_mode != IW_MODE_MONITOR)
+		rvalue |= mgt_commit_list(priv, commit_part2,
+					  sizeof (commit_part2) /
+					  sizeof (commit_part2[0]));
+
+	u = OID_INL_MODE;
+	rvalue |= mgt_commit_list(priv, &u, 1);
+	rvalue |= mgt_update_addr(priv);
+
+	if (rvalue) {
+		/* some request have failed. The device might be in an
+		   incoherent state. We should reset it ! */
+		printk(KERN_DEBUG "%s: mgt_commit has failed. Restart the "
+		       "device \n", priv->ndev->name);
+	}
+}
+
+/* This will tell you if you are allowed to answer a mlme(ex) request .*/
+
+int
+mgt_mlme_answer(islpci_private *priv)
+{
+	u32 mlmeautolevel;
+	/* Acquire a read lock because if we are in a mode change, it's
+	 * possible to answer true, while the card is leaving master to managed
+	 * mode. Answering to a mlme in this situation could hang the card.
+	 */
+	down_read(&priv->mib_sem);
+	mlmeautolevel =
+	    le32_to_cpu(*(u32 *) priv->mib[DOT11_OID_MLMEAUTOLEVEL]);
+	up_read(&priv->mib_sem);
+
+	return ((priv->iw_mode == IW_MODE_MASTER) &&
+		(mlmeautolevel >= DOT11_MLME_INTERMEDIATE));
+}
+
+enum oid_num_t
+mgt_oidtonum(u32 oid)
+{
+	int i;
+
+	for (i = 0; i < OID_NUM_LAST; i++)
+		if (isl_oid[i].oid == oid)
+			return i;
+
+	printk(KERN_DEBUG "looking for an unknown oid 0x%x", oid);
+
+	return OID_NUM_LAST;
+}
+
+int
+mgt_response_to_str(enum oid_num_t n, union oid_res_t *r, char *str)
+{
+	switch (isl_oid[n].flags & OID_FLAG_TYPE) {
+	case OID_TYPE_U32:
+		return snprintf(str, PRIV_STR_SIZE, "%u\n", r->u);
+		break;
+	case OID_TYPE_BUFFER:{
+			struct obj_buffer *buff = r->ptr;
+			return snprintf(str, PRIV_STR_SIZE,
+					"size=%u\naddr=0x%X\n", buff->size,
+					buff->addr);
+		}
+		break;
+	case OID_TYPE_BSS:{
+			struct obj_bss *bss = r->ptr;
+			return snprintf(str, PRIV_STR_SIZE,
+					"age=%u\nchannel=%u\n"
+					"capinfo=0x%X\nrates=0x%X\n"
+					"basic_rates=0x%X\n", bss->age,
+					bss->channel, bss->capinfo,
+					bss->rates, bss->basic_rates);
+		}
+		break;
+	case OID_TYPE_BSSLIST:{
+			struct obj_bsslist *list = r->ptr;
+			int i, k;
+			k = snprintf(str, PRIV_STR_SIZE, "nr=%u\n", list->nr);
+			for (i = 0; i < list->nr; i++)
+				k += snprintf(str + k, PRIV_STR_SIZE - k,
+					      "bss[%u] : \nage=%u\nchannel=%u\n"
+					      "capinfo=0x%X\nrates=0x%X\n"
+					      "basic_rates=0x%X\n",
+					      i, list->bsslist[i].age,
+					      list->bsslist[i].channel,
+					      list->bsslist[i].capinfo,
+					      list->bsslist[i].rates,
+					      list->bsslist[i].basic_rates);
+			return k;
+		}
+		break;
+	case OID_TYPE_FREQUENCIES:{
+			struct obj_frequencies *freq = r->ptr;
+			int i, t;
+			printk("nr : %u\n", freq->nr);
+			t = snprintf(str, PRIV_STR_SIZE, "nr=%u\n", freq->nr);
+			for (i = 0; i < freq->nr; i++)
+				t += snprintf(str + t, PRIV_STR_SIZE - t,
+					      "mhz[%u]=%u\n", i, freq->mhz[i]);
+			return t;
+		}
+		break;
+	case OID_TYPE_MLME:{
+			struct obj_mlme *mlme = r->ptr;
+			return snprintf(str, PRIV_STR_SIZE,
+					"id=0x%X\nstate=0x%X\ncode=0x%X\n",
+					mlme->id, mlme->state, mlme->code);
+		}
+		break;
+	case OID_TYPE_MLMEEX:{
+			struct obj_mlmeex *mlme = r->ptr;
+			return snprintf(str, PRIV_STR_SIZE,
+					"id=0x%X\nstate=0x%X\n"
+					"code=0x%X\nsize=0x%X\n", mlme->id,
+					mlme->state, mlme->code, mlme->size);
+		}
+		break;
+	case OID_TYPE_SSID:{
+			struct obj_ssid *ssid = r->ptr;
+			return snprintf(str, PRIV_STR_SIZE,
+					"length=%u\noctets=%.*s\n",
+					ssid->length, ssid->length,
+					ssid->octets);
+		}
+		break;
+	case OID_TYPE_KEY:{
+			struct obj_key *key = r->ptr;
+			int t, i;
+			t = snprintf(str, PRIV_STR_SIZE,
+				     "type=0x%X\nlength=0x%X\nkey=0x",
+				     key->type, key->length);
+			for (i = 0; i < key->length; i++)
+				t += snprintf(str + t, PRIV_STR_SIZE - t,
+					      "%02X:", key->key[i]);
+			t += snprintf(str + t, PRIV_STR_SIZE - t, "\n");
+			return t;
+		}
+		break;
+	case OID_TYPE_RAW:
+	case OID_TYPE_ADDR:{
+			unsigned char *buff = r->ptr;
+			int t, i;
+			t = snprintf(str, PRIV_STR_SIZE, "hex data=");
+			for (i = 0; i < isl_oid[n].size; i++)
+				t += snprintf(str + t, PRIV_STR_SIZE - t,
+					      "%02X:", buff[i]);
+			t += snprintf(str + t, PRIV_STR_SIZE - t, "\n");
+			return t;
+		}
+		break;
+	default:
+		BUG();
+	}
+	return 0;
+}
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/net/wireless/prism54/oid_mgt.h linux-2.4.28-pre3/drivers/net/wireless/prism54/oid_mgt.h
--- linux-2.4.27/drivers/net/wireless/prism54/oid_mgt.h	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.28-pre3/drivers/net/wireless/prism54/oid_mgt.h	2004-09-10 19:34:00.000000000 +0000
@@ -0,0 +1,58 @@
+/*
+ *  Copyright (C) 2003 Aurelien Alleaume <slts@free.fr>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License
+ *
+ *  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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#if !defined(_OID_MGT_H)
+#define _OID_MGT_H
+
+#include "isl_oid.h"
+#include "islpci_dev.h"
+
+extern struct oid_t isl_oid[];
+
+int mgt_init(islpci_private *);
+
+void mgt_clean(islpci_private *);
+
+/* I don't know where to put these 3 */
+extern const int frequency_list_bg[];
+extern const int frequency_list_a[];
+int channel_of_freq(int);
+
+void mgt_le_to_cpu(int, void *);
+
+int mgt_set_request(islpci_private *, enum oid_num_t, int, void *);
+
+int mgt_get_request(islpci_private *, enum oid_num_t, int, void *,
+		    union oid_res_t *);
+
+int mgt_commit_list(islpci_private *, enum oid_num_t *, int);
+
+void mgt_set(islpci_private *, enum oid_num_t, void *);
+
+void mgt_get(islpci_private *, enum oid_num_t, void *);
+
+void mgt_commit(islpci_private *);
+
+int mgt_mlme_answer(islpci_private *);
+
+enum oid_num_t mgt_oidtonum(u32 oid);
+
+int mgt_response_to_str(enum oid_num_t, union oid_res_t *, char *);
+
+#endif				/* !defined(_OID_MGT_H) */
+/* EOF */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/net/wireless/prism54/prismcompat.h linux-2.4.28-pre3/drivers/net/wireless/prism54/prismcompat.h
--- linux-2.4.27/drivers/net/wireless/prism54/prismcompat.h	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.28-pre3/drivers/net/wireless/prism54/prismcompat.h	2004-09-10 19:32:17.000000000 +0000
@@ -0,0 +1,46 @@
+/*  
+ *  (C) 2004 Margit Schubert-While <margitsw@t-online.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 of the License
+ *
+ *  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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+/*  
+ *	Compatibility header file to aid support of different kernel versions
+ */
+
+#ifdef PRISM54_COMPAT24
+#include "prismcompat24.h"
+#else	/* PRISM54_COMPAT24 */
+
+#ifndef _PRISM_COMPAT_H
+#define _PRISM_COMPAT_H
+
+#include <linux/device.h>
+#include <linux/firmware.h>
+#include <linux/config.h>
+#include <linux/moduleparam.h>
+#include <linux/workqueue.h>
+#include <linux/compiler.h>
+
+#if !defined(CONFIG_FW_LOADER) && !defined(CONFIG_FW_LOADER_MODULE)
+#error Firmware Loading is not configured in the kernel !
+#endif
+
+#define prism54_synchronize_irq(irq) synchronize_irq(irq)
+
+#define PRISM_FW_PDEV		&priv->pdev->dev
+
+#endif				/* _PRISM_COMPAT_H */
+#endif				/* PRISM54_COMPAT24 */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/net/wireless/prism54/prismcompat24.h linux-2.4.28-pre3/drivers/net/wireless/prism54/prismcompat24.h
--- linux-2.4.27/drivers/net/wireless/prism54/prismcompat24.h	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.28-pre3/drivers/net/wireless/prism54/prismcompat24.h	2004-09-10 19:33:15.000000000 +0000
@@ -0,0 +1,72 @@
+/*  
+ *  (C) 2004 Margit Schubert-While <margitsw@t-online.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 of the License
+ *
+ *  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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+/*  
+ *	Compatibility header file to aid support of different kernel versions
+ */
+
+#ifndef _PRISM_COMPAT_H
+#define _PRISM_COMPAT_H
+
+#include <linux/firmware.h>
+#include <linux/config.h>
+#include <linux/tqueue.h>
+#include <linux/version.h>
+#include <linux/compiler.h>
+#include <linux/netdevice.h>
+#include <asm/uaccess.h>
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,25)
+#define module_param(x, y, z)	MODULE_PARM(x, "i")
+#else
+#include <linux/moduleparam.h>
+#endif
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,23)
+#define free_netdev(x)		kfree(x)
+#define pci_name(x)		x->slot_name
+#define irqreturn_t		void
+#define IRQ_HANDLED
+#define IRQ_NONE
+#else
+#include <linux/interrupt.h>
+#endif
+
+#define work_struct		tq_struct
+#define INIT_WORK		INIT_TQUEUE
+#define schedule_work		schedule_task
+
+#if !defined(HAVE_NETDEV_PRIV)
+#define netdev_priv(x)		(x)->priv
+#endif
+
+#if !defined(CONFIG_FW_LOADER) && !defined(CONFIG_FW_LOADER_MODULE)
+#error Firmware Loading is not configured in the kernel !
+#endif
+
+#define prism54_synchronize_irq(irq) synchronize_irq()
+
+#define DEFINE_WAIT(y)			DECLARE_WAITQUEUE(y, current)
+#define prepare_to_wait(x, y, z)	set_current_state(z); \
+					add_wait_queue(x, y)
+#define finish_wait(x, y)		remove_wait_queue(x, y); \
+					set_current_state(TASK_RUNNING)
+
+#define PRISM_FW_PDEV		pci_name(priv->pdev)
+
+#endif				/* _PRISM_COMPAT_H */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/parport/parport_pc.c linux-2.4.28-pre3/drivers/parport/parport_pc.c
--- linux-2.4.27/drivers/parport/parport_pc.c	2004-08-07 23:26:05.000000000 +0000
+++ linux-2.4.28-pre3/drivers/parport/parport_pc.c	2004-09-10 19:34:29.000000000 +0000
@@ -266,95 +266,6 @@ static void parport_pc_interrupt(int irq
 	parport_generic_irq(irq, (struct parport *) dev_id, regs);
 }
 
-void parport_pc_write_data(struct parport *p, unsigned char d)
-{
-	outb (d, DATA (p));
-}
-
-unsigned char parport_pc_read_data(struct parport *p)
-{
-	return inb (DATA (p));
-}
-
-void parport_pc_write_control(struct parport *p, unsigned char d)
-{
-	const unsigned char wm = (PARPORT_CONTROL_STROBE |
-				  PARPORT_CONTROL_AUTOFD |
-				  PARPORT_CONTROL_INIT |
-				  PARPORT_CONTROL_SELECT);
-
-	/* Take this out when drivers have adapted to the newer interface. */
-	if (d & 0x20) {
-		printk (KERN_DEBUG "%s (%s): use data_reverse for this!\n",
-			p->name, p->cad->name);
-		parport_pc_data_reverse (p);
-	}
-
-	__parport_pc_frob_control (p, wm, d & wm);
-}
-
-unsigned char parport_pc_read_control(struct parport *p)
-{
-	const unsigned char wm = (PARPORT_CONTROL_STROBE |
-				  PARPORT_CONTROL_AUTOFD |
-				  PARPORT_CONTROL_INIT |
-				  PARPORT_CONTROL_SELECT);
-	const struct parport_pc_private *priv = p->physport->private_data;
-	return priv->ctr & wm; /* Use soft copy */
-}
-
-unsigned char parport_pc_frob_control (struct parport *p, unsigned char mask,
-				       unsigned char val)
-{
-	const unsigned char wm = (PARPORT_CONTROL_STROBE |
-				  PARPORT_CONTROL_AUTOFD |
-				  PARPORT_CONTROL_INIT |
-				  PARPORT_CONTROL_SELECT);
-
-	/* Take this out when drivers have adapted to the newer interface. */
-	if (mask & 0x20) {
-		printk (KERN_DEBUG "%s (%s): use data_%s for this!\n",
-			p->name, p->cad->name,
-			(val & 0x20) ? "reverse" : "forward");
-		if (val & 0x20)
-			parport_pc_data_reverse (p);
-		else
-			parport_pc_data_forward (p);
-	}
-
-	/* Restrict mask and val to control lines. */
-	mask &= wm;
-	val &= wm;
-
-	return __parport_pc_frob_control (p, mask, val);
-}
-
-unsigned char parport_pc_read_status(struct parport *p)
-{
-	return inb (STATUS (p));
-}
-
-void parport_pc_disable_irq(struct parport *p)
-{
-	__parport_pc_frob_control (p, 0x10, 0);
-}
-
-void parport_pc_enable_irq(struct parport *p)
-{
-	if (p->irq != PARPORT_IRQ_NONE)
-		__parport_pc_frob_control (p, 0x10, 0x10);
-}
-
-void parport_pc_data_forward (struct parport *p)
-{
-	__parport_pc_frob_control (p, 0x20, 0);
-}
-
-void parport_pc_data_reverse (struct parport *p)
-{
-	__parport_pc_frob_control (p, 0x20, 0x20);
-}
-
 void parport_pc_init_state(struct pardevice *dev, struct parport_state *s)
 {
 	s->u.pc.ctr = 0xc;
@@ -414,7 +325,8 @@ static size_t parport_pc_epp_read_data (
 				left -= 16;
 			} else {
 				/* grab single byte from the warp fifo */
-				*((char *)buf)++ = inb (EPPDATA (port));
+				*((char *)buf) = inb (EPPDATA (port));
+				buf++;
 				got++;
 				left--;
 			}
@@ -441,7 +353,8 @@ static size_t parport_pc_epp_read_data (
 		return length;
 	}
 	for (; got < length; got++) {
-		*((char*)buf)++ = inb (EPPDATA(port));
+		*((char*)buf) = inb (EPPDATA(port));
+		buf++;
 		if (inb (STATUS (port)) & 0x01) {
 			/* EPP timeout */
 			clear_epp_timeout (port);
@@ -470,7 +383,8 @@ static size_t parport_pc_epp_write_data 
 		return length;
 	}
 	for (; written < length; written++) {
-		outb (*((char*)buf)++, EPPDATA(port));
+		outb (*((char*)buf), EPPDATA(port));
+		buf++;
 		if (inb (STATUS(port)) & 0x01) {
 			clear_epp_timeout (port);
 			break;
@@ -494,7 +408,8 @@ static size_t parport_pc_epp_read_addr (
 		return length;
 	}
 	for (; got < length; got++) {
-		*((char*)buf)++ = inb (EPPADDR (port));
+		*((char*)buf) = inb (EPPADDR (port));
+		buf++;
 		if (inb (STATUS (port)) & 0x01) {
 			clear_epp_timeout (port);
 			break;
@@ -519,7 +434,8 @@ static size_t parport_pc_epp_write_addr 
 		return length;
 	}
 	for (; written < length; written++) {
-		outb (*((char*)buf)++, EPPADDR (port));
+		outb (*((char*)buf), EPPADDR (port));
+		buf++;
 		if (inb (STATUS (port)) & 0x01) {
 			clear_epp_timeout (port);
 			break;
@@ -2692,6 +2608,7 @@ enum parport_pc_pci_cards {
 	syba_2p_epp,
 	syba_1p_ecp,
 	titan_010l,
+	titan_1284p1,
 	titan_1284p2,
 	avlab_1p,
 	avlab_2p,
@@ -2763,6 +2680,7 @@ static struct parport_pc_pci {
 	/* syba_2p_epp AP138B */	{ 2, { { 0, 0x078 }, { 0, 0x178 }, } },
 	/* syba_1p_ecp W83787 */	{ 1, { { 0, 0x078 }, } },
 	/* titan_010l */		{ 1, { { 3, -1 }, } },
+	/* titan_1284p1 */              { 1, { { 0, 1 }, } },
 	/* titan_1284p2 */		{ 2, { { 0, 1 }, { 2, 3 }, } },
 	/* avlab_1p		*/	{ 1, { { 0, 1}, } },
 	/* avlab_2p		*/	{ 2, { { 0, 1}, { 2, 3 },} },
@@ -2834,6 +2752,7 @@ static struct pci_device_id parport_pc_p
 	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, syba_1p_ecp },
 	{ PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_010L,
 	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, titan_010l },
+	{ 0x9710, 0x9805, 0x1000, 0x0010, 0, 0, titan_1284p1 },
 	{ 0x9710, 0x9815, 0x1000, 0x0020, 0, 0, titan_1284p2 },
 	/* PCI_VENDOR_ID_AVLAB/Intek21 has another bunch of cards ...*/
 	{ 0x14db, 0x2120, PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_1p}, /* AFAVLAB_TK9902 */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/pci/pci.c linux-2.4.28-pre3/drivers/pci/pci.c
--- linux-2.4.27/drivers/pci/pci.c	2004-08-07 23:26:05.000000000 +0000
+++ linux-2.4.28-pre3/drivers/pci/pci.c	2004-09-10 19:33:31.000000000 +0000
@@ -1238,6 +1238,8 @@ struct pci_bus * __devinit pci_add_new_b
 	 * Allocate a new bus, and inherit stuff from the parent..
 	 */
 	child = pci_alloc_bus();
+	if (!child)
+		return NULL;
 
 	list_add_tail(&child->node, &parent->children);
 	child->self = dev;
@@ -1291,7 +1293,11 @@ static int __devinit pci_scan_bridge(str
 		 */
 		if (pass)
 			return max;
+
 		child = pci_add_new_bus(bus, dev, 0);
+		if (!child)
+			return max;
+
 		child->primary = buses & 0xFF;
 		child->secondary = (buses >> 8) & 0xFF;
 		child->subordinate = (buses >> 16) & 0xFF;
@@ -1316,6 +1322,9 @@ static int __devinit pci_scan_bridge(str
 		pci_write_config_word(dev, PCI_STATUS, 0xffff);
 
 		child = pci_add_new_bus(bus, dev, ++max);
+		if (!child)
+			return max;
+
 		buses = (buses & 0xff000000)
 		      | ((unsigned int)(child->primary)     <<  0)
 		      | ((unsigned int)(child->secondary)   <<  8)
@@ -2214,7 +2223,6 @@ EXPORT_SYMBOL(pcibios_find_device);
 
 EXPORT_SYMBOL(isa_dma_bridge_buggy);
 EXPORT_SYMBOL(pci_pci_problems);
-EXPORT_SYMBOL(pciehp_msi_quirk);
 
 /* Pool allocator */
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/pci/quirks.c linux-2.4.28-pre3/drivers/pci/quirks.c
--- linux-2.4.27/drivers/pci/quirks.c	2004-08-07 23:26:05.000000000 +0000
+++ linux-2.4.28-pre3/drivers/pci/quirks.c	2004-09-10 19:32:07.000000000 +0000
@@ -719,13 +719,6 @@ static void __init asus_hides_smbus_lpc(
 	}
 }
 
-int pciehp_msi_quirk;
-
-static void __devinit quirk_pciehp_msi(struct pci_dev *pdev)
-{
-	pciehp_msi_quirk = 1;
-}
-
 /*
  *  The main table of quirks.
  */
@@ -815,8 +808,6 @@ static struct pci_fixup pci_fixups[] __i
 	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82801DB_0,	asus_hides_smbus_lpc },
 	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82801BA_0,	asus_hides_smbus_lpc },
 
-	{ PCI_FIXUP_FINAL,	PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_SMCH,  quirk_pciehp_msi },
-	
 	{ 0 }
 };
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/pcmcia/bulkmem.c linux-2.4.28-pre3/drivers/pcmcia/bulkmem.c
--- linux-2.4.27/drivers/pcmcia/bulkmem.c	2002-11-28 23:53:14.000000000 +0000
+++ linux-2.4.28-pre3/drivers/pcmcia/bulkmem.c	2004-09-10 19:37:29.000000000 +0000
@@ -301,7 +301,7 @@ int MTDHelperEntry(int func, void *a1, v
     {
 	window_handle_t w;
         int ret = pcmcia_request_window(a1, a2, &w);
-        (window_handle_t *)a1 = w;
+        a1 = w;
 	return  ret;
     }
         break;
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/pcmcia/i82365.c linux-2.4.28-pre3/drivers/pcmcia/i82365.c
--- linux-2.4.27/drivers/pcmcia/i82365.c	2003-11-28 18:26:20.000000000 +0000
+++ linux-2.4.28-pre3/drivers/pcmcia/i82365.c	2004-09-10 19:36:43.000000000 +0000
@@ -63,7 +63,6 @@
 #include "cirrus.h"
 #include "vg468.h"
 #include "ricoh.h"
-#include "o2micro.h"
 
 #ifdef PCMCIA_DEBUG
 static int pc_debug = PCMCIA_DEBUG;
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/pcmcia/o2micro.h linux-2.4.28-pre3/drivers/pcmcia/o2micro.h
--- linux-2.4.27/drivers/pcmcia/o2micro.h	2002-11-28 23:53:14.000000000 +0000
+++ linux-2.4.28-pre3/drivers/pcmcia/o2micro.h	2004-09-10 19:36:30.000000000 +0000
@@ -120,4 +120,36 @@
 #define  O2_MODE_E_LED_OUT	0x08
 #define  O2_MODE_E_SKTA_ACTV	0x10
 
+static int o2micro_open(pci_socket_t *socket)
+{
+	/*
+	 * 'reserved' register at 0x94/D4. chaning it to 0xCA (8 bit) enables
+	 * read prefetching which for example makes the RME Hammerfall DSP
+	 * working. for some bridges it is at 0x94, for others at 0xD4. it's
+	 * ok to write to both registers on all O2 bridges.
+	 * from Eric Still, 02Micro.
+	 */
+	if (PCI_FUNC(socket->dev->devfn) == 0) {
+		config_writeb(socket, 0x94, 0xCA);
+		config_writeb(socket, 0xD4, 0xCA);
+	}
+
+	return 0;
+}
+
+static struct pci_socket_ops o2micro_ops = {
+	o2micro_open,
+	yenta_close,
+	yenta_init,
+	yenta_suspend,
+	yenta_get_status,
+	yenta_get_socket,
+	yenta_set_socket,
+	yenta_get_io_map,
+	yenta_set_io_map,
+	yenta_get_mem_map,
+	yenta_set_mem_map,
+	yenta_proc_setup
+};
+
 #endif /* _LINUX_O2MICRO_H */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/pcmcia/ti113x.h linux-2.4.28-pre3/drivers/pcmcia/ti113x.h
--- linux-2.4.27/drivers/pcmcia/ti113x.h	2003-08-25 11:44:42.000000000 +0000
+++ linux-2.4.28-pre3/drivers/pcmcia/ti113x.h	2004-09-10 19:34:01.000000000 +0000
@@ -134,6 +134,10 @@
 /* ExCA IO offset registers */
 #define TI113X_IO_OFFSET(map)		(0x36+((map)<<1))
 
+/* EnE test register */
+#define ENE_TEST_C9			0xc9	/* 8bit */
+#define ENE_TEST_C9_TLTENABLE		0x02
+
 #ifdef CONFIG_CARDBUS
 
 /*
@@ -155,6 +159,17 @@ static int ti_open(pci_socket_t *socket)
 	new = reg & ~I365_INTR_ENA;
 	if (new != reg)
 		exca_writeb(socket, I365_INTCTL, new);
+
+	/*
+	 * for EnE bridges only: clear testbit TLTEnable. this makes the
+	 * RME Hammerfall DSP sound card working.
+	 */
+	if (socket->dev->vendor == PCI_VENDOR_ID_ENE) {
+		u8 test_c9 = config_readb(socket, ENE_TEST_C9);
+		test_c9 &= ~ENE_TEST_C9_TLTENABLE;
+		config_writeb(socket, ENE_TEST_C9, test_c9);
+	}
+
 	return 0;
 }
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/pcmcia/yenta.c linux-2.4.28-pre3/drivers/pcmcia/yenta.c
--- linux-2.4.27/drivers/pcmcia/yenta.c	2004-08-07 23:26:05.000000000 +0000
+++ linux-2.4.28-pre3/drivers/pcmcia/yenta.c	2004-09-10 19:35:29.000000000 +0000
@@ -845,6 +845,7 @@ static void yenta_close(pci_socket_t *so
 
 #include "ti113x.h"
 #include "ricoh.h"
+#include "o2micro.h"
 
 /*
  * Different cardbus controllers have slightly different
@@ -880,6 +881,8 @@ static struct cardbus_override_struct {
 	{ PD(ENE,1410),  &ti_ops },
 	{ PD(ENE,1420),  &ti_ops },
 
+	{ PCI_VENDOR_ID_O2, PCI_ANY_ID, &o2micro_ops },
+
 	{ PD(RICOH,RL5C465), &ricoh_ops },
 	{ PD(RICOH,RL5C466), &ricoh_ops },
 	{ PD(RICOH,RL5C475), &ricoh_ops },
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/s390/Config.in linux-2.4.28-pre3/drivers/s390/Config.in
--- linux-2.4.27/drivers/s390/Config.in	2003-08-25 11:44:42.000000000 +0000
+++ linux-2.4.28-pre3/drivers/s390/Config.in	2004-09-10 19:33:49.000000000 +0000
@@ -88,6 +88,23 @@ if [ "$CONFIG_NET" = "y" ]; then
 	define_bool CONFIG_HOTPLUG y
     fi
 
+    if [ "$CONFIG_QDIO" != "n" -a "$CONFIG_CHANDEV" = "y" -a "$CONFIG_IP_MULTICAST" = "y" ]; then
+      dep_tristate 'Support for Gigabit Ethernet' CONFIG_QETH $CONFIG_QDIO
+      if [ "$CONFIG_QETH" != "n" ]; then
+        comment 'Gigabit Ethernet default settings'
+	if [ "$CONFIG_IPV6" = "y" -o "$CONFIG_IPV6" = "$CONFIG_QETH" ]; then
+		bool '   IPv6 support for qeth' CONFIG_QETH_IPV6
+	else
+		define_bool CONFIG_QETH_IPV6 n
+	fi
+	if [ "$CONFIG_VLAN_8021Q" = "y" -o "$CONFIG_VLAN_8021Q" = "$CONFIG_QETH" ]; then
+		bool '   VLAN support for qeth' CONFIG_QETH_VLAN
+	else
+		define_bool CONFIG_QETH_VLAN n
+	fi
+        bool '   Performance statistics in /proc' CONFIG_QETH_PERF_STATS
+      fi
+    fi
     tristate 'CTC device support' CONFIG_CTC
     tristate 'IUCV device support (VM only)' CONFIG_IUCV
   fi
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/s390/Makefile linux-2.4.28-pre3/drivers/s390/Makefile
--- linux-2.4.27/drivers/s390/Makefile	2003-06-13 14:51:35.000000000 +0000
+++ linux-2.4.28-pre3/drivers/s390/Makefile	2004-09-10 19:34:52.000000000 +0000
@@ -9,6 +9,8 @@ subdir-m := $(subdir-y)
 
 obj-y := s390io.o s390mach.o s390dyn.o ccwcache.o sysinfo.o
 export-objs += ccwcache.o s390dyn.o s390io.o
+obj-$(CONFIG_QDIO) += qdio.o
+export-objs += qdio.o
 
 obj-y += $(foreach dir,$(subdir-y),$(dir)/s390-$(dir).o)
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/s390/block/dasd.c linux-2.4.28-pre3/drivers/s390/block/dasd.c
--- linux-2.4.27/drivers/s390/block/dasd.c	2004-08-07 23:26:05.000000000 +0000
+++ linux-2.4.28-pre3/drivers/s390/block/dasd.c	2004-09-10 19:34:38.000000000 +0000
@@ -6,7 +6,7 @@
  * Bugreports.to..: <Linux390@de.ibm.com>
  * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999-2001
  *
- * $Revision: 1.311 $
+ * $Revision: 1.298.2.11 $
  *
  * History of changes (starts July 2000)
  * 11/09/00 complete redesign after code review
@@ -311,7 +311,7 @@ dasd_add_range (int from, int to, int fe
         /* and add the remaining subranges                                 */
 	for (start = index = from, end = -EINVAL; index <= to; index++) {
                 
-                if (dasd_devindex_from_devno(index) > 0) {
+                if (dasd_devindex_from_devno(index) >= 0) {
                         /* current device is already in range */
                         MESSAGE (KERN_DEBUG,
                                  "dasd_add_range %04x-%04x: "
@@ -3815,7 +3815,7 @@ dasd_oper_handler (int irq, devreg_t * d
 	}
 
         if (device &&
-            device->level >= DASD_STATE_READY) {
+            device->level >= DASD_STATE_NEW) {
                 s390irq_spin_lock_irqsave (device->devinfo.irq, 
                                            flags);
 		DEV_MESSAGE (KERN_DEBUG, device, "%s",
@@ -5188,6 +5188,7 @@ dasd_statistics_write (struct file *file
                          "/proc/dasd/statistics: only 'set' and "
                          "'reset' are supported verbs");
 
+		vfree (buffer);
         	return -EINVAL;
 	}
 
@@ -5243,6 +5244,7 @@ dasd_statistics_write (struct file *file
         
 
 #endif /* DASD_PROFILE */
+        vfree (buffer);
 	return user_len;
 }
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/s390/block/dasd_3990_erp.c linux-2.4.28-pre3/drivers/s390/block/dasd_3990_erp.c
--- linux-2.4.27/drivers/s390/block/dasd_3990_erp.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.28-pre3/drivers/s390/block/dasd_3990_erp.c	2004-09-10 19:36:32.000000000 +0000
@@ -5,7 +5,7 @@
  * Bugreports.to..: <Linux390@de.ibm.com>
  * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 2000, 2001
  *
- * $Revision: 1.52 $
+ * $Revision: 1.52.2.3 $
  *
  * History of changes:
  * 05/14/01 fixed PL030160GTO (BUG() in erp_action_5)
@@ -585,9 +585,8 @@ dasd_3990_erp_alternate_path (ccw_req_t 
                              ioinfo[irq]->opm);
 
 		/* reset status to queued to handle the request again... */
-		check_then_set (&erp->status,
-                                CQR_STATUS_ERROR,
-                                CQR_STATUS_QUEUED);
+		if (erp->status > CQR_STATUS_QUEUED)
+                        erp->status = CQR_STATUS_QUEUED;
 
                 erp->retries = 1;
                 
@@ -598,12 +597,10 @@ dasd_3990_erp_alternate_path (ccw_req_t 
                              "opm=%x) -> permanent error",
                              erp->dstat->lpum,
                              ioinfo[irq]->opm);
-                
-                /* post request with permanent error */
-                check_then_set (&erp->status,
-                                CQR_STATUS_ERROR,
-                                CQR_STATUS_FAILED);
 
+                /* post request with permanent error */
+		if (erp->status > CQR_STATUS_QUEUED)
+                        erp->status = CQR_STATUS_FAILED;
         }
         
 } /* end dasd_3990_erp_alternate_path */
@@ -768,7 +765,6 @@ dasd_3990_erp_action_4 (ccw_req_t *erp,
                                         CQR_STATUS_QUEUED);
                 }
         }
-
 	return erp;
 
 } /* end dasd_3990_erp_action_4 */
@@ -2386,7 +2382,7 @@ dasd_3990_erp_compound_code (ccw_req_t *
                 switch (sense[28]) {
                 case 0x17:
                         /* issue a Diagnostic Control command with an 
-                                * Inhibit Write subcommand and controler modifier */
+                         * Inhibit Write subcommand and controler modifier */
                         erp = dasd_3990_erp_DCTL (erp,
                                                   0x20);
                         break;
@@ -2699,7 +2695,8 @@ dasd_3990_erp_add_erp (ccw_req_t *cqr)
 	if (!erp) {
                 if (cqr->retries <= 0) {
                         DEV_MESSAGE (KERN_ERR, device, "%s",
-                                     "Unable to allocate ERP request (NO retries left)");
+                                     "Unable to allocate ERP request "
+                                     "(NO retries left)");
                 
                         check_then_set (&cqr->status,
                                         CQR_STATUS_ERROR,
@@ -2709,7 +2706,8 @@ dasd_3990_erp_add_erp (ccw_req_t *cqr)
 
                 } else {
                         DEV_MESSAGE (KERN_ERR, device,
-                                     "Unable to allocate ERP request (%i retries left)",
+                                     "Unable to allocate ERP request "
+                                     "(%i retries left)",
                                      cqr->retries);
                 
                         if (!timer_pending(&device->timer)) {
@@ -3169,8 +3167,9 @@ dasd_3990_erp_action (ccw_req_t *cqr)
                 dasd_chanq_enq_head (&device->queue,
                                      erp);
         } else {
-                if ((erp->status == CQR_STATUS_FILLED ) || (erp != device->queue.head)) {
-                        /* something strange happened - log the error and panic */
+                if ((erp->status == CQR_STATUS_FILLED ) ||
+                    (erp != device->queue.head)) {
+                        /* something strange happened - log error and panic */
                         /* print current erp_chain */
                         DEV_MESSAGE (KERN_DEBUG, device, "%s",
                                      "ERP chain at END of ERP-ACTION");
@@ -3188,7 +3187,8 @@ dasd_3990_erp_action (ccw_req_t *cqr)
                                                      temp_erp->refers);
                                 }
                         }
-                        panic ("Problems with ERP chain!!! Please report to linux390@de.ibm.com");
+                        panic ("Problems with ERP chain!!! "
+                               "Please report to linux390@de.ibm.com");
                 }
 
         }
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/s390/char/ctrlchar.c linux-2.4.28-pre3/drivers/s390/char/ctrlchar.c
--- linux-2.4.27/drivers/s390/char/ctrlchar.c	2003-08-25 11:44:42.000000000 +0000
+++ linux-2.4.28-pre3/drivers/s390/char/ctrlchar.c	2004-09-10 19:37:18.000000000 +0000
@@ -9,6 +9,7 @@
 
 #include <linux/config.h>
 #include <linux/stddef.h>
+#include <linux/errno.h>
 #include <linux/sysrq.h>
 #include <linux/ctype.h>
 #include <linux/interrupt.h>
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/s390/net/c7000.c linux-2.4.28-pre3/drivers/s390/net/c7000.c
--- linux-2.4.27/drivers/s390/net/c7000.c	2003-08-25 11:44:42.000000000 +0000
+++ linux-2.4.28-pre3/drivers/s390/net/c7000.c	2004-09-10 19:33:46.000000000 +0000
@@ -3,6 +3,20 @@
 	Author: Bob Scardapane (UTS Global LLC).
 	Version: 3.
 
+	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.
+
 	To use this driver, run the LINUX command:
 
 	insmod c7000 base0=0xYYYY lhost0=s1 uhost0=s2 lappl0=s3 uappl0=s4 dbg=x
@@ -409,16 +423,7 @@ static char	ifnames[MAX_C7000][8] = {"ci
 	One device structure per controller.
 */
 
-/* RBH Try out the new code for 2.4.0 */
-#define NEWSTUFF
-
-#ifdef NEWSTUFF
-#define STRUCT_NET_DEVICE struct net_device
-#else
-#define STRUCT_NET_DEVICE struct device
-#endif
-
-STRUCT_NET_DEVICE	c7000_devices[MAX_C7000];
+struct net_device	c7000_devices[MAX_C7000];
 
 /*
 	Scratch variable filled in with controller name.
@@ -432,6 +437,7 @@ static char	*controller;
 
 MODULE_AUTHOR("Robert Scardapane (UTS Global)");
 MODULE_DESCRIPTION("Network module for Cisco 7000 box.");
+MODULE_LICENSE("GPL");
 
 MODULE_PARM(base0, "1i");
 MODULE_PARM_DESC(base0, "Base unit address for 1st C7000 box.");
@@ -521,16 +527,12 @@ struct	c7000_unit {
 	ccw1_t				ccws[5];	/* control ccws */
 	int				devno;		/* device number */
 	int				irq;		/* subchannel number */
-	int				IO_active;	/* IO activity flag */
+	unsigned long			IO_active;	/* IO activity flag */
 	int				state;		/* fsm state */
 	int				retries;	/* retry counter */
 	unsigned long			flag_a;		/* bh activity flag */
 	devstat_t			devstat;	/* device status */
-#ifdef NEWSTUFF
 	wait_queue_head_t		wait;		/* sleep q head */
-#else
-	struct wait_queue		*wait;		/* sleep q pointer */
-#endif
 	struct c7000_controller		*cntlp;		/* controller pointer */
 	struct c7000_buffer		*free;		/* free buffer anchor */
 	struct c7000_buffer		*proc_head;	/* proc head */
@@ -551,7 +553,7 @@ struct	c7000_unit {
 
 struct c7000_controller {
 	struct	net_device_stats	stats;		/* statistics */
-	STRUCT_NET_DEVICE		*dev;		/* -> device struct */
+	struct net_device		*dev;		/* -> device struct */
 	unsigned int			base_addr;	/* base address */
 	char				lappl[NAMLEN];	/* local appl */
 	char				lhost[NAMLEN];	/* local host */
@@ -560,9 +562,7 @@ struct c7000_controller {
 	unsigned char			version;	/* version = 2 */
 	unsigned char			linkid;		/* link id */
 	struct	c7000_unit		cunits[NUNITS];	/* embedded units */
-#ifdef NEWSTUFF
-	int				tbusy;
-#endif
+	unsigned long			tbusy;
 };
 
 /*
@@ -579,62 +579,29 @@ struct	c7000_rd_header {
 	Set the device structure transmission busy flag.
 */
 
-#ifdef NEWSTUFF
 #define c7000_set_busy(dev) netif_stop_queue(dev)
-#else
-static __inline__ void
-c7000_set_busy(STRUCT_NET_DEVICE *dev)
-{
-	dev->tbusy = 1;
-	eieio();
-	return;
-}
-#endif
 	
 /*
 	Clear the device structure transmission busy flag.
 */
 
-#ifdef NEWSTUFF
 #define c7000_clear_busy(dev) netif_wake_queue(dev)
-#else
-static __inline__ void
-c7000_clear_busy(STRUCT_NET_DEVICE *dev)
-{
-	dev->tbusy = 0;
-	eieio();
-	return;
-}
-#endif
 
 /*
 	Extract the device structure transmission busy flag.
 */
 
-#ifdef NEWSTUFF
 #define c7000_check_busy(dev) netif_queue_stopped(dev)
-#else
-static __inline__ int
-c7000_check_busy(STRUCT_NET_DEVICE *dev)
-{
-	eieio();
-	return(dev->tbusy);
-}
-#endif
 
 /*
 	Set a bit in the device structure transmission busy flag.
 */
 
 static __inline__ void
-c7000_setbit_busy(int nr, STRUCT_NET_DEVICE *dev)
+c7000_setbit_busy(int nr, struct net_device *dev)
 {
-#ifdef NEWSTUFF
 	netif_stop_queue(dev);
 	test_and_set_bit(nr, &((struct c7000_controller *)dev->priv)->tbusy);
-#else
-	set_bit(nr, (void *)&dev->tbusy);
-#endif
 	return;
 }
 
@@ -643,14 +610,10 @@ c7000_setbit_busy(int nr, STRUCT_NET_DEV
 */
 
 static __inline__ void
-c7000_clearbit_busy(int nr, STRUCT_NET_DEVICE *dev)
+c7000_clearbit_busy(int nr, struct net_device *dev)
 {
-#ifdef NEWSTUFF
 	clear_bit(nr, &((struct c7000_controller *)dev->priv)->tbusy);
 	netif_wake_queue(dev);
-#else
-	clear_bit(nr, (void *)&dev->tbusy);
-#endif
 	return;
 }
 
@@ -659,14 +622,10 @@ c7000_clearbit_busy(int nr, STRUCT_NET_D
 */
 
 static __inline__ int
-c7000_ts_busy(int nr, STRUCT_NET_DEVICE *dev)
+c7000_ts_busy(int nr, struct net_device *dev)
 {
-#ifdef NEWSTUFF
 	netif_stop_queue(dev);
 	return test_and_set_bit(nr, &((struct c7000_controller *)dev->priv)->tbusy);
-#else
-	return(test_and_set_bit(nr, (void *)&dev->tbusy));
-#endif
 }
 
 /*
@@ -678,7 +637,7 @@ c7000_error(struct c7000_controller *ccp
 {
 	int			i;
 	struct	c7000_unit	*cup;
-	STRUCT_NET_DEVICE	*dev = ccp->dev;
+	struct net_device	*dev = ccp->dev;
 
 	for (i = 0; i < NUNITS; i++) {
 		cup = &ccp->cunits[i];
@@ -686,12 +645,8 @@ c7000_error(struct c7000_controller *ccp
 	}
 
 	if (dev != NULL)
-#ifdef NEWSTUFF
 		/* RBH XXX Should we be doing this? */
 		dev->state &= ~__LINK_STATE_START;
-#else
-		dev->flags &= ~IFF_RUNNING;
-#endif
 
 	CPrintk(0, "c7000: c7000_error: base unit 0x%x is down\n", ccp->base_addr);
 	return;
@@ -759,9 +714,9 @@ c7000_check_devices(int devno)
 static int
 c7000_haltio(struct c7000_unit *cup)
 {
-	__u32			parm;
+	unsigned long		parm;
 	__u8			flags = 0x00;
-	__u32			saveflags;
+	unsigned long		saveflags;
 	DECLARE_WAITQUEUE(wait, current);
 	int			rc;
 
@@ -792,9 +747,9 @@ c7000_haltio(struct c7000_unit *cup)
 static int
 c7000_doio(struct c7000_unit *cup)
 {
-	__u32			parm;
+	unsigned long		parm;
 	__u8			flags = 0x00;
-	__u32			saveflags;
+	unsigned long		saveflags;
 	DECLARE_WAITQUEUE(wait, current);
 	int			rc;
 
@@ -1013,7 +968,7 @@ c7000_bld_read_chpgm(struct c7000_unit *
 */
 
 static int
-c7000_alloc_buffers(STRUCT_NET_DEVICE *dev)
+c7000_alloc_buffers(struct net_device *dev)
 {
 	int				i;
 	int				j;
@@ -1030,9 +985,10 @@ c7000_alloc_buffers(STRUCT_NET_DEVICE *d
 			bufptr = kmalloc(sizeof(struct c7000_buffer), GFP_KERNEL);
 			data = kmalloc(C7000_BUFSIZE, GFP_KERNEL);
 
-			if (bufptr == NULL)
-			{
-				if(data)
+			if (bufptr == NULL || data == NULL) {
+				if (bufptr)
+					kfree(bufptr);
+				if (data)
 					kfree(data);
 				return(-1);
 			}
@@ -1088,7 +1044,7 @@ c7000_free_chain(struct c7000_buffer *bu
 */
 
 static void
-c7000_free_buffers(STRUCT_NET_DEVICE *dev)
+c7000_free_buffers(struct net_device *dev)
 {
 	int				i;
 	struct	c7000_controller	*ccp = (struct c7000_controller *) dev->priv;
@@ -1328,12 +1284,12 @@ c7000_irq_bh(struct c7000_unit *cup)
 	struct	c7000_rd_header		*head;	
 	struct	sk_buff			*skb;
 	struct	c7000_controller	*ccp;
-	STRUCT_NET_DEVICE		*dev;
+	struct	net_device		*dev;
 	int				rc;
 	__u16				data_length;
-	__u32				parm;
+	unsigned long			parm;
 	__u8				flags = 0x00;
-	__u32				saveflags;
+	unsigned long			saveflags;
 
 	ccp = cup->cntlp;
 	dev = ccp->dev;
@@ -1385,6 +1341,7 @@ c7000_irq_bh(struct c7000_unit *cup)
 			skb->ip_summed = CHECKSUM_UNNECESSARY;
 			netif_rx(skb);
 			ccp->stats.rx_packets++;
+			ccp->stats.rx_bytes += skb->len;
 		} else {
 			CPrintk(0, "c7000: c7000_irq_bh: can not allocate a skb for unit 0x%x\n", cup->devno);
 			ccp->stats.rx_dropped++;
@@ -1403,6 +1360,7 @@ c7000_irq_bh(struct c7000_unit *cup)
 			Rechain the buffer on the running channel program.
 		*/
 
+		buf->ccws[3].cda = buf->ccws[5].cda = (__u32)virt_to_phys(&buf->ccws[6]);
 		if (pbuf != NULL)
 			pbuf->ccws[3].cda = pbuf->ccws[5].cda = (__u32)virt_to_phys(&buf->ccws[0]);
 
@@ -1422,7 +1380,7 @@ c7000_irq_bh(struct c7000_unit *cup)
 			return;
 		}
 
-		parm = (__u32)cup;
+		parm = (unsigned long)cup;
 		cup->state = C7000_READ;
 
 		if ((rc = do_IO(cup->irq, &cup->proc_head->ccws[0], parm, 0xff, flags)) != 0) {
@@ -1979,7 +1937,7 @@ c7000_get_conn(struct c7000_unit *cup)
 */
 
 struct net_device_stats *
-c7000_stats(STRUCT_NET_DEVICE *dev)
+c7000_stats(struct net_device *dev)
 {
 	struct	c7000_controller	*ccp = (struct c7000_controller *)dev->priv;
 
@@ -1991,13 +1949,13 @@ c7000_stats(STRUCT_NET_DEVICE *dev)
 */
 
 static int
-c7000_open(STRUCT_NET_DEVICE *dev)
+c7000_open(struct net_device *dev)
 {
 	int				i;
 	struct	c7000_controller	*ccp = (struct c7000_controller *)dev->priv;
 	struct	c7000_unit		*cup;
 	int				rc;
-	__u32				parm;
+	unsigned long			parm;
 	__u8				flags = 0x00;
 
 	c7000_set_busy(dev);
@@ -2025,16 +1983,11 @@ c7000_open(STRUCT_NET_DEVICE *dev)
 			half routine.
 		*/
 
-#ifndef NEWSTUFF
-		cup->tq.next = NULL;
-#endif
 		cup->tq.sync = 0;
 		cup->tq.routine = (void *)(void *)c7000_irq_bh;
 		cup->tq.data = cup;
 		cup->state = C7000_HALT;
-#ifdef NEWSTUFF
 		init_waitqueue_head(&cup->wait);
-#endif
 		CPrintk(1, "c7000: c7000_open: issuing halt to unit 0x%x\n", cup->devno);
 
 		/*
@@ -2154,7 +2107,7 @@ c7000_open(STRUCT_NET_DEVICE *dev)
 	*/
 
 	cup->state = C7000_READ;
-	parm = (__u32) cup;
+	parm = (unsigned long)cup;
 	set_bit(0, (void *)&cup->IO_active);
 
 	if ((rc = do_IO(cup->irq, &cup->proc_head->ccws[0], parm, 0xff, flags)) != 0) {
@@ -2165,11 +2118,7 @@ c7000_open(STRUCT_NET_DEVICE *dev)
 		return(-EIO);
 	}
 
-#ifdef NEWSTUFF
 	netif_start_queue(dev);
-#else
-	dev->start = 1;
-#endif
 	CPrintk(0, "c7000: c7000_open: base unit 0x%lx is opened\n", dev->base_addr);
 	c7000_clear_busy(dev);
 	MOD_INC_USE_COUNT;	/* increment module usage count */
@@ -2181,18 +2130,13 @@ c7000_open(STRUCT_NET_DEVICE *dev)
 */
 
 static int
-c7000_stop(STRUCT_NET_DEVICE *dev)
+c7000_stop(struct net_device *dev)
 {
 	int				i;
 	struct	c7000_controller	*ccp = (struct c7000_controller *)dev->priv;
 	struct	c7000_unit		*cup;
 	int				rc;
 
-#ifdef NEWSTUFF
-/* nothing? */
-#else
-	dev->start = 0;
-#endif
 	c7000_set_busy(dev);
 
 	/*
@@ -2236,7 +2180,7 @@ c7000_stop(STRUCT_NET_DEVICE *dev)
 */
 
 static int
-c7000_config(STRUCT_NET_DEVICE *dev, struct ifmap *map)
+c7000_config(struct net_device *dev, struct ifmap *map)
 {
 	CPrintk(1, "c7000: c7000_config: entered for base unit 0x%lx\n", dev->base_addr);
 	return(0);
@@ -2247,12 +2191,12 @@ c7000_config(STRUCT_NET_DEVICE *dev, str
 */
 
 static int
-c7000_xmit(struct sk_buff *skb, STRUCT_NET_DEVICE *dev)
+c7000_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	struct	c7000_controller	*ccp = (struct c7000_controller *)dev->priv;
 	struct	c7000_unit		*cup;
-	__u32				saveflags;
-	__u32				parm;
+	unsigned long			saveflags;
+	unsigned long			parm;
 	__u8				flags = 0x00;
 	struct	c7000_buffer		*buf, *pbuf;
 	int				rc;
@@ -2350,7 +2294,7 @@ c7000_xmit(struct sk_buff *skb, STRUCT_N
 	if (test_and_set_bit(0, (void *)&cup->IO_active) == 0) {
 		CPrintk(1, "c7000: c7000_xmit: start IO for unit 0x%x\n", cup->devno);
 		c7000_bld_wrt_chain(cup);
-		parm = (__u32) cup;
+		parm = (unsigned long)cup;
 		cup->state = C7000_WRITE;
 
 		if ((rc = do_IO(cup->irq, &cup->proc_head->ccws[0], parm, 0xff, flags)) != 0) {
@@ -2385,7 +2329,7 @@ c7000_xmit(struct sk_buff *skb, STRUCT_N
 */
 
 static int
-c7000_ioctl(STRUCT_NET_DEVICE *dev, struct ifreq *ifr, int cmd)
+c7000_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 {
 	CPrintk(1, "c7000: c7000_ioctl: entered for base unit 0x%lx with cmd %d\n", dev->base_addr, cmd);
 	return(0);
@@ -2461,7 +2405,7 @@ static void
 c7000_retry_io(struct c7000_unit *cup)
 {
 	int	rc;
-	__u32	parm;
+	unsigned long	parm;
 	__u8	flags = 0x00;
 	ccw1_t	*ccwp;
 
@@ -2472,7 +2416,7 @@ c7000_retry_io(struct c7000_unit *cup)
 	}
 
 	set_bit(0, (void *)&cup->IO_active);
-	parm = (__u32)cup;
+	parm = (unsigned long)cup;
 
 	if (cup->state == C7000_READ || cup->state == C7000_WRITE)
 		ccwp = &cup->proc_head->ccws[0];
@@ -2560,14 +2504,10 @@ c7000_proc_wintr(struct c7000_unit *cup)
 		*/
 
 		buf = c7000_dequeue_buffer(cup);
+		ccp->stats.tx_bytes += buf->len;
+		ccp->stats.tx_packets++;
 		c7000_release_buffer(cup, buf);
 		num_write++;
-
-		/*
-			Update transmitted packets statistic.
-		*/
-
-		ccp->stats.tx_packets++;
 	}
 
 	CPrintk(1, "c7000: c7000_proc_wintr: %d buffers written for unit 0x%x\n", num_write, cup->devno);
@@ -2584,8 +2524,8 @@ c7000_intr(int irq, void *initparm, stru
 	devstat_t			*devstat = ((devstat_t *) initparm);
 	struct	c7000_unit		*cup = NULL;
 	struct	c7000_controller	*ccp = NULL;
-	STRUCT_NET_DEVICE		*dev = NULL;
-	__u32				parm;
+	struct	net_device		*dev = NULL;
+	unsigned long			parm;
 	__u8				flags = 0x00;
 	int				rc;
 
@@ -2618,14 +2558,14 @@ c7000_intr(int irq, void *initparm, stru
 	ccp = cup->cntlp;
 
 	if (ccp == NULL) {
-		CPrintk(0, "c7000: c7000_intr: c7000_cntlp pointer is NULL in c7000_unit structure 0x%x for unit 0x%x\n", (int)cup, cup->devno);
+		CPrintk(0, "c7000: c7000_intr: c7000_cntlp pointer is NULL in c7000_unit structure %p for unit 0x%x\n", cup, cup->devno);
 		return;
 	}
 
 	dev = ccp->dev;
 
 	if (dev == NULL) {
-		CPrintk(0, "c7000: c7000_intr: device pointer is NULL in c7000_controller structure 0x%x for unit 0x%x\n", (int)ccp, cup->devno);
+		CPrintk(0, "c7000: c7000_intr: device pointer is NULL in c7000_controller structure %p for unit 0x%x\n", ccp, cup->devno);
 		return;
 	}
 
@@ -2777,7 +2717,7 @@ c7000_intr(int irq, void *initparm, stru
 			if ((devstat->flag & DEVSTAT_FINAL_STATUS) &&
 			    (cup->free != NULL)) {
 				c7000_bld_read_chain(cup);
-				parm = (__u32)cup;
+				parm = (unsigned long)cup;
 				set_bit(0, (void *)&cup->IO_active);
 
 				if ((rc = do_IO(cup->irq, &cup->proc_head->ccws[0], parm, 0xff, flags)) != 0) {
@@ -2834,7 +2774,7 @@ c7000_intr(int irq, void *initparm, stru
 
 			if (cup->proc_head != NULL) {
 				c7000_bld_wrt_chain(cup);
-				parm = (__u32)cup;
+				parm = (unsigned long)cup;
 				set_bit(0, (void *)&cup->IO_active);
 
 				if ((rc = do_IO(cup->irq, &cup->proc_head->ccws[0], parm, 0xff, flags)) != 0) {
@@ -2932,7 +2872,7 @@ c7000_fill_name(char *dst, char *src)
 */
 
 static int
-c7000_init(STRUCT_NET_DEVICE *dev)
+c7000_init(struct net_device *dev)
 {
 	struct	c7000_controller	*ccp;
 	int				i;
@@ -2970,7 +2910,7 @@ c7000_init(STRUCT_NET_DEVICE *dev)
         dev->addr_len = 0;
         dev->type = ARPHRD_SLIP;
         dev->tx_queue_len = C7000_TXQUEUE_LEN;
-	dev->flags = IFF_NOARP;   
+	dev->flags = IFF_BROADCAST|IFF_MULTICAST|IFF_NOARP;
 	dev->open = c7000_open;
 	dev->stop = c7000_stop;
 	dev->set_config = c7000_config;
@@ -2987,7 +2927,7 @@ c7000_init(STRUCT_NET_DEVICE *dev)
 		return(-ENOMEM);
 	}
 
-	CPrintk(1, "c7000: c7000_init: allocated a c7000_controller structure at address 0x%x\n", (int)ccp);
+	CPrintk(1, "c7000: c7000_init: allocated a c7000_controller structure at address %p\n", ccp);
 	memset(ccp, '\0', sizeof(struct c7000_controller));
 	ccp->dev = dev;
 	ccp->base_addr = dev->base_addr;
@@ -3217,12 +3157,8 @@ init_module(void)
 			Initialize the device structure.
 		*/
 
-		memset(&c7000_devices[i], '\0', sizeof(STRUCT_NET_DEVICE));
-#ifdef NEWSTUFF
+		memset(&c7000_devices[i], '\0', sizeof(struct net_device));
 		strcpy(c7000_devices[i].name, ifnames[i]);
-#else
-		c7000_devices[i].name = &ifnames[i][0];
-#endif
 		c7000_devices[i].base_addr = bases[i];
 		c7000_devices[i].init = c7000_init;
 
@@ -3278,7 +3214,7 @@ cleanup_module(void)
 					free_irq(ccp->cunits[j].irq, &ccp->cunits[j].devstat);
 				}
 
-				CPrintk(1, "c7000: clean_module: free a c7000_controller structure at address 0x%x\n", (int)ccp);
+				CPrintk(1, "c7000: clean_module: free a c7000_controller structure at address %p\n", ccp);
 				kfree(ccp);
 			}
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/s390/net/ctcmain.c linux-2.4.28-pre3/drivers/s390/net/ctcmain.c
--- linux-2.4.27/drivers/s390/net/ctcmain.c	2004-08-07 23:26:05.000000000 +0000
+++ linux-2.4.28-pre3/drivers/s390/net/ctcmain.c	2004-09-10 19:34:04.000000000 +0000
@@ -3096,7 +3096,7 @@ static ssize_t ctc_loglevel_read(struct 
 
 	privptr = (ctc_priv *)dev->priv;
 
-	if (!*sbus || pos == 0)
+	if (!*sbuf || pos == 0)
 		sprintf(sbuf, "0x%02x\n", loglevel);
 
 	l = strlen(sbuf);
@@ -3169,7 +3169,7 @@ static ssize_t ctc_stat_read(struct file
 
 	privptr = (ctc_priv *)dev->priv;
 
-	if (!*sbus || pos == 0) {
+	if (!*sbuf || pos == 0) {
 		p += sprintf(p, "Device FSM state: %s\n",
 			     fsm_getstate_str(privptr->fsm));
 		p += sprintf(p, "RX channel FSM state: %s\n",
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/s390/net/iucv.c linux-2.4.28-pre3/drivers/s390/net/iucv.c
--- linux-2.4.27/drivers/s390/net/iucv.c	2003-08-25 11:44:42.000000000 +0000
+++ linux-2.4.28-pre3/drivers/s390/net/iucv.c	2004-09-10 19:32:31.000000000 +0000
@@ -1,5 +1,5 @@
 /* 
- * $Id: iucv.c,v 1.41 2003/06/24 16:05:32 felfert Exp $
+ * $Id: iucv.c,v 1.40.2.5 2004/06/29 07:37:33 braunu Exp $
  *
  * IUCV network driver
  *
@@ -29,7 +29,7 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * RELEASE-TAG: IUCV lowlevel driver $Revision: 1.41 $
+ * RELEASE-TAG: IUCV lowlevel driver $Revision: 1.40.2.5 $
  *
  */
 
@@ -320,7 +320,7 @@ iucv_dumpit(char *title, void *buf, int 
 #define iucv_debug(lvl, fmt, args...) \
 do { \
 	if (debuglevel >= lvl) \
-		printk(KERN_DEBUG __FUNCTION__ ": " fmt "\n", ## args); \
+		printk(KERN_DEBUG "%s: " fmt "\n", __FUNCTION__, ## args); \
 } while (0)
 
 #else
@@ -334,13 +334,15 @@ do { \
  * Internal functions
  *******************************************************************************/
 
+static int iucv_retrieve_buffer(void);
+
 /**
  * print start banner
  */
 static void
 iucv_banner(void)
 {
-	char vbuf[] = "$Revision: 1.41 $";
+	char vbuf[] = "$Revision: 1.40.2.5 $";
 	char *version = vbuf;
 
 	if ((version = strchr(version, ':'))) {
@@ -418,6 +420,7 @@ iucv_init(void)
 static void
 iucv_exit(void)
 {
+	iucv_retrieve_buffer();
 	if (iucv_external_int_buffer)
 		kfree(iucv_external_int_buffer);
 	if (iucv_param_pool)
@@ -438,17 +441,19 @@ iucv_exit(void)
 static __inline__ iucv_param *
 grab_param(void)
 {
-	iucv_param *ret;
-	int i = 0;
+	iucv_param *ptr;
+        static int hint = 0;
+
+	ptr = iucv_param_pool + hint;
+	do {
+		ptr++;
+		if (ptr >= iucv_param_pool + PARAM_POOL_SIZE)
+			ptr = iucv_param_pool;
+	} while (atomic_compare_and_swap(0, 1, &ptr->in_use));
+	hint = ptr - iucv_param_pool;
 
-	while (atomic_compare_and_swap(0, 1, &iucv_param_pool[i].in_use)) {
-		i++;
-		if (i >= PARAM_POOL_SIZE)
-			i = 0;
-	}
-	ret = &iucv_param_pool[i];
-	memset(&ret->param, 0, sizeof(ret->param));
-	return ret;
+	memset(&ptr->param, 0, sizeof(ptr->param));
+	return ptr;
 }
 
 /**
@@ -549,10 +554,8 @@ b2f0(__u32 code, void *parm)
  *	   - ENOMEM - storage allocation for a new pathid table failed
 */
 static int
-iucv_add_pathid(__u16 pathid, handler *handler)
+__iucv_add_pathid(__u16 pathid, handler *handler)
 {
-	ulong flags;
-
 	iucv_debug(1, "entering");
 
 	iucv_debug(1, "handler is pointing to %p", handler);
@@ -560,21 +563,30 @@ iucv_add_pathid(__u16 pathid, handler *h
 	if (pathid > (max_connections - 1))
 		return -EINVAL;
 
-	spin_lock_irqsave (&iucv_lock, flags);
 	if (iucv_pathid_table[pathid]) {
-		spin_unlock_irqrestore (&iucv_lock, flags);
 		iucv_debug(1, "pathid entry is %p", iucv_pathid_table[pathid]);
 		printk(KERN_WARNING
 		       "%s: Pathid being used, error.\n", __FUNCTION__);
 		return -EINVAL;
 	}
 	iucv_pathid_table[pathid] = handler;
-	spin_unlock_irqrestore (&iucv_lock, flags);
 
 	iucv_debug(1, "exiting");
 	return 0;
 }				/* end of add_pathid function */
 
+static int
+iucv_add_pathid(__u16 pathid, handler *handler)
+{
+	ulong flags;
+	int rc;
+
+	spin_lock_irqsave (&iucv_lock, flags);
+	rc = __iucv_add_pathid(pathid, handler);
+	spin_unlock_irqrestore (&iucv_lock, flags);
+	return rc;
+}
+
 static void
 iucv_remove_pathid(__u16 pathid)
 {
@@ -688,7 +700,6 @@ iucv_remove_handler(handler *handler)
 	spin_lock_irqsave (&iucv_lock, flags);
 	list_del(&handler->list);
 	if (list_empty(&iucv_handler_table)) {
-		iucv_retrieve_buffer();
 		if (register_flag) {
 			unregister_external_interrupt(0x4000, iucv_irq_handler);
 			register_flag = 0;
@@ -764,6 +775,7 @@ iucv_register_program (__u8 pgmname[16],
 		if (iucv_pathid_table == NULL) {
 			printk(KERN_WARNING "%s: iucv_pathid_table storage "
 			       "allocation failed\n", __FUNCTION__);
+			kfree(new_handler);
 			return NULL;
 		}
 		memset (iucv_pathid_table, 0, max_connections * sizeof(handler *));
@@ -1002,6 +1014,8 @@ iucv_accept(__u16 pathid, __u16 msglim_r
 	b2f0_result = b2f0(ACCEPT, parm);
 
 	if (b2f0_result == 0) {
+		if (msglim)
+			*msglim = parm->ipmsglim;
 		if (pgm_data)
 			h->pgm_data = pgm_data;
 		if (flags1_out)
@@ -1133,11 +1147,15 @@ iucv_connect (__u16 *pathid, __u16 msgli
 	iucv_setmask(~(AllInterrupts));
 	messagesDisabled = 1;
 
+	spin_lock_irqsave (&iucv_lock, flags);
 	parm->ipflags1 = (__u8)flags1;
 	b2f0_result = b2f0(CONNECT, parm);
 	memcpy(&local_parm, parm, sizeof(local_parm));
 	release_param(parm);
 	parm = &local_parm;
+	if (b2f0_result == 0)
+		add_pathid_result = __iucv_add_pathid(parm->ippathid, h);
+	spin_unlock_irqrestore (&iucv_lock, flags);
 
 	if (b2f0_result) {
 		iucv_setmask(~0);
@@ -1145,7 +1163,6 @@ iucv_connect (__u16 *pathid, __u16 msgli
 		return b2f0_result;
 	}
 
-	add_pathid_result = iucv_add_pathid(parm->ippathid, h);
 	*pathid = parm->ippathid;
 
 	/* Enable everything again */
@@ -1884,6 +1901,7 @@ iucv_send_prmmsg (__u16 pathid,
 {
 	iparml_dpl *parm;
 	ulong b2f0_result;
+	iucv_param save_param;
 
 	iucv_debug(2, "entering");
 
@@ -1896,7 +1914,13 @@ iucv_send_prmmsg (__u16 pathid,
 	parm->ipflags1 = (IPRMDATA | IPNORPY | flags1);
 	memcpy(parm->iprmmsg, prmmsg, sizeof(parm->iprmmsg));
 
+	memcpy((void *)&save_param, (void *)parm, sizeof(iucv_param));
 	b2f0_result = b2f0(SEND, parm);
+	if (b2f0_result != 0) {
+	    printk("b2f0 call returned %lx\n", b2f0_result);
+	    iucv_dumpit("PL before:", &save_param, sizeof(iucv_param));
+	    iucv_dumpit("PL after:", parm, sizeof(iucv_param));
+	}
 
 	if ((b2f0_result == 0) && (msgid))
 		*msgid = parm->ipmsgid;
@@ -2333,7 +2357,8 @@ iucv_do_int(iucv_GeneralInterrupt * int_
 					iucv_debug(2,
 						   "found a matching handler");
 					break;
-				}
+				} else
+					h = NULL;
 			}
 			spin_unlock_irqrestore (&iucv_lock, flags);
 			if (h) {
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/s390/net/netiucv.c linux-2.4.28-pre3/drivers/s390/net/netiucv.c
--- linux-2.4.27/drivers/s390/net/netiucv.c	2004-08-07 23:26:05.000000000 +0000
+++ linux-2.4.28-pre3/drivers/s390/net/netiucv.c	2004-09-10 19:35:18.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * $Id: netiucv.c,v 1.23 2003/06/24 16:05:32 felfert Exp $
+ * $Id: netiucv.c,v 1.21.8.6 2004/06/29 07:37:33 braunu Exp $
  *
  * IUCV network driver
  *
@@ -28,7 +28,7 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * RELEASE-TAG: IUCV network driver $Revision: 1.23 $
+ * RELEASE-TAG: IUCV network driver $Revision: 1.21.8.6 $
  *
  */
 
@@ -114,17 +114,13 @@ typedef struct iucv_connection_t {
 	spinlock_t               collect_lock;
 	int                      collect_len;
 	int                      max_buffsize;
-	int                      flags;
 	fsm_timer                timer;
-	int                      retry;
 	fsm_instance             *fsm;
 	net_device               *netdev;
 	connection_profile       prof;
 	char                     userid[9];
 } iucv_connection;
 
-#define CONN_FLAGS_BUFSIZE_CHANGED 1
-
 /**
  * Linked list of all connection structs.
  */
@@ -435,6 +431,10 @@ netiucv_callback_txdone(iucv_MessageComp
 	iucv_connection *conn = (iucv_connection *)pgm_data;
 	iucv_event ev;
 
+#ifdef DEBUG
+	printk(KERN_DEBUG "%s() called\n", __FUNCTION__);
+#endif
+
 	ev.conn = conn;
 	ev.data = (void *)eib;
 	fsm_event(conn->fsm, CONN_EVENT_TXDONE, &ev);
@@ -590,7 +590,7 @@ conn_action_rx(fsm_instance *fi, int eve
 	iucv_MessagePending *eib = (iucv_MessagePending *)ev->data;
 	netiucv_priv *privptr = (netiucv_priv *)conn->netdev->priv;
 
-	__u16 msglen = eib->ln1msg2.ipbfln1f;
+	__u32 msglen = eib->ln1msg2.ipbfln1f;
 	int rc;
 
 #ifdef DEBUG
@@ -613,6 +613,7 @@ conn_action_rx(fsm_instance *fi, int eve
 			  conn->rx_buff->data, msglen, NULL, NULL, NULL);
 	if (rc != 0 || msglen < 5) {
 		privptr->stats.rx_errors++;
+		printk(KERN_INFO "iucv_receive returned %08x\n", rc);
 		return;
 	}
 	netiucv_unpack_skb(conn, conn->rx_buff);
@@ -637,7 +638,6 @@ conn_action_txdone(fsm_instance *fi, int
 #ifdef DEBUG
 	printk(KERN_DEBUG "%s() called\n", __FUNCTION__);
 #endif
-	fsm_deltimer(&conn->timer);
 	if (conn && conn->netdev && conn->netdev->priv)
 		privptr = (netiucv_priv *)conn->netdev->priv;
 	conn->prof.tx_pending--;
@@ -645,11 +645,12 @@ conn_action_txdone(fsm_instance *fi, int
 		if ((skb = skb_dequeue(&conn->commit_queue))) {
 			atomic_dec(&skb->users);
 			dev_kfree_skb_any(skb);
-		}
-		if (privptr) {
-			privptr->stats.tx_packets++;
-			privptr->stats.tx_bytes +=
-				(skb->len - NETIUCV_HDRLEN - NETIUCV_HDRLEN);
+			if (privptr) {
+				privptr->stats.tx_packets++;
+				privptr->stats.tx_bytes +=
+					(skb->len - NETIUCV_HDRLEN
+						  - NETIUCV_HDRLEN);
+			}
 		}
 	}
 	conn->tx_buff->data = conn->tx_buff->tail = conn->tx_buff->head;
@@ -677,8 +678,6 @@ conn_action_txdone(fsm_instance *fi, int
 		memcpy(skb_put(conn->tx_buff, NETIUCV_HDRLEN), &header,
 		       NETIUCV_HDRLEN);
 
-		fsm_addtimer(&conn->timer, NETIUCV_TIMEOUT_5SEC,
-			     CONN_EVENT_TIMER, conn);
 		conn->prof.send_stamp = xtime;
 		rc = iucv_send(conn->pathid, NULL, 0, 0, 0, 0,
 			       conn->tx_buff->data, conn->tx_buff->len);
@@ -688,12 +687,11 @@ conn_action_txdone(fsm_instance *fi, int
 		if (conn->prof.tx_pending > conn->prof.tx_max_pending)
 			conn->prof.tx_max_pending = conn->prof.tx_pending;
 		if (rc != 0) {
-			fsm_deltimer(&conn->timer);
 			conn->prof.tx_pending--;
 			fsm_newstate(fi, CONN_STATE_IDLE);
 			if (privptr)
 				privptr->stats.tx_errors += txpackets;
-			printk(KERN_DEBUG "iucv_send returned %08x\n",
+			printk(KERN_INFO "iucv_send returned %08x\n",
 			       rc);
 		} else {
 			if (privptr) {
@@ -762,6 +760,7 @@ conn_action_connack(fsm_instance *fi, in
 #ifdef DEBUG
 	printk(KERN_DEBUG "%s() called\n", __FUNCTION__);
 #endif
+	fsm_deltimer(&conn->timer);
 	fsm_newstate(fi, CONN_STATE_IDLE);
 	conn->pathid = eib->ippathid;
 	netdev->tx_queue_len = eib->ipmsglim;
@@ -769,6 +768,19 @@ conn_action_connack(fsm_instance *fi, in
 }
 
 static void
+conn_action_conntimsev(fsm_instance *fi, int event, void *arg)
+{
+	iucv_connection *conn = (iucv_connection *)arg;
+	__u8 udata[16];
+
+	pr_debug("%s() called\n", __FUNCTION__);
+
+	fsm_deltimer(&conn->timer);
+	iucv_sever(conn->pathid, udata);
+	fsm_newstate(fi, CONN_STATE_STARTWAIT);
+}
+
+static void
 conn_action_connsever(fsm_instance *fi, int event, void *arg)
 {
 	iucv_event *ev = (iucv_event *)arg;
@@ -776,30 +788,17 @@ conn_action_connsever(fsm_instance *fi, 
 	// iucv_ConnectionSevered *eib = (iucv_ConnectionSevered *)ev->data;
 	net_device *netdev = conn->netdev;
 	netiucv_priv *privptr = (netiucv_priv *)netdev->priv;
-	int state = fsm_getstate(fi);
+	__u8 udata[16];
 
 #ifdef DEBUG
 	printk(KERN_DEBUG "%s() called\n", __FUNCTION__);
 #endif
-	switch (state) {
-		case CONN_STATE_SETUPWAIT:
-			printk(KERN_INFO "%s: Remote dropped connection\n",
-			       netdev->name);
-			conn->handle = 0;
-			fsm_newstate(fi, CONN_STATE_STOPPED);
-			fsm_event(privptr->fsm, DEV_EVENT_CONDOWN, netdev);
-			break;
-		case CONN_STATE_IDLE:
-		case CONN_STATE_TX:
-			printk(KERN_INFO "%s: Remote dropped connection\n",
-			       netdev->name);
-			if (conn->handle)
-				iucv_unregister_program(conn->handle);
-			conn->handle = 0;
-			fsm_newstate(fi, CONN_STATE_STOPPED);
-			fsm_event(privptr->fsm, DEV_EVENT_CONDOWN, netdev);
-			break;
-	}
+	fsm_deltimer(&conn->timer);
+	iucv_sever(conn->pathid, udata);
+	printk(KERN_INFO "%s: Remote dropped connection\n",
+	       netdev->name);
+	fsm_newstate(fi, CONN_STATE_STARTWAIT);
+	fsm_event(privptr->fsm, DEV_EVENT_CONDOWN, netdev);
 }
 
 static void
@@ -807,7 +806,7 @@ conn_action_start(fsm_instance *fi, int 
 {
 	iucv_event *ev = (iucv_event *)arg;
 	iucv_connection *conn = ev->conn;
-
+	__u16 msglimit;
 	int rc;
 
 #ifdef DEBUG
@@ -839,10 +838,13 @@ conn_action_start(fsm_instance *fi, int 
 
 	fsm_newstate(fi, CONN_STATE_SETUPWAIT);
 	rc = iucv_connect(&(conn->pathid), NETIUCV_QUEUELEN_DEFAULT, iucvMagic,
-			  conn->userid, iucv_host, 0, NULL, NULL, conn->handle,
+			  conn->userid, iucv_host, 0, NULL, &msglimit, conn->handle,
 			  conn);
 	switch (rc) {
 		case 0:
+			conn->netdev->tx_queue_len = msglimit;
+			fsm_addtimer(&conn->timer, NETIUCV_TIMEOUT_5SEC,
+				CONN_EVENT_TIMER, conn);
 			return;
 		case 11:
 			printk(KERN_NOTICE
@@ -910,6 +912,7 @@ conn_action_stop(fsm_instance *fi, int e
 #ifdef DEBUG
 	printk(KERN_DEBUG "%s() called\n", __FUNCTION__);
 #endif
+	fsm_deltimer(&conn->timer);
 	fsm_newstate(fi, CONN_STATE_STOPPED);
 	netiucv_purge_skb_queue(&conn->collect_queue);
 	if (conn->handle)
@@ -934,8 +937,8 @@ conn_action_inval(fsm_instance *fi, int 
 static const fsm_node conn_fsm[] = {
 	{ CONN_STATE_INVALID,   CONN_EVENT_START,    conn_action_inval      },
 	{ CONN_STATE_STOPPED,   CONN_EVENT_START,    conn_action_start      },
-	{ CONN_STATE_STARTWAIT, CONN_EVENT_START,    conn_action_start      },
 
+	{ CONN_STATE_STOPPED,   CONN_EVENT_STOP,     conn_action_stop       },
 	{ CONN_STATE_STARTWAIT, CONN_EVENT_STOP,     conn_action_stop       },
 	{ CONN_STATE_SETUPWAIT, CONN_EVENT_STOP,     conn_action_stop       },
 	{ CONN_STATE_IDLE,      CONN_EVENT_STOP,     conn_action_stop       },
@@ -950,6 +953,7 @@ static const fsm_node conn_fsm[] = {
 	{ CONN_STATE_TX,        CONN_EVENT_CONN_REQ, conn_action_connreject },
 
 	{ CONN_STATE_SETUPWAIT, CONN_EVENT_CONN_ACK, conn_action_connack    },
+	{ CONN_STATE_SETUPWAIT, CONN_EVENT_TIMER,    conn_action_conntimsev },
 
 	{ CONN_STATE_SETUPWAIT, CONN_EVENT_CONN_REJ, conn_action_connsever  },
 	{ CONN_STATE_IDLE,      CONN_EVENT_CONN_REJ, conn_action_connsever  },
@@ -1026,6 +1030,7 @@ static void
 dev_action_connup(fsm_instance *fi, int event, void *arg)
 {
 	net_device   *dev = (net_device *)arg;
+	netiucv_priv *privptr = (netiucv_priv *)dev->priv;
 
 #ifdef DEBUG
 	printk(KERN_DEBUG "%s() called\n", __FUNCTION__);
@@ -1034,8 +1039,8 @@ dev_action_connup(fsm_instance *fi, int 
 		case DEV_STATE_STARTWAIT:
 			fsm_newstate(fi, DEV_STATE_RUNNING);
 			printk(KERN_INFO
-			       "%s: connected with remote side\n",
-			       dev->name);
+			       "%s: connected with remote side %s\n",
+			       dev->name, privptr->conn->userid);
 			break;
 		case DEV_STATE_STOPWAIT:
 			printk(KERN_INFO
@@ -1056,9 +1061,6 @@ dev_action_connup(fsm_instance *fi, int 
 static void
 dev_action_conndown(fsm_instance *fi, int event, void *arg)
 {
-	net_device   *dev = (net_device *)arg;
-	netiucv_priv *privptr = dev->priv;
-	iucv_event   ev;
 
 #ifdef DEBUG
 	printk(KERN_DEBUG "%s() called\n", __FUNCTION__);
@@ -1066,10 +1068,6 @@ dev_action_conndown(fsm_instance *fi, in
 	switch (fsm_getstate(fi)) {
 		case DEV_STATE_RUNNING:
 			fsm_newstate(fi, DEV_STATE_STARTWAIT);
-			ev.conn = privptr->conn;
-			fsm_event(privptr->conn->fsm, CONN_EVENT_START, &ev);
-			break;
-		case DEV_STATE_STARTWAIT:
 			break;
 		case DEV_STATE_STOPWAIT:
 			fsm_newstate(fi, DEV_STATE_STOPPED);
@@ -1085,7 +1083,6 @@ static const fsm_node dev_fsm[] = {
 
 	{ DEV_STATE_STARTWAIT, DEV_EVENT_STOP,    dev_action_stop     },
 	{ DEV_STATE_STARTWAIT, DEV_EVENT_CONUP,   dev_action_connup   },
-	{ DEV_STATE_STARTWAIT, DEV_EVENT_CONDOWN, dev_action_conndown },
 
 	{ DEV_STATE_RUNNING,   DEV_EVENT_STOP,    dev_action_stop     },
 	{ DEV_STATE_RUNNING,   DEV_EVENT_CONDOWN, dev_action_conndown },
@@ -1141,6 +1138,7 @@ netiucv_transmit_skb(iucv_connection *co
 				       "%s: Could not allocate tx_skb\n",
 				       conn->netdev->name);
 				rc = -ENOMEM;
+				return rc;
 			} else {
 				skb_reserve(nskb, NETIUCV_HDRLEN);
 				memcpy(skb_put(nskb, skb->len),
@@ -1156,10 +1154,7 @@ netiucv_transmit_skb(iucv_connection *co
 		header.next = 0;
 		memcpy(skb_put(nskb, NETIUCV_HDRLEN), &header,  NETIUCV_HDRLEN);
 
-		conn->retry = 0;
 		fsm_newstate(conn->fsm, CONN_STATE_TX);
-		fsm_addtimer(&conn->timer, NETIUCV_TIMEOUT_5SEC,
-			     CONN_EVENT_TIMER, conn);
 		conn->prof.send_stamp = xtime;
 		
 		rc = iucv_send(conn->pathid, NULL, 0, 0, 1 /* single_flag */,
@@ -1171,7 +1166,6 @@ netiucv_transmit_skb(iucv_connection *co
 			conn->prof.tx_max_pending = conn->prof.tx_pending;
 		if (rc != 0) {
 			netiucv_priv *privptr;
-			fsm_deltimer(&conn->timer);
 			fsm_newstate(conn->fsm, CONN_STATE_IDLE);
 			conn->prof.tx_pending--;
 			privptr = (netiucv_priv *)conn->netdev->priv;
@@ -1276,7 +1270,6 @@ static int netiucv_tx(struct sk_buff *sk
 	 */
 	if (fsm_getstate(privptr->fsm) != DEV_STATE_RUNNING) {
 		fsm_event(privptr->fsm, DEV_EVENT_START, dev);
-		dst_link_failure(skb);
 		dev_kfree_skb(skb);
 		privptr->stats.tx_dropped++;
 		privptr->stats.tx_errors++;
@@ -1390,7 +1383,7 @@ netiucv_buffer_close(struct inode *inode
 
 static ssize_t
 netiucv_buffer_write(struct file *file, const char *buf, size_t count,
-			   loff_t *off)
+			   loff_t *ppos)
 {
 	unsigned int ino = ((struct inode *)file->f_dentry->d_inode)->i_ino;
 	net_device   *dev;
@@ -1401,7 +1394,7 @@ netiucv_buffer_write(struct file *file, 
 
 	if (!(dev = find_netdev_by_ino(ino)))
 		return -ENODEV;
-	if (off != &file->f_pos)
+	if (ppos != &file->f_pos)
 		return -ESPIPE;
 
 	privptr = (netiucv_priv *)dev->priv;
@@ -1427,13 +1420,12 @@ netiucv_buffer_write(struct file *file, 
 	privptr->conn->max_buffsize = bs1;
 	if (!(dev->flags & IFF_RUNNING))
 		dev->mtu = bs1 - NETIUCV_HDRLEN - NETIUCV_HDRLEN;
-	privptr->conn->flags |= CONN_FLAGS_BUFSIZE_CHANGED;
 
 	return count;
 }
 
 static ssize_t
-netiucv_buffer_read(struct file *file, char *buf, size_t count, loff_t *off)
+netiucv_buffer_read(struct file *file, char *buf, size_t count, loff_t *ppos)
 {
 	unsigned int ino = ((struct inode *)file->f_dentry->d_inode)->i_ino;
 	char *sbuf = (char *)file->private_data;
@@ -1446,7 +1438,7 @@ netiucv_buffer_read(struct file *file, c
 
 	if (!(dev = find_netdev_by_ino(ino)))
 		return -ENODEV;
-	if (off != &file->f_pos)
+	if (ppos != &file->f_pos)
 		return -ESPIPE;
 
 	privptr = (netiucv_priv *)dev->priv;
@@ -1489,7 +1481,7 @@ netiucv_user_close(struct inode *inode, 
 
 static ssize_t
 netiucv_user_write(struct file *file, const char *buf, size_t count,
-			   loff_t *off)
+			   loff_t *ppos)
 {
 	unsigned int ino = ((struct inode *)file->f_dentry->d_inode)->i_ino;
 	net_device   *dev;
@@ -1501,7 +1493,7 @@ netiucv_user_write(struct file *file, co
 
 	if (!(dev = find_netdev_by_ino(ino)))
 		return -ENODEV;
-	if (off != &file->f_pos)
+	if (ppos != &file->f_pos)
 		return -ESPIPE;
 
 	privptr = (netiucv_priv *)dev->priv;
@@ -1531,7 +1523,7 @@ netiucv_user_write(struct file *file, co
 }
 
 static ssize_t
-netiucv_user_read(struct file *file, char *buf, size_t count, loff_t *off)
+netiucv_user_read(struct file *file, char *buf, size_t count, loff_t *ppos)
 {
 	unsigned int ino = ((struct inode *)file->f_dentry->d_inode)->i_ino;
 	char *sbuf = (char *)file->private_data;
@@ -1544,7 +1536,7 @@ netiucv_user_read(struct file *file, cha
 
 	if (!(dev = find_netdev_by_ino(ino)))
 		return -ENODEV;
-	if (off != &file->f_pos)
+	if (ppos != &file->f_pos)
 		return -ESPIPE;
 
 	privptr = (netiucv_priv *)dev->priv;
@@ -1589,7 +1581,7 @@ netiucv_stat_close(struct inode *inode, 
 }
 
 static ssize_t
-netiucv_stat_write(struct file *file, const char *buf, size_t count, loff_t *off)
+netiucv_stat_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
 {
 	unsigned int ino = ((struct inode *)file->f_dentry->d_inode)->i_ino;
 	net_device *dev;
@@ -1603,7 +1595,7 @@ netiucv_stat_write(struct file *file, co
 }
 
 static ssize_t
-netiucv_stat_read(struct file *file, char *buf, size_t count, loff_t *off)
+netiucv_stat_read(struct file *file, char *buf, size_t count, loff_t *ppos)
 {
 	unsigned int ino = ((struct inode *)file->f_dentry->d_inode)->i_ino;
 	loff_t pos = *ppos;
@@ -1616,7 +1608,7 @@ netiucv_stat_read(struct file *file, cha
 
 	if (!(dev = find_netdev_by_ino(ino)))
 		return -ENODEV;
-	if (off != &file->f_pos)
+	if (ppos != &file->f_pos)
 		return -ESPIPE;
 
 	privptr = (netiucv_priv *)dev->priv;
@@ -1799,7 +1791,7 @@ netiucv_proc_destroy_main(void)
 	proc_net_unregister(netiucv_dir.low_ino);
 #endif
 }
-#endif MODULE
+#endif
 
 /**
  * Create a device specific subdirectory in /proc/net/iucv/ with the
@@ -2059,7 +2051,7 @@ netiucv_free_netdevice(net_device *dev)
 static void
 netiucv_banner(void)
 {
-	char vbuf[] = "$Revision: 1.23 $";
+	char vbuf[] = "$Revision: 1.21.8.6 $";
 	char *version = vbuf;
 
 	if ((version = strchr(version, ':'))) {
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/s390/net/qeth.c linux-2.4.28-pre3/drivers/s390/net/qeth.c
--- linux-2.4.27/drivers/s390/net/qeth.c	2004-08-07 23:26:05.000000000 +0000
+++ linux-2.4.28-pre3/drivers/s390/net/qeth.c	2004-09-10 19:34:31.000000000 +0000
@@ -1,6 +1,6 @@
 /*
  *
- * linux/drivers/s390/net/qeth.c ($Revision: 1.337 $)
+ * linux/drivers/s390/net/qeth.c ($Revision: 1.337.4.24 $)
  *
  * Linux on zSeries OSA Express and HiperSockets support
  *
@@ -28,9 +28,6 @@
  */
 
 /*
- * The driver supports in general all QDIO driven network devices on the
- * Hydra card.
- *
  * For all devices, three channels must be available to the driver. One
  * channel is the read channel, one is the write channel and the third
  * one is the channel used to control QDIO.
@@ -156,6 +153,7 @@ void volatile qeth_eyecatcher(void)
 #include <asm/irq.h>
 #include <asm/s390dyn.h>
 #include <asm/debug.h>
+#include <asm/processor.h>
 
 #include <asm/qdio.h>
 
@@ -171,7 +169,7 @@ MODULE_PARM_DESC(qeth_sparebufs,"the num
 static int global_stay_in_mem=0;
 
 /****************** MODULE STUFF **********************************/
-#define VERSION_QETH_C "$Revision: 1.337 $"
+#define VERSION_QETH_C "$Revision: 1.337.4.24 $"
 static const char *version="qeth S/390 OSA-Express driver (" \
 	VERSION_QETH_C "/" VERSION_QETH_H "/" VERSION_QETH_MPC_H
 	QETH_VERSION_IPV6 QETH_VERSION_VLAN ")";
@@ -183,10 +181,8 @@ MODULE_LICENSE("GPL");
 
 /******************** HERE WE GO ***********************************/
 
-#define PROCFILE_SLEEP_SEM_MAX_VALUE 0
-#define PROCFILE_IOCTL_SEM_MAX_VALUE 3
-static struct semaphore qeth_procfile_ioctl_lock;
-static struct semaphore qeth_procfile_ioctl_sem;
+
+
 static qeth_card_t *firstcard=NULL;
 
 static sparebufs_t sparebufs[MAX_SPARE_BUFFERS];
@@ -224,9 +220,12 @@ typedef struct {
 /* thought I could get along without forward declarations...
  * just lazyness here */
 static int qeth_reinit_thread(void*);
-static void qeth_schedule_recovery(qeth_card_t *card);
+static inline void qeth_schedule_recovery(qeth_card_t *card);
+static int qeth_fake_header(struct sk_buff *skb, struct net_device *dev,
+       			    unsigned short type, void *daddr, void *saddr,
+       			    unsigned len);
 
-inline static int QETH_IP_VERSION(struct sk_buff *skb)
+static inline int QETH_IP_VERSION(struct sk_buff *skb)
 {
         switch (skb->protocol) {
         case ETH_P_IPV6: return 6;
@@ -243,6 +242,21 @@ static inline int qeth_min(int a,int b)
 		return b;
 }
 
+/*
+ * This is our local skb_unshare, only with pskb_copy instead of skb_copy.
+ * We place our headers whare Ethernet MAC was, so we do not need
+ * full skb_copy.
+ */
+static inline struct sk_buff *qeth_pskb_unshare(struct sk_buff *skb, int pri)
+{
+	struct sk_buff *nskb;
+	if (!skb_cloned(skb))
+		return skb;
+	nskb = skb_copy(skb, pri);
+	kfree_skb(skb); /* free our shared copy */
+	return nskb;
+}
+
 static inline unsigned int qeth_get_millis(void)
 {
 	__u64 time;
@@ -291,7 +305,8 @@ static void qeth_wait_nonbusy(unsigned i
 	set_task_state(current,TASK_RUNNING);
 }
 
-static void qeth_get_mac_for_ipm(__u32 ipm,char *mac,struct net_device *dev) {
+static inline void qeth_get_mac_for_ipm(__u32 ipm,char *mac,
+					struct net_device *dev) {
 	if (dev->type==ARPHRD_IEEE802_TR)
 		ip_tr_mc_map(ipm,mac);
 	else
@@ -403,7 +418,7 @@ static int inline my_spin_lock_nonbusy(q
 #define QETH_GET_ADDR(x) ((__u32)x)
 #endif /* CONFIG_ARCH_S390X */
 
-static int qeth_does_card_exist(qeth_card_t *card)
+static inline int qeth_does_card_exist(qeth_card_t *card)
 {
 	qeth_card_t *c=firstcard;
 	int rc=0;
@@ -718,7 +733,9 @@ static int qeth_set_config(struct net_de
 
 static int qeth_is_multicast_skb_at_all(struct sk_buff *skb,int version)
 {
-	int i;
+	int i=RTN_UNSPEC;
+	qeth_card_t *card = (qeth_card_t *)skb->dev->priv;
+
 	if (skb->dst && skb->dst->neighbour) {
 		i=skb->dst->neighbour->type;
 		return ((i==RTN_BROADCAST)||
@@ -731,13 +748,37 @@ static int qeth_is_multicast_skb_at_all(
 	} else if (version==6) {
 		return (skb->nh.raw[24]==0xff)?RTN_MULTICAST:0;
 	}
-	return 0;
+	if (!memcmp(skb->nh.raw,skb->dev->broadcast,6)) {
+		i=RTN_BROADCAST;
+	} else {
+	        __u16 hdr_mac;
+	        hdr_mac=*((__u16*)skb->nh.raw);
+	        /* tr multicast? */
+	        switch (card->link_type) {
+	        case QETH_MPC_LINK_TYPE_HSTR:
+	        case QETH_MPC_LINK_TYPE_LANE_TR:
+	        	if ( (hdr_mac==QETH_TR_MAC_NC) ||
+			     (hdr_mac==QETH_TR_MAC_C) )
+				i = RTN_MULTICAST;
+			break;
+	        /* eth or so multicast? */
+                default:
+                      	if ( (hdr_mac==QETH_ETH_MAC_V4) ||
+			     (hdr_mac==QETH_ETH_MAC_V6) )
+			        i = RTN_MULTICAST;
+	        }
+        }
+	return ((i==RTN_BROADCAST)||
+	        (i==RTN_MULTICAST)||
+	        (i==RTN_ANYCAST))?i:0;
 }
 
 static int qeth_get_prioqueue(qeth_card_t *card,struct sk_buff *skb,
 			      int multicast,int version)
 {
-	if (!version) return QETH_DEFAULT_QUEUE;
+	if (!version &&
+	    (card->type==QETH_CARD_TYPE_OSAE))
+		return QETH_DEFAULT_QUEUE;
         switch (card->no_queues) {
         case 1:
                 return 0;
@@ -1046,7 +1087,7 @@ static int qeth_wait_for_event(atomic_t 
 	return retval;
 }
 
-static int qeth_get_spare_buf(void)
+static inline int qeth_get_spare_buf(void)
 {
 	int i=0;
 	char dbf_text[15];
@@ -1131,8 +1172,8 @@ static inline void qeth_clear_input_buff
 	}
 }
 
-static void qeth_queue_input_buffer(qeth_card_t *card,int bufno,
-				    unsigned int under_int)
+static inline void qeth_queue_input_buffer(qeth_card_t *card,int bufno,
+	       				   unsigned int under_int)
 {
 	int count=0,start=0,stop=0,pos;
 	int result;
@@ -1283,10 +1324,11 @@ static inline struct sk_buff *qeth_get_s
 	return skb;
 }
 
-static struct sk_buff *qeth_get_next_skb(qeth_card_t *card,
-	       				 int *element_ptr,int *pos_in_el_ptr,
-			       		 void **hdr_ptr,
-					 qdio_buffer_t *buffer)
+static inline struct sk_buff *qeth_get_next_skb(qeth_card_t *card,
+		     				int *element_ptr,
+						int *pos_in_el_ptr,
+		       				void **hdr_ptr,
+		       				qdio_buffer_t *buffer)
 {
 	int length;
 	char *data_ptr;
@@ -1394,10 +1436,6 @@ static struct sk_buff *qeth_get_next_skb
 		skb=qeth_get_skb(length+QETH_FAKE_LL_LEN);
 		if (!skb) goto nomem;
 		skb_pull(skb,QETH_FAKE_LL_LEN);
-		if (!skb) {
-			dev_kfree_skb_irq(skb);
-			goto nomem;
-		}
 	} else {
 		skb=qeth_get_skb(length);
 		if (!skb) goto nomem;
@@ -1472,8 +1510,8 @@ nomem:
 	return NULL;
 }
 
-static void qeth_transform_outbound_addrs(qeth_card_t *card,
-					  qdio_buffer_t *buffer)
+static inline void qeth_transform_outbound_addrs(qeth_card_t *card,
+	       					 qdio_buffer_t *buffer)
 {
 	int i;
 	void *ptr;
@@ -1485,7 +1523,8 @@ static void qeth_transform_outbound_addr
 		}
 	}
 }
-static void qeth_get_linux_addrs_for_buffer(qeth_card_t *card,int buffer_no)
+static inline void qeth_get_linux_addrs_for_buffer(qeth_card_t *card,
+						   int buffer_no)
 {
 	int i;
 	void *ptr;
@@ -1501,7 +1540,7 @@ static void qeth_get_linux_addrs_for_buf
 	}
 }
 
-static void qeth_read_in_buffer(qeth_card_t *card,int buffer_no)
+static inline void qeth_read_in_buffer(qeth_card_t *card,int buffer_no)
 {
         struct sk_buff *skb;
         void *hdr_ptr;
@@ -1643,7 +1682,7 @@ static void qeth_read_in_buffer(qeth_car
 			} else {
 				/* clear source MAC for security reasons */
 				memset(skb->mac.raw+
-				       QETH_FAKE_LL_DEST_MAC_POS,0,
+				       QETH_FAKE_LL_SRC_MAC_POS,0,
 				       QETH_FAKE_LL_ADDR_LEN);
 			}
 			memcpy(skb->mac.raw+
@@ -1654,34 +1693,47 @@ static void qeth_read_in_buffer(qeth_car
 			skb->mac.raw=skb->data;
 		}
 
-		skb->ip_summed=card->options.checksum_type;
 		if (card->options.checksum_type==HW_CHECKSUMMING) {
 			/* do we have a checksummed packet? */
-			if (*(__u8*)(hdr_ptr+11)&
-			    QETH_EXT_HEADER_CSUM_TRANSP_REQ) {
-				/* skb->ip_summed is set already */
 
-				/* vlan is not an issue here, it's still in
+			/* we only check for TCP/UDP checksums when the
+			 * pseudo header was also checked sucessfully -- for
+			 * the rest of the packets, it's not clear, whether
+			 * the upper layer csum is alright. And they
+			 * shouldn't occur too often anyway in real life */
+			if ( (*(__u8*)(hdr_ptr+11)&
+			      (QETH_EXT_HEADER_CSUM_HDR_REQ|
+			       QETH_EXT_HEADER_CSUM_TRANSP_REQ)) ==
+			      (QETH_EXT_HEADER_CSUM_HDR_REQ|
+			       QETH_EXT_HEADER_CSUM_TRANSP_REQ) ) {
+				/* csum does not need to be set
+				 * inbound anyway
+				 *
+				 * vlan is not an issue here, it's still in
 				 * the QDIO header, not pushed in the
-				 * skb yet */
+				 * skb yet *
 				int ip_len=(skb->data[0]&0x0f)<<2;
 
 				if (*(__u8*)(hdr_ptr+11)&
 				    QETH_EXT_HEADER_CSUM_TRANSP_FRAME_TYPE) {
-					/* get the UDP checksum */
+					* get the UDP checksum *
 					skb->csum=*(__u16*)
 						(&skb->data[ip_len+
 						 QETH_UDP_CSUM_OFFSET]);
 				} else {
-					/* get the TCP checksum */
+					* get the TCP checksum *
 					skb->csum=*(__u16*)
 						(&skb->data[ip_len+
 						 QETH_TCP_CSUM_OFFSET]);
 				}
+				 */
+				skb->ip_summed=CHECKSUM_UNNECESSARY;
 			} else {
 				/* make the stack check it */
-				skb->ip_summed=SW_CHECKSUMMING;
+				skb->ip_summed=CHECKSUM_NONE;
 			}
+		} else {
+			skb->ip_summed=card->options.checksum_type;
 		}
 
 #ifdef QETH_VLAN
@@ -1735,8 +1787,8 @@ static void qeth_read_in_buffer(qeth_car
 				   buffer_no]);
 }
 
-static void qeth_fill_header(qeth_hdr_t *hdr,struct sk_buff *skb,
-	       		     int version,int multicast)
+static inline void qeth_fill_header(qeth_hdr_t *hdr,struct sk_buff *skb,
+		     		    int version,int multicast)
 {
 #ifdef QETH_DBF_LIKE_HELL
 	char dbf_text[15];
@@ -1750,14 +1802,17 @@ static void qeth_fill_header(qeth_hdr_t 
 
 #ifdef QETH_VLAN
         /* before we're going to overwrite 
-	   this location with next hop ip 
-	*/
+	 * this location with next hop ip.
+	 * v6 uses passthrough, v4 sets the tag in the QDIO header */
 	card = (qeth_card_t *)skb->dev->priv;
 	if ((card->vlangrp != NULL) && 
-	    (version == 4)          &&
 	    vlan_tx_tag_present(skb)) 
 	{
-		hdr->ext_flags = QETH_EXT_HEADER_VLAN_FRAME;
+		if (version == 4) {
+			hdr->ext_flags = QETH_EXT_HEADER_VLAN_FRAME;
+		} else {
+			hdr->ext_flags = QETH_EXT_HEADER_INCLUDE_VLAN_TAG;
+		}
 		hdr->vlan_id  = vlan_tx_tag_get(skb);
 	}
 #endif
@@ -1820,7 +1875,13 @@ static void qeth_fill_header(qeth_hdr_t 
 			    skb->dev->broadcast,6)) { /* broadcast? */
 			hdr->flags=QETH_CAST_BROADCAST|QETH_HEADER_PASSTHRU;
 		} else {
-			hdr->flags=QETH_CAST_UNICAST|QETH_HEADER_PASSTHRU;
+			if (multicast==RTN_MULTICAST) {
+				hdr->flags=QETH_CAST_MULTICAST|
+					QETH_HEADER_PASSTHRU;
+			} else {
+				hdr->flags=QETH_CAST_UNICAST|
+					QETH_HEADER_PASSTHRU;
+			}
 		}
 	}
 #ifdef QETH_DBF_LIKE_HELL
@@ -1836,7 +1897,7 @@ static void qeth_fill_header(qeth_hdr_t 
 #endif /* QETH_DBF_LIKE_HELL */
 }
 
-static int inline qeth_fill_buffer(qdio_buffer_t *buffer,char *dataptr,
+static inline int qeth_fill_buffer(qdio_buffer_t *buffer,char *dataptr,
 		       		   int length,int element)
 {
 	int length_here;
@@ -1891,8 +1952,8 @@ static int inline qeth_fill_buffer(qdio_
 	return element;
 }
 
-static void qeth_flush_packed_packets(qeth_card_t *card,int queue,
-				      int under_int)
+static inline void qeth_flush_packed_packets(qeth_card_t *card,int queue,
+	       				     int under_int)
 {
 	qdio_buffer_t *buffer;
 	int result;
@@ -1951,8 +2012,23 @@ static void qeth_flush_packed_packets(qe
 	 * adapter honors it or not */
 	switch (card->send_state[queue]) {
  	case SEND_STATE_DONT_PACK:
+		/* only request a PCI, if the fill level of the queue
+		 * is close to the high watermark, so that we don't
+		 * loose initiative during packing */
 		if (atomic_read(&card->outbound_used_buffers[queue])
 		    <HIGH_WATERMARK_PACK-WATERMARK_FUZZ) break;
+
+		last_pci=atomic_read(&card->last_pci_pos[queue]);
+		/* compensate queues that wrapped around */
+		if (position_for_do_qdio<last_pci)
+			last_pci-=QDIO_MAX_BUFFERS_PER_Q;
+
+		/* reduce the number of PCIs in cases where we are always
+		 * a little below the high watermark for packing -- request
+		 * PCIs less frequently */
+		if (position_for_do_qdio-last_pci<
+		    HIGH_WATERMARK_PACK-WATERMARK_FUZZ) break;
+
 		/* set the PCI bit */
 		card->outbound_ringbuffer[queue]->
 			buffer[position_for_do_qdio].element[0].flags|=0x40;
@@ -1966,13 +2042,13 @@ static void qeth_flush_packed_packets(qe
 		 * last_pci is the position of the last pci we've set
 		 * position_for_do_qdio is the position we will send out now
 		 * outbound_used_buffers is the number of buffers used (means
-		 *   all buffers hydra has, inclusive position_for_do_qdio)
+		 *   all buffers OSA has, inclusive position_for_do_qdio)
 		 *
 		 * we have to request a pci, if we have got the buffer of the
 		 * last_pci position back.
 		 *
 		 * position_for_do_qdio-outbound_used_buffers is the newest
-		 *   buffer that we got back from hydra
+		 *   buffer that we got back from OSA
 		 *
 		 * if this is greater or equal than the last_pci position,
 		 * we should request a pci, as no pci request is
@@ -2055,8 +2131,8 @@ static inline int qeth_determine_send_er
 	return ERROR_LINK_FAILURE; /* should never happen */
 }
 
-static void qeth_free_buffer(qeth_card_t *card,int queue,int bufno,
-	       		     int qdio_error,int siga_error)
+static inline void qeth_free_buffer(qeth_card_t *card,int queue,int bufno,
+		     		    int qdio_error,int siga_error)
 {
 	struct sk_buff *skb;
 	int error;
@@ -2139,7 +2215,8 @@ static void qeth_free_buffer(qeth_card_t
 			case ERROR_LINK_FAILURE:
 			case ERROR_KICK_THAT_PUPPY:
 				QETH_DBF_TEXT4(0,trace,"endeglnd");
-				dst_link_failure(skb);
+				card->stats->tx_dropped++;
+				card->stats->tx_errors++;
 				atomic_dec(&skb->users);
 				dev_kfree_skb_irq(skb);
 				break;
@@ -2164,7 +2241,7 @@ static void qeth_free_buffer(qeth_card_t
 	card->send_retries[queue][bufno]=0;
 }
 
-static void qeth_free_all_skbs(qeth_card_t *card)
+static inline void qeth_free_all_skbs(qeth_card_t *card)
 {
 	int q,b;
 
@@ -2199,7 +2276,7 @@ static inline void qeth_flush_buffer(qet
 }
 #ifdef QETH_VLAN
 
-void qeth_insert_ipv6_vlan_tag(struct sk_buff *__skb)
+static inline void qeth_insert_ipv6_vlan_tag(struct sk_buff *__skb)
 {
 
 	/* Move the mac addresses to the beginning of the new header.
@@ -2230,9 +2307,9 @@ void qeth_insert_ipv6_vlan_tag(struct sk
 
 
 
-static void qeth_send_packet_fast(qeth_card_t *card,struct sk_buff *skb,
-				  struct net_device *dev,
-				  int queue,int version,int multicast)
+static inline void qeth_send_packet_fast(qeth_card_t *card,struct sk_buff *skb,
+	       				 struct net_device *dev,
+	       				 int queue,int version,int multicast)
 {
 	qeth_ringbuffer_element_t *mybuffer;
 	int position;
@@ -2250,8 +2327,8 @@ static void qeth_send_packet_fast(qeth_c
 		if ((version)&&(!card->realloc_message)) {
 			card->realloc_message=1;
 			PRINT_WARN("%s: not enough headroom in skb. " \
-				   "Try increasing the " \
-				   "add_hhlen parameter by %i.\n",
+				   "Increasing the " \
+				   "add_hhlen parameter by %i may help.\n",
 				   card->dev_name,
 				   QETH_HEADER_SIZE-skb_headroom(skb));
 		}
@@ -2327,9 +2404,11 @@ static void qeth_send_packet_fast(qeth_c
 
 /* no checks, if all elements are used, as then we would not be here (at most
    127 buffers are enqueued) */
-static void qeth_send_packet_packed(qeth_card_t *card,struct sk_buff *skb,
-       				    struct net_device *dev,
-       				    int queue,int version,int multicast)
+static inline void qeth_send_packet_packed(qeth_card_t *card,
+					   struct sk_buff *skb,
+					   struct net_device *dev,
+					   int queue,int version,
+					   int multicast)
 {
 	qeth_ringbuffer_element_t *mybuffer;
 	int elements_needed;
@@ -2490,8 +2569,8 @@ static __inline__ int atomic_return_sub(
 	return old_val;
 }
 
-static int qeth_do_send_packet(qeth_card_t *card,struct sk_buff *skb,
-       			       struct net_device *dev)
+static inline int qeth_do_send_packet(qeth_card_t *card,struct sk_buff *skb,
+	       			      struct net_device *dev)
 {
         int queue,result=0;
 	int multicast,version;
@@ -2610,12 +2689,32 @@ static int qeth_hard_start_xmit(struct s
         qeth_card_t *card;
 	char dbf_text[15];
 	int result;
+	unsigned long stackptr;
 
         card=(qeth_card_t*)(dev->priv);
 
         if (skb==NULL)
 		return 0;
 
+#ifdef CONFIG_ARCH_S390X
+	asm volatile ("lgr %0,15" : "=d" (stackptr));
+#else /* CONFIG_ARCH_S390X */
+	asm volatile ("lr %0,15" : "=d" (stackptr));
+#endif /* CONFIG_ARCH_S390X */
+	/* prevent stack overflows */
+	/* normal and async stack is both 8k on s390 and 16k on s390x,
+	 * so it doesn't matter whether we're in an interrupt */
+	if ( (stackptr & STACK_PTR_MASK)<
+	     (sizeof(struct task_struct) + WORST_CASE_STACK_USAGE) ) {
+		PRINT_ERR("delaying packet transmission " \
+		       	  "due to potential stack overflow\n");
+		sprintf(dbf_text,"STOF%4x",card->irq0);
+		QETH_DBF_TEXT1(1,trace,dbf_text);
+		PRINT_ERR("Backtrace follows:\n");
+		show_trace((unsigned long *)stackptr);
+		return -EBUSY;
+	}
+
 #ifdef QETH_DBF_LIKE_HELL
 	QETH_DBF_HEX4(0,data,skb->data,__max(QETH_DBF_DATA_LEN,skb->len));
 #endif /* QETH_DBF_LIKE_HELL */
@@ -2624,7 +2723,8 @@ static int qeth_hard_start_xmit(struct s
 
 	if (!card) {
 		QETH_DBF_TEXT2(0,trace,"XMNSNOCD");
-		dst_link_failure(skb);
+		card->stats->tx_dropped++;
+		card->stats->tx_errors++;
 		dev_kfree_skb_irq(skb);
 		return 0;
 	}
@@ -2637,11 +2737,29 @@ static int qeth_hard_start_xmit(struct s
 		card->stats->tx_carrier_errors++;
 		sprintf(dbf_text,"XMNS%4x",card->irq0);
 		QETH_DBF_TEXT2(0,trace,dbf_text);
-		dst_link_failure(skb);
+		card->stats->tx_dropped++;
+		card->stats->tx_errors++;
 		dev_kfree_skb_irq(skb);
 		return 0;
 	}
 
+	if (dev->hard_header == qeth_fake_header) {
+		/*
+		 * in theory, if we run in undef-ed QETH_IPV6, we should
+		 * always unshare, because we do skb_push, then overwrite
+		 * that place with OSA header in qeth_send_packet_fast().
+		 * But it is only visible to one application - tcpdump.
+		 * Nobody else cares if (fake) MAC header gets smashed.
+		 * So, we only do it if fake_ll is in effect.
+		 */
+		if ((skb = qeth_pskb_unshare(skb, GFP_ATOMIC)) == NULL) {
+			card->stats->tx_dropped++;
+			dev_kfree_skb_irq(skb);
+			return 0;
+		}
+		skb_pull(skb, QETH_FAKE_LL_LEN);
+	}
+
 	result=qeth_do_send_packet(card,skb,dev);
 
 	if (!result)
@@ -2650,6 +2768,36 @@ static int qeth_hard_start_xmit(struct s
 	return result;
 }
 
+/*
+ * This function is needed to tell af_packet.c to process headers.
+ * It is not called from there, but only from the transmit path,
+ * when we do not need any actual header.
+ *
+ * N.B. Why do we insist on kludging here instead of fixing tcpdump?
+ * Because tcpdump is shared among gazillions of platforms, and
+ * there is a) no reliable way to identify qeth or its packets
+ * in pcap-linux.c (sll->sll_halen is the only hope); b) no easy
+ * way to pass this information from libpcap to tcpdump proper.
+ *
+ * XXX This fails with TR: traffic flows ok, but tcpdump remains confused.
+ */
+int qeth_fake_header(struct sk_buff *skb, struct net_device *dev,
+		     unsigned short type, void *daddr, void *saddr,
+		     unsigned len)
+{
+	unsigned char *hdr;
+
+	hdr = skb_push(skb, QETH_FAKE_LL_LEN);
+	memcpy(hdr, "FAKELLFAKELL", ETH_ALEN*2);
+	if (type != ETH_P_802_3)
+		*(u16 *)(hdr + ETH_ALEN*2) = htons(type);
+	else
+		*(u16 *)(hdr + ETH_ALEN*2) = htons(len);
+
+	/* XXX Maybe dev->hard_header_len here? Then skb_pull by same size. */
+	return QETH_FAKE_LL_LEN;
+}
+
 static struct net_device_stats* qeth_get_stats(struct net_device *dev)
 {
         qeth_card_t *card;
@@ -2803,23 +2951,19 @@ static int qeth_sleepon_ioctl(qeth_card_
 	return retval;
 }
 
-static void qeth_wakeup_procfile(void) 
-{
-	QETH_DBF_TEXT5(0,trace,"procwkup");
-	if (atomic_read(&qeth_procfile_ioctl_sem.count)<
-	    PROCFILE_SLEEP_SEM_MAX_VALUE)
-  		up(&qeth_procfile_ioctl_sem);
-}
-
-
-static int qeth_sleepon_procfile(void)
+static void qeth_snmp_notify(void)
 {
-	QETH_DBF_TEXT5(0,trace,"procslp");
-	if (down_interruptible(&qeth_procfile_ioctl_sem)) {
-      		up(&qeth_procfile_ioctl_sem);
-      		return -ERESTARTSYS;
+	/*notify all  registered processes */
+	struct list_head *l;
+	struct qeth_notify_list *n_entry;
+
+	QETH_DBF_TEXT5(0,trace,"snmpnoti");
+	spin_lock(&notify_lock);
+	list_for_each(l, &notify_list) {
+		n_entry = list_entry(l, struct qeth_notify_list, list);
+		send_sig(n_entry->signum, n_entry->task, 1);
 	}
-	return 0;
+	spin_unlock(&notify_lock);
 }
 
 static char* qeth_send_control_data(qeth_card_t *card,unsigned char *buffer,
@@ -2889,17 +3033,19 @@ again:
 		QETH_DBF_TEXT2(0,trace,"scd:doio");
 		sprintf(dbf_text,"%4x",(__s16)result);
 		QETH_DBF_TEXT2(0,trace,dbf_text);
+		/* re-enable qeth_send_control_data again */
+		atomic_set(&card->write_busy,0);
 		return NULL;
 	}
 
 	if (intparam==IPA_IOCTL_STATE) {
 		if (qeth_sleepon_ioctl(card,QETH_IPA_TIMEOUT)) {
-			QETH_DBF_TEXT2(0,trace,"scd:ioctime");
+			QETH_DBF_TEXT2(0,trace,"scd:ioct");
 			/* re-enable qeth_send_control_data again */
 			atomic_set(&card->write_busy,0);
 			return NULL;
 		}
-		rec_buf=card->ipa_buf;
+		rec_buf=card->dma_stuff->recbuf;
 		sprintf(dbf_text,"scro%4x",card->irq0);
 	} else {
 		if (qeth_sleepon(card,(setip)?QETH_IPA_TIMEOUT:
@@ -2963,6 +3109,15 @@ static int qeth_send_ipa_cmd(qeth_card_t
 		if ((ipa_cmd==IPA_CMD_SETADAPTERPARMS)&&(result==0)) {
 			result=reply->data.setadapterparms.return_code;
 		}
+		if ( (ipa_cmd==IPA_CMD_SETASSPARMS) &&
+		     (result==0) &&
+		     (reply->data.setassparms.assist_no==
+		      IPA_INBOUND_CHECKSUM) &&
+		     (reply->data.setassparms.command_code==
+		      IPA_CMD_ASS_START) ) {
+			card->csum_enable_mask=
+				reply->data.setassparms.data.flags_32bit;
+		}
 	}
         return result;
 }
@@ -3183,6 +3338,18 @@ static int qeth_ioctl_handle_snmp_data(q
 
 static int qeth_ioctl_handle_arp_data(qeth_card_t *card, arp_cmd_t *reply) 
 {
+	if ( (reply->data.setassparms.command_code==
+	      IPA_CMD_ASS_ARP_SET_NO_ENTRIES) ||
+	     (reply->data.setassparms.command_code==
+	      IPA_CMD_ASS_ARP_ADD_ENTRY) ||
+	     (reply->data.setassparms.command_code==
+	      IPA_CMD_ASS_ARP_REMOVE_ENTRY) ) {
+		if (reply->data.setassparms.return_code) {
+			return ARP_RETURNCODE_ERROR;
+		} else {
+			return ARP_RETURNCODE_LASTREPLY;
+		}
+	}
 	if (reply->data.setassparms.seq_no == 1) {
 		if (card->ioctl_buffersize <= 
 		    (sizeof(__u16) + sizeof(int) + reply->data.
@@ -3229,6 +3396,21 @@ static int qeth_ioctl_handle_arp_data(qe
 	}
 	return card->ioctl_returncode;
 }
+static int qeth_is_arp_command(int cmd)
+{
+	switch (cmd) {
+		case IPA_CMD_ASS_ARP_SET_NO_ENTRIES:
+		case IPA_CMD_ASS_ARP_QUERY_CACHE:
+		case IPA_CMD_ASS_ARP_ADD_ENTRY:
+		case IPA_CMD_ASS_ARP_REMOVE_ENTRY:
+		case IPA_CMD_ASS_ARP_FLUSH_CACHE:
+		case IPA_CMD_ASS_ARP_QUERY_INFO:
+		case IPA_CMD_ASS_ARP_QUERY_STATS:
+			return 1;
+		default:
+			return 0;
+	}
+}
 
 static int qeth_look_for_arp_data(qeth_card_t *card) 
 {
@@ -3245,9 +3427,7 @@ static int qeth_look_for_arp_data(qeth_c
 		result=ARP_FLUSH;
 	} else if ( (reply->command == IPA_CMD_SETASSPARMS) &&
 	     (reply->data.setassparms.assist_no == IPA_ARP_PROCESSING) &&
-	     (reply->data.setassparms.command_code == 
-	      IPA_CMD_ASS_ARP_QUERY_INFO) &&
-	     (card->ioctl_returncode == ARP_RETURNCODE_SUCCESS)) {
+	     (qeth_is_arp_command(reply->data.setassparms.command_code)) ) {
 		result = qeth_ioctl_handle_arp_data(card,reply);
 	} else if ( (reply->command == IPA_CMD_SETADAPTERPARMS)	&&
 	            (reply->data.setadapterparms.command_code == 
@@ -3305,8 +3485,9 @@ static int qeth_queryarp(qeth_card_t *ca
 		result = IPA_REPLY_SUCCESS;
 		memcpy(((char *)(card->ioctl_data_buffer)) + sizeof(__u16),
 		       &(card->number_of_entries),sizeof(int));
-		copy_to_user(req->ifr_ifru.ifru_data,
-			     card->ioctl_data_buffer,data_size);		
+		if (copy_to_user(req->ifr_ifru.ifru_data,
+			         card->ioctl_data_buffer,data_size))
+			result =-EFAULT;
 	}
 	card->ioctl_buffer_pointer = NULL;
 	vfree(card->ioctl_data_buffer);
@@ -3373,16 +3554,14 @@ static int qeth_send_snmp_control(qeth_c
 		result = IPA_REPLY_FAILED;
 		goto snmp_out;
 	}
-	if (result == ARP_RETURNCODE_ERROR ) {
-		copy_to_user(req->ifr_ifru.ifru_data+SNMP_REQUEST_DATA_OFFSET,
-			     card->ioctl_data_buffer,card->ioctl_buffersize);
+	if (result == ARP_RETURNCODE_ERROR )
 		result = IPA_REPLY_FAILED;
-	}
-	else {
-		copy_to_user(req->ifr_ifru.ifru_data+SNMP_REQUEST_DATA_OFFSET,
-			     card->ioctl_data_buffer,card->ioctl_buffersize);
+	else
 		result = IPA_REPLY_SUCCESS;
-	}
+
+	if (copy_to_user(req->ifr_ifru.ifru_data + SNMP_REQUEST_DATA_OFFSET,
+			 card->ioctl_data_buffer, card->ioctl_buffersize))
+		result = -EFAULT;
 snmp_out:
 	card->number_of_entries = 0;
 	card->ioctl_buffersize = 0;
@@ -3571,6 +3750,11 @@ static int qeth_send_setdelipm(qeth_card
 			  (result==0xe00e)?"unsupported arp assist cmd": \
 			  (result==0xe00f)?"arp assist not enabled": \
 			  (result==0xe080)?"startlan disabled": \
+			  (result==0xf012)?"unicast IP address invalid": \
+			  (result==0xf013)?"multicast router limit reached": \
+			  (result==0xf014)?"stop assist not supported": \
+			  (result==0xf015)?"multicast assist not set": \
+			  (result==0xf080)?"VM: startlan disabled": \
 			  (result==-1)?"IPA communication timeout": \
 			  "unknown return code")
 
@@ -3612,7 +3796,8 @@ retry:
 		QETH_DBF_TEXT2(0,trace,dbf_text);
 	}
 
-	if (((result==-1)||(result==0xe080))&&(retries--)) {
+	if ( ((result==-1)||(result==0xe080)||(result==0xf080))&&
+	     (retries--) ) {
 		sprintf(dbf_text,"sipr%4x",card->irq0);
 		QETH_DBF_TEXT2(0,trace,dbf_text);
 		if (ip_vers==4) {
@@ -3771,8 +3956,8 @@ static void qeth_set_vipas(qeth_card_t *
      					      le is last entry */
 	char dbf_text[15];
 	int result;
-	__u8 netmask[16]={0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
-		0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
+	__u8 netmask[16]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+		0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
 	qeth_vipa_entry_t *priv_add_list=NULL;
 	qeth_vipa_entry_t *priv_del_list=NULL;
 
@@ -3790,6 +3975,7 @@ static void qeth_set_vipas(qeth_card_t *
 					GFP_KERNEL);
 			if (ne) {
 				ne->version=e->version;
+				ne->flag=e->flag;
 				memcpy(ne->ip,e->ip,16);
 				ne->next=priv_add_list;
 				priv_add_list=ne;
@@ -3821,6 +4007,7 @@ static void qeth_set_vipas(qeth_card_t *
 					GFP_KERNEL);
 			if (ne) {
 				ne->version=e->version;
+				ne->flag=e->flag;
 				memcpy(ne->ip,e->ip,16);
 				ne->next=priv_del_list;
 				priv_del_list=ne;
@@ -3852,7 +4039,7 @@ static void qeth_set_vipas(qeth_card_t *
 			sprintf(dbf_text,"%4x%4x",card->irq0,result);
 			QETH_DBF_TEXT2(0,trace,dbf_text);
 			if (priv_add_list->version==4) {
-				PRINT_ERR("going to leave vipa/rxip %08x" \
+				PRINT_ERR("going to leave vipa/rxip x%08x " \
 					  "unset...\n",
 					  *((__u32*)&priv_add_list->ip[0]));
 				sprintf(dbf_text,"%08x",
@@ -4404,9 +4591,12 @@ static void qeth_clone_ifa6(struct inet6
 }
 #endif /* QETH_IPV6 */
 
+
+
 #define QETH_STANDARD_RETVALS \
 		ret_val=-EIO; \
 		if (result==IPA_REPLY_SUCCESS) ret_val=0; \
+		if (result==-EFAULT) ret_val=-EFAULT; \
 		if (result==IPA_REPLY_FAILED) ret_val=-EIO; \
 		if (result==IPA_REPLY_OPNOTSUPP) ret_val=-EOPNOTSUPP
 
@@ -4429,7 +4619,14 @@ static int qeth_do_ioctl(struct net_devi
 
 	if ((cmd<SIOCDEVPRIVATE) || (cmd>SIOCDEVPRIVATE+5))
 		return -EOPNOTSUPP;
-	copy_from_user(buff,rq->ifr_ifru.ifru_data,sizeof(buff));
+	if (copy_from_user(buff,rq->ifr_ifru.ifru_data,sizeof(buff)))
+		return -EFAULT;
+	data=buff;
+
+	if ((cmd<SIOCDEVPRIVATE) || (cmd>SIOCDEVPRIVATE+5))
+		return -EOPNOTSUPP;
+	if (copy_from_user(buff,rq->ifr_ifru.ifru_data,sizeof(buff)))
+		return -EFAULT;
 	data=buff;
 
 	if ( (!atomic_read(&card->is_registered))||
@@ -4438,9 +4635,14 @@ static int qeth_do_ioctl(struct net_devi
 
 	if (atomic_read(&card->shutdown_phase)) return -ENODEV;
 
-	my_spin_lock(&card->ioctl_lock);
+	if (down_interruptible ( &card->ioctl_sem ) )
+		return -ERESTARTSYS;
+
+	if (atomic_read(&card->shutdown_phase)) {
+		ret_val=-ENODEV;
+		goto out;
+	}
 
-	if (atomic_read(&card->shutdown_phase)) return -ENODEV;
 	if ( (!atomic_read(&card->is_registered))||
 	     (!atomic_read(&card->is_hardsetup))||
 	     (atomic_read(&card->is_gone)) ) {
@@ -4486,7 +4688,7 @@ static int qeth_do_ioctl(struct net_devi
 			ret_val=-EPERM;
 			break;
 		}
-		for (i=4;i<12;i++) if (data[i]) version=6;
+		for (i=12;i<24;i++) if (data[i]) version=6;
 		result=qeth_send_setassparms(card,version,IPA_ARP_PROCESSING,
 					     IPA_CMD_ASS_ARP_REMOVE_ENTRY,
 					     (long)data,16);
@@ -4503,17 +4705,26 @@ static int qeth_do_ioctl(struct net_devi
 		QETH_STANDARD_RETVALS;
 		break;
 	case SIOCDEVPRIVATE+5:
-		result=qeth_send_snmp_control(card,rq,IPA_CMD_SETADAPTERPARMS,
+		result=qeth_send_snmp_control(card,rq,
+					      IPA_CMD_SETADAPTERPARMS,
 					      IPA_SETADP_SET_SNMP_CONTROL,
 					      data,4);
 		QETH_STANDARD_RETVALS;
 		break;
+	case SIOCDEVPRIVATE+6:
+		if (!card->is_guest_lan &&
+		    (card->type == QETH_CARD_TYPE_OSAE))
+			ret_val = 1;
+		else
+			ret_val = 0;
+		break;
 
 	default:
-		return -EOPNOTSUPP;
+		ret_val=-EOPNOTSUPP;
+		goto out;
 	}
 out:
-	my_spin_unlock(&card->ioctl_lock);
+	up (&card->ioctl_sem);
 
 	sprintf(dbf_text,"ret=%4x",ret_val);
 	QETH_DBF_TEXT2(0,trace,dbf_text);
@@ -5240,13 +5451,17 @@ static int qeth_softsetup_card(qeth_card
 					   "failure -- please check the " \
 					   "network, plug in the cable or " \
 					   "enable the OSA port":
+					   (result==0xf080)?
+					   "startlan disabled (VM: LAN " \
+					   "is offline for functions " \
+					   "requiring LAN access.":
 					   "unknown return code");
 				sprintf(dbf_text,"stln%4x",result);
 				QETH_DBF_TEXT2(0,trace,dbf_text);
 				atomic_set(&card->is_softsetup,0);
 				atomic_set(&card->is_startlaned,0);
 				/* do not return an error */
-				if (result==0xe080) {
+				if ((result==0xe080)||(result==0xf080)) {
 					result=0;
 				}
 				goto out;
@@ -5372,7 +5587,8 @@ static int qeth_softsetup_card(qeth_card
 					QETH_DBF_TEXT2(0,trace,dbf_text);
 					atomic_set(&card->is_softsetup,0);
 					/* do not return an error */
-					if (result==0xe080) {
+					if ((result==0xe080)||
+					    (result==0xf080)) {
 						result=0;
 					}
 					goto out;
@@ -5390,8 +5606,9 @@ static int qeth_softsetup_card(qeth_card
 				goto out;
 			}
 
-			sprintf(dbf_text,"%4x%4x",card->ipa6_supported,
-				card->ipa6_enabled);
+			sprintf(dbf_text,"%8x",card->ipa6_supported);
+			QETH_DBF_TEXT2(0,trace,dbf_text);
+			sprintf(dbf_text,"%8x",card->ipa6_enabled);
 			QETH_DBF_TEXT2(0,trace,dbf_text);
 			QETH_DBF_TEXT2(0,trace,"enaipv46");
                         result=qeth_send_setassparms_simple_with_data(
@@ -5461,8 +5678,19 @@ static int qeth_softsetup_card(qeth_card
 				goto go_on_filt;
 			}
 			card->dev->flags|=IFF_BROADCAST;
-			card->broadcast_capable=1;
+			card->broadcast_capable=BROADCAST_WITH_ECHO;
 
+			result=qeth_send_setassparms_simple_with_data(
+                                card,IPA_FILTERING,IPA_CMD_ASS_ENABLE,1);
+			sprintf(dbf_text,"Flt3%4x",result);
+			QETH_DBF_TEXT2(0,trace,dbf_text);
+			QETH_DBF_TEXT2(0,setup,dbf_text);
+			if (!result) {
+				PRINT_INFO("Broadcast packets will not be " \
+					   "echoed back on %s.\n",
+					   card->dev_name);
+				card->broadcast_capable=BROADCAST_WITHOUT_ECHO;
+			}
 		}
 go_on_filt:
 		if (card->options.checksum_type==HW_CHECKSUMMING) {
@@ -5494,7 +5722,7 @@ go_on_filt:
 				result=qeth_send_setassparms_simple_with_data(
 					card,IPA_INBOUND_CHECKSUM,
 					IPA_CMD_ASS_ENABLE,
-					IPA_CHECKSUM_ENABLE_MASK);
+					card->csum_enable_mask);
 				if (result) {
 					PRINT_WARN("Could not enable inbound " \
 						   "checksumming on %s: " \
@@ -5571,7 +5799,14 @@ go_on_checksum:
 
 #ifdef QETH_IPV6
 	if (atomic_read(&card->enable_routing_attempts6)) {
-		if (card->options.routing_type6) {
+		/* for OSAs that can't do v6 multicast routing, we don't try */
+		if ( (card->type==QETH_CARD_TYPE_OSAE) &&
+		     ( (card->options.routing_type6&ROUTER_MASK) ==
+		       MULTICAST_ROUTER) &&
+		     (!qeth_is_supported6(IPA_OSA_MC_ROUTER_AVAIL)) ) {
+			atomic_set(&card->enable_routing_attempts6,0);
+			atomic_set(&card->rt6fld,0);
+		} else if (card->options.routing_type6) {
 			sprintf(dbf_text,"strtg6%2x",
 				card->options.routing_type6);
 			QETH_DBF_TEXT2(0,trace,dbf_text);
@@ -5753,9 +5988,12 @@ static void qeth_recover(void *data)
 	sprintf(dbf_text,"PROB%4x",i);
 	QETH_DBF_TEXT2(0,trace,dbf_text);
 
-        PRINT_WARN("recovery was scheduled on irq 0x%x (%s) with " \
-		   "problem 0x%x\n",
-                   card->irq0,card->dev_name,i);
+	if (i!=PROBLEM_TX_TIMEOUT) {
+		PRINT_WARN("recovery was scheduled on irq 0x%x (%s) with " \
+			   "problem 0x%x\n",
+			   card->irq0,card->dev_name,i);
+	}
+
         switch (i) {
         case PROBLEM_RECEIVED_IDX_TERMINATE:
 		if (atomic_read(&card->in_recovery))
@@ -5802,7 +6040,7 @@ static void qeth_recover(void *data)
         }
 }
 
-static void qeth_schedule_recovery(qeth_card_t *card)
+static inline void qeth_schedule_recovery(qeth_card_t *card)
 {
 	if (card) {
    		INIT_LIST_HEAD(&card->tqueue.list);
@@ -5920,6 +6158,9 @@ static void qeth_qdio_output_handler(int
 	card=(qeth_card_t *)card_ptr;
 
 	if (status&QDIO_STATUS_LOOK_FOR_ERROR) {
+		sbalf15=(card->outbound_ringbuffer[queue]->buffer[
+			 (first_element+count-1)&
+			 QDIO_MAX_BUFFERS_PER_Q].element[15].flags)&0xff;
 		if (status&QDIO_STATUS_ACTIVATE_CHECK_CONDITION) {
 			problem=PROBLEM_ACTIVATE_CHECK_CONDITION;
 			PRINT_WARN("activate queues on irq 0x%x: " \
@@ -5937,9 +6178,29 @@ static void qeth_qdio_output_handler(int
 			qeth_schedule_recovery(card);
 			goto out;
 		}
-		sbalf15=(card->outbound_ringbuffer[queue]->buffer[
-			 (first_element+count-1)&
-			 QDIO_MAX_BUFFERS_PER_Q].element[15].flags)&0xff;
+		if ( (siga_error==0x01) ||
+		     (siga_error==(0x02|QDIO_SIGA_ERROR_B_BIT_SET)) ||
+		     (siga_error==0x03) ) {
+			sprintf(dbf_text,"BS%4x%2x",card->irq0,queue);
+			QETH_DBF_TEXT2(0,trace,dbf_text);
+			QETH_DBF_TEXT2(0,qerr,dbf_text);
+			QETH_DBF_TEXT2(1,setup,dbf_text);
+			sprintf(dbf_text,"%2x%2x%2x%2x",
+				first_element+count-1,
+				siga_error,qdio_error,sbalf15);
+			QETH_DBF_TEXT2(1,trace,dbf_text);
+			QETH_DBF_TEXT2(1,qerr,dbf_text);
+			PRINT_ERR("Outbound queue x%x on irq x%x (%s); " \
+				  "errs: siga: x%x, qdio: x%x, flags15: " \
+				  "x%x. The device will be taken down.\n",
+				  queue,card->irq0,card->dev_name,
+				  siga_error,qdio_error,sbalf15);
+			netif_stop_queue(card->dev);
+			qeth_set_dev_flag_norunning(card);
+			atomic_set(&card->problem,PROBLEM_BAD_SIGA_RESULT);
+			qeth_schedule_recovery(card);
+			goto out;
+		}
 		PRINT_STUPID("outbound qdio transfer error on irq %04x, " \
 			     "queue=%i. qdio_error=0x%x (more than one: %c)," \
 			     " siga_error=0x%x (more than one: %c), " \
@@ -5988,7 +6249,7 @@ static void qeth_qdio_output_handler(int
 			      (&card->outbound_used_buffers[queue])<=
 			      LOW_WATERMARK_PACK);
 		/* first_element is the last buffer that we got back
-		 * from hydra */
+		 * from OSA */
 		if (switch_state||last_pci_hit) {
 			*((__u16*)(&dbf_text2[6]))=card->irq0;
 			QETH_DBF_HEX3(0,trace,dbf_text2,QETH_DBF_TRACE_LEN);
@@ -6010,6 +6271,14 @@ static void qeth_qdio_output_handler(int
 				if (switch_state)
 					card->send_state[queue]=
 						SEND_STATE_DONT_PACK;
+
+				/* reset the last_pci position to avoid
+				 * races, when we get close to packing again
+				 * immediately (in order to never loose
+				 * a PCI) */
+				atomic_set(&card->last_pci_pos[queue],
+					   (-2*QDIO_MAX_BUFFERS_PER_Q));
+
 				netif_wake_queue(card->dev);
 				atomic_set(&card->outbound_ringbuffer_lock[
 					   queue],QETH_LOCK_UNLOCKED);
@@ -6137,8 +6406,9 @@ recover:
                 goto wakeup_out;
         }
 
-        if (!IS_IPA(card->dma_stuff->recbuf)||
-            IS_IPA_REPLY(card->dma_stuff->recbuf)) {
+        if ( (!IS_IPA(card->dma_stuff->recbuf))||
+	     (IS_IPA(card->dma_stuff->recbuf)&&
+	      IS_IPA_REPLY(card->dma_stuff->recbuf)) ) {
                 /* setup or unknown data */
 		result = qeth_look_for_arp_data(card);
 		switch (result) {
@@ -6870,6 +7140,10 @@ static int qeth_idx_activate_read(qeth_c
 	card->portname_required=
 		((!QETH_IDX_NO_PORTNAME_REQUIRED(card->dma_stuff->recbuf))&&
 		 (card->type==QETH_CARD_TYPE_OSAE));
+	/* however, as the portname indication of OSA is wrong, we have to
+         * do this: */
+	card->portname_required=(card->type==QETH_CARD_TYPE_OSAE);
+
 
         memcpy(&temp,QETH_IDX_ACT_FUNC_LEVEL(card->dma_stuff->recbuf),2);
         if (temp!=qeth_peer_func_level(card->func_level)) {
@@ -7220,12 +7494,17 @@ static int qeth_ulp_setup(qeth_card_t *c
 static int qeth_qdio_establish(qeth_card_t *card)
 {
 	int result;
-	char adapter_area[15];
+	char *adapter_area;
 	char dbf_text[15];
 	void **input_array,**output_array,**ptr;
 	int i,j;
 	qdio_initialize_t init_data;
 
+	adapter_area=vmalloc(QDIO_MAX_BUFFERS_PER_Q*sizeof(char));
+	if (!adapter_area) return -ENOMEM;
+
+	memset(adapter_area,0,QDIO_MAX_BUFFERS_PER_Q*sizeof(char));
+
 	adapter_area[0]=_ascebc['P'];
 	adapter_area[1]=_ascebc['C'];
 	adapter_area[2]=_ascebc['I'];
@@ -7235,7 +7514,10 @@ static int qeth_qdio_establish(qeth_card
 	*((unsigned int*)(&adapter_area[12]))=PCI_TIMER_VALUE;
 
 	input_array=vmalloc(QDIO_MAX_BUFFERS_PER_Q*sizeof(void*));
-	if (!input_array) return -ENOMEM;
+	if (!input_array) {
+		vfree(adapter_area);
+		return -ENOMEM;
+	}
 	ptr=input_array;
 	for (j=0;j<QDIO_MAX_BUFFERS_PER_Q;j++) {
 		*ptr=(void*)virt_to_phys
@@ -7247,6 +7529,7 @@ static int qeth_qdio_establish(qeth_card
 			     card->no_queues);
 	if (!output_array) {
 		vfree(input_array);
+		vfree(adapter_area);
 		return -ENOMEM;
 	}
 	ptr=output_array;
@@ -7285,6 +7568,7 @@ static int qeth_qdio_establish(qeth_card
 	
 	vfree(input_array);
 	vfree(output_array);
+	vfree(adapter_area);
 
 	sprintf(dbf_text,"qde=%4i",result);
 	QETH_DBF_TEXT3(0,trace,dbf_text);
@@ -7388,6 +7672,51 @@ static int qeth_verify_card(qeth_card_t 
 	return result;
 }
 
+static void qeth_correct_routing_status(qeth_card_t *card)
+{
+	if (card->type==QETH_CARD_TYPE_IQD) {
+		/* if it's not a mc router, it's no router */
+		if ( (card->options.routing_type4 == PRIMARY_ROUTER) ||
+		     (card->options.routing_type4 == SECONDARY_ROUTER)
+#ifdef QETH_IPV6
+		     ||
+		     (card->options.routing_type6 == PRIMARY_ROUTER) ||
+		     (card->options.routing_type6 == SECONDARY_ROUTER)
+#endif /* QETH_IPV6 */
+		     ) {
+			PRINT_WARN("routing not applicable, reset " \
+				   "routing status.\n");
+			card->options.routing_type4=NO_ROUTER;
+#ifdef QETH_IPV6
+			card->options.routing_type6=NO_ROUTER;
+#endif /* QETH_IPV6 */
+		}
+		card->options.do_prio_queueing=NO_PRIO_QUEUEING;
+	} else {
+		/* if it's a mc router, it's no router */
+		if ( (((!qeth_is_supported(IPA_OSA_MC_ROUTER_AVAIL))&&
+		       card->options.routing_type4 == MULTICAST_ROUTER)) ||
+		     (card->options.routing_type4 == PRIMARY_CONNECTOR) ||
+		     (card->options.routing_type4 == SECONDARY_CONNECTOR)
+#ifdef QETH_IPV6
+		     ||
+		     (((!qeth_is_supported(IPA_OSA_MC_ROUTER_AVAIL))&&
+		       card->options.routing_type6 == MULTICAST_ROUTER)) ||
+		     (card->options.routing_type6 == PRIMARY_CONNECTOR) ||
+		     (card->options.routing_type6 == SECONDARY_CONNECTOR)
+#endif /* QETH_IPV6 */
+		     ) {
+			PRINT_WARN("routing not applicable, reset " \
+				   "routing status. (Did you mean " \
+				   "primary_router or secondary_router?)\n");
+			card->options.routing_type4=NO_ROUTER;
+#ifdef QETH_IPV6
+			card->options.routing_type6=NO_ROUTER;
+#endif /* QETH_IPV6 */
+		}
+	}
+}
+
 #ifdef QETH_IPV6
 extern struct neigh_table arp_tbl;
 int (*qeth_old_arp_constructor)(struct neighbour *);
@@ -7567,6 +7896,8 @@ static int qeth_init_dev(struct net_devi
 		(!(qeth_get_additional_dev_flags(card->type)&IFF_NOARP))?
 		(qeth_get_hard_header(card->link_type)?
 		 qeth_hard_header:NULL):
+#else /* QETH_IPV6 */
+		(card->options.fake_ll==FAKE_LL)?qeth_fake_header:
 #endif /* QETH_IPV6 */
 		NULL;
 	dev->header_cache_update=
@@ -7600,7 +7931,7 @@ static int qeth_init_dev(struct net_devi
 	qeth_send_qipassist(card,4);*/
 
 	/* that was the old place. one id. we need to make sure, that
-	 * hydra knows about us going to use the same id again, so we
+	 * OSA knows about us going to use the same id again, so we
 	 * do that in hardsetup_card every time
 	qeth_get_unique_id(card);*/
 
@@ -7650,8 +7981,9 @@ static int qeth_get_unitaddr(qeth_card_t
 	card->unit_addr2 = prcd[31];
 	card->cula = prcd[63];
 	/* Don't build queues with diag98 for VM guest lan. */
-	card->do_pfix = (MACHINE_HAS_PFIX) ? ((prcd[0x10]!=_ascebc['V']) ||
-					      (prcd[0x11]!=_ascebc['M'])):0;
+	card->is_guest_lan= ((prcd[0x10]==_ascebc['V']) &&
+			     (prcd[0x11]==_ascebc['M']));
+	card->do_pfix = (MACHINE_HAS_PFIX) ? (!(card->is_guest_lan)):0;
 
 	sprintf(dbf_text,"chpid:%02x",card->chpid);
 	QETH_DBF_TEXT2(0,trace,dbf_text);
@@ -8041,8 +8373,12 @@ static int qeth_hardsetup_card(qeth_card
 		QETH_DBF_TEXT2(0,trace,dbf_text);
 	}
 
-	sprintf(dbf_text,"%4x%4x",card->ipa_supported,card->ipa_enabled);
+	sprintf(dbf_text,"%8x",card->ipa_supported);
 	QETH_DBF_TEXT2(0,trace,dbf_text);
+	sprintf(dbf_text,"%8x",card->ipa_enabled);
+	QETH_DBF_TEXT2(0,trace,dbf_text);
+
+	qeth_correct_routing_status(card);
 
 	qeth_get_unique_id(card);
 
@@ -8094,7 +8430,8 @@ static int qeth_hardsetup_card(qeth_card
 			       "card%s%s%s\n" \
 			       "with link type %s (portname: %s)\n",
 			       card->devno0,card->devno1,card->devno2,
-			       qeth_get_cardname(card->type),
+			       qeth_get_cardname(card->type,
+						 card->is_guest_lan),
 			       (card->level[0])?" (level: ":"",
 			       (card->level[0])?card->level:"",
 			       (card->level[0])?")":"",
@@ -8102,16 +8439,32 @@ static int qeth_hardsetup_card(qeth_card
 						       card->link_type),
 			       dbf_text);
 		} else {
-			printk("qeth: Device 0x%X/0x%X/0x%X is a%s " \
-			       "card%s%s%s\nwith link type %s " \
-			       "(no portname needed by interface)\n",
-			       card->devno0,card->devno1,card->devno2,
-			       qeth_get_cardname(card->type),
-			       (card->level[0])?" (level: ":"",
-			       (card->level[0])?card->level:"",
-			       (card->level[0])?")":"",
-			       qeth_get_link_type_name(card->type,
-						       card->link_type));
+			if (card->options.portname[0]) {
+				printk("qeth: Device 0x%X/0x%X/0x%X is a%s " \
+				       "card%s%s%s\nwith link type %s " \
+				       "(no portname needed by interface)\n",
+				       card->devno0,card->devno1,card->devno2,
+				       qeth_get_cardname(card->type,
+							 card->is_guest_lan),
+				       (card->level[0])?" (level: ":"",
+				       (card->level[0])?card->level:"",
+				       (card->level[0])?")":"",
+				       qeth_get_link_type_name(card->type,
+							       card->
+							       link_type));
+			} else {
+				printk("qeth: Device 0x%X/0x%X/0x%X is a%s " \
+				       "card%s%s%s\nwith link type %s\n",
+				       card->devno0,card->devno1,card->devno2,
+				       qeth_get_cardname(card->type,
+							 card->is_guest_lan),
+				       (card->level[0])?" (level: ":"",
+				       (card->level[0])?card->level:"",
+				       (card->level[0])?")":"",
+				       qeth_get_link_type_name(card->type,
+							       card->
+							       link_type));
+			}
 		}
 	}
         
@@ -8210,7 +8563,7 @@ static int qeth_reinit_thread(void *para
 			atomic_set(&card->is_startlaned,0);
 			/* show status in /proc/qeth */
 			atomic_set(&card->is_gone,1);
-			qeth_wakeup_procfile();
+			qeth_snmp_notify();
 		} else {
 			QETH_DBF_TEXT1(0,trace,"ri-sftst");
 			qeth_softsetup_card(card,QETH_LOCK_ALREADY_HELD);
@@ -8223,7 +8576,7 @@ static int qeth_reinit_thread(void *para
 			qeth_restore_dev_flag_state(card);
 			atomic_set(&card->is_gone,0);
 			netif_wake_queue(card->dev);
-			qeth_wakeup_procfile();
+			qeth_snmp_notify();
 		}
 		my_spin_unlock(&setup_lock);
 	}
@@ -8324,7 +8677,8 @@ static qeth_card_t *qeth_alloc_card(void
 	spin_lock_init(&card->wait_q_lock);
 	spin_lock_init(&card->softsetup_lock);
 	spin_lock_init(&card->hardsetup_lock);
-	spin_lock_init(&card->ioctl_lock);
+	sema_init(&card->ioctl_sem, 1);
+
 #ifdef QETH_VLAN
 	spin_lock_init(&card->vlan_lock);
         card->vlangrp = NULL;
@@ -8346,6 +8700,8 @@ static qeth_card_t *qeth_alloc_card(void
 	card->ip_mc_new_state.ipm6_ifa=NULL;
 #endif /* QETH_IPV6 */
 
+	card->csum_enable_mask=IPA_CHECKSUM_DEFAULT_ENABLE_MASK;
+
         /* setup net_device stuff */
 	card->dev->priv=card;
 
@@ -8819,7 +9175,7 @@ static void qeth_detach_handler(int irq,
 	if ((card=qeth_get_card_by_irq(irq))) {
 		qeth_remove_card(card,remove_method);
         }
-	qeth_wakeup_procfile();
+	qeth_snmp_notify();
         my_spin_unlock(&setup_lock);
 }
 
@@ -8905,49 +9261,6 @@ static int qeth_get_bufcnt_from_memamnt(
 	return cnt;
 }
 
-static void qeth_correct_routing_status(qeth_card_t *card)
-{
-	if (card->type==QETH_CARD_TYPE_IQD) {
-		/* if it's not a mc router, it's no router */
-		if ( (card->options.routing_type4 == PRIMARY_ROUTER) ||
-		     (card->options.routing_type4 == SECONDARY_ROUTER) 
-#ifdef QETH_IPV6
-		     ||
-		     (card->options.routing_type6 == PRIMARY_ROUTER) ||
-		     (card->options.routing_type6 == SECONDARY_ROUTER) 
-#endif /* QETH_IPV6 */
-		     ) {
-			PRINT_WARN("routing not applicable, reset " \
-				   "routing status.\n");
-			card->options.routing_type4=NO_ROUTER;
-#ifdef QETH_IPV6
-			card->options.routing_type6=NO_ROUTER;
-#endif /* QETH_IPV6 */
-		}
-		card->options.do_prio_queueing=NO_PRIO_QUEUEING;
-	} else {
-		/* if it's a mc router, it's no router */
-		if ( (card->options.routing_type4 == MULTICAST_ROUTER) ||
-		     (card->options.routing_type4 == PRIMARY_CONNECTOR) ||
-		     (card->options.routing_type4 == SECONDARY_CONNECTOR) 
-#ifdef QETH_IPV6
-		     ||
-		     (card->options.routing_type6 == MULTICAST_ROUTER) ||
-		     (card->options.routing_type6 == PRIMARY_CONNECTOR) ||
-		     (card->options.routing_type6 == SECONDARY_CONNECTOR) 
-#endif /* QETH_IPV6 */
-		     ) {
-			PRINT_WARN("routing not applicable, reset " \
-				   "routing status. (Did you mean " \
-				   "primary_router or secondary_router?)\n");
-			card->options.routing_type4=NO_ROUTER;
-#ifdef QETH_IPV6
-			card->options.routing_type6=NO_ROUTER;
-#endif /* QETH_IPV6 */
-		}
-	}
-}
-
 static int qeth_attach_handler(int irq_to_scan,chandev_probeinfo *probeinfo)
 {
 	int result = 0;
@@ -9102,7 +9415,6 @@ correct_order:
 		goto endloop;
 	}
 	
-	qeth_correct_routing_status(card);
 	qeth_insert_card_into_list(card);
 	
 	QETH_DBF_TEXT3(0,trace,"request0");
@@ -9247,7 +9559,7 @@ static void qeth_chandev_msck_notfunc(st
 			/* means, we prevent looping in
 			 * qeth_send_control_data */
 			atomic_set(&card->write_busy,0);
-			qeth_wakeup_procfile();
+			qeth_snmp_notify();
 		}
 		my_read_unlock(&list_lock);
 	}
@@ -9297,7 +9609,7 @@ struct net_device *qeth_chandev_init_net
 	card->tqueue_sst.sync=0;
 	schedule_task(&card->tqueue_sst);
  out:
-	qeth_wakeup_procfile();
+	qeth_snmp_notify();
 	return dev;
 
 }
@@ -9385,11 +9697,10 @@ static int qeth_ip_event(struct notifier
 	sprintf(dbf_text,"ipevent");
 	QETH_DBF_TEXT3(0,trace,dbf_text);
 	QETH_DBF_HEX3(0,trace,&event,sizeof(unsigned long));
-	QETH_DBF_HEX3(0,trace,&dev,sizeof(void*));
-	sprintf(dbf_text,"%08x",ifa->ifa_address);
-	QETH_DBF_TEXT3(0,trace,dbf_text);
-	sprintf(dbf_text,"%08x",ifa->ifa_mask);
-	QETH_DBF_TEXT3(0,trace,dbf_text);
+		sprintf(dbf_text,"%08x",ifa->ifa_address);
+		QETH_DBF_TEXT3(0,trace,dbf_text);
+		sprintf(dbf_text,"%08x",ifa->ifa_mask);
+		QETH_DBF_TEXT3(0,trace,dbf_text);
 
 #ifdef QETH_VLAN
 	if (qeth_verify_dev(dev)==QETH_VERIFY_IS_VLAN_DEV)
@@ -9418,10 +9729,9 @@ static int qeth_ip6_event(struct notifie
 	sprintf(dbf_text,"ip6event");
 	QETH_DBF_TEXT3(0,trace,dbf_text);
 	QETH_DBF_HEX3(0,trace,&event,sizeof(unsigned long));
-	QETH_DBF_HEX3(0,trace,&dev,sizeof(void*));
-	QETH_DBF_HEX3(0,trace,ifa->addr.s6_addr,QETH_DBF_TRACE_LEN);
-	QETH_DBF_HEX3(0,trace,ifa->addr.s6_addr+QETH_DBF_TRACE_LEN,
-		      QETH_DBF_TRACE_LEN);
+		QETH_DBF_HEX3(0,trace,ifa->addr.s6_addr,QETH_DBF_TRACE_LEN);
+		QETH_DBF_HEX3(0,trace,ifa->addr.s6_addr+QETH_DBF_TRACE_LEN,
+			      QETH_DBF_TRACE_LEN);
 
 #ifdef QETH_VLAN
 	if (qeth_verify_dev(dev)==QETH_VERIFY_IS_VLAN_DEV)
@@ -9438,8 +9748,63 @@ static int qeth_ip6_event(struct notifie
 
 	return NOTIFY_DONE;
 }
+
+static int
+qeth_multicast6_event(struct notifier_block *this,
+		     unsigned long event, void *ptr)
+{
+	qeth_card_t *card;
+	struct ifmcaddr6 *mc  = (struct ifmcaddr6 *) ptr;
+	struct net_device *dev = mc->idev->dev;
+	char dbf_text[15];
+
+	sprintf(dbf_text,"mc6event");
+	QETH_DBF_TEXT3(0,trace,dbf_text);
+	QETH_DBF_HEX3(0,trace,&event,sizeof(unsigned long));
+#ifdef QETH_VLAN
+	if (qeth_verify_dev(dev)==QETH_VERIFY_IS_VLAN_DEV)
+		card = (qeth_card_t *)VLAN_DEV_INFO(dev)->real_dev->priv;
+        else
+#endif
+	card=(qeth_card_t *)dev->priv;
+        if (qeth_does_card_exist(card)) {
+		QETH_DBF_HEX3(0,trace,&card,sizeof(void*));
+		qeth_save_dev_flag_state(card);
+		qeth_start_softsetup_thread(card);
+	}
+
+	return NOTIFY_DONE;
+}
+
 #endif /* QETH_IPV6 */
 
+static int
+qeth_multicast_event(struct notifier_block *this,
+		     unsigned long event, void *ptr)
+{
+	qeth_card_t *card;
+	struct ip_mc_list *mc  = (struct ip_mc_list *) ptr;
+	struct net_device *dev = mc->interface->dev;
+	char dbf_text[15];
+
+	sprintf(dbf_text,"mc4event");
+	QETH_DBF_TEXT3(0,trace,dbf_text);
+	QETH_DBF_HEX3(0,trace,&event,sizeof(unsigned long));
+#ifdef QETH_VLAN
+	if (qeth_verify_dev(dev)==QETH_VERIFY_IS_VLAN_DEV)
+		card = (qeth_card_t *)VLAN_DEV_INFO(dev)->real_dev->priv;
+        else
+#endif
+	card=(qeth_card_t *)dev->priv;
+        if (qeth_does_card_exist(card)) {
+		QETH_DBF_HEX3(0,trace,&card,sizeof(void*));
+		qeth_save_dev_flag_state(card);
+		qeth_start_softsetup_thread(card);
+	}
+
+	return NOTIFY_DONE;
+}
+
 static int qeth_reboot_event(struct notifier_block *this,
    			     unsigned long event,void *ptr)
 {
@@ -9533,9 +9898,11 @@ static int qeth_procfile_open(struct ino
 	int size;
 	tempinfo_t *info;
 
+        MOD_INC_USE_COUNT;
 	info = (tempinfo_t *) vmalloc (sizeof (tempinfo_t));
 	if (info == NULL) {
 		PRINT_WARN("No memory available for data\n");
+		MOD_DEC_USE_COUNT;
 		return -ENOMEM;
 	} else {
 		file->private_data = (void *) info;
@@ -9556,6 +9923,7 @@ static int qeth_procfile_open(struct ino
 		PRINT_WARN("No memory available for data\n");
 		vfree (info);
 		rc=-ENOMEM;
+		MOD_DEC_USE_COUNT;
 		goto out;
 	}
 	
@@ -9583,23 +9951,23 @@ static int qeth_procfile_open(struct ino
 			       "by_ToS");
 		}
 
+		/* a '+' in the routing indicator means, that broadcast
+		 * packets are not echoed back to the sender */
 #ifdef QETH_IPV6
-		if (atomic_read(&card->rt4fld) &&
-		    atomic_read(&card->rt6fld))
-			strcpy(router_str, "no");
-		else if (atomic_read(&card->rt4fld) ||
-			 atomic_read(&card->rt6fld))
-			strcpy(router_str, "mix");
+		if (atomic_read(&card->rt4fld) ||
+	   	    atomic_read(&card->rt6fld))
+			strcpy(router_str, "FLD");
 #else /* QETH_IPV6 */
 		if (atomic_read(&card->rt4fld))
-			strcpy(router_str, "no");
+			strcpy(router_str, "FLD");
 #endif /* QETH_IPV6 */		
 		else if ( ((card->options.routing_type4&ROUTER_MASK)==
 		      PRIMARY_ROUTER) 
 #ifdef QETH_IPV6
 		     &&
-		     ((card->options.routing_type6&ROUTER_MASK)==
-		      PRIMARY_ROUTER) 
+		     ( ((card->options.routing_type6&ROUTER_MASK)==
+			PRIMARY_ROUTER)||
+		       (!qeth_is_supported(IPA_IPv6)) )
 #endif /* QETH_IPV6 */
 		     ) {
 			strcpy(router_str,"pri");
@@ -9608,8 +9976,9 @@ static int qeth_procfile_open(struct ino
 		      SECONDARY_ROUTER) 
 #ifdef QETH_IPV6
 		     &&
-		     ((card->options.routing_type6&ROUTER_MASK)==
-		      SECONDARY_ROUTER) 
+		     ( ((card->options.routing_type6&ROUTER_MASK)==
+			SECONDARY_ROUTER)||
+		       (!qeth_is_supported(IPA_IPv6)) )
 #endif /* QETH_IPV6 */
 		     ) {
 			strcpy(router_str,"sec");
@@ -9618,38 +9987,51 @@ static int qeth_procfile_open(struct ino
 		      MULTICAST_ROUTER) 
 #ifdef QETH_IPV6
 		     &&
-		     ((card->options.routing_type6&ROUTER_MASK)==
-		      MULTICAST_ROUTER) 
+		     ( ((card->options.routing_type6&ROUTER_MASK)==
+			MULTICAST_ROUTER)||
+		       (!qeth_is_supported(IPA_IPv6)) )
 #endif /* QETH_IPV6 */
 		     ) {
-			strcpy(router_str,"mc");
+			if (card->broadcast_capable==BROADCAST_WITHOUT_ECHO)
+				strcpy(router_str,"mc+");
+			else
+				strcpy(router_str,"mc");
 		} else
 		if ( ((card->options.routing_type4&ROUTER_MASK)==
 		      PRIMARY_CONNECTOR) 
 #ifdef QETH_IPV6
 		     &&
-		     ((card->options.routing_type6&ROUTER_MASK)==
-		      PRIMARY_CONNECTOR) 
+		     ( ((card->options.routing_type6&ROUTER_MASK)==
+			PRIMARY_CONNECTOR)||
+		       (!qeth_is_supported(IPA_IPv6)) )
 #endif /* QETH_IPV6 */
 		     ) {
-			strcpy(router_str,"p.c");
+			if (card->broadcast_capable==BROADCAST_WITHOUT_ECHO)
+				strcpy(router_str,"p+c");
+			else
+				strcpy(router_str,"p.c");
 		} else
 		if ( ((card->options.routing_type4&ROUTER_MASK)==
 		      SECONDARY_CONNECTOR)
 #ifdef QETH_IPV6
 		     &&
-		     ((card->options.routing_type6&ROUTER_MASK)==
-		      SECONDARY_CONNECTOR) 
+		     ( ((card->options.routing_type6&ROUTER_MASK)==
+			SECONDARY_CONNECTOR)||
+		       (!qeth_is_supported(IPA_IPv6)) )
 #endif /* QETH_IPV6 */
 		     ) {
-			strcpy(router_str,"s.c");
+			if (card->broadcast_capable==BROADCAST_WITHOUT_ECHO)
+				strcpy(router_str,"s+c");
+			else
+				strcpy(router_str,"s.c");
 		} else
 		if ( ((card->options.routing_type4&ROUTER_MASK)==
 		      NO_ROUTER) 
 #ifdef QETH_IPV6
 		     &&
-		     ((card->options.routing_type6&ROUTER_MASK)==
-		      NO_ROUTER) 
+		     ( ((card->options.routing_type6&ROUTER_MASK)==
+			NO_ROUTER)||
+		       (!qeth_is_supported(IPA_IPv6)) )
 #endif /* QETH_IPV6 */
 		     ) {
 			strcpy(router_str,"no");
@@ -9670,7 +10052,8 @@ static int qeth_procfile_open(struct ino
 					card->chpid,
 					card->dev_name,
 					qeth_get_cardname_short
-					(card->type,card->link_type),
+					(card->type,card->link_type,
+					 card->is_guest_lan),
 					card->options.portno);
 		} else if (!atomic_read(&card->is_startlaned)) {
 			length+=sprintf(buffer+length,
@@ -9680,7 +10063,8 @@ static int qeth_procfile_open(struct ino
 					card->chpid,
 					card->dev_name,
 					qeth_get_cardname_short
-					(card->type,card->link_type),
+					(card->type,card->link_type,
+					 card->is_guest_lan),
 					card->options.portno);
 		} else {
 			length+=sprintf(buffer+length,
@@ -9689,7 +10073,8 @@ static int qeth_procfile_open(struct ino
 					card->devno0,card->devno1,card->devno2,
 					card->chpid,card->dev_name,
 					qeth_get_cardname_short
-					(card->type,card->link_type),
+					(card->type,card->link_type,
+					 card->is_guest_lan),
 					card->options.portno,
 					checksum_str,
 					queueing_str,router_str,bufsize_str,
@@ -10174,6 +10559,7 @@ static int qeth_ipato_procfile_open(stru
 	int size;
 	char entry_type[5];
 
+        MOD_INC_USE_COUNT;
 	info = (tempinfo_t *) vmalloc (sizeof (tempinfo_t));
 	if (info == NULL) {
 		PRINT_WARN("No memory available for data\n");
@@ -10327,13 +10713,25 @@ static ssize_t qeth_procfile_read(struct
 static int qeth_procfile_release(struct inode *inode,struct file *file)
 {
    	tempinfo_t *p_info = (tempinfo_t *) file->private_data;
+	struct list_head *l,*n;
+  	struct qeth_notify_list *n_entry;
 	
 	if (p_info) {
 		if (p_info->data)
 			vfree (p_info->data);
 		vfree (p_info);
 	}
-	
+/*remove task-entry to notify from list */
+	spin_lock(&notify_lock);
+	list_for_each_safe(l, n, &notify_list) {
+		n_entry = list_entry(l, struct qeth_notify_list, list);
+		if (n_entry->task == current) {
+			list_del(&n_entry->list);
+			kfree(n_entry);
+		}
+	}
+	spin_unlock(&notify_lock);
+	MOD_DEC_USE_COUNT;
 	return 0;
 }
 
@@ -10481,118 +10879,35 @@ out:
 	return user_len;
 }
 
-static int qeth_procfile_getinterfaces(unsigned long arg) 
+static int qeth_snmp_register(struct task_struct *p, unsigned long arg)
 {
-	qeth_card_t *card;
+	struct qeth_notify_list *n_entry;
+	struct list_head *l;
+	QETH_DBF_TEXT5(0,trace,"snmpreg");
 
-	char parms[16];
-	char *buffer;
-	char *buffer_pointer;
-	__u32 version,valid_fields,qeth_version,number_of_devices,if_index;
-	__u32 data_size,data_len;
-	unsigned long ioctl_flags;
-	int result=0;
+	/*check first if entry already exists*/
 
-	/* the struct of version 0 is:
-typedef struct dev_list
-{
-  char device_name[IFNAME_MAXLEN]; // OSA-Exp device name (e.g. eth0)
-  __u32 if_index;                  // interface index from kernel
-  __u32 flags;             	   // device charateristics
-} __attribute__((packed)) DEV_LIST;
-
-typedef struct osaexp_dev_ver0
-{
-  __u32 version;                // structure version
-  __u32 valid_fields;           // bitmask of fields that are really filled
-  __u32 qeth_version;           // qeth driver version
-  __u32 number_of_devices;      // number of OSA Express devices
-  struct dev_list devices[0]; // list of OSA Express devices
-} __attribute__((packed)) OSAEXP_DEV_VER0;
-	*/
-
-	version = 0;
-	valid_fields = 0;
-	qeth_version = 0;
-	number_of_devices= 0;
-
-	copy_from_user((void*)parms,(void*)arg,sizeof(parms));
-	memcpy(&data_size,parms,sizeof(__u32));
-
-	if ( !(data_size > 0) ) 
-	     return -EFAULT;
-	if ( data_size > IOCTL_MAX_TRANSFER_SIZE ) 
-	     return -EFAULT;
-	if ( !access_ok(VERIFY_WRITE, (void *)arg, data_size) )
-	     return -EFAULT;
-
-	my_read_lock(&list_lock);
-	card = firstcard;
-#define IOCTL_USER_STRUCT_SIZE (DEV_NAME_LEN*sizeof(char)) + \
-	sizeof(__u32) + sizeof(__u32)
-	while (card) {
-	     if (card->type == QETH_CARD_TYPE_OSAE)
-		  number_of_devices=number_of_devices + IOCTL_USER_STRUCT_SIZE;
-	     card = card->next;
-	}
-#undef IOCTL_USER_STRUCT_SIZE
-	if ((number_of_devices + 4*sizeof(__u32)) >= data_size) {
-		result=-ENOMEM;
-		goto out;
-	}
+	spin_lock(&notify_lock);
+	list_for_each(l, &notify_list) {
+		n_entry = list_entry(l, struct qeth_notify_list, list);
+		if (n_entry->task == p) {
+			n_entry->signum = (int) arg;
+			goto reg_out;
+		}
 
-	number_of_devices=0;
-	card = firstcard;
-	buffer = (char *)vmalloc(data_size);
-	if (!buffer) {
-		result=-EFAULT;
-		goto out;
 	}
-	buffer_pointer = ((char *)(buffer)) + (4*sizeof(__u32)) ; 
-	while (card) {
-	     if ((card->type == QETH_CARD_TYPE_OSAE)&&
-		 (!atomic_read(&card->is_gone))&&
-		 (atomic_read(&card->is_hardsetup))&&
-		 (atomic_read(&card->is_registered))) {
-
-		  memcpy(buffer_pointer,card->dev_name,DEV_NAME_LEN);
-		  buffer_pointer = buffer_pointer + DEV_NAME_LEN;
-		  if_index=card->dev->ifindex;
-		  memcpy(buffer_pointer,&if_index,sizeof(__u32));
-		  buffer_pointer = buffer_pointer + sizeof(__u32);
-		  memcpy(buffer_pointer,&ioctl_flags,sizeof(__u32));
-		  buffer_pointer = buffer_pointer + sizeof(__u32);
-		  number_of_devices=number_of_devices+1;
-	     }
-	     card = card->next;
-	}
-
-	/* we copy the real size */
-	data_len=buffer_pointer-buffer;
-
-	buffer_pointer = buffer;
-	/* copy the header information at the beginning of the buffer */
-	memcpy(buffer_pointer,&version,sizeof(__u32));
-	memcpy(((char *)buffer_pointer)+sizeof(__u32),&valid_fields,
-	       sizeof(__u32));
-	memcpy(((char *)buffer_pointer)+(2*sizeof(__u32)),&qeth_version,
-	       sizeof(__u32));
-	memcpy(((char *)buffer_pointer)+(3*sizeof(__u32)),&number_of_devices,
-	       sizeof(__u32));
-	copy_to_user((char *)arg,buffer,data_len);
-	vfree(buffer);
-out:
-	my_read_unlock(&list_lock);
-	return result;
-
-#undef PARMS_BUFFERLENGTH
-
-};
-
-static int qeth_procfile_interfacechanges(unsigned long arg) 
-{
-	return qeth_sleepon_procfile();
-
+	spin_unlock(&notify_lock);
+	n_entry = (struct qeth_notify_list *)
+			kmalloc(sizeof(struct qeth_notify_list),GFP_KERNEL);
+	if (!n_entry)
+		return -ENOMEM;
+	n_entry->task = p;
+	n_entry->signum = (int) arg;
+	spin_lock(&notify_lock);
+	list_add(&n_entry->list,&notify_list);
+reg_out:
+	spin_unlock(&notify_lock);
+	return 0;
 } 
 
 static int qeth_procfile_ioctl(struct inode *inode, struct file *file,
@@ -10600,19 +10915,17 @@ static int qeth_procfile_ioctl(struct in
 {
 
      int result;
-     down_interruptible(&qeth_procfile_ioctl_lock);
-     switch (cmd) {
 
-     case QETH_IOCPROC_OSAEINTERFACES:
-	     result = qeth_procfile_getinterfaces(arg);
-	     break;
-     case QETH_IOCPROC_INTERFACECHANGES:
-	     result = qeth_procfile_interfacechanges(arg);
+     switch (cmd) {
+     case QETH_IOCPROC_REGISTER:
+	     if ( (arg > 0) && (arg < 32) )
+		     result = qeth_snmp_register(current,arg);
+	     else
+		     result = -EINVAL;
 	     break;
      default:
 	     result = -EOPNOTSUPP;	     
      }
-     up(&qeth_procfile_ioctl_lock);
      return result;
 };
 
@@ -10644,10 +10957,6 @@ static void qeth_add_procfs_entries(void
 					 S_IFREG|0644,&proc_root);
 	if (qeth_proc_file) {
 		qeth_proc_file->proc_fops = &qeth_procfile_fops;
-		sema_init(&qeth_procfile_ioctl_sem,
-			  PROCFILE_SLEEP_SEM_MAX_VALUE);
-		sema_init(&qeth_procfile_ioctl_lock,
-			  PROCFILE_IOCTL_SEM_MAX_VALUE);
 	} else proc_file_registration=-1;
 
 	if (proc_file_registration)
@@ -10796,7 +11105,11 @@ static int __init qeth_init(void)
 	global_stay_in_mem = chandev_persist(chandev_type_qeth);
 #endif /* MODULE */
 
-        spin_lock_init(&setup_lock);
+/*SNMP init stuff*/
+	spin_lock_init(&notify_lock);
+	INIT_LIST_HEAD(&notify_list);
+
+	spin_lock_init(&setup_lock);
 
 	spin_lock_init(&ipato_list_lock);
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/s390/net/qeth.h linux-2.4.28-pre3/drivers/s390/net/qeth.h
--- linux-2.4.27/drivers/s390/net/qeth.h	2003-08-25 11:44:42.000000000 +0000
+++ linux-2.4.28-pre3/drivers/s390/net/qeth.h	2004-09-10 19:33:57.000000000 +0000
@@ -15,7 +15,7 @@
 
 #define QETH_NAME " qeth"
 
-#define VERSION_QETH_H "$Revision: 1.113 $"
+#define VERSION_QETH_H "$Revision: 1.113.4.8 $"
 
 /******************** CONFIG STUFF ***********************/
 //#define QETH_DBF_LIKE_HELL
@@ -47,7 +47,7 @@
 /********************* TUNING STUFF **************************/
 #define HIGH_WATERMARK_PACK		5
 #define LOW_WATERMARK_PACK		2
-#define WATERMARK_FUZZ			2
+#define WATERMARK_FUZZ			1
 
 #define QETH_MAX_INPUT_THRESHOLD 500
 #define QETH_MAX_OUTPUT_THRESHOLD 300 /* ? */
@@ -85,6 +85,22 @@
 #define QETH_HARDSETUP_CLEAR_LAPS 3
 #define QETH_RECOVERY_HARDSETUP_RETRY 2
 
+/* the worst case stack usage is:
+ * qeth_hard_start_xmit
+ * do_QDIO
+ * qeth_qdio_output_handler
+ * do_QDIO
+ * qeth_qdio_output_handler
+ * (no more recursion as we have called netif_stop_queue)
+ */
+#ifdef CONFIG_ARCH_S390X
+#define STACK_PTR_MASK 0x3fff
+#define WORST_CASE_STACK_USAGE 1100
+#else /* CONFIG_ARCH_S390X */
+#define STACK_PTR_MASK 0x1fff
+#define WORST_CASE_STACK_USAGE 800
+#endif /* CONFIG_ARCH_S390X */
+
 /************************* DEBUG FACILITY STUFF *********************/
 
 #define QETH_DBF_HEX(ex,name,level,addr,len) \
@@ -253,6 +269,12 @@
 #define QETH_HEADER_PASSTHRU	0x10
 #define QETH_HEADER_IPV6	0x80
 
+#define QETH_ETH_MAC_V4      0x0100 /* like v4 */
+#define QETH_ETH_MAC_V6      0x3333 /* like v6 */
+/* tr mc mac is longer, but that will be enough to detect mc frames */
+#define QETH_TR_MAC_NC       0xc000 /* non-canonical */
+#define QETH_TR_MAC_C        0x0300 /* canonical */
+
 #define QETH_CAST_FLAGS		0x07
 #define QETH_CAST_UNICAST	6
 #define QETH_CAST_MULTICAST	4
@@ -529,7 +551,7 @@ typedef struct sparebufs_t {
 #define QETH_FAKE_LL_ADDR_LEN ETH_ALEN /* 6 */
 #define QETH_FAKE_LL_DEST_MAC_POS 0
 #define QETH_FAKE_LL_SRC_MAC_POS 6
-#define QETH_FAKE_LL_SRC_MAC_POS_IN_QDIO_HDR 6
+#define QETH_FAKE_LL_SRC_MAC_POS_IN_QDIO_HDR 18
 #define QETH_FAKE_LL_PROT_POS 12 
 #define QETH_FAKE_LL_V4_ADDR_POS 16
 #define QETH_FAKE_LL_V6_ADDR_POS 24
@@ -603,7 +625,7 @@ typedef struct sparebufs_t {
 #define MULTICAST_ROUTER 3
 #define PRIMARY_CONNECTOR 4
 #define SECONDARY_CONNECTOR 5
-#define ROUTER_MASK 0xf /* used to remove SET_ROUTING_FLAG
+#define ROUTER_MASK 0xf /* used to remove RESET_ROUTING_FLAG
 			   from routing_type */
 #define RESET_ROUTING_FLAG 0x10 /* used to indicate, that setting
 				   the routing type is desired */
@@ -629,6 +651,9 @@ typedef struct sparebufs_t {
 #define QETH_DONT_WAIT_FOR_LOCK 1
 #define QETH_LOCK_ALREADY_HELD 2
 
+#define BROADCAST_WITH_ECHO 1
+#define BROADCAST_WITHOUT_ECHO 2
+
 #define PROBLEM_CARD_HAS_STARTLANED 1
 #define PROBLEM_RECEIVED_IDX_TERMINATE 2
 #define PROBLEM_ACTIVATE_CHECK_CONDITION 3
@@ -782,6 +807,7 @@ typedef struct qeth_card_t {			/* pointe
 
 	__u8 link_type;
 
+	int is_guest_lan;
 	int do_pfix; /* to avoid doing diag98 for vm guest lan devices */
 
 	/* inbound buffer management */
@@ -852,7 +878,7 @@ typedef struct qeth_card_t {			/* pointe
 	/* prevents deadlocks :-O */
 	spinlock_t softsetup_lock;
 	spinlock_t hardsetup_lock;
-	spinlock_t ioctl_lock;
+	struct semaphore ioctl_sem;
 	atomic_t softsetup_thread_is_running;
 	struct semaphore softsetup_thread_sem;
 	struct tq_struct tqueue_sst;
@@ -907,6 +933,8 @@ typedef struct qeth_card_t {			/* pointe
 	__u32 ipa6_enabled;
 	__u32 adp_supported;
 
+	__u32 csum_enable_mask;
+
 	atomic_t startlan_attempts;
 	atomic_t enable_routing_attempts4;
 	atomic_t rt4fld;
@@ -1004,6 +1032,15 @@ typedef struct mydevreg_t {
 	struct mydevreg_t *prev;
 } mydevreg_t;
 
+/*user process notification stuff */
+spinlock_t notify_lock;
+struct list_head notify_list;
+struct qeth_notify_list {
+	struct list_head list;
+	struct task_struct *task;
+	int signum;
+};
+
 inline static int qeth_get_arphrd_type(int cardtype,int linktype)
 {
 	switch (cardtype) {
@@ -1011,7 +1048,7 @@ inline static int qeth_get_arphrd_type(i
 				  case QETH_MPC_LINK_TYPE_LANE_TR:
 					  /* fallthrough */
 				  case QETH_MPC_LINK_TYPE_HSTR:
-					  return ARPHRD_IEEE802;
+					  return ARPHRD_IEEE802_TR;
 				  default: return ARPHRD_ETHER;
 				  }
 	case QETH_CARD_TYPE_IQD: return ARPHRD_ETHER;
@@ -1036,22 +1073,33 @@ inline static __u8 qeth_get_adapter_type
 	}
 }
 
-inline static const char *qeth_get_cardname(int cardtype)
+inline static const char *qeth_get_cardname(int cardtype,int is_guest_lan)
 {
-	switch (cardtype) {
-	case QETH_CARD_TYPE_UNKNOWN: return "n unknown";
-	case QETH_CARD_TYPE_OSAE: return "n OSD Express";
-	case QETH_CARD_TYPE_IQD: return " HiperSockets";
-	default: return " strange";
+	if (is_guest_lan) {
+		switch (cardtype) {
+		case QETH_CARD_TYPE_UNKNOWN: return "n unknown";
+		case QETH_CARD_TYPE_OSAE: return " Guest LAN QDIO";
+		case QETH_CARD_TYPE_IQD: return " Guest LAN Hiper";
+		default: return " strange";
+		}
+	} else {
+		switch (cardtype) {
+		case QETH_CARD_TYPE_UNKNOWN: return "n unknown";
+		case QETH_CARD_TYPE_OSAE: return "n OSD Express";
+		case QETH_CARD_TYPE_IQD: return " HiperSockets";
+		default: return " strange";
+		}
 	}
 }
 
 /* max length to be returned: 14 */
-inline static const char *qeth_get_cardname_short(int cardtype,__u8 link_type)
+inline static const char *qeth_get_cardname_short(int cardtype,__u8 link_type,int is_guest_lan)
 {
 	switch (cardtype) {
 	case QETH_CARD_TYPE_UNKNOWN: return "unknown";
-	case QETH_CARD_TYPE_OSAE: switch (link_type) {
+	case QETH_CARD_TYPE_OSAE: if (is_guest_lan)
+					  return "GuestLAN QDIO";
+				  switch (link_type) {
 			      	  case QETH_MPC_LINK_TYPE_FAST_ETHERNET:
 		     			  return "OSD_100";
 			      	  case QETH_MPC_LINK_TYPE_HSTR:
@@ -1068,7 +1116,7 @@ inline static const char *qeth_get_cardn
      					  return "OSD_ATM_LANE";
 				  default: return "OSD_Express";
 				  }
-	case QETH_CARD_TYPE_IQD: return "HiperSockets";
+	case QETH_CARD_TYPE_IQD: return (is_guest_lan)?"GuestLAN Hiper":"HiperSockets";
 	default: return " strange";
 	}
 }
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/s390/net/qeth_mpc.h linux-2.4.28-pre3/drivers/s390/net/qeth_mpc.h
--- linux-2.4.27/drivers/s390/net/qeth_mpc.h	2003-08-25 11:44:42.000000000 +0000
+++ linux-2.4.28-pre3/drivers/s390/net/qeth_mpc.h	2004-09-10 19:34:53.000000000 +0000
@@ -11,7 +11,7 @@
 #ifndef __QETH_MPC_H__
 #define __QETH_MPC_H__
 
-#define VERSION_QETH_MPC_H "$Revision: 1.42 $"
+#define VERSION_QETH_MPC_H "$Revision: 1.42.4.4 $"
 
 #define QETH_IPA_TIMEOUT (card->ipa_timeout)
 #define QETH_MPC_TIMEOUT 2000
@@ -288,6 +288,7 @@ static unsigned char DM_ACT[]={
 #define IPA_PASSTHRU 0x00001000L
 #define IPA_FULL_VLAN 0x00004000L
 #define IPA_SOURCE_MAC_AVAIL 0x00010000L
+#define IPA_OSA_MC_ROUTER_AVAIL 0x00020000L
 
 #define IPA_SETADP_QUERY_COMMANDS_SUPPORTED 0x01
 #define IPA_SETADP_ALTER_MAC_ADDRESS 0x02
@@ -331,7 +332,7 @@ static unsigned char DM_ACT[]={
 #define IPA_CMD_ASS_ARP_QUERY_INFO 0x0104
 #define IPA_CMD_ASS_ARP_QUERY_STATS 0x0204
 
-#define IPA_CHECKSUM_ENABLE_MASK 0x001f
+#define IPA_CHECKSUM_DEFAULT_ENABLE_MASK 0x001a
 
 #define IPA_CMD_ASS_FILTER_SET_TYPES 0x0003
 
@@ -462,11 +463,10 @@ typedef struct ipa_cmd_t {
 } ipa_cmd_t __attribute__ ((packed));
 
 #define QETH_IOC_MAGIC 0x22
-#define QETH_IOCPROC_OSAEINTERFACES _IOWR(QETH_IOC_MAGIC, 1, arg)
-#define QETH_IOCPROC_INTERFACECHANGES _IOWR(QETH_IOC_MAGIC, 2, arg)
+#define QETH_IOCPROC_REGISTER _IOWR(QETH_IOC_MAGIC, 1, int)
 
 #define SNMP_QUERY_CARD_INFO 0x00000002L
-#define SNMP_REGISETER_MIB   0x00000004L
+#define SNMP_REGISTER_MIB    0x00000004L
 #define SNMP_GET_OID         0x00000010L
 #define SNMP_SET_OID         0x00000011L
 #define SNMP_GET_NEXT_OID    0x00000012L
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/s390/qdio.c linux-2.4.28-pre3/drivers/s390/qdio.c
--- linux-2.4.27/drivers/s390/qdio.c	2003-08-25 11:44:42.000000000 +0000
+++ linux-2.4.28-pre3/drivers/s390/qdio.c	2004-09-10 19:33:49.000000000 +0000
@@ -57,7 +57,7 @@ void volatile qdio_eyecatcher(void)
 
 #include <asm/qdio.h>
 
-#define VERSION_QDIO_C "$Revision: 1.145 $"
+#define VERSION_QDIO_C "$Revision: 1.145.4.9 $"
 
 /****************** MODULE PARAMETER VARIABLES ********************/
 MODULE_AUTHOR("Utz Bacher <utz.bacher@de.ibm.com>");
@@ -97,10 +97,12 @@ static struct {
 #endif /* QDIO_PERFORMANCE_STATS */
 
 static int hydra_thinints=0;
+static int omit_svs=0;
 
 static int indicator_used[INDICATORS_PER_CACHELINE];
 static __u32 * volatile indicators;
 static __u32 volatile spare_indicator;
+static atomic_t spare_indicator_usecount;
 
 static debug_info_t *qdio_dbf_setup=NULL;
 static debug_info_t *qdio_dbf_sbal=NULL;
@@ -121,6 +123,7 @@ static rwlock_t irq_list_lock[QDIO_IRQ_B
 static struct semaphore init_sema;
 
 static qdio_chsc_area_t *chsc_area;
+static spinlock_t chsc_area_lock=SPIN_LOCK_UNLOCKED;
 /* iQDIO stuff: */
 static volatile qdio_q_t *tiq_list=NULL; /* volatile as it could change
 					   during a while loop */
@@ -198,7 +201,7 @@ static inline volatile __u64 qdio_get_mi
 }
 static inline unsigned long qdio_get_millis(void)
 {
-	return (unsigned long)(qdio_get_micros()>>12);
+	return (unsigned long)(qdio_get_micros()>>10);
 }
 
 static __inline__ int atomic_return_add (int i, atomic_t *v)
@@ -518,8 +521,10 @@ static __u32 * volatile qdio_get_indicat
 
 	if (found)
 		return indicators+i;
-	else
+	else {
+		atomic_inc(&spare_indicator_usecount);
 		return (__u32 * volatile) &spare_indicator;
+	}
 }
 
 /* locked by the locks in qdio_activate and qdio_cleanup */
@@ -531,6 +536,9 @@ static void qdio_put_indicator(__u32 *ad
 		i=addr-indicators;
 		indicator_used[i]=0;
 	}
+	if (addr==&spare_indicator) {
+		atomic_dec(&spare_indicator_usecount);
+	}
 }
 
 static inline volatile void tiqdio_clear_summary_bit(__u32 *location)
@@ -621,8 +629,8 @@ static inline int qdio_stop_polling(qdio
 		set_slsb(&q->slsb.acc.val[(gsf+QDIO_MAX_BUFFERS_PER_Q-1)&
 			 (QDIO_MAX_BUFFERS_PER_Q-1)],SLSB_P_INPUT_NOT_INIT);
 		/* we don't issue this SYNC_MEMORY, as we trust Rick T and
-		 * moreover will not use the PROCESSING state, so q->polling
-		 * was 0
+		 * moreover will not use the PROCESSING state under VM,
+		 * so q->polling was 0 anyway.
 		SYNC_MEMORY;*/
 		if (q->slsb.acc.val[gsf]==SLSB_P_INPUT_PRIMED) {
 			/* set our summary bit again, as otherwise there is a
@@ -655,6 +663,11 @@ static inline void qdio_unmark_q(qdio_q_
 	if ((q->is_thinint_q)&&(q->is_input_q)) {
 		/* iQDIO */
 		spin_lock_irqsave(&ttiq_list_lock,flags);
+		/* in case cleanup has done this already and simultanously
+		 * qdio_unmark_q is called from the interrupt handler, we've
+		 * got to check this in this specific case again */
+		if ((!q->list_prev)||(!q->list_next))
+			goto out;
 		if (q->list_next==q) {
 			/* q was the only interesting q */
 			tiq_list=NULL;
@@ -667,6 +680,7 @@ static inline void qdio_unmark_q(qdio_q_
 			q->list_next=NULL;
 			q->list_prev=NULL;
 		}
+out:
 		spin_unlock_irqrestore(&ttiq_list_lock,flags);
 	}
 }
@@ -710,7 +724,7 @@ static inline void qdio_translate_buffer
 		       (void*)q->sbal[bufno],SBAL_SIZE);
 }
 
-inline static int qdio_get_outbound_buffer_frontier(qdio_q_t *q)
+static inline int qdio_get_outbound_buffer_frontier(qdio_q_t *q)
 {
 	int f,f_mod_no;
 	volatile char *slsb;
@@ -739,7 +753,7 @@ check_next:
 	if (f==first_not_to_check) goto out;
 	slsbyte=slsb[f_mod_no];
 
-	/* the hydra has not fetched the output yet */
+	/* the card has not fetched the output yet */
 	if (slsbyte==SLSB_CU_OUTPUT_PRIMED) {
 #ifdef QDIO_DBF_LIKE_HELL
 		QDIO_DBF_TEXT5(0,trace,"outpprim");
@@ -747,7 +761,7 @@ check_next:
 		goto out;
 	}
 
-	/* the hydra got it */
+	/* the card got it */
 	if (slsbyte==SLSB_P_OUTPUT_EMPTY) {
 		atomic_dec(&q->number_of_buffers_used);
 		f++;
@@ -797,7 +811,7 @@ out:
 }
 
 /* all buffers are processed */
-inline static int qdio_is_outbound_q_done(qdio_q_t *q)
+static inline int qdio_is_outbound_q_done(qdio_q_t *q)
 {
 	int no_used;
 #ifdef QDIO_DBF_LIKE_HELL
@@ -818,7 +832,7 @@ inline static int qdio_is_outbound_q_don
 	return (no_used==0);
 }
 
-inline static int qdio_has_outbound_q_moved(qdio_q_t *q)
+static inline int qdio_has_outbound_q_moved(qdio_q_t *q)
 {
 	int i;
 
@@ -827,7 +841,6 @@ inline static int qdio_has_outbound_q_mo
 	if ( (i!=GET_SAVED_FRONTIER(q)) ||
 	     (q->error_status_flags&QDIO_STATUS_LOOK_FOR_ERROR) ) {
 		SAVE_FRONTIER(q,i);
-		SAVE_TIMESTAMP(q);
 #ifdef QDIO_DBF_LIKE_HELL
 		QDIO_DBF_TEXT4(0,trace,"oqhasmvd");
 		QDIO_DBF_HEX4(0,trace,&q,sizeof(void*));
@@ -842,9 +855,10 @@ inline static int qdio_has_outbound_q_mo
 	}
 }
 
-inline static void qdio_kick_outbound_q(qdio_q_t *q)
+static inline void qdio_kick_outbound_q(qdio_q_t *q)
 {
 	int result;
+	char dbf_text[15];
 #ifdef QDIO_DBF_LIKE_HELL
 	QDIO_DBF_TEXT4(0,trace,"kickoutq");
 	QDIO_DBF_HEX4(0,trace,&q,sizeof(void*));
@@ -852,9 +866,66 @@ inline static void qdio_kick_outbound_q(
 
 	if (!q->siga_out) return;
 
+	/* here's the story with cc=2 and busy bit set (thanks, Rick):
+	 * VM's CP could present us cc=2 and busy bit set on SIGA-write
+	 * during reconfiguration of their Guest LAN (only in HIPERS mode,
+	 * QDIO mode is asynchronous -- cc=2 and busy bit there will take
+	 * the queues down immediately; and not being under VM we have a
+	 * problem on cc=2 and busy bit set right away).
+	 *
+	 * Therefore qdio_siga_output will try for a short time constantly,
+	 * if such a condition occurs. If it doesn't change, it will
+	 * increase the busy_siga_counter and save the timestamp, and
+	 * schedule the queue for later processing (via mark_q, using the
+	 * queue tasklet). __qdio_outbound_processing will check out the
+	 * counter. If non-zero, it will call qdio_kick_outbound_q as often
+	 * as the value of the counter. This will attempt further SIGA
+	 * instructions.
+	 * Every successful SIGA instruction will decrease the counter.
+	 * After some time of no movement, qdio_kick_outbound_q will
+	 * finally fail and reflect corresponding error codes to call
+	 * the upper layer module and have it take the queues down.
+	 *
+	 * Note that this is a change from the original HiperSockets design
+	 * (saying cc=2 and busy bit means take the queues down), but in
+	 * these days Guest LAN didn't exist... excessive cc=2 with busy bit
+	 * conditions will still take the queues down, but the threshold is
+	 * higher due to the Guest LAN environment.
+	 */
+
 	result=qdio_siga_output(q);
 
-	if (result) {
+		switch (result) {
+		case 0:
+		/* went smooth this time, reset timestamp */
+			QDIO_DBF_TEXT3(0,trace,"cc2reslv");
+			sprintf(dbf_text,"%4x%2x%2x",q->irq,q->q_no,
+				atomic_read(&q->busy_siga_counter));
+			QDIO_DBF_TEXT3(0,trace,dbf_text);
+			q->timing.busy_start=0;
+			break;
+		case (2|QDIO_SIGA_ERROR_B_BIT_SET):
+			/* cc=2 and busy bit: */
+		atomic_inc(&q->busy_siga_counter);
+
+			/* if the last siga was successful, save
+			 * timestamp here */
+			if (!q->timing.busy_start)
+				q->timing.busy_start=NOW;
+
+			/* if we're in time, don't touch error_status_flags
+			 * and siga_error */
+			if (NOW-q->timing.busy_start<QDIO_BUSY_BIT_GIVE_UP) {
+				qdio_mark_q(q);
+				break;
+			}
+			QDIO_DBF_TEXT2(0,trace,"cc2REPRT");
+			sprintf(dbf_text,"%4x%2x%2x",q->irq,q->q_no,
+				atomic_read(&q->busy_siga_counter));
+			QDIO_DBF_TEXT3(0,trace,dbf_text);
+			/* else fallthrough and report error */
+		default:
+			/* for plain cc=1, 2 or 3: */
 		if (q->siga_error)
 			q->error_status_flags|=
 				QDIO_STATUS_MORE_THAN_ONE_SIGA_ERROR;
@@ -864,7 +935,7 @@ inline static void qdio_kick_outbound_q(
 	}
 }
 
-inline static void qdio_kick_outbound_handler(qdio_q_t *q)
+static inline void qdio_kick_outbound_handler(qdio_q_t *q)
 {
 #ifdef QDIO_DBF_LIKE_HELL
 	char dbf_text[15];
@@ -901,8 +972,9 @@ inline static void qdio_kick_outbound_ha
 	q->error_status_flags=0;
 }
 
-static void qdio_outbound_processing(qdio_q_t *q)
+static inline void __qdio_outbound_processing(qdio_q_t *q)
 {
+	int siga_attempts;
 #ifdef QDIO_DBF_LIKE_HELL
 	QDIO_DBF_TEXT4(0,trace,"qoutproc");
 	QDIO_DBF_HEX4(0,trace,&q,sizeof(void*));
@@ -926,6 +998,14 @@ static void qdio_outbound_processing(qdi
 	o_p_nc++;
 #endif /* QDIO_PERFORMANCE_STATS */
 
+	/* see comment in qdio_kick_outbound_q */
+	siga_attempts=atomic_read(&q->busy_siga_counter);
+	while (siga_attempts) {
+		atomic_dec(&q->busy_siga_counter);
+		qdio_kick_outbound_q(q);
+		siga_attempts--;
+	}
+
 #ifdef QDIO_PERFORMANCE_STATS
 	perf_stats.tl_runs++;
 #endif /* QDIO_PERFORMANCE_STATS */
@@ -936,7 +1016,8 @@ static void qdio_outbound_processing(qdi
 
 	if (q->is_iqdio_q) {
 		/* for asynchronous queues, we better check, if the fill
-		 * level is too high */
+		 * level is too high. for synchronous queues, the fill
+		 * level will never be that high. */
 		if (atomic_read(&q->number_of_buffers_used)>
 		    IQDIO_FILL_LEVEL_TO_POLL) {
 			qdio_mark_q(q);
@@ -950,16 +1031,24 @@ static void qdio_outbound_processing(qdi
 	qdio_release_q(q);
 }
 
+static void qdio_outbound_processing(qdio_q_t *q)
+{
+	__qdio_outbound_processing(q);
+}
+
 /************************* INBOUND ROUTINES *******************************/
 
 
-inline static int qdio_get_inbound_buffer_frontier(qdio_q_t *q)
+static inline int qdio_get_inbound_buffer_frontier(qdio_q_t *q)
 {
 	int f,f_mod_no;
 	volatile char *slsb;
 	char slsbyte;
 	int first_not_to_check;
 	char dbf_text[15];
+#ifdef QDIO_USE_PROCESSING_STATE
+	int last_position=-1;
+#endif /* QDIO_USE_PROCESSING_STATE */
 
 #ifdef QDIO_DBF_LIKE_HELL
 	QDIO_DBF_TEXT4(0,trace,"getibfro");
@@ -1002,8 +1091,14 @@ check_next:
 		if (q->siga_sync) {
 			set_slsb(&slsb[f_mod_no],SLSB_P_INPUT_NOT_INIT);
 		} else {
-			set_slsb(&slsb[f_mod_no],SLSB_P_INPUT_PROCESSING);
+			/* set the previous buffer to NOT_INIT. The current
+			 * buffer will be set to PROCESSING at the end of
+			 * this function to avoid further interrupts. */
+			if (last_position>=0)
+				set_slsb(&slsb[last_position],
+					SLSB_P_INPUT_NOT_INIT);
 			atomic_set(&q->polling,1);
+			last_position=f_mod_no;
 		}
 #else /* QDIO_USE_PROCESSING_STATE */
 		set_slsb(&slsb[f_mod_no],SLSB_P_INPUT_NOT_INIT);
@@ -1044,6 +1139,10 @@ check_next:
 		f_mod_no=(f_mod_no+1)&(QDIO_MAX_BUFFERS_PER_Q-1);
 		atomic_dec(&q->number_of_buffers_used);
 
+#ifdef QDIO_USE_PROCESSING_STATE
+		last_position=-1;
+#endif /* QDIO_USE_PROCESSING_STATE */
+
 		goto out;
 	}
 
@@ -1051,6 +1150,11 @@ check_next:
 out:
 	q->first_to_check=f_mod_no;
 
+#ifdef QDIO_USE_PROCESSING_STATE
+	if (last_position>=0)
+		set_slsb(&slsb[last_position],SLSB_P_INPUT_PROCESSING);
+#endif /* QDIO_USE_PROCESSING_STATE */
+
 #ifdef QDIO_DBF_LIKE_HELL
 	QDIO_DBF_HEX4(0,trace,&q->first_to_check,sizeof(int));
 #endif /* QDIO_DBF_LIKE_HELL */
@@ -1058,7 +1162,7 @@ out:
 	return q->first_to_check;
 }
 
-inline static int qdio_has_inbound_q_moved(qdio_q_t *q)
+static inline int qdio_has_inbound_q_moved(qdio_q_t *q)
 {
 	int i;
 
@@ -1095,7 +1199,7 @@ inline static int qdio_has_inbound_q_mov
 }
 
 /* means, no more buffers to be filled */
-inline static int iqdio_is_inbound_q_done(qdio_q_t *q)
+static inline int iqdio_is_inbound_q_done(qdio_q_t *q)
 {
 	int no_used;
 #ifdef QDIO_DBF_LIKE_HELL
@@ -1148,7 +1252,7 @@ inline static int iqdio_is_inbound_q_don
 	return 0;
 }
 
-inline static int qdio_is_inbound_q_done(qdio_q_t *q)
+static inline int qdio_is_inbound_q_done(qdio_q_t *q)
 {
 	int no_used;
 #ifdef QDIO_DBF_LIKE_HELL
@@ -1157,7 +1261,7 @@ inline static int qdio_is_inbound_q_done
 
 	no_used=atomic_read(&q->number_of_buffers_used);
 
-	/* we need that one for synchronization with Hydra, as Hydra
+	/* we need that one for synchronization with the OSA/FCP card, as it
 	 * does a kind of PCI avoidance */
 	SYNC_MEMORY;
 
@@ -1204,7 +1308,7 @@ inline static int qdio_is_inbound_q_done
 	}
 }
 
-inline static void qdio_kick_inbound_handler(qdio_q_t *q)
+static inline void qdio_kick_inbound_handler(qdio_q_t *q)
 {
 	int count=0;
 	int start,end,real_end,i;
@@ -1250,7 +1354,8 @@ inline static void qdio_kick_inbound_han
 #endif /* QDIO_PERFORMANCE_STATS */
 }
 
-static inline void tiqdio_inbound_processing(qdio_q_t *q)
+static inline void __tiqdio_inbound_processing(qdio_q_t *q,
+					       int spare_ind_was_set)
 {
 	qdio_irq_t *irq_ptr;
 	qdio_q_t *oq;
@@ -1282,8 +1387,18 @@ static inline void tiqdio_inbound_proces
 		goto out;
 	}
 
-	if (*(q->dev_st_chg_ind)) {
-		tiqdio_clear_summary_bit((__u32*)q->dev_st_chg_ind);
+	/* we reset spare_ind_was_set, when the queue does not use the
+	 * spare indicator */
+	if (spare_ind_was_set) {
+		spare_ind_was_set==(q->dev_st_chg_ind==&spare_indicator);
+	}
+
+	if ( (*(q->dev_st_chg_ind)) || (spare_ind_was_set) ) {
+		/* q->dev_st_chg_ind is the indicator, be it shared or not.
+		 * only clear it, if indicator is non-shared */
+		if (!spare_ind_was_set) {
+			tiqdio_clear_summary_bit((__u32*)q->dev_st_chg_ind);
+		}
 
 		if (q->hydra_gives_outbound_pcis) {
 			if (!q->siga_sync_done_on_thinints) {
@@ -1297,7 +1412,7 @@ static inline void tiqdio_inbound_proces
 		}
 
 		/* maybe we have to do work on our outbound queues... at least
-		 * we have to check Hydra outbound-int-capable thinint-capable
+		 * we have to check for outbound-int-capable thinint-capable
 		 * queues */
 		if (q->hydra_gives_outbound_pcis) {
 			irq_ptr=(qdio_irq_t*)q->irq_ptr;
@@ -1307,7 +1422,7 @@ static inline void tiqdio_inbound_proces
 				perf_stats.tl_runs--;
 #endif /* QDIO_PERFORMANCE_STATS */
 				if (!qdio_is_outbound_q_done(oq)) {
-					qdio_outbound_processing(oq);
+					__qdio_outbound_processing(oq);
 				}
 			}
 		}
@@ -1330,7 +1445,12 @@ out:
 	qdio_release_q(q);
 }
 
-static void qdio_inbound_processing(qdio_q_t *q)
+static void tiqdio_inbound_processing(qdio_q_t *q)
+{
+	__tiqdio_inbound_processing(q,atomic_read(&spare_indicator_usecount));
+}
+
+static inline void __qdio_inbound_processing(qdio_q_t *q)
 {
 	int q_laps=0;
 
@@ -1375,11 +1495,17 @@ again:
 	qdio_release_q(q);
 }
 
+static void qdio_inbound_processing(qdio_q_t *q)
+{
+	__qdio_inbound_processing(q);
+}
+
 /************************* MAIN ROUTINES *******************************/
 
 static inline void tiqdio_inbound_checks(void)
 {
 	qdio_q_t *q;
+	int spare_ind_was_set=0;
 #ifdef QDIO_USE_PROCESSING_STATE
 	int q_laps=0;
 #endif /* QDIO_USE_PROCESSING_STATE */
@@ -1398,15 +1524,22 @@ static inline void tiqdio_inbound_checks
 again:
 #endif /* QDIO_USE_PROCESSING_STATE */
 
+	/* when the spare indicator is used and set, save that and clear it */
+	if ( (atomic_read(&spare_indicator_usecount)) && (spare_indicator) ) {
+		spare_ind_was_set=1;
+		tiqdio_clear_summary_bit((__u32*)&spare_indicator);
+	}
+
 	q=(qdio_q_t*)tiq_list;
 	/* switch all active queues to processing state */
 	do {
 		if (!q) break;
-		tiqdio_inbound_processing(q);
+		__tiqdio_inbound_processing(q,spare_ind_was_set);
 		q=(qdio_q_t*)q->list_next;
 	} while (q!=(qdio_q_t*)tiq_list);
 
-	/* switch off all queues' processing state */
+	/* switch off all queues' processing state, see comments in
+	 * qdio_get_inbound_buffer_frontier */
 #ifdef QDIO_USE_PROCESSING_STATE
 	q=(qdio_q_t*)tiq_list;
 	do {
@@ -1589,7 +1722,7 @@ next:
 		kfree(irq_ptr->output_qs[i]);
 
 	}
-	if (irq_ptr->qdr) kfree(irq_ptr->qdr);
+	kfree(irq_ptr->qdr);
 	kfree(irq_ptr);
 }
 
@@ -1758,6 +1891,10 @@ static int qdio_alloc_qs(qdio_irq_t *irq
 			((irq_ptr->is_thinint_irq)?&tiqdio_inbound_processing:
 			 &qdio_inbound_processing);
 
+		/* actually this is not used for inbound queues. yet. */
+		atomic_set(&q->busy_siga_counter,0);
+		q->timing.busy_start=0;
+
 /*		for (j=0;j<QDIO_STATS_NUMBER;j++)
 			q->timing.last_transfer_times[j]=(qdio_get_micros()/
 							  QDIO_STATS_NUMBER)*j;
@@ -1849,6 +1986,9 @@ static int qdio_alloc_qs(qdio_irq_t *irq
 		q->tasklet.func=(void(*)(unsigned long))
 			&qdio_outbound_processing;
 
+		atomic_set(&q->busy_siga_counter,0);
+		q->timing.busy_start=0;
+
 		/* fill in slib */
 		if (i>0) irq_ptr->output_qs[i-1]->slib->nsliba=
 				 QDIO_PFIX_GET_ADDR(q->slib);
@@ -1928,9 +2068,10 @@ static int tiqdio_thinint_handler(__u32 
 	perf_stats.start_time_inbound=NOW;
 #endif /* QDIO_PERFORMANCE_STATS */
 
-	/* VM will do the SVS for us
-	 * issue SVS to benefit from iqdio interrupt avoidance (SVS clears AISOI)*/
-	if (!MACHINE_IS_VM) {
+	/* SVS only when needed:
+	 * issue SVS to benefit from iqdio interrupt avoidance
+	 * (SVS clears AISOI)*/
+	if (!omit_svs) {
 		tiqdio_clear_global_summary();
 	}
 
@@ -2014,7 +2155,7 @@ static void qdio_handler(int irq,devstat
 #ifdef QDIO_PERFORMANCE_STATS
 				perf_stats.tl_runs--;
 #endif /* QDIO_PERFORMANCE_STATS */
-				qdio_inbound_processing(q);
+				__qdio_inbound_processing(q);
 			}
 		}
 		if (irq_ptr->hydra_gives_outbound_pcis) {
@@ -2027,7 +2168,7 @@ static void qdio_handler(int irq,devstat
 					if (!irq_ptr->sync_done_on_outb_pcis) {
 						SYNC_MEMORY;
 					}
-					qdio_outbound_processing(q);
+					__qdio_outbound_processing(q);
 				}
 			}
 		}
@@ -2206,6 +2347,9 @@ static int qdio_chsc(qdio_chsc_area_t *c
 static unsigned char qdio_check_siga_needs(int sch)
 {
 	int resp_code,result;
+	unsigned long flags;
+
+	spin_lock_irqsave(&chsc_area_lock,flags);
 
 	memset(chsc_area,0,sizeof(qdio_chsc_area_t));
 	chsc_area->request_block.command_code1=0x0010; /* length */
@@ -2219,7 +2363,8 @@ static unsigned char qdio_check_siga_nee
 		QDIO_PRINT_WARN("CHSC returned cc %i. Using all " \
 				"SIGAs for sch x%x.\n",
 				result,sch);
-		return -1; /* all flags set */
+		result=-1; /* all flags set */
+		goto out;
 	}
 
 	resp_code=chsc_area->request_block.operation_data_area.
@@ -2228,7 +2373,8 @@ static unsigned char qdio_check_siga_nee
 		QDIO_PRINT_WARN("response upon checking SIGA needs " \
 				"is 0x%x. Using all SIGAs for sch x%x.\n",
 				resp_code,sch);
-		return -1; /* all flags set */
+		result=-1; /* all flags set */
+		goto out;
 	}
 	if (
 	    (!(chsc_area->request_block.operation_data_area.
@@ -2240,18 +2386,25 @@ static unsigned char qdio_check_siga_nee
 	    ) {
 		QDIO_PRINT_WARN("huh? problems checking out sch x%x... " \
 				"using all SIGAs.\n",sch);
-		return CHSC_FLAG_SIGA_INPUT_NECESSARY |
+		result=CHSC_FLAG_SIGA_INPUT_NECESSARY |
 			CHSC_FLAG_SIGA_OUTPUT_NECESSARY |
 			CHSC_FLAG_SIGA_SYNC_NECESSARY; /* worst case */
+		goto out;
 	}
 
-	return chsc_area->request_block.operation_data_area.
+	result=chsc_area->request_block.operation_data_area.
 		store_qdio_data_response.qdioac;
+out:
+	spin_unlock_irqrestore(&chsc_area_lock,flags);
+	return result;
 }
 
-static int qdio_check_for_hydra_thinints(void)
+static void qdio_check_for_machine_features(void)
 {
 	int i,result;
+	unsigned long flags;
+
+	spin_lock_irqsave(&chsc_area_lock,flags);
 
 	memset(chsc_area,0,sizeof(qdio_chsc_area_t));
 	chsc_area->request_block.command_code1=0x0010;
@@ -2260,16 +2413,19 @@ static int qdio_check_for_hydra_thinints
 
 	if (result) {
 		QDIO_PRINT_WARN("CHSC returned cc %i. Won't use adapter " \
-				"interrupts for any Hydra.\n",result);
-		return 0;
+				"interrupts for any QDIO device.\n",result);
+		result=0;
+		goto out;
 	}
 
 	i=chsc_area->request_block.operation_data_area.
 		store_qdio_data_response.response_code;
 	if (i!=1) {
 		QDIO_PRINT_WARN("Was not able to determine general " \
-				"characteristics of all Hydras aboard.\n");
-		return 0;
+				"characteristics of all QDIO devices " \
+				"aboard.\n");
+		result=0;
+		goto out;
 	}
 
 	/* 4: request block
@@ -2277,16 +2433,29 @@ static int qdio_check_for_hydra_thinints
 	 * 512: chsc char */
 	/* check for bit 67 */
 	if ( (*(((unsigned int*)(chsc_area))+4+2+2)&0x10000000)!=0x10000000) {
-		return 0;
+		hydra_thinints=0;
 	} else {
-		return 1;
+		hydra_thinints=1;
 	}
+
+	/* check for bit 56: if aif time delay disablement fac installed,
+	 * omit svs even under lpar (good point by rick again) */
+	if ( (*(((unsigned int*)(chsc_area))+4+2+1)&0x00000080)!=0x00000080) {
+		omit_svs=1;
+	} else {
+		omit_svs=0;
+	}
+out:
+	spin_unlock_irqrestore(&chsc_area_lock,flags);
 }
 
 /* the chsc_area is locked by the lock in qdio_activate */
 static unsigned int tiqdio_check_chsc_availability(void) {
 	int result;
 	int i;
+	unsigned long flags;
+
+	spin_lock_irqsave(&chsc_area_lock,flags);
 
 	memset(chsc_area,0,sizeof(qdio_chsc_area_t));
 	chsc_area->request_block.command_code1=0x0010;
@@ -2327,6 +2496,7 @@ static unsigned int tiqdio_check_chsc_av
 		goto exit;
 	}
 exit:
+	spin_unlock_irqrestore(&chsc_area_lock,flags);
 	return result;
 }
 
@@ -2337,6 +2507,7 @@ static unsigned int tiqdio_set_subchanne
 	unsigned long real_addr_local_summary_bit;
 	unsigned long real_addr_dev_st_chg_ind;
 	void *ptr;
+	unsigned long flags;
 	char dbf_text[15];
 
 	unsigned int resp_code;
@@ -2354,6 +2525,8 @@ static unsigned int tiqdio_set_subchanne
 			virt_to_phys((volatile void *)irq_ptr->dev_st_chg_ind);
 	}
 
+	spin_lock_irqsave(&chsc_area_lock,flags);
+
 	memset(chsc_area,0,sizeof(qdio_chsc_area_t));
 	chsc_area->request_block.command_code1=0x0fe0;
 	chsc_area->request_block.command_code2=0x0021;
@@ -2377,7 +2550,8 @@ static unsigned int tiqdio_set_subchanne
 	if (result) {
 		QDIO_PRINT_WARN("could not set indicators on irq x%x, " \
 				"cc=%i.\n",irq_ptr->irq,result);
-		return -EIO;
+		result=-EIO;
+		goto out;
 	}
 
 	resp_code=chsc_area->response_block.response_code;
@@ -2389,14 +2563,18 @@ static unsigned int tiqdio_set_subchanne
 		QDIO_DBF_TEXT1(0,setup,dbf_text);
 		ptr=&chsc_area->response_block;
 		QDIO_DBF_HEX2(1,setup,&ptr,QDIO_DBF_SETUP_LEN);
-		return -EIO;
+		result=-EIO;
+		goto out;
 	}
 
 	QDIO_DBF_TEXT2(0,setup,"setscind");
 	QDIO_DBF_HEX2(0,setup,&real_addr_local_summary_bit,
 		      sizeof(unsigned long));
 	QDIO_DBF_HEX2(0,setup,&real_addr_dev_st_chg_ind,sizeof(unsigned long));
-	return 0;
+	result=0;
+out:
+	spin_unlock_irqrestore(&chsc_area_lock,flags);
+	return result;
 }
 
 /* chsc_area would have to be locked if called from outside qdio_activate */
@@ -2406,10 +2584,13 @@ static unsigned int tiqdio_set_delay_tar
 	unsigned int resp_code;
 	int result;
 	void *ptr;
+	unsigned long flags;
 	char dbf_text[15];
 
 	if (!irq_ptr->is_thinint_irq) return -ENODEV;
 
+	spin_lock_irqsave(&chsc_area_lock,flags);
+
 	memset(chsc_area,0,sizeof(qdio_chsc_area_t));
 	chsc_area->request_block.command_code1=0x0fe0;
 	chsc_area->request_block.command_code2=0x1027;
@@ -2420,7 +2601,8 @@ static unsigned int tiqdio_set_delay_tar
 	if (result) {
 		QDIO_PRINT_WARN("could not set delay target on irq x%x, " \
 				"cc=%i. Continuing.\n",irq_ptr->irq,result);
-		return -EIO;
+		result=-EIO;
+		goto out;
 	}
 
 	resp_code=chsc_area->response_block.response_code;
@@ -2435,7 +2617,10 @@ static unsigned int tiqdio_set_delay_tar
 	}
 	QDIO_DBF_TEXT2(0,trace,"delytrgt");
 	QDIO_DBF_HEX2(0,trace,&delay_target,sizeof(unsigned long));
-	return 0;
+	result=0;
+out:
+	spin_unlock_irqrestore(&chsc_area_lock,flags);
+	return result;
 }
 
 int qdio_cleanup(int irq,int how)
@@ -2445,7 +2630,7 @@ int qdio_cleanup(int irq,int how)
 	int do_an_irqrestore=0;
 	unsigned long flags;
 	int timeout;
-	char dbf_text[15]="12345678";
+	char dbf_text[15];
 
 	result=0;
 	sprintf(dbf_text,"qcln%4x",irq);
@@ -2455,7 +2640,7 @@ int qdio_cleanup(int irq,int how)
 	irq_ptr=qdio_get_irq_ptr(irq);
 	if (!irq_ptr) return -ENODEV;
 
-	spin_lock(&irq_ptr->setting_up_lock);
+	down(&irq_ptr->setting_up_lock);
 
 	/* mark all qs as uninteresting */
 	for (i=0;i<irq_ptr->no_input_qs;i++) {
@@ -2527,7 +2712,7 @@ int qdio_cleanup(int irq,int how)
 	if (do_an_irqrestore)
 		s390irq_spin_unlock_irqrestore(irq,flags);
 
-	spin_unlock(&irq_ptr->setting_up_lock);
+	up(&irq_ptr->setting_up_lock);
 
 	qdio_remove_irq_ptr(irq_ptr);
 	qdio_release_irq_memory(irq_ptr);
@@ -2574,16 +2759,15 @@ int qdio_initialize(qdio_initialize_t *i
 	int result,result2;
 	int found;
 	unsigned long flags;
-	char dbf_text[20]; /* if a printf would print out more than 8 chars */
+	char dbf_text[20]; /* if a printf printed out more than 8 chars */
 
-	down_interruptible(&init_sema);
+	down(&init_sema);
 
 	sprintf(dbf_text,"qini%4x",init_data->irq);
 	QDIO_DBF_TEXT0(0,setup,dbf_text);
 	QDIO_DBF_TEXT0(0,trace,dbf_text);
 	sprintf(dbf_text,"qfmt:%x",init_data->q_format);
 	QDIO_DBF_TEXT0(0,setup,dbf_text);
-	QDIO_DBF_TEXT0(0,setup,init_data->adapter_name);
 	QDIO_DBF_HEX0(0,setup,init_data->adapter_name,8);
 	sprintf(dbf_text,"qpff%4x",init_data->qib_param_field_format);
 	QDIO_DBF_TEXT0(0,setup,dbf_text);
@@ -2672,7 +2856,6 @@ int qdio_initialize(qdio_initialize_t *i
 
 	irq_ptr->qdr=kmalloc(sizeof(qdr_t),GFP_DMA);
   	if (!(irq_ptr->qdr)) {
-   		kfree(irq_ptr->qdr);
    		kfree(irq_ptr);
     		QDIO_PRINT_ERR("kmalloc of irq_ptr->qdr failed!\n");
      		result=-ENOMEM;
@@ -2736,12 +2919,12 @@ int qdio_initialize(qdio_initialize_t *i
 
 	qdio_set_state(irq_ptr,QDIO_IRQ_STATE_INACTIVE);
 
-	irq_ptr->setting_up_lock=SPIN_LOCK_UNLOCKED;
+	sema_init(&irq_ptr->setting_up_lock,1);
 
 	MOD_INC_USE_COUNT;
 	QDIO_DBF_TEXT3(0,setup,"MOD_INC_");
 
-	spin_lock(&irq_ptr->setting_up_lock);
+	down(&irq_ptr->setting_up_lock);
 
 	qdio_insert_irq_ptr(irq_ptr);
 
@@ -2867,10 +3050,10 @@ int qdio_initialize(qdio_initialize_t *i
 		}
 		result=tiqdio_set_subchannel_ind(irq_ptr,0);
 		if (result) {
-			spin_unlock(&irq_ptr->setting_up_lock);
+			up(&irq_ptr->setting_up_lock);
 			qdio_cleanup(irq_ptr->irq,
 				     QDIO_FLAG_CLEANUP_USING_CLEAR);
-			goto out2;
+			goto out;
 		}
 		tiqdio_set_delay_target(irq_ptr,TIQDIO_DELAY_TARGET);
 	}
@@ -2906,9 +3089,9 @@ int qdio_initialize(qdio_initialize_t *i
 	s390irq_spin_unlock_irqrestore(irq_ptr->irq,saveflags);
 
 	if (result) {
-		spin_unlock(&irq_ptr->setting_up_lock);
+		up(&irq_ptr->setting_up_lock);
 		qdio_cleanup(irq_ptr->irq,QDIO_FLAG_CLEANUP_USING_CLEAR);
-		goto out2;
+		goto out;
 	}
 
 	result=qdio_sleepon(&irq_ptr->interrupt_has_arrived,
@@ -2918,9 +3101,9 @@ int qdio_initialize(qdio_initialize_t *i
 		QDIO_PRINT_ERR("establish queues on irq %04x: timed out\n",
 			   irq_ptr->irq);
 		QDIO_DBF_TEXT2(1,setup,"eq:timeo");
-		spin_unlock(&irq_ptr->setting_up_lock);
+		up(&irq_ptr->setting_up_lock);
 		qdio_cleanup(irq_ptr->irq,QDIO_FLAG_CLEANUP_USING_CLEAR);
-		goto out2;
+		goto out;
 	}
 
 	if (!(irq_ptr->io_result_dstat & DEV_STAT_DEV_END)) {
@@ -2937,10 +3120,10 @@ int qdio_initialize(qdio_initialize_t *i
 			       irq_ptr->irq,irq_ptr->io_result_dstat,
 			       irq_ptr->io_result_cstat,
 			       irq_ptr->io_result_flags);
-		spin_unlock(&irq_ptr->setting_up_lock);
+		up(&irq_ptr->setting_up_lock);
 		qdio_cleanup(irq_ptr->irq,QDIO_FLAG_CLEANUP_USING_CLEAR);
 		result=-EIO;
-		goto out2;
+		goto out;
 	}
 
 	if (irq_ptr->io_result_dstat & ~(DEV_STAT_CHN_END|DEV_STAT_DEV_END)) {
@@ -2958,18 +3141,19 @@ int qdio_initialize(qdio_initialize_t *i
 			       irq_ptr->io_result_cstat,
 			       irq_ptr->io_result_flags);
 		result=-EIO;
+		up(&irq_ptr->setting_up_lock);
 		goto out;
 	}
 
-	if (MACHINE_IS_VM)
 		irq_ptr->qdioac=qdio_check_siga_needs(irq_ptr->irq);
-	else { 
-                irq_ptr->qdioac=CHSC_FLAG_SIGA_INPUT_NECESSARY
-                        | CHSC_FLAG_SIGA_OUTPUT_NECESSARY;
-        }
 	sprintf(dbf_text,"qdioac%2x",irq_ptr->qdioac);
 	QDIO_DBF_TEXT2(0,setup,dbf_text);
 
+	/* if this gets set once, we're running under VM and can omit SVSes */
+	if (irq_ptr->qdioac&CHSC_FLAG_SIGA_SYNC_NECESSARY) {
+		omit_svs=1;
+	}
+
 	sprintf(dbf_text,"qib ac%2x",irq_ptr->qib.ac);
 	QDIO_DBF_TEXT2(0,setup,dbf_text);
 
@@ -3026,11 +3210,10 @@ int qdio_initialize(qdio_initialize_t *i
 
 	qdio_set_state(irq_ptr,QDIO_IRQ_STATE_ESTABLISHED);
 
- out:
 	if (irq_ptr) {
-		spin_unlock(&irq_ptr->setting_up_lock);
+		up(&irq_ptr->setting_up_lock);
 	}
- out2:
+ out:
 	up(&init_sema);
 
 	return result;
@@ -3046,7 +3229,7 @@ int qdio_activate(int irq,int flags)
 	irq_ptr=qdio_get_irq_ptr(irq);
 	if (!irq_ptr) return -ENODEV;
 
-	spin_lock(&irq_ptr->setting_up_lock);
+	down(&irq_ptr->setting_up_lock);
 	if (irq_ptr->state==QDIO_IRQ_STATE_INACTIVE) {
 		result=-EBUSY;
 		goto out;
@@ -3141,14 +3324,15 @@ int qdio_activate(int irq,int flags)
 	qdio_set_state(irq_ptr,QDIO_IRQ_STATE_ACTIVE);
 
  out:
-	spin_unlock(&irq_ptr->setting_up_lock);
+	up(&irq_ptr->setting_up_lock);
 
 	return result;
 }
 
 /* buffers filled forwards again to make Rick happy */
-static void qdio_do_qdio_fill_input(qdio_q_t *q,unsigned int qidx,
-				    unsigned int count,qdio_buffer_t *buffers)
+static inline void qdio_do_qdio_fill_input(qdio_q_t *q,unsigned int qidx,
+	       				   unsigned int count,
+					   qdio_buffer_t *buffers)
 {
 	for (;;) {
 		if (!q->is_0copy_sbals_q) {
@@ -3281,7 +3465,7 @@ int do_QDIO(int irq,unsigned int callfla
 					qdio_kick_outbound_q(q);
 				}
 
-				qdio_outbound_processing(q);
+				__qdio_outbound_processing(q);
 			} else {
 				/* under VM, we do a SIGA sync
 				 * unconditionally */
@@ -3309,7 +3493,7 @@ int do_QDIO(int irq,unsigned int callfla
 				 * too long, the upper layer
 				 * module could do a lot of
 				 * traffic in that time */
-				qdio_outbound_processing(q);
+				__qdio_outbound_processing(q);
 			}
 		}
 
@@ -3349,7 +3533,7 @@ static int qdio_perf_procfile_read(char 
 		 perf_stats.siga_ins);
 	_OUTP_IT("Number of SIGA out's issued                     : %u\n",
 		 perf_stats.siga_outs);
-	_OUTP_IT("Number of PCI's caught                          : %u\n",
+	_OUTP_IT("Number of PCIs caught                           : %u\n",
 		 perf_stats.pcis);
 	_OUTP_IT("Number of adapter interrupts caught             : %u\n",
 		 perf_stats.thinints);
@@ -3576,10 +3760,12 @@ int init_QDIO(void)
 
 	qdio_add_procfs_entry();
 
-	hydra_thinints=qdio_check_for_hydra_thinints();
+	qdio_check_for_machine_features();
 
 	sprintf(dbf_text,"hydrati%1x",hydra_thinints);
 	QDIO_DBF_TEXT0(0,setup,dbf_text);
+	sprintf(dbf_text,"omitsvs%1x",omit_svs);
+	QDIO_DBF_TEXT0(0,setup,dbf_text);
 
 	tiqdio_register_thinints();
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/s390/s390io.c linux-2.4.28-pre3/drivers/s390/s390io.c
--- linux-2.4.27/drivers/s390/s390io.c	2004-08-07 23:26:05.000000000 +0000
+++ linux-2.4.28-pre3/drivers/s390/s390io.c	2004-09-10 19:33:16.000000000 +0000
@@ -1,7 +1,7 @@
 /*
  *  drivers/s390/s390io.c
  *   S/390 common I/O routines
- *   $Revision: 1.258 $
+ *   $Revision: 1.247.4.4 $
  *
  *  S390 version
  *    Copyright (C) 1999, 2000 IBM Deutschland Entwicklung GmbH,
@@ -3043,7 +3043,16 @@ s390_process_IRQ (unsigned int irq)
 		if (!ioinfo[irq]->ui.flags.ready)
 			return (ending_status);
 
-		memcpy (udp, &(ioinfo[irq]->devstat), sdevstat);
+		/*
+		 * Special case: We got a deferred cc 3 on a basic sense.
+		 * We have to notify the device driver of the former unit
+		 * check, but must not confuse it by calling it with the status
+		 * for the failed basic sense.
+		 */
+		if (ioinfo[irq]->ui.flags.w4sense)
+			ioinfo[irq]->ui.flags.w4sense = 0;
+		else
+			memcpy (udp, &(ioinfo[irq]->devstat), sdevstat);
 
 		ioinfo[irq]->devstat.intparm = 0;
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/sbus/char/bpp.c linux-2.4.28-pre3/drivers/sbus/char/bpp.c
--- linux-2.4.27/drivers/sbus/char/bpp.c	2001-10-11 16:43:29.000000000 +0000
+++ linux-2.4.28-pre3/drivers/sbus/char/bpp.c	2004-09-10 19:32:08.000000000 +0000
@@ -1073,3 +1073,5 @@ static void __exit bpp_cleanup(void)
 
 module_init(bpp_init);
 module_exit(bpp_cleanup);
+
+MODULE_LICENSE("GPL");
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/sbus/char/vfc_dev.c linux-2.4.28-pre3/drivers/sbus/char/vfc_dev.c
--- linux-2.4.27/drivers/sbus/char/vfc_dev.c	2001-08-12 17:38:48.000000000 +0000
+++ linux-2.4.28-pre3/drivers/sbus/char/vfc_dev.c	2004-09-10 19:35:17.000000000 +0000
@@ -743,4 +743,4 @@ void cleanup_module(void)
 }
 #endif
 
-
+MODULE_LICENSE("GPL");
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/scsi/53c7,8xx.c linux-2.4.28-pre3/drivers/scsi/53c7,8xx.c
--- linux-2.4.27/drivers/scsi/53c7,8xx.c	2003-11-28 18:26:20.000000000 +0000
+++ linux-2.4.28-pre3/drivers/scsi/53c7,8xx.c	2004-09-10 19:32:13.000000000 +0000
@@ -3926,7 +3926,7 @@ NCR53c7xx_queue_command (Scsi_Cmnd *cmd,
 	restore_flags (flags);
 	cmd->result = le32_to_cpu(0xffff);	/* The NCR will overwrite message
 				       and status with valid data */
-	cmd->host_scribble = (unsigned char *) tmp = create_cmd (cmd);
+	cmd->host_scribble = (unsigned char *) create_cmd (cmd);
     }
     cli();
     /*
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/scsi/AM53C974.c linux-2.4.28-pre3/drivers/scsi/AM53C974.c
--- linux-2.4.27/drivers/scsi/AM53C974.c	2001-09-30 19:26:07.000000000 +0000
+++ linux-2.4.28-pre3/drivers/scsi/AM53C974.c	2004-09-10 19:34:48.000000000 +0000
@@ -1027,6 +1027,78 @@ static void do_AM53C974_intr(int irq, vo
 	spin_unlock_irqrestore(&io_request_lock, flags);
 }
 
+/************************************************************************** 
+* Function : AM53C974_set_async(struct Scsi_Host *instance, int target)
+*
+* Purpose : put controller into async. mode
+*
+* Inputs : instance -- which AM53C974
+*          target -- which SCSI target to deal with
+* 
+* Returns : nothing
+**************************************************************************/
+static __inline__ void AM53C974_set_async(struct Scsi_Host *instance, int target)
+{
+	AM53C974_local_declare();
+	struct AM53C974_hostdata *hostdata = (struct AM53C974_hostdata *) instance->hostdata;
+	AM53C974_setio(instance);
+
+	AM53C974_write_8(STPREG, hostdata->sync_per[target]);
+	AM53C974_write_8(SOFREG, (DEF_SOF_RAD << 6) | (DEF_SOF_RAA << 4));
+}
+
+/************************************************************************** 
+* Function : AM53C974_set_sync(struct Scsi_Host *instance, int target)
+*
+* Purpose : put controller into sync. mode
+*
+* Inputs : instance -- which AM53C974
+*          target -- which SCSI target to deal with
+* 
+* Returns : nothing
+**************************************************************************/
+static __inline__ void AM53C974_set_sync(struct Scsi_Host *instance, int target)
+{
+	AM53C974_local_declare();
+	struct AM53C974_hostdata *hostdata = (struct AM53C974_hostdata *) instance->hostdata;
+	AM53C974_setio(instance);
+
+	AM53C974_write_8(STPREG, hostdata->sync_per[target]);
+	AM53C974_write_8(SOFREG, (SOFREG_SO & hostdata->sync_off[target]) |
+			 (DEF_SOF_RAD << 6) | (DEF_SOF_RAA << 4));
+}
+
+/************************************************************************** 
+* Function : AM53C974_transfer_dma(struct Scsi_Host *instance, short dir,
+*                                  unsigned long length, char *data)
+*
+* Purpose : setup DMA transfer
+*
+* Inputs : instance -- which AM53C974
+*          dir -- direction flag, 0: write to device, read from memory; 
+*                                 1: read from device, write to memory
+*          length -- number of bytes to transfer to from buffer
+*          data -- pointer to data buffer
+* 
+* Returns : nothing
+**************************************************************************/
+static __inline__ void AM53C974_transfer_dma(struct Scsi_Host *instance, short dir,
+					unsigned long length, char *data)
+{
+	AM53C974_local_declare();
+	AM53C974_setio(instance);
+
+	AM53C974_write_8(CMDREG, CMDREG_NOP);
+	AM53C974_write_8(DMACMD, (dir << 7) | DMACMD_INTE_D);	/* idle command */
+	AM53C974_write_8(STCLREG, (unsigned char) (length & 0xff));
+	AM53C974_write_8(STCMREG, (unsigned char) ((length & 0xff00) >> 8));
+	AM53C974_write_8(STCHREG, (unsigned char) ((length & 0xff0000) >> 16));
+	AM53C974_write_32(DMASTC, length & 0xffffff);
+	AM53C974_write_32(DMASPA, virt_to_bus(data));
+	AM53C974_write_8(CMDREG, CMDREG_IT | CMDREG_DMA);
+	AM53C974_write_8(DMACMD, (dir << 7) | DMACMD_INTE_D | DMACMD_START);
+}
+
 /************************************************************************
 * Function : AM53C974_intr(int irq, void *dev_id, struct pt_regs *regs) *
 *                                                                       *
@@ -1464,47 +1536,6 @@ static int AM53C974_sync_neg(struct Scsi
 	return (0);
 }
 
-/************************************************************************** 
-* Function : AM53C974_set_async(struct Scsi_Host *instance, int target)
-*
-* Purpose : put controller into async. mode
-*
-* Inputs : instance -- which AM53C974
-*          target -- which SCSI target to deal with
-* 
-* Returns : nothing
-**************************************************************************/
-static __inline__ void AM53C974_set_async(struct Scsi_Host *instance, int target)
-{
-	AM53C974_local_declare();
-	struct AM53C974_hostdata *hostdata = (struct AM53C974_hostdata *) instance->hostdata;
-	AM53C974_setio(instance);
-
-	AM53C974_write_8(STPREG, hostdata->sync_per[target]);
-	AM53C974_write_8(SOFREG, (DEF_SOF_RAD << 6) | (DEF_SOF_RAA << 4));
-}
-
-/************************************************************************** 
-* Function : AM53C974_set_sync(struct Scsi_Host *instance, int target)
-*
-* Purpose : put controller into sync. mode
-*
-* Inputs : instance -- which AM53C974
-*          target -- which SCSI target to deal with
-* 
-* Returns : nothing
-**************************************************************************/
-static __inline__ void AM53C974_set_sync(struct Scsi_Host *instance, int target)
-{
-	AM53C974_local_declare();
-	struct AM53C974_hostdata *hostdata = (struct AM53C974_hostdata *) instance->hostdata;
-	AM53C974_setio(instance);
-
-	AM53C974_write_8(STPREG, hostdata->sync_per[target]);
-	AM53C974_write_8(SOFREG, (SOFREG_SO & hostdata->sync_off[target]) |
-			 (DEF_SOF_RAD << 6) | (DEF_SOF_RAA << 4));
-}
-
 /***********************************************************************
 * Function : AM53C974_information_transfer(struct Scsi_Host *instance, *
 *                          unsigned char statreg, unsigned char isreg, *
@@ -2157,37 +2188,6 @@ static void AM53C974_intr_reselect(struc
 }
 
 /************************************************************************** 
-* Function : AM53C974_transfer_dma(struct Scsi_Host *instance, short dir,
-*                                  unsigned long length, char *data)
-*
-* Purpose : setup DMA transfer
-*
-* Inputs : instance -- which AM53C974
-*          dir -- direction flag, 0: write to device, read from memory; 
-*                                 1: read from device, write to memory
-*          length -- number of bytes to transfer to from buffer
-*          data -- pointer to data buffer
-* 
-* Returns : nothing
-**************************************************************************/
-static __inline__ void AM53C974_transfer_dma(struct Scsi_Host *instance, short dir,
-					unsigned long length, char *data)
-{
-	AM53C974_local_declare();
-	AM53C974_setio(instance);
-
-	AM53C974_write_8(CMDREG, CMDREG_NOP);
-	AM53C974_write_8(DMACMD, (dir << 7) | DMACMD_INTE_D);	/* idle command */
-	AM53C974_write_8(STCLREG, (unsigned char) (length & 0xff));
-	AM53C974_write_8(STCMREG, (unsigned char) ((length & 0xff00) >> 8));
-	AM53C974_write_8(STCHREG, (unsigned char) ((length & 0xff0000) >> 16));
-	AM53C974_write_32(DMASTC, length & 0xffffff);
-	AM53C974_write_32(DMASPA, virt_to_bus(data));
-	AM53C974_write_8(CMDREG, CMDREG_IT | CMDREG_DMA);
-	AM53C974_write_8(DMACMD, (dir << 7) | DMACMD_INTE_D | DMACMD_START);
-}
-
-/************************************************************************** 
 * Function : AM53C974_dma_blast(struct Scsi_Host *instance, unsigned char dmastatus,
 *                               unsigned char statreg)
 *
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/scsi/Config.in linux-2.4.28-pre3/drivers/scsi/Config.in
--- linux-2.4.27/drivers/scsi/Config.in	2004-08-07 23:26:05.000000000 +0000
+++ linux-2.4.28-pre3/drivers/scsi/Config.in	2004-09-10 19:34:24.000000000 +0000
@@ -70,6 +70,8 @@ dep_tristate 'AMI MegaRAID support' CONF
 dep_tristate 'AMI MegaRAID2 support' CONFIG_SCSI_MEGARAID2 $CONFIG_SCSI
 dep_mbool 'Serial ATA (SATA) support' CONFIG_SCSI_SATA $CONFIG_SCSI
 dep_tristate '  ServerWorks Frodo / Apple K2 SATA support (EXPERIMENTAL)' CONFIG_SCSI_SATA_SVW $CONFIG_SCSI_SATA $CONFIG_PCI $CONFIG_EXPERIMENTAL
+dep_tristate '  Intel PIIX/ICH SATA support' CONFIG_SCSI_ATA_PIIX $CONFIG_SCSI_SATA $CONFIG_PCI
+dep_tristate '  NVIDIA SATA support (EXPERIMENTAL)' CONFIG_SCSI_SATA_NV $CONFIG_SCSI_SATA $CONFIG_PCI
 dep_tristate '  Promise SATA TX2/TX4 support (EXPERIMENTAL)' CONFIG_SCSI_SATA_PROMISE $CONFIG_SCSI_SATA $CONFIG_PCI $CONFIG_EXPERIMENTAL
 dep_tristate '  Promise SATA SX4 support (EXPERIMENTAL)' CONFIG_SCSI_SATA_SX4 $CONFIG_SCSI_SATA $CONFIG_PCI $CONFIG_EXPERIMENTAL
 dep_tristate '  Silicon Image SATA support (EXPERIMENTAL)' CONFIG_SCSI_SATA_SIL $CONFIG_SCSI_SATA $CONFIG_PCI $CONFIG_EXPERIMENTAL
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/scsi/Makefile linux-2.4.28-pre3/drivers/scsi/Makefile
--- linux-2.4.27/drivers/scsi/Makefile	2004-08-07 23:26:05.000000000 +0000
+++ linux-2.4.28-pre3/drivers/scsi/Makefile	2004-09-10 19:36:25.000000000 +0000
@@ -131,12 +131,14 @@ obj-$(CONFIG_SCSI_CPQFCTS)	+= cpqfc.o
 obj-$(CONFIG_SCSI_LASI700)	+= lasi700.o 53c700.o
 obj-$(CONFIG_SCSI_NSP32)	+= nsp32.o
 obj-$(CONFIG_SCSI_SATA_SVW)	+= libata.o sata_svw.o
+obj-$(CONFIG_SCSI_ATA_PIIX)	+= libata.o ata_piix.o
 obj-$(CONFIG_SCSI_SATA_PROMISE)	+= libata.o sata_promise.o
 obj-$(CONFIG_SCSI_SATA_SIL)	+= libata.o sata_sil.o
 obj-$(CONFIG_SCSI_SATA_VIA)	+= libata.o sata_via.o
 obj-$(CONFIG_SCSI_SATA_VITESSE)	+= libata.o sata_vsc.o
 obj-$(CONFIG_SCSI_SATA_SIS)	+= libata.o sata_sis.o
 obj-$(CONFIG_SCSI_SATA_SX4)	+= libata.o sata_sx4.o
+obj-$(CONFIG_SCSI_SATA_NV)	+= libata.o sata_nv.o
 
 subdir-$(CONFIG_ARCH_ACORN)	+= ../acorn/scsi
 obj-$(CONFIG_ARCH_ACORN)	+= ../acorn/scsi/acorn-scsi.o
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/scsi/advansys.c linux-2.4.28-pre3/drivers/scsi/advansys.c
--- linux-2.4.27/drivers/scsi/advansys.c	2004-04-14 13:05:31.000000000 +0000
+++ linux-2.4.28-pre3/drivers/scsi/advansys.c	2004-09-10 19:33:35.000000000 +0000
@@ -6118,8 +6118,8 @@ advansys_reset(Scsi_Cmnd *scp)
     } else {
         /* Append to 'done_scp' at the end with 'last_scp'. */
         ASC_ASSERT(last_scp != NULL);
-        REQPNEXT(last_scp) = asc_dequeue_list(&boardp->active,
-            &new_last_scp, ASC_TID_ALL);
+        last_scp->host_scribble = (unsigned char *)asc_dequeue_list(
+			&boardp->active, &new_last_scp, ASC_TID_ALL);
         if (new_last_scp != NULL) {
             ASC_ASSERT(REQPNEXT(last_scp) != NULL);
             for (tscp = REQPNEXT(last_scp); tscp; tscp = REQPNEXT(tscp)) {
@@ -6141,8 +6141,8 @@ advansys_reset(Scsi_Cmnd *scp)
     } else {
         /* Append to 'done_scp' at the end with 'last_scp'. */
         ASC_ASSERT(last_scp != NULL);
-        REQPNEXT(last_scp) = asc_dequeue_list(&boardp->waiting,
-            &new_last_scp, ASC_TID_ALL);
+        last_scp->host_scribble = (unsigned char *)asc_dequeue_list(
+			&boardp->waiting, &new_last_scp, ASC_TID_ALL);
         if (new_last_scp != NULL) {
             ASC_ASSERT(REQPNEXT(last_scp) != NULL);
             for (tscp = REQPNEXT(last_scp); tscp; tscp = REQPNEXT(tscp)) {
@@ -6394,8 +6394,8 @@ advansys_interrupt(int irq, void *dev_id
                     ASC_TID_ALL);
             } else {
                 ASC_ASSERT(last_scp != NULL);
-                REQPNEXT(last_scp) = asc_dequeue_list(&boardp->done,
-                    &new_last_scp, ASC_TID_ALL);
+                last_scp->host_scribble = (unsigned char *)asc_dequeue_list(
+			&boardp->done, &new_last_scp, ASC_TID_ALL);
                 if (new_last_scp != NULL) {
                     ASC_ASSERT(REQPNEXT(last_scp) != NULL);
                     last_scp = new_last_scp;
@@ -6466,7 +6466,7 @@ asc_scsi_done_list(Scsi_Cmnd *scp)
     while (scp != NULL) {
         ASC_DBG1(3, "asc_scsi_done_list: scp 0x%lx\n", (ulong) scp);
         tscp = REQPNEXT(scp);
-        REQPNEXT(scp) = NULL;
+        scp->host_scribble = NULL;
         ASC_STATS(scp->host, done);
         ASC_ASSERT(scp->scsi_done != NULL);
         scp->scsi_done(scp);
@@ -7511,7 +7511,7 @@ asc_enqueue(asc_queue_t *ascq, REQP reqp
     tid = REQPTID(reqp);
     ASC_ASSERT(tid >= 0 && tid <= ADV_MAX_TID);
     if (flag == ASC_FRONT) {
-        REQPNEXT(reqp) = ascq->q_first[tid];
+        reqp->host_scribble = (unsigned char *)ascq->q_first[tid];
         ascq->q_first[tid] = reqp;
         /* If the queue was empty, set the last pointer. */
         if (ascq->q_last[tid] == NULL) {
@@ -7519,10 +7519,10 @@ asc_enqueue(asc_queue_t *ascq, REQP reqp
         }
     } else { /* ASC_BACK */
         if (ascq->q_last[tid] != NULL) {
-            REQPNEXT(ascq->q_last[tid]) = reqp;
+            ascq->q_last[tid]->host_scribble = (unsigned char *)reqp;
         }
         ascq->q_last[tid] = reqp;
-        REQPNEXT(reqp) = NULL;
+        reqp->host_scribble = NULL;
         /* If the queue was empty, set the first pointer. */
         if (ascq->q_first[tid] == NULL) {
             ascq->q_first[tid] = reqp;
@@ -7643,7 +7643,7 @@ asc_dequeue_list(asc_queue_t *ascq, REQP
                     lastp = ascq->q_last[i];
                 } else {
                     ASC_ASSERT(lastp != NULL);
-                    REQPNEXT(lastp) = ascq->q_first[i];
+                    lastp->host_scribble = (unsigned char *)ascq->q_first[i];
                     lastp = ascq->q_last[i];
                 }
                 ascq->q_first[i] = ascq->q_last[i] = NULL;
@@ -7721,8 +7721,8 @@ asc_rmqueue(asc_queue_t *ascq, REQP reqp
              currp; prevp = currp, currp = REQPNEXT(currp)) {
             if (currp == reqp) {
                 ret = ASC_TRUE;
-                REQPNEXT(prevp) = REQPNEXT(currp);
-                REQPNEXT(reqp) = NULL;
+                prevp->host_scribble = (unsigned char *)REQPNEXT(currp);
+                reqp->host_scribble = NULL;
                 if (ascq->q_last[tid] == reqp) {
                     ascq->q_last[tid] = prevp;
                 }
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/scsi/aic7xxx/aic79xx_osm.c linux-2.4.28-pre3/drivers/scsi/aic7xxx/aic79xx_osm.c
--- linux-2.4.27/drivers/scsi/aic7xxx/aic79xx_osm.c	2003-08-25 11:44:42.000000000 +0000
+++ linux-2.4.28-pre3/drivers/scsi/aic7xxx/aic79xx_osm.c	2004-09-10 19:32:30.000000000 +0000
@@ -2931,6 +2931,19 @@ out:
 	ahd_unlock(ahd, &s);
 }
 
+static __inline int
+ahd_linux_dv_fallback(struct ahd_softc *ahd, struct ahd_devinfo *devinfo)
+{
+	u_long s;
+	int retval;
+
+	ahd_lock(ahd, &s);
+	retval = ahd_linux_fallback(ahd, devinfo);
+	ahd_unlock(ahd, &s);
+
+	return (retval);
+}
+
 static void
 ahd_linux_dv_transition(struct ahd_softc *ahd, struct scsi_cmnd *cmd,
 			struct ahd_devinfo *devinfo,
@@ -3567,19 +3580,6 @@ ahd_linux_dv_su(struct ahd_softc *ahd, s
 	cmd->cmnd[4] = le | SSS_START;
 }
 
-static __inline int
-ahd_linux_dv_fallback(struct ahd_softc *ahd, struct ahd_devinfo *devinfo)
-{
-	u_long s;
-	int retval;
-
-	ahd_lock(ahd, &s);
-	retval = ahd_linux_fallback(ahd, devinfo);
-	ahd_unlock(ahd, &s);
-
-	return (retval);
-}
-
 static int
 ahd_linux_fallback(struct ahd_softc *ahd, struct ahd_devinfo *devinfo)
 {
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/scsi/ata_piix.c linux-2.4.28-pre3/drivers/scsi/ata_piix.c
--- linux-2.4.27/drivers/scsi/ata_piix.c	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.28-pre3/drivers/scsi/ata_piix.c	2004-09-10 19:37:11.000000000 +0000
@@ -0,0 +1,680 @@
+/*
+
+    ata_piix.c - Intel PATA/SATA controllers
+
+    Maintained by:  Jeff Garzik <jgarzik@pobox.com>
+    		    Please ALWAYS copy linux-ide@vger.kernel.org
+		    on emails.
+
+
+	Copyright 2003-2004 Red Hat Inc
+	Copyright 2003-2004 Jeff Garzik
+
+
+	Copyright header from piix.c:
+
+    Copyright (C) 1998-1999 Andrzej Krzysztofowicz, Author and Maintainer
+    Copyright (C) 1998-2000 Andre Hedrick <andre@linux-ide.org>
+    Copyright (C) 2003 Red Hat Inc <alan@redhat.com>
+
+    May be copied or modified under the terms of the GNU General Public License
+
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/blkdev.h>
+#include <linux/delay.h>
+#include "scsi.h"
+#include <scsi/scsi_host.h>
+#include <linux/libata.h>
+
+#define DRV_NAME	"ata_piix"
+#define DRV_VERSION	"1.02"
+
+enum {
+	PIIX_IOCFG		= 0x54, /* IDE I/O configuration register */
+	ICH5_PMR		= 0x90, /* port mapping register */
+	ICH5_PCS		= 0x92,	/* port control and status */
+
+	PIIX_FLAG_AHCI		= (1 << 28), /* AHCI possible */
+	PIIX_FLAG_CHECKINTR	= (1 << 29), /* make sure PCI INTx enabled */
+	PIIX_FLAG_COMBINED	= (1 << 30), /* combined mode possible */
+
+	/* combined mode.  if set, PATA is channel 0.
+	 * if clear, PATA is channel 1.
+	 */
+	PIIX_COMB_PATA_P0	= (1 << 1),
+	PIIX_COMB		= (1 << 2), /* combined mode enabled? */
+
+	PIIX_PORT_PRESENT	= (1 << 0),
+	PIIX_PORT_ENABLED	= (1 << 4),
+
+	PIIX_80C_PRI		= (1 << 5) | (1 << 4),
+	PIIX_80C_SEC		= (1 << 7) | (1 << 6),
+
+	ich5_pata		= 0,
+	ich5_sata		= 1,
+	piix4_pata		= 2,
+	ich6_sata		= 3,
+	ich6_sata_rm		= 4,
+};
+
+static int piix_init_one (struct pci_dev *pdev,
+				    const struct pci_device_id *ent);
+
+static void piix_pata_phy_reset(struct ata_port *ap);
+static void piix_sata_phy_reset(struct ata_port *ap);
+static void piix_set_piomode (struct ata_port *ap, struct ata_device *adev);
+static void piix_set_dmamode (struct ata_port *ap, struct ata_device *adev);
+
+static unsigned int in_module_init = 1;
+
+static struct pci_device_id piix_pci_tbl[] = {
+#ifdef ATA_ENABLE_PATA
+	{ 0x8086, 0x7111, PCI_ANY_ID, PCI_ANY_ID, 0, 0, piix4_pata },
+	{ 0x8086, 0x24db, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich5_pata },
+	{ 0x8086, 0x25a2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich5_pata },
+#endif
+
+	/* NOTE: The following PCI ids must be kept in sync with the
+	 * list in drivers/pci/quirks.c.
+	 */
+
+	{ 0x8086, 0x24d1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich5_sata },
+	{ 0x8086, 0x24df, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich5_sata },
+	{ 0x8086, 0x25a3, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich5_sata },
+	{ 0x8086, 0x25b0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich5_sata },
+	{ 0x8086, 0x2651, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata },
+	{ 0x8086, 0x2652, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata_rm },
+	{ 0x8086, 0x2653, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata_rm },
+
+	{ }	/* terminate list */
+};
+
+static struct pci_driver piix_pci_driver = {
+	.name			= DRV_NAME,
+	.id_table		= piix_pci_tbl,
+	.probe			= piix_init_one,
+	.remove			= ata_pci_remove_one,
+};
+
+static Scsi_Host_Template piix_sht = {
+	.module			= THIS_MODULE,
+	.name			= DRV_NAME,
+	.detect			= ata_scsi_detect,
+	.release		= ata_scsi_release,
+	.ioctl                  = ata_scsi_ioctl,
+	.queuecommand		= ata_scsi_queuecmd,
+	.eh_strategy_handler	= ata_scsi_error,
+	.can_queue		= ATA_DEF_QUEUE,
+	.this_id		= ATA_SHT_THIS_ID,
+	.sg_tablesize		= LIBATA_MAX_PRD,
+	.max_sectors		= ATA_MAX_SECTORS,
+	.cmd_per_lun		= ATA_SHT_CMD_PER_LUN,
+	.use_new_eh_code	= ATA_SHT_NEW_EH_CODE,
+	.emulated		= ATA_SHT_EMULATED,
+	.use_clustering		= ATA_SHT_USE_CLUSTERING,
+	.proc_name		= DRV_NAME,
+	.bios_param		= ata_std_bios_param,
+};
+
+static struct ata_port_operations piix_pata_ops = {
+	.port_disable		= ata_port_disable,
+	.set_piomode		= piix_set_piomode,
+	.set_dmamode		= piix_set_dmamode,
+
+	.tf_load		= ata_tf_load_pio,
+	.tf_read		= ata_tf_read_pio,
+	.check_status		= ata_check_status_pio,
+	.exec_command		= ata_exec_command_pio,
+
+	.phy_reset		= piix_pata_phy_reset,
+
+	.bmdma_setup		= ata_bmdma_setup_pio,
+	.bmdma_start		= ata_bmdma_start_pio,
+	.qc_prep		= ata_qc_prep,
+	.qc_issue		= ata_qc_issue_prot,
+
+	.eng_timeout		= ata_eng_timeout,
+
+	.irq_handler		= ata_interrupt,
+	.irq_clear		= ata_bmdma_irq_clear,
+
+	.port_start		= ata_port_start,
+	.port_stop		= ata_port_stop,
+};
+
+static struct ata_port_operations piix_sata_ops = {
+	.port_disable		= ata_port_disable,
+
+	.tf_load		= ata_tf_load_pio,
+	.tf_read		= ata_tf_read_pio,
+	.check_status		= ata_check_status_pio,
+	.exec_command		= ata_exec_command_pio,
+
+	.phy_reset		= piix_sata_phy_reset,
+
+	.bmdma_setup		= ata_bmdma_setup_pio,
+	.bmdma_start		= ata_bmdma_start_pio,
+	.qc_prep		= ata_qc_prep,
+	.qc_issue		= ata_qc_issue_prot,
+
+	.eng_timeout		= ata_eng_timeout,
+
+	.irq_handler		= ata_interrupt,
+	.irq_clear		= ata_bmdma_irq_clear,
+
+	.port_start		= ata_port_start,
+	.port_stop		= ata_port_stop,
+};
+
+static struct ata_port_info piix_port_info[] = {
+	/* ich5_pata */
+	{
+		.sht		= &piix_sht,
+		.host_flags	= ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST |
+				  PIIX_FLAG_CHECKINTR,
+		.pio_mask	= 0x1f,	/* pio0-4 */
+#if 0
+		.mwdma_mask	= 0x06, /* mwdma1-2 */
+#else
+		.mwdma_mask	= 0x00, /* mwdma broken */
+#endif
+		.udma_mask	= ATA_UDMA_MASK_40C, /* FIXME: cbl det */
+		.port_ops	= &piix_pata_ops,
+	},
+
+	/* ich5_sata */
+	{
+		.sht		= &piix_sht,
+		.host_flags	= ATA_FLAG_SATA | ATA_FLAG_SRST |
+				  PIIX_FLAG_COMBINED | PIIX_FLAG_CHECKINTR,
+		.pio_mask	= 0x1f,	/* pio0-4 */
+		.mwdma_mask	= 0x07, /* mwdma0-2 */
+		.udma_mask	= 0x7f,	/* udma0-6 */
+		.port_ops	= &piix_sata_ops,
+	},
+
+	/* piix4_pata */
+	{
+		.sht		= &piix_sht,
+		.host_flags	= ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+		.pio_mask	= 0x1f,	/* pio0-4 */
+#if 0
+		.mwdma_mask	= 0x06, /* mwdma1-2 */
+#else
+		.mwdma_mask	= 0x00, /* mwdma broken */
+#endif
+		.udma_mask	= ATA_UDMA_MASK_40C, /* FIXME: cbl det */
+		.port_ops	= &piix_pata_ops,
+	},
+
+	/* ich6_sata */
+	{
+		.sht		= &piix_sht,
+		.host_flags	= ATA_FLAG_SATA | ATA_FLAG_SRST |
+				  PIIX_FLAG_COMBINED | PIIX_FLAG_CHECKINTR |
+				  ATA_FLAG_SLAVE_POSS,
+		.pio_mask	= 0x1f,	/* pio0-4 */
+		.mwdma_mask	= 0x07, /* mwdma0-2 */
+		.udma_mask	= 0x7f,	/* udma0-6 */
+		.port_ops	= &piix_sata_ops,
+	},
+
+	/* ich6_sata_rm */
+	{
+		.sht		= &piix_sht,
+		.host_flags	= ATA_FLAG_SATA | ATA_FLAG_SRST |
+				  PIIX_FLAG_COMBINED | PIIX_FLAG_CHECKINTR |
+				  ATA_FLAG_SLAVE_POSS | PIIX_FLAG_AHCI,
+		.pio_mask	= 0x1f,	/* pio0-4 */
+		.mwdma_mask	= 0x07, /* mwdma0-2 */
+		.udma_mask	= 0x7f,	/* udma0-6 */
+		.port_ops	= &piix_sata_ops,
+	},
+};
+
+static struct pci_bits piix_enable_bits[] = {
+	{ 0x41U, 1U, 0x80UL, 0x80UL },	/* port 0 */
+	{ 0x43U, 1U, 0x80UL, 0x80UL },	/* port 1 */
+};
+
+MODULE_AUTHOR("Andre Hedrick, Alan Cox, Andrzej Krzysztofowicz, Jeff Garzik");
+MODULE_DESCRIPTION("SCSI low-level driver for Intel PIIX/ICH ATA controllers");
+MODULE_LICENSE("GPL");
+MODULE_DEVICE_TABLE(pci, piix_pci_tbl);
+
+/**
+ *	piix_pata_cbl_detect - Probe host controller cable detect info
+ *	@ap: Port for which cable detect info is desired
+ *
+ *	Read 80c cable indicator from SATA PCI device's PCI config
+ *	register.  This register is normally set by firmware (BIOS).
+ *
+ *	LOCKING:
+ *	None (inherited from caller).
+ */
+static void piix_pata_cbl_detect(struct ata_port *ap)
+{
+	struct pci_dev *pdev = ap->host_set->pdev;
+	u8 tmp, mask;
+
+	/* no 80c support in host controller? */
+	if ((ap->udma_mask & ~ATA_UDMA_MASK_40C) == 0)
+		goto cbl40;
+
+	/* check BIOS cable detect results */
+	mask = ap->port_no == 0 ? PIIX_80C_PRI : PIIX_80C_SEC;
+	pci_read_config_byte(pdev, PIIX_IOCFG, &tmp);
+	if ((tmp & mask) == 0)
+		goto cbl40;
+
+	ap->cbl = ATA_CBL_PATA80;
+	return;
+
+cbl40:
+	ap->cbl = ATA_CBL_PATA40;
+	ap->udma_mask &= ATA_UDMA_MASK_40C;
+}
+
+/**
+ *	piix_pata_phy_reset - Probe specified port on PATA host controller
+ *	@ap: Port to probe
+ *
+ *	Probe PATA phy.
+ *
+ *	LOCKING:
+ *	None (inherited from caller).
+ */
+
+static void piix_pata_phy_reset(struct ata_port *ap)
+{
+	if (!pci_test_config_bits(ap->host_set->pdev,
+				  &piix_enable_bits[ap->port_no])) {
+		ata_port_disable(ap);
+		printk(KERN_INFO "ata%u: port disabled. ignoring.\n", ap->id);
+		return;
+	}
+
+	piix_pata_cbl_detect(ap);
+
+	ata_port_probe(ap);
+
+	ata_bus_reset(ap);
+}
+
+/**
+ *	piix_sata_probe - Probe PCI device for present SATA devices
+ *	@ap: Port associated with the PCI device we wish to probe
+ *
+ *	Reads SATA PCI device's PCI config register Port Configuration
+ *	and Status (PCS) to determine port and device availability.
+ *
+ *	LOCKING:
+ *	None (inherited from caller).
+ *
+ *	RETURNS:
+ *	Non-zero if device detected, zero otherwise.
+ */
+static int piix_sata_probe (struct ata_port *ap)
+{
+	struct pci_dev *pdev = ap->host_set->pdev;
+	int combined = (ap->flags & ATA_FLAG_SLAVE_POSS);
+	int orig_mask, mask, i;
+	u8 pcs;
+
+	mask = (PIIX_PORT_PRESENT << ap->port_no) |
+	       (PIIX_PORT_ENABLED << ap->port_no);
+
+	pci_read_config_byte(pdev, ICH5_PCS, &pcs);
+	orig_mask = (int) pcs & 0xff;
+
+	/* TODO: this is vaguely wrong for ICH6 combined mode,
+	 * where only two of the four SATA ports are mapped
+	 * onto a single ATA channel.  It is also vaguely inaccurate
+	 * for ICH5, which has only two ports.  However, this is ok,
+	 * as further device presence detection code will handle
+	 * any false positives produced here.
+	 */
+
+	for (i = 0; i < 4; i++) {
+		mask = (PIIX_PORT_PRESENT << i) | (PIIX_PORT_ENABLED << i);
+
+		if ((orig_mask & mask) == mask)
+			if (combined || (i == ap->port_no))
+				return 1;
+	}
+
+	return 0;
+}
+
+/**
+ *	piix_sata_phy_reset - Probe specified port on SATA host controller
+ *	@ap: Port to probe
+ *
+ *	Probe SATA phy.
+ *
+ *	LOCKING:
+ *	None (inherited from caller).
+ */
+
+static void piix_sata_phy_reset(struct ata_port *ap)
+{
+	if (!piix_sata_probe(ap)) {
+		ata_port_disable(ap);
+		printk(KERN_INFO "ata%u: SATA port has no device.\n", ap->id);
+		return;
+	}
+
+	ap->cbl = ATA_CBL_SATA;
+
+	ata_port_probe(ap);
+
+	ata_bus_reset(ap);
+}
+
+/**
+ *	piix_set_piomode - Initialize host controller PATA PIO timings
+ *	@ap: Port whose timings we are configuring
+ *	@adev: um
+ *	@pio: PIO mode, 0 - 4
+ *
+ *	Set PIO mode for device, in host controller PCI config space.
+ *
+ *	LOCKING:
+ *	None (inherited from caller).
+ */
+
+static void piix_set_piomode (struct ata_port *ap, struct ata_device *adev)
+{
+	unsigned int pio	= adev->pio_mode - XFER_PIO_0;
+	struct pci_dev *dev	= ap->host_set->pdev;
+	unsigned int is_slave	= (adev->devno != 0);
+	unsigned int master_port= ap->port_no ? 0x42 : 0x40;
+	unsigned int slave_port	= 0x44;
+	u16 master_data;
+	u8 slave_data;
+
+	static const	 /* ISP  RTC */
+	u8 timings[][2]	= { { 0, 0 },
+			    { 0, 0 },
+			    { 1, 0 },
+			    { 2, 1 },
+			    { 2, 3 }, };
+
+	pci_read_config_word(dev, master_port, &master_data);
+	if (is_slave) {
+		master_data |= 0x4000;
+		/* enable PPE, IE and TIME */
+		master_data |= 0x0070;
+		pci_read_config_byte(dev, slave_port, &slave_data);
+		slave_data &= (ap->port_no ? 0x0f : 0xf0);
+		slave_data |=
+			(timings[pio][0] << 2) |
+			(timings[pio][1] << (ap->port_no ? 4 : 0));
+	} else {
+		master_data &= 0xccf8;
+		/* enable PPE, IE and TIME */
+		master_data |= 0x0007;
+		master_data |=
+			(timings[pio][0] << 12) |
+			(timings[pio][1] << 8);
+	}
+	pci_write_config_word(dev, master_port, master_data);
+	if (is_slave)
+		pci_write_config_byte(dev, slave_port, slave_data);
+}
+
+/**
+ *	piix_set_dmamode - Initialize host controller PATA PIO timings
+ *	@ap: Port whose timings we are configuring
+ *	@adev: um
+ *	@udma: udma mode, 0 - 6
+ *
+ *	Set UDMA mode for device, in host controller PCI config space.
+ *
+ *	LOCKING:
+ *	None (inherited from caller).
+ */
+
+static void piix_set_dmamode (struct ata_port *ap, struct ata_device *adev)
+{
+	unsigned int udma	= adev->dma_mode; /* FIXME: MWDMA too */
+	struct pci_dev *dev	= ap->host_set->pdev;
+	u8 maslave		= ap->port_no ? 0x42 : 0x40;
+	u8 speed		= udma;
+	unsigned int drive_dn	= (ap->port_no ? 2 : 0) + adev->devno;
+	int a_speed		= 3 << (drive_dn * 4);
+	int u_flag		= 1 << drive_dn;
+	int v_flag		= 0x01 << drive_dn;
+	int w_flag		= 0x10 << drive_dn;
+	int u_speed		= 0;
+	int			sitre;
+	u16			reg4042, reg4a;
+	u8			reg48, reg54, reg55;
+
+	pci_read_config_word(dev, maslave, &reg4042);
+	DPRINTK("reg4042 = 0x%04x\n", reg4042);
+	sitre = (reg4042 & 0x4000) ? 1 : 0;
+	pci_read_config_byte(dev, 0x48, &reg48);
+	pci_read_config_word(dev, 0x4a, &reg4a);
+	pci_read_config_byte(dev, 0x54, &reg54);
+	pci_read_config_byte(dev, 0x55, &reg55);
+
+	switch(speed) {
+		case XFER_UDMA_4:
+		case XFER_UDMA_2:	u_speed = 2 << (drive_dn * 4); break;
+		case XFER_UDMA_6:
+		case XFER_UDMA_5:
+		case XFER_UDMA_3:
+		case XFER_UDMA_1:	u_speed = 1 << (drive_dn * 4); break;
+		case XFER_UDMA_0:	u_speed = 0 << (drive_dn * 4); break;
+		case XFER_MW_DMA_2:
+		case XFER_MW_DMA_1:	break;
+		default:
+			BUG();
+			return;
+	}
+
+	if (speed >= XFER_UDMA_0) {
+		if (!(reg48 & u_flag))
+			pci_write_config_byte(dev, 0x48, reg48 | u_flag);
+		if (speed == XFER_UDMA_5) {
+			pci_write_config_byte(dev, 0x55, (u8) reg55|w_flag);
+		} else {
+			pci_write_config_byte(dev, 0x55, (u8) reg55 & ~w_flag);
+		}
+		if ((reg4a & a_speed) != u_speed)
+			pci_write_config_word(dev, 0x4a, (reg4a & ~a_speed) | u_speed);
+		if (speed > XFER_UDMA_2) {
+			if (!(reg54 & v_flag))
+				pci_write_config_byte(dev, 0x54, reg54 | v_flag);
+		} else
+			pci_write_config_byte(dev, 0x54, reg54 & ~v_flag);
+	} else {
+		if (reg48 & u_flag)
+			pci_write_config_byte(dev, 0x48, reg48 & ~u_flag);
+		if (reg4a & a_speed)
+			pci_write_config_word(dev, 0x4a, reg4a & ~a_speed);
+		if (reg54 & v_flag)
+			pci_write_config_byte(dev, 0x54, reg54 & ~v_flag);
+		if (reg55 & w_flag)
+			pci_write_config_byte(dev, 0x55, (u8) reg55 & ~w_flag);
+	}
+}
+
+/* move to PCI layer, integrate w/ MSI stuff */
+static void pci_enable_intx(struct pci_dev *pdev)
+{
+	u16 pci_command;
+
+	pci_read_config_word(pdev, PCI_COMMAND, &pci_command);
+	if (pci_command & PCI_COMMAND_INTX_DISABLE) {
+		pci_command &= ~PCI_COMMAND_INTX_DISABLE;
+		pci_write_config_word(pdev, PCI_COMMAND, pci_command);
+	}
+}
+
+#define AHCI_PCI_BAR 5
+#define AHCI_GLOBAL_CTL 0x04
+#define AHCI_ENABLE (1 << 31)
+static int piix_disable_ahci(struct pci_dev *pdev)
+{
+	void *mmio;
+	unsigned long addr;
+	u32 tmp;
+	int rc = 0;
+
+	/* BUG: pci_enable_device has not yet been called.  This
+	 * works because this device is usually set up by BIOS.
+	 */
+
+	addr = pci_resource_start(pdev, AHCI_PCI_BAR);
+	if (!addr || !pci_resource_len(pdev, AHCI_PCI_BAR))
+		return 0;
+	
+	mmio = ioremap(addr, 64);
+	if (!mmio)
+		return -ENOMEM;
+	
+	tmp = readl(mmio + AHCI_GLOBAL_CTL);
+	if (tmp & AHCI_ENABLE) {
+		tmp &= ~AHCI_ENABLE;
+		writel(tmp, mmio + AHCI_GLOBAL_CTL);
+
+		tmp = readl(mmio + AHCI_GLOBAL_CTL);
+		if (tmp & AHCI_ENABLE)
+			rc = -EIO;
+	}
+	
+	iounmap(mmio);
+	return rc;
+}
+
+/**
+ *	piix_init_one - Register PIIX ATA PCI device with kernel services
+ *	@pdev: PCI device to register
+ *	@ent: Entry in piix_pci_tbl matching with @pdev
+ *
+ *	Called from kernel PCI layer.  We probe for combined mode (sigh),
+ *	and then hand over control to libata, for it to do the rest.
+ *
+ *	LOCKING:
+ *	Inherited from PCI layer (may sleep).
+ *
+ *	RETURNS:
+ *	Zero on success, or -ERRNO value.
+ */
+
+static int piix_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+	static int printed_version;
+	struct ata_port_info *port_info[2];
+	unsigned int combined = 0, n_ports = 1;
+	unsigned int pata_chan = 0, sata_chan = 0;
+
+	if (!printed_version++)
+		printk(KERN_DEBUG DRV_NAME " version " DRV_VERSION "\n");
+
+	/* no hotplugging support (FIXME) */
+	if (!in_module_init)
+		return -ENODEV;
+
+	port_info[0] = &piix_port_info[ent->driver_data];
+	port_info[1] = NULL;
+
+	if (port_info[0]->host_flags & PIIX_FLAG_AHCI) {
+		int rc = piix_disable_ahci(pdev);
+		if (rc)
+			return rc;
+	}
+
+	if (port_info[0]->host_flags & PIIX_FLAG_COMBINED) {
+		u8 tmp;
+		pci_read_config_byte(pdev, ICH5_PMR, &tmp);
+
+		if (tmp & PIIX_COMB) {
+			combined = 1;
+			if (tmp & PIIX_COMB_PATA_P0)
+				sata_chan = 1;
+			else
+				pata_chan = 1;
+		}
+	}
+
+	/* On ICH5, some BIOSen disable the interrupt using the
+	 * PCI_COMMAND_INTX_DISABLE bit added in PCI 2.3.
+	 * On ICH6, this bit has the same effect, but only when
+	 * MSI is disabled (and it is disabled, as we don't use
+	 * message-signalled interrupts currently).
+	 */
+	if (port_info[0]->host_flags & PIIX_FLAG_CHECKINTR)
+		pci_enable_intx(pdev);
+
+	if (combined) {
+		port_info[sata_chan] = &piix_port_info[ent->driver_data];
+		port_info[sata_chan]->host_flags |= ATA_FLAG_SLAVE_POSS;
+		port_info[pata_chan] = &piix_port_info[ich5_pata];
+		n_ports++;
+
+		printk(KERN_ERR DRV_NAME ": combined mode not supported\n");
+		return -ENODEV;
+	}
+
+	return ata_pci_init_one(pdev, port_info, n_ports);
+}
+
+/**
+ *	piix_init -
+ *
+ *	LOCKING:
+ *
+ *	RETURNS:
+ *
+ */
+
+static int __init piix_init(void)
+{
+	int rc;
+
+	DPRINTK("pci_module_init\n");
+	rc = pci_module_init(&piix_pci_driver);
+	if (rc)
+		return rc;
+
+	in_module_init = 0;
+
+	DPRINTK("scsi_register_host\n");
+	rc = scsi_register_module(MODULE_SCSI_HA, &piix_sht);
+	if (rc) {
+		rc = -ENODEV;
+		goto err_out;
+	}
+
+	DPRINTK("done\n");
+	return 0;
+
+err_out:
+	pci_unregister_driver(&piix_pci_driver);
+	return rc;
+}
+
+/**
+ *	piix_exit -
+ *
+ *	LOCKING:
+ *
+ */
+
+static void __exit piix_exit(void)
+{
+	scsi_unregister_module(MODULE_SCSI_HA, &piix_sht);
+	pci_unregister_driver(&piix_pci_driver);
+}
+
+module_init(piix_init);
+module_exit(piix_exit);
+
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/scsi/dpt_i2o.c linux-2.4.28-pre3/drivers/scsi/dpt_i2o.c
--- linux-2.4.27/drivers/scsi/dpt_i2o.c	2003-06-13 14:51:36.000000000 +0000
+++ linux-2.4.28-pre3/drivers/scsi/dpt_i2o.c	2004-09-10 19:36:29.000000000 +0000
@@ -434,7 +434,7 @@ static int adpt_queue(Scsi_Cmnd * cmd, v
 			cmd->scsi_done(cmd);
 			return 0;
 		}
-		(struct adpt_device*)(cmd->device->hostdata) = pDev;
+		cmd->device->hostdata = pDev;
 	}
 	pDev->pScsi_dev = cmd->device;
 
@@ -2194,7 +2194,7 @@ static s32 adpt_scsi_register(adpt_hba* 
 		printk ("%s: scsi_register returned NULL\n",pHba->name);
 		return -1;
 	}
-	(adpt_hba*)(host->hostdata[0]) = pHba;
+	host->hostdata[0] = (unsigned long)pHba;
 	pHba->host = host;
 
 	host->irq = pHba->pDev->irq;;
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/scsi/esp.c linux-2.4.28-pre3/drivers/scsi/esp.c
--- linux-2.4.27/drivers/scsi/esp.c	2002-11-28 23:53:14.000000000 +0000
+++ linux-2.4.28-pre3/drivers/scsi/esp.c	2004-09-10 19:37:11.000000000 +0000
@@ -4368,4 +4368,4 @@ static Scsi_Host_Template driver_templat
 
 #include "scsi_module.c"
 
-EXPORT_NO_SYMBOLS;
+MODULE_LICENSE("GPL");
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/scsi/fcal.c linux-2.4.28-pre3/drivers/scsi/fcal.c
--- linux-2.4.27/drivers/scsi/fcal.c	2001-02-09 19:30:23.000000000 +0000
+++ linux-2.4.28-pre3/drivers/scsi/fcal.c	2004-09-10 19:32:17.000000000 +0000
@@ -300,4 +300,4 @@ static Scsi_Host_Template driver_templat
 
 #include "scsi_module.c"
 
-EXPORT_NO_SYMBOLS;
+MODULE_LICENSE("GPL");
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/scsi/ips.c linux-2.4.28-pre3/drivers/scsi/ips.c
--- linux-2.4.27/drivers/scsi/ips.c	2004-08-07 23:26:05.000000000 +0000
+++ linux-2.4.28-pre3/drivers/scsi/ips.c	2004-09-10 19:31:55.000000000 +0000
@@ -133,6 +133,10 @@
 /* 6.10.00  - Remove 1G Addressing Limitations                               */
 /* 6.11.xx  - Get VersionInfo buffer off the stack !              DDTS 60401 */
 /* 6.11.xx  - Make Logical Drive Info structure safe for DMA      DDTS 60639 */
+/* 7.10.xx  - Add highmem_io flag in SCSI Templete for 2.4 kernels           */
+/*          - Fix path/name for scsi_hosts.h include for 2.6 kernels         */
+/*          - Fix sort order of 7k                                           */
+/*          - Remove 3 unused "inline" functions                             */
 /*****************************************************************************/
 
 /*
@@ -176,7 +180,13 @@
 #include <scsi/sg.h>
 
 #include "scsi.h"
+
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,0)
 #include "hosts.h"
+#else
+#include <scsi/scsi_host.h>
+#endif
+
 #include "ips.h"
 
 #include <linux/module.h>
@@ -197,8 +207,8 @@ MODULE_PARM(ips, "s");
 /*
  * DRIVER_VER
  */
-#define IPS_VERSION_HIGH        "7.00"
-#define IPS_VERSION_LOW         ".15 "
+#define IPS_VERSION_HIGH        "7.10"
+#define IPS_VERSION_LOW         ".18 "
 
 #if !defined(__i386__) && !defined(__ia64__) && !defined(__x86_64__)
 #warning "This driver has only been tested on the x86/ia64/x86_64 platforms"
@@ -277,9 +287,9 @@ static Scsi_Host_Template ips_driver_tem
 	.use_clustering		= ENABLE_CLUSTERING,
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
 	.use_new_eh_code	= 1,
-#ifdef RHEL3
-    .vary_io            = 1,
 #endif
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,20)  &&  LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+    .highmem_io          = 1,   
 #endif
 };
 
@@ -477,21 +487,17 @@ static uint32_t ips_statupd_copperhead(i
 static uint32_t ips_statupd_copperhead_memio(ips_ha_t *);
 static uint32_t ips_statupd_morpheus(ips_ha_t *);
 static ips_scb_t *ips_getscb(ips_ha_t *);
-static inline void ips_putq_scb_head(ips_scb_queue_t *, ips_scb_t *);
-static inline void ips_putq_scb_tail(ips_scb_queue_t *, ips_scb_t *);
-static inline void ips_putq_wait_head(ips_wait_queue_t *, Scsi_Cmnd *);
-static inline void ips_putq_wait_tail(ips_wait_queue_t *, Scsi_Cmnd *);
-static inline void ips_putq_copp_head(ips_copp_queue_t *,
-				      ips_copp_wait_item_t *);
-static inline void ips_putq_copp_tail(ips_copp_queue_t *,
+static void ips_putq_scb_head(ips_scb_queue_t *, ips_scb_t *);
+static void ips_putq_wait_tail(ips_wait_queue_t *, Scsi_Cmnd *);
+static void ips_putq_copp_tail(ips_copp_queue_t *,
 				      ips_copp_wait_item_t *);
-static inline ips_scb_t *ips_removeq_scb_head(ips_scb_queue_t *);
-static inline ips_scb_t *ips_removeq_scb(ips_scb_queue_t *, ips_scb_t *);
-static inline Scsi_Cmnd *ips_removeq_wait_head(ips_wait_queue_t *);
-static inline Scsi_Cmnd *ips_removeq_wait(ips_wait_queue_t *, Scsi_Cmnd *);
-static inline ips_copp_wait_item_t *ips_removeq_copp(ips_copp_queue_t *,
+static ips_scb_t *ips_removeq_scb_head(ips_scb_queue_t *);
+static ips_scb_t *ips_removeq_scb(ips_scb_queue_t *, ips_scb_t *);
+static Scsi_Cmnd *ips_removeq_wait_head(ips_wait_queue_t *);
+static Scsi_Cmnd *ips_removeq_wait(ips_wait_queue_t *, Scsi_Cmnd *);
+static ips_copp_wait_item_t *ips_removeq_copp(ips_copp_queue_t *,
 						     ips_copp_wait_item_t *);
-static inline ips_copp_wait_item_t *ips_removeq_copp_head(ips_copp_queue_t *);
+static ips_copp_wait_item_t *ips_removeq_copp_head(ips_copp_queue_t *);
 
 static int ips_is_passthru(Scsi_Cmnd *);
 static int ips_make_passthru(ips_ha_t *, Scsi_Cmnd *, ips_scb_t *, int);
@@ -1888,7 +1894,7 @@ ips_flash_bios(ips_ha_t * ha, ips_passth
 /*   Fill in a single scb sg_list element from an address                   */
 /*   return a -1 if a breakup occurred                                      */
 /****************************************************************************/
-static inline int
+static int
 ips_fill_scb_sg_single(ips_ha_t * ha, dma_addr_t busaddr,
 		       ips_scb_t * scb, int indx, unsigned int e_len)
 {
@@ -2953,7 +2959,7 @@ ips_next(ips_ha_t * ha, int intr)
 /* ASSUMED to be called from within the HA lock                             */
 /*                                                                          */
 /****************************************************************************/
-static inline void
+static void
 ips_putq_scb_head(ips_scb_queue_t * queue, ips_scb_t * item)
 {
 	METHOD_TRACE("ips_putq_scb_head", 1);
@@ -2972,38 +2978,6 @@ ips_putq_scb_head(ips_scb_queue_t * queu
 
 /****************************************************************************/
 /*                                                                          */
-/* Routine Name: ips_putq_scb_tail                                          */
-/*                                                                          */
-/* Routine Description:                                                     */
-/*                                                                          */
-/*   Add an item to the tail of the queue                                   */
-/*                                                                          */
-/* ASSUMED to be called from within the HA lock                             */
-/*                                                                          */
-/****************************************************************************/
-static inline void
-ips_putq_scb_tail(ips_scb_queue_t * queue, ips_scb_t * item)
-{
-	METHOD_TRACE("ips_putq_scb_tail", 1);
-
-	if (!item)
-		return;
-
-	item->q_next = NULL;
-
-	if (queue->tail)
-		queue->tail->q_next = item;
-
-	queue->tail = item;
-
-	if (!queue->head)
-		queue->head = item;
-
-	queue->count++;
-}
-
-/****************************************************************************/
-/*                                                                          */
 /* Routine Name: ips_removeq_scb_head                                       */
 /*                                                                          */
 /* Routine Description:                                                     */
@@ -3013,7 +2987,7 @@ ips_putq_scb_tail(ips_scb_queue_t * queu
 /* ASSUMED to be called from within the HA lock                             */
 /*                                                                          */
 /****************************************************************************/
-static inline ips_scb_t *
+static ips_scb_t *
 ips_removeq_scb_head(ips_scb_queue_t * queue)
 {
 	ips_scb_t *item;
@@ -3048,7 +3022,7 @@ ips_removeq_scb_head(ips_scb_queue_t * q
 /* ASSUMED to be called from within the HA lock                             */
 /*                                                                          */
 /****************************************************************************/
-static inline ips_scb_t *
+static ips_scb_t *
 ips_removeq_scb(ips_scb_queue_t * queue, ips_scb_t * item)
 {
 	ips_scb_t *p;
@@ -3085,34 +3059,6 @@ ips_removeq_scb(ips_scb_queue_t * queue,
 
 /****************************************************************************/
 /*                                                                          */
-/* Routine Name: ips_putq_wait_head                                         */
-/*                                                                          */
-/* Routine Description:                                                     */
-/*                                                                          */
-/*   Add an item to the head of the queue                                   */
-/*                                                                          */
-/* ASSUMED to be called from within the HA lock                             */
-/*                                                                          */
-/****************************************************************************/
-static inline void
-ips_putq_wait_head(ips_wait_queue_t * queue, Scsi_Cmnd * item)
-{
-	METHOD_TRACE("ips_putq_wait_head", 1);
-
-	if (!item)
-		return;
-
-	item->host_scribble = (char *) queue->head;
-	queue->head = item;
-
-	if (!queue->tail)
-		queue->tail = item;
-
-	queue->count++;
-}
-
-/****************************************************************************/
-/*                                                                          */
 /* Routine Name: ips_putq_wait_tail                                         */
 /*                                                                          */
 /* Routine Description:                                                     */
@@ -3122,7 +3068,7 @@ ips_putq_wait_head(ips_wait_queue_t * qu
 /* ASSUMED to be called from within the HA lock                             */
 /*                                                                          */
 /****************************************************************************/
-static inline void
+static void
 ips_putq_wait_tail(ips_wait_queue_t * queue, Scsi_Cmnd * item)
 {
 	METHOD_TRACE("ips_putq_wait_tail", 1);
@@ -3154,7 +3100,7 @@ ips_putq_wait_tail(ips_wait_queue_t * qu
 /* ASSUMED to be called from within the HA lock                             */
 /*                                                                          */
 /****************************************************************************/
-static inline Scsi_Cmnd *
+static Scsi_Cmnd *
 ips_removeq_wait_head(ips_wait_queue_t * queue)
 {
 	Scsi_Cmnd *item;
@@ -3189,7 +3135,7 @@ ips_removeq_wait_head(ips_wait_queue_t *
 /* ASSUMED to be called from within the HA lock                             */
 /*                                                                          */
 /****************************************************************************/
-static inline Scsi_Cmnd *
+static Scsi_Cmnd *
 ips_removeq_wait(ips_wait_queue_t * queue, Scsi_Cmnd * item)
 {
 	Scsi_Cmnd *p;
@@ -3226,34 +3172,6 @@ ips_removeq_wait(ips_wait_queue_t * queu
 
 /****************************************************************************/
 /*                                                                          */
-/* Routine Name: ips_putq_copp_head                                         */
-/*                                                                          */
-/* Routine Description:                                                     */
-/*                                                                          */
-/*   Add an item to the head of the queue                                   */
-/*                                                                          */
-/* ASSUMED to be called from within the HA lock                             */
-/*                                                                          */
-/****************************************************************************/
-static inline void
-ips_putq_copp_head(ips_copp_queue_t * queue, ips_copp_wait_item_t * item)
-{
-	METHOD_TRACE("ips_putq_copp_head", 1);
-
-	if (!item)
-		return;
-
-	item->next = queue->head;
-	queue->head = item;
-
-	if (!queue->tail)
-		queue->tail = item;
-
-	queue->count++;
-}
-
-/****************************************************************************/
-/*                                                                          */
 /* Routine Name: ips_putq_copp_tail                                         */
 /*                                                                          */
 /* Routine Description:                                                     */
@@ -3263,7 +3181,7 @@ ips_putq_copp_head(ips_copp_queue_t * qu
 /* ASSUMED to be called from within the HA lock                             */
 /*                                                                          */
 /****************************************************************************/
-static inline void
+static void
 ips_putq_copp_tail(ips_copp_queue_t * queue, ips_copp_wait_item_t * item)
 {
 	METHOD_TRACE("ips_putq_copp_tail", 1);
@@ -3295,7 +3213,7 @@ ips_putq_copp_tail(ips_copp_queue_t * qu
 /* ASSUMED to be called from within the HA lock                             */
 /*                                                                          */
 /****************************************************************************/
-static inline ips_copp_wait_item_t *
+static ips_copp_wait_item_t *
 ips_removeq_copp_head(ips_copp_queue_t * queue)
 {
 	ips_copp_wait_item_t *item;
@@ -3330,7 +3248,7 @@ ips_removeq_copp_head(ips_copp_queue_t *
 /* ASSUMED to be called from within the HA lock                             */
 /*                                                                          */
 /****************************************************************************/
-static inline ips_copp_wait_item_t *
+static ips_copp_wait_item_t *
 ips_removeq_copp(ips_copp_queue_t * queue, ips_copp_wait_item_t * item)
 {
 	ips_copp_wait_item_t *p;
@@ -4014,7 +3932,7 @@ ips_send_cmd(ips_ha_t * ha, ips_scb_t * 
 			scb->cmd.logical_info.reserved2 = 0;
 			scb->cmd.logical_info.reserved3 = 0;
 			scb->data_len = sizeof (IPS_LD_INFO);
-            scb->data_busaddr = ha->logical_drive_info_dma_addr;
+			scb->data_busaddr = ha->logical_drive_info_dma_addr;
 			scb->flags = 0;
 			scb->cmd.logical_info.buffer_addr = scb->data_busaddr;
 			ret = IPS_SUCCESS;
@@ -4340,7 +4258,7 @@ ips_online(ips_ha_t * ha, ips_scb_t * sc
 
 	if ((scb->basic_status & IPS_GSC_STATUS_MASK) > 1) {
 		memset(ha->logical_drive_info, 0, sizeof (IPS_LD_INFO));
-        return (0);
+		return (0);
 	}
 
 	if (ha->logical_drive_info->drive_info[scb->target_id].state !=
@@ -4579,7 +4497,7 @@ ips_free(ips_ha_t * ha)
 		if (ha->logical_drive_info) {
 			pci_free_consistent(ha->pcidev,
 					    sizeof (IPS_LD_INFO),
-                        ha->logical_drive_info,
+					    ha->logical_drive_info,
 					    ha->logical_drive_info_dma_addr);
 			ha->logical_drive_info = NULL;
 		}
@@ -4773,7 +4691,7 @@ ips_getscb(ips_ha_t * ha)
 	}
 
 	ha->scb_freelist = scb->q_next;
-    scb->flags = 0;
+	scb->flags = 0;
 	scb->q_next = NULL;
 
 	ips_init_scb(ha, scb);
@@ -6831,7 +6749,7 @@ ips_version_check(ips_ha_t * ha, int int
 
 	METHOD_TRACE("ips_version_check", 1);
 
-    VersionInfo = ( IPS_VERSION_DATA * ) ha->ioctl_data;
+	VersionInfo = ( IPS_VERSION_DATA * ) ha->ioctl_data;
 
 	memset(FirmwareVersion, 0, IPS_COMPAT_ID_LENGTH + 1);
 	memset(BiosVersion, 0, IPS_COMPAT_ID_LENGTH + 1);
@@ -6843,7 +6761,7 @@ ips_version_check(ips_ha_t * ha, int int
 	rc = IPS_FAILURE;
 	if (ha->subsys->param[4] & IPS_GET_VERSION_SUPPORT) {	/* If Versioning is Supported */
 		/* Get the Version Info with a Get Version Command */
-        memset( VersionInfo, 0, sizeof (IPS_VERSION_DATA));
+		memset( VersionInfo, 0, sizeof (IPS_VERSION_DATA));
 		rc = ips_get_version_info(ha, ha->ioctl_busaddr, intr);
 		if (rc == IPS_SUCCESS)
 			memcpy(FirmwareVersion, VersionInfo->compatibilityId,
@@ -6999,7 +6917,6 @@ ips_order_controllers(void)
 			for (j = position; j < ips_num_controllers; j++) {
 				switch (ips_ha[j]->ad_type) {
 				case IPS_ADTYPE_SERVERAID6M:
-				case IPS_ADTYPE_SERVERAID7k:
 				case IPS_ADTYPE_SERVERAID7M:
 					if (nvram->adapter_order[i] == 'M') {
 						ips_shift_controllers(position,
@@ -7020,6 +6937,7 @@ ips_order_controllers(void)
 				case IPS_ADTYPE_SERVERAID6I:
 				case IPS_ADTYPE_SERVERAID5I2:
 				case IPS_ADTYPE_SERVERAID5I1:
+				case IPS_ADTYPE_SERVERAID7k:
 					if (nvram->adapter_order[i] == 'S') {
 						ips_shift_controllers(position,
 								      j);
@@ -7548,6 +7466,15 @@ ips_init_phase2(int index)
 MODULE_LICENSE("GPL");
 #endif
 
+#ifdef MODULE_DESCRIPTION
+MODULE_DESCRIPTION("IBM ServeRAID Adapter Driver " IPS_VER_STRING);
+#endif
+
+#ifdef MODULE_VERSION
+MODULE_VERSION(IPS_VER_STRING);
+#endif
+
+
 /*
  * Overrides for Emacs so that we almost follow Linus's tabbing style.
  * Emacs will notice this stuff at the end of the file and automatically
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/scsi/ips.h linux-2.4.28-pre3/drivers/scsi/ips.h
--- linux-2.4.27/drivers/scsi/ips.h	2004-08-07 23:26:05.000000000 +0000
+++ linux-2.4.28-pre3/drivers/scsi/ips.h	2004-09-10 19:33:19.000000000 +0000
@@ -95,14 +95,15 @@
       #define scsi_set_pci_device(sh,dev) (0)
    #endif
 
-   #if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,23)
-      typedef void irqreturn_t;
+   #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+   
+      #ifndef irqreturn_t
+         typedef void irqreturn_t;
+      #endif 
+      
       #define IRQ_NONE
       #define IRQ_HANDLED
       #define IRQ_RETVAL(x)
-   #endif
-
-   #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
       #define IPS_REGISTER_HOSTS(SHT)      scsi_register_module(MODULE_SCSI_HA,SHT)
       #define IPS_UNREGISTER_HOSTS(SHT)    scsi_unregister_module(MODULE_SCSI_HA,SHT)
       #define IPS_ADD_HOST(shost,device)
@@ -1213,13 +1214,13 @@ typedef struct {
 
 #define IPS_VER_MAJOR 7
 #define IPS_VER_MAJOR_STRING "7"
-#define IPS_VER_MINOR 00
-#define IPS_VER_MINOR_STRING "00"
-#define IPS_VER_BUILD 15
-#define IPS_VER_BUILD_STRING "15"
-#define IPS_VER_STRING "7.00.15"
+#define IPS_VER_MINOR 10
+#define IPS_VER_MINOR_STRING "10"
+#define IPS_VER_BUILD 18
+#define IPS_VER_BUILD_STRING "18"
+#define IPS_VER_STRING "7.10.18"
 #define IPS_RELEASE_ID 0x00020000
-#define IPS_BUILD_IDENT 625
+#define IPS_BUILD_IDENT 731
 #define IPS_LEGALCOPYRIGHT_STRING "(C) Copyright IBM Corp. 1994, 2002. All Rights Reserved."
 #define IPS_ADAPTECCOPYRIGHT_STRING "(c) Copyright Adaptec, Inc. 2002 to 2004. All Rights Reserved."
 #define IPS_DELLCOPYRIGHT_STRING "(c) Copyright Dell 2004. All Rights Reserved."
@@ -1230,32 +1231,35 @@ typedef struct {
 #define IPS_VER_SERVERAID2 "2.88.13"
 #define IPS_VER_NAVAJO "2.88.13"
 #define IPS_VER_SERVERAID3 "6.10.24"
-#define IPS_VER_SERVERAID4H "7.00.15"
-#define IPS_VER_SERVERAID4MLx "7.00.15"
-#define IPS_VER_SARASOTA "7.00.15"
-#define IPS_VER_MARCO "7.00.15"
-#define IPS_VER_SEBRING "7.00.15"
+#define IPS_VER_SERVERAID4H "7.10.11"
+#define IPS_VER_SERVERAID4MLx "7.10.18"
+#define IPS_VER_SARASOTA "7.10.18"
+#define IPS_VER_MARCO "7.10.18"
+#define IPS_VER_SEBRING "7.10.18"
+#define IPS_VER_KEYWEST "7.10.18"
 
 /* Compatability IDs for various adapters */
 #define IPS_COMPAT_UNKNOWN ""
-#define IPS_COMPAT_CURRENT "SB610"
+#define IPS_COMPAT_CURRENT "KW710"
 #define IPS_COMPAT_SERVERAID1 "2.25.01"
 #define IPS_COMPAT_SERVERAID2 "2.88.13"
 #define IPS_COMPAT_NAVAJO  "2.88.13"
 #define IPS_COMPAT_KIOWA "2.88.13"
 #define IPS_COMPAT_SERVERAID3H  "SB610"
 #define IPS_COMPAT_SERVERAID3L  "SB610"
-#define IPS_COMPAT_SERVERAID4H  "SB610"
-#define IPS_COMPAT_SERVERAID4M  "SB610"
-#define IPS_COMPAT_SERVERAID4L  "SB610"
-#define IPS_COMPAT_SERVERAID4Mx "SB610"
-#define IPS_COMPAT_SERVERAID4Lx "SB610"
-#define IPS_COMPAT_SARASOTA     "SB610"
-#define IPS_COMPAT_MARCO        "SB610"
-#define IPS_COMPAT_SEBRING      "SB610"
-#define IPS_COMPAT_BIOS "SB610"
+#define IPS_COMPAT_SERVERAID4H  "KW710"
+#define IPS_COMPAT_SERVERAID4M  "KW710"
+#define IPS_COMPAT_SERVERAID4L  "KW710"
+#define IPS_COMPAT_SERVERAID4Mx "KW710"
+#define IPS_COMPAT_SERVERAID4Lx "KW710"
+#define IPS_COMPAT_SARASOTA     "KW710"
+#define IPS_COMPAT_MARCO        "KW710"
+#define IPS_COMPAT_SEBRING      "KW710"
+#define IPS_COMPAT_TAMPA        "KW710"
+#define IPS_COMPAT_KEYWEST      "KW710"
+#define IPS_COMPAT_BIOS "KW710"
 
-#define IPS_COMPAT_MAX_ADAPTER_TYPE 16
+#define IPS_COMPAT_MAX_ADAPTER_TYPE 18
 #define IPS_COMPAT_ID_LENGTH 8
 
 #define IPS_DEFINE_COMPAT_TABLE(tablename) \
@@ -1275,7 +1279,9 @@ typedef struct {
       IPS_COMPAT_SARASOTA,         /* one-channel variety of SARASOTA */  \
       IPS_COMPAT_SARASOTA,         /* two-channel variety of SARASOTA */  \
       IPS_COMPAT_MARCO, \
-      IPS_COMPAT_SEBRING \
+      IPS_COMPAT_SEBRING, \
+	  IPS_COMPAT_TAMPA, \
+      IPS_COMPAT_KEYWEST \
    }
 
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/scsi/libata-core.c linux-2.4.28-pre3/drivers/scsi/libata-core.c
--- linux-2.4.27/drivers/scsi/libata-core.c	2004-08-07 23:26:05.000000000 +0000
+++ linux-2.4.28-pre3/drivers/scsi/libata-core.c	2004-09-10 19:35:18.000000000 +0000
@@ -42,6 +42,7 @@
 #include <linux/libata.h>
 #include <asm/io.h>
 #include <asm/semaphore.h>
+#include <asm/byteorder.h>
 
 #include "libata.h"
 
@@ -49,13 +50,14 @@ static unsigned int ata_busy_sleep (stru
 				    unsigned long tmout_pat,
 			    	    unsigned long tmout);
 static void __ata_dev_select (struct ata_port *ap, unsigned int device);
-static void ata_dma_complete(struct ata_queued_cmd *qc, u8 host_stat);
-static void ata_host_set_pio(struct ata_port *ap);
-static void ata_host_set_udma(struct ata_port *ap);
-static void ata_dev_set_pio(struct ata_port *ap, unsigned int device);
-static void ata_dev_set_udma(struct ata_port *ap, unsigned int device);
 static void ata_set_mode(struct ata_port *ap);
-static int ata_qc_issue_prot(struct ata_queued_cmd *qc);
+static void ata_dev_set_xfermode(struct ata_port *ap, struct ata_device *dev);
+static unsigned int ata_get_mode_mask(struct ata_port *ap, int shift);
+static int fgb(u32 bitmap);
+static int ata_choose_xfer_mode(struct ata_port *ap,
+				u8 *xfer_mode_out,
+				unsigned int *xfer_shift_out);
+static int ata_qc_complete_noop(struct ata_queued_cmd *qc, u8 drv_stat);
 
 static unsigned int ata_unique_id = 1;
 static LIST_HEAD(ata_probe_list);
@@ -65,37 +67,6 @@ MODULE_AUTHOR("Jeff Garzik");
 MODULE_DESCRIPTION("Library module for ATA devices");
 MODULE_LICENSE("GPL");
 
-static const char * thr_state_name[] = {
-	"THR_UNKNOWN",
-	"THR_PORT_RESET",
-	"THR_AWAIT_DEATH",
-	"THR_PROBE_FAILED",
-	"THR_IDLE",
-	"THR_PROBE_SUCCESS",
-	"THR_PROBE_START",
-};
-
-/**
- *	ata_thr_state_name - convert thread state enum to string
- *	@thr_state: thread state to be converted to string
- *
- *	Converts the specified thread state id to a constant C string.
- *
- *	LOCKING:
- *	None.
- *
- *	RETURNS:
- *	The THR_xxx-prefixed string naming the specified thread
- *	state id, or the string "<invalid THR_xxx state>".
- */
-
-static const char *ata_thr_state_name(unsigned int thr_state)
-{
-	if (thr_state < ARRAY_SIZE(thr_state_name))
-		return thr_state_name[thr_state];
-	return "<invalid THR_xxx state>";
-}
-
 /**
  *	msleep - sleep for a number of milliseconds
  *	@msecs: number of milliseconds to sleep
@@ -113,6 +84,11 @@ static void msleep(unsigned long msecs)
 	schedule_timeout(msecs_to_jiffies(msecs) + 1);
 }
 
+void libata_msleep(unsigned long msecs)
+{
+	msleep(msecs);
+}
+
 /**
  *	ata_tf_load_pio - send taskfile registers to host controller
  *	@ap: Port to which output is sent
@@ -574,7 +550,7 @@ static void ata_dev_set_protocol(struct 
 	dev->write_cmd = (cmd >> 8) & 0xff;
 }
 
-static const char * udma_str[] = {
+static const char * xfer_mode_str[] = {
 	"UDMA/16",
 	"UDMA/25",
 	"UDMA/33",
@@ -583,6 +559,14 @@ static const char * udma_str[] = {
 	"UDMA/100",
 	"UDMA/133",
 	"UDMA7",
+	"MWDMA0",
+	"MWDMA1",
+	"MWDMA2",
+	"PIO0",
+	"PIO1",
+	"PIO2",
+	"PIO3",
+	"PIO4",
 };
 
 /**
@@ -600,16 +584,24 @@ static const char * udma_str[] = {
  *	@udma_mask, or the constant C string "<n/a>".
  */
 
-static const char *ata_udma_string(unsigned int udma_mask)
+static const char *ata_mode_string(unsigned int mask)
 {
 	int i;
 
-	for (i = 7; i >= 0; i--) {
-		if (udma_mask & (1 << i))
-			return udma_str[i];
-	}
+	for (i = 7; i >= 0; i--)
+		if (mask & (1 << i))
+			goto out;
+	for (i = ATA_SHIFT_MWDMA + 2; i >= ATA_SHIFT_MWDMA; i--)
+		if (mask & (1 << i))
+			goto out;
+	for (i = ATA_SHIFT_PIO + 4; i >= ATA_SHIFT_PIO; i--)
+		if (mask & (1 << i))
+			goto out;
 
 	return "<n/a>";
+
+out:
+	return xfer_mode_str[i];
 }
 
 /**
@@ -980,10 +972,14 @@ static void ata_dev_identify(struct ata_
 {
 	struct ata_device *dev = &ap->device[device];
 	unsigned int i;
-	u16 tmp, udma_modes;
+	u16 tmp;
+	unsigned long xfer_modes;
 	u8 status;
-	struct ata_taskfile tf;
 	unsigned int using_edd;
+	DECLARE_COMPLETION(wait);
+	struct ata_queued_cmd *qc;
+	unsigned long flags;
+	int rc;
 
 	if (!ata_dev_present(dev)) {
 		DPRINTK("ENTER/EXIT (host %u, dev %u) -- nodev\n",
@@ -1003,27 +999,34 @@ static void ata_dev_identify(struct ata_
 
 	ata_dev_select(ap, device, 1, 1); /* select device 0/1 */
 
-retry:
-	ata_tf_init(ap, &tf, device);
-	tf.ctl |= ATA_NIEN;
-	tf.protocol = ATA_PROT_PIO;
+	qc = ata_qc_new_init(ap, dev);
+	BUG_ON(qc == NULL);
 
+	ata_sg_init_one(qc, dev->id, sizeof(dev->id));
+	qc->pci_dma_dir = PCI_DMA_FROMDEVICE;
+	qc->tf.protocol = ATA_PROT_PIO;
+	qc->nsect = 1;
+
+retry:
 	if (dev->class == ATA_DEV_ATA) {
-		tf.command = ATA_CMD_ID_ATA;
+		qc->tf.command = ATA_CMD_ID_ATA;
 		DPRINTK("do ATA identify\n");
 	} else {
-		tf.command = ATA_CMD_ID_ATAPI;
+		qc->tf.command = ATA_CMD_ID_ATAPI;
 		DPRINTK("do ATAPI identify\n");
 	}
 
-	ata_tf_to_host(ap, &tf);
+	qc->waiting = &wait;
+	qc->complete_fn = ata_qc_complete_noop;
 
-	/* crazy ATAPI devices... */
-	if (dev->class == ATA_DEV_ATAPI)
-		msleep(150);
+	spin_lock_irqsave(&ap->host_set->lock, flags);
+	rc = ata_qc_issue(qc);
+	spin_unlock_irqrestore(&ap->host_set->lock, flags);
 
-	if (ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT))
+	if (rc)
 		goto err_out;
+	else
+		wait_for_completion(&wait);
 
 	status = ata_chk_status(ap);
 	if (status & ATA_ERR) {
@@ -1038,44 +1041,21 @@ retry:
 		 * ATA software reset (SRST, the default) does not appear
 		 * to have this problem.
 		 */
-		if ((using_edd) && (tf.command == ATA_CMD_ID_ATA)) {
+		if ((using_edd) && (qc->tf.command == ATA_CMD_ID_ATA)) {
 			u8 err = ata_chk_err(ap);
 			if (err & ATA_ABORTED) {
 				dev->class = ATA_DEV_ATAPI;
+				qc->cursg = 0;
+				qc->cursg_ofs = 0;
+				qc->cursect = 0;
+				qc->nsect = 1;
 				goto retry;
 			}
 		}
 		goto err_out;
 	}
 
-	/* make sure we have BSY=0, DRQ=1 */
-	if ((status & ATA_DRQ) == 0) {
-		printk(KERN_WARNING "ata%u: dev %u (ATA%s?) not returning id page (0x%x)\n",
-		       ap->id, device,
-		       dev->class == ATA_DEV_ATA ? "" : "PI",
-		       status);
-		goto err_out;
-	}
-
-	/* read IDENTIFY [X] DEVICE page */
-	if (ap->flags & ATA_FLAG_MMIO) {
-		for (i = 0; i < ATA_ID_WORDS; i++)
-			dev->id[i] = readw((void *)ap->ioaddr.data_addr);
-	} else
-		for (i = 0; i < ATA_ID_WORDS; i++)
-			dev->id[i] = inw(ap->ioaddr.data_addr);
-
-	/* wait for host_idle */
-	status = ata_wait_idle(ap);
-	if (status & (ATA_BUSY | ATA_DRQ)) {
-		printk(KERN_WARNING "ata%u: dev %u (ATA%s?) error after id page (0x%x)\n",
-		       ap->id, device,
-		       dev->class == ATA_DEV_ATA ? "" : "PI",
-		       status);
-		goto err_out;
-	}
-
-	ata_irq_on(ap);	/* re-enable interrupts */
+	swap_buf_le16(dev->id, ATA_ID_WORDS);
 
 	/* print device capabilities */
 	printk(KERN_DEBUG "ata%u: dev %u cfg "
@@ -1095,12 +1075,13 @@ retry:
 		goto err_out_nosup;
 	}
 
-	/* we require UDMA support */
-	udma_modes =
-	tmp = dev->id[ATA_ID_UDMA_MODES];
-	if ((tmp & 0xff) == 0) {
-		printk(KERN_DEBUG "ata%u: no udma\n", ap->id);
-		goto err_out_nosup;
+	/* quick-n-dirty find max transfer mode; for printk only */
+	xfer_modes = dev->id[ATA_ID_UDMA_MODES];
+	if (!xfer_modes)
+		xfer_modes = (dev->id[ATA_ID_MWDMA_MODES]) << ATA_SHIFT_MWDMA;
+	if (!xfer_modes) {
+		xfer_modes = (dev->id[ATA_ID_PIO_MODES]) << (ATA_SHIFT_PIO + 3);
+		xfer_modes |= (0x7 << ATA_SHIFT_PIO);
 	}
 
 	ata_dump_id(dev);
@@ -1133,7 +1114,7 @@ retry:
 		/* print device info to dmesg */
 		printk(KERN_INFO "ata%u: dev %u ATA, max %s, %Lu sectors:%s\n",
 		       ap->id, device,
-		       ata_udma_string(udma_modes),
+		       ata_mode_string(xfer_modes),
 		       (unsigned long long)dev->n_sectors,
 		       dev->flags & ATA_DFLAG_LBA48 ? " lba48" : "");
 	}
@@ -1143,15 +1124,18 @@ retry:
 		if (ata_id_is_ata(dev))		/* sanity check */
 			goto err_out_nosup;
 
-		/* see if 16-byte commands supported */
-		tmp = dev->id[0] & 0x3;
-		if (tmp == 1)
-			ap->host->max_cmd_len = 16;
+		rc = atapi_cdb_len(dev->id);
+		if ((rc < 12) || (rc > ATAPI_CDB_LEN)) {
+			printk(KERN_WARNING "ata%u: unsupported CDB len\n", ap->id);
+			goto err_out_nosup;
+		}
+		ap->cdb_len = (unsigned int) rc;
+		ap->host->max_cmd_len = (unsigned char) ap->cdb_len;
 
 		/* print device info to dmesg */
 		printk(KERN_INFO "ata%u: dev %u ATAPI, max %s\n",
 		       ap->id, device,
-		       ata_udma_string(udma_modes));
+		       ata_mode_string(xfer_modes));
 	}
 
 	DPRINTK("EXIT, drv_stat = 0x%x\n", ata_chk_status(ap));
@@ -1167,13 +1151,16 @@ err_out:
 }
 
 /**
- *	ata_port_reset -
- *	@ap:
+ *	ata_bus_probe - Reset and probe ATA bus
+ *	@ap: Bus to probe
  *
  *	LOCKING:
+ *
+ *	RETURNS:
+ *	Zero on success, non-zero on error.
  */
 
-static void ata_port_reset(struct ata_port *ap)
+static int ata_bus_probe(struct ata_port *ap)
 {
 	unsigned int i, found = 0;
 
@@ -1197,14 +1184,12 @@ static void ata_port_reset(struct ata_po
 	if (ap->flags & ATA_FLAG_PORT_DISABLED)
 		goto err_out_disable;
 
-	ap->thr_state = THR_PROBE_SUCCESS;
-
-	return;
+	return 0;
 
 err_out_disable:
 	ap->ops->port_disable(ap);
 err_out:
-	ap->thr_state = THR_PROBE_FAILED;
+	return -1;
 }
 
 /**
@@ -1281,6 +1266,101 @@ void ata_port_disable(struct ata_port *a
 	ap->flags |= ATA_FLAG_PORT_DISABLED;
 }
 
+static struct {
+	unsigned int shift;
+	u8 base;
+} xfer_mode_classes[] = {
+	{ ATA_SHIFT_UDMA,	XFER_UDMA_0 },
+	{ ATA_SHIFT_MWDMA,	XFER_MW_DMA_0 },
+	{ ATA_SHIFT_PIO,	XFER_PIO_0 },
+};
+
+static inline u8 base_from_shift(unsigned int shift)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(xfer_mode_classes); i++)
+		if (xfer_mode_classes[i].shift == shift)
+			return xfer_mode_classes[i].base;
+
+	return 0xff;
+}
+
+static void ata_dev_set_mode(struct ata_port *ap, struct ata_device *dev)
+{
+	int ofs, idx;
+	u8 base;
+
+	if (!ata_dev_present(dev) || (ap->flags & ATA_FLAG_PORT_DISABLED))
+		return;
+
+	if (dev->xfer_shift == ATA_SHIFT_PIO)
+		dev->flags |= ATA_DFLAG_PIO;
+
+	ata_dev_set_xfermode(ap, dev);
+
+	base = base_from_shift(dev->xfer_shift);
+	ofs = dev->xfer_mode - base;
+	idx = ofs + dev->xfer_shift;
+	WARN_ON(idx >= ARRAY_SIZE(xfer_mode_str));
+
+	DPRINTK("idx=%d xfer_shift=%u, xfer_mode=0x%x, base=0x%x, offset=%d\n",
+		idx, dev->xfer_shift, (int)dev->xfer_mode, (int)base, ofs);
+
+	printk(KERN_INFO "ata%u: dev %u configured for %s\n",
+		ap->id, dev->devno, xfer_mode_str[idx]);
+}
+
+static int ata_host_set_pio(struct ata_port *ap)
+{
+	unsigned int mask;
+	int x, i;
+	u8 base, xfer_mode;
+
+	mask = ata_get_mode_mask(ap, ATA_SHIFT_PIO);
+	x = fgb(mask);
+	if (x < 0) {
+		printk(KERN_WARNING "ata%u: no PIO support\n", ap->id);
+		return -1;
+	}
+
+	base = base_from_shift(ATA_SHIFT_PIO);
+	xfer_mode = base + x;
+
+	DPRINTK("base 0x%x xfer_mode 0x%x mask 0x%x x %d\n",
+		(int)base, (int)xfer_mode, mask, x);
+
+	for (i = 0; i < ATA_MAX_DEVICES; i++) {
+		struct ata_device *dev = &ap->device[i];
+		if (ata_dev_present(dev)) {
+			dev->pio_mode = xfer_mode;
+			dev->xfer_mode = xfer_mode;
+			dev->xfer_shift = ATA_SHIFT_PIO;
+			if (ap->ops->set_piomode)
+				ap->ops->set_piomode(ap, dev);
+		}
+	}
+
+	return 0;
+}
+
+static void ata_host_set_dma(struct ata_port *ap, u8 xfer_mode,
+			    unsigned int xfer_shift)
+{
+	int i;
+
+	for (i = 0; i < ATA_MAX_DEVICES; i++) {
+		struct ata_device *dev = &ap->device[i];
+		if (ata_dev_present(dev)) {
+			dev->dma_mode = xfer_mode;
+			dev->xfer_mode = xfer_mode;
+			dev->xfer_shift = xfer_shift;
+			if (ap->ops->set_dmamode)
+				ap->ops->set_dmamode(ap, dev);
+		}
+	}
+}
+
 /**
  *	ata_set_mode - Program timings and issue SET FEATURES - XFER
  *	@ap: port on which timings will be programmed
@@ -1290,29 +1370,28 @@ void ata_port_disable(struct ata_port *a
  */
 static void ata_set_mode(struct ata_port *ap)
 {
-	unsigned int force_pio, i;
-
-	ata_host_set_pio(ap);
-	if (ap->flags & ATA_FLAG_PORT_DISABLED)
-		return;
+	unsigned int i, xfer_shift;
+	u8 xfer_mode;
+	int rc;
 
-	ata_host_set_udma(ap);
-	if (ap->flags & ATA_FLAG_PORT_DISABLED)
-		return;
+	/* step 1: always set host PIO timings */
+	rc = ata_host_set_pio(ap);
+	if (rc)
+		goto err_out;
 
-#ifdef ATA_FORCE_PIO
-	force_pio = 1;
-#else
-	force_pio = 0;
-#endif
+	/* step 2: choose the best data xfer mode */
+	xfer_mode = xfer_shift = 0;
+	rc = ata_choose_xfer_mode(ap, &xfer_mode, &xfer_shift);
+	if (rc)
+		goto err_out;
 
-	if (force_pio) {
-		ata_dev_set_pio(ap, 0);
-		ata_dev_set_pio(ap, 1);
-	} else {
-		ata_dev_set_udma(ap, 0);
-		ata_dev_set_udma(ap, 1);
-	}
+	/* step 3: if that xfer mode isn't PIO, set host DMA timings */
+	if (xfer_shift != ATA_SHIFT_PIO)
+		ata_host_set_dma(ap, xfer_mode, xfer_shift);
+
+	/* step 4: update devices' xfer mode */
+	ata_dev_set_mode(ap, &ap->device[0]);
+	ata_dev_set_mode(ap, &ap->device[1]);
 
 	if (ap->flags & ATA_FLAG_PORT_DISABLED)
 		return;
@@ -1324,6 +1403,11 @@ static void ata_set_mode(struct ata_port
 		struct ata_device *dev = &ap->device[i];
 		ata_dev_set_protocol(dev);
 	}
+
+	return;
+
+err_out:
+	ata_port_disable(ap);
 }
 
 /**
@@ -1585,116 +1669,102 @@ err_out:
 	DPRINTK("EXIT\n");
 }
 
-/**
- *	ata_host_set_pio -
- *	@ap:
- *
- *	LOCKING:
- */
-
-static void ata_host_set_pio(struct ata_port *ap)
+static unsigned int ata_get_mode_mask(struct ata_port *ap, int shift)
 {
 	struct ata_device *master, *slave;
-	unsigned int pio, i;
-	u16 mask;
+	unsigned int mask;
 
 	master = &ap->device[0];
 	slave = &ap->device[1];
 
 	assert (ata_dev_present(master) || ata_dev_present(slave));
 
-	mask = ap->pio_mask;
-	if (ata_dev_present(master))
-		mask &= (master->id[ATA_ID_PIO_MODES] & 0x03);
-	if (ata_dev_present(slave))
-		mask &= (slave->id[ATA_ID_PIO_MODES] & 0x03);
-
-	/* require pio mode 3 or 4 support for host and all devices */
-	if (mask == 0) {
-		printk(KERN_WARNING "ata%u: no PIO3/4 support, ignoring\n",
-		       ap->id);
-		goto err_out;
+	if (shift == ATA_SHIFT_UDMA) {
+		mask = ap->udma_mask;
+		if (ata_dev_present(master))
+			mask &= (master->id[ATA_ID_UDMA_MODES] & 0xff);
+		if (ata_dev_present(slave))
+			mask &= (slave->id[ATA_ID_UDMA_MODES] & 0xff);
+	}
+	else if (shift == ATA_SHIFT_MWDMA) {
+		mask = ap->mwdma_mask;
+		if (ata_dev_present(master))
+			mask &= (master->id[ATA_ID_MWDMA_MODES] & 0x07);
+		if (ata_dev_present(slave))
+			mask &= (slave->id[ATA_ID_MWDMA_MODES] & 0x07);
+	}
+	else if (shift == ATA_SHIFT_PIO) {
+		mask = ap->pio_mask;
+		if (ata_dev_present(master)) {
+			/* spec doesn't return explicit support for
+			 * PIO0-2, so we fake it
+			 */
+			u16 tmp_mode = master->id[ATA_ID_PIO_MODES] & 0x03;
+			tmp_mode <<= 3;
+			tmp_mode |= 0x7;
+			mask &= tmp_mode;
+		}
+		if (ata_dev_present(slave)) {
+			/* spec doesn't return explicit support for
+			 * PIO0-2, so we fake it
+			 */
+			u16 tmp_mode = slave->id[ATA_ID_PIO_MODES] & 0x03;
+			tmp_mode <<= 3;
+			tmp_mode |= 0x7;
+			mask &= tmp_mode;
+		}
+	}
+	else {
+		mask = 0xffffffff; /* shut up compiler warning */
+		BUG();
 	}
 
-	pio = (mask & ATA_ID_PIO4) ? 4 : 3;
-	for (i = 0; i < ATA_MAX_DEVICES; i++)
-		if (ata_dev_present(&ap->device[i])) {
-			ap->device[i].pio_mode = (pio == 3) ?
-				XFER_PIO_3 : XFER_PIO_4;
-			if (ap->ops->set_piomode)
-				ap->ops->set_piomode(ap, &ap->device[i], pio);
-		}
+	return mask;
+}
 
-	return;
+/* find greatest bit */
+static int fgb(u32 bitmap)
+{
+	unsigned int i;
+	int x = -1;
 
-err_out:
-	ap->ops->port_disable(ap);
+	for (i = 0; i < 32; i++)
+		if (bitmap & (1 << i))
+			x = i;
+
+	return x;
 }
 
 /**
- *	ata_host_set_udma -
+ *	ata_choose_xfer_mode -
  *	@ap:
  *
  *	LOCKING:
+ *
+ *	RETURNS:
+ *	Zero on success, negative on error.
  */
 
-static void ata_host_set_udma(struct ata_port *ap)
-{
-	struct ata_device *master, *slave;
-	u16 mask;
-	unsigned int i, j;
-	int udma_mode = -1;
-
-	master = &ap->device[0];
-	slave = &ap->device[1];
-
-	assert (ata_dev_present(master) || ata_dev_present(slave));
-	assert ((ap->flags & ATA_FLAG_PORT_DISABLED) == 0);
-
-	DPRINTK("udma masks: host 0x%X, master 0x%X, slave 0x%X\n",
-		ap->udma_mask,
-		(!ata_dev_present(master)) ? 0xff :
-			(master->id[ATA_ID_UDMA_MODES] & 0xff),
-		(!ata_dev_present(slave)) ? 0xff :
-			(slave->id[ATA_ID_UDMA_MODES] & 0xff));
-
-	mask = ap->udma_mask;
-	if (ata_dev_present(master))
-		mask &= (master->id[ATA_ID_UDMA_MODES] & 0xff);
-	if (ata_dev_present(slave))
-		mask &= (slave->id[ATA_ID_UDMA_MODES] & 0xff);
-
-	i = XFER_UDMA_7;
-	while (i >= XFER_UDMA_0) {
-		j = i - XFER_UDMA_0;
-		DPRINTK("mask 0x%X i 0x%X j %u\n", mask, i, j);
-		if (mask & (1 << j)) {
-			udma_mode = i;
-			break;
+static int ata_choose_xfer_mode(struct ata_port *ap,
+				u8 *xfer_mode_out,
+				unsigned int *xfer_shift_out)
+{
+	unsigned int mask, shift;
+	int x, i;
+
+	for (i = 0; i < ARRAY_SIZE(xfer_mode_classes); i++) {
+		shift = xfer_mode_classes[i].shift;
+		mask = ata_get_mode_mask(ap, shift);
+
+		x = fgb(mask);
+		if (x >= 0) {
+			*xfer_mode_out = xfer_mode_classes[i].base + x;
+			*xfer_shift_out = shift;
+			return 0;
 		}
-
-		i--;
-	}
-
-	/* require udma for host and all attached devices */
-	if (udma_mode < 0) {
-		printk(KERN_WARNING "ata%u: no UltraDMA support, ignoring\n",
-		       ap->id);
-		goto err_out;
 	}
 
-	for (i = 0; i < ATA_MAX_DEVICES; i++)
-		if (ata_dev_present(&ap->device[i])) {
-			ap->device[i].udma_mode = udma_mode;
-			if (ap->ops->set_udmamode)
-				ap->ops->set_udmamode(ap, &ap->device[i],
-						      udma_mode);
-		}
-
-	return;
-
-err_out:
-	ap->ops->port_disable(ap);
+	return -1;
 }
 
 /**
@@ -1707,89 +1777,39 @@ err_out:
 
 static void ata_dev_set_xfermode(struct ata_port *ap, struct ata_device *dev)
 {
-	struct ata_taskfile tf;
+	DECLARE_COMPLETION(wait);
+	struct ata_queued_cmd *qc;
+	int rc;
+	unsigned long flags;
 
 	/* set up set-features taskfile */
 	DPRINTK("set features - xfer mode\n");
-	ata_tf_init(ap, &tf, dev->devno);
-	tf.ctl |= ATA_NIEN;
-	tf.command = ATA_CMD_SET_FEATURES;
-	tf.feature = SETFEATURES_XFER;
-	tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
-	tf.protocol = ATA_PROT_NODATA;
-	if (dev->flags & ATA_DFLAG_PIO)
-		tf.nsect = dev->pio_mode;
-	else
-		tf.nsect = dev->udma_mode;
 
-	/* do bus reset */
-	ata_tf_to_host(ap, &tf);
+	qc = ata_qc_new_init(ap, dev);
+	BUG_ON(qc == NULL);
 
-	/* crazy ATAPI devices... */
-	if (dev->class == ATA_DEV_ATAPI)
-		msleep(150);
+	qc->tf.command = ATA_CMD_SET_FEATURES;
+	qc->tf.feature = SETFEATURES_XFER;
+	qc->tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
+	qc->tf.protocol = ATA_PROT_NODATA;
+	qc->tf.nsect = dev->xfer_mode;
 
-	ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT);
+	qc->waiting = &wait;
+	qc->complete_fn = ata_qc_complete_noop;
 
-	ata_irq_on(ap);	/* re-enable interrupts */
+	spin_lock_irqsave(&ap->host_set->lock, flags);
+	rc = ata_qc_issue(qc);
+	spin_unlock_irqrestore(&ap->host_set->lock, flags);
 
-	ata_wait_idle(ap);
+	if (rc)
+		ata_port_disable(ap);
+	else
+		wait_for_completion(&wait);
 
 	DPRINTK("EXIT\n");
 }
 
 /**
- *	ata_dev_set_udma - Set ATA device's transfer mode to Ultra DMA
- *	@ap: Port associated with device @dev
- *	@device: Device whose mode will be set
- *
- *	LOCKING:
- */
-
-static void ata_dev_set_udma(struct ata_port *ap, unsigned int device)
-{
-	struct ata_device *dev = &ap->device[device];
-
-	if (!ata_dev_present(dev) || (ap->flags & ATA_FLAG_PORT_DISABLED))
-		return;
-
-	ata_dev_set_xfermode(ap, dev);
-
-	assert((dev->udma_mode >= XFER_UDMA_0) &&
-	       (dev->udma_mode <= XFER_UDMA_7));
-	printk(KERN_INFO "ata%u: dev %u configured for %s\n",
-	       ap->id, device,
-	       udma_str[dev->udma_mode - XFER_UDMA_0]);
-}
-
-/**
- *	ata_dev_set_pio - Set ATA device's transfer mode to PIO
- *	@ap: Port associated with device @dev
- *	@device: Device whose mode will be set
- *
- *	LOCKING:
- */
-
-static void ata_dev_set_pio(struct ata_port *ap, unsigned int device)
-{
-	struct ata_device *dev = &ap->device[device];
-
-	if (!ata_dev_present(dev) || (ap->flags & ATA_FLAG_PORT_DISABLED))
-		return;
-
-	/* force PIO mode */
-	dev->flags |= ATA_DFLAG_PIO;
-
-	ata_dev_set_xfermode(ap, dev);
-
-	assert((dev->pio_mode >= XFER_PIO_3) &&
-	       (dev->pio_mode <= XFER_PIO_4));
-	printk(KERN_INFO "ata%u: dev %u configured for PIO%c\n",
-	       ap->id, device,
-	       dev->pio_mode == 3 ? '3' : '4');
-}
-
-/**
  *	ata_sg_clean -
  *	@qc:
  *
@@ -1799,37 +1819,35 @@ static void ata_dev_set_pio(struct ata_p
 static void ata_sg_clean(struct ata_queued_cmd *qc)
 {
 	struct ata_port *ap = qc->ap;
-	struct scsi_cmnd *cmd = qc->scsicmd;
 	struct scatterlist *sg = qc->sg;
-	int dir = scsi_to_pci_dma_dir(cmd->sc_data_direction);
+	int dir = qc->pci_dma_dir;
 
-	assert(dir == SCSI_DATA_READ || dir == SCSI_DATA_WRITE);
-	assert(qc->flags & ATA_QCFLAG_SG);
+	assert(qc->flags & ATA_QCFLAG_DMAMAP);
 	assert(sg != NULL);
 
-	if (!cmd->use_sg)
+	if (qc->flags & ATA_QCFLAG_SINGLE)
 		assert(qc->n_elem == 1);
 
 	DPRINTK("unmapping %u sg elements\n", qc->n_elem);
 
-	if (cmd->use_sg)
+	if (qc->flags & ATA_QCFLAG_SG)
 		pci_unmap_sg(ap->host_set->pdev, sg, qc->n_elem, dir);
 	else
 		pci_unmap_single(ap->host_set->pdev, sg_dma_address(&sg[0]),
 				 sg_dma_len(&sg[0]), dir);
 
-	qc->flags &= ~ATA_QCFLAG_SG;
+	qc->flags &= ~ATA_QCFLAG_DMAMAP;
 	qc->sg = NULL;
 }
 
 /**
- *	ata_fill_sg -
- *	@qc:
+ *	ata_fill_sg - Fill PCI IDE PRD table
+ *	@qc: Metadata associated with taskfile to be transferred
  *
  *	LOCKING:
  *
  */
-void ata_fill_sg(struct ata_queued_cmd *qc)
+static void ata_fill_sg(struct ata_queued_cmd *qc)
 {
 	struct scatterlist *sg = qc->sg;
 	struct ata_port *ap = qc->ap;
@@ -1840,7 +1858,7 @@ void ata_fill_sg(struct ata_queued_cmd *
 
 	idx = 0;
 	for (nelem = qc->n_elem; nelem; nelem--,sg++) {
-		u32 addr, boundary;
+		u32 addr, offset;
 		u32 sg_len, len;
 
 		/* determine if physical DMA addr spans 64K boundary.
@@ -1851,10 +1869,10 @@ void ata_fill_sg(struct ata_queued_cmd *
 		sg_len = sg_dma_len(sg);
 
 		while (sg_len) {
-			boundary = (addr & ~0xffff) + (0xffff + 1);
+			offset = addr & 0xffff;
 			len = sg_len;
-			if ((addr + sg_len) > boundary)
-				len = boundary - addr;
+			if ((offset + sg_len) > 0x10000)
+				len = 0x10000 - offset;
 
 			ap->prd[idx].addr = cpu_to_le32(addr);
 			ap->prd[idx].flags_len = cpu_to_le32(len & 0xffff);
@@ -1871,6 +1889,48 @@ void ata_fill_sg(struct ata_queued_cmd *
 }
 
 /**
+ *	ata_qc_prep - Prepare taskfile for submission
+ *	@qc: Metadata associated with taskfile to be prepared
+ *
+ *	LOCKING:
+ *	spin_lock_irqsave(host_set lock)
+ */
+void ata_qc_prep(struct ata_queued_cmd *qc)
+{
+	if (!(qc->flags & ATA_QCFLAG_DMAMAP))
+		return;
+
+	ata_fill_sg(qc);
+}
+
+void ata_sg_init_one(struct ata_queued_cmd *qc, void *buf, unsigned int buflen)
+{
+	struct scatterlist *sg;
+
+	qc->flags |= ATA_QCFLAG_SINGLE;
+
+	memset(&qc->sgent, 0, sizeof(qc->sgent));
+	qc->sg = &qc->sgent;
+	qc->n_elem = 1;
+	qc->buf_virt = buf;
+
+	sg = qc->sg;
+	sg->page = virt_to_page(buf);
+	sg->offset = (unsigned long) buf & ~PAGE_MASK;
+	sg_dma_len(sg) = buflen;
+
+	WARN_ON(buflen > PAGE_SIZE);
+}
+
+void ata_sg_init(struct ata_queued_cmd *qc, struct scatterlist *sg,
+		 unsigned int n_elem)
+{
+	qc->flags |= ATA_QCFLAG_SG;
+	qc->sg = sg;
+	qc->n_elem = n_elem;
+}
+
+/**
  *	ata_sg_setup_one -
  *	@qc:
  *
@@ -1884,29 +1944,16 @@ void ata_fill_sg(struct ata_queued_cmd *
 static int ata_sg_setup_one(struct ata_queued_cmd *qc)
 {
 	struct ata_port *ap = qc->ap;
-	struct scsi_cmnd *cmd = qc->scsicmd;
-	int dir = scsi_to_pci_dma_dir(cmd->sc_data_direction);
+	int dir = qc->pci_dma_dir;
 	struct scatterlist *sg = qc->sg;
-	unsigned int have_sg = (qc->flags & ATA_QCFLAG_SG);
 	dma_addr_t dma_address;
 
-	assert(sg == &qc->sgent);
-	assert(qc->n_elem == 1);
-
-	sg->address = cmd->request_buffer;
-	sg->page = virt_to_page(cmd->request_buffer);
-	sg->offset = (unsigned long) cmd->request_buffer & ~PAGE_MASK;
-	sg_dma_len(sg) = cmd->request_bufflen;
-
-	if (!have_sg)
-		return 0;
-
-	dma_address = pci_map_single(ap->host_set->pdev, cmd->request_buffer,
-				     cmd->request_bufflen, dir);
+	dma_address = pci_map_single(ap->host_set->pdev, qc->buf_virt,
+				     sg_dma_len(sg), dir);
 
 	sg_dma_address(sg) = dma_address;
 
-	DPRINTK("mapped buffer of %d bytes for %s\n", cmd->request_bufflen,
+	DPRINTK("mapped buffer of %d bytes for %s\n", sg_dma_len(sg),
 		qc->tf.flags & ATA_TFLAG_WRITE ? "write" : "read");
 
 	return 0;
@@ -1926,24 +1973,19 @@ static int ata_sg_setup_one(struct ata_q
 static int ata_sg_setup(struct ata_queued_cmd *qc)
 {
 	struct ata_port *ap = qc->ap;
-	struct scsi_cmnd *cmd = qc->scsicmd;
-	struct scatterlist *sg;
-	int n_elem;
-	unsigned int have_sg = (qc->flags & ATA_QCFLAG_SG);
+	struct scatterlist *sg = qc->sg;
+	int n_elem, dir;
 
-	VPRINTK("ENTER, ata%u, use_sg %d\n", ap->id, cmd->use_sg);
-	assert(cmd->use_sg > 0);
+	VPRINTK("ENTER, ata%u\n", ap->id);
+	assert(qc->flags & ATA_QCFLAG_SG);
+
+	dir = qc->pci_dma_dir;
+	n_elem = pci_map_sg(ap->host_set->pdev, sg, qc->n_elem, dir);
+	if (n_elem < 1)
+		return -1;
+
+	DPRINTK("%d sg elements mapped\n", n_elem);
 
-	sg = (struct scatterlist *)cmd->request_buffer;
-	if (have_sg) {
-		int dir = scsi_to_pci_dma_dir(cmd->sc_data_direction);
-		n_elem = pci_map_sg(ap->host_set->pdev, sg, cmd->use_sg, dir);
-		if (n_elem < 1)
-			return -1;
-		DPRINTK("%d sg elements mapped\n", n_elem);
-	} else {
-		n_elem = cmd->use_sg;
-	}
 	qc->n_elem = n_elem;
 
 	return 0;
@@ -2028,7 +2070,7 @@ static void ata_pio_complete (struct ata
 	}
 
 	drv_stat = ata_wait_idle(ap);
-	if (drv_stat & (ATA_BUSY | ATA_DRQ)) {
+	if (!ata_ok(drv_stat)) {
 		ap->pio_task_state = PIO_ST_ERR;
 		return;
 	}
@@ -2043,6 +2085,128 @@ static void ata_pio_complete (struct ata
 	ata_qc_complete(qc, drv_stat);
 }
 
+void swap_buf_le16(u16 *buf, unsigned int buf_words)
+{
+#ifdef __BIG_ENDIAN
+	unsigned int i;
+
+	for (i = 0; i < buf_words; i++)
+		buf[i] = le16_to_cpu(buf[i]);
+#endif /* __BIG_ENDIAN */
+}
+
+static void ata_mmio_data_xfer(struct ata_port *ap, unsigned char *buf,
+			       unsigned int buflen, int write_data)
+{
+	unsigned int i;
+	unsigned int words = buflen >> 1;
+	u16 *buf16 = (u16 *) buf;
+	void *mmio = (void *)ap->ioaddr.data_addr;
+
+	if (write_data) {
+		for (i = 0; i < words; i++)
+			writew(le16_to_cpu(buf16[i]), mmio);
+	} else {
+		for (i = 0; i < words; i++)
+			buf16[i] = cpu_to_le16(readw(mmio));
+	}
+}
+
+static void ata_pio_data_xfer(struct ata_port *ap, unsigned char *buf,
+			      unsigned int buflen, int write_data)
+{
+	unsigned int dwords = buflen >> 1;
+
+	if (write_data)
+		outsw(ap->ioaddr.data_addr, buf, dwords);
+	else
+		insw(ap->ioaddr.data_addr, buf, dwords);
+}
+
+static void ata_data_xfer(struct ata_port *ap, unsigned char *buf,
+			  unsigned int buflen, int do_write)
+{
+	if (ap->flags & ATA_FLAG_MMIO)
+		ata_mmio_data_xfer(ap, buf, buflen, do_write);
+	else
+		ata_pio_data_xfer(ap, buf, buflen, do_write);
+}
+
+static void ata_pio_sector(struct ata_queued_cmd *qc)
+{
+	int do_write = (qc->tf.flags & ATA_TFLAG_WRITE);
+	struct scatterlist *sg = qc->sg;
+	struct ata_port *ap = qc->ap;
+	struct page *page;
+	unsigned char *buf;
+
+	if (qc->cursect == (qc->nsect - 1))
+		ap->pio_task_state = PIO_ST_LAST;
+
+	page = sg[qc->cursg].page;
+	buf = kmap(page) +
+	      sg[qc->cursg].offset + (qc->cursg_ofs * ATA_SECT_SIZE);
+
+	qc->cursect++;
+	qc->cursg_ofs++;
+
+	if ((qc->cursg_ofs * ATA_SECT_SIZE) == sg_dma_len(&sg[qc->cursg])) {
+		qc->cursg++;
+		qc->cursg_ofs = 0;
+	}
+
+	DPRINTK("data %s, drv_stat 0x%X\n",
+		qc->tf.flags & ATA_TFLAG_WRITE ? "write" : "read",
+		status);
+
+	/* do the actual data transfer */
+	do_write = (qc->tf.flags & ATA_TFLAG_WRITE);
+	ata_data_xfer(ap, buf, ATA_SECT_SIZE, do_write);
+
+	kunmap(page);
+}
+
+static void atapi_pio_sector(struct ata_queued_cmd *qc)
+{
+	struct ata_port *ap = qc->ap;
+	struct ata_device *dev = qc->dev;
+	unsigned int i, ireason, bc_lo, bc_hi, bytes;
+	int i_write, do_write = (qc->tf.flags & ATA_TFLAG_WRITE) ? 1 : 0;
+
+	ap->ops->tf_read(ap, &qc->tf);
+	ireason = qc->tf.nsect;
+	bc_lo = qc->tf.lbam;
+	bc_hi = qc->tf.lbah;
+	bytes = (bc_hi << 8) | bc_lo;
+
+	/* shall be cleared to zero, indicating xfer of data */
+	if (ireason & (1 << 0))
+		goto err_out;
+	
+	/* make sure transfer direction matches expected */
+	i_write = ((ireason & (1 << 1)) == 0) ? 1 : 0;
+	if (do_write != i_write)
+		goto err_out;
+
+	/* make sure byte count is multiple of sector size; not
+	* required by standard (warning! warning!), but IDE driver
+	* does this to simplify things a bit.  We are lazy, and
+	* follow suit.
+	*/
+	if (bytes & (ATA_SECT_SIZE - 1))
+		goto err_out;
+
+	for (i = 0; i < (bytes >> 9); i++)
+		ata_pio_sector(qc);
+	
+	return;
+
+err_out:
+	printk(KERN_INFO "ata%u: dev %u: ATAPI check failed\n",
+	      ap->id, dev->devno);
+	ap->pio_task_state = PIO_ST_ERR;
+}
+
 /**
  *	ata_pio_sector -
  *	@ap:
@@ -2050,12 +2214,9 @@ static void ata_pio_complete (struct ata
  *	LOCKING:
  */
 
-static void ata_pio_sector(struct ata_port *ap)
+static void ata_pio_block(struct ata_port *ap)
 {
 	struct ata_queued_cmd *qc;
-	struct scatterlist *sg;
-	struct scsi_cmnd *cmd;
-	unsigned char *buf;
 	u8 status;
 
 	/*
@@ -2086,36 +2247,29 @@ static void ata_pio_sector(struct ata_po
 	qc = ata_qc_from_tag(ap, ap->active_tag);
 	assert(qc != NULL);
 
-	cmd = qc->scsicmd;
-	sg = qc->sg;
-
-	if (qc->cursect == (qc->nsect - 1))
-		ap->pio_task_state = PIO_ST_LAST;
+	if (is_atapi_taskfile(&qc->tf))
+		atapi_pio_sector(qc);
+	else
+		ata_pio_sector(qc);
+}
 
-	buf = kmap(sg[qc->cursg].page) +
-	      sg[qc->cursg].offset + (qc->cursg_ofs * ATA_SECT_SIZE);
+static void ata_pio_error(struct ata_port *ap)
+{
+	struct ata_queued_cmd *qc;
+	u8 drv_stat;
 
-	qc->cursect++;
-	qc->cursg_ofs++;
+	qc = ata_qc_from_tag(ap, ap->active_tag);
+	assert(qc != NULL);
 
-	if (cmd->use_sg)
-		if ((qc->cursg_ofs * ATA_SECT_SIZE) == sg_dma_len(&sg[qc->cursg])) {
-			qc->cursg++;
-			qc->cursg_ofs = 0;
-		}
+	drv_stat = ata_chk_status(ap);
+	printk(KERN_WARNING "ata%u: PIO error, drv_stat 0x%x\n",
+	       ap->id, drv_stat);
 
-	DPRINTK("data %s, drv_stat 0x%X\n",
-		qc->tf.flags & ATA_TFLAG_WRITE ? "write" : "read",
-		status);
+	ap->pio_task_state = PIO_ST_IDLE;
 
-	/* do the actual data transfer */
-	/* FIXME: mmio-ize */
-	if (qc->tf.flags & ATA_TFLAG_WRITE)
-		outsl(ap->ioaddr.data_addr, buf, ATA_SECT_DWORDS);
-	else
-		insl(ap->ioaddr.data_addr, buf, ATA_SECT_DWORDS);
+	ata_irq_on(ap);
 
-	kunmap(sg[qc->cursg].page);
+	ata_qc_complete(qc, drv_stat | ATA_ERR);
 }
 
 static void ata_pio_task(void *_data)
@@ -2125,7 +2279,7 @@ static void ata_pio_task(void *_data)
 
 	switch (ap->pio_task_state) {
 	case PIO_ST:
-		ata_pio_sector(ap);
+		ata_pio_block(ap);
 		break;
 
 	case PIO_ST_LAST:
@@ -2138,15 +2292,8 @@ static void ata_pio_task(void *_data)
 		break;
 
 	case PIO_ST_TMOUT:
-		printk(KERN_ERR "ata%d: FIXME: PIO_ST_TMOUT\n", /* FIXME */
-		       ap->id);
-		timeout = 11 * HZ;
-		break;
-
 	case PIO_ST_ERR:
-		printk(KERN_ERR "ata%d: FIXME: PIO_ST_ERR\n", /* FIXME */
-		       ap->id);
-		timeout = 11 * HZ;
+		ata_pio_error(ap);
 		break;
 	}
 
@@ -2157,13 +2304,14 @@ static void ata_pio_task(void *_data)
 
 	if ((ap->pio_task_state != PIO_ST_IDLE) &&
 	    (ap->pio_task_state != PIO_ST_TMOUT) &&
-	    (ap->pio_task_state != PIO_ST_ERR))
+	    (ap->pio_task_state != PIO_ST_ERR)) {
 		schedule_task(&ap->pio_task);
+	}
 }
 
 /**
- *	ata_eng_timeout - Handle timeout of queued command
- *	@ap: Port on which timed-out command is active
+ *	ata_qc_timeout - Handle timeout of queued command
+ *	@qc: Command that timed out
  *
  *	Some part of the kernel (currently, only the SCSI layer)
  *	has noticed that the active command on port @ap has not
@@ -2177,23 +2325,15 @@ static void ata_pio_task(void *_data)
  *	transaction completed successfully.
  *
  *	LOCKING:
- *	Inherited from SCSI layer (none, can sleep)
  */
 
-void ata_eng_timeout(struct ata_port *ap)
+static void ata_qc_timeout(struct ata_queued_cmd *qc)
 {
-	u8 host_stat, drv_stat;
-	struct ata_queued_cmd *qc;
+	struct ata_port *ap = qc->ap;
+	u8 host_stat = 0, drv_stat;
 
 	DPRINTK("ENTER\n");
 
-	qc = ata_qc_from_tag(ap, ap->active_tag);
-	if (!qc) {
-		printk(KERN_ERR "ata%u: BUG: timeout without command\n",
-		       ap->id);
-		goto out;
-	}
-
 	/* hack alert!  We cannot use the supplied completion
 	 * function from inside the ->eh_strategy_handler() thread.
 	 * libata is the only user of ->eh_strategy_handler() in
@@ -2203,38 +2343,68 @@ void ata_eng_timeout(struct ata_port *ap
 	qc->scsidone = scsi_finish_command;
 
 	switch (qc->tf.protocol) {
+
 	case ATA_PROT_DMA:
-		if (ap->flags & ATA_FLAG_MMIO) {
-			void *mmio = (void *) ap->ioaddr.bmdma_addr;
-			host_stat = readb(mmio + ATA_DMA_STATUS);
-		} else
-			host_stat = inb(ap->ioaddr.bmdma_addr + ATA_DMA_STATUS);
+	case ATA_PROT_ATAPI_DMA:
+		host_stat = ata_bmdma_status(ap);
 
-		printk(KERN_ERR "ata%u: DMA timeout, stat 0x%x\n",
-		       ap->id, host_stat);
+		/* before we do anything else, clear DMA-Start bit */
+		ata_bmdma_stop(ap);
 
-		ata_dma_complete(qc, host_stat);
-		break;
+		/* fall through */
 
-	case ATA_PROT_NODATA:
-		drv_stat = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 1000);
+	default:
+		ata_altstatus(ap);
+		drv_stat = ata_chk_status(ap);
+
+		/* ack bmdma irq events */
+		ata_bmdma_ack_irq(ap);
 
-		printk(KERN_ERR "ata%u: command 0x%x timeout, stat 0x%x\n",
-		       ap->id, qc->tf.command, drv_stat);
+		printk(KERN_ERR "ata%u: command 0x%x timeout, stat 0x%x host_stat 0x%x\n",
+		       ap->id, qc->tf.command, drv_stat, host_stat);
 
+		/* complete taskfile transaction */
 		ata_qc_complete(qc, drv_stat);
 		break;
+	}
 
-	default:
-		drv_stat = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 1000);
+	DPRINTK("EXIT\n");
+}
 
-		printk(KERN_ERR "ata%u: unknown timeout, cmd 0x%x stat 0x%x\n",
-		       ap->id, qc->tf.command, drv_stat);
+/**
+ *	ata_eng_timeout - Handle timeout of queued command
+ *	@ap: Port on which timed-out command is active
+ *
+ *	Some part of the kernel (currently, only the SCSI layer)
+ *	has noticed that the active command on port @ap has not
+ *	completed after a specified length of time.  Handle this
+ *	condition by disabling DMA (if necessary) and completing
+ *	transactions, with error if necessary.
+ *
+ *	This also handles the case of the "lost interrupt", where
+ *	for some reason (possibly hardware bug, possibly driver bug)
+ *	an interrupt was not delivered to the driver, even though the
+ *	transaction completed successfully.
+ *
+ *	LOCKING:
+ *	Inherited from SCSI layer (none, can sleep)
+ */
 
-		ata_qc_complete(qc, drv_stat);
-		break;
+void ata_eng_timeout(struct ata_port *ap)
+{
+	struct ata_queued_cmd *qc;
+
+	DPRINTK("ENTER\n");
+
+	qc = ata_qc_from_tag(ap, ap->active_tag);
+	if (!qc) {
+		printk(KERN_ERR "ata%u: BUG: timeout without command\n",
+		       ap->id);
+		goto out;
 	}
 
+	ata_qc_timeout(qc);
+
 out:
 	DPRINTK("EXIT\n");
 }
@@ -2289,8 +2459,6 @@ struct ata_queued_cmd *ata_qc_new_init(s
 
 		ata_tf_init(ap, &qc->tf, dev->devno);
 
-		if (likely((dev->flags & ATA_DFLAG_PIO) == 0))
-			qc->flags |= ATA_QCFLAG_DMA;
 		if (dev->flags & ATA_DFLAG_LBA48)
 			qc->tf.flags |= ATA_TFLAG_LBA48;
 	}
@@ -2298,6 +2466,11 @@ struct ata_queued_cmd *ata_qc_new_init(s
 	return qc;
 }
 
+static int ata_qc_complete_noop(struct ata_queued_cmd *qc, u8 drv_stat)
+{
+	return 0;
+}
+
 /**
  *	ata_qc_complete - Complete an active ATA command
  *	@qc: Command to complete
@@ -2310,29 +2483,25 @@ struct ata_queued_cmd *ata_qc_new_init(s
 void ata_qc_complete(struct ata_queued_cmd *qc, u8 drv_stat)
 {
 	struct ata_port *ap = qc->ap;
-	struct scsi_cmnd *cmd = qc->scsicmd;
 	unsigned int tag, do_clear = 0;
+	int rc;
 
 	assert(qc != NULL);	/* ata_qc_from_tag _might_ return NULL */
 	assert(qc->flags & ATA_QCFLAG_ACTIVE);
 
-	if (likely(qc->flags & ATA_QCFLAG_SG))
+	if (likely(qc->flags & ATA_QCFLAG_DMAMAP))
 		ata_sg_clean(qc);
 
-	if (cmd) {
-		if (unlikely(drv_stat & (ATA_ERR | ATA_BUSY | ATA_DRQ))) {
-			if (is_atapi_taskfile(&qc->tf))
-				cmd->result = SAM_STAT_CHECK_CONDITION;
-			else
-				ata_to_sense_error(qc);
-		} else {
-			cmd->result = SAM_STAT_GOOD;
-		}
+	/* call completion callback */
+	rc = qc->complete_fn(qc, drv_stat);
 
-		qc->scsidone(cmd);
-	}
+	/* if callback indicates not to complete command (non-zero),
+	 * return immediately
+	 */
+	if (rc != 0)
+		return;
 
-	qc->flags &= ~ATA_QCFLAG_ACTIVE;
+	qc->flags = 0;
 	tag = qc->tag;
 	if (likely(ata_tag_valid(tag))) {
 		if (tag == ap->active_tag)
@@ -2341,11 +2510,16 @@ void ata_qc_complete(struct ata_queued_c
 		do_clear = 1;
 	}
 
-	if (qc->waiting)
-		complete(qc->waiting);
+	if (qc->waiting) {
+		struct completion *waiting = qc->waiting;
+		qc->waiting = NULL;
+		complete(waiting);
+	}
 
 	if (likely(do_clear))
 		clear_bit(tag, &ap->qactive);
+
+	VPRINTK("EXIT\n");
 }
 
 /**
@@ -2367,25 +2541,21 @@ void ata_qc_complete(struct ata_queued_c
 int ata_qc_issue(struct ata_queued_cmd *qc)
 {
 	struct ata_port *ap = qc->ap;
-	struct scsi_cmnd *cmd = qc->scsicmd;
 
 	if (qc->flags & ATA_QCFLAG_SG) {
-		/* set up SG table */
-		if (cmd->use_sg) {
-			if (ata_sg_setup(qc))
-				goto err_out;
-		} else {
-			if (ata_sg_setup_one(qc))
-				goto err_out;
-		}
-
-		ap->ops->fill_sg(qc);
+		if (ata_sg_setup(qc))
+			goto err_out;
+	} else if (qc->flags & ATA_QCFLAG_SINGLE) {
+		if (ata_sg_setup_one(qc))
+			goto err_out;
 	}
 
+	ap->ops->qc_prep(qc);
+
 	qc->ap->active_tag = qc->tag;
 	qc->flags |= ATA_QCFLAG_ACTIVE;
 
-	return ata_qc_issue_prot(qc);
+	return ap->ops->qc_issue(qc);
 
 err_out:
 	return -1;
@@ -2407,7 +2577,7 @@ err_out:
  *	Zero on success, negative on error.
  */
 
-static int ata_qc_issue_prot(struct ata_queued_cmd *qc)
+int ata_qc_issue_prot(struct ata_queued_cmd *qc)
 {
 	struct ata_port *ap = qc->ap;
 
@@ -2432,6 +2602,12 @@ static int ata_qc_issue_prot(struct ata_
 		break;
 
 	case ATA_PROT_ATAPI:
+		ata_qc_set_polling(qc);
+		ata_tf_to_host_nolock(ap, &qc->tf);
+		schedule_task(&ap->packet_task);
+		break;
+
+	case ATA_PROT_ATAPI_NODATA:
 		ata_tf_to_host_nolock(ap, &qc->tf);
 		schedule_task(&ap->packet_task);
 		break;
@@ -2443,6 +2619,7 @@ static int ata_qc_issue_prot(struct ata_
 		break;
 
 	default:
+		WARN_ON(1);
 		return -1;
 	}
 
@@ -2461,7 +2638,7 @@ void ata_bmdma_setup_mmio (struct ata_qu
 {
 	struct ata_port *ap = qc->ap;
 	unsigned int rw = (qc->tf.flags & ATA_TFLAG_WRITE);
-	u8 host_stat, dmactl;
+	u8 dmactl;
 	void *mmio = (void *) ap->ioaddr.bmdma_addr;
 
 	/* load PRD table addr. */
@@ -2475,10 +2652,6 @@ void ata_bmdma_setup_mmio (struct ata_qu
 		dmactl |= ATA_DMA_WR;
 	writeb(dmactl, mmio + ATA_DMA_CMD);
 
-	/* clear interrupt, error bits */
-	host_stat = readb(mmio + ATA_DMA_STATUS);
-	writeb(host_stat | ATA_DMA_INTR | ATA_DMA_ERR, mmio + ATA_DMA_STATUS);
-
 	/* issue r/w command */
 	ap->ops->exec_command(ap, &qc->tf);
 }
@@ -2526,7 +2699,7 @@ void ata_bmdma_setup_pio (struct ata_que
 {
 	struct ata_port *ap = qc->ap;
 	unsigned int rw = (qc->tf.flags & ATA_TFLAG_WRITE);
-	u8 host_stat, dmactl;
+	u8 dmactl;
 
 	/* load PRD table addr. */
 	outl(ap->prd_dma, ap->ioaddr.bmdma_addr + ATA_DMA_TABLE_OFS);
@@ -2538,11 +2711,6 @@ void ata_bmdma_setup_pio (struct ata_que
 		dmactl |= ATA_DMA_WR;
 	outb(dmactl, ap->ioaddr.bmdma_addr + ATA_DMA_CMD);
 
-	/* clear interrupt, error bits */
-	host_stat = inb(ap->ioaddr.bmdma_addr + ATA_DMA_STATUS);
-	outb(host_stat | ATA_DMA_INTR | ATA_DMA_ERR,
-	     ap->ioaddr.bmdma_addr + ATA_DMA_STATUS);
-
 	/* issue r/w command */
 	ap->ops->exec_command(ap, &qc->tf);
 }
@@ -2566,48 +2734,9 @@ void ata_bmdma_start_pio (struct ata_que
 	     ap->ioaddr.bmdma_addr + ATA_DMA_CMD);
 }
 
-/**
- *	ata_dma_complete - Complete an active ATA BMDMA command
- *	@qc: Command to complete
- *	@host_stat: BMDMA status register contents
- *
- *	LOCKING:
- */
-
-static void ata_dma_complete(struct ata_queued_cmd *qc, u8 host_stat)
+void ata_bmdma_irq_clear(struct ata_port *ap)
 {
-	struct ata_port *ap = qc->ap;
-	VPRINTK("ENTER\n");
-
-	if (ap->flags & ATA_FLAG_MMIO) {
-		void *mmio = (void *) ap->ioaddr.bmdma_addr;
-
-		/* clear start/stop bit */
-		writeb(readb(mmio + ATA_DMA_CMD) & ~ATA_DMA_START,
-		       mmio + ATA_DMA_CMD);
-
-		/* ack intr, err bits */
-		writeb(host_stat | ATA_DMA_INTR | ATA_DMA_ERR,
-		       mmio + ATA_DMA_STATUS);
-	} else {
-		/* clear start/stop bit */
-		outb(inb(ap->ioaddr.bmdma_addr + ATA_DMA_CMD) & ~ATA_DMA_START,
-		     ap->ioaddr.bmdma_addr + ATA_DMA_CMD);
-
-		/* ack intr, err bits */
-		outb(host_stat | ATA_DMA_INTR | ATA_DMA_ERR,
-		     ap->ioaddr.bmdma_addr + ATA_DMA_STATUS);
-	}
-
-
-	/* one-PIO-cycle guaranteed wait, per spec, for HDMA1:0 transition */
-	ata_altstatus(ap);		/* dummy read */
-
-	DPRINTK("host %u, host_stat==0x%X, drv_stat==0x%X\n",
-		ap->id, (u32) host_stat, (u32) ata_chk_status(ap));
-
-	/* get drive status; clear intr; complete txn */
-	ata_qc_complete(qc, ata_wait_idle(ap));
+	ata_bmdma_ack_irq(ap);
 }
 
 /**
@@ -2630,59 +2759,63 @@ inline unsigned int ata_host_intr (struc
 				   struct ata_queued_cmd *qc)
 {
 	u8 status, host_stat;
-	unsigned int handled = 0;
 
 	switch (qc->tf.protocol) {
 
-	/* BMDMA completion */
 	case ATA_PROT_DMA:
 	case ATA_PROT_ATAPI_DMA:
-		if (ap->flags & ATA_FLAG_MMIO) {
-			void *mmio = (void *) ap->ioaddr.bmdma_addr;
-			host_stat = readb(mmio + ATA_DMA_STATUS);
-		} else
-			host_stat = inb(ap->ioaddr.bmdma_addr + ATA_DMA_STATUS);
-		VPRINTK("BUS_DMA (host_stat 0x%X)\n", host_stat);
+	case ATA_PROT_ATAPI:
+		/* check status of DMA engine */
+		host_stat = ata_bmdma_status(ap);
+		VPRINTK("ata%u: host_stat 0x%X\n", ap->id, host_stat);
 
-		if (!(host_stat & ATA_DMA_INTR)) {
-			ap->stats.idle_irq++;
-			break;
-		}
+		/* if it's not our irq... */
+		if (!(host_stat & ATA_DMA_INTR))
+			goto idle_irq;
 
-		ata_dma_complete(qc, host_stat);
-		handled = 1;
-		break;
+		/* before we do anything else, clear DMA-Start bit */
+		ata_bmdma_stop(ap);
 
-	/* command completion, but no data xfer */
-	/* FIXME: a shared interrupt _will_ cause a non-data command
-	 * to be completed prematurely, with an error.
-	 *
-	 * This doesn't matter right now, since we aren't sending
-	 * non-data commands down this pipe except in development
-	 * situations.
-	 */
-	case ATA_PROT_ATAPI:
+		/* fall through */
+
+	case ATA_PROT_ATAPI_NODATA:
 	case ATA_PROT_NODATA:
-		status = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 1000);
-		DPRINTK("BUS_NODATA (drv_stat 0x%X)\n", status);
+		/* check altstatus */
+		status = ata_altstatus(ap);
+		if (status & ATA_BUSY)
+			goto idle_irq;
+
+		/* check main status, clearing INTRQ */
+		status = ata_chk_status(ap);
+		if (unlikely(status & ATA_BUSY))
+			goto idle_irq;
+		DPRINTK("ata%u: protocol %d (dev_stat 0x%X)\n",
+			ap->id, qc->tf.protocol, status);
+
+		/* ack bmdma irq events */
+		ata_bmdma_ack_irq(ap);
+
+		/* complete taskfile transaction */
 		ata_qc_complete(qc, status);
-		handled = 1;
 		break;
 
 	default:
-		ap->stats.idle_irq++;
+		goto idle_irq;
+	}
+
+	return 1;	/* irq handled */
+
+idle_irq:
+	ap->stats.idle_irq++;
 
 #ifdef ATA_IRQ_TRAP
-		if ((ap->stats.idle_irq % 1000) == 0) {
-			handled = 1;
-			ata_irq_ack(ap, 0); /* debug trap */
-			printk(KERN_WARNING "ata%d: irq trap\n", ap->id);
-		}
-#endif
-		break;
+	if ((ap->stats.idle_irq % 1000) == 0) {
+		handled = 1;
+		ata_irq_ack(ap, 0); /* debug trap */
+		printk(KERN_WARNING "ata%d: irq trap\n", ap->id);
 	}
-
-	return handled;
+#endif
+	return 0;	/* irq not handled */
 }
 
 /**
@@ -2716,7 +2849,7 @@ irqreturn_t ata_interrupt (int irq, void
 
 			qc = ata_qc_from_tag(ap, ap->active_tag);
 			if (qc && (!(qc->tf.ctl & ATA_NIEN)))
-				handled += ata_host_intr(ap, qc);
+				handled |= ata_host_intr(ap, qc);
 		}
 	}
 
@@ -2726,62 +2859,6 @@ irqreturn_t ata_interrupt (int irq, void
 }
 
 /**
- *	ata_thread_iter -
- *	@ap:
- *
- *	LOCKING:
- *
- *	RETURNS:
- *
- */
-
-static unsigned long ata_thread_iter(struct ata_port *ap)
-{
-	long timeout = 0;
-
-	DPRINTK("ata%u: thr_state %s\n",
-		ap->id, ata_thr_state_name(ap->thr_state));
-
-	switch (ap->thr_state) {
-	case THR_UNKNOWN:
-		ap->thr_state = THR_PORT_RESET;
-		break;
-
-	case THR_PROBE_START:
-		ap->thr_state = THR_PORT_RESET;
-		break;
-
-	case THR_PORT_RESET:
-		ata_port_reset(ap);
-		break;
-
-	case THR_PROBE_SUCCESS:
-		up(&ap->probe_sem);
-		ap->thr_state = THR_IDLE;
-		break;
-
-	case THR_PROBE_FAILED:
-		up(&ap->probe_sem);
-		ap->thr_state = THR_AWAIT_DEATH;
-		break;
-
-	case THR_AWAIT_DEATH:
-	case THR_IDLE:
-		timeout = -1;
-		break;
-
-	default:
-		printk(KERN_DEBUG "ata%u: unknown thr state %s\n",
-		       ap->id, ata_thr_state_name(ap->thr_state));
-		break;
-	}
-
-	DPRINTK("ata%u: new thr_state %s, returning %ld\n",
-		ap->id, ata_thr_state_name(ap->thr_state), timeout);
-	return timeout;
-}
-
-/**
  *	atapi_packet_task - Write CDB bytes to hardware
  *	@_data: Port to which ATAPI device is attached.
  *
@@ -2812,21 +2889,20 @@ static void atapi_packet_task(void *_dat
 
 	/* make sure DRQ is set */
 	status = ata_chk_status(ap);
-	if ((status & ATA_DRQ) == 0)
+	if ((status & (ATA_BUSY | ATA_DRQ)) != ATA_DRQ)
 		goto err_out;
 
 	/* send SCSI cdb */
-	/* FIXME: mmio-ize */
 	DPRINTK("send cdb\n");
-	outsl(ap->ioaddr.data_addr,
-	      qc->scsicmd->cmnd, ap->host->max_cmd_len / 4);
+	assert(ap->cdb_len >= 12);
+	ata_data_xfer(ap, qc->cdb, ap->cdb_len, 1);
 
 	/* if we are DMA'ing, irq handler takes over from here */
 	if (qc->tf.protocol == ATA_PROT_ATAPI_DMA)
 		ap->ops->bmdma_start(qc);	    /* initiate bmdma */
 
 	/* non-data commands are also handled via irq */
-	else if (qc->scsicmd->sc_data_direction == SCSI_DATA_NONE) {
+	else if (qc->tf.protocol == ATA_PROT_ATAPI_NODATA) {
 		/* do nothing */
 	}
 
@@ -2862,23 +2938,6 @@ void ata_port_stop (struct ata_port *ap)
 	pci_free_consistent(pdev, ATA_PRD_TBL_SZ, ap->prd, ap->prd_dma);
 }
 
-static void ata_probe_task(void *_data)
-{
-	struct ata_port *ap = _data;
-	long timeout;
-
-	timeout = ata_thread_iter(ap);
-	if (timeout < 0)
-		return;
-
-	if (timeout > 0) {
-		set_current_state(TASK_UNINTERRUPTIBLE);
-		schedule_timeout(timeout);
-	}
-
-	schedule_task(&ap->probe_task);
-}
-
 /**
  *	ata_host_remove - Unregister SCSI host structure with upper layers
  *	@ap: Port to unregister
@@ -2931,24 +2990,20 @@ static void ata_host_init(struct ata_por
 	ap->host_set = host_set;
 	ap->port_no = port_no;
 	ap->pio_mask = ent->pio_mask;
+	ap->mwdma_mask = ent->mwdma_mask;
 	ap->udma_mask = ent->udma_mask;
 	ap->flags |= ent->host_flags;
 	ap->ops = ent->port_ops;
-	ap->thr_state = THR_PROBE_START;
 	ap->cbl = ATA_CBL_NONE;
-	ap->device[0].flags = ATA_DFLAG_MASTER;
 	ap->active_tag = ATA_TAG_POISON;
 	ap->last_ctl = 0xFF;
 
 	INIT_TQUEUE(&ap->packet_task, atapi_packet_task, ap);
 	INIT_TQUEUE(&ap->pio_task, ata_pio_task, ap);
-	INIT_TQUEUE(&ap->probe_task, ata_probe_task, ap);
 
 	for (i = 0; i < ATA_MAX_DEVICES; i++)
 		ap->device[i].devno = i;
 
-	init_MUTEX_LOCKED(&ap->probe_sem);
-
 #ifdef ATA_IRQ_TRAP
 	ap->stats.unhandled_irq = 1;
 	ap->stats.idle_irq = 1;
@@ -3027,28 +3082,35 @@ int ata_device_add(struct ata_probe_ent 
 	host_set->irq = ent->irq;
 	host_set->mmio_base = ent->mmio_base;
 	host_set->private_data = ent->private_data;
+	host_set->ops = ent->port_ops;
 
 	/* register each port bound to this device */
 	for (i = 0; i < ent->n_ports; i++) {
 		struct ata_port *ap;
+		unsigned long xfer_mode_mask;
 
 		ap = ata_host_add(ent, host_set, i);
 		if (!ap)
 			goto err_out;
 
 		host_set->ports[i] = ap;
+		xfer_mode_mask =(ap->udma_mask << ATA_SHIFT_UDMA) |
+				(ap->mwdma_mask << ATA_SHIFT_MWDMA) |
+				(ap->pio_mask << ATA_SHIFT_PIO);
 
 		/* print per-port info to dmesg */
 		printk(KERN_INFO "ata%u: %cATA max %s cmd 0x%lX ctl 0x%lX "
 				 "bmdma 0x%lX irq %lu\n",
 			ap->id,
 			ap->flags & ATA_FLAG_SATA ? 'S' : 'P',
-			ata_udma_string(ent->udma_mask),
+			ata_mode_string(xfer_mode_mask),
 	       		ap->ioaddr.cmd_addr,
 	       		ap->ioaddr.ctl_addr,
 	       		ap->ioaddr.bmdma_addr,
 	       		ent->irq);
 
+		ata_chk_status(ap);
+		host_set->ops->irq_clear(ap);
 		count++;
 	}
 
@@ -3066,16 +3128,22 @@ int ata_device_add(struct ata_probe_ent 
 	DPRINTK("probe begin\n");
 	for (i = 0; i < count; i++) {
 		struct ata_port *ap;
+		int rc;
 
 		ap = host_set->ports[i];
 
 		DPRINTK("ata%u: probe begin\n", ap->id);
-		schedule_task(&ap->probe_task);		/* start probe */
-
-		DPRINTK("ata%u: probe-wait begin\n", ap->id);
-		down(&ap->probe_sem);	/* wait for end */
+		rc = ata_bus_probe(ap);
+		DPRINTK("ata%u: probe end\n", ap->id);
 
-		DPRINTK("ata%u: probe-wait end\n", ap->id);
+		if (rc) {
+			/* FIXME: do something useful here?
+			 * Current libata behavior will
+			 * tear down everything when
+			 * the module is removed
+			 * or the h/w is unplugged.
+			 */
+		}
 	}
 
 	pci_set_drvdata(pdev, host_set);
@@ -3276,6 +3344,7 @@ int ata_pci_init_one (struct pci_dev *pd
 	probe_ent->sht = port0->sht;
 	probe_ent->host_flags = port0->host_flags;
 	probe_ent->pio_mask = port0->pio_mask;
+	probe_ent->mwdma_mask = port0->mwdma_mask;
 	probe_ent->udma_mask = port0->udma_mask;
 	probe_ent->port_ops = port0->port_ops;
 
@@ -3298,6 +3367,7 @@ int ata_pci_init_one (struct pci_dev *pd
 		probe_ent2->sht = port1->sht;
 		probe_ent2->host_flags = port1->host_flags;
 		probe_ent2->pio_mask = port1->pio_mask;
+		probe_ent2->mwdma_mask = port1->mwdma_mask;
 		probe_ent2->udma_mask = port1->udma_mask;
 		probe_ent2->port_ops = port1->port_ops;
 	} else {
@@ -3383,10 +3453,10 @@ void ata_pci_remove_one (struct pci_dev 
 	/* FIXME: handle 'rc' failure? */
 
 	free_irq(host_set->irq, host_set);
+	if (host_set->ops->host_stop)
+		host_set->ops->host_stop(host_set);
 	if (host_set->mmio_base)
 		iounmap(host_set->mmio_base);
-	if (host_set->ports[0]->ops->host_stop)
-		host_set->ports[0]->ops->host_stop(host_set);
 
 	pci_release_regions(pdev);
 
@@ -3492,7 +3562,10 @@ EXPORT_SYMBOL_GPL(pci_test_config_bits);
 EXPORT_SYMBOL_GPL(ata_std_bios_param);
 EXPORT_SYMBOL_GPL(ata_std_ports);
 EXPORT_SYMBOL_GPL(ata_device_add);
+EXPORT_SYMBOL_GPL(ata_sg_init);
+EXPORT_SYMBOL_GPL(ata_sg_init_one);
 EXPORT_SYMBOL_GPL(ata_qc_complete);
+EXPORT_SYMBOL_GPL(ata_qc_issue_prot);
 EXPORT_SYMBOL_GPL(ata_eng_timeout);
 EXPORT_SYMBOL_GPL(ata_tf_load_pio);
 EXPORT_SYMBOL_GPL(ata_tf_load_mmio);
@@ -3507,21 +3580,24 @@ EXPORT_SYMBOL_GPL(ata_exec_command_mmio)
 EXPORT_SYMBOL_GPL(ata_port_start);
 EXPORT_SYMBOL_GPL(ata_port_stop);
 EXPORT_SYMBOL_GPL(ata_interrupt);
-EXPORT_SYMBOL_GPL(ata_fill_sg);
+EXPORT_SYMBOL_GPL(ata_qc_prep);
 EXPORT_SYMBOL_GPL(ata_bmdma_setup_pio);
 EXPORT_SYMBOL_GPL(ata_bmdma_start_pio);
 EXPORT_SYMBOL_GPL(ata_bmdma_setup_mmio);
 EXPORT_SYMBOL_GPL(ata_bmdma_start_mmio);
+EXPORT_SYMBOL_GPL(ata_bmdma_irq_clear);
 EXPORT_SYMBOL_GPL(ata_port_probe);
 EXPORT_SYMBOL_GPL(sata_phy_reset);
 EXPORT_SYMBOL_GPL(ata_bus_reset);
 EXPORT_SYMBOL_GPL(ata_port_disable);
 EXPORT_SYMBOL_GPL(ata_pci_init_one);
 EXPORT_SYMBOL_GPL(ata_pci_remove_one);
+EXPORT_SYMBOL_GPL(ata_scsi_ioctl);
 EXPORT_SYMBOL_GPL(ata_scsi_queuecmd);
 EXPORT_SYMBOL_GPL(ata_scsi_error);
 EXPORT_SYMBOL_GPL(ata_scsi_detect);
 EXPORT_SYMBOL_GPL(ata_add_to_probe_list);
+EXPORT_SYMBOL_GPL(libata_msleep);
 EXPORT_SYMBOL_GPL(ata_scsi_release);
 EXPORT_SYMBOL_GPL(ata_host_intr);
 EXPORT_SYMBOL_GPL(ata_dev_id_string);
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/scsi/libata-scsi.c linux-2.4.28-pre3/drivers/scsi/libata-scsi.c
--- linux-2.4.27/drivers/scsi/libata-scsi.c	2004-08-07 23:26:05.000000000 +0000
+++ linux-2.4.28-pre3/drivers/scsi/libata-scsi.c	2004-09-10 19:32:40.000000000 +0000
@@ -31,6 +31,7 @@
 #include <scsi/scsi_host.h>
 #include "sd.h"
 #include <linux/libata.h>
+#include <asm/uaccess.h>
 
 #include "libata.h"
 
@@ -38,13 +39,15 @@ typedef unsigned int (*ata_xlat_func_t)(
 static void ata_scsi_simulate(struct ata_port *ap, struct ata_device *dev,
 			      struct scsi_cmnd *cmd,
 			      void (*done)(struct scsi_cmnd *));
+static struct ata_device *
+ata_scsi_find_dev(struct ata_port *ap, struct scsi_device *scsidev);
 
 
 /**
  *	ata_std_bios_param - generic bios head/sector/cylinder calculator used by sd.
  *	@disk: SCSI device for which BIOS geometry is to be determined
- *	@dev: device major/minor
- *	@ip: location to which geometry will be output
+ *	@bdev: device major/minor
+ *	@geom: location to which geometry will be output
  *
  *	Generic bios head/sector/cylinder calculator
  *	used by sd. Most BIOSes nowadays expect a XXX/255/16  (CHS)
@@ -58,16 +61,53 @@ static void ata_scsi_simulate(struct ata
  *	Zero.
  */
 int ata_std_bios_param(Disk * disk,	/* SCSI disk */
-		       kdev_t dev,	/* Device major, minor */
-		  int *ip /* Heads, sectors, cylinders in that order */ )
+		       kdev_t bdev,	/* Device major, minor */
+		  int *geom /* Heads, sectors, cylinders in that order */ )
 {
-	ip[0] = 255;
-	ip[1] = 63;
-	ip[2] = disk->capacity / (ip[0] * ip[1]);
+	geom[0] = 255;
+	geom[1] = 63;
+	geom[2] = disk->capacity / (geom[0] * geom[1]);
 
 	return 0;
 }
 
+int ata_scsi_ioctl(struct scsi_device *scsidev, int cmd, void __user *arg)
+{
+	struct ata_port *ap;
+	struct ata_device *dev;
+	int val = -EINVAL, rc = -EINVAL;
+
+	ap = (struct ata_port *) &scsidev->host->hostdata[0];
+	if (!ap)
+		goto out;
+
+	dev = ata_scsi_find_dev(ap, scsidev);
+	if (!dev) {
+		rc = -ENODEV;
+		goto out;
+	}
+
+	switch (cmd) {
+	case ATA_IOC_GET_IO32:
+		val = 0;
+		if (copy_to_user(arg, &val, 1))
+			return -EFAULT;
+		return 0;
+
+	case ATA_IOC_SET_IO32:
+		val = (unsigned long) arg;
+		if (val != 0)
+			return -EINVAL;
+		return 0;
+
+	default:
+		rc = -EOPNOTSUPP;
+		break;
+	}
+
+out:
+	return rc;
+}
 
 /**
  *	ata_scsi_qc_new - acquire new ata_queued_cmd reference
@@ -121,34 +161,158 @@ struct ata_queued_cmd *ata_scsi_qc_new(s
  *	ata_to_sense_error - convert ATA error to SCSI error
  *	@qc: Command that we are erroring out
  *
- *	Converts an ATA error into a SCSI error.
- *
- *	Right now, this routine is laughably primitive.  We
- *	don't even examine what ATA told us, we just look at
- *	the command data direction, and return a fatal SCSI
- *	sense error based on that.
+ *	Converts an ATA error into a SCSI error. While we are at it
+ *	we decode and dump the ATA error for the user so that they
+ *	have some idea what really happened at the non make-believe
+ *	layer.
  *
  *	LOCKING:
  *	spin_lock_irqsave(host_set lock)
  */
 
-void ata_to_sense_error(struct ata_queued_cmd *qc)
+void ata_to_sense_error(struct ata_queued_cmd *qc, u8 drv_stat)
 {
 	struct scsi_cmnd *cmd = qc->scsicmd;
+	u8 err = 0;
+	unsigned char *sb = cmd->sense_buffer;
+	/* Based on the 3ware driver translation table */
+	static unsigned char sense_table[][4] = {
+		/* BBD|ECC|ID|MAR */
+		{0xd1, 		ABORTED_COMMAND, 0x00, 0x00}, 	// Device busy                  Aborted command
+		/* BBD|ECC|ID */
+		{0xd0,  	ABORTED_COMMAND, 0x00, 0x00}, 	// Device busy                  Aborted command
+		/* ECC|MC|MARK */
+		{0x61, 		HARDWARE_ERROR, 0x00, 0x00}, 	// Device fault                 Hardware error
+		/* ICRC|ABRT */		/* NB: ICRC & !ABRT is BBD */
+		{0x84, 		ABORTED_COMMAND, 0x47, 0x00}, 	// Data CRC error               SCSI parity error
+		/* MC|ID|ABRT|TRK0|MARK */
+		{0x37, 		NOT_READY, 0x04, 0x00}, 	// Unit offline                 Not ready
+		/* MCR|MARK */
+		{0x09, 		NOT_READY, 0x04, 0x00}, 	// Unrecovered disk error       Not ready
+		/*  Bad address mark */
+		{0x01, 		MEDIUM_ERROR, 0x13, 0x00}, 	// Address mark not found       Address mark not found for data field
+		/* TRK0 */
+		{0x02, 		HARDWARE_ERROR, 0x00, 0x00}, 	// Track 0 not found		  Hardware error
+		/* Abort & !ICRC */
+		{0x04, 		ABORTED_COMMAND, 0x00, 0x00}, 	// Aborted command              Aborted command
+		/* Media change request */
+		{0x08, 		NOT_READY, 0x04, 0x00}, 	// Media change request	  FIXME: faking offline
+		/* SRV */
+		{0x10, 		ABORTED_COMMAND, 0x14, 0x00}, 	// ID not found                 Recorded entity not found
+		/* Media change */
+		{0x08,  	NOT_READY, 0x04, 0x00}, 	// Media change		  FIXME: faking offline
+		/* ECC */
+		{0x40, 		MEDIUM_ERROR, 0x11, 0x04}, 	// Uncorrectable ECC error      Unrecovered read error
+		/* BBD - block marked bad */
+		{0x80, 		MEDIUM_ERROR, 0x11, 0x04}, 	// Block marked bad		  Medium error, unrecovered read error
+		{0xFF, 0xFF, 0xFF, 0xFF}, // END mark 
+	};
+	static unsigned char stat_table[][4] = {
+		/* Must be first because BUSY means no other bits valid */
+		{0x80, 		ABORTED_COMMAND, 0x47, 0x00},	// Busy, fake parity for now
+		{0x20, 		HARDWARE_ERROR,  0x00, 0x00}, 	// Device fault
+		{0x08, 		ABORTED_COMMAND, 0x47, 0x00},	// Timed out in xfer, fake parity for now
+		{0x04, 		RECOVERED_ERROR, 0x11, 0x00},	// Recovered ECC error	  Medium error, recovered
+		{0xFF, 0xFF, 0xFF, 0xFF}, // END mark 
+	};
+	int i = 0;
 
 	cmd->result = SAM_STAT_CHECK_CONDITION;
-
-	cmd->sense_buffer[0] = 0x70;
-	cmd->sense_buffer[2] = MEDIUM_ERROR;
-	cmd->sense_buffer[7] = 14 - 8;	/* addnl. sense len. FIXME: correct? */
-
+	
+	/*
+	 *	Is this an error we can process/parse
+	 */
+	 
+	if(drv_stat & ATA_ERR)
+		/* Read the err bits */
+		err = ata_chk_err(qc->ap);
+
+	/* Display the ATA level error info */
+	
+	printk(KERN_WARNING "ata%u: status=0x%02x { ", qc->ap->id, drv_stat);
+	if(drv_stat & 0x80)
+	{
+		printk("Busy ");
+		err = 0;	/* Data is not valid in this case */
+	}
+	else {
+		if(drv_stat & 0x40)	printk("DriveReady ");
+		if(drv_stat & 0x20)	printk("DeviceFault ");
+		if(drv_stat & 0x10)	printk("SeekComplete ");
+		if(drv_stat & 0x08)	printk("DataRequest ");
+		if(drv_stat & 0x04)	printk("CorrectedError ");
+		if(drv_stat & 0x02)	printk("Index ");
+		if(drv_stat & 0x01)	printk("Error ");
+	}
+	printk("}\n");
+	
+	if(err)
+	{
+		printk(KERN_WARNING "ata%u: error=0x%02x { ", qc->ap->id, err);
+		if(err & 0x04)		printk("DriveStatusError ");
+		if(err & 0x80)
+		{
+			if(err & 0x04)
+				printk("BadCRC ");
+			else
+				printk("Sector ");
+		}
+		if(err & 0x40)		printk("UncorrectableError ");
+		if(err & 0x10)		printk("SectorIdNotFound ");
+		if(err & 0x02)		printk("TrackZeroNotFound ");
+		if(err & 0x01)		printk("AddrMarkNotFound ");
+		printk("}\n");
+		
+		/* Should we dump sector info here too ?? */
+	}
+		
+	
+	/* Look for err */
+	while(sense_table[i][0] != 0xFF)
+	{
+		/* Look for best matches first */
+		if((sense_table[i][0] & err) == sense_table[i][0])
+		{
+			sb[0] = 0x70;
+			sb[2] = sense_table[i][1];
+			sb[7] = 0x0a;
+			sb[12] = sense_table[i][2];
+			sb[13] = sense_table[i][3];
+			return;
+		}
+		i++;
+	}
+	/* No immediate match */
+	if(err)
+		printk(KERN_DEBUG "ata%u: no sense translation for 0x%02x\n", qc->ap->id, err);
+	
+	/* Fall back to interpreting status bits */
+	while(stat_table[i][0] != 0xFF)
+	{
+		if(stat_table[i][0] & drv_stat)
+		{
+			sb[0] = 0x70;
+			sb[2] = stat_table[i][1];
+			sb[7] = 0x0a;
+			sb[12] = stat_table[i][2];
+			sb[13] = stat_table[i][3];
+			return;
+		}
+		i++;
+	}
+	/* No error ?? */
+	printk(KERN_ERR "ata%u: called with no error (%02X)!\n", qc->ap->id, drv_stat);
 	/* additional-sense-code[-qualifier] */
+	
+	sb[0] = 0x70;
+	sb[2] = MEDIUM_ERROR;
+	sb[7] = 0x0A;
 	if (cmd->sc_data_direction == SCSI_DATA_READ) {
-		cmd->sense_buffer[12] = 0x11; /* "unrecovered read error" */
-		cmd->sense_buffer[13] = 0x04;
+		sb[12] = 0x11; /* "unrecovered read error" */
+		sb[13] = 0x04;
 	} else {
-		cmd->sense_buffer[12] = 0x0C; /* "write error -             */
-		cmd->sense_buffer[13] = 0x02; /*  auto-reallocation failed" */
+		sb[12] = 0x0C; /* "write error -             */
+		sb[13] = 0x02; /*  auto-reallocation failed" */
 	}
 }
 
@@ -174,11 +338,137 @@ int ata_scsi_error(struct Scsi_Host *hos
 	ap = (struct ata_port *) &host->hostdata[0];
 	ap->ops->eng_timeout(ap);
 
+	host->in_recovery = 0;
+
+	/* TODO: this is per-command; when queueing is supported
+	 * this code will either change or move to a more
+	 * appropriate place
+	 */
+	host->host_failed--;
+
 	DPRINTK("EXIT\n");
 	return 0;
 }
 
 /**
+ *	ata_scsi_flush_xlat - Translate SCSI SYNCHRONIZE CACHE command
+ *	@qc: Storage for translated ATA taskfile
+ *	@scsicmd: SCSI command to translate (ignored)
+ *
+ *	Sets up an ATA taskfile to issue FLUSH CACHE or
+ *	FLUSH CACHE EXT.
+ *
+ *	LOCKING:
+ *	spin_lock_irqsave(host_set lock)
+ *
+ *	RETURNS:
+ *	Zero on success, non-zero on error.
+ */
+
+static unsigned int ata_scsi_flush_xlat(struct ata_queued_cmd *qc, u8 *scsicmd)
+{
+	struct ata_taskfile *tf = &qc->tf;
+
+	tf->flags |= ATA_TFLAG_DEVICE;
+	tf->protocol = ATA_PROT_NODATA;
+
+	if ((tf->flags & ATA_TFLAG_LBA48) &&
+	    (ata_id_has_flush_ext(qc->dev)))
+		tf->command = ATA_CMD_FLUSH_EXT;
+	else
+		tf->command = ATA_CMD_FLUSH;
+
+	return 0;
+}
+
+/**
+ *	ata_scsi_verify_xlat - Translate SCSI VERIFY command into an ATA one
+ *	@qc: Storage for translated ATA taskfile
+ *	@scsicmd: SCSI command to translate
+ *
+ *	Converts SCSI VERIFY command to an ATA READ VERIFY command.
+ *
+ *	LOCKING:
+ *	spin_lock_irqsave(host_set lock)
+ *
+ *	RETURNS:
+ *	Zero on success, non-zero on error.
+ */
+
+static unsigned int ata_scsi_verify_xlat(struct ata_queued_cmd *qc, u8 *scsicmd)
+{
+	struct ata_taskfile *tf = &qc->tf;
+	unsigned int lba48 = tf->flags & ATA_TFLAG_LBA48;
+	u64 dev_sectors = qc->dev->n_sectors;
+	u64 sect = 0;
+	u32 n_sect = 0;
+
+	tf->flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
+	tf->protocol = ATA_PROT_NODATA;
+	tf->device |= ATA_LBA;
+
+	if (scsicmd[0] == VERIFY) {
+		sect |= ((u64)scsicmd[2]) << 24;
+		sect |= ((u64)scsicmd[3]) << 16;
+		sect |= ((u64)scsicmd[4]) << 8;
+		sect |= ((u64)scsicmd[5]);
+
+		n_sect |= ((u32)scsicmd[7]) << 8;
+		n_sect |= ((u32)scsicmd[8]);
+	}
+
+	else if (scsicmd[0] == VERIFY_16) {
+		sect |= ((u64)scsicmd[2]) << 56;
+		sect |= ((u64)scsicmd[3]) << 48;
+		sect |= ((u64)scsicmd[4]) << 40;
+		sect |= ((u64)scsicmd[5]) << 32;
+		sect |= ((u64)scsicmd[6]) << 24;
+		sect |= ((u64)scsicmd[7]) << 16;
+		sect |= ((u64)scsicmd[8]) << 8;
+		sect |= ((u64)scsicmd[9]);
+
+		n_sect |= ((u32)scsicmd[10]) << 24;
+		n_sect |= ((u32)scsicmd[11]) << 16;
+		n_sect |= ((u32)scsicmd[12]) << 8;
+		n_sect |= ((u32)scsicmd[13]);
+	}
+
+	else
+		return 1;
+
+	if (!n_sect)
+		return 1;
+	if (sect >= dev_sectors)
+		return 1;
+	if ((sect + n_sect) > dev_sectors)
+		return 1;
+	if (lba48) {
+		if (n_sect > (64 * 1024))
+			return 1;
+	} else {
+		if (n_sect > 256)
+			return 1;
+	}
+
+	if (lba48) {
+		tf->hob_nsect = (n_sect >> 8) & 0xff;
+
+		tf->hob_lbah = (sect >> 40) & 0xff;
+		tf->hob_lbam = (sect >> 32) & 0xff;
+		tf->hob_lbal = (sect >> 24) & 0xff;
+	} else
+		tf->device |= (sect >> 24) & 0xf;
+
+	tf->nsect = n_sect & 0xff;
+
+	tf->hob_lbah = (sect >> 16) & 0xff;
+	tf->hob_lbam = (sect >> 8) & 0xff;
+	tf->hob_lbal = sect & 0xff;
+
+	return 0;
+}
+
+/**
  *	ata_scsi_rw_xlat - Translate SCSI r/w command into an ATA one
  *	@qc: Storage for translated ATA taskfile
  *	@scsicmd: SCSI command to translate
@@ -204,10 +494,6 @@ static unsigned int ata_scsi_rw_xlat(str
 	unsigned int lba48 = tf->flags & ATA_TFLAG_LBA48;
 
 	tf->flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
-	tf->hob_nsect = 0;
-	tf->hob_lbal = 0;
-	tf->hob_lbam = 0;
-	tf->hob_lbah = 0;
 	tf->protocol = qc->dev->xfer_protocol;
 	tf->device |= ATA_LBA;
 
@@ -295,6 +581,20 @@ static unsigned int ata_scsi_rw_xlat(str
 	return 1;
 }
 
+static int ata_scsi_qc_complete(struct ata_queued_cmd *qc, u8 drv_stat)
+{
+	struct scsi_cmnd *cmd = qc->scsicmd;
+
+	if (unlikely(drv_stat & (ATA_ERR | ATA_BUSY | ATA_DRQ)))
+		ata_to_sense_error(qc, drv_stat);
+	else
+		cmd->result = SAM_STAT_GOOD;
+
+	qc->scsidone(cmd);
+
+	return 0;
+}
+
 /**
  *	ata_scsi_translate - Translate then issue SCSI command to ATA device
  *	@ap: ATA port to which the command is addressed
@@ -328,6 +628,7 @@ static void ata_scsi_translate(struct at
 	if (!qc)
 		return;
 
+	/* data is present; dma-map it */
 	if (cmd->sc_data_direction == SCSI_DATA_READ ||
 	    cmd->sc_data_direction == SCSI_DATA_WRITE) {
 		if (unlikely(cmd->request_bufflen < 1)) {
@@ -336,9 +637,17 @@ static void ata_scsi_translate(struct at
 			goto err_out;
 		}
 
-		qc->flags |= ATA_QCFLAG_SG; /* data is present; dma-map it */
+		if (cmd->use_sg)
+			ata_sg_init(qc, cmd->request_buffer, cmd->use_sg);
+		else
+			ata_sg_init_one(qc, cmd->request_buffer,
+					cmd->request_bufflen);
+
+		qc->pci_dma_dir = scsi_to_pci_dma_dir(cmd->sc_data_direction);
 	}
 
+	qc->complete_fn = ata_scsi_qc_complete;
+
 	if (xlat_func(qc, scsicmd))
 		goto err_out;
 
@@ -467,7 +776,7 @@ unsigned int ata_scsiop_inq_std(struct a
 		0,
 		0x5,	/* claim SPC-3 version compatibility */
 		2,
-		96 - 4
+		95 - 4
 	};
 
 	/* set scsi removeable (RMB) bit per ata bit */
@@ -478,7 +787,7 @@ unsigned int ata_scsiop_inq_std(struct a
 
 	memcpy(rbuf, hdr, sizeof(hdr));
 
-	if (buflen > 36) {
+	if (buflen > 35) {
 		memcpy(&rbuf[8], "ATA     ", 8);
 		ata_dev_id_string(dev, &rbuf[16], ATA_ID_PROD_OFS, 16);
 		ata_dev_id_string(dev, &rbuf[32], ATA_ID_FW_REV_OFS, 4);
@@ -897,6 +1206,31 @@ void ata_scsi_badcmd(struct scsi_cmnd *c
 	done(cmd);
 }
 
+static int atapi_qc_complete(struct ata_queued_cmd *qc, u8 drv_stat)
+{
+	struct scsi_cmnd *cmd = qc->scsicmd;
+
+	if (unlikely(drv_stat & (ATA_ERR | ATA_BUSY | ATA_DRQ)))
+		cmd->result = SAM_STAT_CHECK_CONDITION;
+	else {
+		u8 *scsicmd = cmd->cmnd;
+
+		if (scsicmd[0] == INQUIRY) {
+			u8 *buf = NULL;
+			unsigned int buflen;
+
+			buflen = ata_scsi_rbuf_get(cmd, &buf);
+			buf[2] = 0x5;
+			buf[3] = (buf[3] & 0xf0) | 2;
+			ata_scsi_rbuf_put(cmd);
+		}
+		cmd->result = SAM_STAT_GOOD;
+	}
+
+	qc->scsidone(cmd);
+
+	return 0;
+}
 /**
  *	atapi_xlat - Initialize PACKET taskfile
  *	@qc: command structure to be initialized
@@ -912,6 +1246,13 @@ void ata_scsi_badcmd(struct scsi_cmnd *c
 static unsigned int atapi_xlat(struct ata_queued_cmd *qc, u8 *scsicmd)
 {
 	struct scsi_cmnd *cmd = qc->scsicmd;
+	struct ata_device *dev = qc->dev;
+	int using_pio = (dev->flags & ATA_DFLAG_PIO);
+	int nodata = (cmd->sc_data_direction == SCSI_DATA_NONE);
+
+	memcpy(&qc->cdb, scsicmd, qc->ap->cdb_len);
+
+	qc->complete_fn = atapi_qc_complete;
 
 	qc->tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
 	if (cmd->sc_data_direction == SCSI_DATA_WRITE) {
@@ -921,19 +1262,18 @@ static unsigned int atapi_xlat(struct at
 
 	qc->tf.command = ATA_CMD_PACKET;
 
-	/* no data - interrupt-driven */
-	if (cmd->sc_data_direction == SCSI_DATA_NONE)
-		qc->tf.protocol = ATA_PROT_ATAPI;
-
-	/* PIO data xfer - polling */
-	else if ((qc->flags & ATA_QCFLAG_DMA) == 0) {
-		ata_qc_set_polling(qc);
-		qc->tf.protocol = ATA_PROT_ATAPI;
+	/* no data, or PIO data xfer */
+	if (using_pio || nodata) {
+		if (nodata)
+			qc->tf.protocol = ATA_PROT_ATAPI_NODATA;
+		else
+			qc->tf.protocol = ATA_PROT_ATAPI;
 		qc->tf.lbam = (8 * 1024) & 0xff;
 		qc->tf.lbah = (8 * 1024) >> 8;
+	}
 
-	/* DMA data xfer - interrupt-driven */
-	} else {
+	/* DMA data xfer */
+	else {
 		qc->tf.protocol = ATA_PROT_ATAPI_DMA;
 		qc->tf.feature |= ATAPI_PKT_DMA;
 
@@ -964,19 +1304,19 @@ static unsigned int atapi_xlat(struct at
  *	Associated ATA device, or %NULL if not found.
  */
 
-static inline struct ata_device *
-ata_scsi_find_dev(struct ata_port *ap, struct scsi_cmnd *cmd)
+static struct ata_device *
+ata_scsi_find_dev(struct ata_port *ap, struct scsi_device *scsidev)
 {
 	struct ata_device *dev;
 
 	/* skip commands not addressed to targets we simulate */
-	if (likely(cmd->target < ATA_MAX_DEVICES))
-		dev = &ap->device[cmd->target];
+	if (likely(scsidev->id < ATA_MAX_DEVICES))
+		dev = &ap->device[scsidev->id];
 	else
 		return NULL;
 
-	if (unlikely((cmd->channel != 0) ||
-		     (cmd->lun != 0)))
+	if (unlikely((scsidev->channel != 0) ||
+		     (scsidev->lun != 0)))
 		return NULL;
 
 	if (unlikely(!ata_dev_present(dev)))
@@ -992,6 +1332,7 @@ ata_scsi_find_dev(struct ata_port *ap, s
 
 /**
  *	ata_get_xlat_func - check if SCSI to ATA translation is possible
+ *	@dev: ATA device
  *	@cmd: SCSI command opcode to consider
  *
  *	Look up the SCSI command given, and determine whether the
@@ -1001,7 +1342,7 @@ ata_scsi_find_dev(struct ata_port *ap, s
  *	Pointer to translation function if possible, %NULL if not.
  */
 
-static inline ata_xlat_func_t ata_get_xlat_func(u8 cmd)
+static inline ata_xlat_func_t ata_get_xlat_func(struct ata_device *dev, u8 cmd)
 {
 	switch (cmd) {
 	case READ_6:
@@ -1012,6 +1353,15 @@ static inline ata_xlat_func_t ata_get_xl
 	case WRITE_10:
 	case WRITE_16:
 		return ata_scsi_rw_xlat;
+
+	case SYNCHRONIZE_CACHE:
+		if (ata_try_flush_cache(dev))
+			return ata_scsi_flush_xlat;
+		break;
+
+	case VERIFY:
+	case VERIFY_16:
+		return ata_scsi_verify_xlat;
 	}
 
 	return NULL;
@@ -1029,11 +1379,12 @@ static inline void ata_scsi_dump_cdb(str
 				     struct scsi_cmnd *cmd)
 {
 #ifdef ATA_DEBUG
+	struct scsi_device *scsidev = cmd->device;
 	u8 *scsicmd = cmd->cmnd;
 
 	DPRINTK("CDB (%u:%d,%d,%d) %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
 		ap->id,
-		cmd->channel, cmd->target, cmd->lun,
+		scsidev->channel, scsidev->id, scsidev->lun,
 		scsicmd[0], scsicmd[1], scsicmd[2], scsicmd[3],
 		scsicmd[4], scsicmd[5], scsicmd[6], scsicmd[7],
 		scsicmd[8]);
@@ -1063,17 +1414,18 @@ int ata_scsi_queuecmd(struct scsi_cmnd *
 {
 	struct ata_port *ap;
 	struct ata_device *dev;
+	struct scsi_device *scsidev = cmd->device;
 
 	/* Note: spin_lock_irqsave is held by caller... */
 	spin_unlock(&io_request_lock);
 
-	ap = (struct ata_port *) &cmd->host->hostdata[0];
+	ap = (struct ata_port *) &scsidev->host->hostdata[0];
 
 	spin_lock(&ap->host_set->lock);
 
 	ata_scsi_dump_cdb(ap, cmd);
 
-	dev = ata_scsi_find_dev(ap, cmd);
+	dev = ata_scsi_find_dev(ap, scsidev);
 	if (unlikely(!dev)) {
 		cmd->result = (DID_BAD_TARGET << 16);
 		done(cmd);
@@ -1081,7 +1433,8 @@ int ata_scsi_queuecmd(struct scsi_cmnd *
 	}
 
 	if (dev->class == ATA_DEV_ATA) {
-		ata_xlat_func_t xlat_func = ata_get_xlat_func(cmd->cmnd[0]);
+		ata_xlat_func_t xlat_func = ata_get_xlat_func(dev,
+							      cmd->cmnd[0]);
 
 		if (xlat_func)
 			ata_scsi_translate(ap, dev, cmd, done, xlat_func);
@@ -1124,7 +1477,7 @@ static void ata_scsi_simulate(struct ata
 
 	switch(scsicmd[0]) {
 		/* no-op's, complete with success */
-		case SYNCHRONIZE_CACHE:		/* FIXME: temporary */
+		case SYNCHRONIZE_CACHE:
 		case REZERO_UNIT:
 		case SEEK_6:
 		case SEEK_10:
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/scsi/libata.h linux-2.4.28-pre3/drivers/scsi/libata.h
--- linux-2.4.27/drivers/scsi/libata.h	2004-08-07 23:26:05.000000000 +0000
+++ linux-2.4.28-pre3/drivers/scsi/libata.h	2004-09-10 19:33:19.000000000 +0000
@@ -35,7 +35,6 @@ struct ata_scsi_args {
 	void			(*done)(struct scsi_cmnd *);
 };
 
-
 /* libata-core.c */
 extern struct ata_queued_cmd *ata_qc_new_init(struct ata_port *ap,
 				      struct ata_device *dev);
@@ -43,10 +42,11 @@ extern int ata_qc_issue(struct ata_queue
 extern void ata_dev_select(struct ata_port *ap, unsigned int device,
                            unsigned int wait, unsigned int can_sleep);
 extern void ata_tf_to_host_nolock(struct ata_port *ap, struct ata_taskfile *tf);
+extern void swap_buf_le16(u16 *buf, unsigned int buf_words);
 
 
 /* libata-scsi.c */
-extern void ata_to_sense_error(struct ata_queued_cmd *qc);
+extern void ata_to_sense_error(struct ata_queued_cmd *qc, u8 drv_stat);
 extern int ata_scsi_error(struct Scsi_Host *host);
 extern unsigned int ata_scsiop_inq_std(struct ata_scsi_args *args, u8 *rbuf,
 			       unsigned int buflen);
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/scsi/megaraid.c linux-2.4.28-pre3/drivers/scsi/megaraid.c
--- linux-2.4.27/drivers/scsi/megaraid.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.28-pre3/drivers/scsi/megaraid.c	2004-09-10 19:31:51.000000000 +0000
@@ -3471,6 +3471,24 @@ int megaraid_detect (Scsi_Host_Template 
 	return count;
 }
 
+static inline void mega_freeSgList (mega_host_config * megaCfg)
+{
+	int i;
+
+	for (i = 0; i < megaCfg->max_cmds; i++) {
+		if (megaCfg->scbList[i].sgList)
+			pci_free_consistent (megaCfg->dev,
+					     sizeof (mega_64sglist) *
+					     MAX_SGLIST,
+					     megaCfg->scbList[i].sgList,
+					     megaCfg->scbList[i].
+					     dma_sghandle64);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)	/* 0x020400 */
+			kfree (megaCfg->scbList[i].sgList);	/* free sgList */
+#endif
+	}
+}
+
 /*---------------------------------------------------------------------
  * Release the controller's resources
  *---------------------------------------------------------------------*/
@@ -3880,24 +3898,6 @@ static void mega_swap_hosts (struct Scsi
 	return;
 }
 
-static inline void mega_freeSgList (mega_host_config * megaCfg)
-{
-	int i;
-
-	for (i = 0; i < megaCfg->max_cmds; i++) {
-		if (megaCfg->scbList[i].sgList)
-			pci_free_consistent (megaCfg->dev,
-					     sizeof (mega_64sglist) *
-					     MAX_SGLIST,
-					     megaCfg->scbList[i].sgList,
-					     megaCfg->scbList[i].
-					     dma_sghandle64);
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)	/* 0x020400 */
-			kfree (megaCfg->scbList[i].sgList);	/* free sgList */
-#endif
-	}
-}
-
 /*----------------------------------------------
  * Get information about the card/driver
  *----------------------------------------------*/
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/scsi/megaraid2.c linux-2.4.28-pre3/drivers/scsi/megaraid2.c
--- linux-2.4.27/drivers/scsi/megaraid2.c	2004-08-07 23:26:05.000000000 +0000
+++ linux-2.4.28-pre3/drivers/scsi/megaraid2.c	2004-09-10 19:33:15.000000000 +0000
@@ -936,6 +936,19 @@ mega_query_adapter(adapter_t *adapter)
 }
 
 
+/**
+ * mega_runpendq()
+ * @adapter - pointer to our soft state
+ *
+ * Runs through the list of pending requests.
+ */
+static inline void
+mega_runpendq(adapter_t *adapter)
+{
+	if(!list_empty(&adapter->pending_list))
+		__mega_runpendq(adapter);
+}
+
 /*
  * megaraid_queue()
  * @scmd - Issue this scsi command
@@ -986,6 +999,98 @@ megaraid_queue(Scsi_Cmnd *scmd, void (*d
 
 
 /**
+ * mega_allocate_scb()
+ * @adapter - pointer to our soft state
+ * @cmd - scsi command from the mid-layer
+ *
+ * Allocate a SCB structure. This is the central structure for controller
+ * commands.
+ */
+static inline scb_t *
+mega_allocate_scb(adapter_t *adapter, Scsi_Cmnd *cmd)
+{
+	struct list_head *head = &adapter->free_list;
+	scb_t	*scb;
+
+	/* Unlink command from Free List */
+	if( !list_empty(head) ) {
+
+		scb = list_entry(head->next, scb_t, list);
+
+		list_del_init(head->next);
+
+		scb->state = SCB_ACTIVE;
+		scb->cmd = cmd;
+		scb->dma_type = MEGA_DMA_TYPE_NONE;
+
+		return scb;
+	}
+
+	return NULL;
+}
+
+
+/**
+ * mega_get_ldrv_num()
+ * @adapter - pointer to our soft state
+ * @cmd - scsi mid layer command
+ * @channel - channel on the controller
+ *
+ * Calculate the logical drive number based on the information in scsi command
+ * and the channel number.
+ */
+static inline int
+mega_get_ldrv_num(adapter_t *adapter, Scsi_Cmnd *cmd, int channel)
+{
+	int		tgt;
+	int		ldrv_num;
+
+	tgt = cmd->target;
+
+	if ( tgt > adapter->this_id )
+		tgt--;	/* we do not get inquires for initiator id */
+
+	ldrv_num = (channel * 15) + tgt;
+
+
+	/*
+	 * If we have a logical drive with boot enabled, project it first
+	 */
+	if( adapter->boot_ldrv_enabled ) {
+		if( ldrv_num == 0 ) {
+			ldrv_num = adapter->boot_ldrv;
+		}
+		else {
+			if( ldrv_num <= adapter->boot_ldrv ) {
+				ldrv_num--;
+			}
+		}
+	}
+
+	/*
+	 * If "delete logical drive" feature is enabled on this controller.
+	 * Do only if at least one delete logical drive operation was done.
+	 *
+	 * Also, after logical drive deletion, instead of logical drive number,
+	 * the value returned should be 0x80+logical drive id.
+	 *
+	 * These is valid only for IO commands.
+	 */
+
+	if (adapter->support_random_del && adapter->read_ldidmap )
+		switch (cmd->cmnd[0]) {
+		case READ_6:	/* fall through */
+		case WRITE_6:	/* fall through */
+		case READ_10:	/* fall through */
+		case WRITE_10:
+			ldrv_num += 0x80;
+		}
+
+	return ldrv_num;
+}
+
+
+/**
  * mega_build_cmd()
  * @adapter - pointer to our soft state
  * @cmd - Prepare using this scsi command
@@ -1566,51 +1671,6 @@ mega_prepare_extpassthru(adapter_t *adap
 }
 
 
-/**
- * mega_allocate_scb()
- * @adapter - pointer to our soft state
- * @cmd - scsi command from the mid-layer
- *
- * Allocate a SCB structure. This is the central structure for controller
- * commands.
- */
-static inline scb_t *
-mega_allocate_scb(adapter_t *adapter, Scsi_Cmnd *cmd)
-{
-	struct list_head *head = &adapter->free_list;
-	scb_t	*scb;
-
-	/* Unlink command from Free List */
-	if( !list_empty(head) ) {
-
-		scb = list_entry(head->next, scb_t, list);
-
-		list_del_init(head->next);
-
-		scb->state = SCB_ACTIVE;
-		scb->cmd = cmd;
-		scb->dma_type = MEGA_DMA_TYPE_NONE;
-
-		return scb;
-	}
-
-	return NULL;
-}
-
-
-/**
- * mega_runpendq()
- * @adapter - pointer to our soft state
- *
- * Runs through the list of pending requests.
- */
-static inline void
-mega_runpendq(adapter_t *adapter)
-{
-	if(!list_empty(&adapter->pending_list))
-		__mega_runpendq(adapter);
-}
-
 static void
 __mega_runpendq(adapter_t *adapter)
 {
@@ -1642,7 +1702,7 @@ __mega_runpendq(adapter_t *adapter)
  * busy. We also take the scb from the pending list if the mailbox is
  * available.
  */
-static inline int
+static int
 issue_scb(adapter_t *adapter, scb_t *scb)
 {
 	volatile mbox64_t	*mbox64 = adapter->mbox64;
@@ -1705,6 +1765,17 @@ issue_scb(adapter_t *adapter, scb_t *scb
 }
 
 
+/*
+ * Wait until the controller's mailbox is available
+ */
+static inline int
+mega_busywait_mbox (adapter_t *adapter)
+{
+	if (adapter->mbox->busy)
+		return __mega_busywait_mbox(adapter);
+	return 0;
+}
+
 /**
  * issue_scb_block()
  * @adapter - pointer to our soft state
@@ -1807,38 +1878,6 @@ bug_blocked_mailbox:
 
 
 /**
- * megaraid_isr_iomapped()
- * @irq - irq
- * @devp - pointer to our soft state
- * @regs - unused
- *
- * Interrupt service routine for io-mapped controllers.
- * Find out if our device is interrupting. If yes, acknowledge the interrupt
- * and service the completed commands.
- */
-static void
-megaraid_isr_iomapped(int irq, void *devp, struct pt_regs *regs)
-{
-	adapter_t	*adapter = devp;
-	unsigned long	flags;
-
-
-	spin_lock_irqsave(adapter->host_lock, flags);
-
-	megaraid_iombox_ack_sequence(adapter);
-
-	/* Loop through any pending requests */
-	if( atomic_read(&adapter->quiescent ) == 0) {
-		mega_runpendq(adapter);
-	}
-
-	spin_unlock_irqrestore(adapter->host_lock, flags);
-
-	return;
-}
-
-
-/**
  * megaraid_iombox_ack_sequence - interrupt ack sequence for IO mapped HBAs
  * @adapter	- controller's soft state
  *
@@ -1901,38 +1940,6 @@ megaraid_iombox_ack_sequence(adapter_t *
 
 
 /**
- * megaraid_isr_memmapped()
- * @irq - irq
- * @devp - pointer to our soft state
- * @regs - unused
- *
- * Interrupt service routine for memory-mapped controllers.
- * Find out if our device is interrupting. If yes, acknowledge the interrupt
- * and service the completed commands.
- */
-static void
-megaraid_isr_memmapped(int irq, void *devp, struct pt_regs *regs)
-{
-	adapter_t	*adapter = devp;
-	unsigned long	flags;
-
-
-	spin_lock_irqsave(adapter->host_lock, flags);
-
-	megaraid_memmbox_ack_sequence(adapter);
-
-	/* Loop through any pending requests */
-	if(atomic_read(&adapter->quiescent) == 0) {
-		mega_runpendq(adapter);
-	}
-
-	spin_unlock_irqrestore(adapter->host_lock, flags);
-
-	return;
-}
-
-
-/**
  * megaraid_memmbox_ack_sequence - interrupt ack sequence for memory mapped HBAs
  * @adapter	- controller's soft state
  *
@@ -2000,6 +2007,70 @@ megaraid_memmbox_ack_sequence(adapter_t 
 
 
 /**
+ * megaraid_isr_iomapped()
+ * @irq - irq
+ * @devp - pointer to our soft state
+ * @regs - unused
+ *
+ * Interrupt service routine for io-mapped controllers.
+ * Find out if our device is interrupting. If yes, acknowledge the interrupt
+ * and service the completed commands.
+ */
+static void
+megaraid_isr_iomapped(int irq, void *devp, struct pt_regs *regs)
+{
+	adapter_t	*adapter = devp;
+	unsigned long	flags;
+
+
+	spin_lock_irqsave(adapter->host_lock, flags);
+
+	megaraid_iombox_ack_sequence(adapter);
+
+	/* Loop through any pending requests */
+	if( atomic_read(&adapter->quiescent ) == 0) {
+		mega_runpendq(adapter);
+	}
+
+	spin_unlock_irqrestore(adapter->host_lock, flags);
+
+	return;
+}
+
+
+/**
+ * megaraid_isr_memmapped()
+ * @irq - irq
+ * @devp - pointer to our soft state
+ * @regs - unused
+ *
+ * Interrupt service routine for memory-mapped controllers.
+ * Find out if our device is interrupting. If yes, acknowledge the interrupt
+ * and service the completed commands.
+ */
+static void
+megaraid_isr_memmapped(int irq, void *devp, struct pt_regs *regs)
+{
+	adapter_t	*adapter = devp;
+	unsigned long	flags;
+
+
+	spin_lock_irqsave(adapter->host_lock, flags);
+
+	megaraid_memmbox_ack_sequence(adapter);
+
+	/* Loop through any pending requests */
+	if(atomic_read(&adapter->quiescent) == 0) {
+		mega_runpendq(adapter);
+	}
+
+	spin_unlock_irqrestore(adapter->host_lock, flags);
+
+	return;
+}
+
+
+/**
  * mega_cmd_done()
  * @adapter - pointer to our soft state
  * @completed - array of ids of completed commands
@@ -2008,7 +2079,7 @@ megaraid_memmbox_ack_sequence(adapter_t 
  *
  * Complete the comamnds and call the scsi mid-layer callback hooks.
  */
-static inline void
+static void
 mega_cmd_done(adapter_t *adapter, u8 completed[], int nstatus, int status)
 {
 	mega_ext_passthru	*epthru = NULL;
@@ -2311,17 +2382,6 @@ mega_free_scb(adapter_t *adapter, scb_t 
 }
 
 
-/*
- * Wait until the controller's mailbox is available
- */
-static inline int
-mega_busywait_mbox (adapter_t *adapter)
-{
-	if (adapter->mbox->busy)
-		return __mega_busywait_mbox(adapter);
-	return 0;
-}
-
 static int
 __mega_busywait_mbox (adapter_t *adapter)
 {
@@ -2476,6 +2536,44 @@ mega_8_to_40ld(mraid_inquiry *inquiry, m
 }
 
 
+static inline void
+mega_free_sgl(adapter_t *adapter)
+{
+	scb_t	*scb;
+	int	i;
+
+	for(i = 0; i < adapter->max_cmds; i++) {
+
+		scb = &adapter->scb_list[i];
+
+		if( scb->sgl64 ) {
+			pci_free_consistent(adapter->dev,
+				sizeof(mega_sgl64) * adapter->sglen,
+				scb->sgl64,
+				scb->sgl_dma_addr);
+
+			scb->sgl64 = NULL;
+		}
+
+		if( scb->pthru ) {
+			pci_free_consistent(adapter->dev, sizeof(mega_passthru),
+				scb->pthru, scb->pthru_dma_addr);
+
+			scb->pthru = NULL;
+		}
+
+		if( scb->epthru ) {
+			pci_free_consistent(adapter->dev,
+				sizeof(mega_ext_passthru),
+				scb->epthru, scb->epthru_dma_addr);
+
+			scb->epthru = NULL;
+		}
+
+	}
+}
+
+
 /*
  * Release the controller's resources
  */
@@ -2605,44 +2703,6 @@ megaraid_release(struct Scsi_Host *host)
 	return 0;
 }
 
-static inline void
-mega_free_sgl(adapter_t *adapter)
-{
-	scb_t	*scb;
-	int	i;
-
-	for(i = 0; i < adapter->max_cmds; i++) {
-
-		scb = &adapter->scb_list[i];
-
-		if( scb->sgl64 ) {
-			pci_free_consistent(adapter->dev,
-				sizeof(mega_sgl64) * adapter->sglen,
-				scb->sgl64,
-				scb->sgl_dma_addr);
-
-			scb->sgl64 = NULL;
-		}
-
-		if( scb->pthru ) {
-			pci_free_consistent(adapter->dev, sizeof(mega_passthru),
-				scb->pthru, scb->pthru_dma_addr);
-
-			scb->pthru = NULL;
-		}
-
-		if( scb->epthru ) {
-			pci_free_consistent(adapter->dev,
-				sizeof(mega_ext_passthru),
-				scb->epthru, scb->epthru_dma_addr);
-
-			scb->epthru = NULL;
-		}
-
-	}
-}
-
-
 /*
  * Get information about the card/driver
  */
@@ -2860,6 +2920,27 @@ megaraid_reset(Scsi_Cmnd *cmd)
 }
 
 
+/**
+ * mega_allocate_inquiry()
+ * @dma_handle - handle returned for dma address
+ * @pdev - handle to pci device
+ *
+ * allocates memory for inquiry structure
+ */
+static inline caddr_t
+mega_allocate_inquiry(dma_addr_t *dma_handle, struct pci_dev *pdev)
+{
+	return pci_alloc_consistent(pdev, sizeof(mega_inquiry3), dma_handle);
+}
+
+
+static inline void
+mega_free_inquiry(caddr_t inquiry, dma_addr_t dma_handle, struct pci_dev *pdev)
+{
+	pci_free_consistent(pdev, sizeof(mega_inquiry3), inquiry, dma_handle);
+}
+
+
 #ifdef CONFIG_PROC_FS
 /* Following code handles /proc fs  */
 
@@ -5069,66 +5150,6 @@ mega_support_cluster(adapter_t *adapter)
 
 
 /**
- * mega_get_ldrv_num()
- * @adapter - pointer to our soft state
- * @cmd - scsi mid layer command
- * @channel - channel on the controller
- *
- * Calculate the logical drive number based on the information in scsi command
- * and the channel number.
- */
-static inline int
-mega_get_ldrv_num(adapter_t *adapter, Scsi_Cmnd *cmd, int channel)
-{
-	int		tgt;
-	int		ldrv_num;
-
-	tgt = cmd->target;
-
-	if ( tgt > adapter->this_id )
-		tgt--;	/* we do not get inquires for initiator id */
-
-	ldrv_num = (channel * 15) + tgt;
-
-
-	/*
-	 * If we have a logical drive with boot enabled, project it first
-	 */
-	if( adapter->boot_ldrv_enabled ) {
-		if( ldrv_num == 0 ) {
-			ldrv_num = adapter->boot_ldrv;
-		}
-		else {
-			if( ldrv_num <= adapter->boot_ldrv ) {
-				ldrv_num--;
-			}
-		}
-	}
-
-	/*
-	 * If "delete logical drive" feature is enabled on this controller.
-	 * Do only if at least one delete logical drive operation was done.
-	 *
-	 * Also, after logical drive deletion, instead of logical drive number,
-	 * the value returned should be 0x80+logical drive id.
-	 *
-	 * These is valid only for IO commands.
-	 */
-
-	if (adapter->support_random_del && adapter->read_ldidmap )
-		switch (cmd->cmnd[0]) {
-		case READ_6:	/* fall through */
-		case WRITE_6:	/* fall through */
-		case READ_10:	/* fall through */
-		case WRITE_10:
-			ldrv_num += 0x80;
-		}
-
-	return ldrv_num;
-}
-
-
-/**
  * mega_reorder_hosts()
  *
  * Hack: reorder the scsi hosts in mid-layer so that the controller with the
@@ -5342,27 +5363,6 @@ mega_adapinq(adapter_t *adapter, dma_add
 }
 
 
-/**
- * mega_allocate_inquiry()
- * @dma_handle - handle returned for dma address
- * @pdev - handle to pci device
- *
- * allocates memory for inquiry structure
- */
-static inline caddr_t
-mega_allocate_inquiry(dma_addr_t *dma_handle, struct pci_dev *pdev)
-{
-	return pci_alloc_consistent(pdev, sizeof(mega_inquiry3), dma_handle);
-}
-
-
-static inline void
-mega_free_inquiry(caddr_t inquiry, dma_addr_t dma_handle, struct pci_dev *pdev)
-{
-	pci_free_consistent(pdev, sizeof(mega_inquiry3), inquiry, dma_handle);
-}
-
-
 /** mega_internal_dev_inquiry()
  * @adapter - pointer to our soft state
  * @ch - channel for this device
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/scsi/megaraid2.h linux-2.4.28-pre3/drivers/scsi/megaraid2.h
--- linux-2.4.27/drivers/scsi/megaraid2.h	2004-08-07 23:26:05.000000000 +0000
+++ linux-2.4.28-pre3/drivers/scsi/megaraid2.h	2004-09-10 19:31:58.000000000 +0000
@@ -1091,14 +1091,12 @@ const char *megaraid_info (struct Scsi_H
 static int megaraid_detect(Scsi_Host_Template *);
 static void mega_find_card(Scsi_Host_Template *, u16, u16);
 static int mega_query_adapter(adapter_t *);
-static inline int issue_scb(adapter_t *, scb_t *);
+static int issue_scb(adapter_t *, scb_t *);
 static int mega_setup_mailbox(adapter_t *);
 
 static int megaraid_queue (Scsi_Cmnd *, void (*)(Scsi_Cmnd *));
 static scb_t * mega_build_cmd(adapter_t *, Scsi_Cmnd *, int *);
-static inline scb_t *mega_allocate_scb(adapter_t *, Scsi_Cmnd *);
 static void __mega_runpendq(adapter_t *);
-static inline void mega_runpendq(adapter_t *);
 static int issue_scb_block(adapter_t *, u_char *);
 
 static void megaraid_isr_memmapped(int, void *, struct pt_regs *);
@@ -1115,9 +1113,8 @@ static int megaraid_reset(Scsi_Cmnd *);
 
 static int mega_build_sglist (adapter_t *adapter, scb_t *scb,
 			      u32 *buffer, u32 *length);
-static inline int mega_busywait_mbox (adapter_t *);
 static int __mega_busywait_mbox (adapter_t *);
-static inline void mega_cmd_done(adapter_t *, u8 [], int, int);
+static void mega_cmd_done(adapter_t *, u8 [], int, int);
 static inline void mega_free_sgl (adapter_t *adapter);
 static void mega_8_to_40ld (mraid_inquiry *inquiry,
 		mega_inquiry3 *enquiry3, mega_product_info *);
@@ -1167,8 +1164,6 @@ static int proc_rdrv(adapter_t *, char *
 
 static int mega_adapinq(adapter_t *, dma_addr_t);
 static int mega_internal_dev_inquiry(adapter_t *, u8, u8, dma_addr_t);
-static inline caddr_t mega_allocate_inquiry(dma_addr_t *, struct pci_dev *);
-static inline void mega_free_inquiry(caddr_t, dma_addr_t, struct pci_dev *);
 static int mega_print_inquiry(char *, char *);
 #endif
 
@@ -1179,7 +1174,6 @@ static mega_ext_passthru* mega_prepare_e
 		scb_t *, Scsi_Cmnd *, int, int);
 static void mega_enum_raid_scsi(adapter_t *);
 static void mega_get_boot_drv(adapter_t *);
-static inline int mega_get_ldrv_num(adapter_t *, Scsi_Cmnd *, int);
 static int mega_support_random_del(adapter_t *);
 static int mega_del_logdrv(adapter_t *, int);
 static int mega_do_del_logdrv(adapter_t *, int);
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/scsi/nsp32.c linux-2.4.28-pre3/drivers/scsi/nsp32.c
--- linux-2.4.27/drivers/scsi/nsp32.c	2003-11-28 18:26:20.000000000 +0000
+++ linux-2.4.28-pre3/drivers/scsi/nsp32.c	2004-09-10 19:35:18.000000000 +0000
@@ -3365,6 +3365,48 @@ static int nsp32_prom_read(nsp32_hw_data
 	return val;
 }
 
+static inline void nsp32_prom_set(nsp32_hw_data *data, int bit, int val)
+{
+	unsigned int base = data->BaseAddress;
+	int tmp;
+
+	tmp = nsp32_index_read1(base, SERIAL_ROM_CTL);
+
+	if (val == 0) {
+		tmp &= ~bit;
+	} else {
+		tmp |=  bit;
+	}
+
+	nsp32_index_write1(base, SERIAL_ROM_CTL, tmp);
+
+	udelay(10);
+}
+
+static inline int nsp32_prom_get(nsp32_hw_data *data, int bit)
+{
+	unsigned int base = data->BaseAddress;
+	int tmp, ret;
+
+	if (bit != SROM_DATA) {
+		nsp32_msg(KERN_ERR, "return value is not appropriate");
+		return 0;
+	}
+
+
+	tmp = nsp32_index_read1(base, SERIAL_ROM_CTL) & bit;
+
+	if (tmp == 0) {
+		ret = 0;
+	} else {
+		ret = 1;
+	}
+
+	udelay(10);
+
+	return ret;
+}
+
 static void nsp32_prom_start (nsp32_hw_data *data)
 {
 	/* start condition */
@@ -3410,49 +3452,6 @@ static int nsp32_prom_read_bit(nsp32_hw_
 	return val;
 }
 
-static inline void nsp32_prom_set(nsp32_hw_data *data, int bit, int val)
-{
-	unsigned int base = data->BaseAddress;
-	int tmp;
-
-	tmp = nsp32_index_read1(base, SERIAL_ROM_CTL);
-
-	if (val == 0) {
-		tmp &= ~bit;
-	} else {
-		tmp |=  bit;
-	}
-
-	nsp32_index_write1(base, SERIAL_ROM_CTL, tmp);
-
-	udelay(10);
-}
-
-static inline int nsp32_prom_get(nsp32_hw_data *data, int bit)
-{
-	unsigned int base = data->BaseAddress;
-	int tmp, ret;
-
-	if (bit != SROM_DATA) {
-		nsp32_msg(KERN_ERR, "return value is not appropriate");
-		return 0;
-	}
-
-
-	tmp = nsp32_index_read1(base, SERIAL_ROM_CTL) & bit;
-
-	if (tmp == 0) {
-		ret = 0;
-	} else {
-		ret = 1;
-	}
-
-	udelay(10);
-
-	return ret;
-}
-
-
 /**************************************************************************
  * Power Management
  */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/scsi/pluto.c linux-2.4.28-pre3/drivers/scsi/pluto.c
--- linux-2.4.27/drivers/scsi/pluto.c	2001-02-09 19:30:23.000000000 +0000
+++ linux-2.4.28-pre3/drivers/scsi/pluto.c	2004-09-10 19:33:54.000000000 +0000
@@ -339,4 +339,4 @@ static Scsi_Host_Template driver_templat
 
 #include "scsi_module.c"
 
-EXPORT_NO_SYMBOLS;
+MODULE_LICENSE("GPL");
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/scsi/qla1280.c linux-2.4.28-pre3/drivers/scsi/qla1280.c
--- linux-2.4.27/drivers/scsi/qla1280.c	2003-11-28 18:26:20.000000000 +0000
+++ linux-2.4.28-pre3/drivers/scsi/qla1280.c	2004-09-10 19:37:20.000000000 +0000
@@ -875,6 +875,41 @@ static int qla1280_read_nvram(struct scs
 }
 
 
+ /*
+    * qla2100_enable_intrs
+    * qla2100_disable_intrs
+    *
+    * Input:
+    *      ha = adapter block pointer.
+    *
+    * Returns:
+    *      None
+  */
+static inline void
+qla1280_enable_intrs(struct scsi_qla_host *ha)
+{
+	struct device_reg *reg;
+
+	reg = ha->iobase;
+	/* enable risc and host interrupts */
+	WRT_REG_WORD(&reg->ictrl, (ISP_EN_INT | ISP_EN_RISC));
+	RD_REG_WORD(&reg->ictrl);	/* PCI Posted Write flush */
+	ha->flags.ints_enabled = 1;
+}
+
+static inline void
+qla1280_disable_intrs(struct scsi_qla_host *ha)
+{
+	struct device_reg *reg;
+
+	reg = ha->iobase;
+	/* disable risc and host interrupts */
+	WRT_REG_WORD(&reg->ictrl, 0);
+	RD_REG_WORD(&reg->ictrl);	/* PCI Posted Write flush */
+	ha->flags.ints_enabled = 0;
+}
+
+
 /**************************************************************************
  * qla1280_do_device_init
  *    This routine will register the device with the SCSI subsystem,
@@ -2049,40 +2084,6 @@ qla1280_mem_free(struct scsi_qla_host *h
 /*                QLogic ISP1280 Hardware Support Functions.                */
 /****************************************************************************/
 
- /*
-    * qla2100_enable_intrs
-    * qla2100_disable_intrs
-    *
-    * Input:
-    *      ha = adapter block pointer.
-    *
-    * Returns:
-    *      None
-  */
-static inline void
-qla1280_enable_intrs(struct scsi_qla_host *ha)
-{
-	struct device_reg *reg;
-
-	reg = ha->iobase;
-	/* enable risc and host interrupts */
-	WRT_REG_WORD(&reg->ictrl, (ISP_EN_INT | ISP_EN_RISC));
-	RD_REG_WORD(&reg->ictrl);	/* PCI Posted Write flush */
-	ha->flags.ints_enabled = 1;
-}
-
-static inline void
-qla1280_disable_intrs(struct scsi_qla_host *ha)
-{
-	struct device_reg *reg;
-
-	reg = ha->iobase;
-	/* disable risc and host interrupts */
-	WRT_REG_WORD(&reg->ictrl, 0);
-	RD_REG_WORD(&reg->ictrl);	/* PCI Posted Write flush */
-	ha->flags.ints_enabled = 0;
-}
-
 /*
  * qla1280_initialize_adapter
  *      Initialize board.
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/scsi/qlogicfc.c linux-2.4.28-pre3/drivers/scsi/qlogicfc.c
--- linux-2.4.27/drivers/scsi/qlogicfc.c	2004-04-14 13:05:31.000000000 +0000
+++ linux-2.4.28-pre3/drivers/scsi/qlogicfc.c	2004-09-10 19:36:03.000000000 +0000
@@ -722,7 +722,7 @@ int isp2x00_detect(Scsi_Host_Template * 
 				continue;
 
 			/* Try to configure DMA attributes. */
-			if (pci_set_dma_mask(pdev, (u64) 0xffffffffffffffff) &&
+			if (pci_set_dma_mask(pdev, (u64) 0xffffffffffffffffULL) &&
 			    pci_set_dma_mask(pdev, (u64) 0xffffffff))
 					continue;
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/scsi/qlogicpti.c linux-2.4.28-pre3/drivers/scsi/qlogicpti.c
--- linux-2.4.27/drivers/scsi/qlogicpti.c	2004-04-14 13:05:31.000000000 +0000
+++ linux-2.4.28-pre3/drivers/scsi/qlogicpti.c	2004-09-10 19:35:48.000000000 +0000
@@ -1533,4 +1533,4 @@ static Scsi_Host_Template driver_templat
 
 #include "scsi_module.c"
 
-EXPORT_NO_SYMBOLS;
+MODULE_LICENSE("GPL");
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/scsi/sata_nv.c linux-2.4.28-pre3/drivers/scsi/sata_nv.c
--- linux-2.4.27/drivers/scsi/sata_nv.c	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.28-pre3/drivers/scsi/sata_nv.c	2004-09-10 19:37:06.000000000 +0000
@@ -0,0 +1,556 @@
+/*
+ *  sata_nv.c - NVIDIA nForce SATA
+ *
+ *  Copyright 2004 NVIDIA Corp.  All rights reserved.
+ *  Copyright 2004 Andrew Chew
+ *
+ *  The contents of this file are subject to the Open
+ *  Software License version 1.1 that can be found at
+ *  http://www.opensource.org/licenses/osl-1.1.txt and is included herein
+ *  by reference.
+ *
+ *  Alternatively, the contents of this file may be used under the terms
+ *  of the GNU General Public License version 2 (the "GPL") as distributed
+ *  in the kernel source COPYING file, in which case the provisions of
+ *  the GPL are applicable instead of the above.  If you wish to allow
+ *  the use of your version of this file only under the terms of the
+ *  GPL and not to allow others to use your version of this file under
+ *  the OSL, indicate your decision by deleting the provisions above and
+ *  replace them with the notice and other provisions required by the GPL.
+ *  If you do not delete the provisions above, a recipient may use your
+ *  version of this file under either the OSL or the GPL.
+ *
+ *  0.03
+ *     - Fixed a bug where the hotplug handlers for non-CK804/MCP04 were using
+ *       mmio_base, which is only set for the CK804/MCP04 case.
+ *
+ *  0.02
+ *     - Added support for CK804 SATA controller.
+ *
+ *  0.01
+ *     - Initial revision.
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/blkdev.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include "scsi.h"
+#include <scsi/scsi_host.h>
+#include <linux/libata.h>
+
+#define DRV_NAME			"sata_nv"
+#define DRV_VERSION			"0.03"
+
+#define NV_PORTS			2
+#define NV_PIO_MASK			0x1f
+#define NV_MWDMA_MASK			0x07
+#define NV_UDMA_MASK			0x7f
+#define NV_PORT0_BMDMA_REG_OFFSET	0x00
+#define NV_PORT1_BMDMA_REG_OFFSET	0x08
+#define NV_PORT0_SCR_REG_OFFSET		0x00
+#define NV_PORT1_SCR_REG_OFFSET		0x40
+
+#define NV_INT_STATUS			0x10
+#define NV_INT_STATUS_CK804		0x440
+#define NV_INT_STATUS_PDEV_INT		0x01
+#define NV_INT_STATUS_PDEV_PM		0x02
+#define NV_INT_STATUS_PDEV_ADDED	0x04
+#define NV_INT_STATUS_PDEV_REMOVED	0x08
+#define NV_INT_STATUS_SDEV_INT		0x10
+#define NV_INT_STATUS_SDEV_PM		0x20
+#define NV_INT_STATUS_SDEV_ADDED	0x40
+#define NV_INT_STATUS_SDEV_REMOVED	0x80
+#define NV_INT_STATUS_PDEV_HOTPLUG	(NV_INT_STATUS_PDEV_ADDED | \
+					NV_INT_STATUS_PDEV_REMOVED)
+#define NV_INT_STATUS_SDEV_HOTPLUG	(NV_INT_STATUS_SDEV_ADDED | \
+					NV_INT_STATUS_SDEV_REMOVED)
+#define NV_INT_STATUS_HOTPLUG		(NV_INT_STATUS_PDEV_HOTPLUG | \
+					NV_INT_STATUS_SDEV_HOTPLUG)
+
+#define NV_INT_ENABLE			0x11
+#define NV_INT_ENABLE_CK804		0x441
+#define NV_INT_ENABLE_PDEV_MASK		0x01
+#define NV_INT_ENABLE_PDEV_PM		0x02
+#define NV_INT_ENABLE_PDEV_ADDED	0x04
+#define NV_INT_ENABLE_PDEV_REMOVED	0x08
+#define NV_INT_ENABLE_SDEV_MASK		0x10
+#define NV_INT_ENABLE_SDEV_PM		0x20
+#define NV_INT_ENABLE_SDEV_ADDED	0x40
+#define NV_INT_ENABLE_SDEV_REMOVED	0x80
+#define NV_INT_ENABLE_PDEV_HOTPLUG	(NV_INT_ENABLE_PDEV_ADDED | \
+					NV_INT_ENABLE_PDEV_REMOVED)
+#define NV_INT_ENABLE_SDEV_HOTPLUG	(NV_INT_ENABLE_SDEV_ADDED | \
+					NV_INT_ENABLE_SDEV_REMOVED)
+#define NV_INT_ENABLE_HOTPLUG		(NV_INT_ENABLE_PDEV_HOTPLUG | \
+					NV_INT_ENABLE_SDEV_HOTPLUG)
+
+#define NV_INT_CONFIG			0x12
+#define NV_INT_CONFIG_METHD		0x01 // 0 = INT, 1 = SMI
+
+// For PCI config register 20
+#define NV_MCP_SATA_CFG_20		0x50
+#define NV_MCP_SATA_CFG_20_SATA_SPACE_EN	0x04
+
+static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent);
+irqreturn_t nv_interrupt (int irq, void *dev_instance, struct pt_regs *regs);
+static u32 nv_scr_read (struct ata_port *ap, unsigned int sc_reg);
+static void nv_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val);
+static void nv_host_stop (struct ata_host_set *host_set);
+static void nv_enable_hotplug(struct ata_probe_ent *probe_ent);
+static void nv_disable_hotplug(struct ata_host_set *host_set);
+static void nv_check_hotplug(struct ata_host_set *host_set);
+static void nv_enable_hotplug_ck804(struct ata_probe_ent *probe_ent);
+static void nv_disable_hotplug_ck804(struct ata_host_set *host_set);
+static void nv_check_hotplug_ck804(struct ata_host_set *host_set);
+
+enum nv_host_type
+{
+	NFORCE2,
+	NFORCE3,
+	CK804
+};
+
+static struct pci_device_id nv_pci_tbl[] = {
+	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE2S_SATA,
+		PCI_ANY_ID, PCI_ANY_ID, 0, 0, NFORCE2 },
+	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA,
+		PCI_ANY_ID, PCI_ANY_ID, 0, 0, NFORCE3 },
+	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA2,
+		PCI_ANY_ID, PCI_ANY_ID, 0, 0, NFORCE3 },
+	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_SATA,
+		PCI_ANY_ID, PCI_ANY_ID, 0, 0, CK804 },
+	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_SATA2,
+		PCI_ANY_ID, PCI_ANY_ID, 0, 0, CK804 },
+	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_SATA,
+		PCI_ANY_ID, PCI_ANY_ID, 0, 0, CK804 },
+	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_SATA2,
+		PCI_ANY_ID, PCI_ANY_ID, 0, 0, CK804 },
+	{ 0, } /* terminate list */
+};
+
+#define NV_HOST_FLAGS_SCR_MMIO	0x00000001
+
+struct nv_host_desc
+{
+	enum nv_host_type	host_type;
+	unsigned long		host_flags;
+	void			(*enable_hotplug)(struct ata_probe_ent *probe_ent);
+	void			(*disable_hotplug)(struct ata_host_set *host_set);
+	void			(*check_hotplug)(struct ata_host_set *host_set);
+
+};
+static struct nv_host_desc nv_device_tbl[] = {
+	{
+		.host_type	= NFORCE2,
+		.host_flags	= 0x00000000,
+		.enable_hotplug	= nv_enable_hotplug,
+		.disable_hotplug= nv_disable_hotplug,
+		.check_hotplug	= nv_check_hotplug,
+	},
+	{
+		.host_type	= NFORCE3,
+		.host_flags	= 0x00000000,
+		.enable_hotplug	= nv_enable_hotplug,
+		.disable_hotplug= nv_disable_hotplug,
+		.check_hotplug	= nv_check_hotplug,
+	},
+	{	.host_type	= CK804,
+		.host_flags	= NV_HOST_FLAGS_SCR_MMIO,
+		.enable_hotplug	= nv_enable_hotplug_ck804,
+		.disable_hotplug= nv_disable_hotplug_ck804,
+		.check_hotplug	= nv_check_hotplug_ck804,
+	},
+};
+
+struct nv_host
+{
+	struct nv_host_desc	*host_desc;
+};
+
+static struct pci_driver nv_pci_driver = {
+	.name			= DRV_NAME,
+	.id_table		= nv_pci_tbl,
+	.probe			= nv_init_one,
+	.remove			= ata_pci_remove_one,
+};
+
+static Scsi_Host_Template nv_sht = {
+	.module			= THIS_MODULE,
+	.name			= DRV_NAME,
+	.detect			= ata_scsi_detect,
+	.release		= ata_scsi_release,
+	.ioctl                  = ata_scsi_ioctl,
+	.queuecommand		= ata_scsi_queuecmd,
+	.eh_strategy_handler	= ata_scsi_error,
+	.can_queue		= ATA_DEF_QUEUE,
+	.this_id		= ATA_SHT_THIS_ID,
+	.sg_tablesize		= LIBATA_MAX_PRD,
+	.max_sectors		= ATA_MAX_SECTORS,
+	.cmd_per_lun		= ATA_SHT_CMD_PER_LUN,
+	.use_new_eh_code	= ATA_SHT_NEW_EH_CODE,
+	.emulated		= ATA_SHT_EMULATED,
+	.use_clustering		= ATA_SHT_USE_CLUSTERING,
+	.proc_name		= DRV_NAME,
+	.bios_param		= ata_std_bios_param,
+};
+
+static struct ata_port_operations nv_ops = {
+	.port_disable		= ata_port_disable,
+	.tf_load		= ata_tf_load_pio,
+	.tf_read		= ata_tf_read_pio,
+	.exec_command		= ata_exec_command_pio,
+	.check_status		= ata_check_status_pio,
+	.phy_reset		= sata_phy_reset,
+	.bmdma_setup		= ata_bmdma_setup_pio,
+	.bmdma_start		= ata_bmdma_start_pio,
+	.qc_prep		= ata_qc_prep,
+	.qc_issue		= ata_qc_issue_prot,
+	.eng_timeout		= ata_eng_timeout,
+	.irq_handler		= nv_interrupt,
+	.irq_clear		= ata_bmdma_irq_clear,
+	.scr_read		= nv_scr_read,
+	.scr_write		= nv_scr_write,
+	.port_start		= ata_port_start,
+	.port_stop		= ata_port_stop,
+	.host_stop		= nv_host_stop,
+};
+
+MODULE_AUTHOR("NVIDIA");
+MODULE_DESCRIPTION("low-level driver for NVIDIA nForce SATA controller");
+MODULE_LICENSE("GPL");
+MODULE_DEVICE_TABLE(pci, nv_pci_tbl);
+
+irqreturn_t nv_interrupt (int irq, void *dev_instance, struct pt_regs *regs)
+{
+	struct ata_host_set *host_set = dev_instance;
+	struct nv_host *host = host_set->private_data;
+	unsigned int i;
+	unsigned int handled = 0;
+	unsigned long flags;
+
+	spin_lock_irqsave(&host_set->lock, flags);
+
+	for (i = 0; i < host_set->n_ports; i++) {
+		struct ata_port *ap;
+
+		ap = host_set->ports[i];
+		if (ap && (!(ap->flags & ATA_FLAG_PORT_DISABLED))) {
+			struct ata_queued_cmd *qc;
+
+			qc = ata_qc_from_tag(ap, ap->active_tag);
+			if (qc && (!(qc->tf.ctl & ATA_NIEN)))
+				handled += ata_host_intr(ap, qc);
+		}
+
+	}
+
+	if (host->host_desc->check_hotplug)
+		host->host_desc->check_hotplug(host_set);
+
+	spin_unlock_irqrestore(&host_set->lock, flags);
+
+	return IRQ_RETVAL(handled);
+}
+
+static u32 nv_scr_read (struct ata_port *ap, unsigned int sc_reg)
+{
+	struct ata_host_set *host_set = ap->host_set;
+	struct nv_host *host = host_set->private_data;
+
+	if (sc_reg > SCR_CONTROL)
+		return 0xffffffffU;
+
+	if (host->host_desc->host_flags & NV_HOST_FLAGS_SCR_MMIO)
+		return readl(ap->ioaddr.scr_addr + (sc_reg * 4));
+	else
+		return inl(ap->ioaddr.scr_addr + (sc_reg * 4));
+}
+
+static void nv_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val)
+{
+	struct ata_host_set *host_set = ap->host_set;
+	struct nv_host *host = host_set->private_data;
+
+	if (sc_reg > SCR_CONTROL)
+		return;
+
+	if (host->host_desc->host_flags & NV_HOST_FLAGS_SCR_MMIO)
+		writel(val, ap->ioaddr.scr_addr + (sc_reg * 4));
+	else
+		outl(val, ap->ioaddr.scr_addr + (sc_reg * 4));
+}
+
+static void nv_host_stop (struct ata_host_set *host_set)
+{
+	struct nv_host *host = host_set->private_data;
+
+	// Disable hotplug event interrupts.
+	if (host->host_desc->disable_hotplug)
+		host->host_desc->disable_hotplug(host_set);
+
+	kfree(host);
+}
+
+static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+	static int printed_version = 0;
+	struct nv_host *host;
+	struct ata_probe_ent *probe_ent = NULL;
+	int rc;
+
+	if (!printed_version++)
+		printk(KERN_DEBUG DRV_NAME " version " DRV_VERSION "\n");
+
+	rc = pci_enable_device(pdev);
+	if (rc)
+		return rc;
+
+	rc = pci_request_regions(pdev, DRV_NAME);
+	if (rc)
+		goto err_out;
+
+	rc = pci_set_dma_mask(pdev, ATA_DMA_MASK);
+	if (rc)
+		goto err_out_regions;
+
+	probe_ent = kmalloc(sizeof(*probe_ent), GFP_KERNEL);
+	if (!probe_ent) {
+		rc = -ENOMEM;
+		goto err_out_regions;
+	}
+
+	host = kmalloc(sizeof(struct nv_host), GFP_KERNEL);
+	if (!host) {
+		rc = -ENOMEM;
+		goto err_out_free_ent;
+	}
+
+	host->host_desc = &nv_device_tbl[ent->driver_data];
+
+	memset(probe_ent, 0, sizeof(*probe_ent));
+	INIT_LIST_HEAD(&probe_ent->node);
+
+	probe_ent->pdev = pdev;
+	probe_ent->sht = &nv_sht;
+	probe_ent->host_flags = ATA_FLAG_SATA |
+				ATA_FLAG_SATA_RESET |
+				ATA_FLAG_SRST |
+				ATA_FLAG_NO_LEGACY;
+
+	probe_ent->port_ops = &nv_ops;
+	probe_ent->n_ports = NV_PORTS;
+	probe_ent->irq = pdev->irq;
+	probe_ent->irq_flags = SA_SHIRQ;
+	probe_ent->pio_mask = NV_PIO_MASK;
+	probe_ent->mwdma_mask = NV_MWDMA_MASK;
+	probe_ent->udma_mask = NV_UDMA_MASK;
+
+	probe_ent->port[0].cmd_addr = pci_resource_start(pdev, 0);
+	ata_std_ports(&probe_ent->port[0]);
+	probe_ent->port[0].altstatus_addr =
+	probe_ent->port[0].ctl_addr =
+		pci_resource_start(pdev, 1) | ATA_PCI_CTL_OFS;
+	probe_ent->port[0].bmdma_addr =
+		pci_resource_start(pdev, 4) | NV_PORT0_BMDMA_REG_OFFSET;
+
+	probe_ent->port[1].cmd_addr = pci_resource_start(pdev, 2);
+	ata_std_ports(&probe_ent->port[1]);
+	probe_ent->port[1].altstatus_addr =
+	probe_ent->port[1].ctl_addr =
+		pci_resource_start(pdev, 3) | ATA_PCI_CTL_OFS;
+	probe_ent->port[1].bmdma_addr =
+		pci_resource_start(pdev, 4) | NV_PORT1_BMDMA_REG_OFFSET;
+
+	probe_ent->private_data = host;
+
+	if (host->host_desc->host_flags & NV_HOST_FLAGS_SCR_MMIO) {
+		unsigned long base;
+
+		probe_ent->mmio_base = ioremap(pci_resource_start(pdev, 5),
+				pci_resource_len(pdev, 5));
+		if (probe_ent->mmio_base == NULL)
+			goto err_out_iounmap;
+
+		base = (unsigned long)probe_ent->mmio_base;
+
+		probe_ent->port[0].scr_addr =
+			base + NV_PORT0_SCR_REG_OFFSET;
+		probe_ent->port[1].scr_addr =
+			base + NV_PORT1_SCR_REG_OFFSET;
+	} else {
+
+		probe_ent->port[0].scr_addr =
+			pci_resource_start(pdev, 5) | NV_PORT0_SCR_REG_OFFSET;
+		probe_ent->port[1].scr_addr =
+			pci_resource_start(pdev, 5) | NV_PORT1_SCR_REG_OFFSET;
+	}
+
+	pci_set_master(pdev);
+
+	// Enable hotplug event interrupts.
+	if (host->host_desc->enable_hotplug)
+		host->host_desc->enable_hotplug(probe_ent);
+
+	ata_add_to_probe_list(probe_ent);
+
+	return 0;
+
+err_out_iounmap:
+	if (host->host_desc->host_flags & NV_HOST_FLAGS_SCR_MMIO)
+		iounmap(probe_ent->mmio_base);
+
+err_out_free_ent:
+	kfree(probe_ent);
+
+err_out_regions:
+	pci_release_regions(pdev);
+
+err_out:
+	pci_disable_device(pdev);
+	return rc;
+}
+
+static void nv_enable_hotplug(struct ata_probe_ent *probe_ent)
+{
+	u8 intr_mask;
+
+	outb(NV_INT_STATUS_HOTPLUG,
+		probe_ent->port[0].scr_addr + NV_INT_STATUS);
+
+	intr_mask = inb(probe_ent->port[0].scr_addr + NV_INT_ENABLE);
+	intr_mask |= NV_INT_ENABLE_HOTPLUG;
+
+	outb(intr_mask, probe_ent->port[0].scr_addr + NV_INT_ENABLE);
+}
+
+static void nv_disable_hotplug(struct ata_host_set *host_set)
+{
+	u8 intr_mask;
+
+	intr_mask = inb(host_set->ports[0]->ioaddr.scr_addr + NV_INT_ENABLE);
+
+	intr_mask &= ~(NV_INT_ENABLE_HOTPLUG);
+
+	outb(intr_mask, host_set->ports[0]->ioaddr.scr_addr + NV_INT_ENABLE);
+}
+
+static void nv_check_hotplug(struct ata_host_set *host_set)
+{
+	u8 intr_status;
+
+	intr_status = inb(host_set->ports[0]->ioaddr.scr_addr + NV_INT_STATUS);
+
+	// Clear interrupt status.
+	outb(0xff, host_set->ports[0]->ioaddr.scr_addr + NV_INT_STATUS);
+
+	if (intr_status & NV_INT_STATUS_HOTPLUG) {
+		if (intr_status & NV_INT_STATUS_PDEV_ADDED)
+			printk(KERN_WARNING "nv_sata: "
+				"Primary device added\n");
+
+		if (intr_status & NV_INT_STATUS_PDEV_REMOVED)
+			printk(KERN_WARNING "nv_sata: "
+				"Primary device removed\n");
+
+		if (intr_status & NV_INT_STATUS_SDEV_ADDED)
+			printk(KERN_WARNING "nv_sata: "
+				"Secondary device added\n");
+
+		if (intr_status & NV_INT_STATUS_SDEV_REMOVED)
+			printk(KERN_WARNING "nv_sata: "
+				"Secondary device removed\n");
+	}
+}
+
+static void nv_enable_hotplug_ck804(struct ata_probe_ent *probe_ent)
+{
+	u8 intr_mask;
+	u8 regval;
+
+	pci_read_config_byte(probe_ent->pdev, NV_MCP_SATA_CFG_20, &regval);
+	regval |= NV_MCP_SATA_CFG_20_SATA_SPACE_EN;
+	pci_write_config_byte(probe_ent->pdev, NV_MCP_SATA_CFG_20, regval);
+
+	writeb(NV_INT_STATUS_HOTPLUG, probe_ent->mmio_base + NV_INT_STATUS_CK804);
+
+	intr_mask = readb(probe_ent->mmio_base + NV_INT_ENABLE_CK804);
+	intr_mask |= NV_INT_ENABLE_HOTPLUG;
+
+	writeb(intr_mask, probe_ent->mmio_base + NV_INT_ENABLE_CK804);
+}
+
+static void nv_disable_hotplug_ck804(struct ata_host_set *host_set)
+{
+	u8 intr_mask;
+	u8 regval;
+
+	intr_mask = readb(host_set->mmio_base + NV_INT_ENABLE_CK804);
+
+	intr_mask &= ~(NV_INT_ENABLE_HOTPLUG);
+
+	writeb(intr_mask, host_set->mmio_base + NV_INT_ENABLE_CK804);
+
+	pci_read_config_byte(host_set->pdev, NV_MCP_SATA_CFG_20, &regval);
+	regval &= ~NV_MCP_SATA_CFG_20_SATA_SPACE_EN;
+	pci_write_config_byte(host_set->pdev, NV_MCP_SATA_CFG_20, regval);
+}
+
+static void nv_check_hotplug_ck804(struct ata_host_set *host_set)
+{
+	u8 intr_status;
+
+	intr_status = readb(host_set->mmio_base + NV_INT_STATUS_CK804);
+
+	// Clear interrupt status.
+	writeb(0xff, host_set->mmio_base + NV_INT_STATUS_CK804);
+
+	if (intr_status & NV_INT_STATUS_HOTPLUG) {
+		if (intr_status & NV_INT_STATUS_PDEV_ADDED)
+			printk(KERN_WARNING "nv_sata: "
+				"Primary device added\n");
+
+		if (intr_status & NV_INT_STATUS_PDEV_REMOVED)
+			printk(KERN_WARNING "nv_sata: "
+				"Primary device removed\n");
+
+		if (intr_status & NV_INT_STATUS_SDEV_ADDED)
+			printk(KERN_WARNING "nv_sata: "
+				"Secondary device added\n");
+
+		if (intr_status & NV_INT_STATUS_SDEV_REMOVED)
+			printk(KERN_WARNING "nv_sata: "
+				"Secondary device removed\n");
+	}
+}
+
+static int __init nv_init(void)
+{
+	int rc;
+
+	rc = pci_module_init(&nv_pci_driver);
+	if (rc)
+		return rc;
+	
+	rc = scsi_register_module(MODULE_SCSI_HA, &nv_sht);
+	if (rc) {
+		pci_unregister_driver(&nv_pci_driver);
+		/* TODO: does scsi_register_module return errno val? */
+		return -ENODEV;
+	}
+
+	return 0;
+}
+
+static void __exit nv_exit(void)
+{
+	scsi_unregister_module(MODULE_SCSI_HA, &nv_sht);
+	pci_unregister_driver(&nv_pci_driver);
+}
+
+module_init(nv_init);
+module_exit(nv_exit);
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/scsi/sata_promise.c linux-2.4.28-pre3/drivers/scsi/sata_promise.c
--- linux-2.4.27/drivers/scsi/sata_promise.c	2004-08-07 23:26:05.000000000 +0000
+++ linux-2.4.28-pre3/drivers/scsi/sata_promise.c	2004-09-10 19:31:55.000000000 +0000
@@ -42,6 +42,7 @@
 #define DRV_NAME	"sata_promise"
 #define DRV_VERSION	"1.00"
 
+#define msleep libata_msleep	/* 2.4-specific */
 
 enum {
 	PDC_PKT_SUBMIT		= 0x40, /* Command packet pointer addr */
@@ -74,24 +75,23 @@ struct pdc_port_priv {
 static u32 pdc_sata_scr_read (struct ata_port *ap, unsigned int sc_reg);
 static void pdc_sata_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val);
 static int pdc_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *ent);
-static void pdc_dma_setup(struct ata_queued_cmd *qc);
-static void pdc_dma_start(struct ata_queued_cmd *qc);
 static irqreturn_t pdc_interrupt (int irq, void *dev_instance, struct pt_regs *regs);
 static void pdc_eng_timeout(struct ata_port *ap);
 static int pdc_port_start(struct ata_port *ap);
 static void pdc_port_stop(struct ata_port *ap);
 static void pdc_phy_reset(struct ata_port *ap);
-static void pdc_fill_sg(struct ata_queued_cmd *qc);
+static void pdc_qc_prep(struct ata_queued_cmd *qc);
 static void pdc_tf_load_mmio(struct ata_port *ap, struct ata_taskfile *tf);
 static void pdc_exec_command_mmio(struct ata_port *ap, struct ata_taskfile *tf);
-static inline void pdc_dma_complete (struct ata_port *ap,
-                                     struct ata_queued_cmd *qc, int have_err);
+static void pdc_irq_clear(struct ata_port *ap);
+static int pdc_qc_issue_prot(struct ata_queued_cmd *qc);
 
 static Scsi_Host_Template pdc_sata_sht = {
 	.module			= THIS_MODULE,
 	.name			= DRV_NAME,
 	.detect			= ata_scsi_detect,
 	.release		= ata_scsi_release,
+	.ioctl                  = ata_scsi_ioctl,
 	.queuecommand		= ata_scsi_queuecmd,
 	.eh_strategy_handler	= ata_scsi_error,
 	.can_queue		= ATA_DEF_QUEUE,
@@ -113,11 +113,11 @@ static struct ata_port_operations pdc_sa
 	.check_status		= ata_check_status_mmio,
 	.exec_command		= pdc_exec_command_mmio,
 	.phy_reset		= pdc_phy_reset,
-	.bmdma_setup            = pdc_dma_setup,
-	.bmdma_start            = pdc_dma_start,
-	.fill_sg		= pdc_fill_sg,
+	.qc_prep		= pdc_qc_prep,
+	.qc_issue		= pdc_qc_issue_prot,
 	.eng_timeout		= pdc_eng_timeout,
 	.irq_handler		= pdc_interrupt,
+	.irq_clear		= pdc_irq_clear,
 	.scr_read		= pdc_sata_scr_read,
 	.scr_write		= pdc_sata_scr_write,
 	.port_start		= pdc_port_start,
@@ -130,7 +130,8 @@ static struct ata_port_info pdc_port_inf
 		.sht		= &pdc_sata_sht,
 		.host_flags	= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
 				  ATA_FLAG_SRST | ATA_FLAG_MMIO,
-		.pio_mask	= 0x03, /* pio3-4 */
+		.pio_mask	= 0x1f, /* pio0-4 */
+		.mwdma_mask	= 0x07, /* mwdma0-2 */
 		.udma_mask	= 0x7f, /* udma0-6 ; FIXME */
 		.port_ops	= &pdc_sata_ops,
 	},
@@ -140,7 +141,8 @@ static struct ata_port_info pdc_port_inf
 		.sht		= &pdc_sata_sht,
 		.host_flags	= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
 				  ATA_FLAG_SRST | ATA_FLAG_MMIO,
-		.pio_mask	= 0x03, /* pio3-4 */
+		.pio_mask	= 0x1f, /* pio0-4 */
+		.mwdma_mask	= 0x07, /* mwdma0-2 */
 		.udma_mask	= 0x7f, /* udma0-6 ; FIXME */
 		.port_ops	= &pdc_sata_ops,
 	},
@@ -262,33 +264,33 @@ static void pdc_sata_scr_write (struct a
 	writel(val, (void *) ap->ioaddr.scr_addr + (sc_reg * 4));
 }
 
-static void pdc_fill_sg(struct ata_queued_cmd *qc)
+static void pdc_qc_prep(struct ata_queued_cmd *qc)
 {
 	struct pdc_port_priv *pp = qc->ap->private_data;
 	unsigned int i;
 
 	VPRINTK("ENTER\n");
 
-	ata_fill_sg(qc);
-
-	i = pdc_pkt_header(&qc->tf, qc->ap->prd_dma,  qc->dev->devno, pp->pkt);
+	switch (qc->tf.protocol) {
+	case ATA_PROT_DMA:
+		ata_qc_prep(qc);
+		/* fall through */
 
-	if (qc->tf.flags & ATA_TFLAG_LBA48)
-		i = pdc_prep_lba48(&qc->tf, pp->pkt, i);
-	else
-		i = pdc_prep_lba28(&qc->tf, pp->pkt, i);
+	case ATA_PROT_NODATA:
+		i = pdc_pkt_header(&qc->tf, qc->ap->prd_dma,
+				   qc->dev->devno, pp->pkt);
 
-	pdc_pkt_footer(&qc->tf, pp->pkt, i);
-}
+		if (qc->tf.flags & ATA_TFLAG_LBA48)
+			i = pdc_prep_lba48(&qc->tf, pp->pkt, i);
+		else
+			i = pdc_prep_lba28(&qc->tf, pp->pkt, i);
 
-static inline void pdc_dma_complete (struct ata_port *ap,
-                                     struct ata_queued_cmd *qc,
-				     int have_err)
-{
-	u8 err_bit = have_err ? ATA_ERR : 0;
+		pdc_pkt_footer(&qc->tf, pp->pkt, i);
+		break;
 
-	/* get drive status; clear intr; complete txn */
-	ata_qc_complete(qc, ata_wait_idle(ap) | err_bit);
+	default:
+		break;
+	}
 }
 
 static void pdc_eng_timeout(struct ata_port *ap)
@@ -315,17 +317,9 @@ static void pdc_eng_timeout(struct ata_p
 
 	switch (qc->tf.protocol) {
 	case ATA_PROT_DMA:
-		printk(KERN_ERR "ata%u: DMA timeout\n", ap->id);
-		ata_qc_complete(qc, ata_wait_idle(ap) | ATA_ERR);
-		break;
-
 	case ATA_PROT_NODATA:
-		drv_stat = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 1000);
-
-		printk(KERN_ERR "ata%u: command 0x%x timeout, stat 0x%x\n",
-		       ap->id, qc->tf.command, drv_stat);
-
-		ata_qc_complete(qc, drv_stat);
+		printk(KERN_ERR "ata%u: command timeout\n", ap->id);
+		ata_qc_complete(qc, ata_wait_idle(ap) | ATA_ERR);
 		break;
 
 	default:
@@ -358,13 +352,8 @@ static inline unsigned int pdc_host_intr
 
 	switch (qc->tf.protocol) {
 	case ATA_PROT_DMA:
-		pdc_dma_complete(ap, qc, have_err);
-		handled = 1;
-		break;
-
-	case ATA_PROT_NODATA:   /* command completion, but no data xfer */
-		status = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 1000);
-		DPRINTK("BUS_NODATA (drv_stat 0x%X)\n", status);
+	case ATA_PROT_NODATA:
+		status = ata_wait_idle(ap);
 		if (have_err)
 			status |= ATA_ERR;
 		ata_qc_complete(qc, status);
@@ -379,6 +368,14 @@ static inline unsigned int pdc_host_intr
         return handled;
 }
 
+static void pdc_irq_clear(struct ata_port *ap)
+{
+	struct ata_host_set *host_set = ap->host_set;
+	void *mmio = host_set->mmio_base;
+
+	readl(mmio + PDC_INT_SEQMASK);
+}
+
 static irqreturn_t pdc_interrupt (int irq, void *dev_instance, struct pt_regs *regs)
 {
 	struct ata_host_set *host_set = dev_instance;
@@ -432,13 +429,7 @@ static irqreturn_t pdc_interrupt (int ir
 	return IRQ_RETVAL(handled);
 }
 
-static void pdc_dma_setup(struct ata_queued_cmd *qc)
-{
-	/* nothing for now.  later, we will call standard
-	 * code in libata-core for ATAPI here */
-}
-
-static void pdc_dma_start(struct ata_queued_cmd *qc)
+static inline void pdc_packet_start(struct ata_queued_cmd *qc)
 {
 	struct ata_port *ap = qc->ap;
 	struct pdc_port_priv *pp = ap->private_data;
@@ -456,17 +447,38 @@ static void pdc_dma_start(struct ata_que
 	readl((void *) ap->ioaddr.cmd_addr + PDC_PKT_SUBMIT); /* flush */
 }
 
+static int pdc_qc_issue_prot(struct ata_queued_cmd *qc)
+{
+	switch (qc->tf.protocol) {
+	case ATA_PROT_DMA:
+	case ATA_PROT_NODATA:
+		pdc_packet_start(qc);
+		return 0;
+
+	case ATA_PROT_ATAPI_DMA:
+		BUG();
+		break;
+
+	default:
+		break;
+	}
+
+	return ata_qc_issue_prot(qc);
+}
+
 static void pdc_tf_load_mmio(struct ata_port *ap, struct ata_taskfile *tf)
 {
-	if (tf->protocol != ATA_PROT_DMA)
-		ata_tf_load_mmio(ap, tf);
+	WARN_ON (tf->protocol == ATA_PROT_DMA ||
+		 tf->protocol == ATA_PROT_NODATA);
+	ata_tf_load_mmio(ap, tf);
 }
 
 
 static void pdc_exec_command_mmio(struct ata_port *ap, struct ata_taskfile *tf)
 {
-	if (tf->protocol != ATA_PROT_DMA)
-		ata_exec_command_mmio(ap, tf);
+	WARN_ON (tf->protocol == ATA_PROT_DMA ||
+		 tf->protocol == ATA_PROT_NODATA);
+	ata_exec_command_mmio(ap, tf);
 }
 
 
@@ -519,8 +531,7 @@ static void pdc_host_init(unsigned int c
 	writel(tmp, mmio + PDC_TBG_MODE);
 
 	readl(mmio + PDC_TBG_MODE);	/* flush */
-	set_current_state(TASK_UNINTERRUPTIBLE);
-	schedule_timeout(msecs_to_jiffies(10) + 1);
+	msleep(10);
 
 	/* adjust slew rate control register. */
 	tmp = readl(mmio + PDC_SLEW_CTL);
@@ -578,6 +589,7 @@ static int pdc_sata_init_one (struct pci
 	probe_ent->sht		= pdc_port_info[board_idx].sht;
 	probe_ent->host_flags	= pdc_port_info[board_idx].host_flags;
 	probe_ent->pio_mask	= pdc_port_info[board_idx].pio_mask;
+	probe_ent->mwdma_mask	= pdc_port_info[board_idx].mwdma_mask;
 	probe_ent->udma_mask	= pdc_port_info[board_idx].udma_mask;
 	probe_ent->port_ops	= pdc_port_info[board_idx].port_ops;
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/scsi/sata_sil.c linux-2.4.28-pre3/drivers/scsi/sata_sil.c
--- linux-2.4.27/drivers/scsi/sata_sil.c	2004-08-07 23:26:05.000000000 +0000
+++ linux-2.4.28-pre3/drivers/scsi/sata_sil.c	2004-09-10 19:35:04.000000000 +0000
@@ -6,7 +6,7 @@
  *		    on emails.
  *
  *  Copyright 2003 Red Hat, Inc.
- *  Copyright 2003 Benjamin Herrenschmidt <benh@kernel.crashing.org>
+ *  Copyright 2003 Benjamin Herrenschmidt
  *
  *  The contents of this file are subject to the Open
  *  Software License version 1.1 that can be found at
@@ -86,6 +86,7 @@ struct sil_drivelist {
 	{ "ST360015AS",		SIL_QUIRK_MOD15WRITE },
 	{ "ST380023AS",		SIL_QUIRK_MOD15WRITE },
 	{ "ST3120023AS",	SIL_QUIRK_MOD15WRITE },
+	{ "ST3160023AS",	SIL_QUIRK_MOD15WRITE },
 	{ "ST340014ASL",	SIL_QUIRK_MOD15WRITE },
 	{ "ST360014ASL",	SIL_QUIRK_MOD15WRITE },
 	{ "ST380011ASL",	SIL_QUIRK_MOD15WRITE },
@@ -107,6 +108,7 @@ static Scsi_Host_Template sil_sht = {
 	.name			= DRV_NAME,
 	.detect			= ata_scsi_detect,
 	.release		= ata_scsi_release,
+	.ioctl                  = ata_scsi_ioctl,
 	.queuecommand		= ata_scsi_queuecmd,
 	.eh_strategy_handler	= ata_scsi_error,
 	.can_queue		= ATA_DEF_QUEUE,
@@ -132,9 +134,11 @@ static struct ata_port_operations sil_op
 	.post_set_mode		= sil_post_set_mode,
 	.bmdma_setup            = ata_bmdma_setup_mmio,
 	.bmdma_start            = ata_bmdma_start_mmio,
-	.fill_sg		= ata_fill_sg,
+	.qc_prep		= ata_qc_prep,
+	.qc_issue		= ata_qc_issue_prot,
 	.eng_timeout		= ata_eng_timeout,
 	.irq_handler		= ata_interrupt,
+	.irq_clear		= ata_bmdma_irq_clear,
 	.scr_read		= sil_scr_read,
 	.scr_write		= sil_scr_write,
 	.port_start		= ata_port_start,
@@ -147,7 +151,8 @@ static struct ata_port_info sil_port_inf
 		.sht		= &sil_sht,
 		.host_flags	= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
 				  ATA_FLAG_SRST | ATA_FLAG_MMIO,
-		.pio_mask	= 0x03,			/* pio3-4 */
+		.pio_mask	= 0x1f,			/* pio0-4 */
+		.mwdma_mask	= 0x07,			/* mwdma0-2 */
 		.udma_mask	= 0x3f,			/* udma0-5 */
 		.port_ops	= &sil_ops,
 	}, /* sil_3114 */
@@ -155,7 +160,8 @@ static struct ata_port_info sil_port_inf
 		.sht		= &sil_sht,
 		.host_flags	= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
 				  ATA_FLAG_SRST | ATA_FLAG_MMIO,
-		.pio_mask	= 0x03,			/* pio3-4 */
+		.pio_mask	= 0x1f,			/* pio0-4 */
+		.mwdma_mask	= 0x07,			/* mwdma0-2 */
 		.udma_mask	= 0x3f,			/* udma0-5 */
 		.port_ops	= &sil_ops,
 	},
@@ -303,6 +309,7 @@ static void sil_dev_config(struct ata_po
 		       ap->id, dev->devno);
 		ap->host->max_sectors = 15;
 		ap->host->hostt->max_sectors = 15;
+		dev->flags |= ATA_DFLAG_LOCK_SECTORS;
 		return;
 	}
 
@@ -357,6 +364,7 @@ static int sil_init_one (struct pci_dev 
 	probe_ent->sht = sil_port_info[ent->driver_data].sht;
 	probe_ent->n_ports = (ent->driver_data == sil_3114) ? 4 : 2;
 	probe_ent->pio_mask = sil_port_info[ent->driver_data].pio_mask;
+	probe_ent->mwdma_mask = sil_port_info[ent->driver_data].mwdma_mask;
 	probe_ent->udma_mask = sil_port_info[ent->driver_data].udma_mask;
        	probe_ent->irq = pdev->irq;
        	probe_ent->irq_flags = SA_SHIRQ;
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/scsi/sata_sis.c linux-2.4.28-pre3/drivers/scsi/sata_sis.c
--- linux-2.4.27/drivers/scsi/sata_sis.c	2004-08-07 23:26:05.000000000 +0000
+++ linux-2.4.28-pre3/drivers/scsi/sata_sis.c	2004-09-10 19:34:29.000000000 +0000
@@ -78,6 +78,7 @@ static Scsi_Host_Template sis_sht = {
 	.name			= DRV_NAME,
 	.detect			= ata_scsi_detect,
 	.release		= ata_scsi_release,
+	.ioctl                  = ata_scsi_ioctl,
 	.queuecommand		= ata_scsi_queuecmd,
 	.eh_strategy_handler	= ata_scsi_error,
 	.can_queue		= ATA_DEF_QUEUE,
@@ -101,9 +102,11 @@ static struct ata_port_operations sis_op
 	.phy_reset		= sata_phy_reset,
 	.bmdma_setup            = ata_bmdma_setup_pio,
 	.bmdma_start            = ata_bmdma_start_pio,
-	.fill_sg		= ata_fill_sg,
+	.qc_prep		= ata_qc_prep,
+	.qc_issue		= ata_qc_issue_prot,
 	.eng_timeout		= ata_eng_timeout,
 	.irq_handler		= ata_interrupt,
+	.irq_clear		= ata_bmdma_irq_clear,
 	.scr_read		= sis_scr_read,
 	.scr_write		= sis_scr_write,
 	.port_start		= ata_port_start,
@@ -226,7 +229,8 @@ static int sis_init_one (struct pci_dev 
 		probe_ent->host_flags |= SIS_FLAG_CFGSCR;
 	}
 
-	probe_ent->pio_mask = 0x03;
+	probe_ent->pio_mask = 0x1f;
+	probe_ent->mwdma_mask = 0x7;
 	probe_ent->udma_mask = 0x7f;
 	probe_ent->port_ops = &sis_ops;
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/scsi/sata_svw.c linux-2.4.28-pre3/drivers/scsi/sata_svw.c
--- linux-2.4.27/drivers/scsi/sata_svw.c	2004-08-07 23:26:05.000000000 +0000
+++ linux-2.4.28-pre3/drivers/scsi/sata_svw.c	2004-09-10 19:35:43.000000000 +0000
@@ -207,6 +207,7 @@ static Scsi_Host_Template k2_sata_sht = 
 	.name			= DRV_NAME,
 	.detect			= ata_scsi_detect,
 	.release		= ata_scsi_release,
+	.ioctl                  = ata_scsi_ioctl,
 	.queuecommand		= ata_scsi_queuecmd,
 	.eh_strategy_handler	= ata_scsi_error,
 	.can_queue		= ATA_DEF_QUEUE,
@@ -234,9 +235,11 @@ static struct ata_port_operations k2_sat
 	.phy_reset		= sata_phy_reset,
 	.bmdma_setup            = ata_bmdma_setup_mmio,
 	.bmdma_start            = ata_bmdma_start_mmio,
-	.fill_sg		= ata_fill_sg,
+	.qc_prep		= ata_qc_prep,
+	.qc_issue		= ata_qc_issue_prot,
 	.eng_timeout		= ata_eng_timeout,
 	.irq_handler		= ata_interrupt,
+	.irq_clear		= ata_bmdma_irq_clear,
 	.scr_read		= k2_sata_scr_read,
 	.scr_write		= k2_sata_scr_write,
 	.port_start		= ata_port_start,
@@ -339,6 +342,7 @@ static int k2_sata_init_one (struct pci_
 	 * if we don't fill these
 	 */
 	probe_ent->pio_mask = 0x1f;
+	probe_ent->mwdma_mask = 0x7;
 	probe_ent->udma_mask = 0x7f;
 
 	/* We have 4 ports per PCI function */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/scsi/sata_sx4.c linux-2.4.28-pre3/drivers/scsi/sata_sx4.c
--- linux-2.4.27/drivers/scsi/sata_sx4.c	2004-08-07 23:26:05.000000000 +0000
+++ linux-2.4.28-pre3/drivers/scsi/sata_sx4.c	2004-09-10 19:34:46.000000000 +0000
@@ -146,19 +146,15 @@ struct pdc_host_priv {
 
 
 static int pdc_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *ent);
-static void pdc20621_dma_setup(struct ata_queued_cmd *qc);
-static void pdc20621_dma_start(struct ata_queued_cmd *qc);
 static irqreturn_t pdc20621_interrupt (int irq, void *dev_instance, struct pt_regs *regs);
 static void pdc_eng_timeout(struct ata_port *ap);
 static void pdc_20621_phy_reset (struct ata_port *ap);
 static int pdc_port_start(struct ata_port *ap);
 static void pdc_port_stop(struct ata_port *ap);
-static void pdc20621_fill_sg(struct ata_queued_cmd *qc);
+static void pdc20621_qc_prep(struct ata_queued_cmd *qc);
 static void pdc_tf_load_mmio(struct ata_port *ap, struct ata_taskfile *tf);
 static void pdc_exec_command_mmio(struct ata_port *ap, struct ata_taskfile *tf);
 static void pdc20621_host_stop(struct ata_host_set *host_set);
-static inline void pdc_dma_complete (struct ata_port *ap,
-                                     struct ata_queued_cmd *qc, int have_err);
 static unsigned int pdc20621_dimm_init(struct ata_probe_ent *pe);
 static int pdc20621_detect_dimm(struct ata_probe_ent *pe);
 static unsigned int pdc20621_i2c_read(struct ata_probe_ent *pe, 
@@ -171,6 +167,8 @@ static void pdc20621_get_from_dimm(struc
 #endif
 static void pdc20621_put_to_dimm(struct ata_probe_ent *pe, 
 				 void *psource, u32 offset, u32 size);
+static void pdc20621_irq_clear(struct ata_port *ap);
+static int pdc20621_qc_issue_prot(struct ata_queued_cmd *qc);
 
 
 static Scsi_Host_Template pdc_sata_sht = {
@@ -178,6 +176,7 @@ static Scsi_Host_Template pdc_sata_sht =
 	.name			= DRV_NAME,
 	.detect			= ata_scsi_detect,
 	.release		= ata_scsi_release,
+	.ioctl                  = ata_scsi_ioctl,
 	.queuecommand		= ata_scsi_queuecmd,
 	.eh_strategy_handler	= ata_scsi_error,
 	.can_queue		= ATA_DEF_QUEUE,
@@ -199,11 +198,11 @@ static struct ata_port_operations pdc_20
 	.check_status		= ata_check_status_mmio,
 	.exec_command		= pdc_exec_command_mmio,
 	.phy_reset		= pdc_20621_phy_reset,
-	.bmdma_setup            = pdc20621_dma_setup,
-	.bmdma_start            = pdc20621_dma_start,
-	.fill_sg		= pdc20621_fill_sg,
+	.qc_prep		= pdc20621_qc_prep,
+	.qc_issue		= pdc20621_qc_issue_prot,
 	.eng_timeout		= pdc_eng_timeout,
 	.irq_handler		= pdc20621_interrupt,
+	.irq_clear		= pdc20621_irq_clear,
 	.port_start		= pdc_port_start,
 	.port_stop		= pdc_port_stop,
 	.host_stop		= pdc20621_host_stop,
@@ -215,7 +214,8 @@ static struct ata_port_info pdc_port_inf
 		.sht		= &pdc_sata_sht,
 		.host_flags	= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
 				  ATA_FLAG_SRST | ATA_FLAG_MMIO,
-		.pio_mask	= 0x03, /* pio3-4 */
+		.pio_mask	= 0x1f, /* pio0-4 */
+		.mwdma_mask	= 0x07, /* mwdma0-2 */
 		.udma_mask	= 0x7f, /* udma0-6 ; FIXME */
 		.port_ops	= &pdc_20621_ops,
 	},
@@ -375,7 +375,10 @@ static inline unsigned int pdc20621_ata_
 
 	/* dimm dma S/G, and next-pkt */
 	dw = i >> 2;
-	buf32[dw] = cpu_to_le32(dimm_sg);
+	if (tf->protocol == ATA_PROT_NODATA)
+		buf32[dw] = 0;
+	else
+		buf32[dw] = cpu_to_le32(dimm_sg);
 	buf32[dw + 1] = 0;
 	i += 8;
 
@@ -435,7 +438,7 @@ static inline void pdc20621_host_pkt(str
 		buf32[dw + 3]);
 }
 
-static void pdc20621_fill_sg(struct ata_queued_cmd *qc)
+static void pdc20621_dma_prep(struct ata_queued_cmd *qc)
 {
 	struct scatterlist *sg = qc->sg;
 	struct ata_port *ap = qc->ap;
@@ -447,6 +450,8 @@ static void pdc20621_fill_sg(struct ata_
 	unsigned int i, last, idx, total_len = 0, sgt_len;
 	u32 *buf = (u32 *) &pp->dimm_buf[PDC_DIMM_HEADER_SZ];
 
+	assert(qc->flags & ATA_QCFLAG_DMAMAP);
+
 	VPRINTK("ata%u: ENTER\n", ap->id);
 
 	/* hard-code chip #0 */
@@ -496,6 +501,56 @@ static void pdc20621_fill_sg(struct ata_
 	VPRINTK("ata pkt buf ofs %u, prd size %u, mmio copied\n", i, sgt_len);
 }
 
+static void pdc20621_nodata_prep(struct ata_queued_cmd *qc)
+{
+	struct ata_port *ap = qc->ap;
+	struct pdc_port_priv *pp = ap->private_data;
+	void *mmio = ap->host_set->mmio_base;
+	struct pdc_host_priv *hpriv = ap->host_set->private_data;
+	void *dimm_mmio = hpriv->dimm_mmio;
+	unsigned int portno = ap->port_no;
+	unsigned int i;
+
+	VPRINTK("ata%u: ENTER\n", ap->id);
+
+	/* hard-code chip #0 */
+	mmio += PDC_CHIP0_OFS;
+
+	i = pdc20621_ata_pkt(&qc->tf, qc->dev->devno, &pp->dimm_buf[0], portno);
+
+	if (qc->tf.flags & ATA_TFLAG_LBA48)
+		i = pdc_prep_lba48(&qc->tf, &pp->dimm_buf[0], i);
+	else
+		i = pdc_prep_lba28(&qc->tf, &pp->dimm_buf[0], i);
+
+	pdc_pkt_footer(&qc->tf, &pp->dimm_buf[0], i);
+
+	/* copy three S/G tables and two packets to DIMM MMIO window */
+	memcpy_toio(dimm_mmio + (portno * PDC_DIMM_WINDOW_STEP),
+		    &pp->dimm_buf, PDC_DIMM_HEADER_SZ);
+
+	/* force host FIFO dump */
+	writel(0x00000001, mmio + PDC_20621_GENERAL_CTL);
+
+	readl(dimm_mmio);	/* MMIO PCI posting flush */
+
+	VPRINTK("ata pkt buf ofs %u, prd size %u, mmio copied\n", i, sgt_len);
+}
+
+static void pdc20621_qc_prep(struct ata_queued_cmd *qc)
+{
+	switch (qc->tf.protocol) {
+	case ATA_PROT_DMA:
+		pdc20621_dma_prep(qc);
+		break;
+	case ATA_PROT_NODATA:
+		pdc20621_nodata_prep(qc);
+		break;
+	default:
+		break;
+	}
+}
+
 static void __pdc20621_push_hdma(struct ata_queued_cmd *qc,
 				 unsigned int seq,
 				 u32 pkt_ofs)
@@ -571,13 +626,7 @@ static void pdc20621_dump_hdma(struct at
 static inline void pdc20621_dump_hdma(struct ata_queued_cmd *qc) { }
 #endif /* ATA_VERBOSE_DEBUG */
 
-static void pdc20621_dma_setup(struct ata_queued_cmd *qc)
-{
-	/* nothing for now.  later, we will call standard
-	 * code in libata-core for ATAPI here */
-}
-
-static void pdc20621_dma_start(struct ata_queued_cmd *qc)
+static void pdc20621_packet_start(struct ata_queued_cmd *qc)
 {
 	struct ata_port *ap = qc->ap;
 	struct ata_host_set *host_set = ap->host_set;
@@ -585,24 +634,21 @@ static void pdc20621_dma_start(struct at
 	void *mmio = host_set->mmio_base;
 	unsigned int rw = (qc->tf.flags & ATA_TFLAG_WRITE);
 	u8 seq = (u8) (port_no + 1);
-	unsigned int doing_hdma = 0, port_ofs;
+	unsigned int port_ofs;
 
 	/* hard-code chip #0 */
 	mmio += PDC_CHIP0_OFS;
 
 	VPRINTK("ata%u: ENTER\n", ap->id);
 
+	wmb();			/* flush PRD, pkt writes */
+
 	port_ofs = PDC_20621_DIMM_BASE + (PDC_DIMM_WINDOW_STEP * port_no);
 
 	/* if writing, we (1) DMA to DIMM, then (2) do ATA command */
-	if (rw) {
-		doing_hdma = 1;
+	if (rw && qc->tf.protocol == ATA_PROT_DMA) {
 		seq += 4;
-	}
 
-	wmb();			/* flush PRD, pkt writes */
-
-	if (doing_hdma) {
 		pdc20621_dump_hdma(qc);
 		pdc20621_push_hdma(qc, seq, port_ofs + PDC_DIMM_HOST_PKT);
 		VPRINTK("queued ofs 0x%x (%u), seq %u\n",
@@ -623,6 +669,25 @@ static void pdc20621_dma_start(struct at
 	}
 }
 
+static int pdc20621_qc_issue_prot(struct ata_queued_cmd *qc)
+{
+	switch (qc->tf.protocol) {
+	case ATA_PROT_DMA:
+	case ATA_PROT_NODATA:
+		pdc20621_packet_start(qc);
+		return 0;
+
+	case ATA_PROT_ATAPI_DMA:
+		BUG();
+		break;
+
+	default:
+		break;
+	}
+
+	return ata_qc_issue_prot(qc);
+}
+
 static inline unsigned int pdc20621_host_intr( struct ata_port *ap,
                                           struct ata_queued_cmd *qc,
 					  unsigned int doing_hdma,
@@ -643,7 +708,8 @@ static inline unsigned int pdc20621_host
 		if (doing_hdma) {
 			VPRINTK("ata%u: read hdma, 0x%x 0x%x\n", ap->id,
 				readl(mmio + 0x104), readl(mmio + PDC_HDMA_CTLSTAT));
-			pdc_dma_complete(ap, qc, 0);
+			/* get drive status; clear intr; complete txn */
+			ata_qc_complete(qc, ata_wait_idle(ap));
 			pdc20621_pop_hdma(qc);
 		}
 
@@ -680,7 +746,8 @@ static inline unsigned int pdc20621_host
 		else {
 			VPRINTK("ata%u: write ata, 0x%x 0x%x\n", ap->id,
 				readl(mmio + 0x104), readl(mmio + PDC_HDMA_CTLSTAT));
-			pdc_dma_complete(ap, qc, 0);
+			/* get drive status; clear intr; complete txn */
+			ata_qc_complete(qc, ata_wait_idle(ap));
 			pdc20621_pop_hdma(qc);
 		}
 		handled = 1;
@@ -700,6 +767,16 @@ static inline unsigned int pdc20621_host
 	return handled;
 }
 
+static void pdc20621_irq_clear(struct ata_port *ap)
+{
+	struct ata_host_set *host_set = ap->host_set;
+	void *mmio = host_set->mmio_base;
+
+	mmio += PDC_CHIP0_OFS;
+
+	readl(mmio + PDC_20621_SEQMASK);
+}
+
 static irqreturn_t pdc20621_interrupt (int irq, void *dev_instance, struct pt_regs *regs)
 {
 	struct ata_host_set *host_set = dev_instance;
@@ -764,16 +841,6 @@ static irqreturn_t pdc20621_interrupt (i
 	return IRQ_RETVAL(handled);
 }
 
-static inline void pdc_dma_complete (struct ata_port *ap,
-                                     struct ata_queued_cmd *qc,
-				     int have_err)
-{
-	u8 err_bit = have_err ? ATA_ERR : 0;
-
-	/* get drive status; clear intr; complete txn */
-	ata_qc_complete(qc, ata_wait_idle(ap) | err_bit);
-}
-
 static void pdc_eng_timeout(struct ata_port *ap)
 {
 	u8 drv_stat;
@@ -798,17 +865,9 @@ static void pdc_eng_timeout(struct ata_p
 
 	switch (qc->tf.protocol) {
 	case ATA_PROT_DMA:
-		printk(KERN_ERR "ata%u: DMA timeout\n", ap->id);
-		ata_qc_complete(qc, ata_wait_idle(ap) | ATA_ERR);
-		break;
-
 	case ATA_PROT_NODATA:
-		drv_stat = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 1000);
-
-		printk(KERN_ERR "ata%u: command 0x%x timeout, stat 0x%x\n",
-		       ap->id, qc->tf.command, drv_stat);
-
-		ata_qc_complete(qc, drv_stat);
+		printk(KERN_ERR "ata%u: command timeout\n", ap->id);
+		ata_qc_complete(qc, ata_wait_idle(ap) | ATA_ERR);
 		break;
 
 	default:
@@ -827,15 +886,17 @@ out:
 
 static void pdc_tf_load_mmio(struct ata_port *ap, struct ata_taskfile *tf)
 {
-	if (tf->protocol != ATA_PROT_DMA)
-		ata_tf_load_mmio(ap, tf);
+	WARN_ON (tf->protocol == ATA_PROT_DMA ||
+		 tf->protocol == ATA_PROT_NODATA);
+	ata_tf_load_mmio(ap, tf);
 }
 
 
 static void pdc_exec_command_mmio(struct ata_port *ap, struct ata_taskfile *tf)
 {
-	if (tf->protocol != ATA_PROT_DMA)
-		ata_exec_command_mmio(ap, tf);
+	WARN_ON (tf->protocol == ATA_PROT_DMA ||
+		 tf->protocol == ATA_PROT_NODATA);
+	ata_exec_command_mmio(ap, tf);
 }
 
 
@@ -1366,6 +1427,7 @@ static int pdc_sata_init_one (struct pci
 	probe_ent->sht		= pdc_port_info[board_idx].sht;
 	probe_ent->host_flags	= pdc_port_info[board_idx].host_flags;
 	probe_ent->pio_mask	= pdc_port_info[board_idx].pio_mask;
+	probe_ent->mwdma_mask	= pdc_port_info[board_idx].mwdma_mask;
 	probe_ent->udma_mask	= pdc_port_info[board_idx].udma_mask;
 	probe_ent->port_ops	= pdc_port_info[board_idx].port_ops;
 
@@ -1376,21 +1438,11 @@ static int pdc_sata_init_one (struct pci
 	probe_ent->private_data = hpriv;
 	base += PDC_CHIP0_OFS;
 
+	probe_ent->n_ports = 4;
 	pdc_sata_setup_port(&probe_ent->port[0], base + 0x200);
 	pdc_sata_setup_port(&probe_ent->port[1], base + 0x280);
-
-	/* notice 4-port boards */
-	switch (board_idx) {
-	case board_20621:
-       		probe_ent->n_ports = 4;
-
-		pdc_sata_setup_port(&probe_ent->port[2], base + 0x300);
-		pdc_sata_setup_port(&probe_ent->port[3], base + 0x380);
-		break;
-	default:
-		BUG();
-		break;
-	}
+	pdc_sata_setup_port(&probe_ent->port[2], base + 0x300);
+	pdc_sata_setup_port(&probe_ent->port[3], base + 0x380);
 
 	pci_set_master(pdev);
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/scsi/sata_via.c linux-2.4.28-pre3/drivers/scsi/sata_via.c
--- linux-2.4.27/drivers/scsi/sata_via.c	2004-08-07 23:26:05.000000000 +0000
+++ linux-2.4.28-pre3/drivers/scsi/sata_via.c	2004-09-10 19:36:58.000000000 +0000
@@ -83,6 +83,7 @@ static Scsi_Host_Template svia_sht = {
 	.name			= DRV_NAME,
 	.detect			= ata_scsi_detect,
 	.release		= ata_scsi_release,
+	.ioctl                  = ata_scsi_ioctl,
 	.queuecommand		= ata_scsi_queuecmd,
 	.eh_strategy_handler	= ata_scsi_error,
 	.can_queue		= ATA_DEF_QUEUE,
@@ -109,10 +110,13 @@ static struct ata_port_operations svia_s
 
 	.bmdma_setup            = ata_bmdma_setup_pio,
 	.bmdma_start            = ata_bmdma_start_pio,
-	.fill_sg		= ata_fill_sg,
+	.qc_prep		= ata_qc_prep,
+	.qc_issue		= ata_qc_issue_prot,
+
 	.eng_timeout		= ata_eng_timeout,
 
 	.irq_handler		= ata_interrupt,
+	.irq_clear		= ata_bmdma_irq_clear,
 
 	.scr_read		= svia_scr_read,
 	.scr_write		= svia_scr_write,
@@ -209,6 +213,7 @@ static int svia_init_one (struct pci_dev
 	probe_ent->irq = pdev->irq;
 	probe_ent->irq_flags = SA_SHIRQ;
 	probe_ent->pio_mask = 0x1f;
+	probe_ent->mwdma_mask = 0x07;
 	probe_ent->udma_mask = 0x7f;
 
 	probe_ent->port[0].cmd_addr = pci_resource_start(pdev, 0);
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/scsi/sata_vsc.c linux-2.4.28-pre3/drivers/scsi/sata_vsc.c
--- linux-2.4.27/drivers/scsi/sata_vsc.c	2004-08-07 23:26:05.000000000 +0000
+++ linux-2.4.28-pre3/drivers/scsi/sata_vsc.c	2004-09-10 19:35:22.000000000 +0000
@@ -192,6 +192,7 @@ static Scsi_Host_Template vsc_sata_sht =
 	.name			= DRV_NAME,
 	.detect			= ata_scsi_detect,
 	.release		= ata_scsi_release,
+	.ioctl                  = ata_scsi_ioctl,
 	.queuecommand		= ata_scsi_queuecmd,
 	.eh_strategy_handler	= ata_scsi_error,
 	.can_queue		= ATA_DEF_QUEUE,
@@ -216,9 +217,11 @@ static struct ata_port_operations vsc_sa
 	.phy_reset		= sata_phy_reset,
 	.bmdma_setup            = ata_bmdma_setup_mmio,
 	.bmdma_start            = ata_bmdma_start_mmio,
-	.fill_sg		= ata_fill_sg,
+	.qc_prep		= ata_qc_prep,
+	.qc_issue		= ata_qc_issue_prot,
 	.eng_timeout		= ata_eng_timeout,
 	.irq_handler		= vsc_sata_interrupt,
+	.irq_clear		= ata_bmdma_irq_clear,
 	.scr_read		= vsc_sata_scr_read,
 	.scr_write		= vsc_sata_scr_write,
 	.port_start		= ata_port_start,
@@ -316,6 +319,7 @@ static int __devinit vsc_sata_init_one (
 	 * if we don't fill these
 	 */
 	probe_ent->pio_mask = 0x1f;
+	probe_ent->mwdma_mask = 0x07;
 	probe_ent->udma_mask = 0x7f;
 
 	/* We have 4 ports per PCI function */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/scsi/scsi_debug.c linux-2.4.28-pre3/drivers/scsi/scsi_debug.c
--- linux-2.4.27/drivers/scsi/scsi_debug.c	2002-11-28 23:53:14.000000000 +0000
+++ linux-2.4.28-pre3/drivers/scsi/scsi_debug.c	2004-09-10 19:35:30.000000000 +0000
@@ -48,7 +48,7 @@
 
 #include "scsi_debug.h"
 
-static const char * scsi_debug_version_str = "Version: 0.61 (20020815)";
+static const char * scsi_debug_version_str = "Version: 0.63 (20040831)";
 
 
 #ifndef SCSI_CMD_READ_16
@@ -73,7 +73,7 @@ static const char * scsi_debug_version_s
 #define SCSI_DEBUG_OPT_MEDIUM_ERR   2
 #define SCSI_DEBUG_OPT_EVERY_NTH   4
 
-#define OPT_MEDIUM_ERR_ADDR   0x1234
+#define OPT_MEDIUM_ERR_ADDR   0x1234  /* that's 4660 in decimal */
 
 static int scsi_debug_num_devs = DEF_NR_FAKE_DEVS;
 static int scsi_debug_opts = DEF_OPTS;
@@ -124,7 +124,7 @@ static struct sdebug_queued_cmd queued_a
 
 static unsigned char * fake_storep;	/* ramdisk storage */
 
-static unsigned char broken_buff[SDEBUG_SENSE_LEN];
+static unsigned char spare_buff[SDEBUG_SENSE_LEN];
 
 static int num_aborts = 0;
 static int num_dev_resets = 0;
@@ -193,8 +193,7 @@ int scsi_debug_queuecommand(Scsi_Cmnd * 
 	else 
 		buff = (unsigned char *) SCpnt->request_buffer;
 	if (NULL == buff) {
-		printk(KERN_WARNING "scsi_debug:qc: buff was NULL??\n");
-		buff = broken_buff;	/* just point at dummy */
+		buff = spare_buff;	/* just point at dummy */
 		bufflen = SDEBUG_SENSE_LEN;
 	}
 
@@ -370,7 +369,7 @@ int scsi_debug_queuecommand(Scsi_Cmnd * 
 		if ((errsts = check_reset(SCpnt, devip)))
 			break;
 		mk_sense_buffer(devip, ILLEGAL_REQUEST, 0x20, 0, 14);
-		errsts = (COMMAND_COMPLETE << 8) | (CHECK_CONDITION << 1);
+		errsts = (DRIVER_SENSE << 24) | (CHECK_CONDITION << 1);
 		break;
 	}
 	return schedule_resp(SCpnt, devip, done, errsts, scsi_debug_delay);
@@ -390,7 +389,7 @@ static int check_reset(Scsi_Cmnd * SCpnt
 	if (devip->reset) {
 		devip->reset = 0;
 		mk_sense_buffer(devip, UNIT_ATTENTION, 0x29, 0, 14);
-		return (COMMAND_COMPLETE << 8) | (CHECK_CONDITION << 1);
+		return (DRIVER_SENSE << 24) | (CHECK_CONDITION << 1);
 	}
 	return 0;
 }
@@ -451,7 +450,7 @@ static int resp_inquiry(unsigned char * 
 	arr[0] = pq_pdt;
 	if (0x2 & cmd[1]) {  /* CMDDT bit set */
 		mk_sense_buffer(devip, ILLEGAL_REQUEST, 0x24, 0, 14);
-		return (COMMAND_COMPLETE << 8) | (CHECK_CONDITION << 1);
+		return (DRIVER_SENSE << 24) | (CHECK_CONDITION << 1);
 	} else if (0x1 & cmd[1]) {  /* EVPD bit set */
 		int dev_id_num, len;
 		char dev_id_str[6];
@@ -476,7 +475,7 @@ static int resp_inquiry(unsigned char * 
 		} else {
 			/* Illegal request, invalid field in cdb */
 			mk_sense_buffer(devip, ILLEGAL_REQUEST, 0x24, 0, 14);
-			return (COMMAND_COMPLETE << 8) | (CHECK_CONDITION << 1);
+			return (DRIVER_SENSE << 24) | (CHECK_CONDITION << 1);
 		}
 		memcpy(buff, arr, min_len); 
 		return 0;
@@ -589,7 +588,7 @@ static int resp_mode_sense(unsigned char
 	memset(arr, 0, SDEBUG_MAX_MSENSE_SZ);
 	if (0x3 == pcontrol) {  /* Saving values not supported */
 		mk_sense_buffer(devip, ILLEGAL_REQUEST, 0x39, 0, 14);
-		return (COMMAND_COMPLETE << 8) | (CHECK_CONDITION << 1);
+		return (DRIVER_SENSE << 24) | (CHECK_CONDITION << 1);
 	}
 	dev_spec = DEV_READONLY(target) ? 0x80 : 0x0;
 	if (msense_6) {
@@ -631,7 +630,7 @@ static int resp_mode_sense(unsigned char
 		break;
 	default:
 		mk_sense_buffer(devip, ILLEGAL_REQUEST, 0x24, 0, 14);
-		return (COMMAND_COMPLETE << 8) | (CHECK_CONDITION << 1);
+		return (DRIVER_SENSE << 24) | (CHECK_CONDITION << 1);
 	}
 	if (msense_6)
 		arr[0] = offset - 1;
@@ -655,14 +654,14 @@ static int resp_read(Scsi_Cmnd * SCpnt, 
 
 	if (upper_blk || (block + num > CAPACITY)) {
 		mk_sense_buffer(devip, ILLEGAL_REQUEST, 0x21, 0, 14);
-		return (COMMAND_COMPLETE << 8) | (CHECK_CONDITION << 1);
+		return (DRIVER_SENSE << 24) | (CHECK_CONDITION << 1);
 	}
 	if ((SCSI_DEBUG_OPT_MEDIUM_ERR & scsi_debug_opts) &&
-	    (block >= OPT_MEDIUM_ERR_ADDR) && 
-	    (block < (OPT_MEDIUM_ERR_ADDR + num))) {
+	    (block <= OPT_MEDIUM_ERR_ADDR) &&
+            ((block + num) > OPT_MEDIUM_ERR_ADDR)) {
 		mk_sense_buffer(devip, MEDIUM_ERROR, 0x11, 0, 14);
 		/* claim unrecoverable read error */
-		return (COMMAND_COMPLETE << 8) | (CHECK_CONDITION << 1);
+		return (DRIVER_SENSE << 24) | (CHECK_CONDITION << 1);
 	}
 	read_lock_irqsave(&atomic_rw, iflags);
         sgcount = 0;
@@ -704,7 +703,7 @@ static int resp_write(Scsi_Cmnd * SCpnt,
 
 	if (upper_blk || (block + num > CAPACITY)) {
 		mk_sense_buffer(devip, ILLEGAL_REQUEST, 0x21, 0, 14);
-		return (COMMAND_COMPLETE << 8) | (CHECK_CONDITION << 1);
+		return (DRIVER_SENSE << 24) | (CHECK_CONDITION << 1);
 	}
 
 	write_lock_irqsave(&atomic_rw, iflags);
@@ -744,7 +743,7 @@ static int resp_report_luns(unsigned cha
 	alloc_len = cmd[9] + (cmd[8] << 8) + (cmd[7] << 16) + (cmd[6] << 24);
 	if ((alloc_len < 16) || (select_report > 2)) {
 		mk_sense_buffer(devip, ILLEGAL_REQUEST, 0x24, 0, 14);
-		return (COMMAND_COMPLETE << 8) | (CHECK_CONDITION << 1);
+		return (DRIVER_SENSE << 24) | (CHECK_CONDITION << 1);
 	}
 	if (bufflen > 3) {
 		memset(buff, 0, bufflen);
@@ -773,8 +772,10 @@ static void timer_intr_handler(unsigned 
 		return;
 	}
 	sqcp->in_use = 0;
-	if (sqcp->done_funct)
+	if (sqcp->done_funct) {
+		sqcp->a_cmnd->result = sqcp->scsi_result;
 		sqcp->done_funct(sqcp->a_cmnd); /* callback to mid level */
+	}
 	sqcp->done_funct = NULL;
 	spin_unlock_irqrestore(&queued_arr_lock, iflags);
 }
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/scsi/scsi_error.c linux-2.4.28-pre3/drivers/scsi/scsi_error.c
--- linux-2.4.27/drivers/scsi/scsi_error.c	2004-04-14 13:05:31.000000000 +0000
+++ linux-2.4.28-pre3/drivers/scsi/scsi_error.c	2004-09-10 19:31:58.000000000 +0000
@@ -664,7 +664,10 @@ STATIC void scsi_send_eh_cmnd(Scsi_Cmnd 
 			SCpnt->eh_state = SUCCESS;
 			break;
 		case NEEDS_RETRY:
-			goto retry;
+			if ((++SCpnt->retries) < SCpnt->allowed)
+				goto retry;
+			SCpnt->eh_state = SUCCESS;
+			break;
 		case FAILED:
 		default:
 			SCpnt->eh_state = FAILED;
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/scsi/scsi_merge.c linux-2.4.28-pre3/drivers/scsi/scsi_merge.c
--- linux-2.4.27/drivers/scsi/scsi_merge.c	2002-11-28 23:53:14.000000000 +0000
+++ linux-2.4.28-pre3/drivers/scsi/scsi_merge.c	2004-09-10 19:36:55.000000000 +0000
@@ -418,7 +418,7 @@ __inline static int __scsi_back_merge_fn
 		return 0;
 
 	if (!BH_PHYS_4G(req->bhtail, bh))
-		return 0;
+		goto new_end_segment;
 
 	if (use_clustering) {
 		/* 
@@ -477,7 +477,7 @@ __inline static int __scsi_front_merge_f
 		return 0;
 
 	if (!BH_PHYS_4G(bh, req->bh))
-		return 0;
+		goto new_start_segment;
 
 	if (use_clustering) {
 		/* 
@@ -640,7 +640,7 @@ __inline static int __scsi_merge_request
 		return 0;
 
 	if (!BH_PHYS_4G(req->bhtail, next->bh))
-		return 0;
+		goto dont_combine;
 
 	/*
 	 * The main question is whether the two segments at the boundaries
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/scsi/scsi_scan.c linux-2.4.28-pre3/drivers/scsi/scsi_scan.c
--- linux-2.4.27/drivers/scsi/scsi_scan.c	2004-08-07 23:26:05.000000000 +0000
+++ linux-2.4.28-pre3/drivers/scsi/scsi_scan.c	2004-09-10 19:36:19.000000000 +0000
@@ -157,6 +157,7 @@ static struct dev_info device_list[] =
  	{"TOSHIBA","CDROM","*", BLIST_ISROM},
  	{"TOSHIBA","CD-ROM","*", BLIST_ISROM},
 	{"MegaRAID", "LD", "*", BLIST_FORCELUN},
+	{"3PARdata", "VV", "*", BLIST_SPARSELUN | BLIST_LARGELUN},    // 3PARdata InServ Virtual Volume
 	{"DGC",  "RAID",      "*", BLIST_SPARSELUN | BLIST_LARGELUN}, // Dell PV 650F (tgt @ LUN 0)
 	{"DGC",  "DISK",      "*", BLIST_SPARSELUN | BLIST_LARGELUN}, // Dell PV 650F (no tgt @ LUN 0) 
 	{"DELL", "PV660F",   "*", BLIST_SPARSELUN | BLIST_LARGELUN},
@@ -189,6 +190,7 @@ static struct dev_info device_list[] =
 	{"HITACHI", "DF500", "*", BLIST_SPARSELUN},
 	{"HITACHI", "DF600", "*", BLIST_SPARSELUN},
 	{"IBM", "ProFibre 4000R", "*", BLIST_SPARSELUN | BLIST_LARGELUN},
+	{"IOI", "Media Bay", "*", BLIST_FORCELUN},
 	{"HITACHI", "OPEN-", "*", BLIST_SPARSELUN | BLIST_LARGELUN},  /* HITACHI XP Arrays */
 	{"HITACHI", "DISK-SUBSYSTEM", "*", BLIST_SPARSELUN | BLIST_LARGELUN},  /* HITACHI 9960 */
 	{"WINSYS","FLASHDISK G6", "*", BLIST_SPARSELUN},
@@ -208,6 +210,7 @@ static struct dev_info device_list[] =
 	{"SMSC", "USB 2 HS", "*", BLIST_SPARSELUN | BLIST_LARGELUN}, 
 	{"XYRATEX", "RS", "*", BLIST_SPARSELUN | BLIST_LARGELUN},
 	{"NEC", "iStorage", "*", BLIST_SPARSELUN | BLIST_LARGELUN | BLIST_FORCELUN},
+	{"Xyratex", "4200", "*", BLIST_SPARSELUN | BLIST_LARGELUN},
 
 	/*
 	 * Must be at end of list...
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/scsi/scsiiom.c linux-2.4.28-pre3/drivers/scsi/scsiiom.c
--- linux-2.4.27/drivers/scsi/scsiiom.c	2000-12-31 19:06:00.000000000 +0000
+++ linux-2.4.28-pre3/drivers/scsi/scsiiom.c	2004-09-10 19:32:17.000000000 +0000
@@ -211,6 +211,24 @@ dc390_dma_intr (PACB pACB)
 };
 #endif
 
+static void __inline__
+dc390_InvalidCmd( PACB pACB )
+{
+    if( pACB->pActiveDCB->pActiveSRB->SRBState & (SRB_START_+SRB_MSGOUT) )
+	DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD);
+}
+
+#define DC390_ENABLE_MSGOUT DC390_write8 (ScsiCmd, SET_ATN_CMD)
+
+/* abort command */
+static void __inline__
+dc390_EnableMsgOut_Abort ( PACB pACB, PSRB pSRB )
+{
+    pSRB->MsgOutBuf[0] = ABORT; 
+    pSRB->MsgCnt = 1; DC390_ENABLE_MSGOUT;
+    pSRB->pSRBDCB->DCBFlag &= ~ABORT_DEV_;
+}
+
 void __inline__
 DC390_Interrupt( int irq, void *dev_id, struct pt_regs *regs)
 {
@@ -569,8 +587,6 @@ dc390_printMsg (UCHAR *MsgBuf, UCHAR len
 };
 #endif
 
-#define DC390_ENABLE_MSGOUT DC390_write8 (ScsiCmd, SET_ATN_CMD)
-
 /* reject_msg */
 static void __inline__
 dc390_MsgIn_reject (PACB pACB, PSRB pSRB)
@@ -580,15 +596,6 @@ dc390_MsgIn_reject (PACB pACB, PSRB pSRB
   DEBUG0 (printk (KERN_INFO "DC390: Reject message\n");)
 }
 
-/* abort command */
-static void __inline__
-dc390_EnableMsgOut_Abort ( PACB pACB, PSRB pSRB )
-{
-    pSRB->MsgOutBuf[0] = ABORT; 
-    pSRB->MsgCnt = 1; DC390_ENABLE_MSGOUT;
-    pSRB->pSRBDCB->DCBFlag &= ~ABORT_DEV_;
-}
-
 static PSRB
 dc390_MsgIn_QTag (PACB pACB, PDCB pDCB, UCHAR tag)
 {
@@ -1355,6 +1362,47 @@ dc390_add_dev (PACB pACB, PDCB pDCB, PSC
 };
 
 
+static void __inline__
+dc390_RequestSense( PACB pACB, PDCB pDCB, PSRB pSRB )
+{
+    PSCSICMD  pcmd;
+
+    REMOVABLEDEBUG(printk (KERN_INFO "DC390: RequestSense (Cmd %02x, Id %02x, LUN %02x)\n",\
+	    pSRB->pcmd->cmnd[0], pDCB->TargetID, pDCB->TargetLUN);)
+
+    pSRB->SRBFlag |= AUTO_REQSENSE;
+    //pSRB->Segment0[0] = (UINT) pSRB->CmdBlock[0];
+    //pSRB->Segment0[1] = (UINT) pSRB->CmdBlock[4];
+    //pSRB->Segment1[0] = ((UINT)(pSRB->pcmd->cmd_len) << 8) + pSRB->SGcount;
+    //pSRB->Segment1[1] = pSRB->TotalXferredLen;
+    pSRB->SavedSGCount = pSRB->SGcount;
+    pSRB->SavedTotXLen = pSRB->TotalXferredLen;
+    pSRB->AdaptStatus = 0;
+    pSRB->TargetStatus = 0; /* CHECK_CONDITION<<1; */
+
+    pcmd = pSRB->pcmd;
+
+    pSRB->Segmentx.address = (PUCHAR) &(pcmd->sense_buffer);
+    pSRB->Segmentx.length = sizeof(pcmd->sense_buffer);
+    pSRB->pSegmentList = &pSRB->Segmentx;
+    pSRB->SGcount = 1;
+    pSRB->SGIndex = 0;
+
+    //pSRB->CmdBlock[0] = REQUEST_SENSE;
+    //pSRB->CmdBlock[1] = pDCB->TargetLUN << 5;
+    //(USHORT) pSRB->CmdBlock[2] = 0;
+    //(USHORT) pSRB->CmdBlock[4] = sizeof(pcmd->sense_buffer);
+    //pSRB->ScsiCmdLen = 6;
+
+    pSRB->TotalXferredLen = 0;
+    pSRB->SGToBeXferLen = 0;
+    if( dc390_StartSCSI( pACB, pDCB, pSRB ) ) {
+	dc390_Going_to_Waiting ( pDCB, pSRB );
+	dc390_waiting_timer (pACB, HZ/5);
+    }
+}
+
+
 void
 dc390_SRBdone( PACB pACB, PDCB pDCB, PSRB pSRB )
 {
@@ -1738,53 +1786,3 @@ dc390_ScsiRstDetect( PACB pACB )
     return;
 }
 
-
-static void __inline__
-dc390_RequestSense( PACB pACB, PDCB pDCB, PSRB pSRB )
-{
-    PSCSICMD  pcmd;
-
-    REMOVABLEDEBUG(printk (KERN_INFO "DC390: RequestSense (Cmd %02x, Id %02x, LUN %02x)\n",\
-	    pSRB->pcmd->cmnd[0], pDCB->TargetID, pDCB->TargetLUN);)
-
-    pSRB->SRBFlag |= AUTO_REQSENSE;
-    //pSRB->Segment0[0] = (UINT) pSRB->CmdBlock[0];
-    //pSRB->Segment0[1] = (UINT) pSRB->CmdBlock[4];
-    //pSRB->Segment1[0] = ((UINT)(pSRB->pcmd->cmd_len) << 8) + pSRB->SGcount;
-    //pSRB->Segment1[1] = pSRB->TotalXferredLen;
-    pSRB->SavedSGCount = pSRB->SGcount;
-    pSRB->SavedTotXLen = pSRB->TotalXferredLen;
-    pSRB->AdaptStatus = 0;
-    pSRB->TargetStatus = 0; /* CHECK_CONDITION<<1; */
-
-    pcmd = pSRB->pcmd;
-
-    pSRB->Segmentx.address = (PUCHAR) &(pcmd->sense_buffer);
-    pSRB->Segmentx.length = sizeof(pcmd->sense_buffer);
-    pSRB->pSegmentList = &pSRB->Segmentx;
-    pSRB->SGcount = 1;
-    pSRB->SGIndex = 0;
-
-    //pSRB->CmdBlock[0] = REQUEST_SENSE;
-    //pSRB->CmdBlock[1] = pDCB->TargetLUN << 5;
-    //(USHORT) pSRB->CmdBlock[2] = 0;
-    //(USHORT) pSRB->CmdBlock[4] = sizeof(pcmd->sense_buffer);
-    //pSRB->ScsiCmdLen = 6;
-
-    pSRB->TotalXferredLen = 0;
-    pSRB->SGToBeXferLen = 0;
-    if( dc390_StartSCSI( pACB, pDCB, pSRB ) ) {
-	dc390_Going_to_Waiting ( pDCB, pSRB );
-	dc390_waiting_timer (pACB, HZ/5);
-    }
-}
-
-
-
-static void __inline__
-dc390_InvalidCmd( PACB pACB )
-{
-    if( pACB->pActiveDCB->pActiveSRB->SRBState & (SRB_START_+SRB_MSGOUT) )
-	DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD);
-}
-
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/scsi/seagate.c linux-2.4.28-pre3/drivers/scsi/seagate.c
--- linux-2.4.27/drivers/scsi/seagate.c	2003-08-25 11:44:42.000000000 +0000
+++ linux-2.4.28-pre3/drivers/scsi/seagate.c	2004-09-10 19:34:33.000000000 +0000
@@ -698,7 +698,7 @@ int seagate_st0x_queue_command (Scsi_Cmn
 	done_fn = done;
 	current_target = SCpnt->target;
 	current_lun = SCpnt->lun;
-	(const void *) current_cmnd = SCpnt->cmnd;
+	current_cmnd = SCpnt->cmnd;
 	current_data = (unsigned char *) SCpnt->request_buffer;
 	current_bufflen = SCpnt->request_bufflen;
 	SCint = SCpnt;
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/scsi/sg.c linux-2.4.28-pre3/drivers/scsi/sg.c
--- linux-2.4.27/drivers/scsi/sg.c	2003-11-28 18:26:20.000000000 +0000
+++ linux-2.4.28-pre3/drivers/scsi/sg.c	2004-09-10 19:34:39.000000000 +0000
@@ -742,6 +742,16 @@ static int sg_common_write(Sg_fd * sfp, 
     return 0;
 }
 
+static inline unsigned sg_jif_to_ms(int jifs)
+{
+    if (jifs <= 0)
+	return 0U;
+    else {
+	unsigned int j = (unsigned int)jifs;
+	return (j < (UINT_MAX / 1000)) ? ((j * 1000) / HZ) : ((j / HZ) * 1000);
+    }
+}
+
 static int sg_ioctl(struct inode * inode, struct file * filp,
                     unsigned int cmd_in, unsigned long arg)
 {
@@ -1640,6 +1650,24 @@ static int sg_build_sgat(Sg_scatter_hold
     return mx_sc_elems; /* number of scat_gath elements allocated */
 }
 
+static inline int sg_alloc_kiovec(int nr, struct kiobuf **bufp, int *szp)
+{
+#if SG_NEW_KIOVEC
+    return alloc_kiovec_sz(nr, bufp, szp);
+#else
+    return alloc_kiovec(nr, bufp);
+#endif
+}
+
+static inline void sg_free_kiovec(int nr, struct kiobuf **bufp, int *szp)
+{
+#if SG_NEW_KIOVEC
+    free_kiovec_sz(nr, bufp, szp);
+#else
+    free_kiovec(nr, bufp);
+#endif
+}
+
 static void sg_unmap_and(Sg_scatter_hold * schp, int free_also)
 {
 #ifdef SG_ALLOW_DIO_CODE
@@ -2568,15 +2596,6 @@ static char * sg_malloc(const Sg_fd * sf
     return resp;
 }
 
-static inline int sg_alloc_kiovec(int nr, struct kiobuf **bufp, int *szp)
-{
-#if SG_NEW_KIOVEC
-    return alloc_kiovec_sz(nr, bufp, szp);
-#else
-    return alloc_kiovec(nr, bufp);
-#endif
-}
-
 static void sg_low_free(char * buff, int size, int mem_src)
 {
     if (! buff) return;
@@ -2620,15 +2639,6 @@ static void sg_free(char * buff, int siz
         sg_low_free(buff, size, mem_src);
 }
 
-static inline void sg_free_kiovec(int nr, struct kiobuf **bufp, int *szp)
-{
-#if SG_NEW_KIOVEC
-    free_kiovec_sz(nr, bufp, szp);
-#else
-    free_kiovec(nr, bufp);
-#endif
-}
-
 static int sg_ms_to_jif(unsigned int msecs)
 {
     if ((UINT_MAX / 2U) < msecs)
@@ -2638,16 +2648,6 @@ static int sg_ms_to_jif(unsigned int mse
 					       : (((int)msecs / 1000) * HZ);
 }
 
-static inline unsigned sg_jif_to_ms(int jifs)
-{
-    if (jifs <= 0)
-	return 0U;
-    else {
-	unsigned int j = (unsigned int)jifs;
-	return (j < (UINT_MAX / 1000)) ? ((j * 1000) / HZ) : ((j / HZ) * 1000);
-    }
-}
-
 static unsigned char allow_ops[] = {TEST_UNIT_READY, REQUEST_SENSE,
 INQUIRY, READ_CAPACITY, READ_BUFFER, READ_6, READ_10, READ_12,
 MODE_SENSE, MODE_SENSE_10, LOG_SENSE};
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/scsi/sim710.c linux-2.4.28-pre3/drivers/scsi/sim710.c
--- linux-2.4.27/drivers/scsi/sim710.c	2002-08-03 00:39:44.000000000 +0000
+++ linux-2.4.28-pre3/drivers/scsi/sim710.c	2004-09-10 19:36:28.000000000 +0000
@@ -921,172 +921,6 @@ handle_script_int(struct Scsi_Host * hos
 }
 
 
-/* A quick wrapper for sim710_intr_handle to grab the spin lock */
-
-static void
-do_sim710_intr_handle(int irq, void *dev_id, struct pt_regs *regs)
-{
-    unsigned long flags;
-
-    spin_lock_irqsave(&io_request_lock, flags);
-    sim710_intr_handle(irq, dev_id, regs);
-    spin_unlock_irqrestore(&io_request_lock, flags);
-}
-
-
-/* A "high" level interrupt handler */
-
-static void
-sim710_intr_handle(int irq, void *dev_id, struct pt_regs *regs)
-{
-    struct Scsi_Host * host = (struct Scsi_Host *)dev_id;
-    struct sim710_hostdata *hostdata = (struct sim710_hostdata *)host->hostdata[0];
-    Scsi_Cmnd * cmd;
-    unsigned char istat, dstat;
-    unsigned char sstat0;
-    u32 scratch, dsps, resume_offset = 0;
-
-    istat = NCR_read8(ISTAT_REG);
-    if (!(istat & (ISTAT_SIP|ISTAT_DIP)))
-	return;
-    else {
-	sim710_intrs++;
-	dsps = NCR_read32(DSPS_REG);
-	hostdata->state = STATE_HALTED;
-	sstat0 = dstat = 0;
-	scratch = NCR_read32(SCRATCH_REG);
-	if (istat & ISTAT_SIP) {
-	    sstat0 = NCR_read8(SSTAT0_REG);
-	}
-	if (istat & ISTAT_DIP) {
-	    udelay(10);		/* Some comment somewhere about 10cycles
-				 * between accesses to sstat0 and dstat ??? */
-	    dstat = NCR_read8(DSTAT_REG);
-	}
-	DEB(DEB_INTS, printk("scsi%d: Int %d, istat %02x, sstat0 %02x "
-		"dstat %02x, dsp [%04x], scratch %02x\n",
-	    host->host_no, sim710_intrs, istat, sstat0, dstat,
-	    (u32 *)(bus_to_virt(NCR_read32(DSP_REG))) - hostdata->script,
-	    scratch));
-	if (scratch & 0x100) {
-	    u8 *p = hostdata->msgin_buf;
-
-	    DEB(DEB_INTS, printk("  msgin_buf: %02x %02x %02x %02x\n",
-			p[0], p[1], p[2], p[3]));
-	}
-	if ((dstat & DSTAT_SIR) && dsps == A_int_reselected) {
-	    /* Reselected.  Identify the target from LCRC_REG, and
-	     * update current command.  If we were trying to select
-	     * a device, then that command needs to go back on the
-	     * issue_queue for later.
-	     */
-	    unsigned char lcrc = NCR_read8(LCRC_REG_10);
-	    int id = 0;
-
-	    if (!(lcrc & 0x7f)) {
-		printk("scsi%d: Reselected with LCRC = %02x\n",
-			host->host_no, lcrc);
-		cmd = NULL;
-	    }
-	    else {
-		while (!(lcrc & 1)) {
-		    id++;
-		    lcrc >>= 1;
-		}
-		DEB(DEB_DISC, printk("scsi%d: Reselected by ID %d\n",
-			host->host_no, id));
-		if (hostdata->running) {
-		    /* Clear SIGP */
-		    (void)NCR_read8(CTEST2_REG_700);
-
-		    DEB(DEB_DISC, printk("scsi%d: Select of %d interrupted "
-				"by reselect from %d (%p)\n",
-				host->host_no, hostdata->running->target,
-				id, hostdata->target[id].cur_cmd));
-		    cmd = hostdata->running;
-		    hostdata->target[cmd->target].cur_cmd = NULL;
-		    cmd->SCp.ptr = (unsigned char *) hostdata->issue_queue;
-		    hostdata->issue_queue = cmd;
-		}
-		cmd = hostdata->running = hostdata->target[id].cur_cmd;
-	    }
-	}
-	else
-	    cmd = hostdata->running;
-
-	if (!cmd) {
-	    printk("scsi%d: No active command!\n", host->host_no);
-	    printk("scsi%d: Int %d, istat %02x, sstat0 %02x "
-		"dstat %02x, dsp [%04x], scratch %02x, dsps %08x\n",
-		host->host_no, sim710_intrs, istat, sstat0, dstat,
-		(u32 *)(bus_to_virt(NCR_read32(DSP_REG))) - hostdata->script,
-		NCR_read32(SCRATCH_REG), dsps);
-	    /* resume_offset is zero, which will cause a host reset */
-	}
-	else if (sstat0 & SSTAT0_700_STO) {
-	    DEB(DEB_TOUT, printk("scsi%d: Selection timeout\n", host->host_no));
-	    cmd->result = DID_NO_CONNECT << 16;
-	    SCSI_DONE(cmd);
-	    hostdata->target[cmd->target].cur_cmd = NULL;
-	    resume_offset = Ent_reselect;
-	}
-	else if (sstat0 & (SSTAT0_SGE|SSTAT0_UDC|SSTAT0_RST|SSTAT0_PAR)) {
-	    printk("scsi%d: Serious error, sstat0 = %02x\n", host->host_no,
-			    sstat0);
-	    sim710_errors++;
-	    /* resume_offset is zero, which will cause a host reset */
-	}
-	else if (dstat & (DSTAT_BF|DSTAT_ABRT|DSTAT_SSI|DSTAT_WTD)) {
-	    printk("scsi%d: Serious error, dstat = %02x\n", host->host_no,
-			    dstat);
-	    sim710_errors++;
-	    /* resume_offset is zero, which will cause a host reset */
-	}
-	else if (dstat & DSTAT_SIR)
-	    resume_offset = handle_script_int(host, cmd);
-	else if (sstat0 & SSTAT0_MA)
-	    resume_offset = handle_phase_mismatch(host, cmd);
-	else if (dstat & DSTAT_IID) {
-	    /* This can be due to a quick reselect while doing a WAIT
-	     * DISCONNECT.
-	     */
-	    resume_offset = handle_idd(host, cmd);
-	}
-	else {
-	    sim710_errors++;
-	    printk("scsi%d: Spurious interrupt!\n", host->host_no);
-	    /* resume_offset is zero, which will cause a host reset */
-	}
-    }
-
-    if (resume_offset) {
-	if (resume_offset == Ent_reselect) {
-	    hostdata->running = NULL;
-	    hostdata->state = STATE_IDLE;
-	}
-	else
-	    hostdata->state = STATE_BUSY;
-	DEB(DEB_RESUME, printk("scsi%d: Resuming at script[0x%x]\n",
-		host->host_no, resume_offset/4));
-#ifdef DEBUG_LIMIT_INTS
-	if (sim710_intrs < DEBUG_LIMIT_INTS)
-#endif
-	{
-	    NCR_write32(SCRATCH_REG, 0);
-	    NCR_write32(DSP_REG, virt_to_bus(hostdata->script+resume_offset/4));
-	}
-	if (resume_offset == Ent_reselect)
-	    run_process_issue_queue(hostdata);
-    }
-    else {
-	printk("scsi%d: Failed to handle interrupt.  Failing commands "
-		"and resetting SCSI bus and chip\n", host->host_no);
-	mdelay(1000);		/* Give chance to read screen!! */
-	full_reset(host);
-    }
-}
-
-
 static void
 run_command (struct sim710_hostdata *hostdata, Scsi_Cmnd *cmd)
 {
@@ -1284,6 +1118,172 @@ process_issue_queue (struct sim710_hostd
 }
 
 
+/* A quick wrapper for sim710_intr_handle to grab the spin lock */
+
+static void
+do_sim710_intr_handle(int irq, void *dev_id, struct pt_regs *regs)
+{
+    unsigned long flags;
+
+    spin_lock_irqsave(&io_request_lock, flags);
+    sim710_intr_handle(irq, dev_id, regs);
+    spin_unlock_irqrestore(&io_request_lock, flags);
+}
+
+
+/* A "high" level interrupt handler */
+
+static void
+sim710_intr_handle(int irq, void *dev_id, struct pt_regs *regs)
+{
+    struct Scsi_Host * host = (struct Scsi_Host *)dev_id;
+    struct sim710_hostdata *hostdata = (struct sim710_hostdata *)host->hostdata[0];
+    Scsi_Cmnd * cmd;
+    unsigned char istat, dstat;
+    unsigned char sstat0;
+    u32 scratch, dsps, resume_offset = 0;
+
+    istat = NCR_read8(ISTAT_REG);
+    if (!(istat & (ISTAT_SIP|ISTAT_DIP)))
+	return;
+    else {
+	sim710_intrs++;
+	dsps = NCR_read32(DSPS_REG);
+	hostdata->state = STATE_HALTED;
+	sstat0 = dstat = 0;
+	scratch = NCR_read32(SCRATCH_REG);
+	if (istat & ISTAT_SIP) {
+	    sstat0 = NCR_read8(SSTAT0_REG);
+	}
+	if (istat & ISTAT_DIP) {
+	    udelay(10);		/* Some comment somewhere about 10cycles
+				 * between accesses to sstat0 and dstat ??? */
+	    dstat = NCR_read8(DSTAT_REG);
+	}
+	DEB(DEB_INTS, printk("scsi%d: Int %d, istat %02x, sstat0 %02x "
+		"dstat %02x, dsp [%04x], scratch %02x\n",
+	    host->host_no, sim710_intrs, istat, sstat0, dstat,
+	    (u32 *)(bus_to_virt(NCR_read32(DSP_REG))) - hostdata->script,
+	    scratch));
+	if (scratch & 0x100) {
+	    u8 *p = hostdata->msgin_buf;
+
+	    DEB(DEB_INTS, printk("  msgin_buf: %02x %02x %02x %02x\n",
+			p[0], p[1], p[2], p[3]));
+	}
+	if ((dstat & DSTAT_SIR) && dsps == A_int_reselected) {
+	    /* Reselected.  Identify the target from LCRC_REG, and
+	     * update current command.  If we were trying to select
+	     * a device, then that command needs to go back on the
+	     * issue_queue for later.
+	     */
+	    unsigned char lcrc = NCR_read8(LCRC_REG_10);
+	    int id = 0;
+
+	    if (!(lcrc & 0x7f)) {
+		printk("scsi%d: Reselected with LCRC = %02x\n",
+			host->host_no, lcrc);
+		cmd = NULL;
+	    }
+	    else {
+		while (!(lcrc & 1)) {
+		    id++;
+		    lcrc >>= 1;
+		}
+		DEB(DEB_DISC, printk("scsi%d: Reselected by ID %d\n",
+			host->host_no, id));
+		if (hostdata->running) {
+		    /* Clear SIGP */
+		    (void)NCR_read8(CTEST2_REG_700);
+
+		    DEB(DEB_DISC, printk("scsi%d: Select of %d interrupted "
+				"by reselect from %d (%p)\n",
+				host->host_no, hostdata->running->target,
+				id, hostdata->target[id].cur_cmd));
+		    cmd = hostdata->running;
+		    hostdata->target[cmd->target].cur_cmd = NULL;
+		    cmd->SCp.ptr = (unsigned char *) hostdata->issue_queue;
+		    hostdata->issue_queue = cmd;
+		}
+		cmd = hostdata->running = hostdata->target[id].cur_cmd;
+	    }
+	}
+	else
+	    cmd = hostdata->running;
+
+	if (!cmd) {
+	    printk("scsi%d: No active command!\n", host->host_no);
+	    printk("scsi%d: Int %d, istat %02x, sstat0 %02x "
+		"dstat %02x, dsp [%04x], scratch %02x, dsps %08x\n",
+		host->host_no, sim710_intrs, istat, sstat0, dstat,
+		(u32 *)(bus_to_virt(NCR_read32(DSP_REG))) - hostdata->script,
+		NCR_read32(SCRATCH_REG), dsps);
+	    /* resume_offset is zero, which will cause a host reset */
+	}
+	else if (sstat0 & SSTAT0_700_STO) {
+	    DEB(DEB_TOUT, printk("scsi%d: Selection timeout\n", host->host_no));
+	    cmd->result = DID_NO_CONNECT << 16;
+	    SCSI_DONE(cmd);
+	    hostdata->target[cmd->target].cur_cmd = NULL;
+	    resume_offset = Ent_reselect;
+	}
+	else if (sstat0 & (SSTAT0_SGE|SSTAT0_UDC|SSTAT0_RST|SSTAT0_PAR)) {
+	    printk("scsi%d: Serious error, sstat0 = %02x\n", host->host_no,
+			    sstat0);
+	    sim710_errors++;
+	    /* resume_offset is zero, which will cause a host reset */
+	}
+	else if (dstat & (DSTAT_BF|DSTAT_ABRT|DSTAT_SSI|DSTAT_WTD)) {
+	    printk("scsi%d: Serious error, dstat = %02x\n", host->host_no,
+			    dstat);
+	    sim710_errors++;
+	    /* resume_offset is zero, which will cause a host reset */
+	}
+	else if (dstat & DSTAT_SIR)
+	    resume_offset = handle_script_int(host, cmd);
+	else if (sstat0 & SSTAT0_MA)
+	    resume_offset = handle_phase_mismatch(host, cmd);
+	else if (dstat & DSTAT_IID) {
+	    /* This can be due to a quick reselect while doing a WAIT
+	     * DISCONNECT.
+	     */
+	    resume_offset = handle_idd(host, cmd);
+	}
+	else {
+	    sim710_errors++;
+	    printk("scsi%d: Spurious interrupt!\n", host->host_no);
+	    /* resume_offset is zero, which will cause a host reset */
+	}
+    }
+
+    if (resume_offset) {
+	if (resume_offset == Ent_reselect) {
+	    hostdata->running = NULL;
+	    hostdata->state = STATE_IDLE;
+	}
+	else
+	    hostdata->state = STATE_BUSY;
+	DEB(DEB_RESUME, printk("scsi%d: Resuming at script[0x%x]\n",
+		host->host_no, resume_offset/4));
+#ifdef DEBUG_LIMIT_INTS
+	if (sim710_intrs < DEBUG_LIMIT_INTS)
+#endif
+	{
+	    NCR_write32(SCRATCH_REG, 0);
+	    NCR_write32(DSP_REG, virt_to_bus(hostdata->script+resume_offset/4));
+	}
+	if (resume_offset == Ent_reselect)
+	    run_process_issue_queue(hostdata);
+    }
+    else {
+	printk("scsi%d: Failed to handle interrupt.  Failing commands "
+		"and resetting SCSI bus and chip\n", host->host_no);
+	mdelay(1000);		/* Give chance to read screen!! */
+	full_reset(host);
+    }
+}
+
+
 int
 sim710_queuecommand(Scsi_Cmnd * cmd, void (*done)(Scsi_Cmnd *))
 {
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/sound/ac97_codec.c linux-2.4.28-pre3/drivers/sound/ac97_codec.c
--- linux-2.4.27/drivers/sound/ac97_codec.c	2003-11-28 18:26:20.000000000 +0000
+++ linux-2.4.28-pre3/drivers/sound/ac97_codec.c	2004-09-10 19:32:44.000000000 +0000
@@ -30,6 +30,9 @@
  **************************************************************************
  *
  * History
+ * Feb 25, 2004 Liam Girdwood
+ *  Added support for codecs that require a warm reset to power up.
+ *  Support for WM9713
  * May 02, 2003 Liam Girdwood <liam.girdwood@wolfsonmicro.com>
  *	Removed non existant WM9700
  *	Added support for WM9705, WM9708, WM9709, WM9710, WM9711
@@ -71,6 +74,7 @@ static int wolfson_init03(struct ac97_co
 static int wolfson_init04(struct ac97_codec * codec);
 static int wolfson_init05(struct ac97_codec * codec);
 static int wolfson_init11(struct ac97_codec * codec);
+static int wolfson_init13(struct ac97_codec * codec);
 static int tritech_init(struct ac97_codec * codec);
 static int tritech_maestro_init(struct ac97_codec * codec);
 static int sigmatel_9708_init(struct ac97_codec *codec);
@@ -107,6 +111,7 @@ static struct ac97_ops wolfson_ops03 = {
 static struct ac97_ops wolfson_ops04 = { wolfson_init04, NULL, NULL };
 static struct ac97_ops wolfson_ops05 = { wolfson_init05, NULL, NULL };
 static struct ac97_ops wolfson_ops11 = { wolfson_init11, NULL, NULL };
+static struct ac97_ops wolfson_ops13 = { wolfson_init13, NULL, NULL };
 static struct ac97_ops tritech_ops = { tritech_init, NULL, NULL };
 static struct ac97_ops tritech_m_ops = { tritech_maestro_init, NULL, NULL };
 static struct ac97_ops sigmatel_9708_ops = { sigmatel_9708_init, NULL, NULL };
@@ -150,6 +155,7 @@ static const struct {
 	{0x43525931, "Cirrus Logic CS4299 rev A", &crystal_digital_ops},
 	{0x43525933, "Cirrus Logic CS4299 rev C", &crystal_digital_ops},
 	{0x43525934, "Cirrus Logic CS4299 rev D", &crystal_digital_ops},
+	{0x43585430, "CXT48",			&default_ops,		AC97_DELUDED_MODEM },
 	{0x43585442, "CXT66",			&default_ops,		AC97_DELUDED_MODEM },
 	{0x44543031, "Diamond Technology DT0893", &default_ops},
 	{0x45838308, "ESS Allegro ES1988",	&null_ops},
@@ -168,6 +174,7 @@ static const struct {
 	{0x574D4C05, "Wolfson WM9705/WM9710",   &wolfson_ops05},
 	{0x574D4C09, "Wolfson WM9709",		&null_ops},
 	{0x574D4C12, "Wolfson WM9711/9712",	&wolfson_ops11},
+	{0x574D4C13, "Wolfson WM9713",	&wolfson_ops13, AC97_DEFAULT_POWER_OFF},
 	{0x83847600, "SigmaTel STAC????",	&null_ops},
 	{0x83847604, "SigmaTel STAC9701/3/4/5", &null_ops},
 	{0x83847605, "SigmaTel STAC9704",	&null_ops},
@@ -793,6 +800,9 @@ EXPORT_SYMBOL(ac97_release_codec);
  *	Currently codec_wait is used to wait for AC97 codec
  *	reset to complete. 
  *
+ *  Some codecs will power down when a register reset is
+ *  performed. We now check for such codecs.
+ *
  *	Returns 1 (true) on success, or 0 (false) on failure.
  */
  
@@ -805,35 +815,18 @@ int ac97_probe_codec(struct ac97_codec *
 	u16 f;
 	struct list_head *l;
 	struct ac97_driver *d;
-	
-	/* probing AC97 codec, AC97 2.0 says that bit 15 of register 0x00 (reset) should 
-	 * be read zero.
-	 *
-	 * FIXME: is the following comment outdated?  -jgarzik 
-	 * Probing of AC97 in this way is not reliable, it is not even SAFE !!
-	 */
-	codec->codec_write(codec, AC97_RESET, 0L);
 
-	/* also according to spec, we wait for codec-ready state */	
+	/* wait for codec-ready state */	
 	if (codec->codec_wait)
 		codec->codec_wait(codec);
 	else
 		udelay(10);
-
-	if ((audio = codec->codec_read(codec, AC97_RESET)) & 0x8000) {
-		printk(KERN_ERR "ac97_codec: %s ac97 codec not present\n",
-		       (codec->id & 0x2) ? (codec->id&1 ? "4th" : "Tertiary") 
-		       : (codec->id&1 ? "Secondary":  "Primary"));
-		return 0;
-	}
-
-	/* probe for Modem Codec */
-	codec->modem = ac97_check_modem(codec);
-	codec->name = NULL;
-	codec->codec_ops = &default_ops;
-
+	
+	/* will the codec power down if register reset ? */
 	id1 = codec->codec_read(codec, AC97_VENDOR_ID1);
 	id2 = codec->codec_read(codec, AC97_VENDOR_ID2);
+	codec->name = NULL;
+	codec->codec_ops = &null_ops;
 	for (i = 0; i < ARRAY_SIZE(ac97_codec_ids); i++) {
 		if (ac97_codec_ids[i].id == ((id1 << 16) | id2)) {
 			codec->type = ac97_codec_ids[i].id;
@@ -843,11 +836,35 @@ int ac97_probe_codec(struct ac97_codec *
 			break;
 		}
 	}
-
 	codec->model = (id1 << 16) | id2;
+	if ((codec->flags & AC97_DEFAULT_POWER_OFF) == 0) {
+		/* reset codec and wait for the ready bit before we continue */
+		codec->codec_write(codec, AC97_RESET, 0L);
+		if (codec->codec_wait)
+			codec->codec_wait(codec);
+		else
+			udelay(10);
+	}
 	
+	/* probing AC97 codec, AC97 2.0 says that bit 15 of register 0x00 (reset) should 
+	 * be read zero.
+	 *
+	 * FIXME: is the following comment outdated?  -jgarzik 
+	 * Probing of AC97 in this way is not reliable, it is not even SAFE !!
+	 */
+	if ((audio = codec->codec_read(codec, AC97_RESET)) & 0x8000) {
+		printk(KERN_ERR "ac97_codec: %s ac97 codec not present\n",
+		       (codec->id & 0x2) ? (codec->id&1 ? "4th" : "Tertiary") 
+		       : (codec->id&1 ? "Secondary":  "Primary"));
+		return 0;
+	}
+	
+	/* probe for Modem Codec */
+	codec->modem = ac97_check_modem(codec);
+	
+	/* enable SPDIF */
 	f = codec->codec_read(codec, AC97_EXTENDED_STATUS);
-	if(f & 4)
+	if((codec->codec_ops == &null_ops) && (f & 4))
 		codec->codec_ops = &default_digital_ops;
 	
 	/* A device which thinks its a modem but isnt */
@@ -916,11 +933,6 @@ static int ac97_init_mixer(struct ac97_c
 	codec->recmask_io = ac97_recmask_io;
 	codec->mixer_ioctl = ac97_mixer_ioctl;
 
-	/* codec specific initialization for 4-6 channel output or secondary codec stuff */
-	if (codec->codec_ops->init != NULL) {
-		codec->codec_ops->init(codec);
-	}
-
 	/* initialize mixer channel volumes */
 	for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) {
 		struct mixer_defaults *md = &mixer_defaults[i];
@@ -930,6 +942,11 @@ static int ac97_init_mixer(struct ac97_c
 			continue;
 		ac97_set_mixer(codec, md->mixer, md->value);
 	}
+	
+	/* codec specific initialization for 4-6 channel output or secondary codec stuff */
+	if (codec->codec_ops->init != NULL) {
+		codec->codec_ops->init(codec);
+	}
 
 	/*
 	 *	Volume is MUTE only on this device. We have to initialise
@@ -1085,6 +1102,19 @@ static int wolfson_init11(struct ac97_co
 	return 0;
 }
 
+/* WM9713 */
+static int wolfson_init13(struct ac97_codec * codec)
+{
+	codec->codec_write(codec, AC97_RECORD_GAIN, 0x00a0);	
+	codec->codec_write(codec, AC97_POWER_CONTROL, 0x0000);
+	codec->codec_write(codec, AC97_EXTENDED_MODEM_ID, 0xDA00);
+	codec->codec_write(codec, AC97_EXTEND_MODEM_STAT, 0x3810);
+	codec->codec_write(codec, AC97_PHONE_VOL, 0x0808);
+	codec->codec_write(codec, AC97_PCBEEP_VOL, 0x0808);
+
+	return 0;
+}
+
 static int tritech_init(struct ac97_codec * codec)
 {
 	codec->codec_write(codec, 0x26, 0x0300);
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/sound/i810_audio.c linux-2.4.28-pre3/drivers/sound/i810_audio.c
--- linux-2.4.27/drivers/sound/i810_audio.c	2004-08-07 23:26:05.000000000 +0000
+++ linux-2.4.28-pre3/drivers/sound/i810_audio.c	2004-09-10 19:36:12.000000000 +0000
@@ -304,6 +304,14 @@ static struct pci_device_id i810_pci_tbl
 	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, NVIDIA_NFORCE},
 	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_MCP3_AUDIO,
 	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, NVIDIA_NFORCE},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_MCP2S_AUDIO,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, NVIDIA_NFORCE},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_CK8S_AUDIO,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, NVIDIA_NFORCE},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_CK804_AUDIO,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, NVIDIA_NFORCE},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_MCP04_AUDIO,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, NVIDIA_NFORCE},
 	{PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_OPUS_7445,
 	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, AMD768},
 	{PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8111_AUDIO,
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/usb/devices.c linux-2.4.28-pre3/drivers/usb/devices.c
--- linux-2.4.27/drivers/usb/devices.c	2002-11-28 23:53:14.000000000 +0000
+++ linux-2.4.28-pre3/drivers/usb/devices.c	2004-09-10 19:34:31.000000000 +0000
@@ -387,22 +387,31 @@ static char *usb_dump_desc(char *start, 
 
 	if (start > end)
 		return start;
-		
+
+	/*
+	 * Grab device's exclusive_access mutex to prevent its driver or
+	 * devio from using this device while we are accessing it.
+	 */
+	down (&dev->exclusive_access);
+
 	start = usb_dump_device_descriptor(start, end, &dev->descriptor);
 
 	if (start > end)
-		return start;
-	
+		goto out;
+
 	start = usb_dump_device_strings (start, end, dev);
 	
 	for (i = 0; i < dev->descriptor.bNumConfigurations; i++) {
 		if (start > end)
-			return start;
+			goto out;
 		start = usb_dump_config(dev->speed,
 				start, end, dev->config + i,
 				/* active ? */
 				(dev->config + i) == dev->actconfig);
 	}
+
+out:
+	up (&dev->exclusive_access);
 	return start;
 }
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/usb/devio.c linux-2.4.28-pre3/drivers/usb/devio.c
--- linux-2.4.27/drivers/usb/devio.c	2004-08-07 23:26:05.000000000 +0000
+++ linux-2.4.28-pre3/drivers/usb/devio.c	2004-09-10 19:34:52.000000000 +0000
@@ -1158,6 +1158,13 @@ static int usbdev_ioctl(struct inode *in
 		up_read(&ps->devsem);
 		return -ENODEV;
 	}
+
+	/*
+	 * grab device's exclusive_access mutex to prevent its driver from
+	 * using this device while it is being accessed by us.
+	 */
+	down(&ps->dev->exclusive_access);
+
 	switch (cmd) {
 	case USBDEVFS_CONTROL:
 		ret = proc_control(ps, (void *)arg);
@@ -1237,6 +1244,7 @@ static int usbdev_ioctl(struct inode *in
 		ret = proc_ioctl(ps, (void *) arg);
 		break;
 	}
+	up(&ps->dev->exclusive_access);
 	up_read(&ps->devsem);
 	if (ret >= 0)
 		inode->i_atime = CURRENT_TIME;
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/usb/gadget/net2280.c linux-2.4.28-pre3/drivers/usb/gadget/net2280.c
--- linux-2.4.27/drivers/usb/gadget/net2280.c	2004-04-14 13:05:32.000000000 +0000
+++ linux-2.4.28-pre3/drivers/usb/gadget/net2280.c	2004-09-10 19:33:30.000000000 +0000
@@ -537,7 +537,10 @@ write_fifo (struct net2280_ep *ep, struc
 	}
 
 	/* write just one packet at a time */
-	count = min (ep->ep.maxpacket, total);
+	count = ep->ep.maxpacket;
+	if (count > total)	/* min() cannot be used on a bitfield */
+		count = total;
+
 	VDEBUG (ep->dev, "write %s fifo (IN) %d bytes%s req %p\n",
 			ep->ep.name, count,
 			(count != ep->ep.maxpacket) ? " (short)" : "",
@@ -2191,7 +2194,8 @@ static void handle_ep_small (struct net2
 		unsigned	len;
 
 		len = req->req.length - req->req.actual;
-		len = min (ep->ep.maxpacket, len);
+		if (len > ep->ep.maxpacket)
+			len = ep->ep.maxpacket;
 		req->req.actual += len;
 
 		/* if we wrote it all, we're usually done */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/usb/hid-core.c linux-2.4.28-pre3/drivers/usb/hid-core.c
--- linux-2.4.27/drivers/usb/hid-core.c	2004-04-14 13:05:32.000000000 +0000
+++ linux-2.4.28-pre3/drivers/usb/hid-core.c	2004-09-10 19:35:22.000000000 +0000
@@ -620,14 +620,16 @@ static __u8 *fetch_item(__u8 *start, __u
 
 				case 2:
 					if ((end - start) >= 2) {
-						item->data.u16 = le16_to_cpu( get_unaligned(((__u16*)start)++));
+						item->data.u16 = le16_to_cpu(get_unaligned((__u16*)start));
+						start = (__u8 *)((__u16 *)start + 1);
 						return start;
 					}
 
 				case 3:
 					item->size++;
 					if ((end - start) >= 4) {
-						item->data.u32 = le32_to_cpu( get_unaligned(((__u32*)start)++));
+						item->data.u32 = le32_to_cpu(get_unaligned((__u32*)start));
+						start = (__u8 *)((__u32 *)start + 1);
 						return start;
 					}
 			}
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/usb/host/ehci-hcd.c linux-2.4.28-pre3/drivers/usb/host/ehci-hcd.c
--- linux-2.4.27/drivers/usb/host/ehci-hcd.c	2004-08-07 23:26:05.000000000 +0000
+++ linux-2.4.28-pre3/drivers/usb/host/ehci-hcd.c	2004-09-10 19:34:48.000000000 +0000
@@ -303,7 +303,8 @@ static int bios_handoff (struct ehci_hcd
 		if (cap & (1 << 16)) {
 			ehci_err (ehci, "BIOS handoff failed (%d, %04x)\n",
 				where, cap);
-			return 1;
+			pci_write_config_dword (ehci->hcd.pdev, where, 0);
+			return 0;
 		} 
 		ehci_dbg (ehci, "BIOS handoff succeeded\n");
 	}
@@ -547,7 +548,8 @@ static void ehci_stop (struct usb_hcd *h
 
 	/* root hub is shut down separately (first, when possible) */
 	spin_lock_irq (&ehci->lock);
-	ehci_work (ehci, NULL);
+	if (ehci->async)
+		ehci_work (ehci, NULL);
 	spin_unlock_irq (&ehci->lock);
 	ehci_mem_cleanup (ehci);
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/usb/host/hc_sl811.c linux-2.4.28-pre3/drivers/usb/host/hc_sl811.c
--- linux-2.4.27/drivers/usb/host/hc_sl811.c	2003-11-28 18:26:20.000000000 +0000
+++ linux-2.4.28-pre3/drivers/usb/host/hc_sl811.c	2004-09-10 19:37:01.000000000 +0000
@@ -117,9 +117,6 @@
 
 static int urb_debug = 0;
 
-#include "hc_simple.c"
-#include "hc_sl811_rh.c"
-
 /* Include hardware and board depens */
 #include <asm/hc_sl811-hw.h>
 
@@ -601,6 +598,9 @@ static inline int hc_parse_trans (hci_t 
 	return 0;
 }
 
+#include "hc_simple.c"
+#include "hc_sl811_rh.c"
+
 /************************************************************************
  * Function Name : hc_start_int
  *  
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/usb/host/usb-uhci.c linux-2.4.28-pre3/drivers/usb/host/usb-uhci.c
--- linux-2.4.27/drivers/usb/host/usb-uhci.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.28-pre3/drivers/usb/host/usb-uhci.c	2004-09-10 19:34:36.000000000 +0000
@@ -2746,13 +2746,8 @@ _static void uhci_interrupt (int irq, vo
 	dbg("interrupt");
 
 	if (status != 1) {
-		// Avoid too much error messages at a time
-		if (time_after(jiffies, s->last_error_time + ERROR_SUPPRESSION_TIME)) {
-			warn("interrupt, status %x, frame# %i", status, 
-			     UHCI_GET_CURRENT_FRAME(s));
-			s->last_error_time = jiffies;
-		}
-		
+		dbg("status %x, frame# %i", status, UHCI_GET_CURRENT_FRAME(s));
+
 		// remove host controller halted state
 		if ((status&0x20) && (s->running)) {
 			err("Host controller halted, trying to restart.");
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/usb/host/usb-uhci.h linux-2.4.28-pre3/drivers/usb/host/usb-uhci.h
--- linux-2.4.27/drivers/usb/host/usb-uhci.h	2003-06-13 14:51:36.000000000 +0000
+++ linux-2.4.28-pre3/drivers/usb/host/usb-uhci.h	2004-09-10 19:35:32.000000000 +0000
@@ -218,7 +218,6 @@ typedef struct uhci {
 	int timeout_urbs;
 	struct pci_dev *uhci_pci;
 	struct pci_pool *desc_pool;
-	long last_error_time;          // last error output in uhci_interrupt()
 } uhci_t, *puhci_t;
 
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/usb/kaweth.c linux-2.4.28-pre3/drivers/usb/kaweth.c
--- linux-2.4.27/drivers/usb/kaweth.c	2003-08-25 11:44:42.000000000 +0000
+++ linux-2.4.28-pre3/drivers/usb/kaweth.c	2004-09-10 19:36:01.000000000 +0000
@@ -735,7 +735,7 @@ static int kaweth_start_xmit(struct sk_b
 		}
 	}
 
-	private_header = __skb_push(skb, 2);
+	private_header = (u16 *)__skb_push(skb, 2);
 	*private_header = cpu_to_le16(skb->len-2);
 	kaweth->tx_skb = skb;
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/usb/ov511.c linux-2.4.28-pre3/drivers/usb/ov511.c
--- linux-2.4.27/drivers/usb/ov511.c	2003-06-13 14:51:36.000000000 +0000
+++ linux-2.4.28-pre3/drivers/usb/ov511.c	2004-09-10 19:33:43.000000000 +0000
@@ -334,8 +334,8 @@ static struct symbolic_list urb_errlist[
  **********************************************************************/
 
 static void ov51x_clear_snapshot(struct usb_ov511 *);
-static inline int sensor_get_picture(struct usb_ov511 *,
-				     struct video_picture *);
+static int sensor_get_picture(struct usb_ov511 *,
+			      struct video_picture *);
 #if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)
 static int sensor_get_exposure(struct usb_ov511 *, unsigned char *);
 static int ov51x_control_ioctl(struct inode *, struct file *, unsigned int,
@@ -2014,7 +2014,7 @@ sensor_set_picture(struct usb_ov511 *ov,
 	return 0;
 }
 
-static inline int
+static int
 sensor_get_picture(struct usb_ov511 *ov, struct video_picture *p)
 {
 	int rc;
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/usb/se401.c linux-2.4.28-pre3/drivers/usb/se401.c
--- linux-2.4.27/drivers/usb/se401.c	2002-11-28 23:53:14.000000000 +0000
+++ linux-2.4.28-pre3/drivers/usb/se401.c	2004-09-10 19:33:38.000000000 +0000
@@ -986,6 +986,44 @@ static int se401_newframe(struct usb_se4
 	return 0;
 }
 
+static inline void usb_se401_remove_disconnected (struct usb_se401 *se401)
+{
+	int i;
+
+        se401->dev = NULL;
+        se401->frame[0].grabstate = FRAME_ERROR;
+        se401->frame[1].grabstate = FRAME_ERROR;
+
+	se401->streaming = 0;
+
+	wake_up_interruptible(&se401->wq);
+
+	for (i=0; i<SE401_NUMSBUF; i++) if (se401->urb[i]) {
+		se401->urb[i]->next = NULL;
+		usb_unlink_urb(se401->urb[i]);
+		usb_free_urb(se401->urb[i]);
+		se401->urb[i] = NULL;
+		kfree(se401->sbuf[i].data);
+	}
+	for (i=0; i<SE401_NUMSCRATCH; i++) if (se401->scratch[i].data) {
+		kfree(se401->scratch[i].data);
+	}
+	if (se401->inturb) {
+		usb_unlink_urb(se401->inturb);
+		usb_free_urb(se401->inturb);
+	}
+        info("%s disconnected", se401->camera_name);
+
+#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)
+	destroy_proc_se401_cam(se401);
+#endif
+
+        /* Free the memory */
+	kfree(se401->width);
+	kfree(se401->height);
+	kfree(se401);
+}
+
 
 /****************************************************************************
  *
@@ -1531,44 +1569,6 @@ static void se401_disconnect(struct usb_
 	unlock_kernel();
 }
 
-static inline void usb_se401_remove_disconnected (struct usb_se401 *se401)
-{
-	int i;
-
-        se401->dev = NULL;
-        se401->frame[0].grabstate = FRAME_ERROR;
-        se401->frame[1].grabstate = FRAME_ERROR;
-
-	se401->streaming = 0;
-
-	wake_up_interruptible(&se401->wq);
-
-	for (i=0; i<SE401_NUMSBUF; i++) if (se401->urb[i]) {
-		se401->urb[i]->next = NULL;
-		usb_unlink_urb(se401->urb[i]);
-		usb_free_urb(se401->urb[i]);
-		se401->urb[i] = NULL;
-		kfree(se401->sbuf[i].data);
-	}
-	for (i=0; i<SE401_NUMSCRATCH; i++) if (se401->scratch[i].data) {
-		kfree(se401->scratch[i].data);
-	}
-	if (se401->inturb) {
-		usb_unlink_urb(se401->inturb);
-		usb_free_urb(se401->inturb);
-	}
-        info("%s disconnected", se401->camera_name);
-
-#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)
-	destroy_proc_se401_cam(se401);
-#endif
-
-        /* Free the memory */
-	kfree(se401->width);
-	kfree(se401->height);
-	kfree(se401);
-}
-
 static struct usb_driver se401_driver = {
         name:		"se401",
         id_table:	device_table,
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/usb/storage/scsiglue.c linux-2.4.28-pre3/drivers/usb/storage/scsiglue.c
--- linux-2.4.27/drivers/usb/storage/scsiglue.c	2004-08-07 23:26:05.000000000 +0000
+++ linux-2.4.28-pre3/drivers/usb/storage/scsiglue.c	2004-09-10 19:34:53.000000000 +0000
@@ -127,7 +127,7 @@ static int release(struct Scsi_Host *psh
 	wait_for_completion(&(us->notify));
 
 	/* remove the pointer to the data structure we were using */
-	(struct us_data*)psh->hostdata[0] = NULL;
+	psh->hostdata[0] = (unsigned long)NULL;
 
 	/* we always have a successful release */
 	return 0;
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/usb/storage/sddr09.c linux-2.4.28-pre3/drivers/usb/storage/sddr09.c
--- linux-2.4.27/drivers/usb/storage/sddr09.c	2003-08-25 11:44:42.000000000 +0000
+++ linux-2.4.28-pre3/drivers/usb/storage/sddr09.c	2004-09-10 19:36:27.000000000 +0000
@@ -444,6 +444,7 @@ sddr09_test_unit_ready(struct us_data *u
  * byte 0: opcode: 03
  * byte 4: data length
  */
+#if 0
 static int
 sddr09_request_sense(struct us_data *us, unsigned char *sensebuf, int buflen) {
 	unsigned char command[12] = {
@@ -465,7 +466,7 @@ sddr09_request_sense(struct us_data *us,
 
 	return result;
 }
-
+#endif
 /*
  * Read Command: 12 bytes.
  * byte 0: opcode: E8
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/usb/storage/transport.c linux-2.4.28-pre3/drivers/usb/storage/transport.c
--- linux-2.4.27/drivers/usb/storage/transport.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.28-pre3/drivers/usb/storage/transport.c	2004-09-10 19:34:09.000000000 +0000
@@ -627,8 +627,17 @@ void usb_stor_invoke_transport(Scsi_Cmnd
 	int need_auto_sense;
 	int result;
 
+	/*
+	 * Grab device's exclusive_access mutex to prevent libusb/usbfs from
+	 * sending out a command in the middle of ours (if libusb sends a
+	 * get_descriptor or something on pipe 0 after our CBW and before
+	 * our CSW, and then we get a stall, we have trouble).
+	 */
+	down(&(us->pusb_dev->exclusive_access));
+
 	/* send the command to the transport layer */
 	result = us->transport(srb, us);
+	up(&(us->pusb_dev->exclusive_access));
 
 	/* if the command gets aborted by the higher layers, we need to
 	 * short-circuit all other processing
@@ -748,7 +757,9 @@ void usb_stor_invoke_transport(Scsi_Cmnd
 		srb->use_sg = 0;
 
 		/* issue the auto-sense command */
+		down(&(us->pusb_dev->exclusive_access));
 		temp_result = us->transport(us->srb, us);
+		up(&(us->pusb_dev->exclusive_access));
 
 		/* let's clean up right away */
 		srb->request_buffer = old_request_buffer;
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/usb/storage/unusual_devs.h linux-2.4.28-pre3/drivers/usb/storage/unusual_devs.h
--- linux-2.4.27/drivers/usb/storage/unusual_devs.h	2004-08-07 23:26:05.000000000 +0000
+++ linux-2.4.28-pre3/drivers/usb/storage/unusual_devs.h	2004-09-10 19:36:15.000000000 +0000
@@ -430,6 +430,13 @@ UNUSUAL_DEV(  0x066b, 0x0105, 0x0100, 0x
 		US_FL_SINGLE_LUN ),
 #endif
 
+/* Reported by Darsen Lu <darsen@micro.ee.nthu.edu.tw> */
+UNUSUAL_DEV( 0x066f, 0x8000, 0x0001, 0x0001,
+		"SigmaTel",
+		"USBMSC Audio Player",
+		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		US_FL_FIX_CAPACITY ),
+
 /* Submitted by Benny Sjostrand <benny@hostmobility.com> */
 UNUSUAL_DEV( 0x0686, 0x4011, 0x0001, 0x0001,
 		"Minolta",
@@ -679,7 +686,7 @@ UNUSUAL_DEV( 0x090c, 0x1132, 0x0000, 0xf
 UNUSUAL_DEV(  0x097a, 0x0001, 0x0000, 0x0001,
 		"Minds@Work",
 		"Digital Wallet",
- 		US_SC_SCSI, US_PR_CB, NULL,
+ 		US_SC_DEVICE, US_PR_DEVICE, NULL,
 		US_FL_MODE_XLATE ),
 
 UNUSUAL_DEV(  0x0a16, 0x8888, 0x0100, 0x0100,
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/usb/storage/usb.c linux-2.4.28-pre3/drivers/usb/storage/usb.c
--- linux-2.4.27/drivers/usb/storage/usb.c	2004-08-07 23:26:05.000000000 +0000
+++ linux-2.4.28-pre3/drivers/usb/storage/usb.c	2004-09-10 19:33:26.000000000 +0000
@@ -994,7 +994,7 @@ static void * storage_probe(struct usb_d
 		 * the host controller thread in us_detect.  But how else are
 		 * we to do it?
 		 */
-		(struct us_data *)ss->htmplt.proc_dir = ss; 
+		ss->htmplt.proc_dir = (void *)ss; 
 
 		/* Just before we start our control thread, initialize
 		 * the device if it needs initialization */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/usb/usb.c linux-2.4.28-pre3/drivers/usb/usb.c
--- linux-2.4.27/drivers/usb/usb.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.28-pre3/drivers/usb/usb.c	2004-09-10 19:34:58.000000000 +0000
@@ -989,6 +989,7 @@ struct usb_device *usb_alloc_dev(struct 
 	INIT_LIST_HEAD(&dev->filelist);
 
 	init_MUTEX(&dev->serialize);
+	init_MUTEX(&dev->exclusive_access);
 
 	dev->bus->op->allocate(dev);
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/usb/w9968cf.c linux-2.4.28-pre3/drivers/usb/w9968cf.c
--- linux-2.4.27/drivers/usb/w9968cf.c	2004-04-14 13:05:37.000000000 +0000
+++ linux-2.4.28-pre3/drivers/usb/w9968cf.c	2004-09-10 19:34:07.000000000 +0000
@@ -446,8 +446,8 @@ static inline unsigned long w9968cf_get_
 /* High-level CMOS sensor control functions */
 static int w9968cf_sensor_set_control(struct w9968cf_device*,int cid,int val);
 static int w9968cf_sensor_get_control(struct w9968cf_device*,int cid,int *val);
-static inline int w9968cf_sensor_cmd(struct w9968cf_device*, 
-                                     unsigned int cmd, void *arg);
+static int w9968cf_sensor_cmd(struct w9968cf_device*, 
+                              unsigned int cmd, void *arg);
 static int w9968cf_sensor_init(struct w9968cf_device*);
 static int w9968cf_sensor_update_settings(struct w9968cf_device*);
 static int w9968cf_sensor_get_picture(struct w9968cf_device*);
@@ -463,7 +463,7 @@ static int w9968cf_init_chip(struct w996
 static int w9968cf_set_picture(struct w9968cf_device*, struct video_picture);
 static int w9968cf_set_window(struct w9968cf_device*, struct video_window);
 static inline u16 w9968cf_valid_palette(u16 palette);
-static inline u16 w9968cf_valid_depth(u16 palette);
+static u16 w9968cf_valid_depth(u16 palette);
 static inline u8 w9968cf_need_decompression(u16 palette);
 static int w9968cf_postprocess_frame(struct w9968cf_device*, 
                                      struct w9968cf_frame_t*);
@@ -2214,7 +2214,7 @@ static inline u16 w9968cf_valid_palette(
   Return the depth corresponding to the given palette.
   Palette _must_ be supported !
   --------------------------------------------------------------------------*/
-static inline u16 w9968cf_valid_depth(u16 palette)
+static u16 w9968cf_valid_depth(u16 palette)
 {
 	u8 i=0;
 	while (w9968cf_formatlist[i].palette != palette)
@@ -2433,7 +2433,7 @@ w9968cf_sensor_get_control(struct w9968c
 }
 
 
-static inline int
+static int
 w9968cf_sensor_cmd(struct w9968cf_device* cam, unsigned int cmd, void* arg)
 {
 	struct i2c_client* c = cam->sensor_client;
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/video/fbcon.c linux-2.4.28-pre3/drivers/video/fbcon.c
--- linux-2.4.27/drivers/video/fbcon.c	2003-08-25 11:44:42.000000000 +0000
+++ linux-2.4.28-pre3/drivers/video/fbcon.c	2004-09-10 19:35:55.000000000 +0000
@@ -1877,7 +1877,10 @@ static inline int fbcon_set_font(int uni
        font length must be multiple of 256, at least. And 256 is multiple
        of 4 */
     k = 0;
-    while (p > new_data) k += *--(u32 *)p;
+    while (p > new_data) {
+	    p = (u8 *)((u32 *)p - 1);
+	    k += *(u32 *) p;
+    }
     FNTSUM(new_data) = k;
     /* Check if the same font is on some other console already */
     for (i = 0; i < MAX_NR_CONSOLES; i++) {
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/video/matrox/matroxfb_g450.c linux-2.4.28-pre3/drivers/video/matrox/matroxfb_g450.c
--- linux-2.4.27/drivers/video/matrox/matroxfb_g450.c	2003-06-13 14:51:37.000000000 +0000
+++ linux-2.4.28-pre3/drivers/video/matrox/matroxfb_g450.c	2004-09-10 19:36:29.000000000 +0000
@@ -558,7 +558,7 @@ static int matroxfb_g450_program(void* m
 }
 
 static int matroxfb_g450_verify_mode(void* md, u_int32_t arg) {
-	MINFO_FROM(md);
+//	MINFO_FROM(md);
 	
 	switch (arg) {
 		case MATROXFB_OUTPUT_MODE_PAL:
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/video/pm3fb.c linux-2.4.28-pre3/drivers/video/pm3fb.c
--- linux-2.4.27/drivers/video/pm3fb.c	2004-04-14 13:05:38.000000000 +0000
+++ linux-2.4.28-pre3/drivers/video/pm3fb.c	2004-09-10 19:35:12.000000000 +0000
@@ -3838,11 +3838,9 @@ void cleanup_module(void)
 				    (unsigned char *) -1) {
 					pm3fb_unmapIO(l_fb_info);
 #if (defined KERNEL_2_4) || (defined KERNEL_2_5)
-					release_mem_region(l_fb_info->p_fb,
-							   l_fb_info->
-							   fb_size);
-					release_mem_region(l_fb_info->
-							   pIOBase,
+					release_mem_region((u_long)l_fb_info->p_fb,
+							   l_fb_info->fb_size);
+					release_mem_region((u_long)l_fb_info->pIOBase,
 							   PM3_REGS_SIZE);
 #endif /* KERNEL_2_4 or KERNEL_2_5 */
 				}
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/video/riva/fbdev.c linux-2.4.28-pre3/drivers/video/riva/fbdev.c
--- linux-2.4.27/drivers/video/riva/fbdev.c	2004-08-07 23:26:05.000000000 +0000
+++ linux-2.4.28-pre3/drivers/video/riva/fbdev.c	2004-09-10 19:35:58.000000000 +0000
@@ -117,7 +117,7 @@
 static void rivafb_blank(int blank, struct fb_info *info);
 
 extern void riva_setup_accel(struct rivafb_info *rinfo);
-extern inline void wait_for_idle(struct rivafb_info *rinfo);
+extern void wait_for_idle(struct rivafb_info *rinfo);
 
 
 
@@ -2221,7 +2221,6 @@ err_out_free_base1:
 	release_mem_region(rinfo->fb_base_phys, rinfo->base1_region_size);
 err_out_free_base0:
 	release_mem_region(rinfo->ctrl_base_phys, rinfo->base0_region_size);
-err_out_kfree:
 	kfree(rinfo);
 err_out:
 	return -ENODEV;
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/drivers/video/sstfb.c linux-2.4.28-pre3/drivers/video/sstfb.c
--- linux-2.4.27/drivers/video/sstfb.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.28-pre3/drivers/video/sstfb.c	2004-09-10 19:35:34.000000000 +0000
@@ -968,7 +968,6 @@ static int sstfb_ioctl(struct inode *ino
                        struct fb_info *info)
 {
 #define sst_info	((struct sstfb_info *) info)
-	int i;
 	u_long p;
 	u32 tmp, val;
 	u32 fbiinit0;
@@ -980,12 +979,14 @@ static int sstfb_ioctl(struct inode *ino
 		
 #if (SST_DEBUG_VAR >0)
 	/* tmp ioctl : dumps fb_display[0-5] */
-	case _IO('F', 0xdb):		/* 0x46db */
+	case _IO('F', 0xdb):		/* 0x46db */ {
+		int i;
 		f_dprintk("dumping fb_display[0-5].var\n");
 		for (i = 0 ; i< 6 ; i++) {
 			print_var(&fb_display[i].var, "var(%d)", i);
 		}
 		return 0;
+	}
 #endif /* (SST_DEBUG_VAR >0) */
 
 	/* fills the lfb up to given count of pixels */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/Config.in linux-2.4.28-pre3/fs/Config.in
--- linux-2.4.27/fs/Config.in	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.28-pre3/fs/Config.in	2004-09-10 19:35:42.000000000 +0000
@@ -121,7 +121,7 @@ if [ "$CONFIG_NET" = "y" ]; then
 
    dep_tristate 'NFS server support' CONFIG_NFSD $CONFIG_INET
    dep_mbool '  Provide NFSv3 server support' CONFIG_NFSD_V3 $CONFIG_NFSD
-   dep_mbool '  Provide NFS server over TCP support (EXPERIMENTAL)' CONFIG_NFSD_TCP $CONFIG_NFSD $CONFIG_EXPERIMENTAL
+   dep_mbool '  Provide NFS server over TCP support' CONFIG_NFSD_TCP $CONFIG_NFSD
 
    if [ "$CONFIG_NFS_FS" = "y" -o "$CONFIG_NFSD" = "y" ]; then
       define_tristate CONFIG_SUNRPC y
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/affs/super.c linux-2.4.28-pre3/fs/affs/super.c
--- linux-2.4.27/fs/affs/super.c	2004-08-07 23:26:05.000000000 +0000
+++ linux-2.4.28-pre3/fs/affs/super.c	2004-09-10 19:35:52.000000000 +0000
@@ -130,7 +130,7 @@ parse_options(char *options, uid_t *uid,
 					printk("AFFS: Argument for set[ug]id option missing\n");
 					return 0;
 				} else {
-					(f ? *uid : *gid) = simple_strtoul(value,&value,0);
+					*(f ? uid : gid) = simple_strtoul(value,&value,0);
 					if (*value) {
 						printk("AFFS: Bad set[ug]id argument\n");
 						return 0;
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/befs/btree.c linux-2.4.28-pre3/fs/befs/btree.c
--- linux-2.4.27/fs/befs/btree.c	2003-06-13 14:51:37.000000000 +0000
+++ linux-2.4.28-pre3/fs/befs/btree.c	2004-09-10 19:37:12.000000000 +0000
@@ -85,7 +85,7 @@ typedef struct {
 } befs_btree_node;
 
 /* local constants */
-const static befs_off_t befs_bt_inval = 0xffffffffffffffff;
+const static befs_off_t befs_bt_inval = 0xffffffffffffffffULL;
 
 /* local functions */
 static int befs_btree_seekleaf(struct super_block *sb, befs_data_stream * ds,
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/befs/linuxvfs.c linux-2.4.28-pre3/fs/befs/linuxvfs.c
--- linux-2.4.27/fs/befs/linuxvfs.c	2003-06-13 14:51:37.000000000 +0000
+++ linux-2.4.28-pre3/fs/befs/linuxvfs.c	2004-09-10 19:37:29.000000000 +0000
@@ -55,13 +55,6 @@ static int befs_remount(struct super_blo
 static int befs_statfs(struct super_block *, struct statfs *);
 static int parse_options(char *, befs_mount_options *);
 
-static ssize_t befs_listxattr(struct dentry *dentry, char *buffer, size_t size);
-static ssize_t befs_getxattr(struct dentry *dentry, const char *name,
-			     void *buffer, size_t size);
-static int befs_setxattr(struct dentry *dentry, const char *name, void *value,
-			 size_t size, int flags);
-static int befs_removexattr(struct dentry *dentry, const char *name);
-
 /* slab cache for befs_inode_info objects */
 static kmem_cache_t *befs_inode_cachep;
 
@@ -584,11 +577,11 @@ befs_utf2nls(struct super_block *sb, con
 		}
 	}
 	result[o] = '\0';
+	*out_len = o;
 
 	befs_debug(sb, "<--- utf2nls()");
 
 	return o;
-	*out_len = o;
 
       conv_err:
 	befs_error(sb, "Name using charecter set %s contains a charecter that "
@@ -675,35 +668,6 @@ befs_nls2utf(struct super_block *sb, con
 	return -EILSEQ;
 }
 
-/****Xattr****/
-
-static ssize_t
-befs_listxattr(struct dentry *dentry, char *buffer, size_t size)
-{
-	printk(KERN_ERR "befs_listxattr called\n");
-	return 0;
-}
-
-static ssize_t
-befs_getxattr(struct dentry *dentry, const char *name,
-	      void *buffer, size_t size)
-{
-	return 0;
-}
-
-static int
-befs_setxattr(struct dentry *dentry, const char *name,
-	      void *value, size_t size, int flags)
-{
-	return 0;
-}
-
-static int
-befs_removexattr(struct dentry *dentry, const char *name)
-{
-	return 0;
-}
-
 /****Superblock****/
 
 static int
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/buffer.c linux-2.4.28-pre3/fs/buffer.c
--- linux-2.4.27/fs/buffer.c	2004-08-07 23:26:05.000000000 +0000
+++ linux-2.4.28-pre3/fs/buffer.c	2004-09-10 19:35:21.000000000 +0000
@@ -160,7 +160,7 @@ static inline void write_buffer(struct b
 	ll_rw_block(WRITE, 1, &bh);
 }
 
-void unlock_buffer(struct buffer_head *bh)
+void fastcall unlock_buffer(struct buffer_head *bh)
 {
 	clear_bit(BH_Wait_IO, &bh->b_state);
 	clear_bit(BH_Launder, &bh->b_state);
@@ -371,6 +371,7 @@ int sync_buffers(kdev_t dev, int wait)
 	}
 	return err;
 }
+EXPORT_SYMBOL(sync_buffers);
 
 int fsync_super(struct super_block *sb)
 {
@@ -649,7 +650,7 @@ struct buffer_head * get_hash_table(kdev
 	return bh;
 }
 
-void buffer_insert_list(struct buffer_head *bh, struct list_head *list)
+void fastcall buffer_insert_list(struct buffer_head *bh, struct list_head *list)
 {
 	spin_lock(&lru_list_lock);
 	if (buffer_attached(bh))
@@ -1092,7 +1093,7 @@ void balance_dirty(void)
 }
 EXPORT_SYMBOL(balance_dirty);
 
-inline void __mark_dirty(struct buffer_head *bh)
+inline void fastcall __mark_dirty(struct buffer_head *bh)
 {
 	bh->b_flushtime = jiffies + bdf_prm.b_un.age_buffer;
 	refile_buffer(bh);
@@ -1100,13 +1101,13 @@ inline void __mark_dirty(struct buffer_h
 
 /* atomic version, the user must call balance_dirty() by hand
    as soon as it become possible to block */
-void __mark_buffer_dirty(struct buffer_head *bh)
+void fastcall __mark_buffer_dirty(struct buffer_head *bh)
 {
 	if (!atomic_set_buffer_dirty(bh))
 		__mark_dirty(bh);
 }
 
-void mark_buffer_dirty(struct buffer_head *bh)
+void fastcall mark_buffer_dirty(struct buffer_head *bh)
 {
 	if (!atomic_set_buffer_dirty(bh)) {
 		if (block_dump)
@@ -1122,7 +1123,7 @@ void set_buffer_flushtime(struct buffer_
 }
 EXPORT_SYMBOL(set_buffer_flushtime);
 
-inline int get_buffer_flushtime(void)
+int get_buffer_flushtime(void)
 {
 	return bdf_prm.b_un.interval;
 }
@@ -1260,8 +1261,9 @@ struct buffer_head * get_unused_buffer_h
 
 	/*
 	 * If we need an async buffer, use the reserved buffer heads.
+	 * Non-PF_MEMALLOC tasks can just loop in create_buffers().
 	 */
-	if (async) {
+	if (async && (current->flags & PF_MEMALLOC)) {
 		spin_lock(&unused_list_lock);
 		if (unused_list) {
 			bh = unused_list;
@@ -2730,7 +2732,7 @@ static int sync_page_buffers(struct buff
  *       obtain a reference to a buffer head within a page.  So we must
  *	 lock out all of these paths to cleanly toss the page.
  */
-int try_to_free_buffers(struct page * page, unsigned int gfp_mask)
+int fastcall try_to_free_buffers(struct page * page, unsigned int gfp_mask)
 {
 	struct buffer_head * tmp, * bh = page->buffers;
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/ext3/super.c linux-2.4.28-pre3/fs/ext3/super.c
--- linux-2.4.27/fs/ext3/super.c	2004-08-07 23:26:05.000000000 +0000
+++ linux-2.4.28-pre3/fs/ext3/super.c	2004-09-10 19:36:45.000000000 +0000
@@ -1302,6 +1302,7 @@ static journal_t *ext3_get_journal(struc
 	if (!journal) {
 		printk(KERN_ERR "EXT3-fs: Could not load journal inode\n");
 		iput(journal_inode);
+		return NULL;
 	}
 	ext3_init_journal_params(EXT3_SB(sb), journal);
 	return journal;
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/file_table.c linux-2.4.28-pre3/fs/file_table.c
--- linux-2.4.27/fs/file_table.c	2002-11-28 23:53:15.000000000 +0000
+++ linux-2.4.28-pre3/fs/file_table.c	2004-09-10 19:32:15.000000000 +0000
@@ -97,7 +97,7 @@ int init_private_file(struct file *filp,
 		return 0;
 }
 
-void fput(struct file * file)
+void fastcall fput(struct file * file)
 {
 	struct dentry * dentry = file->f_dentry;
 	struct vfsmount * mnt = file->f_vfsmnt;
@@ -126,7 +126,7 @@ void fput(struct file * file)
 	}
 }
 
-struct file * fget(unsigned int fd)
+struct file fastcall *fget(unsigned int fd)
 {
 	struct file * file;
 	struct files_struct *files = current->files;
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/freevxfs/vxfs_extern.h linux-2.4.28-pre3/fs/freevxfs/vxfs_extern.h
--- linux-2.4.27/fs/freevxfs/vxfs_extern.h	2002-02-25 19:38:08.000000000 +0000
+++ linux-2.4.28-pre3/fs/freevxfs/vxfs_extern.h	2004-09-10 19:37:01.000000000 +0000
@@ -72,7 +72,7 @@ extern int			vxfs_read_olt(struct super_
 
 /* vxfs_subr.c */
 extern struct page *		vxfs_get_page(struct address_space *, u_long);
-extern __inline__ void		vxfs_put_page(struct page *);
+extern void			vxfs_put_page(struct page *);
 extern struct buffer_head *	vxfs_bread(struct inode *, int);
 
 #endif /* _VXFS_EXTERN_H_ */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/freevxfs/vxfs_subr.c linux-2.4.28-pre3/fs/freevxfs/vxfs_subr.c
--- linux-2.4.27/fs/freevxfs/vxfs_subr.c	2002-02-25 19:38:08.000000000 +0000
+++ linux-2.4.28-pre3/fs/freevxfs/vxfs_subr.c	2004-09-10 19:33:37.000000000 +0000
@@ -50,6 +50,12 @@ struct address_space_operations vxfs_aop
 	.sync_page =		block_sync_page,
 };
 
+__inline__ void
+vxfs_put_page(struct page *pp)
+{
+	kunmap(pp);
+	page_cache_release(pp);
+}
 
 /**
  * vxfs_get_page - read a page into memory.
@@ -88,13 +94,6 @@ fail:
 	return ERR_PTR(-EIO);
 }
 
-__inline__ void
-vxfs_put_page(struct page *pp)
-{
-	kunmap(pp);
-	page_cache_release(pp);
-}
-
 /**
  * vxfs_bread - read buffer for a give inode,block tuple
  * @ip:		inode
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/hfs/file_hdr.c linux-2.4.28-pre3/fs/hfs/file_hdr.c
--- linux-2.4.27/fs/hfs/file_hdr.c	2004-08-07 23:26:05.000000000 +0000
+++ linux-2.4.28-pre3/fs/hfs/file_hdr.c	2004-09-10 19:35:42.000000000 +0000
@@ -241,7 +241,9 @@ static struct hfs_hdr_layout *dup_layout
 	if (HFS_NEW(new)) {
 		memcpy(new, old, sizeof(*new));
 		for (lcv = 0; lcv < new->entries; ++lcv) {
-			(char *)(new->order[lcv]) += (char *)new - (char *)old;
+			new->order[lcv] = (struct hfs_hdr_descr *)
+					  ((char *)(new->order[lcv]) +
+					   ((char *)new - (char *)old));
 		}
 	}
 	return new;
@@ -640,18 +642,19 @@ static hfs_rwret_t hdr_write(struct file
         int left, lcv, written = 0;
 	struct hdr_hdr meta;
 	int built_meta = 0;
-        off_t pos;
+        loff_t pos;
 
 	if (!S_ISREG(inode->i_mode)) {
 		hfs_warn("hfs_hdr_write: mode = %07o\n", inode->i_mode);
 		return -EINVAL;
 	}
+
+	pos = (filp->f_flags & O_APPEND) ? inode->i_size : *ppos;
+
 	if (count <= 0 || pos != (unsigned)pos) {
 		return 0;
 	}
 
-	pos = (filp->f_flags & O_APPEND) ? inode->i_size : *ppos;
-
 	if (!HFS_I(inode)->layout) {
 		HFS_I(inode)->layout = dup_layout(HFS_I(inode)->default_layout);
 	}
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/intermezzo/cache.c linux-2.4.28-pre3/fs/intermezzo/cache.c
--- linux-2.4.27/fs/intermezzo/cache.c	2002-11-28 23:53:15.000000000 +0000
+++ linux-2.4.28-pre3/fs/intermezzo/cache.c	2004-09-10 19:34:18.000000000 +0000
@@ -78,6 +78,14 @@ inline void presto_cache_init_hash(void)
         }
 }
 
+int izo_ioctl_packlen(struct izo_ioctl_data *data)
+{
+        int len = sizeof(struct izo_ioctl_data);
+        len += size_round(data->ioc_inllen1);
+        len += size_round(data->ioc_inllen2);
+        return len;
+}
+
 /* map a device to a cache */
 struct presto_cache *presto_cache_find(kdev_t dev)
 {
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/intermezzo/sysctl.c linux-2.4.28-pre3/fs/intermezzo/sysctl.c
--- linux-2.4.27/fs/intermezzo/sysctl.c	2002-11-28 23:53:15.000000000 +0000
+++ linux-2.4.28-pre3/fs/intermezzo/sysctl.c	2004-09-10 19:32:55.000000000 +0000
@@ -290,6 +290,8 @@ int /* __init */ init_intermezzo_sysctl(
 	 * happens once per reboot.
 	 */
 	for(i = 0; i < total_dev; i++) {
+		void *p;
+
 		/* entry for this /proc/sys/intermezzo/intermezzo"i" */
 		ctl_table *psdev = &presto_table[i + PRESTO_PRIMARY_CTLCNT];
 		/* entries for the individual "files" in this "directory" */
@@ -302,7 +304,8 @@ int /* __init */ init_intermezzo_sysctl(
 		/* the psdev has to point to psdev_entries, and fix the number */
 		psdev->ctl_name = psdev->ctl_name + i + 1; /* sorry */
 
-		PRESTO_ALLOC((void*)psdev->procname, PROCNAME_SIZE);
+		PRESTO_ALLOC(p, PROCNAME_SIZE);
+		psdev->procname = p;
 		if (!psdev->procname) {
 			PRESTO_FREE(dev_ctl_table,
 				    sizeof(ctl_table) * total_entries);
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/jbd/journal.c linux-2.4.28-pre3/fs/jbd/journal.c
--- linux-2.4.27/fs/jbd/journal.c	2004-04-14 13:05:40.000000000 +0000
+++ linux-2.4.28-pre3/fs/jbd/journal.c	2004-09-10 19:32:54.000000000 +0000
@@ -1581,7 +1581,7 @@ void journal_ack_err (journal_t *journal
  * journal_datalist_lock spinlock: most callers will need those anyway
  * in order to probe the buffer's journaling state safely.
  */
-void __jbd_unexpected_dirty_buffer(char *function, int line, 
+void __jbd_unexpected_dirty_buffer(const char *function, int line, 
 				 struct journal_head *jh)
 {
 	struct buffer_head *bh = jh2bh(jh);
@@ -1646,7 +1646,7 @@ void shrink_journal_memory(void)
  * Simple support for retying memory allocations.  Introduced to help to
  * debug different VM deadlock avoidance strategies. 
  */
-void * __jbd_kmalloc (char *where, size_t size, int flags, int retry)
+void * __jbd_kmalloc (const char *where, size_t size, int flags, int retry)
 {
 	void *p;
 	static unsigned long last_warning;
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/jfs/jfs_metapage.c linux-2.4.28-pre3/fs/jfs/jfs_metapage.c
--- linux-2.4.27/fs/jfs/jfs_metapage.c	2004-08-07 23:26:05.000000000 +0000
+++ linux-2.4.28-pre3/fs/jfs/jfs_metapage.c	2004-09-10 19:35:59.000000000 +0000
@@ -606,6 +606,7 @@ again:
 			if (page) {
 				block_flushpage(page, 0);
 				UnlockPage(page);
+				page_cache_release(page);
 			}
 		}
 	}
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/jfs/jfs_mount.c linux-2.4.28-pre3/fs/jfs/jfs_mount.c
--- linux-2.4.27/fs/jfs/jfs_mount.c	2003-11-28 18:26:21.000000000 +0000
+++ linux-2.4.28-pre3/fs/jfs/jfs_mount.c	2004-09-10 19:33:35.000000000 +0000
@@ -197,9 +197,6 @@ int jfs_mount(struct super_block *sb)
 	/*
 	 *      unwind on error
 	 */
-//errout42: /* close fileset inode allocation map */
-	diUnmount(ipimap, 1);
-
       errout41:		/* close fileset inode allocation map inode */
 	diFreeSpecial(ipimap);
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/namei.c linux-2.4.28-pre3/fs/namei.c
--- linux-2.4.27/fs/namei.c	2004-08-07 23:26:06.000000000 +0000
+++ linux-2.4.28-pre3/fs/namei.c	2004-09-10 19:33:55.000000000 +0000
@@ -447,7 +447,7 @@ static inline void follow_dotdot(struct 
  *
  * We expect 'base' to be positive and a directory.
  */
-int link_path_walk(const char * name, struct nameidata *nd)
+int fastcall link_path_walk(const char * name, struct nameidata *nd)
 {
 	struct dentry *dentry;
 	struct inode *inode;
@@ -653,7 +653,7 @@ return_err:
 	return err;
 }
 
-int path_walk(const char * name, struct nameidata *nd)
+int fastcall path_walk(const char * name, struct nameidata *nd)
 {
 	current->total_link_count = 0;
 	return link_path_walk(name, nd);
@@ -741,7 +741,7 @@ walk_init_root(const char *name, struct 
 }
 
 /* SMP-safe */
-int path_lookup(const char *path, unsigned flags, struct nameidata *nd)
+int fastcall path_lookup(const char *path, unsigned flags, struct nameidata *nd)
 {
 	int error = 0;
 	if (path_init(path, flags, nd))
@@ -751,7 +751,7 @@ int path_lookup(const char *path, unsign
 
 
 /* SMP-safe */
-int path_init(const char *name, unsigned int flags, struct nameidata *nd)
+int fastcall path_init(const char *name, unsigned int flags, struct nameidata *nd)
 {
 	nd->last_type = LAST_ROOT; /* if there are only slashes... */
 	nd->flags = flags;
@@ -847,7 +847,7 @@ access:
  * that namei follows links, while lnamei does not.
  * SMP-safe
  */
-int __user_walk(const char *name, unsigned flags, struct nameidata *nd)
+int fastcall __user_walk(const char *name, unsigned flags, struct nameidata *nd)
 {
 	char *tmp;
 	int err;
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/ncpfs/ncplib_kernel.h linux-2.4.28-pre3/fs/ncpfs/ncplib_kernel.h
--- linux-2.4.27/fs/ncpfs/ncplib_kernel.h	2001-02-09 19:29:44.000000000 +0000
+++ linux-2.4.28-pre3/fs/ncpfs/ncplib_kernel.h	2004-09-10 19:33:28.000000000 +0000
@@ -131,7 +131,7 @@ int ncp__vol2io(unsigned char *, unsigne
 
 #endif /* CONFIG_NCPFS_NLS */
 
-inline int
+int
 ncp_strnicmp(struct nls_table *,
 		const unsigned char *, const unsigned char *, int);
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/nfsd/nfs3xdr.c linux-2.4.28-pre3/fs/nfsd/nfs3xdr.c
--- linux-2.4.27/fs/nfsd/nfs3xdr.c	2003-06-13 14:51:37.000000000 +0000
+++ linux-2.4.28-pre3/fs/nfsd/nfs3xdr.c	2004-09-10 19:31:49.000000000 +0000
@@ -273,7 +273,7 @@ xdr_argsize_check(struct svc_rqst *rqstp
 {
 	struct svc_buf	*buf = &rqstp->rq_argbuf;
 
-	return p - buf->base <= buf->buflen;
+	return p >= buf->base && p <= buf->base + buf->buflen ;
 }
 
 static inline int
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/nfsd/vfs.c linux-2.4.28-pre3/fs/nfsd/vfs.c
--- linux-2.4.27/fs/nfsd/vfs.c	2003-11-28 18:26:21.000000000 +0000
+++ linux-2.4.28-pre3/fs/nfsd/vfs.c	2004-09-10 19:34:10.000000000 +0000
@@ -586,6 +586,22 @@ found:
 	return ra;
 }
 
+/* copied from fs/read_write.c */
+static inline loff_t llseek(struct file *file, loff_t offset, int origin)
+{
+	loff_t (*fn)(struct file *, loff_t, int);
+	loff_t retval;
+
+	fn = default_llseek;
+	if (file->f_op && file->f_op->llseek)
+		fn = file->f_op->llseek;
+	lock_kernel();
+	retval = fn(file, offset, origin);
+	unlock_kernel();
+	return retval;
+}
+
+
 /*
  * Read data from a file. count must contain the requested read count
  * on entry. On return, *count contains the number of bytes actually read.
@@ -621,7 +637,7 @@ nfsd_read(struct svc_rqst *rqstp, struct
 		file.f_ralen = ra->p_ralen;
 		file.f_rawin = ra->p_rawin;
 	}
-	file.f_pos = offset;
+	llseek(&file, offset, 0);
 
 	oldfs = get_fs(); set_fs(KERNEL_DS);
 	err = file.f_op->read(&file, buf, *count, &file.f_pos);
@@ -706,7 +722,8 @@ nfsd_write(struct svc_rqst *rqstp, struc
 	if (stable && !EX_WGATHER(exp))
 		file.f_flags |= O_SYNC;
 
-	file.f_pos = offset;		/* set write offset */
+
+	llseek(&file, offset, 0);
 
 	/* Write the data. */
 	oldfs = get_fs(); set_fs(KERNEL_DS);
@@ -1398,10 +1415,12 @@ nfsd_readdir(struct svc_rqst *rqstp, str
 	err = nfsd_open(rqstp, fhp, S_IFDIR, MAY_READ, &file);
 	if (err)
 		goto out;
-	if (offset > ~(u32) 0)
-		goto out_close;
 
-	file.f_pos = offset;
+	offset = llseek(&file, offset, 0);
+	if (offset < 0) {
+		err = nfserrno((int)offset);
+		goto out_close;
+	}
 
 	/* Set up the readdir context */
 	memset(&cd, 0, sizeof(cd));
@@ -1429,11 +1448,13 @@ nfsd_readdir(struct svc_rqst *rqstp, str
 	/* If we didn't fill the buffer completely, we're at EOF */
 	eof = !cd.eob;
 
+
+	offset = llseek(&file, 0LL, 1);
 	if (cd.offset) {
 		if (rqstp->rq_vers == 3)
-			(void)xdr_encode_hyper(cd.offset, file.f_pos);
+			(void)xdr_encode_hyper(cd.offset, offset);
 		else
-			*cd.offset = htonl(file.f_pos);
+			*cd.offset = htonl(offset);
 	}
 
 	p = cd.buffer;
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/ntfs/fs.c linux-2.4.28-pre3/fs/ntfs/fs.c
--- linux-2.4.27/fs/ntfs/fs.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.28-pre3/fs/ntfs/fs.c	2004-09-10 19:33:01.000000000 +0000
@@ -1045,7 +1045,7 @@ struct super_block *ntfs_read_super(stru
 	}
 	ntfs_debug(DEBUG_OTHER, "$Mft at cluster 0x%lx\n", vol->mft_lcn);
 	brelse(bh);
-	NTFS_SB(vol) = sb;
+	vol->sb = sb;
 	if (vol->cluster_size > PAGE_SIZE) {
 		ntfs_error("Partition cluster size is not supported yet (it "
 			   "is > max kernel blocksize).\n");
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/ntfs/util.c linux-2.4.28-pre3/fs/ntfs/util.c
--- linux-2.4.27/fs/ntfs/util.c	2001-08-13 23:40:19.000000000 +0000
+++ linux-2.4.28-pre3/fs/ntfs/util.c	2004-09-10 19:31:52.000000000 +0000
@@ -165,13 +165,13 @@ int ntfs_decodeuni(ntfs_volume *vol, cha
 void ntfs_put(ntfs_io *dest, void *src, ntfs_size_t n)
 {
 	ntfs_memcpy(dest->param, src, n);
-	((char*)dest->param) += n;
+	dest->param = (char*)dest->param + n;
 }
 
 void ntfs_get(void* dest, ntfs_io *src, ntfs_size_t n)
 {
 	ntfs_memcpy(dest, src->param, n);
-	((char*)src->param) += n;
+	src->param = (char*)src->param + n;
 }
 
 void *ntfs_calloc(int size)
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/partitions/ibm.c linux-2.4.28-pre3/fs/partitions/ibm.c
--- linux-2.4.27/fs/partitions/ibm.c	2002-08-03 00:39:45.000000000 +0000
+++ linux-2.4.28-pre3/fs/partitions/ibm.c	2004-09-10 19:37:14.000000000 +0000
@@ -9,6 +9,7 @@
  * 07/10/00 Fixed detection of CMS formatted disks     
  * 02/13/00 VTOC partition support added
  * 12/27/01 fixed PL030593 (CMS reserved minidisk not detected on 64 bit)
+ * 07/24/03 no longer using contents of freed page for CMS label recognition (BZ3611)
  */
 
 #include <linux/config.h>
@@ -141,7 +142,7 @@ ibm_partition(struct gendisk *hd, struct
 		/*
 		 * VM style CMS1 labeled disk
 		 */
-		int *label = (int *) data;
+		int *label = (int *) vlabel;
 
 		if (label[13] != 0) {
 			printk("CMS1/%8s(MDSK):", name);
@@ -158,7 +159,8 @@ ibm_partition(struct gendisk *hd, struct
 		add_gd_partition(hd, first_part_minor,
 				 offset*(blocksize >> 9),
 				 size-offset*(blocksize >> 9));
-	} else if (strncmp(type, "VOL1", 4) == 0) {
+	} else if ((strncmp(type, "VOL1", 4) == 0) &&
+		(!info->FBA_layout) && (!strcmp(info->type, "ECKD"))) {
 		/*
 		 * New style VOL1 labeled disk
 		 */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/partitions/ldm.h linux-2.4.28-pre3/fs/partitions/ldm.h
--- linux-2.4.27/fs/partitions/ldm.h	2002-11-28 23:53:15.000000000 +0000
+++ linux-2.4.28-pre3/fs/partitions/ldm.h	2004-09-10 19:33:39.000000000 +0000
@@ -38,8 +38,8 @@ struct parsed_partitions;
 /* Magic numbers in CPU format. */
 #define MAGIC_VMDB	0x564D4442		/* VMDB */
 #define MAGIC_VBLK	0x56424C4B		/* VBLK */
-#define MAGIC_PRIVHEAD	0x5052495648454144	/* PRIVHEAD */
-#define MAGIC_TOCBLOCK	0x544F43424C4F434B	/* TOCBLOCK */
+#define MAGIC_PRIVHEAD	0x5052495648454144ULL	/* PRIVHEAD */
+#define MAGIC_TOCBLOCK	0x544F43424C4F434BULL	/* TOCBLOCK */
 
 /* The defined vblk types. */
 #define VBLK_VOL5		0x51		/* Volume,     version 5 */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/readdir.c linux-2.4.28-pre3/fs/readdir.c
--- linux-2.4.27/fs/readdir.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.28-pre3/fs/readdir.c	2004-09-10 19:34:46.000000000 +0000
@@ -264,7 +264,7 @@ static int filldir(void * __buf, const c
 	put_user(reclen, &dirent->d_reclen);
 	copy_to_user(dirent->d_name, name, namlen);
 	put_user(0, dirent->d_name + namlen);
-	((char *) dirent) += reclen;
+	dirent = (void *)dirent + reclen;
 	buf->current_dir = dirent;
 	buf->count -= reclen;
 	return 0;
@@ -347,7 +347,7 @@ static int filldir64(void * __buf, const
 	copy_to_user(dirent, &d, NAME_OFFSET(&d));
 	copy_to_user(dirent->d_name, name, namlen);
 	put_user(0, dirent->d_name + namlen);
-	((char *) dirent) += reclen;
+	dirent = (void *)dirent + reclen;
 	buf->current_dir = dirent;
 	buf->count -= reclen;
 	return 0;
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/xfs/linux-2.4/xfs_aops.c linux-2.4.28-pre3/fs/xfs/linux-2.4/xfs_aops.c
--- linux-2.4.27/fs/xfs/linux-2.4/xfs_aops.c	2004-08-07 23:26:06.000000000 +0000
+++ linux-2.4.28-pre3/fs/xfs/linux-2.4/xfs_aops.c	2004-09-10 19:37:07.000000000 +0000
@@ -209,6 +209,7 @@ xfs_map_at_offset(
 	sector_shift = block_bits - BBSHIFT;
 	bn = iomapp->iomap_bn >> sector_shift;
 	bn += delta;
+	BUG_ON(!bn && !(iomapp->iomap_flags & IOMAP_REALTIME));
 	ASSERT((bn << sector_shift) >= iomapp->iomap_bn);
 
 	lock_buffer(bh);
@@ -887,7 +888,7 @@ linvfs_get_block_core(
 
 			bn = iomap.iomap_bn >> (inode->i_blkbits - BBSHIFT);
 			bn += delta;
-
+			BUG_ON(!bn && !(iomap.iomap_flags & IOMAP_REALTIME));
 			bh_result->b_blocknr = bn;
 			set_buffer_mapped(bh_result);
 		}
@@ -911,10 +912,10 @@ linvfs_get_block_core(
 	}
 
 	if (iomap.iomap_flags & IOMAP_DELAY) {
-		if (unlikely(direct))
-			BUG();
+		BUG_ON(direct);
 		if (create) {
 			set_buffer_mapped(bh_result);
+			set_buffer_uptodate(bh_result);
 		}
 		set_buffer_delay(bh_result);
 	}
@@ -934,17 +935,6 @@ linvfs_get_block(
 }
 
 STATIC int
-linvfs_get_block_sync(
-	struct inode		*inode,
-	long			iblock,
-	struct buffer_head	*bh_result,
-	int			create)
-{
-	return linvfs_get_block_core(inode, iblock, bh_result,
-					create, 0, BMAPI_SYNC|BMAPI_WRITE);
-}
-
-STATIC int
 linvfs_get_block_direct(
 	struct inode		*inode,
 	long			iblock,
@@ -1155,13 +1145,7 @@ linvfs_prepare_write(
 	unsigned int		from,
 	unsigned int		to)
 {
-	if (file && (file->f_flags & O_SYNC)) {
-		return block_prepare_write(page, from, to,
-						linvfs_get_block_sync);
-	} else {
-		return block_prepare_write(page, from, to,
-						linvfs_get_block);
-	}
+	return block_prepare_write(page, from, to, linvfs_get_block);
 }
 
 /*
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/xfs/linux-2.4/xfs_buf.c linux-2.4.28-pre3/fs/xfs/linux-2.4/xfs_buf.c
--- linux-2.4.27/fs/xfs/linux-2.4/xfs_buf.c	2004-08-07 23:26:06.000000000 +0000
+++ linux-2.4.28-pre3/fs/xfs/linux-2.4/xfs_buf.c	2004-09-10 19:32:47.000000000 +0000
@@ -767,11 +767,8 @@ pagebuf_get(				/* allocate a buffer		*/
 	pb = _pagebuf_find(target, ioff, isize, flags, new_pb);
 	if (pb == new_pb) {
 		error = _pagebuf_lookup_pages(pb, flags);
-		if (unlikely(error)) {
-			printk(KERN_WARNING
-			       "pagebuf_get: failed to lookup pages\n");
+		if (error)
 			goto no_buffer;
-		}
 	} else {
 		pagebuf_deallocate(new_pb);
 		if (unlikely(pb == NULL))
@@ -1445,6 +1442,7 @@ xfs_free_buftarg(
 	xfs_flush_buftarg(btp, 1);
 	if (external)
 		xfs_blkdev_put(btp->pbr_bdev);
+	iput(btp->pbr_mapping->host);
 	kmem_free(btp, sizeof(*btp));
 }
 
@@ -1458,7 +1456,7 @@ xfs_incore_relse(
 	truncate_inode_pages(btp->pbr_mapping, 0LL);
 }
 
-void
+int
 xfs_setsize_buftarg(
 	xfs_buftarg_t		*btp,
 	unsigned int		blocksize,
@@ -1472,7 +1470,40 @@ xfs_setsize_buftarg(
 		printk(KERN_WARNING
 			"XFS: Cannot set_blocksize to %u on device 0x%x\n",
 			sectorsize, kdev_t_to_nr(btp->pbr_kdev));
+		return EINVAL;
 	}
+	return 0;
+}
+
+STATIC int
+xfs_mapping_buftarg(
+	xfs_buftarg_t		*btp,
+	struct block_device	*bdev)
+{
+	kdev_t			kdev;
+	struct inode		*inode;
+	struct address_space	*mapping;
+	static struct address_space_operations mapping_aops = {
+		.sync_page = block_sync_page,
+	};
+
+	kdev = to_kdev_t(bdev->bd_dev);
+	inode = new_inode(bdev->bd_inode->i_sb);
+	if (!inode) {
+		printk(KERN_WARNING
+			"XFS: Cannot allocate mapping inode for device %s\n",
+			XFS_BUFTARG_NAME(btp));
+		return ENOMEM;
+	}
+	inode->i_mode = S_IFBLK;
+	inode->i_dev  = kdev;
+	inode->i_rdev = kdev;
+	inode->i_bdev = bdev;
+	mapping = &inode->i_data;
+	mapping->a_ops = &mapping_aops;
+	mapping->gfp_mask = GFP_KERNEL;
+	btp->pbr_mapping = mapping;
+	return 0;
 }
 
 xfs_buftarg_t *
@@ -1480,16 +1511,14 @@ xfs_alloc_buftarg(
 	struct block_device	*bdev)
 {
 	xfs_buftarg_t		*btp;
+	kdev_t			kdev;
 
 	btp = kmem_zalloc(sizeof(*btp), KM_SLEEP);
 
+	kdev = to_kdev_t(bdev->bd_dev);
 	btp->pbr_dev =  bdev->bd_dev;
-	btp->pbr_kdev = to_kdev_t(btp->pbr_dev);
+	btp->pbr_kdev = kdev;
 	btp->pbr_bdev = bdev;
-	btp->pbr_mapping = bdev->bd_inode->i_mapping;
-	xfs_setsize_buftarg(btp, PAGE_CACHE_SIZE,
-			    get_hardsect_size(btp->pbr_kdev));
-
 	switch (MAJOR(btp->pbr_dev)) {
 	case MD_MAJOR:
 	case EVMS_MAJOR:
@@ -1499,8 +1528,15 @@ xfs_alloc_buftarg(
 		btp->pbr_flags = PBR_SECTOR_ONLY;
 		break;
 	}
-
+	if (xfs_setsize_buftarg(btp, PAGE_CACHE_SIZE, get_hardsect_size(kdev)))
+		goto error;
+	if (xfs_mapping_buftarg(btp, bdev))
+		goto error;
 	return btp;
+
+error:
+	kmem_free(btp, sizeof(*btp));
+	return NULL;
 }
 
 /*
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/xfs/linux-2.4/xfs_buf.h linux-2.4.28-pre3/fs/xfs/linux-2.4/xfs_buf.h
--- linux-2.4.27/fs/xfs/linux-2.4/xfs_buf.h	2004-08-07 23:26:06.000000000 +0000
+++ linux-2.4.28-pre3/fs/xfs/linux-2.4/xfs_buf.h	2004-09-10 19:36:31.000000000 +0000
@@ -617,7 +617,7 @@ static inline int xfs_bdwrite(void *mp, 
  
 extern xfs_buftarg_t *xfs_alloc_buftarg(struct block_device *);
 extern void xfs_free_buftarg(xfs_buftarg_t *, int);
-extern void xfs_setsize_buftarg(xfs_buftarg_t *, unsigned int, unsigned int);
+extern int xfs_setsize_buftarg(xfs_buftarg_t *, unsigned int, unsigned int);
 extern void xfs_incore_relse(xfs_buftarg_t *, int, int);
 extern int xfs_flush_buftarg(xfs_buftarg_t *, int);
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/xfs/linux-2.4/xfs_ioctl.c linux-2.4.28-pre3/fs/xfs/linux-2.4/xfs_ioctl.c
--- linux-2.4.27/fs/xfs/linux-2.4/xfs_ioctl.c	2004-08-07 23:26:06.000000000 +0000
+++ linux-2.4.28-pre3/fs/xfs/linux-2.4/xfs_ioctl.c	2004-09-10 19:36:44.000000000 +0000
@@ -71,14 +71,6 @@
 #include <linux/iobuf.h>
 
 /*
- * ioctl commands that are used by Linux filesystems
- */
-#define XFS_IOC_GETXFLAGS	_IOR('f', 1, long)
-#define XFS_IOC_SETXFLAGS	_IOW('f', 2, long)
-#define XFS_IOC_GETVERSION	_IOR('v', 1, long)
-
-
-/*
  * xfs_find_handle maps from userspace xfs_fsop_handlereq structure to
  * a file or fs handle.
  *
@@ -827,13 +819,23 @@ xfs_ioctl(
 	case XFS_IOC_FREEZE:
 		if (!capable(CAP_SYS_ADMIN))
 			return -EPERM;
-		xfs_fs_freeze(mp);
+
+		if (vp->v_vfsp->vfs_frozen == SB_UNFROZEN) {
+			freeze_bdev(mp->m_ddev_targp->pbr_bdev);
+			if (mp->m_rtdev_targp)
+				freeze_bdev(mp->m_rtdev_targp->pbr_bdev);
+		}
 		return 0;
 
 	case XFS_IOC_THAW:
 		if (!capable(CAP_SYS_ADMIN))
 			return -EPERM;
-		xfs_fs_thaw(mp);
+
+		if (vp->v_vfsp->vfs_frozen != SB_UNFROZEN) {
+			thaw_bdev(mp->m_ddev_targp->pbr_bdev, inode->i_sb);
+			if (mp->m_rtdev_targp)
+				thaw_bdev(mp->m_ddev_targp->pbr_bdev, NULL);
+		}
 		return 0;
 
 	case XFS_IOC_GOINGDOWN: {
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/xfs/linux-2.4/xfs_linux.h linux-2.4.28-pre3/fs/xfs/linux-2.4/xfs_linux.h
--- linux-2.4.27/fs/xfs/linux-2.4/xfs_linux.h	2004-08-07 23:26:06.000000000 +0000
+++ linux-2.4.28-pre3/fs/xfs/linux-2.4/xfs_linux.h	2004-09-10 19:35:59.000000000 +0000
@@ -35,6 +35,9 @@
 #include <linux/types.h>
 #include <linux/config.h>
 
+#undef __user
+#define __user
+
 /*
  * Some types are conditional depending on the target system.
  * XFS_BIG_BLKNOS needs block layer disk addresses to be 64 bits.
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/xfs/linux-2.4/xfs_lrw.c linux-2.4.28-pre3/fs/xfs/linux-2.4/xfs_lrw.c
--- linux-2.4.27/fs/xfs/linux-2.4/xfs_lrw.c	2004-08-07 23:26:06.000000000 +0000
+++ linux-2.4.28-pre3/fs/xfs/linux-2.4/xfs_lrw.c	2004-09-10 19:32:18.000000000 +0000
@@ -604,7 +604,7 @@ xfs_write(
 	io = &xip->i_iocore;
 	mp = io->io_mount;
 
-	xfs_check_frozen(mp, bdp, XFS_FREEZE_WRITE);
+	fs_check_frozen(vp->v_vfsp, SB_FREEZE_WRITE);
 
 	if (XFS_FORCED_SHUTDOWN(xip->i_mount)) {
 		return -EIO;
@@ -619,8 +619,6 @@ xfs_write(
 		iolock = XFS_IOLOCK_SHARED;
 		locktype = VRWLOCK_WRITE_DIRECT;
 	} else {
-		if (io->io_flags & XFS_IOCORE_RT)
-			return XFS_ERROR(-EINVAL);
 		iolock = XFS_IOLOCK_EXCL;
 		locktype = VRWLOCK_WRITE;
 	}
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/xfs/linux-2.4/xfs_super.c linux-2.4.28-pre3/fs/xfs/linux-2.4/xfs_super.c
--- linux-2.4.27/fs/xfs/linux-2.4/xfs_super.c	2004-08-07 23:26:06.000000000 +0000
+++ linux-2.4.28-pre3/fs/xfs/linux-2.4/xfs_super.c	2004-09-10 19:35:59.000000000 +0000
@@ -568,32 +568,73 @@ linvfs_remount(
 	return -error;
 }
 
+struct super_block *freeze_bdev(struct block_device *bdev)
+{
+	struct super_block *sb;
+	struct vfs *vfsp;
+	int error;
+
+	sb = get_super(to_kdev_t(bdev->bd_dev));
+	if (sb && !(sb->s_flags & MS_RDONLY)) {
+		vfsp = LINVFS_GET_VFS(sb);
+
+		/* Stop new writers */
+		vfsp->vfs_frozen = SB_FREEZE_WRITE;
+		wmb();
+
+		/* Flush the refcache */
+		VFS_SYNC(vfsp, SYNC_REFCACHE|SYNC_WAIT, NULL, error);
+
+		/* Flush delalloc and delwri data */
+		VFS_SYNC(vfsp, SYNC_DELWRI|SYNC_WAIT, NULL, error);
+
+		/* Pause transaction subsystem */
+		vfsp->vfs_frozen = SB_FREEZE_TRANS;
+		wmb();
+
+		/* Flush any remaining inodes into buffers */
+		VFS_SYNC(vfsp, SYNC_ATTR|SYNC_WAIT, NULL, error);
+
+		 /* Push all buffers out to disk */
+		sync_buffers(sb->s_dev, 1);
+
+		/* Push the superblock and write an unmount record */
+		VFS_FREEZE(vfsp);
+	}
+
+	sync_buffers(to_kdev_t(bdev->bd_dev), 1);
+	return sb;      /* thaw_bdev releases sb->s_umount */
+}
+
+void thaw_bdev(struct block_device *bdev, struct super_block *sb)
+{
+	if (sb) {
+		struct vfs *vfsp = LINVFS_GET_VFS(sb);
+
+		BUG_ON(sb->s_bdev != bdev);
+
+		vfsp->vfs_frozen = SB_UNFROZEN;
+		wmb();
+		wake_up(&vfsp->vfs_wait_unfrozen);
+
+		drop_super(sb);
+	}
+}
+
 STATIC void
 linvfs_freeze_fs(
 	struct super_block	*sb)
 {
-	vfs_t			*vfsp = LINVFS_GET_VFS(sb);
-	vnode_t			*vp;
-	int			error;
-
 	if (sb->s_flags & MS_RDONLY)
 		return;
-	VFS_ROOT(vfsp, &vp, error);
-	VOP_IOCTL(vp, LINVFS_GET_IP(vp), NULL, 0, XFS_IOC_FREEZE, 0, error);
-	VN_RELE(vp);
+	freeze_bdev(sb->s_bdev);
 }
 
 STATIC void
 linvfs_unfreeze_fs(
 	struct super_block	*sb)
 {
-	vfs_t			*vfsp = LINVFS_GET_VFS(sb);
-	vnode_t			*vp;
-	int			error;
-
-	VFS_ROOT(vfsp, &vp, error);
-	VOP_IOCTL(vp, LINVFS_GET_IP(vp), NULL, 0, XFS_IOC_THAW, 0, error);
-	VN_RELE(vp);
+	thaw_bdev(sb->s_bdev, sb);
 }
 
 STATIC int
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/xfs/linux-2.4/xfs_super.h linux-2.4.28-pre3/fs/xfs/linux-2.4/xfs_super.h
--- linux-2.4.27/fs/xfs/linux-2.4/xfs_super.h	2004-08-07 23:26:06.000000000 +0000
+++ linux-2.4.28-pre3/fs/xfs/linux-2.4/xfs_super.h	2004-09-10 19:34:20.000000000 +0000
@@ -136,5 +136,7 @@ extern void xfs_blkdev_put(struct block_
 
 /* matching a 2.6 kernel export, thus no xfs_ prefix */
 extern struct dentry *d_alloc_anon(struct inode *inode);
+extern struct super_block *freeze_bdev(struct block_device *bdev);
+extern void thaw_bdev(struct block_device *bdev, struct super_block *sb);
 
 #endif	/* __XFS_SUPER_H__ */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/xfs/linux-2.4/xfs_vfs.c linux-2.4.28-pre3/fs/xfs/linux-2.4/xfs_vfs.c
--- linux-2.4.27/fs/xfs/linux-2.4/xfs_vfs.c	2004-08-07 23:26:06.000000000 +0000
+++ linux-2.4.28-pre3/fs/xfs/linux-2.4/xfs_vfs.c	2004-09-10 19:33:27.000000000 +0000
@@ -243,6 +243,18 @@ vfs_force_shutdown(
 	((*bhvtovfsops(next)->vfs_force_shutdown)(next, fl, file, line));
 }
 
+void
+vfs_freeze(
+	struct bhv_desc		*bdp)
+{
+	struct bhv_desc		*next = bdp;
+
+	ASSERT(next);
+	while (! (bhvtovfsops(next))->vfs_freeze)
+		next = BHV_NEXT(next);
+	((*bhvtovfsops(next)->vfs_freeze)(next));
+}
+
 vfs_t *
 vfs_allocate( void )
 {
@@ -251,6 +263,7 @@ vfs_allocate( void )
 	vfsp = kmem_zalloc(sizeof(vfs_t), KM_SLEEP);
 	bhv_head_init(VFS_BHVHEAD(vfsp), "vfs");
 	init_waitqueue_head(&vfsp->vfs_wait_sync_task);
+	init_waitqueue_head(&vfsp->vfs_wait_unfrozen);
 	return vfsp;
 }
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/xfs/linux-2.4/xfs_vfs.h linux-2.4.28-pre3/fs/xfs/linux-2.4/xfs_vfs.h
--- linux-2.4.27/fs/xfs/linux-2.4/xfs_vfs.h	2004-08-07 23:26:06.000000000 +0000
+++ linux-2.4.28-pre3/fs/xfs/linux-2.4/xfs_vfs.h	2004-09-10 19:35:55.000000000 +0000
@@ -53,6 +53,8 @@ typedef struct vfs {
 	struct super_block	*vfs_super;	/* Linux superblock structure */
 	struct task_struct	*vfs_sync_task;
 	wait_queue_head_t	vfs_wait_sync_task;
+	int			vfs_frozen;
+	wait_queue_head_t	vfs_wait_unfrozen;
 } vfs_t;
 
 #define vfs_fbhv		vfs_bh.bh_first	/* 1st on vfs behavior chain */
@@ -114,6 +116,7 @@ typedef int	(*vfs_quotactl_t)(bhv_desc_t
 typedef void	(*vfs_init_vnode_t)(bhv_desc_t *,
 				struct vnode *, bhv_desc_t *, int);
 typedef void	(*vfs_force_shutdown_t)(bhv_desc_t *, int, char *, int);
+typedef void	(*vfs_freeze_t)(bhv_desc_t *);
 typedef	struct inode * (*vfs_get_inode_t)(bhv_desc_t *, xfs_ino_t, int);
 
 typedef struct vfsops {
@@ -132,6 +135,7 @@ typedef struct vfsops {
 	vfs_get_inode_t		vfs_get_inode;	/* bhv specific iget */
 	vfs_init_vnode_t	vfs_init_vnode;	/* initialize a new vnode */
 	vfs_force_shutdown_t	vfs_force_shutdown;	/* crash and burn */
+	vfs_freeze_t		vfs_freeze;	/* freeze fs for snapshot */
 } vfsops_t;
 
 /*
@@ -152,6 +156,7 @@ typedef struct vfsops {
 #define VFS_GET_INODE(v, ino, fl)	( vfs_get_inode(VHEAD(v), ino,fl) )
 #define VFS_INIT_VNODE(v, vp,b,ul)	( vfs_init_vnode(VHEAD(v), vp,b,ul) )
 #define VFS_FORCE_SHUTDOWN(v, fl,f,l)	( vfs_force_shutdown(VHEAD(v), fl,f,l) )
+#define VFS_FREEZE(v)			( vfs_freeze(VHEAD(v)) )
 
 /*
  * PVFS's.  Operates on behavior descriptor pointers.
@@ -170,6 +175,7 @@ typedef struct vfsops {
 #define PVFS_GET_INODE(b, ino,fl)	( vfs_get_inode(b, ino,fl) )
 #define PVFS_INIT_VNODE(b, vp,b2,ul)	( vfs_init_vnode(b, vp,b2,ul) )
 #define PVFS_FORCE_SHUTDOWN(b, fl,f,l)	( vfs_force_shutdown(b, fl,f,l) )
+#define PVFS_FREEZE(b)			( vfs_freeze(b) )
 
 extern int vfs_mount(bhv_desc_t *, struct xfs_mount_args *, struct cred *);
 extern int vfs_parseargs(bhv_desc_t *, char *, struct xfs_mount_args *, int);
@@ -185,6 +191,7 @@ extern int vfs_quotactl(bhv_desc_t *, in
 extern struct inode *vfs_get_inode(bhv_desc_t *, xfs_ino_t, int);
 extern void vfs_init_vnode(bhv_desc_t *, struct vnode *, bhv_desc_t *, int);
 extern void vfs_force_shutdown(bhv_desc_t *, int, char *, int);
+extern void vfs_freeze(bhv_desc_t *);
 
 typedef struct bhv_vfsops {
 	struct vfsops		bhv_common;
@@ -205,4 +212,14 @@ extern void bhv_insert_all_vfsops(struct
 extern void bhv_remove_all_vfsops(struct vfs *, int);
 extern void bhv_remove_vfsops(struct vfs *, int);
 
+enum {
+	SB_UNFROZEN = 0,
+	SB_FREEZE_WRITE	= 1,
+	SB_FREEZE_TRANS = 2,
+};
+
+#define fs_frozen(vfsp)		((vfsp)->vfs_frozen)
+#define fs_check_frozen(vfsp, level) \
+	wait_event((vfsp)->vfs_wait_unfrozen, ((vfsp)->vfs_frozen < (level)))
+
 #endif	/* __XFS_VFS_H__ */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/xfs/quota/xfs_dquot.c linux-2.4.28-pre3/fs/xfs/quota/xfs_dquot.c
--- linux-2.4.27/fs/xfs/quota/xfs_dquot.c	2004-02-18 13:36:32.000000000 +0000
+++ linux-2.4.28-pre3/fs/xfs/quota/xfs_dquot.c	2004-09-10 19:32:18.000000000 +0000
@@ -145,7 +145,7 @@ xfs_qm_dqinit(
 		 dqp->q_res_icount = 0;
 		 dqp->q_res_rtbcount = 0;
 		 dqp->q_pincount = 0;
-		 dqp->q_hash = 0;
+		 dqp->q_hash = NULL;
 		 ASSERT(dqp->dq_flnext == dqp->dq_flprev);
 
 #ifdef XFS_DQUOT_TRACE
@@ -187,9 +187,9 @@ xfs_qm_dqdestroy(
  */
 STATIC void
 xfs_qm_dqinit_core(
-	xfs_dqid_t	 id,
-	uint		 type,
-	xfs_dqblk_t	 *d)
+	xfs_dqid_t	id,
+	uint		type,
+	xfs_dqblk_t	*d)
 {
 	/*
 	 * Caller has zero'd the entire dquot 'chunk' already.
@@ -250,6 +250,36 @@ __xfs_dqtrace_entry(
 
 
 /*
+ * If default limits are in force, push them into the dquot now.
+ * We overwrite the dquot limits only if they are zero and this
+ * is not the root dquot.
+ */
+void
+xfs_qm_adjust_dqlimits(
+	xfs_mount_t		*mp,
+	xfs_disk_dquot_t	*d)
+{
+	xfs_quotainfo_t		*q = mp->m_quotainfo;
+
+	ASSERT(!INT_ISZERO(d->d_id, ARCH_CONVERT));
+
+	if (q->qi_bsoftlimit && INT_ISZERO(d->d_blk_softlimit, ARCH_CONVERT))
+		INT_SET(d->d_blk_softlimit, ARCH_CONVERT, q->qi_bsoftlimit);
+	if (q->qi_bhardlimit && INT_ISZERO(d->d_blk_hardlimit, ARCH_CONVERT))
+		INT_SET(d->d_blk_hardlimit, ARCH_CONVERT, q->qi_bhardlimit);
+	if (q->qi_isoftlimit && INT_ISZERO(d->d_ino_softlimit, ARCH_CONVERT))
+		INT_SET(d->d_ino_softlimit, ARCH_CONVERT, q->qi_isoftlimit);
+	if (q->qi_ihardlimit && INT_ISZERO(d->d_ino_hardlimit, ARCH_CONVERT))
+		INT_SET(d->d_ino_hardlimit, ARCH_CONVERT, q->qi_ihardlimit);
+	if (q->qi_rtbsoftlimit &&
+	    INT_ISZERO(d->d_rtb_softlimit, ARCH_CONVERT))
+		INT_SET(d->d_rtb_softlimit, ARCH_CONVERT, q->qi_rtbsoftlimit);
+	if (q->qi_rtbhardlimit &&
+	    INT_ISZERO(d->d_rtb_hardlimit, ARCH_CONVERT))
+		INT_SET(d->d_rtb_hardlimit, ARCH_CONVERT, q->qi_rtbhardlimit);
+}
+
+/*
  * Check the limits and timers of a dquot and start or reset timers
  * if necessary.
  * This gets called even when quota enforcement is OFF, which makes our
@@ -265,53 +295,81 @@ xfs_qm_adjust_dqtimers(
 	xfs_mount_t		*mp,
 	xfs_disk_dquot_t	*d)
 {
-	/*
-	 * The dquot had better be locked. We are modifying it here.
-	 */
-
-	/*
-	 * root's limits are not real limits.
-	 */
-	if (INT_ISZERO(d->d_id, ARCH_CONVERT))
-		return;
+	ASSERT(!INT_ISZERO(d->d_id, ARCH_CONVERT));
 
 #ifdef QUOTADEBUG
 	if (INT_GET(d->d_blk_hardlimit, ARCH_CONVERT))
-		ASSERT(INT_GET(d->d_blk_softlimit, ARCH_CONVERT) <= INT_GET(d->d_blk_hardlimit, ARCH_CONVERT));
+		ASSERT(INT_GET(d->d_blk_softlimit, ARCH_CONVERT) <=
+			INT_GET(d->d_blk_hardlimit, ARCH_CONVERT));
 	if (INT_GET(d->d_ino_hardlimit, ARCH_CONVERT))
-		ASSERT(INT_GET(d->d_ino_softlimit, ARCH_CONVERT) <= INT_GET(d->d_ino_hardlimit, ARCH_CONVERT));
+		ASSERT(INT_GET(d->d_ino_softlimit, ARCH_CONVERT) <=
+			INT_GET(d->d_ino_hardlimit, ARCH_CONVERT));
+	if (INT_GET(d->d_rtb_hardlimit, ARCH_CONVERT))
+		ASSERT(INT_GET(d->d_rtb_softlimit, ARCH_CONVERT) <=
+			INT_GET(d->d_rtb_hardlimit, ARCH_CONVERT));
 #endif
 	if (INT_ISZERO(d->d_btimer, ARCH_CONVERT)) {
 		if ((INT_GET(d->d_blk_softlimit, ARCH_CONVERT) &&
-		    (INT_GET(d->d_bcount, ARCH_CONVERT) >= INT_GET(d->d_blk_softlimit, ARCH_CONVERT))) ||
+		    (INT_GET(d->d_bcount, ARCH_CONVERT) >=
+				INT_GET(d->d_blk_softlimit, ARCH_CONVERT))) ||
 		    (INT_GET(d->d_blk_hardlimit, ARCH_CONVERT) &&
-		    (INT_GET(d->d_bcount, ARCH_CONVERT) >= INT_GET(d->d_blk_hardlimit, ARCH_CONVERT)))) {
-			INT_SET(d->d_btimer, ARCH_CONVERT, get_seconds() + XFS_QI_BTIMELIMIT(mp));
+		    (INT_GET(d->d_bcount, ARCH_CONVERT) >=
+				INT_GET(d->d_blk_hardlimit, ARCH_CONVERT)))) {
+			INT_SET(d->d_btimer, ARCH_CONVERT,
+				get_seconds() + XFS_QI_BTIMELIMIT(mp));
 		}
 	} else {
 		if ((INT_ISZERO(d->d_blk_softlimit, ARCH_CONVERT) ||
-		    (INT_GET(d->d_bcount, ARCH_CONVERT) < INT_GET(d->d_blk_softlimit, ARCH_CONVERT))) &&
+		    (INT_GET(d->d_bcount, ARCH_CONVERT) <
+				INT_GET(d->d_blk_softlimit, ARCH_CONVERT))) &&
 		    (INT_ISZERO(d->d_blk_hardlimit, ARCH_CONVERT) ||
-		    (INT_GET(d->d_bcount, ARCH_CONVERT) < INT_GET(d->d_blk_hardlimit, ARCH_CONVERT)))) {
+		    (INT_GET(d->d_bcount, ARCH_CONVERT) <
+				INT_GET(d->d_blk_hardlimit, ARCH_CONVERT)))) {
 			INT_ZERO(d->d_btimer, ARCH_CONVERT);
 		}
 	}
 
 	if (INT_ISZERO(d->d_itimer, ARCH_CONVERT)) {
 		if ((INT_GET(d->d_ino_softlimit, ARCH_CONVERT) &&
-		    (INT_GET(d->d_icount, ARCH_CONVERT) >= INT_GET(d->d_ino_softlimit, ARCH_CONVERT))) ||
+		    (INT_GET(d->d_icount, ARCH_CONVERT) >=
+				INT_GET(d->d_ino_softlimit, ARCH_CONVERT))) ||
 		    (INT_GET(d->d_ino_hardlimit, ARCH_CONVERT) &&
-		    (INT_GET(d->d_icount, ARCH_CONVERT) >= INT_GET(d->d_ino_hardlimit, ARCH_CONVERT)))) {
-			INT_SET(d->d_itimer, ARCH_CONVERT, get_seconds() + XFS_QI_ITIMELIMIT(mp));
+		    (INT_GET(d->d_icount, ARCH_CONVERT) >=
+				INT_GET(d->d_ino_hardlimit, ARCH_CONVERT)))) {
+			INT_SET(d->d_itimer, ARCH_CONVERT,
+				get_seconds() + XFS_QI_ITIMELIMIT(mp));
 		}
 	} else {
 		if ((INT_ISZERO(d->d_ino_softlimit, ARCH_CONVERT) ||
-		    (INT_GET(d->d_icount, ARCH_CONVERT) < INT_GET(d->d_ino_softlimit, ARCH_CONVERT)))  &&
+		    (INT_GET(d->d_icount, ARCH_CONVERT) <
+				INT_GET(d->d_ino_softlimit, ARCH_CONVERT)))  &&
 		    (INT_ISZERO(d->d_ino_hardlimit, ARCH_CONVERT) ||
-		    (INT_GET(d->d_icount, ARCH_CONVERT) < INT_GET(d->d_ino_hardlimit, ARCH_CONVERT)))) {
+		    (INT_GET(d->d_icount, ARCH_CONVERT) <
+				INT_GET(d->d_ino_hardlimit, ARCH_CONVERT)))) {
 			INT_ZERO(d->d_itimer, ARCH_CONVERT);
 		}
 	}
+
+	if (INT_ISZERO(d->d_rtbtimer, ARCH_CONVERT)) {
+		if ((INT_GET(d->d_rtb_softlimit, ARCH_CONVERT) &&
+		    (INT_GET(d->d_rtbcount, ARCH_CONVERT) >=
+				INT_GET(d->d_rtb_softlimit, ARCH_CONVERT))) ||
+		    (INT_GET(d->d_rtb_hardlimit, ARCH_CONVERT) &&
+		    (INT_GET(d->d_rtbcount, ARCH_CONVERT) >=
+				INT_GET(d->d_rtb_hardlimit, ARCH_CONVERT)))) {
+			INT_SET(d->d_rtbtimer, ARCH_CONVERT,
+				get_seconds() + XFS_QI_RTBTIMELIMIT(mp));
+		}
+	} else {
+		if ((INT_ISZERO(d->d_rtb_softlimit, ARCH_CONVERT) ||
+		    (INT_GET(d->d_rtbcount, ARCH_CONVERT) <
+				INT_GET(d->d_rtb_softlimit, ARCH_CONVERT))) &&
+		    (INT_ISZERO(d->d_rtb_hardlimit, ARCH_CONVERT) ||
+		    (INT_GET(d->d_rtbcount, ARCH_CONVERT) <
+				INT_GET(d->d_rtb_hardlimit, ARCH_CONVERT)))) {
+			INT_ZERO(d->d_rtbtimer, ARCH_CONVERT);
+		}
+	}
 }
 
 /*
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/xfs/quota/xfs_dquot.h linux-2.4.28-pre3/fs/xfs/quota/xfs_dquot.h
--- linux-2.4.27/fs/xfs/quota/xfs_dquot.h	2004-02-18 13:36:32.000000000 +0000
+++ linux-2.4.28-pre3/fs/xfs/quota/xfs_dquot.h	2004-09-10 19:33:21.000000000 +0000
@@ -209,6 +209,8 @@ extern int		xfs_qm_dqflock_nowait(xfs_dq
 extern void		xfs_qm_dqflock_pushbuf_wait(xfs_dquot_t *dqp);
 extern void		xfs_qm_adjust_dqtimers(xfs_mount_t *,
 					xfs_disk_dquot_t *);
+extern void		xfs_qm_adjust_dqlimits(xfs_mount_t *,
+					xfs_disk_dquot_t *);
 extern int		xfs_qm_dqwarn(xfs_disk_dquot_t *, uint);
 extern int		xfs_qm_dqget(xfs_mount_t *, xfs_inode_t *,
 					xfs_dqid_t, uint, uint, xfs_dquot_t **);
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/xfs/quota/xfs_qm.c linux-2.4.28-pre3/fs/xfs/quota/xfs_qm.c
--- linux-2.4.27/fs/xfs/quota/xfs_qm.c	2004-08-07 23:26:06.000000000 +0000
+++ linux-2.4.28-pre3/fs/xfs/quota/xfs_qm.c	2004-09-10 19:33:48.000000000 +0000
@@ -229,11 +229,8 @@ xfs_qm_hold_quotafs_ref(
 	 */
 	XFS_QM_LOCK(xfs_Gqm);
 
-	if (xfs_Gqm == NULL) {
-		if ((xfs_Gqm = xfs_Gqm_init()) == NULL) {
-			return (XFS_ERROR(EINVAL));
-		}
-	}
+	if (xfs_Gqm == NULL)
+		xfs_Gqm = xfs_Gqm_init();
 	/*
 	 * We can keep a list of all filesystems with quotas mounted for
 	 * debugging and statistical purposes, but ...
@@ -1216,22 +1213,46 @@ xfs_qm_init_quotainfo(
 			     XFS_QMOPT_DQSUSER|XFS_QMOPT_DOWARN,
 			     &dqp);
 	if (! error) {
+		xfs_disk_dquot_t	*ddqp = &dqp->q_core;
+
 		/*
 		 * The warnings and timers set the grace period given to
 		 * a user or group before he or she can not perform any
 		 * more writing. If it is zero, a default is used.
 		 */
-		qinf->qi_btimelimit = INT_GET(dqp->q_core.d_btimer, ARCH_CONVERT) ?
-			INT_GET(dqp->q_core.d_btimer, ARCH_CONVERT) : XFS_QM_BTIMELIMIT;
-		qinf->qi_itimelimit = INT_GET(dqp->q_core.d_itimer, ARCH_CONVERT) ?
-			INT_GET(dqp->q_core.d_itimer, ARCH_CONVERT) : XFS_QM_ITIMELIMIT;
-		qinf->qi_rtbtimelimit = INT_GET(dqp->q_core.d_rtbtimer, ARCH_CONVERT) ?
-			INT_GET(dqp->q_core.d_rtbtimer, ARCH_CONVERT) : XFS_QM_RTBTIMELIMIT;
-		qinf->qi_bwarnlimit = INT_GET(dqp->q_core.d_bwarns, ARCH_CONVERT) ?
-			INT_GET(dqp->q_core.d_bwarns, ARCH_CONVERT) : XFS_QM_BWARNLIMIT;
-		qinf->qi_iwarnlimit = INT_GET(dqp->q_core.d_iwarns, ARCH_CONVERT) ?
-			INT_GET(dqp->q_core.d_iwarns, ARCH_CONVERT) : XFS_QM_IWARNLIMIT;
-
+		qinf->qi_btimelimit =
+				INT_GET(ddqp->d_btimer, ARCH_CONVERT) ?
+				INT_GET(ddqp->d_btimer, ARCH_CONVERT) :
+				XFS_QM_BTIMELIMIT;
+		qinf->qi_itimelimit =
+				INT_GET(ddqp->d_itimer, ARCH_CONVERT) ?
+				INT_GET(ddqp->d_itimer, ARCH_CONVERT) :
+				XFS_QM_ITIMELIMIT;
+		qinf->qi_rtbtimelimit =
+				INT_GET(ddqp->d_rtbtimer, ARCH_CONVERT) ?
+				INT_GET(ddqp->d_rtbtimer, ARCH_CONVERT) :
+				XFS_QM_RTBTIMELIMIT;
+		qinf->qi_bwarnlimit =
+				INT_GET(ddqp->d_bwarns, ARCH_CONVERT) ?
+				INT_GET(ddqp->d_bwarns, ARCH_CONVERT) :
+				XFS_QM_BWARNLIMIT;
+		qinf->qi_iwarnlimit =
+				INT_GET(ddqp->d_iwarns, ARCH_CONVERT) ?
+				INT_GET(ddqp->d_iwarns, ARCH_CONVERT) :
+				XFS_QM_IWARNLIMIT;
+		qinf->qi_bhardlimit =
+				INT_GET(ddqp->d_blk_hardlimit, ARCH_CONVERT);
+		qinf->qi_bsoftlimit =
+				INT_GET(ddqp->d_blk_softlimit, ARCH_CONVERT);
+		qinf->qi_ihardlimit =
+				INT_GET(ddqp->d_ino_hardlimit, ARCH_CONVERT);
+		qinf->qi_isoftlimit =
+				INT_GET(ddqp->d_ino_softlimit, ARCH_CONVERT);
+		qinf->qi_rtbhardlimit =
+				INT_GET(ddqp->d_rtb_hardlimit, ARCH_CONVERT);
+		qinf->qi_rtbsoftlimit =
+				INT_GET(ddqp->d_rtb_softlimit, ARCH_CONVERT);
+ 
 		/*
 		 * We sent the XFS_QMOPT_DQSUSER flag to dqget because
 		 * we don't want this dquot cached. We haven't done a
@@ -1691,10 +1712,12 @@ xfs_qm_quotacheck_dqadjust(
 	}
 
 	/*
-	 * Adjust the timers since we just changed usages
+	 * Set default limits, adjust timers (since we changed usages)
 	 */
-	if (! XFS_IS_SUSER_DQUOT(dqp))
+	if (! XFS_IS_SUSER_DQUOT(dqp)) {
+		xfs_qm_adjust_dqlimits(dqp->q_mount, &dqp->q_core);
 		xfs_qm_adjust_dqtimers(dqp->q_mount, &dqp->q_core);
+	}
 
 	dqp->dq_flags |= XFS_DQ_DIRTY;
 }
@@ -1735,7 +1758,7 @@ STATIC int
 xfs_qm_dqusage_adjust(
 	xfs_mount_t	*mp,		/* mount point for filesystem */
 	xfs_ino_t	ino,		/* inode number to get data for */
-	void		*buffer,	/* not used */
+	void		__user *buffer,	/* not used */
 	int		ubsize,		/* not used */
 	void		*private_data,	/* not used */
 	xfs_daddr_t	bno,		/* starting block of inode cluster */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/xfs/quota/xfs_qm.h linux-2.4.28-pre3/fs/xfs/quota/xfs_qm.h
--- linux-2.4.27/fs/xfs/quota/xfs_qm.h	2004-02-18 13:36:32.000000000 +0000
+++ linux-2.4.28-pre3/fs/xfs/quota/xfs_qm.h	2004-09-10 19:34:45.000000000 +0000
@@ -136,9 +136,14 @@ typedef struct xfs_quotainfo {
 	xfs_qwarncnt_t	 qi_bwarnlimit;	 /* limit for num warnings */
 	xfs_qwarncnt_t	 qi_iwarnlimit;	 /* limit for num warnings */
 	mutex_t		 qi_quotaofflock;/* to serialize quotaoff */
-	/* Some useful precalculated constants */
 	xfs_filblks_t	 qi_dqchunklen;	 /* # BBs in a chunk of dqs */
 	uint		 qi_dqperchunk;	 /* # ondisk dqs in above chunk */
+	xfs_qcnt_t	 qi_bhardlimit;	 /* default data blk hard limit */
+	xfs_qcnt_t	 qi_bsoftlimit;	 /* default data blk soft limit */
+	xfs_qcnt_t	 qi_ihardlimit;	 /* default inode count hard limit */
+	xfs_qcnt_t	 qi_isoftlimit;	 /* default inode count soft limit */
+	xfs_qcnt_t	 qi_rtbhardlimit;/* default realtime blk hard limit */
+	xfs_qcnt_t	 qi_rtbsoftlimit;/* default realtime blk soft limit */
 } xfs_quotainfo_t;
 
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/xfs/quota/xfs_qm_stats.c linux-2.4.28-pre3/fs/xfs/quota/xfs_qm_stats.c
--- linux-2.4.27/fs/xfs/quota/xfs_qm_stats.c	2004-02-18 13:36:32.000000000 +0000
+++ linux-2.4.28-pre3/fs/xfs/quota/xfs_qm_stats.c	2004-09-10 19:33:14.000000000 +0000
@@ -137,8 +137,8 @@ xfs_qm_read_stats(
 void
 xfs_qm_init_procfs(void)
 {
-	create_proc_read_entry("fs/xfs/xqmstat", 0, 0, xfs_qm_read_stats, NULL);
-	create_proc_read_entry("fs/xfs/xqm", 0, 0, xfs_qm_read_xfsquota, NULL);
+	create_proc_read_entry("fs/xfs/xqmstat", 0, NULL, xfs_qm_read_stats, NULL);
+	create_proc_read_entry("fs/xfs/xqm", 0, NULL, xfs_qm_read_xfsquota, NULL);
 }
 
 void
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/xfs/quota/xfs_qm_syscalls.c linux-2.4.28-pre3/fs/xfs/quota/xfs_qm_syscalls.c
--- linux-2.4.27/fs/xfs/quota/xfs_qm_syscalls.c	2004-08-07 23:26:06.000000000 +0000
+++ linux-2.4.28-pre3/fs/xfs/quota/xfs_qm_syscalls.c	2004-09-10 19:34:03.000000000 +0000
@@ -648,8 +648,11 @@ xfs_qm_scall_setqlim(
 	if (hard == 0 || hard >= soft) {
 		INT_SET(ddq->d_blk_hardlimit, ARCH_CONVERT, hard);
 		INT_SET(ddq->d_blk_softlimit, ARCH_CONVERT, soft);
-	}
-	else {
+		if (id == 0) {
+			mp->m_quotainfo->qi_bhardlimit = hard;
+			mp->m_quotainfo->qi_bsoftlimit = soft;
+		}
+	} else {
 		qdprintk("blkhard %Ld < blksoft %Ld\n", hard, soft);
 	}
 	hard = (newlim->d_fieldmask & FS_DQ_RTBHARD) ?
@@ -661,40 +664,49 @@ xfs_qm_scall_setqlim(
 	if (hard == 0 || hard >= soft) {
 		INT_SET(ddq->d_rtb_hardlimit, ARCH_CONVERT, hard);
 		INT_SET(ddq->d_rtb_softlimit, ARCH_CONVERT, soft);
-	}
-	else
+		if (id == 0) {
+			mp->m_quotainfo->qi_rtbhardlimit = hard;
+			mp->m_quotainfo->qi_rtbsoftlimit = soft;
+		}
+	} else {
 		qdprintk("rtbhard %Ld < rtbsoft %Ld\n", hard, soft);
+	}
 
 	hard = (newlim->d_fieldmask & FS_DQ_IHARD) ?
 		(xfs_qcnt_t) newlim->d_ino_hardlimit :
-		INT_GET(ddq->d_ino_hardlimit, ARCH_CONVERT);
+			INT_GET(ddq->d_ino_hardlimit, ARCH_CONVERT);
 	soft = (newlim->d_fieldmask & FS_DQ_ISOFT) ?
 		(xfs_qcnt_t) newlim->d_ino_softlimit :
-		INT_GET(ddq->d_ino_softlimit, ARCH_CONVERT);
+			INT_GET(ddq->d_ino_softlimit, ARCH_CONVERT);
 	if (hard == 0 || hard >= soft) {
 		INT_SET(ddq->d_ino_hardlimit, ARCH_CONVERT, hard);
 		INT_SET(ddq->d_ino_softlimit, ARCH_CONVERT, soft);
-	}
-	else
+		if (id == 0) {
+			mp->m_quotainfo->qi_ihardlimit = hard;
+			mp->m_quotainfo->qi_isoftlimit = soft;
+		}
+	} else {
 		qdprintk("ihard %Ld < isoft %Ld\n", hard, soft);
+	}
 
 	if (id == 0) {
 		/*
 		 * Timelimits for the super user set the relative time
 		 * the other users can be over quota for this file system.
-		 * If it is zero a default is used.
+		 * If it is zero a default is used.  Ditto for the default
+		 * soft and hard limit values (already done, above).
 		 */
 		if (newlim->d_fieldmask & FS_DQ_BTIMER) {
 			mp->m_quotainfo->qi_btimelimit = newlim->d_btimer;
-			INT_SET(dqp->q_core.d_btimer, ARCH_CONVERT, newlim->d_btimer);
+			INT_SET(ddq->d_btimer, ARCH_CONVERT, newlim->d_btimer);
 		}
 		if (newlim->d_fieldmask & FS_DQ_ITIMER) {
 			mp->m_quotainfo->qi_itimelimit = newlim->d_itimer;
-			INT_SET(dqp->q_core.d_itimer, ARCH_CONVERT, newlim->d_itimer);
+			INT_SET(ddq->d_itimer, ARCH_CONVERT, newlim->d_itimer);
 		}
 		if (newlim->d_fieldmask & FS_DQ_RTBTIMER) {
 			mp->m_quotainfo->qi_rtbtimelimit = newlim->d_rtbtimer;
-			INT_SET(dqp->q_core.d_rtbtimer, ARCH_CONVERT, newlim->d_rtbtimer);
+			INT_SET(ddq->d_rtbtimer, ARCH_CONVERT, newlim->d_rtbtimer);
 		}
 	} else /* if (XFS_IS_QUOTA_ENFORCED(mp)) */ {
 		/*
@@ -1114,7 +1126,7 @@ mutex_t	      qcheck_lock;
 	  cmn_err(CE_DEBUG, "%s (#%d)", title, (int) (l)->qh_nelems); \
 	  for (dqp = (xfs_dqtest_t *)(l)->qh_next; dqp != NULL; \
 	       dqp = (xfs_dqtest_t *)dqp->NXT) { \
-		cmn_err(CE_DEBUG, "  %d\. \"%d (%s)\"  bcnt = %d, icnt = %d", \
+		cmn_err(CE_DEBUG, "  %d. \"%d (%s)\"  bcnt = %d, icnt = %d", \
 			 ++i, dqp->d_id, DQFLAGTO_TYPESTR(dqp),	     \
 			 dqp->d_bcount, dqp->d_icount); } \
 }
@@ -1299,7 +1311,7 @@ STATIC int
 xfs_qm_internalqcheck_adjust(
 	xfs_mount_t	*mp,		/* mount point for filesystem */
 	xfs_ino_t	ino,		/* inode number to get data for */
-	void		*buffer,	/* not used */
+	void		__user *buffer,	/* not used */
 	int		ubsize,		/* not used */
 	void		*private_data,	/* not used */
 	xfs_daddr_t	bno,		/* starting block of inode cluster */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/xfs/quota/xfs_trans_dquot.c linux-2.4.28-pre3/fs/xfs/quota/xfs_trans_dquot.c
--- linux-2.4.27/fs/xfs/quota/xfs_trans_dquot.c	2004-02-18 13:36:32.000000000 +0000
+++ linux-2.4.28-pre3/fs/xfs/quota/xfs_trans_dquot.c	2004-09-10 19:37:20.000000000 +0000
@@ -452,9 +452,13 @@ xfs_trans_apply_dquot_deltas(
 				INT_MOD(d->d_rtbcount, ARCH_CONVERT, (xfs_qcnt_t)totalrtbdelta);
 
 			/*
+			 * Get any default limits in use.
 			 * Start/reset the timer(s) if needed.
 			 */
-			xfs_qm_adjust_dqtimers(tp->t_mountp, d);
+			if (!INT_ISZERO(d->d_id, ARCH_CONVERT)) {
+				xfs_qm_adjust_dqlimits(tp->t_mountp, d);
+				xfs_qm_adjust_dqtimers(tp->t_mountp, d);
+			}
 
 			dqp->dq_flags |= XFS_DQ_DIRTY;
 			/*
@@ -625,6 +629,7 @@ xfs_trans_unreserve_and_mod_dquots(
 STATIC int
 xfs_trans_dqresv(
 	xfs_trans_t	*tp,
+	xfs_mount_t	*mp,
 	xfs_dquot_t	*dqp,
 	long		nblks,
 	long		ninos,
@@ -635,6 +640,7 @@ xfs_trans_dqresv(
 	xfs_qcnt_t	softlimit;
 	time_t		btimer;
 	xfs_qcnt_t	*resbcountp;
+	xfs_quotainfo_t	*q = mp->m_quotainfo;
 
 	if (! (flags & XFS_QMOPT_DQLOCK)) {
 		xfs_dqlock(dqp);
@@ -642,13 +648,21 @@ xfs_trans_dqresv(
 	ASSERT(XFS_DQ_IS_LOCKED(dqp));
 	if (flags & XFS_TRANS_DQ_RES_BLKS) {
 		hardlimit = INT_GET(dqp->q_core.d_blk_hardlimit, ARCH_CONVERT);
+		if (!hardlimit)
+			hardlimit = q->qi_bhardlimit;
 		softlimit = INT_GET(dqp->q_core.d_blk_softlimit, ARCH_CONVERT);
+		if (!softlimit)
+			softlimit = q->qi_bsoftlimit;
 		btimer = INT_GET(dqp->q_core.d_btimer, ARCH_CONVERT);
 		resbcountp = &dqp->q_res_bcount;
 	} else {
 		ASSERT(flags & XFS_TRANS_DQ_RES_RTBLKS);
 		hardlimit = INT_GET(dqp->q_core.d_rtb_hardlimit, ARCH_CONVERT);
+		if (!hardlimit)
+			hardlimit = q->qi_rtbhardlimit;
 		softlimit = INT_GET(dqp->q_core.d_rtb_softlimit, ARCH_CONVERT);
+		if (!softlimit)
+			softlimit = q->qi_rtbsoftlimit;
 		btimer = INT_GET(dqp->q_core.d_rtbtimer, ARCH_CONVERT);
 		resbcountp = &dqp->q_res_rtbcount;
 	}
@@ -689,14 +703,18 @@ xfs_trans_dqresv(
 			}
 		}
 		if (ninos > 0) {
-			if (INT_GET(dqp->q_core.d_ino_hardlimit, ARCH_CONVERT) > 0ULL &&
-			    INT_GET(dqp->q_core.d_icount, ARCH_CONVERT) >=
-			    INT_GET(dqp->q_core.d_ino_hardlimit, ARCH_CONVERT)) {
+			hardlimit = INT_GET(dqp->q_core.d_ino_hardlimit, ARCH_CONVERT);
+			if (!hardlimit)
+				hardlimit = q->qi_ihardlimit;
+			softlimit = INT_GET(dqp->q_core.d_ino_softlimit, ARCH_CONVERT);
+			if (!softlimit)
+				softlimit = q->qi_isoftlimit;
+			if (hardlimit > 0ULL &&
+			    INT_GET(dqp->q_core.d_icount, ARCH_CONVERT) >= hardlimit) {
 				error = EDQUOT;
 				goto error_return;
-			} else if (INT_GET(dqp->q_core.d_ino_softlimit, ARCH_CONVERT) > 0ULL &&
-				   INT_GET(dqp->q_core.d_icount, ARCH_CONVERT) >=
-				   INT_GET(dqp->q_core.d_ino_softlimit, ARCH_CONVERT)) {
+			} else if (softlimit > 0ULL &&
+				   INT_GET(dqp->q_core.d_icount, ARCH_CONVERT) >= softlimit) {
 				/*
 				 * If timer or warnings has expired,
 				 * return EDQUOT
@@ -786,19 +804,20 @@ xfs_trans_reserve_quota_bydquots(
 	resvd = 0;
 
 	if (udqp) {
-		if (xfs_trans_dqresv(tp, udqp, nblks, ninos, flags))
+		if (xfs_trans_dqresv(tp, mp, udqp, nblks, ninos, flags))
 			return (EDQUOT);
 		resvd = 1;
 	}
 
 	if (gdqp) {
-		if (xfs_trans_dqresv(tp, gdqp, nblks, ninos, flags)) {
+		if (xfs_trans_dqresv(tp, mp, gdqp, nblks, ninos, flags)) {
 			/*
 			 * can't do it, so backout previous reservation
 			 */
 			if (resvd) {
-				xfs_trans_dqresv(tp, udqp,  -nblks, -ninos,
-						 flags);
+				flags |= XFS_QMOPT_FORCE_RES;
+				xfs_trans_dqresv(tp, mp, udqp,
+						 -nblks, -ninos, flags);
 			}
 			return (EDQUOT);
 		}
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/xfs/support/ktrace.c linux-2.4.28-pre3/fs/xfs/support/ktrace.c
--- linux-2.4.27/fs/xfs/support/ktrace.c	2004-02-18 13:36:32.000000000 +0000
+++ linux-2.4.28-pre3/fs/xfs/support/ktrace.c	2004-09-10 19:33:53.000000000 +0000
@@ -30,14 +30,7 @@
  * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
  */
 
-#include <linux/types.h>
-#include <linux/slab.h>
-
-#include <xfs_types.h>
-#include "kmem.h"
-#include "spin.h"
-#include "debug.h"
-#include "ktrace.h"
+#include <xfs.h>
 
 static kmem_zone_t *ktrace_hdr_zone;
 static kmem_zone_t *ktrace_ent_zone;
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/xfs/support/move.c linux-2.4.28-pre3/fs/xfs/support/move.c
--- linux-2.4.27/fs/xfs/support/move.c	2004-02-18 13:36:32.000000000 +0000
+++ linux-2.4.28-pre3/fs/xfs/support/move.c	2004-09-10 19:34:29.000000000 +0000
@@ -30,13 +30,7 @@
  * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
  */
 
-#include <linux/string.h>
-#include <linux/errno.h>
-#include <asm/uaccess.h>
-
-#include <xfs_types.h>
-#include "debug.h"
-#include "move.h"
+#include <xfs.h>
 
 /* Read from kernel buffer at src to user/kernel buffer defined
  * by the uio structure. Advance the pointer in the uio struct
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/xfs/xfs_acl.h linux-2.4.28-pre3/fs/xfs/xfs_acl.h
--- linux-2.4.27/fs/xfs/xfs_acl.h	2004-08-07 23:26:06.000000000 +0000
+++ linux-2.4.28-pre3/fs/xfs/xfs_acl.h	2004-09-10 19:31:51.000000000 +0000
@@ -95,7 +95,7 @@ extern int xfs_acl_vremove(struct vnode 
 #define _ACL_XFS_IACCESS(i,m,c) (XFS_IFORK_Q(i) ? xfs_acl_iaccess(i,m,c) : -1)
 
 #define _ACL_ALLOC(a)		((a) = kmem_zone_alloc(xfs_acl_zone, KM_SLEEP))
-#define _ACL_FREE(a)		((a)? kmem_zone_free(xfs_acl_zone, (a)) : 0)
+#define _ACL_FREE(a)		((a)? kmem_zone_free(xfs_acl_zone, (a)):(void)0)
 
 #else
 #define xfs_acl_zone_init(zone,name)
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/xfs/xfs_alloc.c linux-2.4.28-pre3/fs/xfs/xfs_alloc.c
--- linux-2.4.27/fs/xfs/xfs_alloc.c	2004-04-14 13:05:40.000000000 +0000
+++ linux-2.4.28-pre3/fs/xfs/xfs_alloc.c	2004-09-10 19:32:31.000000000 +0000
@@ -665,7 +665,7 @@ xfs_alloc_ag_vextent_exact(
 	 * Allocate/initialize a cursor for the by-number freespace btree.
 	 */
 	bno_cur = xfs_btree_init_cursor(args->mp, args->tp, args->agbp,
-		args->agno, XFS_BTNUM_BNO, 0, 0);
+		args->agno, XFS_BTNUM_BNO, NULL, 0);
 	/*
 	 * Lookup bno and minlen in the btree (minlen is irrelevant, really).
 	 * Look for the closest free block <= bno, it must contain bno
@@ -721,7 +721,7 @@ xfs_alloc_ag_vextent_exact(
 	 * Allocate/initialize a cursor for the by-size btree.
 	 */
 	cnt_cur = xfs_btree_init_cursor(args->mp, args->tp, args->agbp,
-		args->agno, XFS_BTNUM_CNT, 0, 0);
+		args->agno, XFS_BTNUM_CNT, NULL, 0);
 	ASSERT(args->agbno + args->len <=
 		INT_GET(XFS_BUF_TO_AGF(args->agbp)->agf_length,
 			ARCH_CONVERT));
@@ -788,7 +788,7 @@ xfs_alloc_ag_vextent_near(
 	 * Get a cursor for the by-size btree.
 	 */
 	cnt_cur = xfs_btree_init_cursor(args->mp, args->tp, args->agbp,
-		args->agno, XFS_BTNUM_CNT, 0, 0);
+		args->agno, XFS_BTNUM_CNT, NULL, 0);
 	ltlen = 0;
 	bno_cur_lt = bno_cur_gt = NULL;
 	/*
@@ -916,7 +916,7 @@ xfs_alloc_ag_vextent_near(
 		 * Set up a cursor for the by-bno tree.
 		 */
 		bno_cur_lt = xfs_btree_init_cursor(args->mp, args->tp,
-			args->agbp, args->agno, XFS_BTNUM_BNO, 0, 0);
+			args->agbp, args->agno, XFS_BTNUM_BNO, NULL, 0);
 		/*
 		 * Fix up the btree entries.
 		 */
@@ -944,7 +944,7 @@ xfs_alloc_ag_vextent_near(
 	 * Allocate and initialize the cursor for the leftward search.
 	 */
 	bno_cur_lt = xfs_btree_init_cursor(args->mp, args->tp, args->agbp,
-		args->agno, XFS_BTNUM_BNO, 0, 0);
+		args->agno, XFS_BTNUM_BNO, NULL, 0);
 	/*
 	 * Lookup <= bno to find the leftward search's starting point.
 	 */
@@ -956,7 +956,7 @@ xfs_alloc_ag_vextent_near(
 		 * search.
 		 */
 		bno_cur_gt = bno_cur_lt;
-		bno_cur_lt = 0;
+		bno_cur_lt = NULL;
 	}
 	/*
 	 * Found something.  Duplicate the cursor for the rightward search.
@@ -1301,7 +1301,7 @@ xfs_alloc_ag_vextent_size(
 	 * Allocate and initialize a cursor for the by-size btree.
 	 */
 	cnt_cur = xfs_btree_init_cursor(args->mp, args->tp, args->agbp,
-		args->agno, XFS_BTNUM_CNT, 0, 0);
+		args->agno, XFS_BTNUM_CNT, NULL, 0);
 	bno_cur = NULL;
 	/*
 	 * Look for an entry >= maxlen+alignment-1 blocks.
@@ -1406,7 +1406,7 @@ xfs_alloc_ag_vextent_size(
 	 * Allocate and initialize a cursor for the by-block tree.
 	 */
 	bno_cur = xfs_btree_init_cursor(args->mp, args->tp, args->agbp,
-		args->agno, XFS_BTNUM_BNO, 0, 0);
+		args->agno, XFS_BTNUM_BNO, NULL, 0);
 	if ((error = xfs_alloc_fixup_trees(cnt_cur, bno_cur, fbno, flen,
 			rbno, rlen, XFSA_FIXUP_CNT_OK)))
 		goto error0;
@@ -1553,7 +1553,7 @@ xfs_free_ag_extent(
 	/*
 	 * Allocate and initialize a cursor for the by-block btree.
 	 */
-	bno_cur = xfs_btree_init_cursor(mp, tp, agbp, agno, XFS_BTNUM_BNO, 0,
+	bno_cur = xfs_btree_init_cursor(mp, tp, agbp, agno, XFS_BTNUM_BNO, NULL,
 		0);
 	cnt_cur = NULL;
 	/*
@@ -1613,7 +1613,7 @@ xfs_free_ag_extent(
 	/*
 	 * Now allocate and initialize a cursor for the by-size tree.
 	 */
-	cnt_cur = xfs_btree_init_cursor(mp, tp, agbp, agno, XFS_BTNUM_CNT, 0,
+	cnt_cur = xfs_btree_init_cursor(mp, tp, agbp, agno, XFS_BTNUM_CNT, NULL,
 		0);
 	/*
 	 * Have both left and right contiguous neighbors.
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/xfs/xfs_alloc_btree.c linux-2.4.28-pre3/fs/xfs/xfs_alloc_btree.c
--- linux-2.4.27/fs/xfs/xfs_alloc_btree.c	2004-02-18 13:36:32.000000000 +0000
+++ linux-2.4.28-pre3/fs/xfs/xfs_alloc_btree.c	2004-09-10 19:32:06.000000000 +0000
@@ -263,7 +263,7 @@ xfs_alloc_delrec(
 			/*
 			 * Update the cursor so there's one fewer level.
 			 */
-			xfs_btree_setbuf(cur, level, 0);
+			xfs_btree_setbuf(cur, level, NULL);
 			cur->bc_nlevels--;
 		} else if (level > 0 &&
 			   (error = xfs_alloc_decrement(cur, level, &i)))
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/xfs/xfs_attr.c linux-2.4.28-pre3/fs/xfs/xfs_attr.c
--- linux-2.4.27/fs/xfs/xfs_attr.c	2004-08-07 23:26:06.000000000 +0000
+++ linux-2.4.28-pre3/fs/xfs/xfs_attr.c	2004-09-10 19:35:24.000000000 +0000
@@ -104,7 +104,6 @@ STATIC int xfs_attr_rmtval_set(xfs_da_ar
 STATIC int xfs_attr_rmtval_remove(xfs_da_args_t *args);
 
 #define ATTR_RMTVALUE_MAPSIZE	1	/* # of map entries at once */
-#define ATTR_RMTVALUE_TRANSBLKS	8	/* max # of blks in a transaction */
 
 #if defined(XFS_ATTR_TRACE)
 ktrace_t *xfs_attr_trace_buf;
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/xfs/xfs_bmap.c linux-2.4.28-pre3/fs/xfs/xfs_bmap.c
--- linux-2.4.27/fs/xfs/xfs_bmap.c	2004-08-07 23:26:06.000000000 +0000
+++ linux-2.4.28-pre3/fs/xfs/xfs_bmap.c	2004-09-10 19:36:54.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000-2003 Silicon Graphics, Inc.  All Rights Reserved.
+ * Copyright (c) 2000-2004 Silicon Graphics, Inc.  All Rights Reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of version 2 of the GNU General Public License as
@@ -203,8 +203,6 @@ STATIC void
 xfs_bmap_check_extents(
 	xfs_inode_t		*ip,		/* incore inode pointer */
 	int			whichfork);	/* data or attr fork */
-#else
-#define	xfs_bmap_check_extents(ip,w)
 #endif
 
 /*
@@ -3429,6 +3427,20 @@ xfs_bmap_do_search_extents(
 	int		high;		/* high index of binary search */
 	int		low;		/* low index of binary search */
 
+	/*
+	 * Initialize the extent entry structure to catch access to
+	 * uninitialized br_startblock field.
+	 */
+	got.br_startoff = 0xffa5a5a5a5a5a5a5LL;
+	got.br_blockcount = 0xa55a5a5a5a5a5a5aLL;
+	got.br_state = XFS_EXT_INVALID;
+
+#if XFS_BIG_BLKNOS
+	got.br_startblock = 0xffffa5a5a5a5a5a5LL;
+#else
+	got.br_startblock = 0xffffa5a5;
+#endif
+
 	if (lastx != NULLEXTNUM && lastx < nextents)
 		ep = base + lastx;
 	else
@@ -3527,6 +3539,8 @@ xfs_bmap_search_extents(
 	xfs_bmbt_rec_t  *base;          /* base of extent list */
 	xfs_extnum_t    lastx;          /* last extent index used */
 	xfs_extnum_t    nextents;       /* extent list size */
+	xfs_bmbt_rec_t  *ep;            /* extent list entry pointer */
+	int		rt;		/* realtime flag    */
 
 	XFS_STATS_INC(xs_look_exlist);
 	ifp = XFS_IFORK_PTR(ip, whichfork);
@@ -3534,8 +3548,18 @@ xfs_bmap_search_extents(
 	nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t);
 	base = &ifp->if_u1.if_extents[0];
 
-	return xfs_bmap_do_search_extents(base, lastx, nextents, bno, eofp,
+	ep = xfs_bmap_do_search_extents(base, lastx, nextents, bno, eofp,
 					  lastxp, gotp, prevp);
+	rt = ip->i_d.di_flags & XFS_DIFLAG_REALTIME;
+	if(!rt && !gotp->br_startblock && (*lastxp != NULLEXTNUM)) {
+                cmn_err(CE_PANIC,"Access to block zero: fs: <%s> inode: %lld "
+			"start_block : %llx start_off : %llx blkcnt : %llx "
+			"extent-state : %x \n",
+			(ip->i_mount)->m_fsname,(long long)ip->i_ino,
+			gotp->br_startblock, gotp->br_startoff,
+			gotp->br_blockcount,gotp->br_state);
+        }
+        return ep;
 }
 
 
@@ -4689,8 +4713,41 @@ xfs_bmapi(
 					}
 					break;
 				}
+
+				/*
+				 * Split changing sb for alen and indlen since
+				 * they could be coming from different places.
+				 */
+				if (ip->i_d.di_flags & XFS_DIFLAG_REALTIME) {
+					xfs_extlen_t	extsz;
+					xfs_extlen_t	ralen;
+					if (!(extsz = ip->i_d.di_extsize))
+						extsz = mp->m_sb.sb_rextsize;
+					ralen = roundup(alen, extsz);
+					ralen = ralen / mp->m_sb.sb_rextsize;
+					if (xfs_mod_incore_sb(mp,
+						XFS_SBS_FREXTENTS,
+						-(ralen), rsvd)) {
+						if (XFS_IS_QUOTA_ON(ip->i_mount))
+							XFS_TRANS_UNRESERVE_BLKQUOTA(
+						     		mp, NULL, ip,
+								(long)alen);
+						break;
+					}
+				} else {
+					if (xfs_mod_incore_sb(mp,
+							      XFS_SBS_FDBLOCKS,
+							      -(alen), rsvd)) {
+						if (XFS_IS_QUOTA_ON(ip->i_mount))
+							XFS_TRANS_UNRESERVE_BLKQUOTA(
+								mp, NULL, ip,
+								(long)alen);
+						break;
+					}
+				}
+
 				if (xfs_mod_incore_sb(mp, XFS_SBS_FDBLOCKS,
-						-(alen + indlen), rsvd)) {
+						-(indlen), rsvd)) {
 					XFS_TRANS_UNRESERVE_BLKQUOTA(
 						mp, NULL, ip, (long)alen);
 					break;
@@ -5445,7 +5502,7 @@ int						/* error code */
 xfs_getbmap(
 	bhv_desc_t		*bdp,		/* XFS behavior descriptor*/
 	struct getbmap		*bmv,		/* user bmap structure */
-	void			*ap,		/* pointer to user's array */
+	void			__user *ap,	/* pointer to user's array */
 	int			interface)	/* interface flags */
 {
 	__int64_t		bmvend;		/* last block requested */
@@ -5634,8 +5691,10 @@ xfs_getbmap(
 					(__int64_t)(bmvend - bmv->bmv_offset));
 				bmv->bmv_entries++;
 				ap = (interface & BMV_IF_EXTENDED) ?
-					(void *)((struct getbmapx *)ap + 1) :
-					(void *)((struct getbmap *)ap + 1);
+						(void __user *)
+					((struct getbmapx __user *)ap + 1) :
+						(void __user *)
+					((struct getbmap __user *)ap + 1);
 			}
 		}
 	} while (nmap && nexleft && bmv->bmv_length);
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/xfs/xfs_bmap.h linux-2.4.28-pre3/fs/xfs/xfs_bmap.h
--- linux-2.4.27/fs/xfs/xfs_bmap.h	2004-08-07 23:26:06.000000000 +0000
+++ linux-2.4.28-pre3/fs/xfs/xfs_bmap.h	2004-09-10 19:32:46.000000000 +0000
@@ -328,7 +328,7 @@ int						/* error code */
 xfs_getbmap(
 	bhv_desc_t		*bdp,		/* XFS behavior descriptor*/
 	struct getbmap		*bmv,		/* user bmap structure */
-	void			*ap,		/* pointer to user's array */
+	void			__user *ap,	/* pointer to user's array */
 	int			iflags);	/* interface flags */
 
 /*
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/xfs/xfs_bmap_btree.c linux-2.4.28-pre3/fs/xfs/xfs_bmap_btree.c
--- linux-2.4.27/fs/xfs/xfs_bmap_btree.c	2004-08-07 23:26:06.000000000 +0000
+++ linux-2.4.28-pre3/fs/xfs/xfs_bmap_btree.c	2004-09-10 19:31:58.000000000 +0000
@@ -1953,7 +1953,7 @@ xfs_bmbt_get_block(
 		*bpp = cur->bc_bufs[level];
 		rval = XFS_BUF_TO_BMBT_BLOCK(*bpp);
 	} else {
-		*bpp = 0;
+		*bpp = NULL;
 		ifp = XFS_IFORK_PTR(cur->bc_private.b.ip,
 			cur->bc_private.b.whichfork);
 		rval = ifp->if_broot;
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/xfs/xfs_bmap_btree.h linux-2.4.28-pre3/fs/xfs/xfs_bmap_btree.h
--- linux-2.4.27/fs/xfs/xfs_bmap_btree.h	2004-08-07 23:26:06.000000000 +0000
+++ linux-2.4.28-pre3/fs/xfs/xfs_bmap_btree.h	2004-09-10 19:35:41.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+ * Copyright (c) 2000,2002-2004 Silicon Graphics, Inc.  All Rights Reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of version 2 of the GNU General Public License as
@@ -153,7 +153,7 @@ typedef enum {
  */
 typedef enum {
 	XFS_EXT_NORM, XFS_EXT_UNWRITTEN,
-	XFS_EXT_DMAPI_OFFLINE
+	XFS_EXT_DMAPI_OFFLINE, XFS_EXT_INVALID
 } xfs_exntst_t;
 
 /*
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/xfs/xfs_buf_item.c linux-2.4.28-pre3/fs/xfs/xfs_buf_item.c
--- linux-2.4.27/fs/xfs/xfs_buf_item.c	2004-08-07 23:26:06.000000000 +0000
+++ linux-2.4.28-pre3/fs/xfs/xfs_buf_item.c	2004-09-10 19:32:38.000000000 +0000
@@ -55,8 +55,6 @@
 #include "xfs_error.h"
 
 
-#define	ROUNDUPNBWORD(x)	(((x) + (NBWORD - 1)) & ~(NBWORD - 1))
-
 kmem_zone_t	*xfs_buf_item_zone;
 
 #ifdef XFS_TRANS_DEBUG
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/xfs/xfs_da_btree.c linux-2.4.28-pre3/fs/xfs/xfs_da_btree.c
--- linux-2.4.27/fs/xfs/xfs_da_btree.c	2004-08-07 23:26:06.000000000 +0000
+++ linux-2.4.28-pre3/fs/xfs/xfs_da_btree.c	2004-09-10 19:36:39.000000000 +0000
@@ -2092,7 +2092,7 @@ xfs_da_do_buf(
 	int		caller,
 	inst_t		*ra)
 {
-	xfs_buf_t	*bp = 0;
+	xfs_buf_t	*bp = NULL;
 	xfs_buf_t	**bplist;
 	int		error=0;
 	int		i;
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/xfs/xfs_dfrag.c linux-2.4.28-pre3/fs/xfs/xfs_dfrag.c
--- linux-2.4.27/fs/xfs/xfs_dfrag.c	2004-04-14 13:05:40.000000000 +0000
+++ linux-2.4.28-pre3/fs/xfs/xfs_dfrag.c	2004-09-10 19:31:49.000000000 +0000
@@ -65,7 +65,7 @@
  */
 int
 xfs_swapext(
-	xfs_swapext_t   *sxp)
+	xfs_swapext_t	__user *sxp)
 {
 	xfs_swapext_t	sx;
 	xfs_inode_t     *ip=NULL, *tip=NULL, *ips[2];
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/xfs/xfs_dfrag.h linux-2.4.28-pre3/fs/xfs/xfs_dfrag.h
--- linux-2.4.27/fs/xfs/xfs_dfrag.h	2004-02-18 13:36:32.000000000 +0000
+++ linux-2.4.28-pre3/fs/xfs/xfs_dfrag.h	2004-09-10 19:34:10.000000000 +0000
@@ -60,7 +60,7 @@ typedef struct xfs_swapext
 /*
  * Syscall interface for xfs_swapext
  */
-int	xfs_swapext(struct xfs_swapext *sx);
+int	xfs_swapext(struct xfs_swapext __user *sx);
 
 #endif	/* __KERNEL__ */
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/xfs/xfs_dinode.h linux-2.4.28-pre3/fs/xfs/xfs_dinode.h
--- linux-2.4.27/fs/xfs/xfs_dinode.h	2004-02-18 13:36:32.000000000 +0000
+++ linux-2.4.28-pre3/fs/xfs/xfs_dinode.h	2004-09-10 19:35:22.000000000 +0000
@@ -456,6 +456,7 @@ xfs_dinode_t *xfs_buf_to_dinode(struct x
 #define XFS_DIFLAG_SYNC_BIT      5	/* inode is written synchronously */
 #define XFS_DIFLAG_NOATIME_BIT   6	/* do not update atime */
 #define XFS_DIFLAG_NODUMP_BIT    7	/* do not dump */
+#define XFS_DIFLAG_RTINHERIT_BIT 8	/* create with realtime bit set */
 #define XFS_DIFLAG_REALTIME      (1 << XFS_DIFLAG_REALTIME_BIT)
 #define XFS_DIFLAG_PREALLOC      (1 << XFS_DIFLAG_PREALLOC_BIT)
 #define XFS_DIFLAG_NEWRTBM       (1 << XFS_DIFLAG_NEWRTBM_BIT)
@@ -464,5 +465,11 @@ xfs_dinode_t *xfs_buf_to_dinode(struct x
 #define XFS_DIFLAG_SYNC          (1 << XFS_DIFLAG_SYNC_BIT)
 #define XFS_DIFLAG_NOATIME       (1 << XFS_DIFLAG_NOATIME_BIT)
 #define XFS_DIFLAG_NODUMP        (1 << XFS_DIFLAG_NODUMP_BIT)
+#define XFS_DIFLAG_RTINHERIT     (1 << XFS_DIFLAG_RTINHERIT_BIT)
+
+#define XFS_DIFLAG_ANY \
+	(XFS_DIFLAG_REALTIME | XFS_DIFLAG_PREALLOC | XFS_DIFLAG_NEWRTBM | \
+	 XFS_DIFLAG_IMMUTABLE | XFS_DIFLAG_APPEND | XFS_DIFLAG_SYNC | \
+	 XFS_DIFLAG_NOATIME | XFS_DIFLAG_NODUMP | XFS_DIFLAG_RTINHERIT)
 
 #endif	/* __XFS_DINODE_H__ */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/xfs/xfs_dir2_trace.c linux-2.4.28-pre3/fs/xfs/xfs_dir2_trace.c
--- linux-2.4.27/fs/xfs/xfs_dir2_trace.c	2004-02-18 13:36:32.000000000 +0000
+++ linux-2.4.28-pre3/fs/xfs/xfs_dir2_trace.c	2004-09-10 19:37:25.000000000 +0000
@@ -211,7 +211,7 @@ xfs_dir2_trace_args_s(
 		(void *)((unsigned long)(args->inumber >> 32)),
 		(void *)((unsigned long)(args->inumber & 0xFFFFFFFF)),
 		(void *)args->dp, (void *)args->trans,
-		(void *)(unsigned long)args->justcheck, (void *)(long)s, 0);
+		(void *)(unsigned long)args->justcheck, (void *)(long)s, NULL);
 }
 
 void
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/xfs/xfs_fs.h linux-2.4.28-pre3/fs/xfs/xfs_fs.h
--- linux-2.4.27/fs/xfs/xfs_fs.h	2004-04-14 13:05:40.000000000 +0000
+++ linux-2.4.28-pre3/fs/xfs/xfs_fs.h	2004-09-10 19:34:35.000000000 +0000
@@ -76,6 +76,7 @@ struct fsxattr {
 #define XFS_XFLAG_SYNC		0x00000020	/* all writes synchronous */
 #define XFS_XFLAG_NOATIME	0x00000040	/* do not update access time */
 #define XFS_XFLAG_NODUMP	0x00000080	/* do not include in backups */
+#define XFS_XFLAG_RTINHERIT	0x00000100	/* create with rt bit set */
 #define XFS_XFLAG_HASATTR	0x80000000	/* no DIFLAG for this	*/
 
 /*
@@ -164,7 +165,7 @@ typedef struct xfs_flock64 {
 	__s64		l_start;
 	__s64		l_len;		/* len == 0 means until end of file */
 	__s32		l_sysid;
-	pid_t		l_pid;
+	__u32		l_pid;
 	__s32		l_pad[4];	/* reserve area			    */
 } xfs_flock64_t;
 
@@ -313,10 +314,10 @@ typedef struct xfs_bstat {
  * The user-level BulkStat Request interface structure.
  */
 typedef struct xfs_fsop_bulkreq {
-	__u64		*lastip;	/* last inode # pointer		*/
+	__u64		__user *lastip;	/* last inode # pointer		*/
 	__s32		icount;		/* count of entries in buffer	*/
-	void		*ubuffer;	/* user buffer for inode desc.	*/
-	__s32		*ocount;	/* output count pointer		*/
+	void		__user *ubuffer;/* user buffer for inode desc.	*/
+	__s32		__user *ocount;	/* output count pointer		*/
 } xfs_fsop_bulkreq_t;
 
 
@@ -344,12 +345,12 @@ typedef struct xfs_error_injection {
  */
 typedef struct xfs_fsop_handlereq {
 	__u32		fd;		/* fd for FD_TO_HANDLE		*/
-	void		*path;		/* user pathname		*/
+	void		__user *path;	/* user pathname		*/
 	__u32		oflags;		/* open flags			*/
-	void		*ihandle;	/* user supplied handle		*/
+	void		__user *ihandle;/* user supplied handle		*/
 	__u32		ihandlen;	/* user supplied length		*/
-	void		*ohandle;	/* user buffer for handle	*/
-	__u32		*ohandlen;	/* user buffer length		*/
+	void		__user *ohandle;/* user buffer for handle	*/
+	__u32		__user *ohandlen;/* user buffer length		*/
 } xfs_fsop_handlereq_t;
 
 /*
@@ -360,35 +361,35 @@ typedef struct xfs_fsop_handlereq {
  */
 
 typedef struct xfs_fsop_setdm_handlereq {
-	struct xfs_fsop_handlereq hreq; /* handle interface structure */
-	struct fsdmidata *data;		/* DMAPI data to set	      */
+	struct xfs_fsop_handlereq	hreq;	/* handle information	*/
+	struct fsdmidata		__user *data;	/* DMAPI data	*/
 } xfs_fsop_setdm_handlereq_t;
 
 typedef struct xfs_attrlist_cursor {
-	__u32	opaque[4];
+	__u32		opaque[4];
 } xfs_attrlist_cursor_t;
 
 typedef struct xfs_fsop_attrlist_handlereq {
-	struct xfs_fsop_handlereq hreq; /* handle interface structure */
-	struct xfs_attrlist_cursor pos; /* opaque cookie, list offset */
-	__u32 flags;			/* flags, use ROOT/USER names */
-	__u32 buflen;			/* length of buffer supplied  */
-	void *buffer;			/* attrlist data to return    */
+	struct xfs_fsop_handlereq	hreq; /* handle interface structure */
+	struct xfs_attrlist_cursor	pos; /* opaque cookie, list offset */
+	__u32				flags;	/* which namespace to use */
+	__u32				buflen;	/* length of buffer supplied */
+	void				__user *buffer;	/* returned names */
 } xfs_fsop_attrlist_handlereq_t;
 
 typedef struct xfs_attr_multiop {
-	__u32	am_opcode;
-	__s32	am_error;
-	void	*am_attrname;
-	void	*am_attrvalue;
-	__u32	am_length;
-	__u32	am_flags;
+	__u32		am_opcode;
+	__s32		am_error;
+	void		__user *am_attrname;
+	void		__user *am_attrvalue;
+	__u32		am_length;
+	__u32		am_flags;
 } xfs_attr_multiop_t;
 
 typedef struct xfs_fsop_attrmulti_handlereq {
-	struct xfs_fsop_handlereq hreq; /* handle interface structure */
-	__u32 opcount;			/* count of following multiop */
-	struct xfs_attr_multiop *ops;	/* attr_multi data to get/set */
+	struct xfs_fsop_handlereq	hreq; /* handle interface structure */
+	__u32				opcount;/* count of following multiop */
+	struct xfs_attr_multiop		__user *ops; /* attr_multi data */
 } xfs_fsop_attrmulti_handlereq_t;
 
 /*
@@ -445,6 +446,13 @@ typedef struct xfs_handle {
 #define XFS_FSOP_GOING_FLAGS_NOLOGFLUSH		0x2	/* don't flush log nor data */
 
 /*
+ * ioctl commands that are used by Linux filesystems
+ */
+#define XFS_IOC_GETXFLAGS	_IOR('f', 1, long)
+#define XFS_IOC_SETXFLAGS	_IOW('f', 2, long)
+#define XFS_IOC_GETVERSION	_IOR('v', 1, long)
+
+/*
  * ioctl commands that replace IRIX fcntl()'s
  * For 'documentation' purposed more than anything else,
  * the "cmd #" field reflects the IRIX fcntl number.
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/xfs/xfs_fsops.c linux-2.4.28-pre3/fs/xfs/xfs_fsops.c
--- linux-2.4.27/fs/xfs/xfs_fsops.c	2004-08-07 23:26:06.000000000 +0000
+++ linux-2.4.28-pre3/fs/xfs/xfs_fsops.c	2004-09-10 19:34:52.000000000 +0000
@@ -142,6 +142,7 @@ xfs_growfs_data_private(
 	int			dpct;
 	int			error;
 	xfs_agnumber_t		nagcount;
+	xfs_agnumber_t		nagimax = 0;
 	xfs_rfsblock_t		nb, nb_mod;
 	xfs_rfsblock_t		new;
 	xfs_rfsblock_t		nfree;
@@ -183,7 +184,7 @@ xfs_growfs_data_private(
 		memset(&mp->m_perag[oagcount], 0,
 			(nagcount - oagcount) * sizeof(xfs_perag_t));
 		mp->m_flags |= XFS_MOUNT_32BITINODES;
-		xfs_initialize_perag(mp, nagcount);
+		nagimax = xfs_initialize_perag(mp, nagcount);
 		up_write(&mp->m_peraglock);
 	}
 	tp = xfs_trans_alloc(mp, XFS_TRANS_GROWFS);
@@ -372,6 +373,9 @@ xfs_growfs_data_private(
 	if (error) {
 		return error;
 	}
+	/* New allocation groups fully initialized, so update mount struct */
+	if (nagimax)
+		mp->m_maxagi = nagimax;
 	if (mp->m_sb.sb_imax_pct) {
 		__uint64_t icount = mp->m_sb.sb_dblocks * mp->m_sb.sb_imax_pct;
 		do_div(icount, 100);
@@ -507,9 +511,9 @@ xfs_reserve_blocks(
 	__uint64_t              *inval,
 	xfs_fsop_resblks_t      *outval)
 {
-	__uint64_t              lcounter, delta;
-	__uint64_t              request;
-	unsigned long s;
+	__int64_t		lcounter, delta;
+	__uint64_t		request;
+	unsigned long		s;
 
 	/* If inval is null, report current values and return */
 
@@ -536,8 +540,7 @@ xfs_reserve_blocks(
 		mp->m_resblks = request;
 	} else {
 		delta = request - mp->m_resblks;
-		lcounter = mp->m_sb.sb_fdblocks;
-		lcounter -= delta;
+		lcounter = mp->m_sb.sb_fdblocks - delta;
 		if (lcounter < 0) {
 			/* We can't satisfy the request, just get what we can */
 			mp->m_resblks += mp->m_sb.sb_fdblocks;
@@ -583,63 +586,22 @@ xfs_fs_log_dummy(xfs_mount_t *mp)
 }
 
 int
-xfs_fs_freeze(
-	xfs_mount_t	*mp)
-{
-	vfs_t		*vfsp;
-	/*REFERENCED*/
-	int		error;
-
-	vfsp = XFS_MTOVFS(mp);
-
-	/* Stop new writers */
-	xfs_start_freeze(mp, XFS_FREEZE_WRITE);
-
-	/* Flush the refcache */
-	xfs_refcache_purge_mp(mp);
-
-	/* Flush delalloc and delwri data */
-	VFS_SYNC(vfsp, SYNC_DELWRI|SYNC_WAIT, NULL, error);
-
-	/* Pause transaction subsystem */
-	xfs_start_freeze(mp, XFS_FREEZE_TRANS);
-
-	/* Flush any remaining inodes into buffers */
-	VFS_SYNC(vfsp, SYNC_ATTR|SYNC_WAIT, NULL, error);
-
-	/* Push all buffers out to disk */
-	xfs_binval(mp->m_ddev_targp);
-	if (mp->m_rtdev_targp) {
-		xfs_binval(mp->m_rtdev_targp);
-	}
-
-	/* Push the superblock and write an unmount record */
-	xfs_log_unmount_write(mp);
-	xfs_unmountfs_writesb(mp);
-
-	return 0;
-}
-
-int
-xfs_fs_thaw(
-	xfs_mount_t	*mp)
-{
-	xfs_finish_freeze(mp);
-	return 0;
-}
-
-int
 xfs_fs_goingdown(
 	xfs_mount_t	*mp,
 	__uint32_t	inflags)
 {
-	switch (inflags)
-	{
-	case XFS_FSOP_GOING_FLAGS_DEFAULT:
-		xfs_fs_freeze(mp);
-		xfs_force_shutdown(mp, XFS_FORCE_UMOUNT);
-		xfs_fs_thaw(mp);
+	switch (inflags) {
+	case XFS_FSOP_GOING_FLAGS_DEFAULT: {
+		struct vfs *vfsp = XFS_MTOVFS(mp);
+		struct super_block *sb = freeze_bdev(vfsp->vfs_super->s_bdev);
+
+		if (sb) {
+			xfs_force_shutdown(mp, XFS_FORCE_UMOUNT);
+			thaw_bdev(sb->s_bdev, sb);
+		}
+	
 		break;
+	}
 	case XFS_FSOP_GOING_FLAGS_LOGFLUSH:
 		xfs_force_shutdown(mp, XFS_FORCE_UMOUNT);
 		break;
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/xfs/xfs_fsops.h linux-2.4.28-pre3/fs/xfs/xfs_fsops.h
--- linux-2.4.27/fs/xfs/xfs_fsops.h	2004-04-14 13:05:40.000000000 +0000
+++ linux-2.4.28-pre3/fs/xfs/xfs_fsops.h	2004-09-10 19:32:41.000000000 +0000
@@ -60,14 +60,6 @@ xfs_reserve_blocks(
 	xfs_fsop_resblks_t	*outval);
 
 int
-xfs_fs_freeze(
-	xfs_mount_t		*mp);
-
-int
-xfs_fs_thaw(
-	xfs_mount_t		*mp);
-
-int
 xfs_fs_goingdown(
 	xfs_mount_t		*mp,
 	__uint32_t		inflags);
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/xfs/xfs_inode.c linux-2.4.28-pre3/fs/xfs/xfs_inode.c
--- linux-2.4.27/fs/xfs/xfs_inode.c	2004-08-07 23:26:06.000000000 +0000
+++ linux-2.4.28-pre3/fs/xfs/xfs_inode.c	2004-09-10 19:37:09.000000000 +0000
@@ -860,25 +860,28 @@ xfs_dic2xflags(
 	xfs_arch_t		arch)
 {
 	__uint16_t		di_flags;
-	uint			flags = 0;
+	uint			flags;
 
 	di_flags = INT_GET(dic->di_flags, arch);
-	if (di_flags & XFS_DIFLAG_REALTIME)
-		flags |= XFS_XFLAG_REALTIME;
-	if (di_flags & XFS_DIFLAG_PREALLOC)
-		flags |= XFS_XFLAG_PREALLOC;
-	if (di_flags & XFS_DIFLAG_IMMUTABLE)
-		flags |= XFS_XFLAG_IMMUTABLE;
-	if (di_flags & XFS_DIFLAG_APPEND)
-		flags |= XFS_XFLAG_APPEND;
-	if (di_flags & XFS_DIFLAG_SYNC)
-		flags |= XFS_XFLAG_SYNC;
-	if (di_flags & XFS_DIFLAG_NOATIME)
-		flags |= XFS_XFLAG_NOATIME;
-	if (di_flags & XFS_DIFLAG_NODUMP)
-		flags |= XFS_XFLAG_NODUMP;
-	if (XFS_CFORK_Q_ARCH(dic, arch))
-		flags |= XFS_XFLAG_HASATTR;
+	flags = XFS_CFORK_Q_ARCH(dic, arch) ? XFS_XFLAG_HASATTR : 0;
+	if (di_flags & XFS_DIFLAG_ANY) {
+		if (di_flags & XFS_DIFLAG_REALTIME)
+			flags |= XFS_XFLAG_REALTIME;
+		if (di_flags & XFS_DIFLAG_PREALLOC)
+			flags |= XFS_XFLAG_PREALLOC;
+		if (di_flags & XFS_DIFLAG_IMMUTABLE)
+			flags |= XFS_XFLAG_IMMUTABLE;
+		if (di_flags & XFS_DIFLAG_APPEND)
+			flags |= XFS_XFLAG_APPEND;
+		if (di_flags & XFS_DIFLAG_SYNC)
+			flags |= XFS_XFLAG_SYNC;
+		if (di_flags & XFS_DIFLAG_NOATIME)
+			flags |= XFS_XFLAG_NOATIME;
+		if (di_flags & XFS_DIFLAG_NODUMP)
+			flags |= XFS_XFLAG_NODUMP;
+		if (di_flags & XFS_DIFLAG_RTINHERIT)
+			flags |= XFS_XFLAG_RTINHERIT;
+	}
 	return flags;
 }
 
@@ -1236,8 +1239,15 @@ xfs_ialloc(
 		break;
 	case S_IFREG:
 	case S_IFDIR:
-		if (pip->i_d.di_flags &
-		    (XFS_DIFLAG_NOATIME|XFS_DIFLAG_NODUMP|XFS_DIFLAG_SYNC)) {
+		if (unlikely(pip->i_d.di_flags & XFS_DIFLAG_ANY)) {
+			if (pip->i_d.di_flags & XFS_DIFLAG_RTINHERIT) {
+				if ((mode & S_IFMT) == S_IFDIR) {
+					ip->i_d.di_flags |= XFS_DIFLAG_RTINHERIT;
+				} else {
+					ip->i_d.di_flags |= XFS_DIFLAG_REALTIME;
+					ip->i_iocore.io_flags |= XFS_IOCORE_RT;
+				}
+			}
 			if ((pip->i_d.di_flags & XFS_DIFLAG_NOATIME) &&
 			    xfs_inherit_noatime)
 				ip->i_d.di_flags |= XFS_DIFLAG_NOATIME;
@@ -1248,6 +1258,7 @@ xfs_ialloc(
 			    xfs_inherit_sync)
 				ip->i_d.di_flags |= XFS_DIFLAG_SYNC;
 		}
+		/* FALLTHROUGH */
 	case S_IFLNK:
 		ip->i_d.di_format = XFS_DINODE_FMT_EXTENTS;
 		ip->i_df.if_flags = XFS_IFEXTENTS;
@@ -3579,6 +3590,7 @@ corrupt_out:
 	return XFS_ERROR(EFSCORRUPTED);
 }
 
+
 /*
  * Flush all inactive inodes in mp.  Return true if no user references
  * were found, false otherwise.
@@ -3634,7 +3646,6 @@ xfs_iflush_all(
 					continue;
 				}
 				if (!(flag & XFS_FLUSH_ALL)) {
-					ASSERT(0);
 					busy = 1;
 					done = 1;
 					break;
@@ -3851,6 +3862,6 @@ xfs_ilock_trace(xfs_inode_t *ip, int loc
 		     (void *)ra,		/* caller of ilock */
 		     (void *)(unsigned long)current_cpu(),
 		     (void *)(unsigned long)current_pid(),
-		     0,0,0,0,0,0,0,0,0,0);
+		     NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL);
 }
 #endif
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/xfs/xfs_iomap.c linux-2.4.28-pre3/fs/xfs/xfs_iomap.c
--- linux-2.4.27/fs/xfs/xfs_iomap.c	2004-08-07 23:26:06.000000000 +0000
+++ linux-2.4.28-pre3/fs/xfs/xfs_iomap.c	2004-09-10 19:32:40.000000000 +0000
@@ -165,20 +165,24 @@ xfs_imap_to_bmap(
 		nisize = io->io_new_size;
 
 	for (pbm = 0; imaps && pbm < iomaps; imaps--, iomapp++, imap++, pbm++) {
-		iomapp->iomap_target = io->io_flags & XFS_IOCORE_RT ?
-			mp->m_rtdev_targp : mp->m_ddev_targp;
 		iomapp->iomap_offset = XFS_FSB_TO_B(mp, imap->br_startoff);
 		iomapp->iomap_delta = offset - iomapp->iomap_offset;
 		iomapp->iomap_bsize = XFS_FSB_TO_B(mp, imap->br_blockcount);
 		iomapp->iomap_flags = flags;
 
+		if (io->io_flags & XFS_IOCORE_RT) {
+			iomapp->iomap_flags |= IOMAP_REALTIME;
+			iomapp->iomap_target = mp->m_rtdev_targp;
+		} else {
+			iomapp->iomap_target = mp->m_ddev_targp;
+		}
 		start_block = imap->br_startblock;
 		if (start_block == HOLESTARTBLOCK) {
 			iomapp->iomap_bn = IOMAP_DADDR_NULL;
-			iomapp->iomap_flags = IOMAP_HOLE;
+			iomapp->iomap_flags |= IOMAP_HOLE;
 		} else if (start_block == DELAYSTARTBLOCK) {
 			iomapp->iomap_bn = IOMAP_DADDR_NULL;
-			iomapp->iomap_flags = IOMAP_DELAY;
+			iomapp->iomap_flags |= IOMAP_DELAY;
 		} else {
 			iomapp->iomap_bn = XFS_FSB_TO_DB_IO(io, start_block);
 			if (ISUNWRITTEN(imap))
@@ -512,6 +516,15 @@ xfs_iomap_write_direct(
 
 	*ret_imap = imap[0];
 	*nmaps = 1;
+	if ( !(io->io_flags & XFS_IOCORE_RT)  && !ret_imap->br_startblock) {
+                cmn_err(CE_PANIC,"Access to block zero:  fs <%s> inode: %lld "
+                        "start_block : %llx start_off : %llx blkcnt : %llx "
+                        "extent-state : %x \n",
+                        (ip->i_mount)->m_fsname,
+                        (long long)ip->i_ino,
+                        ret_imap->br_startblock, ret_imap->br_startoff,
+                        ret_imap->br_blockcount,ret_imap->br_state);
+        }
 	return 0;
 
  error0:	/* Cancel bmap, unlock inode, and cancel trans */
@@ -572,8 +585,10 @@ retry:
 	 * out to the file system's write iosize.  We clean up any extra
 	 * space left over when the file is closed in xfs_inactive().
 	 *
-	 * We don't bother with this for sync writes, because we need
-	 * to minimize the amount we write for good performance.
+	 * For sync writes, we are flushing delayed allocate space to
+	 * try to make additional space available for allocation near
+	 * the filesystem full boundary - preallocation hurts in that
+	 * situation, of course.
 	 */
 	if (!(ioflag & BMAPI_SYNC) && ((offset + count) > ip->i_d.di_size)) {
 		xfs_off_t	aligned_offset;
@@ -598,6 +613,20 @@ retry:
 				return error;
 			}
 			for (n = 0; n < nimaps; n++) {
+				if ( !(io->io_flags & XFS_IOCORE_RT)  && 
+					!imap[n].br_startblock) {
+					cmn_err(CE_PANIC,"Access to block "
+						"zero:  fs <%s> inode: %lld "
+						"start_block : %llx start_off "
+						": %llx blkcnt : %llx "
+						"extent-state : %x \n",
+						(ip->i_mount)->m_fsname,
+						(long long)ip->i_ino,
+						imap[n].br_startblock,
+						imap[n].br_startoff,
+						imap[n].br_blockcount,
+						imap[n].br_state);
+        			}
 				if ((imap[n].br_startblock != HOLESTARTBLOCK) &&
 				    (imap[n].br_startblock != DELAYSTARTBLOCK)) {
 					goto write_map;
@@ -621,7 +650,8 @@ write_map:
 	 * request to a stripe width boundary if the file size is >=
 	 * stripe width and we are allocating past the allocation eof.
 	 */
-	if (mp->m_swidth && (mp->m_flags & XFS_MOUNT_SWALLOC)
+	if (!(io->io_flags & XFS_IOCORE_RT) && mp->m_swidth 
+	    && (mp->m_flags & XFS_MOUNT_SWALLOC)
 	    && (isize >= XFS_FSB_TO_B(mp, mp->m_swidth)) && aeof) {
 		int eof;
 		xfs_fileoff_t new_last_fsb;
@@ -639,8 +669,8 @@ write_map:
 	 * if the file size is >= stripe unit size, and we are allocating past
 	 * the allocation eof.
 	 */
-	} else if (mp->m_dalign && (isize >= XFS_FSB_TO_B(mp, mp->m_dalign))
-		   && aeof) {
+	} else if (!(io->io_flags & XFS_IOCORE_RT) && mp->m_dalign &&
+		   (isize >= XFS_FSB_TO_B(mp, mp->m_dalign)) && aeof) {
 		int eof;
 		xfs_fileoff_t new_last_fsb;
 		new_last_fsb = roundup_64(last_fsb, mp->m_dalign);
@@ -651,8 +681,22 @@ write_map:
 		if (eof) {
 			last_fsb = new_last_fsb;
 		}
-	}
+	/*
+	 * Round up the allocation request to a real-time extent boundary
+	 * if the file is on the real-time subvolume.
+	 */
+	} else if (io->io_flags & XFS_IOCORE_RT && aeof) {
+		int eof;
+		xfs_fileoff_t new_last_fsb;
 
+		new_last_fsb = roundup_64(last_fsb, mp->m_sb.sb_rextsize);
+		error = XFS_BMAP_EOF(mp, io, new_last_fsb, XFS_DATA_FORK, &eof);
+		if (error) {
+			return error;
+		}
+		if (eof)
+			last_fsb = new_last_fsb;
+	}
 	error = xfs_bmapi(NULL, ip, offset_fsb,
 			  (xfs_filblks_t)(last_fsb - offset_fsb),
 			  XFS_BMAPI_DELAY | XFS_BMAPI_WRITE |
@@ -680,6 +724,15 @@ write_map:
 
 	*ret_imap = imap[0];
 	*nmaps = 1;
+	if ( !(io->io_flags & XFS_IOCORE_RT)  && !ret_imap->br_startblock) {
+		cmn_err(CE_PANIC,"Access to block zero:  fs <%s> inode: %lld "
+                        "start_block : %llx start_off : %llx blkcnt : %llx "
+                        "extent-state : %x \n",
+                        (ip->i_mount)->m_fsname,
+                        (long long)ip->i_ino,
+                        ret_imap->br_startblock, ret_imap->br_startoff,
+                        ret_imap->br_blockcount,ret_imap->br_state);
+	}
 	return 0;
 }
 
@@ -697,6 +750,7 @@ xfs_iomap_write_allocate(
 	int		*retmap)
 {
 	xfs_mount_t	*mp = ip->i_mount;
+	xfs_iocore_t    *io = &ip->i_iocore;
 	xfs_fileoff_t	offset_fsb, last_block;
 	xfs_fileoff_t	end_fsb, map_start_fsb;
 	xfs_fsblock_t	first_block;
@@ -802,6 +856,18 @@ xfs_iomap_write_allocate(
 		 */
 
 		for (i = 0; i < nimaps; i++) {
+			if ( !(io->io_flags & XFS_IOCORE_RT)  && 
+				!imap[i].br_startblock) {
+				cmn_err(CE_PANIC,"Access to block zero:  "
+					"fs <%s> inode: %lld "
+					"start_block : %llx start_off : %llx " 
+					"blkcnt : %llx extent-state : %x \n",
+					(ip->i_mount)->m_fsname,
+					(long long)ip->i_ino,
+					imap[i].br_startblock,
+					imap[i].br_startoff,
+				        imap[i].br_blockcount,imap[i].br_state);
+                        }
 			if ((map->br_startoff >= imap[i].br_startoff) &&
 			    (map->br_startoff < (imap[i].br_startoff +
 						 imap[i].br_blockcount))) {
@@ -837,6 +903,7 @@ xfs_iomap_write_unwritten(
 	size_t		count)
 {
 	xfs_mount_t	*mp = ip->i_mount;
+	xfs_iocore_t    *io = &ip->i_iocore;
 	xfs_trans_t	*tp;
 	xfs_fileoff_t	offset_fsb;
 	xfs_filblks_t	count_fsb;
@@ -853,7 +920,8 @@ xfs_iomap_write_unwritten(
 				&ip->i_iocore, offset, count);
 
 	offset_fsb = XFS_B_TO_FSBT(mp, offset);
-	count_fsb = XFS_B_TO_FSB(mp, count);
+	count_fsb = XFS_B_TO_FSB(mp, (xfs_ufsize_t)offset + count);
+	count_fsb = (xfs_filblks_t)(count_fsb - offset_fsb);
 
 	do {
 		nres = XFS_DIOSTRAT_SPACE_RES(mp, 0);
@@ -898,6 +966,16 @@ xfs_iomap_write_unwritten(
 		xfs_iunlock(ip, XFS_ILOCK_EXCL);
 		if (error)
 			goto error0;
+		
+		if ( !(io->io_flags & XFS_IOCORE_RT)  && !imap.br_startblock) {
+			cmn_err(CE_PANIC,"Access to block zero:  fs <%s> "
+				"inode: %lld start_block : %llx start_off : "
+				"%llx blkcnt : %llx extent-state : %x \n",
+				(ip->i_mount)->m_fsname,
+				(long long)ip->i_ino,
+				imap.br_startblock,imap.br_startoff,
+				imap.br_blockcount,imap.br_state);
+        	}
 
 		if ((numblks_fsb = imap.br_blockcount) == 0) {
 			/*
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/xfs/xfs_iomap.h linux-2.4.28-pre3/fs/xfs/xfs_iomap.h
--- linux-2.4.27/fs/xfs/xfs_iomap.h	2004-02-18 13:36:32.000000000 +0000
+++ linux-2.4.28-pre3/fs/xfs/xfs_iomap.h	2004-09-10 19:34:06.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003 Silicon Graphics, Inc.  All Rights Reserved.
+ * Copyright (c) 2003,2004 Silicon Graphics, Inc.  All Rights Reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of version 2 of the GNU General Public License as
@@ -42,6 +42,7 @@ typedef enum {				/* iomap_flags values 
 	IOMAP_EOF =		0x01,	/* mapping contains EOF   */
 	IOMAP_HOLE =		0x02,	/* mapping covers a hole  */
 	IOMAP_DELAY =		0x04,	/* mapping covers delalloc region  */
+	IOMAP_REALTIME =	0x10,	/* mapping on the realtime device  */
 	IOMAP_UNWRITTEN =	0x20,	/* mapping covers allocated */
 					/* but uninitialized file data  */
 	IOMAP_NEW =		0x40	/* just allocate */
@@ -57,7 +58,7 @@ typedef enum {
 	BMAPI_IGNSTATE = (1 << 4),	/* ignore unwritten state on read */
 	BMAPI_DIRECT = (1 << 5),		/* direct instead of buffered write */
 	BMAPI_MMAP = (1 << 6),		/* allocate for mmap write */
-	BMAPI_SYNC = (1 << 7),		/* sync write */
+	BMAPI_SYNC = (1 << 7),		/* sync write to flush delalloc space */
 	BMAPI_TRYLOCK = (1 << 8),	/* non-blocking request */
 	BMAPI_DEVICE = (1 << 9),	/* we only want to know the device */
 } bmapi_flags_t;
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/xfs/xfs_itable.c linux-2.4.28-pre3/fs/xfs/xfs_itable.c
--- linux-2.4.27/fs/xfs/xfs_itable.c	2004-08-07 23:26:06.000000000 +0000
+++ linux-2.4.28-pre3/fs/xfs/xfs_itable.c	2004-09-10 19:36:46.000000000 +0000
@@ -68,7 +68,7 @@ int		       		/* error status */
 xfs_bulkstat_one(
 	xfs_mount_t	*mp,		/* mount point for filesystem */
 	xfs_ino_t	ino,		/* inode number to get data for */
-	void		*buffer,	/* buffer to place output in */
+	void		__user *buffer,	/* buffer to place output in */
 	int		ubsize,		/* size of buffer */
 	void		*private_data,	/* my private data */
 	xfs_daddr_t	bno,		/* starting bno of inode cluster */
@@ -231,7 +231,7 @@ xfs_bulkstat(
 	bulkstat_one_pf		formatter, /* func that'd fill a single buf */
 	void			*private_data,/* private data for formatter */
 	size_t			statstruct_size, /* sizeof struct filling */
-	xfs_caddr_t		ubuffer, /* buffer with inode stats */
+	char			__user *ubuffer, /* buffer with inode stats */
 	int			flags,	/* defined in xfs_itable.h */
 	int			*done)	/* 1 if there're more stats to get */
 {
@@ -265,7 +265,7 @@ xfs_bulkstat(
 	int			tmp;	/* result value from btree calls */
 	int			ubcount; /* size of user's buffer */
 	int			ubleft;	/* bytes left in user's buffer */
-	xfs_caddr_t		ubufp;	/* current pointer into user's buffer */
+	char			__user *ubufp;	/* pointer into user's buffer */
 	int			ubelem;	/* spaces used in user's buffer */
 	int			ubused;	/* bytes used by formatter */
 	xfs_buf_t		*bp;	/* ptr to on-disk inode cluster buf */
@@ -633,7 +633,7 @@ int					/* error status */
 xfs_bulkstat_single(
 	xfs_mount_t		*mp,	/* mount point for filesystem */
 	xfs_ino_t		*lastinop, /* inode to return */
-	xfs_caddr_t		buffer,	/* buffer with inode stats */
+	char			__user *buffer, /* buffer with inode stats */
 	int			*done)	/* 1 if there're more stats to get */
 {
 	int			count;	/* count value for bulkstat call */
@@ -682,7 +682,7 @@ xfs_inumbers(
 	xfs_mount_t	*mp,		/* mount point for filesystem */
 	xfs_ino_t	*lastino,	/* last inode returned */
 	int		*count,		/* size of buffer/count returned */
-	xfs_caddr_t	ubuffer)	/* buffer with inode descriptions */
+	xfs_inogrp_t	__user *ubuffer)/* buffer with inode descriptions */
 {
 	xfs_buf_t	*agbp;
 	xfs_agino_t	agino;
@@ -766,7 +766,7 @@ xfs_inumbers(
 				error = XFS_ERROR(EFAULT);
 				break;
 			}
-			ubuffer += bufidx * sizeof(*buffer);
+			ubuffer += bufidx;
 			*count += bufidx;
 			bufidx = 0;
 		}
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/xfs/xfs_itable.h linux-2.4.28-pre3/fs/xfs/xfs_itable.h
--- linux-2.4.27/fs/xfs/xfs_itable.h	2004-08-07 23:26:06.000000000 +0000
+++ linux-2.4.28-pre3/fs/xfs/xfs_itable.h	2004-09-10 19:36:12.000000000 +0000
@@ -40,7 +40,7 @@
  */
 typedef int (*bulkstat_one_pf)(struct xfs_mount	*mp,
 			       xfs_ino_t	ino,
-			       void		*buffer,
+			       void		__user *buffer,
 			       int		ubsize,
 			       void		*private_data,
 			       xfs_daddr_t	bno,
@@ -73,7 +73,7 @@ xfs_bulkstat(
 	bulkstat_one_pf formatter,	/* func that'd fill a single buf */
 	void		*private_data,	/* private data for formatter */
 	size_t		statstruct_size,/* sizeof struct that we're filling */
-	xfs_caddr_t	ubuffer,	/* buffer with inode stats */
+	char		__user *ubuffer,/* buffer with inode stats */
 	int		flags,		/* flag to control access method */
 	int		*done);		/* 1 if there're more stats to get */
 
@@ -81,14 +81,14 @@ int
 xfs_bulkstat_single(
 	xfs_mount_t		*mp,
 	xfs_ino_t		*lastinop,
-	xfs_caddr_t		buffer,
+	char			__user *buffer,
 	int			*done);
 
 int
 xfs_bulkstat_one(
 	xfs_mount_t		*mp,
 	xfs_ino_t		ino,
-	void			*buffer,
+	void			__user *buffer,
 	int			ubsize,
 	void			*private_data,
 	xfs_daddr_t		bno,
@@ -101,6 +101,6 @@ xfs_inumbers(
 	xfs_mount_t		*mp,	/* mount point for filesystem */
 	xfs_ino_t		*last,	/* last inode returned */
 	int			*count,	/* size of buffer/count returned */
-	xfs_caddr_t		buffer);/* buffer with inode descriptions */
+	xfs_inogrp_t		__user *buffer);/* buffer with inode info */
 
 #endif	/* __XFS_ITABLE_H__ */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/xfs/xfs_log.c linux-2.4.28-pre3/fs/xfs/xfs_log.c
--- linux-2.4.27/fs/xfs/xfs_log.c	2004-08-07 23:26:06.000000000 +0000
+++ linux-2.4.28-pre3/fs/xfs/xfs_log.c	2004-09-10 19:36:10.000000000 +0000
@@ -122,7 +122,6 @@ STATIC void		xlog_ticket_put(xlog_t *log
 /* local debug functions */
 #if defined(DEBUG) && !defined(XLOG_NOLOG)
 STATIC void	xlog_verify_dest_ptr(xlog_t *log, __psint_t ptr);
-STATIC void	xlog_verify_disk_cycle_no(xlog_t *log, xlog_in_core_t *iclog);
 STATIC void	xlog_verify_grant_head(xlog_t *log, int equals);
 STATIC void	xlog_verify_iclog(xlog_t *log, xlog_in_core_t *iclog,
 				  int count, boolean_t syncing);
@@ -130,7 +129,6 @@ STATIC void	xlog_verify_tail_lsn(xlog_t 
 				     xfs_lsn_t tail_lsn);
 #else
 #define xlog_verify_dest_ptr(a,b)
-#define xlog_verify_disk_cycle_no(a,b)
 #define xlog_verify_grant_head(a,b)
 #define xlog_verify_iclog(a,b,c,d)
 #define xlog_verify_tail_lsn(a,b,c)
@@ -356,13 +354,13 @@ xfs_log_notify(xfs_mount_t	  *mp,		/* mo
 	if (!xlog_debug && xlog_target == log->l_targ)
 		return 0;
 #endif
-	cb->cb_next = 0;
+	cb->cb_next = NULL;
 	spl = LOG_LOCK(log);
 	abortflg = (iclog->ic_state & XLOG_STATE_IOERROR);
 	if (!abortflg) {
 		ASSERT_ALWAYS((iclog->ic_state == XLOG_STATE_ACTIVE) ||
 			      (iclog->ic_state == XLOG_STATE_WANT_SYNC));
-		cb->cb_next = 0;
+		cb->cb_next = NULL;
 		*(iclog->ic_callback_tail) = cb;
 		iclog->ic_callback_tail = &(cb->cb_next);
 	}
@@ -564,7 +562,7 @@ xfs_log_unmount_write(xfs_mount_t *mp)
 	xlog_in_core_t	 *first_iclog;
 #endif
 	xfs_log_iovec_t  reg[1];
-	xfs_log_ticket_t tic = 0;
+	xfs_log_ticket_t tic = NULL;
 	xfs_lsn_t	 lsn;
 	int		 error;
 	SPLDECL(s);
@@ -813,7 +811,7 @@ xfs_log_need_covered(xfs_mount_t *mp)
 	xlog_t		*log = mp->m_log;
 	vfs_t		*vfsp = XFS_MTOVFS(mp);
 
-	if (mp->m_frozen || XFS_FORCED_SHUTDOWN(mp) ||
+	if (fs_frozen(vfsp) || XFS_FORCED_SHUTDOWN(mp) ||
 	    (vfsp->vfs_flag & VFS_RDONLY))
 		return 0;
 
@@ -1277,7 +1275,7 @@ xlog_commit_record(xfs_mount_t  *mp,
 	int		error;
 	xfs_log_iovec_t	reg[1];
 
-	reg[0].i_addr = 0;
+	reg[0].i_addr = NULL;
 	reg[0].i_len = 0;
 
 	ASSERT_ALWAYS(iclog);
@@ -1413,9 +1411,13 @@ xlog_sync(xlog_t		*log,
 	xlog_pack_data(log, iclog);       /* put cycle number in every block */
 
 	/* real byte length */
-	INT_SET(iclog->ic_header.h_len, 
-		ARCH_CONVERT,
-		iclog->ic_offset + iclog->ic_roundoff);
+	if (XFS_SB_VERSION_HASLOGV2(&log->l_mp->m_sb)) {
+		INT_SET(iclog->ic_header.h_len, 
+			ARCH_CONVERT,
+			iclog->ic_offset + iclog->ic_roundoff);
+	} else {
+		INT_SET(iclog->ic_header.h_len, ARCH_CONVERT, iclog->ic_offset);
+	}
 
 	/* put ops count in correct order */
 	ops = iclog->ic_header.h_num_logops;
@@ -1857,7 +1859,7 @@ xlog_state_clean_log(xlog_t *log)
 		if (iclog->ic_state == XLOG_STATE_DIRTY) {
 			iclog->ic_state	= XLOG_STATE_ACTIVE;
 			iclog->ic_offset       = 0;
-			iclog->ic_callback	= 0;   /* don't need to free */
+			iclog->ic_callback	= NULL;   /* don't need to free */
 			/*
 			 * If the number of ops in this iclog indicate it just
 			 * contains the dummy transaction, we can
@@ -2080,7 +2082,7 @@ xlog_state_do_callback(
 
 			while (cb != 0) {
 				iclog->ic_callback_tail = &(iclog->ic_callback);
-				iclog->ic_callback = 0;
+				iclog->ic_callback = NULL;
 				LOG_UNLOCK(log, s);
 
 				/* perform callbacks in the order given */
@@ -3098,7 +3100,7 @@ xlog_state_ticket_alloc(xlog_t *log)
 		log->l_ticket_cnt++;
 		log->l_ticket_tcnt++;
 	}
-	t_list->t_next = 0;
+	t_list->t_next = NULL;
 	log->l_tail = t_list;
 	LOG_UNLOCK(log, s);
 }	/* xlog_state_ticket_alloc */
@@ -3126,7 +3128,7 @@ xlog_ticket_put(xlog_t		*log,
 	/* no need to clear fields */
 #else
 	/* When we debug, it is easier if tickets are cycled */
-	ticket->t_next     = 0;
+	ticket->t_next     = NULL;
 	if (log->l_tail != 0) {
 		log->l_tail->t_next = ticket;
 	} else {
@@ -3242,33 +3244,6 @@ xlog_verify_dest_ptr(xlog_t     *log,
 		xlog_panic("xlog_verify_dest_ptr: invalid ptr");
 }	/* xlog_verify_dest_ptr */
 
-
-#ifdef DEBUG
-/* check split LR write */
-STATIC void
-xlog_verify_disk_cycle_no(xlog_t	 *log,
-			  xlog_in_core_t *iclog)
-{
-    xfs_buf_t	*bp;
-    uint	cycle_no;
-    xfs_caddr_t ptr;
-    xfs_daddr_t	i;
-
-    if (BLOCK_LSN(iclog->ic_header.h_lsn, ARCH_CONVERT) < 10) {
-	cycle_no = CYCLE_LSN(iclog->ic_header.h_lsn, ARCH_CONVERT);
-	bp = xlog_get_bp(log, 1);
-	ASSERT(bp);
-	for (i = 0; i < BLOCK_LSN(iclog->ic_header.h_lsn, ARCH_CONVERT); i++) {
-	    xlog_bread(log, i, 1, bp);
-	    ptr = xlog_align(log, i, 1, bp);
-	    if (GET_CYCLE(ptr, ARCH_CONVERT) != cycle_no)
-		xlog_warn("XFS: xlog_verify_disk_cycle_no: bad cycle no");
-	}
-	xlog_put_bp(bp);
-    }
-}	/* xlog_verify_disk_cycle_no */
-#endif
-
 STATIC void
 xlog_verify_grant_head(xlog_t *log, int equals)
 {
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/xfs/xfs_log_recover.c linux-2.4.28-pre3/fs/xfs/xfs_log_recover.c
--- linux-2.4.27/fs/xfs/xfs_log_recover.c	2004-08-07 23:26:06.000000000 +0000
+++ linux-2.4.28-pre3/fs/xfs/xfs_log_recover.c	2004-09-10 19:36:45.000000000 +0000
@@ -2047,12 +2047,11 @@ xfs_qm_dqcheck(
 		errs++;
 	}
 
-	if (! errs) {
+	if (! errs && !INT_ISZERO(ddq->d_id, ARCH_CONVERT)) {
 		if (INT_GET(ddq->d_blk_softlimit, ARCH_CONVERT) &&
 		    INT_GET(ddq->d_bcount, ARCH_CONVERT) >=
 				INT_GET(ddq->d_blk_softlimit, ARCH_CONVERT)) {
-			if (INT_ISZERO(ddq->d_btimer, ARCH_CONVERT) &&
-			    !INT_ISZERO(ddq->d_id, ARCH_CONVERT)) {
+			if (INT_ISZERO(ddq->d_btimer, ARCH_CONVERT)) {
 				if (flags & XFS_QMOPT_DOWARN)
 					cmn_err(CE_ALERT,
 					"%s : Dquot ID 0x%x (0x%p) "
@@ -2065,8 +2064,7 @@ xfs_qm_dqcheck(
 		if (INT_GET(ddq->d_ino_softlimit, ARCH_CONVERT) &&
 		    INT_GET(ddq->d_icount, ARCH_CONVERT) >=
 				INT_GET(ddq->d_ino_softlimit, ARCH_CONVERT)) {
-			if (INT_ISZERO(ddq->d_itimer, ARCH_CONVERT) &&
-			    !INT_ISZERO(ddq->d_id, ARCH_CONVERT)) {
+			if (INT_ISZERO(ddq->d_itimer, ARCH_CONVERT)) {
 				if (flags & XFS_QMOPT_DOWARN)
 					cmn_err(CE_ALERT,
 					"%s : Dquot ID 0x%x (0x%p) "
@@ -2076,6 +2074,19 @@ xfs_qm_dqcheck(
 				errs++;
 			}
 		}
+		if (INT_GET(ddq->d_rtb_softlimit, ARCH_CONVERT) &&
+		    INT_GET(ddq->d_rtbcount, ARCH_CONVERT) >=
+				INT_GET(ddq->d_rtb_softlimit, ARCH_CONVERT)) {
+			if (INT_ISZERO(ddq->d_rtbtimer, ARCH_CONVERT)) {
+				if (flags & XFS_QMOPT_DOWARN)
+					cmn_err(CE_ALERT,
+					"%s : Dquot ID 0x%x (0x%p) "
+					"RTBLK TIMER NOT STARTED",
+					str, (int)
+					INT_GET(ddq->d_id, ARCH_CONVERT), ddq);
+				errs++;
+			}
+		}
 	}
 
 	if (!errs || !(flags & XFS_QMOPT_DQREPAIR))
@@ -2319,7 +2330,7 @@ xlog_recover_do_inode_trans(
 		 * invalidate the buffer when we write it out below.
 		 */
 		imap.im_blkno = 0;
-		xfs_imap(log->l_mp, 0, ino, &imap, 0);
+		xfs_imap(log->l_mp, NULL, ino, &imap, 0);
 	}
 
 	/*
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/xfs/xfs_mount.c linux-2.4.28-pre3/fs/xfs/xfs_mount.c
--- linux-2.4.27/fs/xfs/xfs_mount.c	2004-08-07 23:26:06.000000000 +0000
+++ linux-2.4.28-pre3/fs/xfs/xfs_mount.c	2004-09-10 19:35:59.000000000 +0000
@@ -140,9 +140,6 @@ xfs_mount_init(void)
 	 */
 	xfs_trans_ail_init(mp);
 
-	/* Init freeze sync structures */
-	spinlock_init(&mp->m_freeze_lock, "xfs_freeze");
-	init_sv(&mp->m_wait_unfreeze, SV_DEFAULT, "xfs_freeze", 0);
 	atomic_set(&mp->m_active_trans, 0);
 
 	return mp;
@@ -192,8 +189,6 @@ xfs_mount_free(
 		VFS_REMOVEBHV(vfsp, &mp->m_bhv);
 	}
 
-	spinlock_destroy(&mp->m_freeze_lock);
-	sv_destroy(&mp->m_wait_unfreeze);
 	kmem_free(mp, sizeof(xfs_mount_t));
 }
 
@@ -283,17 +278,22 @@ xfs_mount_validate_sb(
 		return XFS_ERROR(EFSCORRUPTED);
 	}
 
-#if !XFS_BIG_BLKNOS
+	ASSERT(PAGE_SHIFT >= sbp->sb_blocklog);
+	ASSERT(sbp->sb_blocklog >= BBSHIFT);
+
+#if XFS_BIG_BLKNOS     /* Limited by ULONG_MAX of page cache index */
+	if (unlikely(
+	    (sbp->sb_dblocks >> (PAGE_SHIFT - sbp->sb_blocklog)) > ULONG_MAX ||
+	    (sbp->sb_rblocks >> (PAGE_SHIFT - sbp->sb_blocklog)) > ULONG_MAX)) {
+#else                  /* Limited by UINT_MAX of sectors */
 	if (unlikely(
-	    (sbp->sb_dblocks << (__uint64_t)(sbp->sb_blocklog - BBSHIFT))
-		> UINT_MAX ||
-	    (sbp->sb_rblocks << (__uint64_t)(sbp->sb_blocklog - BBSHIFT))
-		> UINT_MAX)) {
+	    (sbp->sb_dblocks << (sbp->sb_blocklog - BBSHIFT)) > UINT_MAX ||
+	    (sbp->sb_rblocks << (sbp->sb_blocklog - BBSHIFT)) > UINT_MAX)) {
+#endif
 		cmn_err(CE_WARN,
 	"XFS: File system is too large to be mounted on this system.");
 		return XFS_ERROR(E2BIG);
 	}
-#endif
 
 	if (unlikely(sbp->sb_inprogress)) {
 		cmn_err(CE_WARN, "XFS: file system busy");
@@ -318,10 +318,10 @@ xfs_mount_validate_sb(
 	return 0;
 }
 
-void
-xfs_initialize_perag(xfs_mount_t *mp, int agcount)
+xfs_agnumber_t
+xfs_initialize_perag(xfs_mount_t *mp, xfs_agnumber_t agcount)
 {
-	int		index, max_metadata;
+	xfs_agnumber_t	index, max_metadata;
 	xfs_perag_t	*pag;
 	xfs_agino_t	agino;
 	xfs_ino_t	ino;
@@ -377,7 +377,7 @@ xfs_initialize_perag(xfs_mount_t *mp, in
 			pag->pagi_inodeok = 1;
 		}
 	}
-	mp->m_maxagi = index;
+	return index;
 }
 
 /*
@@ -638,9 +638,8 @@ xfs_mountfs(
 	xfs_buf_t	*bp;
 	xfs_sb_t	*sbp = &(mp->m_sb);
 	xfs_inode_t	*rip;
-	vnode_t		*rvp = 0;
+	vnode_t		*rvp = NULL;
 	int		readio_log, writeio_log;
-	vmap_t		vmap;
 	xfs_daddr_t	d;
 	__uint64_t	ret64;
 	__int64_t	update_flags;
@@ -952,7 +951,7 @@ xfs_mountfs(
 	mp->m_perag =
 		kmem_zalloc(sbp->sb_agcount * sizeof(xfs_perag_t), KM_SLEEP);
 
-	xfs_initialize_perag(mp, sbp->sb_agcount);
+	mp->m_maxagi = xfs_initialize_perag(mp, sbp->sb_agcount);
 
 	/*
 	 * log's mount-time initialization. Perform 1st part recovery if needed
@@ -984,7 +983,6 @@ xfs_mountfs(
 
 	ASSERT(rip != NULL);
 	rvp = XFS_ITOV(rip);
-	VMAP(rvp, vmap);
 
 	if (unlikely((rip->i_d.di_mode & S_IFMT) != S_IFDIR)) {
 		cmn_err(CE_WARN, "XFS: corrupted root inode");
@@ -1048,7 +1046,6 @@ xfs_mountfs(
 	 * Free up the root inode.
 	 */
 	VN_RELE(rvp);
-	vn_purge(rvp, &vmap);
  error3:
 	xfs_log_unmount_dealloc(mp);
  error2:
@@ -1582,59 +1579,3 @@ xfs_mount_log_sbunit(
 	xfs_mod_sb(tp, fields);
 	xfs_trans_commit(tp, 0, NULL);
 }
-
-/* Functions to lock access out of the filesystem for forced
- * shutdown or snapshot.
- */
-
-void
-xfs_start_freeze(
-	xfs_mount_t	*mp,
-	int		level)
-{
-	unsigned long	s = mutex_spinlock(&mp->m_freeze_lock);
-
-	mp->m_frozen = level;
-	mutex_spinunlock(&mp->m_freeze_lock, s);
-
-	if (level == XFS_FREEZE_TRANS) {
-		while (atomic_read(&mp->m_active_trans) > 0)
-			delay(100);
-	}
-}
-
-void
-xfs_finish_freeze(
-	xfs_mount_t	*mp)
-{
-	unsigned long	s = mutex_spinlock(&mp->m_freeze_lock);
-
-	if (mp->m_frozen) {
-		mp->m_frozen = 0;
-		sv_broadcast(&mp->m_wait_unfreeze);
-	}
-
-	mutex_spinunlock(&mp->m_freeze_lock, s);
-}
-
-void
-xfs_check_frozen(
-	xfs_mount_t	*mp,
-	bhv_desc_t	*bdp,
-	int		level)
-{
-	unsigned long	s;
-
-	if (mp->m_frozen) {
-		s = mutex_spinlock(&mp->m_freeze_lock);
-
-		if (mp->m_frozen < level) {
-			mutex_spinunlock(&mp->m_freeze_lock, s);
-		} else {
-			sv_wait(&mp->m_wait_unfreeze, 0, &mp->m_freeze_lock, s);
-		}
-	}
-
-	if (level == XFS_FREEZE_TRANS)
-		atomic_inc(&mp->m_active_trans);
-}
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/xfs/xfs_mount.h linux-2.4.28-pre3/fs/xfs/xfs_mount.h
--- linux-2.4.27/fs/xfs/xfs_mount.h	2004-08-07 23:26:06.000000000 +0000
+++ linux-2.4.28-pre3/fs/xfs/xfs_mount.h	2004-09-10 19:32:45.000000000 +0000
@@ -382,10 +382,6 @@ typedef struct xfs_mount {
 	struct xfs_dmops	m_dm_ops;	/* vector of DMI ops */
 	struct xfs_qmops	m_qm_ops;	/* vector of XQM ops */
 	struct xfs_ioops	m_io_ops;	/* vector of I/O ops */
-	lock_t			m_freeze_lock;	/* Lock for m_frozen */
-	uint			m_frozen;	/* FS frozen for shutdown or
-						 * snapshot */
-	sv_t			m_wait_unfreeze;/* waiting to unfreeze */
 	atomic_t		m_active_trans;	/* number trans frozen */
 } xfs_mount_t;
 
@@ -555,20 +551,10 @@ extern int	xfs_readsb(xfs_mount_t *mp);
 extern void	xfs_freesb(xfs_mount_t *);
 extern void	xfs_do_force_shutdown(bhv_desc_t *, int, char *, int);
 extern int	xfs_syncsub(xfs_mount_t *, int, int, int *);
-extern void	xfs_initialize_perag(xfs_mount_t *, int);
+extern xfs_agnumber_t	xfs_initialize_perag(xfs_mount_t *, xfs_agnumber_t);
 extern void	xfs_xlatesb(void *, struct xfs_sb *, int, xfs_arch_t,
 			__int64_t);
 
-/*
- * Flags for freeze operations.
- */
-#define XFS_FREEZE_WRITE	1
-#define XFS_FREEZE_TRANS	2
-
-extern void	xfs_start_freeze(xfs_mount_t *, int);
-extern void	xfs_finish_freeze(xfs_mount_t *);
-extern void	xfs_check_frozen(xfs_mount_t *, bhv_desc_t *, int);
-
 extern struct vfsops xfs_vfsops;
 extern struct vnodeops xfs_vnodeops;
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/xfs/xfs_quota.h linux-2.4.28-pre3/fs/xfs/xfs_quota.h
--- linux-2.4.27/fs/xfs/xfs_quota.h	2004-04-14 13:05:40.000000000 +0000
+++ linux-2.4.28-pre3/fs/xfs/xfs_quota.h	2004-09-10 19:34:52.000000000 +0000
@@ -309,23 +309,27 @@ typedef struct xfs_dqtrxops {
 } xfs_dqtrxops_t;
 
 #define XFS_DQTRXOP(mp, tp, op, args...) \
-			((mp)->m_qm_ops.xfs_dqtrxops ? \
-			((mp)->m_qm_ops.xfs_dqtrxops->op)(tp, ## args) : 0)
+		((mp)->m_qm_ops.xfs_dqtrxops ? \
+		((mp)->m_qm_ops.xfs_dqtrxops->op)(tp, ## args) : 0)
+
+#define XFS_DQTRXOP_VOID(mp, tp, op, args...) \
+		((mp)->m_qm_ops.xfs_dqtrxops ? \
+		((mp)->m_qm_ops.xfs_dqtrxops->op)(tp, ## args) : (void)0)
 
 #define XFS_TRANS_DUP_DQINFO(mp, otp, ntp) \
-	XFS_DQTRXOP(mp, otp, qo_dup_dqinfo, ntp)
+	XFS_DQTRXOP_VOID(mp, otp, qo_dup_dqinfo, ntp)
 #define XFS_TRANS_FREE_DQINFO(mp, tp) \
-	XFS_DQTRXOP(mp, tp, qo_free_dqinfo)
+	XFS_DQTRXOP_VOID(mp, tp, qo_free_dqinfo)
 #define XFS_TRANS_MOD_DQUOT_BYINO(mp, tp, ip, field, delta) \
-	XFS_DQTRXOP(mp, tp, qo_mod_dquot_byino, ip, field, delta)
+	XFS_DQTRXOP_VOID(mp, tp, qo_mod_dquot_byino, ip, field, delta)
 #define XFS_TRANS_APPLY_DQUOT_DELTAS(mp, tp) \
-	XFS_DQTRXOP(mp, tp, qo_apply_dquot_deltas)
+	XFS_DQTRXOP_VOID(mp, tp, qo_apply_dquot_deltas)
 #define XFS_TRANS_RESERVE_QUOTA_NBLKS(mp, tp, ip, nblks, ninos, fl) \
 	XFS_DQTRXOP(mp, tp, qo_reserve_quota_nblks, mp, ip, nblks, ninos, fl)
 #define XFS_TRANS_RESERVE_QUOTA_BYDQUOTS(mp, tp, ud, gd, nb, ni, fl) \
 	XFS_DQTRXOP(mp, tp, qo_reserve_quota_bydquots, mp, ud, gd, nb, ni, fl)
 #define XFS_TRANS_UNRESERVE_AND_MOD_DQUOTS(mp, tp) \
-	XFS_DQTRXOP(mp, tp, qo_unreserve_and_mod_dquots)
+	XFS_DQTRXOP_VOID(mp, tp, qo_unreserve_and_mod_dquots)
 
 #define XFS_TRANS_RESERVE_BLKQUOTA(mp, tp, ip, nblks) \
 	XFS_TRANS_RESERVE_QUOTA_NBLKS(mp, tp, ip, nblks, 0, \
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/xfs/xfs_rtalloc.c linux-2.4.28-pre3/fs/xfs/xfs_rtalloc.c
--- linux-2.4.27/fs/xfs/xfs_rtalloc.c	2004-08-07 23:26:06.000000000 +0000
+++ linux-2.4.28-pre3/fs/xfs/xfs_rtalloc.c	2004-09-10 19:33:27.000000000 +0000
@@ -2353,13 +2353,7 @@ xfs_rtmount_inodes(
 	ASSERT(sbp->sb_rsumino != NULLFSINO);
 	error = xfs_iget(mp, NULL, sbp->sb_rsumino, 0, &mp->m_rsumip, 0);
 	if (error) {
-		vnode_t		*rbmvp;		/* vnode for bitmap file */
-		vmap_t		vmap;		/* vmap to delete vnode */
-
-		rbmvp = XFS_ITOV(mp->m_rbmip);
-		VMAP(rbmvp, vmap);
-		VN_RELE(rbmvp);
-		vn_purge(rbmvp, &vmap);
+		VN_RELE(XFS_ITOV(mp->m_rbmip));
 		return error;
 	}
 	ASSERT(mp->m_rsumip != NULL);
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/xfs/xfs_sb.h linux-2.4.28-pre3/fs/xfs/xfs_sb.h
--- linux-2.4.27/fs/xfs/xfs_sb.h	2004-08-07 23:26:06.000000000 +0000
+++ linux-2.4.28-pre3/fs/xfs/xfs_sb.h	2004-09-10 19:35:32.000000000 +0000
@@ -250,9 +250,9 @@ int xfs_sb_good_version(xfs_sb_t *sbp);
 	((((sbp)->sb_versionnum >= XFS_SB_VERSION_1) && \
 	  ((sbp)->sb_versionnum <= XFS_SB_VERSION_3)) || \
 	   ((XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_4) && \
-	    !(((sbp)->sb_versionnum & ~XFS_SB_VERSION_OKREALBITS) && \
-	      ((sbp)->sb_versionnum & XFS_SB_VERSION_MOREBITSBIT) && \
-	      ((sbp)->sb_features2 & ~XFS_SB_VERSION2_OKREALBITS))
+	    !(((sbp)->sb_versionnum & ~XFS_SB_VERSION_OKREALBITS) || \
+	      (((sbp)->sb_versionnum & XFS_SB_VERSION_MOREBITSBIT) && \
+	       ((sbp)->sb_features2 & ~XFS_SB_VERSION2_OKREALBITS)))
 
 #ifdef __KERNEL__
 #define	XFS_SB_GOOD_VERSION(sbp)	\
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/xfs/xfs_trans.c linux-2.4.28-pre3/fs/xfs/xfs_trans.c
--- linux-2.4.27/fs/xfs/xfs_trans.c	2004-08-07 23:26:06.000000000 +0000
+++ linux-2.4.28-pre3/fs/xfs/xfs_trans.c	2004-09-10 19:35:22.000000000 +0000
@@ -131,7 +131,9 @@ xfs_trans_alloc(
 	xfs_mount_t	*mp,
 	uint		type)
 {
-	xfs_check_frozen(mp, NULL, XFS_FREEZE_TRANS);
+	fs_check_frozen(XFS_MTOVFS(mp), SB_FREEZE_TRANS);
+	atomic_inc(&mp->m_active_trans);
+
 	return (_xfs_trans_alloc(mp, type));
 
 }
@@ -489,6 +491,9 @@ xfs_trans_apply_sb_deltas(
 	if (tp->t_frextents_delta != 0) {
 		INT_MOD(sbp->sb_frextents, ARCH_CONVERT, tp->t_frextents_delta);
 	}
+	if (tp->t_res_frextents_delta != 0) {
+		INT_MOD(sbp->sb_frextents, ARCH_CONVERT, tp->t_res_frextents_delta);
+	}
 	if (tp->t_dblocks_delta != 0) {
 		INT_MOD(sbp->sb_dblocks, ARCH_CONVERT, tp->t_dblocks_delta);
 		whole = 1;
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/xfs/xfs_trans_item.c linux-2.4.28-pre3/fs/xfs/xfs_trans_item.c
--- linux-2.4.27/fs/xfs/xfs_trans_item.c	2004-08-07 23:26:06.000000000 +0000
+++ linux-2.4.28-pre3/fs/xfs/xfs_trans_item.c	2004-09-10 19:36:44.000000000 +0000
@@ -290,7 +290,7 @@ xfs_trans_next_item(xfs_trans_t *tp, xfs
 	}
 	ASSERT(0);
 	/* NOTREACHED */
-	return 0; /* keep gcc quite */
+	return NULL; /* keep gcc quite */
 }
 
 /*
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/xfs/xfs_types.h linux-2.4.28-pre3/fs/xfs/xfs_types.h
--- linux-2.4.27/fs/xfs/xfs_types.h	2004-02-18 13:36:32.000000000 +0000
+++ linux-2.4.28-pre3/fs/xfs/xfs_types.h	2004-09-10 19:34:49.000000000 +0000
@@ -58,7 +58,7 @@ typedef enum { B_FALSE,B_TRUE }	boolean_
 typedef __int64_t		prid_t;		/* project ID */
 typedef __uint32_t		inst_t;		/* an instruction */
 
-typedef __u64			xfs_off_t;
+typedef __s64			xfs_off_t;	/* <file offset> type */
 typedef __u64			xfs_ino_t;	/* <inode> type */
 typedef __s64			xfs_daddr_t;	/* <disk address> type */
 typedef char *			xfs_caddr_t;	/* <core address> type */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/xfs/xfs_vfsops.c linux-2.4.28-pre3/fs/xfs/xfs_vfsops.c
--- linux-2.4.27/fs/xfs/xfs_vfsops.c	2004-08-07 23:26:06.000000000 +0000
+++ linux-2.4.28-pre3/fs/xfs/xfs_vfsops.c	2004-09-10 19:35:35.000000000 +0000
@@ -431,6 +431,16 @@ xfs_mount(
 	logdev = rtdev = NULL;
 
 	/*
+	 * Setup xfs_mount function vectors from available behaviors
+	 */
+	p = vfs_bhv_lookup(vfsp, VFS_POSITION_DM);
+	mp->m_dm_ops = p ? *(xfs_dmops_t *) vfs_bhv_custom(p) : xfs_dmcore_stub;
+	p = vfs_bhv_lookup(vfsp, VFS_POSITION_QM);
+	mp->m_qm_ops = p ? *(xfs_qmops_t *) vfs_bhv_custom(p) : xfs_qmcore_stub;
+	p = vfs_bhv_lookup(vfsp, VFS_POSITION_IO);
+	mp->m_io_ops = p ? *(xfs_ioops_t *) vfs_bhv_custom(p) : xfs_iocore_xfs;
+
+	/*
 	 * Open real time and log devices - order is important.
 	 */
 	if (args->logname[0]) {
@@ -455,68 +465,73 @@ xfs_mount(
 	}
 
 	/*
-	 * Setup xfs_mount function vectors from available behaviors
-	 */
-	p = vfs_bhv_lookup(vfsp, VFS_POSITION_DM);
-	mp->m_dm_ops = p ? *(xfs_dmops_t *) vfs_bhv_custom(p) : xfs_dmcore_stub;
-	p = vfs_bhv_lookup(vfsp, VFS_POSITION_QM);
-	mp->m_qm_ops = p ? *(xfs_qmops_t *) vfs_bhv_custom(p) : xfs_qmcore_stub;
-	p = vfs_bhv_lookup(vfsp, VFS_POSITION_IO);
-	mp->m_io_ops = p ? *(xfs_ioops_t *) vfs_bhv_custom(p) : xfs_iocore_xfs;
-
-	/*
 	 * Setup xfs_mount buffer target pointers
 	 */
+	error = ENOMEM;
 	mp->m_ddev_targp = xfs_alloc_buftarg(ddev);
-	if (rtdev)
+	if (!mp->m_ddev_targp) {
+		xfs_blkdev_put(logdev);
+		xfs_blkdev_put(rtdev);
+		return error;
+	}
+	if (rtdev) {
 		mp->m_rtdev_targp = xfs_alloc_buftarg(rtdev);
+		if (!mp->m_rtdev_targp)
+			goto error0;
+	}
 	mp->m_logdev_targp = (logdev && logdev != ddev) ?
 				xfs_alloc_buftarg(logdev) : mp->m_ddev_targp;
+	if (!mp->m_logdev_targp)
+		goto error0;
 
 	/*
 	 * Setup flags based on mount(2) options and then the superblock
 	 */
 	error = xfs_start_flags(vfsp, args, mp);
 	if (error)
-		goto error;
+		goto error1;
 	error = xfs_readsb(mp);
 	if (error)
-		goto error;
+		goto error1;
 	error = xfs_finish_flags(vfsp, args, mp);
-	if (error) {
-		xfs_freesb(mp);
-		goto error;
-	}
+	if (error)
+		goto error2;
 
 	/*
 	 * Setup xfs_mount buffer target pointers based on superblock
 	 */
-	xfs_setsize_buftarg(mp->m_ddev_targp, mp->m_sb.sb_blocksize,
-			    mp->m_sb.sb_sectsize);
-	if (logdev && logdev != ddev) {
+	error = xfs_setsize_buftarg(mp->m_ddev_targp, mp->m_sb.sb_blocksize,
+				    mp->m_sb.sb_sectsize);
+	if (!error && logdev && logdev != ddev) {
 		unsigned int	log_sector_size = BBSIZE;
 
 		if (XFS_SB_VERSION_HASSECTOR(&mp->m_sb))
 			log_sector_size = mp->m_sb.sb_logsectsize;
-		xfs_setsize_buftarg(mp->m_logdev_targp, mp->m_sb.sb_blocksize,
-				    log_sector_size);
-	}
-	if (rtdev)
-		xfs_setsize_buftarg(mp->m_rtdev_targp, mp->m_sb.sb_blocksize,
-				    mp->m_sb.sb_blocksize);
+		error = xfs_setsize_buftarg(mp->m_logdev_targp,
+					    mp->m_sb.sb_blocksize,
+					    log_sector_size);
+	}
+	if (!error && rtdev)
+		error = xfs_setsize_buftarg(mp->m_rtdev_targp,
+					    mp->m_sb.sb_blocksize,
+					    mp->m_sb.sb_sectsize);
+	if (error)
+		goto error2;
 
-	if (!(error = XFS_IOINIT(vfsp, args, flags)))
+	error = XFS_IOINIT(vfsp, args, flags);
+	if (!error)
 		return 0;
-
- error:
+error2:
+	if (mp->m_sb_bp)
+		xfs_freesb(mp);
+error1:
 	xfs_binval(mp->m_ddev_targp);
-	if (logdev != NULL && logdev != ddev) {
+	if (logdev && logdev != ddev)
 		xfs_binval(mp->m_logdev_targp);
-	}
-	if (rtdev != NULL) {
+	if (rtdev)
 		xfs_binval(mp->m_rtdev_targp);
-	}
-	xfs_unmountfs_close(mp, NULL);
+error0:
+	xfs_unmountfs_close(mp, credp);
 	return error;
 }
 
@@ -1508,7 +1523,10 @@ xfs_syncsub(
 	 * eventually kicked out of the cache.
 	 */
 	if (flags & SYNC_REFCACHE) {
-		xfs_refcache_purge_some(mp);
+		if (flags & SYNC_WAIT)
+			xfs_refcache_purge_mp(mp);
+		else
+			xfs_refcache_purge_some(mp);
 	}
 
 	/*
@@ -1866,6 +1884,20 @@ xfs_showargs(
 	return 0;
 }
 
+STATIC void
+xfs_freeze(
+	bhv_desc_t	*bdp)
+{
+	xfs_mount_t	*mp = XFS_BHVTOM(bdp);
+
+	while (atomic_read(&mp->m_active_trans) > 0)
+		delay(100);
+
+	/* Push the superblock and write an unmount record */
+	xfs_log_unmount_write(mp);
+	xfs_unmountfs_writesb(mp);
+}
+
 
 vfsops_t xfs_vfsops = {
 	BHV_IDENTITY_INIT(VFS_BHV_XFS,VFS_POSITION_XFS),
@@ -1883,4 +1915,5 @@ vfsops_t xfs_vfsops = {
 	.vfs_get_inode		= xfs_get_inode,
 	.vfs_init_vnode		= xfs_initialize_vnode,
 	.vfs_force_shutdown	= xfs_do_force_shutdown,
+	.vfs_freeze		= xfs_freeze,
 };
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/fs/xfs/xfs_vnodeops.c linux-2.4.28-pre3/fs/xfs/xfs_vnodeops.c
--- linux-2.4.27/fs/xfs/xfs_vnodeops.c	2004-08-07 23:26:06.000000000 +0000
+++ linux-2.4.28-pre3/fs/xfs/xfs_vnodeops.c	2004-09-10 19:35:38.000000000 +0000
@@ -283,7 +283,7 @@ xfs_getattr(
 /*
  * xfs_setattr
  */
-STATIC int
+int
 xfs_setattr(
 	bhv_desc_t		*bdp,
 	vattr_t			*vap,
@@ -305,6 +305,7 @@ xfs_setattr(
 	int			mandlock_before, mandlock_after;
 	struct xfs_dquot	*udqp, *gdqp, *olddquot1, *olddquot2;
 	int			file_owner;
+	int			need_iolock = (flags & ATTR_DMI) == 0;
 
 	vp = BHV_TO_VNODE(bdp);
 	vn_trace_entry(vp, __FUNCTION__, (inst_t *)__return_address);
@@ -406,7 +407,8 @@ xfs_setattr(
 				goto error_return;
 			}
 		}
-		lock_flags |= XFS_IOLOCK_EXCL;
+		if (need_iolock)
+			lock_flags |= XFS_IOLOCK_EXCL;
 	}
 
 	xfs_ilock(ip, lock_flags);
@@ -678,7 +680,8 @@ xfs_setattr(
 					     XFS_TRANS_PERM_LOG_RES,
 					     XFS_ITRUNCATE_LOG_COUNT))) {
 			xfs_trans_cancel(tp, 0);
-			xfs_iunlock(ip, XFS_IOLOCK_EXCL);
+			if (need_iolock)
+				xfs_iunlock(ip, XFS_IOLOCK_EXCL);
 			return code;
 		}
 		commit_flags = XFS_TRANS_RELEASE_LOG_RES;
@@ -823,10 +826,15 @@ xfs_setattr(
 				mp->m_sb.sb_blocklog;
 		}
 		if (mask & XFS_AT_XFLAGS) {
-			ip->i_d.di_flags = 0;
-			if (vap->va_xflags & XFS_XFLAG_REALTIME) {
+			/* can't set PREALLOC this way, just preserve it */
+			ip->i_d.di_flags =
+				(ip->i_d.di_flags & XFS_DIFLAG_PREALLOC);
+			if (vap->va_xflags & XFS_XFLAG_REALTIME &&
+			    (ip->i_d.di_mode & S_IFMT) == S_IFREG) {
 				ip->i_d.di_flags |= XFS_DIFLAG_REALTIME;
 				ip->i_iocore.io_flags |= XFS_IOCORE_RT;
+			} else {
+				ip->i_iocore.io_flags &= ~XFS_IOCORE_RT;
 			}
 			if (vap->va_xflags & XFS_XFLAG_IMMUTABLE)
 				ip->i_d.di_flags |= XFS_DIFLAG_IMMUTABLE;
@@ -838,7 +846,9 @@ xfs_setattr(
 				ip->i_d.di_flags |= XFS_DIFLAG_NOATIME;
 			if (vap->va_xflags & XFS_XFLAG_NODUMP)
 				ip->i_d.di_flags |= XFS_DIFLAG_NODUMP;
-			/* can't set PREALLOC this way, just ignore it */
+			if ((vap->va_xflags & XFS_XFLAG_RTINHERIT) &&
+			    (ip->i_d.di_mode & S_IFMT) == S_IFDIR)
+				ip->i_d.di_flags |= XFS_DIFLAG_RTINHERIT;
 		}
 		xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
 		timeflags |= XFS_ICHGTIME_CHG;
@@ -1822,8 +1832,6 @@ xfs_lookup(
 }
 
 
-#define	XFS_CREATE_NEW_MAXTRIES	10000
-
 /*
  * xfs_create (create a new file).
  */
@@ -4292,6 +4300,7 @@ xfs_free_file_space(
 	int			rt;
 	xfs_fileoff_t		startoffset_fsb;
 	xfs_trans_t		*tp;
+	int			need_iolock = (attr_flags & ATTR_DMI) == 0;
 
 	vn_trace_entry(XFS_ITOV(ip), __FUNCTION__, (inst_t *)__return_address);
 	mp = ip->i_mount;
@@ -4319,7 +4328,8 @@ xfs_free_file_space(
 			return(error);
 	}
 
-	xfs_ilock(ip, XFS_IOLOCK_EXCL);
+	if (need_iolock)
+		xfs_ilock(ip, XFS_IOLOCK_EXCL);
 	rounding = MAX((__uint8_t)(1 << mp->m_sb.sb_blocklog),
 			(__uint8_t)NBPP);
 	ilen = len + (offset & (rounding - 1));
@@ -4338,7 +4348,7 @@ xfs_free_file_space(
 		error = xfs_bmapi(NULL, ip, startoffset_fsb, 1, 0, NULL, 0,
 			&imap, &nimap, NULL);
 		if (error)
-			return error;
+			goto out_unlock_iolock;
 		ASSERT(nimap == 0 || nimap == 1);
 		if (nimap && imap.br_startblock != HOLESTARTBLOCK) {
 			xfs_daddr_t	block;
@@ -4353,7 +4363,7 @@ xfs_free_file_space(
 		error = xfs_bmapi(NULL, ip, endoffset_fsb - 1, 1, 0, NULL, 0,
 			&imap, &nimap, NULL);
 		if (error)
-			return error;
+			goto out_unlock_iolock;
 		ASSERT(nimap == 0 || nimap == 1);
 		if (nimap && imap.br_startblock != HOLESTARTBLOCK) {
 			ASSERT(imap.br_startblock != DELAYSTARTBLOCK);
@@ -4442,14 +4452,17 @@ xfs_free_file_space(
 		xfs_iunlock(ip, XFS_ILOCK_EXCL);
 	}
 
-	xfs_iunlock(ip, XFS_IOLOCK_EXCL);
+ out_unlock_iolock:
+	if (need_iolock)
+		xfs_iunlock(ip, XFS_IOLOCK_EXCL);
 	return error;
 
  error0:
 	xfs_bmap_cancel(&free_list);
  error1:
 	xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES | XFS_TRANS_ABORT);
-	xfs_iunlock(ip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL);
+	xfs_iunlock(ip, need_iolock ? (XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL) :
+		    XFS_ILOCK_EXCL);
 	return error;
 }
 
@@ -4606,20 +4619,21 @@ xfs_change_file_space(
 	xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
 	xfs_trans_ihold(tp, ip);
 
-	ip->i_d.di_mode &= ~S_ISUID;
-
-	/*
-	 * Note that we don't have to worry about mandatory
-	 * file locking being disabled here because we only
-	 * clear the S_ISGID bit if the Group execute bit is
-	 * on, but if it was on then mandatory locking wouldn't
-	 * have been enabled.
-	 */
-	if (ip->i_d.di_mode & S_IXGRP)
-		ip->i_d.di_mode &= ~S_ISGID;
+	if ((attr_flags & ATTR_DMI) == 0) {
+		ip->i_d.di_mode &= ~S_ISUID;
 
-	xfs_ichgtime(ip, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
+		/*
+		 * Note that we don't have to worry about mandatory
+		 * file locking being disabled here because we only
+		 * clear the S_ISGID bit if the Group execute bit is
+		 * on, but if it was on then mandatory locking wouldn't
+		 * have been enabled.
+		 */
+		if (ip->i_d.di_mode & S_IXGRP)
+			ip->i_d.di_mode &= ~S_ISGID;
 
+		xfs_ichgtime(ip, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
+	}
 	if (setprealloc)
 		ip->i_d.di_flags |= XFS_DIFLAG_PREALLOC;
 	else if (clrprealloc)
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/include/asm-i386/apic.h linux-2.4.28-pre3/include/asm-i386/apic.h
--- linux-2.4.27/include/asm-i386/apic.h	2002-08-03 00:39:45.000000000 +0000
+++ linux-2.4.28-pre3/include/asm-i386/apic.h	2004-09-10 19:37:14.000000000 +0000
@@ -77,7 +77,7 @@ extern void init_apic_mappings (void);
 extern void smp_local_timer_interrupt (struct pt_regs * regs);
 extern void setup_APIC_clocks (void);
 extern void setup_apic_nmi_watchdog (void);
-extern inline void nmi_watchdog_tick (struct pt_regs * regs);
+extern void nmi_watchdog_tick (struct pt_regs * regs);
 extern int APIC_init_uniprocessor (void);
 extern void disable_APIC_timer(void);
 extern void enable_APIC_timer(void);
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/include/asm-i386/rwsem.h linux-2.4.28-pre3/include/asm-i386/rwsem.h
--- linux-2.4.27/include/asm-i386/rwsem.h	2002-11-28 23:53:15.000000000 +0000
+++ linux-2.4.28-pre3/include/asm-i386/rwsem.h	2004-09-10 19:34:24.000000000 +0000
@@ -113,8 +113,8 @@ LOCK_PREFIX	"  incl      (%%eax)\n\t" /*
 		"  jmp       1b\n"
 		LOCK_SECTION_END
 		"# ending down_read\n\t"
-		: "+m"(sem->count)
-		: "a"(sem)
+		: "=m"(sem->count)
+		: "a"(sem), "m"(sem->count)
 		: "memory", "cc");
 }
 
@@ -151,8 +151,8 @@ static inline void __down_write(struct r
 	tmp = RWSEM_ACTIVE_WRITE_BIAS;
 	__asm__ __volatile__(
 		"# beginning down_write\n\t"
-LOCK_PREFIX	"  xadd      %0,(%%eax)\n\t" /* subtract 0x0000ffff, returns the old value */
-		"  testl     %0,%0\n\t" /* was the count 0 before? */
+LOCK_PREFIX	"  xadd      %%edx,(%%eax)\n\t" /* subtract 0x0000ffff, returns the old value */
+		"  testl     %%edx,%%edx\n\t" /* was the count 0 before? */
 		"  jnz       2f\n\t" /* jump if we weren't granted the lock */
 		"1:\n\t"
 		LOCK_SECTION_START("")
@@ -163,8 +163,8 @@ LOCK_PREFIX	"  xadd      %0,(%%eax)\n\t"
 		"  jmp       1b\n"
 		LOCK_SECTION_END
 		"# ending down_write"
-		: "+d"(tmp), "+m"(sem->count)
-		: "a"(sem)
+		: "=m"(sem->count), "=d"(tmp)
+		: "a"(sem), "1"(tmp), "m"(sem->count)
 		: "memory", "cc");
 }
 
@@ -202,8 +202,8 @@ LOCK_PREFIX	"  xadd      %%edx,(%%eax)\n
 		"  jmp       1b\n"
 		LOCK_SECTION_END
 		"# ending __up_read\n"
-		: "+m"(sem->count), "+d"(tmp)
-		: "a"(sem)
+		: "=m"(sem->count), "=d"(tmp)
+		: "a"(sem), "1"(tmp), "m"(sem->count)
 		: "memory", "cc");
 }
 
@@ -228,8 +228,8 @@ LOCK_PREFIX	"  xaddl     %%edx,(%%eax)\n
 		"  jmp       1b\n"
 		LOCK_SECTION_END
 		"# ending __up_write\n"
-		: "+m"(sem->count)
-		: "a"(sem), "i"(-RWSEM_ACTIVE_WRITE_BIAS)
+		: "=m"(sem->count)
+		: "a"(sem), "i"(-RWSEM_ACTIVE_WRITE_BIAS), "m"(sem->count)
 		: "memory", "cc", "edx");
 }
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/include/asm-i386/smp.h linux-2.4.28-pre3/include/asm-i386/smp.h
--- linux-2.4.27/include/asm-i386/smp.h	2002-11-28 23:53:15.000000000 +0000
+++ linux-2.4.28-pre3/include/asm-i386/smp.h	2004-09-10 19:32:11.000000000 +0000
@@ -39,7 +39,7 @@ extern int cpu_sibling_map[];
 
 extern void smp_flush_tlb(void);
 extern void smp_message_irq(int cpl, void *dev_id, struct pt_regs *regs);
-extern void smp_send_reschedule(int cpu);
+extern void fastcall smp_send_reschedule(int cpu);
 extern void smp_invalidate_rcv(void);		/* Process an NMI */
 extern void (*mtrr_hook) (void);
 extern void zap_low_mappings (void);
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/include/asm-i386/smpboot.h linux-2.4.28-pre3/include/asm-i386/smpboot.h
--- linux-2.4.27/include/asm-i386/smpboot.h	2004-08-07 23:26:06.000000000 +0000
+++ linux-2.4.28-pre3/include/asm-i386/smpboot.h	2004-09-10 19:36:56.000000000 +0000
@@ -130,8 +130,8 @@ static inline int target_cpus(void)
 			cpu = (cpu+1)%smp_num_cpus;
 			return cpu_to_physical_apicid(cpu);
 		default:
+			return cpu_online_map;
 	}
-	return cpu_online_map;
 }
 #else
 #define target_cpus() (cpu_online_map)
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/include/asm-i386/unistd.h linux-2.4.28-pre3/include/asm-i386/unistd.h
--- linux-2.4.27/include/asm-i386/unistd.h	2002-11-28 23:53:15.000000000 +0000
+++ linux-2.4.28-pre3/include/asm-i386/unistd.h	2004-09-10 19:35:39.000000000 +0000
@@ -372,7 +372,7 @@ static inline _syscall1(int,dup,int,fd)
 static inline _syscall3(int,execve,const char *,file,char **,argv,char **,envp)
 static inline _syscall3(int,open,const char *,file,int,flag,int,mode)
 static inline _syscall1(int,close,int,fd)
-static inline _syscall1(int,_exit,int,exitcode)
+static inline _syscall1(void,_exit,int,exitcode)
 static inline _syscall3(pid_t,waitpid,pid_t,pid,int *,wait_stat,int,options)
 static inline _syscall1(int,delete_module,const char *,name)
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/include/asm-ppc/unistd.h linux-2.4.28-pre3/include/asm-ppc/unistd.h
--- linux-2.4.27/include/asm-ppc/unistd.h	2003-11-28 18:26:21.000000000 +0000
+++ linux-2.4.28-pre3/include/asm-ppc/unistd.h	2004-09-10 19:33:01.000000000 +0000
@@ -382,7 +382,7 @@ static inline _syscall1(int,dup,int,fd)
 static inline _syscall3(int,execve,const char *,file,char **,argv,char **,envp)
 static inline _syscall3(int,open,const char *,file,int,flag,int,mode)
 static inline _syscall1(int,close,int,fd)
-static inline _syscall1(int,_exit,int,exitcode)
+static inline _syscall1(void,_exit,int,exitcode)
 static inline _syscall3(pid_t,waitpid,pid_t,pid,int *,wait_stat,int,options)
 static inline _syscall1(int,delete_module,const char *,name)
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/include/asm-s390/kmap_types.h linux-2.4.28-pre3/include/asm-s390/kmap_types.h
--- linux-2.4.27/include/asm-s390/kmap_types.h	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.28-pre3/include/asm-s390/kmap_types.h	2004-09-10 19:33:03.000000000 +0000
@@ -0,0 +1,16 @@
+#ifndef _ASM_KMAP_TYPES_H
+#define _ASM_KMAP_TYPES_H
+
+enum km_type {
+	KM_BOUNCE_READ,
+	KM_SKB_SUNRPC_DATA,
+	KM_SKB_DATA_SOFTIRQ,
+	KM_USER0,
+	KM_USER1,
+	KM_BH_IRQ,
+	KM_SOFTIRQ0,
+	KM_SOFTIRQ1,
+	KM_TYPE_NR
+};
+
+#endif
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/include/asm-s390/lowcore.h linux-2.4.28-pre3/include/asm-s390/lowcore.h
--- linux-2.4.27/include/asm-s390/lowcore.h	2002-08-03 00:39:45.000000000 +0000
+++ linux-2.4.28-pre3/include/asm-s390/lowcore.h	2004-09-10 19:34:47.000000000 +0000
@@ -47,6 +47,7 @@
 #define __LC_IPLDEV                     0xC7C
 
 #define __LC_JIFFY_TIMER		0xC80
+#define __LC_INT_CLOCK			0xC88
 
 #define __LC_PANIC_MAGIC                0xE00
 
@@ -165,8 +166,9 @@ struct _lowcore
 
         /* SMP info area: defined by DJB */
         __u64        jiffy_timer;              /* 0xc80 */
-	atomic_t     ext_call_fast;            /* 0xc88 */
-        __u8         pad11[0xe00-0xc8c];       /* 0xc8c */
+        __u64        int_clock;                /* 0xc88 */
+	atomic_t     ext_call_fast;            /* 0xc90 */
+        __u8         pad11[0xe00-0xc94];       /* 0xc94 */
 
         /* 0xe00 is used as indicator for dump tools */
         /* whether the kernel died with panic() or not */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/include/asm-s390/pgtable.h linux-2.4.28-pre3/include/asm-s390/pgtable.h
--- linux-2.4.27/include/asm-s390/pgtable.h	2003-08-25 11:44:44.000000000 +0000
+++ linux-2.4.28-pre3/include/asm-s390/pgtable.h	2004-09-10 19:36:19.000000000 +0000
@@ -426,9 +426,12 @@ static inline pte_t mk_pte_phys(unsigned
 	__pte;                                                            \
 })
 
-#define arch_set_page_uptodate(__page)					  \
+#define SetPageUptodate(_page) \
 	do {								  \
-		asm volatile ("sske %0,%1" : : "d" (get_storage_key()),	  \
+		struct page *__page = (_page);				  \
+		if (!test_and_set_bit(PG_uptodate, &__page->flags))	  \
+			asm volatile ("sske %0,%1" 			  \
+			      : : "d" (get_storage_key()),		  \
 			      "a" (__pa((__page-mem_map) << PAGE_SHIFT)));\
 	} while (0)
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/include/asm-s390/processor.h linux-2.4.28-pre3/include/asm-s390/processor.h
--- linux-2.4.27/include/asm-s390/processor.h	2003-06-13 14:51:38.000000000 +0000
+++ linux-2.4.28-pre3/include/asm-s390/processor.h	2004-09-10 19:34:46.000000000 +0000
@@ -50,6 +50,8 @@ struct cpuinfo_S390
 
 extern void print_cpu_info(struct cpuinfo_S390 *);
 
+extern void show_trace(unsigned long* esp);
+
 /* Lazy FPU handling on uni-processor */
 extern struct task_struct *last_task_used_math;
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/include/asm-s390/qdio.h linux-2.4.28-pre3/include/asm-s390/qdio.h
--- linux-2.4.27/include/asm-s390/qdio.h	2003-08-25 11:44:44.000000000 +0000
+++ linux-2.4.28-pre3/include/asm-s390/qdio.h	2004-09-10 19:36:38.000000000 +0000
@@ -11,7 +11,7 @@
 #ifndef __QDIO_H__
 #define __QDIO_H__
 
-#define VERSION_QDIO_H "$Revision: 1.66 $"
+#define VERSION_QDIO_H "$Revision: 1.66.4.4 $"
 
 /* note, that most of the typedef's are from ingo. */
 
@@ -42,11 +42,18 @@
 #define QDIO_MAX_ELEMENTS_PER_BUFFER 16
 #define SBAL_SIZE 256
 
-#define IQDIO_FILL_LEVEL_TO_POLL (QDIO_MAX_BUFFERS_PER_Q*4/3)
+/* unfortunately this can't be (QDIO_MAX_BUFFERS_PER_Q*4/3) or so -- as
+ * we never know, whether we'll get initiative again, e.g. to give the
+ * transmit skb's back to the stack, however the stack may be waiting for
+ * them... therefore we define 4 as threshold to start polling (which
+ * will stop as soon as the asynchronous queue catches up)
+ * btw, this only applies to the asynchronous HiperSockets queue */
+#define IQDIO_FILL_LEVEL_TO_POLL 4
 
 #define TIQDIO_THININT_ISC 3
 #define TIQDIO_DELAY_TARGET 0
-#define QDIO_BUSY_BIT_PATIENCE 2000 /* in microsecs */
+#define QDIO_BUSY_BIT_PATIENCE 100 /* in microsecs */
+#define QDIO_BUSY_BIT_GIVE_UP 10000000 /* 10 seconds */
 #define IQDIO_GLOBAL_LAPS 2 /* GLOBAL_LAPS are not used as we */
 #define IQDIO_GLOBAL_LAPS_INT 1 /* dont global summary */
 #define IQDIO_LOCAL_LAPS 4
@@ -612,6 +619,8 @@ typedef struct _slsb {
 typedef struct qdio_q_t {
 	volatile slsb_t slsb;
 
+	char unused[QDIO_MAX_BUFFERS_PER_Q];
+
 	__u32 * volatile dev_st_chg_ind;
 
 	int is_input_q;
@@ -697,7 +706,9 @@ typedef struct qdio_q_t {
 		int last_transfer_index; */
 
 		__u64 last_transfer_time;
+		__u64 busy_start;
 	} timing;
+	atomic_t busy_siga_counter;
         unsigned int queue_type;
 } __attribute__ ((aligned(256))) qdio_q_t;
 
@@ -713,7 +724,7 @@ typedef struct qdio_irq_t {
 	unsigned int sync_done_on_outb_pcis;
 
 	unsigned int state;
-	spinlock_t setting_up_lock;
+	struct semaphore setting_up_lock;
 
 	unsigned int no_input_qs;
 	unsigned int no_output_qs;
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/include/asm-s390/sigp.h linux-2.4.28-pre3/include/asm-s390/sigp.h
--- linux-2.4.27/include/asm-s390/sigp.h	2002-11-28 23:53:15.000000000 +0000
+++ linux-2.4.28-pre3/include/asm-s390/sigp.h	2004-09-10 19:34:58.000000000 +0000
@@ -106,7 +106,7 @@ signal_processor_p(__u32 parameter,__u16
  * Signal processor with parameter and return status
  */
 extern __inline__ sigp_ccode
-signal_processor_ps(__u32 *statusptr, __u32 parameter,
+signal_processor_ps(unsigned long *statusptr, __u32 parameter,
 		    __u16 cpu_addr, sigp_order_code order_code)
 {
 	sigp_ccode ccode;
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/include/asm-s390/smp.h linux-2.4.28-pre3/include/asm-s390/smp.h
--- linux-2.4.27/include/asm-s390/smp.h	2002-11-28 23:53:15.000000000 +0000
+++ linux-2.4.28-pre3/include/asm-s390/smp.h	2004-09-10 19:34:54.000000000 +0000
@@ -26,6 +26,9 @@ typedef struct
 	__u16      cpu;
 } sigp_info;
 
+extern int smp_call_function_on(void (*func) (void *info), void *info,
+				int nonatomic, int wait, int cpu);
+
 extern unsigned long cpu_online_map;
 
 #define NO_PROC_ID		0xFF		/* No processor magic marker */
@@ -46,23 +49,28 @@ extern unsigned long cpu_online_map;
 
 extern __inline__ int cpu_logical_map(int cpu)
 {
-        return cpu;
+	return cpu;
 }
 
 extern __inline__ int cpu_number_map(int cpu)
 {
-        return cpu;
+	return cpu;
 }
 
 extern __inline__ __u16 hard_smp_processor_id(void)
 {
-        __u16 cpu_address;
+	__u16 cpu_address;
  
-        __asm__ ("stap %0\n" : "=m" (cpu_address));
-        return cpu_address;
+	__asm__ ("stap %0\n" : "=m" (cpu_address));
+	return cpu_address;
 }
 
 #define cpu_logical_map(cpu) (cpu)
 
 #endif
+
+#ifndef CONFIG_SMP
+#define smp_call_function_on(func,info,nonatomic,wait,cpu)      ({ 0; })
+#endif
+
 #endif
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/include/asm-s390x/kmap_types.h linux-2.4.28-pre3/include/asm-s390x/kmap_types.h
--- linux-2.4.27/include/asm-s390x/kmap_types.h	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.28-pre3/include/asm-s390x/kmap_types.h	2004-09-10 19:32:00.000000000 +0000
@@ -0,0 +1,16 @@
+#ifndef _ASM_KMAP_TYPES_H
+#define _ASM_KMAP_TYPES_H
+
+enum km_type {
+	KM_BOUNCE_READ,
+	KM_SKB_SUNRPC_DATA,
+	KM_SKB_DATA_SOFTIRQ,
+	KM_USER0,
+	KM_USER1,
+	KM_BH_IRQ,
+	KM_SOFTIRQ0,
+	KM_SOFTIRQ1,
+	KM_TYPE_NR
+};
+
+#endif
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/include/asm-s390x/lowcore.h linux-2.4.28-pre3/include/asm-s390x/lowcore.h
--- linux-2.4.27/include/asm-s390x/lowcore.h	2002-11-28 23:53:15.000000000 +0000
+++ linux-2.4.28-pre3/include/asm-s390x/lowcore.h	2004-09-10 19:36:12.000000000 +0000
@@ -48,6 +48,7 @@
 #define __LC_IPLDEV                     0xDB8
 
 #define __LC_JIFFY_TIMER		0xDC0
+#define __LC_INT_CLOCK			0xDC8
 
 #define __LC_PANIC_MAGIC                0xE00
 
@@ -164,8 +165,9 @@ struct _lowcore
 
         /* SMP info area: defined by DJB */
         __u64        jiffy_timer;              /* 0xdc0 */
-	__u64        ext_call_fast;            /* 0xdc8 */
-        __u8         pad12[0xe00-0xdd0];       /* 0xdd0 */
+        __u64        int_clock;                /* 0xdc8 */
+	__u64        ext_call_fast;            /* 0xdd0 */
+        __u8         pad12[0xe00-0xdd8];       /* 0xdd8 */
 
         /* 0xe00 is used as indicator for dump tools */
         /* whether the kernel died with panic() or not */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/include/asm-s390x/pgtable.h linux-2.4.28-pre3/include/asm-s390x/pgtable.h
--- linux-2.4.27/include/asm-s390x/pgtable.h	2003-08-25 11:44:44.000000000 +0000
+++ linux-2.4.28-pre3/include/asm-s390x/pgtable.h	2004-09-10 19:34:20.000000000 +0000
@@ -484,9 +484,11 @@ extern inline pte_t mk_pte_phys(unsigned
 	__pte;                                                            \
 })
 
-#define arch_set_page_uptodate(__page)					  \
+#define SetPageUptodate(_page) \
 	do {								  \
-		asm volatile ("sske %0,%1" : : "d" (0),			  \
+		struct page *__page = (_page);				  \
+		if (!test_and_set_bit(PG_uptodate, &__page->flags))	  \
+			asm volatile ("sske %0,%1" : : "d" (0),		  \
 			      "a" (__pa((__page-mem_map) << PAGE_SHIFT)));\
 	} while (0)
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/include/asm-s390x/processor.h linux-2.4.28-pre3/include/asm-s390x/processor.h
--- linux-2.4.27/include/asm-s390x/processor.h	2003-06-13 14:51:38.000000000 +0000
+++ linux-2.4.28-pre3/include/asm-s390x/processor.h	2004-09-10 19:36:29.000000000 +0000
@@ -52,6 +52,8 @@ struct cpuinfo_S390
 
 extern void print_cpu_info(struct cpuinfo_S390 *);
 
+extern void show_trace(unsigned long* esp);
+
 /* Lazy FPU handling on uni-processor */
 extern struct task_struct *last_task_used_math;
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/include/asm-s390x/qdio.h linux-2.4.28-pre3/include/asm-s390x/qdio.h
--- linux-2.4.27/include/asm-s390x/qdio.h	2003-08-25 11:44:44.000000000 +0000
+++ linux-2.4.28-pre3/include/asm-s390x/qdio.h	2004-09-10 19:34:58.000000000 +0000
@@ -11,7 +11,7 @@
 #ifndef __QDIO_H__
 #define __QDIO_H__
 
-#define VERSION_QDIO_H "$Revision: 1.57 $"
+#define VERSION_QDIO_H "$Revision: 1.57.4.4 $"
 
 /* note, that most of the typedef's are from ingo. */
 
@@ -42,11 +42,18 @@
 #define QDIO_MAX_ELEMENTS_PER_BUFFER 16
 #define SBAL_SIZE 256
 
-#define IQDIO_FILL_LEVEL_TO_POLL (QDIO_MAX_BUFFERS_PER_Q*4/3)
+/* unfortunately this can't be (QDIO_MAX_BUFFERS_PER_Q*4/3) or so -- as
+ * we never know, whether we'll get initiative again, e.g. to give the
+ * transmit skb's back to the stack, however the stack may be waiting for
+ * them... therefore we define 4 as threshold to start polling (which
+ * will stop as soon as the asynchronous queue catches up)
+ * btw, this only applies to the asynchronous HiperSockets queue */
+#define IQDIO_FILL_LEVEL_TO_POLL 4
 
 #define TIQDIO_THININT_ISC 3
 #define TIQDIO_DELAY_TARGET 0
-#define QDIO_BUSY_BIT_PATIENCE 2000 /* in microsecs */
+#define QDIO_BUSY_BIT_PATIENCE 100 /* in microsecs */
+#define QDIO_BUSY_BIT_GIVE_UP 10000000 /* 10 seconds */
 #define IQDIO_GLOBAL_LAPS 2 /* GLOBAL_LAPS are not used as we */
 #define IQDIO_GLOBAL_LAPS_INT 1 /* dont global summary */
 #define IQDIO_LOCAL_LAPS 4
@@ -612,6 +619,8 @@ typedef struct _slsb {
 typedef struct qdio_q_t {
 	volatile slsb_t slsb;
 
+	char unused[QDIO_MAX_BUFFERS_PER_Q];
+
 	__u32 * volatile dev_st_chg_ind;
 
 	int is_input_q;
@@ -697,7 +706,9 @@ typedef struct qdio_q_t {
 		int last_transfer_index; */
 
 		__u64 last_transfer_time;
+		__u64 busy_start;
 	} timing;
+	atomic_t busy_siga_counter;
         unsigned int queue_type;
 } __attribute__ ((aligned(256))) qdio_q_t;
 
@@ -713,7 +724,7 @@ typedef struct qdio_irq_t {
 	unsigned int sync_done_on_outb_pcis;
 
 	unsigned int state;
-	spinlock_t setting_up_lock;
+	struct semaphore setting_up_lock;
 
 	unsigned int no_input_qs;
 	unsigned int no_output_qs;
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/include/asm-s390x/siginfo.h linux-2.4.28-pre3/include/asm-s390x/siginfo.h
--- linux-2.4.27/include/asm-s390x/siginfo.h	2002-08-03 00:39:45.000000000 +0000
+++ linux-2.4.28-pre3/include/asm-s390x/siginfo.h	2004-09-10 19:36:45.000000000 +0000
@@ -19,7 +19,7 @@ typedef union sigval {
 } sigval_t;
 
 #define SI_MAX_SIZE	128
-#define SI_PAD_SIZE	((SI_MAX_SIZE/sizeof(int)) - 3)
+#define SI_PAD_SIZE	((SI_MAX_SIZE/sizeof(int)) - 4)
 
 typedef struct siginfo {
 	int si_signo;
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/include/asm-s390x/sigp.h linux-2.4.28-pre3/include/asm-s390x/sigp.h
--- linux-2.4.27/include/asm-s390x/sigp.h	2002-11-28 23:53:15.000000000 +0000
+++ linux-2.4.28-pre3/include/asm-s390x/sigp.h	2004-09-10 19:34:24.000000000 +0000
@@ -107,7 +107,7 @@ signal_processor_p(__u64 parameter,__u16
  * Signal processor with parameter and return status
  */
 extern __inline__ sigp_ccode
-signal_processor_ps(__u32 *statusptr, __u64 parameter,
+signal_processor_ps(unsigned long *statusptr, __u64 parameter,
 		    __u16 cpu_addr, sigp_order_code order_code)
 {
 	sigp_ccode ccode;
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/include/asm-s390x/smp.h linux-2.4.28-pre3/include/asm-s390x/smp.h
--- linux-2.4.27/include/asm-s390x/smp.h	2002-11-28 23:53:15.000000000 +0000
+++ linux-2.4.28-pre3/include/asm-s390x/smp.h	2004-09-10 19:34:49.000000000 +0000
@@ -26,6 +26,9 @@ typedef struct
 	__u16      cpu;
 } sigp_info;
 
+extern int smp_call_function_on(void (*func) (void *info), void *info,
+				int nonatomic, int wait, int cpu);
+
 extern unsigned long cpu_online_map;
 
 #define NO_PROC_ID		0xFF		/* No processor magic marker */
@@ -65,4 +68,9 @@ extern __inline__ __u16 hard_smp_process
 #define cpu_logical_map(cpu) (cpu)
 
 #endif
+
+#ifndef CONFIG_SMP
+#define smp_call_function_on(func,info,nonatomic,wait,cpu)      ({ 0; })
+#endif
+
 #endif
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/include/asm-sparc/sigcontext.h linux-2.4.28-pre3/include/asm-sparc/sigcontext.h
--- linux-2.4.27/include/asm-sparc/sigcontext.h	1999-09-08 18:14:32.000000000 +0000
+++ linux-2.4.28-pre3/include/asm-sparc/sigcontext.h	2004-09-10 19:33:19.000000000 +0000
@@ -57,20 +57,6 @@ typedef struct {
 	} si_fpqueue [16];
 } __siginfo_fpu_t;
 
-#ifdef __KERNEL__
-
-/* This magic should be in g_upper[0] for all upper parts
-   to be valid.
-   This is generated by sparc64 only, but for 32bit processes,
-   so we define it here as well.  */
-#define SIGINFO_EXTRA_V8PLUS_MAGIC      0x130e269
-typedef struct {
-	unsigned   int g_upper[8];
-	unsigned   int o_upper[8];
-} siginfo_extra_v8plus_t;
-
-#endif
-
 #endif /* !(__ASSEMBLY__) */
 
 #endif /* !(__SPARC_SIGCONTEXT_H) */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/include/asm-sparc64/asi.h linux-2.4.28-pre3/include/asm-sparc64/asi.h
--- linux-2.4.27/include/asm-sparc64/asi.h	2003-11-28 18:26:21.000000000 +0000
+++ linux-2.4.28-pre3/include/asm-sparc64/asi.h	2004-09-10 19:33:16.000000000 +0000
@@ -8,125 +8,138 @@
  */
 
 /* V9 Architecture mandary ASIs. */
-#define ASI_N			0x04 /* Nucleus					*/
-#define ASI_NL			0x0c /* Nucleus, little endian			*/
-#define ASI_AIUP		0x10 /* Primary, user				*/
-#define ASI_AIUS		0x11 /* Secondary, user				*/
-#define ASI_AIUPL		0x18 /* Primary, user, little endian		*/
-#define ASI_AIUSL		0x19 /* Secondary, user, little endian		*/
-#define ASI_P			0x80 /* Primary, implicit			*/
-#define ASI_S			0x81 /* Secondary, implicit			*/
-#define ASI_PNF			0x82 /* Primary, no fault			*/
-#define ASI_SNF			0x83 /* Secondary, no fault			*/
-#define ASI_PL			0x88 /* Primary, implicit, little endian	*/
-#define ASI_SL			0x89 /* Secondary, implicit, little endian	*/
-#define ASI_PNFL		0x8a /* Primary, no fault, little endian	*/
-#define ASI_SNFL		0x8b /* Secondary, no fault, little endian	*/
+#define ASI_N			0x04 /* Nucleus				*/
+#define ASI_NL			0x0c /* Nucleus, little endian		*/
+#define ASI_AIUP		0x10 /* Primary, user			*/
+#define ASI_AIUS		0x11 /* Secondary, user			*/
+#define ASI_AIUPL		0x18 /* Primary, user, little endian	*/
+#define ASI_AIUSL		0x19 /* Secondary, user, little endian	*/
+#define ASI_P			0x80 /* Primary, implicit		*/
+#define ASI_S			0x81 /* Secondary, implicit		*/
+#define ASI_PNF			0x82 /* Primary, no fault		*/
+#define ASI_SNF			0x83 /* Secondary, no fault		*/
+#define ASI_PL			0x88 /* Primary, implicit, l-endian	*/
+#define ASI_SL			0x89 /* Secondary, implicit, l-endian	*/
+#define ASI_PNFL		0x8a /* Primary, no fault, l-endian	*/
+#define ASI_SNFL		0x8b /* Secondary, no fault, l-endian	*/
 
 /* SpitFire and later extended ASIs.  The "(III)" marker designates
- * UltraSparc-III specific ASIs.
+ * UltraSparc-III and later specific ASIs.  The "(CMT)" marker designates
+ * Chip Multi Threading specific ASIs.
  */
-#define ASI_PHYS_USE_EC		0x14 /* PADDR, E-cachable			*/
-#define ASI_PHYS_BYPASS_EC_E	0x15 /* PADDR, E-bit				*/
-#define ASI_PHYS_USE_EC_L	0x1c /* PADDR, E-cachable, little endian	*/
-#define ASI_PHYS_BYPASS_EC_E_L	0x1d /* PADDR, E-bit, little endian		*/
-#define ASI_NUCLEUS_QUAD_LDD	0x24 /* Cachable, qword load			*/
-#define ASI_NUCLEUS_QUAD_LDD_L	0x2c /* Cachable, qword load, little endian 	*/
-#define ASI_PCACHE_DATA_STATUS	0x30 /* (III) PCache data status RAM diag	*/
-#define ASI_PCACHE_DATA		0x31 /* (III) PCache data RAM diag		*/
-#define ASI_PCACHE_TAG		0x32 /* (III) PCache tag RAM diag		*/
-#define ASI_PCACHE_SNOOP_TAG	0x33 /* (III) PCache snoop tag RAM diag		*/
-#define ASI_QUAD_LDD_PHYS	0x34 /* (III+) PADDR, qword load		*/
-#define ASI_WCACHE_VALID_BITS	0x38 /* (III) WCache Valid Bits diag		*/
-#define ASI_WCACHE_DATA		0x39 /* (III) WCache data RAM diag		*/
-#define ASI_WCACHE_TAG		0x3a /* (III) WCache tag RAM diag		*/
-#define ASI_WCACHE_SNOOP_TAG	0x3b /* (III) WCache snoop tag RAM diag		*/
-#define ASI_QUAD_LDD_PHYS_L	0x3c /* (III+) PADDR, qword load, little endian	*/
-#define ASI_SRAM_FAST_INIT	0x40 /* (III+) Fast SRAM init			*/
-#define ASI_DCACHE_INVALIDATE	0x42 /* (III) DCache Invalidate diag		*/
-#define ASI_DCACHE_UTAG		0x43 /* (III) DCache uTag diag			*/
-#define ASI_DCACHE_SNOOP_TAG	0x44 /* (III) DCache snoop tag RAM diag		*/
-#define ASI_LSU_CONTROL		0x45 /* Load-store control unit			*/
-#define ASI_DCU_CONTROL_REG	0x45 /* (III) DCache Unit Control Register	*/
-#define ASI_DCACHE_DATA		0x46 /* Data cache data-ram diag access		*/
-#define ASI_DCACHE_TAG		0x47 /* Data cache tag/valid ram diag access	*/
-#define ASI_INTR_DISPATCH_STAT	0x48 /* IRQ vector dispatch status		*/
-#define ASI_INTR_RECEIVE	0x49 /* IRQ vector receive status		*/
-#define ASI_UPA_CONFIG		0x4a /* UPA config space			*/
-#define ASI_JBUS_CONFIG		0x4a /* (IIIi) JBUS Config Register		*/
-#define ASI_SAFARI_CONFIG	0x4a /* (III) Safari Config Register		*/
-#define ASI_SAFARI_ADDRESS	0x4a /* (III) Safari Address Register		*/
-#define ASI_ESTATE_ERROR_EN	0x4b /* E-cache error enable space		*/
-#define ASI_AFSR		0x4c /* Async fault status register		*/
-#define ASI_AFAR		0x4d /* Async fault address register		*/
-#define ASI_EC_TAG_DATA		0x4e /* E-cache tag/valid ram diag access	*/
-#define ASI_IMMU		0x50 /* Insn-MMU main register space		*/
-#define ASI_IMMU_TSB_8KB_PTR	0x51 /* Insn-MMU 8KB TSB pointer register	*/
-#define ASI_IMMU_TSB_64KB_PTR	0x52 /* Insn-MMU 64KB TSB pointer register	*/
-#define ASI_ITLB_DATA_IN	0x54 /* Insn-MMU TLB data in register		*/
-#define ASI_ITLB_DATA_ACCESS	0x55 /* Insn-MMU TLB data access register	*/
-#define ASI_ITLB_TAG_READ	0x56 /* Insn-MMU TLB tag read register		*/
-#define ASI_IMMU_DEMAP		0x57 /* Insn-MMU TLB demap			*/
-#define ASI_DMMU		0x58 /* Data-MMU main register space		*/
-#define ASI_DMMU_TSB_8KB_PTR	0x59 /* Data-MMU 8KB TSB pointer register	*/
-#define ASI_DMMU_TSB_64KB_PTR	0x5a /* Data-MMU 16KB TSB pointer register	*/
-#define ASI_DMMU_TSB_DIRECT_PTR	0x5b /* Data-MMU TSB direct pointer register	*/
-#define ASI_DTLB_DATA_IN	0x5c /* Data-MMU TLB data in register		*/
-#define ASI_DTLB_DATA_ACCESS	0x5d /* Data-MMU TLB data access register	*/
-#define ASI_DTLB_TAG_READ	0x5e /* Data-MMU TLB tag read register		*/
-#define ASI_DMMU_DEMAP		0x5f /* Data-MMU TLB demap			*/
-#define ASI_IIU_INST_TRAP	0x60 /* (III) Instruction Breakpoint register	*/
-#define ASI_IC_INSTR		0x66 /* Insn cache instrucion ram diag access	*/
-#define ASI_IC_TAG		0x67 /* Insn cache tag/valid ram diag access	*/
-#define ASI_IC_STAG		0x68 /* (III) Insn cache snoop tag ram diag	*/
-#define ASI_IC_PRE_DECODE	0x6e /* Insn cache pre-decode ram diag access	*/
-#define ASI_IC_NEXT_FIELD	0x6f /* Insn cache next-field ram diag access	*/
-#define ASI_BRPRED_ARRAY	0x6f /* (III) Branch Prediction RAM diag	*/
-#define ASI_BLK_AIUP		0x70 /* Primary, user, block load/store		*/
-#define ASI_BLK_AIUS		0x71 /* Secondary, user, block load/store	*/
-#define ASI_MCU_CTRL_REG	0x72 /* (III) Memory controller registers	*/
-#define ASI_EC_DATA		0x74 /* (III) E-cache data staging register	*/
-#define ASI_EC_CTRL		0x75 /* (III) E-cache control register		*/
-#define ASI_EC_W		0x76 /* E-cache diag write access		*/
-#define ASI_UDB_ERROR_W		0x77 /* External UDB error registers write	*/
-#define ASI_UDB_CONTROL_W	0x77 /* External UDB control registers write	*/
-#define ASI_INTR_W		0x77 /* IRQ vector dispatch write		*/
-#define ASI_INTR_DATAN_W	0x77 /* (III) Outgoing irq vector data reg N	*/
-#define ASI_INTR_DISPATCH_W	0x77 /* (III) Interrupt vector dispatch		*/
-#define ASI_BLK_AIUPL		0x78 /* Primary, user, little, blk ld/st	*/
-#define ASI_BLK_AIUSL		0x79 /* Secondary, user, little, blk ld/st	*/
-#define ASI_EC_R		0x7e /* E-cache diag read access		*/
-#define ASI_UDBH_ERROR_R	0x7f /* External UDB error registers read hi	*/
-#define ASI_UDBL_ERROR_R	0x7f /* External UDB error registers read low	*/
-#define ASI_UDBH_CONTROL_R	0x7f /* External UDB control registers read hi	*/
-#define ASI_UDBL_CONTROL_R	0x7f /* External UDB control registers read low	*/
-#define ASI_INTR_R		0x7f /* IRQ vector dispatch read		*/
-#define ASI_INTR_DATAN_R	0x7f /* (III) Incoming irq vector data reg N	*/
-#define ASI_PST8_P		0xc0 /* Primary, 8 8-bit, partial		*/
-#define ASI_PST8_S		0xc1 /* Secondary, 8 8-bit, partial		*/
-#define ASI_PST16_P		0xc2 /* Primary, 4 16-bit, partial		*/
-#define ASI_PST16_S		0xc3 /* Seconary, 4 16-bit, partial		*/
-#define ASI_PST32_P		0xc4 /* Primary, 2 32-bit, partial		*/
-#define ASI_PST32_S		0xc5 /* Secondary, 2 32-bit, partial		*/
-#define ASI_PST8_PL		0xc8 /* Primary, 8 8-bit, partial, little	*/
-#define ASI_PST8_SL		0xc9 /* Secondary, 8 8-bit, partial, little	*/
-#define ASI_PST16_PL		0xca /* Primary, 4 16-bit, partial, little	*/
-#define ASI_PST16_SL		0xcb /* Seconary, 4 16-bit, partial, little	*/
-#define ASI_PST32_PL		0xcc /* Primary, 2 32-bit, partial, little	*/
-#define ASI_PST32_SL		0xcd /* Secondary, 2 32-bit, partial, little	*/
-#define ASI_FL8_P		0xd0 /* Primary, 1 8-bit, fpu ld/st		*/
-#define ASI_FL8_S		0xd1 /* Secondary, 1 8-bit, fpu ld/st		*/
-#define ASI_FL16_P		0xd2 /* Primary, 1 16-bit, fpu ld/st		*/
-#define ASI_FL16_S		0xd3 /* Secondary, 1 16-bit, fpu ld/st		*/
-#define ASI_FL8_PL		0xd8 /* Primary, 1 8-bit, fpu ld/st, little	*/
-#define ASI_FL8_SL		0xd9 /* Secondary, 1 8-bit, fpu ld/st, little	*/
-#define ASI_FL16_PL		0xda /* Primary, 1 16-bit, fpu ld/st, little	*/
-#define ASI_FL16_SL		0xdb /* Secondary, 1 16-bit, fpu ld/st, little	*/
-#define ASI_BLK_COMMIT_P	0xe0 /* Primary, blk store commit		*/
-#define ASI_BLK_COMMIT_S	0xe1 /* Secondary, blk store commit		*/
-#define ASI_BLK_P		0xf0 /* Primary, blk ld/st			*/
-#define ASI_BLK_S		0xf1 /* Secondary, blk ld/st			*/
-#define ASI_BLK_PL		0xf8 /* Primary, blk ld/st, little		*/
-#define ASI_BLK_SL		0xf9 /* Secondary, blk ld/st, little		*/
+#define ASI_PHYS_USE_EC		0x14 /* PADDR, E-cachable		*/
+#define ASI_PHYS_BYPASS_EC_E	0x15 /* PADDR, E-bit			*/
+#define ASI_PHYS_USE_EC_L	0x1c /* PADDR, E-cachable, little endian*/
+#define ASI_PHYS_BYPASS_EC_E_L	0x1d /* PADDR, E-bit, little endian	*/
+#define ASI_NUCLEUS_QUAD_LDD	0x24 /* Cachable, qword load		*/
+#define ASI_NUCLEUS_QUAD_LDD_L	0x2c /* Cachable, qword load, l-endian 	*/
+#define ASI_PCACHE_DATA_STATUS	0x30 /* (III) PCache data stat RAM diag	*/
+#define ASI_PCACHE_DATA		0x31 /* (III) PCache data RAM diag	*/
+#define ASI_PCACHE_TAG		0x32 /* (III) PCache tag RAM diag	*/
+#define ASI_PCACHE_SNOOP_TAG	0x33 /* (III) PCache snoop tag RAM diag	*/
+#define ASI_QUAD_LDD_PHYS	0x34 /* (III+) PADDR, qword load	*/
+#define ASI_WCACHE_VALID_BITS	0x38 /* (III) WCache Valid Bits diag	*/
+#define ASI_WCACHE_DATA		0x39 /* (III) WCache data RAM diag	*/
+#define ASI_WCACHE_TAG		0x3a /* (III) WCache tag RAM diag	*/
+#define ASI_WCACHE_SNOOP_TAG	0x3b /* (III) WCache snoop tag RAM diag	*/
+#define ASI_QUAD_LDD_PHYS_L	0x3c /* (III+) PADDR, qw-load, l-endian	*/
+#define ASI_SRAM_FAST_INIT	0x40 /* (III+) Fast SRAM init		*/
+#define ASI_CORE_AVAILABLE	0x41 /* (CMT) LP Available		*/
+#define ASI_CORE_ENABLE_STAT	0x41 /* (CMT) LP Enable Status		*/
+#define ASI_CORE_ENABLE		0x41 /* (CMT) LP Enable RW		*/
+#define ASI_XIR_STEERING	0x41 /* (CMT) XIR Steering RW		*/
+#define ASI_CORE_RUNNING_RW	0x41 /* (CMT) LP Running RW		*/
+#define ASI_CORE_RUNNING_W1S	0x41 /* (CMT) LP Running Write-One Set	*/
+#define ASI_CORE_RUNNING_W1C	0x41 /* (CMT) LP Running Write-One Clr	*/
+#define ASI_CORE_RUNNING_STAT	0x41 /* (CMT) LP Running Status		*/
+#define ASI_CMT_ERROR_STEERING	0x41 /* (CMT) Error Steering RW		*/
+#define ASI_DCACHE_INVALIDATE	0x42 /* (III) DCache Invalidate diag	*/
+#define ASI_DCACHE_UTAG		0x43 /* (III) DCache uTag diag		*/
+#define ASI_DCACHE_SNOOP_TAG	0x44 /* (III) DCache snoop tag RAM diag	*/
+#define ASI_LSU_CONTROL		0x45 /* Load-store control unit		*/
+#define ASI_DCU_CONTROL_REG	0x45 /* (III) DCache Unit Control reg	*/
+#define ASI_DCACHE_DATA		0x46 /* DCache data-ram diag access	*/
+#define ASI_DCACHE_TAG		0x47 /* Dcache tag/valid ram diag access*/
+#define ASI_INTR_DISPATCH_STAT	0x48 /* IRQ vector dispatch status	*/
+#define ASI_INTR_RECEIVE	0x49 /* IRQ vector receive status	*/
+#define ASI_UPA_CONFIG		0x4a /* UPA config space		*/
+#define ASI_JBUS_CONFIG		0x4a /* (IIIi) JBUS Config Register	*/
+#define ASI_SAFARI_CONFIG	0x4a /* (III) Safari Config Register	*/
+#define ASI_SAFARI_ADDRESS	0x4a /* (III) Safari Address Register	*/
+#define ASI_ESTATE_ERROR_EN	0x4b /* E-cache error enable space	*/
+#define ASI_AFSR		0x4c /* Async fault status register	*/
+#define ASI_AFAR		0x4d /* Async fault address register	*/
+#define ASI_EC_TAG_DATA		0x4e /* E-cache tag/valid ram diag acc	*/
+#define ASI_IMMU		0x50 /* Insn-MMU main register space	*/
+#define ASI_IMMU_TSB_8KB_PTR	0x51 /* Insn-MMU 8KB TSB pointer reg	*/
+#define ASI_IMMU_TSB_64KB_PTR	0x52 /* Insn-MMU 64KB TSB pointer reg	*/
+#define ASI_ITLB_DATA_IN	0x54 /* Insn-MMU TLB data in reg	*/
+#define ASI_ITLB_DATA_ACCESS	0x55 /* Insn-MMU TLB data access reg	*/
+#define ASI_ITLB_TAG_READ	0x56 /* Insn-MMU TLB tag read reg	*/
+#define ASI_IMMU_DEMAP		0x57 /* Insn-MMU TLB demap		*/
+#define ASI_DMMU		0x58 /* Data-MMU main register space	*/
+#define ASI_DMMU_TSB_8KB_PTR	0x59 /* Data-MMU 8KB TSB pointer reg	*/
+#define ASI_DMMU_TSB_64KB_PTR	0x5a /* Data-MMU 16KB TSB pointer reg	*/
+#define ASI_DMMU_TSB_DIRECT_PTR	0x5b /* Data-MMU TSB direct pointer reg	*/
+#define ASI_DTLB_DATA_IN	0x5c /* Data-MMU TLB data in reg	*/
+#define ASI_DTLB_DATA_ACCESS	0x5d /* Data-MMU TLB data access reg	*/
+#define ASI_DTLB_TAG_READ	0x5e /* Data-MMU TLB tag read reg	*/
+#define ASI_DMMU_DEMAP		0x5f /* Data-MMU TLB demap		*/
+#define ASI_IIU_INST_TRAP	0x60 /* (III) Instruction Breakpoint	*/
+#define ASI_INTR_ID		0x63 /* (CMT) Interrupt ID register	*/
+#define ASI_CORE_ID		0x63 /* (CMT) LP ID register		*/
+#define ASI_CESR_ID		0x63 /* (CMT) CESR ID register		*/
+#define ASI_IC_INSTR		0x66 /* Insn cache instrucion ram diag	*/
+#define ASI_IC_TAG		0x67 /* Insn cache tag/valid ram diag 	*/
+#define ASI_IC_STAG		0x68 /* (III) Insn cache snoop tag ram	*/
+#define ASI_IC_PRE_DECODE	0x6e /* Insn cache pre-decode ram diag	*/
+#define ASI_IC_NEXT_FIELD	0x6f /* Insn cache next-field ram diag	*/
+#define ASI_BRPRED_ARRAY	0x6f /* (III) Branch Prediction RAM diag*/
+#define ASI_BLK_AIUP		0x70 /* Primary, user, block load/store	*/
+#define ASI_BLK_AIUS		0x71 /* Secondary, user, block ld/st	*/
+#define ASI_MCU_CTRL_REG	0x72 /* (III) Memory controller regs	*/
+#define ASI_EC_DATA		0x74 /* (III) E-cache data staging reg	*/
+#define ASI_EC_CTRL		0x75 /* (III) E-cache control reg	*/
+#define ASI_EC_W		0x76 /* E-cache diag write access	*/
+#define ASI_UDB_ERROR_W		0x77 /* External UDB error regs W	*/
+#define ASI_UDB_CONTROL_W	0x77 /* External UDB control regs W	*/
+#define ASI_INTR_W		0x77 /* IRQ vector dispatch write	*/
+#define ASI_INTR_DATAN_W	0x77 /* (III) Out irq vector data reg N	*/
+#define ASI_INTR_DISPATCH_W	0x77 /* (III) Interrupt vector dispatch	*/
+#define ASI_BLK_AIUPL		0x78 /* Primary, user, little, blk ld/st*/
+#define ASI_BLK_AIUSL		0x79 /* Secondary, user, little, blk ld/st*/
+#define ASI_EC_R		0x7e /* E-cache diag read access	*/
+#define ASI_UDBH_ERROR_R	0x7f /* External UDB error regs rd hi	*/
+#define ASI_UDBL_ERROR_R	0x7f /* External UDB error regs rd low	*/
+#define ASI_UDBH_CONTROL_R	0x7f /* External UDB control regs rd hi	*/
+#define ASI_UDBL_CONTROL_R	0x7f /* External UDB control regs rd low*/
+#define ASI_INTR_R		0x7f /* IRQ vector dispatch read	*/
+#define ASI_INTR_DATAN_R	0x7f /* (III) In irq vector data reg N	*/
+#define ASI_PST8_P		0xc0 /* Primary, 8 8-bit, partial	*/
+#define ASI_PST8_S		0xc1 /* Secondary, 8 8-bit, partial	*/
+#define ASI_PST16_P		0xc2 /* Primary, 4 16-bit, partial	*/
+#define ASI_PST16_S		0xc3 /* Secondary, 4 16-bit, partial	*/
+#define ASI_PST32_P		0xc4 /* Primary, 2 32-bit, partial	*/
+#define ASI_PST32_S		0xc5 /* Secondary, 2 32-bit, partial	*/
+#define ASI_PST8_PL		0xc8 /* Primary, 8 8-bit, partial, L	*/
+#define ASI_PST8_SL		0xc9 /* Secondary, 8 8-bit, partial, L	*/
+#define ASI_PST16_PL		0xca /* Primary, 4 16-bit, partial, L	*/
+#define ASI_PST16_SL		0xcb /* Secondary, 4 16-bit, partial, L	*/
+#define ASI_PST32_PL		0xcc /* Primary, 2 32-bit, partial, L	*/
+#define ASI_PST32_SL		0xcd /* Secondary, 2 32-bit, partial, L	*/
+#define ASI_FL8_P		0xd0 /* Primary, 1 8-bit, fpu ld/st	*/
+#define ASI_FL8_S		0xd1 /* Secondary, 1 8-bit, fpu ld/st	*/
+#define ASI_FL16_P		0xd2 /* Primary, 1 16-bit, fpu ld/st	*/
+#define ASI_FL16_S		0xd3 /* Secondary, 1 16-bit, fpu ld/st	*/
+#define ASI_FL8_PL		0xd8 /* Primary, 1 8-bit, fpu ld/st, L	*/
+#define ASI_FL8_SL		0xd9 /* Secondary, 1 8-bit, fpu ld/st, L*/
+#define ASI_FL16_PL		0xda /* Primary, 1 16-bit, fpu ld/st, L	*/
+#define ASI_FL16_SL		0xdb /* Secondary, 1 16-bit, fpu ld/st,L*/
+#define ASI_BLK_COMMIT_P	0xe0 /* Primary, blk store commit	*/
+#define ASI_BLK_COMMIT_S	0xe1 /* Secondary, blk store commit	*/
+#define ASI_BLK_P		0xf0 /* Primary, blk ld/st		*/
+#define ASI_BLK_S		0xf1 /* Secondary, blk ld/st		*/
+#define ASI_BLK_PL		0xf8 /* Primary, blk ld/st, little	*/
+#define ASI_BLK_SL		0xf9 /* Secondary, blk ld/st, little	*/
 
 #endif /* _SPARC64_ASI_H */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/include/asm-sparc64/cmt.h linux-2.4.28-pre3/include/asm-sparc64/cmt.h
--- linux-2.4.27/include/asm-sparc64/cmt.h	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.28-pre3/include/asm-sparc64/cmt.h	2004-09-10 19:36:46.000000000 +0000
@@ -0,0 +1,59 @@
+#ifndef _SPARC64_CMT_H
+#define _SPARC64_CMT_H
+
+/* cmt.h: Chip Multi-Threading register definitions
+ *
+ * Copyright (C) 2004 David S. Miller (davem@redhat.com)
+ */
+
+/* ASI_CORE_ID - private */
+#define LP_ID		0x0000000000000010UL
+#define  LP_ID_MAX	0x00000000003f0000UL
+#define  LP_ID_ID	0x000000000000003fUL
+
+/* ASI_INTR_ID - private */
+#define LP_INTR_ID	0x0000000000000000UL
+#define  LP_INTR_ID_ID	0x00000000000003ffUL
+
+/* ASI_CESR_ID - private */
+#define CESR_ID		0x0000000000000040UL
+#define  CESR_ID_ID	0x00000000000000ffUL
+
+/* ASI_CORE_AVAILABLE - shared */
+#define LP_AVAIL	0x0000000000000000UL
+#define  LP_AVAIL_1	0x0000000000000002UL
+#define  LP_AVAIL_0	0x0000000000000001UL
+
+/* ASI_CORE_ENABLE_STATUS - shared */
+#define LP_ENAB_STAT	0x0000000000000010UL
+#define  LP_ENAB_STAT_1	0x0000000000000002UL
+#define  LP_ENAB_STAT_0	0x0000000000000001UL
+
+/* ASI_CORE_ENABLE - shared */
+#define LP_ENAB		0x0000000000000020UL
+#define  LP_ENAB_1	0x0000000000000002UL
+#define  LP_ENAB_0	0x0000000000000001UL
+
+/* ASI_CORE_RUNNING - shared */
+#define LP_RUNNING_RW	0x0000000000000050UL
+#define LP_RUNNING_W1S	0x0000000000000060UL
+#define LP_RUNNING_W1C	0x0000000000000068UL
+#define  LP_RUNNING_1	0x0000000000000002UL
+#define  LP_RUNNING_0	0x0000000000000001UL
+
+/* ASI_CORE_RUNNING_STAT - shared */
+#define LP_RUN_STAT	0x0000000000000058UL
+#define  LP_RUN_STAT_1	0x0000000000000002UL
+#define  LP_RUN_STAT_0	0x0000000000000001UL
+
+/* ASI_XIR_STEERING - shared */
+#define LP_XIR_STEER	0x0000000000000030UL
+#define  LP_XIR_STEER_1	0x0000000000000002UL
+#define  LP_XIR_STEER_0	0x0000000000000001UL
+
+/* ASI_CMT_ERROR_STEERING - shared */
+#define CMT_ER_STEER	0x0000000000000040UL
+#define  CMT_ER_STEER_1	0x0000000000000002UL
+#define  CMT_ER_STEER_0	0x0000000000000001UL
+
+#endif /* _SPARC64_CMT_H */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/include/asm-sparc64/page.h linux-2.4.28-pre3/include/asm-sparc64/page.h
--- linux-2.4.27/include/asm-sparc64/page.h	2004-08-07 23:26:06.000000000 +0000
+++ linux-2.4.28-pre3/include/asm-sparc64/page.h	2004-09-10 19:34:22.000000000 +0000
@@ -36,7 +36,7 @@ extern void do_BUG(const char *file, int
 extern void _clear_page(void *page);
 #define clear_page(X)	_clear_page((void *)(X))
 extern void clear_user_page(void *page, unsigned long vaddr);
-#define copy_page(X,Y)	__memcpy((void *)(X), (void *)(Y), PAGE_SIZE)
+#define copy_page(X,Y)	memcpy((void *)(X), (void *)(Y), PAGE_SIZE)
 extern void copy_user_page(void *to, void *from, unsigned long vaddr);
 
 /* GROSS, defining this makes gcc pass these types as aggregates,
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/include/asm-sparc64/pbm.h linux-2.4.28-pre3/include/asm-sparc64/pbm.h
--- linux-2.4.27/include/asm-sparc64/pbm.h	2003-11-28 18:26:21.000000000 +0000
+++ linux-2.4.28-pre3/include/asm-sparc64/pbm.h	2004-09-10 19:37:30.000000000 +0000
@@ -70,6 +70,13 @@ struct pci_iommu {
 	 */
 	u32		lowest_consistent_map;
 
+	/* In order to deal with some buggy third-party PCI bridges that
+	 * do wrong prefetching, we never mark valid mappings as invalid.
+	 * Instead we point them at this dummy page.
+	 */
+	unsigned long	dummy_page;
+	unsigned long	dummy_page_pa;
+
 	/* If PBM_NCLUSTERS is ever decreased to 4 or lower,
 	 * or if largest supported page_table_sz * 8K goes above
 	 * 2GB, you must increase the size of the type of
@@ -93,6 +100,8 @@ struct pci_iommu {
 	u32 dma_addr_mask;
 };
 
+extern void pci_iommu_table_init(struct pci_iommu *, int);
+
 /* This describes a PCI bus module's streaming buffer. */
 struct pci_strbuf {
 	int		strbuf_enabled;		/* Present and using it? */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/include/asm-sparc64/pgtable.h linux-2.4.28-pre3/include/asm-sparc64/pgtable.h
--- linux-2.4.27/include/asm-sparc64/pgtable.h	2004-08-07 23:26:06.000000000 +0000
+++ linux-2.4.28-pre3/include/asm-sparc64/pgtable.h	2004-09-10 19:32:07.000000000 +0000
@@ -101,32 +101,36 @@
 #endif /* !(__ASSEMBLY__) */
 
 /* Spitfire/Cheetah TTE bits. */
-#define _PAGE_VALID	0x8000000000000000	/* Valid TTE                          */
-#define _PAGE_R		0x8000000000000000	/* Used to keep ref bit up to date    */
-#define _PAGE_SZ4MB	0x6000000000000000	/* 4MB Page                           */
-#define _PAGE_SZ512K	0x4000000000000000	/* 512K Page                          */
-#define _PAGE_SZ64K	0x2000000000000000	/* 64K Page                           */
-#define _PAGE_SZ8K	0x0000000000000000	/* 8K Page                            */
-#define _PAGE_NFO	0x1000000000000000	/* No Fault Only                      */
-#define _PAGE_IE	0x0800000000000000	/* Invert Endianness                  */
-#define _PAGE_SN	0x0000800000000000	/* (Cheetah) Snoop                    */
-#define _PAGE_PADDR_SF	0x000001FFFFFFE000	/* (Spitfire) Phys Address [40:13]    */
-#define _PAGE_PADDR	0x000007FFFFFFE000	/* (Cheetah) Phys Address [42:13]     */
-#define _PAGE_SOFT	0x0000000000001F80	/* Software bits                      */
-#define _PAGE_L		0x0000000000000040	/* Locked TTE                         */
-#define _PAGE_CP	0x0000000000000020	/* Cacheable in Physical Cache        */
-#define _PAGE_CV	0x0000000000000010	/* Cacheable in Virtual Cache         */
-#define _PAGE_E		0x0000000000000008	/* side-Effect                        */
-#define _PAGE_P		0x0000000000000004	/* Privileged Page                    */
-#define _PAGE_W		0x0000000000000002	/* Writable                           */
-#define _PAGE_G		0x0000000000000001	/* Global                             */
+#define _PAGE_VALID	0x8000000000000000	/* Valid TTE                 */
+#define _PAGE_R		0x8000000000000000	/* Keep ref bit up to date   */
+#define _PAGE_SZ4MB	0x6000000000000000	/* 4MB Page                  */
+#define _PAGE_SZ512K	0x4000000000000000	/* 512K Page                 */
+#define _PAGE_SZ64K	0x2000000000000000	/* 64K Page                  */
+#define _PAGE_SZ8K	0x0000000000000000	/* 8K Page                   */
+#define _PAGE_NFO	0x1000000000000000	/* No Fault Only             */
+#define _PAGE_IE	0x0800000000000000	/* Invert Endianness         */
+#define _PAGE_SOFT2	0x07FC000000000000	/* Software bits, set 2      */
+#define _PAGE_RES1	0x0003000000000000	/* Reserved                  */
+#define _PAGE_SN	0x0000800000000000	/* (Cheetah) Snoop           */
+#define _PAGE_RES2	0x0000780000000000	/* Reserved                  */
+#define _PAGE_PADDR_SF	0x000001FFFFFFE000	/* (Spitfire) paddr[40:13]   */
+#define _PAGE_PADDR	0x000007FFFFFFE000	/* (Cheetah) paddr[42:13]    */
+#define _PAGE_SOFT	0x0000000000001F80	/* Software bits             */
+#define _PAGE_L		0x0000000000000040	/* Locked TTE                */
+#define _PAGE_CP	0x0000000000000020	/* Cacheable in P-Cache      */
+#define _PAGE_CV	0x0000000000000010	/* Cacheable in V-Cache      */
+#define _PAGE_E		0x0000000000000008	/* side-Effect               */
+#define _PAGE_P		0x0000000000000004	/* Privileged Page           */
+#define _PAGE_W		0x0000000000000002	/* Writable                  */
+#define _PAGE_G		0x0000000000000001	/* Global                    */
 
 /* Here are the SpitFire software bits we use in the TTE's. */
-#define _PAGE_MODIFIED	0x0000000000000800	/* Modified Page (ie. dirty)          */
-#define _PAGE_ACCESSED	0x0000000000000400	/* Accessed Page (ie. referenced)     */
-#define _PAGE_READ	0x0000000000000200	/* Readable SW Bit                    */
-#define _PAGE_WRITE	0x0000000000000100	/* Writable SW Bit                    */
-#define _PAGE_PRESENT	0x0000000000000080	/* Present Page (ie. not swapped out) */
+#define _PAGE_EXEC	0x0000000000001000	/* Executable SW bit         */
+#define _PAGE_MODIFIED	0x0000000000000800	/* Modified Page (ie. dirty) */
+#define _PAGE_ACCESSED	0x0000000000000400	/* Accessed Page (ie. ref'd) */
+#define _PAGE_READ	0x0000000000000200	/* Readable SW Bit           */
+#define _PAGE_WRITE	0x0000000000000100	/* Writable SW Bit           */
+#define _PAGE_PRESENT	0x0000000000000080	/* Present                   */
 
 #if PAGE_SHIFT == 13
 #define _PAGE_SZBITS	_PAGE_SZ8K
@@ -150,16 +154,27 @@
 
 /* Don't set the TTE _PAGE_W bit here, else the dirty bit never gets set. */
 #define PAGE_SHARED	__pgprot (_PAGE_PRESENT | _PAGE_VALID | _PAGE_CACHE | \
-				  __ACCESS_BITS | _PAGE_WRITE)
+				  __ACCESS_BITS | _PAGE_WRITE | _PAGE_EXEC)
 
 #define PAGE_COPY	__pgprot (_PAGE_PRESENT | _PAGE_VALID | _PAGE_CACHE | \
-				  __ACCESS_BITS)
+				  __ACCESS_BITS | _PAGE_EXEC)
 
 #define PAGE_READONLY	__pgprot (_PAGE_PRESENT | _PAGE_VALID | _PAGE_CACHE | \
-				  __ACCESS_BITS)
+				  __ACCESS_BITS | _PAGE_EXEC)
 
 #define PAGE_KERNEL	__pgprot (_PAGE_PRESENT | _PAGE_VALID | _PAGE_CACHE | \
-				  __PRIV_BITS | __ACCESS_BITS | __DIRTY_BITS)
+				  __PRIV_BITS | \
+				  __ACCESS_BITS | __DIRTY_BITS | _PAGE_EXEC)
+
+#define PAGE_SHARED_NOEXEC	__pgprot (_PAGE_PRESENT | _PAGE_VALID | \
+					  _PAGE_CACHE | \
+					  __ACCESS_BITS | _PAGE_WRITE)
+
+#define PAGE_COPY_NOEXEC	__pgprot (_PAGE_PRESENT | _PAGE_VALID | \
+					  _PAGE_CACHE | __ACCESS_BITS)
+
+#define PAGE_READONLY_NOEXEC	__pgprot (_PAGE_PRESENT | _PAGE_VALID | \
+					  _PAGE_CACHE | __ACCESS_BITS)
 
 #define PAGE_INVALID	__pgprot (0)
 
@@ -170,18 +185,18 @@
 #define pg_iobits (_PAGE_VALID | _PAGE_PRESENT | __DIRTY_BITS | __ACCESS_BITS | _PAGE_E)
 
 #define __P000	PAGE_NONE
-#define __P001	PAGE_READONLY
-#define __P010	PAGE_COPY
-#define __P011	PAGE_COPY
+#define __P001	PAGE_READONLY_NOEXEC
+#define __P010	PAGE_COPY_NOEXEC
+#define __P011	PAGE_COPY_NOEXEC
 #define __P100	PAGE_READONLY
 #define __P101	PAGE_READONLY
 #define __P110	PAGE_COPY
 #define __P111	PAGE_COPY
 
 #define __S000	PAGE_NONE
-#define __S001	PAGE_READONLY
-#define __S010	PAGE_SHARED
-#define __S011	PAGE_SHARED
+#define __S001	PAGE_READONLY_NOEXEC
+#define __S010	PAGE_SHARED_NOEXEC
+#define __S011	PAGE_SHARED_NOEXEC
 #define __S100	PAGE_READONLY
 #define __S101	PAGE_READONLY
 #define __S110	PAGE_SHARED
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/include/asm-sparc64/sigcontext.h linux-2.4.28-pre3/include/asm-sparc64/sigcontext.h
--- linux-2.4.27/include/asm-sparc64/sigcontext.h	1999-09-08 18:14:32.000000000 +0000
+++ linux-2.4.28-pre3/include/asm-sparc64/sigcontext.h	2004-09-10 19:33:37.000000000 +0000
@@ -83,18 +83,6 @@ struct sigcontext {
 	unsigned long		sigc_mask;
 };
 
-#ifdef __KERNEL__
-
-/* This magic should be in g_upper[0] for all upper parts
-   to be valid.  */
-#define SIGINFO_EXTRA_V8PLUS_MAGIC	0x130e269
-typedef struct {
-	unsigned   int g_upper[8];
-	unsigned   int o_upper[8];
-} siginfo_extra_v8plus_t;
-
-#endif
-
 #endif /* !(__ASSEMBLY__) */
 
 #endif /* !(__SPARC64_SIGCONTEXT_H) */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/include/asm-sparc64/string.h linux-2.4.28-pre3/include/asm-sparc64/string.h
--- linux-2.4.27/include/asm-sparc64/string.h	2001-10-01 16:19:56.000000000 +0000
+++ linux-2.4.28-pre3/include/asm-sparc64/string.h	2004-09-10 19:36:38.000000000 +0000
@@ -15,59 +15,25 @@
 
 #include <asm/asi.h>
 
-extern void __memmove(void *,const void *,__kernel_size_t);
-extern __kernel_size_t __memcpy(void *,const void *,__kernel_size_t);
 extern void *__memset(void *,int,__kernel_size_t);
-extern void *__builtin_memcpy(void *,const void *,__kernel_size_t);
-extern void *__builtin_memset(void *,int,__kernel_size_t);
 
 #ifndef EXPORT_SYMTAB_STROPS
 
 /* First the mem*() things. */
-#define __HAVE_ARCH_BCOPY
 #define __HAVE_ARCH_MEMMOVE
-
-#undef memmove
-#define memmove(_to, _from, _n) \
-({ \
-	void *_t = (_to); \
-	__memmove(_t, (_from), (_n)); \
-	_t; \
-})
+extern void *memmove(void *, const void *, __kernel_size_t);
 
 #define __HAVE_ARCH_MEMCPY
-
-static inline void *__constant_memcpy(void *to, const void *from, __kernel_size_t n)
-{
-	if(n) {
-		if(n <= 32) {
-			__builtin_memcpy(to, from, n);
-		} else {
-			__memcpy(to, from, n);
-		}
-	}
-	return to;
-}
-
-static inline void *__nonconstant_memcpy(void *to, const void *from, __kernel_size_t n)
-{
-	__memcpy(to, from, n);
-	return to;
-}
-
-#undef memcpy
-#define memcpy(t, f, n) \
-(__builtin_constant_p(n) ? \
- __constant_memcpy((t),(f),(n)) : \
- __nonconstant_memcpy((t),(f),(n)))
+extern void *memcpy(void *, const void *, __kernel_size_t);
 
 #define __HAVE_ARCH_MEMSET
+extern void *__builtin_memset(void *,int,__kernel_size_t);
 
 static inline void *__constant_memset(void *s, int c, __kernel_size_t count)
 {
 	extern __kernel_size_t __bzero(void *, __kernel_size_t);
 
-	if(!c) {
+	if (!c) {
 		__bzero(s, count);
 		return s;
 	} else
@@ -85,19 +51,19 @@ static inline void *__constant_memset(vo
 #define __HAVE_ARCH_MEMSCAN
 
 #undef memscan
-#define memscan(__arg0, __char, __arg2)						\
-({										\
-	extern void *__memscan_zero(void *, size_t);				\
-	extern void *__memscan_generic(void *, int, size_t);			\
-	void *__retval, *__addr = (__arg0);					\
-	size_t __size = (__arg2);						\
-										\
-	if(__builtin_constant_p(__char) && !(__char))				\
-		__retval = __memscan_zero(__addr, __size);			\
-	else									\
-		__retval = __memscan_generic(__addr, (__char), __size);		\
-										\
-	__retval;								\
+#define memscan(__arg0, __char, __arg2)					\
+({									\
+	extern void *__memscan_zero(void *, size_t);			\
+	extern void *__memscan_generic(void *, int, size_t);		\
+	void *__retval, *__addr = (__arg0);				\
+	size_t __size = (__arg2);					\
+									\
+	if(__builtin_constant_p(__char) && !(__char))			\
+		__retval = __memscan_zero(__addr, __size);		\
+	else								\
+		__retval = __memscan_generic(__addr, (__char), __size);	\
+									\
+	__retval;							\
 })
 
 #define __HAVE_ARCH_MEMCMP
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/include/asm-sparc64/uaccess.h linux-2.4.28-pre3/include/asm-sparc64/uaccess.h
--- linux-2.4.27/include/asm-sparc64/uaccess.h	2001-10-01 16:19:56.000000000 +0000
+++ linux-2.4.28-pre3/include/asm-sparc64/uaccess.h	2004-09-10 19:34:18.000000000 +0000
@@ -249,26 +249,50 @@ __asm__ __volatile__(							\
 
 extern int __get_user_bad(void);
 
-extern __kernel_size_t __copy_from_user(void *to, const void *from,
-					__kernel_size_t size);
+extern unsigned long ___copy_from_user(void *to, const void *from,
+				       unsigned long size);
+extern unsigned long copy_from_user_fixup(void *to, const void *from,
+					  unsigned long size);
+static inline unsigned long copy_from_user(void *to, const void *from,
+					   unsigned long size)
+{
+	unsigned long ret = ___copy_from_user(to, from, size);
+
+	if (ret)
+		ret = copy_from_user_fixup(to, from, size);
+	return ret;
+}
+#define __copy_from_user copy_from_user
+
+extern unsigned long ___copy_to_user(void *to, const void *from,
+				     unsigned long size);
+extern unsigned long copy_to_user_fixup(void *to, const void *from,
+					unsigned long size);
+static inline unsigned long copy_to_user(void *to, const void *from,
+					 unsigned long size)
+{
+	unsigned long ret = ___copy_to_user(to, from, size);
 
-extern __kernel_size_t __copy_to_user(void *to, const void *from,
-				      __kernel_size_t size);
+	if (ret)
+		ret = copy_to_user_fixup(to, from, size);
+	return ret;
+}
+#define __copy_to_user copy_to_user
 
-extern __kernel_size_t __copy_in_user(void *to, const void *from,
-				      __kernel_size_t size);
+extern unsigned long ___copy_in_user(void *to, const void *from,
+				     unsigned long size);
+extern unsigned long copy_in_user_fixup(void *to, void *from,
+					unsigned long size);
+static inline unsigned long copy_in_user(void *to, void *from,
+					 unsigned long size)
+{
+	unsigned long ret = ___copy_in_user(to, from, size);
 
-#define copy_from_user(to,from,n)		\
-	__copy_from_user((void *)(to),	\
-		    (void *)(from), (__kernel_size_t)(n))
-
-#define copy_to_user(to,from,n) \
-	__copy_to_user((void *)(to), \
-	(void *) (from), (__kernel_size_t)(n))
-
-#define copy_in_user(to,from,n) \
-	__copy_in_user((void *)(to), \
-	(void *) (from), (__kernel_size_t)(n))
+	if (ret)
+		ret = copy_in_user_fixup(to, from, size);
+	return ret;
+}
+#define __copy_in_user copy_in_user
 
 extern __inline__ __kernel_size_t __clear_user(void *addr, __kernel_size_t size)
 {
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/include/asm-x86_64/apic.h linux-2.4.28-pre3/include/asm-x86_64/apic.h
--- linux-2.4.27/include/asm-x86_64/apic.h	2003-06-13 14:51:38.000000000 +0000
+++ linux-2.4.28-pre3/include/asm-x86_64/apic.h	2004-09-10 19:35:04.000000000 +0000
@@ -78,7 +78,7 @@ extern void init_apic_mappings (void);
 extern void smp_local_timer_interrupt (struct pt_regs * regs);
 extern void setup_APIC_clocks (void);
 extern void setup_apic_nmi_watchdog (void);
-extern inline void nmi_watchdog_tick (struct pt_regs * regs, unsigned reason);
+extern void nmi_watchdog_tick (struct pt_regs * regs, unsigned reason);
 extern int APIC_init_uniprocessor (void);
 extern void disable_APIC_timer(void);
 extern void enable_APIC_timer(void);
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/include/asm-x86_64/unistd.h linux-2.4.28-pre3/include/asm-x86_64/unistd.h
--- linux-2.4.27/include/asm-x86_64/unistd.h	2004-02-18 13:36:32.000000000 +0000
+++ linux-2.4.28-pre3/include/asm-x86_64/unistd.h	2004-09-10 19:36:20.000000000 +0000
@@ -673,7 +673,7 @@ static inline long close(unsigned int fd
 }
 
 extern long sys_exit(int) __attribute__((noreturn));
-extern inline long exit(int error_code)
+static inline void exit(int error_code)
 {
 	sys_exit(error_code);
 }
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/include/linux/ac97_codec.h linux-2.4.28-pre3/include/linux/ac97_codec.h
--- linux-2.4.27/include/linux/ac97_codec.h	2003-08-25 11:44:44.000000000 +0000
+++ linux-2.4.28-pre3/include/linux/ac97_codec.h	2004-09-10 19:32:18.000000000 +0000
@@ -290,6 +290,7 @@ struct ac97_ops
 	
 #define AC97_DELUDED_MODEM	1	/* Audio codec reports its a modem */
 #define AC97_NO_PCM_VOLUME	2	/* Volume control is missing 	   */
+#define AC97_DEFAULT_POWER_OFF 4 /* Needs warm reset to power up */
 };
 
 extern int ac97_read_proc (char *page_out, char **start, off_t off,
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/include/linux/agp_backend.h linux-2.4.28-pre3/include/linux/agp_backend.h
--- linux-2.4.27/include/linux/agp_backend.h	2003-11-28 18:26:21.000000000 +0000
+++ linux-2.4.28-pre3/include/linux/agp_backend.h	2004-09-10 19:36:20.000000000 +0000
@@ -55,6 +55,7 @@ enum chipset_type {
 	INTEL_I855_PM,
 	INTEL_I860,
 	INTEL_I865_G,
+	INTEL_I915_G,
 	INTEL_I7205,
 	INTEL_I7505,
 	INTEL_460GX,
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/include/linux/ata.h linux-2.4.28-pre3/include/linux/ata.h
--- linux-2.4.27/include/linux/ata.h	2004-08-07 23:26:06.000000000 +0000
+++ linux-2.4.28-pre3/include/linux/ata.h	2004-09-10 19:32:51.000000000 +0000
@@ -42,6 +42,7 @@ enum {
 	ATA_ID_SERNO_OFS	= 10,
 	ATA_ID_MAJOR_VER	= 80,
 	ATA_ID_PIO_MODES	= 64,
+	ATA_ID_MWDMA_MODES	= 63,
 	ATA_ID_UDMA_MODES	= 88,
 	ATA_ID_PIO4		= (1 << 1),
 
@@ -78,9 +79,11 @@ enum {
 	ATA_NIEN		= (1 << 1),	/* disable-irq flag */
 	ATA_LBA			= (1 << 6),	/* LBA28 selector */
 	ATA_DEV1		= (1 << 4),	/* Select Device 1 (slave) */
-	ATA_BUSY		= (1 << 7),	/* BSY status bit */
 	ATA_DEVICE_OBS		= (1 << 7) | (1 << 5), /* obs bits in dev reg */
 	ATA_DEVCTL_OBS		= (1 << 3),	/* obsolete bit in devctl reg */
+	ATA_BUSY		= (1 << 7),	/* BSY status bit */
+	ATA_DRDY		= (1 << 6),	/* device ready */
+	ATA_DF			= (1 << 5),	/* device fault */
 	ATA_DRQ			= (1 << 3),	/* data request i/o */
 	ATA_ERR			= (1 << 0),	/* have an error */
 	ATA_SRST		= (1 << 2),	/* software reset */
@@ -131,13 +134,20 @@ enum {
 	XFER_UDMA_2		= 0x42,
 	XFER_UDMA_1		= 0x41,
 	XFER_UDMA_0		= 0x40,
+	XFER_MW_DMA_2		= 0x22,
+	XFER_MW_DMA_1		= 0x21,
+	XFER_MW_DMA_0		= 0x20,
 	XFER_PIO_4		= 0x0C,
 	XFER_PIO_3		= 0x0B,
+	XFER_PIO_2		= 0x0A,
+	XFER_PIO_1		= 0x09,
+	XFER_PIO_0		= 0x08,
 
 	/* ATAPI stuff */
 	ATAPI_PKT_DMA		= (1 << 0),
 	ATAPI_DMADIR		= (1 << 2),	/* ATAPI data dir:
 						   0=to device, 1=to host */
+	ATAPI_CDB_LEN		= 16,
 
 	/* cable types */
 	ATA_CBL_NONE		= 0,
@@ -167,16 +177,22 @@ enum ata_tf_protocols {
 	ATA_PROT_PIO,		/* PIO single sector */
 	ATA_PROT_PIO_MULT,	/* PIO multiple sector */
 	ATA_PROT_DMA,		/* DMA */
-	ATA_PROT_ATAPI,		/* packet command */
+	ATA_PROT_ATAPI,		/* packet command, PIO data xfer*/
+	ATA_PROT_ATAPI_NODATA,	/* packet command, no data */
 	ATA_PROT_ATAPI_DMA,	/* packet command with special DMA sauce */
 };
 
+enum ata_ioctls {
+	ATA_IOC_GET_IO32	= 0x309,
+	ATA_IOC_SET_IO32	= 0x324,
+};
+
 /* core structures */
 
 struct ata_prd {
 	u32			addr;
 	u32			flags_len;
-} __attribute__((packed));
+};
 
 struct ata_taskfile {
 	unsigned long		flags;		/* ATA_TFLAG_xxx */
@@ -204,11 +220,13 @@ struct ata_taskfile {
 #define ata_id_is_ata(dev)	(((dev)->id[0] & (1 << 15)) == 0)
 #define ata_id_rahead_enabled(dev) ((dev)->id[85] & (1 << 6))
 #define ata_id_wcache_enabled(dev) ((dev)->id[85] & (1 << 5))
+#define ata_id_has_flush(dev) ((dev)->id[83] & (1 << 12))
+#define ata_id_has_flush_ext(dev) ((dev)->id[83] & (1 << 13))
 #define ata_id_has_lba48(dev)	((dev)->id[83] & (1 << 10))
 #define ata_id_has_wcache(dev)	((dev)->id[82] & (1 << 5))
 #define ata_id_has_pm(dev)	((dev)->id[82] & (1 << 3))
-#define ata_id_has_lba(dev)	((dev)->id[49] & (1 << 8))
-#define ata_id_has_dma(dev)	((dev)->id[49] & (1 << 9))
+#define ata_id_has_lba(dev)	((dev)->id[49] & (1 << 9))
+#define ata_id_has_dma(dev)	((dev)->id[49] & (1 << 8))
 #define ata_id_removeable(dev)	((dev)->id[0] & (1 << 7))
 #define ata_id_u32(dev,n)	\
 	(((u32) (dev)->id[(n) + 1] << 16) | ((u32) (dev)->id[(n)]))
@@ -218,10 +236,27 @@ struct ata_taskfile {
 	  ((u64) dev->id[(n) + 1] << 16) |	\
 	  ((u64) dev->id[(n) + 0]) )
 
+static inline int atapi_cdb_len(u16 *dev_id)
+{
+	u16 tmp = dev_id[0] & 0x3;
+	switch (tmp) {
+	case 0:		return 12;
+	case 1:		return 16;
+	default:	return -1;
+	}
+}
+
 static inline int is_atapi_taskfile(struct ata_taskfile *tf)
 {
 	return (tf->protocol == ATA_PROT_ATAPI) ||
+	       (tf->protocol == ATA_PROT_ATAPI_NODATA) ||
 	       (tf->protocol == ATA_PROT_ATAPI_DMA);
 }
 
+static inline int ata_ok(u8 status)
+{
+	return ((status & (ATA_BUSY | ATA_DRDY | ATA_DF | ATA_DRQ | ATA_ERR))
+			== ATA_DRDY);
+}
+
 #endif /* __LINUX_ATA_H__ */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/include/linux/blkdev.h linux-2.4.28-pre3/include/linux/blkdev.h
--- linux-2.4.27/include/linux/blkdev.h	2004-02-18 13:36:32.000000000 +0000
+++ linux-2.4.28-pre3/include/linux/blkdev.h	2004-09-10 19:33:16.000000000 +0000
@@ -233,7 +233,7 @@ extern struct blk_dev_struct blk_dev[MAX
 extern void grok_partitions(struct gendisk *dev, int drive, unsigned minors, long size);
 extern void register_disk(struct gendisk *dev, kdev_t first, unsigned minors, struct block_device_operations *ops, long size);
 extern void generic_make_request(int rw, struct buffer_head * bh);
-extern inline request_queue_t *blk_get_queue(kdev_t dev);
+extern request_queue_t *blk_get_queue(kdev_t dev);
 extern void blkdev_release_request(struct request *);
 
 /*
@@ -246,7 +246,7 @@ extern void blk_queue_headactive(request
 extern void blk_queue_throttle_sectors(request_queue_t *, int);
 extern void blk_queue_make_request(request_queue_t *, make_request_fn *);
 extern void generic_unplug_device(void *);
-extern inline int blk_seg_merge_ok(struct buffer_head *, struct buffer_head *);
+extern int blk_seg_merge_ok(struct buffer_head *, struct buffer_head *);
 
 extern int * blk_size[MAX_BLKDEV];
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/include/linux/fs.h linux-2.4.28-pre3/include/linux/fs.h
--- linux-2.4.27/include/linux/fs.h	2004-08-07 23:26:06.000000000 +0000
+++ linux-2.4.28-pre3/include/linux/fs.h	2004-09-10 19:33:26.000000000 +0000
@@ -1259,7 +1259,7 @@ static inline void mark_buffer_dirty_ino
 }
 
 extern void set_buffer_flushtime(struct buffer_head *);
-extern inline int get_buffer_flushtime(void);
+extern int get_buffer_flushtime(void);
 extern void balance_dirty(void);
 extern int check_disk_change(kdev_t);
 extern int invalidate_inodes(struct super_block *);
@@ -1523,7 +1523,7 @@ extern int writeout_one_page(struct page
 extern int generic_file_mmap(struct file *, struct vm_area_struct *);
 extern int file_read_actor(read_descriptor_t * desc, struct page *page, unsigned long offset, unsigned long size);
 extern ssize_t generic_file_read(struct file *, char *, size_t, loff_t *);
-extern inline ssize_t do_generic_direct_read(struct file *, char *, size_t, loff_t *);
+extern ssize_t do_generic_direct_read(struct file *, char *, size_t, loff_t *);
 extern int precheck_file_write(struct file *, struct inode *, size_t *, loff_t *);
 extern ssize_t generic_file_write(struct file *, const char *, size_t, loff_t *);
 extern void do_generic_file_read(struct file *, loff_t *, read_descriptor_t *, read_actor_t);
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/include/linux/fsfilter.h linux-2.4.28-pre3/include/linux/fsfilter.h
--- linux-2.4.27/include/linux/fsfilter.h	2002-11-28 23:53:15.000000000 +0000
+++ linux-2.4.28-pre3/include/linux/fsfilter.h	2004-09-10 19:32:04.000000000 +0000
@@ -74,22 +74,22 @@ extern struct filter_fs filter_oppar[FIL
 
 struct filter_fs *filter_get_filter_fs(const char *cache_type);
 void filter_setup_journal_ops(struct filter_fs *ops, char *cache_type);
-inline struct super_operations *filter_c2usops(struct filter_fs *cache);
-inline struct inode_operations *filter_c2ufiops(struct filter_fs *cache);
-inline struct inode_operations *filter_c2udiops(struct filter_fs *cache);
-inline struct inode_operations *filter_c2usiops(struct filter_fs *cache);
-inline struct file_operations *filter_c2uffops(struct filter_fs *cache);
-inline struct file_operations *filter_c2udfops(struct filter_fs *cache);
-inline struct file_operations *filter_c2usfops(struct filter_fs *cache);
-inline struct super_operations *filter_c2csops(struct filter_fs *cache);
-inline struct inode_operations *filter_c2cfiops(struct filter_fs *cache);
-inline struct inode_operations *filter_c2cdiops(struct filter_fs *cache);
-inline struct inode_operations *filter_c2csiops(struct filter_fs *cache);
-inline struct file_operations *filter_c2cffops(struct filter_fs *cache);
-inline struct file_operations *filter_c2cdfops(struct filter_fs *cache);
-inline struct file_operations *filter_c2csfops(struct filter_fs *cache);
-inline struct dentry_operations *filter_c2cdops(struct filter_fs *cache);
-inline struct dentry_operations *filter_c2udops(struct filter_fs *cache);
+struct super_operations *filter_c2usops(struct filter_fs *cache);
+struct inode_operations *filter_c2ufiops(struct filter_fs *cache);
+struct inode_operations *filter_c2udiops(struct filter_fs *cache);
+struct inode_operations *filter_c2usiops(struct filter_fs *cache);
+struct file_operations *filter_c2uffops(struct filter_fs *cache);
+struct file_operations *filter_c2udfops(struct filter_fs *cache);
+struct file_operations *filter_c2usfops(struct filter_fs *cache);
+struct super_operations *filter_c2csops(struct filter_fs *cache);
+struct inode_operations *filter_c2cfiops(struct filter_fs *cache);
+struct inode_operations *filter_c2cdiops(struct filter_fs *cache);
+struct inode_operations *filter_c2csiops(struct filter_fs *cache);
+struct file_operations *filter_c2cffops(struct filter_fs *cache);
+struct file_operations *filter_c2cdfops(struct filter_fs *cache);
+struct file_operations *filter_c2csfops(struct filter_fs *cache);
+struct dentry_operations *filter_c2cdops(struct filter_fs *cache);
+struct dentry_operations *filter_c2udops(struct filter_fs *cache);
 
 void filter_setup_super_ops(struct filter_fs *cache, struct super_operations *cache_ops, struct super_operations *filter_sops);
 void filter_setup_dir_ops(struct filter_fs *cache, struct inode *cache_inode, struct inode_operations *filter_iops, struct file_operations *ffops);
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/include/linux/ide.h linux-2.4.28-pre3/include/linux/ide.h
--- linux-2.4.27/include/linux/ide.h	2004-04-14 13:05:40.000000000 +0000
+++ linux-2.4.28-pre3/include/linux/ide.h	2004-09-10 19:33:03.000000000 +0000
@@ -1445,10 +1445,10 @@ typedef struct pkt_task_s {
 	void			*special;
 } pkt_task_t;
 
-extern inline void SELECT_DRIVE(ide_drive_t *);
-extern inline void SELECT_INTERRUPT(ide_drive_t *);
-extern inline void SELECT_MASK(ide_drive_t *, int);
-extern inline void QUIRK_LIST(ide_drive_t *);
+extern void SELECT_DRIVE(ide_drive_t *);
+extern void SELECT_INTERRUPT(ide_drive_t *);
+extern void SELECT_MASK(ide_drive_t *, int);
+extern void QUIRK_LIST(ide_drive_t *);
 
 extern void ata_input_data(ide_drive_t *, void *, u32);
 extern void ata_output_data(ide_drive_t *, void *, u32);
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/include/linux/in6.h linux-2.4.28-pre3/include/linux/in6.h
--- linux-2.4.27/include/linux/in6.h	2003-06-13 14:51:38.000000000 +0000
+++ linux-2.4.28-pre3/include/linux/in6.h	2004-09-10 19:35:30.000000000 +0000
@@ -3,7 +3,7 @@
  *	Linux INET6 implementation 
  *
  *	Authors:
- *	Pedro Roque		<roque@di.fc.ul.pt>	
+ *	Pedro Roque		<pedro_m@yahoo.com>	
  *
  *	Sources:
  *	IPv6 Program Interfaces for BSD Systems
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/include/linux/intermezzo_fs.h linux-2.4.28-pre3/include/linux/intermezzo_fs.h
--- linux-2.4.27/include/linux/intermezzo_fs.h	2002-11-28 23:53:15.000000000 +0000
+++ linux-2.4.28-pre3/include/linux/intermezzo_fs.h	2004-09-10 19:34:33.000000000 +0000
@@ -49,8 +49,6 @@ struct lento_vfs_context {
         struct presto_version remote_version;
 };
 
-static inline int izo_ioctl_is_invalid(struct izo_ioctl_data *data);
-
 #ifdef __KERNEL__
 # include <linux/smp.h>
 # include <linux/fsfilter.h>
@@ -336,7 +334,7 @@ int izo_psdev_get_free_channel(void);
 int presto_psdev_init(void);
 int izo_psdev_setpid(int minor);
 extern void presto_psdev_cleanup(void);
-inline int presto_lento_up(int minor);
+int presto_lento_up(int minor);
 int izo_psdev_setchannel(struct file *file, int fd);
 
 /* inode.c */
@@ -347,7 +345,7 @@ void presto_set_ops(struct inode *inode,
 void presto_frob_dop(struct dentry *de);
 char *presto_path(struct dentry *dentry, struct dentry *root,
                   char *buffer, int buflen);
-inline struct presto_dentry_data *izo_alloc_ddata(void);
+struct presto_dentry_data *izo_alloc_ddata(void);
 int presto_set_dd(struct dentry *);
 int presto_init_ddata_cache(void);
 void presto_cleanup_ddata_cache(void);
@@ -412,7 +410,7 @@ int presto_set_fsetroot(struct dentry *d
                        unsigned int flags);
 int presto_set_fsetroot_from_ioc(struct dentry *dentry, char *fsetname,
                                  unsigned int flags);
-inline int presto_is_read_only(struct presto_file_set *);
+int presto_is_read_only(struct presto_file_set *);
 int presto_truncate_lml(struct presto_file_set *fset);
 int lento_write_lml(char *path,
                      __u64 remote_ino,
@@ -420,13 +418,13 @@ int lento_write_lml(char *path,
                      __u32 remote_version,
                     struct presto_version *remote_file_version);
 int lento_complete_closes(char *path);
-inline int presto_f2m(struct presto_file_set *fset);
+int presto_f2m(struct presto_file_set *fset);
 int presto_prep(struct dentry *, struct presto_cache **,
                        struct presto_file_set **);
 /* cache.c */
 extern struct presto_cache *presto_cache_init(void);
-extern inline void presto_cache_add(struct presto_cache *cache, kdev_t dev);
-extern inline void presto_cache_init_hash(void);
+extern void presto_cache_add(struct presto_cache *cache, kdev_t dev);
+extern void presto_cache_init_hash(void);
 
 struct presto_cache *presto_cache_find(kdev_t dev);
 
@@ -553,7 +551,7 @@ int lento_iopen(const char *name, ino_t 
 
 #define JOURNAL_PAGE_SZ  PAGE_SIZE
 
-__inline__ int presto_no_journal(struct presto_file_set *fset);
+int presto_no_journal(struct presto_file_set *fset);
 int journal_fetch(int minor);
 int presto_log(struct presto_file_set *fset, struct rec_info *rec,
                const char *buf, size_t size,
@@ -658,6 +656,8 @@ loff_t izo_rcvd_write(struct presto_file
 loff_t izo_rcvd_upd_remote(struct presto_file_set *fset, char * uuid,  __u64 remote_recno,
                            __u64 remote_offset);
 
+int izo_ioctl_packlen(struct izo_ioctl_data *data);
+
 /* sysctl.c */
 int init_intermezzo_sysctl(void);
 void cleanup_intermezzo_sysctl(void);
@@ -715,6 +715,54 @@ static inline char *strdup(char *str)
         return tmp;
 }
 
+static inline int izo_ioctl_is_invalid(struct izo_ioctl_data *data)
+{
+        if (data->ioc_len > (1<<30)) {
+                CERROR("IZO ioctl: ioc_len larger than 1<<30\n");
+                return 1;
+        }
+        if (data->ioc_inllen1 > (1<<30)) {
+                CERROR("IZO ioctl: ioc_inllen1 larger than 1<<30\n");
+                return 1;
+        }
+        if (data->ioc_inllen2 > (1<<30)) {
+                CERROR("IZO ioctl: ioc_inllen2 larger than 1<<30\n");
+                return 1;
+        }
+        if (data->ioc_inlbuf1 && !data->ioc_inllen1) {
+                CERROR("IZO ioctl: inlbuf1 pointer but 0 length\n");
+                return 1;
+        }
+        if (data->ioc_inlbuf2 && !data->ioc_inllen2) {
+                CERROR("IZO ioctl: inlbuf2 pointer but 0 length\n");
+                return 1;
+        }
+        if (data->ioc_pbuf1 && !data->ioc_plen1) {
+                CERROR("IZO ioctl: pbuf1 pointer but 0 length\n");
+                return 1;
+        }
+        if (data->ioc_pbuf2 && !data->ioc_plen2) {
+                CERROR("IZO ioctl: pbuf2 pointer but 0 length\n");
+                return 1;
+        }
+        if (izo_ioctl_packlen(data) != data->ioc_len ) {
+                CERROR("IZO ioctl: packlen exceeds ioc_len\n");
+                return 1;
+        }
+        if (data->ioc_inllen1 &&
+            data->ioc_bulk[data->ioc_inllen1 - 1] != '\0') {
+                CERROR("IZO ioctl: inlbuf1 not 0 terminated\n");
+                return 1;
+        }
+        if (data->ioc_inllen2 &&
+            data->ioc_bulk[size_round(data->ioc_inllen1) + data->ioc_inllen2
+                           - 1] != '\0') {
+                CERROR("IZO ioctl: inlbuf2 not 0 terminated\n");
+                return 1;
+        }
+        return 0;
+}
+
 /* buffer MUST be at least the size of izo_ioctl_hdr */
 static inline int izo_ioctl_getdata(char *buf, char *end, void *arg)
 {
@@ -798,8 +846,6 @@ int kml_fsreint(struct kml_rec *rec, cha
 int kml_iocreint(__u32 size, char *ptr, __u32 offset, int dird,
                  uuid_t uuid, __u32 generate_kml);
 
-static inline int izo_ioctl_packlen(struct izo_ioctl_data *data);
-
 static inline void izo_ioctl_init(struct izo_ioctl_data *data)
 {
         memset(data, 0, sizeof(*data));
@@ -861,62 +907,6 @@ static inline char *izo_error(int err)
         return "Unknown InterMezzo error";
 }
 
-static inline int izo_ioctl_packlen(struct izo_ioctl_data *data)
-{
-        int len = sizeof(struct izo_ioctl_data);
-        len += size_round(data->ioc_inllen1);
-        len += size_round(data->ioc_inllen2);
-        return len;
-}
-
-static inline int izo_ioctl_is_invalid(struct izo_ioctl_data *data)
-{
-        if (data->ioc_len > (1<<30)) {
-                CERROR("IZO ioctl: ioc_len larger than 1<<30\n");
-                return 1;
-        }
-        if (data->ioc_inllen1 > (1<<30)) {
-                CERROR("IZO ioctl: ioc_inllen1 larger than 1<<30\n");
-                return 1;
-        }
-        if (data->ioc_inllen2 > (1<<30)) {
-                CERROR("IZO ioctl: ioc_inllen2 larger than 1<<30\n");
-                return 1;
-        }
-        if (data->ioc_inlbuf1 && !data->ioc_inllen1) {
-                CERROR("IZO ioctl: inlbuf1 pointer but 0 length\n");
-                return 1;
-        }
-        if (data->ioc_inlbuf2 && !data->ioc_inllen2) {
-                CERROR("IZO ioctl: inlbuf2 pointer but 0 length\n");
-                return 1;
-        }
-        if (data->ioc_pbuf1 && !data->ioc_plen1) {
-                CERROR("IZO ioctl: pbuf1 pointer but 0 length\n");
-                return 1;
-        }
-        if (data->ioc_pbuf2 && !data->ioc_plen2) {
-                CERROR("IZO ioctl: pbuf2 pointer but 0 length\n");
-                return 1;
-        }
-        if (izo_ioctl_packlen(data) != data->ioc_len ) {
-                CERROR("IZO ioctl: packlen exceeds ioc_len\n");
-                return 1;
-        }
-        if (data->ioc_inllen1 &&
-            data->ioc_bulk[data->ioc_inllen1 - 1] != '\0') {
-                CERROR("IZO ioctl: inlbuf1 not 0 terminated\n");
-                return 1;
-        }
-        if (data->ioc_inllen2 &&
-            data->ioc_bulk[size_round(data->ioc_inllen1) + data->ioc_inllen2
-                           - 1] != '\0') {
-                CERROR("IZO ioctl: inlbuf2 not 0 terminated\n");
-                return 1;
-        }
-        return 0;
-}
-
 /* kml_unpack.c */
 char *kml_print_rec(struct kml_rec *rec, int brief);
 int kml_unpack(struct kml_rec *rec, char **buf, char *end);
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/include/linux/ipv6_route.h linux-2.4.28-pre3/include/linux/ipv6_route.h
--- linux-2.4.27/include/linux/ipv6_route.h	2003-11-28 18:26:21.000000000 +0000
+++ linux-2.4.28-pre3/include/linux/ipv6_route.h	2004-09-10 19:33:06.000000000 +0000
@@ -2,7 +2,7 @@
  *	Linux INET6 implementation 
  *
  *	Authors:
- *	Pedro Roque		<roque@di.fc.ul.pt>	
+ *	Pedro Roque		<pedro_m@yahoo.com>	
  *
  *	This program is free software; you can redistribute it and/or
  *      modify it under the terms of the GNU General Public License
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/include/linux/irq_cpustat.h linux-2.4.28-pre3/include/linux/irq_cpustat.h
--- linux-2.4.27/include/linux/irq_cpustat.h	2001-11-22 19:46:18.000000000 +0000
+++ linux-2.4.28-pre3/include/linux/irq_cpustat.h	2004-09-10 19:36:54.000000000 +0000
@@ -22,7 +22,7 @@ extern irq_cpustat_t irq_stat[];			/* de
 #ifdef CONFIG_SMP
 #define __IRQ_STAT(cpu, member)	(irq_stat[cpu].member)
 #else
-#define __IRQ_STAT(cpu, member)	((void)(cpu), irq_stat[0].member)
+#define __IRQ_STAT(cpu, member)	(irq_stat[((void)(cpu), 0)].member)
 #endif	
 
   /* arch independent irq_stat fields */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/include/linux/jbd.h linux-2.4.28-pre3/include/linux/jbd.h
--- linux-2.4.27/include/linux/jbd.h	2003-06-13 14:51:38.000000000 +0000
+++ linux-2.4.28-pre3/include/linux/jbd.h	2004-09-10 19:36:27.000000000 +0000
@@ -70,7 +70,7 @@ extern int journal_enable_debug;
 #define jbd_debug(f, a...)	/**/
 #endif
 
-extern void * __jbd_kmalloc (char *where, size_t size, int flags, int retry);
+extern void * __jbd_kmalloc (const char *where, size_t size, int flags, int retry);
 #define jbd_kmalloc(size, flags) \
 	__jbd_kmalloc(__FUNCTION__, (size), (flags), journal_oom_retry)
 #define jbd_rep_kmalloc(size, flags) \
@@ -867,7 +867,7 @@ do {								      \
 	schedule();						      \
 } while (1)
 
-extern void __jbd_unexpected_dirty_buffer(char *, int, struct journal_head *);
+extern void __jbd_unexpected_dirty_buffer(const char *, int, struct journal_head *);
 #define jbd_unexpected_dirty_buffer(jh) \
 	__jbd_unexpected_dirty_buffer(__FUNCTION__, __LINE__, (jh))
 	
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/include/linux/kernel.h linux-2.4.28-pre3/include/linux/kernel.h
--- linux-2.4.27/include/linux/kernel.h	2004-08-07 23:26:06.000000000 +0000
+++ linux-2.4.28-pre3/include/linux/kernel.h	2004-09-10 19:31:52.000000000 +0000
@@ -51,8 +51,10 @@ extern int console_printk[];
 
 #ifdef __i386__
 #define FASTCALL(x)	x __attribute__((regparm(3)))
+#define fastcall	__attribute__((regparm(3)))
 #else
 #define FASTCALL(x)	x
+#define fastcall
 #endif
 
 struct completion;
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/include/linux/libata.h linux-2.4.28-pre3/include/linux/libata.h
--- linux-2.4.27/include/linux/libata.h	2004-08-07 23:26:06.000000000 +0000
+++ linux-2.4.28-pre3/include/linux/libata.h	2004-09-10 19:36:13.000000000 +0000
@@ -32,7 +32,6 @@
 /*
  * compile-time options
  */
-#undef ATA_FORCE_PIO		/* do not configure or use DMA */
 #undef ATA_DEBUG		/* debugging output */
 #undef ATA_VERBOSE_DEBUG	/* yet more debugging output */
 #undef ATA_IRQ_TRAP		/* define to ack screaming irqs */
@@ -89,9 +88,7 @@ enum {
 	/* struct ata_device stuff */
 	ATA_DFLAG_LBA48		= (1 << 0), /* device supports LBA48 */
 	ATA_DFLAG_PIO		= (1 << 1), /* device currently in PIO mode */
-	ATA_DFLAG_MASTER	= (1 << 2), /* is device 0? */
-	ATA_DFLAG_WCACHE	= (1 << 3), /* has write cache we can
-					     * (hopefully) flush? */
+	ATA_DFLAG_LOCK_SECTORS	= (1 << 2), /* don't adjust max_sectors */
 
 	ATA_DEV_UNKNOWN		= 0,	/* unknown device */
 	ATA_DEV_ATA		= 1,	/* ATA device */
@@ -111,8 +108,9 @@ enum {
 	ATA_FLAG_SATA_RESET	= (1 << 7), /* use COMRESET */
 
 	ATA_QCFLAG_ACTIVE	= (1 << 1), /* cmd not yet ack'd to scsi lyer */
-	ATA_QCFLAG_DMA		= (1 << 2), /* data delivered via DMA */
-	ATA_QCFLAG_SG		= (1 << 4), /* have s/g table? */
+	ATA_QCFLAG_SG		= (1 << 3), /* have s/g table? */
+	ATA_QCFLAG_SINGLE	= (1 << 4), /* no s/g, just a single buffer */
+	ATA_QCFLAG_DMAMAP	= ATA_QCFLAG_SG | ATA_QCFLAG_SINGLE,
 
 	/* various lengths of time */
 	ATA_TMOUT_EDD		= 5 * HZ,	/* hueristic */
@@ -134,24 +132,17 @@ enum {
 	BUS_IDENTIFY		= 8,
 	BUS_PACKET		= 9,
 
-	/* thread states */
-	THR_UNKNOWN		= 0,
-	THR_PORT_RESET		= (THR_UNKNOWN + 1),
-	THR_AWAIT_DEATH		= (THR_PORT_RESET + 1),
-	THR_PROBE_FAILED	= (THR_AWAIT_DEATH + 1),
-	THR_IDLE		= (THR_PROBE_FAILED + 1),
-	THR_PROBE_SUCCESS	= (THR_IDLE + 1),
-	THR_PROBE_START		= (THR_PROBE_SUCCESS + 1),
-
 	/* SATA port states */
 	PORT_UNKNOWN		= 0,
 	PORT_ENABLED		= 1,
 	PORT_DISABLED		= 2,
 
-	/* ata_qc_cb_t flags - note uses above ATA_QCFLAG_xxx namespace,
-	 * but not numberspace
+	/* encoding various smaller bitmaps into a single
+	 * unsigned long bitmap
 	 */
-	ATA_QCFLAG_TIMEOUT	= (1 << 0),
+	ATA_SHIFT_UDMA		= 0,
+	ATA_SHIFT_MWDMA		= 8,
+	ATA_SHIFT_PIO		= 11,
 };
 
 enum pio_task_states {
@@ -166,12 +157,13 @@ enum pio_task_states {
 };
 
 /* forward declarations */
+struct scsi_device;
 struct ata_port_operations;
 struct ata_port;
 struct ata_queued_cmd;
 
 /* typedefs */
-typedef void (*ata_qc_cb_t) (struct ata_queued_cmd *qc, unsigned int flags);
+typedef int (*ata_qc_cb_t) (struct ata_queued_cmd *qc, u8 drv_stat);
 
 struct ata_ioports {
 	unsigned long		cmd_addr;
@@ -199,6 +191,7 @@ struct ata_probe_ent {
 	struct ata_ioports	port[ATA_MAX_PORTS];
 	unsigned int		n_ports;
 	unsigned int		pio_mask;
+	unsigned int		mwdma_mask;
 	unsigned int		udma_mask;
 	unsigned int		legacy_mode;
 	unsigned long		irq;
@@ -215,6 +208,7 @@ struct ata_host_set {
 	void			*mmio_base;
 	unsigned int		n_ports;
 	void			*private_data;
+	struct ata_port_operations *ops;
 	struct ata_port *	ports[0];
 };
 
@@ -225,19 +219,26 @@ struct ata_queued_cmd {
 	struct scsi_cmnd	*scsicmd;
 	void			(*scsidone)(struct scsi_cmnd *);
 
+	struct ata_taskfile	tf;
+	u8			cdb[ATAPI_CDB_LEN];
+
 	unsigned long		flags;		/* ATA_QCFLAG_xxx */
 	unsigned int		tag;
 	unsigned int		n_elem;
+
+	int			pci_dma_dir;
+
 	unsigned int		nsect;
 	unsigned int		cursect;
 	unsigned int		cursg;
 	unsigned int		cursg_ofs;
-	struct ata_taskfile	tf;
+
 	struct scatterlist	sgent;
+	void			*buf_virt;
 
 	struct scatterlist	*sg;
 
-	ata_qc_cb_t		callback;
+	ata_qc_cb_t		complete_fn;
 
 	struct completion	*waiting;
 
@@ -256,8 +257,10 @@ struct ata_device {
 	unsigned int		class;		/* ATA_DEV_xxx */
 	unsigned int		devno;		/* 0 or 1 */
 	u16			id[ATA_ID_WORDS]; /* IDENTIFY xxx DEVICE data */
-	unsigned int		pio_mode;
-	unsigned int		udma_mode;
+	u8			pio_mode;
+	u8			dma_mode;
+	u8			xfer_mode;
+	unsigned int		xfer_shift;	/* ATA_SHIFT_xxx */
 
 	/* cache info about current transfer mode */
 	u8			xfer_protocol;	/* taskfile xfer protocol */
@@ -282,8 +285,10 @@ struct ata_port {
 	unsigned int		bus_state;
 	unsigned int		port_state;
 	unsigned int		pio_mask;
+	unsigned int		mwdma_mask;
 	unsigned int		udma_mask;
 	unsigned int		cbl;	/* cable type; ATA_CBL_xxx */
+	unsigned int		cdb_len;
 
 	struct ata_device	device[ATA_MAX_DEVICES];
 
@@ -294,18 +299,12 @@ struct ata_port {
 	struct ata_host_stats	stats;
 	struct ata_host_set	*host_set;
 
-	struct semaphore	probe_sem;
-
-	unsigned int		thr_state;
-
 	struct tq_struct	packet_task;
 
 	struct tq_struct	pio_task;
 	unsigned int		pio_task_state;
 	unsigned long		pio_task_timeout;
 
-	struct tq_struct	probe_task;
-
 	void			*private_data;
 };
 
@@ -314,10 +313,8 @@ struct ata_port_operations {
 
 	void (*dev_config) (struct ata_port *, struct ata_device *);
 
-	void (*set_piomode) (struct ata_port *, struct ata_device *,
-			     unsigned int);
-	void (*set_udmamode) (struct ata_port *, struct ata_device *,
-			     unsigned int);
+	void (*set_piomode) (struct ata_port *, struct ata_device *);
+	void (*set_dmamode) (struct ata_port *, struct ata_device *);
 
 	void (*tf_load) (struct ata_port *ap, struct ata_taskfile *tf);
 	void (*tf_read) (struct ata_port *ap, struct ata_taskfile *tf);
@@ -330,10 +327,14 @@ struct ata_port_operations {
 
 	void (*bmdma_setup) (struct ata_queued_cmd *qc);
 	void (*bmdma_start) (struct ata_queued_cmd *qc);
-	void (*fill_sg) (struct ata_queued_cmd *qc);
+
+	void (*qc_prep) (struct ata_queued_cmd *qc);
+	int (*qc_issue) (struct ata_queued_cmd *qc);
+
 	void (*eng_timeout) (struct ata_port *ap);
 
 	irqreturn_t (*irq_handler)(int, void *, struct pt_regs *);
+	void (*irq_clear) (struct ata_port *);
 
 	u32 (*scr_read) (struct ata_port *ap, unsigned int sc_reg);
 	void (*scr_write) (struct ata_port *ap, unsigned int sc_reg,
@@ -349,6 +350,7 @@ struct ata_port_info {
 	Scsi_Host_Template	*sht;
 	unsigned long		host_flags;
 	unsigned long		pio_mask;
+	unsigned long		mwdma_mask;
 	unsigned long		udma_mask;
 	struct ata_port_operations	*port_ops;
 };
@@ -370,6 +372,7 @@ extern int ata_pci_init_one (struct pci_
 extern void ata_pci_remove_one (struct pci_dev *pdev);
 extern int ata_device_add(struct ata_probe_ent *ent);
 extern int ata_scsi_detect(Scsi_Host_Template *sht);
+extern int ata_scsi_ioctl(struct scsi_device *dev, int cmd, void __user *arg);
 extern int ata_scsi_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *));
 extern int ata_scsi_error(struct Scsi_Host *host);
 extern int ata_scsi_release(struct Scsi_Host *host);
@@ -390,18 +393,25 @@ extern void ata_exec_command_mmio(struct
 extern int ata_port_start (struct ata_port *ap);
 extern void ata_port_stop (struct ata_port *ap);
 extern irqreturn_t ata_interrupt (int irq, void *dev_instance, struct pt_regs *regs);
-extern void ata_fill_sg(struct ata_queued_cmd *qc);
+extern void ata_qc_prep(struct ata_queued_cmd *qc);
+extern int ata_qc_issue_prot(struct ata_queued_cmd *qc);
+extern void ata_sg_init_one(struct ata_queued_cmd *qc, void *buf,
+		unsigned int buflen);
+extern void ata_sg_init(struct ata_queued_cmd *qc, struct scatterlist *sg,
+		 unsigned int n_elem);
 extern void ata_dev_id_string(struct ata_device *dev, unsigned char *s,
 			      unsigned int ofs, unsigned int len);
 extern void ata_bmdma_setup_mmio (struct ata_queued_cmd *qc);
 extern void ata_bmdma_start_mmio (struct ata_queued_cmd *qc);
 extern void ata_bmdma_setup_pio (struct ata_queued_cmd *qc);
 extern void ata_bmdma_start_pio (struct ata_queued_cmd *qc);
+extern void ata_bmdma_irq_clear(struct ata_port *ap);
 extern int pci_test_config_bits(struct pci_dev *pdev, struct pci_bits *bits);
 extern void ata_qc_complete(struct ata_queued_cmd *qc, u8 drv_stat);
 extern void ata_eng_timeout(struct ata_port *ap);
 extern void ata_add_to_probe_list (struct ata_probe_ent *probe_ent);
 extern int ata_std_bios_param(Disk * disk, kdev_t dev, int *ip);
+extern void libata_msleep(unsigned long msecs);
 
 
 static inline unsigned long msecs_to_jiffies(unsigned long msecs)
@@ -476,7 +486,6 @@ static inline u8 ata_wait_idle(struct at
 
 static inline void ata_qc_set_polling(struct ata_queued_cmd *qc)
 {
-	qc->flags &= ~ATA_QCFLAG_DMA;
 	qc->tf.ctl |= ATA_NIEN;
 }
 
@@ -502,6 +511,7 @@ static inline void ata_tf_init(struct at
 static inline u8 ata_irq_on(struct ata_port *ap)
 {
 	struct ata_ioports *ioaddr = &ap->ioaddr;
+	u8 tmp;
 
 	ap->ctl &= ~ATA_NIEN;
 	ap->last_ctl = ap->ctl;
@@ -510,7 +520,11 @@ static inline u8 ata_irq_on(struct ata_p
 		writeb(ap->ctl, ioaddr->ctl_addr);
 	else
 		outb(ap->ctl, ioaddr->ctl_addr);
-	return ata_wait_idle(ap);
+	tmp = ata_wait_idle(ap);
+
+	ap->ops->irq_clear(ap);
+
+	return tmp;
 }
 
 static inline u8 ata_irq_ack(struct ata_port *ap, unsigned int chk_drq)
@@ -559,4 +573,51 @@ static inline unsigned int sata_dev_pres
 	return ((scr_read(ap, SCR_STATUS) & 0xf) == 0x3) ? 1 : 0;
 }
 
+static inline void ata_bmdma_stop(struct ata_port *ap)
+{
+	if (ap->flags & ATA_FLAG_MMIO) {
+		void *mmio = (void *) ap->ioaddr.bmdma_addr;
+
+		/* clear start/stop bit */
+		writeb(readb(mmio + ATA_DMA_CMD) & ~ATA_DMA_START,
+		      mmio + ATA_DMA_CMD);
+	} else {
+		/* clear start/stop bit */
+		outb(inb(ap->ioaddr.bmdma_addr + ATA_DMA_CMD) & ~ATA_DMA_START,
+		    ap->ioaddr.bmdma_addr + ATA_DMA_CMD);
+	}
+
+	/* one-PIO-cycle guaranteed wait, per spec, for HDMA1:0 transition */
+	ata_altstatus(ap);	      /* dummy read */
+}
+
+static inline void ata_bmdma_ack_irq(struct ata_port *ap)
+{
+	if (ap->flags & ATA_FLAG_MMIO) {
+		void *mmio = ((void *) ap->ioaddr.bmdma_addr) + ATA_DMA_STATUS;
+		writeb(readb(mmio), mmio);
+	} else {
+		unsigned long addr = ap->ioaddr.bmdma_addr + ATA_DMA_STATUS;
+		outb(inb(addr), addr);
+	}
+}
+
+static inline u8 ata_bmdma_status(struct ata_port *ap)
+{
+	u8 host_stat;
+	if (ap->flags & ATA_FLAG_MMIO) {
+		void *mmio = (void *) ap->ioaddr.bmdma_addr;
+		host_stat = readb(mmio + ATA_DMA_STATUS);
+	} else
+		host_stat = inb(ap->ioaddr.bmdma_addr + ATA_DMA_STATUS);
+	return host_stat;
+}
+
+static inline int ata_try_flush_cache(struct ata_device *dev)
+{
+	return ata_id_wcache_enabled(dev) ||
+	       ata_id_has_flush(dev) ||
+	       ata_id_has_flush_ext(dev);
+}
+
 #endif /* __LINUX_LIBATA_H__ */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/include/linux/mm.h linux-2.4.28-pre3/include/linux/mm.h
--- linux-2.4.27/include/linux/mm.h	2003-11-28 18:26:21.000000000 +0000
+++ linux-2.4.28-pre3/include/linux/mm.h	2004-09-10 19:32:15.000000000 +0000
@@ -308,11 +308,9 @@ typedef struct page {
 /* Make it prettier to test the above... */
 #define UnlockPage(page)	unlock_page(page)
 #define Page_Uptodate(page)	test_bit(PG_uptodate, &(page)->flags)
-#define SetPageUptodate(page) \
-	do {								\
-		arch_set_page_uptodate(page);				\
-		set_bit(PG_uptodate, &(page)->flags);			\
-	} while (0)
+#ifndef SetPageUptodate
+#define SetPageUptodate(page)	set_bit(PG_uptodate, &(page)->flags)
+#endif
 #define ClearPageUptodate(page)	clear_bit(PG_uptodate, &(page)->flags)
 #define PageDirty(page)		test_bit(PG_dirty, &(page)->flags)
 #define SetPageDirty(page)	set_bit(PG_dirty, &(page)->flags)
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/include/linux/netdevice.h linux-2.4.28-pre3/include/linux/netdevice.h
--- linux-2.4.27/include/linux/netdevice.h	2004-08-07 23:26:06.000000000 +0000
+++ linux-2.4.28-pre3/include/linux/netdevice.h	2004-09-10 19:36:57.000000000 +0000
@@ -352,8 +352,8 @@ struct net_device
 
 	struct Qdisc		*qdisc;
 	struct Qdisc		*qdisc_sleeping;
-	struct Qdisc		*qdisc_list;
 	struct Qdisc		*qdisc_ingress;
+	struct list_head	qdisc_list;
 	unsigned long		tx_queue_len;	/* Max frames per queue allowed */
 
 	/* hard_start_xmit synchronizer */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/include/linux/netfilter_ipv4/ip_conntrack.h linux-2.4.28-pre3/include/linux/netfilter_ipv4/ip_conntrack.h
--- linux-2.4.27/include/linux/netfilter_ipv4/ip_conntrack.h	2004-08-07 23:26:06.000000000 +0000
+++ linux-2.4.28-pre3/include/linux/netfilter_ipv4/ip_conntrack.h	2004-09-10 19:36:54.000000000 +0000
@@ -249,6 +249,7 @@ extern void ip_ct_refresh(struct ip_conn
 /* Call me when a conntrack is destroyed. */
 extern void (*ip_conntrack_destroyed)(struct ip_conntrack *conntrack);
 
+extern int ip_ct_no_defrag;
 /* Returns new sk_buff, or NULL */
 struct sk_buff *
 ip_ct_gather_frags(struct sk_buff *skb);
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/include/linux/netfilter_ipv4/ip_conntrack_ftp.h linux-2.4.28-pre3/include/linux/netfilter_ipv4/ip_conntrack_ftp.h
--- linux-2.4.27/include/linux/netfilter_ipv4/ip_conntrack_ftp.h	2002-11-28 23:53:15.000000000 +0000
+++ linux-2.4.28-pre3/include/linux/netfilter_ipv4/ip_conntrack_ftp.h	2004-09-10 19:37:24.000000000 +0000
@@ -4,11 +4,6 @@
 
 #ifdef __KERNEL__
 
-#include <linux/netfilter_ipv4/lockhelp.h>
-
-/* Protects ftp part of conntracks */
-DECLARE_LOCK_EXTERN(ip_ftp_lock);
-
 #define FTP_PORT	21
 
 #endif /* __KERNEL__ */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/include/linux/netfilter_ipv4/ip_conntrack_irc.h linux-2.4.28-pre3/include/linux/netfilter_ipv4/ip_conntrack_irc.h
--- linux-2.4.27/include/linux/netfilter_ipv4/ip_conntrack_irc.h	2002-11-28 23:53:15.000000000 +0000
+++ linux-2.4.28-pre3/include/linux/netfilter_ipv4/ip_conntrack_irc.h	2004-09-10 19:34:06.000000000 +0000
@@ -33,8 +33,6 @@ struct ip_ct_irc_master {
 
 #ifdef __KERNEL__
 
-#include <linux/netfilter_ipv4/lockhelp.h>
-
 #define IRC_PORT	6667
 
 struct dccproto {
@@ -42,9 +40,6 @@ struct dccproto {
 	int matchlen;
 };
 
-/* Protects irc part of conntracks */
-DECLARE_LOCK_EXTERN(ip_irc_lock);
-
 #endif /* __KERNEL__ */
 
 #endif /* _IP_CONNTRACK_IRC_H */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/include/linux/nfsd/const.h linux-2.4.28-pre3/include/linux/nfsd/const.h
--- linux-2.4.27/include/linux/nfsd/const.h	2003-06-13 14:51:38.000000000 +0000
+++ linux-2.4.28-pre3/include/linux/nfsd/const.h	2004-09-10 19:35:42.000000000 +0000
@@ -12,6 +12,7 @@
 #include <linux/nfs.h>
 #include <linux/nfs2.h>
 #include <linux/nfs3.h>
+#include <asm/page.h>
 
 /*
  * Maximum protocol version supported by knfsd
@@ -19,9 +20,16 @@
 #define NFSSVC_MAXVERS		3
 
 /*
- * Maximum blocksize supported by daemon currently at 8K
+ * Maximum blocksize supported by daemon.  We want the largest
+ * value which 1) fits in a UDP datagram less some headers
+ * 2) is a multiple of page size 3) can be successfully kmalloc()ed
+ * by each nfsd.   
  */
-#define NFSSVC_MAXBLKSIZE	(8*1024)
+#if PAGE_SIZE > (16*1024)
+#define NFSSVC_MAXBLKSIZE	(32*1024)
+#else
+#define NFSSVC_MAXBLKSIZE	(2*PAGE_SIZE)
+#endif
 
 #ifdef __KERNEL__
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/include/linux/nfsd/xdr3.h linux-2.4.28-pre3/include/linux/nfsd/xdr3.h
--- linux-2.4.27/include/linux/nfsd/xdr3.h	2001-11-22 19:47:57.000000000 +0000
+++ linux-2.4.28-pre3/include/linux/nfsd/xdr3.h	2004-09-10 19:33:43.000000000 +0000
@@ -41,7 +41,7 @@ struct nfsd3_writeargs {
 	__u32			count;
 	int			stable;
 	__u8 *			data;
-	int			len;
+	__u32			len;
 };
 
 struct nfsd3_createargs {
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/include/linux/parport_pc.h linux-2.4.28-pre3/include/linux/parport_pc.h
--- linux-2.4.27/include/linux/parport_pc.h	2001-11-14 22:52:47.000000000 +0000
+++ linux-2.4.28-pre3/include/linux/parport_pc.h	2004-09-10 19:36:33.000000000 +0000
@@ -41,7 +41,7 @@ struct parport_pc_private {
 	struct pci_dev *dev;
 };
 
-extern __inline__ void parport_pc_write_data(struct parport *p, unsigned char d)
+static __inline__ void parport_pc_write_data(struct parport *p, unsigned char d)
 {
 #ifdef DEBUG_PARPORT
 	printk (KERN_DEBUG "parport_pc_write_data(%p,0x%02x)\n", p, d);
@@ -49,7 +49,7 @@ extern __inline__ void parport_pc_write_
 	outb(d, DATA(p));
 }
 
-extern __inline__ unsigned char parport_pc_read_data(struct parport *p)
+static __inline__ unsigned char parport_pc_read_data(struct parport *p)
 {
 	unsigned char val = inb (DATA (p));
 #ifdef DEBUG_PARPORT
@@ -124,17 +124,17 @@ static __inline__ unsigned char __parpor
 	return ctr;
 }
 
-extern __inline__ void parport_pc_data_reverse (struct parport *p)
+static __inline__ void parport_pc_data_reverse (struct parport *p)
 {
 	__parport_pc_frob_control (p, 0x20, 0x20);
 }
 
-extern __inline__ void parport_pc_data_forward (struct parport *p)
+static __inline__ void parport_pc_data_forward (struct parport *p)
 {
 	__parport_pc_frob_control (p, 0x20, 0x00);
 }
 
-extern __inline__ void parport_pc_write_control (struct parport *p,
+static __inline__ void parport_pc_write_control (struct parport *p,
 						 unsigned char d)
 {
 	const unsigned char wm = (PARPORT_CONTROL_STROBE |
@@ -152,7 +152,7 @@ extern __inline__ void parport_pc_write_
 	__parport_pc_frob_control (p, wm, d & wm);
 }
 
-extern __inline__ unsigned char parport_pc_read_control(struct parport *p)
+static __inline__ unsigned char parport_pc_read_control(struct parport *p)
 {
 	const unsigned char rm = (PARPORT_CONTROL_STROBE |
 				  PARPORT_CONTROL_AUTOFD |
@@ -162,7 +162,7 @@ extern __inline__ unsigned char parport_
 	return priv->ctr & rm; /* Use soft copy */
 }
 
-extern __inline__ unsigned char parport_pc_frob_control (struct parport *p,
+static __inline__ unsigned char parport_pc_frob_control (struct parport *p,
 							 unsigned char mask,
 							 unsigned char val)
 {
@@ -189,18 +189,18 @@ extern __inline__ unsigned char parport_
 	return __parport_pc_frob_control (p, mask, val);
 }
 
-extern __inline__ unsigned char parport_pc_read_status(struct parport *p)
+static __inline__ unsigned char parport_pc_read_status(struct parport *p)
 {
 	return inb(STATUS(p));
 }
 
 
-extern __inline__ void parport_pc_disable_irq(struct parport *p)
+static __inline__ void parport_pc_disable_irq(struct parport *p)
 {
 	__parport_pc_frob_control (p, 0x10, 0x00);
 }
 
-extern __inline__ void parport_pc_enable_irq(struct parport *p)
+static __inline__ void parport_pc_enable_irq(struct parport *p)
 {
 	__parport_pc_frob_control (p, 0x10, 0x10);
 }
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/include/linux/pci.h linux-2.4.28-pre3/include/linux/pci.h
--- linux-2.4.27/include/linux/pci.h	2004-08-07 23:26:06.000000000 +0000
+++ linux-2.4.28-pre3/include/linux/pci.h	2004-09-10 19:34:46.000000000 +0000
@@ -835,7 +835,5 @@ extern int pci_pci_problems;
 #define PCIPCI_VSFX		16
 #define PCIPCI_ALIMAGIK		32
 
-extern int pciehp_msi_quirk;
-
 #endif /* __KERNEL__ */
 #endif /* LINUX_PCI_H */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/include/linux/pci_ids.h linux-2.4.28-pre3/include/linux/pci_ids.h
--- linux-2.4.27/include/linux/pci_ids.h	2004-08-07 23:26:06.000000000 +0000
+++ linux-2.4.28-pre3/include/linux/pci_ids.h	2004-09-10 19:34:18.000000000 +0000
@@ -606,6 +606,7 @@
 #define PCI_DEVICE_ID_HP_ZX1_IOC	0x122a
 #define PCI_DEVICE_ID_HP_PCIX_LBA	0x122e
 #define PCI_DEVICE_ID_HP_SX1000_IOC	0x127c
+#define PCI_DEVICE_ID_HP_CISS		0x3210
 
 #define PCI_VENDOR_ID_PCTECH		0x1042
 #define PCI_DEVICE_ID_PCTECH_RZ1000	0x1000
@@ -980,13 +981,16 @@
 #define PCI_DEVICE_ID_NVIDIA_UVTNT2		0x002D
 #define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_IDE	0x0035
 #define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_SATA	0x0036
+#define PCI_DEVICE_ID_NVIDIA_MCP04_AUDIO	0x003a
 #define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_SATA2	0x003e
 #define PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_IDE	0x0053
 #define PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_SATA	0x0054
 #define PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_SATA2	0x0055
+#define PCI_DEVICE_ID_NVIDIA_CK804_AUDIO	0x0059
 #define PCI_DEVICE_ID_NVIDIA_NFORCE2_IDE	0x0065
 #define PCI_DEVICE_ID_NVIDIA_MCP2_AUDIO		0x006a
 #define PCI_DEVICE_ID_NVIDIA_NFORCE2S_IDE	0x0085
+#define PCI_DEVICE_ID_NVIDIA_MCP2S_AUDIO	0x008a
 #define PCI_DEVICE_ID_NVIDIA_NFORCE2S_SATA	0x008e
 #define PCI_DEVICE_ID_NVIDIA_ITNT2		0x00A0
 #define PCI_DEVICE_ID_NVIDIA_NFORCE3		0x00d1
@@ -995,6 +999,7 @@
 #define PCI_DEVICE_ID_NVIDIA_NFORCE3S		0x00e1
 #define PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA	0x00e3
 #define PCI_DEVICE_ID_NVIDIA_NFORCE3S_IDE	0x00e5
+#define PCI_DEVICE_ID_NVIDIA_CK8S_AUDIO		0x00ea
 #define PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA2	0x00ee
 #define PCI_DEVICE_ID_NVIDIA_GEFORCE_SDR	0x0100
 #define PCI_DEVICE_ID_NVIDIA_GEFORCE_DDR	0x0101
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/include/linux/pkt_sched.h linux-2.4.28-pre3/include/linux/pkt_sched.h
--- linux-2.4.27/include/linux/pkt_sched.h	2004-08-07 23:26:06.000000000 +0000
+++ linux-2.4.28-pre3/include/linux/pkt_sched.h	2004-09-10 19:36:01.000000000 +0000
@@ -433,6 +433,16 @@ enum {
 #define TCA_ATM_MAX	TCA_ATM_STATE
 
 /* Network emulator */
+
+enum
+{
+	TCA_NETEM_UNSPEC,
+	TCA_NETEM_CORR,
+	TCA_NETEM_DELAY_DIST,
+};
+
+#define TCA_NETEM_MAX	TCA_NETEM_DELAY_DIST
+
 struct tc_netem_qopt
 {
 	__u32	latency;	/* added delay (us) */
@@ -443,4 +453,13 @@ struct tc_netem_qopt
 	__u32	jitter;		/* random jitter in latency (us) */
 };
 
+struct tc_netem_corr
+{
+	__u32	delay_corr;	/* delay correlation */
+	__u32	loss_corr;	/* packet loss correlation */
+	__u32	dup_corr;	/* duplicate correlation  */
+};
+
+#define NETEM_DIST_SCALE	8192
+
 #endif
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/include/linux/rbtree.h linux-2.4.28-pre3/include/linux/rbtree.h
--- linux-2.4.27/include/linux/rbtree.h	2001-11-22 19:46:18.000000000 +0000
+++ linux-2.4.28-pre3/include/linux/rbtree.h	2004-09-10 19:34:03.000000000 +0000
@@ -121,6 +121,12 @@ rb_root_t;
 extern void rb_insert_color(rb_node_t *, rb_root_t *);
 extern void rb_erase(rb_node_t *, rb_root_t *);
 
+/* Find logical next and previous nodes in a tree */
+extern rb_node_t *rb_next(rb_node_t *);
+extern rb_node_t *rb_prev(rb_node_t *);
+extern rb_node_t *rb_first(rb_root_t *);
+extern rb_node_t *rb_last(rb_root_t *);
+
 static inline void rb_link_node(rb_node_t * node, rb_node_t * parent, rb_node_t ** rb_link)
 {
 	node->rb_parent = parent;
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/include/linux/reiserfs_fs.h linux-2.4.28-pre3/include/linux/reiserfs_fs.h
--- linux-2.4.27/include/linux/reiserfs_fs.h	2003-08-25 11:44:44.000000000 +0000
+++ linux-2.4.28-pre3/include/linux/reiserfs_fs.h	2004-09-10 19:36:41.000000000 +0000
@@ -1771,25 +1771,25 @@ int reiserfs_convert_objectid_map_v1(str
 /* stree.c */
 int B_IS_IN_TREE(const struct buffer_head *);
 extern inline void copy_short_key (void * to, const void * from);
-extern inline void copy_item_head(struct item_head * p_v_to, 
+extern void copy_item_head(struct item_head * p_v_to,
 								  const struct item_head * p_v_from);
 
 // first key is in cpu form, second - le
-extern inline int comp_keys (const struct key * le_key, 
+extern int comp_keys (const struct key * le_key,
 			     const struct cpu_key * cpu_key);
-extern inline int  comp_short_keys (const struct key * le_key, 
+extern int  comp_short_keys (const struct key * le_key,
 				    const struct cpu_key * cpu_key);
-extern inline void le_key2cpu_key (struct cpu_key * to, const struct key * from);
+extern void le_key2cpu_key (struct cpu_key * to, const struct key * from);
 
 // both are cpu keys
-extern inline int comp_cpu_keys (const struct cpu_key *, const struct cpu_key *);
-extern inline int comp_short_cpu_keys (const struct cpu_key *, 
+extern  int comp_cpu_keys (const struct cpu_key *, const struct cpu_key *);
+extern int comp_short_cpu_keys (const struct cpu_key *,
 				       const struct cpu_key *);
-extern inline void cpu_key2cpu_key (struct cpu_key *, const struct cpu_key *);
+extern void cpu_key2cpu_key (struct cpu_key *, const struct cpu_key *);
 
 // both are in le form
-extern inline int comp_le_keys (const struct key *, const struct key *);
-extern inline int comp_short_le_keys (const struct key *, const struct key *);
+extern int comp_le_keys (const struct key *, const struct key *);
+extern int comp_short_le_keys (const struct key *, const struct key *);
 
 //
 // get key version from on disk key - kludge
@@ -1824,7 +1824,7 @@ int search_by_key (struct super_block *,
 int search_for_position_by_key (struct super_block * p_s_sb, 
 								const struct cpu_key * p_s_cpu_key, 
 								struct path * p_s_search_path);
-extern inline void decrement_bcount (struct buffer_head * p_s_bh);
+extern void decrement_bcount (struct buffer_head * p_s_bh);
 void decrement_counters_in_path (struct path * p_s_search_path);
 void pathrelse (struct path * p_s_search_path);
 int reiserfs_check_path(struct path *p) ;
@@ -1902,7 +1902,7 @@ void sd_attrs_to_i_attrs( __u16 sd_attrs
 void i_attrs_to_sd_attrs( struct inode *inode, __u16 *sd_attrs );
 
 /* namei.c */
-inline void set_de_name_and_namelen (struct reiserfs_dir_entry * de);
+void set_de_name_and_namelen (struct reiserfs_dir_entry * de);
 int search_by_entry_key (struct super_block * sb, const struct cpu_key * key, 
 			 struct path * path, 
 			 struct reiserfs_dir_entry * de);
@@ -2050,7 +2050,7 @@ int balance_internal (struct tree_balanc
                       struct buffer_head **);
 
 /* do_balance.c */
-inline void do_balance_mark_leaf_dirty (struct tree_balance * tb, 
+void do_balance_mark_leaf_dirty (struct tree_balance * tb,
 					struct buffer_head * bh, int flag);
 #define do_balance_mark_internal_dirty do_balance_mark_leaf_dirty
 #define do_balance_mark_sb_dirty do_balance_mark_leaf_dirty
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/include/linux/sched.h linux-2.4.28-pre3/include/linux/sched.h
--- linux-2.4.27/include/linux/sched.h	2004-08-07 23:26:06.000000000 +0000
+++ linux-2.4.28-pre3/include/linux/sched.h	2004-09-10 19:32:37.000000000 +0000
@@ -763,7 +763,7 @@ extern struct mm_struct * start_lazy_tlb
 extern void end_lazy_tlb(struct mm_struct *mm);
 
 /* mmdrop drops the mm and the page tables */
-extern inline void FASTCALL(__mmdrop(struct mm_struct *));
+extern void FASTCALL(__mmdrop(struct mm_struct *));
 static inline void mmdrop(struct mm_struct * mm)
 {
 	if (atomic_dec_and_test(&mm->mm_count))
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/include/linux/usb.h linux-2.4.28-pre3/include/linux/usb.h
--- linux-2.4.27/include/linux/usb.h	2003-11-28 18:26:21.000000000 +0000
+++ linux-2.4.28-pre3/include/linux/usb.h	2004-09-10 19:34:29.000000000 +0000
@@ -828,6 +828,8 @@ struct usb_device {
 
 	atomic_t refcnt;		/* Reference count */
 	struct semaphore serialize;
+	struct semaphore exclusive_access; /* prevent driver & proc accesses  */
+					   /* from overlapping cmds at device */
 
 	unsigned int toggle[2];		/* one bit for each endpoint ([0] = IN, [1] = OUT) */
 	unsigned int halted[2];		/* endpoint halts; one bit per endpoint # & direction; */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/include/net/if_inet6.h linux-2.4.28-pre3/include/net/if_inet6.h
--- linux-2.4.27/include/net/if_inet6.h	2003-11-28 18:26:21.000000000 +0000
+++ linux-2.4.28-pre3/include/net/if_inet6.h	2004-09-10 19:37:07.000000000 +0000
@@ -3,7 +3,7 @@
  *	Linux INET6 implementation 
  *
  *	Authors:
- *	Pedro Roque		<roque@di.fc.ul.pt>	
+ *	Pedro Roque		<pedro_m@yahoo.com>	
  *
  *
  *	This program is free software; you can redistribute it and/or
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/include/net/ip.h linux-2.4.28-pre3/include/net/ip.h
--- linux-2.4.27/include/net/ip.h	2003-11-28 18:26:21.000000000 +0000
+++ linux-2.4.28-pre3/include/net/ip.h	2004-09-10 19:35:52.000000000 +0000
@@ -137,7 +137,7 @@ struct ip_reply_arg {
 void ip_send_reply(struct sock *sk, struct sk_buff *skb, struct ip_reply_arg *arg,
 		   unsigned int len); 
 
-extern __inline__ int ip_finish_output(struct sk_buff *skb);
+extern int ip_finish_output(struct sk_buff *skb);
 
 struct ipv4_config
 {
@@ -228,6 +228,7 @@ extern int	ip_call_ra_chain(struct sk_bu
  */
  
 struct sk_buff *ip_defrag(struct sk_buff *skb);
+extern void ipfrag_flush(void);
 extern int ip_frag_nqueues;
 extern atomic_t ip_frag_mem;
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/include/net/ip6_fib.h linux-2.4.28-pre3/include/net/ip6_fib.h
--- linux-2.4.27/include/net/ip6_fib.h	2003-08-25 11:44:44.000000000 +0000
+++ linux-2.4.28-pre3/include/net/ip6_fib.h	2004-09-10 19:36:10.000000000 +0000
@@ -2,7 +2,7 @@
  *	Linux INET6 implementation 
  *
  *	Authors:
- *	Pedro Roque		<roque@di.fc.ul.pt>	
+ *	Pedro Roque		<pedro_m@yahoo.com>	
  *
  *	This program is free software; you can redistribute it and/or
  *      modify it under the terms of the GNU General Public License
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/include/net/ipv6.h linux-2.4.28-pre3/include/net/ipv6.h
--- linux-2.4.27/include/net/ipv6.h	2004-04-14 13:05:40.000000000 +0000
+++ linux-2.4.28-pre3/include/net/ipv6.h	2004-09-10 19:36:28.000000000 +0000
@@ -2,7 +2,7 @@
  *	Linux INET6 implementation
  *
  *	Authors:
- *	Pedro Roque		<roque@di.fc.ul.pt>
+ *	Pedro Roque		<pedro_m@yahoo.com>
  *
  *	$Id: ipv6.h,v 1.23 2000/12/13 18:31:48 davem Exp $
  *
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/include/net/irda/irlmp_frame.h linux-2.4.28-pre3/include/net/irda/irlmp_frame.h
--- linux-2.4.27/include/net/irda/irlmp_frame.h	2000-12-11 21:33:22.000000000 +0000
+++ linux-2.4.28-pre3/include/net/irda/irlmp_frame.h	2004-09-10 19:33:34.000000000 +0000
@@ -40,7 +40,7 @@
 
 #define CONTROL_BIT    0x80
 
-inline void irlmp_send_data_pdu(struct lap_cb *self, __u8 dlsap, __u8 slsap, 
+void irlmp_send_data_pdu(struct lap_cb *self, __u8 dlsap, __u8 slsap, 
 				int expedited, struct sk_buff *skb);
 void irlmp_send_lcf_pdu(struct lap_cb *self, __u8 dlsap, __u8 slsap, 
 			__u8 opcode, struct sk_buff *skb);
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/include/net/irda/timer.h linux-2.4.28-pre3/include/net/irda/timer.h
--- linux-2.4.27/include/net/irda/timer.h	2001-11-09 22:22:17.000000000 +0000
+++ linux-2.4.28-pre3/include/net/irda/timer.h	2004-09-10 19:32:03.000000000 +0000
@@ -72,21 +72,21 @@ typedef void (*TIMER_CALLBACK)(void *);
 void irda_start_timer(struct timer_list *ptimer, int timeout, void* data,
 		      TIMER_CALLBACK callback);
 
-inline void irlap_start_slot_timer(struct irlap_cb *self, int timeout);
-inline void irlap_start_query_timer(struct irlap_cb *self, int timeout);
-inline void irlap_start_final_timer(struct irlap_cb *self, int timeout);
-inline void irlap_start_wd_timer(struct irlap_cb *self, int timeout);
-inline void irlap_start_backoff_timer(struct irlap_cb *self, int timeout);
+void irlap_start_slot_timer(struct irlap_cb *self, int timeout);
+void irlap_start_query_timer(struct irlap_cb *self, int timeout);
+void irlap_start_final_timer(struct irlap_cb *self, int timeout);
+void irlap_start_wd_timer(struct irlap_cb *self, int timeout);
+void irlap_start_backoff_timer(struct irlap_cb *self, int timeout);
 
 void irlap_start_mbusy_timer(struct irlap_cb *self, int timeout);
 void irlap_stop_mbusy_timer(struct irlap_cb *);
 
 struct lsap_cb;
 struct lap_cb;
-inline void irlmp_start_watchdog_timer(struct lsap_cb *, int timeout);
-inline void irlmp_start_discovery_timer(struct irlmp_cb *, int timeout);
-inline void irlmp_start_idle_timer(struct lap_cb *, int timeout);
-inline void irlmp_stop_idle_timer(struct lap_cb *self); 
+void irlmp_start_watchdog_timer(struct lsap_cb *, int timeout);
+void irlmp_start_discovery_timer(struct irlmp_cb *, int timeout);
+void irlmp_start_idle_timer(struct lap_cb *, int timeout);
+void irlmp_stop_idle_timer(struct lap_cb *self); 
 
 #endif
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/include/net/neighbour.h linux-2.4.28-pre3/include/net/neighbour.h
--- linux-2.4.27/include/net/neighbour.h	2003-11-28 18:26:21.000000000 +0000
+++ linux-2.4.28-pre3/include/net/neighbour.h	2004-09-10 19:37:07.000000000 +0000
@@ -5,7 +5,7 @@
  *	Generic neighbour manipulation
  *
  *	Authors:
- *	Pedro Roque		<roque@di.fc.ul.pt>
+ *	Pedro Roque		<pedro_m@yahoo.com>
  *	Alexey Kuznetsov	<kuznet@ms2.inr.ac.ru>
  */
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/include/net/pkt_sched.h linux-2.4.28-pre3/include/net/pkt_sched.h
--- linux-2.4.27/include/net/pkt_sched.h	2004-02-18 13:36:32.000000000 +0000
+++ linux-2.4.28-pre3/include/net/pkt_sched.h	2004-09-10 19:33:03.000000000 +0000
@@ -80,11 +80,11 @@ struct Qdisc
 #define TCQ_F_THROTTLED	2
 #define TCQ_F_INGRES	4
 	struct Qdisc_ops	*ops;
-	struct Qdisc		*next;
 	u32			handle;
 	atomic_t		refcnt;
 	struct sk_buff_head	q;
 	struct net_device	*dev;
+	struct list_head	list;
 
 	struct tc_stats		stats;
 	int			(*reshape_fail)(struct sk_buff *skb, struct Qdisc *q);
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/include/net/sctp/command.h linux-2.4.28-pre3/include/net/sctp/command.h
--- linux-2.4.27/include/net/sctp/command.h	2004-08-07 23:26:06.000000000 +0000
+++ linux-2.4.28-pre3/include/net/sctp/command.h	2004-09-10 19:36:21.000000000 +0000
@@ -94,6 +94,9 @@ typedef enum {
 	SCTP_CMD_REPORT_FWDTSN,	 /* Report new cumulative TSN Ack. */
 	SCTP_CMD_PROCESS_FWDTSN, /* Skips were reported, so process further. */
 	SCTP_CMD_CLEAR_INIT_TAG, /* Clears association peer's inittag. */
+	SCTP_CMD_DEL_NON_PRIMARY, /* Removes non-primary peer transports. */
+	SCTP_CMD_T3_RTX_TIMERS_STOP, /* Stops T3-rtx pending timers */
+	SCTP_CMD_FORCE_PRIM_RETRAN,  /* Forces retrans. over primary path. */
 	SCTP_CMD_LAST
 } sctp_verb_t;
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/include/net/sctp/constants.h linux-2.4.28-pre3/include/net/sctp/constants.h
--- linux-2.4.27/include/net/sctp/constants.h	2004-08-07 23:26:06.000000000 +0000
+++ linux-2.4.28-pre3/include/net/sctp/constants.h	2004-09-10 19:31:59.000000000 +0000
@@ -175,6 +175,10 @@ typedef enum {
 	SCTP_IERROR_BAD_TAG,
 	SCTP_IERROR_BIG_GAP,
 	SCTP_IERROR_DUP_TSN,
+	SCTP_IERROR_HIGH_TSN,
+	SCTP_IERROR_IGNORE_TSN,
+	SCTP_IERROR_NO_DATA,
+	SCTP_IERROR_BAD_STREAM,
 
 } sctp_ierror_t;
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/include/net/sctp/sm.h linux-2.4.28-pre3/include/net/sctp/sm.h
--- linux-2.4.27/include/net/sctp/sm.h	2004-08-07 23:26:06.000000000 +0000
+++ linux-2.4.28-pre3/include/net/sctp/sm.h	2004-09-10 19:33:49.000000000 +0000
@@ -322,6 +322,9 @@ void sctp_send_stale_cookie_err(const st
 				const struct sctp_chunk *chunk,
 				sctp_cmd_seq_t *commands,
 				struct sctp_chunk *err_chunk);
+int sctp_eat_data(const struct sctp_association *asoc,
+		  struct sctp_chunk *chunk,
+		  sctp_cmd_seq_t *commands);
 
 /* 3rd level prototypes */
 __u32 sctp_generate_tag(const struct sctp_endpoint *);
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/include/scsi/scsi.h linux-2.4.28-pre3/include/scsi/scsi.h
--- linux-2.4.27/include/scsi/scsi.h	2003-11-28 18:26:21.000000000 +0000
+++ linux-2.4.28-pre3/include/scsi/scsi.h	2004-09-10 19:37:12.000000000 +0000
@@ -91,6 +91,7 @@
 #define WRITE_LONG_2          0xea
 #define READ_16               0x88
 #define WRITE_16              0x8a
+#define VERIFY_16	      0x8f
 #define SERVICE_ACTION_IN     0x9e
 /* values for service action in */
 #define SAI_READ_CAPACITY_16  0x10
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/kernel/fork.c linux-2.4.28-pre3/kernel/fork.c
--- linux-2.4.27/kernel/fork.c	2004-04-14 13:05:40.000000000 +0000
+++ linux-2.4.28-pre3/kernel/fork.c	2004-09-10 19:32:37.000000000 +0000
@@ -39,7 +39,7 @@ int last_pid;
 
 struct task_struct *pidhash[PIDHASH_SZ];
 
-void add_wait_queue(wait_queue_head_t *q, wait_queue_t * wait)
+void fastcall add_wait_queue(wait_queue_head_t *q, wait_queue_t * wait)
 {
 	unsigned long flags;
 
@@ -49,7 +49,7 @@ void add_wait_queue(wait_queue_head_t *q
 	wq_write_unlock_irqrestore(&q->lock, flags);
 }
 
-void add_wait_queue_exclusive(wait_queue_head_t *q, wait_queue_t * wait)
+void fastcall add_wait_queue_exclusive(wait_queue_head_t *q, wait_queue_t * wait)
 {
 	unsigned long flags;
 
@@ -59,7 +59,7 @@ void add_wait_queue_exclusive(wait_queue
 	wq_write_unlock_irqrestore(&q->lock, flags);
 }
 
-void remove_wait_queue(wait_queue_head_t *q, wait_queue_t * wait)
+void fastcall remove_wait_queue(wait_queue_head_t *q, wait_queue_t * wait)
 {
 	unsigned long flags;
 
@@ -264,7 +264,7 @@ struct mm_struct * mm_alloc(void)
  * is dropped: either by a lazy thread or by
  * mmput. Free the page directory and the mm.
  */
-inline void __mmdrop(struct mm_struct *mm)
+void fastcall __mmdrop(struct mm_struct *mm)
 {
 	BUG_ON(mm == &init_mm);
 	pgd_free(mm->pgd);
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/kernel/panic.c linux-2.4.28-pre3/kernel/panic.c
--- linux-2.4.27/kernel/panic.c	2003-11-28 18:26:21.000000000 +0000
+++ linux-2.4.28-pre3/kernel/panic.c	2004-09-10 19:36:59.000000000 +0000
@@ -59,7 +59,7 @@ NORET_TYPE void panic(const char * fmt, 
 	
 	bust_spinlocks(1);
 	va_start(args, fmt);
-	vsprintf(buf, fmt, args);
+	vsnprintf(buf, sizeof(buf), fmt, args);
 	va_end(args);
 	printk(KERN_EMERG "Kernel panic: %s\n",buf);
 	if (in_interrupt())
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/kernel/sched.c linux-2.4.28-pre3/kernel/sched.c
--- linux-2.4.27/kernel/sched.c	2003-11-28 18:26:21.000000000 +0000
+++ linux-2.4.28-pre3/kernel/sched.c	2004-09-10 19:36:20.000000000 +0000
@@ -209,7 +209,7 @@ static inline int preemption_goodness(st
  */
 static FASTCALL(void reschedule_idle(struct task_struct * p));
 
-static void reschedule_idle(struct task_struct * p)
+static void fastcall reschedule_idle(struct task_struct * p)
 {
 #ifdef CONFIG_SMP
 	int this_cpu = smp_processor_id();
@@ -367,7 +367,7 @@ out:
 	return success;
 }
 
-inline int wake_up_process(struct task_struct * p)
+inline int fastcall wake_up_process(struct task_struct * p)
 {
 	return try_to_wake_up(p, 0);
 }
@@ -405,7 +405,7 @@ static void process_timeout(unsigned lon
  *
  * In all cases the return value is guaranteed to be non-negative.
  */
-signed long schedule_timeout(signed long timeout)
+signed long fastcall schedule_timeout(signed long timeout)
 {
 	struct timer_list timer;
 	unsigned long expire;
@@ -735,7 +735,7 @@ static inline void __wake_up_common (wai
 	}
 }
 
-void __wake_up(wait_queue_head_t *q, unsigned int mode, int nr)
+void fastcall __wake_up(wait_queue_head_t *q, unsigned int mode, int nr)
 {
 	if (q) {
 		unsigned long flags;
@@ -745,7 +745,7 @@ void __wake_up(wait_queue_head_t *q, uns
 	}
 }
 
-void __wake_up_sync(wait_queue_head_t *q, unsigned int mode, int nr)
+void fastcall __wake_up_sync(wait_queue_head_t *q, unsigned int mode, int nr)
 {
 	if (q) {
 		unsigned long flags;
@@ -755,7 +755,7 @@ void __wake_up_sync(wait_queue_head_t *q
 	}
 }
 
-void complete(struct completion *x)
+void fastcall complete(struct completion *x)
 {
 	unsigned long flags;
 
@@ -765,7 +765,7 @@ void complete(struct completion *x)
 	spin_unlock_irqrestore(&x->wait.lock, flags);
 }
 
-void wait_for_completion(struct completion *x)
+void fastcall wait_for_completion(struct completion *x)
 {
 	spin_lock_irq(&x->wait.lock);
 	if (!x->done) {
@@ -800,7 +800,7 @@ void wait_for_completion(struct completi
 	__remove_wait_queue(q, &wait);				\
 	wq_write_unlock_irqrestore(&q->lock,flags);
 
-void interruptible_sleep_on(wait_queue_head_t *q)
+void fastcall interruptible_sleep_on(wait_queue_head_t *q)
 {
 	SLEEP_ON_VAR
 
@@ -811,7 +811,7 @@ void interruptible_sleep_on(wait_queue_h
 	SLEEP_ON_TAIL
 }
 
-long interruptible_sleep_on_timeout(wait_queue_head_t *q, long timeout)
+long fastcall interruptible_sleep_on_timeout(wait_queue_head_t *q, long timeout)
 {
 	SLEEP_ON_VAR
 
@@ -824,7 +824,7 @@ long interruptible_sleep_on_timeout(wait
 	return timeout;
 }
 
-void sleep_on(wait_queue_head_t *q)
+void fastcall sleep_on(wait_queue_head_t *q)
 {
 	SLEEP_ON_VAR
 	
@@ -835,7 +835,7 @@ void sleep_on(wait_queue_head_t *q)
 	SLEEP_ON_TAIL
 }
 
-long sleep_on_timeout(wait_queue_head_t *q, long timeout)
+long fastcall sleep_on_timeout(wait_queue_head_t *q, long timeout)
 {
 	SLEEP_ON_VAR
 	
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/kernel/softirq.c linux-2.4.28-pre3/kernel/softirq.c
--- linux-2.4.27/kernel/softirq.c	2002-11-28 23:53:15.000000000 +0000
+++ linux-2.4.28-pre3/kernel/softirq.c	2004-09-10 19:33:21.000000000 +0000
@@ -111,7 +111,7 @@ restart:
 /*
  * This function must run with irq disabled!
  */
-inline void cpu_raise_softirq(unsigned int cpu, unsigned int nr)
+inline fastcall void cpu_raise_softirq(unsigned int cpu, unsigned int nr)
 {
 	__cpu_raise_softirq(cpu, nr);
 
@@ -128,7 +128,7 @@ inline void cpu_raise_softirq(unsigned i
 		wakeup_softirqd(cpu);
 }
 
-void raise_softirq(unsigned int nr)
+void fastcall raise_softirq(unsigned int nr)
 {
 	unsigned long flags;
 
@@ -149,7 +149,7 @@ void open_softirq(int nr, void (*action)
 struct tasklet_head tasklet_vec[NR_CPUS] __cacheline_aligned;
 struct tasklet_head tasklet_hi_vec[NR_CPUS] __cacheline_aligned;
 
-void __tasklet_schedule(struct tasklet_struct *t)
+void fastcall __tasklet_schedule(struct tasklet_struct *t)
 {
 	int cpu = smp_processor_id();
 	unsigned long flags;
@@ -161,7 +161,7 @@ void __tasklet_schedule(struct tasklet_s
 	local_irq_restore(flags);
 }
 
-void __tasklet_hi_schedule(struct tasklet_struct *t)
+void fastcall __tasklet_hi_schedule(struct tasklet_struct *t)
 {
 	int cpu = smp_processor_id();
 	unsigned long flags;
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/kernel/sysctl.c linux-2.4.28-pre3/kernel/sysctl.c
--- linux-2.4.27/kernel/sysctl.c	2004-08-07 23:26:06.000000000 +0000
+++ linux-2.4.28-pre3/kernel/sysctl.c	2004-09-10 19:32:38.000000000 +0000
@@ -879,7 +879,7 @@ static int do_proc_dointvec(ctl_table *t
 				if (!isspace(c))
 					break;
 				left--;
-				((char *) buffer)++;
+				buffer++;
 			}
 			if (!left)
 				break;
@@ -1032,7 +1032,7 @@ int proc_dointvec_minmax(ctl_table *tabl
 				if (!isspace(c))
 					break;
 				left--;
-				((char *) buffer)++;
+				buffer++;
 			}
 			if (!left)
 				break;
@@ -1133,7 +1133,7 @@ static int do_proc_doulongvec_minmax(ctl
 				if (!isspace(c))
 					break;
 				left--;
-				((char *) buffer)++;
+				buffer++;
 			}
 			if (!left)
 				break;
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/lib/brlock.c linux-2.4.28-pre3/lib/brlock.c
--- linux-2.4.27/lib/brlock.c	2001-11-09 22:11:15.000000000 +0000
+++ linux-2.4.28-pre3/lib/brlock.c	2004-09-10 19:35:56.000000000 +0000
@@ -20,7 +20,7 @@
 brlock_read_lock_t __brlock_array[NR_CPUS][__BR_IDX_MAX] =
    { [0 ... NR_CPUS-1] = { [0 ... __BR_IDX_MAX-1] = RW_LOCK_UNLOCKED } };
 
-void __br_write_lock (enum brlock_indices idx)
+void fastcall __br_write_lock (enum brlock_indices idx)
 {
 	int i;
 
@@ -28,7 +28,7 @@ void __br_write_lock (enum brlock_indice
 		write_lock(&__brlock_array[cpu_logical_map(i)][idx]);
 }
 
-void __br_write_unlock (enum brlock_indices idx)
+void fastcall __br_write_unlock (enum brlock_indices idx)
 {
 	int i;
 
@@ -44,7 +44,7 @@ brlock_read_lock_t __brlock_array[NR_CPU
 struct br_wrlock __br_write_locks[__BR_IDX_MAX] =
    { [0 ... __BR_IDX_MAX-1] = { SPIN_LOCK_UNLOCKED } };
 
-void __br_write_lock (enum brlock_indices idx)
+void fastcall __br_write_lock (enum brlock_indices idx)
 {
 	int i;
 
@@ -59,7 +59,7 @@ again:
 		}
 }
 
-void __br_write_unlock (enum brlock_indices idx)
+void fastcall __br_write_unlock (enum brlock_indices idx)
 {
 	spin_unlock(&__br_write_locks[idx].lock);
 }
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/lib/crc32.c linux-2.4.28-pre3/lib/crc32.c
--- linux-2.4.27/lib/crc32.c	2004-04-14 13:05:40.000000000 +0000
+++ linux-2.4.28-pre3/lib/crc32.c	2004-09-10 19:31:52.000000000 +0000
@@ -99,7 +99,9 @@ u32 attribute((pure)) crc32_le(u32 crc, 
 	/* Align it */
 	if(unlikely(((long)b)&3 && len)){
 		do {
-			DO_CRC(*((u8 *)b)++);
+			u8 *p = (u8 *)b;
+			DO_CRC(*p++);
+			b = (void *)p;
 		} while ((--len) && ((long)b)&3 );
 	}
 	if(likely(len >= 4)){
@@ -120,7 +122,9 @@ u32 attribute((pure)) crc32_le(u32 crc, 
 	/* And the last few bytes */
 	if(len){
 		do {
-			DO_CRC(*((u8 *)b)++);
+			u8 *p = (u8 *)b;
+			DO_CRC(*p++);
+			b = (void *)p;
 		} while (--len);
 	}
 
@@ -200,7 +204,9 @@ u32 attribute((pure)) crc32_be(u32 crc, 
 	/* Align it */
 	if(unlikely(((long)b)&3 && len)){
 		do {
-			DO_CRC(*((u8 *)b)++);
+			u8 *p = (u8 *)b;
+			DO_CRC(*p++);
+			b = (u32 *)p;
 		} while ((--len) && ((long)b)&3 );
 	}
 	if(likely(len >= 4)){
@@ -221,7 +227,9 @@ u32 attribute((pure)) crc32_be(u32 crc, 
 	/* And the last few bytes */
 	if(len){
 		do {
-			DO_CRC(*((u8 *)b)++);
+			u8 *p = (u8 *)b;
+			DO_CRC(*p++);
+			b = (void *)p;
 		} while (--len);
 	}
 	return __be32_to_cpu(crc);
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/lib/rbtree.c linux-2.4.28-pre3/lib/rbtree.c
--- linux-2.4.27/lib/rbtree.c	2002-08-03 00:39:46.000000000 +0000
+++ linux-2.4.28-pre3/lib/rbtree.c	2004-09-10 19:35:37.000000000 +0000
@@ -294,3 +294,74 @@ void rb_erase(rb_node_t * node, rb_root_
 		__rb_erase_color(child, parent, root);
 }
 EXPORT_SYMBOL(rb_erase);
+
+/*
+ * This function returns the first node (in sort order) of the tree.
+ */
+rb_node_t *rb_first(rb_root_t *root)
+{
+	rb_node_t *n;
+
+	n = root->rb_node;
+	if (!n)
+		return NULL;
+	while (n->rb_left)
+		n = n->rb_left;
+	return n;
+}
+EXPORT_SYMBOL(rb_first);
+
+rb_node_t *rb_last(rb_root_t *root)
+{
+	rb_node_t *n;
+
+	n = root->rb_node;
+	if (!n)
+		return NULL;
+	while (n->rb_right)
+		n = n->rb_right;
+	return n;
+}
+EXPORT_SYMBOL(rb_last);
+
+rb_node_t *rb_next(rb_node_t *node)
+{
+	/* If we have a right-hand child, go down and then left as far
+	   as we can. */
+	if (node->rb_right) {
+		node = node->rb_right;
+		while (node->rb_left)
+			node = node->rb_left;
+	}
+
+	/* No right-hand children.  Everything down and left is
+	   smaller than us, so any 'next' node must be in the general
+	   direction of our parent. Go up the tree; any time the
+	   ancestor is a right-hand child of its parent, keep going
+	   up. First time it's a left-hand child of its parent, said
+	   parent is our 'next' node. */
+	while (node->rb_parent && node == node->rb_parent->rb_right)
+		node = node->rb_parent;
+
+	return node->rb_parent;
+}
+EXPORT_SYMBOL(rb_next);
+
+rb_node_t *rb_prev(rb_node_t *node)
+{
+	/* If we have a left-hand child, go down and then right as far
+	   as we can. */
+	if (node->rb_left) {
+		node = node->rb_left;
+		while (node->rb_right)
+			node = node->rb_right;	 
+	}
+
+	/* No left-hand children. Go up till we find an ancestor which
+	   is a right-hand child of its parent */
+	while (node->rb_parent && node == node->rb_parent->rb_left)
+		node = node->rb_parent;
+
+	return node->rb_parent;
+}
+EXPORT_SYMBOL(rb_prev);
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/lib/rwsem.c linux-2.4.28-pre3/lib/rwsem.c
--- linux-2.4.27/lib/rwsem.c	2004-08-07 23:26:06.000000000 +0000
+++ linux-2.4.28-pre3/lib/rwsem.c	2004-09-10 19:32:08.000000000 +0000
@@ -160,7 +160,7 @@ static inline struct rw_semaphore *rwsem
 /*
  * wait for the read lock to be granted
  */
-struct rw_semaphore *rwsem_down_read_failed(struct rw_semaphore *sem)
+struct rw_semaphore fastcall *rwsem_down_read_failed(struct rw_semaphore *sem)
 {
 	struct rwsem_waiter waiter;
 
@@ -176,7 +176,7 @@ struct rw_semaphore *rwsem_down_read_fai
 /*
  * wait for the write lock to be granted
  */
-struct rw_semaphore *rwsem_down_write_failed(struct rw_semaphore *sem)
+struct rw_semaphore fastcall *rwsem_down_write_failed(struct rw_semaphore *sem)
 {
 	struct rwsem_waiter waiter;
 
@@ -193,7 +193,7 @@ struct rw_semaphore *rwsem_down_write_fa
  * handle waking up a waiter on the semaphore
  * - up_read has decremented the active part of the count if we come here
  */
-struct rw_semaphore *rwsem_wake(struct rw_semaphore *sem)
+struct rw_semaphore fastcall *rwsem_wake(struct rw_semaphore *sem)
 {
 	rwsemtrace(sem,"Entering rwsem_wake");
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/lib/string.c linux-2.4.28-pre3/lib/string.c
--- linux-2.4.27/lib/string.c	2002-08-03 00:39:46.000000000 +0000
+++ linux-2.4.28-pre3/lib/string.c	2004-09-10 19:36:36.000000000 +0000
@@ -380,14 +380,13 @@ void * memset(void * s,int c,size_t coun
  * You should not use this function to access IO space, use memcpy_toio()
  * or memcpy_fromio() instead.
  */
-char * bcopy(const char * src, char * dest, int count)
+void bcopy(const void * srcp, void * destp, size_t count)
 {
-	char *tmp = dest;
+	const char *src = srcp;
+	char *dest = destp;
 
 	while (count--)
-		*tmp++ = *src++;
-
-	return dest;
+		*dest++ = *src++;
 }
 #endif
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/mm/filemap.c linux-2.4.28-pre3/mm/filemap.c
--- linux-2.4.27/mm/filemap.c	2004-04-14 13:05:41.000000000 +0000
+++ linux-2.4.28-pre3/mm/filemap.c	2004-09-10 19:33:53.000000000 +0000
@@ -68,7 +68,7 @@ spinlock_cacheline_t pagemap_lru_lock_ca
 #define CLUSTER_OFFSET(x)	(((x) >> page_cluster) << page_cluster)
 
 static void FASTCALL(add_page_to_hash_queue(struct page * page, struct page **p));
-static void add_page_to_hash_queue(struct page * page, struct page **p)
+static void fastcall add_page_to_hash_queue(struct page * page, struct page **p)
 {
 	struct page *next = *p;
 
@@ -151,7 +151,7 @@ static inline int sync_page(struct page 
 /*
  * Add a page to the dirty page list.
  */
-void set_page_dirty(struct page *page)
+void fastcall set_page_dirty(struct page *page)
 {
 	if (!test_and_set_bit(PG_dirty, &page->flags)) {
 		struct address_space *mapping = page->mapping;
@@ -260,7 +260,7 @@ static void truncate_complete_page(struc
 }
 
 static int FASTCALL(truncate_list_pages(struct list_head *, unsigned long, unsigned *));
-static int truncate_list_pages(struct list_head *head, unsigned long start, unsigned *partial)
+static int fastcall truncate_list_pages(struct list_head *head, unsigned long start, unsigned *partial)
 {
 	struct list_head *curr;
 	struct page * page;
@@ -382,7 +382,7 @@ static inline int invalidate_this_page2(
 }
 
 static int FASTCALL(invalidate_list_pages2(struct list_head *));
-static int invalidate_list_pages2(struct list_head *head)
+static int fastcall invalidate_list_pages2(struct list_head *head)
 {
 	struct list_head *curr;
 	struct page * page;
@@ -755,7 +755,7 @@ int add_to_page_cache_unique(struct page
  * and schedules an I/O to read in its contents from disk.
  */
 static int FASTCALL(page_cache_read(struct file * file, unsigned long offset));
-static int page_cache_read(struct file * file, unsigned long offset)
+static int fastcall page_cache_read(struct file * file, unsigned long offset)
 {
 	struct address_space *mapping = file->f_dentry->d_inode->i_mapping;
 	struct page **hash = page_hash(mapping, offset);
@@ -790,7 +790,7 @@ static int page_cache_read(struct file *
  */
 static int FASTCALL(read_cluster_nonblocking(struct file * file, unsigned long offset,
 					     unsigned long filesize));
-static int read_cluster_nonblocking(struct file * file, unsigned long offset,
+static int fastcall read_cluster_nonblocking(struct file * file, unsigned long offset,
 	unsigned long filesize)
 {
 	unsigned long pages = CLUSTER_PAGES;
@@ -871,7 +871,7 @@ static inline wait_queue_head_t *page_wa
  * callbacks that would result into the blkdev layer waking
  * up the page after a queue unplug.
  */
-void wakeup_page_waiters(struct page * page)
+void fastcall wakeup_page_waiters(struct page * page)
 {
 	wait_queue_head_t * head;
 
@@ -927,7 +927,7 @@ void ___wait_on_page(struct page *page)
  * of the waiters for all of the pages in the appropriate
  * wait queue are woken.
  */
-void unlock_page(struct page *page)
+void fastcall unlock_page(struct page *page)
 {
 	wait_queue_head_t *waitqueue = page_waitqueue(page);
 	ClearPageLaunder(page);
@@ -974,7 +974,7 @@ static void __lock_page(struct page *pag
  * Get an exclusive lock on the page, optimistically
  * assuming it's not locked..
  */
-void lock_page(struct page *page)
+void fastcall lock_page(struct page *page)
 {
 	if (TryLockPage(page))
 		__lock_page(page);
@@ -1025,7 +1025,7 @@ struct page *find_trylock_page(struct ad
  * during blocking operations..
  */
 static struct page * FASTCALL(__find_lock_page_helper(struct address_space *, unsigned long, struct page *));
-static struct page * __find_lock_page_helper(struct address_space *mapping,
+static struct page * fastcall __find_lock_page_helper(struct address_space *mapping,
 					unsigned long offset, struct page *hash)
 {
 	struct page *page;
@@ -1388,7 +1388,7 @@ static void generic_file_readahead(int r
  * If it was already so marked, move it to the active queue and drop
  * the referenced bit.  Otherwise, just mark it for future action..
  */
-void mark_page_accessed(struct page *page)
+void fastcall mark_page_accessed(struct page *page)
 {
 	if (!PageActive(page) && PageReferenced(page)) {
 		activate_page(page);
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/mm/highmem.c linux-2.4.28-pre3/mm/highmem.c
--- linux-2.4.27/mm/highmem.c	2003-06-13 14:51:39.000000000 +0000
+++ linux-2.4.28-pre3/mm/highmem.c	2004-09-10 19:35:33.000000000 +0000
@@ -129,7 +129,7 @@ start:
 	return vaddr;
 }
 
-void *kmap_high(struct page *page, int nonblocking)
+void fastcall *kmap_high(struct page *page, int nonblocking)
 {
 	unsigned long vaddr;
 
@@ -154,7 +154,7 @@ void *kmap_high(struct page *page, int n
 	return (void*) vaddr;
 }
 
-void kunmap_high(struct page *page)
+void fastcall kunmap_high(struct page *page)
 {
 	unsigned long vaddr;
 	unsigned long nr;
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/mm/memory.c linux-2.4.28-pre3/mm/memory.c
--- linux-2.4.27/mm/memory.c	2003-11-28 18:26:21.000000000 +0000
+++ linux-2.4.28-pre3/mm/memory.c	2004-09-10 19:34:37.000000000 +0000
@@ -1396,7 +1396,7 @@ int handle_mm_fault(struct mm_struct *mm
  * On a two-level page table, this ends up actually being entirely
  * optimized away.
  */
-pmd_t *__pmd_alloc(struct mm_struct *mm, pgd_t *pgd, unsigned long address)
+pmd_t fastcall *__pmd_alloc(struct mm_struct *mm, pgd_t *pgd, unsigned long address)
 {
 	pmd_t *new;
 
@@ -1430,7 +1430,7 @@ out:
  * We've already handled the fast-path in-line, and we own the
  * page table lock.
  */
-pte_t *pte_alloc(struct mm_struct *mm, pmd_t *pmd, unsigned long address)
+pte_t fastcall *pte_alloc(struct mm_struct *mm, pmd_t *pmd, unsigned long address)
 {
 	if (pmd_none(*pmd)) {
 		pte_t *new;
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/mm/oom_kill.c linux-2.4.28-pre3/mm/oom_kill.c
--- linux-2.4.27/mm/oom_kill.c	2004-02-18 13:36:32.000000000 +0000
+++ linux-2.4.28-pre3/mm/oom_kill.c	2004-09-10 19:31:52.000000000 +0000
@@ -141,7 +141,7 @@ static struct task_struct * select_bad_p
  * CAP_SYS_RAW_IO set, send SIGTERM instead (but it's unlikely that
  * we select a process with CAP_SYS_RAW_IO set).
  */
-void oom_kill_task(struct task_struct *p)
+static void __oom_kill_task(struct task_struct *p)
 {
 	printk(KERN_ERR "Out of Memory: Killed process %d (%s).\n", p->pid, p->comm);
 
@@ -161,6 +161,26 @@ void oom_kill_task(struct task_struct *p
 	}
 }
 
+static struct mm_struct *oom_kill_task(struct task_struct *p)
+{
+	struct mm_struct *mm;
+
+	task_lock(p);
+	mm = p->mm;
+	if (mm) {
+		spin_lock(&mmlist_lock);
+		if (atomic_read(&mm->mm_users))
+			atomic_inc(&mm->mm_users);
+		else
+			mm = NULL;
+		spin_unlock(&mmlist_lock);
+	}
+	task_unlock(p);
+	if (mm)
+		__oom_kill_task(p);
+	return mm;
+}
+
 /**
  * oom_kill - kill the "best" process when we run out of memory
  *
@@ -172,21 +192,27 @@ void oom_kill_task(struct task_struct *p
 static void oom_kill(void)
 {
 	struct task_struct *p, *q;
+	struct mm_struct *mm;
 
+retry:
 	read_lock(&tasklist_lock);
 	p = select_bad_process();
 
 	/* Found nothing?!?! Either we hang forever, or we panic. */
 	if (p == NULL)
 		panic("Out of memory and no killable processes...\n");
-
+	mm = oom_kill_task(p);
+	if (!mm) {
+		read_unlock(&tasklist_lock);
+		goto retry;
+	}
 	/* kill all processes that share the ->mm (i.e. all threads) */
 	for_each_task(q) {
-		if (q->mm == p->mm)
-			oom_kill_task(q);
+		if (q->mm == mm)
+			__oom_kill_task(q);
 	}
 	read_unlock(&tasklist_lock);
-
+	mmput(mm);
 	/*
 	 * Make kswapd go out of the way, so "p" has a good chance of
 	 * killing itself before someone else gets the chance to ask
@@ -263,7 +289,7 @@ void out_of_memory(void)
 	spin_lock(&oom_lock);
 
 reset:
-	if (first < now)
+	if ((long)first - (long)now < 0)
 		first = now;
 	count = 0;
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/mm/page_alloc.c linux-2.4.28-pre3/mm/page_alloc.c
--- linux-2.4.27/mm/page_alloc.c	2004-08-07 23:26:06.000000000 +0000
+++ linux-2.4.28-pre3/mm/page_alloc.c	2004-09-10 19:32:27.000000000 +0000
@@ -109,7 +109,7 @@ static struct tq_struct free_pages_ok_no
  * -- wli
  */
 
-static void __free_pages_ok (struct page *page, unsigned int order)
+static void fastcall __free_pages_ok (struct page *page, unsigned int order)
 {
 	unsigned long index, page_idx, mask, flags;
 	free_area_t *area;
@@ -239,7 +239,7 @@ static inline struct page * expand (zone
 }
 
 static FASTCALL(struct page * rmqueue(zone_t *zone, unsigned int order));
-static struct page * rmqueue(zone_t *zone, unsigned int order)
+static struct page * fastcall rmqueue(zone_t *zone, unsigned int order)
 {
 	free_area_t * area = zone->free_area + order;
 	unsigned int curr_order = order;
@@ -285,7 +285,7 @@ static struct page * rmqueue(zone_t *zon
 }
 
 #ifndef CONFIG_DISCONTIGMEM
-struct page *_alloc_pages(unsigned int gfp_mask, unsigned int order)
+struct page * fastcall _alloc_pages(unsigned int gfp_mask, unsigned int order)
 {
 	return __alloc_pages(gfp_mask, order,
 		contig_page_data.node_zonelists+(gfp_mask & GFP_ZONEMASK));
@@ -293,7 +293,7 @@ struct page *_alloc_pages(unsigned int g
 #endif
 
 static struct page * FASTCALL(balance_classzone(zone_t *, unsigned int, unsigned int, int *));
-static struct page * balance_classzone(zone_t * classzone, unsigned int gfp_mask, unsigned int order, int * freed)
+static struct page * fastcall balance_classzone(zone_t * classzone, unsigned int gfp_mask, unsigned int order, int * freed)
 {
 	struct page * page = NULL;
 	int __freed;
@@ -371,7 +371,7 @@ static inline unsigned long zone_free_pa
 /*
  * This is the 'heart' of the zoned buddy allocator:
  */
-struct page * __alloc_pages(unsigned int gfp_mask, unsigned int order, zonelist_t *zonelist)
+struct page * fastcall __alloc_pages(unsigned int gfp_mask, unsigned int order, zonelist_t *zonelist)
 {
 	zone_t **zone, * classzone;
 	struct page * page;
@@ -484,7 +484,7 @@ struct page * __alloc_pages(unsigned int
 /*
  * Common helper functions.
  */
-unsigned long __get_free_pages(unsigned int gfp_mask, unsigned int order)
+fastcall unsigned long __get_free_pages(unsigned int gfp_mask, unsigned int order)
 {
 	struct page * page;
 
@@ -494,7 +494,7 @@ unsigned long __get_free_pages(unsigned 
 	return (unsigned long) page_address(page);
 }
 
-unsigned long get_zeroed_page(unsigned int gfp_mask)
+fastcall unsigned long get_zeroed_page(unsigned int gfp_mask)
 {
 	struct page * page;
 
@@ -507,13 +507,13 @@ unsigned long get_zeroed_page(unsigned i
 	return 0;
 }
 
-void __free_pages(struct page *page, unsigned int order)
+fastcall void __free_pages(struct page *page, unsigned int order)
 {
 	if (!PageReserved(page) && put_page_testzero(page))
 		__free_pages_ok(page, order);
 }
 
-void free_pages(unsigned long addr, unsigned int order)
+fastcall void free_pages(unsigned long addr, unsigned int order)
 {
 	if (addr != 0)
 		__free_pages(virt_to_page(addr), order);
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/mm/slab.c linux-2.4.28-pre3/mm/slab.c
--- linux-2.4.27/mm/slab.c	2003-11-28 18:26:21.000000000 +0000
+++ linux-2.4.28-pre3/mm/slab.c	2004-09-10 19:36:16.000000000 +0000
@@ -1735,7 +1735,7 @@ static void enable_all_cpucaches (void)
  *
  * Called from do_try_to_free_pages() and __alloc_pages()
  */
-int kmem_cache_reap (int gfp_mask)
+int fastcall kmem_cache_reap (int gfp_mask)
 {
 	slab_t *slabp;
 	kmem_cache_t *searchp;
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/mm/swap.c linux-2.4.28-pre3/mm/swap.c
--- linux-2.4.27/mm/swap.c	2003-11-28 18:26:21.000000000 +0000
+++ linux-2.4.28-pre3/mm/swap.c	2004-09-10 19:34:11.000000000 +0000
@@ -44,7 +44,7 @@ static inline void activate_page_nolock(
 	}
 }
 
-void activate_page(struct page * page)
+void fastcall activate_page(struct page * page)
 {
 	spin_lock(&pagemap_lru_lock);
 	activate_page_nolock(page);
@@ -55,7 +55,7 @@ void activate_page(struct page * page)
  * lru_cache_add: add a page to the page lists
  * @page: the page to add
  */
-void lru_cache_add(struct page * page)
+void fastcall lru_cache_add(struct page * page)
 {
 	if (!PageLRU(page)) {
 		spin_lock(&pagemap_lru_lock);
@@ -72,7 +72,7 @@ void lru_cache_add(struct page * page)
  * This function is for when the caller already holds
  * the pagemap_lru_lock.
  */
-void __lru_cache_del(struct page * page)
+void fastcall __lru_cache_del(struct page * page)
 {
 	if (TestClearPageLRU(page)) {
 		if (PageActive(page)) {
@@ -87,7 +87,7 @@ void __lru_cache_del(struct page * page)
  * lru_cache_del: remove a page from the page lists
  * @page: the page to remove
  */
-void lru_cache_del(struct page * page)
+void fastcall lru_cache_del(struct page * page)
 {
 	spin_lock(&pagemap_lru_lock);
 	__lru_cache_del(page);
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/mm/swapfile.c linux-2.4.28-pre3/mm/swapfile.c
--- linux-2.4.27/mm/swapfile.c	2003-08-25 11:44:44.000000000 +0000
+++ linux-2.4.28-pre3/mm/swapfile.c	2004-09-10 19:33:06.000000000 +0000
@@ -256,7 +256,7 @@ static int exclusive_swap_page(struct pa
  * work, but we opportunistically check whether
  * we need to get all the locks first..
  */
-int can_share_swap_page(struct page *page)
+int fastcall can_share_swap_page(struct page *page)
 {
 	int retval = 0;
 
@@ -284,7 +284,7 @@ int can_share_swap_page(struct page *pag
  * Work out if there are any other processes sharing this
  * swap cache page. Free it if you can. Return success.
  */
-int remove_exclusive_swap_page(struct page *page)
+int fastcall remove_exclusive_swap_page(struct page *page)
 {
 	int retval;
 	struct swap_info_struct * p;
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/mm/vmscan.c linux-2.4.28-pre3/mm/vmscan.c
--- linux-2.4.27/mm/vmscan.c	2004-02-18 13:36:32.000000000 +0000
+++ linux-2.4.28-pre3/mm/vmscan.c	2004-09-10 19:32:44.000000000 +0000
@@ -323,7 +323,7 @@ out_unlock:
 }
 
 static int FASTCALL(swap_out(zone_t * classzone));
-static int swap_out(zone_t * classzone)
+static int fastcall swap_out(zone_t * classzone)
 {
 	int counter, nr_pages = SWAP_CLUSTER_MAX;
 	struct mm_struct *mm;
@@ -366,7 +366,7 @@ empty:
 
 static void FASTCALL(refill_inactive(int nr_pages, zone_t * classzone));
 static int FASTCALL(shrink_cache(int nr_pages, zone_t * classzone, unsigned int gfp_mask, int * failed_swapout));
-static int shrink_cache(int nr_pages, zone_t * classzone, unsigned int gfp_mask, int * failed_swapout)
+static int fastcall shrink_cache(int nr_pages, zone_t * classzone, unsigned int gfp_mask, int * failed_swapout)
 {
 	struct list_head * entry;
 	int max_scan = (classzone->nr_inactive_pages + classzone->nr_active_pages) / vm_cache_scan_ratio;
@@ -577,7 +577,7 @@ page_mapped:
  * We move them the other way when we see the
  * reference bit on the page.
  */
-static void refill_inactive(int nr_pages, zone_t * classzone)
+static void fastcall refill_inactive(int nr_pages, zone_t * classzone)
 {
 	struct list_head * entry;
 	unsigned long ratio;
@@ -610,7 +610,7 @@ static void refill_inactive(int nr_pages
 }
 
 static int FASTCALL(shrink_caches(zone_t * classzone, unsigned int gfp_mask, int nr_pages, int * failed_swapout));
-static int shrink_caches(zone_t * classzone, unsigned int gfp_mask, int nr_pages, int * failed_swapout)
+static int fastcall shrink_caches(zone_t * classzone, unsigned int gfp_mask, int nr_pages, int * failed_swapout)
 {
 	nr_pages -= kmem_cache_reap(gfp_mask);
 	if (nr_pages <= 0)
@@ -627,7 +627,7 @@ out:
 
 static int check_classzone_need_balance(zone_t * classzone);
 
-int try_to_free_pages_zone(zone_t *classzone, unsigned int gfp_mask)
+int fastcall try_to_free_pages_zone(zone_t *classzone, unsigned int gfp_mask)
 {
 	gfp_mask = pf_gfp_mask(gfp_mask);
 
@@ -665,7 +665,7 @@ int try_to_free_pages_zone(zone_t *class
 	return 0;
 }
 
-int try_to_free_pages(unsigned int gfp_mask)
+int fastcall try_to_free_pages(unsigned int gfp_mask)
 {
 	pg_data_t *pgdat;
 	zonelist_t *zonelist;
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/net/appletalk/ddp.c linux-2.4.28-pre3/net/appletalk/ddp.c
--- linux-2.4.27/net/appletalk/ddp.c	2001-09-10 14:57:00.000000000 +0000
+++ linux-2.4.28-pre3/net/appletalk/ddp.c	2004-09-10 19:37:18.000000000 +0000
@@ -106,8 +106,8 @@ extern void aarp_proxy_remove(struct net
 #endif /* APPLETALK_DEBUG */
 
 #ifdef CONFIG_SYSCTL
-extern inline void atalk_register_sysctl(void);
-extern inline void atalk_unregister_sysctl(void);
+extern void atalk_register_sysctl(void);
+extern void atalk_unregister_sysctl(void);
 #endif /* CONFIG_SYSCTL */
 
 struct datalink_proto *ddp_dl, *aarp_dl;
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/net/atm/lec.c linux-2.4.28-pre3/net/atm/lec.c
--- linux-2.4.27/net/atm/lec.c	2004-08-07 23:26:06.000000000 +0000
+++ linux-2.4.28-pre3/net/atm/lec.c	2004-09-10 19:35:31.000000000 +0000
@@ -71,9 +71,9 @@ static int lec_send_packet(struct sk_buf
 static int lec_close(struct net_device *dev);
 static struct net_device_stats *lec_get_stats(struct net_device *dev);
 static void lec_init(struct net_device *dev);
-static inline struct lec_arp_table* lec_arp_find(struct lec_priv *priv,
+static struct lec_arp_table* lec_arp_find(struct lec_priv *priv,
                                                      unsigned char *mac_addr);
-static inline int lec_arp_remove(struct lec_priv *priv,
+static int lec_arp_remove(struct lec_priv *priv,
 				     struct lec_arp_table *to_remove);
 /* LANE2 functions */
 static void lane2_associate_ind (struct net_device *dev, u8 *mac_address,
@@ -1137,7 +1137,7 @@ lec_arp_add(struct lec_priv *priv, struc
 /*
  * Remove entry from lec_arp_table
  */
-static inline int 
+static int 
 lec_arp_remove(struct lec_priv *priv,
                struct lec_arp_table *to_remove)
 {
@@ -1424,7 +1424,7 @@ lec_arp_destroy(struct lec_priv *priv)
 /* 
  * Find entry by mac_address
  */
-static inline struct lec_arp_table*
+static struct lec_arp_table*
 lec_arp_find(struct lec_priv *priv,
              unsigned char *mac_addr)
 {
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/net/bluetooth/l2cap.c linux-2.4.28-pre3/net/bluetooth/l2cap.c
--- linux-2.4.27/net/bluetooth/l2cap.c	2004-08-07 23:26:06.000000000 +0000
+++ linux-2.4.28-pre3/net/bluetooth/l2cap.c	2004-09-10 19:34:31.000000000 +0000
@@ -70,7 +70,7 @@ struct bluez_sock_list l2cap_sk_list = {
 
 static int l2cap_conn_del(struct hci_conn *conn, int err);
 
-static inline void l2cap_chan_add(struct l2cap_conn *conn, struct sock *sk, struct sock *parent);
+static void __l2cap_chan_add(struct l2cap_conn *conn, struct sock *sk, struct sock *parent);
 static void l2cap_chan_del(struct sock *sk, int err);
 static int  l2cap_chan_send(struct sock *sk, struct msghdr *msg, int len);
 
@@ -420,6 +420,14 @@ done:
 	return err;
 }
 
+static inline void l2cap_chan_add(struct l2cap_conn *conn, struct sock *sk, struct sock *parent)
+{
+	struct l2cap_chan_list *l = &conn->chan_list;
+	write_lock(&l->lock);
+	__l2cap_chan_add(conn, sk, parent);
+	write_unlock(&l->lock);
+}
+
 static int l2cap_do_connect(struct sock *sk)
 {
 	bdaddr_t *src = &bluez_pi(sk)->src;
@@ -897,14 +905,6 @@ static void __l2cap_chan_add(struct l2ca
 		bluez_accept_enqueue(parent, sk);
 }
 
-static inline void l2cap_chan_add(struct l2cap_conn *conn, struct sock *sk, struct sock *parent)
-{
-	struct l2cap_chan_list *l = &conn->chan_list;
-	write_lock(&l->lock);
-	__l2cap_chan_add(conn, sk, parent);
-	write_unlock(&l->lock);
-}
-
 /* Delete channel. 
  * Must be called on the locked socket. */
 static void l2cap_chan_del(struct sock *sk, int err)
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/net/bluetooth/rfcomm/core.c linux-2.4.28-pre3/net/bluetooth/rfcomm/core.c
--- linux-2.4.27/net/bluetooth/rfcomm/core.c	2004-04-14 13:05:41.000000000 +0000
+++ linux-2.4.28-pre3/net/bluetooth/rfcomm/core.c	2004-09-10 19:35:38.000000000 +0000
@@ -406,7 +406,7 @@ int rfcomm_dlc_send(struct rfcomm_dlc *d
 	return len;
 }
 
-void __rfcomm_dlc_throttle(struct rfcomm_dlc *d)
+void fastcall __rfcomm_dlc_throttle(struct rfcomm_dlc *d)
 {
 	BT_DBG("dlc %p state %ld", d, d->state);
 
@@ -417,7 +417,7 @@ void __rfcomm_dlc_throttle(struct rfcomm
 	rfcomm_schedule(RFCOMM_SCHED_TX);
 }
 
-void __rfcomm_dlc_unthrottle(struct rfcomm_dlc *d)
+void fastcall __rfcomm_dlc_unthrottle(struct rfcomm_dlc *d)
 {
 	BT_DBG("dlc %p state %ld", d, d->state);
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/net/bluetooth/sco.c linux-2.4.28-pre3/net/bluetooth/sco.c
--- linux-2.4.27/net/bluetooth/sco.c	2003-08-25 11:44:44.000000000 +0000
+++ linux-2.4.28-pre3/net/bluetooth/sco.c	2004-09-10 19:37:14.000000000 +0000
@@ -67,9 +67,8 @@ static struct bluez_sock_list sco_sk_lis
 	lock: RW_LOCK_UNLOCKED
 };
 
-static inline int sco_chan_add(struct sco_conn *conn, struct sock *sk, struct sock *parent);
+static void __sco_chan_add(struct sco_conn *conn, struct sock *sk, struct sock *parent);
 static void sco_chan_del(struct sock *sk, int err);
-static inline struct sock * sco_chan_get(struct sco_conn *conn);
 
 static int  sco_conn_del(struct hci_conn *conn, int err);
 
@@ -150,6 +149,15 @@ static struct sco_conn *sco_conn_add(str
 	return conn;
 }
 
+static inline struct sock * sco_chan_get(struct sco_conn *conn)
+{
+	struct sock *sk = NULL;
+	sco_conn_lock(conn);
+	sk = conn->sk;
+	sco_conn_unlock(conn);
+	return sk;
+}
+
 static int sco_conn_del(struct hci_conn *hcon, int err)
 {
 	struct sco_conn *conn;
@@ -176,6 +184,20 @@ static int sco_conn_del(struct hci_conn 
 	return 0;
 }
 
+static inline int sco_chan_add(struct sco_conn *conn, struct sock *sk, struct sock *parent)
+{
+	int err = 0;
+
+	sco_conn_lock(conn);
+	if (conn->sk) {
+		err = -EBUSY;
+	} else {
+		__sco_chan_add(conn, sk, parent);
+	}
+	sco_conn_unlock(conn);
+	return err;
+}
+
 int sco_connect(struct sock *sk)
 {
 	bdaddr_t *src = &bluez_pi(sk)->src;
@@ -743,29 +765,6 @@ static void __sco_chan_add(struct sco_co
 		bluez_accept_enqueue(parent, sk);
 }
 
-static inline int sco_chan_add(struct sco_conn *conn, struct sock *sk, struct sock *parent)
-{
-	int err = 0;
-
-	sco_conn_lock(conn);
-	if (conn->sk) {
-		err = -EBUSY;
-	} else {
-		__sco_chan_add(conn, sk, parent);
-	}
-	sco_conn_unlock(conn);
-	return err;
-}
-
-static inline struct sock * sco_chan_get(struct sco_conn *conn)
-{
-	struct sock *sk = NULL;
-	sco_conn_lock(conn);
-	sk = conn->sk;
-	sco_conn_unlock(conn);
-	return sk;
-}
-
 /* Delete channel. 
  * Must be called on the locked socket. */
 static void sco_chan_del(struct sock *sk, int err)
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/net/core/neighbour.c linux-2.4.28-pre3/net/core/neighbour.c
--- linux-2.4.27/net/core/neighbour.c	2004-02-18 13:36:32.000000000 +0000
+++ linux-2.4.28-pre3/net/core/neighbour.c	2004-09-10 19:32:17.000000000 +0000
@@ -2,7 +2,7 @@
  *	Generic address resolution entity
  *
  *	Authors:
- *	Pedro Roque		<roque@di.fc.ul.pt>
+ *	Pedro Roque		<pedro_m@yahoo.com>
  *	Alexey Kuznetsov	<kuznet@ms2.inr.ac.ru>
  *
  *	This program is free software; you can redistribute it and/or
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/net/ipv4/ip_fragment.c linux-2.4.28-pre3/net/ipv4/ip_fragment.c
--- linux-2.4.27/net/ipv4/ip_fragment.c	2003-06-13 14:51:39.000000000 +0000
+++ linux-2.4.28-pre3/net/ipv4/ip_fragment.c	2004-09-10 19:33:32.000000000 +0000
@@ -168,14 +168,18 @@ static void ipfrag_secret_rebuild(unsign
 atomic_t ip_frag_mem = ATOMIC_INIT(0);	/* Memory used for fragments */
 
 /* Memory Tracking Functions. */
-static __inline__ void frag_kfree_skb(struct sk_buff *skb)
+static __inline__ void frag_kfree_skb(struct sk_buff *skb, int *work)
 {
+	if (work)
+		*work -= skb->truesize;
 	atomic_sub(skb->truesize, &ip_frag_mem);
 	kfree_skb(skb);
 }
 
-static __inline__ void frag_free_queue(struct ipq *qp)
+static __inline__ void frag_free_queue(struct ipq *qp, int *work)
 {
+	if (work)
+		*work -= sizeof(struct ipq);
 	atomic_sub(sizeof(struct ipq), &ip_frag_mem);
 	kfree(qp);
 }
@@ -194,7 +198,7 @@ static __inline__ struct ipq *frag_alloc
 /* Destruction primitives. */
 
 /* Complete destruction of ipq. */
-static void ip_frag_destroy(struct ipq *qp)
+static void ip_frag_destroy(struct ipq *qp, int *work)
 {
 	struct sk_buff *fp;
 
@@ -206,18 +210,18 @@ static void ip_frag_destroy(struct ipq *
 	while (fp) {
 		struct sk_buff *xp = fp->next;
 
-		frag_kfree_skb(fp);
+		frag_kfree_skb(fp, work);
 		fp = xp;
 	}
 
 	/* Finally, release the queue descriptor itself. */
-	frag_free_queue(qp);
+	frag_free_queue(qp, work);
 }
 
-static __inline__ void ipq_put(struct ipq *ipq)
+static __inline__ void ipq_put(struct ipq *ipq, int *work)
 {
 	if (atomic_dec_and_test(&ipq->refcnt))
-		ip_frag_destroy(ipq);
+		ip_frag_destroy(ipq, work);
 }
 
 /* Kill ipq entry. It is not destroyed immediately,
@@ -236,16 +240,19 @@ static __inline__ void ipq_kill(struct i
 }
 
 /* Memory limiting on fragments.  Evictor trashes the oldest 
- * fragment queue until we are back under the low threshold.
+ * fragment queue until we are back under the threshold.
  */
-static void ip_evictor(void)
+static void __ip_evictor(int threshold)
 {
 	struct ipq *qp;
 	struct list_head *tmp;
+	int work;
 
-	for(;;) {
-		if (atomic_read(&ip_frag_mem) <= sysctl_ipfrag_low_thresh)
-			return;
+	work = atomic_read(&ip_frag_mem) - threshold;
+	if (work <= 0)
+		return;
+
+	while (work > 0) {
 		read_lock(&ipfrag_lock);
 		if (list_empty(&ipq_lru_list)) {
 			read_unlock(&ipfrag_lock);
@@ -261,11 +268,16 @@ static void ip_evictor(void)
 			ipq_kill(qp);
 		spin_unlock(&qp->lock);
 
-		ipq_put(qp);
+		ipq_put(qp, &work);
 		IP_INC_STATS_BH(IpReasmFails);
 	}
 }
 
+static inline void ip_evictor(void)
+{
+	__ip_evictor(sysctl_ipfrag_low_thresh);
+}
+
 /*
  * Oops, a fragment queue timed out.  Kill it and send an ICMP reply.
  */
@@ -293,7 +305,7 @@ static void ip_expire(unsigned long arg)
 	}
 out:
 	spin_unlock(&qp->lock);
-	ipq_put(qp);
+	ipq_put(qp, NULL);
 }
 
 /* Creation primitives. */
@@ -316,7 +328,7 @@ static struct ipq *ip_frag_intern(unsign
 			atomic_inc(&qp->refcnt);
 			write_unlock(&ipfrag_lock);
 			qp_in->last_in |= COMPLETE;
-			ipq_put(qp_in);
+			ipq_put(qp_in, NULL);
 			return qp;
 		}
 	}
@@ -505,7 +517,7 @@ static void ip_frag_queue(struct ipq *qp
 				qp->fragments = next;
 
 			qp->meat -= free_it->len;
-			frag_kfree_skb(free_it);
+			frag_kfree_skb(free_it, NULL);
 		}
 	}
 
@@ -656,7 +668,7 @@ struct sk_buff *ip_defrag(struct sk_buff
 			ret = ip_frag_reasm(qp, dev);
 
 		spin_unlock(&qp->lock);
-		ipq_put(qp);
+		ipq_put(qp, NULL);
 		return ret;
 	}
 
@@ -675,3 +687,8 @@ void ipfrag_init(void)
 	ipfrag_secret_timer.expires = jiffies + sysctl_ipfrag_secret_interval;
 	add_timer(&ipfrag_secret_timer);
 }
+
+void ipfrag_flush(void)
+{
+	__ip_evictor(0);
+}
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/net/ipv4/ip_output.c linux-2.4.28-pre3/net/ipv4/ip_output.c
--- linux-2.4.27/net/ipv4/ip_output.c	2003-11-28 18:26:21.000000000 +0000
+++ linux-2.4.28-pre3/net/ipv4/ip_output.c	2004-09-10 19:37:11.000000000 +0000
@@ -184,7 +184,7 @@ static inline int ip_finish_output2(stru
 	return -EINVAL;
 }
 
-__inline__ int ip_finish_output(struct sk_buff *skb)
+static __inline__ int __ip_finish_output(struct sk_buff *skb)
 {
 	struct net_device *dev = skb->dst->dev;
 
@@ -195,6 +195,11 @@ __inline__ int ip_finish_output(struct s
 		       ip_finish_output2);
 }
 
+int ip_finish_output(struct sk_buff *skb)
+{
+	return __ip_finish_output(skb);
+}
+
 int ip_mc_output(struct sk_buff *skb)
 {
 	struct sock *sk = skb->sk;
@@ -253,7 +258,7 @@ int ip_mc_output(struct sk_buff *skb)
 				newskb->dev, ip_dev_loopback_xmit);
 	}
 
-	return ip_finish_output(skb);
+	return __ip_finish_output(skb);
 }
 
 int ip_output(struct sk_buff *skb)
@@ -269,7 +274,7 @@ int ip_output(struct sk_buff *skb)
 		ip_do_nat(skb);
 #endif
 
-	return ip_finish_output(skb);
+	return __ip_finish_output(skb);
 }
 
 /* Queues a packet to be sent, and starts the transmitter if necessary.  
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/net/ipv4/netfilter/arp_tables.c linux-2.4.28-pre3/net/ipv4/netfilter/arp_tables.c
--- linux-2.4.27/net/ipv4/netfilter/arp_tables.c	2004-08-07 23:26:06.000000000 +0000
+++ linux-2.4.28-pre3/net/ipv4/netfilter/arp_tables.c	2004-09-10 19:34:33.000000000 +0000
@@ -101,7 +101,7 @@ static inline int arp_packet_match(const
 {
 	char *arpptr = (char *)(arphdr + 1);
 	char *src_devaddr, *tgt_devaddr;
-	u32 *src_ipaddr, *tgt_ipaddr;
+	u32 src_ipaddr, tgt_ipaddr;
 	int i, ret;
 
 #define FWINV(bool,invflg) ((bool) ^ !!(arpinfo->invflags & invflg))
@@ -140,11 +140,11 @@ static inline int arp_packet_match(const
 
 	src_devaddr = arpptr;
 	arpptr += dev->addr_len;
-	src_ipaddr = (u32 *) arpptr;
+	memcpy(&src_ipaddr, arpptr, sizeof(u32));
 	arpptr += sizeof(u32);
 	tgt_devaddr = arpptr;
 	arpptr += dev->addr_len;
-	tgt_ipaddr = (u32 *) arpptr;
+	memcpy(&tgt_ipaddr, arpptr, sizeof(u32));
 
 	if (FWINV(arp_devaddr_compare(&arpinfo->src_devaddr, src_devaddr, dev->addr_len),
 		  ARPT_INV_SRCDEVADDR) ||
@@ -155,19 +155,19 @@ static inline int arp_packet_match(const
 		return 0;
 	}
 
-	if (FWINV(((*src_ipaddr) & arpinfo->smsk.s_addr) != arpinfo->src.s_addr,
+	if (FWINV(((src_ipaddr) & arpinfo->smsk.s_addr) != arpinfo->src.s_addr,
 		  ARPT_INV_SRCIP) ||
-	    FWINV((((*tgt_ipaddr) & arpinfo->tmsk.s_addr) != arpinfo->tgt.s_addr),
+	    FWINV((((tgt_ipaddr) & arpinfo->tmsk.s_addr) != arpinfo->tgt.s_addr),
 		  ARPT_INV_TGTIP)) {
 		dprintf("Source or target IP address mismatch.\n");
 
 		dprintf("SRC: %u.%u.%u.%u. Mask: %u.%u.%u.%u. Target: %u.%u.%u.%u.%s\n",
-			NIPQUAD(*src_ipaddr),
+			NIPQUAD(src_ipaddr),
 			NIPQUAD(arpinfo->smsk.s_addr),
 			NIPQUAD(arpinfo->src.s_addr),
 			arpinfo->invflags & ARPT_INV_SRCIP ? " (INV)" : "");
 		dprintf("TGT: %u.%u.%u.%u Mask: %u.%u.%u.%u Target: %u.%u.%u.%u.%s\n",
-			NIPQUAD(*tgt_ipaddr),
+			NIPQUAD(tgt_ipaddr),
 			NIPQUAD(arpinfo->tmsk.s_addr),
 			NIPQUAD(arpinfo->tgt.s_addr),
 			arpinfo->invflags & ARPT_INV_TGTIP ? " (INV)" : "");
@@ -188,7 +188,10 @@ static inline int arp_packet_match(const
 	}
 
 	for (i = 0, ret = 0; i < IFNAMSIZ/sizeof(unsigned long); i++) {
-		ret |= (((const unsigned long *)outdev)[i]
+		unsigned long odev;
+		memcpy(&odev, outdev + i*sizeof(unsigned long),
+		       sizeof(unsigned long));
+		ret |= (odev
 			^ ((const unsigned long *)arpinfo->outiface)[i])
 			& ((const unsigned long *)arpinfo->outiface_mask)[i];
 	}
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/net/ipv4/netfilter/ip_conntrack_core.c linux-2.4.28-pre3/net/ipv4/netfilter/ip_conntrack_core.c
--- linux-2.4.27/net/ipv4/netfilter/ip_conntrack_core.c	2004-08-07 23:26:06.000000000 +0000
+++ linux-2.4.28-pre3/net/ipv4/netfilter/ip_conntrack_core.c	2004-09-10 19:31:50.000000000 +0000
@@ -1183,6 +1183,8 @@ void ip_ct_refresh(struct ip_conntrack *
 	WRITE_UNLOCK(&ip_conntrack_lock);
 }
 
+int ip_ct_no_defrag;
+
 /* Returns new sk_buff, or NULL */
 struct sk_buff *
 ip_ct_gather_frags(struct sk_buff *skb)
@@ -1191,6 +1193,12 @@ ip_ct_gather_frags(struct sk_buff *skb)
 #ifdef CONFIG_NETFILTER_DEBUG
 	unsigned int olddebug = skb->nf_debug;
 #endif
+
+	if (unlikely(ip_ct_no_defrag)) {
+		kfree_skb(skb);
+		return NULL;
+	}
+
 	if (sk) {
 		sock_hold(sk);
 		skb_orphan(skb);
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/net/ipv4/netfilter/ip_conntrack_ftp.c linux-2.4.28-pre3/net/ipv4/netfilter/ip_conntrack_ftp.c
--- linux-2.4.27/net/ipv4/netfilter/ip_conntrack_ftp.c	2003-08-25 11:44:44.000000000 +0000
+++ linux-2.4.28-pre3/net/ipv4/netfilter/ip_conntrack_ftp.c	2004-09-10 19:36:16.000000000 +0000
@@ -11,7 +11,7 @@
 #include <linux/netfilter_ipv4/ip_conntrack_helper.h>
 #include <linux/netfilter_ipv4/ip_conntrack_ftp.h>
 
-DECLARE_LOCK(ip_ftp_lock);
+static DECLARE_LOCK(ip_ftp_lock);
 struct module *ip_conntrack_ftp = THIS_MODULE;
 
 #define MAX_PORTS 8
@@ -338,7 +338,6 @@ static int help(const struct iphdr *iph,
 	memset(&expect, 0, sizeof(expect));
 
 	/* Update the ftp info */
-	LOCK_BH(&ip_ftp_lock);
 	if (htonl((array[0] << 24) | (array[1] << 16) | (array[2] << 8) | array[3])
 	    == ct->tuplehash[dir].tuple.src.ip) {
 		exp->seq = ntohl(tcph->seq) + matchoff;
@@ -358,7 +357,8 @@ static int help(const struct iphdr *iph,
 		   <lincoln@cesar.org.br> for reporting this potential
 		   problem (DMZ machines opening holes to internal
 		   networks, or the packet filter itself). */
-		if (!loose) goto out;
+		if (!loose)
+			return NF_ACCEPT;
 	}
 
 	exp->tuple = ((struct ip_conntrack_tuple)
@@ -376,9 +376,6 @@ static int help(const struct iphdr *iph,
 
 	/* Ignore failure; should only happen with NAT */
 	ip_conntrack_expect_related(ct, &expect);
- out:
-	UNLOCK_BH(&ip_ftp_lock);
-
 	return NF_ACCEPT;
 }
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/net/ipv4/netfilter/ip_conntrack_irc.c linux-2.4.28-pre3/net/ipv4/netfilter/ip_conntrack_irc.c
--- linux-2.4.27/net/ipv4/netfilter/ip_conntrack_irc.c	2003-11-28 18:26:21.000000000 +0000
+++ linux-2.4.28-pre3/net/ipv4/netfilter/ip_conntrack_irc.c	2004-09-10 19:36:14.000000000 +0000
@@ -29,7 +29,6 @@
 #include <net/checksum.h>
 #include <net/tcp.h>
 
-#include <linux/netfilter_ipv4/lockhelp.h>
 #include <linux/netfilter_ipv4/ip_conntrack_helper.h>
 #include <linux/netfilter_ipv4/ip_conntrack_irc.h>
 
@@ -61,7 +60,6 @@ struct dccproto dccprotos[NUM_DCCPROTO] 
 };
 #define MINMATCHLEN	5
 
-DECLARE_LOCK(ip_irc_lock);
 struct module *ip_conntrack_irc = THIS_MODULE;
 
 #if 0
@@ -208,8 +206,6 @@ static int help(const struct iphdr *iph,
 			
 			memset(&expect, 0, sizeof(expect));
 
-			LOCK_BH(&ip_irc_lock);
-
 			/* save position of address in dcc string,
 			 * neccessary for NAT */
 			DEBUGP("tcph->seq = %u\n", tcph->seq);
@@ -236,8 +232,6 @@ static int help(const struct iphdr *iph,
 				ntohs(exp->tuple.dst.u.tcp.port));
 
 			ip_conntrack_expect_related(ct, &expect);
-			UNLOCK_BH(&ip_irc_lock);
-
 			return NF_ACCEPT;
 		} /* for .. NUM_DCCPROTO */
 	} /* while data < ... */
@@ -315,7 +309,5 @@ static void fini(void)
 	}
 }
 
-EXPORT_SYMBOL(ip_irc_lock);
-
 module_init(init);
 module_exit(fini);
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/net/ipv4/netfilter/ip_conntrack_standalone.c linux-2.4.28-pre3/net/ipv4/netfilter/ip_conntrack_standalone.c
--- linux-2.4.27/net/ipv4/netfilter/ip_conntrack_standalone.c	2004-08-07 23:26:06.000000000 +0000
+++ linux-2.4.28-pre3/net/ipv4/netfilter/ip_conntrack_standalone.c	2004-09-10 19:34:35.000000000 +0000
@@ -393,6 +393,13 @@ static int init_or_cleanup(int init)
  cleanup_inandlocalops:
 	nf_unregister_hook(&ip_conntrack_local_out_ops);
  cleanup_inops:
+	/* Frag queues may hold fragments with skb->dst == NULL */
+	ip_ct_no_defrag = 1;
+	local_bh_disable();
+	br_write_lock(BR_NETPROTO_LOCK);
+	br_write_unlock(BR_NETPROTO_LOCK);
+	ipfrag_flush();
+	local_bh_enable();
 	nf_unregister_hook(&ip_conntrack_in_ops);
  cleanup_proc:
 	proc_net_remove("ip_conntrack");
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/net/ipv4/netfilter/ip_nat_ftp.c linux-2.4.28-pre3/net/ipv4/netfilter/ip_nat_ftp.c
--- linux-2.4.27/net/ipv4/netfilter/ip_nat_ftp.c	2003-08-25 11:44:44.000000000 +0000
+++ linux-2.4.28-pre3/net/ipv4/netfilter/ip_nat_ftp.c	2004-09-10 19:35:47.000000000 +0000
@@ -24,8 +24,6 @@ static int ports_c = 0;
 MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
 #endif
 
-DECLARE_LOCK_EXTERN(ip_ftp_lock);
-
 /* FIXME: Time out? --RR */
 
 static unsigned int
@@ -48,8 +46,6 @@ ftp_nat_expected(struct sk_buff **pskb,
 	DEBUGP("nat_expected: We have a connection!\n");
 	exp_ftp_info = &ct->master->help.exp_ftp_info;
 
-	LOCK_BH(&ip_ftp_lock);
-
 	if (exp_ftp_info->ftptype == IP_CT_FTP_PORT
 	    || exp_ftp_info->ftptype == IP_CT_FTP_EPRT) {
 		/* PORT command: make connection go to the client. */
@@ -64,7 +60,6 @@ ftp_nat_expected(struct sk_buff **pskb,
 		DEBUGP("nat_expected: PASV cmd. %u.%u.%u.%u->%u.%u.%u.%u\n",
 		       NIPQUAD(newsrcip), NIPQUAD(newdstip));
 	}
-	UNLOCK_BH(&ip_ftp_lock);
 
 	if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC)
 		newip = newsrcip;
@@ -100,8 +95,6 @@ mangle_rfc959_packet(struct sk_buff **ps
 {
 	char buffer[sizeof("nnn,nnn,nnn,nnn,nnn,nnn")];
 
-	MUST_BE_LOCKED(&ip_ftp_lock);
-
 	sprintf(buffer, "%u,%u,%u,%u,%u,%u",
 		NIPQUAD(newip), port>>8, port&0xFF);
 
@@ -123,8 +116,6 @@ mangle_eprt_packet(struct sk_buff **pskb
 {
 	char buffer[sizeof("|1|255.255.255.255|65535|")];
 
-	MUST_BE_LOCKED(&ip_ftp_lock);
-
 	sprintf(buffer, "|1|%u.%u.%u.%u|%u|", NIPQUAD(newip), port);
 
 	DEBUGP("calling ip_nat_mangle_tcp_packet\n");
@@ -145,8 +136,6 @@ mangle_epsv_packet(struct sk_buff **pskb
 {
 	char buffer[sizeof("|||65535|")];
 
-	MUST_BE_LOCKED(&ip_ftp_lock);
-
 	sprintf(buffer, "|||%u|", port);
 
 	DEBUGP("calling ip_nat_mangle_tcp_packet\n");
@@ -166,7 +155,7 @@ static int (*mangle[])(struct sk_buff **
     [IP_CT_FTP_EPSV] mangle_epsv_packet
 };
 
-static int ftp_data_fixup(const struct ip_ct_ftp_expect *ct_ftp_info,
+static int ftp_data_fixup(const struct ip_ct_ftp_expect *exp_ftp_info,
 			  struct ip_conntrack *ct,
 			  struct sk_buff **pskb,
 			  enum ip_conntrack_info ctinfo,
@@ -178,15 +167,14 @@ static int ftp_data_fixup(const struct i
 	u_int16_t port;
 	struct ip_conntrack_tuple newtuple;
 
-	MUST_BE_LOCKED(&ip_ftp_lock);
 	DEBUGP("FTP_NAT: seq %u + %u in %u\n",
-	       expect->seq, ct_ftp_info->len,
+	       expect->seq, exp_ftp_info->len,
 	       ntohl(tcph->seq));
 
 	/* Change address inside packet to match way we're mapping
 	   this connection. */
-	if (ct_ftp_info->ftptype == IP_CT_FTP_PASV
-	    || ct_ftp_info->ftptype == IP_CT_FTP_EPSV) {
+	if (exp_ftp_info->ftptype == IP_CT_FTP_PASV
+	    || exp_ftp_info->ftptype == IP_CT_FTP_EPSV) {
 		/* PASV/EPSV response: must be where client thinks server
 		   is */
 		newip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
@@ -208,7 +196,7 @@ static int ftp_data_fixup(const struct i
 	newtuple.src.u.tcp.port = expect->tuple.src.u.tcp.port;
 
 	/* Try to get same port: if not, try to change it. */
-	for (port = ct_ftp_info->port; port != 0; port++) {
+	for (port = exp_ftp_info->port; port != 0; port++) {
 		newtuple.dst.u.tcp.port = htons(port);
 
 		if (ip_conntrack_change_expect(expect, &newtuple) == 0)
@@ -217,9 +205,9 @@ static int ftp_data_fixup(const struct i
 	if (port == 0)
 		return 0;
 
-	if (!mangle[ct_ftp_info->ftptype](pskb, newip, port,
+	if (!mangle[exp_ftp_info->ftptype](pskb, newip, port,
 					  expect->seq - ntohl(tcph->seq),
-					  ct_ftp_info->len, ct, ctinfo))
+					  exp_ftp_info->len, ct, ctinfo))
 		return 0;
 
 	return 1;
@@ -236,12 +224,12 @@ static unsigned int help(struct ip_connt
 	struct tcphdr *tcph = (void *)iph + iph->ihl*4;
 	unsigned int datalen;
 	int dir;
-	struct ip_ct_ftp_expect *ct_ftp_info;
+	struct ip_ct_ftp_expect *exp_ftp_info;
 
 	if (!exp)
 		DEBUGP("ip_nat_ftp: no exp!!");
 
-	ct_ftp_info = &exp->help.exp_ftp_info;
+	exp_ftp_info = &exp->help.exp_ftp_info;
 
 	/* Only mangle things once: original direction in POST_ROUTING
 	   and reply direction on PRE_ROUTING. */
@@ -257,29 +245,23 @@ static unsigned int help(struct ip_connt
 	}
 
 	datalen = (*pskb)->len - iph->ihl * 4 - tcph->doff * 4;
-	LOCK_BH(&ip_ftp_lock);
 	/* If it's in the right range... */
-	if (between(exp->seq + ct_ftp_info->len,
+	if (between(exp->seq + exp_ftp_info->len,
 		    ntohl(tcph->seq),
 		    ntohl(tcph->seq) + datalen)) {
-		if (!ftp_data_fixup(ct_ftp_info, ct, pskb, ctinfo, exp)) {
-			UNLOCK_BH(&ip_ftp_lock);
+		if (!ftp_data_fixup(exp_ftp_info, ct, pskb, ctinfo, exp))
 			return NF_DROP;
-		}
 	} else {
 		/* Half a match?  This means a partial retransmisison.
 		   It's a cracker being funky. */
 		if (net_ratelimit()) {
 			printk("FTP_NAT: partial packet %u/%u in %u/%u\n",
-			       exp->seq, ct_ftp_info->len,
+			       exp->seq, exp_ftp_info->len,
 			       ntohl(tcph->seq),
 			       ntohl(tcph->seq) + datalen);
 		}
-		UNLOCK_BH(&ip_ftp_lock);
 		return NF_DROP;
 	}
-	UNLOCK_BH(&ip_ftp_lock);
-
 	return NF_ACCEPT;
 }
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/net/ipv4/netfilter/ip_nat_irc.c linux-2.4.28-pre3/net/ipv4/netfilter/ip_nat_irc.c
--- linux-2.4.27/net/ipv4/netfilter/ip_nat_irc.c	2003-11-28 18:26:21.000000000 +0000
+++ linux-2.4.28-pre3/net/ipv4/netfilter/ip_nat_irc.c	2004-09-10 19:37:20.000000000 +0000
@@ -46,9 +46,6 @@ MODULE_PARM(ports, "1-" __MODULE_STRING(
 MODULE_PARM_DESC(ports, "port numbers of IRC servers");
 #endif
 
-/* protects irc part of conntracks */
-DECLARE_LOCK_EXTERN(ip_irc_lock);
-
 /* FIXME: Time out? --RR */
 
 static unsigned int
@@ -89,7 +86,7 @@ irc_nat_expected(struct sk_buff **pskb,
 	return ip_nat_setup_info(ct, &mr, hooknum);
 }
 
-static int irc_data_fixup(const struct ip_ct_irc_expect *ct_irc_info,
+static int irc_data_fixup(const struct ip_ct_irc_expect *exp_irc_info,
 			  struct ip_conntrack *ct,
 			  struct sk_buff **pskb,
 			  enum ip_conntrack_info ctinfo,
@@ -104,23 +101,16 @@ static int irc_data_fixup(const struct i
 	/* "4294967296 65635 " */
 	char buffer[18];
 
-	MUST_BE_LOCKED(&ip_irc_lock);
-
 	DEBUGP("IRC_NAT: info (seq %u + %u) in %u\n",
-	       expect->seq, ct_irc_info->len,
+	       expect->seq, exp_irc_info->len,
 	       ntohl(tcph->seq));
 
 	newip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
 
 	/* Alter conntrack's expectations. */
-
-	/* We can read expect here without conntrack lock, since it's
-	   only set in ip_conntrack_irc, with ip_irc_lock held
-	   writable */
-
 	t = expect->tuple;
 	t.dst.ip = newip;
-	for (port = ct_irc_info->port; port != 0; port++) {
+	for (port = exp_irc_info->port; port != 0; port++) {
 		t.dst.u.tcp.port = htons(port);
 		if (ip_conntrack_change_expect(expect, &t) == 0) {
 			DEBUGP("using port %d", port);
@@ -150,7 +140,7 @@ static int irc_data_fixup(const struct i
 
 	return ip_nat_mangle_tcp_packet(pskb, ct, ctinfo, 
 					expect->seq - ntohl(tcph->seq),
-					ct_irc_info->len, buffer, 
+					exp_irc_info->len, buffer, 
 					strlen(buffer));
 }
 
@@ -165,12 +155,12 @@ static unsigned int help(struct ip_connt
 	struct tcphdr *tcph = (void *) iph + iph->ihl * 4;
 	unsigned int datalen;
 	int dir;
-	struct ip_ct_irc_expect *ct_irc_info;
+	struct ip_ct_irc_expect *exp_irc_info;
 
 	if (!exp)
 		DEBUGP("ip_nat_irc: no exp!!");
 		
-	ct_irc_info = &exp->help.exp_irc_info;
+	exp_irc_info = &exp->help.exp_irc_info;
 
 	/* Only mangle things once: original direction in POST_ROUTING
 	   and reply direction on PRE_ROUTING. */
@@ -187,30 +177,24 @@ static unsigned int help(struct ip_connt
 	DEBUGP("got beyond not touching\n");
 
 	datalen = (*pskb)->len - iph->ihl * 4 - tcph->doff * 4;
-	LOCK_BH(&ip_irc_lock);
 	/* Check wether the whole IP/address pattern is carried in the payload */
-	if (between(exp->seq + ct_irc_info->len,
+	if (between(exp->seq + exp_irc_info->len,
 		    ntohl(tcph->seq),
 		    ntohl(tcph->seq) + datalen)) {
-		if (!irc_data_fixup(ct_irc_info, ct, pskb, ctinfo, exp)) {
-			UNLOCK_BH(&ip_irc_lock);
+		if (!irc_data_fixup(exp_irc_info, ct, pskb, ctinfo, exp))
 			return NF_DROP;
-		}
 	} else { 
 		/* Half a match?  This means a partial retransmisison.
 		   It's a cracker being funky. */
 		if (net_ratelimit()) {
 			printk
 			    ("IRC_NAT: partial packet %u/%u in %u/%u\n",
-			     exp->seq, ct_irc_info->len,
+			     exp->seq, exp_irc_info->len,
 			     ntohl(tcph->seq),
 			     ntohl(tcph->seq) + datalen);
 		}
-		UNLOCK_BH(&ip_irc_lock);
 		return NF_DROP;
 	}
-	UNLOCK_BH(&ip_irc_lock);
-
 	return NF_ACCEPT;
 }
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/net/ipv4/netfilter/ip_nat_snmp_basic.c linux-2.4.28-pre3/net/ipv4/netfilter/ip_nat_snmp_basic.c
--- linux-2.4.27/net/ipv4/netfilter/ip_nat_snmp_basic.c	2003-11-28 18:26:21.000000000 +0000
+++ linux-2.4.28-pre3/net/ipv4/netfilter/ip_nat_snmp_basic.c	2004-09-10 19:36:28.000000000 +0000
@@ -862,6 +862,77 @@ static unsigned char snmp_request_decode
 	return 1;
 }
 
+/* 
+ * Fast checksum update for possibly oddly-aligned UDP byte, from the
+ * code example in the draft.
+ */
+static void fast_csum(unsigned char *csum,
+                      const unsigned char *optr,
+                      const unsigned char *nptr,
+                      int odd)
+{
+	long x, old, new;
+	
+	x = csum[0] * 256 + csum[1];
+	
+	x =~ x & 0xFFFF;
+	
+	if (odd) old = optr[0] * 256;
+	else old = optr[0];
+	
+	x -= old & 0xFFFF;
+	if (x <= 0) {
+		x--;
+		x &= 0xFFFF;
+	}
+	
+	if (odd) new = nptr[0] * 256;
+	else new = nptr[0];
+	
+	x += new & 0xFFFF;
+	if (x & 0x10000) {
+		x++;
+		x &= 0xFFFF;
+	}
+	
+	x =~ x & 0xFFFF;
+	csum[0] = x / 256;
+	csum[1] = x & 0xFF;
+}
+
+/* 
+ * Mangle IP address.
+ * 	- begin points to the start of the snmp messgae
+ *      - addr points to the start of the address
+ */
+static void inline mangle_address(unsigned char *begin,
+                                  unsigned char *addr,
+                                  const struct oct1_map *map,
+                                  u_int16_t *check)
+{
+	if (map->from == NOCT1(*addr)) {
+		u_int32_t old;
+		
+		if (debug)
+			memcpy(&old, (unsigned char *)addr, sizeof(old));
+			
+		*addr = map->to;
+		
+		/* Update UDP checksum if being used */
+		if (*check) {
+			unsigned char odd = !((addr - begin) % 2);
+			
+			fast_csum((unsigned char *)check,
+			          &map->from, &map->to, odd);
+			          
+		}
+		
+		if (debug)
+			printk(KERN_DEBUG "bsalg: mapped %u.%u.%u.%u to "
+			       "%u.%u.%u.%u\n", NIPQUAD(old), NIPQUAD(*addr));
+	}
+}
+
 static unsigned char snmp_trap_decode(struct asn1_ctx *ctx,
                                       struct snmp_v1_trap *trap,
                                       const struct oct1_map *map,
@@ -952,77 +1023,6 @@ static void hex_dump(unsigned char *buf,
 	printk("\n");
 }
 
-/* 
- * Fast checksum update for possibly oddly-aligned UDP byte, from the
- * code example in the draft.
- */
-static void fast_csum(unsigned char *csum,
-                      const unsigned char *optr,
-                      const unsigned char *nptr,
-                      int odd)
-{
-	long x, old, new;
-	
-	x = csum[0] * 256 + csum[1];
-	
-	x =~ x & 0xFFFF;
-	
-	if (odd) old = optr[0] * 256;
-	else old = optr[0];
-	
-	x -= old & 0xFFFF;
-	if (x <= 0) {
-		x--;
-		x &= 0xFFFF;
-	}
-	
-	if (odd) new = nptr[0] * 256;
-	else new = nptr[0];
-	
-	x += new & 0xFFFF;
-	if (x & 0x10000) {
-		x++;
-		x &= 0xFFFF;
-	}
-	
-	x =~ x & 0xFFFF;
-	csum[0] = x / 256;
-	csum[1] = x & 0xFF;
-}
-
-/* 
- * Mangle IP address.
- * 	- begin points to the start of the snmp messgae
- *      - addr points to the start of the address
- */
-static void inline mangle_address(unsigned char *begin,
-                                  unsigned char *addr,
-                                  const struct oct1_map *map,
-                                  u_int16_t *check)
-{
-	if (map->from == NOCT1(*addr)) {
-		u_int32_t old;
-		
-		if (debug)
-			memcpy(&old, (unsigned char *)addr, sizeof(old));
-			
-		*addr = map->to;
-		
-		/* Update UDP checksum if being used */
-		if (*check) {
-			unsigned char odd = !((addr - begin) % 2);
-			
-			fast_csum((unsigned char *)check,
-			          &map->from, &map->to, odd);
-			          
-		}
-		
-		if (debug)
-			printk(KERN_DEBUG "bsalg: mapped %u.%u.%u.%u to "
-			       "%u.%u.%u.%u\n", NIPQUAD(old), NIPQUAD(*addr));
-	}
-}
-
 /*
  * Parse and mangle SNMP message according to mapping.
  * (And this is the fucking 'basic' method).
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/net/ipv4/tcp_input.c linux-2.4.28-pre3/net/ipv4/tcp_input.c
--- linux-2.4.27/net/ipv4/tcp_input.c	2004-08-07 23:26:07.000000000 +0000
+++ linux-2.4.28-pre3/net/ipv4/tcp_input.c	2004-09-10 19:33:09.000000000 +0000
@@ -851,8 +851,10 @@ static void tcp_init_metrics(struct sock
 	 * to low value, and then abruptly stops to do it and starts to delay
 	 * ACKs, wait for troubles.
 	 */
-	if (dst->rtt > tp->srtt)
+	if (dst->rtt > tp->srtt) {
 		tp->srtt = dst->rtt;
+		tp->rtt_seq = tp->snd_nxt;
+	}
 	if (dst->rttvar > tp->mdev) {
 		tp->mdev = dst->rttvar;
 		tp->mdev_max = tp->rttvar = max(tp->mdev, TCP_RTO_MIN);
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/net/ipv6/addrconf.c linux-2.4.28-pre3/net/ipv6/addrconf.c
--- linux-2.4.27/net/ipv6/addrconf.c	2003-11-28 18:26:21.000000000 +0000
+++ linux-2.4.28-pre3/net/ipv6/addrconf.c	2004-09-10 19:36:55.000000000 +0000
@@ -3,7 +3,7 @@
  *	Linux INET6 implementation
  *
  *	Authors:
- *	Pedro Roque		<roque@di.fc.ul.pt>	
+ *	Pedro Roque		<pedro_m@yahoo.com>	
  *	Alexey Kuznetsov	<kuznet@ms2.inr.ac.ru>
  *
  *	$Id: addrconf.c,v 1.69 2001/10/31 21:55:54 davem Exp $
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/net/ipv6/af_inet6.c linux-2.4.28-pre3/net/ipv6/af_inet6.c
--- linux-2.4.27/net/ipv6/af_inet6.c	2004-08-07 23:26:07.000000000 +0000
+++ linux-2.4.28-pre3/net/ipv6/af_inet6.c	2004-09-10 19:35:17.000000000 +0000
@@ -3,7 +3,7 @@
  *	Linux INET6 implementation 
  *
  *	Authors:
- *	Pedro Roque		<roque@di.fc.ul.pt>	
+ *	Pedro Roque		<pedro_m@yahoo.com>	
  *
  *	Adapted from linux/net/ipv4/af_inet.c
  *
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/net/ipv6/datagram.c linux-2.4.28-pre3/net/ipv6/datagram.c
--- linux-2.4.27/net/ipv6/datagram.c	2003-06-13 14:51:39.000000000 +0000
+++ linux-2.4.28-pre3/net/ipv6/datagram.c	2004-09-10 19:32:35.000000000 +0000
@@ -3,7 +3,7 @@
  *	Linux INET6 implementation 
  *
  *	Authors:
- *	Pedro Roque		<roque@di.fc.ul.pt>	
+ *	Pedro Roque		<pedro_m@yahoo.com>	
  *
  *	$Id: datagram.c,v 1.23 2001/09/01 00:31:50 davem Exp $
  *
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/net/ipv6/exthdrs.c linux-2.4.28-pre3/net/ipv6/exthdrs.c
--- linux-2.4.27/net/ipv6/exthdrs.c	2004-04-14 13:05:41.000000000 +0000
+++ linux-2.4.28-pre3/net/ipv6/exthdrs.c	2004-09-10 19:32:16.000000000 +0000
@@ -3,7 +3,7 @@
  *	Linux INET6 implementation
  *
  *	Authors:
- *	Pedro Roque		<roque@di.fc.ul.pt>
+ *	Pedro Roque		<pedro_m@yahoo.com>
  *	Andi Kleen		<ak@muc.de>
  *	Alexey Kuznetsov	<kuznet@ms2.inr.ac.ru>
  *
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/net/ipv6/icmp.c linux-2.4.28-pre3/net/ipv6/icmp.c
--- linux-2.4.27/net/ipv6/icmp.c	2004-08-07 23:26:07.000000000 +0000
+++ linux-2.4.28-pre3/net/ipv6/icmp.c	2004-09-10 19:33:37.000000000 +0000
@@ -3,7 +3,7 @@
  *	Linux INET6 implementation
  *
  *	Authors:
- *	Pedro Roque		<roque@di.fc.ul.pt>
+ *	Pedro Roque		<pedro_m@yahoo.com>
  *
  *	$Id: icmp.c,v 1.37 2001/09/18 22:29:10 davem Exp $
  *
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/net/ipv6/ip6_fib.c linux-2.4.28-pre3/net/ipv6/ip6_fib.c
--- linux-2.4.27/net/ipv6/ip6_fib.c	2003-08-25 11:44:44.000000000 +0000
+++ linux-2.4.28-pre3/net/ipv6/ip6_fib.c	2004-09-10 19:36:25.000000000 +0000
@@ -3,7 +3,7 @@
  *	Forwarding Information Database
  *
  *	Authors:
- *	Pedro Roque		<roque@di.fc.ul.pt>	
+ *	Pedro Roque		<pedro_m@yahoo.com>	
  *
  *	$Id: ip6_fib.c,v 1.25 2001/10/31 21:55:55 davem Exp $
  *
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/net/ipv6/ip6_input.c linux-2.4.28-pre3/net/ipv6/ip6_input.c
--- linux-2.4.27/net/ipv6/ip6_input.c	2003-08-25 11:44:44.000000000 +0000
+++ linux-2.4.28-pre3/net/ipv6/ip6_input.c	2004-09-10 19:36:09.000000000 +0000
@@ -3,7 +3,7 @@
  *	Linux INET6 implementation 
  *
  *	Authors:
- *	Pedro Roque		<roque@di.fc.ul.pt>
+ *	Pedro Roque		<pedro_m@yahoo.com>
  *	Ian P. Morris		<I.P.Morris@soton.ac.uk>
  *
  *	$Id: ip6_input.c,v 1.19 2000/12/13 18:31:50 davem Exp $
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/net/ipv6/ip6_output.c linux-2.4.28-pre3/net/ipv6/ip6_output.c
--- linux-2.4.27/net/ipv6/ip6_output.c	2003-08-25 11:44:44.000000000 +0000
+++ linux-2.4.28-pre3/net/ipv6/ip6_output.c	2004-09-10 19:32:21.000000000 +0000
@@ -3,7 +3,7 @@
  *	Linux INET6 implementation 
  *
  *	Authors:
- *	Pedro Roque		<roque@di.fc.ul.pt>	
+ *	Pedro Roque		<pedro_m@yahoo.com>	
  *
  *	$Id: ip6_output.c,v 1.33 2001/09/20 00:35:35 davem Exp $
  *
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/net/ipv6/ipv6_sockglue.c linux-2.4.28-pre3/net/ipv6/ipv6_sockglue.c
--- linux-2.4.27/net/ipv6/ipv6_sockglue.c	2004-04-14 13:05:41.000000000 +0000
+++ linux-2.4.28-pre3/net/ipv6/ipv6_sockglue.c	2004-09-10 19:32:28.000000000 +0000
@@ -3,7 +3,7 @@
  *	Linux INET6 implementation 
  *
  *	Authors:
- *	Pedro Roque		<roque@di.fc.ul.pt>	
+ *	Pedro Roque		<pedro_m@yahoo.com>	
  *
  *	Based on linux/net/ipv4/ip_sockglue.c
  *
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/net/ipv6/mcast.c linux-2.4.28-pre3/net/ipv6/mcast.c
--- linux-2.4.27/net/ipv6/mcast.c	2004-08-07 23:26:07.000000000 +0000
+++ linux-2.4.28-pre3/net/ipv6/mcast.c	2004-09-10 19:36:36.000000000 +0000
@@ -3,7 +3,7 @@
  *	Linux INET6 implementation 
  *
  *	Authors:
- *	Pedro Roque		<roque@di.fc.ul.pt>	
+ *	Pedro Roque		<pedro_m@yahoo.com>	
  *
  *	$Id: mcast.c,v 1.38 2001/08/15 07:36:31 davem Exp $
  *
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/net/ipv6/ndisc.c linux-2.4.28-pre3/net/ipv6/ndisc.c
--- linux-2.4.27/net/ipv6/ndisc.c	2004-04-14 13:05:41.000000000 +0000
+++ linux-2.4.28-pre3/net/ipv6/ndisc.c	2004-09-10 19:35:27.000000000 +0000
@@ -3,7 +3,7 @@
  *	Linux INET6 implementation 
  *
  *	Authors:
- *	Pedro Roque		<roque@di.fc.ul.pt>	
+ *	Pedro Roque		<pedro_m@yahoo.com>	
  *	Mike Shaver		<shaver@ingenia.com>
  *
  *	This program is free software; you can redistribute it and/or
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/net/ipv6/netfilter/ip6t_LOG.c linux-2.4.28-pre3/net/ipv6/netfilter/ip6t_LOG.c
--- linux-2.4.27/net/ipv6/netfilter/ip6t_LOG.c	2003-08-25 11:44:44.000000000 +0000
+++ linux-2.4.28-pre3/net/ipv6/netfilter/ip6t_LOG.c	2004-09-10 19:33:38.000000000 +0000
@@ -56,7 +56,7 @@ static u_int8_t ip6_nexthdr(u_int8_t cur
 		repeatedly...with a large stick...no, an even LARGER
 		stick...no, you're still not thinking big enough */
 			nexthdr = **hdrptr;
-			hdrlen = *hdrptr[1] * 4 + 8;
+			hdrlen = (*hdrptr)[1] * 4 + 8;
 			*hdrptr = *hdrptr + hdrlen;
 			break;
 		/*stupid rfc2402 */
@@ -64,7 +64,7 @@ static u_int8_t ip6_nexthdr(u_int8_t cur
 		case IPPROTO_ROUTING:
 		case IPPROTO_HOPOPTS:
 			nexthdr = **hdrptr;
-			hdrlen = *hdrptr[1] * 8 + 8;
+			hdrlen = (*hdrptr)[1] * 8 + 8;
 			*hdrptr = *hdrptr + hdrlen;
 			break;
 		case IPPROTO_FRAGMENT:
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/net/ipv6/protocol.c linux-2.4.28-pre3/net/ipv6/protocol.c
--- linux-2.4.27/net/ipv6/protocol.c	2001-05-20 00:56:43.000000000 +0000
+++ linux-2.4.28-pre3/net/ipv6/protocol.c	2004-09-10 19:32:54.000000000 +0000
@@ -7,7 +7,7 @@
  *
  * Version:	$Id: protocol.c,v 1.10 2001/05/18 02:25:49 davem Exp $
  *
- * Authors:	Pedro Roque	<roque@di.fc.ul.pt>
+ * Authors:	Pedro Roque	<pedro_m@yahoo.com>
  *
  *		This program is free software; you can redistribute it and/or
  *		modify it under the terms of the GNU General Public License
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/net/ipv6/raw.c linux-2.4.28-pre3/net/ipv6/raw.c
--- linux-2.4.27/net/ipv6/raw.c	2004-08-07 23:26:07.000000000 +0000
+++ linux-2.4.28-pre3/net/ipv6/raw.c	2004-09-10 19:34:11.000000000 +0000
@@ -3,7 +3,7 @@
  *	Linux INET6 implementation 
  *
  *	Authors:
- *	Pedro Roque		<roque@di.fc.ul.pt>	
+ *	Pedro Roque		<pedro_m@yahoo.com>	
  *
  *	Adapted from linux/net/ipv4/raw.c
  *
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/net/ipv6/reassembly.c linux-2.4.28-pre3/net/ipv6/reassembly.c
--- linux-2.4.27/net/ipv6/reassembly.c	2003-08-25 11:44:44.000000000 +0000
+++ linux-2.4.28-pre3/net/ipv6/reassembly.c	2004-09-10 19:33:41.000000000 +0000
@@ -3,7 +3,7 @@
  *	Linux INET6 implementation 
  *
  *	Authors:
- *	Pedro Roque		<roque@di.fc.ul.pt>	
+ *	Pedro Roque		<pedro_m@yahoo.com>	
  *
  *	$Id: reassembly.c,v 1.26 2001/03/07 22:00:57 davem Exp $
  *
@@ -191,14 +191,18 @@ static void ip6_frag_secret_rebuild(unsi
 atomic_t ip6_frag_mem = ATOMIC_INIT(0);
 
 /* Memory Tracking Functions. */
-static inline void frag_kfree_skb(struct sk_buff *skb)
+static inline void frag_kfree_skb(struct sk_buff *skb, int *work)
 {
+	if (work)
+		*work -= skb->truesize;
 	atomic_sub(skb->truesize, &ip6_frag_mem);
 	kfree_skb(skb);
 }
 
-static inline void frag_free_queue(struct frag_queue *fq)
+static inline void frag_free_queue(struct frag_queue *fq, int *work)
 {
+	if (work)
+		*work -= sizeof(struct frag_queue);
 	atomic_sub(sizeof(struct frag_queue), &ip6_frag_mem);
 	kfree(fq);
 }
@@ -216,7 +220,7 @@ static inline struct frag_queue *frag_al
 /* Destruction primitives. */
 
 /* Complete destruction of fq. */
-static void ip6_frag_destroy(struct frag_queue *fq)
+static void ip6_frag_destroy(struct frag_queue *fq, int *work)
 {
 	struct sk_buff *fp;
 
@@ -228,17 +232,17 @@ static void ip6_frag_destroy(struct frag
 	while (fp) {
 		struct sk_buff *xp = fp->next;
 
-		frag_kfree_skb(fp);
+		frag_kfree_skb(fp, work);
 		fp = xp;
 	}
 
-	frag_free_queue(fq);
+	frag_free_queue(fq, work);
 }
 
-static __inline__ void fq_put(struct frag_queue *fq)
+static __inline__ void fq_put(struct frag_queue *fq, int *work)
 {
 	if (atomic_dec_and_test(&fq->refcnt))
-		ip6_frag_destroy(fq);
+		ip6_frag_destroy(fq, work);
 }
 
 /* Kill fq entry. It is not destroyed immediately,
@@ -260,10 +264,13 @@ static void ip6_evictor(void)
 {
 	struct frag_queue *fq;
 	struct list_head *tmp;
+	int work;
 
-	for(;;) {
-		if (atomic_read(&ip6_frag_mem) <= sysctl_ip6frag_low_thresh)
-			return;
+	work = atomic_read(&ip6_frag_mem) - sysctl_ip6frag_low_thresh;
+	if (work <= 0)
+		return;
+
+	while(work > 0) {
 		read_lock(&ip6_frag_lock);
 		if (list_empty(&ip6_frag_lru_list)) {
 			read_unlock(&ip6_frag_lock);
@@ -279,7 +286,7 @@ static void ip6_evictor(void)
 			fq_kill(fq);
 		spin_unlock(&fq->lock);
 
-		fq_put(fq);
+		fq_put(fq, &work);
 		IP6_INC_STATS_BH(Ip6ReasmFails);
 	}
 }
@@ -316,7 +323,7 @@ static void ip6_frag_expire(unsigned lon
 	}
 out:
 	spin_unlock(&fq->lock);
-	fq_put(fq);
+	fq_put(fq, NULL);
 }
 
 /* Creation primitives. */
@@ -336,7 +343,7 @@ static struct frag_queue *ip6_frag_inter
 			atomic_inc(&fq->refcnt);
 			write_unlock(&ip6_frag_lock);
 			fq_in->last_in |= COMPLETE;
-			fq_put(fq_in);
+			fq_put(fq_in, NULL);
 			return fq;
 		}
 	}
@@ -533,7 +540,7 @@ static void ip6_frag_queue(struct frag_q
 				fq->fragments = next;
 
 			fq->meat -= free_it->len;
-			frag_kfree_skb(free_it);
+			frag_kfree_skb(free_it, NULL);
 		}
 	}
 
@@ -733,7 +740,7 @@ int ipv6_reassembly(struct sk_buff **skb
 			ret = ip6_frag_reasm(fq, skbp, dev);
 
 		spin_unlock(&fq->lock);
-		fq_put(fq);
+		fq_put(fq, NULL);
 		return ret;
 	}
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/net/ipv6/route.c linux-2.4.28-pre3/net/ipv6/route.c
--- linux-2.4.27/net/ipv6/route.c	2004-02-18 13:36:32.000000000 +0000
+++ linux-2.4.28-pre3/net/ipv6/route.c	2004-09-10 19:33:10.000000000 +0000
@@ -3,7 +3,7 @@
  *	FIB front-end.
  *
  *	Authors:
- *	Pedro Roque		<roque@di.fc.ul.pt>	
+ *	Pedro Roque		<pedro_m@yahoo.com>	
  *
  *	$Id: route.c,v 1.56 2001/10/31 21:55:55 davem Exp $
  *
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/net/ipv6/sit.c linux-2.4.28-pre3/net/ipv6/sit.c
--- linux-2.4.27/net/ipv6/sit.c	2004-08-07 23:26:07.000000000 +0000
+++ linux-2.4.28-pre3/net/ipv6/sit.c	2004-09-10 19:36:53.000000000 +0000
@@ -3,7 +3,7 @@
  *	Linux INET6 implementation
  *
  *	Authors:
- *	Pedro Roque		<roque@di.fc.ul.pt>	
+ *	Pedro Roque		<pedro_m@yahoo.com>	
  *	Alexey Kuznetsov	<kuznet@ms2.inr.ac.ru>
  *
  *	$Id: sit.c,v 1.53 2001/09/25 05:09:53 davem Exp $
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/net/ipv6/tcp_ipv6.c linux-2.4.28-pre3/net/ipv6/tcp_ipv6.c
--- linux-2.4.27/net/ipv6/tcp_ipv6.c	2004-08-07 23:26:07.000000000 +0000
+++ linux-2.4.28-pre3/net/ipv6/tcp_ipv6.c	2004-09-10 19:35:17.000000000 +0000
@@ -3,7 +3,7 @@
  *	Linux INET6 implementation 
  *
  *	Authors:
- *	Pedro Roque		<roque@di.fc.ul.pt>	
+ *	Pedro Roque		<pedro_m@yahoo.com>	
  *
  *	$Id: tcp_ipv6.c,v 1.142.2.1 2001/12/21 05:06:08 davem Exp $
  *
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/net/ipv6/udp.c linux-2.4.28-pre3/net/ipv6/udp.c
--- linux-2.4.27/net/ipv6/udp.c	2004-08-07 23:26:07.000000000 +0000
+++ linux-2.4.28-pre3/net/ipv6/udp.c	2004-09-10 19:36:30.000000000 +0000
@@ -3,7 +3,7 @@
  *	Linux INET6 implementation 
  *
  *	Authors:
- *	Pedro Roque		<roque@di.fc.ul.pt>	
+ *	Pedro Roque		<pedro_m@yahoo.com>	
  *
  *	Based on linux/ipv4/udp.c
  *
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/net/ipx/af_ipx.c linux-2.4.28-pre3/net/ipx/af_ipx.c
--- linux-2.4.27/net/ipx/af_ipx.c	2001-09-30 19:26:13.000000000 +0000
+++ linux-2.4.28-pre3/net/ipx/af_ipx.c	2004-09-10 19:32:54.000000000 +0000
@@ -1544,7 +1544,8 @@ static int ipxrtr_route_packet(struct so
 	ipx->ipx_pktsize = htons(len + sizeof(struct ipxhdr));
 	IPX_SKB_CB(skb)->ipx_tctrl = 0;
 	ipx->ipx_type 	 = usipx->sipx_type;
-	skb->h.raw 	 = (void *)skb->nh.ipxh = ipx;
+	skb->nh.ipxh	 = ipx;
+	skb->h.raw 	 = (void *)skb->nh.ipxh;
 
 	IPX_SKB_CB(skb)->last_hop.index = -1;
 #ifdef CONFIG_IPX_INTERN
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/net/irda/ircomm/ircomm_param.c linux-2.4.28-pre3/net/irda/ircomm/ircomm_param.c
--- linux-2.4.27/net/irda/ircomm/ircomm_param.c	2003-11-28 18:26:21.000000000 +0000
+++ linux-2.4.28-pre3/net/irda/ircomm/ircomm_param.c	2004-09-10 19:34:52.000000000 +0000
@@ -198,7 +198,7 @@ static int ircomm_param_service_type(voi
 		IRDA_DEBUG(2, "%s(), No common service type to use!\n", __FUNCTION__);
 		return -1;
 	}
-	IRDA_DEBUG(0, __FUNCTION__ "%s(), services in common=%02x\n", __FUNCTION__,
+	IRDA_DEBUG(0, "%s(), services in common=%02x\n", __FUNCTION__ ,
 		   service_type);
 
 	/*
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/net/irda/irlmp.c linux-2.4.28-pre3/net/irda/irlmp.c
--- linux-2.4.27/net/irda/irlmp.c	2003-06-13 14:51:39.000000000 +0000
+++ linux-2.4.28-pre3/net/irda/irlmp.c	2004-09-10 19:36:47.000000000 +0000
@@ -1241,7 +1241,7 @@ void irlmp_flow_indication(struct lap_cb
 	/* Get the number of lsap. That's the only safe way to know
 	 * that we have looped around... - Jean II */
 	lsap_todo = HASHBIN_GET_SIZE(self->lsaps);
-	IRDA_DEBUG(4, __FUNCTION__ "() : %d lsaps to scan\n", lsap_todo);
+	IRDA_DEBUG(4, "%s() : %d lsaps to scan\n", __FUNCTION__ , lsap_todo);
 
 	/* Poll lsap in order until the queue is full or until we
 	 * tried them all.
@@ -1255,7 +1255,7 @@ void irlmp_flow_indication(struct lap_cb
 			/* Note that if there is only one LSAP on the LAP
 			 * (most common case), self->flow_next is always NULL,
 			 * so we always avoid this loop. - Jean II */
-			IRDA_DEBUG(4, __FUNCTION__ "() : searching my LSAP\n");
+			IRDA_DEBUG(4, "%s() : searching my LSAP\n", __FUNCTION__ );
 
 			/* We look again in hashbins, because the lsap
 			 * might have gone away... - Jean II */
@@ -1274,14 +1274,14 @@ void irlmp_flow_indication(struct lap_cb
 
 		/* Next time, we will get the next one (or the first one) */
 		self->flow_next = (struct lsap_cb *) hashbin_get_next(self->lsaps);
-		IRDA_DEBUG(4, __FUNCTION__ "() : curr is %p, next was %p and is now %p, still %d to go - queue len = %d\n", curr, next, self->flow_next, lsap_todo, IRLAP_GET_TX_QUEUE_LEN(self->irlap));
+		IRDA_DEBUG(4, "%s() : curr is %p, next was %p and is now %p, still %d to go - queue len = %d\n", __FUNCTION__ , curr, next, self->flow_next, lsap_todo, IRLAP_GET_TX_QUEUE_LEN(self->irlap));
 
 		/* Inform lsap user that it can send one more packet. */
 		if (curr->notify.flow_indication != NULL)
 			curr->notify.flow_indication(curr->notify.instance, 
 						     curr, flow);
 		else
-			IRDA_DEBUG(1, __FUNCTION__ "(), no handler\n");
+			IRDA_DEBUG(1, "%s(), no handler\n", __FUNCTION__ );
 	}
 }
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/net/irda/wrapper.c linux-2.4.28-pre3/net/irda/wrapper.c
--- linux-2.4.27/net/irda/wrapper.c	2003-11-28 18:26:21.000000000 +0000
+++ linux-2.4.28-pre3/net/irda/wrapper.c	2004-09-10 19:36:09.000000000 +0000
@@ -37,8 +37,6 @@
 #include <net/irda/irlap_frame.h>
 #include <net/irda/irda_device.h>
 
-static inline int stuff_byte(__u8 byte, __u8 *buf);
-
 static void state_outside_frame(struct net_device *dev, 
 				struct net_device_stats *stats, 
 				iobuff_t *rx_buff, __u8 byte);
@@ -62,6 +60,32 @@ static void (*state[])(struct net_device
 };
 
 /*
+ * Function stuff_byte (byte, buf)
+ *
+ *    Byte stuff one single byte and put the result in buffer pointed to by
+ *    buf. The buffer must at all times be able to have two bytes inserted.
+ * 
+ */
+static inline int stuff_byte(__u8 byte, __u8 *buf) 
+{
+	switch (byte) {
+	case BOF: /* FALLTHROUGH */
+	case EOF: /* FALLTHROUGH */
+	case CE:
+		/* Insert transparently coded */
+		buf[0] = CE;               /* Send link escape */
+		buf[1] = byte^IRDA_TRANS;    /* Complement bit 5 */
+		return 2;
+		/* break; */
+	default:
+		 /* Non-special value, no transparency required */
+		buf[0] = byte;
+		return 1;
+		/* break; */
+	}
+}
+
+/*
  * Function async_wrap (skb, *tx_buff, buffsize)
  *
  *    Makes a new buffer with wrapping and stuffing, should check that 
@@ -140,32 +164,6 @@ int async_wrap_skb(struct sk_buff *skb, 
 }
 
 /*
- * Function stuff_byte (byte, buf)
- *
- *    Byte stuff one single byte and put the result in buffer pointed to by
- *    buf. The buffer must at all times be able to have two bytes inserted.
- * 
- */
-static inline int stuff_byte(__u8 byte, __u8 *buf) 
-{
-	switch (byte) {
-	case BOF: /* FALLTHROUGH */
-	case EOF: /* FALLTHROUGH */
-	case CE:
-		/* Insert transparently coded */
-		buf[0] = CE;               /* Send link escape */
-		buf[1] = byte^IRDA_TRANS;    /* Complement bit 5 */
-		return 2;
-		/* break; */
-	default:
-		 /* Non-special value, no transparency required */
-		buf[0] = byte;
-		return 1;
-		/* break; */
-	}
-}
-
-/*
  * Function async_bump (buf, len, stats)
  *
  *    Got a frame, make a copy of it, and pass it up the stack! We can try
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/net/netlink/af_netlink.c linux-2.4.28-pre3/net/netlink/af_netlink.c
--- linux-2.4.27/net/netlink/af_netlink.c	2004-02-18 13:36:32.000000000 +0000
+++ linux-2.4.28-pre3/net/netlink/af_netlink.c	2004-09-10 19:34:55.000000000 +0000
@@ -42,6 +42,7 @@
 #include <linux/notifier.h>
 #include <net/sock.h>
 #include <net/scm.h>
+#include <linux/tqueue.h>
 
 #define Nprintk(a...)
 
@@ -63,6 +64,15 @@ struct netlink_opt
 	void			(*data_ready)(struct sock *sk, int bytes);
 };
 
+struct netlink_work
+{
+	struct sock 		*sk;
+	int 			len;
+	struct tq_struct	work;
+};
+
+static DECLARE_TASK_QUEUE(tq_netlink);
+static DECLARE_WAIT_QUEUE_HEAD(netlink_thread_wait);
 static struct sock *nl_table[MAX_LINKS];
 static DECLARE_WAIT_QUEUE_HEAD(nl_table_wait);
 static unsigned nl_nonroot[MAX_LINKS];
@@ -81,6 +91,15 @@ static atomic_t nl_table_users = ATOMIC_
 
 static struct notifier_block *netlink_chain;
 
+void netlink_tq_handler(void *data)
+{
+	struct netlink_work *work = data;
+	
+	work->sk->data_ready(work->sk, work->len);
+	sock_put(work->sk);
+	kfree(work);
+}
+
 static void netlink_sock_destruct(struct sock *sk)
 {
 	skb_queue_purge(&sk->receive_queue);
@@ -437,6 +456,8 @@ retry:
 
 	if (atomic_read(&sk->rmem_alloc) > sk->rcvbuf ||
 	    test_bit(0, &sk->protinfo.af_netlink->state)) {
+		struct task_struct *client;
+		
 		if (!timeo) {
 			if (ssk->protinfo.af_netlink->pid == 0)
 				netlink_overrun(sk);
@@ -445,6 +466,19 @@ retry:
 			return -EAGAIN;
 		}
 
+		if (!sk->protinfo.af_netlink->pid) {
+			/* Kernel is sending information to user space
+			 * and socket buffer is full: Wake up user */
+			
+			client = find_task_by_pid(sk->protinfo.af_netlink->pid);
+			if (!client) {
+				sock_put(sk);
+				kfree_skb(skb);
+				return -EAGAIN;
+			}
+			wake_up_process(client);
+		}
+
 		__set_current_state(TASK_INTERRUPTIBLE);
 		add_wait_queue(&sk->protinfo.af_netlink->wait, &wait);
 
@@ -467,8 +501,26 @@ retry:
 	skb_orphan(skb);
 	skb_set_owner_r(skb, sk);
 	skb_queue_tail(&sk->receive_queue, skb);
-	sk->data_ready(sk, len);
-	sock_put(sk);
+
+	if (!sk->protinfo.af_netlink->pid) {
+		struct netlink_work *nlwork = 
+			kmalloc(sizeof(struct netlink_work), GFP_KERNEL);
+		
+		if  (!nlwork) {
+			sock_put(sk);
+			return -EAGAIN;
+		}
+		
+		INIT_TQUEUE(&nlwork->work, netlink_tq_handler, nlwork);
+		nlwork->sk = sk;
+		nlwork->len = len;
+		queue_task(&nlwork->work, &tq_netlink);
+		wake_up(&netlink_thread_wait);
+	} else {
+		sk->data_ready(sk, len);
+		sock_put(sk);
+	}
+	
 	return len;
 
 no_dst:
@@ -490,7 +542,22 @@ static __inline__ int netlink_broadcast_
                 skb_orphan(skb);
 		skb_set_owner_r(skb, sk);
 		skb_queue_tail(&sk->receive_queue, skb);
-		sk->data_ready(sk, skb->len);
+
+		if (!sk->protinfo.af_netlink->pid) {
+			struct netlink_work *nlwork = 
+				kmalloc(sizeof(struct netlink_work), GFP_KERNEL);
+		
+			if  (!nlwork) 
+				return -EAGAIN;
+		
+			INIT_TQUEUE(&nlwork->work, netlink_tq_handler, nlwork);
+			nlwork->sk = sk;
+			nlwork->len = skb->len;
+			queue_task(&nlwork->work, &tq_netlink);
+			wake_up(&netlink_thread_wait);
+		} else 
+			sk->data_ready(sk, skb->len);
+
 		return 0;
 	}
 	return -1;
@@ -534,11 +601,12 @@ void netlink_broadcast(struct sock *ssk,
 			netlink_overrun(sk);
 			/* Clone failed. Notify ALL listeners. */
 			failure = 1;
+			sock_put(sk);
 		} else if (netlink_broadcast_deliver(sk, skb2)) {
 			netlink_overrun(sk);
+			sock_put(sk);
 		} else
 			skb2 = NULL;
-		sock_put(sk);
 	}
 
 	netlink_unlock_table();
@@ -868,6 +936,26 @@ void netlink_ack(struct sk_buff *in_skb,
 	netlink_unicast(in_skb->sk, skb, NETLINK_CB(in_skb).pid, MSG_DONTWAIT);
 }
 
+static int netlink_thread(void *unused)
+{
+	struct task_struct *tsk = current;
+	DECLARE_WAITQUEUE(wait, tsk);
+
+	daemonize();
+	strcpy(tsk->comm, "knetlinkd");
+	sigfillset(&tsk->blocked);
+	mb();
+
+	for (;;) {
+		run_task_queue(&tq_netlink);
+		
+		__set_current_state(TASK_INTERRUPTIBLE);
+		add_wait_queue(&netlink_thread_wait, &wait);
+		schedule();
+		__set_current_state(TASK_RUNNING);
+		remove_wait_queue(&netlink_thread_wait, &wait);
+	}
+}
 
 #ifdef NL_EMULATE_DEV
 
@@ -1027,6 +1115,8 @@ static int __init netlink_proto_init(voi
 #ifdef CONFIG_PROC_FS
 	create_proc_read_entry("net/netlink", 0, 0, netlink_read_proc, NULL);
 #endif
+	kernel_thread(netlink_thread, NULL, CLONE_FS | CLONE_FILES | CLONE_SIGNAL);
+	
 	return 0;
 }
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/net/netsyms.c linux-2.4.28-pre3/net/netsyms.c
--- linux-2.4.27/net/netsyms.c	2004-08-07 23:26:07.000000000 +0000
+++ linux-2.4.28-pre3/net/netsyms.c	2004-09-10 19:34:17.000000000 +0000
@@ -283,6 +283,7 @@ EXPORT_SYMBOL(ip_dev_find);
 EXPORT_SYMBOL(inetdev_by_index);
 EXPORT_SYMBOL(in_dev_finish_destroy);
 EXPORT_SYMBOL(ip_defrag);
+EXPORT_SYMBOL(ipfrag_flush);
 
 /* Route manipulation */
 EXPORT_SYMBOL(ip_rt_ioctl);
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/net/sched/sch_api.c linux-2.4.28-pre3/net/sched/sch_api.c
--- linux-2.4.27/net/sched/sch_api.c	2002-11-28 23:53:16.000000000 +0000
+++ linux-2.4.28-pre3/net/sched/sch_api.c	2004-09-10 19:34:33.000000000 +0000
@@ -32,6 +32,7 @@
 #include <linux/init.h>
 #include <linux/proc_fs.h>
 #include <linux/kmod.h>
+#include <linux/list.h>
 
 #include <net/sock.h>
 #include <net/pkt_sched.h>
@@ -193,7 +194,7 @@ struct Qdisc *qdisc_lookup(struct net_de
 {
 	struct Qdisc *q;
 
-	for (q = dev->qdisc_list; q; q = q->next) {
+	list_for_each_entry(q, &dev->qdisc_list, list) {
 		if (q->handle == handle)
 			return q;
 	}
@@ -424,6 +425,7 @@ qdisc_create(struct net_device *dev, u32
 
 	memset(sch, 0, size);
 
+	INIT_LIST_HEAD(&sch->list);
 	skb_queue_head_init(&sch->q);
 
 	if (handle == TC_H_INGRESS)
@@ -449,8 +451,7 @@ qdisc_create(struct net_device *dev, u32
 
 	if (!ops->init || (err = ops->init(sch, tca[TCA_OPTIONS-1])) == 0) {
 		write_lock(&qdisc_tree_lock);
-		sch->next = dev->qdisc_list;
-		dev->qdisc_list = sch;
+		list_add_tail(&sch->list, &dev->qdisc_list);
 		write_unlock(&qdisc_tree_lock);
 #ifdef CONFIG_NET_ESTIMATOR
 		if (tca[TCA_RATE-1])
@@ -805,15 +806,18 @@ static int tc_dump_qdisc(struct sk_buff 
 		if (idx > s_idx)
 			s_q_idx = 0;
 		read_lock(&qdisc_tree_lock);
-		for (q = dev->qdisc_list, q_idx = 0; q;
-		     q = q->next, q_idx++) {
-			if (q_idx < s_q_idx)
+		q_idx = 0;
+		list_for_each_entry(q, &dev->qdisc_list, list) {
+			if (q_idx < s_q_idx) {
+				q_idx++;
 				continue;
+			}
 			if (tc_fill_qdisc(skb, q, 0, NETLINK_CB(cb->skb).pid,
 					  cb->nlh->nlmsg_seq, NLM_F_MULTI, RTM_NEWQDISC) <= 0) {
 				read_unlock(&qdisc_tree_lock);
 				goto done;
 			}
+			q_idx++;
 		}
 		read_unlock(&qdisc_tree_lock);
 	}
@@ -1024,13 +1028,16 @@ static int tc_dump_tclass(struct sk_buff
 		return 0;
 
 	s_t = cb->args[0];
+	t = 0;
 
 	read_lock(&qdisc_tree_lock);
-	for (q=dev->qdisc_list, t=0; q; q = q->next, t++) {
-		if (t < s_t) continue;
-		if (!q->ops->cl_ops) continue;
-		if (tcm->tcm_parent && TC_H_MAJ(tcm->tcm_parent) != q->handle)
+	list_for_each_entry(q, &dev->qdisc_list, list) {
+		if (t < s_t || !q->ops->cl_ops ||
+		    (tcm->tcm_parent &&
+		     TC_H_MAJ(tcm->tcm_parent) != q->handle)) {
+			t++;
 			continue;
+		}
 		if (t > s_t)
 			memset(&cb->args[1], 0, sizeof(cb->args)-sizeof(cb->args[0]));
 		arg.w.fn = qdisc_class_dump;
@@ -1043,6 +1050,7 @@ static int tc_dump_tclass(struct sk_buff
 		cb->args[1] = arg.w.count;
 		if (arg.w.stop)
 			break;
+		t++;
 	}
 	read_unlock(&qdisc_tree_lock);
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/net/sched/sch_atm.c linux-2.4.28-pre3/net/sched/sch_atm.c
--- linux-2.4.27/net/sched/sch_atm.c	2004-02-18 13:36:32.000000000 +0000
+++ linux-2.4.28-pre3/net/sched/sch_atm.c	2004-09-10 19:34:39.000000000 +0000
@@ -566,7 +566,6 @@ static int atm_tc_init(struct Qdisc *sch
 	struct atm_qdisc_data *p = PRIV(sch);
 
 	DPRINTK("atm_tc_init(sch %p,[qdisc %p],opt %p)\n",sch,p,opt);
-	memset(p,0,sizeof(*p));
 	p->flows = &p->link;
 	if(!(p->link.q = qdisc_create_dflt(sch->dev,&pfifo_qdisc_ops)))
 		p->link.q = &noop_qdisc;
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/net/sched/sch_cbq.c linux-2.4.28-pre3/net/sched/sch_cbq.c
--- linux-2.4.27/net/sched/sch_cbq.c	2004-08-07 23:26:07.000000000 +0000
+++ linux-2.4.28-pre3/net/sched/sch_cbq.c	2004-09-10 19:32:38.000000000 +0000
@@ -1712,15 +1712,18 @@ static void cbq_destroy_filters(struct c
 	}
 }
 
-static void cbq_destroy_class(struct cbq_class *cl)
+static void cbq_destroy_class(struct Qdisc *sch, struct cbq_class *cl)
 {
+	struct cbq_sched_data *q = (struct cbq_sched_data *)sch->data;
+
 	cbq_destroy_filters(cl);
 	qdisc_destroy(cl->q);
 	qdisc_put_rtab(cl->R_tab);
 #ifdef CONFIG_NET_ESTIMATOR
 	qdisc_kill_estimator(&cl->stats);
 #endif
-	kfree(cl);
+	if (cl != &q->link)
+		kfree(cl);
 }
 
 static void
@@ -1743,8 +1746,7 @@ cbq_destroy(struct Qdisc* sch)
 
 		for (cl = q->classes[h]; cl; cl = next) {
 			next = cl->next;
-			if (cl != &q->link)
-				cbq_destroy_class(cl);
+			cbq_destroy_class(sch, cl);
 		}
 	}
 
@@ -1766,7 +1768,7 @@ static void cbq_put(struct Qdisc *sch, u
 		spin_unlock_bh(&sch->dev->queue_lock);
 #endif
 
-		cbq_destroy_class(cl);
+		cbq_destroy_class(sch, cl);
 	}
 }
 
@@ -2000,7 +2002,7 @@ static int cbq_delete(struct Qdisc *sch,
 	sch_tree_unlock(sch);
 
 	if (--cl->refcnt == 0)
-		cbq_destroy_class(cl);
+		cbq_destroy_class(sch, cl);
 
 	return 0;
 }
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/net/sched/sch_dsmark.c linux-2.4.28-pre3/net/sched/sch_dsmark.c
--- linux-2.4.27/net/sched/sch_dsmark.c	2004-08-07 23:26:07.000000000 +0000
+++ linux-2.4.28-pre3/net/sched/sch_dsmark.c	2004-09-10 19:32:54.000000000 +0000
@@ -329,8 +329,6 @@ int dsmark_init(struct Qdisc *sch,struct
 	    !tb[TCA_DSMARK_INDICES-1] ||
 	    RTA_PAYLOAD(tb[TCA_DSMARK_INDICES-1]) < sizeof(__u16))
                 return -EINVAL;
-	memset(p,0,sizeof(*p));
-	p->filter_list = NULL;
 	p->indices = *(__u16 *) RTA_DATA(tb[TCA_DSMARK_INDICES-1]);
 	if (!p->indices)
 		return -EINVAL;
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/net/sched/sch_generic.c linux-2.4.28-pre3/net/sched/sch_generic.c
--- linux-2.4.27/net/sched/sch_generic.c	2004-02-18 13:36:32.000000000 +0000
+++ linux-2.4.28-pre3/net/sched/sch_generic.c	2004-09-10 19:32:10.000000000 +0000
@@ -29,6 +29,7 @@
 #include <linux/skbuff.h>
 #include <linux/rtnetlink.h>
 #include <linux/init.h>
+#include <linux/list.h>
 #include <net/sock.h>
 #include <net/pkt_sched.h>
 
@@ -391,6 +392,7 @@ struct Qdisc * qdisc_create_dflt(struct 
 		return NULL;
 	memset(sch, 0, size);
 
+	INIT_LIST_HEAD(&sch->list);
 	skb_queue_head_init(&sch->q);
 	sch->ops = ops;
 	sch->enqueue = ops->enqueue;
@@ -420,22 +422,10 @@ void qdisc_reset(struct Qdisc *qdisc)
 void qdisc_destroy(struct Qdisc *qdisc)
 {
 	struct Qdisc_ops *ops = qdisc->ops;
-	struct net_device *dev;
 
 	if (!atomic_dec_and_test(&qdisc->refcnt))
 		return;
-
-	dev = qdisc->dev;
-
-	if (dev) {
-		struct Qdisc *q, **qp;
-		for (qp = &qdisc->dev->qdisc_list; (q=*qp) != NULL; qp = &q->next) {
-			if (q == qdisc) {
-				*qp = q->next;
-				break;
-			}
-		}
-	}
+	list_del(&qdisc->list);
 #ifdef CONFIG_NET_ESTIMATOR
 	qdisc_kill_estimator(&qdisc->stats);
 #endif
@@ -464,10 +454,8 @@ void dev_activate(struct net_device *dev
 				printk(KERN_INFO "%s: activation failed\n", dev->name);
 				return;
 			}
-
 			write_lock(&qdisc_tree_lock);
-			qdisc->next = dev->qdisc_list;
-			dev->qdisc_list = qdisc;
+			list_add_tail(&qdisc->list, &dev->qdisc_list);
 			write_unlock(&qdisc_tree_lock);
 
 		} else {
@@ -513,7 +501,7 @@ void dev_init_scheduler(struct net_devic
 	dev->qdisc = &noop_qdisc;
 	spin_unlock_bh(&dev->queue_lock);
 	dev->qdisc_sleeping = &noop_qdisc;
-	dev->qdisc_list = NULL;
+	INIT_LIST_HEAD(&dev->qdisc_list);
 	write_unlock(&qdisc_tree_lock);
 
 	dev_watchdog_init(dev);
@@ -535,9 +523,8 @@ void dev_shutdown(struct net_device *dev
 		qdisc_destroy(qdisc);
         }
 #endif
-	BUG_TRAP(dev->qdisc_list == NULL);
+	BUG_TRAP(list_empty(&dev->qdisc_list));
 	BUG_TRAP(!timer_pending(&dev->watchdog_timer));
-	dev->qdisc_list = NULL;
 	spin_unlock_bh(&dev->queue_lock);
 	write_unlock(&qdisc_tree_lock);
 }
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/net/sched/sch_hfsc.c linux-2.4.28-pre3/net/sched/sch_hfsc.c
--- linux-2.4.27/net/sched/sch_hfsc.c	2004-08-07 23:26:07.000000000 +0000
+++ linux-2.4.28-pre3/net/sched/sch_hfsc.c	2004-09-10 19:34:35.000000000 +0000
@@ -61,6 +61,7 @@
 #include <linux/slab.h>
 #include <linux/timer.h>
 #include <linux/list.h>
+#include <linux/rbtree.h>
 #include <linux/init.h>
 #include <linux/netdevice.h>
 #include <linux/rtnetlink.h>
@@ -131,9 +132,11 @@ struct hfsc_class
 	struct list_head children;	/* child classes */
 	struct Qdisc	*qdisc;		/* leaf qdisc */
 
-	struct list_head actlist;	/* active children list */
-	struct list_head alist;		/* active children list member */
-	struct list_head ellist;	/* eligible list member */
+	rb_node_t el_node;		/* qdisc's eligible tree member */
+	rb_root_t vt_tree;		/* active children sorted by cl_vt */
+	rb_node_t vt_node;		/* parent's vt_tree member */
+	rb_root_t cf_tree;		/* active children sorted by cl_f */
+	rb_node_t cf_node;		/* parent's cf_heap member */
 	struct list_head hlist;		/* hash list member */
 	struct list_head dlist;		/* drop list member */
 
@@ -159,6 +162,9 @@ struct hfsc_class
 					   adjustment */
 	u64	cl_vtoff;		/* inter-period cumulative vt offset */
 	u64	cl_cvtmax;		/* max child's vt in the last period */
+	u64	cl_cvtoff;		/* cumulative cvtmax of all periods */
+	u64	cl_pcvtoff;		/* parent's cvtoff at initalization
+					   time */
 
 	struct internal_sc cl_rsc;	/* internal real-time service curve */
 	struct internal_sc cl_fsc;	/* internal fair service curve */
@@ -181,7 +187,7 @@ struct hfsc_sched
 	u16	defcls;				/* default class id */
 	struct hfsc_class root;			/* root class */
 	struct list_head clhash[HFSC_HSIZE];	/* class hash */
-	struct list_head eligible;		/* eligible list */
+	rb_root_t eligible;			/* eligible tree */
 	struct list_head droplist;		/* active leaf class list (for
 						   dropping) */
 	struct sk_buff_head requeue;		/* requeued packet */
@@ -217,82 +223,51 @@ do {									\
 
 
 /*
- * eligible list holds backlogged classes being sorted by their eligible times.
- * there is one eligible list per hfsc instance.
+ * eligible tree holds backlogged classes being sorted by their eligible times.
+ * there is one eligible tree per hfsc instance.
  */
 
 static void
-ellist_insert(struct hfsc_class *cl)
+eltree_insert(struct hfsc_class *cl)
 {
-	struct list_head *head = &cl->sched->eligible;
-	struct hfsc_class *p;
-
-	/* check the last entry first */
-	if (list_empty(head) ||
-	    ((p = list_entry(head->prev, struct hfsc_class, ellist)) &&
-	     p->cl_e <= cl->cl_e)) {
-		list_add_tail(&cl->ellist, head);
-		return;
-	}
-
-	list_for_each_entry(p, head, ellist) {
-		if (cl->cl_e < p->cl_e) {
-			/* insert cl before p */
-			list_add_tail(&cl->ellist, &p->ellist);
-			return;
-		}
+	rb_node_t **p = &cl->sched->eligible.rb_node;
+	rb_node_t *parent = NULL;
+	struct hfsc_class *cl1;
+
+	while (*p != NULL) {
+		parent = *p;
+		cl1 = rb_entry(parent, struct hfsc_class, el_node);
+		if (cl->cl_e >= cl1->cl_e)
+			p = &parent->rb_right;
+		else
+			p = &parent->rb_left;
 	}
-	ASSERT(0); /* should not reach here */
+	rb_link_node(&cl->el_node, parent, p);
+	rb_insert_color(&cl->el_node, &cl->sched->eligible);
 }
 
 static inline void
-ellist_remove(struct hfsc_class *cl)
+eltree_remove(struct hfsc_class *cl)
 {
-	list_del(&cl->ellist);
+	rb_erase(&cl->el_node, &cl->sched->eligible);
 }
 
-static void
-ellist_update(struct hfsc_class *cl)
+static inline void
+eltree_update(struct hfsc_class *cl)
 {
-	struct list_head *head = &cl->sched->eligible;
-	struct hfsc_class *p, *last;
-
-	/*
-	 * the eligible time of a class increases monotonically.
-	 * if the next entry has a larger eligible time, nothing to do.
-	 */
-	if (cl->ellist.next == head ||
-	    ((p = list_entry(cl->ellist.next, struct hfsc_class, ellist)) &&
-	     cl->cl_e <= p->cl_e))
-		return;
-
-	/* check the last entry */
-	last = list_entry(head->prev, struct hfsc_class, ellist);
-	if (last->cl_e <= cl->cl_e) {
-		list_move_tail(&cl->ellist, head);
-		return;
-	}
-
-	/*
-	 * the new position must be between the next entry
-	 * and the last entry
-	 */
-	list_for_each_entry_continue(p, head, ellist) {
-		if (cl->cl_e < p->cl_e) {
-			list_move_tail(&cl->ellist, &p->ellist);
-			return;
-		}
-	}
-	ASSERT(0); /* should not reach here */
+	eltree_remove(cl);
+	eltree_insert(cl);
 }
 
 /* find the class with the minimum deadline among the eligible classes */
 static inline struct hfsc_class *
-ellist_get_mindl(struct list_head *head, u64 cur_time)
+eltree_get_mindl(struct hfsc_sched *q, u64 cur_time)
 {
 	struct hfsc_class *p, *cl = NULL;
+	rb_node_t *n;
 
-	list_for_each_entry(p, head, ellist) {
+	for (n = rb_first(&q->eligible); n != NULL; n = rb_next(n)) {
+		p = rb_entry(n, struct hfsc_class, el_node);
 		if (p->cl_e > cur_time)
 			break;
 		if (cl == NULL || p->cl_d < cl->cl_d)
@@ -303,92 +278,62 @@ ellist_get_mindl(struct list_head *head,
 
 /* find the class with minimum eligible time among the eligible classes */
 static inline struct hfsc_class *
-ellist_get_minel(struct list_head *head)
+eltree_get_minel(struct hfsc_sched *q)
 {
-	if (list_empty(head))
+	rb_node_t *n;
+	
+	n = rb_first(&q->eligible);
+	if (n == NULL)
 		return NULL;
-	return list_entry(head->next, struct hfsc_class, ellist);
+	return rb_entry(n, struct hfsc_class, el_node);
 }
 
 /*
- * active children list holds backlogged child classes being sorted
- * by their virtual time. each intermediate class has one active
- * children list.
+ * vttree holds holds backlogged child classes being sorted by their virtual
+ * time. each intermediate class has one vttree.
  */
 static void
-actlist_insert(struct hfsc_class *cl)
+vttree_insert(struct hfsc_class *cl)
 {
-	struct list_head *head = &cl->cl_parent->actlist;
-	struct hfsc_class *p;
-
-	/* check the last entry first */
-	if (list_empty(head) ||
-	    ((p = list_entry(head->prev, struct hfsc_class, alist)) &&
-	     p->cl_vt <= cl->cl_vt)) {
-		list_add_tail(&cl->alist, head);
-		return;
-	}
-
-	list_for_each_entry(p, head, alist) {
-		if (cl->cl_vt < p->cl_vt) {
-			/* insert cl before p */
-			list_add_tail(&cl->alist, &p->alist);
-			return;
-		}
+	rb_node_t **p = &cl->cl_parent->vt_tree.rb_node;
+	rb_node_t *parent = NULL;
+	struct hfsc_class *cl1;
+
+	while (*p != NULL) {
+		parent = *p;
+		cl1 = rb_entry(parent, struct hfsc_class, vt_node);
+		if (cl->cl_vt >= cl1->cl_vt)
+			p = &parent->rb_right;
+		else
+			p = &parent->rb_left;
 	}
-	ASSERT(0); /* should not reach here */
+	rb_link_node(&cl->vt_node, parent, p);
+	rb_insert_color(&cl->vt_node, &cl->cl_parent->vt_tree);
 }
 
 static inline void
-actlist_remove(struct hfsc_class *cl)
+vttree_remove(struct hfsc_class *cl)
 {
-	list_del(&cl->alist);
+	rb_erase(&cl->vt_node, &cl->cl_parent->vt_tree);
 }
 
-static void
-actlist_update(struct hfsc_class *cl)
+static inline void
+vttree_update(struct hfsc_class *cl)
 {
-	struct list_head *head = &cl->cl_parent->actlist;
-	struct hfsc_class *p, *last;
-
-	/*
-	 * the virtual time of a class increases monotonically.
-	 * if the next entry has a larger virtual time, nothing to do.
-	 */
-	if (cl->alist.next == head ||
-	    ((p = list_entry(cl->alist.next, struct hfsc_class, alist)) &&
-	     cl->cl_vt <= p->cl_vt))
-		return;
-
-	/* check the last entry */
-	last = list_entry(head->prev, struct hfsc_class, alist);
-	if (last->cl_vt <= cl->cl_vt) {
-		list_move_tail(&cl->alist, head);
-		return;
-	}
-
-	/*
-	 * the new position must be between the next entry
-	 * and the last entry
-	 */
-	list_for_each_entry_continue(p, head, alist) {
-		if (cl->cl_vt < p->cl_vt) {
-			list_move_tail(&cl->alist, &p->alist);
-			return;
-		}
-	}
-	ASSERT(0); /* should not reach here */
+	vttree_remove(cl);
+	vttree_insert(cl);
 }
 
 static inline struct hfsc_class *
-actlist_firstfit(struct hfsc_class *cl, u64 cur_time)
+vttree_firstfit(struct hfsc_class *cl, u64 cur_time)
 {
 	struct hfsc_class *p;
+	rb_node_t *n;
 
-	list_for_each_entry(p, &cl->actlist, alist) {
-		if (p->cl_f <= cur_time) {
+	for (n = rb_first(&cl->vt_tree); n != NULL; n = rb_next(n)) {
+		p = rb_entry(n, struct hfsc_class, vt_node);
+		if (p->cl_f <= cur_time)
 			return p;
-		}
 	}
 	return NULL;
 }
@@ -397,14 +342,14 @@ actlist_firstfit(struct hfsc_class *cl, 
  * get the leaf class with the minimum vt in the hierarchy
  */
 static struct hfsc_class *
-actlist_get_minvt(struct hfsc_class *cl, u64 cur_time)
+vttree_get_minvt(struct hfsc_class *cl, u64 cur_time)
 {
 	/* if root-class's cfmin is bigger than cur_time nothing to do */
 	if (cl->cl_cfmin > cur_time)
 		return NULL;
 
 	while (cl->level > 0) {
-		cl = actlist_firstfit(cl, cur_time);
+		cl = vttree_firstfit(cl, cur_time);
 		if (cl == NULL)
 			return NULL;
 		/*
@@ -416,6 +361,38 @@ actlist_get_minvt(struct hfsc_class *cl,
 	return cl;
 }
 
+static void
+cftree_insert(struct hfsc_class *cl)
+{
+	rb_node_t **p = &cl->cl_parent->cf_tree.rb_node;
+	rb_node_t *parent = NULL;
+	struct hfsc_class *cl1;
+
+	while (*p != NULL) {
+		parent = *p;
+		cl1 = rb_entry(parent, struct hfsc_class, cf_node);
+		if (cl->cl_f >= cl1->cl_f)
+			p = &parent->rb_right;
+		else
+			p = &parent->rb_left;
+	}
+	rb_link_node(&cl->cf_node, parent, p);
+	rb_insert_color(&cl->cf_node, &cl->cl_parent->cf_tree);
+}
+
+static inline void
+cftree_remove(struct hfsc_class *cl)
+{
+	rb_erase(&cl->cf_node, &cl->cl_parent->cf_tree);
+}
+
+static inline void
+cftree_update(struct hfsc_class *cl)
+{
+	cftree_remove(cl);
+	cftree_insert(cl);
+}
+
 /*
  * service curve support functions
  *
@@ -709,7 +686,7 @@ init_ed(struct hfsc_class *cl, unsigned 
 	cl->cl_e = rtsc_y2x(&cl->cl_eligible, cl->cl_cumul);
 	cl->cl_d = rtsc_y2x(&cl->cl_deadline, cl->cl_cumul + next_len);
 
-	ellist_insert(cl);
+	eltree_insert(cl);
 }
 
 static void
@@ -718,7 +695,7 @@ update_ed(struct hfsc_class *cl, unsigne
 	cl->cl_e = rtsc_y2x(&cl->cl_eligible, cl->cl_cumul);
 	cl->cl_d = rtsc_y2x(&cl->cl_deadline, cl->cl_cumul + next_len);
 
-	ellist_update(cl);
+	eltree_update(cl);
 }
 
 static inline void
@@ -727,32 +704,25 @@ update_d(struct hfsc_class *cl, unsigned
 	cl->cl_d = rtsc_y2x(&cl->cl_deadline, cl->cl_cumul + next_len);
 }
 
-static void
+static inline void
 update_cfmin(struct hfsc_class *cl)
 {
+	rb_node_t *n = rb_first(&cl->cf_tree);
 	struct hfsc_class *p;
-	u64 cfmin;
 
-	if (list_empty(&cl->actlist)) {
+	if (n == NULL) {
 		cl->cl_cfmin = 0;
 		return;
 	}
-	cfmin = HT_INFINITY;
-	list_for_each_entry(p, &cl->actlist, alist) {
-		if (p->cl_f == 0) {
-			cl->cl_cfmin = 0;
-			return;
-		}
-		if (p->cl_f < cfmin)
-			cfmin = p->cl_f;
-	}
-	cl->cl_cfmin = cfmin;
+	p = rb_entry(n, struct hfsc_class, cf_node);
+	cl->cl_cfmin = p->cl_f;
 }
 
 static void
 init_vf(struct hfsc_class *cl, unsigned int len)
 {
-	struct hfsc_class *max_cl, *p;
+	struct hfsc_class *max_cl;
+	rb_node_t *n;
 	u64 vt, f, cur_time;
 	int go_active;
 
@@ -765,9 +735,9 @@ init_vf(struct hfsc_class *cl, unsigned 
 			go_active = 0;
 
 		if (go_active) {
-			if (!list_empty(&cl->cl_parent->actlist)) {
-				max_cl = list_entry(cl->cl_parent->actlist.prev,
-				                    struct hfsc_class, alist);
+			n = rb_last(&cl->cl_parent->vt_tree);
+			if (n != NULL) {
+				max_cl = rb_entry(n, struct hfsc_class,vt_node);
 				/*
 				 * set vt to the average of the min and max
 				 * classes.  if the parent's period didn't
@@ -783,19 +753,20 @@ init_vf(struct hfsc_class *cl, unsigned 
 			} else {
 				/*
 				 * first child for a new parent backlog period.
-				 * add parent's cvtmax to vtoff of children
-				 * to make a new vt (vtoff + vt) larger than
-				 * the vt in the last period for all children.
+				 * add parent's cvtmax to cvtoff to make a new
+				 * vt (vtoff + vt) larger than the vt in the
+				 * last period for all children.
 				 */
 				vt = cl->cl_parent->cl_cvtmax;
-				list_for_each_entry(p, &cl->cl_parent->children,
-				                                       siblings)
-					p->cl_vtoff += vt;
-				cl->cl_vt = 0;
+				cl->cl_parent->cl_cvtoff += vt;
 				cl->cl_parent->cl_cvtmax = 0;
 				cl->cl_parent->cl_cvtmin = 0;
+				cl->cl_vt = 0;
 			}
 
+			cl->cl_vtoff = cl->cl_parent->cl_cvtoff -
+							cl->cl_pcvtoff;
+
 			/* update the virtual curve */
 			vt = cl->cl_vt + cl->cl_vtoff;
 			rtsc_min(&cl->cl_virtual, &cl->cl_fsc, vt,
@@ -812,7 +783,8 @@ init_vf(struct hfsc_class *cl, unsigned 
 				cl->cl_parentperiod++;
 			cl->cl_f = 0;
 
-			actlist_insert(cl);
+			vttree_insert(cl);
+			cftree_insert(cl);
 
 			if (cl->cl_flags & HFSC_USC) {
 				/* class has upper limit curve */
@@ -832,6 +804,7 @@ init_vf(struct hfsc_class *cl, unsigned 
 		f = max(cl->cl_myf, cl->cl_cfmin);
 		if (f != cl->cl_f) {
 			cl->cl_f = f;
+			cftree_update(cl);
 			update_cfmin(cl->cl_parent);
 		}
 	}
@@ -864,9 +837,10 @@ update_vf(struct hfsc_class *cl, unsigne
 			if (cl->cl_vt > cl->cl_parent->cl_cvtmax)
 				cl->cl_parent->cl_cvtmax = cl->cl_vt;
 
-			/* remove this class from the vt list */
-			actlist_remove(cl);
+			/* remove this class from the vt tree */
+			vttree_remove(cl);
 
+			cftree_remove(cl);
 			update_cfmin(cl->cl_parent);
 
 			continue;
@@ -888,8 +862,8 @@ update_vf(struct hfsc_class *cl, unsigne
 			cl->cl_vt = cl->cl_parent->cl_cvtmin;
 		}
 
-		/* update the vt list */
-		actlist_update(cl);
+		/* update the vt tree */
+		vttree_update(cl);
 
 		if (cl->cl_flags & HFSC_USC) {
 			cl->cl_myf = cl->cl_myfadj + rtsc_y2x(&cl->cl_ulimit,
@@ -919,6 +893,7 @@ update_vf(struct hfsc_class *cl, unsigne
 		f = max(cl->cl_myf, cl->cl_cfmin);
 		if (f != cl->cl_f) {
 			cl->cl_f = f;
+			cftree_update(cl);
 			update_cfmin(cl->cl_parent);
 		}
 	}
@@ -939,13 +914,13 @@ static void
 set_passive(struct hfsc_class *cl)
 {
 	if (cl->cl_flags & HFSC_RSC)
-		ellist_remove(cl);
+		eltree_remove(cl);
 
 	list_del(&cl->dlist);
 
 	/*
-	 * actlist is now handled in update_vf() so that update_vf(cl, 0, 0)
-	 * needs to be called explicitly to remove a class from actlist
+	 * vttree is now handled in update_vf() so that update_vf(cl, 0, 0)
+	 * needs to be called explicitly to remove a class from vttree.
 	 */
 }
 
@@ -1168,7 +1143,8 @@ hfsc_change_class(struct Qdisc *sch, u32
 		cl->qdisc = &noop_qdisc;
 	cl->stats.lock = &sch->dev->queue_lock;
 	INIT_LIST_HEAD(&cl->children);
-	INIT_LIST_HEAD(&cl->actlist);
+	cl->vt_tree = RB_ROOT;
+	cl->cf_tree = RB_ROOT;
 
 	sch_tree_lock(sch);
 	list_add_tail(&cl->hlist, &q->clhash[hfsc_hash(classid)]);
@@ -1176,6 +1152,7 @@ hfsc_change_class(struct Qdisc *sch, u32
 	if (parent->level == 0)
 		hfsc_purge_queue(sch, parent);
 	hfsc_adjust_levels(parent);
+	cl->cl_pcvtoff = parent->cl_cvtoff;
 	sch_tree_unlock(sch);
 
 #ifdef CONFIG_NET_ESTIMATOR
@@ -1500,7 +1477,7 @@ hfsc_schedule_watchdog(struct Qdisc *sch
 	u64 next_time = 0;
 	long delay;
 
-	if ((cl = ellist_get_minel(&q->eligible)) != NULL)
+	if ((cl = eltree_get_minel(q)) != NULL)
 		next_time = cl->cl_e;
 	if (q->root.cl_cfmin != 0) {
 		if (next_time == 0 || next_time > q->root.cl_cfmin)
@@ -1525,13 +1502,12 @@ hfsc_init_qdisc(struct Qdisc *sch, struc
 		return -EINVAL;
 	qopt = RTA_DATA(opt);
 
-	memset(q, 0, sizeof(struct hfsc_sched));
 	sch->stats.lock = &sch->dev->queue_lock;
 
 	q->defcls = qopt->defcls;
 	for (i = 0; i < HFSC_HSIZE; i++)
 		INIT_LIST_HEAD(&q->clhash[i]);
-	INIT_LIST_HEAD(&q->eligible);
+	q->eligible = RB_ROOT;
 	INIT_LIST_HEAD(&q->droplist);
 	skb_queue_head_init(&q->requeue);
 
@@ -1543,7 +1519,8 @@ hfsc_init_qdisc(struct Qdisc *sch, struc
 		q->root.qdisc = &noop_qdisc;
 	q->root.stats.lock = &sch->dev->queue_lock;
 	INIT_LIST_HEAD(&q->root.children);
-	INIT_LIST_HEAD(&q->root.actlist);
+	q->root.vt_tree = RB_ROOT;
+	q->root.cf_tree = RB_ROOT;
 
 	list_add(&q->root.hlist, &q->clhash[hfsc_hash(q->root.classid)]);
 
@@ -1584,6 +1561,8 @@ hfsc_reset_class(struct hfsc_class *cl)
 	cl->cl_vtoff        = 0;
 	cl->cl_cvtmin       = 0;
 	cl->cl_cvtmax       = 0;
+	cl->cl_cvtoff       = 0;
+	cl->cl_pcvtoff      = 0;
 	cl->cl_vtperiod     = 0;
 	cl->cl_parentperiod = 0;
 	cl->cl_f            = 0;
@@ -1591,7 +1570,9 @@ hfsc_reset_class(struct hfsc_class *cl)
 	cl->cl_myfadj       = 0;
 	cl->cl_cfmin        = 0;
 	cl->cl_nactive      = 0;
-	INIT_LIST_HEAD(&cl->actlist);
+
+	cl->vt_tree = RB_ROOT;
+	cl->cf_tree = RB_ROOT;
 	qdisc_reset(cl->qdisc);
 
 	if (cl->cl_flags & HFSC_RSC)
@@ -1614,7 +1595,7 @@ hfsc_reset_qdisc(struct Qdisc *sch)
 			hfsc_reset_class(cl);
 	}
 	__skb_queue_purge(&q->requeue);
-	INIT_LIST_HEAD(&q->eligible);
+	q->eligible = RB_ROOT;
 	INIT_LIST_HEAD(&q->droplist);
 	del_timer(&q->wd_timer);
 	sch->flags &= ~TCQ_F_THROTTLED;
@@ -1712,14 +1693,14 @@ hfsc_dequeue(struct Qdisc *sch)
 	 * find the class with the minimum deadline among
 	 * the eligible classes.
 	 */
-	if ((cl = ellist_get_mindl(&q->eligible, cur_time)) != NULL) {
+	if ((cl = eltree_get_mindl(q, cur_time)) != NULL) {
 		realtime = 1;
 	} else {
 		/*
 		 * use link-sharing criteria
 		 * get the class with the minimum vt in the hierarchy
 		 */
-		cl = actlist_get_minvt(&q->root, cur_time);
+		cl = vttree_get_minvt(&q->root, cur_time);
 		if (cl == NULL) {
 			sch->stats.overlimits++;
 			hfsc_schedule_watchdog(sch, cur_time);
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/net/sched/sch_htb.c linux-2.4.28-pre3/net/sched/sch_htb.c
--- linux-2.4.27/net/sched/sch_htb.c	2004-08-07 23:26:07.000000000 +0000
+++ linux-2.4.28-pre3/net/sched/sch_htb.c	2004-09-10 19:32:01.000000000 +0000
@@ -77,7 +77,7 @@
 #define HTB_HYSTERESIS 1/* whether to use mode hysteresis for speedup */
 #define HTB_QLOCK(S) spin_lock_bh(&(S)->dev->queue_lock)
 #define HTB_QUNLOCK(S) spin_unlock_bh(&(S)->dev->queue_lock)
-#define HTB_VER 0x30010	/* major must be matched with number suplied by TC as version */
+#define HTB_VER 0x30011	/* major must be matched with number suplied by TC as version */
 
 #if HTB_VER >> 16 != TC_HTB_PROTOVER
 #error "Mismatched sch_htb.c and pkt_sch.h"
@@ -172,6 +172,11 @@ struct htb_class
 	    struct htb_class_inner {
 		    rb_root_t feed[TC_HTB_NUMPRIO];	/* feed trees */
 		    rb_node_t *ptr[TC_HTB_NUMPRIO];	/* current class ptr */
+		    /* When class changes from state 1->2 and disconnects from 
+		       parent's feed then we lost ptr value and start from the
+		       first child again. Here we store classid of the
+		       last valid ptr (used when ptr is NULL). */
+		    u32 last_ptr_id[TC_HTB_NUMPRIO];
 	    } inner;
     } un;
     rb_node_t node[TC_HTB_NUMPRIO];	/* node for self or feed tree */
@@ -218,6 +223,7 @@ struct htb_sched
     rb_root_t row[TC_HTB_MAXDEPTH][TC_HTB_NUMPRIO];
     int row_mask[TC_HTB_MAXDEPTH];
     rb_node_t *ptr[TC_HTB_MAXDEPTH][TC_HTB_NUMPRIO];
+    u32 last_ptr_id[TC_HTB_MAXDEPTH][TC_HTB_NUMPRIO];
 
     /* self wait list - roots of wait PQs per row */
     rb_root_t wait_pq[TC_HTB_MAXDEPTH];
@@ -576,8 +582,13 @@ static void htb_deactivate_prios(struct 
 			int prio = ffz(~m);
 			m &= ~(1 << prio);
 			
-			if (p->un.inner.ptr[prio] == cl->node+prio)
-				htb_next_rb_node(p->un.inner.ptr + prio);
+			if (p->un.inner.ptr[prio] == cl->node+prio) {
+				/* we are removing child which is pointed to from
+				   parent feed - forget the pointer but remember
+				   classid */
+				p->un.inner.last_ptr_id[prio] = cl->classid;
+				p->un.inner.ptr[prio] = NULL;
+			}
 			
 			htb_safe_rb_erase(cl->node + prio,p->un.inner.feed + prio);
 			
@@ -908,25 +919,56 @@ static long htb_do_events(struct htb_sch
 	return HZ/10;
 }
 
+/* Returns class->node+prio from id-tree where classe's id is >= id. NULL
+   is no such one exists. */
+static rb_node_t *
+htb_id_find_next_upper(int prio,rb_node_t *n,u32 id)
+{
+	rb_node_t *r = NULL;
+	while (n) {
+		struct htb_class *cl = rb_entry(n,struct htb_class,node[prio]);
+		if (id == cl->classid) return n;
+		
+		if (id > cl->classid) {
+			n = n->rb_right;
+		} else {
+			r = n;
+			n = n->rb_left;
+		}
+	}
+	return r;
+}
+
 /**
  * htb_lookup_leaf - returns next leaf class in DRR order
  *
  * Find leaf where current feed pointers points to.
  */
 static struct htb_class *
-htb_lookup_leaf(rb_root_t *tree,int prio,rb_node_t **pptr)
+htb_lookup_leaf(HTB_ARGQ rb_root_t *tree,int prio,rb_node_t **pptr,u32 *pid)
 {
 	int i;
 	struct {
 		rb_node_t *root;
 		rb_node_t **pptr;
+		u32 *pid;
 	} stk[TC_HTB_MAXDEPTH],*sp = stk;
 	
 	BUG_TRAP(tree->rb_node);
 	sp->root = tree->rb_node;
 	sp->pptr = pptr;
+	sp->pid = pid;
 
 	for (i = 0; i < 65535; i++) {
+		HTB_DBG(4,2,"htb_lleaf ptr=%p pid=%X\n",*sp->pptr,*sp->pid);
+
+		if (!*sp->pptr && *sp->pid) { 
+			/* ptr was invalidated but id is valid - try to recover 
+			   the original or next ptr */
+			*sp->pptr = htb_id_find_next_upper(prio,sp->root,*sp->pid);
+		}
+		*sp->pid = 0; /* ptr is valid now so that remove this hint as it
+			         can become out of date quickly */
 		if (!*sp->pptr) { /* we are at right end; rewind & go up */
 			*sp->pptr = sp->root;
 			while ((*sp->pptr)->rb_left) 
@@ -944,6 +986,7 @@ htb_lookup_leaf(rb_root_t *tree,int prio
 				return cl;
 			(++sp)->root = cl->un.inner.feed[prio].rb_node;
 			sp->pptr = cl->un.inner.ptr+prio;
+			sp->pid = cl->un.inner.last_ptr_id+prio;
 		}
 	}
 	BUG_TRAP(0);
@@ -958,7 +1001,8 @@ htb_dequeue_tree(struct htb_sched *q,int
 	struct sk_buff *skb = NULL;
 	struct htb_class *cl,*start;
 	/* look initial class up in the row */
-	start = cl = htb_lookup_leaf (q->row[level]+prio,prio,q->ptr[level]+prio);
+	start = cl = htb_lookup_leaf (HTB_PASSQ q->row[level]+prio,prio,
+			q->ptr[level]+prio,q->last_ptr_id[level]+prio);
 	
 	do {
 next:
@@ -979,8 +1023,8 @@ next:
 			if ((q->row_mask[level] & (1 << prio)) == 0)
 				return NULL; 
 			
-			next = htb_lookup_leaf (q->row[level]+prio,
-					prio,q->ptr[level]+prio);
+			next = htb_lookup_leaf (HTB_PASSQ q->row[level]+prio,
+					prio,q->ptr[level]+prio,q->last_ptr_id[level]+prio);
 			if (cl == start) /* fix start if we just deleted it */
 				start = next;
 			cl = next;
@@ -995,7 +1039,8 @@ next:
 		}
 		q->nwc_hit++;
 		htb_next_rb_node((level?cl->parent->un.inner.ptr:q->ptr[0])+prio);
-		cl = htb_lookup_leaf (q->row[level]+prio,prio,q->ptr[level]+prio);
+		cl = htb_lookup_leaf (HTB_PASSQ q->row[level]+prio,prio,q->ptr[level]+prio,
+				q->last_ptr_id[level]+prio);
 	} while (cl != start);
 
 	if (likely(skb != NULL)) {
@@ -1186,7 +1231,6 @@ static int htb_init(struct Qdisc *sch, s
 				HTB_VER >> 16,HTB_VER & 0xffff,gopt->version);
 		return -EINVAL;
 	}
-	memset(q,0,sizeof(*q));
 	q->debug = gopt->debug;
 	HTB_DBG(0,1,"htb_init sch=%p handle=%X r2q=%d\n",sch,sch->handle,gopt->rate2quantum);
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/net/sched/sch_ingress.c linux-2.4.28-pre3/net/sched/sch_ingress.c
--- linux-2.4.27/net/sched/sch_ingress.c	2004-02-18 13:36:32.000000000 +0000
+++ linux-2.4.28-pre3/net/sched/sch_ingress.c	2004-09-10 19:36:16.000000000 +0000
@@ -254,8 +254,6 @@ int ingress_init(struct Qdisc *sch,struc
 	}
 
 	DPRINTK("ingress_init(sch %p,[qdisc %p],opt %p)\n",sch,p,opt);
-	memset(p, 0, sizeof(*p));
-	p->filter_list = NULL;
 	p->q = &noop_qdisc;
 	MOD_INC_USE_COUNT;
 	return 0;
@@ -296,9 +294,6 @@ static void ingress_destroy(struct Qdisc
 		p->filter_list = tp->next;
 		tcf_destroy(tp);
 	}
-	memset(p, 0, sizeof(*p));
-	p->filter_list = NULL;
-
 #if 0
 /* for future use */
 	qdisc_destroy(p->q);
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/net/sched/sch_netem.c linux-2.4.28-pre3/net/sched/sch_netem.c
--- linux-2.4.27/net/sched/sch_netem.c	2004-08-07 23:26:07.000000000 +0000
+++ linux-2.4.28-pre3/net/sched/sch_netem.c	2004-09-10 19:34:49.000000000 +0000
@@ -6,13 +6,15 @@
  * 		as published by the Free Software Foundation; either version
  * 		2 of the License, or (at your option) any later version.
  *
+ *  		Many of the algorithms and ideas for this came from
+ *		NIST Net which is not copyrighted. 
+ *
  * Authors:	Stephen Hemminger <shemminger@osdl.org>
  *		Catalin(ux aka Dino) BOIE <catab at umbrella dot ro>
  */
 
 #include <linux/config.h>
 #include <linux/module.h>
-#include <linux/init.h>
 #include <asm/bitops.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
@@ -23,11 +25,33 @@
 
 #include <net/pkt_sched.h>
 
-/*	Network emulator
- *
- *	This scheduler can alters spacing and order
- *	Similar to NISTnet and BSD Dummynet.
- */
+#define qdisc_priv(q)	((void *)(q->data))
+
+/*	Network Emulation Queuing algorithm.
+	====================================
+
+	Sources: [1] Mark Carson, Darrin Santay, "NIST Net - A Linux-based
+		 Network Emulation Tool
+		 [2] Luigi Rizzo, DummyNet for FreeBSD
+
+	 ----------------------------------------------------------------
+
+	 This started out as a simple way to delay outgoing packets to
+	 test TCP but has grown to include most of the functionality
+	 of a full blown network emulator like NISTnet. It can delay
+	 packets and add random jitter (and correlation). The random
+	 distribution can be loaded from a table as well to provide
+	 normal, Pareto, or experimental curves. Packet loss,
+	 duplication, and reordering can also be emulated.
+
+	 This qdisc does not do classification that can be handled in
+	 layering other disciplines.  It does not need to do bandwidth
+	 control either since that can be handled by using token
+	 bucket or other rate control.
+
+	 The simulator is limited by the Linux timer resolution
+	 and will create packet bursts on the HZ boundary (1ms).
+*/
 
 struct netem_sched_data {
 	struct Qdisc	*qdisc;
@@ -40,6 +64,17 @@ struct netem_sched_data {
 	u32 counter;
 	u32 gap;
 	u32 jitter;
+	u32 duplicate;
+
+	struct crndstate {
+		unsigned long last;
+		unsigned long rho;
+	} delay_cor, loss_cor, dup_cor;
+
+	struct disttable {
+		u32  size;
+		s16 table[0];
+	} *delay_dist;
 };
 
 /* Time stamp put into socket buffer control block */
@@ -47,576 +82,110 @@ struct netem_skb_cb {
 	psched_time_t	time_to_send;
 };
 
-/* This is the distribution table for the normal distribution produced
- * with NISTnet tools.
- * The entries represent a scaled inverse of the cumulative distribution
- * function.
+/* init_crandom - initialize correlated random number generator
+ * Use entropy source for initial seed.
  */
-#define TABLESIZE	2048
-#define TABLEFACTOR	8192
+static void init_crandom(struct crndstate *state, unsigned long rho)
+{
+	state->rho = rho;
+	state->last = net_random();
+}
 
-static const short disttable[TABLESIZE] = {
-	-31473,		-26739,		-25226,		-24269,
-	-23560,		-22993,		-22518,		-22109,
-	-21749,		-21426,		-21133,		-20865,
-	-20618,		-20389,		-20174,		-19972,
-	-19782,		-19601,		-19430,		-19267,
-	-19112,		-18962,		-18819,		-18681,
-	-18549,		-18421,		-18298,		-18178,
-	-18062,		-17950,		-17841,		-17735,
-	-17632,		-17532,		-17434,		-17339,
-	-17245,		-17155,		-17066,		-16979,
-	-16894,		-16811,		-16729,		-16649,
-	-16571,		-16494,		-16419,		-16345,
-	-16272,		-16201,		-16130,		-16061,
-	-15993,		-15926,		-15861,		-15796,
-	-15732,		-15669,		-15607,		-15546,
-	-15486,		-15426,		-15368,		-15310,
-	-15253,		-15196,		-15140,		-15086,
-	-15031,		-14977,		-14925,		-14872,
-	-14821,		-14769,		-14719,		-14669,
-	-14619,		-14570,		-14522,		-14473,
-	-14426,		-14379,		-14332,		-14286,
-	-14241,		-14196,		-14150,		-14106,
-	-14062,		-14019,		-13976,		-13933,
-	-13890,		-13848,		-13807,		-13765,
-	-13724,		-13684,		-13643,		-13604,
-	-13564,		-13525,		-13486,		-13447,
-	-13408,		-13370,		-13332,		-13295,
-	-13258,		-13221,		-13184,		-13147,
-	-13111,		-13075,		-13040,		-13004,
-	-12969,		-12934,		-12899,		-12865,
-	-12830,		-12796,		-12762,		-12729,
-	-12695,		-12662,		-12629,		-12596,
-	-12564,		-12531,		-12499,		-12467,
-	-12435,		-12404,		-12372,		-12341,
-	-12310,		-12279,		-12248,		-12218,
-	-12187,		-12157,		-12127,		-12097,
-	-12067,		-12038,		-12008,		-11979,
-	-11950,		-11921,		-11892,		-11863,
-	-11835,		-11806,		-11778,		-11750,
-	-11722,		-11694,		-11666,		-11639,
-	-11611,		-11584,		-11557,		-11530,
-	-11503,		-11476,		-11450,		-11423,
-	-11396,		-11370,		-11344,		-11318,
-	-11292,		-11266,		-11240,		-11214,
-	-11189,		-11164,		-11138,		-11113,
-	-11088,		-11063,		-11038,		-11013,
-	-10988,		-10964,		-10939,		-10915,
-	-10891,		-10866,		-10843,		-10818,
-	-10794,		-10770,		-10747,		-10723,
-	-10700,		-10676,		-10652,		-10630,
-	-10606,		-10583,		-10560,		-10537,
-	-10514,		-10491,		-10469,		-10446,
-	-10424,		-10401,		-10378,		-10356,
-	-10334,		-10312,		-10290,		-10267,
-	-10246,		-10224,		-10202,		-10180,
-	-10158,		-10137,		-10115,		-10094,
-	-10072,		-10051,		-10030,		-10009,
-	-9988,		-9967,		-9945,		-9925,
-	-9904,		-9883,		-9862,		-9842,
-	-9821,		-9800,		-9780,		-9760,
-	-9739,		-9719,		-9699,		-9678,
-	-9658,		-9638,		-9618,		-9599,
-	-9578,		-9559,		-9539,		-9519,
-	-9499,		-9480,		-9461,		-9441,
-	-9422,		-9402,		-9383,		-9363,
-	-9344,		-9325,		-9306,		-9287,
-	-9268,		-9249,		-9230,		-9211,
-	-9192,		-9173,		-9155,		-9136,
-	-9117,		-9098,		-9080,		-9062,
-	-9043,		-9025,		-9006,		-8988,
-	-8970,		-8951,		-8933,		-8915,
-	-8897,		-8879,		-8861,		-8843,
-	-8825,		-8807,		-8789,		-8772,
-	-8754,		-8736,		-8718,		-8701,
-	-8683,		-8665,		-8648,		-8630,
-	-8613,		-8595,		-8578,		-8561,
-	-8543,		-8526,		-8509,		-8492,
-	-8475,		-8458,		-8441,		-8423,
-	-8407,		-8390,		-8373,		-8356,
-	-8339,		-8322,		-8305,		-8289,
-	-8272,		-8255,		-8239,		-8222,
-	-8206,		-8189,		-8172,		-8156,
-	-8140,		-8123,		-8107,		-8090,
-	-8074,		-8058,		-8042,		-8025,
-	-8009,		-7993,		-7977,		-7961,
-	-7945,		-7929,		-7913,		-7897,
-	-7881,		-7865,		-7849,		-7833,
-	-7817,		-7802,		-7786,		-7770,
-	-7754,		-7739,		-7723,		-7707,
-	-7692,		-7676,		-7661,		-7645,
-	-7630,		-7614,		-7599,		-7583,
-	-7568,		-7553,		-7537,		-7522,
-	-7507,		-7492,		-7476,		-7461,
-	-7446,		-7431,		-7416,		-7401,
-	-7385,		-7370,		-7356,		-7340,
-	-7325,		-7311,		-7296,		-7281,
-	-7266,		-7251,		-7236,		-7221,
-	-7207,		-7192,		-7177,		-7162,
-	-7148,		-7133,		-7118,		-7104,
-	-7089,		-7075,		-7060,		-7046,
-	-7031,		-7016,		-7002,		-6988,
-	-6973,		-6959,		-6944,		-6930,
-	-6916,		-6901,		-6887,		-6873,
-	-6859,		-6844,		-6830,		-6816,
-	-6802,		-6788,		-6774,		-6760,
-	-6746,		-6731,		-6717,		-6704,
-	-6690,		-6675,		-6661,		-6647,
-	-6633,		-6620,		-6606,		-6592,
-	-6578,		-6564,		-6550,		-6537,
-	-6523,		-6509,		-6495,		-6482,
-	-6468,		-6454,		-6441,		-6427,
-	-6413,		-6400,		-6386,		-6373,
-	-6359,		-6346,		-6332,		-6318,
-	-6305,		-6291,		-6278,		-6264,
-	-6251,		-6238,		-6224,		-6211,
-	-6198,		-6184,		-6171,		-6158,
-	-6144,		-6131,		-6118,		-6105,
-	-6091,		-6078,		-6065,		-6052,
-	-6039,		-6025,		-6012,		-5999,
-	-5986,		-5973,		-5960,		-5947,
-	-5934,		-5921,		-5908,		-5895,
-	-5882,		-5869,		-5856,		-5843,
-	-5830,		-5817,		-5804,		-5791,
-	-5779,		-5766,		-5753,		-5740,
-	-5727,		-5714,		-5702,		-5689,
-	-5676,		-5663,		-5650,		-5638,
-	-5625,		-5612,		-5600,		-5587,
-	-5575,		-5562,		-5549,		-5537,
-	-5524,		-5512,		-5499,		-5486,
-	-5474,		-5461,		-5449,		-5436,
-	-5424,		-5411,		-5399,		-5386,
-	-5374,		-5362,		-5349,		-5337,
-	-5324,		-5312,		-5299,		-5287,
-	-5275,		-5263,		-5250,		-5238,
-	-5226,		-5213,		-5201,		-5189,
-	-5177,		-5164,		-5152,		-5140,
-	-5128,		-5115,		-5103,		-5091,
-	-5079,		-5067,		-5055,		-5043,
-	-5030,		-5018,		-5006,		-4994,
-	-4982,		-4970,		-4958,		-4946,
-	-4934,		-4922,		-4910,		-4898,
-	-4886,		-4874,		-4862,		-4850,
-	-4838,		-4826,		-4814,		-4803,
-	-4791,		-4778,		-4767,		-4755,
-	-4743,		-4731,		-4719,		-4708,
-	-4696,		-4684,		-4672,		-4660,
-	-4649,		-4637,		-4625,		-4613,
-	-4601,		-4590,		-4578,		-4566,
-	-4554,		-4543,		-4531,		-4520,
-	-4508,		-4496,		-4484,		-4473,
-	-4461,		-4449,		-4438,		-4427,
-	-4415,		-4403,		-4392,		-4380,
-	-4368,		-4357,		-4345,		-4334,
-	-4322,		-4311,		-4299,		-4288,
-	-4276,		-4265,		-4253,		-4242,
-	-4230,		-4219,		-4207,		-4196,
-	-4184,		-4173,		-4162,		-4150,
-	-4139,		-4128,		-4116,		-4105,
-	-4094,		-4082,		-4071,		-4060,
-	-4048,		-4037,		-4026,		-4014,
-	-4003,		-3992,		-3980,		-3969,
-	-3958,		-3946,		-3935,		-3924,
-	-3913,		-3901,		-3890,		-3879,
-	-3868,		-3857,		-3845,		-3834,
-	-3823,		-3812,		-3801,		-3790,
-	-3779,		-3767,		-3756,		-3745,
-	-3734,		-3723,		-3712,		-3700,
-	-3689,		-3678,		-3667,		-3656,
-	-3645,		-3634,		-3623,		-3612,
-	-3601,		-3590,		-3579,		-3568,
-	-3557,		-3545,		-3535,		-3524,
-	-3513,		-3502,		-3491,		-3480,
-	-3469,		-3458,		-3447,		-3436,
-	-3425,		-3414,		-3403,		-3392,
-	-3381,		-3370,		-3360,		-3348,
-	-3337,		-3327,		-3316,		-3305,
-	-3294,		-3283,		-3272,		-3262,
-	-3251,		-3240,		-3229,		-3218,
-	-3207,		-3197,		-3185,		-3175,
-	-3164,		-3153,		-3142,		-3132,
-	-3121,		-3110,		-3099,		-3088,
-	-3078,		-3067,		-3056,		-3045,
-	-3035,		-3024,		-3013,		-3003,
-	-2992,		-2981,		-2970,		-2960,
-	-2949,		-2938,		-2928,		-2917,
-	-2906,		-2895,		-2885,		-2874,
-	-2864,		-2853,		-2842,		-2832,
-	-2821,		-2810,		-2800,		-2789,
-	-2778,		-2768,		-2757,		-2747,
-	-2736,		-2725,		-2715,		-2704,
-	-2694,		-2683,		-2673,		-2662,
-	-2651,		-2641,		-2630,		-2620,
-	-2609,		-2599,		-2588,		-2578,
-	-2567,		-2556,		-2546,		-2535,
-	-2525,		-2515,		-2504,		-2493,
-	-2483,		-2472,		-2462,		-2451,
-	-2441,		-2431,		-2420,		-2410,
-	-2399,		-2389,		-2378,		-2367,
-	-2357,		-2347,		-2336,		-2326,
-	-2315,		-2305,		-2295,		-2284,
-	-2274,		-2263,		-2253,		-2243,
-	-2232,		-2222,		-2211,		-2201,
-	-2191,		-2180,		-2170,		-2159,
-	-2149,		-2139,		-2128,		-2118,
-	-2107,		-2097,		-2087,		-2076,
-	-2066,		-2056,		-2046,		-2035,
-	-2025,		-2014,		-2004,		-1994,
-	-1983,		-1973,		-1963,		-1953,
-	-1942,		-1932,		-1921,		-1911,
-	-1901,		-1891,		-1880,		-1870,
-	-1860,		-1849,		-1839,		-1829,
-	-1819,		-1808,		-1798,		-1788,
-	-1778,		-1767,		-1757,		-1747,
-	-1736,		-1726,		-1716,		-1706,
-	-1695,		-1685,		-1675,		-1665,
-	-1654,		-1644,		-1634,		-1624,
-	-1613,		-1603,		-1593,		-1583,
-	-1573,		-1563,		-1552,		-1542,
-	-1532,		-1522,		-1511,		-1501,
-	-1491,		-1481,		-1471,		-1461,
-	-1450,		-1440,		-1430,		-1420,
-	-1409,		-1400,		-1389,		-1379,
-	-1369,		-1359,		-1348,		-1339,
-	-1328,		-1318,		-1308,		-1298,
-	-1288,		-1278,		-1267,		-1257,
-	-1247,		-1237,		-1227,		-1217,
-	-1207,		-1196,		-1186,		-1176,
-	-1166,		-1156,		-1146,		-1135,
-	-1126,		-1115,		-1105,		-1095,
-	-1085,		-1075,		-1065,		-1055,
-	-1044,		-1034,		-1024,		-1014,
-	-1004,		-994,		-984,		-974,
-	-964,		-954,		-944,		-933,
-	-923,		-913,		-903,		-893,
-	-883,		-873,		-863,		-853,
-	-843,		-833,		-822,		-812,
-	-802,		-792,		-782,		-772,
-	-762,		-752,		-742,		-732,
-	-722,		-712,		-702,		-691,
-	-682,		-671,		-662,		-651,
-	-641,		-631,		-621,		-611,
-	-601,		-591,		-581,		-571,
-	-561,		-551,		-541,		-531,
-	-521,		-511,		-501,		-491,
-	-480,		-471,		-460,		-451,
-	-440,		-430,		-420,		-410,
-	-400,		-390,		-380,		-370,
-	-360,		-350,		-340,		-330,
-	-320,		-310,		-300,		-290,
-	-280,		-270,		-260,		-250,
-	-240,		-230,		-220,		-210,
-	-199,		-190,		-179,		-170,
-	-159,		-150,		-139,		-129,
-	-119,		-109,		-99,		-89,
-	-79,		-69,		-59,		-49,
-	-39,		-29,		-19,		-9,
-	1,		11,		21,		31,
-	41,		51,		61,		71,
-	81,		91,		101,		111,
-	121,		131,		141,		152,
-	161,		172,		181,		192,
-	202,		212,		222,		232,
-	242,		252,		262,		272,
-	282,		292,		302,		312,
-	322,		332,		342,		352,
-	362,		372,		382,		392,
-	402,		412,		422,		433,
-	442,		453,		462,		473,
-	483,		493,		503,		513,
-	523,		533,		543,		553,
-	563,		573,		583,		593,
-	603,		613,		623,		633,
-	643,		653,		664,		673,
-	684,		694,		704,		714,
-	724,		734,		744,		754,
-	764,		774,		784,		794,
-	804,		815,		825,		835,
-	845,		855,		865,		875,
-	885,		895,		905,		915,
-	925,		936,		946,		956,
-	966,		976,		986,		996,
-	1006,		1016,		1026,		1037,
-	1047,		1057,		1067,		1077,
-	1087,		1097,		1107,		1117,
-	1128,		1138,		1148,		1158,
-	1168,		1178,		1188,		1198,
-	1209,		1219,		1229,		1239,
-	1249,		1259,		1269,		1280,
-	1290,		1300,		1310,		1320,
-	1330,		1341,		1351,		1361,
-	1371,		1381,		1391,		1402,
-	1412,		1422,		1432,		1442,
-	1452,		1463,		1473,		1483,
-	1493,		1503,		1513,		1524,
-	1534,		1544,		1554,		1565,
-	1575,		1585,		1595,		1606,
-	1616,		1626,		1636,		1647,
-	1656,		1667,		1677,		1687,
-	1697,		1708,		1718,		1729,
-	1739,		1749,		1759,		1769,
-	1780,		1790,		1800,		1810,
-	1821,		1831,		1841,		1851,
-	1862,		1872,		1883,		1893,
-	1903,		1913,		1923,		1934,
-	1944,		1955,		1965,		1975,
-	1985,		1996,		2006,		2016,
-	2027,		2037,		2048,		2058,
-	2068,		2079,		2089,		2099,
-	2110,		2120,		2130,		2141,
-	2151,		2161,		2172,		2182,
-	2193,		2203,		2213,		2224,
-	2234,		2245,		2255,		2265,
-	2276,		2286,		2297,		2307,
-	2318,		2328,		2338,		2349,
-	2359,		2370,		2380,		2391,
-	2401,		2412,		2422,		2433,
-	2443,		2454,		2464,		2475,
-	2485,		2496,		2506,		2517,
-	2527,		2537,		2548,		2559,
-	2569,		2580,		2590,		2601,
-	2612,		2622,		2632,		2643,
-	2654,		2664,		2675,		2685,
-	2696,		2707,		2717,		2728,
-	2738,		2749,		2759,		2770,
-	2781,		2791,		2802,		2813,
-	2823,		2834,		2845,		2855,
-	2866,		2877,		2887,		2898,
-	2909,		2919,		2930,		2941,
-	2951,		2962,		2973,		2984,
-	2994,		3005,		3015,		3027,
-	3037,		3048,		3058,		3069,
-	3080,		3091,		3101,		3113,
-	3123,		3134,		3145,		3156,
-	3166,		3177,		3188,		3199,
-	3210,		3220,		3231,		3242,
-	3253,		3264,		3275,		3285,
-	3296,		3307,		3318,		3329,
-	3340,		3351,		3362,		3373,
-	3384,		3394,		3405,		3416,
-	3427,		3438,		3449,		3460,
-	3471,		3482,		3493,		3504,
-	3515,		3526,		3537,		3548,
-	3559,		3570,		3581,		3592,
-	3603,		3614,		3625,		3636,
-	3647,		3659,		3670,		3681,
-	3692,		3703,		3714,		3725,
-	3736,		3747,		3758,		3770,
-	3781,		3792,		3803,		3814,
-	3825,		3837,		3848,		3859,
-	3870,		3881,		3893,		3904,
-	3915,		3926,		3937,		3949,
-	3960,		3971,		3983,		3994,
-	4005,		4017,		4028,		4039,
-	4051,		4062,		4073,		4085,
-	4096,		4107,		4119,		4130,
-	4141,		4153,		4164,		4175,
-	4187,		4198,		4210,		4221,
-	4233,		4244,		4256,		4267,
-	4279,		4290,		4302,		4313,
-	4325,		4336,		4348,		4359,
-	4371,		4382,		4394,		4406,
-	4417,		4429,		4440,		4452,
-	4464,		4475,		4487,		4499,
-	4510,		4522,		4533,		4545,
-	4557,		4569,		4581,		4592,
-	4604,		4616,		4627,		4639,
-	4651,		4663,		4674,		4686,
-	4698,		4710,		4722,		4734,
-	4746,		4758,		4769,		4781,
-	4793,		4805,		4817,		4829,
-	4841,		4853,		4865,		4877,
-	4889,		4900,		4913,		4925,
-	4936,		4949,		4961,		4973,
-	4985,		4997,		5009,		5021,
-	5033,		5045,		5057,		5070,
-	5081,		5094,		5106,		5118,
-	5130,		5143,		5155,		5167,
-	5179,		5191,		5204,		5216,
-	5228,		5240,		5253,		5265,
-	5278,		5290,		5302,		5315,
-	5327,		5340,		5352,		5364,
-	5377,		5389,		5401,		5414,
-	5426,		5439,		5451,		5464,
-	5476,		5489,		5502,		5514,
-	5527,		5539,		5552,		5564,
-	5577,		5590,		5603,		5615,
-	5628,		5641,		5653,		5666,
-	5679,		5691,		5704,		5717,
-	5730,		5743,		5756,		5768,
-	5781,		5794,		5807,		5820,
-	5833,		5846,		5859,		5872,
-	5885,		5897,		5911,		5924,
-	5937,		5950,		5963,		5976,
-	5989,		6002,		6015,		6028,
-	6042,		6055,		6068,		6081,
-	6094,		6108,		6121,		6134,
-	6147,		6160,		6174,		6187,
-	6201,		6214,		6227,		6241,
-	6254,		6267,		6281,		6294,
-	6308,		6321,		6335,		6348,
-	6362,		6375,		6389,		6403,
-	6416,		6430,		6443,		6457,
-	6471,		6485,		6498,		6512,
-	6526,		6540,		6554,		6567,
-	6581,		6595,		6609,		6623,
-	6637,		6651,		6665,		6679,
-	6692,		6706,		6721,		6735,
-	6749,		6763,		6777,		6791,
-	6805,		6819,		6833,		6848,
-	6862,		6876,		6890,		6905,
-	6919,		6933,		6948,		6962,
-	6976,		6991,		7005,		7020,
-	7034,		7049,		7064,		7078,
-	7093,		7107,		7122,		7136,
-	7151,		7166,		7180,		7195,
-	7210,		7225,		7240,		7254,
-	7269,		7284,		7299,		7314,
-	7329,		7344,		7359,		7374,
-	7389,		7404,		7419,		7434,
-	7449,		7465,		7480,		7495,
-	7510,		7526,		7541,		7556,
-	7571,		7587,		7602,		7618,
-	7633,		7648,		7664,		7680,
-	7695,		7711,		7726,		7742,
-	7758,		7773,		7789,		7805,
-	7821,		7836,		7852,		7868,
-	7884,		7900,		7916,		7932,
-	7948,		7964,		7981,		7997,
-	8013,		8029,		8045,		8061,
-	8078,		8094,		8110,		8127,
-	8143,		8160,		8176,		8193,
-	8209,		8226,		8242,		8259,
-	8276,		8292,		8309,		8326,
-	8343,		8360,		8377,		8394,
-	8410,		8428,		8444,		8462,
-	8479,		8496,		8513,		8530,
-	8548,		8565,		8582,		8600,
-	8617,		8634,		8652,		8670,
-	8687,		8704,		8722,		8740,
-	8758,		8775,		8793,		8811,
-	8829,		8847,		8865,		8883,
-	8901,		8919,		8937,		8955,
-	8974,		8992,		9010,		9029,
-	9047,		9066,		9084,		9103,
-	9121,		9140,		9159,		9177,
-	9196,		9215,		9234,		9253,
-	9272,		9291,		9310,		9329,
-	9349,		9368,		9387,		9406,
-	9426,		9445,		9465,		9484,
-	9504,		9524,		9544,		9563,
-	9583,		9603,		9623,		9643,
-	9663,		9683,		9703,		9723,
-	9744,		9764,		9785,		9805,
-	9826,		9846,		9867,		9888,
-	9909,		9930,		9950,		9971,
-	9993,		10013,		10035,		10056,
-	10077,		10099,		10120,		10142,
-	10163,		10185,		10207,		10229,
-	10251,		10273,		10294,		10317,
-	10339,		10361,		10384,		10406,
-	10428,		10451,		10474,		10496,
-	10519,		10542,		10565,		10588,
-	10612,		10635,		10658,		10682,
-	10705,		10729,		10752,		10776,
-	10800,		10824,		10848,		10872,
-	10896,		10921,		10945,		10969,
-	10994,		11019,		11044,		11069,
-	11094,		11119,		11144,		11169,
-	11195,		11221,		11246,		11272,
-	11298,		11324,		11350,		11376,
-	11402,		11429,		11456,		11482,
-	11509,		11536,		11563,		11590,
-	11618,		11645,		11673,		11701,
-	11728,		11756,		11785,		11813,
-	11842,		11870,		11899,		11928,
-	11957,		11986,		12015,		12045,
-	12074,		12104,		12134,		12164,
-	12194,		12225,		12255,		12286,
-	12317,		12348,		12380,		12411,
-	12443,		12475,		12507,		12539,
-	12571,		12604,		12637,		12670,
-	12703,		12737,		12771,		12804,
-	12839,		12873,		12907,		12942,
-	12977,		13013,		13048,		13084,
-	13120,		13156,		13192,		13229,
-	13267,		13304,		13341,		13379,
-	13418,		13456,		13495,		13534,
-	13573,		13613,		13653,		13693,
-	13734,		13775,		13817,		13858,
-	13901,		13943,		13986,		14029,
-	14073,		14117,		14162,		14206,
-	14252,		14297,		14343,		14390,
-	14437,		14485,		14533,		14582,
-	14631,		14680,		14731,		14782,
-	14833,		14885,		14937,		14991,
-	15044,		15099,		15154,		15210,
-	15266,		15324,		15382,		15441,
-	15500,		15561,		15622,		15684,
-	15747,		15811,		15877,		15943,
-	16010,		16078,		16148,		16218,
-	16290,		16363,		16437,		16513,
-	16590,		16669,		16749,		16831,
-	16915,		17000,		17088,		17177,
-	17268,		17362,		17458,		17556,
-	17657,		17761,		17868,		17977,
-	18090,		18207,		18328,		18452,
-	18581,		18715,		18854,		18998,
-	19149,		19307,		19472,		19645,
-	19828,		20021,		20226,		20444,
-	20678,		20930,		21204,		21503,
-	21835,		22206,		22630,		23124,
-	23721,		24478,		25529,		27316,
-};
+/* get_crandom - correlated random number generator
+ * Next number depends on last value.
+ * rho is scaled to avoid floating point.
+ */
+static unsigned long get_crandom(struct crndstate *state)
+{
+	u64 value, rho;
+	unsigned long answer;
+
+	if (state->rho == 0)	/* no correllation */
+		return net_random();
+
+	value = net_random();
+	rho = (u64)state->rho + 1;
+	answer = (value * ((1ull<<32) - rho) + state->last * rho) >> 32;
+	state->last = answer;
+	return answer;
+}
 
 /* tabledist - return a pseudo-randomly distributed value with mean mu and
  * std deviation sigma.  Uses table lookup to approximate the desired
  * distribution, and a uniformly-distributed pseudo-random source.
  */
-static inline int tabledist(int mu, int sigma)
+static long tabledist(unsigned long mu, long sigma, 
+		      struct crndstate *state, const struct disttable *dist)
 {
-	int x;
-	int index;
-	int sigmamod, sigmadiv;
+	long t, x;
+	unsigned long rnd;
 
 	if (sigma == 0)
 		return mu;
 
-	index = (net_random() & (TABLESIZE-1));
-	sigmamod = sigma%TABLEFACTOR;
-	sigmadiv = sigma/TABLEFACTOR;
-	x = sigmamod*disttable[index];
+	rnd = get_crandom(state);
+
+	/* default uniform distribution */
+	if (dist == NULL) 
+		return (rnd % (2*sigma)) - sigma + mu;
 
+	t = dist->table[rnd % dist->size];
+	x = (sigma % NETEM_DIST_SCALE) * t;
 	if (x >= 0)
-		x += TABLEFACTOR/2;
+		x += NETEM_DIST_SCALE/2;
 	else
-		x -= TABLEFACTOR/2;
+		x -= NETEM_DIST_SCALE/2;
 
-	x /= TABLEFACTOR;
-	x += sigmadiv*disttable[index];
-	x += mu;
-	return x;
+	return  x / NETEM_DIST_SCALE + (sigma / NETEM_DIST_SCALE) * t + mu;
 }
 
-/* Enqueue packets with underlying discipline (fifo)
- * but mark them with current time first.
- */
-static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch)
+/* Put skb in the private delayed queue. */
+static int delay_skb(struct Qdisc *sch, struct sk_buff *skb)
 {
-	struct netem_sched_data *q = (struct netem_sched_data *)sch->data;
+	struct netem_sched_data *q = qdisc_priv(sch);
 	struct netem_skb_cb *cb = (struct netem_skb_cb *)skb->cb;
 	psched_time_t now;
-	long delay;
+	
+	PSCHED_GET_TIME(now);
+	PSCHED_TADD2(now, tabledist(q->latency, q->jitter, 
+				    &q->delay_cor, q->delay_dist),
+		     cb->time_to_send);
+	
+	/* Always queue at tail to keep packets in order */
+	if (likely(q->delayed.qlen < q->limit)) {
+		__skb_queue_tail(&q->delayed, skb);
+		sch->q.qlen++;
+		sch->stats.bytes += skb->len;
+		sch->stats.packets++;
+		return NET_XMIT_SUCCESS;
+	}
+
+	sch->stats.drops++;
+	kfree_skb(skb);
+	return NET_XMIT_DROP;
+}
+
+static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch)
+{
+	struct netem_sched_data *q = qdisc_priv(sch);
 
 	pr_debug("netem_enqueue skb=%p @%lu\n", skb, jiffies);
 
 	/* Random packet drop 0 => none, ~0 => all */
-	if (q->loss && q->loss >= net_random()) {
+	if (q->loss && q->loss >= get_crandom(&q->loss_cor)) {
+		pr_debug("netem_enqueue: random loss\n");
 		sch->stats.drops++;
 		return 0;	/* lie about loss so TCP doesn't know */
 	}
 
+	/* Random duplication */
+	if (q->duplicate && q->duplicate >= get_crandom(&q->dup_cor)) {
+		struct sk_buff *skb2 = skb_clone(skb, GFP_ATOMIC);
+
+		pr_debug("netem_enqueue: dup %p\n", skb2);
+		if (skb2)
+			delay_skb(sch, skb2);
+	}
 
 	/* If doing simple delay then gap == 0 so all packets
 	 * go into the delayed holding queue
@@ -634,33 +203,14 @@ static int netem_enqueue(struct sk_buff 
 	}
 	
 	q->counter = 0;
-	
-	PSCHED_GET_TIME(now);
-	if (q->jitter) 
-		delay = tabledist(q->latency, q->jitter);
-	else
-		delay = q->latency;
 
-	PSCHED_TADD2(now, delay, cb->time_to_send);
-	
-	/* Always queue at tail to keep packets in order */
-	if (likely(q->delayed.qlen < q->limit)) {
-		__skb_queue_tail(&q->delayed, skb);
-		sch->q.qlen++;
-		sch->stats.bytes += skb->len;
-		sch->stats.packets++;
-		return 0;
-	}
-
-	sch->stats.drops++;
-	kfree_skb(skb);
-	return NET_XMIT_DROP;
+	return delay_skb(sch, skb);
 }
 
 /* Requeue packets but don't change time stamp */
 static int netem_requeue(struct sk_buff *skb, struct Qdisc *sch)
 {
-	struct netem_sched_data *q = (struct netem_sched_data *)sch->data;
+	struct netem_sched_data *q = qdisc_priv(sch);
 	int ret;
 
 	if ((ret = q->qdisc->ops->requeue(skb, q->qdisc)) == 0)
@@ -671,7 +221,7 @@ static int netem_requeue(struct sk_buff 
 
 static unsigned int netem_drop(struct Qdisc* sch)
 {
-	struct netem_sched_data *q = (struct netem_sched_data *)sch->data;
+	struct netem_sched_data *q = qdisc_priv(sch);
 	unsigned int len;
 
 	if ((len = q->qdisc->ops->drop(q->qdisc)) != 0) {
@@ -687,7 +237,7 @@ static unsigned int netem_drop(struct Qd
  */
 static struct sk_buff *netem_dequeue(struct Qdisc *sch)
 {
-	struct netem_sched_data *q = (struct netem_sched_data *)sch->data;
+	struct netem_sched_data *q = qdisc_priv(sch);
 	struct sk_buff *skb;
 	psched_time_t now;
 
@@ -727,7 +277,7 @@ static void netem_watchdog(unsigned long
 
 static void netem_reset(struct Qdisc *sch)
 {
-	struct netem_sched_data *q = (struct netem_sched_data *)sch->data;
+	struct netem_sched_data *q = qdisc_priv(sch);
 
 	qdisc_reset(q->qdisc);
 	skb_queue_purge(&q->delayed);
@@ -753,92 +303,163 @@ static int set_fifo_limit(struct Qdisc *
 	return ret;
 }
 
-static int netem_change(struct Qdisc *sch, struct rtattr *opt)
+/*
+ * Distribution data is a variable size payload containing
+ * signed 16 bit values.
+ */
+static int get_dist_table(struct Qdisc *sch, const struct rtattr *attr)
 {
-	struct netem_sched_data *q = (struct netem_sched_data *)sch->data;
-	struct tc_netem_qopt *qopt = RTA_DATA(opt);
-	struct Qdisc *child;
-	int ret;
+	struct netem_sched_data *q = qdisc_priv(sch);
+	unsigned long n = RTA_PAYLOAD(attr)/sizeof(__s16);
+	const __s16 *data = RTA_DATA(attr);
+	struct disttable *d;
+	int i;
+
+	if (n > 65536)
+		return -EINVAL;
 
-	if (opt->rta_len < RTA_LENGTH(sizeof(*qopt)))
+	d = kmalloc(sizeof(*d) + n*sizeof(d->table[0]), GFP_KERNEL);
+	if (!d)
+		return -ENOMEM;
+
+	d->size = n;
+	for (i = 0; i < n; i++)
+		d->table[i] = data[i];
+	
+	spin_lock_bh(&sch->dev->queue_lock);
+	d = xchg(&q->delay_dist, d);
+	spin_unlock_bh(&sch->dev->queue_lock);
+
+	kfree(d);
+	return 0;
+}
+
+static int get_correlation(struct Qdisc *sch, const struct rtattr *attr)
+{
+	struct netem_sched_data *q = qdisc_priv(sch);
+	const struct tc_netem_corr *c = RTA_DATA(attr);
+
+	if (RTA_PAYLOAD(attr) != sizeof(*c))
 		return -EINVAL;
 
-	child = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops);
-	if (!child)
+	init_crandom(&q->delay_cor, c->delay_corr);
+	init_crandom(&q->loss_cor, c->loss_corr);
+	init_crandom(&q->dup_cor, c->dup_corr);
+	return 0;
+}
+
+static int netem_change(struct Qdisc *sch, struct rtattr *opt)
+{
+	struct netem_sched_data *q = qdisc_priv(sch);
+	struct tc_netem_qopt *qopt;
+	int ret;
+	
+	if (opt == NULL || RTA_PAYLOAD(opt) < sizeof(*qopt))
 		return -EINVAL;
 
-	ret = set_fifo_limit(child, qopt->limit);
+	qopt = RTA_DATA(opt);
+	ret = set_fifo_limit(q->qdisc, qopt->limit);
 	if (ret) {
-		qdisc_destroy(child);
+		pr_debug("netem: can't set fifo limit\n");
 		return ret;
 	}
-
-	sch_tree_lock(sch);
-	if (child) {
-		child = xchg(&q->qdisc, child);
-		if (child != &noop_qdisc)
-			qdisc_destroy(child);
 	
-		q->latency = qopt->latency;
-		q->jitter = qopt->jitter;
-		q->limit = qopt->limit;
-		q->gap = qopt->gap;
-		q->loss = qopt->loss;
+	q->latency = qopt->latency;
+	q->jitter = qopt->jitter;
+	q->limit = qopt->limit;
+	q->gap = qopt->gap;
+	q->loss = qopt->loss;
+	q->duplicate = qopt->duplicate;
+
+	/* Handle nested options after initial queue options.
+	 * Should have put all options in nested format but too late now.
+	 */ 
+	if (RTA_PAYLOAD(opt) > sizeof(*qopt)) {
+		struct rtattr *tb[TCA_NETEM_MAX];
+		if (rtattr_parse(tb, TCA_NETEM_MAX, 
+				 RTA_DATA(opt) + sizeof(*qopt),
+				 RTA_PAYLOAD(opt) - sizeof(*qopt)))
+			return -EINVAL;
+
+		if (tb[TCA_NETEM_CORR-1]) {
+			ret = get_correlation(sch, tb[TCA_NETEM_CORR-1]);
+			if (ret)
+				return ret;
+		}
+
+		if (tb[TCA_NETEM_DELAY_DIST-1]) {
+			ret = get_dist_table(sch, tb[TCA_NETEM_DELAY_DIST-1]);
+			if (ret)
+				return ret;
+		}
 	}
-	sch_tree_unlock(sch);
+
 
 	return 0;
 }
 
 static int netem_init(struct Qdisc *sch, struct rtattr *opt)
 {
-	struct netem_sched_data *q = (struct netem_sched_data *)sch->data;
-	int err;
+	struct netem_sched_data *q = qdisc_priv(sch);
+	int ret;
 
 	if (!opt)
 		return -EINVAL;
 
 	MOD_INC_USE_COUNT;
 	skb_queue_head_init(&q->delayed);
-	q->qdisc = &noop_qdisc;
-
 	init_timer(&q->timer);
 	q->timer.function = netem_watchdog;
 	q->timer.data = (unsigned long) sch;
 	q->counter = 0;
 
-	err = netem_change(sch, opt);
-	if (err != 0)
+	q->qdisc = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops);
+	if (!q->qdisc) {
+		pr_debug("netem: qdisc create failed\n");
+		return -ENOMEM;
+	}
+
+	ret = netem_change(sch, opt);
+	if (ret) {
+		pr_debug("netem: change failed\n");
+		qdisc_destroy(q->qdisc);
 		MOD_DEC_USE_COUNT;
-	return err;
+	}
+	return ret;
 }
 
 static void netem_destroy(struct Qdisc *sch)
 {
-	struct netem_sched_data *q = (struct netem_sched_data *)sch->data;
-
-	del_timer(&q->timer);
+	struct netem_sched_data *q = qdisc_priv(sch);
 
+	del_timer_sync(&q->timer);
 	qdisc_destroy(q->qdisc);
-	q->qdisc = &noop_qdisc;
-
+	kfree(q->delay_dist);
 	MOD_DEC_USE_COUNT;
 }
 
 static int netem_dump(struct Qdisc *sch, struct sk_buff *skb)
 {
-	struct netem_sched_data *q = (struct netem_sched_data *)sch->data;
+	const struct netem_sched_data *q = qdisc_priv(sch);
 	unsigned char	 *b = skb->tail;
+	struct rtattr *rta = (struct rtattr *) b;
 	struct tc_netem_qopt qopt;
+	struct tc_netem_corr cor;
 
 	qopt.latency = q->latency;
 	qopt.jitter = q->jitter;
 	qopt.limit = q->limit;
 	qopt.loss = q->loss;
 	qopt.gap = q->gap;
-
+	qopt.duplicate = q->duplicate;
 	RTA_PUT(skb, TCA_OPTIONS, sizeof(qopt), &qopt);
 
+	cor.delay_corr = q->delay_cor.rho;
+	cor.loss_corr = q->loss_cor.rho;
+	cor.dup_corr = q->dup_cor.rho;
+	RTA_PUT(skb, TCA_NETEM_CORR, sizeof(cor), &cor);
+	rta->rta_len = skb->tail - b;
+
 	return skb->len;
 
 rtattr_failure:
@@ -849,7 +470,7 @@ rtattr_failure:
 static int netem_dump_class(struct Qdisc *sch, unsigned long cl,
 			  struct sk_buff *skb, struct tcmsg *tcm)
 {
-	struct netem_sched_data *q = (struct netem_sched_data*)sch->data;
+	struct netem_sched_data *q = qdisc_priv(sch);
 
 	if (cl != 1) 	/* only one class */
 		return -ENOENT;
@@ -863,7 +484,7 @@ static int netem_dump_class(struct Qdisc
 static int netem_graft(struct Qdisc *sch, unsigned long arg, struct Qdisc *new,
 		     struct Qdisc **old)
 {
-	struct netem_sched_data *q = (struct netem_sched_data *)sch->data;
+	struct netem_sched_data *q = qdisc_priv(sch);
 
 	if (new == NULL)
 		new = &noop_qdisc;
@@ -879,7 +500,7 @@ static int netem_graft(struct Qdisc *sch
 
 static struct Qdisc *netem_leaf(struct Qdisc *sch, unsigned long arg)
 {
-	struct netem_sched_data *q = (struct netem_sched_data *)sch->data;
+	struct netem_sched_data *q = qdisc_priv(sch);
 	return q->qdisc;
 }
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/net/sctp/associola.c linux-2.4.28-pre3/net/sctp/associola.c
--- linux-2.4.27/net/sctp/associola.c	2004-08-07 23:26:07.000000000 +0000
+++ linux-2.4.28-pre3/net/sctp/associola.c	2004-09-10 19:34:10.000000000 +0000
@@ -1108,6 +1108,7 @@ static inline int sctp_peer_needs_update
 	case SCTP_STATE_ESTABLISHED:
 	case SCTP_STATE_SHUTDOWN_PENDING:
 	case SCTP_STATE_SHUTDOWN_RECEIVED:
+	case SCTP_STATE_SHUTDOWN_SENT:
 		if ((asoc->rwnd > asoc->a_rwnd) &&
 		    ((asoc->rwnd - asoc->a_rwnd) >=
 		     min_t(__u32, (asoc->base.sk->sk_rcvbuf >> 1), asoc->pmtu)))
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/net/sctp/inqueue.c linux-2.4.28-pre3/net/sctp/inqueue.c
--- linux-2.4.27/net/sctp/inqueue.c	2004-04-14 13:05:41.000000000 +0000
+++ linux-2.4.28-pre3/net/sctp/inqueue.c	2004-09-10 19:34:10.000000000 +0000
@@ -81,7 +81,7 @@ void sctp_inq_free(struct sctp_inq *queu
 	struct sctp_chunk *chunk;
 
 	/* Empty the queue.  */
-	while ((chunk = (struct sctp_chunk *) skb_dequeue(&queue->in)))
+	while ((chunk = (struct sctp_chunk *) skb_dequeue(&queue->in)) != NULL)
 		sctp_chunk_free(chunk);
 
 	/* If there is a packet which is currently being worked on,
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/net/sctp/output.c linux-2.4.28-pre3/net/sctp/output.c
--- linux-2.4.27/net/sctp/output.c	2004-08-07 23:26:07.000000000 +0000
+++ linux-2.4.28-pre3/net/sctp/output.c	2004-09-10 19:34:36.000000000 +0000
@@ -133,7 +133,7 @@ void sctp_packet_free(struct sctp_packet
 
 	SCTP_DEBUG_PRINTK("%s: packet:%p\n", __FUNCTION__, packet);
 
-        while ((chunk = (struct sctp_chunk *)__skb_dequeue(&packet->chunks)))
+        while ((chunk = (struct sctp_chunk *)__skb_dequeue(&packet->chunks)) != NULL)
 		sctp_chunk_free(chunk);
 
 	if (packet->malloced)
@@ -370,7 +370,7 @@ int sctp_packet_transmit(struct sctp_pac
 	 * [This whole comment explains WORD_ROUND() below.]
 	 */
 	SCTP_DEBUG_PRINTK("***sctp_transmit_packet***\n");
-	while ((chunk = (struct sctp_chunk *)__skb_dequeue(&packet->chunks))) {
+	while ((chunk = (struct sctp_chunk *)__skb_dequeue(&packet->chunks)) != NULL) {
 		if (sctp_chunk_is_data(chunk)) {
 
 			if (!chunk->has_tsn) {
@@ -511,7 +511,7 @@ err:
 	 * will get resent or dropped later.
 	 */
 
-	while ((chunk = (struct sctp_chunk *)__skb_dequeue(&packet->chunks))) {
+	while ((chunk = (struct sctp_chunk *)__skb_dequeue(&packet->chunks)) != NULL) {
 		if (!sctp_chunk_is_data(chunk))
     			sctp_chunk_free(chunk);
 	}
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/net/sctp/outqueue.c linux-2.4.28-pre3/net/sctp/outqueue.c
--- linux-2.4.27/net/sctp/outqueue.c	2004-08-07 23:26:07.000000000 +0000
+++ linux-2.4.28-pre3/net/sctp/outqueue.c	2004-09-10 19:33:27.000000000 +0000
@@ -245,7 +245,7 @@ void sctp_outq_teardown(struct sctp_outq
 	/* Throw away unacknowledged chunks. */
 	list_for_each(pos, &q->asoc->peer.transport_addr_list) {
 		transport = list_entry(pos, struct sctp_transport, transports);
-		while ((lchunk = sctp_list_dequeue(&transport->transmitted))) {
+		while ((lchunk = sctp_list_dequeue(&transport->transmitted)) != NULL) {
 			chunk = list_entry(lchunk, struct sctp_chunk,
 					   transmitted_list);
 			/* Mark as part of a failed message. */
@@ -282,7 +282,7 @@ void sctp_outq_teardown(struct sctp_outq
 	}
 
 	/* Throw away any leftover data chunks. */
-	while ((chunk = sctp_outq_dequeue_data(q))) {
+	while ((chunk = sctp_outq_dequeue_data(q)) != NULL) {
 
 		/* Mark as send failure. */
 		sctp_chunk_fail(chunk, q->error);
@@ -292,7 +292,7 @@ void sctp_outq_teardown(struct sctp_outq
 	q->error = 0;
 
 	/* Throw away any leftover control chunks. */
-	while ((chunk = (struct sctp_chunk *) skb_dequeue(&q->control)))
+	while ((chunk = (struct sctp_chunk *) skb_dequeue(&q->control)) != NULL)
 		sctp_chunk_free(chunk);
 }
 
@@ -525,10 +525,10 @@ static int sctp_outq_flush_rtx(struct sc
 			       int rtx_timeout, int *start_timer)
 {
 	struct list_head *lqueue;
-	struct list_head *lchunk;
+	struct list_head *lchunk, *lchunk1;
 	struct sctp_transport *transport = pkt->transport;
 	sctp_xmit_t status;
-	struct sctp_chunk *chunk;
+	struct sctp_chunk *chunk, *chunk1;
 	struct sctp_association *asoc;
 	int error = 0;
 
@@ -615,6 +615,12 @@ static int sctp_outq_flush_rtx(struct sc
 			 * the transmitted list.
 			 */
 			list_add_tail(lchunk, &transport->transmitted);
+
+			/* Mark the chunk as ineligible for fast retransmit 
+			 * after it is retransmitted.
+			 */
+			chunk->fast_retransmit = 0;
+
 			*start_timer = 1;
 			q->empty = 0;
 
@@ -622,6 +628,18 @@ static int sctp_outq_flush_rtx(struct sc
 			lchunk = sctp_list_dequeue(lqueue);
 			break;
 		};
+
+		/* If we are here due to a retransmit timeout or a fast
+		 * retransmit and if there are any chunks left in the retransmit
+		 * queue that could not fit in the PMTU sized packet, they need			 * to be marked as ineligible for a subsequent fast retransmit.
+		 */
+		if (rtx_timeout && !lchunk) {
+			list_for_each(lchunk1, lqueue) {
+				chunk1 = list_entry(lchunk1, struct sctp_chunk,
+						    transmitted_list);
+				chunk1->fast_retransmit = 0;
+			}
+		}
 	}
 
 	return error;
@@ -681,7 +699,7 @@ int sctp_outq_flush(struct sctp_outq *q,
 	 */
 
 	queue = &q->control;
-	while ((chunk = (struct sctp_chunk *)skb_dequeue(queue))) {
+	while ((chunk = (struct sctp_chunk *)skb_dequeue(queue)) != NULL) {
 		/* Pick the right transport to use. */
 		new_transport = chunk->transport;
 
@@ -812,7 +830,7 @@ int sctp_outq_flush(struct sctp_outq *q,
 		start_timer = 0;
 		queue = &q->out;
 
-		while ((chunk = sctp_outq_dequeue_data(q))) {
+		while ((chunk = sctp_outq_dequeue_data(q)) != NULL) {
 			/* RFC 2960 6.5 Every DATA chunk MUST carry a valid
 			 * stream identifier.
 			 */
@@ -866,7 +884,7 @@ int sctp_outq_flush(struct sctp_outq *q,
 			SCTP_DEBUG_PRINTK("TX TSN 0x%x skb->head "
 					"%p skb->users %d.\n",
 					ntohl(chunk->subh.data_hdr->tsn),
-					chunk->skb ?chunk->skb->head : 0,
+					chunk->skb ?chunk->skb->head : NULL,
 					chunk->skb ?
 					atomic_read(&chunk->skb->users) : -1);
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/net/sctp/protocol.c linux-2.4.28-pre3/net/sctp/protocol.c
--- linux-2.4.27/net/sctp/protocol.c	2004-08-07 23:26:07.000000000 +0000
+++ linux-2.4.28-pre3/net/sctp/protocol.c	2004-09-10 19:35:00.000000000 +0000
@@ -97,7 +97,7 @@ __init int sctp_proc_init(void)
 {
 	if (!proc_net_sctp) {
 		struct proc_dir_entry *ent;
-		ent = proc_mkdir("net/sctp", 0);
+		ent = proc_mkdir("net/sctp", NULL);
 		if (ent) {
 			ent->owner = THIS_MODULE;
 			proc_net_sctp = ent;
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/net/sctp/sm_sideeffect.c linux-2.4.28-pre3/net/sctp/sm_sideeffect.c
--- linux-2.4.27/net/sctp/sm_sideeffect.c	2004-08-07 23:26:07.000000000 +0000
+++ linux-2.4.28-pre3/net/sctp/sm_sideeffect.c	2004-09-10 19:35:31.000000000 +0000
@@ -529,6 +529,23 @@ static void sctp_cmd_hb_timers_stop(sctp
 	}
 }
 
+/* Helper function to stop any pending T3-RTX timers */
+static void sctp_cmd_t3_rtx_timers_stop(sctp_cmd_seq_t *cmds,
+				        struct sctp_association *asoc)
+{
+	struct sctp_transport *t;
+	struct list_head *pos;
+
+	list_for_each(pos, &asoc->peer.transport_addr_list) {
+		t = list_entry(pos, struct sctp_transport, transports);
+		if (timer_pending(&t->T3_rtx_timer) &&
+		    del_timer(&t->T3_rtx_timer)) {
+			sctp_transport_put(t);
+		}
+	}
+}
+
+
 /* Helper function to update the heartbeat timer. */
 static void sctp_cmd_hb_timer_update(sctp_cmd_seq_t *cmds,
 				     struct sctp_association *asoc,
@@ -749,6 +766,26 @@ static void sctp_cmd_process_fwdtsn(stru
 	return;
 }
 
+/* Helper function to remove the association non-primary peer 
+ * transports.
+ */ 
+static void sctp_cmd_del_non_primary(struct sctp_association *asoc)
+{
+	struct sctp_transport *t;
+	struct list_head *pos;
+	struct list_head *temp;
+
+	list_for_each_safe(pos, temp, &asoc->peer.transport_addr_list) {
+		t = list_entry(pos, struct sctp_transport, transports);
+		if (!sctp_cmp_addr_exact(&t->ipaddr,
+		                         &asoc->peer.primary_addr)) {
+			sctp_assoc_del_peer(asoc, &t->ipaddr);
+		}
+	}
+
+	return;
+}
+
 /* These three macros allow us to pull the debugging code out of the
  * main flow of sctp_do_sm() to keep attention focused on the real
  * functionality there.
@@ -1048,6 +1085,27 @@ int sctp_cmd_interpreter(sctp_event_t ev
 			if (cmd->obj.ptr)
 				sctp_add_cmd_sf(commands, SCTP_CMD_REPLY,
 						SCTP_CHUNK(cmd->obj.ptr));
+
+			/* FIXME - Eventually come up with a cleaner way to
+			 * enabling COOKIE-ECHO + DATA bundling during 
+			 * multihoming stale cookie scenarios, the following 
+			 * command plays with asoc->peer.retran_path to 
+			 * avoid the problem of sending the COOKIE-ECHO and 
+			 * DATA in different paths, which could result 
+			 * in the association being ABORTed if the DATA chunk 
+			 * is processed first by the server.  Checking the
+			 * init error counter simply causes this command
+			 * to be executed only during failed attempts of
+			 * association establishment.
+			 */
+			if ((asoc->peer.retran_path != 
+			     asoc->peer.primary_path) && 
+			    (asoc->counters[SCTP_COUNTER_INIT_ERROR] > 0)) {
+				sctp_add_cmd_sf(commands, 
+				                SCTP_CMD_FORCE_PRIM_RETRAN,
+						SCTP_NULL());
+			}
+
 			break;
 
 		case SCTP_CMD_GEN_SHUTDOWN:
@@ -1282,6 +1340,19 @@ int sctp_cmd_interpreter(sctp_event_t ev
 		case SCTP_CMD_CLEAR_INIT_TAG:
 			asoc->peer.i.init_tag = 0;
 			break;
+		case SCTP_CMD_DEL_NON_PRIMARY:
+			sctp_cmd_del_non_primary(asoc);
+			break;
+		case SCTP_CMD_T3_RTX_TIMERS_STOP:
+			sctp_cmd_t3_rtx_timers_stop(commands, asoc);
+			break;
+		case SCTP_CMD_FORCE_PRIM_RETRAN:
+			t = asoc->peer.retran_path;
+			asoc->peer.retran_path = asoc->peer.primary_path;
+			error = sctp_outq_uncork(&asoc->outqueue);
+			local_cork = 0;
+			asoc->peer.retran_path = t;
+			break;
 		default:
 			printk(KERN_WARNING "Impossible command: %u, %p\n",
 			       cmd->verb, cmd->obj.ptr);
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/net/sctp/sm_statefuns.c linux-2.4.28-pre3/net/sctp/sm_statefuns.c
--- linux-2.4.27/net/sctp/sm_statefuns.c	2004-08-07 23:26:07.000000000 +0000
+++ linux-2.4.28-pre3/net/sctp/sm_statefuns.c	2004-09-10 19:34:36.000000000 +0000
@@ -472,8 +472,6 @@ sctp_disposition_t sctp_sf_do_5_1C_ack(c
 	 */
 	sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP,
 			SCTP_TO(SCTP_EVENT_TIMEOUT_T1_INIT));
-	sctp_add_cmd_sf(commands, SCTP_CMD_COUNTER_RESET,
-			SCTP_COUNTER(SCTP_COUNTER_INIT_ERROR));
 	sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_START,
 			SCTP_TO(SCTP_EVENT_TIMEOUT_T1_COOKIE));
 	sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE,
@@ -674,6 +672,15 @@ sctp_disposition_t sctp_sf_do_5_1E_ca(co
 	if (!sctp_vtag_verify(chunk, asoc))
 		return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
 
+	/* Reset init error count upon receipt of COOKIE-ACK,
+	 * to avoid problems with the managemement of this
+	 * counter in stale cookie situations when a transition back
+	 * from the COOKIE-ECHOED state to the COOKIE-WAIT
+	 * state is performed.
+	 */
+	sctp_add_cmd_sf(commands, SCTP_CMD_COUNTER_RESET,
+	                SCTP_COUNTER(SCTP_COUNTER_INIT_ERROR));
+
 	/* RFC 2960 5.1 Normal Establishment of an Association
 	 *
 	 * E) Upon reception of the COOKIE ACK, endpoint "A" will move
@@ -995,7 +1002,7 @@ static int sctp_sf_check_restart_addrs(c
 	/* Search through all current addresses and make sure
 	 * we aren't adding any new ones.
 	 */
-	new_addr = 0;
+	new_addr = NULL;
 	found = 0;
 
 	list_for_each(pos, &new_asoc->peer.transport_addr_list) {
@@ -1872,8 +1879,6 @@ sctp_disposition_t sctp_sf_do_5_2_6_stal
 	time_t stale;
 	sctp_cookie_preserve_param_t bht;
 	sctp_errhdr_t *err;
-	struct list_head *pos;
-	struct sctp_transport *t;
 	struct sctp_chunk *reply;
 	struct sctp_bind_addr *bp;
 	int attempts;
@@ -1920,20 +1925,27 @@ sctp_disposition_t sctp_sf_do_5_2_6_stal
 	/* Clear peer's init_tag cached in assoc as we are sending a new INIT */
 	sctp_add_cmd_sf(commands, SCTP_CMD_CLEAR_INIT_TAG, SCTP_NULL());
 
+	/* Stop pending T3-rtx and heartbeat timers */
+	sctp_add_cmd_sf(commands, SCTP_CMD_T3_RTX_TIMERS_STOP, SCTP_NULL());
+	sctp_add_cmd_sf(commands, SCTP_CMD_HB_TIMERS_STOP, SCTP_NULL());
+
+	/* Delete non-primary peer ip addresses since we are transitioning
+	 * back to the COOKIE-WAIT state
+	 */
+	sctp_add_cmd_sf(commands, SCTP_CMD_DEL_NON_PRIMARY, SCTP_NULL());
+
+	/* If we've sent any data bundled with COOKIE-ECHO we will need to 
+	 * resend 
+	 */
+	sctp_add_cmd_sf(commands, SCTP_CMD_RETRAN, 
+			SCTP_TRANSPORT(asoc->peer.primary_path));
+
 	/* Cast away the const modifier, as we want to just
 	 * rerun it through as a sideffect.
 	 */
 	sctp_add_cmd_sf(commands, SCTP_CMD_COUNTER_INC,
 			SCTP_COUNTER(SCTP_COUNTER_INIT_ERROR));
 
-	/* If we've sent any data bundled with COOKIE-ECHO we need to
-	 * resend.
-	 */
-	list_for_each(pos, &asoc->peer.transport_addr_list) {
-		t = list_entry(pos, struct sctp_transport, transports);
-		sctp_add_cmd_sf(commands, SCTP_CMD_RETRAN, SCTP_TRANSPORT(t));
-	}
-
 	sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP,
 			SCTP_TO(SCTP_EVENT_TIMEOUT_T1_COOKIE));
 	sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE,
@@ -2321,12 +2333,7 @@ sctp_disposition_t sctp_sf_eat_data_6_2(
 					sctp_cmd_seq_t *commands)
 {
 	struct sctp_chunk *chunk = arg;
-	sctp_datahdr_t *data_hdr;
-	struct sctp_chunk *err;
-	size_t datalen;
-	sctp_verb_t deliver;
-	int tmp;
-	__u32 tsn;
+	int error;
 
 	if (!sctp_vtag_verify(chunk, asoc)) {
 		sctp_add_cmd_sf(commands, SCTP_CMD_REPORT_BAD_TAG,
@@ -2334,158 +2341,22 @@ sctp_disposition_t sctp_sf_eat_data_6_2(
 		return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
         }
 
-	data_hdr = chunk->subh.data_hdr = (sctp_datahdr_t *)chunk->skb->data;
-	skb_pull(chunk->skb, sizeof(sctp_datahdr_t));
-
-	tsn = ntohl(data_hdr->tsn);
-	SCTP_DEBUG_PRINTK("eat_data: TSN 0x%x.\n", tsn);
-
-	/* ASSERT:  Now skb->data is really the user data.  */
-
-	/* Process ECN based congestion.
-	 *
-	 * Since the chunk structure is reused for all chunks within
-	 * a packet, we use ecn_ce_done to track if we've already
-	 * done CE processing for this packet.
-	 *
-	 * We need to do ECN processing even if we plan to discard the
-	 * chunk later.
-	 */
-
-	if (!chunk->ecn_ce_done) {
-		struct sctp_af *af;
-		chunk->ecn_ce_done = 1;
-
-		af = sctp_get_af_specific(
-			ipver2af(chunk->skb->nh.iph->version));
-
-		if (af && af->is_ce(chunk->skb) && asoc->peer.ecn_capable) {
-			/* Do real work as sideffect. */
-			sctp_add_cmd_sf(commands, SCTP_CMD_ECN_CE,
-					SCTP_U32(tsn));
-		}
-	}
-
-	tmp = sctp_tsnmap_check(&asoc->peer.tsn_map, tsn);
-	if (tmp < 0) {
-		/* The TSN is too high--silently discard the chunk and
-		 * count on it getting retransmitted later.
-		 */
+	error = sctp_eat_data(asoc, chunk, commands );
+	switch (error) {
+	case SCTP_IERROR_NO_ERROR:
+		break;
+	case SCTP_IERROR_HIGH_TSN:
+	case SCTP_IERROR_BAD_STREAM:
 		goto discard_noforce;
-	} else if (tmp > 0) {
-		/* This is a duplicate.  Record it.  */
-		sctp_add_cmd_sf(commands, SCTP_CMD_REPORT_DUP, SCTP_U32(tsn));
+	case SCTP_IERROR_DUP_TSN:
+	case SCTP_IERROR_IGNORE_TSN:
 		goto discard_force;
+	case SCTP_IERROR_NO_DATA:
+		goto consume;
+	default:
+		BUG();
 	}
 
-	/* This is a new TSN.  */
-
-	/* Discard if there is no room in the receive window.
-	 * Actually, allow a little bit of overflow (up to a MTU).
-	 */
-	datalen = ntohs(chunk->chunk_hdr->length);
-	datalen -= sizeof(sctp_data_chunk_t);
-
-	deliver = SCTP_CMD_CHUNK_ULP;
-
-	/* Think about partial delivery. */
-	if ((datalen >= asoc->rwnd) && (!asoc->ulpq.pd_mode)) {
-
-		/* Even if we don't accept this chunk there is
-		 * memory pressure.
-		 */
-		sctp_add_cmd_sf(commands, SCTP_CMD_PART_DELIVER, SCTP_NULL());
-	}
-
-        /* Spill over rwnd a little bit.  Note: While allowed, this spill over
-	 * seems a bit troublesome in that frag_point varies based on
-	 * PMTU.  In cases, such as loopback, this might be a rather
-	 * large spill over.
-	 */
-	if (!asoc->rwnd || asoc->rwnd_over ||
-	    (datalen > asoc->rwnd + asoc->frag_point)) {
-
-		/* If this is the next TSN, consider reneging to make
-		 * room.   Note: Playing nice with a confused sender.  A
-		 * malicious sender can still eat up all our buffer
-		 * space and in the future we may want to detect and
-		 * do more drastic reneging.
-		 */
-		if (sctp_tsnmap_has_gap(&asoc->peer.tsn_map) &&
-		    (sctp_tsnmap_get_ctsn(&asoc->peer.tsn_map) + 1) == tsn) {
-			SCTP_DEBUG_PRINTK("Reneging for tsn:%u\n", tsn);
-			deliver = SCTP_CMD_RENEGE;
-		} else {
-			SCTP_DEBUG_PRINTK("Discard tsn: %u len: %Zd, "
-					  "rwnd: %d\n", tsn, datalen,
-					  asoc->rwnd);
-			goto discard_force;
-		}
-	}
-
-	/*
-	 * Section 3.3.10.9 No User Data (9)
-	 *
-	 * Cause of error
-	 * ---------------
-	 * No User Data:  This error cause is returned to the originator of a
-	 * DATA chunk if a received DATA chunk has no user data.
-	 */
-	if (unlikely(0 == datalen)) {
-		err = sctp_make_abort_no_data(asoc, chunk, tsn);
-		if (err) {
-			sctp_add_cmd_sf(commands, SCTP_CMD_REPLY,
-					SCTP_CHUNK(err));
-		}
-		/* We are going to ABORT, so we might as well stop
-		 * processing the rest of the chunks in the packet.
-		 */
-		sctp_add_cmd_sf(commands, SCTP_CMD_DISCARD_PACKET,SCTP_NULL());
-		sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED,
-				SCTP_U32(SCTP_ERROR_NO_DATA));
-		SCTP_INC_STATS(SctpAborteds);
-		SCTP_DEC_STATS(SctpCurrEstab);
-		return SCTP_DISPOSITION_CONSUME;
-	}
-
-	/* If definately accepting the DATA chunk, record its TSN, otherwise
-	 * wait for renege processing.
-	 */
-	if (SCTP_CMD_CHUNK_ULP == deliver)
-		sctp_add_cmd_sf(commands, SCTP_CMD_REPORT_TSN, SCTP_U32(tsn));
-
-	/* Note: Some chunks may get overcounted (if we drop) or overcounted
-	 * if we renege and the chunk arrives again.
-	 */
-	if (chunk->chunk_hdr->flags & SCTP_DATA_UNORDERED)
-		SCTP_INC_STATS(SctpInUnorderChunks);
-	else
-		SCTP_INC_STATS(SctpInOrderChunks);
-
-	/* RFC 2960 6.5 Stream Identifier and Stream Sequence Number
-	 *
-	 * If an endpoint receive a DATA chunk with an invalid stream
-	 * identifier, it shall acknowledge the reception of the DATA chunk
-	 * following the normal procedure, immediately send an ERROR chunk
-	 * with cause set to "Invalid Stream Identifier" (See Section 3.3.10)
-	 * and discard the DATA chunk.
-	 */
-	if (ntohs(data_hdr->stream) >= asoc->c.sinit_max_instreams) {
-		err = sctp_make_op_error(asoc, chunk, SCTP_ERROR_INV_STRM,
-					 &data_hdr->stream,
-					 sizeof(data_hdr->stream));
-		if (err)
-			sctp_add_cmd_sf(commands, SCTP_CMD_REPLY,
-					SCTP_CHUNK(err));
-		goto discard_noforce;
-	}
-
-	/* Send the data up to the user.  Note:  Schedule  the
-	 * SCTP_CMD_CHUNK_ULP cmd before the SCTP_CMD_GEN_SACK, as the SACK
-	 * chunk needs the updated rwnd.
-	 */
-	sctp_add_cmd_sf(commands, deliver, SCTP_CHUNK(chunk));
-
 	if (asoc->autoclose) {
 		sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_RESTART,
 				SCTP_TO(SCTP_EVENT_TIMEOUT_AUTOCLOSE));
@@ -2551,6 +2422,9 @@ discard_noforce:
 				SCTP_TO(SCTP_EVENT_TIMEOUT_SACK));
 	}
 	return SCTP_DISPOSITION_DISCARD;
+consume:
+	return SCTP_DISPOSITION_CONSUME;
+	
 }
 
 /*
@@ -2576,11 +2450,7 @@ sctp_disposition_t sctp_sf_eat_data_fast
 				     sctp_cmd_seq_t *commands)
 {
 	struct sctp_chunk *chunk = arg;
-	sctp_datahdr_t *data_hdr;
-	struct sctp_chunk *err;
-	size_t datalen;
-	int tmp;
-	__u32 tsn;
+	int error;
 
 	if (!sctp_vtag_verify(chunk, asoc)) {
 		sctp_add_cmd_sf(commands, SCTP_CMD_REPORT_BAD_TAG,
@@ -2588,110 +2458,23 @@ sctp_disposition_t sctp_sf_eat_data_fast
 		return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
 	}
 
-	data_hdr = chunk->subh.data_hdr = (sctp_datahdr_t *) chunk->skb->data;
-	skb_pull(chunk->skb, sizeof(sctp_datahdr_t));
-
-	tsn = ntohl(data_hdr->tsn);
-
-	SCTP_DEBUG_PRINTK("eat_data: TSN 0x%x.\n", tsn);
-
-	/* ASSERT:  Now skb->data is really the user data.  */
-
-	/* Process ECN based congestion.
-	 *
-	 * Since the chunk structure is reused for all chunks within
-	 * a packet, we use ecn_ce_done to track if we've already
-	 * done CE processing for this packet.
-	 *
-	 * We need to do ECN processing even if we plan to discard the
-	 * chunk later.
-	 */
-	if (!chunk->ecn_ce_done) {
-		struct sctp_af *af;
-		chunk->ecn_ce_done = 1;
-
-		af = sctp_get_af_specific(
-			ipver2af(chunk->skb->nh.iph->version));
-
-		if (af && af->is_ce(chunk->skb) && asoc->peer.ecn_capable) {
-			/* Do real work as sideffect. */
-			sctp_add_cmd_sf(commands, SCTP_CMD_ECN_CE,
-					SCTP_U32(tsn));
-		}
-	}
-
-	tmp = sctp_tsnmap_check(&asoc->peer.tsn_map, tsn);
-	if (tmp < 0) {
-		/* The TSN is too high--silently discard the chunk and
-		 * count on it getting retransmitted later.
-		 */
-		goto gen_shutdown;
-	} else if (tmp > 0) {
-		/* This is a duplicate.  Record it.  */
-		sctp_add_cmd_sf(commands, SCTP_CMD_REPORT_DUP, SCTP_U32(tsn));
-		goto gen_shutdown;
-	}
-
-	/* This is a new TSN.  */
 
-	datalen = ntohs(chunk->chunk_hdr->length);
-	datalen -= sizeof(sctp_data_chunk_t);
-
-	/*
-	 * Section 3.3.10.9 No User Data (9)
-	 *
-	 * Cause of error
-	 * ---------------
-	 * No User Data:  This error cause is returned to the originator of a
-	 * DATA chunk if a received DATA chunk has no user data.
-	 */
-	if (unlikely(0 == datalen)) {
-		err = sctp_make_abort_no_data(asoc, chunk, tsn);
-		if (err) {
-			sctp_add_cmd_sf(commands, SCTP_CMD_REPLY,
-					SCTP_CHUNK(err));
-		}
-		/* We are going to ABORT, so we might as well stop
-		 * processing the rest of the chunks in the packet.
-		 */
-		sctp_add_cmd_sf(commands, SCTP_CMD_DISCARD_PACKET,SCTP_NULL());
-		sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED,
-				SCTP_U32(SCTP_ERROR_NO_DATA));
-		SCTP_INC_STATS(SctpAborteds);
-		SCTP_DEC_STATS(SctpCurrEstab);
-		return SCTP_DISPOSITION_CONSUME;
-	}
-
-	/* We are accepting this DATA chunk. */
-
-	/* Record the fact that we have received this TSN.  */
-	sctp_add_cmd_sf(commands, SCTP_CMD_REPORT_TSN, SCTP_U32(tsn));
-
-	if (chunk->chunk_hdr->flags & SCTP_DATA_UNORDERED)
-		SCTP_INC_STATS(SctpInUnorderChunks);
-	else
-		SCTP_INC_STATS(SctpInOrderChunks);
-
-	/* RFC 2960 6.5 Stream Identifier and Stream Sequence Number
-	 *
-	 * If an endpoint receive a DATA chunk with an invalid stream
-	 * identifier, it shall acknowledge the reception of the DATA chunk
-	 * following the normal procedure, immediately send an ERROR chunk
-	 * with cause set to "Invalid Stream Identifier" (See Section 3.3.10)
-	 * and discard the DATA chunk.
-	 */
-	if (ntohs(data_hdr->stream) >= asoc->c.sinit_max_instreams) {
-		err = sctp_make_op_error(asoc, chunk, SCTP_ERROR_INV_STRM,
-					 &data_hdr->stream,
-					 sizeof(data_hdr->stream));
-		if (err) {
-			sctp_add_cmd_sf(commands, SCTP_CMD_REPLY,
-					SCTP_CHUNK(err));
-		}
+	error = sctp_eat_data(asoc, chunk, commands );
+	switch (error) {
+	case SCTP_IERROR_NO_ERROR:
+	case SCTP_IERROR_HIGH_TSN:
+	case SCTP_IERROR_DUP_TSN:
+	case SCTP_IERROR_IGNORE_TSN:
+	case SCTP_IERROR_BAD_STREAM:
+		break;
+	case SCTP_IERROR_NO_DATA:
+		goto consume;
+	default:
+		BUG();
 	}
 
 	/* Go a head and force a SACK, since we are shutting down. */
-gen_shutdown:
+
 	/* Implementor's Guide.
 	 *
 	 * While in SHUTDOWN-SENT state, the SHUTDOWN sender MUST immediately
@@ -2707,6 +2490,8 @@ gen_shutdown:
 		sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_RESTART,
 				SCTP_TO(SCTP_EVENT_TIMEOUT_T2_SHUTDOWN));
 	}
+
+consume:
 	return SCTP_DISPOSITION_CONSUME;
 }
 
@@ -4709,7 +4494,7 @@ struct sctp_sackhdr *sctp_sm_pull_sack(s
 	num_blocks = ntohs(sack->num_gap_ack_blocks);
 	num_dup_tsns = ntohs(sack->num_dup_tsns);
 	len = sizeof(struct sctp_sackhdr);
-	len = (num_blocks + num_dup_tsns) * sizeof(__u32);
+	len += (num_blocks + num_dup_tsns) * sizeof(__u32);
 	if (len > chunk->skb->len)
 		return NULL;
 
@@ -4848,3 +4633,171 @@ void sctp_send_stale_cookie_err(const st
 			sctp_chunk_free (err_chunk);
 	}
 }
+
+
+/* Process a data chunk */
+int sctp_eat_data(const struct sctp_association *asoc,
+		  struct sctp_chunk *chunk,
+		  sctp_cmd_seq_t *commands)
+{
+	sctp_datahdr_t *data_hdr;
+	struct sctp_chunk *err;
+	size_t datalen;
+	sctp_verb_t deliver;
+	int tmp;
+	__u32 tsn;
+
+	data_hdr = chunk->subh.data_hdr = (sctp_datahdr_t *)chunk->skb->data;
+	skb_pull(chunk->skb, sizeof(sctp_datahdr_t));
+
+	tsn = ntohl(data_hdr->tsn);
+	SCTP_DEBUG_PRINTK("eat_data: TSN 0x%x.\n", tsn);
+
+	/* ASSERT:  Now skb->data is really the user data.  */
+
+	/* Process ECN based congestion.
+	 *
+	 * Since the chunk structure is reused for all chunks within
+	 * a packet, we use ecn_ce_done to track if we've already
+	 * done CE processing for this packet.
+	 *
+	 * We need to do ECN processing even if we plan to discard the
+	 * chunk later.
+	 */
+
+	if (!chunk->ecn_ce_done) {
+		struct sctp_af *af;
+		chunk->ecn_ce_done = 1;
+
+		af = sctp_get_af_specific(
+			ipver2af(chunk->skb->nh.iph->version));
+
+		if (af && af->is_ce(chunk->skb) && asoc->peer.ecn_capable) {
+			/* Do real work as sideffect. */
+			sctp_add_cmd_sf(commands, SCTP_CMD_ECN_CE,
+					SCTP_U32(tsn));
+		}
+	}
+
+	tmp = sctp_tsnmap_check(&asoc->peer.tsn_map, tsn);
+	if (tmp < 0) {
+		/* The TSN is too high--silently discard the chunk and
+		 * count on it getting retransmitted later.
+		 */
+		return SCTP_IERROR_HIGH_TSN;
+	} else if (tmp > 0) {
+		/* This is a duplicate.  Record it.  */
+		sctp_add_cmd_sf(commands, SCTP_CMD_REPORT_DUP, SCTP_U32(tsn));
+		return SCTP_IERROR_DUP_TSN;
+	}
+
+	/* This is a new TSN.  */
+
+	/* Discard if there is no room in the receive window.
+	 * Actually, allow a little bit of overflow (up to a MTU).
+	 */
+	datalen = ntohs(chunk->chunk_hdr->length);
+	datalen -= sizeof(sctp_data_chunk_t);
+
+	deliver = SCTP_CMD_CHUNK_ULP;
+
+	/* Think about partial delivery. */
+	if ((datalen >= asoc->rwnd) && (!asoc->ulpq.pd_mode)) {
+
+		/* Even if we don't accept this chunk there is
+		 * memory pressure.
+		 */
+		sctp_add_cmd_sf(commands, SCTP_CMD_PART_DELIVER, SCTP_NULL());
+	}
+
+        /* Spill over rwnd a little bit.  Note: While allowed, this spill over
+	 * seems a bit troublesome in that frag_point varies based on
+	 * PMTU.  In cases, such as loopback, this might be a rather
+	 * large spill over.
+	 */
+	if (!asoc->rwnd || asoc->rwnd_over ||
+	    (datalen > asoc->rwnd + asoc->frag_point)) {
+
+		/* If this is the next TSN, consider reneging to make
+		 * room.   Note: Playing nice with a confused sender.  A
+		 * malicious sender can still eat up all our buffer
+		 * space and in the future we may want to detect and
+		 * do more drastic reneging.
+		 */
+		if (sctp_tsnmap_has_gap(&asoc->peer.tsn_map) &&
+		    (sctp_tsnmap_get_ctsn(&asoc->peer.tsn_map) + 1) == tsn) {
+			SCTP_DEBUG_PRINTK("Reneging for tsn:%u\n", tsn);
+			deliver = SCTP_CMD_RENEGE;
+		} else {
+			SCTP_DEBUG_PRINTK("Discard tsn: %u len: %Zd, "
+					  "rwnd: %d\n", tsn, datalen,
+					  asoc->rwnd);
+			return SCTP_IERROR_IGNORE_TSN;
+		}
+	}
+
+	/*
+	 * Section 3.3.10.9 No User Data (9)
+	 *
+	 * Cause of error
+	 * ---------------
+	 * No User Data:  This error cause is returned to the originator of a
+	 * DATA chunk if a received DATA chunk has no user data.
+	 */
+	if (unlikely(0 == datalen)) {
+		err = sctp_make_abort_no_data(asoc, chunk, tsn);
+		if (err) {
+			sctp_add_cmd_sf(commands, SCTP_CMD_REPLY,
+					SCTP_CHUNK(err));
+		}
+		/* We are going to ABORT, so we might as well stop
+		 * processing the rest of the chunks in the packet.
+		 */
+		sctp_add_cmd_sf(commands, SCTP_CMD_DISCARD_PACKET,SCTP_NULL());
+		sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED,
+				SCTP_U32(SCTP_ERROR_NO_DATA));
+		SCTP_INC_STATS(SctpAborteds);
+		SCTP_DEC_STATS(SctpCurrEstab);
+		return SCTP_IERROR_NO_DATA;
+	}
+
+	/* If definately accepting the DATA chunk, record its TSN, otherwise
+	 * wait for renege processing.
+	 */
+	if (SCTP_CMD_CHUNK_ULP == deliver)
+		sctp_add_cmd_sf(commands, SCTP_CMD_REPORT_TSN, SCTP_U32(tsn));
+
+	/* Note: Some chunks may get overcounted (if we drop) or overcounted
+	 * if we renege and the chunk arrives again.
+	 */
+	if (chunk->chunk_hdr->flags & SCTP_DATA_UNORDERED)
+		SCTP_INC_STATS(SctpInUnorderChunks);
+	else
+		SCTP_INC_STATS(SctpInOrderChunks);
+
+	/* RFC 2960 6.5 Stream Identifier and Stream Sequence Number
+	 *
+	 * If an endpoint receive a DATA chunk with an invalid stream
+	 * identifier, it shall acknowledge the reception of the DATA chunk
+	 * following the normal procedure, immediately send an ERROR chunk
+	 * with cause set to "Invalid Stream Identifier" (See Section 3.3.10)
+	 * and discard the DATA chunk.
+	 */
+	if (ntohs(data_hdr->stream) >= asoc->c.sinit_max_instreams) {
+		err = sctp_make_op_error(asoc, chunk, SCTP_ERROR_INV_STRM,
+					 &data_hdr->stream,
+					 sizeof(data_hdr->stream));
+		if (err)
+			sctp_add_cmd_sf(commands, SCTP_CMD_REPLY,
+					SCTP_CHUNK(err));
+		return SCTP_IERROR_BAD_STREAM;
+	}
+
+	/* Send the data up to the user.  Note:  Schedule  the
+	 * SCTP_CMD_CHUNK_ULP cmd before the SCTP_CMD_GEN_SACK, as the SACK
+	 * chunk needs the updated rwnd.
+	 */
+	sctp_add_cmd_sf(commands, deliver, SCTP_CHUNK(chunk));
+
+	return SCTP_IERROR_NO_ERROR;
+}
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/net/sctp/socket.c linux-2.4.28-pre3/net/sctp/socket.c
--- linux-2.4.27/net/sctp/socket.c	2004-08-07 23:26:07.000000000 +0000
+++ linux-2.4.28-pre3/net/sctp/socket.c	2004-09-10 19:32:58.000000000 +0000
@@ -86,8 +86,6 @@
 
 /* Forward declarations for internal helper functions. */
 static int sctp_writeable(struct sock *sk);
-static inline int sctp_wspace(struct sctp_association *asoc);
-static inline void sctp_set_owner_w(struct sctp_chunk *chunk);
 static void sctp_wfree(struct sk_buff *skb);
 static int sctp_wait_for_sndbuf(struct sctp_association *, long *timeo_p,
 				size_t msg_len);
@@ -95,7 +93,8 @@ static int sctp_wait_for_packet(struct s
 static int sctp_wait_for_connect(struct sctp_association *, long *timeo_p);
 static int sctp_wait_for_accept(struct sock *sk, long timeo);
 static void sctp_wait_for_close(struct sock *sk, long timeo);
-static inline int sctp_verify_addr(struct sock *, union sctp_addr *, int);
+static struct sctp_af *sctp_sockaddr_af(struct sctp_opt *opt,
+					union sctp_addr *addr, int len);
 static int sctp_bindx_add(struct sock *, struct sockaddr *, int);
 static int sctp_bindx_rem(struct sock *, struct sockaddr *, int);
 static int sctp_send_asconf_add_ip(struct sock *, struct sockaddr *, int);
@@ -111,6 +110,64 @@ static char *sctp_hmac_alg = SCTP_COOKIE
 extern kmem_cache_t *sctp_bucket_cachep;
 extern int sctp_assoc_valid(struct sock *sk, struct sctp_association *asoc);
 
+/* Get the sndbuf space available at the time on the association.  */
+static inline int sctp_wspace(struct sctp_association *asoc)
+{
+	struct sock *sk = asoc->base.sk;
+	int amt = 0;
+
+	amt = sk->sk_sndbuf - asoc->sndbuf_used;
+	if (amt < 0)
+		amt = 0;
+	return amt;
+}
+
+/* Increment the used sndbuf space count of the corresponding association by
+ * the size of the outgoing data chunk.
+ * Also, set the skb destructor for sndbuf accounting later.
+ *
+ * Since it is always 1-1 between chunk and skb, and also a new skb is always
+ * allocated for chunk bundling in sctp_packet_transmit(), we can use the
+ * destructor in the data chunk skb for the purpose of the sndbuf space
+ * tracking.
+ */
+static inline void sctp_set_owner_w(struct sctp_chunk *chunk)
+{
+	struct sctp_association *asoc = chunk->asoc;
+	struct sock *sk = asoc->base.sk;
+
+	/* The sndbuf space is tracked per association.  */
+	sctp_association_hold(asoc);
+
+	chunk->skb->destructor = sctp_wfree;
+	/* Save the chunk pointer in skb for sctp_wfree to use later.  */
+	*((struct sctp_chunk **)(chunk->skb->cb)) = chunk;
+
+	asoc->sndbuf_used += SCTP_DATA_SNDSIZE(chunk);
+	sk->sk_wmem_queued += SCTP_DATA_SNDSIZE(chunk);
+}
+
+/* Verify that this is a valid address. */
+static inline int sctp_verify_addr(struct sock *sk, union sctp_addr *addr,
+				   int len)
+{
+	struct sctp_af *af;
+
+	/* Verify basic sockaddr. */
+	af = sctp_sockaddr_af(sctp_sk(sk), addr, len);
+	if (!af)
+		return -EINVAL;
+
+	/* Is this a valid SCTP address?  */
+	if (!af->addr_valid(addr, sctp_sk(sk)))
+		return -EINVAL;
+
+	if (!sctp_sk(sk)->pf->send_verify(sctp_sk(sk), (addr)))
+		return -EINVAL;
+
+	return 0;
+}
+
 /* Look up the association by its id.  If this is not a UDP-style
  * socket, the ID field is always ignored.
  */
@@ -999,7 +1056,7 @@ SCTP_STATIC int sctp_sendmsg(struct sock
 	struct sctp_sndrcvinfo *sinfo;
 	struct sctp_initmsg *sinit;
 	sctp_assoc_t associd = NULL;
-	sctp_cmsgs_t cmsgs = { 0 };
+	sctp_cmsgs_t cmsgs = { NULL };
 	int err;
 	sctp_scope_t scope;
 	long timeo;
@@ -1630,6 +1687,32 @@ static int sctp_setsockopt_peer_addr_par
 	if (copy_from_user(&params, optval, optlen))
 		return -EFAULT;
 
+	/*
+	 * API 7. Socket Options (setting the default value for the endpoint)
+	 * All options that support specific settings on an association by
+	 * filling in either an association id variable or a sockaddr_storage
+	 * SHOULD also support setting of the same value for the entire endpoint
+	 * (i.e. future associations). To accomplish this the following logic is
+	 * used when setting one of these options:
+
+	 * c) If neither the sockaddr_storage or association identification is
+	 *    set i.e. the sockaddr_storage is set to all 0's (INADDR_ANY) and
+	 *    the association identification is 0, the settings are a default
+	 *    and to be applied to the endpoint (all future associations).
+	 */
+
+	/* update default value for endpoint (all future associations) */
+	if (!params.spp_assoc_id && 
+	    sctp_is_any(( union sctp_addr *)&params.spp_address)) {
+		if (params.spp_hbinterval)
+			sctp_sk(sk)->paddrparam.spp_hbinterval =
+						params.spp_hbinterval;
+		if (sctp_max_retrans_path)
+			sctp_sk(sk)->paddrparam.spp_pathmaxrxt =
+						params.spp_pathmaxrxt;
+		return 0;
+	}
+
 	trans = sctp_addr_id2transport(sk, &params.spp_address,
 				       params.spp_assoc_id);
 	if (!trans)
@@ -2795,6 +2878,17 @@ static int sctp_getsockopt_peer_addr_par
 	if (copy_from_user(&params, optval, *optlen))
 		return -EFAULT;
 
+	/* If no association id is specified retrieve the default value
+	 * for the endpoint that will be used for all future associations
+	 */
+	if (!params.spp_assoc_id &&
+	    sctp_is_any(( union sctp_addr *)&params.spp_address)) {
+		params.spp_hbinterval = sctp_sk(sk)->paddrparam.spp_hbinterval;
+		params.spp_pathmaxrxt = sctp_sk(sk)->paddrparam.spp_pathmaxrxt;
+
+		goto done;
+	}
+
 	trans = sctp_addr_id2transport(sk, &params.spp_address,
 				       params.spp_assoc_id);
 	if (!trans)
@@ -2814,6 +2908,7 @@ static int sctp_getsockopt_peer_addr_par
 	 */
 	params.spp_pathmaxrxt = trans->error_threshold;
 
+done:
 	if (copy_to_user(optval, &params, len))
 		return -EFAULT;
 
@@ -4138,64 +4233,6 @@ no_packet:
 	return NULL;
 }
 
-/* Verify that this is a valid address. */
-static inline int sctp_verify_addr(struct sock *sk, union sctp_addr *addr,
-				   int len)
-{
-	struct sctp_af *af;
-
-	/* Verify basic sockaddr. */
-	af = sctp_sockaddr_af(sctp_sk(sk), addr, len);
-	if (!af)
-		return -EINVAL;
-
-	/* Is this a valid SCTP address?  */
-	if (!af->addr_valid(addr, sctp_sk(sk)))
-		return -EINVAL;
-
-	if (!sctp_sk(sk)->pf->send_verify(sctp_sk(sk), (addr)))
-		return -EINVAL;
-
-	return 0;
-}
-
-/* Get the sndbuf space available at the time on the association.  */
-static inline int sctp_wspace(struct sctp_association *asoc)
-{
-	struct sock *sk = asoc->base.sk;
-	int amt = 0;
-
-	amt = sk->sk_sndbuf - asoc->sndbuf_used;
-	if (amt < 0)
-		amt = 0;
-	return amt;
-}
-
-/* Increment the used sndbuf space count of the corresponding association by
- * the size of the outgoing data chunk.
- * Also, set the skb destructor for sndbuf accounting later.
- *
- * Since it is always 1-1 between chunk and skb, and also a new skb is always
- * allocated for chunk bundling in sctp_packet_transmit(), we can use the
- * destructor in the data chunk skb for the purpose of the sndbuf space
- * tracking.
- */
-static inline void sctp_set_owner_w(struct sctp_chunk *chunk)
-{
-	struct sctp_association *asoc = chunk->asoc;
-	struct sock *sk = asoc->base.sk;
-
-	/* The sndbuf space is tracked per association.  */
-	sctp_association_hold(asoc);
-
-	chunk->skb->destructor = sctp_wfree;
-	/* Save the chunk pointer in skb for sctp_wfree to use later.  */
-	*((struct sctp_chunk **)(chunk->skb->cb)) = chunk;
-
-	asoc->sndbuf_used += SCTP_DATA_SNDSIZE(chunk);
-	sk->sk_wmem_queued += SCTP_DATA_SNDSIZE(chunk);
-}
-
 /* If sndbuf has changed, wake up per association sndbuf waiters.  */
 static void __sctp_write_space(struct sctp_association *asoc)
 {
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/net/sctp/ulpevent.c linux-2.4.28-pre3/net/sctp/ulpevent.c
--- linux-2.4.27/net/sctp/ulpevent.c	2004-08-07 23:26:07.000000000 +0000
+++ linux-2.4.28-pre3/net/sctp/ulpevent.c	2004-09-10 19:35:54.000000000 +0000
@@ -48,13 +48,23 @@
 #include <net/sctp/sctp.h>
 #include <net/sctp/sm.h>
 
-static inline void sctp_ulpevent_set_owner(struct sctp_ulpevent *event,
-					   const struct sctp_association *asoc);
-static inline void sctp_ulpevent_release_owner(struct sctp_ulpevent *event);
 static void sctp_ulpevent_receive_data(struct sctp_ulpevent *event,
 				       struct sctp_association *asoc);
 static void sctp_ulpevent_release_data(struct sctp_ulpevent *event);
 
+/* Stub skb destructor.  */
+static void sctp_stub_rfree(struct sk_buff *skb)
+{
+/* WARNING:  This function is just a warning not to use the
+ * skb destructor.  If the skb is shared, we may get the destructor
+ * callback on some processor that does not own the sock_lock.  This
+ * was occuring with PACKET socket applications that were monitoring
+ * our skbs.   We can't take the sock_lock, because we can't risk
+ * recursing if we do really own the sock lock.  Instead, do all
+ * of our rwnd manipulation while we own the sock_lock outright.
+ */
+}
+
 /* Create a new sctp_ulpevent.  */
 struct sctp_ulpevent *sctp_ulpevent_new(int size, int msg_flags, int gfp)
 {
@@ -87,6 +97,30 @@ int sctp_ulpevent_is_notification(const 
 	return MSG_NOTIFICATION == (event->msg_flags & MSG_NOTIFICATION);
 }
 
+/* Hold the association in case the msg_name needs read out of
+ * the association.
+ */
+static inline void sctp_ulpevent_set_owner(struct sctp_ulpevent *event,
+					   const struct sctp_association *asoc)
+{
+	struct sk_buff *skb;
+
+	/* Cast away the const, as we are just wanting to
+	 * bump the reference count.
+	 */
+	sctp_association_hold((struct sctp_association *)asoc);
+	skb = sctp_event2skb(event);
+	skb->sk = asoc->base.sk;
+	event->asoc = (struct sctp_association *)asoc;
+	skb->destructor = sctp_stub_rfree;
+}
+
+/* A simple destructor to give up the reference to the association. */
+static inline void sctp_ulpevent_release_owner(struct sctp_ulpevent *event)
+{
+	sctp_association_put(event->asoc);
+}
+
 /* Create and initialize an SCTP_ASSOC_CHANGE event.
  *
  * 5.3.1.1 SCTP_ASSOC_CHANGE
@@ -789,43 +823,6 @@ void sctp_ulpevent_read_sndrcvinfo(const
 		 sizeof(struct sctp_sndrcvinfo), (void *)&sinfo);
 }
 
-/* Stub skb destructor.  */
-static void sctp_stub_rfree(struct sk_buff *skb)
-{
-/* WARNING:  This function is just a warning not to use the
- * skb destructor.  If the skb is shared, we may get the destructor
- * callback on some processor that does not own the sock_lock.  This
- * was occuring with PACKET socket applications that were monitoring
- * our skbs.   We can't take the sock_lock, because we can't risk
- * recursing if we do really own the sock lock.  Instead, do all
- * of our rwnd manipulation while we own the sock_lock outright.
- */
-}
-
-/* Hold the association in case the msg_name needs read out of
- * the association.
- */
-static inline void sctp_ulpevent_set_owner(struct sctp_ulpevent *event,
-					   const struct sctp_association *asoc)
-{
-	struct sk_buff *skb;
-
-	/* Cast away the const, as we are just wanting to
-	 * bump the reference count.
-	 */
-	sctp_association_hold((struct sctp_association *)asoc);
-	skb = sctp_event2skb(event);
-	skb->sk = asoc->base.sk;
-	event->asoc = (struct sctp_association *)asoc;
-	skb->destructor = sctp_stub_rfree;
-}
-
-/* A simple destructor to give up the reference to the association. */
-static inline void sctp_ulpevent_release_owner(struct sctp_ulpevent *event)
-{
-	sctp_association_put(event->asoc);
-}
-
 /* Do accounting for bytes received and hold a reference to the association
  * for each skb.
  */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/net/sctp/ulpqueue.c linux-2.4.28-pre3/net/sctp/ulpqueue.c
--- linux-2.4.27/net/sctp/ulpqueue.c	2004-08-07 23:26:07.000000000 +0000
+++ linux-2.4.28-pre3/net/sctp/ulpqueue.c	2004-09-10 19:31:49.000000000 +0000
@@ -49,10 +49,10 @@
 #include <net/sctp/sm.h>
 
 /* Forward declarations for internal helpers.  */
-static inline struct sctp_ulpevent * sctp_ulpq_reasm(struct sctp_ulpq *ulpq,
-						     struct sctp_ulpevent *);
-static inline struct sctp_ulpevent *sctp_ulpq_order(struct sctp_ulpq *,
-						    struct sctp_ulpevent *);
+static struct sctp_ulpevent * sctp_ulpq_reasm(struct sctp_ulpq *ulpq,
+						struct sctp_ulpevent *);
+static struct sctp_ulpevent * sctp_ulpq_order(struct sctp_ulpq *,
+						struct sctp_ulpevent *);
 
 /* 1st Level Abstractions */
 
@@ -97,12 +97,12 @@ void sctp_ulpq_flush(struct sctp_ulpq *u
 	struct sk_buff *skb;
 	struct sctp_ulpevent *event;
 
-	while ((skb = __skb_dequeue(&ulpq->lobby))) {
+	while ((skb = __skb_dequeue(&ulpq->lobby)) != NULL) {
 		event = sctp_skb2event(skb);
 		sctp_ulpevent_free(event);
 	}
 
-	while ((skb = __skb_dequeue(&ulpq->reasm))) {
+	while ((skb = __skb_dequeue(&ulpq->reasm)) != NULL) {
 		event = sctp_skb2event(skb);
 		sctp_ulpevent_free(event);
 	}
@@ -466,8 +466,8 @@ done:
 /* Helper function to reassemble chunks.  Hold chunks on the reasm queue that
  * need reassembling.
  */
-static inline struct sctp_ulpevent *sctp_ulpq_reasm(struct sctp_ulpq *ulpq,
-						   struct sctp_ulpevent *event)
+static struct sctp_ulpevent *sctp_ulpq_reasm(struct sctp_ulpq *ulpq,
+						struct sctp_ulpevent *event)
 {
 	struct sctp_ulpevent *retval = NULL;
 
@@ -645,8 +645,8 @@ static inline void sctp_ulpq_store_order
 
 }
 
-static inline struct sctp_ulpevent *sctp_ulpq_order(struct sctp_ulpq *ulpq,
-					struct sctp_ulpevent *event)
+static struct sctp_ulpevent *sctp_ulpq_order(struct sctp_ulpq *ulpq,
+						struct sctp_ulpevent *event)
 {
 	__u16 sid, ssn;
 	struct sctp_stream *in;
@@ -756,7 +756,7 @@ static __u16 sctp_ulpq_renege_order(stru
 
 	tsnmap = &ulpq->asoc->peer.tsn_map;
 
-	while ((skb = __skb_dequeue_tail(&ulpq->lobby))) {
+	while ((skb = __skb_dequeue_tail(&ulpq->lobby)) != NULL) {
 		freed += skb_headlen(skb);
 		event = sctp_skb2event(skb);
 		tsn = event->tsn;
@@ -782,7 +782,7 @@ static __u16 sctp_ulpq_renege_frags(stru
 	tsnmap = &ulpq->asoc->peer.tsn_map;
 
 	/* Walk backwards through the list, reneges the newest tsns. */
-	while ((skb = __skb_dequeue_tail(&ulpq->reasm))) {
+	while ((skb = __skb_dequeue_tail(&ulpq->reasm)) != NULL) {
 		freed += skb_headlen(skb);
 		event = sctp_skb2event(skb);
 		tsn = event->tsn;
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.27/net/sunrpc/xprt.c linux-2.4.28-pre3/net/sunrpc/xprt.c
--- linux-2.4.27/net/sunrpc/xprt.c	2003-11-28 18:26:21.000000000 +0000
+++ linux-2.4.28-pre3/net/sunrpc/xprt.c	2004-09-10 19:35:48.000000000 +0000
@@ -1244,19 +1244,6 @@ do_xprt_transmit(struct rpc_task *task)
 /*
  * Reserve an RPC call slot.
  */
-void
-xprt_reserve(struct rpc_task *task)
-{
-	struct rpc_xprt	*xprt = task->tk_xprt;
-
-	task->tk_status = -EIO;
-	if (!xprt->shutdown) {
-		spin_lock(&xprt->xprt_lock);
-		do_xprt_reserve(task);
-		spin_unlock(&xprt->xprt_lock);
-	}
-}
-
 static inline void
 do_xprt_reserve(struct rpc_task *task)
 {
@@ -1279,6 +1266,19 @@ do_xprt_reserve(struct rpc_task *task)
 	rpc_sleep_on(&xprt->backlog, task, NULL, NULL);
 }
 
+void
+xprt_reserve(struct rpc_task *task)
+{
+	struct rpc_xprt	*xprt = task->tk_xprt;
+
+	task->tk_status = -EIO;
+	if (!xprt->shutdown) {
+		spin_lock(&xprt->xprt_lock);
+		do_xprt_reserve(task);
+		spin_unlock(&xprt->xprt_lock);
+	}
+}
+
 /*
  * Allocate a 'unique' XID
  */
