diff -Nru a/Documentation/Configure.help b/Documentation/Configure.help
--- a/Documentation/Configure.help	2004-08-13 17:37:30 -07:00
+++ b/Documentation/Configure.help	2004-08-23 20:35:40 -07:00
@@ -4696,12 +4696,6 @@
   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
@@ -7971,7 +7965,7 @@
 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>
@@ -7989,6 +7983,37 @@
 
   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)
@@ -9299,6 +9324,16 @@
 
   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.
 
@@ -17272,10 +17307,11 @@
   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
@@ -25405,13 +25441,13 @@
 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
diff -Nru a/Documentation/ftape.txt b/Documentation/ftape.txt
--- a/Documentation/ftape.txt	2002-02-05 09:40:37 -08:00
+++ b/Documentation/ftape.txt	2004-08-19 02:04:14 -07:00
@@ -15,7 +15,7 @@
 
 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 @@
 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 @@
 
    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 -Nru a/MAINTAINERS b/MAINTAINERS
--- a/MAINTAINERS	2004-08-13 14:21:05 -07:00
+++ b/MAINTAINERS	2004-08-23 15:01:27 -07:00
@@ -177,10 +177,8 @@
 
 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
@@ -1454,9 +1452,8 @@
 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
diff -Nru a/Makefile b/Makefile
--- a/Makefile	2004-08-15 12:34:40 -07:00
+++ b/Makefile	2004-08-25 02:51:22 -07:00
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 4
 SUBLEVEL = 28
-EXTRAVERSION = -pre1
+EXTRAVERSION = -pre1-bk3
 
 KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
 
diff -Nru a/arch/alpha/config.in b/arch/alpha/config.in
--- a/arch/alpha/config.in	2004-01-27 12:27:39 -08:00
+++ b/arch/alpha/config.in	2004-01-07 11:21:26 -08:00
@@ -314,7 +314,7 @@
 	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 -Nru a/arch/arm/config.in b/arch/arm/config.in
--- a/arch/arm/config.in	2004-01-27 12:27:40 -08:00
+++ b/arch/arm/config.in	2004-01-07 11:22:40 -08:00
@@ -498,7 +498,7 @@
 	"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 -Nru a/arch/cris/config.in b/arch/cris/config.in
--- a/arch/cris/config.in	2004-01-27 12:27:40 -08:00
+++ b/arch/cris/config.in	2004-01-07 11:23:44 -08:00
@@ -30,7 +30,7 @@
 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 -Nru a/arch/i386/config.in b/arch/i386/config.in
--- a/arch/i386/config.in	2004-01-27 12:27:39 -08:00
+++ b/arch/i386/config.in	2004-01-07 11:21:07 -08:00
@@ -326,7 +326,7 @@
 	 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 -Nru a/arch/i386/defconfig b/arch/i386/defconfig
--- a/arch/i386/defconfig	2004-08-03 16:25:48 -07:00
+++ b/arch/i386/defconfig	2004-08-15 16:53:43 -07:00
@@ -758,7 +758,7 @@
 # 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 -Nru a/arch/i386/kernel/pci-irq.c b/arch/i386/kernel/pci-irq.c
--- a/arch/i386/kernel/pci-irq.c	2004-05-31 16:01:54 -07:00
+++ b/arch/i386/kernel/pci-irq.c	2004-08-23 15:01:27 -07:00
@@ -1112,10 +1112,6 @@
 				}
 				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 -Nru a/arch/ia64/config.in b/arch/ia64/config.in
--- a/arch/ia64/config.in	2004-01-27 12:27:40 -08:00
+++ b/arch/ia64/config.in	2004-01-07 11:23:06 -08:00
@@ -123,7 +123,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
 tristate 'Kernel support for MISC binaries' CONFIG_BINFMT_MISC
 
 if [ "$CONFIG_IA64_HP_SIM" = "n" ]; then
diff -Nru a/arch/ia64/defconfig b/arch/ia64/defconfig
--- a/arch/ia64/defconfig	2004-05-10 20:15:43 -07:00
+++ b/arch/ia64/defconfig	2004-08-15 16:53:43 -07:00
@@ -755,7 +755,7 @@
 # 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 -Nru a/arch/m68k/config.in b/arch/m68k/config.in
--- a/arch/m68k/config.in	2004-01-27 12:27:40 -08:00
+++ b/arch/m68k/config.in	2004-01-07 11:22:10 -08:00
@@ -98,7 +98,7 @@
 	 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 -Nru a/arch/mips/config-shared.in b/arch/mips/config-shared.in
--- a/arch/mips/config-shared.in	2004-01-27 12:27:39 -08:00
+++ b/arch/mips/config-shared.in	2004-01-07 11:21:57 -08:00
@@ -943,7 +943,7 @@
 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 -Nru a/arch/mips/defconfig b/arch/mips/defconfig
--- a/arch/mips/defconfig	2004-01-27 12:27:40 -08:00
+++ b/arch/mips/defconfig	2004-08-15 16:53:43 -07:00
@@ -607,7 +607,7 @@
 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 -Nru a/arch/mips64/defconfig b/arch/mips64/defconfig
--- a/arch/mips64/defconfig	2004-01-27 12:27:40 -08:00
+++ b/arch/mips64/defconfig	2004-08-15 16:53:43 -07:00
@@ -563,7 +563,7 @@
 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 -Nru a/arch/parisc/config.in b/arch/parisc/config.in
--- a/arch/parisc/config.in	2004-01-27 12:27:40 -08:00
+++ b/arch/parisc/config.in	2004-01-07 11:23:30 -08:00
@@ -88,7 +88,7 @@
 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 -Nru a/arch/ppc/defconfig b/arch/ppc/defconfig
--- a/arch/ppc/defconfig	2004-01-27 12:27:40 -08:00
+++ b/arch/ppc/defconfig	2004-08-15 16:53:43 -07:00
@@ -812,7 +812,7 @@
 # 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 -Nru a/arch/ppc64/defconfig b/arch/ppc64/defconfig
--- a/arch/ppc64/defconfig	2004-01-27 12:27:39 -08:00
+++ b/arch/ppc64/defconfig	2004-08-15 16:53:43 -07:00
@@ -668,7 +668,7 @@
 # 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 -Nru a/arch/s390/config.in b/arch/s390/config.in
--- a/arch/s390/config.in	2003-08-29 16:12:42 -07:00
+++ b/arch/s390/config.in	2004-01-07 11:23:20 -08:00
@@ -57,7 +57,7 @@
 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 -Nru a/arch/s390/defconfig b/arch/s390/defconfig
--- a/arch/s390/defconfig	2003-12-12 08:10:13 -08:00
+++ b/arch/s390/defconfig	2004-08-18 09:09:02 -07:00
@@ -129,6 +129,14 @@
 #
 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 @@
 #
 #    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_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 -Nru a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S
--- a/arch/s390/kernel/entry.S	2003-02-19 05:04:42 -08:00
+++ b/arch/s390/kernel/entry.S	2004-08-18 09:09:00 -07:00
@@ -690,7 +690,12 @@
 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 @@
         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 @@
 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_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 @@
 	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 @@
 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 @@
 .Lvfork:       .long  sys_vfork
 
 .Lschedtail:   .long  schedule_tail
-
+.Laccount_ticks:.long account_ticks
diff -Nru a/arch/s390/kernel/s390_ksyms.c b/arch/s390/kernel/s390_ksyms.c
--- a/arch/s390/kernel/s390_ksyms.c	2003-12-12 07:18:03 -08:00
+++ b/arch/s390/kernel/s390_ksyms.c	2004-08-18 09:08:54 -07:00
@@ -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(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 -Nru a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c
--- a/arch/s390/kernel/smp.c	2002-07-30 04:27:40 -07:00
+++ b/arch/s390/kernel/smp.c	2004-08-18 09:08:54 -07:00
@@ -92,7 +92,7 @@
 
 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 @@
  * 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 @@
 	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 @@
 	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_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 @@
 }
 
 /*
- * 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 -Nru a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c
--- a/arch/s390/kernel/time.c	2003-02-19 05:04:58 -08:00
+++ b/arch/s390/kernel/time.c	2004-08-18 09:09:00 -07:00
@@ -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 @@
 {
 	__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 @@
 	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 @@
  */
 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 @@
         }
 
 	/* 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 -Nru a/arch/s390x/config.in b/arch/s390x/config.in
--- a/arch/s390x/config.in	2003-08-29 16:12:55 -07:00
+++ b/arch/s390x/config.in	2004-01-07 11:23:55 -08:00
@@ -60,7 +60,7 @@
 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 -Nru a/arch/s390x/defconfig b/arch/s390x/defconfig
--- a/arch/s390x/defconfig	2003-12-12 08:10:16 -08:00
+++ b/arch/s390x/defconfig	2004-08-18 09:09:02 -07:00
@@ -129,6 +129,14 @@
 #
 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_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 -Nru a/arch/s390x/kernel/entry.S b/arch/s390x/kernel/entry.S
--- a/arch/s390x/kernel/entry.S	2003-06-27 04:39:02 -07:00
+++ b/arch/s390x/kernel/entry.S	2004-08-18 09:09:00 -07:00
@@ -722,7 +722,12 @@
         .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 @@
 	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 @@
 	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 @@
 	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 -Nru a/arch/s390x/kernel/linux32.c b/arch/s390x/kernel/linux32.c
--- a/arch/s390x/kernel/linux32.c	2003-12-12 08:10:21 -08:00
+++ b/arch/s390x/kernel/linux32.c	2004-08-18 09:08:54 -07:00
@@ -4427,7 +4427,7 @@
     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 @@
     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 @@
     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 @@
 	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 -Nru a/arch/s390x/kernel/s390_ksyms.c b/arch/s390x/kernel/s390_ksyms.c
--- a/arch/s390x/kernel/s390_ksyms.c	2003-12-12 08:10:21 -08:00
+++ b/arch/s390x/kernel/s390_ksyms.c	2004-08-18 09:08:54 -07:00
@@ -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_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 -Nru a/arch/s390x/kernel/smp.c b/arch/s390x/kernel/smp.c
--- a/arch/s390x/kernel/smp.c	2003-02-19 05:04:42 -08:00
+++ b/arch/s390x/kernel/smp.c	2004-08-18 09:08:54 -07:00
@@ -92,7 +92,7 @@
 
 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 @@
  * 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 @@
 	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 @@
  */
 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 @@
 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 @@
 
 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 @@
 
 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 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_clear_bit);
 EXPORT_SYMBOL(smp_num_cpus);
 EXPORT_SYMBOL(smp_call_function);
+
diff -Nru a/arch/s390x/kernel/time.c b/arch/s390x/kernel/time.c
--- a/arch/s390x/kernel/time.c	2003-02-19 05:05:10 -08:00
+++ b/arch/s390x/kernel/time.c	2004-08-18 09:09:00 -07:00
@@ -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 @@
 {
 	__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 @@
  * 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 @@
  */
 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 @@
         }
 
 	/* 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 -Nru a/arch/sh/config.in b/arch/sh/config.in
--- a/arch/sh/config.in	2004-01-27 12:27:40 -08:00
+++ b/arch/sh/config.in	2004-01-07 11:22:49 -08:00
@@ -282,7 +282,7 @@
 	"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 -Nru a/arch/sh64/config.in b/arch/sh64/config.in
--- a/arch/sh64/config.in	2004-05-04 06:08:27 -07:00
+++ b/arch/sh64/config.in	2004-01-07 11:20:14 -08:00
@@ -150,7 +150,7 @@
 	"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 -Nru a/arch/sh64/defconfig b/arch/sh64/defconfig
--- a/arch/sh64/defconfig	2004-05-04 05:56:04 -07:00
+++ b/arch/sh64/defconfig	2004-08-15 16:53:43 -07:00
@@ -386,7 +386,7 @@
 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 -Nru a/arch/sparc/config.in b/arch/sparc/config.in
--- a/arch/sparc/config.in	2004-01-27 12:27:39 -08:00
+++ b/arch/sparc/config.in	2004-01-07 11:21:38 -08:00
@@ -73,7 +73,7 @@
    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 -Nru a/arch/sparc64/config.in b/arch/sparc64/config.in
--- a/arch/sparc64/config.in	2004-05-07 15:08:14 -07:00
+++ b/arch/sparc64/config.in	2004-01-07 11:22:20 -08:00
@@ -78,7 +78,7 @@
    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 -Nru a/arch/sparc64/kernel/itlb_base.S b/arch/sparc64/kernel/itlb_base.S
--- a/arch/sparc64/kernel/itlb_base.S	2004-07-01 00:50:57 -07:00
+++ b/arch/sparc64/kernel/itlb_base.S	2004-08-16 13:34:48 -07:00
@@ -44,6 +44,7 @@
 	 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
 3:	rdpr		%pstate, %g4			! Move into alternate globals
diff -Nru a/arch/x86_64/config.in b/arch/x86_64/config.in
--- a/arch/x86_64/config.in	2004-03-21 12:13:55 -08:00
+++ b/arch/x86_64/config.in	2004-01-07 11:20:26 -08:00
@@ -117,7 +117,7 @@
    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 -Nru a/drivers/block/cciss.c b/drivers/block/cciss.c
--- a/drivers/block/cciss.c	2004-08-13 13:57:06 -07:00
+++ b/drivers/block/cciss.c	2004-08-16 11:04:26 -07:00
@@ -168,6 +168,35 @@
 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, 
@@ -629,6 +658,7 @@
 static inline void register_cciss_ioctl32(void) {}
 static inline void unregister_cciss_ioctl32(void) {}
 #endif
+
 /*
  * ioctl 
  */
@@ -2132,35 +2162,6 @@
         ulong page_remapped    = (ulong) ioremap(page_base, page_offs+size);
 
         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;
 }
 
 /* 
diff -Nru a/drivers/block/cpqarray.c b/drivers/block/cpqarray.c
--- a/drivers/block/cpqarray.c	2004-01-20 08:47:56 -08:00
+++ b/drivers/block/cpqarray.c	2004-08-16 10:50:37 -07:00
@@ -960,6 +960,20 @@
 	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 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 -Nru a/drivers/block/ll_rw_blk.c b/drivers/block/ll_rw_blk.c
--- a/drivers/block/ll_rw_blk.c	2004-03-15 08:52:56 -08:00
+++ b/drivers/block/ll_rw_blk.c	2004-08-15 19:28:55 -07:00
@@ -132,7 +132,7 @@
 	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 @@
 		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 @@
 /*
  * 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 @@
 	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 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_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 @@
 {
 	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 @@
 	 * 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 -Nru a/drivers/char/ip2main.c b/drivers/char/ip2main.c
--- a/drivers/char/ip2main.c	2003-09-03 10:56:16 -07:00
+++ b/drivers/char/ip2main.c	2004-08-16 11:41:24 -07:00
@@ -282,8 +282,8 @@
 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 @@
 	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 @@
 	}
 }
 
-static inline void
+static void
 do_status( i2ChanStrPtr pCh )
 {
 	int status;
diff -Nru a/drivers/char/istallion.c b/drivers/char/istallion.c
--- a/drivers/char/istallion.c	2004-07-30 06:29:39 -07:00
+++ b/drivers/char/istallion.c	2004-08-16 11:27:24 -07:00
@@ -4546,6 +4546,26 @@
 /*****************************************************************************/
 
 /*
+ *	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
@@ -4621,26 +4641,6 @@
 	}
 
 	return(0);
-}
-
-/*****************************************************************************/
-
-/*
- *	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);
 }
 
 /*****************************************************************************/
diff -Nru a/drivers/char/mxser.c b/drivers/char/mxser.c
--- a/drivers/char/mxser.c	2002-07-29 09:49:49 -07:00
+++ b/drivers/char/mxser.c	2004-08-16 11:17:23 -07:00
@@ -1385,66 +1385,6 @@
 	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_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)
 {
@@ -1568,6 +1470,104 @@
 				info->IER &= ~UART_IER_THRI;
 				outb(info->IER, info->base + UART_IER);
 			}
+		}
+	}
+}
+
+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 */
 		}
 	}
 }
diff -Nru a/drivers/hotplug/cpqphp_ctrl.c b/drivers/hotplug/cpqphp_ctrl.c
--- a/drivers/hotplug/cpqphp_ctrl.c	2003-08-20 20:08:28 -07:00
+++ b/drivers/hotplug/cpqphp_ctrl.c	2004-06-29 08:36:21 -07:00
@@ -1726,7 +1726,14 @@
 	
 	//  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 -Nru a/drivers/hotplug/pciehp.h b/drivers/hotplug/pciehp.h
--- a/drivers/hotplug/pciehp.h	2004-03-17 17:44:34 -08:00
+++ b/drivers/hotplug/pciehp.h	2004-06-28 15:47:57 -07:00
@@ -45,8 +45,6 @@
 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 -Nru a/drivers/hotplug/pciehp_ctrl.c b/drivers/hotplug/pciehp_ctrl.c
--- a/drivers/hotplug/pciehp_ctrl.c	2004-04-01 12:47:58 -08:00
+++ b/drivers/hotplug/pciehp_ctrl.c	2004-06-28 15:47:57 -07:00
@@ -1053,6 +1053,34 @@
    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 @@
 	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 @@
 	
 	/* 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 @@
 	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 @@
 		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 @@
 		/* 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 @@
 	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 @@
 					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 @@
 {
 	struct slot *p_slot = (struct slot *) slot;
 	u8 getstatus;
-	int rc;
 	
 	pushbutton_pending = 0;
 
@@ -1638,23 +1613,7 @@
 		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 @@
 			/* 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 @@
 	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 @@
 	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 -Nru a/drivers/hotplug/pciehp_hpc.c b/drivers/hotplug/pciehp_hpc.c
--- a/drivers/hotplug/pciehp_hpc.c	2004-03-17 14:00:30 -08:00
+++ b/drivers/hotplug/pciehp_hpc.c	2004-06-28 15:47:57 -07:00
@@ -346,10 +346,11 @@
 		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 @@
 		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 @@
 			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 @@
 			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 @@
 			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 @@
 			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 @@
 			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 @@
 			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 @@
 		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 -Nru a/drivers/hotplug/pciehp_pci.c b/drivers/hotplug/pciehp_pci.c
--- a/drivers/hotplug/pciehp_pci.c	2004-03-17 14:00:30 -08:00
+++ b/drivers/hotplug/pciehp_pci.c	2004-06-28 15:47:57 -07:00
@@ -117,9 +117,7 @@
 			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 -Nru a/drivers/hotplug/pciehprm_acpi.c b/drivers/hotplug/pciehprm_acpi.c
--- a/drivers/hotplug/pciehprm_acpi.c	2004-03-17 14:00:30 -08:00
+++ b/drivers/hotplug/pciehprm_acpi.c	2004-06-28 15:47:57 -07:00
@@ -217,6 +217,10 @@
 	}
 
 	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 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 @@
 			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 -Nru a/drivers/hotplug/pciehprm_nonacpi.c b/drivers/hotplug/pciehprm_nonacpi.c
--- a/drivers/hotplug/pciehprm_nonacpi.c	2004-03-17 14:00:30 -08:00
+++ b/drivers/hotplug/pciehprm_nonacpi.c	2004-06-28 15:47:57 -07:00
@@ -281,7 +281,7 @@
 
 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 @@
 				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 -Nru a/drivers/hotplug/shpchp.h b/drivers/hotplug/shpchp.h
--- a/drivers/hotplug/shpchp.h	2004-03-17 17:44:30 -08:00
+++ b/drivers/hotplug/shpchp.h	2004-06-28 15:47:57 -07:00
@@ -61,6 +61,7 @@
 	u8 configured;
 	u8 switch_save;
 	u8 presence_save;
+	u8 pwr_save;
 	u32 base_length[0x06];
 	u8 base_type[0x06];
 	u16 reserved2;
diff -Nru a/drivers/hotplug/shpchp_ctrl.c b/drivers/hotplug/shpchp_ctrl.c
--- a/drivers/hotplug/shpchp_ctrl.c	2004-04-01 12:53:20 -08:00
+++ b/drivers/hotplug/shpchp_ctrl.c	2004-06-28 15:47:57 -07:00
@@ -137,6 +137,8 @@
 	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 @@
 		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 @@
 					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 @@
 						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 @@
 		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 @@
 		func->function = 0;
 		func->configured = 0;
 		func->switch_save = 0x10;
+		func->pwr_save = 0;
 		func->is_a_board = 0;
 	}
 
@@ -2038,7 +2048,6 @@
 {
 	struct slot *p_slot = (struct slot *) slot;
 	u8 getstatus;
-	int rc;
 	
 	pushbutton_pending = 0;
 
@@ -2052,23 +2061,7 @@
 		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 @@
 			/* 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 @@
 	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 @@
 
 	/* 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 @@
 	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 -Nru a/drivers/hotplug/shpchp_hpc.c b/drivers/hotplug/shpchp_hpc.c
--- a/drivers/hotplug/shpchp_hpc.c	2004-04-01 12:55:20 -08:00
+++ b/drivers/hotplug/shpchp_hpc.c	2004-06-28 15:47:57 -07:00
@@ -1547,15 +1547,6 @@
 		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 @@
 			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 -Nru a/drivers/hotplug/shpchp_pci.c b/drivers/hotplug/shpchp_pci.c
--- a/drivers/hotplug/shpchp_pci.c	2004-03-17 14:00:30 -08:00
+++ b/drivers/hotplug/shpchp_pci.c	2004-06-28 15:47:57 -07:00
@@ -481,6 +481,7 @@
 				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 -Nru a/drivers/hotplug/shpchprm_acpi.c b/drivers/hotplug/shpchprm_acpi.c
--- a/drivers/hotplug/shpchprm_acpi.c	2004-03-17 14:00:30 -08:00
+++ b/drivers/hotplug/shpchprm_acpi.c	2004-06-28 15:47:57 -07:00
@@ -217,6 +217,10 @@
 	}
 
 	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 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 @@
 
 			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 -Nru a/drivers/hotplug/shpchprm_nonacpi.c b/drivers/hotplug/shpchprm_nonacpi.c
--- a/drivers/hotplug/shpchprm_nonacpi.c	2004-03-17 14:00:30 -08:00
+++ b/drivers/hotplug/shpchprm_nonacpi.c	2004-06-28 15:47:57 -07:00
@@ -213,7 +213,7 @@
 
 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 @@
 
 			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 -Nru a/drivers/ide/pci/triflex.c b/drivers/ide/pci/triflex.c
--- a/drivers/ide/pci/triflex.c	2003-03-24 06:45:35 -08:00
+++ b/drivers/ide/pci/triflex.c	2004-02-17 15:22:54 -08:00
@@ -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 @@
 	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 @@
 		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 @@
 	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 -Nru a/drivers/ide/pci/triflex.h b/drivers/ide/pci/triflex.h
--- a/drivers/ide/pci/triflex.h	2003-03-24 10:30:41 -08:00
+++ b/drivers/ide/pci/triflex.h	2004-02-17 15:27:28 -08:00
@@ -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 @@
 };
 
 #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 -Nru a/drivers/ieee1394/eth1394.c b/drivers/ieee1394/eth1394.c
--- a/drivers/ieee1394/eth1394.c	2003-08-30 22:05:49 -07:00
+++ b/drivers/ieee1394/eth1394.c	2004-08-16 11:51:42 -07:00
@@ -149,6 +149,20 @@
 		 "(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,
@@ -883,21 +897,6 @@
 	list_add(lh, pdgl);
 
 	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)
diff -Nru a/drivers/isdn/hisax/isar.c b/drivers/isdn/hisax/isar.c
--- a/drivers/isdn/hisax/isar.c	2003-01-25 18:02:15 -08:00
+++ b/drivers/isdn/hisax/isar.c	2004-08-16 12:02:53 -07:00
@@ -428,6 +428,21 @@
 	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
@@ -960,21 +975,6 @@
 				debugl1(cs, "unknown pump stev %x", devt);
 			break;
 	}
-}
-
-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
diff -Nru a/drivers/media/radio/radio-maestro.c b/drivers/media/radio/radio-maestro.c
--- a/drivers/media/radio/radio-maestro.c	2002-02-04 23:49:25 -08:00
+++ b/drivers/media/radio/radio-maestro.c	2004-08-16 12:13:07 -07:00
@@ -307,30 +307,6 @@
 	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;
@@ -377,4 +353,28 @@
 	} else
 		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 -Nru a/drivers/media/video/w9966.c b/drivers/media/video/w9966.c
--- a/drivers/media/video/w9966.c	2003-02-06 14:34:07 -08:00
+++ b/drivers/media/video/w9966.c	2004-08-16 12:18:28 -07:00
@@ -691,6 +691,14 @@
 	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
@@ -721,14 +729,6 @@
 {
 	const u8 pins = w9966_rreg(cam, 0x18);
 	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.
diff -Nru a/drivers/mtd/chips/cfi_cmdset_0002.c b/drivers/mtd/chips/cfi_cmdset_0002.c
--- a/drivers/mtd/chips/cfi_cmdset_0002.c	2003-01-24 16:25:19 -08:00
+++ b/drivers/mtd/chips/cfi_cmdset_0002.c	2004-07-24 00:06:06 -07:00
@@ -461,7 +461,6 @@
 	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 @@
 			wake_up(&chip->wq);
 			cfi_spin_unlock(chip->mutex);
 			DISABLE_VPP(map);
-			ret = -EIO;
+			return -EIO;
 		}
 	}
 
@@ -563,7 +562,7 @@
 	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 -Nru a/drivers/mtd/devices/doc1000.c b/drivers/mtd/devices/doc1000.c
--- a/drivers/mtd/devices/doc1000.c	2003-01-24 16:25:20 -08:00
+++ b/drivers/mtd/devices/doc1000.c	2004-08-16 12:33:26 -07:00
@@ -137,6 +137,119 @@
 	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 @@
 
 /*====================================================================*/
 
-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);
@@ -349,79 +421,6 @@
 	
 	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 -Nru a/drivers/net/8139too.c b/drivers/net/8139too.c
--- a/drivers/net/8139too.c	2004-05-27 10:07:01 -07:00
+++ b/drivers/net/8139too.c	2004-08-15 19:28:55 -07:00
@@ -614,7 +614,7 @@
 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 @@
 	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 -Nru a/drivers/net/dmfe.c b/drivers/net/dmfe.c
--- a/drivers/net/dmfe.c	2003-08-26 13:39:47 -07:00
+++ b/drivers/net/dmfe.c	2004-08-16 12:40:22 -07:00
@@ -863,6 +863,20 @@
 
 
 /*
+ *	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
  */
 
@@ -1749,20 +1763,6 @@
 	udelay(1);
 
 	return phy_data;
-}
-
-
-/*
- *	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;
 }
 
 
diff -Nru a/drivers/net/e100/e100_main.c b/drivers/net/e100/e100_main.c
--- a/drivers/net/e100/e100_main.c	2004-05-25 02:02:59 -07:00
+++ b/drivers/net/e100/e100_main.c	2004-08-16 13:20:02 -07:00
@@ -1073,6 +1073,116 @@
 	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 @@
 	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 @@
 }
 
 /**
- * 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
  *
@@ -2153,116 +2263,6 @@
 			bdp->tx_thld = 189;
 		}
 	}			/* 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 */
diff -Nru a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c
--- a/drivers/net/e1000/e1000_main.c	2004-06-18 17:00:00 -07:00
+++ b/drivers/net/e1000/e1000_main.c	2004-08-16 13:27:57 -07:00
@@ -248,6 +248,34 @@
 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_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_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
  **/
@@ -2579,41 +2614,6 @@
 		return -EOPNOTSUPP;
 	}
 	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
diff -Nru a/drivers/net/eql.c b/drivers/net/eql.c
--- a/drivers/net/eql.c	2004-06-18 14:21:34 -07:00
+++ b/drivers/net/eql.c	2004-08-16 13:15:09 -07:00
@@ -335,6 +335,152 @@
 }
 
 
+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 @@
 	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 @@
  *	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 @@
 
 #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 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;
@@ -942,22 +960,6 @@
 	return slave;
 }
 
-
-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)
 {
diff -Nru a/drivers/net/hamachi.c b/drivers/net/hamachi.c
--- a/drivers/net/hamachi.c	2002-10-28 17:40:52 -08:00
+++ b/drivers/net/hamachi.c	2004-08-16 12:44:45 -07:00
@@ -1369,109 +1369,6 @@
 	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)
@@ -1675,6 +1572,109 @@
 		writew(0x0001, dev->base_addr + RxCmd);
 
 	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
diff -Nru a/drivers/net/hamradio/dmascc.c b/drivers/net/hamradio/dmascc.c
--- a/drivers/net/hamradio/dmascc.c	2003-10-27 05:35:37 -08:00
+++ b/drivers/net/hamradio/dmascc.c	2004-08-16 13:41:59 -07:00
@@ -356,6 +356,12 @@
 
 #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 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 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 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 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;
 
@@ -1402,12 +1408,5 @@
     }
     restore_flags(flags);
   }
-}
-
-
-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 -Nru a/drivers/net/irda/nsc-ircc.c b/drivers/net/irda/nsc-ircc.c
--- a/drivers/net/irda/nsc-ircc.c	2004-01-14 10:21:16 -08:00
+++ b/drivers/net/irda/nsc-ircc.c	2004-08-23 04:19:52 -07:00
@@ -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 @@
 	}
 	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 -Nru a/drivers/net/ns83820.c b/drivers/net/ns83820.c
--- a/drivers/net/ns83820.c	2004-08-08 01:58:48 -07:00
+++ b/drivers/net/ns83820.c	2004-08-07 04:09:39 -07:00
@@ -1585,6 +1585,7 @@
 	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 @@
 		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 -Nru a/drivers/net/smc9194.c b/drivers/net/smc9194.c
--- a/drivers/net/smc9194.c	2003-01-28 08:19:58 -08:00
+++ b/drivers/net/smc9194.c	2004-08-16 12:49:13 -07:00
@@ -1132,131 +1132,6 @@
 	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
@@ -1445,6 +1320,131 @@
 	lp->packets_waiting--;
 
 	outb( saved_packet, ioaddr + PNR_ARR );
+	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;
 }
 
diff -Nru a/drivers/parport/parport_pc.c b/drivers/parport/parport_pc.c
--- a/drivers/parport/parport_pc.c	2004-08-08 01:59:53 -07:00
+++ b/drivers/parport/parport_pc.c	2004-07-28 03:28:16 -07:00
@@ -266,95 +266,6 @@
 	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;
@@ -2697,6 +2608,7 @@
 	syba_2p_epp,
 	syba_1p_ecp,
 	titan_010l,
+	titan_1284p1,
 	titan_1284p2,
 	avlab_1p,
 	avlab_2p,
@@ -2768,6 +2680,7 @@
 	/* 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 },} },
@@ -2839,6 +2752,7 @@
 	  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 -Nru a/drivers/pci/pci.c b/drivers/pci/pci.c
--- a/drivers/pci/pci.c	2004-05-07 05:11:41 -07:00
+++ b/drivers/pci/pci.c	2004-06-28 15:47:57 -07:00
@@ -2214,7 +2214,6 @@
 
 EXPORT_SYMBOL(isa_dma_bridge_buggy);
 EXPORT_SYMBOL(pci_pci_problems);
-EXPORT_SYMBOL(pciehp_msi_quirk);
 
 /* Pool allocator */
 
diff -Nru a/drivers/pci/quirks.c b/drivers/pci/quirks.c
--- a/drivers/pci/quirks.c	2004-04-01 12:44:23 -08:00
+++ b/drivers/pci/quirks.c	2004-06-28 15:47:57 -07:00
@@ -719,13 +719,6 @@
 	}
 }
 
-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 @@
 	{ 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 -Nru a/drivers/pcmcia/i82365.c b/drivers/pcmcia/i82365.c
--- a/drivers/pcmcia/i82365.c	2003-09-27 08:41:26 -07:00
+++ b/drivers/pcmcia/i82365.c	2004-08-21 14:51:47 -07:00
@@ -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 -Nru a/drivers/pcmcia/o2micro.h b/drivers/pcmcia/o2micro.h
--- a/drivers/pcmcia/o2micro.h	2002-10-18 16:10:30 -07:00
+++ b/drivers/pcmcia/o2micro.h	2004-06-25 14:36:08 -07:00
@@ -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 -Nru a/drivers/pcmcia/ti113x.h b/drivers/pcmcia/ti113x.h
--- a/drivers/pcmcia/ti113x.h	2003-08-08 07:07:45 -07:00
+++ b/drivers/pcmcia/ti113x.h	2004-08-21 15:46:00 -07:00
@@ -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 @@
 	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 -Nru a/drivers/pcmcia/yenta.c b/drivers/pcmcia/yenta.c
--- a/drivers/pcmcia/yenta.c	2004-05-17 13:09:06 -07:00
+++ b/drivers/pcmcia/yenta.c	2004-06-25 14:51:44 -07:00
@@ -845,6 +845,7 @@
 
 #include "ti113x.h"
 #include "ricoh.h"
+#include "o2micro.h"
 
 /*
  * Different cardbus controllers have slightly different
@@ -879,6 +880,8 @@
 	{ PD(ENE,1225),  &ti_ops },
 	{ 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 },
diff -Nru a/drivers/s390/Config.in b/drivers/s390/Config.in
--- a/drivers/s390/Config.in	2003-06-29 08:10:25 -07:00
+++ b/drivers/s390/Config.in	2004-08-18 09:09:02 -07:00
@@ -88,6 +88,23 @@
 	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 -Nru a/drivers/s390/Makefile b/drivers/s390/Makefile
--- a/drivers/s390/Makefile	2003-02-19 03:09:14 -08:00
+++ b/drivers/s390/Makefile	2004-08-18 09:09:02 -07:00
@@ -9,6 +9,8 @@
 
 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 -Nru a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c
--- a/drivers/s390/block/dasd.c	2004-07-30 06:29:39 -07:00
+++ b/drivers/s390/block/dasd.c	2004-08-18 09:09:00 -07:00
@@ -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 @@
         /* 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 @@
 	}
 
         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 @@
                          "/proc/dasd/statistics: only 'set' and "
                          "'reset' are supported verbs");
 
+		vfree (buffer);
         	return -EINVAL;
 	}
 
@@ -5243,6 +5244,7 @@
         
 
 #endif /* DASD_PROFILE */
+        vfree (buffer);
 	return user_len;
 }
 
diff -Nru a/drivers/s390/block/dasd_3990_erp.c b/drivers/s390/block/dasd_3990_erp.c
--- a/drivers/s390/block/dasd_3990_erp.c	2003-12-12 08:10:38 -08:00
+++ b/drivers/s390/block/dasd_3990_erp.c	2004-08-18 09:09:00 -07:00
@@ -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 @@
                              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 @@
                              "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 @@
                                         CQR_STATUS_QUEUED);
                 }
         }
-
 	return erp;
 
 } /* end dasd_3990_erp_action_4 */
@@ -2386,7 +2382,7 @@
                 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 @@
 	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 @@
 
                 } 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_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 @@
                                                      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 -Nru a/drivers/s390/char/ctrlchar.c b/drivers/s390/char/ctrlchar.c
--- a/drivers/s390/char/ctrlchar.c	2003-06-27 04:39:05 -07:00
+++ b/drivers/s390/char/ctrlchar.c	2004-08-18 09:08:54 -07:00
@@ -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 -Nru a/drivers/s390/net/ctcmain.c b/drivers/s390/net/ctcmain.c
--- a/drivers/s390/net/ctcmain.c	2004-07-30 06:29:39 -07:00
+++ b/drivers/s390/net/ctcmain.c	2004-08-18 09:09:01 -07:00
@@ -3096,7 +3096,7 @@
 
 	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 @@
 
 	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 -Nru a/drivers/s390/net/iucv.c b/drivers/s390/net/iucv.c
--- a/drivers/s390/net/iucv.c	2003-06-27 04:39:06 -07:00
+++ b/drivers/s390/net/iucv.c	2004-08-18 09:09:02 -07:00
@@ -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 @@
 #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 @@
  * 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 @@
 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 @@
 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 @@
  *	   - 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 @@
 	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 @@
 	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 @@
 		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 @@
 	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_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 @@
 		return b2f0_result;
 	}
 
-	add_pathid_result = iucv_add_pathid(parm->ippathid, h);
 	*pathid = parm->ippathid;
 
 	/* Enable everything again */
@@ -1884,6 +1901,7 @@
 {
 	iparml_dpl *parm;
 	ulong b2f0_result;
+	iucv_param save_param;
 
 	iucv_debug(2, "entering");
 
@@ -1896,7 +1914,13 @@
 	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_debug(2,
 						   "found a matching handler");
 					break;
-				}
+				} else
+					h = NULL;
 			}
 			spin_unlock_irqrestore (&iucv_lock, flags);
 			if (h) {
diff -Nru a/drivers/s390/net/netiucv.c b/drivers/s390/net/netiucv.c
--- a/drivers/s390/net/netiucv.c	2004-07-30 06:29:39 -07:00
+++ b/drivers/s390/net/netiucv.c	2004-08-18 09:09:02 -07:00
@@ -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 @@
 	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 @@
 	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 @@
 	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->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 @@
 #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 @@
 		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 @@
 		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 @@
 		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 @@
 #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 @@
 }
 
 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 @@
 	// 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 @@
 {
 	iucv_event *ev = (iucv_event *)arg;
 	iucv_connection *conn = ev->conn;
-
+	__u16 msglimit;
 	int rc;
 
 #ifdef DEBUG
@@ -839,10 +838,13 @@
 
 	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 @@
 #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 @@
 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 @@
 	{ 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 @@
 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 @@
 		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 @@
 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 @@
 	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 @@
 
 	{ 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 @@
 				       "%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 @@
 		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 @@
 			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 @@
 	 */
 	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 @@
 
 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 @@
 
 	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 @@
 	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 @@
 
 	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 @@
 
 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 @@
 
 	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 @@
 }
 
 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 @@
 
 	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 @@
 }
 
 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 @@
 }
 
 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 @@
 
 	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 @@
 	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 @@
 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 -Nru a/drivers/s390/net/qeth.c b/drivers/s390/net/qeth.c
--- a/drivers/s390/net/qeth.c	2004-07-30 06:29:39 -07:00
+++ b/drivers/s390/net/qeth.c	2004-08-18 09:09:02 -07:00
@@ -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 @@
 #include <asm/irq.h>
 #include <asm/s390dyn.h>
 #include <asm/debug.h>
+#include <asm/processor.h>
 
 #include <asm/qdio.h>
 
@@ -171,7 +169,7 @@
 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 @@
 
 /******************** 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 @@
 /* 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 @@
 		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 @@
 	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 @@
 #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_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 @@
 	} 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 @@
 	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 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 @@
 	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 @@
 		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 @@
 	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_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_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 @@
 			} 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 @@
 			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 @@
 				   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 @@
 
 #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 @@
 			    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 @@
 #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 @@
 	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 @@
 	 * 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 @@
 		 * 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 @@
 	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 @@
 			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 @@
 	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 @@
 }
 #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 @@
 
 
 
-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 @@
 		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 @@
 
 /* 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 @@
 	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 @@
         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 @@
 
 	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 @@
 		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 @@
 	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 @@
 	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 @@
 		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 @@
 		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_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 @@
 	}
 	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 @@
 		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 @@
 		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 @@
 		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 @@
 			  (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 @@
 		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 @@
      					      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 @@
 					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 @@
 					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 @@
 			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 @@
 }
 #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 @@
 
 	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 @@
 
 	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 @@
 			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 @@
 		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 @@
 					   "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 @@
 					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 @@
 				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 @@
 				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 @@
 				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 @@
 
 #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 @@
 	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_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 @@
 	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 @@
 			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 @@
 			      (&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 @@
 				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 @@
                 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 @@
 	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_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 @@
 	*((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 @@
 			     card->no_queues);
 	if (!output_array) {
 		vfree(input_array);
+		vfree(adapter_area);
 		return -ENOMEM;
 	}
 	ptr=output_array;
@@ -7285,6 +7568,7 @@
 	
 	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 @@
 	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 @@
 		(!(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 @@
 	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 @@
 	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 @@
 		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 @@
 			       "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 @@
 						       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 @@
 			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 @@
 			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 @@
 	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 @@
 	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 @@
 	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 @@
 	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 @@
 		goto endloop;
 	}
 	
-	qeth_correct_routing_status(card);
 	qeth_insert_card_into_list(card);
 	
 	QETH_DBF_TEXT3(0,trace,"request0");
@@ -9247,7 +9559,7 @@
 			/* 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 @@
 	card->tqueue_sst.sync=0;
 	schedule_task(&card->tqueue_sst);
  out:
-	qeth_wakeup_procfile();
+	qeth_snmp_notify();
 	return dev;
 
 }
@@ -9385,11 +9697,10 @@
 	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 @@
 	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 @@
 
 	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 @@
 	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 @@
 		PRINT_WARN("No memory available for data\n");
 		vfree (info);
 		rc=-ENOMEM;
+		MOD_DEC_USE_COUNT;
 		goto out;
 	}
 	
@@ -9583,23 +9951,23 @@
 			       "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 @@
 		      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 @@
 		      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 @@
 					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 @@
 					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 @@
 					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 @@
 	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 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 @@
 	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 @@
 {
 
      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 @@
 					 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 @@
 	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 -Nru a/drivers/s390/net/qeth.h b/drivers/s390/net/qeth.h
--- a/drivers/s390/net/qeth.h	2003-07-07 08:03:56 -07:00
+++ b/drivers/s390/net/qeth.h	2004-08-18 09:09:02 -07:00
@@ -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 @@
 #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 @@
 #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 @@
 #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 @@
 
 	__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 @@
 	/* 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 @@
 	__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 @@
 	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 @@
 				  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 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 @@
      					  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 -Nru a/drivers/s390/net/qeth_mpc.h b/drivers/s390/net/qeth_mpc.h
--- a/drivers/s390/net/qeth_mpc.h	2003-07-07 08:03:56 -07:00
+++ b/drivers/s390/net/qeth_mpc.h	2004-08-18 09:09:02 -07:00
@@ -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 @@
 #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 @@
 #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 @@
 } 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 -Nru a/drivers/s390/qdio.c b/drivers/s390/qdio.c
--- a/drivers/s390/qdio.c	2003-07-07 08:05:42 -07:00
+++ b/drivers/s390/qdio.c	2004-08-18 09:09:02 -07:00
@@ -57,7 +57,7 @@
 
 #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 @@
 #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 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 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 @@
 
 	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 @@
 		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 @@
 		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 @@
 	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 @@
 			q->list_next=NULL;
 			q->list_prev=NULL;
 		}
+out:
 		spin_unlock_irqrestore(&ttiq_list_lock,flags);
 	}
 }
@@ -710,7 +724,7 @@
 		       (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 @@
 	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 @@
 		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 @@
 }
 
 /* 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 @@
 	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 @@
 	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 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 @@
 
 	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_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 @@
 	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 @@
 	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 @@
 
 	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 @@
 	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 @@
 		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 @@
 		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 @@
 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 @@
 	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 @@
 }
 
 /* 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 @@
 	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 @@
 
 	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 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 @@
 #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 @@
 		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 @@
 		}
 
 		/* 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 @@
 				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 @@
 	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 @@
 	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 @@
 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 @@
 		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 @@
 			((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 @@
 		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 @@
 	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 @@
 #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 @@
 					if (!irq_ptr->sync_done_on_outb_pcis) {
 						SYNC_MEMORY;
 					}
-					qdio_outbound_processing(q);
+					__qdio_outbound_processing(q);
 				}
 			}
 		}
@@ -2206,6 +2347,9 @@
 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 @@
 		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 @@
 		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 @@
 	    ) {
 		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 @@
 
 	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 @@
 	 * 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 @@
 		goto exit;
 	}
 exit:
+	spin_unlock_irqrestore(&chsc_area_lock,flags);
 	return result;
 }
 
@@ -2337,6 +2507,7 @@
 	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 @@
 			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 @@
 	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 @@
 		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 @@
 	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 @@
 	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 @@
 	}
 	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 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 @@
 	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 @@
 	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 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 @@
 
 	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 @@
 
 	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 @@
 		}
 		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 @@
 	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 @@
 		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 @@
 			       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 @@
 			       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 @@
 
 	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 @@
 	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 @@
 	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 @@
 					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 @@
 				 * 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 @@
 		 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,9 +3760,11 @@
 
 	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 -Nru a/drivers/s390/s390io.c b/drivers/s390/s390io.c
--- a/drivers/s390/s390io.c	2004-07-30 06:29:39 -07:00
+++ b/drivers/s390/s390io.c	2004-08-18 09:08:54 -07:00
@@ -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 @@
 		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 -Nru a/drivers/scsi/AM53C974.c b/drivers/scsi/AM53C974.c
--- a/drivers/scsi/AM53C974.c	2002-02-04 23:49:26 -08:00
+++ b/drivers/scsi/AM53C974.c	2004-08-16 14:47:29 -07:00
@@ -1027,6 +1027,78 @@
 	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 @@
 	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, *
@@ -2154,37 +2185,6 @@
 	AM53C974_write_8(CMDREG, CMDREG_MA);
 	hostdata->dma_busy = 0;
 	hostdata->connected->SCp.phase = PHASE_CMDOUT;
-}
-
-/************************************************************************** 
-* 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);
 }
 
 /************************************************************************** 
diff -Nru a/drivers/scsi/aic7xxx/aic79xx_osm.c b/drivers/scsi/aic7xxx/aic79xx_osm.c
--- a/drivers/scsi/aic7xxx/aic79xx_osm.c	2003-05-23 12:24:11 -07:00
+++ b/drivers/scsi/aic7xxx/aic79xx_osm.c	2004-08-16 16:02:23 -07:00
@@ -2931,6 +2931,19 @@
 	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,
@@ -3565,19 +3578,6 @@
 	cmd->cmd_len = 6;
 	cmd->cmnd[0] = START_STOP_UNIT;
 	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
diff -Nru a/drivers/scsi/ata_piix.c b/drivers/scsi/ata_piix.c
--- a/drivers/scsi/ata_piix.c	2004-07-10 09:49:35 -07:00
+++ b/drivers/scsi/ata_piix.c	2004-08-14 12:38:51 -07:00
@@ -2,6 +2,10 @@
 
     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
@@ -102,6 +106,7 @@
 	.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,
diff -Nru a/drivers/scsi/ips.c b/drivers/scsi/ips.c
--- a/drivers/scsi/ips.c	2004-03-23 08:08:02 -08:00
+++ b/drivers/scsi/ips.c	2004-08-16 14:09:52 -07:00
@@ -802,6 +802,168 @@
 
 /****************************************************************************/
 /*                                                                          */
+/* Routine Name: ips_removeq_copp_head                                      */
+/*                                                                          */
+/* Routine Description:                                                     */
+/*                                                                          */
+/*   Remove the head of the queue                                           */
+/*                                                                          */
+/* ASSUMED to be called from within the HA lock                             */
+/*                                                                          */
+/****************************************************************************/
+static inline ips_copp_wait_item_t *
+ips_removeq_copp_head(ips_copp_queue_t * queue)
+{
+	ips_copp_wait_item_t *item;
+
+	METHOD_TRACE("ips_removeq_copp_head", 1);
+
+	item = queue->head;
+
+	if (!item) {
+		return (NULL);
+	}
+
+	queue->head = item->next;
+	item->next = NULL;
+
+	if (queue->tail == item)
+		queue->tail = NULL;
+
+	queue->count--;
+
+	return (item);
+}
+
+/****************************************************************************/
+/*                                                                          */
+/* Routine Name: ips_removeq_copp                                           */
+/*                                                                          */
+/* Routine Description:                                                     */
+/*                                                                          */
+/*   Remove an item from a queue                                            */
+/*                                                                          */
+/* ASSUMED to be called from within the HA lock                             */
+/*                                                                          */
+/****************************************************************************/
+static inline 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;
+
+	METHOD_TRACE("ips_removeq_copp", 1);
+
+	if (!item)
+		return (NULL);
+
+	if (item == queue->head) {
+		return (ips_removeq_copp_head(queue));
+	}
+
+	p = queue->head;
+
+	while ((p) && (item != p->next))
+		p = p->next;
+
+	if (p) {
+		/* found a match */
+		p->next = item->next;
+
+		if (!item->next)
+			queue->tail = p;
+
+		item->next = NULL;
+		queue->count--;
+
+		return (item);
+	}
+
+	return (NULL);
+}
+
+/****************************************************************************/
+/*                                                                          */
+/* Routine Name: ips_removeq_wait_head                                      */
+/*                                                                          */
+/* Routine Description:                                                     */
+/*                                                                          */
+/*   Remove the head of the queue                                           */
+/*                                                                          */
+/* ASSUMED to be called from within the HA lock                             */
+/*                                                                          */
+/****************************************************************************/
+static inline Scsi_Cmnd *
+ips_removeq_wait_head(ips_wait_queue_t * queue)
+{
+	Scsi_Cmnd *item;
+
+	METHOD_TRACE("ips_removeq_wait_head", 1);
+
+	item = queue->head;
+
+	if (!item) {
+		return (NULL);
+	}
+
+	queue->head = (Scsi_Cmnd *) item->host_scribble;
+	item->host_scribble = NULL;
+
+	if (queue->tail == item)
+		queue->tail = NULL;
+
+	queue->count--;
+
+	return (item);
+}
+
+/****************************************************************************/
+/*                                                                          */
+/* Routine Name: ips_removeq_wait                                           */
+/*                                                                          */
+/* Routine Description:                                                     */
+/*                                                                          */
+/*   Remove an item from a queue                                            */
+/*                                                                          */
+/* ASSUMED to be called from within the HA lock                             */
+/*                                                                          */
+/****************************************************************************/
+static inline Scsi_Cmnd *
+ips_removeq_wait(ips_wait_queue_t * queue, Scsi_Cmnd * item)
+{
+	Scsi_Cmnd *p;
+
+	METHOD_TRACE("ips_removeq_wait", 1);
+
+	if (!item)
+		return (NULL);
+
+	if (item == queue->head) {
+		return (ips_removeq_wait_head(queue));
+	}
+
+	p = queue->head;
+
+	while ((p) && (item != (Scsi_Cmnd *) p->host_scribble))
+		p = (Scsi_Cmnd *) p->host_scribble;
+
+	if (p) {
+		/* found a match */
+		p->host_scribble = item->host_scribble;
+
+		if (!item->host_scribble)
+			queue->tail = p;
+
+		item->host_scribble = NULL;
+		queue->count--;
+
+		return (item);
+	}
+
+	return (NULL);
+}
+
+/****************************************************************************/
+/*                                                                          */
 /* Routine Name: ips_eh_abort                                               */
 /*                                                                          */
 /* Routine Description:                                                     */
@@ -859,6 +1021,87 @@
 
 /****************************************************************************/
 /*                                                                          */
+/* Routine Name: ips_removeq_scb_head                                       */
+/*                                                                          */
+/* Routine Description:                                                     */
+/*                                                                          */
+/*   Remove the head of the queue                                           */
+/*                                                                          */
+/* ASSUMED to be called from within the HA lock                             */
+/*                                                                          */
+/****************************************************************************/
+static inline ips_scb_t *
+ips_removeq_scb_head(ips_scb_queue_t * queue)
+{
+	ips_scb_t *item;
+
+	METHOD_TRACE("ips_removeq_scb_head", 1);
+
+	item = queue->head;
+
+	if (!item) {
+		return (NULL);
+	}
+
+	queue->head = item->q_next;
+	item->q_next = NULL;
+
+	if (queue->tail == item)
+		queue->tail = NULL;
+
+	queue->count--;
+
+	return (item);
+}
+
+/****************************************************************************/
+/*                                                                          */
+/* Routine Name: ips_removeq_scb                                            */
+/*                                                                          */
+/* Routine Description:                                                     */
+/*                                                                          */
+/*   Remove an item from a queue                                            */
+/*                                                                          */
+/* ASSUMED to be called from within the HA lock                             */
+/*                                                                          */
+/****************************************************************************/
+static inline ips_scb_t *
+ips_removeq_scb(ips_scb_queue_t * queue, ips_scb_t * item)
+{
+	ips_scb_t *p;
+
+	METHOD_TRACE("ips_removeq_scb", 1);
+
+	if (!item)
+		return (NULL);
+
+	if (item == queue->head) {
+		return (ips_removeq_scb_head(queue));
+	}
+
+	p = queue->head;
+
+	while ((p) && (item != p->q_next))
+		p = p->q_next;
+
+	if (p) {
+		/* found a match */
+		p->q_next = item->q_next;
+
+		if (!item->q_next)
+			queue->tail = p;
+
+		item->q_next = NULL;
+		queue->count--;
+
+		return (item);
+	}
+
+	return (NULL);
+}
+
+/****************************************************************************/
+/*                                                                          */
 /* Routine Name: ips_eh_reset                                               */
 /*                                                                          */
 /* Routine Description:                                                     */
@@ -1058,6 +1301,70 @@
 
 /****************************************************************************/
 /*                                                                          */
+/* Routine Name: ips_putq_copp_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_copp_tail(ips_copp_queue_t * queue, ips_copp_wait_item_t * item)
+{
+	METHOD_TRACE("ips_putq_copp_tail", 1);
+
+	if (!item)
+		return;
+
+	item->next = NULL;
+
+	if (queue->tail)
+		queue->tail->next = item;
+
+	queue->tail = item;
+
+	if (!queue->head)
+		queue->head = item;
+
+	queue->count++;
+}
+
+/****************************************************************************/
+/*                                                                          */
+/* Routine Name: ips_putq_wait_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_wait_tail(ips_wait_queue_t * queue, Scsi_Cmnd * item)
+{
+	METHOD_TRACE("ips_putq_wait_tail", 1);
+
+	if (!item)
+		return;
+
+	item->host_scribble = NULL;
+
+	if (queue->tail)
+		queue->tail->host_scribble = (char *) item;
+
+	queue->tail = item;
+
+	if (!queue->head)
+		queue->head = item;
+
+	queue->count++;
+}
+
+/****************************************************************************/
+/*                                                                          */
 /* Routine Name: ips_queue                                                  */
 /*                                                                          */
 /* Routine Description:                                                     */
@@ -2693,6 +3000,66 @@
 
 /****************************************************************************/
 /*                                                                          */
+/* Routine Name: ips_putq_scb_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_scb_head(ips_scb_queue_t * queue, ips_scb_t * item)
+{
+	METHOD_TRACE("ips_putq_scb_head", 1);
+
+	if (!item)
+		return;
+
+	item->q_next = queue->head;
+	queue->head = item;
+
+	if (!queue->tail)
+		queue->tail = item;
+
+	queue->count++;
+}
+
+/****************************************************************************/
+/*                                                                          */
+/* 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_next                                                   */
 /*                                                                          */
 /* Routine Description:                                                     */
@@ -2944,147 +3311,6 @@
 
 /****************************************************************************/
 /*                                                                          */
-/* Routine Name: ips_putq_scb_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_scb_head(ips_scb_queue_t * queue, ips_scb_t * item)
-{
-	METHOD_TRACE("ips_putq_scb_head", 1);
-
-	if (!item)
-		return;
-
-	item->q_next = queue->head;
-	queue->head = item;
-
-	if (!queue->tail)
-		queue->tail = item;
-
-	queue->count++;
-}
-
-/****************************************************************************/
-/*                                                                          */
-/* 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:                                                     */
-/*                                                                          */
-/*   Remove the head of the queue                                           */
-/*                                                                          */
-/* ASSUMED to be called from within the HA lock                             */
-/*                                                                          */
-/****************************************************************************/
-static inline ips_scb_t *
-ips_removeq_scb_head(ips_scb_queue_t * queue)
-{
-	ips_scb_t *item;
-
-	METHOD_TRACE("ips_removeq_scb_head", 1);
-
-	item = queue->head;
-
-	if (!item) {
-		return (NULL);
-	}
-
-	queue->head = item->q_next;
-	item->q_next = NULL;
-
-	if (queue->tail == item)
-		queue->tail = NULL;
-
-	queue->count--;
-
-	return (item);
-}
-
-/****************************************************************************/
-/*                                                                          */
-/* Routine Name: ips_removeq_scb                                            */
-/*                                                                          */
-/* Routine Description:                                                     */
-/*                                                                          */
-/*   Remove an item from a queue                                            */
-/*                                                                          */
-/* ASSUMED to be called from within the HA lock                             */
-/*                                                                          */
-/****************************************************************************/
-static inline ips_scb_t *
-ips_removeq_scb(ips_scb_queue_t * queue, ips_scb_t * item)
-{
-	ips_scb_t *p;
-
-	METHOD_TRACE("ips_removeq_scb", 1);
-
-	if (!item)
-		return (NULL);
-
-	if (item == queue->head) {
-		return (ips_removeq_scb_head(queue));
-	}
-
-	p = queue->head;
-
-	while ((p) && (item != p->q_next))
-		p = p->q_next;
-
-	if (p) {
-		/* found a match */
-		p->q_next = item->q_next;
-
-		if (!item->q_next)
-			queue->tail = p;
-
-		item->q_next = NULL;
-		queue->count--;
-
-		return (item);
-	}
-
-	return (NULL);
-}
-
-/****************************************************************************/
-/*                                                                          */
 /* Routine Name: ips_putq_wait_head                                         */
 /*                                                                          */
 /* Routine Description:                                                     */
@@ -3113,119 +3339,6 @@
 
 /****************************************************************************/
 /*                                                                          */
-/* Routine Name: ips_putq_wait_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_wait_tail(ips_wait_queue_t * queue, Scsi_Cmnd * item)
-{
-	METHOD_TRACE("ips_putq_wait_tail", 1);
-
-	if (!item)
-		return;
-
-	item->host_scribble = NULL;
-
-	if (queue->tail)
-		queue->tail->host_scribble = (char *) item;
-
-	queue->tail = item;
-
-	if (!queue->head)
-		queue->head = item;
-
-	queue->count++;
-}
-
-/****************************************************************************/
-/*                                                                          */
-/* Routine Name: ips_removeq_wait_head                                      */
-/*                                                                          */
-/* Routine Description:                                                     */
-/*                                                                          */
-/*   Remove the head of the queue                                           */
-/*                                                                          */
-/* ASSUMED to be called from within the HA lock                             */
-/*                                                                          */
-/****************************************************************************/
-static inline Scsi_Cmnd *
-ips_removeq_wait_head(ips_wait_queue_t * queue)
-{
-	Scsi_Cmnd *item;
-
-	METHOD_TRACE("ips_removeq_wait_head", 1);
-
-	item = queue->head;
-
-	if (!item) {
-		return (NULL);
-	}
-
-	queue->head = (Scsi_Cmnd *) item->host_scribble;
-	item->host_scribble = NULL;
-
-	if (queue->tail == item)
-		queue->tail = NULL;
-
-	queue->count--;
-
-	return (item);
-}
-
-/****************************************************************************/
-/*                                                                          */
-/* Routine Name: ips_removeq_wait                                           */
-/*                                                                          */
-/* Routine Description:                                                     */
-/*                                                                          */
-/*   Remove an item from a queue                                            */
-/*                                                                          */
-/* ASSUMED to be called from within the HA lock                             */
-/*                                                                          */
-/****************************************************************************/
-static inline Scsi_Cmnd *
-ips_removeq_wait(ips_wait_queue_t * queue, Scsi_Cmnd * item)
-{
-	Scsi_Cmnd *p;
-
-	METHOD_TRACE("ips_removeq_wait", 1);
-
-	if (!item)
-		return (NULL);
-
-	if (item == queue->head) {
-		return (ips_removeq_wait_head(queue));
-	}
-
-	p = queue->head;
-
-	while ((p) && (item != (Scsi_Cmnd *) p->host_scribble))
-		p = (Scsi_Cmnd *) p->host_scribble;
-
-	if (p) {
-		/* found a match */
-		p->host_scribble = item->host_scribble;
-
-		if (!item->host_scribble)
-			queue->tail = p;
-
-		item->host_scribble = NULL;
-		queue->count--;
-
-		return (item);
-	}
-
-	return (NULL);
-}
-
-/****************************************************************************/
-/*                                                                          */
 /* Routine Name: ips_putq_copp_head                                         */
 /*                                                                          */
 /* Routine Description:                                                     */
@@ -3250,119 +3363,6 @@
 		queue->tail = item;
 
 	queue->count++;
-}
-
-/****************************************************************************/
-/*                                                                          */
-/* Routine Name: ips_putq_copp_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_copp_tail(ips_copp_queue_t * queue, ips_copp_wait_item_t * item)
-{
-	METHOD_TRACE("ips_putq_copp_tail", 1);
-
-	if (!item)
-		return;
-
-	item->next = NULL;
-
-	if (queue->tail)
-		queue->tail->next = item;
-
-	queue->tail = item;
-
-	if (!queue->head)
-		queue->head = item;
-
-	queue->count++;
-}
-
-/****************************************************************************/
-/*                                                                          */
-/* Routine Name: ips_removeq_copp_head                                      */
-/*                                                                          */
-/* Routine Description:                                                     */
-/*                                                                          */
-/*   Remove the head of the queue                                           */
-/*                                                                          */
-/* ASSUMED to be called from within the HA lock                             */
-/*                                                                          */
-/****************************************************************************/
-static inline ips_copp_wait_item_t *
-ips_removeq_copp_head(ips_copp_queue_t * queue)
-{
-	ips_copp_wait_item_t *item;
-
-	METHOD_TRACE("ips_removeq_copp_head", 1);
-
-	item = queue->head;
-
-	if (!item) {
-		return (NULL);
-	}
-
-	queue->head = item->next;
-	item->next = NULL;
-
-	if (queue->tail == item)
-		queue->tail = NULL;
-
-	queue->count--;
-
-	return (item);
-}
-
-/****************************************************************************/
-/*                                                                          */
-/* Routine Name: ips_removeq_copp                                           */
-/*                                                                          */
-/* Routine Description:                                                     */
-/*                                                                          */
-/*   Remove an item from a queue                                            */
-/*                                                                          */
-/* ASSUMED to be called from within the HA lock                             */
-/*                                                                          */
-/****************************************************************************/
-static inline 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;
-
-	METHOD_TRACE("ips_removeq_copp", 1);
-
-	if (!item)
-		return (NULL);
-
-	if (item == queue->head) {
-		return (ips_removeq_copp_head(queue));
-	}
-
-	p = queue->head;
-
-	while ((p) && (item != p->next))
-		p = p->next;
-
-	if (p) {
-		/* found a match */
-		p->next = item->next;
-
-		if (!item->next)
-			queue->tail = p;
-
-		item->next = NULL;
-		queue->count--;
-
-		return (item);
-	}
-
-	return (NULL);
 }
 
 /****************************************************************************/
diff -Nru a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c
--- a/drivers/scsi/libata-core.c	2004-08-12 10:38:12 -07:00
+++ b/drivers/scsi/libata-core.c	2004-08-16 09:32:03 -07:00
@@ -42,6 +42,7 @@
 #include <linux/libata.h>
 #include <asm/io.h>
 #include <asm/semaphore.h>
+#include <asm/byteorder.h>
 
 #include "libata.h"
 
@@ -1054,6 +1055,8 @@
 		goto err_out;
 	}
 
+	swap_buf_le16(dev->id, ATA_ID_WORDS);
+
 	/* print device capabilities */
 	printk(KERN_DEBUG "ata%u: dev %u cfg "
 	       "49:%04x 82:%04x 83:%04x 84:%04x 85:%04x 86:%04x 87:%04x 88:%04x\n",
@@ -2082,6 +2085,16 @@
 	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)
 {
@@ -2092,22 +2105,22 @@
 
 	if (write_data) {
 		for (i = 0; i < words; i++)
-			writew(buf16[i], mmio);
+			writew(le16_to_cpu(buf16[i]), mmio);
 	} else {
 		for (i = 0; i < words; i++)
-			buf16[i] = readw(mmio);
+			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 >> 2;
+	unsigned int dwords = buflen >> 1;
 
 	if (write_data)
-		outsl(ap->ioaddr.data_addr, buf, dwords);
+		outsw(ap->ioaddr.data_addr, buf, dwords);
 	else
-		insl(ap->ioaddr.data_addr, buf, dwords);
+		insw(ap->ioaddr.data_addr, buf, dwords);
 }
 
 static void ata_data_xfer(struct ata_port *ap, unsigned char *buf,
@@ -2119,6 +2132,81 @@
 		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:
@@ -2126,14 +2214,10 @@
  *	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 page *page;
-	unsigned char *buf;
 	u8 status;
-	int do_write;
 
 	/*
 	 * This is purely hueristic.  This is a fast path.
@@ -2163,32 +2247,10 @@
 	qc = ata_qc_from_tag(ap, ap->active_tag);
 	assert(qc != NULL);
 
-	sg = qc->sg;
-
-	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);
+	if (is_atapi_taskfile(&qc->tf))
+		atapi_pio_sector(qc);
+	else
+		ata_pio_sector(qc);
 }
 
 static void ata_pio_error(struct ata_port *ap)
@@ -2217,7 +2279,7 @@
 
 	switch (ap->pio_task_state) {
 	case PIO_ST:
-		ata_pio_sector(ap);
+		ata_pio_block(ap);
 		break;
 
 	case PIO_ST_LAST:
@@ -2556,6 +2618,7 @@
 		break;
 
 	default:
+		WARN_ON(1);
 		return -1;
 	}
 
@@ -3528,6 +3591,7 @@
 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);
diff -Nru a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c
--- a/drivers/scsi/libata-scsi.c	2004-07-10 09:50:00 -07:00
+++ b/drivers/scsi/libata-scsi.c	2004-08-17 22:52:31 -07:00
@@ -31,6 +31,7 @@
 #include <scsi/scsi_host.h>
 #include "sd.h"
 #include <linux/libata.h>
+#include <asm/uaccess.h>
 
 #include "libata.h"
 
@@ -38,6 +39,8 @@
 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);
 
 
 /**
@@ -59,15 +62,52 @@
  */
 int ata_std_bios_param(Disk * disk,	/* SCSI disk */
 		       kdev_t dev,	/* Device major, minor */
-		  int *ip /* Heads, sectors, cylinders in that order */ )
+		  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 = (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 @@
  *	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 @@
 	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 @@
 	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;
 
@@ -300,7 +586,7 @@
 	struct scsi_cmnd *cmd = qc->scsicmd;
 
 	if (unlikely(drv_stat & (ATA_ERR | ATA_BUSY | ATA_DRQ)))
-		ata_to_sense_error(qc);
+		ata_to_sense_error(qc, drv_stat);
 	else
 		cmd->result = SAM_STAT_GOOD;
 
@@ -490,7 +776,7 @@
 		0,
 		0x5,	/* claim SPC-3 version compatibility */
 		2,
-		96 - 4
+		95 - 4
 	};
 
 	/* set scsi removeable (RMB) bit per ata bit */
@@ -501,7 +787,7 @@
 
 	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);
@@ -1018,19 +1304,19 @@
  *	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)))
@@ -1046,6 +1332,7 @@
 
 /**
  *	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
@@ -1055,7 +1342,7 @@
  *	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:
@@ -1066,6 +1353,15 @@
 	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;
@@ -1083,11 +1379,12 @@
 				     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]);
@@ -1117,17 +1414,18 @@
 {
 	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);
@@ -1135,7 +1433,8 @@
 	}
 
 	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);
@@ -1178,7 +1477,7 @@
 
 	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 -Nru a/drivers/scsi/libata.h b/drivers/scsi/libata.h
--- a/drivers/scsi/libata.h	2004-05-16 15:42:02 -07:00
+++ b/drivers/scsi/libata.h	2004-08-17 22:52:31 -07:00
@@ -35,7 +35,6 @@
 	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 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 -Nru a/drivers/scsi/megaraid.c b/drivers/scsi/megaraid.c
--- a/drivers/scsi/megaraid.c	2004-01-01 14:59:12 -08:00
+++ b/drivers/scsi/megaraid.c	2004-08-16 14:49:52 -07:00
@@ -3471,6 +3471,24 @@
 	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
  *---------------------------------------------------------------------*/
@@ -3878,24 +3896,6 @@
 		shtwo->next = save;
 	}
 	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
-	}
 }
 
 /*----------------------------------------------
diff -Nru a/drivers/scsi/megaraid2.c b/drivers/scsi/megaraid2.c
--- a/drivers/scsi/megaraid2.c	2004-04-08 22:48:27 -07:00
+++ b/drivers/scsi/megaraid2.c	2004-08-16 15:40:29 -07:00
@@ -936,6 +936,19 @@
 }
 
 
+/**
+ * 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 @@
 
 
 /**
+ * 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_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 @@
  * 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 @@
 }
 
 
+/*
+ * 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 @@
 
 
 /**
- * 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_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_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 @@
  *
  * 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 @@
 }
 
 
-/*
- * 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 @@
 }
 
 
+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 @@
 	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 @@
 }
 
 
+/**
+ * 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_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
@@ -5339,27 +5360,6 @@
 	}
 
 	return 0;
-}
-
-
-/**
- * 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);
 }
 
 
diff -Nru a/drivers/scsi/megaraid2.h b/drivers/scsi/megaraid2.h
--- a/drivers/scsi/megaraid2.h	2004-04-20 17:00:00 -07:00
+++ b/drivers/scsi/megaraid2.h	2004-08-16 15:28:04 -07:00
@@ -1091,14 +1091,12 @@
 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 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 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 @@
 		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 -Nru a/drivers/scsi/nsp32.c b/drivers/scsi/nsp32.c
--- a/drivers/scsi/nsp32.c	2003-09-25 23:36:03 -07:00
+++ b/drivers/scsi/nsp32.c	2004-08-16 15:46:27 -07:00
@@ -3365,6 +3365,48 @@
 	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 */
@@ -3409,49 +3451,6 @@
 
 	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 -Nru a/drivers/scsi/qla1280.c b/drivers/scsi/qla1280.c
--- a/drivers/scsi/qla1280.c	2003-10-03 09:29:32 -07:00
+++ b/drivers/scsi/qla1280.c	2004-08-16 14:13:42 -07:00
@@ -875,6 +875,41 @@
 }
 
 
+ /*
+    * 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,
@@ -2048,40 +2083,6 @@
 /****************************************************************************/
 /*                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
diff -Nru a/drivers/scsi/sata_nv.c b/drivers/scsi/sata_nv.c
--- a/drivers/scsi/sata_nv.c	2004-07-04 14:42:24 -07:00
+++ b/drivers/scsi/sata_nv.c	2004-08-18 17:50:30 -07:00
@@ -20,6 +20,11 @@
  *  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.02
+ *     - Added support for CK804 SATA controller.
+ *
+ *  0.01
+ *     - Initial revision.
  */
 
 #include <linux/config.h>
@@ -35,7 +40,7 @@
 #include <linux/libata.h>
 
 #define DRV_NAME			"sata_nv"
-#define DRV_VERSION			"0.01"
+#define DRV_VERSION			"0.02"
 
 #define NV_PORTS			2
 #define NV_PIO_MASK			0x1f
@@ -47,6 +52,7 @@
 #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
@@ -63,6 +69,7 @@
 					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
@@ -81,30 +88,86 @@
 #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, },
+		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, },
+		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, },
+		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, },
+		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, },
+		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, },
+		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, },
+		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,
@@ -117,6 +180,7 @@
 	.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,
@@ -160,11 +224,10 @@
 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;
-	u8 intr_status;
-	u8 intr_enable;
 
 	spin_lock_irqsave(&host_set->lock, flags);
 
@@ -180,35 +243,11 @@
 				handled += ata_host_intr(ap, qc);
 		}
 
-		intr_status = inb(ap->ioaddr.scr_addr + NV_INT_STATUS);
-		intr_enable = inb(ap->ioaddr.scr_addr + NV_INT_ENABLE);
-
-		// Clear interrupt status.
-		outb(0xff, ap->ioaddr.scr_addr + NV_INT_STATUS);
-
-		if (intr_status & NV_INT_STATUS_HOTPLUG) {
-			if (intr_status & NV_INT_STATUS_PDEV_ADDED) {
-				printk(KERN_WARNING "ata%u: "
-					"Primary device added\n", ap->id);
-			}
-
-			if (intr_status & NV_INT_STATUS_PDEV_REMOVED) {
-				printk(KERN_WARNING "ata%u: "
-					"Primary device removed\n", ap->id);
-			}
-
-			if (intr_status & NV_INT_STATUS_SDEV_ADDED) {
-				printk(KERN_WARNING "ata%u: "
-					"Secondary device added\n", ap->id);
-			}
-
-			if (intr_status & NV_INT_STATUS_SDEV_REMOVED) {
-				printk(KERN_WARNING "ata%u: "
-					"Secondary device removed\n", ap->id);
-			}
-		}
 	}
 
+	if (host->host_desc->check_hotplug)
+		host->host_desc->check_hotplug(host_set);
+
 	spin_unlock_irqrestore(&host_set->lock, flags);
 
 	return IRQ_RETVAL(handled);
@@ -216,41 +255,48 @@
 
 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;
 
-	return inl(ap->ioaddr.scr_addr + (sc_reg * 4));
+	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;
 
-	outl(val, ap->ioaddr.scr_addr + (sc_reg * 4));
+	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)
 {
-	int i;
+	struct nv_host *host = host_set->private_data;
 
-	for (i=0; i<host_set->n_ports; i++) {
-		u8 intr_mask;
+	// Disable hotplug event interrupts.
+	if (host->host_desc->disable_hotplug)
+		host->host_desc->disable_hotplug(host_set);
 
-		// Disable hotplug event interrupts.
-		intr_mask = inb(host_set->ports[i]->ioaddr.scr_addr +
-				NV_INT_ENABLE);
-		intr_mask &= ~(NV_INT_ENABLE_HOTPLUG);
-		outb(intr_mask, host_set->ports[i]->ioaddr.scr_addr +
-				NV_INT_ENABLE);
-	}
+	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 i;
 	int rc;
 
 	if (!printed_version++)
@@ -274,6 +320,14 @@
 		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);
 
@@ -283,6 +337,7 @@
 				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;
@@ -298,8 +353,6 @@
 		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[0].scr_addr =
-		pci_resource_start(pdev, 5) | NV_PORT0_SCR_REG_OFFSET;
 
 	probe_ent->port[1].cmd_addr = pci_resource_start(pdev, 2);
 	ata_std_ports(&probe_ent->port[1]);
@@ -308,33 +361,167 @@
 		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->port[1].scr_addr =
-		pci_resource_start(pdev, 5) | NV_PORT1_SCR_REG_OFFSET;
 
-	pci_set_master(pdev);
+	probe_ent->private_data = host;
 
-	// Enable hotplug event interrupts.
-	for (i=0; i<probe_ent->n_ports; i++) {
-		u8 intr_mask;
+	if (host->host_desc->host_flags & NV_HOST_FLAGS_SCR_MMIO) {
+		unsigned long base;
 
-		outb(NV_INT_STATUS_HOTPLUG, probe_ent->port[i].scr_addr +
-						NV_INT_STATUS);
-
-		intr_mask = inb(probe_ent->port[i].scr_addr + NV_INT_ENABLE);
-		intr_mask |= NV_INT_ENABLE_HOTPLUG;
-		outb(intr_mask, probe_ent->port[i].scr_addr + NV_INT_ENABLE);
+		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,
+		(unsigned long)probe_ent->mmio_base + NV_INT_STATUS);
+
+	intr_mask = inb((unsigned long)probe_ent->mmio_base + NV_INT_ENABLE);
+	intr_mask |= NV_INT_ENABLE_HOTPLUG;
+
+	outb(intr_mask, (unsigned long)probe_ent->mmio_base + NV_INT_ENABLE);
+}
+
+static void nv_disable_hotplug(struct ata_host_set *host_set)
+{
+	u8 intr_mask;
+
+	intr_mask = inb((unsigned long)host_set->mmio_base + NV_INT_ENABLE);
+
+	intr_mask &= ~(NV_INT_ENABLE_HOTPLUG);
+
+	outb(intr_mask, (unsigned long)host_set->mmio_base + NV_INT_ENABLE);
+}
+
+static void nv_check_hotplug(struct ata_host_set *host_set)
+{
+	u8 intr_status;
+
+	intr_status = inb((unsigned long)host_set->mmio_base + NV_INT_STATUS);
+
+	// Clear interrupt status.
+	outb(0xff, (unsigned long)host_set->mmio_base + 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)
diff -Nru a/drivers/scsi/sata_promise.c b/drivers/scsi/sata_promise.c
--- a/drivers/scsi/sata_promise.c	2004-07-07 16:45:30 -07:00
+++ b/drivers/scsi/sata_promise.c	2004-08-14 12:38:51 -07:00
@@ -91,6 +91,7 @@
 	.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,
diff -Nru a/drivers/scsi/sata_sil.c b/drivers/scsi/sata_sil.c
--- a/drivers/scsi/sata_sil.c	2004-07-04 14:42:24 -07:00
+++ b/drivers/scsi/sata_sil.c	2004-08-14 12:38:51 -07:00
@@ -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
@@ -108,6 +108,7 @@
 	.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,
diff -Nru a/drivers/scsi/sata_sis.c b/drivers/scsi/sata_sis.c
--- a/drivers/scsi/sata_sis.c	2004-07-04 14:42:24 -07:00
+++ b/drivers/scsi/sata_sis.c	2004-08-14 12:38:51 -07:00
@@ -78,6 +78,7 @@
 	.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,
diff -Nru a/drivers/scsi/sata_svw.c b/drivers/scsi/sata_svw.c
--- a/drivers/scsi/sata_svw.c	2004-07-04 14:42:24 -07:00
+++ b/drivers/scsi/sata_svw.c	2004-08-14 12:38:51 -07:00
@@ -207,6 +207,7 @@
 	.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,
diff -Nru a/drivers/scsi/sata_sx4.c b/drivers/scsi/sata_sx4.c
--- a/drivers/scsi/sata_sx4.c	2004-07-07 16:38:58 -07:00
+++ b/drivers/scsi/sata_sx4.c	2004-08-14 12:38:51 -07:00
@@ -176,6 +176,7 @@
 	.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,
diff -Nru a/drivers/scsi/sata_via.c b/drivers/scsi/sata_via.c
--- a/drivers/scsi/sata_via.c	2004-07-04 14:42:24 -07:00
+++ b/drivers/scsi/sata_via.c	2004-08-14 12:38:51 -07:00
@@ -83,6 +83,7 @@
 	.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,
diff -Nru a/drivers/scsi/sata_vsc.c b/drivers/scsi/sata_vsc.c
--- a/drivers/scsi/sata_vsc.c	2004-07-04 14:42:24 -07:00
+++ b/drivers/scsi/sata_vsc.c	2004-08-14 12:38:51 -07:00
@@ -192,6 +192,7 @@
 	.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,
diff -Nru a/drivers/scsi/scsi_merge.c b/drivers/scsi/scsi_merge.c
--- a/drivers/scsi/scsi_merge.c	2002-11-18 05:04:41 -08:00
+++ b/drivers/scsi/scsi_merge.c	2004-08-16 11:24:30 -07:00
@@ -418,7 +418,7 @@
 		return 0;
 
 	if (!BH_PHYS_4G(req->bhtail, bh))
-		return 0;
+		goto new_end_segment;
 
 	if (use_clustering) {
 		/* 
@@ -477,7 +477,7 @@
 		return 0;
 
 	if (!BH_PHYS_4G(bh, req->bh))
-		return 0;
+		goto new_start_segment;
 
 	if (use_clustering) {
 		/* 
@@ -640,7 +640,7 @@
 		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 -Nru a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
--- a/drivers/scsi/scsi_scan.c	2004-08-13 12:00:25 -07:00
+++ b/drivers/scsi/scsi_scan.c	2004-08-12 15:33:36 -07:00
@@ -190,6 +190,7 @@
 	{"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},
diff -Nru a/drivers/scsi/scsiiom.c b/drivers/scsi/scsiiom.c
--- a/drivers/scsi/scsiiom.c	2002-02-05 09:40:08 -08:00
+++ b/drivers/scsi/scsiiom.c	2004-08-16 14:29:30 -07:00
@@ -211,6 +211,24 @@
 };
 #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 @@
 };
 #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 @@
   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 @@
 };
 
 
+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 )
 {
@@ -1736,55 +1784,5 @@
 	dc390_Waiting_process( 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 -Nru a/drivers/scsi/sg.c b/drivers/scsi/sg.c
--- a/drivers/scsi/sg.c	2003-11-08 01:11:00 -08:00
+++ b/drivers/scsi/sg.c	2004-08-15 19:28:55 -07:00
@@ -742,6 +742,16 @@
     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 @@
     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 @@
     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 @@
         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)
@@ -2636,16 +2646,6 @@
     else
 	return ((int)msecs < (INT_MAX / 1000)) ? (((int)msecs * HZ) / 1000)
 					       : (((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,
diff -Nru a/drivers/scsi/sim710.c b/drivers/scsi/sim710.c
--- a/drivers/scsi/sim710.c	2002-06-25 02:12:38 -07:00
+++ b/drivers/scsi/sim710.c	2004-08-16 13:55:56 -07:00
@@ -921,172 +921,6 @@
 }
 
 
-/* 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)
 {
@@ -1281,6 +1115,172 @@
 	    restore_flags (flags);
     } while (!done);
     process_issue_queue_running = 0;
+}
+
+
+/* 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);
+    }
 }
 
 
diff -Nru a/drivers/usb/host/hc_sl811.c b/drivers/usb/host/hc_sl811.c
--- a/drivers/usb/host/hc_sl811.c	2003-10-06 04:21:21 -07:00
+++ b/drivers/usb/host/hc_sl811.c	2004-08-16 17:12:01 -07:00
@@ -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>
 
@@ -600,6 +597,9 @@
 
 	return 0;
 }
+
+#include "hc_simple.c"
+#include "hc_sl811_rh.c"
 
 /************************************************************************
  * Function Name : hc_start_int
diff -Nru a/drivers/usb/kaweth.c b/drivers/usb/kaweth.c
--- a/drivers/usb/kaweth.c	2003-06-18 09:46:17 -07:00
+++ b/drivers/usb/kaweth.c	2004-08-07 04:18:04 -07:00
@@ -735,7 +735,7 @@
 		}
 	}
 
-	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 -Nru a/drivers/usb/ov511.c b/drivers/usb/ov511.c
--- a/drivers/usb/ov511.c	2003-01-01 17:47:18 -08:00
+++ b/drivers/usb/ov511.c	2004-08-16 16:20:02 -07:00
@@ -334,8 +334,8 @@
  **********************************************************************/
 
 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 @@
 	return 0;
 }
 
-static inline int
+static int
 sensor_get_picture(struct usb_ov511 *ov, struct video_picture *p)
 {
 	int rc;
diff -Nru a/drivers/usb/se401.c b/drivers/usb/se401.c
--- a/drivers/usb/se401.c	2002-08-20 14:55:36 -07:00
+++ b/drivers/usb/se401.c	2004-08-16 16:56:42 -07:00
@@ -986,6 +986,44 @@
 	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);
+}
+
 
 /****************************************************************************
  *
@@ -1529,44 +1567,6 @@
 		se401->removed = 1;
 	}
 	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 = {
diff -Nru a/drivers/usb/w9968cf.c b/drivers/usb/w9968cf.c
--- a/drivers/usb/w9968cf.c	2004-04-09 17:31:45 -07:00
+++ b/drivers/usb/w9968cf.c	2004-08-16 16:44:58 -07:00
@@ -446,8 +446,8 @@
 /* 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_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 @@
   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 @@
 }
 
 
-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 -Nru a/drivers/video/pm3fb.c b/drivers/video/pm3fb.c
--- a/drivers/video/pm3fb.c	2004-02-26 02:19:23 -08:00
+++ b/drivers/video/pm3fb.c	2004-08-07 04:09:39 -07:00
@@ -3838,11 +3838,9 @@
 				    (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 -Nru a/drivers/video/riva/fbdev.c b/drivers/video/riva/fbdev.c
--- a/drivers/video/riva/fbdev.c	2004-08-07 04:09:39 -07:00
+++ b/drivers/video/riva/fbdev.c	2004-08-16 17:19:14 -07:00
@@ -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);
 
 
 
diff -Nru a/fs/Config.in b/fs/Config.in
--- a/fs/Config.in	2004-01-24 06:57:41 -08:00
+++ b/fs/Config.in	2004-08-15 16:53:43 -07:00
@@ -121,7 +121,7 @@
 
    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 -Nru a/fs/buffer.c b/fs/buffer.c
--- a/fs/buffer.c	2004-08-08 01:58:48 -07:00
+++ b/fs/buffer.c	2004-08-15 19:28:55 -07:00
@@ -1122,7 +1122,7 @@
 }
 EXPORT_SYMBOL(set_buffer_flushtime);
 
-inline int get_buffer_flushtime(void)
+int get_buffer_flushtime(void)
 {
 	return bdf_prm.b_un.interval;
 }
diff -Nru a/fs/nfsd/nfs3xdr.c b/fs/nfsd/nfs3xdr.c
--- a/fs/nfsd/nfs3xdr.c	2003-01-02 15:31:12 -08:00
+++ b/fs/nfsd/nfs3xdr.c	2004-08-13 20:23:06 -07:00
@@ -273,7 +273,7 @@
 {
 	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 -Nru a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
--- a/fs/nfsd/vfs.c	2003-09-03 18:46:11 -07:00
+++ b/fs/nfsd/vfs.c	2004-08-15 16:54:28 -07:00
@@ -586,6 +586,22 @@
 	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 @@
 		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 @@
 	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 @@
 	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 @@
 	/* 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 -Nru a/fs/partitions/ibm.c b/fs/partitions/ibm.c
--- a/fs/partitions/ibm.c	2002-04-24 06:23:09 -07:00
+++ b/fs/partitions/ibm.c	2004-08-18 09:08:59 -07:00
@@ -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 @@
 		/*
 		 * 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 @@
 		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 -Nru a/include/asm-i386/apic.h b/include/asm-i386/apic.h
--- a/include/asm-i386/apic.h	2002-04-04 16:21:36 -08:00
+++ b/include/asm-i386/apic.h	2004-08-15 19:28:55 -07:00
@@ -77,7 +77,7 @@
 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 -Nru a/include/asm-s390/kmap_types.h b/include/asm-s390/kmap_types.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-s390/kmap_types.h	2004-08-18 09:08:54 -07:00
@@ -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 -Nru a/include/asm-s390/lowcore.h b/include/asm-s390/lowcore.h
--- a/include/asm-s390/lowcore.h	2002-03-11 06:13:30 -08:00
+++ b/include/asm-s390/lowcore.h	2004-08-18 09:09:00 -07:00
@@ -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 @@
 
         /* 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 -Nru a/include/asm-s390/pgtable.h b/include/asm-s390/pgtable.h
--- a/include/asm-s390/pgtable.h	2003-06-27 04:38:55 -07:00
+++ b/include/asm-s390/pgtable.h	2004-08-18 09:08:54 -07:00
@@ -426,9 +426,12 @@
 	__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 -Nru a/include/asm-s390/processor.h b/include/asm-s390/processor.h
--- a/include/asm-s390/processor.h	2003-03-19 09:54:55 -08:00
+++ b/include/asm-s390/processor.h	2004-08-18 09:08:54 -07:00
@@ -50,6 +50,8 @@
 
 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 -Nru a/include/asm-s390/qdio.h b/include/asm-s390/qdio.h
--- a/include/asm-s390/qdio.h	2003-07-07 08:05:42 -07:00
+++ b/include/asm-s390/qdio.h	2004-08-18 09:09:02 -07:00
@@ -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 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 @@
 		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 @@
 	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 -Nru a/include/asm-s390/sigp.h b/include/asm-s390/sigp.h
--- a/include/asm-s390/sigp.h	2002-07-30 04:27:40 -07:00
+++ b/include/asm-s390/sigp.h	2004-08-18 09:08:54 -07:00
@@ -106,7 +106,7 @@
  * 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 -Nru a/include/asm-s390/smp.h b/include/asm-s390/smp.h
--- a/include/asm-s390/smp.h	2002-07-30 04:27:40 -07:00
+++ b/include/asm-s390/smp.h	2004-08-18 09:08:54 -07:00
@@ -26,6 +26,9 @@
 	__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 __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 -Nru a/include/asm-s390x/kmap_types.h b/include/asm-s390x/kmap_types.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-s390x/kmap_types.h	2004-08-18 09:08:54 -07:00
@@ -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 -Nru a/include/asm-s390x/lowcore.h b/include/asm-s390x/lowcore.h
--- a/include/asm-s390x/lowcore.h	2002-07-30 04:27:40 -07:00
+++ b/include/asm-s390x/lowcore.h	2004-08-18 09:09:00 -07:00
@@ -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 @@
 
         /* 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 -Nru a/include/asm-s390x/pgtable.h b/include/asm-s390x/pgtable.h
--- a/include/asm-s390x/pgtable.h	2003-06-27 04:38:55 -07:00
+++ b/include/asm-s390x/pgtable.h	2004-08-18 09:08:54 -07:00
@@ -484,9 +484,11 @@
 	__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 -Nru a/include/asm-s390x/processor.h b/include/asm-s390x/processor.h
--- a/include/asm-s390x/processor.h	2003-03-19 09:54:55 -08:00
+++ b/include/asm-s390x/processor.h	2004-08-18 09:08:54 -07:00
@@ -52,6 +52,8 @@
 
 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 -Nru a/include/asm-s390x/qdio.h b/include/asm-s390x/qdio.h
--- a/include/asm-s390x/qdio.h	2003-07-07 08:05:42 -07:00
+++ b/include/asm-s390x/qdio.h	2004-08-18 09:09:02 -07:00
@@ -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 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 @@
 		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 @@
 	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 -Nru a/include/asm-s390x/siginfo.h b/include/asm-s390x/siginfo.h
--- a/include/asm-s390x/siginfo.h	2002-03-11 06:13:30 -08:00
+++ b/include/asm-s390x/siginfo.h	2004-08-18 09:08:54 -07:00
@@ -19,7 +19,7 @@
 } 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 -Nru a/include/asm-s390x/sigp.h b/include/asm-s390x/sigp.h
--- a/include/asm-s390x/sigp.h	2002-07-30 04:27:40 -07:00
+++ b/include/asm-s390x/sigp.h	2004-08-18 09:08:54 -07:00
@@ -107,7 +107,7 @@
  * 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 -Nru a/include/asm-s390x/smp.h b/include/asm-s390x/smp.h
--- a/include/asm-s390x/smp.h	2002-07-30 04:27:40 -07:00
+++ b/include/asm-s390x/smp.h	2004-08-18 09:08:54 -07:00
@@ -26,6 +26,9 @@
 	__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 @@
 #define cpu_logical_map(cpu) (cpu)
 
 #endif
+
+#ifndef CONFIG_SMP
+#define smp_call_function_on(func,info,nonatomic,wait,cpu)      ({ 0; })
+#endif
+
 #endif
diff -Nru a/include/asm-x86_64/apic.h b/include/asm-x86_64/apic.h
--- a/include/asm-x86_64/apic.h	2003-11-18 10:50:32 -08:00
+++ b/include/asm-x86_64/apic.h	2004-08-15 19:28:55 -07:00
@@ -78,7 +78,7 @@
 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 -Nru a/include/linux/ata.h b/include/linux/ata.h
--- a/include/linux/ata.h	2004-07-28 10:17:56 -07:00
+++ b/include/linux/ata.h	2004-08-17 22:48:07 -07:00
@@ -182,12 +182,17 @@
 	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 */
@@ -215,6 +220,8 @@
 #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))
diff -Nru a/include/linux/blkdev.h b/include/linux/blkdev.h
--- a/include/linux/blkdev.h	2003-12-08 05:44:17 -08:00
+++ b/include/linux/blkdev.h	2004-08-15 19:28:55 -07:00
@@ -233,7 +233,7 @@
 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_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 -Nru a/include/linux/fs.h b/include/linux/fs.h
--- a/include/linux/fs.h	2004-06-14 22:29:26 -07:00
+++ b/include/linux/fs.h	2004-08-15 19:28:55 -07:00
@@ -1259,7 +1259,7 @@
 }
 
 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 *);
diff -Nru a/include/linux/ide.h b/include/linux/ide.h
--- a/include/linux/ide.h	2004-01-08 11:11:03 -08:00
+++ b/include/linux/ide.h	2004-08-15 19:28:55 -07:00
@@ -1445,10 +1445,10 @@
 	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 -Nru a/include/linux/libata.h b/include/linux/libata.h
--- a/include/linux/libata.h	2004-07-10 09:50:00 -07:00
+++ b/include/linux/libata.h	2004-08-14 12:38:51 -07:00
@@ -371,6 +371,7 @@
 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);
@@ -609,6 +610,13 @@
 	} 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 -Nru a/include/linux/mm.h b/include/linux/mm.h
--- a/include/linux/mm.h	2003-10-07 05:19:34 -07:00
+++ b/include/linux/mm.h	2004-08-18 09:08:54 -07:00
@@ -308,11 +308,9 @@
 /* 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 -Nru a/include/linux/nfsd/const.h b/include/linux/nfsd/const.h
--- a/include/linux/nfsd/const.h	2002-12-16 14:50:41 -08:00
+++ b/include/linux/nfsd/const.h	2004-08-15 16:53:48 -07:00
@@ -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 -Nru a/include/linux/nfsd/xdr3.h b/include/linux/nfsd/xdr3.h
--- a/include/linux/nfsd/xdr3.h	2002-02-04 23:44:09 -08:00
+++ b/include/linux/nfsd/xdr3.h	2004-08-15 16:48:43 -07:00
@@ -41,7 +41,7 @@
 	__u32			count;
 	int			stable;
 	__u8 *			data;
-	int			len;
+	__u32			len;
 };
 
 struct nfsd3_createargs {
diff -Nru a/include/linux/parport_pc.h b/include/linux/parport_pc.h
--- a/include/linux/parport_pc.h	2002-02-04 23:41:48 -08:00
+++ b/include/linux/parport_pc.h	2004-08-15 19:28:55 -07:00
@@ -41,7 +41,7 @@
 	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 @@
 	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 @@
 	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 @@
 	__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 @@
 	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 @@
 	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 -Nru a/include/linux/pci.h b/include/linux/pci.h
--- a/include/linux/pci.h	2004-07-07 12:48:53 -07:00
+++ b/include/linux/pci.h	2004-06-28 15:47:57 -07:00
@@ -835,7 +835,5 @@
 #define PCIPCI_VSFX		16
 #define PCIPCI_ALIMAGIK		32
 
-extern int pciehp_msi_quirk;
-
 #endif /* __KERNEL__ */
 #endif /* LINUX_PCI_H */
diff -Nru a/include/linux/rbtree.h b/include/linux/rbtree.h
--- a/include/linux/rbtree.h	2002-02-05 12:18:53 -08:00
+++ b/include/linux/rbtree.h	2004-08-15 19:28:01 -07:00
@@ -121,6 +121,12 @@
 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 -Nru a/include/linux/sched.h b/include/linux/sched.h
--- a/include/linux/sched.h	2004-04-21 18:27:29 -07:00
+++ b/include/linux/sched.h	2004-08-15 19:28:55 -07:00
@@ -763,7 +763,7 @@
 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 -Nru a/include/net/ip.h b/include/net/ip.h
--- a/include/net/ip.h	2003-09-19 04:01:00 -07:00
+++ b/include/net/ip.h	2004-08-15 19:28:55 -07:00
@@ -137,7 +137,7 @@
 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
 {
diff -Nru a/include/net/irda/irlmp_frame.h b/include/net/irda/irlmp_frame.h
--- a/include/net/irda/irlmp_frame.h	2002-02-05 09:39:48 -08:00
+++ b/include/net/irda/irlmp_frame.h	2004-08-17 06:25:35 -07:00
@@ -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 -Nru a/include/net/irda/timer.h b/include/net/irda/timer.h
--- a/include/net/irda/timer.h	2002-02-04 23:55:11 -08:00
+++ b/include/net/irda/timer.h	2004-08-17 06:20:00 -07:00
@@ -72,21 +72,21 @@
 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 -Nru a/include/scsi/scsi.h b/include/scsi/scsi.h
--- a/include/scsi/scsi.h	2003-08-28 19:20:12 -07:00
+++ b/include/scsi/scsi.h	2004-08-14 04:43:14 -07:00
@@ -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 -Nru a/kernel/fork.c b/kernel/fork.c
--- a/kernel/fork.c	2004-08-08 01:58:48 -07:00
+++ b/kernel/fork.c	2004-08-15 19:28:55 -07:00
@@ -264,7 +264,7 @@
  * is dropped: either by a lazy thread or by
  * mmput. Free the page directory and the mm.
  */
-inline void fastcall __mmdrop(struct mm_struct *mm)
+void fastcall __mmdrop(struct mm_struct *mm)
 {
 	BUG_ON(mm == &init_mm);
 	pgd_free(mm->pgd);
diff -Nru a/lib/rbtree.c b/lib/rbtree.c
--- a/lib/rbtree.c	2001-09-23 16:23:13 -07:00
+++ b/lib/rbtree.c	2004-08-15 19:28:01 -07:00
@@ -294,3 +294,74 @@
 		__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 -Nru a/net/appletalk/ddp.c b/net/appletalk/ddp.c
--- a/net/appletalk/ddp.c	2002-02-04 23:45:08 -08:00
+++ b/net/appletalk/ddp.c	2004-08-17 05:39:59 -07:00
@@ -106,8 +106,8 @@
 #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 -Nru a/net/atm/lec.c b/net/atm/lec.c
--- a/net/atm/lec.c	2004-07-21 17:19:48 -07:00
+++ b/net/atm/lec.c	2004-08-17 05:46:21 -07:00
@@ -71,9 +71,9 @@
 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 @@
 /*
  * 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 @@
 /* 
  * 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 -Nru a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
--- a/net/bluetooth/l2cap.c	2004-07-09 14:41:05 -07:00
+++ b/net/bluetooth/l2cap.c	2004-08-17 05:54:38 -07:00
@@ -70,7 +70,7 @@
 
 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 @@
 	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;
@@ -895,14 +903,6 @@
 
 	if (parent)
 		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. 
diff -Nru a/net/bluetooth/sco.c b/net/bluetooth/sco.c
--- a/net/bluetooth/sco.c	2003-05-19 14:02:05 -07:00
+++ b/net/bluetooth/sco.c	2004-08-17 06:01:52 -07:00
@@ -67,9 +67,8 @@
 	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 @@
 	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 @@
 	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;
@@ -741,29 +763,6 @@
 
 	if (parent)
 		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. 
diff -Nru a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
--- a/net/ipv4/ip_output.c	2003-10-11 12:02:30 -07:00
+++ b/net/ipv4/ip_output.c	2004-08-15 19:28:55 -07:00
@@ -184,7 +184,7 @@
 	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 @@
 		       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 @@
 				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 @@
 		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 -Nru a/net/ipv4/netfilter/ip_nat_snmp_basic.c b/net/ipv4/netfilter/ip_nat_snmp_basic.c
--- a/net/ipv4/netfilter/ip_nat_snmp_basic.c	2003-09-21 18:25:06 -07:00
+++ b/net/ipv4/netfilter/ip_nat_snmp_basic.c	2004-08-17 06:09:44 -07:00
@@ -862,6 +862,77 @@
 	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,
@@ -950,77 +1021,6 @@
 		printk("%02x ", *(buf + i));
 	}
 	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));
-	}
 }
 
 /*
diff -Nru a/net/irda/wrapper.c b/net/irda/wrapper.c
--- a/net/irda/wrapper.c	2003-10-11 12:19:29 -07:00
+++ b/net/irda/wrapper.c	2004-08-17 06:34:04 -07:00
@@ -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 @@
 };
 
 /*
+ * 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 
@@ -137,32 +161,6 @@
 	tx_buff[n++] = EOF;
 
 	return n;
-}
-
-/*
- * 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; */
-	}
 }
 
 /*
diff -Nru a/net/sched/sch_atm.c b/net/sched/sch_atm.c
--- a/net/sched/sch_atm.c	2003-12-24 19:19:50 -08:00
+++ b/net/sched/sch_atm.c	2004-08-16 17:10:19 -07:00
@@ -566,7 +566,6 @@
 	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 -Nru a/net/sched/sch_dsmark.c b/net/sched/sch_dsmark.c
--- a/net/sched/sch_dsmark.c	2004-04-11 14:15:16 -07:00
+++ b/net/sched/sch_dsmark.c	2004-08-16 17:10:19 -07:00
@@ -329,8 +329,6 @@
 	    !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 -Nru a/net/sched/sch_hfsc.c b/net/sched/sch_hfsc.c
--- a/net/sched/sch_hfsc.c	2004-06-18 13:53:45 -07:00
+++ b/net/sched/sch_hfsc.c	2004-08-16 17:10:19 -07:00
@@ -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 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 @@
 					   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 @@
 	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 @@
 
 
 /*
- * 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 @@
 
 /* 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 @@
  * 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 @@
 	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 @@
 	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 @@
 	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 @@
 	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 @@
 			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 @@
 			} 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 @@
 				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 @@
 		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 @@
 			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 @@
 			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 @@
 		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 @@
 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 @@
 		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 @@
 	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 @@
 	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 @@
 		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 @@
 		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 @@
 	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 @@
 	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_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 @@
 	 * 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 -Nru a/net/sched/sch_htb.c b/net/sched/sch_htb.c
--- a/net/sched/sch_htb.c	2004-08-09 16:50:48 -07:00
+++ b/net/sched/sch_htb.c	2004-08-16 17:10:19 -07:00
@@ -1231,7 +1231,6 @@
 				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 -Nru a/net/sched/sch_ingress.c b/net/sched/sch_ingress.c
--- a/net/sched/sch_ingress.c	2003-12-24 19:19:50 -08:00
+++ b/net/sched/sch_ingress.c	2004-08-16 17:10:19 -07:00
@@ -254,8 +254,6 @@
 	}
 
 	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 @@
 		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 -Nru a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c
--- a/net/sunrpc/xprt.c	2003-10-11 14:12:53 -07:00
+++ b/net/sunrpc/xprt.c	2004-08-15 19:28:55 -07:00
@@ -1244,19 +1244,6 @@
 /*
  * 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)
 {
@@ -1277,6 +1264,19 @@
 	task->tk_status = -EAGAIN;
 	task->tk_timeout = 0;
 	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);
+	}
 }
 
 /*
