diff -Nru a/Documentation/CodingStyle b/Documentation/CodingStyle
--- a/Documentation/CodingStyle	Mon Feb 17 14:57:27 2003
+++ b/Documentation/CodingStyle	Mon Feb 17 14:57:27 2003
@@ -173,7 +173,7 @@
 user helper that "GNU emacs" automatically formats the C sources for
 you, and you've noticed that yes, it does do that, but the defaults it
 uses are less than desirable (in fact, they are worse than random
-typing - a infinite number of monkeys typing into GNU emacs would never
+typing - an infinite number of monkeys typing into GNU emacs would never
 make a good program). 
 
 So, you can either get rid of GNU emacs, or change it to use saner
diff -Nru a/Documentation/cli-sti-removal.txt b/Documentation/cli-sti-removal.txt
--- a/Documentation/cli-sti-removal.txt	Mon Feb 17 14:57:27 2003
+++ b/Documentation/cli-sti-removal.txt	Mon Feb 17 14:57:27 2003
@@ -121,9 +121,8 @@
 
 another related change is that synchronize_irq() now takes a parameter:
 synchronize_irq(irq). This change too has the purpose of making SMP
-to make the transition easier, we've still kept the cli(), sti(),
-save_flags() and restore_flags() macros defined on UP systems - but
-their usage will be phased out until the 2.6 kernel is released.
+synchronization more lightweight - this way you can wait for your own
+interrupt handler to finish, no need to wait for other IRQ sources.
 
 
 why were these changes done? The main reason was the architectural burden
diff -Nru a/Documentation/filesystems/Locking b/Documentation/filesystems/Locking
--- a/Documentation/filesystems/Locking	Mon Feb 17 14:57:28 2003
+++ b/Documentation/filesystems/Locking	Mon Feb 17 14:57:28 2003
@@ -21,7 +21,7 @@
 		dcache_lock	may block
 d_revalidate:	no		yes
 d_hash		no		yes
-d_compare:	yes		no
+d_compare:	no		no 
 d_delete:	yes		no
 d_release:	no		yes
 d_iput:		no		yes
diff -Nru a/Documentation/s390/Debugging390.txt b/Documentation/s390/Debugging390.txt
--- a/Documentation/s390/Debugging390.txt	Mon Feb 17 14:57:27 2003
+++ b/Documentation/s390/Debugging390.txt	Mon Feb 17 14:57:27 2003
@@ -10,7 +10,7 @@
 This document is intended to give an good overview of how to debug 
 Linux for s/390 & z/Architecture it isn't intended as a complete reference & not a
 tutorial on the fundamentals of C & assembly, it dosen't go into
-390 IO in any detail. It is intended to compliment the documents in the
+390 IO in any detail. It is intended to complement the documents in the
 reference section below & any other worthwhile references you get.
 
 It is intended like the Enterprise Systems Architecture/390 Reference Summary
diff -Nru a/Makefile b/Makefile
--- a/Makefile	Mon Feb 17 14:57:26 2003
+++ b/Makefile	Mon Feb 17 14:57:26 2003
@@ -1,6 +1,6 @@
 VERSION = 2
 PATCHLEVEL = 5
-SUBLEVEL = 61
+SUBLEVEL = 62
 EXTRAVERSION =
 
 # *DOCUMENTATION*
@@ -405,30 +405,17 @@
 
 .PHONY: prepare
 prepare: include/linux/version.h include/asm include/config/MARKER
-ifdef CONFIG_MODVERSIONS
 ifdef KBUILD_MODULES
 ifeq ($(origin SUBDIRS),file)
 	$(Q)rm -rf $(MODVERDIR)
-	$(Q)mkdir $(MODVERDIR)
 else
 	@echo '*** Warning: Overriding SUBDIRS on the command line can cause'
-	@echo '***          inconsistencies with module symbol versions'
-endif
+	@echo '***          inconsistencies'
 endif
+	$(Q)mkdir -p $(MODVERDIR)
 endif
 	@echo '  Starting the build. KBUILD_BUILTIN=$(KBUILD_BUILTIN) KBUILD_MODULES=$(KBUILD_MODULES)'
 
-#	We need to build init/vermagic.o before descending since all modules
-#	(*.ko) need it already
-
-ifdef CONFIG_MODULES
-
-prepare: init/vermagic.o
-
-init/vermagic.o: include/linux/version.h
-
-endif
-
 #	This can be used by arch/$ARCH/Makefile to preprocess
 #	their vmlinux.lds.S file
 
@@ -518,21 +505,15 @@
 
 #	Build modules
 
-.PHONY: modules __modversions
-modules: $(SUBDIRS) __modversions
-
-ifdef CONFIG_MODVERSIONS
-
-__modversions: vmlinux $(SUBDIRS)
-	@echo '  Recording module symbol versions.';
-	$(Q)$(MAKE) -rR -f scripts/Makefile.modver
-
-endif
+.PHONY: modules
+modules: $(SUBDIRS) $(if $(CONFIG_MODVERSIONS),vmlinux)
+	@echo '  Building modules, stage 2.';
+	$(Q)$(MAKE) -rR -f scripts/Makefile.modpost
 
 #	Install modules
 
 .PHONY: modules_install
-modules_install: _modinst_ $(patsubst %, _modinst_%, $(SUBDIRS)) _modinst_post
+modules_install: _modinst_ _modinst_post
 
 .PHONY: _modinst_
 _modinst_:
@@ -540,6 +521,7 @@
 	@rm -f $(MODLIB)/build
 	@mkdir -p $(MODLIB)/kernel
 	@ln -s $(TOPDIR) $(MODLIB)/build
+	$(Q)$(MAKE) -rR -f scripts/Makefile.modinst
 
 # If System.map exists, run depmod.  This deliberately does not have a
 # dependency on System.map since that would run the dependency tree on
@@ -552,13 +534,9 @@
 depmod_opts	:= -b $(INSTALL_MOD_PATH) -r
 endif
 .PHONY: _modinst_post
-_modinst_post:
+_modinst_post: _modinst_
 	if [ -r System.map ]; then $(DEPMOD) -ae -F System.map $(depmod_opts) $(KERNELRELEASE); fi
 
-.PHONY: $(patsubst %, _modinst_%, $(SUBDIRS))
-$(patsubst %, _modinst_%, $(SUBDIRS)) :
-	$(Q)$(MAKE) -rR -f scripts/Makefile.modinst obj=$(patsubst _modinst_%,%,$@)
-
 else # CONFIG_MODULES
 
 # Modules not configured
@@ -726,8 +704,8 @@
 	$(call cmd,rmclean)
 	@find . $(RCS_FIND_IGNORE) \
 	 	\( -name '*.[oas]' -o -name '*.ko' -o -name '.*.cmd' \
-		-o -name '.*.d' -o -name '.*.tmp' \) -type f \
-		-print | xargs rm -f
+		-o -name '.*.d' -o -name '.*.tmp' -o -name '*.mod.c' \) \
+		-type f -print | xargs rm -f
 
 # mrproper - delete configuration + modules + core files
 #
diff -Nru a/arch/alpha/kernel/asm-offsets.c b/arch/alpha/kernel/asm-offsets.c
--- a/arch/alpha/kernel/asm-offsets.c	Mon Feb 17 14:57:28 2003
+++ b/arch/alpha/kernel/asm-offsets.c	Mon Feb 17 14:57:28 2003
@@ -7,6 +7,7 @@
 #include <linux/types.h>
 #include <linux/stddef.h>
 #include <linux/sched.h>
+#include <linux/ptrace.h>
 #include <asm/io.h>
 
 #define DEFINE(sym, val) \
diff -Nru a/arch/alpha/kernel/core_marvel.c b/arch/alpha/kernel/core_marvel.c
--- a/arch/alpha/kernel/core_marvel.c	Mon Feb 17 14:57:26 2003
+++ b/arch/alpha/kernel/core_marvel.c	Mon Feb 17 14:57:26 2003
@@ -1058,10 +1058,10 @@
 		}
 	}
 
-	printk("MARVEL - using hose %d as AGP\n", hose->index);
-
 	if (!hose || !hose->sg_pci)
 		return NULL;
+
+	printk("MARVEL - using hose %d as AGP\n", hose->index);
 
 	/* 
 	 * Get the csrs from the hose.
diff -Nru a/arch/alpha/kernel/pci.c b/arch/alpha/kernel/pci.c
--- a/arch/alpha/kernel/pci.c	Mon Feb 17 14:57:26 2003
+++ b/arch/alpha/kernel/pci.c	Mon Feb 17 14:57:26 2003
@@ -57,12 +57,6 @@
  */
 
 static void __init
-quirk_eisa_bridge(struct pci_dev *dev)
-{
-	dev->class = PCI_CLASS_BRIDGE_EISA << 8;
-}
-
-static void __init
 quirk_isa_bridge(struct pci_dev *dev)
 {
 	dev->class = PCI_CLASS_BRIDGE_ISA << 8;
@@ -125,8 +119,6 @@
 }
 
 struct pci_fixup pcibios_fixups[] __initdata = {
-	{ PCI_FIXUP_HEADER, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82375,
-	  quirk_eisa_bridge },
 	{ PCI_FIXUP_HEADER, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82378,
 	  quirk_isa_bridge },
 	{ PCI_FIXUP_HEADER, PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M5229,
diff -Nru a/arch/alpha/kernel/sys_marvel.c b/arch/alpha/kernel/sys_marvel.c
--- a/arch/alpha/kernel/sys_marvel.c	Mon Feb 17 14:57:28 2003
+++ b/arch/alpha/kernel/sys_marvel.c	Mon Feb 17 14:57:28 2003
@@ -223,7 +223,7 @@
 	 */
 	val = io7->csrs->PO7_LSI_CTL[which].csr;
 	val &= ~(0x1ffUL << 14);		/* clear the target pid */
-	val |= ((unsigned long)where << 14);	/* set teh new target pid */
+	val |= ((unsigned long)where << 14);	/* set the new target pid */
 
 	io7->csrs->PO7_LSI_CTL[which].csr = val;
 	mb();
@@ -240,7 +240,7 @@
 	 */
 	val = io7->csrs->PO7_MSI_CTL[which].csr;
 	val &= ~(0x1ffUL << 14);		/* clear the target pid */
-	val |= ((unsigned long)where << 14);	/* set teh new target pid */
+	val |= ((unsigned long)where << 14);	/* set the new target pid */
 
 	io7->csrs->PO7_MSI_CTL[which].csr = val;
 	mb();
diff -Nru a/arch/alpha/kernel/systbls.S b/arch/alpha/kernel/systbls.S
--- a/arch/alpha/kernel/systbls.S	Mon Feb 17 14:57:27 2003
+++ b/arch/alpha/kernel/systbls.S	Mon Feb 17 14:57:27 2003
@@ -432,6 +432,7 @@
 	.quad sys_remap_file_pages		/* 410 */
 	.quad sys_set_tid_address
 	.quad sys_restart_syscall
+	.quad sys_fadvise64
 
 	.size sys_call_table, . - sys_call_table
 	.type sys_call_table, @object
diff -Nru a/arch/alpha/lib/csum_ipv6_magic.S b/arch/alpha/lib/csum_ipv6_magic.S
--- a/arch/alpha/lib/csum_ipv6_magic.S	Mon Feb 17 14:57:27 2003
+++ b/arch/alpha/lib/csum_ipv6_magic.S	Mon Feb 17 14:57:27 2003
@@ -84,7 +84,7 @@
 	extwl	$0,2,$1		# e0    : fold 17-bit value
 	zapnot	$0,3,$0		# .. e1 :
 	addq	$0,$1,$0	# e0    :
-	not	$0,$0		# e1    : and compliment.
+	not	$0,$0		# e1    : and complement.
 
 	zapnot	$0,3,$0		# e0    :
 	ret			# .. e1 :
diff -Nru a/arch/alpha/mm/numa.c b/arch/alpha/mm/numa.c
--- a/arch/alpha/mm/numa.c	Mon Feb 17 14:57:26 2003
+++ b/arch/alpha/mm/numa.c	Mon Feb 17 14:57:26 2003
@@ -64,6 +64,7 @@
 	unsigned long bootmap_size, bootmap_pages, bootmap_start;
 	unsigned long start, end;
 	unsigned long node_pfn_start, node_pfn_end;
+	unsigned long node_min_pfn, node_max_pfn;
 	int i;
 	unsigned long node_datasz = PFN_UP(sizeof(pg_data_t));
 	int show_init = 0;
@@ -76,8 +77,9 @@
 	memdesc = (struct memdesc_struct *)
 	  (hwrpb->mddt_offset + (unsigned long) hwrpb);
 
-	/* find the bounds of this node (min_low_pfn/max_low_pfn) */
-	min_low_pfn = ~0UL;
+	/* find the bounds of this node (node_min_pfn/node_max_pfn) */
+	node_min_pfn = ~0UL;
+	node_max_pfn = 0UL;
 	for_each_mem_cluster(memdesc, cluster, i) {
 		/* Bit 0 is console/PALcode reserved.  Bit 1 is
 		   non-volatile memory -- we might want to mark
@@ -104,42 +106,48 @@
 		if (end > node_pfn_end)
 			end = node_pfn_end;
 
-		if (start < min_low_pfn)
-			min_low_pfn = start;
-		if (end > max_low_pfn)
-			max_pfn = max_low_pfn = end;
+		if (start < node_min_pfn)
+			node_min_pfn = start;
+		if (end > node_max_pfn)
+			node_max_pfn = end;
 	}
 
-	if (mem_size_limit && max_low_pfn > mem_size_limit) {
+	if (mem_size_limit && node_max_pfn > mem_size_limit) {
 		static int msg_shown = 0;
 		if (!msg_shown) {
 			msg_shown = 1;
 			printk("setup: forcing memory size to %ldK (from %ldK).\n",
 			       mem_size_limit << (PAGE_SHIFT - 10),
-			       max_low_pfn    << (PAGE_SHIFT - 10));
+			       node_max_pfn    << (PAGE_SHIFT - 10));
 		}
-		max_low_pfn = mem_size_limit;
+		node_max_pfn = mem_size_limit;
 	}
 
-	if (min_low_pfn >= max_low_pfn)
+	if (node_min_pfn >= node_max_pfn)
 		return;
 
-	num_physpages += max_low_pfn - min_low_pfn;
+	/* Update global {min,max}_low_pfn from node information. */
+	if (node_min_pfn < min_low_pfn)
+		min_low_pfn = node_min_pfn;
+	if (node_max_pfn > max_low_pfn)
+		max_pfn = max_low_pfn = node_max_pfn;
+
+	num_physpages += node_max_pfn - node_min_pfn;
 
 #if 0 /* we'll try this one again in a little while */
 	/* Cute trick to make sure our local node data is on local memory */
-	node_data[nid] = (pg_data_t *)(__va(min_low_pfn << PAGE_SHIFT));
+	node_data[nid] = (pg_data_t *)(__va(node_min_pfn << PAGE_SHIFT));
 #endif
 	/* Quasi-mark the pg_data_t as in-use */
-	min_low_pfn += node_datasz;
-	if (min_low_pfn >= max_low_pfn) {
+	node_min_pfn += node_datasz;
+	if (node_min_pfn >= node_max_pfn) {
 		printk(" not enough mem to reserve NODE_DATA");
 		return;
 	}
 	NODE_DATA(nid)->bdata = &node_bdata[nid];
 
 	printk(" Detected node memory:   start %8lu, end %8lu\n",
-	       min_low_pfn, max_low_pfn);
+	       node_min_pfn, node_max_pfn);
 
 	DBGDCONT(" DISCONTIG: node_data[%d]   is at 0x%p\n", nid, NODE_DATA(nid));
 	DBGDCONT(" DISCONTIG: NODE_DATA(%d)->bdata is at 0x%p\n", nid, NODE_DATA(nid)->bdata);
@@ -149,15 +157,15 @@
 	end_kernel_pfn = PFN_UP(virt_to_phys(kernel_end));
 	bootmap_start = -1;
 
-	if (!nid && (max_low_pfn < end_kernel_pfn || min_low_pfn > start_kernel_pfn))
+	if (!nid && (node_max_pfn < end_kernel_pfn || node_min_pfn > start_kernel_pfn))
 		panic("kernel loaded out of ram");
 
 	/* Zone start phys-addr must be 2^(MAX_ORDER-1) aligned */
-	min_low_pfn = (min_low_pfn + ((1UL << (MAX_ORDER-1))-1)) & ~((1UL << (MAX_ORDER-1))-1);
+	node_min_pfn = (node_min_pfn + ((1UL << (MAX_ORDER-1))-1)) & ~((1UL << (MAX_ORDER-1))-1);
 
 	/* We need to know how many physically contiguous pages
 	   we'll need for the bootmap.  */
-	bootmap_pages = bootmem_bootmap_pages(max_low_pfn-min_low_pfn);
+	bootmap_pages = bootmem_bootmap_pages(node_max_pfn-node_min_pfn);
 
 	/* Now find a good region where to allocate the bootmap.  */
 	for_each_mem_cluster(memdesc, cluster, i) {
@@ -167,13 +175,13 @@
 		start = cluster->start_pfn;
 		end = start + cluster->numpages;
 
-		if (start >= max_low_pfn || end <= min_low_pfn)
+		if (start >= node_max_pfn || end <= node_min_pfn)
 			continue;
 
-		if (end > max_low_pfn)
-			end = max_low_pfn;
-		if (start < min_low_pfn)
-			start = min_low_pfn;
+		if (end > node_max_pfn)
+			end = node_max_pfn;
+		if (start < node_min_pfn)
+			start = node_min_pfn;
 
 		if (start < start_kernel_pfn) {
 			if (end > end_kernel_pfn
@@ -195,7 +203,7 @@
 
 	/* Allocate the bootmap and mark the whole MM as reserved.  */
 	bootmap_size = init_bootmem_node(NODE_DATA(nid), bootmap_start,
-					 min_low_pfn, max_low_pfn);
+					 node_min_pfn, node_max_pfn);
 	DBGDCONT(" bootmap_start %lu, bootmap_size %lu, bootmap_pages %lu\n",
 		 bootmap_start, bootmap_size, bootmap_pages);
 
@@ -207,13 +215,13 @@
 		start = cluster->start_pfn;
 		end = cluster->start_pfn + cluster->numpages;
 
-		if (start >= max_low_pfn || end <= min_low_pfn)
+		if (start >= node_max_pfn || end <= node_min_pfn)
 			continue;
 
-		if (end > max_low_pfn)
-			end = max_low_pfn;
-		if (start < min_low_pfn)
-			start = min_low_pfn;
+		if (end > node_max_pfn)
+			end = node_max_pfn;
+		if (start < node_min_pfn)
+			start = node_min_pfn;
 
 		if (start < start_kernel_pfn) {
 			if (end > end_kernel_pfn) {
@@ -249,6 +257,9 @@
 	show_mem_layout();
 
 	numnodes = 0;
+
+	min_low_pfn = ~0UL;
+	max_low_pfn = 0UL;
 	for (nid = 0; nid < MAX_NUMNODES; nid++)
 		setup_memory_node(nid, kernel_end);
 
diff -Nru a/arch/arm/Kconfig b/arch/arm/Kconfig
--- a/arch/arm/Kconfig	Mon Feb 17 14:57:27 2003
+++ b/arch/arm/Kconfig	Mon Feb 17 14:57:27 2003
@@ -539,8 +539,8 @@
 	depends on CPU_FREQ
 	default y
 
-config CPU_FREQ_26_API
-	bool
+config CPU_FREQ_PROC_INTF
+	tristate
 	depends on CPU_FREQ
 	default y
 
diff -Nru a/arch/arm/common/sa1111-pcibuf.c b/arch/arm/common/sa1111-pcibuf.c
--- a/arch/arm/common/sa1111-pcibuf.c	Mon Feb 17 14:57:26 2003
+++ b/arch/arm/common/sa1111-pcibuf.c	Mon Feb 17 14:57:26 2003
@@ -54,7 +54,7 @@
 	dma_addr_t	safe_dma_addr;
 };
 
-LIST_HEAD(safe_buffers);
+static LIST_HEAD(safe_buffers);
 
 
 #define SIZE_SMALL	1024
diff -Nru a/arch/arm/common/sa1111.c b/arch/arm/common/sa1111.c
--- a/arch/arm/common/sa1111.c	Mon Feb 17 14:57:28 2003
+++ b/arch/arm/common/sa1111.c	Mon Feb 17 14:57:28 2003
@@ -218,7 +218,7 @@
  * be triggered.  In fact, its very difficult, if not impossible to get
  * INTSET to re-trigger the interrupt.
  */
-static void sa1111_rerun_lowirq(unsigned int irq)
+static int sa1111_retrigger_lowirq(unsigned int irq)
 {
 	unsigned int mask = SA1111_IRQMASK_LO(irq);
 	int i;
@@ -233,6 +233,7 @@
 	if (i == 8)
 		printk(KERN_ERR "Danger Will Robinson: failed to "
 			"re-trigger IRQ%d\n", irq);
+	return i == 8 ? -1 : 0;
 }
 
 static int sa1111_type_lowirq(unsigned int irq, unsigned int flags)
@@ -270,7 +271,7 @@
 	.ack		= sa1111_ack_irq,
 	.mask		= sa1111_mask_lowirq,
 	.unmask		= sa1111_unmask_lowirq,
-	.rerun		= sa1111_rerun_lowirq,
+	.retrigger	= sa1111_retrigger_lowirq,
 	.type		= sa1111_type_lowirq,
 	.wake		= sa1111_wake_lowirq,
 };
@@ -292,7 +293,7 @@
  * be triggered.  In fact, its very difficult, if not impossible to get
  * INTSET to re-trigger the interrupt.
  */
-static void sa1111_rerun_highirq(unsigned int irq)
+static int sa1111_retrigger_highirq(unsigned int irq)
 {
 	unsigned int mask = SA1111_IRQMASK_HI(irq);
 	int i;
@@ -307,6 +308,7 @@
 	if (i == 8)
 		printk(KERN_ERR "Danger Will Robinson: failed to "
 			"re-trigger IRQ%d\n", irq);
+	return i == 8 ? -1 : 0;
 }
 
 static int sa1111_type_highirq(unsigned int irq, unsigned int flags)
@@ -344,7 +346,7 @@
 	.ack		= sa1111_ack_irq,
 	.mask		= sa1111_mask_highirq,
 	.unmask		= sa1111_unmask_highirq,
-	.rerun		= sa1111_rerun_highirq,
+	.retrigger	= sa1111_retrigger_highirq,
 	.type		= sa1111_type_highirq,
 	.wake		= sa1111_wake_highirq,
 };
diff -Nru a/arch/arm/def-configs/epxa10db b/arch/arm/def-configs/epxa10db
--- a/arch/arm/def-configs/epxa10db	Mon Feb 17 14:57:27 2003
+++ b/arch/arm/def-configs/epxa10db	Mon Feb 17 14:57:27 2003
@@ -1,27 +1,31 @@
 #
-# Automatically generated by make menuconfig: don't edit
+# Automatically generated make config: don't edit
 #
 CONFIG_ARM=y
-# CONFIG_EISA is not set
-# CONFIG_SBUS is not set
-# CONFIG_MCA is not set
+CONFIG_MMU=y
+CONFIG_SWAP=y
 CONFIG_UID16=y
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
-# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
-# CONFIG_GENERIC_BUST_SPINLOCK is not set
-# CONFIG_GENERIC_ISA_DMA is not set
 
 #
 # Code maturity level options
 #
 CONFIG_EXPERIMENTAL=y
-# CONFIG_OBSOLETE is not set
+
+#
+# General setup
+#
+CONFIG_SYSVIPC=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+CONFIG_LOG_BUF_SHIFT=14
 
 #
 # Loadable module support
 #
 CONFIG_MODULES=y
-# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
 # CONFIG_KMOD is not set
 
 #
@@ -33,6 +37,7 @@
 # CONFIG_ARCH_CLPS7500 is not set
 # CONFIG_ARCH_CLPS711X is not set
 # CONFIG_ARCH_CO285 is not set
+# CONFIG_ARCH_PXA is not set
 # CONFIG_ARCH_EBSA110 is not set
 CONFIG_ARCH_CAMELOT=y
 # CONFIG_ARCH_FOOTBRIDGE is not set
@@ -46,106 +51,71 @@
 #
 # Archimedes/A5000 Implementations
 #
-# CONFIG_ARCH_ARC is not set
-# CONFIG_ARCH_A5K is not set
+
+#
+# Archimedes/A5000 Implementations (select only ONE)
+#
+
+#
+# CLPS711X/EP721X Implementations
+#
+
+#
+# Epxa10db
+#
+
+#
+# PLD hotswap support
+#
+CONFIG_PLD=y
+# CONFIG_PLD_HOTSWAP is not set
 
 #
 # Footbridge Implementations
 #
-# CONFIG_ARCH_CATS is not set
-# CONFIG_ARCH_PERSONAL_SERVER is not set
-# CONFIG_ARCH_EBSA285_ADDIN is not set
-# CONFIG_ARCH_EBSA285_HOST is not set
-# CONFIG_ARCH_NETWINDER is not set
+
+#
+# IOP310 Implementation Options
+#
+
+#
+# IOP310 Chipset Features
+#
+
+#
+# Intel PXA250/210 Implementations
+#
 
 #
 # SA11x0 Implementations
 #
-# CONFIG_SA1100_ASSABET is not set
-# CONFIG_ASSABET_NEPONSET is not set
-# CONFIG_SA1100_ADSBITSY is not set
-# CONFIG_SA1100_BRUTUS is not set
-# CONFIG_SA1100_CERF is not set
-# CONFIG_SA1100_H3100 is not set
-# CONFIG_SA1100_H3600 is not set
-# CONFIG_SA1100_H3800 is not set
-# CONFIG_SA1100_H3XXX is not set
-# CONFIG_SA1100_EXTENEX1 is not set
-# CONFIG_SA1100_FLEXANET is not set
-# CONFIG_SA1100_FREEBIRD is not set
-# CONFIG_SA1100_GRAPHICSCLIENT is not set
-# CONFIG_SA1100_GRAPHICSMASTER is not set
-# CONFIG_SA1100_BADGE4 is not set
-# CONFIG_SA1100_JORNADA720 is not set
-# CONFIG_SA1100_HUW_WEBPANEL is not set
-# CONFIG_SA1100_ITSY is not set
-# CONFIG_SA1100_LART is not set
-# CONFIG_SA1100_NANOENGINE is not set
-# CONFIG_SA1100_OMNIMETER is not set
-# CONFIG_SA1100_PANGOLIN is not set
-# CONFIG_SA1100_PLEB is not set
-# CONFIG_SA1100_PT_SYSTEM3 is not set
-# CONFIG_SA1100_SHANNON is not set
-# CONFIG_SA1100_SHERMAN is not set
-# CONFIG_SA1100_SIMPAD is not set
-# CONFIG_SA1100_PFS168 is not set
-# CONFIG_SA1100_VICTOR is not set
-# CONFIG_SA1100_XP860 is not set
-# CONFIG_SA1100_YOPY is not set
-# CONFIG_SA1100_USB is not set
-# CONFIG_SA1100_USB_NETLINK is not set
-# CONFIG_SA1100_USB_CHAR is not set
-# CONFIG_H3600_SLEEVE is not set
 
 #
-# CLPS711X/EP721X Implementations
+# Processor Type
 #
-# CONFIG_ARCH_AUTCPU12 is not set
-# CONFIG_ARCH_CDB89712 is not set
-# CONFIG_ARCH_CLEP7312 is not set
-# CONFIG_ARCH_EDB7211 is not set
-# CONFIG_ARCH_P720T is not set
-# CONFIG_ARCH_FORTUNET is not set
-# CONFIG_ARCH_EP7211 is not set
-# CONFIG_ARCH_EP7212 is not set
-# CONFIG_ARCH_ACORN is not set
-# CONFIG_FOOTBRIDGE is not set
-# CONFIG_FOOTBRIDGE_HOST is not set
-# CONFIG_FOOTBRIDGE_ADDIN is not set
 CONFIG_CPU_32=y
-# CONFIG_CPU_26 is not set
-# CONFIG_CPU_32v3 is not set
-CONFIG_CPU_32v4=y
-# CONFIG_CPU_ARM610 is not set
-# CONFIG_CPU_ARM710 is not set
-# CONFIG_CPU_ARM720T is not set
-# CONFIG_CPU_ARM920T is not set
 CONFIG_CPU_ARM922T=y
-CONFIG_CPU_ARM922_CPU_IDLE=y
-CONFIG_CPU_ARM922_I_CACHE_ON=y
-CONFIG_CPU_ARM922_D_CACHE_ON=y
-# CONFIG_CPU_ARM922_WRITETHROUGH is not set
-# CONFIG_CPU_ARM926T is not set
-# CONFIG_CPU_ARM1020 is not set
-# CONFIG_CPU_SA110 is not set
-# CONFIG_CPU_SA1100 is not set
-# CONFIG_XSCALE_PMU is not set
+CONFIG_CPU_32v4=y
+
+#
+# Processor Features
+#
 # CONFIG_ARM_THUMB is not set
-# CONFIG_DISCONTIGMEM is not set
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
 
 #
 # General setup
 #
-# CONFIG_PCI is not set
-# CONFIG_ISA is not set
-# CONFIG_ISA_DMA is not set
-# CONFIG_FIQ is not set
+# CONFIG_ZBOOT_ROM is not set
+CONFIG_ZBOOT_ROM_TEXT=0
+CONFIG_ZBOOT_ROM_BSS=0
 # CONFIG_HOTPLUG is not set
-# CONFIG_PCMCIA is not set
-CONFIG_NET=y
-CONFIG_SYSVIPC=y
-# CONFIG_BSD_PROCESS_ACCT is not set
-CONFIG_SYSCTL=y
+
+#
+# At least one math emulation must be selected
+#
 CONFIG_FPE_NWFPE=y
 # CONFIG_FPE_FASTFPE is not set
 CONFIG_KCORE_ELF=y
@@ -154,7 +124,7 @@
 CONFIG_BINFMT_ELF=y
 # CONFIG_BINFMT_MISC is not set
 # CONFIG_PM is not set
-# CONFIG_APM is not set
+# CONFIG_PREEMPT is not set
 # CONFIG_ARTHUR is not set
 CONFIG_CMDLINE="mem=32M console=ttyUA0,38400 root=/dev/mtdblock0 rw"
 CONFIG_ALIGNMENT_TRAP=y
@@ -171,9 +141,14 @@
 CONFIG_MTD_DEBUG=y
 CONFIG_MTD_DEBUG_VERBOSE=0
 CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_CONCAT is not set
 # CONFIG_MTD_REDBOOT_PARTS is not set
-CONFIG_MTD_BOOTLDR_PARTS=y
+# CONFIG_MTD_CMDLINE_PARTS is not set
 # CONFIG_MTD_AFS_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
 CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLOCK=y
 # CONFIG_FTL is not set
@@ -192,9 +167,6 @@
 # CONFIG_MTD_ROM is not set
 # CONFIG_MTD_ABSENT is not set
 # CONFIG_MTD_OBSOLETE_CHIPS is not set
-# CONFIG_MTD_AMDSTD is not set
-# CONFIG_MTD_SHARP is not set
-# CONFIG_MTD_JEDEC is not set
 
 #
 # Mapping drivers for chip access
@@ -202,24 +174,23 @@
 # CONFIG_MTD_PHYSMAP is not set
 # CONFIG_MTD_NORA is not set
 # CONFIG_MTD_ARM_INTEGRATOR is not set
-# CONFIG_MTD_CDB89712 is not set
-# CONFIG_MTD_SA1100 is not set
-# CONFIG_MTD_DC21285 is not set
-# CONFIG_MTD_IQ80310 is not set
 CONFIG_MTD_EPXA10DB=y
-# CONFIG_MTD_PCI is not set
+# CONFIG_MTD_EDB7312 is not set
+# CONFIG_MTD_UCLINUX is not set
 
 #
 # Self-contained MTD device drivers
 #
-# CONFIG_MTD_PMC551 is not set
 # CONFIG_MTD_SLRAM is not set
 # CONFIG_MTD_MTDRAM is not set
 # CONFIG_MTD_BLKMTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
 # CONFIG_MTD_DOC1000 is not set
 # CONFIG_MTD_DOC2000 is not set
 # CONFIG_MTD_DOC2001 is not set
-# CONFIG_MTD_DOCPROBE is not set
 
 #
 # NAND Flash Device Drivers
@@ -227,21 +198,14 @@
 # CONFIG_MTD_NAND is not set
 
 #
-# Plug and Play configuration
+# Plug and Play support
 #
 # CONFIG_PNP is not set
-# CONFIG_ISAPNP is not set
 
 #
 # Block devices
 #
 # CONFIG_BLK_DEV_FD is not set
-# CONFIG_BLK_DEV_XD is not set
-# CONFIG_PARIDE is not set
-# CONFIG_BLK_CPQ_DA is not set
-# CONFIG_BLK_CPQ_CISS_DA is not set
-# CONFIG_CISS_SCSI_TAPE is not set
-# CONFIG_BLK_DEV_DAC960 is not set
 # CONFIG_BLK_DEV_LOOP is not set
 # CONFIG_BLK_DEV_NBD is not set
 CONFIG_BLK_DEV_RAM=y
@@ -252,23 +216,22 @@
 # Multi-device support (RAID and LVM)
 #
 # CONFIG_MD is not set
-# CONFIG_BLK_DEV_MD is not set
-# CONFIG_MD_LINEAR is not set
-# CONFIG_MD_RAID0 is not set
-# CONFIG_MD_RAID1 is not set
-# CONFIG_MD_RAID5 is not set
-# CONFIG_MD_MULTIPATH is not set
-# CONFIG_BLK_DEV_LVM is not set
+
+#
+# Networking support
+#
+CONFIG_NET=y
 
 #
 # Networking options
 #
 CONFIG_PACKET=y
 # CONFIG_PACKET_MMAP is not set
-# CONFIG_NETLINK is not set
+# CONFIG_NETLINK_DEV is not set
 # CONFIG_NETFILTER is not set
 # CONFIG_FILTER is not set
 CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
 CONFIG_INET=y
 # CONFIG_IP_MULTICAST is not set
 # CONFIG_IP_ADVANCED_ROUTER is not set
@@ -278,19 +241,26 @@
 # CONFIG_IP_PNP_RARP is not set
 # CONFIG_NET_IPIP is not set
 # CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
 # CONFIG_INET_ECN is not set
 # CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_XFRM_USER is not set
 # CONFIG_IPV6 is not set
-# CONFIG_KHTTPD is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+CONFIG_IPV6_SCTP__=y
+# CONFIG_IP_SCTP is not set
 # CONFIG_ATM is not set
 # CONFIG_VLAN_8021Q is not set
-# CONFIG_IPX is not set
-# CONFIG_ATALK is not set
+# CONFIG_LLC is not set
 # CONFIG_DECNET is not set
 # CONFIG_BRIDGE is not set
 # CONFIG_X25 is not set
 # CONFIG_LAPB is not set
-# CONFIG_LLC is not set
 # CONFIG_NET_DIVERT is not set
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
@@ -303,54 +273,27 @@
 # CONFIG_NET_SCHED is not set
 
 #
-# Network device support
+# Network testing
 #
+# CONFIG_NET_PKTGEN is not set
 CONFIG_NETDEVICES=y
-
-#
-# ARCnet devices
-#
-# CONFIG_ARCNET is not set
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_EQUALIZER is not set
 # CONFIG_TUN is not set
+# CONFIG_ETHERTAP is not set
 
 #
 # Ethernet (10 or 100Mbit)
 #
 CONFIG_NET_ETHERNET=y
-# CONFIG_ARM_AM79C961A is not set
 CONFIG_ETHER00=m
-# CONFIG_SUNLANCE is not set
-# CONFIG_SUNBMAC is not set
-# CONFIG_SUNQE is not set
-# CONFIG_SUNLANCE is not set
-# CONFIG_SUNGEM is not set
-# CONFIG_NET_VENDOR_3COM is not set
-# CONFIG_LANCE is not set
-# CONFIG_NET_VENDOR_SMC is not set
-# CONFIG_NET_VENDOR_RACAL is not set
-# CONFIG_NET_ISA is not set
-# CONFIG_NET_PCI is not set
-# CONFIG_NET_POCKET is not set
 
 #
 # Ethernet (1000 Mbit)
 #
-# CONFIG_ACENIC is not set
-# CONFIG_DL2K is not set
-# CONFIG_MYRI_SBUS is not set
-# CONFIG_NS83820 is not set
-# CONFIG_HAMACHI is not set
-# CONFIG_YELLOWFIN is not set
-# CONFIG_SK98LIN is not set
-# CONFIG_FDDI is not set
-# CONFIG_HIPPI is not set
-# CONFIG_PLIP is not set
 CONFIG_PPP=y
 CONFIG_PPP_MULTILINK=y
-# CONFIG_PPP_FILTER is not set
 CONFIG_PPP_ASYNC=y
 CONFIG_PPP_SYNC_TTY=y
 # CONFIG_PPP_DEFLATE is not set
@@ -364,11 +307,8 @@
 # CONFIG_NET_RADIO is not set
 
 #
-# Token Ring devices
+# Token Ring devices (depends on LLC=y)
 #
-# CONFIG_TR is not set
-# CONFIG_NET_FC is not set
-# CONFIG_RCPCI is not set
 # CONFIG_SHAPER is not set
 
 #
@@ -377,21 +317,19 @@
 # CONFIG_WAN is not set
 
 #
-# Amateur Radio support
+# IrDA (infrared) support
 #
-# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
 
 #
-# IrDA (infrared) support
+# Amateur Radio support
 #
-# CONFIG_IRDA is not set
+# CONFIG_HAMRADIO is not set
 
 #
-# ATA/IDE/MFM/RLL support
+# ATA/ATAPI/MFM/RLL support
 #
 # CONFIG_IDE is not set
-# CONFIG_BLK_DEV_IDE_MODES is not set
-# CONFIG_BLK_DEV_HD is not set
 
 #
 # SCSI support
@@ -402,59 +340,48 @@
 # I2O device support
 #
 # CONFIG_I2O is not set
-# CONFIG_I2O_BLOCK is not set
-# CONFIG_I2O_LAN is not set
-# CONFIG_I2O_SCSI is not set
-# CONFIG_I2O_PROC is not set
 
 #
 # ISDN subsystem
 #
-# CONFIG_ISDN is not set
+# CONFIG_ISDN_BOOL is not set
 
 #
-# Input core support
+# Input device support
 #
 # CONFIG_INPUT is not set
-# CONFIG_INPUT_KEYBDEV is not set
-# CONFIG_INPUT_MOUSEDEV is not set
-# CONFIG_INPUT_JOYDEV is not set
-# CONFIG_INPUT_EVDEV is not set
+
+#
+# Userland interfaces
+#
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+# CONFIG_SERIO is not set
+
+#
+# Input Device Drivers
+#
 
 #
 # Character devices
 #
-# CONFIG_VT is not set
-# CONFIG_SERIAL is not set
-# CONFIG_SERIAL_EXTENDED is not set
 # CONFIG_SERIAL_NONSTANDARD is not set
 
 #
 # Serial drivers
 #
-# CONFIG_SERIAL_ANAKIN is not set
-# CONFIG_SERIAL_ANAKIN_CONSOLE is not set
-# CONFIG_SERIAL_AMBA is not set
-# CONFIG_SERIAL_AMBA_CONSOLE is not set
-# CONFIG_SERIAL_CLPS711X is not set
-# CONFIG_SERIAL_CLPS711X_CONSOLE is not set
-# CONFIG_SERIAL_21285 is not set
-# CONFIG_SERIAL_21285_OLD is not set
-# CONFIG_SERIAL_21285_CONSOLE is not set
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+# CONFIG_SERIAL_DZ is not set
 CONFIG_SERIAL_UART00=y
 CONFIG_SERIAL_UART00_CONSOLE=y
-# CONFIG_SERIAL_SA1100 is not set
-# CONFIG_SERIAL_SA1100_CONSOLE is not set
-# CONFIG_SERIAL_8250 is not set
-# CONFIG_SERIAL_8250_CONSOLE is not set
-# CONFIG_ATOMWIDE_SERIAL is not set
-# CONFIG_DUALSP_SERIAL is not set
-# CONFIG_SERIAL_8250_EXTENDED is not set
-# CONFIG_SERIAL_8250_MANY_PORTS is not set
-# CONFIG_SERIAL_8250_SHARE_IRQ is not set
-# CONFIG_SERIAL_8250_DETECT_IRQ is not set
-# CONFIG_SERIAL_8250_MULTIPORT is not set
-# CONFIG_SERIAL_8250_RSA is not set
 CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
 CONFIG_UNIX98_PTYS=y
@@ -466,33 +393,36 @@
 # CONFIG_I2C is not set
 
 #
+# I2C Hardware Sensors Mainboard support
+#
+
+#
+# I2C Hardware Sensors Chip support
+#
+
+#
 # L3 serial bus support
 #
 # CONFIG_L3 is not set
-# CONFIG_L3_ALGOBIT is not set
-# CONFIG_L3_BIT_SA1100_GPIO is not set
-# CONFIG_L3_SA1111 is not set
-# CONFIG_BIT_SA1100_GPIO is not set
 
 #
 # Mice
 #
 # CONFIG_BUSMOUSE is not set
-# CONFIG_MOUSE is not set
+# CONFIG_QIC02_TAPE is not set
 
 #
-# Joysticks
+# IPMI
 #
-# CONFIG_INPUT_GAMEPORT is not set
-# CONFIG_QIC02_TAPE is not set
+# CONFIG_IPMI_HANDLER is not set
 
 #
 # Watchdog Cards
 #
 # CONFIG_WATCHDOG is not set
-# CONFIG_INTEL_RNG is not set
 # CONFIG_NVRAM is not set
 # CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
@@ -503,6 +433,7 @@
 # CONFIG_FTAPE is not set
 # CONFIG_AGP is not set
 # CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
 
 #
 # Multimedia devices
@@ -516,50 +447,39 @@
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
 # CONFIG_REISERFS_FS is not set
-# CONFIG_REISERFS_CHECK is not set
-# CONFIG_REISERFS_PROC_INFO is not set
 # CONFIG_ADFS_FS is not set
-# CONFIG_ADFS_FS_RW is not set
 # CONFIG_AFFS_FS is not set
 # CONFIG_HFS_FS is not set
+# CONFIG_BEFS_FS is not set
 # CONFIG_BFS_FS is not set
 # CONFIG_EXT3_FS is not set
 # CONFIG_JBD is not set
-# CONFIG_JBD_DEBUG is not set
 # CONFIG_FAT_FS is not set
-# CONFIG_MSDOS_FS is not set
-# CONFIG_UMSDOS_FS is not set
-# CONFIG_VFAT_FS is not set
 # CONFIG_EFS_FS is not set
 # CONFIG_JFFS_FS is not set
 CONFIG_JFFS2_FS=y
 CONFIG_JFFS2_FS_DEBUG=0
+# CONFIG_JFFS2_FS_NAND is not set
 # CONFIG_CRAMFS is not set
 CONFIG_TMPFS=y
 CONFIG_RAMFS=y
 # CONFIG_ISO9660_FS is not set
-# CONFIG_JOLIET is not set
-# CONFIG_ZISOFS is not set
+# CONFIG_JFS_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_VXFS_FS is not set
 # CONFIG_NTFS_FS is not set
-# CONFIG_NTFS_DEBUG is not set
-# CONFIG_NTFS_RW is not set
 # CONFIG_HPFS_FS is not set
 CONFIG_PROC_FS=y
 # CONFIG_DEVFS_FS is not set
-# CONFIG_DEVFS_MOUNT is not set
-# CONFIG_DEVFS_DEBUG is not set
 CONFIG_DEVPTS_FS=y
 # CONFIG_QNX4FS_FS is not set
-# CONFIG_QNX4FS_RW is not set
 CONFIG_ROMFS_FS=y
 CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
 # CONFIG_SYSV_FS is not set
 # CONFIG_UDF_FS is not set
-# CONFIG_UDF_RW is not set
 # CONFIG_UFS_FS is not set
-# CONFIG_UFS_FS_WRITE is not set
+# CONFIG_XFS_FS is not set
 
 #
 # Network File Systems
@@ -568,107 +488,52 @@
 # CONFIG_INTERMEZZO_FS is not set
 CONFIG_NFS_FS=y
 # CONFIG_NFS_V3 is not set
+# CONFIG_NFS_V4 is not set
 # CONFIG_ROOT_NFS is not set
 # CONFIG_NFSD is not set
-# CONFIG_NFSD_V3 is not set
 CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_GSS is not set
 CONFIG_LOCKD=y
+# CONFIG_EXPORTFS is not set
+# CONFIG_CIFS is not set
 # CONFIG_SMB_FS is not set
 # CONFIG_NCP_FS is not set
-# CONFIG_NCPFS_PACKET_SIGNING is not set
-# CONFIG_NCPFS_IOCTL_LOCKING is not set
-# CONFIG_NCPFS_STRONG is not set
-# CONFIG_NCPFS_NFS_NS is not set
-# CONFIG_NCPFS_OS2_NS is not set
-# CONFIG_NCPFS_SMALLDOS is not set
-# CONFIG_NCPFS_NLS is not set
-# CONFIG_NCPFS_EXTRAS is not set
-# CONFIG_ZISOFS_FS is not set
-# CONFIG_ZLIB_FS_INFLATE is not set
+# CONFIG_AFS_FS is not set
 
 #
 # Partition Types
 #
 # CONFIG_PARTITION_ADVANCED is not set
-CONFIG_MSDOS_PARTITION=y
-# CONFIG_SMB_NLS is not set
-# CONFIG_NLS is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+# CONFIG_MDA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+
+#
+# Misc devices
+#
 
 #
 # Multimedia Capabilities Port drivers
 #
 # CONFIG_MCP is not set
-# CONFIG_MCP_SA1100 is not set
-# CONFIG_MCP_UCB1200 is not set
-# CONFIG_MCP_UCB1200_AUDIO is not set
-# CONFIG_MCP_UCB1200_TS is not set
+
+#
+# Console Switches
+#
+# CONFIG_SWITCHES is not set
 
 #
 # USB support
 #
-# CONFIG_USB is not set
-# CONFIG_USB_EHCI_HCD is not set
-# CONFIG_USB_UHCI is not set
-# CONFIG_USB_UHCI_ALT is not set
-# CONFIG_USB_OHCI is not set
-# CONFIG_USB_OHCI_SA1111 is not set
-# CONFIG_USB_AUDIO is not set
-# CONFIG_USB_BLUETOOTH is not set
-# CONFIG_USB_STORAGE is not set
-# CONFIG_USB_STORAGE_DEBUG is not set
-# CONFIG_USB_STORAGE_DATAFAB is not set
-# CONFIG_USB_STORAGE_FREECOM is not set
-# CONFIG_USB_STORAGE_ISD200 is not set
-# CONFIG_USB_STORAGE_DPCM is not set
-# CONFIG_USB_STORAGE_HP8200e is not set
-# CONFIG_USB_STORAGE_SDDR09 is not set
-# CONFIG_USB_STORAGE_JUMPSHOT is not set
-# CONFIG_USB_ACM is not set
-# CONFIG_USB_PRINTER is not set
-# CONFIG_USB_DC2XX is not set
-# CONFIG_USB_MDC800 is not set
-# CONFIG_USB_SCANNER is not set
-# CONFIG_USB_MICROTEK is not set
-# CONFIG_USB_HPUSBSCSI is not set
-# CONFIG_USB_PEGASUS is not set
-# CONFIG_USB_KAWETH is not set
-# CONFIG_USB_CATC is not set
-# CONFIG_USB_CDCETHER is not set
-# CONFIG_USB_USBNET is not set
-# CONFIG_USB_USS720 is not set
-
-#
-# USB Serial Converter support
-#
-# CONFIG_USB_SERIAL is not set
-# CONFIG_USB_SERIAL_GENERIC is not set
-# CONFIG_USB_SERIAL_BELKIN is not set
-# CONFIG_USB_SERIAL_WHITEHEAT is not set
-# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set
-# CONFIG_USB_SERIAL_EMPEG is not set
-# CONFIG_USB_SERIAL_FTDI_SIO is not set
-# CONFIG_USB_SERIAL_VISOR is not set
-# CONFIG_USB_SERIAL_IPAQ is not set
-# CONFIG_USB_SERIAL_IR is not set
-# CONFIG_USB_SERIAL_EDGEPORT is not set
-# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set
-# CONFIG_USB_SERIAL_KEYSPAN is not set
-# CONFIG_USB_SERIAL_KEYSPAN_USA28 is not set
-# CONFIG_USB_SERIAL_KEYSPAN_USA28X is not set
-# CONFIG_USB_SERIAL_KEYSPAN_USA28XA is not set
-# CONFIG_USB_SERIAL_KEYSPAN_USA28XB is not set
-# CONFIG_USB_SERIAL_KEYSPAN_USA19 is not set
-# CONFIG_USB_SERIAL_KEYSPAN_USA18X is not set
-# CONFIG_USB_SERIAL_KEYSPAN_USA19W is not set
-# CONFIG_USB_SERIAL_KEYSPAN_USA49W is not set
-# CONFIG_USB_SERIAL_MCT_U232 is not set
-# CONFIG_USB_SERIAL_KLSI is not set
-# CONFIG_USB_SERIAL_PL2303 is not set
-# CONFIG_USB_SERIAL_CYBERJACK is not set
-# CONFIG_USB_SERIAL_XIRCOM is not set
-# CONFIG_USB_SERIAL_OMNINET is not set
-# CONFIG_USB_RIO500 is not set
-# CONFIG_USB_AUERSWALD is not set
 
 #
 # Bluetooth support
@@ -681,19 +546,21 @@
 CONFIG_FRAME_POINTER=y
 # CONFIG_DEBUG_USER is not set
 # CONFIG_DEBUG_INFO is not set
-# CONFIG_NO_PGT_CACHE is not set
 # CONFIG_DEBUG_KERNEL is not set
-# CONFIG_DEBUG_SLAB is not set
-# CONFIG_MAGIC_SYSRQ is not set
-# CONFIG_DEBUG_SPINLOCK is not set
-# CONFIG_DEBUG_WAITQ is not set
-# CONFIG_DEBUG_BUGVERBOSE is not set
-# CONFIG_DEBUG_ERRORS is not set
-# CONFIG_DEBUG_LL is not set
-# CONFIG_DEBUG_DC21285_PORT is not set
-# CONFIG_DEBUG_CLPS711X_UART2 is not set
+
+#
+# Security options
+#
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
 
 #
 # Library routines
 #
 # CONFIG_CRC32 is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
diff -Nru a/arch/arm/kernel/init_task.c b/arch/arm/kernel/init_task.c
--- a/arch/arm/kernel/init_task.c	Mon Feb 17 14:57:28 2003
+++ b/arch/arm/kernel/init_task.c	Mon Feb 17 14:57:28 2003
@@ -13,6 +13,7 @@
 static struct fs_struct init_fs = INIT_FS;
 static struct files_struct init_files = INIT_FILES;
 static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
+static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
 struct mm_struct init_mm = INIT_MM(init_mm);
 
 /*
diff -Nru a/arch/arm/kernel/irq.c b/arch/arm/kernel/irq.c
--- a/arch/arm/kernel/irq.c	Mon Feb 17 14:57:26 2003
+++ b/arch/arm/kernel/irq.c	Mon Feb 17 14:57:26 2003
@@ -29,6 +29,7 @@
 #include <linux/init.h>
 #include <linux/seq_file.h>
 #include <linux/errno.h>
+#include <linux/list.h>
 
 #include <asm/irq.h>
 #include <asm/system.h>
@@ -45,6 +46,7 @@
 
 static volatile unsigned long irq_err_count;
 static spinlock_t irq_controller_lock;
+static LIST_HEAD(irq_pending);
 
 struct irqdesc irq_desc[NR_IRQS];
 void (*init_arch_irq)(void) __initdata = NULL;
@@ -69,9 +71,10 @@
 };
 
 static struct irqdesc bad_irq_desc = {
-	.chip	= &bad_chip,
-	.handle = do_bad_IRQ,
-	.depth	= 1,
+	.chip		= &bad_chip,
+	.handle		= do_bad_IRQ,
+	.pend		= LIST_HEAD_INIT(bad_irq_desc.pend),
+	.disable_depth	= 1,
 };
 
 /**
@@ -90,6 +93,7 @@
 
 	spin_lock_irqsave(&irq_controller_lock, flags);
 	desc->disable_depth++;
+	list_del_init(&desc->pend);
 	spin_unlock_irqrestore(&irq_controller_lock, flags);
 }
 
@@ -122,9 +126,11 @@
 		 * from here since the caller might be in an
 		 * interrupt-protected region.
 		 */
-		if (desc->pending) {
+		if (desc->pending && list_empty(&desc->pend)) {
 			desc->pending = 0;
-			desc->chip->rerun(irq);
+			if (!desc->chip->retrigger ||
+			    desc->chip->retrigger(irq))
+				list_add(&desc->pend, &irq_pending);
 		}
 	}
 	spin_unlock_irqrestore(&irq_controller_lock, flags);
@@ -346,6 +352,40 @@
 	}
 }
 
+static void do_pending_irqs(struct pt_regs *regs)
+{
+	struct list_head head, *l, *n;
+
+	do {
+		struct irqdesc *desc;
+
+		/*
+		 * First, take the pending interrupts off the list.
+		 * The act of calling the handlers may add some IRQs
+		 * back onto the list.
+		 */
+		head = irq_pending;
+		INIT_LIST_HEAD(&irq_pending);
+		head.next->prev = &head;
+		head.prev->next = &head;
+
+		/*
+		 * Now run each entry.  We must delete it from our
+		 * list before calling the handler.
+		 */
+		list_for_each_safe(l, n, &head) {
+			desc = list_entry(l, struct irqdesc, pend);
+			list_del_init(&desc->pend);
+			desc->handle(desc - irq_desc, desc, regs);
+		}
+
+		/*
+		 * The list must be empty.
+		 */
+		BUG_ON(!list_empty(&head));
+	} while (!list_empty(&irq_pending));
+}
+
 /*
  * do_IRQ handles all hardware IRQ's.  Decoded IRQs should not
  * come via this function.  Instead, they should provide their
@@ -365,6 +405,13 @@
 	irq_enter();
 	spin_lock(&irq_controller_lock);
 	desc->handle(irq, desc, regs);
+
+	/*
+	 * Now re-run any pending interrupts.
+	 */
+	if (!list_empty(&irq_pending))
+		do_pending_irqs(regs);
+
 	spin_unlock(&irq_controller_lock);
 	irq_exit();
 }
@@ -740,8 +787,10 @@
 	extern void init_dma(void);
 	int irq;
 
-	for (irq = 0, desc = irq_desc; irq < NR_IRQS; irq++, desc++)
+	for (irq = 0, desc = irq_desc; irq < NR_IRQS; irq++, desc++) {
 		*desc = bad_irq_desc;
+		INIT_LIST_HEAD(&desc->pend);
+	}
 
 	init_arch_irq();
 	init_dma();
diff -Nru a/arch/arm/kernel/ptrace.c b/arch/arm/kernel/ptrace.c
--- a/arch/arm/kernel/ptrace.c	Mon Feb 17 14:57:26 2003
+++ b/arch/arm/kernel/ptrace.c	Mon Feb 17 14:57:26 2003
@@ -446,7 +446,7 @@
  * Ensure no single-step breakpoint is pending.  Returns non-zero
  * value if child was being single-stepped.
  */
-void __ptrace_cancel_bpt(struct task_struct *child)
+void ptrace_cancel_bpt(struct task_struct *child)
 {
 	int i, nsaved = child->thread.debug.nsaved;
 
@@ -468,7 +468,8 @@
  */
 void ptrace_disable(struct task_struct *child)
 {
-	__ptrace_cancel_bpt(child);
+	child->ptrace &= ~PT_SINGLESTEP;
+	ptrace_cancel_bpt(child);
 }
 
 /*
@@ -486,7 +487,7 @@
 	if (tsk->thread.debug.nsaved == 0)
 		printk(KERN_ERR "ptrace: bogus breakpoint trap\n");
 
-	__ptrace_cancel_bpt(tsk);
+	ptrace_cancel_bpt(tsk);
 
 	info.si_signo = SIGTRAP;
 	info.si_errno = 0;
@@ -637,7 +638,8 @@
 				clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
 			child->exit_code = data;
 			/* make sure single-step breakpoint is gone. */
-			__ptrace_cancel_bpt(child);
+			child->ptrace &= ~PT_SINGLESTEP;
+			ptrace_cancel_bpt(child);
 			wake_up_process(child);
 			ret = 0;
 			break;
@@ -649,7 +651,8 @@
 		 */
 		case PTRACE_KILL:
 			/* make sure single-step breakpoint is gone. */
-			__ptrace_cancel_bpt(child);
+			child->ptrace &= ~PT_SINGLESTEP;
+			ptrace_cancel_bpt(child);
 			if (child->state != TASK_ZOMBIE) {
 				child->exit_code = SIGKILL;
 				wake_up_process(child);
@@ -664,7 +667,7 @@
 			ret = -EIO;
 			if ((unsigned long) data > _NSIG)
 				break;
-			child->thread.debug.nsaved = -1;
+			child->ptrace |= PT_SINGLESTEP;
 			clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
 			child->exit_code = data;
 			/* give it a chance to run. */
diff -Nru a/arch/arm/kernel/ptrace.h b/arch/arm/kernel/ptrace.h
--- a/arch/arm/kernel/ptrace.h	Mon Feb 17 14:57:27 2003
+++ b/arch/arm/kernel/ptrace.h	Mon Feb 17 14:57:27 2003
@@ -1,26 +1,12 @@
 /*
  *  linux/arch/arm/kernel/ptrace.h
  *
- *  Copyright (C) 2000-2002 Russell King
+ *  Copyright (C) 2000-2003 Russell King
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
-extern void __ptrace_cancel_bpt(struct task_struct *);
+extern void ptrace_cancel_bpt(struct task_struct *);
 extern void ptrace_set_bpt(struct task_struct *);
 extern void ptrace_break(struct task_struct *, struct pt_regs *);
-
-/*
- * Clear a breakpoint, if one exists.
- */
-static inline int ptrace_cancel_bpt(struct task_struct *tsk)
-{
-	int nsaved = tsk->thread.debug.nsaved;
-
-	if (nsaved)
-		__ptrace_cancel_bpt(tsk);
-
-	return nsaved;
-}
-
diff -Nru a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c
--- a/arch/arm/kernel/signal.c	Mon Feb 17 14:57:26 2003
+++ b/arch/arm/kernel/signal.c	Mon Feb 17 14:57:26 2003
@@ -216,8 +216,10 @@
 		goto badframe;
 
 	/* Send SIGTRAP if we're single-stepping */
-	if (ptrace_cancel_bpt(current))
+	if (current->ptrace & PT_SINGLESTEP) {
+		ptrace_cancel_bpt(current);
 		send_sig(SIGTRAP, current, 1);
+	}
 
 	return regs->ARM_r0;
 
@@ -256,8 +258,10 @@
 		goto badframe;
 
 	/* Send SIGTRAP if we're single-stepping */
-	if (ptrace_cancel_bpt(current))
+	if (current->ptrace & PT_SINGLESTEP) {
+		ptrace_cancel_bpt(current);
 		send_sig(SIGTRAP, current, 1);
+	}
 
 	return regs->ARM_r0;
 
@@ -441,19 +445,48 @@
 	return err;
 }
 
+static inline void restart_syscall(struct pt_regs *regs)
+{
+	regs->ARM_r0 = regs->ARM_ORIG_r0;
+	regs->ARM_pc -= thumb_mode(regs) ? 2 : 4;
+}
+
 /*
  * OK, we're invoking a handler
  */	
 static void
-handle_signal(unsigned long sig, struct k_sigaction *ka,
-	      siginfo_t *info, sigset_t *oldset, struct pt_regs * regs)
+handle_signal(unsigned long sig, siginfo_t *info, sigset_t *oldset,
+	      struct pt_regs * regs, int syscall)
 {
 	struct thread_info *thread = current_thread_info();
 	struct task_struct *tsk = current;
+	struct k_sigaction *ka = &tsk->sighand->action[sig-1];
 	int usig = sig;
 	int ret;
 
 	/*
+	 * If we were from a system call, check for system call restarting...
+	 */
+	if (syscall) {
+		switch (regs->ARM_r0) {
+		case -ERESTART_RESTARTBLOCK:
+			current_thread_info()->restart_block.fn =
+				do_no_restart_syscall;
+		case -ERESTARTNOHAND:
+			regs->ARM_r0 = -EINTR;
+			break;
+		case -ERESTARTSYS:
+			if (!(ka->sa.sa_flags & SA_RESTART)) {
+				regs->ARM_r0 = -EINTR;
+				break;
+			}
+			/* fallthrough */
+		case -ERESTARTNOINTR:
+			restart_syscall(regs);
+		}
+	}
+
+	/*
 	 * translate the signal
 	 */
 	if (usig < 32 && thread->exec_domain && thread->exec_domain->signal_invmap)
@@ -504,7 +537,7 @@
 static int do_signal(sigset_t *oldset, struct pt_regs *regs, int syscall)
 {
 	siginfo_t info;
-	int single_stepping;
+	int signr;
 
 	/*
 	 * We want the common case to go fast, which
@@ -515,130 +548,14 @@
 	if (!user_mode(regs))
 		return 0;
 
-	single_stepping = ptrace_cancel_bpt(current);
-
-	for (;;) {
-		unsigned long signr = 0;
-		struct k_sigaction *ka;
-
-		spin_lock_irq(&current->sighand->siglock);
-		signr = dequeue_signal(current, &current->blocked, &info);
-		spin_unlock_irq(&current->sighand->siglock);
-
-		if (!signr)
-			break;
+	if (current->ptrace & PT_SINGLESTEP)
+		ptrace_cancel_bpt(current);
 
-		if ((current->ptrace & PT_PTRACED) && signr != SIGKILL) {
-			/* Let the debugger run.  */
-			current->exit_code = signr;
-			set_current_state(TASK_STOPPED);
-			notify_parent(current, SIGCHLD);
-			schedule();
-			single_stepping |= ptrace_cancel_bpt(current);
-
-			/* We're back.  Did the debugger cancel the sig?  */
-			signr = current->exit_code;
-			if (signr == 0)
-				continue;
-			current->exit_code = 0;
-
-			/* The debugger continued.  Ignore SIGSTOP.  */
-			if (signr == SIGSTOP)
-				continue;
-
-			/* Update the siginfo structure.  Is this good? */
-			if (signr != info.si_signo) {
-				info.si_signo = signr;
-				info.si_errno = 0;
-				info.si_code = SI_USER;
-				info.si_pid = current->parent->pid;
-				info.si_uid = current->parent->uid;
-			}
-
-			/* If the (new) signal is now blocked, requeue it.  */
-			if (sigismember(&current->blocked, signr)) {
-				send_sig_info(signr, &info, current);
-				continue;
-			}
-		}
-
-		ka = &current->sig->action[signr-1];
-		if (ka->sa.sa_handler == SIG_IGN) {
-			if (signr != SIGCHLD)
-				continue;
-			/* Check for SIGCHLD: it's special.  */
-			while (sys_wait4(-1, NULL, WNOHANG, NULL) > 0)
-				/* nothing */;
-			continue;
-		}
-
-		if (ka->sa.sa_handler == SIG_DFL) {
-			int exit_code = signr;
-
-			/* Init gets no signals it doesn't want.  */
-			if (current->pid == 1)
-				continue;
-
-			switch (signr) {
-			case SIGCONT: case SIGCHLD: case SIGWINCH: case SIGURG:
-				continue;
-
-			case SIGTSTP: case SIGTTIN: case SIGTTOU:
-				if (is_orphaned_pgrp(current->pgrp))
-					continue;
-				/* FALLTHRU */
-
-			case SIGSTOP: {
-				struct signal_struct *sig;
-				set_current_state(TASK_STOPPED);
-				current->exit_code = signr;
-				sig = current->parent->sig;
-				if (sig && !(sig->action[SIGCHLD-1].sa.sa_flags & SA_NOCLDSTOP))
-					notify_parent(current, SIGCHLD);
-				schedule();
-				single_stepping |= ptrace_cancel_bpt(current);
-				continue;
-			}
-
-			case SIGQUIT: case SIGILL: case SIGTRAP:
-			case SIGABRT: case SIGFPE: case SIGSEGV:
-			case SIGBUS: case SIGSYS: case SIGXCPU: case SIGXFSZ:
-				if (do_coredump(signr, exit_code, regs))
-					exit_code |= 0x80;
-				/* FALLTHRU */
-
-			default:
-				sig_exit(signr, exit_code, &info);
-				/* NOTREACHED */
-			}
-		}
-
-		/* Are we from a system call? */
-		if (syscall) {
-			/* If so, check system call restarting.. */
-			switch (regs->ARM_r0) {
-			case -ERESTART_RESTARTBLOCK:
-				current_thread_info()->restart_block.fn =
-					do_no_restart_syscall;
-			case -ERESTARTNOHAND:
-				regs->ARM_r0 = -EINTR;
-				break;
-
-			case -ERESTARTSYS:
-				if (!(ka->sa.sa_flags & SA_RESTART)) {
-					regs->ARM_r0 = -EINTR;
-					break;
-				}
-				/* fallthrough */
-			case -ERESTARTNOINTR:
-				regs->ARM_r0 = regs->ARM_ORIG_r0;
-				regs->ARM_pc -= 4;
-			}
-		}
-		/* Whee!  Actually deliver the signal.  */
-		handle_signal(signr, ka, &info, oldset, regs);
-		if (single_stepping)
-		    	ptrace_set_bpt(current);
+	signr = get_signal_to_deliver(&info, regs, NULL);
+	if (signr > 0) {
+		handle_signal(signr, &info, oldset, regs, syscall);
+		if (current->ptrace & PT_SINGLESTEP)
+			ptrace_set_bpt(current);
 		return 1;
 	}
 
@@ -668,11 +585,10 @@
 		if (regs->ARM_r0 == -ERESTARTNOHAND ||
 		    regs->ARM_r0 == -ERESTARTSYS ||
 		    regs->ARM_r0 == -ERESTARTNOINTR) {
-			regs->ARM_r0 = regs->ARM_ORIG_r0;
-			regs->ARM_pc -= 4;
+			restart_syscall(regs);
 		}
 	}
-	if (single_stepping)
+	if (current->ptrace & PT_SINGLESTEP)
 		ptrace_set_bpt(current);
 	return 0;
 }
diff -Nru a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c
--- a/arch/arm/kernel/traps.c	Mon Feb 17 14:57:27 2003
+++ b/arch/arm/kernel/traps.c	Mon Feb 17 14:57:27 2003
@@ -52,9 +52,14 @@
 
 void dump_backtrace_entry(unsigned long where, unsigned long from)
 {
+#ifdef CONFIG_KALLSYMS
+	printk("[<%08lx>] ", where);
+	print_symbol("(%s) ", where);
+	printk("from [<%08lx>] ", from);
+	print_symbol("(%s)\n", from);
+#else
 	printk("Function entered at [<%08lx>] from [<%08lx>]\n", where, from);
-	print_symbol("  %s", where);
-	printk("\n");
+#endif
 }
 
 /*
@@ -503,11 +508,11 @@
 	die_if_kernel("unknown data abort code", regs, instr);
 }
 
-void __bug(const char *file, int line, void *data)
+volatile void __bug(const char *file, int line, void *data)
 {
 	printk(KERN_CRIT"kernel BUG at %s:%d!", file, line);
 	if (data)
-		printk(KERN_CRIT" - extra data = %p", data);
+		printk(" - extra data = %p", data);
 	printk("\n");
 	*(int *)0 = 0;
 }
diff -Nru a/arch/arm/lib/backtrace.S b/arch/arm/lib/backtrace.S
--- a/arch/arm/lib/backtrace.S	Mon Feb 17 14:57:27 2003
+++ b/arch/arm/lib/backtrace.S	Mon Feb 17 14:57:27 2003
@@ -82,11 +82,20 @@
 		teq	r3, r2
 		bleq	.Ldumpstm
 
-		teq	frame, next
-		movne	frame, next
-		teqne	frame, #0
-		bne	3b
-		LOADREGS(fd, sp!, {r4 - r8, pc})
+		/*
+		 * A zero next framepointer means we're done.
+		 */
+		teq	next, #0
+		LOADREGS(eqfd, sp!, {r4 - r8, pc})
+
+		/*
+		 * The next framepointer must be above the
+		 * current framepointer.
+		 */
+		cmp	next, frame
+		mov	frame, next
+		bhi	3b
+		b	1007f
 
 /*
  * Fixup for LDMDB
diff -Nru a/arch/arm/mach-epxa10db/irq.c b/arch/arm/mach-epxa10db/irq.c
--- a/arch/arm/mach-epxa10db/irq.c	Mon Feb 17 14:57:27 2003
+++ b/arch/arm/mach-epxa10db/irq.c	Mon Feb 17 14:57:27 2003
@@ -19,6 +19,9 @@
  */
 #include <linux/init.h>
 #include <linux/ioport.h>
+#include <linux/stddef.h>
+#include <linux/timer.h>
+#include <linux/list.h>
 #include <asm/io.h>
 #include <asm/hardware.h>
 #include <asm/irq.h>
diff -Nru a/arch/arm/mach-footbridge/irq.c b/arch/arm/mach-footbridge/irq.c
--- a/arch/arm/mach-footbridge/irq.c	Mon Feb 17 14:57:28 2003
+++ b/arch/arm/mach-footbridge/irq.c	Mon Feb 17 14:57:28 2003
@@ -15,6 +15,7 @@
  *   16-Mar-1999 RMK	Added autodetect of ISA PICs
  */
 #include <linux/ioport.h>
+#include <linux/list.h>
 #include <linux/init.h>
 
 #include <asm/mach/irq.h>
diff -Nru a/arch/arm/mach-footbridge/isa-irq.c b/arch/arm/mach-footbridge/isa-irq.c
--- a/arch/arm/mach-footbridge/isa-irq.c	Mon Feb 17 14:57:28 2003
+++ b/arch/arm/mach-footbridge/isa-irq.c	Mon Feb 17 14:57:28 2003
@@ -16,6 +16,7 @@
  */
 #include <linux/ioport.h>
 #include <linux/interrupt.h>
+#include <linux/list.h>
 #include <linux/init.h>
 
 #include <asm/mach/irq.h>
diff -Nru a/arch/arm/mach-iop310/iop310-irq.c b/arch/arm/mach-iop310/iop310-irq.c
--- a/arch/arm/mach-iop310/iop310-irq.c	Mon Feb 17 14:57:28 2003
+++ b/arch/arm/mach-iop310/iop310-irq.c	Mon Feb 17 14:57:28 2003
@@ -15,6 +15,7 @@
  */
 #include <linux/init.h>
 #include <linux/interrupt.h>
+#include <linux/list.h>
 
 #include <asm/mach/irq.h>
 #include <asm/irq.h>
diff -Nru a/arch/arm/mach-iop310/iop310-pci.c b/arch/arm/mach-iop310/iop310-pci.c
--- a/arch/arm/mach-iop310/iop310-pci.c	Mon Feb 17 14:57:27 2003
+++ b/arch/arm/mach-iop310/iop310-pci.c	Mon Feb 17 14:57:27 2003
@@ -360,6 +360,8 @@
 	if (!res)
 		panic("PCI: unable to alloc resources");
 
+	memset(res, 0, sizeof(struct resource) * 2);
+
 	switch (nr) {
 	case 0:
 		res[0].start = IOP310_PCIPRI_LOWER_IO + 0x6e000000;
diff -Nru a/arch/arm/mach-iop310/iq80310-irq.c b/arch/arm/mach-iop310/iq80310-irq.c
--- a/arch/arm/mach-iop310/iq80310-irq.c	Mon Feb 17 14:57:27 2003
+++ b/arch/arm/mach-iop310/iq80310-irq.c	Mon Feb 17 14:57:27 2003
@@ -15,6 +15,7 @@
  *     Fixes for various revision boards - DS
  */
 #include <linux/init.h>
+#include <linux/list.h>
 
 #include <asm/irq.h>
 #include <asm/mach/irq.h>
diff -Nru a/arch/arm/mach-iop310/xs80200-irq.c b/arch/arm/mach-iop310/xs80200-irq.c
--- a/arch/arm/mach-iop310/xs80200-irq.c	Mon Feb 17 14:57:27 2003
+++ b/arch/arm/mach-iop310/xs80200-irq.c	Mon Feb 17 14:57:27 2003
@@ -11,6 +11,7 @@
  * published by the Free Software Foundation.
  */
 #include <linux/init.h>
+#include <linux/list.h>
 
 #include <asm/mach/irq.h>
 #include <asm/irq.h>
diff -Nru a/arch/arm/mach-pxa/irq.c b/arch/arm/mach-pxa/irq.c
--- a/arch/arm/mach-pxa/irq.c	Mon Feb 17 14:57:28 2003
+++ b/arch/arm/mach-pxa/irq.c	Mon Feb 17 14:57:28 2003
@@ -86,19 +86,6 @@
 }
 
 /*
- * Since we can't actually physically mask edge triggered interrupts
- * without the risk of missing transitions, we therefore logically mask
- * them and defer their processing through tis function.
- */
-
-static void pxa_manual_rerun(unsigned int irq)
-{
-	struct pt_regs regs;
-	memset(&regs, 0, sizeof(regs));
-	irq_desc[irq].handle(irq, &irq_desc[irq], &regs);
-}
-
-/*
  * GPIO IRQs must be acknoledged.  This is for GPIO 0 and 1.
  */
 
@@ -111,7 +98,6 @@
 	.ack		= pxa_ack_low_gpio,
 	.mask		= pxa_mask_irq,
 	.unmask		= pxa_unmask_irq,
-	.rerun		= pxa_manual_rerun,
 	.type		= pxa_gpio_irq_type,
 };
 
diff -Nru a/arch/arm/mach-rpc/irq.c b/arch/arm/mach-rpc/irq.c
--- a/arch/arm/mach-rpc/irq.c	Mon Feb 17 14:57:26 2003
+++ b/arch/arm/mach-rpc/irq.c	Mon Feb 17 14:57:26 2003
@@ -1,4 +1,5 @@
 #include <linux/init.h>
+#include <linux/list.h>
 
 #include <asm/mach/irq.h>
 #include <asm/hardware/iomd.h>
diff -Nru a/arch/arm/mach-sa1100/irq.c b/arch/arm/mach-sa1100/irq.c
--- a/arch/arm/mach-sa1100/irq.c	Mon Feb 17 14:57:28 2003
+++ b/arch/arm/mach-sa1100/irq.c	Mon Feb 17 14:57:28 2003
@@ -13,6 +13,7 @@
 #include <linux/module.h>
 #include <linux/ioport.h>
 #include <linux/ptrace.h>
+#include <linux/device.h>
 
 #include <asm/hardware.h>
 #include <asm/irq.h>
@@ -24,20 +25,12 @@
 /*
  * SA1100 GPIO edge detection for IRQs:
  * IRQs are generated on Falling-Edge, Rising-Edge, or both.
- * This must be called *before* the appropriate IRQ is registered.
  * Use this instead of directly setting GRER/GFER.
  */
 static int GPIO_IRQ_rising_edge;
 static int GPIO_IRQ_falling_edge;
 static int GPIO_IRQ_mask = (1 << 11) - 1;
 
-static void sa1100_manual_rerun(unsigned int irq)
-{
-	struct pt_regs regs;
-	memset(&regs, 0, sizeof(regs));
-	irq_desc[irq].handle(irq, &irq_desc[irq], &regs);
-}
-
 /*
  * To get the GPIO number from an IRQ number
  */
@@ -105,7 +98,6 @@
 	.ack		= sa1100_low_gpio_ack,
 	.mask		= sa1100_low_gpio_mask,
 	.unmask		= sa1100_low_gpio_unmask,
-	.rerun		= sa1100_manual_rerun,
 	.type		= sa1100_gpio_type,
 	.wake		= sa1100_low_gpio_wake,
 };
@@ -189,7 +181,6 @@
 	.ack		= sa1100_high_gpio_ack,
 	.mask		= sa1100_high_gpio_mask,
 	.unmask		= sa1100_high_gpio_unmask,
-	.rerun		= sa1100_manual_rerun,
 	.type		= sa1100_gpio_type,
 	.wake		= sa1100_high_gpio_wake,
 };
@@ -212,7 +203,6 @@
 	.ack		= sa1100_mask_irq,
 	.mask		= sa1100_mask_irq,
 	.unmask		= sa1100_unmask_irq,
-	/* rerun should never be called */
 };
 
 static struct resource irq_resource = {
@@ -267,10 +257,4 @@
 	 */
 	set_irq_chip(IRQ_GPIO11_27, &sa1100_normal_chip);
 	set_irq_chained_handler(IRQ_GPIO11_27, sa1100_high_gpio_handler);
-
-	/*
-	 * We generally don't want the LCD IRQ being
-	 * enabled as soon as we request it.
-	 */
-	set_irq_flags(IRQ_LCD, IRQF_VALID/* | IRQF_NOAUTOEN*/);
 }
diff -Nru a/arch/arm/mach-sa1100/xp860.c b/arch/arm/mach-sa1100/xp860.c
--- a/arch/arm/mach-sa1100/xp860.c	Mon Feb 17 14:57:27 2003
+++ b/arch/arm/mach-sa1100/xp860.c	Mon Feb 17 14:57:27 2003
@@ -15,9 +15,9 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 #include <asm/mach/serial_sa1100.h>
+#include <asm/hardware/sa1111.h>
 
 #include "generic.h"
-#include "sa1111.h"
 
 
 static void xp860_power_off(void)
diff -Nru a/arch/arm/mm/consistent.c b/arch/arm/mm/consistent.c
--- a/arch/arm/mm/consistent.c	Mon Feb 17 14:57:28 2003
+++ b/arch/arm/mm/consistent.c	Mon Feb 17 14:57:28 2003
@@ -83,7 +83,7 @@
 	struct vm_region *c;
 
 	printk("Consistent Allocation Map (%s):\n", fn);
-	list_for_each_entry(c, &head->list, vm_list) {
+	list_for_each_entry(c, &head->vm_list, vm_list) {
 		printk(" %p:  %08lx - %08lx   (0x%08x)\n", c,
 		       c->vm_start, c->vm_end, c->vm_end - c->vm_start);
 	}
diff -Nru a/arch/arm/mm/proc-xscale.S b/arch/arm/mm/proc-xscale.S
--- a/arch/arm/mm/proc-xscale.S	Mon Feb 17 14:57:28 2003
+++ b/arch/arm/mm/proc-xscale.S	Mon Feb 17 14:57:28 2003
@@ -678,7 +678,7 @@
 	mcr	p15, 0, r0, c15, c1, 0		@ affects USR or SVC modes
 	mrc	p15, 0, r0, c1, c0, 0		@ get control register
 	bic	r0, r0, #0x0200			@ .... ..R. .... ....
-	bic	r0, r0, #0x0082			@ .... .... B... ..A.
+	bic	r0, r0, #0x0002			@ .... .... .... ..A.
 	orr	r0, r0, #0x0005			@ .... .... .... .C.M
 	orr	r0, r0, #0x3900			@ ..VI Z..S .... ....
 	mov	pc, lr
diff -Nru a/arch/arm/vmlinux-armv.lds.in b/arch/arm/vmlinux-armv.lds.in
--- a/arch/arm/vmlinux-armv.lds.in	Mon Feb 17 14:57:27 2003
+++ b/arch/arm/vmlinux-armv.lds.in	Mon Feb 17 14:57:27 2003
@@ -7,7 +7,11 @@
 	
 OUTPUT_ARCH(arm)
 ENTRY(stext)
+#ifndef __ARMEB__
 jiffies = jiffies_64;
+#else
+jiffies = jiffies_64 + 4;
+#endif
 SECTIONS
 {
 	. = TEXTADDR;
diff -Nru a/arch/cris/drivers/eeprom.c b/arch/cris/drivers/eeprom.c
--- a/arch/cris/drivers/eeprom.c	Mon Feb 17 14:57:27 2003
+++ b/arch/cris/drivers/eeprom.c	Mon Feb 17 14:57:27 2003
@@ -207,7 +207,7 @@
      * it will mirror the address space:
      * 1. We read two locations (that are mirrored), 
      *    if the content differs * it's a 16kB EEPROM.
-     * 2. if it doesn't differ - write diferent value to one of the locations,
+     * 2. if it doesn't differ - write different value to one of the locations,
      *    check the other - if content still is the same it's a 2k EEPROM,
      *    restore original data.
      */
diff -Nru a/arch/i386/Kconfig b/arch/i386/Kconfig
--- a/arch/i386/Kconfig	Mon Feb 17 14:57:27 2003
+++ b/arch/i386/Kconfig	Mon Feb 17 14:57:27 2003
@@ -969,7 +969,7 @@
 	  If in doubt, say N.
 
 config CPU_FREQ_PROC_INTF
-	bool "/proc/cpufreq interface (DEPRECATED)"
+	tristate "/proc/cpufreq interface (DEPRECATED)"
 	depends on CPU_FREQ && PROC_FS
 	help
 	  This enables the /proc/cpufreq interface for controlling
@@ -994,9 +994,19 @@
 
 	  If in doubt, say N.
 
+config CPU_FREQ_TABLE
+       tristate "CPU frequency table helpers"
+       depends on CPU_FREQ
+       default y
+       help
+         Many CPUFreq drivers use these helpers, so only say N here if
+	 the CPUFreq driver of your choice doesn't need these helpers.
+
+	 If in doubt, say Y.
+
 config X86_ACPI_CPUFREQ
 	tristate "ACPI Processor P-States driver"
-	depends on CPU_FREQ && ACPI_PROCESSOR
+	depends on CPU_FREQ_TABLE && ACPI_PROCESSOR
 	help
 	  This driver adds a CPUFreq driver which utilizes the ACPI
 	  Processor Performance States.
@@ -1007,7 +1017,7 @@
 
 config X86_POWERNOW_K6
 	tristate "AMD Mobile K6-2/K6-3 PowerNow!"
-	depends on CPU_FREQ
+	depends on CPU_FREQ_TABLE
 	help
 	  This adds the CPUFreq driver for mobile AMD K6-2+ and mobile
 	  AMD K6-3+ processors.
@@ -1018,7 +1028,7 @@
 
 config X86_POWERNOW_K7
 	tristate "AMD Mobile Athlon/Duron PowerNow!"
-	depends on CPU_FREQ
+	depends on CPU_FREQ_TABLE
 	help
 	  This adds the CPUFreq driver for mobile AMD K7 mobile processors.
 
@@ -1028,7 +1038,7 @@
 
 config ELAN_CPUFREQ
 	tristate "AMD Elan"
-	depends on CPU_FREQ && MELAN
+	depends on CPU_FREQ_TABLE && MELAN
 	---help---
 	  This adds the CPUFreq driver for AMD Elan SC400 and SC410
 	  processors.
@@ -1055,7 +1065,7 @@
 
 config X86_SPEEDSTEP
 	tristate "Intel Speedstep"
-	depends on CPU_FREQ
+	depends on CPU_FREQ_TABLE
 	help
 	  This adds the CPUFreq driver for certain mobile Intel Pentium III
 	  (Coppermine), all mobile Intel Pentium III-M (Tulatin) and all
@@ -1067,7 +1077,7 @@
 
 config X86_P4_CLOCKMOD
 	tristate "Intel Pentium 4 clock modulation"
-	depends on CPU_FREQ
+	depends on CPU_FREQ_TABLE
 	help
 	  This adds the CPUFreq driver for Intel Pentium 4 / XEON
 	  processors.
diff -Nru a/arch/i386/kernel/cpu/mtrr/generic.c b/arch/i386/kernel/cpu/mtrr/generic.c
--- a/arch/i386/kernel/cpu/mtrr/generic.c	Mon Feb 17 14:57:27 2003
+++ b/arch/i386/kernel/cpu/mtrr/generic.c	Mon Feb 17 14:57:27 2003
@@ -83,15 +83,13 @@
 	if (!mask)
 		return;
 	if (mask & MTRR_CHANGE_MASK_FIXED)
-		printk
-		    ("mtrr: your CPUs had inconsistent fixed MTRR settings\n");
+		printk(KERN_WARNING "mtrr: your CPUs had inconsistent fixed MTRR settings\n");
 	if (mask & MTRR_CHANGE_MASK_VARIABLE)
-		printk
-		    ("mtrr: your CPUs had inconsistent variable MTRR settings\n");
+		printk(KERN_WARNING "mtrr: your CPUs had inconsistent variable MTRR settings\n");
 	if (mask & MTRR_CHANGE_MASK_DEFTYPE)
-		printk
-		    ("mtrr: your CPUs had inconsistent MTRRdefType settings\n");
-	printk("mtrr: probably your BIOS does not setup all CPUs\n");
+		printk(KERN_WARNING "mtrr: your CPUs had inconsistent MTRRdefType settings\n");
+	printk(KERN_INFO "mtrr: probably your BIOS does not setup all CPUs.\n");
+	printk(KERN_INFO "mtrr: corrected configuration.\n");
 }
 
 
@@ -338,23 +336,19 @@
 	    boot_cpu_data.x86_model == 1 &&
 	    boot_cpu_data.x86_mask <= 7) {
 		if (base & ((1 << (22 - PAGE_SHIFT)) - 1)) {
-			printk(KERN_WARNING
-			       "mtrr: base(0x%lx000) is not 4 MiB aligned\n",
-			       base);
+			printk(KERN_WARNING "mtrr: base(0x%lx000) is not 4 MiB aligned\n", base);
 			return -EINVAL;
 		}
 		if (!(base + size < 0x70000000 || base > 0x7003FFFF) &&
 		    (type == MTRR_TYPE_WRCOMB
 		     || type == MTRR_TYPE_WRBACK)) {
-			printk(KERN_WARNING
-			       "mtrr: writable mtrr between 0x70000000 and 0x7003FFFF may hang the CPU.\n");
+			printk(KERN_WARNING "mtrr: writable mtrr between 0x70000000 and 0x7003FFFF may hang the CPU.\n");
 			return -EINVAL;
 		}
 	}
 
 	if (base + size < 0x100) {
-		printk(KERN_WARNING
-		       "mtrr: cannot set region below 1 MiB (0x%lx000,0x%lx000)\n",
+		printk(KERN_WARNING "mtrr: cannot set region below 1 MiB (0x%lx000,0x%lx000)\n",
 		       base, size);
 		return -EINVAL;
 	}
@@ -364,8 +358,7 @@
 	for (lbase = base; !(lbase & 1) && (last & 1);
 	     lbase = lbase >> 1, last = last >> 1) ;
 	if (lbase != last) {
-		printk(KERN_WARNING
-		       "mtrr: base(0x%lx000) is not aligned on a size(0x%lx000) boundary\n",
+		printk(KERN_WARNING "mtrr: base(0x%lx000) is not aligned on a size(0x%lx000) boundary\n",
 		       base, size);
 		return -EINVAL;
 	}
diff -Nru a/arch/i386/kernel/io_apic.c b/arch/i386/kernel/io_apic.c
--- a/arch/i386/kernel/io_apic.c	Mon Feb 17 14:57:27 2003
+++ b/arch/i386/kernel/io_apic.c	Mon Feb 17 14:57:27 2003
@@ -668,7 +668,9 @@
 
 		if ((mp_bus_id_to_type[lbus] == MP_BUS_ISA ||
 		     mp_bus_id_to_type[lbus] == MP_BUS_EISA ||
-		     mp_bus_id_to_type[lbus] == MP_BUS_MCA) &&
+		     mp_bus_id_to_type[lbus] == MP_BUS_MCA ||
+		     mp_bus_id_to_type[lbus] == MP_BUS_NEC98
+		    ) &&
 		    (mp_irqs[i].mpc_irqtype == type) &&
 		    (mp_irqs[i].mpc_srcbusirq == irq))
 
@@ -762,6 +764,12 @@
 #define default_MCA_trigger(idx)	(1)
 #define default_MCA_polarity(idx)	(0)
 
+/* NEC98 interrupts are always polarity zero edge triggered,
+ * when listed as conforming in the MP table. */
+
+#define default_NEC98_trigger(idx)     (0)
+#define default_NEC98_polarity(idx)    (0)
+
 static int __init MPBIOS_polarity(int idx)
 {
 	int bus = mp_irqs[idx].mpc_srcbus;
@@ -796,6 +804,11 @@
 					polarity = default_MCA_polarity(idx);
 					break;
 				}
+				case MP_BUS_NEC98: /* NEC 98 pin */
+				{
+					polarity = default_NEC98_polarity(idx);
+					break;
+				}
 				default:
 				{
 					printk(KERN_WARNING "broken BIOS!!\n");
@@ -865,6 +878,11 @@
 					trigger = default_MCA_trigger(idx);
 					break;
 				}
+				case MP_BUS_NEC98: /* NEC 98 pin */
+				{
+					trigger = default_NEC98_trigger(idx);
+					break;
+				}
 				default:
 				{
 					printk(KERN_WARNING "broken BIOS!!\n");
@@ -926,6 +944,7 @@
 		case MP_BUS_ISA: /* ISA pin */
 		case MP_BUS_EISA:
 		case MP_BUS_MCA:
+		case MP_BUS_NEC98:
 		{
 			irq = mp_irqs[idx].mpc_srcbusirq;
 			break;
@@ -1133,8 +1152,9 @@
 
 void __init UNEXPECTED_IO_APIC(void)
 {
-	printk(KERN_WARNING " WARNING: unexpected IO-APIC, please mail\n");
-	printk(KERN_WARNING "          to linux-smp@vger.kernel.org\n");
+	printk(KERN_WARNING "INFO: unexpected IO-APIC, please file a report at\n");
+	printk(KERN_WARNING "      http://bugzilla.kernel.org\n");
+	printk(KERN_WARNING "      if your kernel is less than 3 months old.\n");
 }
 
 void __init print_IO_APIC(void)
diff -Nru a/arch/i386/kernel/mpparse.c b/arch/i386/kernel/mpparse.c
--- a/arch/i386/kernel/mpparse.c	Mon Feb 17 14:57:27 2003
+++ b/arch/i386/kernel/mpparse.c	Mon Feb 17 14:57:27 2003
@@ -169,7 +169,7 @@
 	num_processors++;
 
 	if (m->mpc_apicid > MAX_APICS) {
-		printk("Processor #%d INVALID. (Max ID: %d).\n",
+		printk(KERN_WARNING "Processor #%d INVALID. (Max ID: %d).\n",
 			m->mpc_apicid, MAX_APICS);
 		--num_processors;
 		return;
@@ -182,7 +182,7 @@
 	 * Validate version
 	 */
 	if (ver == 0x0) {
-		printk("BIOS bug, APIC version is 0 for CPU#%d! fixing up to 0x10. (tell your hw vendor)\n", m->mpc_apicid);
+		printk(KERN_WARNING "BIOS bug, APIC version is 0 for CPU#%d! fixing up to 0x10. (tell your hw vendor)\n", m->mpc_apicid);
 		ver = 0x10;
 	}
 	apic_version[m->mpc_apicid] = ver;
@@ -209,8 +209,10 @@
 		mp_current_pci_id++;
 	} else if (strncmp(str, BUSTYPE_MCA, sizeof(BUSTYPE_MCA)-1) == 0) {
 		mp_bus_id_to_type[m->mpc_busid] = MP_BUS_MCA;
+	} else if (strncmp(str, BUSTYPE_NEC98, sizeof(BUSTYPE_NEC98)-1) == 0) {
+		mp_bus_id_to_type[m->mpc_busid] = MP_BUS_NEC98;
 	} else {
-		printk("Unknown bustype %s - ignoring\n", str);
+		printk(KERN_WARNING "Unknown bustype %s - ignoring\n", str);
 	}
 }
 
@@ -219,10 +221,10 @@
 	if (!(m->mpc_flags & MPC_APIC_USABLE))
 		return;
 
-	printk("I/O APIC #%d Version %d at 0x%lX.\n",
+	printk(KERN_INFO "I/O APIC #%d Version %d at 0x%lX.\n",
 		m->mpc_apicid, m->mpc_apicver, m->mpc_apicaddr);
 	if (nr_ioapics >= MAX_IO_APICS) {
-		printk("Max # of I/O APICs (%d) exceeded (found %d).\n",
+		printk(KERN_CRIT "Max # of I/O APICs (%d) exceeded (found %d).\n",
 			MAX_IO_APICS, nr_ioapics);
 		panic("Recompile kernel with bigger MAX_IO_APICS!.\n");
 	}
@@ -272,10 +274,10 @@
 #ifdef CONFIG_X86_NUMAQ
 static void __init MP_translation_info (struct mpc_config_translation *m)
 {
-	printk("Translation: record %d, type %d, quad %d, global %d, local %d\n", mpc_record, m->trans_type, m->trans_quad, m->trans_global, m->trans_local);
+	printk(KERN_INFO "Translation: record %d, type %d, quad %d, global %d, local %d\n", mpc_record, m->trans_type, m->trans_quad, m->trans_global, m->trans_local);
 
 	if (mpc_record >= MAX_MPC_ENTRY) 
-		printk("MAX_MPC_ENTRY exceeded!\n");
+		printk(KERN_ERR "MAX_MPC_ENTRY exceeded!\n");
 	else
 		translation_table[mpc_record] = m; /* stash this for later */
 	if (m->trans_quad+1 > numnodes)
@@ -293,10 +295,10 @@
 	unsigned char *oemptr = ((unsigned char *)oemtable)+count;
 	
 	mpc_record = 0;
-	printk("Found an OEM MPC table at %8p - parsing it ... \n", oemtable);
+	printk(KERN_INFO "Found an OEM MPC table at %8p - parsing it ... \n", oemtable);
 	if (memcmp(oemtable->oem_signature,MPC_OEM_SIGNATURE,4))
 	{
-		printk("SMP mpc oemtable: bad signature [%c%c%c%c]!\n",
+		printk(KERN_WARNING "SMP mpc oemtable: bad signature [%c%c%c%c]!\n",
 			oemtable->oem_signature[0],
 			oemtable->oem_signature[1],
 			oemtable->oem_signature[2],
@@ -305,7 +307,7 @@
 	}
 	if (mpf_checksum((unsigned char *)oemtable,oemtable->oem_length))
 	{
-		printk("SMP oem mptable: checksum error!\n");
+		printk(KERN_WARNING "SMP oem mptable: checksum error!\n");
 		return;
 	}
 	while (count < oemtable->oem_length) {
@@ -322,7 +324,7 @@
 			}
 			default:
 			{
-				printk("Unrecognised OEM table entry type! - %d\n", (int) *oemptr);
+				printk(KERN_WARNING "Unrecognised OEM table entry type! - %d\n", (int) *oemptr);
 				return;
 			}
 		}
@@ -364,7 +366,7 @@
 	}
 	memcpy(oem,mpc->mpc_oem,8);
 	oem[8]=0;
-	printk("OEM ID: %s ",oem);
+	printk(KERN_INFO "OEM ID: %s ",oem);
 
 	memcpy(str,mpc->mpc_productid,12);
 	str[12]=0;
@@ -479,12 +481,12 @@
 	 *  If it does, we assume it's valid.
 	 */
 	if (mpc_default_type == 5) {
-		printk("ISA/PCI bus type with no IRQ information... falling back to ELCR\n");
+		printk(KERN_INFO "ISA/PCI bus type with no IRQ information... falling back to ELCR\n");
 
 		if (ELCR_trigger(0) || ELCR_trigger(1) || ELCR_trigger(2) || ELCR_trigger(13))
-			printk("ELCR contains invalid data... not using ELCR\n");
+			printk(KERN_WARNING "ELCR contains invalid data... not using ELCR\n");
 		else {
-			printk("Using ELCR to identify PCI interrupts\n");
+			printk(KERN_INFO "Using ELCR to identify PCI interrupts\n");
 			ELCR_fallback = 1;
 		}
 	}
@@ -559,7 +561,8 @@
 	bus.mpc_busid = 0;
 	switch (mpc_default_type) {
 		default:
-			printk("???\nUnknown standard configuration %d\n",
+			printk("???\n");
+			printk(KERN_ERR "Unknown standard configuration %d\n",
 				mpc_default_type);
 			/* fall through */
 		case 1:
@@ -628,12 +631,12 @@
 	else if (acpi_lapic)
 		printk(KERN_INFO "Using ACPI for processor (LAPIC) configuration information\n");
 
-	printk("Intel MultiProcessor Specification v1.%d\n", mpf->mpf_specification);
+	printk("KERN_INFO Intel MultiProcessor Specification v1.%d\n", mpf->mpf_specification);
 	if (mpf->mpf_feature2 & (1<<7)) {
-		printk("    IMCR and PIC compatibility mode.\n");
+		printk(KERN_INFO "    IMCR and PIC compatibility mode.\n");
 		pic_mode = 1;
 	} else {
-		printk("    Virtual Wire compatibility mode.\n");
+		printk(KERN_INFO "    Virtual Wire compatibility mode.\n");
 		pic_mode = 0;
 	}
 
@@ -642,7 +645,7 @@
 	 */
 	if (mpf->mpf_feature1 != 0) {
 
-		printk("Default MP configuration #%d\n", mpf->mpf_feature1);
+		printk(KERN_INFO "Default MP configuration #%d\n", mpf->mpf_feature1);
 		construct_default_ISA_mptable(mpf->mpf_feature1);
 
 	} else if (mpf->mpf_physptr) {
@@ -665,7 +668,7 @@
 		if (!mp_irq_entries) {
 			struct mpc_config_bus bus;
 
-			printk("BIOS bug, no explicit IRQ entries, using default mptable. (tell your hw vendor)\n");
+			printk(KERN_ERR "BIOS bug, no explicit IRQ entries, using default mptable. (tell your hw vendor)\n");
 
 			bus.mpc_type = MP_BUS;
 			bus.mpc_busid = 0;
@@ -678,7 +681,7 @@
 	} else
 		BUG();
 
-	printk("Processors: %d\n", num_processors);
+	printk(KERN_INFO "Processors: %d\n", num_processors);
 	/*
 	 * Only use the first configuration found.
 	 */
@@ -702,7 +705,7 @@
 				|| (mpf->mpf_specification == 4)) ) {
 
 			smp_found_config = 1;
-			printk("found SMP MP-table at %08lx\n",
+			printk(KERN_INFO "found SMP MP-table at %08lx\n",
 						virt_to_phys(mpf));
 			reserve_bootmem(virt_to_phys(mpf), PAGE_SIZE);
 			if (mpf->mpf_physptr)
@@ -752,8 +755,6 @@
 	address = *(unsigned short *)phys_to_virt(0x40E);
 	address <<= 4;
 	smp_scan_config(address, 0x400);
-	if (smp_found_config)
-		printk(KERN_WARNING "WARNING: MP table in the EBDA can be UNSAFE, contact linux-smp@vger.kernel.org if you experience SMP problems!\n");
 }
 
 
diff -Nru a/arch/i386/kernel/process.c b/arch/i386/kernel/process.c
--- a/arch/i386/kernel/process.c	Mon Feb 17 14:57:26 2003
+++ b/arch/i386/kernel/process.c	Mon Feb 17 14:57:26 2003
@@ -36,6 +36,7 @@
 #include <linux/mc146818rtc.h>
 #include <linux/module.h>
 #include <linux/kallsyms.h>
+#include <linux/ptrace.h>
 
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
diff -Nru a/arch/i386/kernel/smp.c b/arch/i386/kernel/smp.c
--- a/arch/i386/kernel/smp.c	Mon Feb 17 14:57:26 2003
+++ b/arch/i386/kernel/smp.c	Mon Feb 17 14:57:26 2003
@@ -452,9 +452,11 @@
 
 void flush_tlb_all(void)
 {
+	preempt_disable();
 	smp_call_function (flush_tlb_all_ipi,0,1,1);
 
 	do_flush_tlb_all_local();
+	preempt_enable();
 }
 
 /*
diff -Nru a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c
--- a/arch/i386/kernel/traps.c	Mon Feb 17 14:57:27 2003
+++ b/arch/i386/kernel/traps.c	Mon Feb 17 14:57:27 2003
@@ -24,6 +24,7 @@
 #include <linux/interrupt.h>
 #include <linux/highmem.h>
 #include <linux/kallsyms.h>
+#include <linux/ptrace.h>
 
 #ifdef CONFIG_EISA
 #include <linux/ioport.h>
diff -Nru a/arch/i386/kernel/vm86.c b/arch/i386/kernel/vm86.c
--- a/arch/i386/kernel/vm86.c	Mon Feb 17 14:57:26 2003
+++ b/arch/i386/kernel/vm86.c	Mon Feb 17 14:57:26 2003
@@ -40,6 +40,7 @@
 #include <linux/smp.h>
 #include <linux/smp_lock.h>
 #include <linux/highmem.h>
+#include <linux/ptrace.h>
 
 #include <asm/uaccess.h>
 #include <asm/pgalloc.h>
diff -Nru a/arch/i386/mach-voyager/voyager_thread.c b/arch/i386/mach-voyager/voyager_thread.c
--- a/arch/i386/mach-voyager/voyager_thread.c	Mon Feb 17 14:57:27 2003
+++ b/arch/i386/mach-voyager/voyager_thread.c	Mon Feb 17 14:57:27 2003
@@ -57,7 +57,7 @@
 }
 
 static int
-execute_helper(void *string)
+execute(const char *string)
 {
 	int ret;
 
@@ -74,20 +74,11 @@
 		NULL,
 	};
 
-	if((ret = exec_usermodehelper(argv[0], argv, envp)) < 0) {
-		printk(KERN_ERR "Voyager failed to execute \"%s\"\n",
-		       (char *)string);
+	if ((ret = call_usermodehelper(argv[0], argv, envp, 1)) != 0) {
+		printk(KERN_ERR "Voyager failed to run \"%s\": %i\n",
+		       string, ret);
 	}
 	return ret;
-}
-
-static void
-execute(char *string)
-{
-	if(kernel_thread(execute_helper, (void *)string, CLONE_VFORK | SIGCHLD) < 0) {
-		printk(KERN_ERR "Voyager failed to fork before exec of \"%s\"\n",
-		       string);
-	}
 }
 
 static void
diff -Nru a/arch/i386/math-emu/fpu_entry.c b/arch/i386/math-emu/fpu_entry.c
--- a/arch/i386/math-emu/fpu_entry.c	Mon Feb 17 14:57:28 2003
+++ b/arch/i386/math-emu/fpu_entry.c	Mon Feb 17 14:57:28 2003
@@ -25,6 +25,7 @@
  +---------------------------------------------------------------------------*/
 
 #include <linux/signal.h>
+#include <linux/ptrace.h>
 
 #include <asm/uaccess.h>
 #include <asm/desc.h>
diff -Nru a/arch/ia64/sn/io/io.c b/arch/ia64/sn/io/io.c
--- a/arch/ia64/sn/io/io.c	Mon Feb 17 14:57:27 2003
+++ b/arch/ia64/sn/io/io.c	Mon Feb 17 14:57:27 2003
@@ -631,7 +631,7 @@
 }
 
 /*
- * Check that an address is in teh real small window widget 0 space
+ * Check that an address is in the real small window widget 0 space
  * or else in the big window we're using to emulate small window 0
  * in the kernel.
  */
@@ -708,7 +708,7 @@
 /*
  * hub_setup_prb(nasid, prbnum, credits, conveyor)
  *
- * 	Put a PRB into fire-and-forget mode if conveyor isn't set.  Otehrwise,
+ * 	Put a PRB into fire-and-forget mode if conveyor isn't set.  Otherwise,
  * 	put it into conveyor belt mode with the specified number of credits.
  */
 void
diff -Nru a/arch/m68k/kernel/traps.c b/arch/m68k/kernel/traps.c
--- a/arch/m68k/kernel/traps.c	Mon Feb 17 14:57:28 2003
+++ b/arch/m68k/kernel/traps.c	Mon Feb 17 14:57:28 2003
@@ -29,6 +29,7 @@
 #include <linux/string.h>
 #include <linux/linkage.h>
 #include <linux/init.h>
+#include <linux/ptrace.h>
 
 #include <asm/setup.h>
 #include <asm/fpu.h>
diff -Nru a/arch/m68knommu/kernel/asm-offsets.c b/arch/m68knommu/kernel/asm-offsets.c
--- a/arch/m68knommu/kernel/asm-offsets.c	Mon Feb 17 14:57:28 2003
+++ b/arch/m68knommu/kernel/asm-offsets.c	Mon Feb 17 14:57:28 2003
@@ -11,6 +11,7 @@
 #include <linux/stddef.h>
 #include <linux/sched.h>
 #include <linux/kernel_stat.h>
+#include <linux/ptrace.h>
 #include <asm/bootinfo.h>
 #include <asm/irq.h>
 #include <asm/hardirq.h>
diff -Nru a/arch/m68knommu/kernel/traps.c b/arch/m68knommu/kernel/traps.c
--- a/arch/m68knommu/kernel/traps.c	Mon Feb 17 14:57:27 2003
+++ b/arch/m68knommu/kernel/traps.c	Mon Feb 17 14:57:27 2003
@@ -27,6 +27,7 @@
 #include <linux/string.h>
 #include <linux/linkage.h>
 #include <linux/init.h>
+#include <linux/ptrace.h>
 
 #include <asm/setup.h>
 #include <asm/fpu.h>
diff -Nru a/arch/mips/ddb5xxx/common/nile4.c b/arch/mips/ddb5xxx/common/nile4.c
--- a/arch/mips/ddb5xxx/common/nile4.c	Mon Feb 17 14:57:27 2003
+++ b/arch/mips/ddb5xxx/common/nile4.c	Mon Feb 17 14:57:27 2003
@@ -109,7 +109,7 @@
          * When programming a PDAR, the register should be read immediately
          * after writing it. This ensures that address decoders are properly
          * configured.
-	 * [jsun] is this really necesary?
+	 * [jsun] is this really necessary?
          */
         ddb_in32(pdar);
         ddb_in32(pdar + 4);
diff -Nru a/arch/mips/kernel/irixsig.c b/arch/mips/kernel/irixsig.c
--- a/arch/mips/kernel/irixsig.c	Mon Feb 17 14:57:28 2003
+++ b/arch/mips/kernel/irixsig.c	Mon Feb 17 14:57:28 2003
@@ -12,6 +12,7 @@
 #include <linux/smp.h>
 #include <linux/smp_lock.h>
 #include <linux/time.h>
+#include <linux/ptrace.h>
 
 #include <asm/ptrace.h>
 #include <asm/uaccess.h>
diff -Nru a/arch/mips/kernel/sysmips.c b/arch/mips/kernel/sysmips.c
--- a/arch/mips/kernel/sysmips.c	Mon Feb 17 14:57:27 2003
+++ b/arch/mips/kernel/sysmips.c	Mon Feb 17 14:57:27 2003
@@ -16,6 +16,7 @@
 #include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/utsname.h>
+#include <linux/ptrace.h>
 
 #include <asm/cachectl.h>
 #include <asm/pgalloc.h>
diff -Nru a/arch/parisc/hpux/fs.c b/arch/parisc/hpux/fs.c
--- a/arch/parisc/hpux/fs.c	Mon Feb 17 14:57:27 2003
+++ b/arch/parisc/hpux/fs.c	Mon Feb 17 14:57:27 2003
@@ -9,6 +9,7 @@
 #include <linux/file.h>
 #include <linux/smp_lock.h>
 #include <linux/slab.h>
+#include <linux/ptrace.h>
 #include <asm/errno.h>
 #include <asm/uaccess.h>
 
diff -Nru a/arch/parisc/kernel/sys_parisc32.c b/arch/parisc/kernel/sys_parisc32.c
--- a/arch/parisc/kernel/sys_parisc32.c	Mon Feb 17 14:57:27 2003
+++ b/arch/parisc/kernel/sys_parisc32.c	Mon Feb 17 14:57:27 2003
@@ -53,6 +53,7 @@
 #include <linux/binfmts.h>
 #include <linux/namei.h>
 #include <linux/vfs.h>
+#include <linux/ptrace.h>
 
 #include <asm/types.h>
 #include <asm/uaccess.h>
diff -Nru a/arch/parisc/kernel/syscall.S b/arch/parisc/kernel/syscall.S
--- a/arch/parisc/kernel/syscall.S	Mon Feb 17 14:57:28 2003
+++ b/arch/parisc/kernel/syscall.S	Mon Feb 17 14:57:28 2003
@@ -320,7 +320,8 @@
 #ifdef __LP64__
 /* Use ENTRY_SAME for 32-bit syscalls which are the same on wide and
  * narrow palinux.  Use ENTRY_DIFF for those where a 32-bit specific
- * implementation is required on wide palinux.
+ * implementation is required on wide palinux.  Use ENTRY_COMP where
+ * the compatability layer has a useful 32-bit implementation.
  */
 #define ENTRY_SAME(_name_) .dword sys_##_name_
 #define ENTRY_DIFF(_name_) .dword sys32_##_name_
@@ -597,7 +598,7 @@
 	ENTRY_SAME(ni_syscall)		/* tkill */
 
 	ENTRY_SAME(sendfile64)
-	ENTRY_SAME(futex)		/* 210 */
+	ENTRY_COMP(futex)		/* 210 */
 	ENTRY_SAME(sched_setaffinity)
 	ENTRY_SAME(sched_getaffinity)
 	ENTRY_SAME(set_thread_area)
diff -Nru a/arch/ppc/boot/common/cpc700_memory.c b/arch/ppc/boot/common/cpc700_memory.c
--- a/arch/ppc/boot/common/cpc700_memory.c	Mon Feb 17 14:57:28 2003
+++ b/arch/ppc/boot/common/cpc700_memory.c	Mon Feb 17 14:57:28 2003
@@ -6,7 +6,7 @@
  * Author: Dan Cox
  *
  * 2001-2002 (c) MontaVista, Software, Inc.  This file is licensed under
- * the terms of the GNU General Public License version 2.1.  This program
+ * the terms of the GNU General Public License version 2.  This program
  * is licensed "as is" without any warranty of any kind, whether express
  * or implied.
  */
diff -Nru a/arch/ppc/boot/common/misc-common.c b/arch/ppc/boot/common/misc-common.c
--- a/arch/ppc/boot/common/misc-common.c	Mon Feb 17 14:57:27 2003
+++ b/arch/ppc/boot/common/misc-common.c	Mon Feb 17 14:57:27 2003
@@ -9,7 +9,7 @@
  * Derived from arch/ppc/boot/prep/misc.c
  *
  * 2000-2001 (c) MontaVista, Software, Inc.  This file is licensed under
- * the terms of the GNU General Public License version 2.1.  This program
+ * the terms of the GNU General Public License version 2.  This program
  * is licensed "as is" without any warranty of any kind, whether express
  * or implied.
  */
diff -Nru a/arch/ppc/boot/common/mpc10x_memory.c b/arch/ppc/boot/common/mpc10x_memory.c
--- a/arch/ppc/boot/common/mpc10x_memory.c	Mon Feb 17 14:57:27 2003
+++ b/arch/ppc/boot/common/mpc10x_memory.c	Mon Feb 17 14:57:27 2003
@@ -10,7 +10,7 @@
  *         mgreer@mvista.com
  *
  * 2001-2002 (c) MontaVista, Software, Inc.  This file is licensed under
- * the terms of the GNU General Public License version 2.1.  This program
+ * the terms of the GNU General Public License version 2.  This program
  * is licensed "as is" without any warranty of any kind, whether express
  * or implied.
  */
diff -Nru a/arch/ppc/boot/common/util.S b/arch/ppc/boot/common/util.S
--- a/arch/ppc/boot/common/util.S	Mon Feb 17 14:57:28 2003
+++ b/arch/ppc/boot/common/util.S	Mon Feb 17 14:57:28 2003
@@ -15,7 +15,7 @@
  * Derived from arch/ppc/boot/prep/head.S (Cort Dougan, many others).
  *
  * 2001 (c) MontaVista, Software, Inc.  This file is licensed under
- * the terms of the GNU General Public License version 2.1.  This program
+ * the terms of the GNU General Public License version 2.  This program
  * is licensed "as is" without any warranty of any kind, whether express
  * or implied.
  */
diff -Nru a/arch/ppc/boot/include/mpc10x.h b/arch/ppc/boot/include/mpc10x.h
--- a/arch/ppc/boot/include/mpc10x.h	Mon Feb 17 14:57:27 2003
+++ b/arch/ppc/boot/include/mpc10x.h	Mon Feb 17 14:57:27 2003
@@ -13,7 +13,7 @@
  *         mgreer@mvista.com
  *
  * 2001-2002 (c) MontaVista, Software, Inc.  This file is licensed under
- * the terms of the GNU General Public License version 2.1.  This program
+ * the terms of the GNU General Public License version 2.  This program
  * is licensed "as is" without any warranty of any kind, whether express
  * or implied.
  */
diff -Nru a/arch/ppc/boot/simple/Makefile b/arch/ppc/boot/simple/Makefile
--- a/arch/ppc/boot/simple/Makefile	Mon Feb 17 14:57:26 2003
+++ b/arch/ppc/boot/simple/Makefile	Mon Feb 17 14:57:26 2003
@@ -4,7 +4,7 @@
 # Author: Tom Rini <trini@mvista.com>
 #
 # 2001-2002 (c) MontaVista, Software, Inc.  This file is licensed under
-# the terms of the GNU General Public License version 2.1.  This program
+# the terms of the GNU General Public License version 2.  This program
 # is licensed "as is" without any warranty of any kind, whether express
 # or implied.
 #
diff -Nru a/arch/ppc/boot/simple/gt64260_tty.c b/arch/ppc/boot/simple/gt64260_tty.c
--- a/arch/ppc/boot/simple/gt64260_tty.c	Mon Feb 17 14:57:27 2003
+++ b/arch/ppc/boot/simple/gt64260_tty.c	Mon Feb 17 14:57:27 2003
@@ -7,7 +7,7 @@
  * Author: Mark A. Greer <mgreer@mvista.com>
  *
  * 2001 (c) MontaVista, Software, Inc.  This file is licensed under
- * the terms of the GNU General Public License version 2.1.  This program
+ * the terms of the GNU General Public License version 2.  This program
  * is licensed "as is" without any warranty of any kind, whether express
  * or implied.
  */
diff -Nru a/arch/ppc/boot/simple/head.S b/arch/ppc/boot/simple/head.S
--- a/arch/ppc/boot/simple/head.S	Mon Feb 17 14:57:27 2003
+++ b/arch/ppc/boot/simple/head.S	Mon Feb 17 14:57:27 2003
@@ -8,7 +8,7 @@
  * Derived from arch/ppc/boot/prep/head.S (Cort Dougan, many others).
  *
  * 2001 (c) MontaVista, Software, Inc.  This file is licensed under
- * the terms of the GNU General Public License version 2.1.  This program
+ * the terms of the GNU General Public License version 2.  This program
  * is licensed "as is" without any warranty of any kind, whether express
  * or implied.
  */
diff -Nru a/arch/ppc/boot/simple/misc-ev64260.S b/arch/ppc/boot/simple/misc-ev64260.S
--- a/arch/ppc/boot/simple/misc-ev64260.S	Mon Feb 17 14:57:28 2003
+++ b/arch/ppc/boot/simple/misc-ev64260.S	Mon Feb 17 14:57:28 2003
@@ -7,7 +7,7 @@
  * Author: Mark Greer <mgreer@mvista.com>
  *
  * 2001 (c) MontaVista, Software, Inc.  This file is licensed under
- * the terms of the GNU General Public License version 2.1.  This program
+ * the terms of the GNU General Public License version 2.  This program
  * is licensed "as is" without any warranty of any kind, whether express
  * or implied.
  */
diff -Nru a/arch/ppc/boot/simple/misc-spruce.c b/arch/ppc/boot/simple/misc-spruce.c
--- a/arch/ppc/boot/simple/misc-spruce.c	Mon Feb 17 14:57:27 2003
+++ b/arch/ppc/boot/simple/misc-spruce.c	Mon Feb 17 14:57:27 2003
@@ -9,7 +9,7 @@
  * Derived from arch/ppc/boot/prep/misc.c
  *
  * 2000-2001 (c) MontaVista, Software, Inc.  This file is licensed under
- * the terms of the GNU General Public License version 2.1.  This program
+ * the terms of the GNU General Public License version 2.  This program
  * is licensed "as is" without any warranty of any kind, whether express
  * or implied.
  */
diff -Nru a/arch/ppc/boot/simple/misc.c b/arch/ppc/boot/simple/misc.c
--- a/arch/ppc/boot/simple/misc.c	Mon Feb 17 14:57:28 2003
+++ b/arch/ppc/boot/simple/misc.c	Mon Feb 17 14:57:28 2003
@@ -11,7 +11,7 @@
  * Derived from arch/ppc/boot/prep/misc.c
  *
  * 2001 (c) MontaVista, Software, Inc.  This file is licensed under
- * the terms of the GNU General Public License version 2.1.  This program
+ * the terms of the GNU General Public License version 2.  This program
  * is licensed "as is" without any warranty of any kind, whether express
  * or implied.
  */
diff -Nru a/arch/ppc/boot/simple/relocate.S b/arch/ppc/boot/simple/relocate.S
--- a/arch/ppc/boot/simple/relocate.S	Mon Feb 17 14:57:27 2003
+++ b/arch/ppc/boot/simple/relocate.S	Mon Feb 17 14:57:27 2003
@@ -10,7 +10,7 @@
  * Derived from arch/ppc/boot/prep/head.S (Cort Dougan, many others).
  *
  * 2001-2002 (c) MontaVista, Software, Inc.  This file is licensed under
- * the terms of the GNU General Public License version 2.1.  This program
+ * the terms of the GNU General Public License version 2.  This program
  * is licensed "as is" without any warranty of any kind, whether express
  * or implied.
  */
diff -Nru a/arch/ppc/boot/simple/rw4/ppc_40x.h b/arch/ppc/boot/simple/rw4/ppc_40x.h
--- a/arch/ppc/boot/simple/rw4/ppc_40x.h	Mon Feb 17 14:57:27 2003
+++ b/arch/ppc/boot/simple/rw4/ppc_40x.h	Mon Feb 17 14:57:27 2003
@@ -41,9 +41,9 @@
 #define dbsr            0x3f0               /* debug status register         */
 #define dccr            0x3fa               /* data cache control reg.       */
 #define dcwr            0x3ba               /* data cache write-thru reg     */
-#define dear            0x3d5               /* data exeption address reg     */
-#define esr             0x3d4               /* execption syndrome registe    */
-#define evpr            0x3d6               /* exeption vector prefix reg    */
+#define dear            0x3d5               /* data exception address reg    */
+#define esr             0x3d4               /* exception syndrome registe    */
+#define evpr            0x3d6               /* exception vector prefix reg   */
 #define iccr            0x3fb               /* instruction cache cntrl re    */
 #define icdbdr          0x3d3               /* instr cache dbug data reg     */
 #define lrreg           0x008               /* link register                 */
diff -Nru a/arch/ppc/boot/utils/addnote.c b/arch/ppc/boot/utils/addnote.c
--- a/arch/ppc/boot/utils/addnote.c	Mon Feb 17 14:57:28 2003
+++ b/arch/ppc/boot/utils/addnote.c	Mon Feb 17 14:57:28 2003
@@ -14,6 +14,7 @@
  * Usage: addnote zImage
  */
 #include <stdio.h>
+#include <stdlib.h>
 #include <fcntl.h>
 #include <unistd.h>
 #include <string.h>
diff -Nru a/arch/ppc/boot/utils/hack-coff.c b/arch/ppc/boot/utils/hack-coff.c
--- a/arch/ppc/boot/utils/hack-coff.c	Mon Feb 17 14:57:27 2003
+++ b/arch/ppc/boot/utils/hack-coff.c	Mon Feb 17 14:57:27 2003
@@ -11,8 +11,10 @@
  * 2 of the License, or (at your option) any later version.
  */
 #include <stdio.h>
+#include <stdlib.h>
 #include <unistd.h>
 #include <fcntl.h>
+#include <string.h>
 #include "rs6000.h"
 
 #define AOUT_MAGIC	0x010b
diff -Nru a/arch/ppc/boot/utils/mkbugboot.c b/arch/ppc/boot/utils/mkbugboot.c
--- a/arch/ppc/boot/utils/mkbugboot.c	Mon Feb 17 14:57:27 2003
+++ b/arch/ppc/boot/utils/mkbugboot.c	Mon Feb 17 14:57:27 2003
@@ -7,7 +7,7 @@
  * Author: Matt Porter <mporter@mvista.com>
  *
  * 2001 (c) MontaVista, Software, Inc.  This file is licensed under
- * the terms of the GNU General Public License version 2.1.  This program
+ * the terms of the GNU General Public License version 2.  This program
  * is licensed "as is" without any warranty of any kind, whether express
  * or implied.
  */
diff -Nru a/arch/ppc/boot/utils/mknote.c b/arch/ppc/boot/utils/mknote.c
--- a/arch/ppc/boot/utils/mknote.c	Mon Feb 17 14:57:28 2003
+++ b/arch/ppc/boot/utils/mknote.c	Mon Feb 17 14:57:28 2003
@@ -11,6 +11,7 @@
  */
 
 #include <stdio.h>
+#include <string.h>
 
 #define PL(x) printf("%c%c%c%c", ((x)>>24)&0xff, ((x)>>16)&0xff, ((x)>>8)&0xff, (x)&0xff );
 
diff -Nru a/arch/ppc/kernel/head.S b/arch/ppc/kernel/head.S
--- a/arch/ppc/kernel/head.S	Mon Feb 17 14:57:27 2003
+++ b/arch/ppc/kernel/head.S	Mon Feb 17 14:57:27 2003
@@ -1337,7 +1337,7 @@
 	blr
 
 /* 7400 <= rev 2.7 and 7410 rev = 1.0 suffer from some
- * erratas we work around here.
+ * errata we work around here.
  * Moto MPC710CE.pdf describes them, those are errata
  * #3, #4 and #5
  * Note that we assume the firmware didn't choose to
diff -Nru a/arch/ppc/kernel/head_4xx.S b/arch/ppc/kernel/head_4xx.S
--- a/arch/ppc/kernel/head_4xx.S	Mon Feb 17 14:57:28 2003
+++ b/arch/ppc/kernel/head_4xx.S	Mon Feb 17 14:57:28 2003
@@ -923,6 +923,8 @@
 	ori	r3,r3,KERNELBASE@l
 	tophys(r4,r3)			/* Load the kernel physical address */
 
+	iccci	r0,r3			/* Invalidate the i-cache before use */
+
 	/* Load the kernel PID.
 	*/
 	li	r0,0
diff -Nru a/arch/ppc/kernel/irq.c b/arch/ppc/kernel/irq.c
--- a/arch/ppc/kernel/irq.c	Mon Feb 17 14:57:28 2003
+++ b/arch/ppc/kernel/irq.c	Mon Feb 17 14:57:28 2003
@@ -20,7 +20,7 @@
  * The MPC8xx has an interrupt mask in the SIU.  If a bit is set, the
  * interrupt is _enabled_.  As expected, IRQ0 is bit 0 in the 32-bit
  * mask register (of which only 16 are defined), hence the weird shifting
- * and compliment of the cached_irq_mask.  I want to be able to stuff
+ * and complement of the cached_irq_mask.  I want to be able to stuff
  * this right into the SIU SMASK register.
  * Many of the prep/chrp functions are conditional compiled on CONFIG_8xx
  * to reduce code space and undefined function references.
diff -Nru a/arch/ppc/kernel/misc.S b/arch/ppc/kernel/misc.S
--- a/arch/ppc/kernel/misc.S	Mon Feb 17 14:57:28 2003
+++ b/arch/ppc/kernel/misc.S	Mon Feb 17 14:57:28 2003
@@ -1273,8 +1273,8 @@
 	.long sys_io_getevents
 	.long sys_io_submit	/* 230 */
 	.long sys_io_cancel
-	.long sys_ni_syscall	/* reserved for alloc_hugepages */
-	.long sys_ni_syscall	/* reserved for free_hugepages */
+	.long sys_set_tid_address
+	.long sys_fadvise64
 	.long sys_exit_group
 	.long sys_lookup_dcookie /* 235 */
 	.long sys_epoll_create
diff -Nru a/arch/ppc/kernel/ppc_ksyms.c b/arch/ppc/kernel/ppc_ksyms.c
--- a/arch/ppc/kernel/ppc_ksyms.c	Mon Feb 17 14:57:28 2003
+++ b/arch/ppc/kernel/ppc_ksyms.c	Mon Feb 17 14:57:28 2003
@@ -14,6 +14,7 @@
 #include <linux/pci.h>
 #include <linux/delay.h>
 #include <linux/ide.h>
+#include <linux/pm.h>
 
 #include <asm/page.h>
 #include <asm/semaphore.h>
@@ -69,8 +70,6 @@
 long long __lshrdi3(long long, int);
 int abs(int);
 
-extern unsigned char __res[];
-
 extern unsigned long mm_ptov (unsigned long paddr);
 
 EXPORT_SYMBOL(clear_page);
@@ -180,6 +179,7 @@
 EXPORT_SYMBOL(consistent_alloc);
 EXPORT_SYMBOL(consistent_free);
 EXPORT_SYMBOL(consistent_sync);
+EXPORT_SYMBOL(flush_dcache_all);
 #endif
 
 EXPORT_SYMBOL(open);
@@ -269,6 +269,8 @@
 #endif /* CONFIG_NVRAM */
 EXPORT_SYMBOL(to_tm);
 
+EXPORT_SYMBOL(pm_power_off);
+
 EXPORT_SYMBOL_NOVERS(__ashrdi3);
 EXPORT_SYMBOL_NOVERS(__ashldi3);
 EXPORT_SYMBOL_NOVERS(__lshrdi3);
@@ -329,10 +331,12 @@
 #endif
 
 #ifdef  CONFIG_8xx
-EXPORT_SYMBOL(__res);
 EXPORT_SYMBOL(cpm_install_handler);
 EXPORT_SYMBOL(cpm_free_handler);
 #endif /* CONFIG_8xx */
+#if defined(CONFIG_8xx) || defined(CONFIG_4xx)
+EXPORT_SYMBOL(__res);
+#endif
 #if defined(CONFIG_8xx) || defined(CONFIG_8260)
 EXPORT_SYMBOL(request_8xxirq);
 #endif
diff -Nru a/arch/ppc/kernel/process.c b/arch/ppc/kernel/process.c
--- a/arch/ppc/kernel/process.c	Mon Feb 17 14:57:27 2003
+++ b/arch/ppc/kernel/process.c	Mon Feb 17 14:57:27 2003
@@ -54,6 +54,7 @@
 static struct fs_struct init_fs = INIT_FS;
 static struct files_struct init_files = INIT_FILES;
 static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
+static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
 struct mm_struct init_mm = INIT_MM(init_mm);
 
 /* this is 8kB-aligned so we can get to the thread_info struct
diff -Nru a/arch/ppc/kernel/ptrace.c b/arch/ppc/kernel/ptrace.c
--- a/arch/ppc/kernel/ptrace.c	Mon Feb 17 14:57:27 2003
+++ b/arch/ppc/kernel/ptrace.c	Mon Feb 17 14:57:27 2003
@@ -369,11 +369,9 @@
         if (!test_thread_flag(TIF_SYSCALL_TRACE)
 	    || !(current->ptrace & PT_PTRACED))
 		return;
-	current->exit_code = SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
-					? 0x80 : 0);
-	current->state = TASK_STOPPED;
-	notify_parent(current, SIGCHLD);
-	schedule();
+	ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
+				 ? 0x80 : 0));
+
 	/*
 	 * this isn't the same as continuing with a signal, but it will do
 	 * for normal use.  strace only continues with a signal if the
diff -Nru a/arch/ppc/kernel/setup.c b/arch/ppc/kernel/setup.c
--- a/arch/ppc/kernel/setup.c	Mon Feb 17 14:57:28 2003
+++ b/arch/ppc/kernel/setup.c	Mon Feb 17 14:57:28 2003
@@ -129,6 +129,8 @@
 	ppc_md.halt();
 }
 
+void (*pm_power_off)(void) = machine_power_off;
+
 #ifdef CONFIG_TAU
 extern u32 cpu_temp(unsigned long cpu);
 extern u32 cpu_temp_both(unsigned long cpu);
diff -Nru a/arch/ppc/kernel/signal.c b/arch/ppc/kernel/signal.c
--- a/arch/ppc/kernel/signal.c	Mon Feb 17 14:57:28 2003
+++ b/arch/ppc/kernel/signal.c	Mon Feb 17 14:57:28 2003
@@ -389,7 +389,7 @@
 {
 	struct sigcontext *sc;
 	struct rt_sigframe *rt_sf;
-	struct k_sigaction *ka = &current->sig->action[sig-1];
+	struct k_sigaction *ka = &current->sighand->action[sig-1];
 
 	if (TRAP(regs) == 0x0C00 /* System Call! */
 	    && ((int)regs->result == -ERESTARTNOHAND ||
@@ -486,7 +486,7 @@
 
 	signr = get_signal_to_deliver(&info, regs, NULL);
 	if (signr > 0) {
-		ka = &current->sig->action[signr-1];
+		ka = &current->sighand->action[signr-1];
 		if ( (ka->sa.sa_flags & SA_ONSTACK)
 		     && (! on_sig_stack(regs->gpr[1])))
 			newsp = (current->sas_ss_sp + current->sas_ss_size);
diff -Nru a/arch/ppc/platforms/4xx/ash.c b/arch/ppc/platforms/4xx/ash.c
--- a/arch/ppc/platforms/4xx/ash.c	Mon Feb 17 14:57:26 2003
+++ b/arch/ppc/platforms/4xx/ash.c	Mon Feb 17 14:57:26 2003
@@ -6,7 +6,7 @@
  * Author: Armin Kuster <akuster@mvista.com>
  *
  * 2001-2002 (c) MontaVista, Software, Inc.  This file is licensed under
- * the terms of the GNU General Public License version 2.1.  This program
+ * the terms of the GNU General Public License version 2.  This program
  * is licensed "as is" without any warranty of any kind, whether express
  * or implied.
  */
diff -Nru a/arch/ppc/platforms/4xx/ash.h b/arch/ppc/platforms/4xx/ash.h
--- a/arch/ppc/platforms/4xx/ash.h	Mon Feb 17 14:57:26 2003
+++ b/arch/ppc/platforms/4xx/ash.h	Mon Feb 17 14:57:26 2003
@@ -7,7 +7,7 @@
  * Author: Armin Kuster <akuster@mvista.com>
  *
  * 2000-2002 (c) MontaVista, Software, Inc.  This file is licensed under
- * the terms of the GNU General Public License version 2.1.  This program
+ * the terms of the GNU General Public License version 2.  This program
  * is licensed "as is" without any warranty of any kind, whether express
  * or implied.
  */
diff -Nru a/arch/ppc/platforms/4xx/cedar.c b/arch/ppc/platforms/4xx/cedar.c
--- a/arch/ppc/platforms/4xx/cedar.c	Mon Feb 17 14:57:27 2003
+++ b/arch/ppc/platforms/4xx/cedar.c	Mon Feb 17 14:57:27 2003
@@ -6,7 +6,7 @@
  * Author: Armin Kuster <akuster@mvista.com>
  *
  * 2001 (c) MontaVista, Software, Inc.  This file is licensed under
- * the terms of the GNU General Public License version 2.1.  This program
+ * the terms of the GNU General Public License version 2.  This program
  * is licensed "as is" without any warranty of any kind, whether express
  * or implied.
  */
diff -Nru a/arch/ppc/platforms/4xx/cedar.h b/arch/ppc/platforms/4xx/cedar.h
--- a/arch/ppc/platforms/4xx/cedar.h	Mon Feb 17 14:57:27 2003
+++ b/arch/ppc/platforms/4xx/cedar.h	Mon Feb 17 14:57:27 2003
@@ -7,7 +7,7 @@
  * Author: Armin Kuster <akuster@mvista.com>
  *
  * 2000 (c) MontaVista, Software, Inc.  This file is licensed under
- * the terms of the GNU General Public License version 2.1.  This program
+ * the terms of the GNU General Public License version 2.  This program
  * is licensed "as is" without any warranty of any kind, whether express
  * or implied.
  */
diff -Nru a/arch/ppc/platforms/4xx/ep405.c b/arch/ppc/platforms/4xx/ep405.c
--- a/arch/ppc/platforms/4xx/ep405.c	Mon Feb 17 14:57:26 2003
+++ b/arch/ppc/platforms/4xx/ep405.c	Mon Feb 17 14:57:26 2003
@@ -7,7 +7,7 @@
  * Author: Matthew Locke <mlocke@mvista.com>
  * 
  * 2001 (c) MontaVista, Software, Inc.  This file is licensed under
- * the terms of the GNU General Public License version 2.1.  This program
+ * the terms of the GNU General Public License version 2.  This program
  * is licensed "as is" without any warranty of any kind, whether express
  * or implied.
  */
diff -Nru a/arch/ppc/platforms/4xx/ep405.h b/arch/ppc/platforms/4xx/ep405.h
--- a/arch/ppc/platforms/4xx/ep405.h	Mon Feb 17 14:57:26 2003
+++ b/arch/ppc/platforms/4xx/ep405.h	Mon Feb 17 14:57:26 2003
@@ -7,7 +7,7 @@
  * Author: Matthew Locke <mlocke@mvista.com>
  *
  * 2000 (c) MontaVista, Software, Inc.  This file is licensed under
- * the terms of the GNU General Public License version 2.1.  This program
+ * the terms of the GNU General Public License version 2.  This program
  * is licensed "as is" without any warranty of any kind, whether express
  * or implied.
  */
diff -Nru a/arch/ppc/platforms/4xx/ibm405gp.c b/arch/ppc/platforms/4xx/ibm405gp.c
--- a/arch/ppc/platforms/4xx/ibm405gp.c	Mon Feb 17 14:57:27 2003
+++ b/arch/ppc/platforms/4xx/ibm405gp.c	Mon Feb 17 14:57:27 2003
@@ -4,7 +4,7 @@
  * Author: Armin Kuster <akuster@mvista.com>
  *
  * 2001 (c) MontaVista, Software, Inc.  This file is licensed under
- * the terms of the GNU General Public License version 2.1.  This program
+ * the terms of the GNU General Public License version 2.  This program
  * is licensed "as is" without any warranty of any kind, whether express
  * or implied.
  */
diff -Nru a/arch/ppc/platforms/4xx/ibm405gp.h b/arch/ppc/platforms/4xx/ibm405gp.h
--- a/arch/ppc/platforms/4xx/ibm405gp.h	Mon Feb 17 14:57:26 2003
+++ b/arch/ppc/platforms/4xx/ibm405gp.h	Mon Feb 17 14:57:26 2003
@@ -4,7 +4,7 @@
  * Author: Armin Kuster akuster@mvista.com
  *
  * 2001 (c) MontaVista, Software, Inc.  This file is licensed under
- * the terms of the GNU General Public License version 2.1.  This program
+ * the terms of the GNU General Public License version 2.  This program
  * is licensed "as is" without any warranty of any kind, whether express
  * or implied.
  */
diff -Nru a/arch/ppc/platforms/4xx/ibm405gpr.c b/arch/ppc/platforms/4xx/ibm405gpr.c
--- a/arch/ppc/platforms/4xx/ibm405gpr.c	Mon Feb 17 14:57:27 2003
+++ b/arch/ppc/platforms/4xx/ibm405gpr.c	Mon Feb 17 14:57:27 2003
@@ -4,7 +4,7 @@
  * Author: Armin Kuster <akuster@mvista.com>
  *
  * 2002 (c) MontaVista, Software, Inc.  This file is licensed under
- * the terms of the GNU General Public License version 2.1.  This program
+ * the terms of the GNU General Public License version 2.  This program
  * is licensed "as is" without any warranty of any kind, whether express
  * or implied.
  */
diff -Nru a/arch/ppc/platforms/4xx/ibm405gpr.h b/arch/ppc/platforms/4xx/ibm405gpr.h
--- a/arch/ppc/platforms/4xx/ibm405gpr.h	Mon Feb 17 14:57:27 2003
+++ b/arch/ppc/platforms/4xx/ibm405gpr.h	Mon Feb 17 14:57:27 2003
@@ -4,7 +4,7 @@
  * Author: Armin Kuster <akuster@mvista.com>
  *
  * 2002 (c) MontaVista, Software, Inc.  This file is licensed under
- * the terms of the GNU General Public License version 2.1.  This program
+ * the terms of the GNU General Public License version 2.  This program
  * is licensed "as is" without any warranty of any kind, whether express
  * or implied.
  */
diff -Nru a/arch/ppc/platforms/4xx/ibmnp405h.c b/arch/ppc/platforms/4xx/ibmnp405h.c
--- a/arch/ppc/platforms/4xx/ibmnp405h.c	Mon Feb 17 14:57:28 2003
+++ b/arch/ppc/platforms/4xx/ibmnp405h.c	Mon Feb 17 14:57:28 2003
@@ -4,7 +4,7 @@
  * Author: Armin Kuster <akuster@mvista.com>
  *
  * 2000-2002 (c) MontaVista, Software, Inc.  This file is licensed under
- * the terms of the GNU General Public License version 2.1.  This program
+ * the terms of the GNU General Public License version 2.  This program
  * is licensed "as is" without any warranty of any kind, whether express
  * or implied.
  */
diff -Nru a/arch/ppc/platforms/4xx/ibmnp405h.h b/arch/ppc/platforms/4xx/ibmnp405h.h
--- a/arch/ppc/platforms/4xx/ibmnp405h.h	Mon Feb 17 14:57:27 2003
+++ b/arch/ppc/platforms/4xx/ibmnp405h.h	Mon Feb 17 14:57:27 2003
@@ -4,7 +4,7 @@
  * Author: Armin Kuster <akuster@mvista.com>
  *
  * 2002 (c) MontaVista, Software, Inc.  This file is licensed under
- * the terms of the GNU General Public License version 2.1.  This program
+ * the terms of the GNU General Public License version 2.  This program
  * is licensed "as is" without any warranty of any kind, whether express
  * or implied.
  */
diff -Nru a/arch/ppc/platforms/4xx/ibmnp405l.c b/arch/ppc/platforms/4xx/ibmnp405l.c
--- a/arch/ppc/platforms/4xx/ibmnp405l.c	Mon Feb 17 14:57:27 2003
+++ b/arch/ppc/platforms/4xx/ibmnp405l.c	Mon Feb 17 14:57:27 2003
@@ -4,7 +4,7 @@
  * Author: Armin Kuster <akuster@mvista.com>
  *
  * 2000-2001 (c) MontaVista, Software, Inc.  This file is licensed under
- * the terms of the GNU General Public License version 2.1.  This program
+ * the terms of the GNU General Public License version 2.  This program
  * is licensed "as is" without any warranty of any kind, whether express
  * or implied.
  */
diff -Nru a/arch/ppc/platforms/4xx/ibmnp405l.h b/arch/ppc/platforms/4xx/ibmnp405l.h
--- a/arch/ppc/platforms/4xx/ibmnp405l.h	Mon Feb 17 14:57:27 2003
+++ b/arch/ppc/platforms/4xx/ibmnp405l.h	Mon Feb 17 14:57:27 2003
@@ -4,7 +4,7 @@
  * Author: Armin Kuster <akuster@mvista.com>
  *
  * 2001 (c) MontaVista, Software, Inc.  This file is licensed under
- * the terms of the GNU General Public License version 2.1.  This program
+ * the terms of the GNU General Public License version 2.  This program
  * is licensed "as is" without any warranty of any kind, whether express
  * or implied.
  */
diff -Nru a/arch/ppc/platforms/4xx/ibmnp4gs.c b/arch/ppc/platforms/4xx/ibmnp4gs.c
--- a/arch/ppc/platforms/4xx/ibmnp4gs.c	Mon Feb 17 14:57:27 2003
+++ b/arch/ppc/platforms/4xx/ibmnp4gs.c	Mon Feb 17 14:57:27 2003
@@ -4,7 +4,7 @@
  * Author: Armin Kuster <akuster@mvista.com>
  *
  * 2000-2002 (c) MontaVista, Software, Inc.  This file is licensed under
- * the terms of the GNU General Public License version 2.1.  This program
+ * the terms of the GNU General Public License version 2.  This program
  * is licensed "as is" without any warranty of any kind, whether express
  * or implied.
  */
diff -Nru a/arch/ppc/platforms/4xx/ibmnp4gs.h b/arch/ppc/platforms/4xx/ibmnp4gs.h
--- a/arch/ppc/platforms/4xx/ibmnp4gs.h	Mon Feb 17 14:57:27 2003
+++ b/arch/ppc/platforms/4xx/ibmnp4gs.h	Mon Feb 17 14:57:27 2003
@@ -4,7 +4,7 @@
  * Author: Armin Kuster <akuster@mvista.com>
  *
  * 2002 (c) MontaVista, Software, Inc.  This file is licensed under
- * the terms of the GNU General Public License version 2.1.  This program
+ * the terms of the GNU General Public License version 2.  This program
  * is licensed "as is" without any warranty of any kind, whether express
  * or implied.
  */
diff -Nru a/arch/ppc/platforms/4xx/ibmstb3.c b/arch/ppc/platforms/4xx/ibmstb3.c
--- a/arch/ppc/platforms/4xx/ibmstb3.c	Mon Feb 17 14:57:26 2003
+++ b/arch/ppc/platforms/4xx/ibmstb3.c	Mon Feb 17 14:57:26 2003
@@ -4,7 +4,7 @@
  * Author: Armin Kuster <akuster@mvista.com>
  *
  * 2000-2001 (c) MontaVista, Software, Inc.  This file is licensed under
- * the terms of the GNU General Public License version 2.1.  This program
+ * the terms of the GNU General Public License version 2.  This program
  * is licensed "as is" without any warranty of any kind, whether express
  * or implied.
  */
diff -Nru a/arch/ppc/platforms/4xx/ibmstb3.h b/arch/ppc/platforms/4xx/ibmstb3.h
--- a/arch/ppc/platforms/4xx/ibmstb3.h	Mon Feb 17 14:57:28 2003
+++ b/arch/ppc/platforms/4xx/ibmstb3.h	Mon Feb 17 14:57:28 2003
@@ -4,7 +4,7 @@
  * Authors: Armin Kuster <akuster@mvista.com>, Tom Rini <trini@mvista.com>
  *
  * 2001 (c) MontaVista, Software, Inc.  This file is licensed under
- * the terms of the GNU General Public License version 2.1.  This program
+ * the terms of the GNU General Public License version 2.  This program
  * is licensed "as is" without any warranty of any kind, whether express
  * or implied.
  */
diff -Nru a/arch/ppc/platforms/4xx/ibmstb4.c b/arch/ppc/platforms/4xx/ibmstb4.c
--- a/arch/ppc/platforms/4xx/ibmstb4.c	Mon Feb 17 14:57:26 2003
+++ b/arch/ppc/platforms/4xx/ibmstb4.c	Mon Feb 17 14:57:26 2003
@@ -4,7 +4,7 @@
  * Author: Armin Kuster <akuster@mvista.com>
  *
  * 2000-2001 (c) MontaVista, Software, Inc.  This file is licensed under
- * the terms of the GNU General Public License version 2.1.  This program
+ * the terms of the GNU General Public License version 2.  This program
  * is licensed "as is" without any warranty of any kind, whether express
  * or implied.
  */
diff -Nru a/arch/ppc/platforms/4xx/ibmstb4.h b/arch/ppc/platforms/4xx/ibmstb4.h
--- a/arch/ppc/platforms/4xx/ibmstb4.h	Mon Feb 17 14:57:28 2003
+++ b/arch/ppc/platforms/4xx/ibmstb4.h	Mon Feb 17 14:57:28 2003
@@ -4,7 +4,7 @@
  * Author: Armin Kuster <akuster@mvista.com>
  *
  * 2001 (c) MontaVista, Software, Inc.  This file is licensed under
- * the terms of the GNU General Public License version 2.1.  This program
+ * the terms of the GNU General Public License version 2.  This program
  * is licensed "as is" without any warranty of any kind, whether express
  * or implied.
  */
diff -Nru a/arch/ppc/platforms/4xx/ibmstbx25.c b/arch/ppc/platforms/4xx/ibmstbx25.c
--- a/arch/ppc/platforms/4xx/ibmstbx25.c	Mon Feb 17 14:57:27 2003
+++ b/arch/ppc/platforms/4xx/ibmstbx25.c	Mon Feb 17 14:57:27 2003
@@ -4,7 +4,7 @@
  * Author: Armin Kuster <akuster@mvista.com>
  *
  * 2000-2002 (c) MontaVista, Software, Inc.  This file is licensed under
- * the terms of the GNU General Public License version 2.1.  This program
+ * the terms of the GNU General Public License version 2.  This program
  * is licensed "as is" without any warranty of any kind, whether express
  * or implied.
  */
diff -Nru a/arch/ppc/platforms/4xx/ibmstbx25.h b/arch/ppc/platforms/4xx/ibmstbx25.h
--- a/arch/ppc/platforms/4xx/ibmstbx25.h	Mon Feb 17 14:57:27 2003
+++ b/arch/ppc/platforms/4xx/ibmstbx25.h	Mon Feb 17 14:57:27 2003
@@ -4,7 +4,7 @@
  * Author: Armin Kuster <akuster@mvista.com>
  *
  * 2002 (c) MontaVista, Software, Inc.  This file is licensed under
- * the terms of the GNU General Public License version 2.1.  This program
+ * the terms of the GNU General Public License version 2.  This program
  * is licensed "as is" without any warranty of any kind, whether express
  * or implied.
  */
diff -Nru a/arch/ppc/platforms/4xx/redwood.c b/arch/ppc/platforms/4xx/redwood.c
--- a/arch/ppc/platforms/4xx/redwood.c	Mon Feb 17 14:57:28 2003
+++ b/arch/ppc/platforms/4xx/redwood.c	Mon Feb 17 14:57:28 2003
@@ -4,7 +4,7 @@
  * Author: Frank Rowand <frank_rowand@mvista.com>, or source@mvista.com
  *
  * 2000-2001 (c) MontaVista, Software, Inc.  This file is licensed under
- * the terms of the GNU General Public License version 2.1.  This program
+ * the terms of the GNU General Public License version 2.  This program
  * is licensed "as is" without any warranty of any kind, whether express
  * or implied.
  */
diff -Nru a/arch/ppc/platforms/4xx/redwood.h b/arch/ppc/platforms/4xx/redwood.h
--- a/arch/ppc/platforms/4xx/redwood.h	Mon Feb 17 14:57:28 2003
+++ b/arch/ppc/platforms/4xx/redwood.h	Mon Feb 17 14:57:28 2003
@@ -7,7 +7,7 @@
  * Author: Frank Rowand <frank_rowand@mvista.com>, or source@mvista.com
  * 
  * 2001 (c) MontaVista, Software, Inc.  This file is licensed under
- * the terms of the GNU General Public License version 2.1.  This program
+ * the terms of the GNU General Public License version 2.  This program
  * is licensed "as is" without any warranty of any kind, whether express
  * or implied.
  */
diff -Nru a/arch/ppc/platforms/4xx/redwood5.c b/arch/ppc/platforms/4xx/redwood5.c
--- a/arch/ppc/platforms/4xx/redwood5.c	Mon Feb 17 14:57:27 2003
+++ b/arch/ppc/platforms/4xx/redwood5.c	Mon Feb 17 14:57:27 2003
@@ -6,7 +6,7 @@
  * Author: Armin Kuster <akuster@mvista.com>
  *
  * 2000-2001 (c) MontaVista, Software, Inc.  This file is licensed under
- * the terms of the GNU General Public License version 2.1.  This program
+ * the terms of the GNU General Public License version 2.  This program
  * is licensed "as is" without any warranty of any kind, whether express
  * or implied.
  */
diff -Nru a/arch/ppc/platforms/4xx/redwood5.h b/arch/ppc/platforms/4xx/redwood5.h
--- a/arch/ppc/platforms/4xx/redwood5.h	Mon Feb 17 14:57:26 2003
+++ b/arch/ppc/platforms/4xx/redwood5.h	Mon Feb 17 14:57:26 2003
@@ -7,7 +7,7 @@
  * Author: Armin Kuster <akuster@mvista.com>
  *
  * 2001 (c) MontaVista, Software, Inc.  This file is licensed under
- * the terms of the GNU General Public License version 2.1.  This program
+ * the terms of the GNU General Public License version 2.  This program
  * is licensed "as is" without any warranty of any kind, whether express
  * or implied.
  */
diff -Nru a/arch/ppc/platforms/4xx/redwood6.c b/arch/ppc/platforms/4xx/redwood6.c
--- a/arch/ppc/platforms/4xx/redwood6.c	Mon Feb 17 14:57:28 2003
+++ b/arch/ppc/platforms/4xx/redwood6.c	Mon Feb 17 14:57:28 2003
@@ -4,7 +4,7 @@
  * Author: Armin Kuster <akuster@mvista.com>
  *
  * 2002 (c) MontaVista, Software, Inc.  This file is licensed under
- * the terms of the GNU General Public License version 2.1.  This program
+ * the terms of the GNU General Public License version 2.  This program
  * is licensed "as is" without any warranty of any kind, whether express
  * or implied.
  */
diff -Nru a/arch/ppc/platforms/4xx/redwood6.h b/arch/ppc/platforms/4xx/redwood6.h
--- a/arch/ppc/platforms/4xx/redwood6.h	Mon Feb 17 14:57:27 2003
+++ b/arch/ppc/platforms/4xx/redwood6.h	Mon Feb 17 14:57:27 2003
@@ -7,7 +7,7 @@
  * Author: Armin Kuster <akuster@mvista.com>
  *
  * 2002 (c) MontaVista, Software, Inc.  This file is licensed under
- * the terms of the GNU General Public License version 2.1.  This program
+ * the terms of the GNU General Public License version 2.  This program
  * is licensed "as is" without any warranty of any kind, whether express
  * or implied.
  */
diff -Nru a/arch/ppc/platforms/4xx/sycamore.c b/arch/ppc/platforms/4xx/sycamore.c
--- a/arch/ppc/platforms/4xx/sycamore.c	Mon Feb 17 14:57:27 2003
+++ b/arch/ppc/platforms/4xx/sycamore.c	Mon Feb 17 14:57:27 2003
@@ -7,7 +7,7 @@
  * Author: Armin Kuster <akuster@mvista.com>
  *
  * 2000-2002 (c) MontaVista, Software, Inc.  This file is licensed under
- * the terms of the GNU General Public License version 2.1.  This program
+ * the terms of the GNU General Public License version 2.  This program
  * is licensed "as is" without any warranty of any kind, whether express
  * or implied.
  */
diff -Nru a/arch/ppc/platforms/4xx/sycamore.h b/arch/ppc/platforms/4xx/sycamore.h
--- a/arch/ppc/platforms/4xx/sycamore.h	Mon Feb 17 14:57:27 2003
+++ b/arch/ppc/platforms/4xx/sycamore.h	Mon Feb 17 14:57:27 2003
@@ -7,7 +7,7 @@
  * Author: Armin Kuster <akuster@mvista.com>
  *
  * 2000 (c) MontaVista, Software, Inc.  This file is licensed under
- * the terms of the GNU General Public License version 2.1.  This program
+ * the terms of the GNU General Public License version 2.  This program
  * is licensed "as is" without any warranty of any kind, whether express
  * or implied.
  */
diff -Nru a/arch/ppc/platforms/4xx/walnut.c b/arch/ppc/platforms/4xx/walnut.c
--- a/arch/ppc/platforms/4xx/walnut.c	Mon Feb 17 14:57:27 2003
+++ b/arch/ppc/platforms/4xx/walnut.c	Mon Feb 17 14:57:27 2003
@@ -9,7 +9,7 @@
  * Copyright(c) 1999-2000 Grant Erickson <grant@lcse.umn.edu>
  *
  * 2002 (c) MontaVista, Software, Inc.  This file is licensed under
- * the terms of the GNU General Public License version 2.1.  This program
+ * the terms of the GNU General Public License version 2.  This program
  * is licensed "as is" without any warranty of any kind, whether express
  * or implied.
  */
diff -Nru a/arch/ppc/platforms/4xx/walnut.h b/arch/ppc/platforms/4xx/walnut.h
--- a/arch/ppc/platforms/4xx/walnut.h	Mon Feb 17 14:57:27 2003
+++ b/arch/ppc/platforms/4xx/walnut.h	Mon Feb 17 14:57:27 2003
@@ -11,7 +11,7 @@
  * Copyright (c) 1999 Grant Erickson <grant@lcse.umn.edu>
  *
  * 2000 (c) MontaVista, Software, Inc.  This file is licensed under
- * the terms of the GNU General Public License version 2.1.  This program
+ * the terms of the GNU General Public License version 2.  This program
  * is licensed "as is" without any warranty of any kind, whether express
  * or implied.
  */
diff -Nru a/arch/ppc/platforms/ev64260.h b/arch/ppc/platforms/ev64260.h
--- a/arch/ppc/platforms/ev64260.h	Mon Feb 17 14:57:26 2003
+++ b/arch/ppc/platforms/ev64260.h	Mon Feb 17 14:57:26 2003
@@ -6,7 +6,7 @@
  * Author: Mark A. Greer <mgreer@mvista.com>
  *
  * 2001 (c) MontaVista, Software, Inc.  This file is licensed under
- * the terms of the GNU General Public License version 2.1.  This program
+ * the terms of the GNU General Public License version 2.  This program
  * is licensed "as is" without any warranty of any kind, whether express
  * or implied.
  */
diff -Nru a/arch/ppc/platforms/ev64260_setup.c b/arch/ppc/platforms/ev64260_setup.c
--- a/arch/ppc/platforms/ev64260_setup.c	Mon Feb 17 14:57:27 2003
+++ b/arch/ppc/platforms/ev64260_setup.c	Mon Feb 17 14:57:27 2003
@@ -6,7 +6,7 @@
  * Author: Mark A. Greer <mgreer@mvista.com>
  *
  * 2001 (c) MontaVista, Software, Inc.  This file is licensed under
- * the terms of the GNU General Public License version 2.1.  This program
+ * the terms of the GNU General Public License version 2.  This program
  * is licensed "as is" without any warranty of any kind, whether express
  * or implied.
  */
diff -Nru a/arch/ppc/platforms/k2.h b/arch/ppc/platforms/k2.h
--- a/arch/ppc/platforms/k2.h	Mon Feb 17 14:57:27 2003
+++ b/arch/ppc/platforms/k2.h	Mon Feb 17 14:57:27 2003
@@ -6,7 +6,7 @@
  * Author: Matt Porter <mporter@mvista.com>
  *
  * 2001 (c) MontaVista, Software, Inc.  This file is licensed under
- * the terms of the GNU General Public License version 2.1.  This program
+ * the terms of the GNU General Public License version 2.  This program
  * is licensed "as is" without any warranty of any kind, whether express
  * or implied.
  */
diff -Nru a/arch/ppc/platforms/k2_pci.c b/arch/ppc/platforms/k2_pci.c
--- a/arch/ppc/platforms/k2_pci.c	Mon Feb 17 14:57:28 2003
+++ b/arch/ppc/platforms/k2_pci.c	Mon Feb 17 14:57:28 2003
@@ -6,7 +6,7 @@
  * Author: Matt Porter <mporter@mvista.com>
  *
  * 2001 (c) MontaVista, Software, Inc.  This file is licensed under
- * the terms of the GNU General Public License version 2.1.  This program
+ * the terms of the GNU General Public License version 2.  This program
  * is licensed "as is" without any warranty of any kind, whether express
  * or implied.
  */
diff -Nru a/arch/ppc/platforms/k2_setup.c b/arch/ppc/platforms/k2_setup.c
--- a/arch/ppc/platforms/k2_setup.c	Mon Feb 17 14:57:27 2003
+++ b/arch/ppc/platforms/k2_setup.c	Mon Feb 17 14:57:27 2003
@@ -6,7 +6,7 @@
  * Author: Matt Porter <mporter@mvista.com>
  *
  * 2001 (c) MontaVista, Software, Inc.  This file is licensed under
- * the terms of the GNU General Public License version 2.1.  This program
+ * the terms of the GNU General Public License version 2.  This program
  * is licensed "as is" without any warranty of any kind, whether express
  * or implied.
  */
diff -Nru a/arch/ppc/platforms/lopec_pci.c b/arch/ppc/platforms/lopec_pci.c
--- a/arch/ppc/platforms/lopec_pci.c	Mon Feb 17 14:57:27 2003
+++ b/arch/ppc/platforms/lopec_pci.c	Mon Feb 17 14:57:27 2003
@@ -7,7 +7,7 @@
  *         danc@mvista.com (or, alternately, source@mvista.com)
  *
  * 2001-2002 (c) MontaVista, Software, Inc.  This file is licensed under
- * the terms of the GNU General Public License version 2.1.  This program
+ * the terms of the GNU General Public License version 2.  This program
  * is licensed "as is" without any warranty of any kind, whether express
  * or implied.
  */
diff -Nru a/arch/ppc/platforms/lopec_serial.h b/arch/ppc/platforms/lopec_serial.h
--- a/arch/ppc/platforms/lopec_serial.h	Mon Feb 17 14:57:28 2003
+++ b/arch/ppc/platforms/lopec_serial.h	Mon Feb 17 14:57:28 2003
@@ -7,7 +7,7 @@
  *         danc@mvista.com (or, alternately, source@mvista.com)
  *
  * 2001 (c) MontaVista, Software, Inc.  This file is licensed under
- * the terms of the GNU General Public License version 2.1.  This program
+ * the terms of the GNU General Public License version 2.  This program
  * is licensed "as is" without any warranty of any kind, whether express
  * or implied.
  */
diff -Nru a/arch/ppc/platforms/lopec_setup.c b/arch/ppc/platforms/lopec_setup.c
--- a/arch/ppc/platforms/lopec_setup.c	Mon Feb 17 14:57:27 2003
+++ b/arch/ppc/platforms/lopec_setup.c	Mon Feb 17 14:57:27 2003
@@ -7,7 +7,7 @@
  *         danc@mvista.com
  *
  * 2001-2002 (c) MontaVista, Software, Inc.  This file is licensed under
- * the terms of the GNU General Public License version 2.1.  This program
+ * the terms of the GNU General Public License version 2.  This program
  * is licensed "as is" without any warranty of any kind, whether express
  * or implied.
  */
diff -Nru a/arch/ppc/platforms/mcpn765.h b/arch/ppc/platforms/mcpn765.h
--- a/arch/ppc/platforms/mcpn765.h	Mon Feb 17 14:57:27 2003
+++ b/arch/ppc/platforms/mcpn765.h	Mon Feb 17 14:57:27 2003
@@ -7,7 +7,7 @@
  *         mgreer@mvista.com
  *
  * 2001 (c) MontaVista, Software, Inc.  This file is licensed under
- * the terms of the GNU General Public License version 2.1.  This program
+ * the terms of the GNU General Public License version 2.  This program
  * is licensed "as is" without any warranty of any kind, whether express
  * or implied.
  */
diff -Nru a/arch/ppc/platforms/mcpn765_pci.c b/arch/ppc/platforms/mcpn765_pci.c
--- a/arch/ppc/platforms/mcpn765_pci.c	Mon Feb 17 14:57:27 2003
+++ b/arch/ppc/platforms/mcpn765_pci.c	Mon Feb 17 14:57:27 2003
@@ -7,7 +7,7 @@
  *         mgreer@mvista.com
  *
  * 2001 (c) MontaVista, Software, Inc.  This file is licensed under
- * the terms of the GNU General Public License version 2.1.  This program
+ * the terms of the GNU General Public License version 2.  This program
  * is licensed "as is" without any warranty of any kind, whether express
  * or implied.
  */
diff -Nru a/arch/ppc/platforms/mcpn765_serial.h b/arch/ppc/platforms/mcpn765_serial.h
--- a/arch/ppc/platforms/mcpn765_serial.h	Mon Feb 17 14:57:28 2003
+++ b/arch/ppc/platforms/mcpn765_serial.h	Mon Feb 17 14:57:28 2003
@@ -7,7 +7,7 @@
  *         mgreer@mvista.com
  *
  * 2001 (c) MontaVista, Software, Inc.  This file is licensed under
- * the terms of the GNU General Public License version 2.1.  This program
+ * the terms of the GNU General Public License version 2.  This program
  * is licensed "as is" without any warranty of any kind, whether express
  * or implied.
  */
diff -Nru a/arch/ppc/platforms/mcpn765_setup.c b/arch/ppc/platforms/mcpn765_setup.c
--- a/arch/ppc/platforms/mcpn765_setup.c	Mon Feb 17 14:57:27 2003
+++ b/arch/ppc/platforms/mcpn765_setup.c	Mon Feb 17 14:57:27 2003
@@ -7,7 +7,7 @@
  *         mgreer@mvista.com
  *
  * 2001-2002 (c) MontaVista, Software, Inc.  This file is licensed under
- * the terms of the GNU General Public License version 2.1.  This program
+ * the terms of the GNU General Public License version 2.  This program
  * is licensed "as is" without any warranty of any kind, whether express
  * or implied.
  */
diff -Nru a/arch/ppc/platforms/menf1.h b/arch/ppc/platforms/menf1.h
--- a/arch/ppc/platforms/menf1.h	Mon Feb 17 14:57:26 2003
+++ b/arch/ppc/platforms/menf1.h	Mon Feb 17 14:57:26 2003
@@ -6,7 +6,7 @@
  * Author: Matt Porter <mporter@mvista.com>
  *
  * 2001 (c) MontaVista, Software, Inc.  This file is licensed under
- * the terms of the GNU General Public License version 2.1.  This program
+ * the terms of the GNU General Public License version 2.  This program
  * is licensed "as is" without any warranty of any kind, whether express
  * or implied.
  */
diff -Nru a/arch/ppc/platforms/menf1_pci.c b/arch/ppc/platforms/menf1_pci.c
--- a/arch/ppc/platforms/menf1_pci.c	Mon Feb 17 14:57:27 2003
+++ b/arch/ppc/platforms/menf1_pci.c	Mon Feb 17 14:57:27 2003
@@ -6,7 +6,7 @@
  * Author: Matt Porter <mporter@mvista.com>
  *
  * 2001 (c) MontaVista, Software, Inc.  This file is licensed under
- * the terms of the GNU General Public License version 2.1.  This program
+ * the terms of the GNU General Public License version 2.  This program
  * is licensed "as is" without any warranty of any kind, whether express
  * or implied.
  */
diff -Nru a/arch/ppc/platforms/menf1_setup.c b/arch/ppc/platforms/menf1_setup.c
--- a/arch/ppc/platforms/menf1_setup.c	Mon Feb 17 14:57:28 2003
+++ b/arch/ppc/platforms/menf1_setup.c	Mon Feb 17 14:57:28 2003
@@ -6,7 +6,7 @@
  * Author: Matt Porter <mporter@mvista.com>
  *
  * 2001 (c) MontaVista, Software, Inc.  This file is licensed under
- * the terms of the GNU General Public License version 2.1.  This program
+ * the terms of the GNU General Public License version 2.  This program
  * is licensed "as is" without any warranty of any kind, whether express
  * or implied.
  */
diff -Nru a/arch/ppc/platforms/mvme5100.h b/arch/ppc/platforms/mvme5100.h
--- a/arch/ppc/platforms/mvme5100.h	Mon Feb 17 14:57:28 2003
+++ b/arch/ppc/platforms/mvme5100.h	Mon Feb 17 14:57:28 2003
@@ -6,7 +6,7 @@
  * Author: Matt Porter <mporter@mvista.com>
  *
  * 2001 (c) MontaVista, Software, Inc.  This file is licensed under
- * the terms of the GNU General Public License version 2.1.  This program
+ * the terms of the GNU General Public License version 2.  This program
  * is licensed "as is" without any warranty of any kind, whether express
  * or implied.
  */
diff -Nru a/arch/ppc/platforms/mvme5100_pci.c b/arch/ppc/platforms/mvme5100_pci.c
--- a/arch/ppc/platforms/mvme5100_pci.c	Mon Feb 17 14:57:26 2003
+++ b/arch/ppc/platforms/mvme5100_pci.c	Mon Feb 17 14:57:26 2003
@@ -6,7 +6,7 @@
  * Author: Matt Porter <mporter@mvista.com>
  *
  * 2001 (c) MontaVista, Software, Inc.  This file is licensed under
- * the terms of the GNU General Public License version 2.1.  This program
+ * the terms of the GNU General Public License version 2.  This program
  * is licensed "as is" without any warranty of any kind, whether express
  * or implied.
  */
diff -Nru a/arch/ppc/platforms/mvme5100_serial.h b/arch/ppc/platforms/mvme5100_serial.h
--- a/arch/ppc/platforms/mvme5100_serial.h	Mon Feb 17 14:57:27 2003
+++ b/arch/ppc/platforms/mvme5100_serial.h	Mon Feb 17 14:57:27 2003
@@ -6,7 +6,7 @@
  * Author: Matt Porter <mporter@mvista.com>
  *
  * 2001 (c) MontaVista, Software, Inc.  This file is licensed under
- * the terms of the GNU General Public License version 2.1.  This program
+ * the terms of the GNU General Public License version 2.  This program
  * is licensed "as is" without any warranty of any kind, whether express
  * or implied.
  */
diff -Nru a/arch/ppc/platforms/mvme5100_setup.c b/arch/ppc/platforms/mvme5100_setup.c
--- a/arch/ppc/platforms/mvme5100_setup.c	Mon Feb 17 14:57:27 2003
+++ b/arch/ppc/platforms/mvme5100_setup.c	Mon Feb 17 14:57:27 2003
@@ -6,7 +6,7 @@
  * Author: Matt Porter <mporter@mvista.com>
  *
  * 2001 (c) MontaVista, Software, Inc.  This file is licensed under
- * the terms of the GNU General Public License version 2.1.  This program
+ * the terms of the GNU General Public License version 2.  This program
  * is licensed "as is" without any warranty of any kind, whether express
  * or implied.
  */
diff -Nru a/arch/ppc/platforms/pal4.h b/arch/ppc/platforms/pal4.h
--- a/arch/ppc/platforms/pal4.h	Mon Feb 17 14:57:26 2003
+++ b/arch/ppc/platforms/pal4.h	Mon Feb 17 14:57:26 2003
@@ -6,7 +6,7 @@
  * Author: Dan Cox
  *
  * 2002 (c) MontaVista, Software, Inc.  This file is licensed under
- * the terms of the GNU General Public License version 2.1.  This program
+ * the terms of the GNU General Public License version 2.  This program
  * is licensed "as is" without any warranty of any kind, whether express
  * or implied.
  */
diff -Nru a/arch/ppc/platforms/pal4_pci.c b/arch/ppc/platforms/pal4_pci.c
--- a/arch/ppc/platforms/pal4_pci.c	Mon Feb 17 14:57:28 2003
+++ b/arch/ppc/platforms/pal4_pci.c	Mon Feb 17 14:57:28 2003
@@ -6,7 +6,7 @@
  * Author: Dan Cox 
  *
  * 2002 (c) MontaVista, Software, Inc.  This file is licensed under
- * the terms of the GNU General Public License version 2.1.  This program
+ * the terms of the GNU General Public License version 2.  This program
  * is licensed "as is" without any warranty of any kind, whether express
  * or implied.
  */
diff -Nru a/arch/ppc/platforms/pal4_serial.h b/arch/ppc/platforms/pal4_serial.h
--- a/arch/ppc/platforms/pal4_serial.h	Mon Feb 17 14:57:28 2003
+++ b/arch/ppc/platforms/pal4_serial.h	Mon Feb 17 14:57:28 2003
@@ -6,7 +6,7 @@
  * Author: Dan Cox
  *
  * 2002 (c) MontaVista, Software, Inc.  This file is licensed under
- * the terms of the GNU General Public License version 2.1.  This program
+ * the terms of the GNU General Public License version 2.  This program
  * is licensed "as is" without any warranty of any kind, whether express
  * or implied.
  */
diff -Nru a/arch/ppc/platforms/pal4_setup.c b/arch/ppc/platforms/pal4_setup.c
--- a/arch/ppc/platforms/pal4_setup.c	Mon Feb 17 14:57:28 2003
+++ b/arch/ppc/platforms/pal4_setup.c	Mon Feb 17 14:57:28 2003
@@ -6,7 +6,7 @@
  * Author: Dan Cox
  *
  * 2002 (c) MontaVista, Software, Inc.  This file is licensed under
- * the terms of the GNU General Public License version 2.1.  This program
+ * the terms of the GNU General Public License version 2.  This program
  * is licensed "as is" without any warranty of any kind, whether express
  * or implied.
  */
diff -Nru a/arch/ppc/platforms/pcore.h b/arch/ppc/platforms/pcore.h
--- a/arch/ppc/platforms/pcore.h	Mon Feb 17 14:57:27 2003
+++ b/arch/ppc/platforms/pcore.h	Mon Feb 17 14:57:27 2003
@@ -6,7 +6,7 @@
  * Author: Matt Porter <mporter@mvista.com>
  *
  * 2001 (c) MontaVista, Software, Inc.  This file is licensed under
- * the terms of the GNU General Public License version 2.1.  This program
+ * the terms of the GNU General Public License version 2.  This program
  * is licensed "as is" without any warranty of any kind, whether express
  * or implied.
  */
diff -Nru a/arch/ppc/platforms/pcore_pci.c b/arch/ppc/platforms/pcore_pci.c
--- a/arch/ppc/platforms/pcore_pci.c	Mon Feb 17 14:57:27 2003
+++ b/arch/ppc/platforms/pcore_pci.c	Mon Feb 17 14:57:27 2003
@@ -6,7 +6,7 @@
  * Author: Matt Porter <mporter@mvista.com>
  *
  * 2001 (c) MontaVista, Software, Inc.  This file is licensed under
- * the terms of the GNU General Public License version 2.1.  This program
+ * the terms of the GNU General Public License version 2.  This program
  * is licensed "as is" without any warranty of any kind, whether express
  * or implied.
  */
diff -Nru a/arch/ppc/platforms/pcore_setup.c b/arch/ppc/platforms/pcore_setup.c
--- a/arch/ppc/platforms/pcore_setup.c	Mon Feb 17 14:57:26 2003
+++ b/arch/ppc/platforms/pcore_setup.c	Mon Feb 17 14:57:26 2003
@@ -6,7 +6,7 @@
  * Author: Matt Porter <mporter@mvista.com>
  *
  * 2001 (c) MontaVista, Software, Inc.  This file is licensed under
- * the terms of the GNU General Public License version 2.1.  This program
+ * the terms of the GNU General Public License version 2.  This program
  * is licensed "as is" without any warranty of any kind, whether express
  * or implied.
  */
diff -Nru a/arch/ppc/platforms/powerpmc250.c b/arch/ppc/platforms/powerpmc250.c
--- a/arch/ppc/platforms/powerpmc250.c	Mon Feb 17 14:57:27 2003
+++ b/arch/ppc/platforms/powerpmc250.c	Mon Feb 17 14:57:27 2003
@@ -8,7 +8,7 @@
  * 	Matt Porter <mporter@mvista.com>
  *
  * 2001 (c) MontaVista, Software, Inc.  This file is licensed under
- * the terms of the GNU General Public License version 2.1.  This program
+ * the terms of the GNU General Public License version 2.  This program
  * is licensed "as is" without any warranty of any kind, whether express
  * or implied.
  */
diff -Nru a/arch/ppc/platforms/powerpmc250.h b/arch/ppc/platforms/powerpmc250.h
--- a/arch/ppc/platforms/powerpmc250.h	Mon Feb 17 14:57:27 2003
+++ b/arch/ppc/platforms/powerpmc250.h	Mon Feb 17 14:57:27 2003
@@ -8,7 +8,7 @@
  * Borrowed heavily from prpmc750.h by Matt Porter <mporter@mvista.com>
  *
  * 2001 (c) MontaVista, Software, Inc.  This file is licensed under
- * the terms of the GNU General Public License version 2.1.  This program
+ * the terms of the GNU General Public License version 2.  This program
  * is licensed "as is" without any warranty of any kind, whether express
  * or implied.
  */
diff -Nru a/arch/ppc/platforms/powerpmc250_serial.h b/arch/ppc/platforms/powerpmc250_serial.h
--- a/arch/ppc/platforms/powerpmc250_serial.h	Mon Feb 17 14:57:27 2003
+++ b/arch/ppc/platforms/powerpmc250_serial.h	Mon Feb 17 14:57:27 2003
@@ -6,7 +6,7 @@
  * Author: Troy Benjegerdes <tbenjegerdes@mvista.com>
  *
  * 2001 (c) MontaVista, Software, Inc.  This file is licensed under
- * the terms of the GNU General Public License version 2.1.  This program
+ * the terms of the GNU General Public License version 2.  This program
  * is licensed "as is" without any warranty of any kind, whether express
  * or implied.
  */
diff -Nru a/arch/ppc/platforms/pplus_pci.c b/arch/ppc/platforms/pplus_pci.c
--- a/arch/ppc/platforms/pplus_pci.c	Mon Feb 17 14:57:28 2003
+++ b/arch/ppc/platforms/pplus_pci.c	Mon Feb 17 14:57:28 2003
@@ -10,7 +10,7 @@
  * Troy Benjegerdes.
  *
  * 2001 (c) MontaVista, Software, Inc.  This file is licensed under
- * the terms of the GNU General Public License version 2.1.  This program
+ * the terms of the GNU General Public License version 2.  This program
  * is licensed "as is" without any warranty of any kind, whether express
  * or implied.
  */
diff -Nru a/arch/ppc/platforms/pplus_setup.c b/arch/ppc/platforms/pplus_setup.c
--- a/arch/ppc/platforms/pplus_setup.c	Mon Feb 17 14:57:28 2003
+++ b/arch/ppc/platforms/pplus_setup.c	Mon Feb 17 14:57:28 2003
@@ -10,7 +10,7 @@
  * Troy Benjegerdes.
  *
  * 2001-2002 (c) MontaVista, Software, Inc.  This file is licensed under
- * the terms of the GNU General Public License version 2.1.  This program
+ * the terms of the GNU General Public License version 2.  This program
  * is licensed "as is" without any warranty of any kind, whether express
  * or implied.
  */
diff -Nru a/arch/ppc/platforms/prpmc750_pci.c b/arch/ppc/platforms/prpmc750_pci.c
--- a/arch/ppc/platforms/prpmc750_pci.c	Mon Feb 17 14:57:28 2003
+++ b/arch/ppc/platforms/prpmc750_pci.c	Mon Feb 17 14:57:28 2003
@@ -6,7 +6,7 @@
  * Author: Matt Porter <mporter@mvista.com>
  *
  * 2001 (c) MontaVista, Software, Inc.  This file is licensed under
- * the terms of the GNU General Public License version 2.1.  This program
+ * the terms of the GNU General Public License version 2.  This program
  * is licensed "as is" without any warranty of any kind, whether express
  * or implied.
  */
diff -Nru a/arch/ppc/platforms/prpmc750_serial.h b/arch/ppc/platforms/prpmc750_serial.h
--- a/arch/ppc/platforms/prpmc750_serial.h	Mon Feb 17 14:57:27 2003
+++ b/arch/ppc/platforms/prpmc750_serial.h	Mon Feb 17 14:57:27 2003
@@ -6,7 +6,7 @@
  * Author: Matt Porter <mporter@mvista.com>
  *
  * 2001 (c) MontaVista, Software, Inc.  This file is licensed under
- * the terms of the GNU General Public License version 2.1.  This program
+ * the terms of the GNU General Public License version 2.  This program
  * is licensed "as is" without any warranty of any kind, whether express
  * or implied.
  */
diff -Nru a/arch/ppc/platforms/prpmc750_setup.c b/arch/ppc/platforms/prpmc750_setup.c
--- a/arch/ppc/platforms/prpmc750_setup.c	Mon Feb 17 14:57:27 2003
+++ b/arch/ppc/platforms/prpmc750_setup.c	Mon Feb 17 14:57:27 2003
@@ -6,7 +6,7 @@
  * Author: Matt Porter <mporter@mvista.com>
  *
  * 2001 (c) MontaVista, Software, Inc.  This file is licensed under
- * the terms of the GNU General Public License version 2.1.  This program
+ * the terms of the GNU General Public License version 2.  This program
  * is licensed "as is" without any warranty of any kind, whether express
  * or implied.
  */
diff -Nru a/arch/ppc/platforms/prpmc800.h b/arch/ppc/platforms/prpmc800.h
--- a/arch/ppc/platforms/prpmc800.h	Mon Feb 17 14:57:28 2003
+++ b/arch/ppc/platforms/prpmc800.h	Mon Feb 17 14:57:28 2003
@@ -6,7 +6,7 @@
  * Author: Dale Farnsworth <dale.farnsworth@mvista.com>
  *
  * 2001 (c) MontaVista, Software, Inc.  This file is licensed under
- * the terms of the GNU General Public License version 2.1.  This program
+ * the terms of the GNU General Public License version 2.  This program
  * is licensed "as is" without any warranty of any kind, whether express
  * or implied.
  */
diff -Nru a/arch/ppc/platforms/prpmc800_pci.c b/arch/ppc/platforms/prpmc800_pci.c
--- a/arch/ppc/platforms/prpmc800_pci.c	Mon Feb 17 14:57:27 2003
+++ b/arch/ppc/platforms/prpmc800_pci.c	Mon Feb 17 14:57:27 2003
@@ -6,7 +6,7 @@
  * Author: Dale Farnsworth <dale.farnsworth@mvista.com>
  *
  * 2001 (c) MontaVista, Software, Inc.  This file is licensed under
- * the terms of the GNU General Public License version 2.1.  This program
+ * the terms of the GNU General Public License version 2.  This program
  * is licensed "as is" without any warranty of any kind, whether express
  * or implied.
  */
diff -Nru a/arch/ppc/platforms/prpmc800_serial.h b/arch/ppc/platforms/prpmc800_serial.h
--- a/arch/ppc/platforms/prpmc800_serial.h	Mon Feb 17 14:57:28 2003
+++ b/arch/ppc/platforms/prpmc800_serial.h	Mon Feb 17 14:57:28 2003
@@ -6,7 +6,7 @@
  * Author: Dale Farnsworth	dale.farnsworth@mvista.com
  *
  * 2001 (c) MontaVista, Software, Inc.  This file is licensed under
- * the terms of the GNU General Public License version 2.1.  This program
+ * the terms of the GNU General Public License version 2.  This program
  * is licensed "as is" without any warranty of any kind, whether express
  * or implied.
  */
diff -Nru a/arch/ppc/platforms/prpmc800_setup.c b/arch/ppc/platforms/prpmc800_setup.c
--- a/arch/ppc/platforms/prpmc800_setup.c	Mon Feb 17 14:57:27 2003
+++ b/arch/ppc/platforms/prpmc800_setup.c	Mon Feb 17 14:57:27 2003
@@ -3,7 +3,7 @@
  * Author: Dale Farnsworth <dale.farnsworth@mvista.com>
  *
  * 2001 (c) MontaVista, Software, Inc.  This file is licensed under
- * the terms of the GNU General Public License version 2.1.  This program
+ * the terms of the GNU General Public License version 2.  This program
  * is licensed "as is" without any warranty of any kind, whether express
  * or implied.
  */
diff -Nru a/arch/ppc/platforms/sandpoint.h b/arch/ppc/platforms/sandpoint.h
--- a/arch/ppc/platforms/sandpoint.h	Mon Feb 17 14:57:27 2003
+++ b/arch/ppc/platforms/sandpoint.h	Mon Feb 17 14:57:27 2003
@@ -7,7 +7,7 @@
  *         mgreer@mvista.com
  *
  * 2000-2001 (c) MontaVista, Software, Inc.  This file is licensed under
- * the terms of the GNU General Public License version 2.1.  This program
+ * the terms of the GNU General Public License version 2.  This program
  * is licensed "as is" without any warranty of any kind, whether express
  * or implied.
  */
diff -Nru a/arch/ppc/platforms/sandpoint_pci.c b/arch/ppc/platforms/sandpoint_pci.c
--- a/arch/ppc/platforms/sandpoint_pci.c	Mon Feb 17 14:57:26 2003
+++ b/arch/ppc/platforms/sandpoint_pci.c	Mon Feb 17 14:57:26 2003
@@ -7,7 +7,7 @@
  *         mgreer@mvista.com
  *
  * 2000-2001 (c) MontaVista, Software, Inc.  This file is licensed under
- * the terms of the GNU General Public License version 2.1.  This program
+ * the terms of the GNU General Public License version 2.  This program
  * is licensed "as is" without any warranty of any kind, whether express
  * or implied.
  */
diff -Nru a/arch/ppc/platforms/sandpoint_serial.h b/arch/ppc/platforms/sandpoint_serial.h
--- a/arch/ppc/platforms/sandpoint_serial.h	Mon Feb 17 14:57:27 2003
+++ b/arch/ppc/platforms/sandpoint_serial.h	Mon Feb 17 14:57:27 2003
@@ -7,7 +7,7 @@
  *         mgreer@mvista.com
  *
  * 2001 (c) MontaVista, Software, Inc.  This file is licensed under
- * the terms of the GNU General Public License version 2.1.  This program
+ * the terms of the GNU General Public License version 2.  This program
  * is licensed "as is" without any warranty of any kind, whether express
  * or implied.
  */
diff -Nru a/arch/ppc/platforms/sandpoint_setup.c b/arch/ppc/platforms/sandpoint_setup.c
--- a/arch/ppc/platforms/sandpoint_setup.c	Mon Feb 17 14:57:28 2003
+++ b/arch/ppc/platforms/sandpoint_setup.c	Mon Feb 17 14:57:28 2003
@@ -7,7 +7,7 @@
  *         mgreer@mvista.com
  *
  * 2000-2002 (c) MontaVista, Software, Inc.  This file is licensed under
- * the terms of the GNU General Public License version 2.1.  This program
+ * the terms of the GNU General Public License version 2.  This program
  * is licensed "as is" without any warranty of any kind, whether express
  * or implied.
  */
diff -Nru a/arch/ppc/platforms/spruce.h b/arch/ppc/platforms/spruce.h
--- a/arch/ppc/platforms/spruce.h	Mon Feb 17 14:57:27 2003
+++ b/arch/ppc/platforms/spruce.h	Mon Feb 17 14:57:27 2003
@@ -8,7 +8,7 @@
  *          jpeters@mvista.com
  *
  * 2001 (c) MontaVista, Software, Inc.  This file is licensed under
- * the terms of the GNU General Public License version 2.1.  This program
+ * the terms of the GNU General Public License version 2.  This program
  * is licensed "as is" without any warranty of any kind, whether express
  * or implied.
  */
diff -Nru a/arch/ppc/platforms/spruce_pci.c b/arch/ppc/platforms/spruce_pci.c
--- a/arch/ppc/platforms/spruce_pci.c	Mon Feb 17 14:57:27 2003
+++ b/arch/ppc/platforms/spruce_pci.c	Mon Feb 17 14:57:27 2003
@@ -7,7 +7,7 @@
  *         jpeters@mvista.com
  *
  * 2000 (c) MontaVista, Software, Inc.  This file is licensed under
- * the terms of the GNU General Public License version 2.1.  This program
+ * the terms of the GNU General Public License version 2.  This program
  * is licensed "as is" without any warranty of any kind, whether express
  * or implied.
  */
diff -Nru a/arch/ppc/platforms/spruce_serial.h b/arch/ppc/platforms/spruce_serial.h
--- a/arch/ppc/platforms/spruce_serial.h	Mon Feb 17 14:57:28 2003
+++ b/arch/ppc/platforms/spruce_serial.h	Mon Feb 17 14:57:28 2003
@@ -8,7 +8,7 @@
  *          jpeters@mvista.com
  *
  * 2000 (c) MontaVista, Software, Inc.  This file is licensed under
- * the terms of the GNU General Public License version 2.1.  This program
+ * the terms of the GNU General Public License version 2.  This program
  * is licensed "as is" without any warranty of any kind, whether express
  * or implied.
  */
diff -Nru a/arch/ppc/platforms/spruce_setup.c b/arch/ppc/platforms/spruce_setup.c
--- a/arch/ppc/platforms/spruce_setup.c	Mon Feb 17 14:57:26 2003
+++ b/arch/ppc/platforms/spruce_setup.c	Mon Feb 17 14:57:26 2003
@@ -7,7 +7,7 @@
  *          Matt Porter <mporter@mvista.com>
  *
  * 2001-2002 (c) MontaVista, Software, Inc.  This file is licensed under
- * the terms of the GNU General Public License version 2.1.  This program
+ * the terms of the GNU General Public License version 2.  This program
  * is licensed "as is" without any warranty of any kind, whether express
  * or implied.
  */
diff -Nru a/arch/ppc/platforms/zx4500.h b/arch/ppc/platforms/zx4500.h
--- a/arch/ppc/platforms/zx4500.h	Mon Feb 17 14:57:27 2003
+++ b/arch/ppc/platforms/zx4500.h	Mon Feb 17 14:57:27 2003
@@ -6,7 +6,7 @@
  *         mgreer@mvista.com
  *
  * 2000-2001 (c) MontaVista, Software, Inc.  This file is licensed under
- * the terms of the GNU General Public License version 2.1.  This program
+ * the terms of the GNU General Public License version 2.  This program
  * is licensed "as is" without any warranty of any kind, whether express
  * or implied.
  */
diff -Nru a/arch/ppc/platforms/zx4500_pci.c b/arch/ppc/platforms/zx4500_pci.c
--- a/arch/ppc/platforms/zx4500_pci.c	Mon Feb 17 14:57:28 2003
+++ b/arch/ppc/platforms/zx4500_pci.c	Mon Feb 17 14:57:28 2003
@@ -7,7 +7,7 @@
  *         mgreer@mvista.com
  *
  * 2000-2001 (c) MontaVista, Software, Inc.  This file is licensed under
- * the terms of the GNU General Public License version 2.1.  This program
+ * the terms of the GNU General Public License version 2.  This program
  * is licensed "as is" without any warranty of any kind, whether express
  * or implied.
  */
diff -Nru a/arch/ppc/platforms/zx4500_serial.h b/arch/ppc/platforms/zx4500_serial.h
--- a/arch/ppc/platforms/zx4500_serial.h	Mon Feb 17 14:57:28 2003
+++ b/arch/ppc/platforms/zx4500_serial.h	Mon Feb 17 14:57:28 2003
@@ -7,7 +7,7 @@
  *         mgreer@mvista.com
  *
  * 2000-2001 (c) MontaVista, Software, Inc.  This file is licensed under
- * the terms of the GNU General Public License version 2.1.  This program
+ * the terms of the GNU General Public License version 2.  This program
  * is licensed "as is" without any warranty of any kind, whether express
  * or implied.
  */
diff -Nru a/arch/ppc/platforms/zx4500_setup.c b/arch/ppc/platforms/zx4500_setup.c
--- a/arch/ppc/platforms/zx4500_setup.c	Mon Feb 17 14:57:26 2003
+++ b/arch/ppc/platforms/zx4500_setup.c	Mon Feb 17 14:57:26 2003
@@ -7,7 +7,7 @@
  *         mgreer@mvista.com
  *
  * 2000-2001 (c) MontaVista, Software, Inc.  This file is licensed under
- * the terms of the GNU General Public License version 2.1.  This program
+ * the terms of the GNU General Public License version 2.  This program
  * is licensed "as is" without any warranty of any kind, whether express
  * or implied.
  */
diff -Nru a/arch/ppc/syslib/cpc700.h b/arch/ppc/syslib/cpc700.h
--- a/arch/ppc/syslib/cpc700.h	Mon Feb 17 14:57:27 2003
+++ b/arch/ppc/syslib/cpc700.h	Mon Feb 17 14:57:27 2003
@@ -7,7 +7,7 @@
  *         mgreer@mvista.com
  *
  * 2000-2002 (c) MontaVista, Software, Inc.  This file is licensed under
- * the terms of the GNU General Public License version 2.1.  This program
+ * the terms of the GNU General Public License version 2.  This program
  * is licensed "as is" without any warranty of any kind, whether express
  * or implied.
  */
diff -Nru a/arch/ppc/syslib/cpc700_pic.c b/arch/ppc/syslib/cpc700_pic.c
--- a/arch/ppc/syslib/cpc700_pic.c	Mon Feb 17 14:57:27 2003
+++ b/arch/ppc/syslib/cpc700_pic.c	Mon Feb 17 14:57:27 2003
@@ -9,7 +9,7 @@
  *          jpeters@mvista.com
  *
  * 2001-2002 (c) MontaVista, Software, Inc.  This file is licensed under
- * the terms of the GNU General Public License version 2.1.  This program
+ * the terms of the GNU General Public License version 2.  This program
  * is licensed "as is" without any warranty of any kind, whether express
  * or implied.
  */
diff -Nru a/arch/ppc/syslib/cpc710.h b/arch/ppc/syslib/cpc710.h
--- a/arch/ppc/syslib/cpc710.h	Mon Feb 17 14:57:27 2003
+++ b/arch/ppc/syslib/cpc710.h	Mon Feb 17 14:57:27 2003
@@ -6,7 +6,7 @@
  * Author: Matt Porter <mporter@mvista.com>
  *
  * 2001 (c) MontaVista, Software, Inc.  This file is licensed under
- * the terms of the GNU General Public License version 2.1.  This program
+ * the terms of the GNU General Public License version 2.  This program
  * is licensed "as is" without any warranty of any kind, whether express
  * or implied.
  */
diff -Nru a/arch/ppc/syslib/gt64260_common.c b/arch/ppc/syslib/gt64260_common.c
--- a/arch/ppc/syslib/gt64260_common.c	Mon Feb 17 14:57:26 2003
+++ b/arch/ppc/syslib/gt64260_common.c	Mon Feb 17 14:57:26 2003
@@ -8,7 +8,7 @@
  * Author: Mark A. Greer <mgreer@mvista.com>
  *
  * 2001 (c) MontaVista, Software, Inc.  This file is licensed under
- * the terms of the GNU General Public License version 2.1.  This program
+ * the terms of the GNU General Public License version 2.  This program
  * is licensed "as is" without any warranty of any kind, whether express
  * or implied.
  */
diff -Nru a/arch/ppc/syslib/gt64260_pic.c b/arch/ppc/syslib/gt64260_pic.c
--- a/arch/ppc/syslib/gt64260_pic.c	Mon Feb 17 14:57:27 2003
+++ b/arch/ppc/syslib/gt64260_pic.c	Mon Feb 17 14:57:27 2003
@@ -9,7 +9,7 @@
  * Based on sources from Rabeeh Khoury / Galileo Technology
  *
  * 2001 (c) MontaVista, Software, Inc.  This file is licensed under
- * the terms of the GNU General Public License version 2.1.  This program
+ * the terms of the GNU General Public License version 2.  This program
  * is licensed "as is" without any warranty of any kind, whether express
  * or implied.
  */
diff -Nru a/arch/ppc/syslib/harrier.c b/arch/ppc/syslib/harrier.c
--- a/arch/ppc/syslib/harrier.c	Mon Feb 17 14:57:27 2003
+++ b/arch/ppc/syslib/harrier.c	Mon Feb 17 14:57:27 2003
@@ -7,7 +7,7 @@
  *         dale.farnsworth@mvista.com
  *
  * 2001 (c) MontaVista, Software, Inc.  This file is licensed under
- * the terms of the GNU General Public License version 2.1.  This program
+ * the terms of the GNU General Public License version 2.  This program
  * is licensed "as is" without any warranty of any kind, whether express
  * or implied.
  */
diff -Nru a/arch/ppc/syslib/mpc10x_common.c b/arch/ppc/syslib/mpc10x_common.c
--- a/arch/ppc/syslib/mpc10x_common.c	Mon Feb 17 14:57:27 2003
+++ b/arch/ppc/syslib/mpc10x_common.c	Mon Feb 17 14:57:27 2003
@@ -8,7 +8,7 @@
  *         mgreer@mvista.com
  *
  * 2001 (c) MontaVista, Software, Inc.  This file is licensed under
- * the terms of the GNU General Public License version 2.1.  This program
+ * the terms of the GNU General Public License version 2.  This program
  * is licensed "as is" without any warranty of any kind, whether express
  * or implied.
  */
diff -Nru a/arch/ppc/syslib/pci_auto.c b/arch/ppc/syslib/pci_auto.c
--- a/arch/ppc/syslib/pci_auto.c	Mon Feb 17 14:57:27 2003
+++ b/arch/ppc/syslib/pci_auto.c	Mon Feb 17 14:57:27 2003
@@ -6,7 +6,7 @@
  * Author: Matt Porter <mporter@mvista.com>
  *
  * 2001 (c) MontaVista, Software, Inc.  This file is licensed under
- * the terms of the GNU General Public License version 2.1.  This program
+ * the terms of the GNU General Public License version 2.  This program
  * is licensed "as is" without any warranty of any kind, whether express
  * or implied.
  */
diff -Nru a/arch/ppc/syslib/ppc405_pci.c b/arch/ppc/syslib/ppc405_pci.c
--- a/arch/ppc/syslib/ppc405_pci.c	Mon Feb 17 14:57:27 2003
+++ b/arch/ppc/syslib/ppc405_pci.c	Mon Feb 17 14:57:27 2003
@@ -4,7 +4,7 @@
  * Further modifications by Armin Kuster <akuster@mvista.com>
  *
  * 2000 (c) MontaVista, Software, Inc.  This file is licensed under
- * the terms of the GNU General Public License version 2.1.  This program
+ * the terms of the GNU General Public License version 2.  This program
  * is licensed "as is" without any warranty of any kind, whether express
  * or implied.
  *
diff -Nru a/arch/ppc/syslib/ppc4xx_dma.c b/arch/ppc/syslib/ppc4xx_dma.c
--- a/arch/ppc/syslib/ppc4xx_dma.c	Mon Feb 17 14:57:28 2003
+++ b/arch/ppc/syslib/ppc4xx_dma.c	Mon Feb 17 14:57:28 2003
@@ -4,7 +4,7 @@
  * arch/ppc/kernel/ppc405_dma.c
  *
  * 2000 (c) MontaVista, Software, Inc.  This file is licensed under
- * the terms of the GNU General Public License version 2.1.  This program
+ * the terms of the GNU General Public License version 2.  This program
  * is licensed "as is" without any warranty of any kind, whether express
  * or implied.
  *
diff -Nru a/arch/ppc/syslib/ppc4xx_pm.c b/arch/ppc/syslib/ppc4xx_pm.c
--- a/arch/ppc/syslib/ppc4xx_pm.c	Mon Feb 17 14:57:26 2003
+++ b/arch/ppc/syslib/ppc4xx_pm.c	Mon Feb 17 14:57:26 2003
@@ -2,7 +2,7 @@
  * Author: Armin Kuster <akuster@mvista.com>
  *
  * 2002 (c) MontaVista, Software, Inc.  This file is licensed under
- * the terms of the GNU General Public License version 2.1.  This program
+ * the terms of the GNU General Public License version 2.  This program
  * is licensed "as is" without any warranty of any kind, whether express
  * or implied.
  *
diff -Nru a/arch/ppc/syslib/ppc4xx_serial.c b/arch/ppc/syslib/ppc4xx_serial.c
--- a/arch/ppc/syslib/ppc4xx_serial.c	Mon Feb 17 14:57:26 2003
+++ b/arch/ppc/syslib/ppc4xx_serial.c	Mon Feb 17 14:57:26 2003
@@ -9,7 +9,7 @@
  * be merged with other similar processor/boards.	-- Dan
  *
  * 2000 (c) MontaVista, Software, Inc.  This file is licensed under
- * the terms of the GNU General Public License version 2.1.  This program
+ * the terms of the GNU General Public License version 2.  This program
  * is licensed "as is" without any warranty of any kind, whether express
  * or implied.
  *
diff -Nru a/arch/ppc/syslib/pplus_common.c b/arch/ppc/syslib/pplus_common.c
--- a/arch/ppc/syslib/pplus_common.c	Mon Feb 17 14:57:27 2003
+++ b/arch/ppc/syslib/pplus_common.c	Mon Feb 17 14:57:27 2003
@@ -7,7 +7,7 @@
  *         mgreer@mvista.com
  *
  * 2001 (c) MontaVista, Software, Inc.  This file is licensed under
- * the terms of the GNU General Public License version 2.1.  This program
+ * the terms of the GNU General Public License version 2.  This program
  * is licensed "as is" without any warranty of any kind, whether express
  * or implied.
  */
diff -Nru a/arch/ppc/syslib/todc_time.c b/arch/ppc/syslib/todc_time.c
--- a/arch/ppc/syslib/todc_time.c	Mon Feb 17 14:57:28 2003
+++ b/arch/ppc/syslib/todc_time.c	Mon Feb 17 14:57:28 2003
@@ -8,7 +8,7 @@
  *         mgreer@mvista.com
  *
  * 2001 (c) MontaVista, Software, Inc.  This file is licensed under
- * the terms of the GNU General Public License version 2.1.  This program
+ * the terms of the GNU General Public License version 2.  This program
  * is licensed "as is" without any warranty of any kind, whether express
  * or implied.
  */
diff -Nru a/arch/ppc64/Kconfig b/arch/ppc64/Kconfig
--- a/arch/ppc64/Kconfig	Mon Feb 17 14:57:27 2003
+++ b/arch/ppc64/Kconfig	Mon Feb 17 14:57:27 2003
@@ -128,6 +128,10 @@
 	tristate "Firmware flash interface"
 	depends on !PPC_ISERIES
 
+config SCANLOG
+	tristate "Scanlog dump interface"
+	depends on !PPC_ISERIES
+
 config PPC_RTAS
 	bool "Proc interface to RTAS"
 	depends on !PPC_ISERIES
@@ -186,9 +190,6 @@
 	  ELF (Executable and Linkable Format) is a format for libraries and
 	  executables used across different architectures and operating
 	  systems.
-
-config BINFMT_ELF32
-	tristate "Kernel support for 32-bit ELF binaries"
 
 config BINFMT_MISC
 	tristate "Kernel support for MISC binaries"
diff -Nru a/arch/ppc64/defconfig b/arch/ppc64/defconfig
--- a/arch/ppc64/defconfig	Mon Feb 17 14:57:27 2003
+++ b/arch/ppc64/defconfig	Mon Feb 17 14:57:27 2003
@@ -26,7 +26,12 @@
 #
 # Loadable module support
 #
-# CONFIG_MODULES is not set
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+# CONFIG_KMOD is not set
 
 #
 # Platform support
@@ -256,6 +261,7 @@
 # Ethernet (10 or 100Mbit)
 #
 CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
 # CONFIG_OAKNET is not set
 # CONFIG_HAPPYMEAL is not set
 # CONFIG_SUNGEM is not set
@@ -452,6 +458,7 @@
 # CONFIG_AGP is not set
 # CONFIG_DRM is not set
 CONFIG_RAW_DRIVER=y
+# CONFIG_HANGCHECK_TIMER is not set
 
 #
 # Multimedia devices
diff -Nru a/arch/ppc64/kernel/Makefile b/arch/ppc64/kernel/Makefile
--- a/arch/ppc64/kernel/Makefile	Mon Feb 17 14:57:28 2003
+++ b/arch/ppc64/kernel/Makefile	Mon Feb 17 14:57:28 2003
@@ -30,3 +30,4 @@
 obj-$(CONFIG_PROFILING)		+= profile.o
 obj-$(CONFIG_MODULES)		+= module.o ppc_ksyms.o
 obj-$(CONFIG_PPC_RTAS)		+= rtas-proc.o
+obj-$(CONFIG_SCANLOG)		+= scanlog.o
diff -Nru a/arch/ppc64/kernel/align.c b/arch/ppc64/kernel/align.c
--- a/arch/ppc64/kernel/align.c	Mon Feb 17 14:57:28 2003
+++ b/arch/ppc64/kernel/align.c	Mon Feb 17 14:57:28 2003
@@ -237,8 +237,12 @@
 	dsisr = regs->dsisr;
 
 	/* Power4 doesn't set DSISR for an alignment interrupt */
-	if (__is_processor(PV_POWER4) || __is_processor(PV_POWER4p))
-		dsisr = make_dsisr( *((unsigned *)regs->nip) );
+	if (__is_processor(PV_POWER4) || __is_processor(PV_POWER4p)) {
+		unsigned int real_instr;
+		if (__get_user(real_instr, (unsigned int *)regs->nip))
+			return 0;
+		dsisr = make_dsisr(real_instr);
+	}
 
 	/* extract the operation and registers from the dsisr */
 	reg = (dsisr >> 5) & 0x1f;	/* source/dest register */
diff -Nru a/arch/ppc64/kernel/binfmt_elf32.c b/arch/ppc64/kernel/binfmt_elf32.c
--- a/arch/ppc64/kernel/binfmt_elf32.c	Mon Feb 17 14:57:26 2003
+++ b/arch/ppc64/kernel/binfmt_elf32.c	Mon Feb 17 14:57:26 2003
@@ -74,12 +74,6 @@
 #define init_elf_binfmt init_elf32_binfmt
 
 #undef CONFIG_BINFMT_ELF
-#ifdef CONFIG_BINFMT_ELF32
-#define CONFIG_BINFMT_ELF CONFIG_BINFMT_ELF32
-#endif
-#undef CONFIG_BINFMT_ELF_MODULE
-#ifdef CONFIG_BINFMT_ELF32_MODULE
-#define CONFIG_BINFMT_ELF_MODULE CONFIG_BINFMT_ELF32_MODULE
-#endif
+#define CONFIG_BINFMT_ELF 1
 
 #include "../../../fs/binfmt_elf.c"
diff -Nru a/arch/ppc64/kernel/entry.S b/arch/ppc64/kernel/entry.S
--- a/arch/ppc64/kernel/entry.S	Mon Feb 17 14:57:26 2003
+++ b/arch/ppc64/kernel/entry.S	Mon Feb 17 14:57:26 2003
@@ -102,7 +102,6 @@
  * Need to vector to 32 Bit or default sys_call_table here,
  * based on caller's run-mode / personality.
  */
-#ifdef CONFIG_BINFMT_ELF32
 	andi.	r11,r10,_TIF_32BIT
 	beq-	15f
 	ld	r10,.SYS_CALL_TABLE32@toc(2)
@@ -118,7 +117,6 @@
 	clrldi	r8,r8,32
 	b	17f
 15:
-#endif
 	ld	r10,.SYS_CALL_TABLE@toc(2)
 17:	slwi	r0,r0,3
 	ldx	r10,r10,r0	/* Fetch system call handler [ptr] */
@@ -171,7 +169,6 @@
  * Need to vector to 32 Bit or default sys_call_table here,
  * based on caller's run-mode / personality.
  */
-#ifdef CONFIG_BINFMT_ELF32
 	clrrdi	r10,r1,THREAD_SHIFT
 	ld	r10,TI_FLAGS(r10)
 	andi.	r11,r10,_TIF_32BIT
@@ -189,7 +186,6 @@
 	clrldi	r8,r8,32
 	b	57f
 55:
-#endif
 	ld	r10,.SYS_CALL_TABLE@toc(2)
 57:
 	slwi	r0,r0,3
diff -Nru a/arch/ppc64/kernel/i8259.c b/arch/ppc64/kernel/i8259.c
--- a/arch/ppc64/kernel/i8259.c	Mon Feb 17 14:57:28 2003
+++ b/arch/ppc64/kernel/i8259.c	Mon Feb 17 14:57:28 2003
@@ -11,10 +11,11 @@
 #include <linux/sched.h>
 #include <linux/signal.h>
 #include <linux/cache.h>
-#include <asm/io.h>
-#include "i8259.h"
 #include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <asm/io.h>
 #include <asm/ppcdebug.h>
+#include "i8259.h"
 
 unsigned char cached_8259[2] = { 0xff, 0xff };
 #define cached_A1 (cached_8259[0])
diff -Nru a/arch/ppc64/kernel/ioctl32.c b/arch/ppc64/kernel/ioctl32.c
--- a/arch/ppc64/kernel/ioctl32.c	Mon Feb 17 14:57:28 2003
+++ b/arch/ppc64/kernel/ioctl32.c	Mon Feb 17 14:57:28 2003
@@ -3656,6 +3656,7 @@
 COMPATIBLE_IOCTL(TCSETAW),
 COMPATIBLE_IOCTL(TCSETAF),
 COMPATIBLE_IOCTL(TCSBRK),
+COMPATIBLE_IOCTL(TCSBRKP),
 COMPATIBLE_IOCTL(TCXONC),
 COMPATIBLE_IOCTL(TCFLSH),
 COMPATIBLE_IOCTL(TCGETS),
@@ -4495,7 +4496,7 @@
 {
 	int i;
 	if (!additional_ioctls) {
-		additional_ioctls = get_zeroed_page(GFP_KERNEL);
+		additional_ioctls = (struct ioctl_trans *)get_zeroed_page(GFP_KERNEL);
 		if (!additional_ioctls)
 			return -ENOMEM;
 	}
diff -Nru a/arch/ppc64/kernel/misc.S b/arch/ppc64/kernel/misc.S
--- a/arch/ppc64/kernel/misc.S	Mon Feb 17 14:57:28 2003
+++ b/arch/ppc64/kernel/misc.S	Mon Feb 17 14:57:28 2003
@@ -499,7 +499,6 @@
 SYSCALL(execve)
 SYSCALL(waitpid)
 
-#ifdef CONFIG_BINFMT_ELF32
 /* Why isn't this a) automatic, b) written in 'C'? */	
 	.balign 8
 _GLOBAL(sys_call_table32)
@@ -631,8 +630,8 @@
 	.llong .sys_mprotect		/* 125 */
 	.llong .compat_sys_sigprocmask
 	.llong .sys_ni_syscall		/* old create_module syscall */
-	.llong .sys32_init_module
-	.llong .sys32_delete_module
+	.llong .sys_init_module
+	.llong .sys_delete_module
 	.llong .sys_ni_syscall		/* 130 old get_kernel_syms syscall */
 	.llong .sys_quotactl
 	.llong .sys32_getpgid
@@ -666,7 +665,7 @@
 	.llong .sys32_sched_get_priority_min  /* 160 */
 	.llong .sys32_sched_rr_get_interval
 	.llong .compat_sys_nanosleep
-	.llong .sys32_mremap
+	.llong .sys_mremap
 	.llong .sys_setresuid
 	.llong .sys_getresuid	        /* 165 */
 	.llong .sys_ni_syscall		/* old query_module syscall */
@@ -724,7 +723,7 @@
 	.llong .sys_removexattr
 	.llong .sys_lremovexattr
 	.llong .sys_fremovexattr	/* 220 */
-	.llong .sys_futex
+	.llong .compat_sys_futex
 	.llong .sys32_sched_setaffinity
 	.llong .sys32_sched_getaffinity
 	.llong .sys_ni_syscall
@@ -735,10 +734,10 @@
 	.llong .sys_ni_syscall		/* reserved for sys_io_getevents */
 	.llong .sys_ni_syscall		/* 230 - reserved for sys_io_submit */
 	.llong .sys_ni_syscall		/* reserved for sys_io_cancel */
-	.llong .sys_ni_syscall		/* reserved for alloc_hugepages */
-	.llong .sys_ni_syscall		/* reserved for free_hugepages */
+	.llong .sys_set_tid_address
+	.llong .ppc32_fadvise64
 	.llong .sys_exit_group
-	.llong .sys32_lookup_dcookie	/* 245 */
+	.llong .ppc32_lookup_dcookie	/* 245 */
 	.llong .sys_epoll_create
 	.llong .sys_epoll_ctl
 	.llong .sys_epoll_wait
@@ -747,7 +746,6 @@
 	.rept NR_syscalls-239
 		.llong .sys_ni_syscall
 	.endr
-#endif
 
 	.balign 8
 _GLOBAL(sys_call_table)
@@ -983,8 +981,8 @@
 	.llong .sys_io_getevents
 	.llong .sys_io_submit		/* 230 */
 	.llong .sys_io_cancel
-	.llong .sys_ni_syscall
-	.llong .sys_ni_syscall
+	.llong .sys_set_tid_address
+	.llong .sys_fadvise64
 	.llong .sys_exit_group
 	.llong .sys_lookup_dcookie	/* 235 */
 	.llong .sys_epoll_create
diff -Nru a/arch/ppc64/kernel/process.c b/arch/ppc64/kernel/process.c
--- a/arch/ppc64/kernel/process.c	Mon Feb 17 14:57:27 2003
+++ b/arch/ppc64/kernel/process.c	Mon Feb 17 14:57:27 2003
@@ -31,6 +31,7 @@
 #include <linux/init.h>
 #include <linux/init_task.h>
 #include <linux/prctl.h>
+#include <linux/ptrace.h>
 
 #include <asm/pgtable.h>
 #include <asm/uaccess.h>
diff -Nru a/arch/ppc64/kernel/ptrace.c b/arch/ppc64/kernel/ptrace.c
--- a/arch/ppc64/kernel/ptrace.c	Mon Feb 17 14:57:28 2003
+++ b/arch/ppc64/kernel/ptrace.c	Mon Feb 17 14:57:28 2003
@@ -292,11 +292,11 @@
 		return;
 	if (!(current->ptrace & PT_PTRACED))
 		return;
-	current->exit_code = SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
-					? 0x80 : 0);
-	current->state = TASK_STOPPED;
-	notify_parent(current, SIGCHLD);
-	schedule();
+	/* the 0x80 provides a way for the tracing parent to distinguish
+	   between a syscall stop and SIGTRAP delivery */
+	ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
+				 ? 0x80 : 0));
+
 	/*
 	 * this isn't the same as continuing with a signal, but it will do
 	 * for normal use.  strace only continues with a signal if the
diff -Nru a/arch/ppc64/kernel/rtas.c b/arch/ppc64/kernel/rtas.c
--- a/arch/ppc64/kernel/rtas.c	Mon Feb 17 14:57:27 2003
+++ b/arch/ppc64/kernel/rtas.c	Mon Feb 17 14:57:27 2003
@@ -15,6 +15,7 @@
 #include <linux/kernel.h>
 #include <linux/types.h>
 #include <linux/spinlock.h>
+#include <linux/module.h>
 
 #include <asm/prom.h>
 #include <asm/rtas.h>
@@ -56,6 +57,9 @@
 
 extern unsigned long reloc_offset(void);
 
+spinlock_t rtas_data_buf_lock = SPIN_LOCK_UNLOCKED;
+char rtas_data_buf[RTAS_DATA_BUF_SIZE];
+
 void
 phys_call_rtas(int token, int nargs, int nret, ...)
 {
@@ -278,3 +282,10 @@
 		rtas_flash_bypass_warning();
         rtas_power_off();
 }
+
+EXPORT_SYMBOL(rtas_proc_dir);
+EXPORT_SYMBOL(rtas_firmware_flash_list);
+EXPORT_SYMBOL(rtas_token);
+EXPORT_SYMBOL(rtas_call);
+EXPORT_SYMBOL(rtas_data_buf);
+EXPORT_SYMBOL(rtas_data_buf_lock);
diff -Nru a/arch/ppc64/kernel/rtasd.c b/arch/ppc64/kernel/rtasd.c
--- a/arch/ppc64/kernel/rtasd.c	Mon Feb 17 14:57:27 2003
+++ b/arch/ppc64/kernel/rtasd.c	Mon Feb 17 14:57:27 2003
@@ -147,8 +147,8 @@
 {
 	int error;
 
-	error = rtas_call(rtas_token("set-indicator"), 3, 1, NULL, SURVEILLANCE_TOKEN,
-			0, SURVEILLANCE_TIMEOUT);
+	error = rtas_call(rtas_token("set-indicator"), 3, 1, NULL,
+			  SURVEILLANCE_TOKEN, 0, SURVEILLANCE_TIMEOUT);
 
 	if (error) {
 		printk(KERN_ERR "rtasd: could not enable surveillance\n");
@@ -243,11 +243,13 @@
 
 		} while(error == 0);
 
-		/* Check all cpus for pending events before sleeping*/
-		if (!first_pass) {
-			set_current_state(TASK_INTERRUPTIBLE);
-			schedule_timeout((HZ*60/rtas_event_scan_rate) / 2);
-		}
+		/*
+		 * Check all cpus for pending events quickly, sleeping for
+		 * at least one second since some machines have problems
+		 * if we call event-scan too quickly
+		 */
+		set_current_state(TASK_INTERRUPTIBLE);
+		schedule_timeout(first_pass ? HZ : (HZ*60/rtas_event_scan_rate) / 2);
 	}
 
 	if (first_pass && surveillance_requested) {
@@ -255,10 +257,9 @@
 		if (enable_surveillance())
 			goto error_vfree;
 		DEBUG("surveillance enabled\n");
-	} else {
-		first_pass = 0;
 	}
 
+	first_pass = 0;
 	goto repeat;
 
 error_vfree:
diff -Nru a/arch/ppc64/kernel/scanlog.c b/arch/ppc64/kernel/scanlog.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/arch/ppc64/kernel/scanlog.c	Mon Feb 17 14:57:28 2003
@@ -0,0 +1,249 @@
+/*
+ *  c 2001 PPC 64 Team, IBM Corp
+ *
+ *      This program is free software; you can redistribute it and/or
+ *      modify it under the terms of the GNU General Public License
+ *      as published by the Free Software Foundation; either version
+ *      2 of the License, or (at your option) any later version.
+ *
+ * scan-log-data driver for PPC64  Todd Inglett <tinglett@vnet.ibm.com>
+ *
+ * When ppc64 hardware fails the service processor dumps internal state
+ * of the system.  After a reboot the operating system can access a dump
+ * of this data using this driver.  A dump exists if the device-tree
+ * /chosen/ibm,scan-log-data property exists.
+ *
+ * This driver exports /proc/ppc64/scan-log-dump which can be read.
+ * The driver supports only sequential reads.
+ *
+ * The driver looks at a write to the driver for the single word "reset".
+ * If given, the driver will reset the scanlog so the platform can free it.
+ */
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/proc_fs.h>
+#include <linux/init.h>
+#include <asm/uaccess.h>
+#include <asm/rtas.h>
+#include <asm/prom.h>
+
+#define MODULE_VERSION "1.0"
+#define MODULE_NAME "scanlog"
+
+/* Status returns from ibm,scan-log-dump */
+#define SCANLOG_COMPLETE 0
+#define SCANLOG_HWERROR -1
+#define SCANLOG_CONTINUE 1
+
+#define DEBUG(A...) do { if (scanlog_debug) printk(KERN_ERR "scanlog: " A); } while (0)
+
+static int scanlog_debug;
+static unsigned int ibm_scan_log_dump;			/* RTAS token */
+static struct proc_dir_entry *proc_ppc64_scan_log_dump;	/* The proc file */
+
+extern struct proc_dir_entry *proc_rtas;
+
+
+static ssize_t scanlog_read(struct file *file, char *buf,
+			    size_t count, loff_t *ppos)
+{
+        struct inode * inode = file->f_dentry->d_inode;
+	struct proc_dir_entry *dp;
+	unsigned int *data;
+	unsigned long status;
+	unsigned long len, off;
+	unsigned int wait_time;
+
+        dp = PDE(inode);
+ 	data = (unsigned int *)dp->data;
+
+	if (!data) {
+		printk(KERN_ERR "scanlog: read failed no data\n");
+		return -EIO;
+	}
+
+	if (count > RTAS_DATA_BUF_SIZE)
+		count = RTAS_DATA_BUF_SIZE;
+
+	if (count < 1024) {
+		/* This is the min supported by this RTAS call.  Rather
+		 * than do all the buffering we insist the user code handle
+		 * larger reads.  As long as cp works... :)
+		 */
+		printk(KERN_ERR "scanlog: cannot perform a small read (%ld)\n", count);
+		return -EINVAL;
+	}
+
+	if (verify_area(VERIFY_WRITE, buf, count))
+		return -EFAULT;
+
+	for (;;) {
+		wait_time = HZ/2;	/* default wait if no data */
+		spin_lock(&rtas_data_buf_lock);
+		memcpy(rtas_data_buf, data, RTAS_DATA_BUF_SIZE);
+		status = rtas_call(ibm_scan_log_dump, 2, 1, NULL,
+				   __pa(rtas_data_buf), count);
+		memcpy(data, rtas_data_buf, RTAS_DATA_BUF_SIZE);
+		spin_unlock(&rtas_data_buf_lock);
+
+		DEBUG("status=%ld, data[0]=%x, data[1]=%x, data[2]=%x\n",
+		      status, data[0], data[1], data[2]);
+		switch (status) {
+		    case SCANLOG_COMPLETE:
+			DEBUG("hit eof\n");
+			return 0;
+		    case SCANLOG_HWERROR:
+			DEBUG("hardware error reading scan log data\n");
+			return -EIO;
+		    case SCANLOG_CONTINUE:
+			/* We may or may not have data yet */
+			len = data[1];
+			off = data[2];
+			if (len > 0) {
+				if (copy_to_user(buf, ((char *)data)+off, len))
+					return -EFAULT;
+				return len;
+			}
+			/* Break to sleep default time */
+			break;
+		    default:
+			if (status > 9900 && status <= 9905) {
+				/* No data.  RTAS is hinting at a delay required
+				 * between 1-100000 milliseconds
+				 */
+				int ms = 1;
+				for (; status > 9900; status--)
+					ms = ms * 10;
+				/* Use microseconds for reasonable accuracy */
+				ms *= 1000;
+				wait_time = ms / (1000000/HZ); /* round down is fine */
+				/* Fall through to sleep */
+			} else {
+				printk(KERN_ERR "scanlog: unknown error from rtas: %ld\n", status);
+				return -EIO;
+			}
+		}
+		/* Apparently no data yet.  Wait and try again. */
+		set_current_state(TASK_INTERRUPTIBLE);
+		schedule_timeout(wait_time);
+	}
+	/*NOTREACHED*/
+}
+
+static ssize_t scanlog_write(struct file * file, const char * buf,
+			     size_t count, loff_t *ppos)
+{
+	unsigned long status;
+
+	if (buf) {
+		if (strncmp(buf, "reset", 5) == 0) {
+			DEBUG("reset scanlog\n");
+			status = rtas_call(ibm_scan_log_dump, 2, 1, NULL, NULL, 0);
+			DEBUG("rtas returns %ld\n", status);
+		} else if (strncmp(buf, "debugon", 7) == 0) {
+			printk(KERN_ERR "scanlog: debug on\n");
+			scanlog_debug = 1;
+		} else if (strncmp(buf, "debugoff", 8) == 0) {
+			printk(KERN_ERR "scanlog: debug off\n");
+			scanlog_debug = 0;
+		}
+	}
+	return count;
+}
+
+static int scanlog_open(struct inode * inode, struct file * file)
+{
+	struct proc_dir_entry *dp = PDE(inode);
+	unsigned int *data = (unsigned int *)dp->data;
+
+	if (!data) {
+		printk(KERN_ERR "scanlog: open failed no data\n");
+		return -EIO;
+	}
+
+	if (data[0] != 0) {
+		/* This imperfect test stops a second copy of the
+		 * data (or a reset while data is being copied)
+		 */
+		return -EBUSY;
+	}
+
+	data[0] = 0;	/* re-init so we restart the scan */
+
+	return 0;
+}
+
+static int scanlog_release(struct inode * inode, struct file * file)
+{
+	struct proc_dir_entry *dp = PDE(inode);
+	unsigned int *data = (unsigned int *)dp->data;
+
+	if (!data) {
+		printk(KERN_ERR "scanlog: release failed no data\n");
+		return -EIO;
+	}
+	data[0] = 0;
+
+	return 0;
+}
+
+struct file_operations scanlog_fops = {
+	owner:		THIS_MODULE,
+	read:		scanlog_read,
+	write:		scanlog_write,
+	open:		scanlog_open,
+	release:	scanlog_release,
+};
+
+int __init scanlog_init(void)
+{
+	struct proc_dir_entry *ent;
+
+	ibm_scan_log_dump = rtas_token("ibm,scan-log-dump");
+	if (ibm_scan_log_dump == RTAS_UNKNOWN_SERVICE) {
+		printk(KERN_ERR "scan-log-dump not implemented on this system\n");
+		return -EIO;
+	}
+
+	if (proc_rtas == NULL)
+                proc_rtas = proc_mkdir("rtas", 0);
+
+	if (proc_rtas == NULL) {
+		printk(KERN_ERR "Failed to create /proc/rtas in scanlog_init\n");
+		return -EIO;
+	}
+
+        ent = create_proc_entry("scan-log-dump",  S_IRUSR, proc_rtas);
+	if (ent) {
+		ent->proc_fops = &scanlog_fops;
+		/* Ideally we could allocate a buffer < 4G */
+		ent->data = kmalloc(RTAS_DATA_BUF_SIZE, GFP_KERNEL);
+		if (!ent->data) {
+			printk(KERN_ERR "Failed to allocate a buffer\n");
+			remove_proc_entry("scan-log-dump", ent->parent);
+			return -ENOMEM;
+		}
+		((unsigned int *)ent->data)[0] = 0;
+	} else {
+		printk(KERN_ERR "Failed to create ppc64/scan-log-dump proc entry\n");
+		return -EIO;
+	}
+	proc_ppc64_scan_log_dump = ent;
+
+	return 0;
+}
+
+void __exit scanlog_cleanup(void)
+{
+	if (proc_ppc64_scan_log_dump) {
+		if (proc_ppc64_scan_log_dump->data)
+			kfree(proc_ppc64_scan_log_dump->data);
+		remove_proc_entry("scan-log-dump", proc_ppc64_scan_log_dump->parent);
+	}
+}
+
+module_init(scanlog_init);
+module_exit(scanlog_cleanup);
+MODULE_LICENSE("GPL");
diff -Nru a/arch/ppc64/kernel/signal32.c b/arch/ppc64/kernel/signal32.c
--- a/arch/ppc64/kernel/signal32.c	Mon Feb 17 14:57:28 2003
+++ b/arch/ppc64/kernel/signal32.c	Mon Feb 17 14:57:28 2003
@@ -750,6 +750,8 @@
 	return ret;
 }
 
+extern int do_signal(sigset_t *oldset, struct pt_regs *regs);
+
 int sys32_rt_sigsuspend(compat_sigset_t* unewset, size_t sigsetsize, int p3,
 		int p4, int p6, int p7, struct pt_regs *regs)
 {
diff -Nru a/arch/ppc64/kernel/smp.c b/arch/ppc64/kernel/smp.c
--- a/arch/ppc64/kernel/smp.c	Mon Feb 17 14:57:28 2003
+++ b/arch/ppc64/kernel/smp.c	Mon Feb 17 14:57:28 2003
@@ -63,7 +63,6 @@
 extern int cpu_idle(void *unused);
 void smp_call_function_interrupt(void);
 void smp_message_pass(int target, int msg, unsigned long data, int wait);
-static unsigned long iSeries_smp_message[NR_CPUS];
 
 void xics_setup_cpu(void);
 void xics_cause_IPI(int cpu);
@@ -87,6 +86,8 @@
 }
 
 #ifdef CONFIG_PPC_ISERIES
+static unsigned long iSeries_smp_message[NR_CPUS];
+
 void iSeries_smp_message_recv( struct pt_regs * regs )
 {
 	int cpu = smp_processor_id();
@@ -563,8 +564,6 @@
 
 void __init smp_prepare_cpus(unsigned int max_cpus)
 {
-	int i;
-
 	/* Fixup boot cpu */
 	smp_store_cpu_info(smp_processor_id());
 	cpu_callin_map[smp_processor_id()] = 1;
diff -Nru a/arch/ppc64/kernel/sys32.S b/arch/ppc64/kernel/sys32.S
--- a/arch/ppc64/kernel/sys32.S	Mon Feb 17 14:57:28 2003
+++ b/arch/ppc64/kernel/sys32.S	Mon Feb 17 14:57:28 2003
@@ -289,8 +289,7 @@
 	li	r3,-EFAULT
 	blr
 
-	.data
-	.align	8
+	.balign	8
 _GLOBAL(socketcall_table_begin)
 	.llong		.do_sys_socket
 	.llong		.do_sys_bind
diff -Nru a/arch/ppc64/kernel/sys_ppc32.c b/arch/ppc64/kernel/sys_ppc32.c
--- a/arch/ppc64/kernel/sys_ppc32.c	Mon Feb 17 14:57:27 2003
+++ b/arch/ppc64/kernel/sys_ppc32.c	Mon Feb 17 14:57:27 2003
@@ -58,6 +58,7 @@
 #include <linux/dnotify.h>
 #include <linux/security.h>
 #include <linux/compat.h>
+#include <linux/ptrace.h>
 
 #include <asm/types.h>
 #include <asm/ipc.h>
@@ -607,10 +608,6 @@
 }
 /* end of readdir & getdents */
 
-
-
-/* 32-bit timeval and related flotsam.  */
-
 /*
  * Ooo, nasty.  We need here to frob 32-bit unsigned longs to
  * 64-bit unsigned longs.
@@ -768,13 +765,9 @@
 	return ret;
 }
 
-/* Note: it is necessary to treat n as an unsigned int, 
- * with the corresponding cast to a signed int to insure that the 
- * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
- * and the register representation of a signed int (msr in 64-bit mode) is performed.
- */
-asmlinkage int ppc32_select(u32 n, u32* inp, u32* outp, u32* exp, u32 tvp_x)
+int ppc32_select(u32 n, u32* inp, u32* outp, u32* exp, u32 tvp_x)
 {
+	/* sign extend n */
 	return sys32_select((int)n, inp, outp, exp, tvp_x);
 }
 
@@ -819,45 +812,6 @@
 	return sys_sysfs((int)option, arg1, arg2);
 }
 
-
-
-
-extern unsigned long do_mremap(unsigned long addr,
-	unsigned long old_len, unsigned long new_len,
-	unsigned long flags, unsigned long new_addr);
-                
-asmlinkage unsigned long sys32_mremap(unsigned long addr, unsigned long old_len, unsigned long new_len,
-                                    	unsigned long flags, u32 __new_addr)
-{
-	unsigned long ret = -EINVAL;
-	unsigned long new_addr = AA(__new_addr);
-	
-	if (old_len > 0xf0000000UL || new_len > 0xf0000000UL)
-		goto out;
-	if (addr > 0xf0000000UL - old_len)
-		goto out;
-	down_write(&current->mm->mmap_sem);
-	if (flags & MREMAP_FIXED) {
-		if (new_addr > 0xf0000000UL - new_len)
-			goto out_sem;
-	} else if (addr > 0xf0000000UL - new_len) {
-		ret = -ENOMEM;
-		if (!(flags & MREMAP_MAYMOVE))
-			goto out_sem;
-		new_addr = get_unmapped_area (NULL, addr, new_len, 0, 0);
-		if (!new_addr)
-			goto out_sem;
-		flags |= MREMAP_FIXED;
-	}
-	ret = do_mremap(addr, old_len, new_len, flags, new_addr);
-out_sem:
-	up_write(&current->mm->mmap_sem);
-out:
-	return ret;       
-}
-
-
-
 /* Handle adjtimex compatability. */
 struct timex32 {
 	u32 modes;
@@ -934,38 +888,6 @@
 	return ret;
 }
 
-#ifdef CONFIG_MODULES
-
-extern asmlinkage long sys_init_module(void *, unsigned long, const char *);
-
-asmlinkage int sys32_init_module(void *umod, u32 len, const char *uargs)
-{
-	return sys_init_module(umod, len, uargs);
-}
-
-extern asmlinkage long sys_delete_module(const char *, unsigned int);
-
-asmlinkage int sys32_delete_module(const char *name_user, unsigned int flags)
-{
-	return sys_delete_module(name_user, flags);
-}
-
-#else /* CONFIG_MODULES */
-
-asmlinkage int
-sys32_init_module(const char *name_user, struct module *mod_user)
-{
-	return -ENOSYS;
-}
-
-asmlinkage int
-sys32_delete_module(const char *name_user)
-{
-	return -ENOSYS;
-}
-
-#endif  /* CONFIG_MODULES */
-
 /* Stuff for NFS server syscalls... */
 struct nfsctl_svc32 {
 	u16			svc32_port;
@@ -3097,9 +3019,9 @@
 	return retval;
 }
 
-asmlinkage long sys32_execve(unsigned long a0, unsigned long a1, unsigned long a2,
-			                       unsigned long a3, unsigned long a4, unsigned long a5,
-			                       struct pt_regs *regs)
+long sys32_execve(unsigned long a0, unsigned long a1, unsigned long a2,
+		  unsigned long a3, unsigned long a4, unsigned long a5,
+		  struct pt_regs *regs)
 {
 	int error;
 	char * filename;
@@ -3348,9 +3270,6 @@
 	return sys_getsid((int)pid);
 }
 
-
-
-
 extern asmlinkage long sys_kill(int pid, int sig);
 
 /* Note: it is necessary to treat pid and sig as unsigned ints,
@@ -3402,16 +3321,11 @@
 	return sys_msync(start, len, (int)flags);
 }
 
-
 extern asmlinkage long sys_nice(int increment);
 
-/* Note: it is necessary to treat increment as an unsigned int,
- * with the corresponding cast to a signed int to insure that the 
- * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
- * and the register representation of a signed int (msr in 64-bit mode) is performed.
- */
-asmlinkage long sys32_nice(u32 increment)
+long sys32_nice(u32 increment)
 {
+	/* sign extend increment */
 	return sys_nice((int)increment);
 }
 
@@ -3564,13 +3478,9 @@
 
 extern asmlinkage long sys_sethostname(char *name, int len);
 
-/* Note: it is necessary to treat len as an unsigned int,
- * with the corresponding cast to a signed int to insure that the 
- * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
- * and the register representation of a signed int (msr in 64-bit mode) is performed.
- */
 asmlinkage long sys32_sethostname(char *name, u32 len)
 {
+	/* sign extend len */
 	return sys_sethostname(name, (int)len);
 }
 
@@ -3590,17 +3500,12 @@
 
 extern asmlinkage long sys_setpriority(int which, int who, int niceval);
 
-/* Note: it is necessary to treat which, who, and niceval as unsigned ints,
- * with the corresponding cast to a signed int to insure that the 
- * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
- * and the register representation of a signed int (msr in 64-bit mode) is performed.
- */
-asmlinkage long sys32_setpriority(u32 which, u32 who, u32 niceval)
+long sys32_setpriority(u32 which, u32 who, u32 niceval)
 {
+	/* sign extend which, who and niceval */
 	return sys_setpriority((int)which, (int)who, (int)niceval);
 }
 
-
 extern asmlinkage long sys_ssetmask(int newmask);
 
 /* Note: it is necessary to treat newmask as an unsigned int,
@@ -3613,17 +3518,12 @@
 	return sys_ssetmask((int) newmask);
 }
 
-
 extern asmlinkage long sys_syslog(int type, char * buf, int len);
 
-/* Note: it is necessary to treat type and len as an unsigned int,
- * with the corresponding cast to a signed int to insure that the 
- * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
- * and the register representation of a signed int (msr in 64-bit mode) is performed.
- */
-asmlinkage long sys32_syslog(u32 type, char * buf, u32 len)
+long sys32_syslog(u32 type, char * buf, u32 len)
 {
-	return sys_syslog((int)type, buf, (int)len);
+	/* sign extend len */
+	return sys_syslog(type, buf, (int)len);
 }
 
 
@@ -3652,51 +3552,6 @@
 	return sys_umount(name, (int)flags);
 }
 
-
-extern ssize_t sys_pread64(unsigned int fd, char *buf, size_t count,
-			   loff_t pos);
-
-extern ssize_t sys_pwrite64(unsigned int fd, const char *buf, size_t count,
-			    loff_t pos);
-
-compat_ssize_t sys32_pread64(unsigned int fd, char *ubuf, compat_size_t count,
-			u32 reg6, u32 poshi, u32 poslo)
-{
-	return sys_pread64(fd, ubuf, count, ((loff_t)AA(poshi) << 32) | AA(poslo));
-}
-
-compat_ssize_t sys32_pwrite64(unsigned int fd, char *ubuf, compat_size_t count,
-			 u32 reg6, u32 poshi, u32 poslo)
-{
-	return sys_pwrite64(fd, ubuf, count, ((loff_t)AA(poshi) << 32) | AA(poslo));
-}
-
-extern ssize_t sys_readahead(int fd, loff_t offset, size_t count);
-
-compat_ssize_t sys32_readahead(int fd, u32 r4, u32 offhi, u32 offlo, u32 count)
-{
-        return sys_readahead(fd, ((loff_t)offhi << 32) | offlo, AA(count));
-}
-
-extern asmlinkage long sys_truncate(const char * path, unsigned long length);
-extern asmlinkage long sys_ftruncate(unsigned int fd, unsigned long length);
-
-asmlinkage int sys32_truncate64(const char * path, u32 reg4, unsigned long high, unsigned long low)
-{
-     	if ((int)high < 0)
-		return -EINVAL;
-	else
-		return sys_truncate(path, (high << 32) | low);
-}
-
-asmlinkage int sys32_ftruncate64(unsigned int fd, u32 reg4, unsigned long high, unsigned long low)
-{
-     	if ((int)high < 0)
-		return -EINVAL;
-	else
-		return sys_ftruncate(fd, (high << 32) | low);
-}
-
 asmlinkage long sys32_fcntl64(unsigned int fd, unsigned int cmd, unsigned long arg)
 {
 	if (cmd >= F_GETLK64 && cmd <= F_SETLKW64)
@@ -3845,6 +3700,7 @@
 	
 	return error;
 }
+
 extern unsigned long sys_mmap(unsigned long addr, size_t len,
 			      unsigned long prot, unsigned long flags,
 			      unsigned long fd, off_t offset);
@@ -3857,11 +3713,65 @@
 	return sys_mmap(addr, len, prot, flags, fd, pgoff << 12);
 }
 
+/* 
+ * long long munging:
+ * The 32 bit ABI passes long longs in an odd even register pair.
+ */
+extern ssize_t sys_pread64(unsigned int fd, char *buf, size_t count,
+			   loff_t pos);
+
+extern ssize_t sys_pwrite64(unsigned int fd, const char *buf, size_t count,
+			    loff_t pos);
+
+compat_ssize_t sys32_pread64(unsigned int fd, char *ubuf, compat_size_t count,
+			     u32 reg6, u32 poshi, u32 poslo)
+{
+	return sys_pread64(fd, ubuf, count, ((loff_t)poshi << 32) | poslo);
+}
+
+compat_ssize_t sys32_pwrite64(unsigned int fd, char *ubuf, compat_size_t count,
+			      u32 reg6, u32 poshi, u32 poslo)
+{
+	return sys_pwrite64(fd, ubuf, count, ((loff_t)poshi << 32) | poslo);
+}
+
+extern ssize_t sys_readahead(int fd, loff_t offset, size_t count);
+
+compat_ssize_t sys32_readahead(int fd, u32 r4, u32 offhi, u32 offlo, u32 count)
+{
+	return sys_readahead(fd, ((loff_t)offhi << 32) | offlo, count);
+}
+
+extern asmlinkage long sys_truncate(const char * path, unsigned long length);
+extern asmlinkage long sys_ftruncate(unsigned int fd, unsigned long length);
+
+asmlinkage int sys32_truncate64(const char * path, u32 reg4,
+				unsigned long high, unsigned long low)
+{
+	return sys_truncate(path, (high << 32) | low);
+}
+
+asmlinkage int sys32_ftruncate64(unsigned int fd, u32 reg4, unsigned long high,
+				 unsigned long low)
+{
+	return sys_ftruncate(fd, (high << 32) | low);
+}
+
 extern int sys_lookup_dcookie(u64 cookie64, char *buf, size_t len);
 
-long sys32_lookup_dcookie(u32 cookie_high, u32 cookie_low, char *buf,
+long ppc32_lookup_dcookie(u32 cookie_high, u32 cookie_low, char *buf,
 			  size_t len)
 {
 	return sys_lookup_dcookie((u64)cookie_high << 32 | cookie_low,
 				  buf, len);
 }
+
+extern int sys_fadvise64(int fd, loff_t offset, size_t len, int advice);
+
+long ppc32_fadvise64(int fd, u32 unused, u32 offset_high, u32 offset_low,
+		     size_t len, int advice)
+{
+	return sys_fadvise64(fd, (u64)offset_high << 32 | offset_low, len,
+			     advice);
+}
+
diff -Nru a/arch/ppc64/kernel/time.c b/arch/ppc64/kernel/time.c
--- a/arch/ppc64/kernel/time.c	Mon Feb 17 14:57:28 2003
+++ b/arch/ppc64/kernel/time.c	Mon Feb 17 14:57:28 2003
@@ -267,7 +267,6 @@
 	unsigned long cur_tb;
 	struct paca_struct *lpaca = get_paca();
 	unsigned long cpu = lpaca->xPacaIndex;
-	struct ItLpQueue * lpq;
 
 	irq_enter();
 
@@ -301,9 +300,11 @@
 	set_dec(next_dec);
 
 #ifdef CONFIG_PPC_ISERIES
-	lpq = lpaca->lpQueuePtr;
-	if (lpq && ItLpQueue_isLpIntPending(lpq))
-		lpEvent_count += ItLpQueue_process(lpq, regs); 
+	{
+		struct ItLpQueue *lpq = lpaca->lpQueuePtr;
+		if (lpq && ItLpQueue_isLpIntPending(lpq))
+			lpEvent_count += ItLpQueue_process(lpq, regs);
+	}
 #endif
 
 	irq_exit();
diff -Nru a/arch/ppc64/kernel/traps.c b/arch/ppc64/kernel/traps.c
--- a/arch/ppc64/kernel/traps.c	Mon Feb 17 14:57:27 2003
+++ b/arch/ppc64/kernel/traps.c	Mon Feb 17 14:57:27 2003
@@ -151,61 +151,87 @@
 	/* What should we do here? We could issue a shutdown or hard reset. */
 }
 
-static int power4_handle_mce(struct pt_regs *regs)
+/* 
+ * See if we can recover from a machine check exception.
+ * This is only called on power4 (or above) and only via
+ * the Firmware Non-Maskable Interrupts (fwnmi) handler
+ * which provides the error analysis for us.
+ *
+ * Return 1 if corrected (or delivered a signal).
+ * Return 0 if there is nothing we can do.
+ */
+static int recover_mce(struct pt_regs *regs, struct rtas_error_log err)
 {
+	siginfo_t info;
+
+	if (err.disposition == DISP_FULLY_RECOVERED) {
+		/* Platform corrected itself */
+		return 1;
+	} else if ((regs->msr & MSR_RI) &&
+		   user_mode(regs) &&
+		   err.severity == SEVERITY_ERROR_SYNC &&
+		   err.disposition == DISP_NOT_RECOVERED &&
+		   err.target == TARGET_MEMORY &&
+		   err.type == TYPE_ECC_UNCORR &&
+		   !(current->pid == 0 || current->pid == 1)) {
+		/* Kill off a user process with an ECC error */
+		info.si_signo = SIGBUS;
+		info.si_errno = 0;
+		/* XXX something better for ECC error? */
+		info.si_code = BUS_ADRERR;
+		info.si_addr = (void *)regs->nip;
+		printk(KERN_ERR "MCE: uncorrectable ecc error for pid %d\n",
+		       current->pid);
+		_exception(SIGBUS, &info, regs);
+		return 1;
+	}
 	return 0;
 }
 
+/*
+ * Handle a machine check.
+ *
+ * Note that on Power 4 and beyond Firmware Non-Maskable Interrupts (fwnmi)
+ * should be present.  If so the handler which called us tells us if the
+ * error was recovered (never true if RI=0).
+ *
+ * On hardware prior to Power 4 these exceptions were asynchronous which
+ * means we can't tell exactly where it occurred and so we can't recover.
+ *
+ * Note that the debugger should test RI=0 and warn the user that system
+ * state has been corrupted.
+ */
 void
 MachineCheckException(struct pt_regs *regs)
 {
-	siginfo_t info;
+	struct rtas_error_log err, *errp;
 
 	if (fwnmi_active) {
-		struct rtas_error_log *errhdr = FWNMI_get_errinfo(regs);
-		if (errhdr) {
-			/* ToDo: attempt to recover from some errors here */
-		}
-		FWNMI_release_errinfo();
+		errp = FWNMI_get_errinfo(regs);
+		if (errp)
+			err = *errp;
+		FWNMI_release_errinfo();	/* frees errp */
+		if (errp && recover_mce(regs, err))
+			return;
 	}
 
-	if (!user_mode(regs)) {
-		/* Attempt to recover if the interrupt is recoverable */
-		if (regs->msr & MSR_RI) {
-			if ((__is_processor(PV_POWER4) ||
-			     __is_processor(PV_POWER4p)) &&
-			     power4_handle_mce(regs))
-				return;
-		}
-
 #ifdef CONFIG_DEBUG_KERNEL
-		if (debugger_fault_handler) {
-			debugger_fault_handler(regs);
-			return;
-		}
-		if (debugger)
-			debugger(regs);
-#endif
-		console_verbose();
-		spin_lock_irq(&die_lock);
-		bust_spinlocks(1);
-		printk("Machine check in kernel mode.\n");
-		printk("Caused by (from SRR1=%lx): ", regs->msr);
-		show_regs(regs);
-		bust_spinlocks(0);
-		spin_unlock_irq(&die_lock);
-		panic("Unrecoverable Machine Check");
+	if (debugger_fault_handler) {
+		debugger_fault_handler(regs);
+		return;
 	}
-
-	/*
-	 * XXX we should check RI bit on exception exit and kill the
-	 * task if it was cleared
-	 */
-	info.si_signo = SIGBUS;
-	info.si_errno = 0;
-	info.si_code = BUS_ADRERR;
-	info.si_addr = (void *)regs->nip;
-	_exception(SIGSEGV, &info, regs);
+	if (debugger)
+		debugger(regs);
+#endif
+	console_verbose();
+	spin_lock_irq(&die_lock);
+	bust_spinlocks(1);
+	printk("Machine check in kernel mode.\n");
+	printk("Caused by (from SRR1=%lx): ", regs->msr);
+	show_regs(regs);
+	bust_spinlocks(0);
+	spin_unlock_irq(&die_lock);
+	panic("Unrecoverable Machine Check");
 }
 
 void
diff -Nru a/arch/ppc64/xmon/start.c b/arch/ppc64/xmon/start.c
--- a/arch/ppc64/xmon/start.c	Mon Feb 17 14:57:28 2003
+++ b/arch/ppc64/xmon/start.c	Mon Feb 17 14:57:28 2003
@@ -17,7 +17,6 @@
 #include <asm/udbg.h>
 
 extern void xmon_printf(const char *fmt, ...);
-static int xmon_expect(const char *str, unsigned int timeout);
 
 #define TB_SPEED	25000000
 
@@ -120,32 +119,6 @@
 static char line[256];
 static char *lineptr;
 static int lineleft;
-
-int xmon_expect(const char *str, unsigned int timeout)
-{
-	int c;
-	unsigned int t0;
-
-	timeout *= TB_SPEED;
-	t0 = readtb();
-	do {
-		lineptr = line;
-		for (;;) {
-			c = xmon_read_poll();
-			if (c == -1) {
-				if (readtb() - t0 > timeout)
-					return 0;
-				continue;
-			}
-			if (c == '\n')
-				break;
-			if (c != '\r' && lineptr < &line[sizeof(line) - 1])
-				*lineptr++ = c;
-		}
-		*lineptr = 0;
-	} while (strstr(line, str) == NULL);
-	return 1;
-}
 
 int
 xmon_getchar(void)
diff -Nru a/arch/ppc64/xmon/xmon.c b/arch/ppc64/xmon/xmon.c
--- a/arch/ppc64/xmon/xmon.c	Mon Feb 17 14:57:28 2003
+++ b/arch/ppc64/xmon/xmon.c	Mon Feb 17 14:57:28 2003
@@ -2072,6 +2072,10 @@
 	int instr;
 	int num_parms;
 
+	/* dont look for traceback table in userspace */
+	if (codeaddr < PAGE_OFFSET)
+		return 0;
+
 	if (tab == NULL)
 		return 0;
 	memset(tab, 0, sizeof(tab));
diff -Nru a/arch/s390x/kernel/entry.S b/arch/s390x/kernel/entry.S
--- a/arch/s390x/kernel/entry.S	Mon Feb 17 14:57:27 2003
+++ b/arch/s390x/kernel/entry.S	Mon Feb 17 14:57:27 2003
@@ -629,7 +629,7 @@
 	.long  SYSCALL(sys_fremovexattr,sys32_fremovexattr_wrapper) /* 235 */
 	.long  SYSCALL(sys_gettid,sys_gettid)
 	.long  SYSCALL(sys_tkill,sys_tkill)
-	.long  SYSCALL(sys_futex,sys32_futex_wrapper)
+	.long  SYSCALL(sys_futex,compat_sys_futex_wrapper)
 	.long  SYSCALL(sys_sched_setaffinity,sys32_sched_setaffinity_wrapper)
 	.long  SYSCALL(sys_sched_getaffinity,sys32_sched_getaffinity_wrapper) /* 240 */
 	.long  SYSCALL(sys_ni_syscall,sys_ni_syscall)
diff -Nru a/arch/s390x/kernel/linux32.c b/arch/s390x/kernel/linux32.c
--- a/arch/s390x/kernel/linux32.c	Mon Feb 17 14:57:27 2003
+++ b/arch/s390x/kernel/linux32.c	Mon Feb 17 14:57:27 2003
@@ -58,6 +58,7 @@
 #include <linux/binfmts.h>
 #include <linux/compat.h>
 #include <linux/vfs.h>
+#include <linux/ptrace.h>
 
 #include <asm/types.h>
 #include <asm/ipc.h>
@@ -4045,28 +4046,6 @@
 		if (put_user(kernel_mask, user_mask_ptr))
 			ret = -EFAULT;
 	}
-
-	return ret;
-}
-
-asmlinkage int 
-sys_futex(void *uaddr, int op, int val, struct timespec *utime);
-
-asmlinkage int
-sys32_futex(void *uaddr, int op, int val, 
-		 struct compat_timespec *timeout32)
-{
-	struct timespec tmp;
-	mm_segment_t old_fs;
-	int ret;
-
-	if (timeout32 && get_compat_timespec(&tmp, timeout32))
-		return -EINVAL;
-
-	old_fs = get_fs();
-	set_fs(KERNEL_DS);
-	ret = sys_futex(uaddr, op, val, timeout32 ? &tmp : NULL);
-	set_fs(old_fs);
 
 	return ret;
 }
diff -Nru a/arch/s390x/kernel/wrapper32.S b/arch/s390x/kernel/wrapper32.S
--- a/arch/s390x/kernel/wrapper32.S	Mon Feb 17 14:57:28 2003
+++ b/arch/s390x/kernel/wrapper32.S	Mon Feb 17 14:57:28 2003
@@ -1088,13 +1088,13 @@
 	llgfr	%r4,%r4			# long
 	jg	sys32_fstat64		# branch to system call
 
-	.globl  sys32_futex_wrapper 
-sys32_futex_wrapper:
-	llgtr	%r2,%r2			# void *
+	.globl  compat_sys_futex_wrapper 
+compat_sys_futex_wrapper:
+	llgtr	%r2,%r2			# u32 *
 	lgfr	%r3,%r3			# int
 	lgfr	%r4,%r4			# int
-	llgtr	%r5,%r5			# struct timespec *
-	jg	sys32_futex		# branch to system call
+	llgtr	%r5,%r5			# struct compat_timespec *
+	jg	compat_sys_futex	# branch to system call
 
 	.globl	sys32_setxattr_wrapper
 sys32_setxattr_wrapper:
diff -Nru a/arch/sh/kernel/process.c b/arch/sh/kernel/process.c
--- a/arch/sh/kernel/process.c	Mon Feb 17 14:57:27 2003
+++ b/arch/sh/kernel/process.c	Mon Feb 17 14:57:27 2003
@@ -15,6 +15,7 @@
 #include <linux/mm.h>
 #include <linux/slab.h>
 #include <linux/a.out.h>
+#include <linux/ptrace.h>
 
 #include <asm/io.h>
 #include <asm/uaccess.h>
diff -Nru a/arch/sparc64/Kconfig b/arch/sparc64/Kconfig
--- a/arch/sparc64/Kconfig	Mon Feb 17 14:57:28 2003
+++ b/arch/sparc64/Kconfig	Mon Feb 17 14:57:28 2003
@@ -151,7 +151,7 @@
 	  If in doubt, say N.
 
 config CPU_FREQ_PROC_INTF
-	bool "/proc/cpufreq interface (DEPRECATED)"
+	tristate "/proc/cpufreq interface (DEPRECATED)"
 	depends on CPU_FREQ && PROC_FS
 	help
 	  This enables the /proc/cpufreq interface for controlling
@@ -162,9 +162,14 @@
 	  
 	  If in doubt, say N.
 
+config CPU_FREQ_TABLE
+       tristate
+       default y
+
+
 config US3_FREQ
 	tristate "UltraSPARC-III CPU Frequency driver"
-	depends on CPU_FREQ
+	depends on CPU_FREQ_TABLE
 	help
 	  This adds the CPUFreq driver for UltraSPARC-III processors.
 
diff -Nru a/arch/sparc64/kernel/sys_sparc32.c b/arch/sparc64/kernel/sys_sparc32.c
--- a/arch/sparc64/kernel/sys_sparc32.c	Mon Feb 17 14:57:27 2003
+++ b/arch/sparc64/kernel/sys_sparc32.c	Mon Feb 17 14:57:27 2003
@@ -54,6 +54,7 @@
 #include <linux/compat.h>
 #include <linux/vfs.h>
 #include <linux/netfilter_ipv4/ip_tables.h>
+#include <linux/ptrace.h>
 
 #include <asm/types.h>
 #include <asm/ipc.h>
diff -Nru a/arch/um/kernel/exec_kern.c b/arch/um/kernel/exec_kern.c
--- a/arch/um/kernel/exec_kern.c	Mon Feb 17 14:57:27 2003
+++ b/arch/um/kernel/exec_kern.c	Mon Feb 17 14:57:27 2003
@@ -5,6 +5,7 @@
 
 #include "linux/slab.h"
 #include "linux/smp_lock.h"
+#include "linux/ptrace.h"
 #include "asm/ptrace.h"
 #include "asm/pgtable.h"
 #include "asm/tlbflush.h"
diff -Nru a/arch/um/kernel/signal_kern.c b/arch/um/kernel/signal_kern.c
--- a/arch/um/kernel/signal_kern.c	Mon Feb 17 14:57:27 2003
+++ b/arch/um/kernel/signal_kern.c	Mon Feb 17 14:57:27 2003
@@ -14,6 +14,7 @@
 #include "linux/slab.h"
 #include "linux/tty.h"
 #include "linux/binfmts.h"
+#include "linux/ptrace.h"
 #include "asm/signal.h"
 #include "asm/uaccess.h"
 #include "asm/unistd.h"
diff -Nru a/arch/um/kernel/skas/process_kern.c b/arch/um/kernel/skas/process_kern.c
--- a/arch/um/kernel/skas/process_kern.c	Mon Feb 17 14:57:27 2003
+++ b/arch/um/kernel/skas/process_kern.c	Mon Feb 17 14:57:27 2003
@@ -5,6 +5,7 @@
 
 #include "linux/sched.h"
 #include "linux/slab.h"
+#include "linux/ptrace.h"
 #include "kern_util.h"
 #include "time_user.h"
 #include "signal_user.h"
diff -Nru a/arch/um/kernel/tt/process_kern.c b/arch/um/kernel/tt/process_kern.c
--- a/arch/um/kernel/tt/process_kern.c	Mon Feb 17 14:57:28 2003
+++ b/arch/um/kernel/tt/process_kern.c	Mon Feb 17 14:57:28 2003
@@ -7,6 +7,7 @@
 #include "linux/signal.h"
 #include "linux/kernel.h"
 #include "linux/interrupt.h"
+#include "linux/ptrace.h"
 #include "asm/system.h"
 #include "asm/pgalloc.h"
 #include "asm/ptrace.h"
diff -Nru a/arch/um/kernel/tt/syscall_kern.c b/arch/um/kernel/tt/syscall_kern.c
--- a/arch/um/kernel/tt/syscall_kern.c	Mon Feb 17 14:57:26 2003
+++ b/arch/um/kernel/tt/syscall_kern.c	Mon Feb 17 14:57:26 2003
@@ -6,6 +6,7 @@
 #include "linux/types.h"
 #include "linux/utime.h"
 #include "linux/sys.h"
+#include "linux/ptrace.h"
 #include "asm/unistd.h"
 #include "asm/ptrace.h"
 #include "asm/uaccess.h"
diff -Nru a/arch/v850/kernel/asm-consts.c b/arch/v850/kernel/asm-consts.c
--- a/arch/v850/kernel/asm-consts.c	Mon Feb 17 14:57:27 2003
+++ b/arch/v850/kernel/asm-consts.c	Mon Feb 17 14:57:27 2003
@@ -11,6 +11,7 @@
 #include <linux/stddef.h>
 #include <linux/sched.h>
 #include <linux/kernel_stat.h>
+#include <linux/ptrace.h>
 #include <asm/irq.h>
 #include <asm/hardirq.h>
 #include <asm/errno.h>
diff -Nru a/arch/x86_64/ia32/ia32entry.S b/arch/x86_64/ia32/ia32entry.S
--- a/arch/x86_64/ia32/ia32entry.S	Mon Feb 17 14:57:27 2003
+++ b/arch/x86_64/ia32/ia32entry.S	Mon Feb 17 14:57:27 2003
@@ -440,7 +440,7 @@
 	.quad sys_fremovexattr
 	.quad sys_tkill		/* 238 */ 
 	.quad sys_sendfile64 
-	.quad sys32_futex		/* 240 */
+	.quad compat_sys_futex		/* 240 */
         .quad sys32_sched_setaffinity
         .quad sys32_sched_getaffinity
 	.quad sys_set_thread_area
diff -Nru a/arch/x86_64/ia32/sys_ia32.c b/arch/x86_64/ia32/sys_ia32.c
--- a/arch/x86_64/ia32/sys_ia32.c	Mon Feb 17 14:57:27 2003
+++ b/arch/x86_64/ia32/sys_ia32.c	Mon Feb 17 14:57:27 2003
@@ -59,6 +59,7 @@
 #include <linux/aio_abi.h>
 #include <linux/compat.h>
 #include <linux/vfs.h>
+#include <linux/ptrace.h>
 #include <asm/mman.h>
 #include <asm/types.h>
 #include <asm/uaccess.h>
@@ -2197,26 +2198,6 @@
 	if (err > 0) 
 		err = put_user((u32)mask, new_mask_ptr); 
 	return err;
-}
-
-extern int sys_futex(unsigned long uaddr, int op, int val, struct timespec *t); 
-
-asmlinkage long
-sys32_futex(unsigned long uaddr, int op, int val, struct compat_timespec *utime32)
-{
-	struct timespec t;
-	mm_segment_t oldfs = get_fs(); 
-	int err;
-
-	if (utime32 && get_compat_timespec(&t, utime32))
-		return -EFAULT;
-
-	/* the set_fs is safe because futex doesn't use the seg limit 
-	   for valid page checking of uaddr. */ 
-	set_fs(KERNEL_DS); 
-	err = sys_futex(uaddr, op, val, utime32 ? &t : NULL);
-	set_fs(oldfs); 
-	return err; 
 }
 
 extern long sys_io_setup(unsigned nr_reqs, aio_context_t *ctx);
diff -Nru a/drivers/Makefile b/drivers/Makefile
--- a/drivers/Makefile	Mon Feb 17 14:57:28 2003
+++ b/drivers/Makefile	Mon Feb 17 14:57:28 2003
@@ -45,3 +45,4 @@
 obj-$(CONFIG_ISDN_BOOL)		+= isdn/
 obj-$(CONFIG_MCA)		+= mca/
 obj-$(CONFIG_EISA)		+= eisa/
+obj-$(CONFIG_CPU_FREQ)		+= cpufreq/
diff -Nru a/drivers/acorn/block/fd1772.c b/drivers/acorn/block/fd1772.c
--- a/drivers/acorn/block/fd1772.c	Mon Feb 17 14:57:27 2003
+++ b/drivers/acorn/block/fd1772.c	Mon Feb 17 14:57:27 2003
@@ -336,7 +336,7 @@
  */
 static int Probing = 0;
 
-/* This flag is set when a dummy seek is necesary to make the WP
+/* This flag is set when a dummy seek is necessary to make the WP
  * status bit accessible.
  */
 static int NeedSeek = 0;
diff -Nru a/drivers/acorn/scsi/acornscsi.c b/drivers/acorn/scsi/acornscsi.c
--- a/drivers/acorn/scsi/acornscsi.c	Mon Feb 17 14:57:27 2003
+++ b/drivers/acorn/scsi/acornscsi.c	Mon Feb 17 14:57:27 2003
@@ -116,7 +116,7 @@
 
 #ifdef DEBUG_TARGET
 #define DBG(cmd,xxx...) \
-  if (cmd->target == DEBUG_TARGET) { \
+  if (cmd->device->id == DEBUG_TARGET) { \
     xxx; \
   }
 #else
@@ -575,7 +575,7 @@
 char acornscsi_target(AS_Host *host)
 {
 	if (host->SCpnt)
-		return '0' + host->SCpnt->target;
+		return '0' + host->SCpnt->device->id;
 	return 'H';
 }
 
@@ -742,7 +742,7 @@
      * In this case, we don't want to write to the registers
      */
     if (!(sbic_arm_read(host->scsi.io_port, ASR) & (ASR_INT|ASR_BSY|ASR_CIP))) {
-	sbic_arm_write(host->scsi.io_port, DESTID, SCpnt->target);
+	sbic_arm_write(host->scsi.io_port, DESTID, SCpnt->device->id);
 	sbic_arm_write(host->scsi.io_port, CMND, CMND_SELWITHATN);
     }
 
@@ -759,7 +759,7 @@
 
 #if (DEBUG & (DEBUG_ABORT|DEBUG_CONNECT))
     DBG(SCpnt,printk("scsi%d.%c: starting cmd %02X\n",
-	    host->host->host_no, '0' + SCpnt->target,
+	    host->host->host_no, '0' + SCpnt->device->id,
 	    SCpnt->cmnd[0]));
 #endif
 
@@ -775,7 +775,7 @@
 	    SCpnt->tag = SCpnt->device->current_tag;
 	} else
 #endif
-	    set_bit(SCpnt->target * 8 + SCpnt->lun, host->busyluns);
+	    set_bit(SCpnt->device->id * 8 + SCpnt->device->lun, host->busyluns);
 
 	host->stats.removes += 1;
 
@@ -868,7 +868,7 @@
 				host->host->host_no, SCpnt->result);
 			print_command(SCpnt->cmnd);
 			acornscsi_dumpdma(host, "done");
-		 	acornscsi_dumplog(host, SCpnt->target);
+		 	acornscsi_dumplog(host, SCpnt->device->id);
 			SCpnt->result &= 0xffff;
 			SCpnt->result |= DID_ERROR << 16;
 		    }
@@ -878,7 +878,7 @@
 	if (!SCpnt->scsi_done)
 	    panic("scsi%d.H: null scsi_done function in acornscsi_done", host->host->host_no);
 
-	clear_bit(SCpnt->target * 8 + SCpnt->lun, host->busyluns);
+	clear_bit(SCpnt->device->id * 8 + SCpnt->device->lun, host->busyluns);
 
 	SCpnt->scsi_done(SCpnt);
     } else
@@ -1035,7 +1035,7 @@
 
     if (direction == DMA_OUT) {
 #if (DEBUG & DEBUG_NO_WRITE)
-	if (NO_WRITE & (1 << host->SCpnt->target)) {
+	if (NO_WRITE & (1 << host->SCpnt->device->id)) {
 	    printk(KERN_CRIT "scsi%d.%c: I can't handle DMA_OUT!\n",
 		    host->host->host_no, acornscsi_target(host));
 	    return;
@@ -1511,7 +1511,7 @@
 	if (host->scsi.phase != PHASE_STATUSIN) {
 	    printk(KERN_ERR "scsi%d.%c: command complete following non-status in phase?\n",
 		    host->host->host_no, acornscsi_target(host));
-	    acornscsi_dumplog(host, host->SCpnt->target);
+	    acornscsi_dumplog(host, host->SCpnt->device->id);
 	}
 	host->scsi.phase = PHASE_DONE;
 	host->scsi.SCp.Message = message[0];
@@ -1567,8 +1567,8 @@
 	 * transfer.  Re-initiate sync transfer negociation now, and if
 	 * we got a REJECT in response to SDTR, then it'll be set to DONE.
 	 */
-	if (host->device[host->SCpnt->target].sync_state == SYNC_SENT_REQUEST)
-	    host->device[host->SCpnt->target].sync_state = SYNC_NEGOCIATE;
+	if (host->device[host->SCpnt->device->id].sync_state == SYNC_SENT_REQUEST)
+	    host->device[host->SCpnt->device->id].sync_state = SYNC_NEGOCIATE;
 #endif
 
 	/*
@@ -1591,7 +1591,7 @@
 	    printk(KERN_NOTICE "scsi%d.%c: disabling tagged queueing\n",
 		    host->host->host_no, acornscsi_target(host));
 	    host->SCpnt->device->tagged_queue = 0;
-	    set_bit(host->SCpnt->target * 8 + host->SCpnt->lun, host->busyluns);
+	    set_bit(host->SCpnt->device->id * 8 + host->SCpnt->device->lun, host->busyluns);
 	    break;
 #endif
 	case EXTENDED_MESSAGE | (EXTENDED_SDTR << 8):
@@ -1600,9 +1600,9 @@
 	     */
 	    printk(KERN_NOTICE "scsi%d.%c: Using asynchronous transfer\n",
 		    host->host->host_no, acornscsi_target(host));
-	    host->device[host->SCpnt->target].sync_xfer = SYNCHTRANSFER_2DBA;
-	    host->device[host->SCpnt->target].sync_state = SYNC_ASYNCHRONOUS;
-	    sbic_arm_write(host->scsi.io_port, SYNCHTRANSFER, host->device[host->SCpnt->target].sync_xfer);
+	    host->device[host->SCpnt->device->id].sync_xfer = SYNCHTRANSFER_2DBA;
+	    host->device[host->SCpnt->device->id].sync_state = SYNC_ASYNCHRONOUS;
+	    sbic_arm_write(host->scsi.io_port, SYNCHTRANSFER, host->device[host->SCpnt->device->id].sync_xfer);
 	    break;
 
 	default:
@@ -1625,18 +1625,18 @@
 	switch (message[2]) {
 #ifdef CONFIG_SCSI_ACORNSCSI_SYNC
 	case EXTENDED_SDTR:
-	    if (host->device[host->SCpnt->target].sync_state == SYNC_SENT_REQUEST) {
+	    if (host->device[host->SCpnt->device->id].sync_state == SYNC_SENT_REQUEST) {
 		/*
 		 * We requested synchronous transfers.  This isn't quite right...
 		 * We can only say if this succeeded if we proceed on to execute the
 		 * command from this message.  If we get a MESSAGE PARITY ERROR,
 		 * and the target retries fail, then we fallback to asynchronous mode
 		 */
-		host->device[host->SCpnt->target].sync_state = SYNC_COMPLETED;
+		host->device[host->SCpnt->device->id].sync_state = SYNC_COMPLETED;
 		printk(KERN_NOTICE "scsi%d.%c: Using synchronous transfer, offset %d, %d ns\n",
 			host->host->host_no, acornscsi_target(host),
 			message[4], message[3] * 4);
-		host->device[host->SCpnt->target].sync_xfer =
+		host->device[host->SCpnt->device->id].sync_xfer =
 			calc_sync_xfer(message[3] * 4, message[4]);
 	    } else {
 		unsigned char period, length;
@@ -1649,10 +1649,10 @@
 		length = min_t(unsigned int, message[4], sdtr_size);
 		msgqueue_addmsg(&host->scsi.msgs, 5, EXTENDED_MESSAGE, 3,
 				 EXTENDED_SDTR, period, length);
-		host->device[host->SCpnt->target].sync_xfer =
+		host->device[host->SCpnt->device->id].sync_xfer =
 			calc_sync_xfer(period * 4, length);
 	    }
-	    sbic_arm_write(host->scsi.io_port, SYNCHTRANSFER, host->device[host->SCpnt->target].sync_xfer);
+	    sbic_arm_write(host->scsi.io_port, SYNCHTRANSFER, host->device[host->SCpnt->device->id].sync_xfer);
 	    break;
 #else
 	    /* We do not accept synchronous transfers.  Respond with a
@@ -1738,8 +1738,8 @@
 #endif
 
     msgqueue_addmsg(&host->scsi.msgs, 1,
-		     IDENTIFY(host->device[host->SCpnt->target].disconnect_ok,
-			     host->SCpnt->lun));
+		     IDENTIFY(host->device[host->SCpnt->device->id].disconnect_ok,
+			     host->SCpnt->device->lun));
 
 #if 0
     /* does the device need the current command aborted */
@@ -1764,8 +1764,8 @@
 #endif
 
 #ifdef CONFIG_SCSI_ACORNSCSI_SYNC
-    if (host->device[host->SCpnt->target].sync_state == SYNC_NEGOCIATE) {
-	host->device[host->SCpnt->target].sync_state = SYNC_SENT_REQUEST;
+    if (host->device[host->SCpnt->device->id].sync_state == SYNC_NEGOCIATE) {
+	host->device[host->SCpnt->device->id].sync_state = SYNC_SENT_REQUEST;
 	msgqueue_addmsg(&host->scsi.msgs, 5,
 			 EXTENDED_MESSAGE, 3, EXTENDED_SDTR,
 			 sdtr_period / 4, sdtr_size);
@@ -1792,7 +1792,7 @@
 
     residual = host->SCpnt->request_bufflen - host->scsi.SCp.scsi_xferred;
 
-    sbic_arm_write(host->scsi.io_port, SYNCHTRANSFER, host->device[host->SCpnt->target].sync_xfer);
+    sbic_arm_write(host->scsi.io_port, SYNCHTRANSFER, host->device[host->SCpnt->device->id].sync_xfer);
     sbic_arm_writenext(host->scsi.io_port, residual >> 16);
     sbic_arm_writenext(host->scsi.io_port, residual >> 8);
     sbic_arm_writenext(host->scsi.io_port, residual);
@@ -1828,7 +1828,7 @@
     if (host->SCpnt && !host->scsi.disconnectable) {
 	printk(KERN_ERR "scsi%d.%d: reconnected while command in "
 		"progress to target %d?\n",
-		host->host->host_no, target, host->SCpnt->target);
+		host->host->host_no, target, host->SCpnt->device->id);
 	host->SCpnt = NULL;
     }
 
@@ -1839,7 +1839,7 @@
     host->scsi.reconnected.tag = 0;
 
     if (host->scsi.disconnectable && host->SCpnt &&
-	host->SCpnt->target == target && host->SCpnt->lun == lun)
+	host->SCpnt->device->id == target && host->SCpnt->device->lun == lun)
 	ok = 1;
 
     if (!ok && queue_probetgtlun(&host->queues.disconnected, target, lun))
@@ -1876,9 +1876,9 @@
 {
     if (host->scsi.disconnectable && host->SCpnt) {
 	host->scsi.disconnectable = 0;
-	if (host->SCpnt->target == host->scsi.reconnected.target &&
-	    host->SCpnt->lun	== host->scsi.reconnected.lun &&
-	    host->SCpnt->tag	== host->scsi.reconnected.tag) {
+	if (host->SCpnt->device->id  == host->scsi.reconnected.target &&
+	    host->SCpnt->device->lun == host->scsi.reconnected.lun &&
+	    host->SCpnt->tag         == host->scsi.reconnected.tag) {
 #if (DEBUG & (DEBUG_QUEUES|DEBUG_DISCON))
 	    DBG(host->SCpnt, printk("scsi%d.%c: reconnected",
 		    host->host->host_no, acornscsi_target(host)));
@@ -1992,7 +1992,7 @@
     ADD_STATUS(8, ssr, host->scsi.phase, in_irq);
 
     if (host->SCpnt && !host->scsi.disconnectable)
-	ADD_STATUS(host->SCpnt->target, ssr, host->scsi.phase, in_irq);
+	ADD_STATUS(host->SCpnt->device->id, ssr, host->scsi.phase, in_irq);
 
     switch (ssr) {
     case 0x00:				/* reset state - not advanced			*/
@@ -2030,7 +2030,7 @@
 		break;
 	    ssr = sbic_arm_read(host->scsi.io_port, SSR);
 	    ADD_STATUS(8, ssr, host->scsi.phase, 1);
-	    ADD_STATUS(host->SCpnt->target, ssr, host->scsi.phase, 1);
+	    ADD_STATUS(host->SCpnt->device->id, ssr, host->scsi.phase, 1);
 	    goto connected;
 	    
 	case 0x42:			/* select timed out				*/
@@ -2049,7 +2049,7 @@
 	default:
 	    printk(KERN_ERR "scsi%d.%c: PHASE_CONNECTING, SSR %02X?\n",
 		    host->host->host_no, acornscsi_target(host), ssr);
-	    acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->target : 8);
+	    acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->device->id : 8);
 	    acornscsi_abortcmd(host, host->SCpnt->tag);
 	}
 	return INTR_PROCESSING;
@@ -2085,7 +2085,7 @@
 	default:
 	    printk(KERN_ERR "scsi%d.%c: PHASE_CONNECTED, SSR %02X?\n",
 		    host->host->host_no, acornscsi_target(host), ssr);
-	    acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->target : 8);
+	    acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->device->id : 8);
 	    acornscsi_abortcmd(host, host->SCpnt->tag);
 	}
 	return INTR_PROCESSING;
@@ -2123,7 +2123,7 @@
 	default:
 	    printk(KERN_ERR "scsi%d.%c: PHASE_MSGOUT, SSR %02X?\n",
 		    host->host->host_no, acornscsi_target(host), ssr);
-	    acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->target : 8);
+	    acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->device->id : 8);
 	}
 	return INTR_PROCESSING;
 
@@ -2168,7 +2168,7 @@
 	default:
 	    printk(KERN_ERR "scsi%d.%c: PHASE_COMMAND, SSR %02X?\n",
 		    host->host->host_no, acornscsi_target(host), ssr);
-	    acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->target : 8);
+	    acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->device->id : 8);
 	}
 	return INTR_PROCESSING;
 
@@ -2181,7 +2181,7 @@
 	} else {
 	    printk(KERN_ERR "scsi%d.%c: PHASE_DISCONNECT, SSR %02X instead of disconnect?\n",
 		    host->host->host_no, acornscsi_target(host), ssr);
-	    acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->target : 8);
+	    acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->device->id : 8);
 	}
 	return INTR_NEXT_COMMAND;
 
@@ -2191,7 +2191,7 @@
 	else {
 	    printk(KERN_ERR "scsi%d.%c: PHASE_IDLE, SSR %02X while idle?\n",
 		    host->host->host_no, acornscsi_target(host), ssr);
-	    acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->target : 8);
+	    acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->device->id : 8);
 	}
 	return INTR_PROCESSING;
 
@@ -2206,7 +2206,7 @@
 	 */
 	if (ssr != 0x8f && !acornscsi_reconnect_finish(host))
 	    return INTR_IDLE;
-	ADD_STATUS(host->SCpnt->target, ssr, host->scsi.phase, in_irq);
+	ADD_STATUS(host->SCpnt->device->id, ssr, host->scsi.phase, in_irq);
 	switch (ssr) {
 	case 0x88:			/* data out phase				*/
 					/* -> PHASE_DATAOUT				*/
@@ -2251,7 +2251,7 @@
 	default:
 	    printk(KERN_ERR "scsi%d.%c: PHASE_RECONNECTED, SSR %02X after reconnect?\n",
 		    host->host->host_no, acornscsi_target(host), ssr);
-	    acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->target : 8);
+	    acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->device->id : 8);
 	}
 	return INTR_PROCESSING;
 
@@ -2300,7 +2300,7 @@
 	default:
 	    printk(KERN_ERR "scsi%d.%c: PHASE_DATAIN, SSR %02X?\n",
 		    host->host->host_no, acornscsi_target(host), ssr);
-	    acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->target : 8);
+	    acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->device->id : 8);
 	}
 	return INTR_PROCESSING;
 
@@ -2352,7 +2352,7 @@
 	default:
 	    printk(KERN_ERR "scsi%d.%c: PHASE_DATAOUT, SSR %02X?\n",
 		    host->host->host_no, acornscsi_target(host), ssr);
-	    acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->target : 8);
+	    acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->device->id : 8);
 	}
 	return INTR_PROCESSING;
 
@@ -2373,7 +2373,7 @@
 	default:
 	    printk(KERN_ERR "scsi%d.%c: PHASE_STATUSIN, SSR %02X instead of MESSAGE_IN?\n",
 		    host->host->host_no, acornscsi_target(host), ssr);
-	    acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->target : 8);
+	    acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->device->id : 8);
 	}
 	return INTR_PROCESSING;
 
@@ -2396,14 +2396,14 @@
 	case 0x85:
 	    printk("scsi%d.%c: strange message in disconnection\n",
 		host->host->host_no, acornscsi_target(host));
-	    acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->target : 8);
+	    acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->device->id : 8);
 	    acornscsi_done(host, &host->SCpnt, DID_ERROR);
 	    break;
 
 	default:
 	    printk(KERN_ERR "scsi%d.%c: PHASE_MSGIN, SSR %02X after message in?\n",
 		    host->host->host_no, acornscsi_target(host), ssr);
-	    acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->target : 8);
+	    acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->device->id : 8);
 	}
 	return INTR_PROCESSING;
 
@@ -2421,7 +2421,7 @@
 	default:
 	    printk(KERN_ERR "scsi%d.%c: PHASE_DONE, SSR %02X instead of disconnect?\n",
 		    host->host->host_no, acornscsi_target(host), ssr);
-	    acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->target : 8);
+	    acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->device->id : 8);
 	}
 	return INTR_PROCESSING;
 
@@ -2447,14 +2447,14 @@
 	default:
 	    printk(KERN_ERR "scsi%d.%c: PHASE_ABORTED, SSR %02X?\n",
 		    host->host->host_no, acornscsi_target(host), ssr);
-	    acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->target : 8);
+	    acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->device->id : 8);
 	}
 	return INTR_PROCESSING;
 
     default:
 	printk(KERN_ERR "scsi%d.%c: unknown driver phase %d\n",
 		host->host->host_no, acornscsi_target(host), ssr);
-	acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->target : 8);
+	acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->device->id : 8);
     }
     return INTR_PROCESSING;
 }
@@ -2531,9 +2531,9 @@
     }
 
 #if (DEBUG & DEBUG_NO_WRITE)
-    if (acornscsi_cmdtype(SCpnt->cmnd[0]) == CMD_WRITE && (NO_WRITE & (1 << SCpnt->target))) {
+    if (acornscsi_cmdtype(SCpnt->cmnd[0]) == CMD_WRITE && (NO_WRITE & (1 << SCpnt->device->id))) {
 	printk(KERN_CRIT "scsi%d.%c: WRITE attempted with NO_WRITE flag set\n",
-	    SCpnt->host->host_no, '0' + SCpnt->target);
+	    SCpnt->host->host_no, '0' + SCpnt->device->id);
 	SCpnt->result = DID_NO_CONNECT << 16;
 	done(SCpnt);
 	return 0;
@@ -2708,7 +2708,7 @@
 
 		printk(KERN_WARNING "acornscsi_abort: ");
 		print_sbic_status(asr, ssr, host->scsi.phase);
-		acornscsi_dumplog(host, SCpnt->target);
+		acornscsi_dumplog(host, SCpnt->device->id);
 	}
 #endif
 
@@ -2724,7 +2724,7 @@
 //#if (DEBUG & DEBUG_ABORT)
 		printk("clear ");
 //#endif
-		clear_bit(SCpnt->target * 8 + SCpnt->lun, host->busyluns);
+		clear_bit(SCpnt->device->id * 8 + SCpnt->device->lun, host->busyluns);
 
 	/*
 	 * We found the command, and cleared it out.  Either
@@ -2758,7 +2758,7 @@
 	 */
 	default:
 	case res_not_running:
-		acornscsi_dumplog(host, SCpnt->target);
+		acornscsi_dumplog(host, SCpnt->device->id);
 #if (DEBUG & DEBUG_ABORT)
 		result = SCSI_ABORT_SNOOZE;
 #else
@@ -2796,7 +2796,7 @@
 
 	printk(KERN_WARNING "acornscsi_reset: ");
 	print_sbic_status(asr, ssr, host->scsi.phase);
-	acornscsi_dumplog(host, SCpnt->target);
+	acornscsi_dumplog(host, SCpnt->device->id);
     }
 #endif
 
diff -Nru a/drivers/acorn/scsi/fas216.c b/drivers/acorn/scsi/fas216.c
--- a/drivers/acorn/scsi/fas216.c	Mon Feb 17 14:57:27 2003
+++ b/drivers/acorn/scsi/fas216.c	Mon Feb 17 14:57:27 2003
@@ -96,6 +96,47 @@
 
 static int level_mask = LOG_ERROR;
 
+static int __init fas216_log_setup(char *str)
+{
+	char *s;
+
+	level_mask = 0;
+
+	while ((s = strsep(&str, ",")) != NULL) {
+		switch (s[0]) {
+		case 'a':
+			if (strcmp(s, "all") == 0)
+				level_mask |= -1;
+			break;
+		case 'b':
+			if (strncmp(s, "bus", 3) == 0)
+				level_mask |= LOG_BUSSERVICE;
+			if (strncmp(s, "buf", 3) == 0)
+				level_mask |= LOG_BUFFER;
+			break;
+		case 'c':
+			level_mask |= LOG_CONNECT;
+			break;
+		case 'e':
+			level_mask |= LOG_ERROR;
+			break;
+		case 'm':
+			level_mask |= LOG_MESSAGES;
+			break;
+		case 'n':
+			if (strcmp(s, "none") == 0)
+				level_mask = 0;
+			break;
+		case 's':
+			level_mask |= LOG_FUNCTIONDONE;
+			break;
+		}
+	}
+	return 1;
+}
+
+__setup("fas216_logging=", fas216_log_setup);
+
 static inline unsigned char fas216_readb(FAS216_Info *info, unsigned int reg)
 {
 	unsigned int off = reg << info->scsi.io_shift;
@@ -244,7 +285,7 @@
 static char fas216_target(FAS216_Info *info)
 {
 	if (info->SCpnt)
-		return '0' + info->SCpnt->target;
+		return '0' + info->SCpnt->device->id;
 	else
 		return 'H';
 }
@@ -267,7 +308,7 @@
 		return;
 
 	va_start(args, fmt);
-	fas216_do_log(info, '0' + SCpnt->target, fmt, args);
+	fas216_do_log(info, '0' + SCpnt->device->id, fmt, args);
 	va_end(args);
 
 	printk(" CDB: ");
@@ -495,7 +536,7 @@
  */
 static void fas216_handlesync(FAS216_Info *info, char *msg)
 {
-	struct fas216_device *dev = &info->device[info->SCpnt->target];
+	struct fas216_device *dev = &info->device[info->SCpnt->device->id];
 	enum { sync, async, none, reject } res = none;
 
 #ifdef SCSI2_SYNC
@@ -578,7 +619,7 @@
 		dev->period = msg[3];
 		dev->sof    = msg[4];
 		dev->stp    = fas216_syncperiod(info, msg[3] * 4);
-		fas216_set_sync(info, info->SCpnt->target);
+		fas216_set_sync(info, info->SCpnt->device->id);
 		break;
 
 	case reject:
@@ -591,7 +632,7 @@
 		dev->period = info->ifcfg.asyncperiod / 4;
 		dev->sof    = 0;
 		dev->stp    = info->scsi.async_stp;
-		fas216_set_sync(info, info->SCpnt->target);
+		fas216_set_sync(info, info->SCpnt->device->id);
 		break;
 
 	case none:
@@ -608,7 +649,7 @@
  */
 static void fas216_handlewide(FAS216_Info *info, char *msg)
 {
-	struct fas216_device *dev = &info->device[info->SCpnt->target];
+	struct fas216_device *dev = &info->device[info->SCpnt->device->id];
 	enum { wide, bit8, none, reject } res = none;
 
 #ifdef SCSI2_WIDE
@@ -725,7 +766,7 @@
 		bytes_transferred -= SCp->this_residual;
 		if (!next_SCp(SCp) && bytes_transferred) {
 			printk(KERN_WARNING "scsi%d.%c: out of buffers\n",
-				info->host->host_no, '0' + info->SCpnt->target);
+				info->host->host_no, '0' + info->SCpnt->device->id);
 			return;
 		}
 	}
@@ -848,7 +889,7 @@
 	 * use DMA mode.  If we are using asynchronous transfers, we may
 	 * use DMA mode or PIO mode.
 	 */
-	if (info->device[info->SCpnt->target].sof)
+	if (info->device[info->SCpnt->device->id].sof)
 		dmatype = fasdma_real_all;
 	else
 		dmatype = fasdma_pio;
@@ -1023,10 +1064,10 @@
 		info->origSCpnt = SCpnt;
 		info->SCpnt = NULL;
 
-		if (info->device[SCpnt->target].wide_state == neg_inprogress)
-			info->device[SCpnt->target].wide_state = neg_wait;
-		if (info->device[SCpnt->target].sync_state == neg_inprogress)
-			info->device[SCpnt->target].sync_state = neg_wait;
+		if (info->device[SCpnt->device->id].wide_state == neg_inprogress)
+			info->device[SCpnt->device->id].wide_state = neg_wait;
+		if (info->device[SCpnt->device->id].sync_state == neg_inprogress)
+			info->device[SCpnt->device->id].sync_state = neg_wait;
 	}
 
 	fas216_log(info, LOG_CONNECT, "reconnect phase=%02X", info->scsi.phase);
@@ -1073,7 +1114,7 @@
 
 	ok = 0;
 	if (info->scsi.disconnectable && info->SCpnt &&
-	    info->SCpnt->target == target && info->SCpnt->lun == identify_msg)
+	    info->SCpnt->device->id == target && info->SCpnt->device->lun == identify_msg)
 		ok = 1;
 
 	if (!ok && queue_probetgtlun(&info->queues.disconnected, target, identify_msg))
@@ -1118,15 +1159,15 @@
 	fas216_checkmagic(info);
 
 	fas216_log(info, LOG_CONNECT, "Connected: %1x %1x %02x, reconnected: %1x %1x %02x",
-		info->SCpnt->target, info->SCpnt->lun, info->SCpnt->tag,
+		info->SCpnt->device->id, info->SCpnt->device->lun, info->SCpnt->tag,
 		info->scsi.reconnected.target, info->scsi.reconnected.lun,
 		info->scsi.reconnected.tag);
 
 	if (info->scsi.disconnectable && info->SCpnt) {
 		info->scsi.disconnectable = 0;
-		if (info->SCpnt->target == info->scsi.reconnected.target &&
-		    info->SCpnt->lun    == info->scsi.reconnected.lun &&
-		    info->SCpnt->tag    == info->scsi.reconnected.tag) {
+		if (info->SCpnt->device->id  == info->scsi.reconnected.target &&
+		    info->SCpnt->device->lun == info->scsi.reconnected.lun &&
+		    info->SCpnt->tag         == info->scsi.reconnected.tag) {
 			fas216_log(info, LOG_CONNECT, "reconnected");
 		} else {
 			queue_add_cmd_tail(&info->queues.disconnected, info->SCpnt);
@@ -1617,13 +1658,13 @@
 		 * set of messages.  If we have more than one byte to
 		 * send, we need to assert ATN again.
 		 */
-		if (info->device[info->SCpnt->target].parity_check) {
+		if (info->device[info->SCpnt->device->id].parity_check) {
 			/*
 			 * We were testing... good, the device
 			 * supports parity checking.
 			 */
-			info->device[info->SCpnt->target].parity_check = 0;
-			info->device[info->SCpnt->target].parity_enabled = 1;
+			info->device[info->SCpnt->device->id].parity_check = 0;
+			info->device[info->SCpnt->device->id].parity_enabled = 1;
 			fas216_writeb(info, REG_CNTL1, info->scsi.cfg[0]);
 		}
 
@@ -1831,11 +1872,11 @@
 	fas216_cmd(info, CMD_FLUSHFIFO);
 
 	/* load bus-id and timeout */
-	fas216_writeb(info, REG_SDID, BUSID(SCpnt->target));
+	fas216_writeb(info, REG_SDID, BUSID(SCpnt->device->id));
 	fas216_writeb(info, REG_STIM, info->ifcfg.select_timeout);
 
 	/* synchronous transfers */
-	fas216_set_sync(info, SCpnt->target);
+	fas216_set_sync(info, SCpnt->device->id);
 
 	tot_msglen = msgqueue_msglength(&info->scsi.msgs);
 
@@ -1845,7 +1886,7 @@
 		int msgnr = 0, i;
 
 		printk("scsi%d.%c: message out: ",
-			info->host->host_no, '0' + SCpnt->target);
+			info->host->host_no, '0' + SCpnt->device->id);
 		while ((msg = msgqueue_getmsg(&info->scsi.msgs, msgnr++)) != NULL) {
 			printk("{ ");
 			for (i = 0; i < msg->length; i++)
@@ -1923,7 +1964,7 @@
 	info->SCpnt = SCpnt;
 	info->dma.transfer_type = fasdma_none;
 
-	if (parity_test(info, SCpnt->target))
+	if (parity_test(info, SCpnt->device->id))
 		fas216_writeb(info, REG_CNTL1, info->scsi.cfg[0] | CNTL1_PTE);
 	else
 		fas216_writeb(info, REG_CNTL1, info->scsi.cfg[0]);
@@ -1932,13 +1973,13 @@
 	 * Don't allow request sense commands to disconnect.
 	 */
 	disconnect_ok = SCpnt->cmnd[0] != REQUEST_SENSE &&
-			info->device[SCpnt->target].disconnect_ok;
+			info->device[SCpnt->device->id].disconnect_ok;
 
 	/*
 	 * build outgoing message bytes
 	 */
 	msgqueue_flush(&info->scsi.msgs);
-	msgqueue_addmsg(&info->scsi.msgs, 1, IDENTIFY(disconnect_ok, SCpnt->lun));
+	msgqueue_addmsg(&info->scsi.msgs, 1, IDENTIFY(disconnect_ok, SCpnt->device->lun));
 
 	/*
 	 * add tag message if required
@@ -1948,8 +1989,8 @@
 
 	do {
 #ifdef SCSI2_WIDE
-		if (info->device[SCpnt->target].wide_state == neg_wait) {
-			info->device[SCpnt->target].wide_state = neg_inprogress;
+		if (info->device[SCpnt->device->id].wide_state == neg_wait) {
+			info->device[SCpnt->device->id].wide_state = neg_inprogress;
 			msgqueue_addmsg(&info->scsi.msgs, 4,
 					EXTENDED_MESSAGE, 2, EXTENDED_WDTR,
 					info->ifcfg.wide_max_size);
@@ -1957,11 +1998,11 @@
 		}
 #endif
 #ifdef SCSI2_SYNC
-		if ((info->device[SCpnt->target].sync_state == neg_wait ||
-		     info->device[SCpnt->target].sync_state == neg_complete) &&
+		if ((info->device[SCpnt->device->id].sync_state == neg_wait ||
+		     info->device[SCpnt->device->id].sync_state == neg_complete) &&
 		    (SCpnt->cmnd[0] == REQUEST_SENSE ||
 		     SCpnt->cmnd[0] == INQUIRY)) {
-			info->device[SCpnt->target].sync_state = neg_inprogress;
+			info->device[SCpnt->device->id].sync_state = neg_inprogress;
 			msgqueue_addmsg(&info->scsi.msgs, 5,
 					EXTENDED_MESSAGE, 3, EXTENDED_SDTR,
 					1000 / info->ifcfg.clockrate,
@@ -1988,7 +2029,7 @@
 			SCpnt->tag = SCpnt->device->current_tag;
 	} else
 #endif
-		set_bit(SCpnt->target * 8 + SCpnt->lun, info->busyluns);
+		set_bit(SCpnt->device->id * 8 + SCpnt->device->lun, info->busyluns);
 
 	info->stats.removes += 1;
 	switch (SCpnt->cmnd[0]) {
@@ -2033,11 +2074,11 @@
 	fas216_cmd(info, CMD_FLUSHFIFO);
 
 	/* load bus-id and timeout */
-	fas216_writeb(info, REG_SDID, BUSID(SCpnt->target));
+	fas216_writeb(info, REG_SDID, BUSID(SCpnt->device->id));
 	fas216_writeb(info, REG_STIM, info->ifcfg.select_timeout);
 
 	/* synchronous transfers */
-	fas216_set_sync(info, SCpnt->target);
+	fas216_set_sync(info, SCpnt->device->id);
 
 	msg = msgqueue_getmsg(&info->scsi.msgs, 0);
 
@@ -2102,7 +2143,7 @@
 	if (info->scsi.disconnectable && info->SCpnt) {
 		fas216_log(info, LOG_CONNECT,
 			"moved command for %d to disconnected queue",
-			info->SCpnt->target);
+			info->SCpnt->device->id);
 		queue_add_cmd_tail(&info->queues.disconnected, info->SCpnt);
 		info->scsi.disconnectable = 0;
 		info->SCpnt = NULL;
@@ -2155,7 +2196,7 @@
 static void
 fas216_rq_sns_done(FAS216_Info *info, Scsi_Cmnd *SCpnt, unsigned int result)
 {
-	fas216_log_target(info, LOG_CONNECT, SCpnt->target,
+	fas216_log_target(info, LOG_CONNECT, SCpnt->device->id,
 		   "request sense complete, result=0x%04x%02x%02x",
 		   result, SCpnt->SCp.Message, SCpnt->SCp.Status);
 
@@ -2166,7 +2207,7 @@
 		 * confuse the higher levels.
 		 */
 		memset(SCpnt->sense_buffer, 0, sizeof(SCpnt->sense_buffer));
-//printk("scsi%d.%c: sense buffer: ", info->host->host_no, '0' + SCpnt->target);
+//printk("scsi%d.%c: sense buffer: ", info->host->host_no, '0' + SCpnt->device->id);
 //{ int i; for (i = 0; i < 32; i++) printk("%02x ", SCpnt->sense_buffer[i]); printk("\n"); }
 	/*
 	 * Note that we don't set SCpnt->result, since that should
@@ -2235,7 +2276,7 @@
 		default:
 			printk(KERN_ERR "scsi%d.%c: incomplete data transfer "
 				"detected: res=%08X ptr=%p len=%X CDB: ",
-				info->host->host_no, '0' + SCpnt->target,
+				info->host->host_no, '0' + SCpnt->device->id,
 				SCpnt->result, info->scsi.SCp.ptr,
 				info->scsi.SCp.this_residual);
 			print_command(SCpnt->cmnd);
@@ -2259,11 +2300,11 @@
 	if (SCpnt->cmnd[0] == REQUEST_SENSE)
 		goto done;
 
-	fas216_log_target(info, LOG_CONNECT, SCpnt->target,
+	fas216_log_target(info, LOG_CONNECT, SCpnt->device->id,
 			  "requesting sense");
 	memset(SCpnt->cmnd, 0, sizeof (SCpnt->cmnd));
 	SCpnt->cmnd[0] = REQUEST_SENSE;
-	SCpnt->cmnd[1] = SCpnt->lun << 5;
+	SCpnt->cmnd[1] = SCpnt->device->lun << 5;
 	SCpnt->cmnd[4] = sizeof(SCpnt->sense_buffer);
 	SCpnt->cmd_len = COMMAND_SIZE(SCpnt->cmnd[0]);
 	SCpnt->SCp.buffer = NULL;
@@ -2285,7 +2326,7 @@
 	 */
 	if (info->reqSCpnt)
 		printk(KERN_WARNING "scsi%d.%c: loosing request command\n",
-			info->host->host_no, '0' + SCpnt->target);
+			info->host->host_no, '0' + SCpnt->device->id);
 	info->reqSCpnt = SCpnt;
 }
 
@@ -2324,7 +2365,7 @@
 	if (info->scsi.SCp.ptr && info->scsi.SCp.this_residual == 0) {
 		printk("scsi%d.%c: zero bytes left to transfer, but "
 		       "buffer pointer still valid: ptr=%p len=%08x CDB: ",
-		       info->host->host_no, '0' + SCpnt->target,
+		       info->host->host_no, '0' + SCpnt->device->id,
 		       info->scsi.SCp.ptr, info->scsi.SCp.this_residual);
 		info->scsi.SCp.ptr = NULL;
 		print_command(SCpnt->cmnd);
@@ -2335,8 +2376,8 @@
 	 * the sense information, fas216_kick will re-assert the busy
 	 * status.
 	 */
-	info->device[SCpnt->target].parity_check = 0;
-	clear_bit(SCpnt->target * 8 + SCpnt->lun, info->busyluns);
+	info->device[SCpnt->device->id].parity_check = 0;
+	clear_bit(SCpnt->device->id * 8 + SCpnt->device->lun, info->busyluns);
 
 	fn = (void (*)(FAS216_Info *, Scsi_Cmnd *, unsigned int))SCpnt->host_scribble;
 	fn(info, SCpnt, result);
@@ -2365,7 +2406,7 @@
  */
 int fas216_queue_command(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
 {
-	FAS216_Info *info = (FAS216_Info *)SCpnt->host->hostdata;
+	FAS216_Info *info = (FAS216_Info *)SCpnt->device->host->hostdata;
 	int result;
 
 	fas216_checkmagic(info);
@@ -2412,7 +2453,7 @@
  */
 static void fas216_internal_done(Scsi_Cmnd *SCpnt)
 {
-	FAS216_Info *info = (FAS216_Info *)SCpnt->host->hostdata;
+	FAS216_Info *info = (FAS216_Info *)SCpnt->device->host->hostdata;
 
 	fas216_checkmagic(info);
 
@@ -2429,7 +2470,7 @@
  */
 int fas216_command(Scsi_Cmnd *SCpnt)
 {
-	FAS216_Info *info = (FAS216_Info *)SCpnt->host->hostdata;
+	FAS216_Info *info = (FAS216_Info *)SCpnt->device->host->hostdata;
 
 	fas216_checkmagic(info);
 
@@ -2555,7 +2596,7 @@
 		 * been set.
 		 */
 		info->origSCpnt = NULL;
-		clear_bit(SCpnt->target * 8 + SCpnt->lun, info->busyluns);
+		clear_bit(SCpnt->device->id * 8 + SCpnt->device->lun, info->busyluns);
 		printk("waiting for execution ");
 		res = res_success;
 	} else
@@ -2574,7 +2615,7 @@
  */
 int fas216_eh_abort(Scsi_Cmnd *SCpnt)
 {
-	FAS216_Info *info = (FAS216_Info *)SCpnt->host->hostdata;
+	FAS216_Info *info = (FAS216_Info *)SCpnt->device->host->hostdata;
 	int result = FAILED;
 
 	fas216_checkmagic(info);
@@ -2631,9 +2672,9 @@
  */
 int fas216_eh_device_reset(Scsi_Cmnd *SCpnt)
 {
-	FAS216_Info *info = (FAS216_Info *)SCpnt->host->hostdata;
+	FAS216_Info *info = (FAS216_Info *)SCpnt->device->host->hostdata;
 	unsigned long flags;
-	int i, res = FAILED, target = SCpnt->target;
+	int i, res = FAILED, target = SCpnt->device->id;
 
 	fas216_log(info, LOG_ERROR, "device reset for target %d", target);
 
@@ -2647,7 +2688,7 @@
 		 * and we need a bus reset.
 		 */
 		if (info->SCpnt && !info->scsi.disconnectable &&
-		    info->SCpnt->target == SCpnt->target)
+		    info->SCpnt->device->id == SCpnt->device->id)
 			break;
 
 		/*
@@ -2658,9 +2699,9 @@
 		 */
 		queue_remove_all_target(&info->queues.issue, target);
 		queue_remove_all_target(&info->queues.disconnected, target);
-		if (info->origSCpnt && info->origSCpnt->target == target)
+		if (info->origSCpnt && info->origSCpnt->device->id == target)
 			info->origSCpnt = NULL;
-		if (info->reqSCpnt && info->reqSCpnt->target == target)
+		if (info->reqSCpnt && info->reqSCpnt->device->id == target)
 			info->reqSCpnt = NULL;
 		for (i = 0; i < 8; i++)
 			clear_bit(target * 8 + i, info->busyluns);
@@ -2712,7 +2753,7 @@
  */
 int fas216_eh_bus_reset(Scsi_Cmnd *SCpnt)
 {
-	FAS216_Info *info = (FAS216_Info *)SCpnt->host->hostdata;
+	FAS216_Info *info = (FAS216_Info *)SCpnt->device->host->hostdata;
 	unsigned long flags;
 	Scsi_Device *SDpnt;
 
@@ -2750,9 +2791,9 @@
 
 		queue_remove_all_target(&info->queues.issue, SDpnt->id);
 		queue_remove_all_target(&info->queues.disconnected, SDpnt->id);
-		if (info->origSCpnt && info->origSCpnt->target == SDpnt->id)
+		if (info->origSCpnt && info->origSCpnt->device->id == SDpnt->id)
 			info->origSCpnt = NULL;
-		if (info->reqSCpnt && info->reqSCpnt->target == SDpnt->id)
+		if (info->reqSCpnt && info->reqSCpnt->device->id == SDpnt->id)
 			info->reqSCpnt = NULL;
 		info->SCpnt = NULL;
 
@@ -2809,12 +2850,12 @@
  */
 int fas216_eh_host_reset(Scsi_Cmnd *SCpnt)
 {
-	FAS216_Info *info = (FAS216_Info *)SCpnt->host->hostdata;
+	FAS216_Info *info = (FAS216_Info *)SCpnt->device->host->hostdata;
 
 	fas216_checkmagic(info);
 
 	printk("scsi%d.%c: %s: resetting host\n",
-		info->host->host_no, '0' + SCpnt->target, __FUNCTION__);
+		info->host->host_no, '0' + SCpnt->device->id, __FUNCTION__);
 
 	/*
 	 * Reset the SCSI chip.
diff -Nru a/drivers/acorn/scsi/queue.c b/drivers/acorn/scsi/queue.c
--- a/drivers/acorn/scsi/queue.c	Mon Feb 17 14:57:26 2003
+++ b/drivers/acorn/scsi/queue.c	Mon Feb 17 14:57:26 2003
@@ -170,7 +170,7 @@
 	spin_lock_irqsave(&queue->queue_lock, flags);
 	list_for_each(l, &queue->head) {
 		QE_t *q = list_entry(l, QE_t, list);
-		if (!test_bit(q->SCpnt->target * 8 + q->SCpnt->lun, exclude)) {
+		if (!test_bit(q->SCpnt->device->id * 8 + q->SCpnt->device->lun, exclude)) {
 			SCpnt = __queue_remove(queue, l);
 			break;
 		}
@@ -217,7 +217,7 @@
 	spin_lock_irqsave(&queue->queue_lock, flags);
 	list_for_each(l, &queue->head) {
 		QE_t *q = list_entry(l, QE_t, list);
-		if (q->SCpnt->target == target && q->SCpnt->lun == lun &&
+		if (q->SCpnt->device->id == target && q->SCpnt->device->lun == lun &&
 		    q->SCpnt->tag == tag) {
 			SCpnt = __queue_remove(queue, l);
 			break;
@@ -243,7 +243,7 @@
 	spin_lock_irqsave(&queue->queue_lock, flags);
 	list_for_each(l, &queue->head) {
 		QE_t *q = list_entry(l, QE_t, list);
-		if (q->SCpnt->target == target)
+		if (q->SCpnt->device->id == target)
 			__queue_remove(queue, l);
 	}
 	spin_unlock_irqrestore(&queue->queue_lock, flags);
@@ -267,7 +267,7 @@
 	spin_lock_irqsave(&queue->queue_lock, flags);
 	list_for_each(l, &queue->head) {
 		QE_t *q = list_entry(l, QE_t, list);
-		if (q->SCpnt->target == target && q->SCpnt->lun == lun) {
+		if (q->SCpnt->device->id == target && q->SCpnt->device->lun == lun) {
 			found = 1;
 			break;
 		}
diff -Nru a/drivers/acorn/scsi/scsi.h b/drivers/acorn/scsi/scsi.h
--- a/drivers/acorn/scsi/scsi.h	Mon Feb 17 14:57:27 2003
+++ b/drivers/acorn/scsi/scsi.h	Mon Feb 17 14:57:27 2003
@@ -92,8 +92,8 @@
 
 		if (SCpnt->request_bufflen != len)
 			printk(KERN_WARNING "scsi%d.%c: bad request buffer "
-			       "length %d, should be %ld\n", SCpnt->host->host_no,
-			       '0' + SCpnt->target, SCpnt->request_bufflen, len);
+			       "length %d, should be %ld\n", SCpnt->device->host->host_no,
+			       '0' + SCpnt->device->id, SCpnt->request_bufflen, len);
 		SCpnt->request_bufflen = len;
 #endif
 	} else {
diff -Nru a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c
--- a/drivers/acpi/thermal.c	Mon Feb 17 14:57:28 2003
+++ b/drivers/acpi/thermal.c	Mon Feb 17 14:57:28 2003
@@ -436,7 +436,7 @@
 	envp[0] = "HOME=/";
 	envp[1] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin";
 	
-	call_usermodehelper(argv[0], argv, envp);
+	call_usermodehelper(argv[0], argv, envp, 0);
 
 	return_VALUE(0);
 }
diff -Nru a/drivers/base/hotplug.c b/drivers/base/hotplug.c
--- a/drivers/base/hotplug.c	Mon Feb 17 14:57:26 2003
+++ b/drivers/base/hotplug.c	Mon Feb 17 14:57:26 2003
@@ -114,7 +114,7 @@
 
 	pr_debug ("%s: %s %s %s %s %s %s\n", __FUNCTION__, argv [0], argv[1],
 		  envp[0], envp[1], envp[2], envp[3]);
-	retval = call_usermodehelper (argv [0], argv, envp);
+	retval = call_usermodehelper (argv [0], argv, envp, 0);
 	if (retval)
 		pr_debug ("%s - call_usermodehelper returned %d\n",
 			  __FUNCTION__, retval);
diff -Nru a/drivers/block/cciss.c b/drivers/block/cciss.c
--- a/drivers/block/cciss.c	Mon Feb 17 14:57:28 2003
+++ b/drivers/block/cciss.c	Mon Feb 17 14:57:28 2003
@@ -114,6 +114,9 @@
 
 static inline void addQ(CommandList_struct **Qptr, CommandList_struct *c);
 static void start_io( ctlr_info_t *h);
+static int sendcmd( __u8 cmd, int ctlr, void *buff, size_t size,
+	unsigned int use_unit_num, unsigned int log_unit, __u8 page_code,
+	unsigned char *scsi3addr);
 
 #ifdef CONFIG_PROC_FS
 static int cciss_proc_get_info(char *buffer, char **start, off_t offset, 
@@ -353,7 +356,7 @@
 	 * but I'm already using way to many device nodes to claim another one
 	 * for "raw controller".
 	 */
-	if (inode->i_bdev->bd_inode->i_size == 0) {
+	if (hba[ctlr]->drv[dsk].nr_blocks == 0) {
 		if (minor(inode->i_rdev) != 0)
 			return -ENXIO;
 		if (!capable(CAP_SYS_ADMIN))
@@ -809,6 +812,7 @@
 	/* zero out the disk size info */ 
 	h->drv[logvol].nr_blocks = 0;
 	h->drv[logvol].block_size = 0;
+	h->drv[logvol].cylinders = 0;
 	h->drv[logvol].LunID = 0;
 	return(0);
 }
@@ -1002,6 +1006,73 @@
         return(return_status);
 
 }
+static void cciss_geometry_inquiry(int ctlr, int logvol,
+			int withirq, unsigned int total_size,
+			unsigned int block_size, InquiryData_struct *inq_buff,
+			drive_info_struct *drv)
+{
+	int return_code;
+	memset(inq_buff, 0, sizeof(InquiryData_struct));
+	if (withirq)
+		return_code = sendcmd_withirq(CISS_INQUIRY, ctlr,
+			inq_buff, sizeof(*inq_buff), 1, logvol ,0xC1);
+	else
+		return_code = sendcmd(CISS_INQUIRY, ctlr, inq_buff,
+			sizeof(*inq_buff), 1, logvol ,0xC1, NULL);
+	if (return_code == IO_OK) {
+		if(inq_buff->data_byte[8] == 0xFF) {
+			printk(KERN_WARNING
+				"cciss: reading geometry failed, volume "
+				"does not support reading geometry\n");
+			drv->block_size = block_size;
+			drv->nr_blocks = total_size;
+			drv->heads = 255;
+			drv->sectors = 32; // Sectors per track
+			drv->cylinders = total_size / 255 / 32;
+		} else {
+			drv->block_size = block_size;
+			drv->nr_blocks = total_size;
+			drv->heads = inq_buff->data_byte[6];
+			drv->sectors = inq_buff->data_byte[7];
+			drv->cylinders = (inq_buff->data_byte[4] & 0xff) << 8;
+			drv->cylinders += inq_buff->data_byte[5];
+		}
+	} else { /* Get geometry failed */
+		printk(KERN_WARNING "cciss: reading geometry failed, "
+			"continuing with default geometry\n");
+		drv->block_size = block_size;
+		drv->nr_blocks = total_size;
+		drv->heads = 255;
+		drv->sectors = 32; // Sectors per track
+		drv->cylinders = total_size / 255 / 32;
+	}
+	printk(KERN_INFO "      heads= %d, sectors= %d, cylinders= %d\n\n",
+		drv->heads, drv->sectors, drv->cylinders);
+}
+static void
+cciss_read_capacity(int ctlr, int logvol, ReadCapdata_struct *buf,
+		int withirq, unsigned int *total_size, unsigned int *block_size)
+{
+	int return_code;
+	memset(buf, 0, sizeof(*buf));
+	if (withirq)
+		return_code = sendcmd_withirq(CCISS_READ_CAPACITY,
+			ctlr, buf, sizeof(*buf), 1, logvol, 0 );
+	else
+		return_code = sendcmd(CCISS_READ_CAPACITY,
+			ctlr, buf, sizeof(*buf), 1, logvol, 0, NULL );
+	if (return_code == IO_OK) {
+		*total_size = be32_to_cpu(*((__u32 *) &buf->total_size[0]))+1;
+		*block_size = be32_to_cpu(*((__u32 *) &buf->block_size[0]));
+	} else { /* read capacity command failed */
+		printk(KERN_WARNING "cciss: read capacity failed\n");
+		*total_size = 0;
+		*block_size = BLOCK_SIZE;
+	}
+	printk(KERN_INFO "      blocks= %d block_size= %d\n",
+		*total_size, *block_size);
+	return;
+}
 static int register_new_disk(int ctlr)
 {
         struct gendisk *disk;
@@ -1013,9 +1084,9 @@
 	int new_lun_index = 0;
 	int free_index_found = 0;
 	int free_index = 0;
-	ReportLunData_struct *ld_buff;
-	ReadCapdata_struct *size_buff;
-	InquiryData_struct *inq_buff;
+	ReportLunData_struct *ld_buff = NULL;
+	ReadCapdata_struct *size_buff = NULL;
+	InquiryData_struct *inq_buff = NULL;
 	int return_code;
 	int listlength = 0;
 	__u32 lunid = 0;
@@ -1030,26 +1101,14 @@
 	
 	ld_buff = kmalloc(sizeof(ReportLunData_struct), GFP_KERNEL);
 	if (ld_buff == NULL)
-	{
-		printk(KERN_ERR "cciss: out of memory\n");
-		return -1;
-	}
+		goto mem_msg;
 	memset(ld_buff, 0, sizeof(ReportLunData_struct));
 	size_buff = kmalloc(sizeof( ReadCapdata_struct), GFP_KERNEL);
         if (size_buff == NULL)
-        {
-                printk(KERN_ERR "cciss: out of memory\n");
-		kfree(ld_buff);
-                return -1;
-        }
+		goto mem_msg;
 	inq_buff = kmalloc(sizeof( InquiryData_struct), GFP_KERNEL);
         if (inq_buff == NULL)
-        {
-                printk(KERN_ERR "cciss: out of memory\n");
-                kfree(ld_buff);
-		kfree(size_buff);
-                return -1;
-        }
+		goto mem_msg;
 	
 	return_code = sendcmd_withirq(CISS_REPORT_LOG, ctlr, ld_buff, 
 			sizeof(ReportLunData_struct), 0, 0, 0 );
@@ -1068,7 +1127,7 @@
 		printk(KERN_WARNING "cciss: report logical volume"
 			" command failed\n");
 		listlength = 0;
-		return -1;
+		goto free_err;
 	}
 	num_luns = listlength / 8; // 8 bytes pre entry
 	if (num_luns > CISS_MAX_LUN)
@@ -1119,7 +1178,7 @@
 	 if (!new_lun_found)
 	 {
 		printk(KERN_WARNING "cciss:  New Logical Volume not found\n");
-		return -1;
+		goto free_err;
 	 }
 	 /* Now find the free index 	*/
 	for(i=0; i <CISS_MAX_LUN; i++)
@@ -1140,7 +1199,7 @@
 	if (!free_index_found)
 	{
 		printk(KERN_WARNING "cciss: unable to find free slot for disk\n");
-                return -1;
+		goto free_err;
          }
 
 	logvol = free_index;
@@ -1148,118 +1207,49 @@
 		/* there could be gaps in lun numbers, track hightest */
 	if(hba[ctlr]->highest_lun < lunid)
 		hba[ctlr]->highest_lun = logvol;
-		
-	memset(size_buff, 0, sizeof(ReadCapdata_struct));
-	return_code = sendcmd_withirq(CCISS_READ_CAPACITY, ctlr, size_buff,
-		sizeof( ReadCapdata_struct), 1, logvol, 0 );
-	if (return_code == IO_OK)
-	{
-		total_size = (0xff & 
-			(unsigned int)(size_buff->total_size[0])) << 24;
-		total_size |= (0xff & 
-				(unsigned int)(size_buff->total_size[1])) << 16;
-		total_size |= (0xff & 
-				(unsigned int)(size_buff->total_size[2])) << 8;
-		total_size |= (0xff & (unsigned int)
-				(size_buff->total_size[3])); 
-		total_size++; // command returns highest block address
-
-		block_size = (0xff & 
-				(unsigned int)(size_buff->block_size[0])) << 24;
-               	block_size |= (0xff & 
-				(unsigned int)(size_buff->block_size[1])) << 16;
-               	block_size |= (0xff & 
-				(unsigned int)(size_buff->block_size[2])) << 8;
-               	block_size |= (0xff & 
-				(unsigned int)(size_buff->block_size[3]));
-	} else /* read capacity command failed */ 
-	{
-			printk(KERN_WARNING "cciss: read capacity failed\n");
-			total_size = 0;
-			block_size = BLOCK_SIZE;
-	}	
-	printk(KERN_INFO "      blocks= %u block_size= %d\n", 
-					total_size, block_size);
-	/* Execute the command to read the disk geometry */
-	memset(inq_buff, 0, sizeof(InquiryData_struct));
-	return_code = sendcmd_withirq(CISS_INQUIRY, ctlr, inq_buff,
-                	sizeof(InquiryData_struct), 1, logvol ,0xC1 );
-	if (return_code == IO_OK)
-		{
-			if(inq_buff->data_byte[8] == 0xFF)
-			{
-			   printk(KERN_WARNING "cciss: reading geometry failed, "
-				"volume does not support reading geometry\n");
-
-                           hba[ctlr]->drv[logvol].block_size = block_size;
-                           hba[ctlr]->drv[logvol].nr_blocks = total_size;
-                           hba[ctlr]->drv[logvol].heads = 255;
-                           hba[ctlr]->drv[logvol].sectors = 32; // Sectors per track
-                           hba[ctlr]->drv[logvol].cylinders = total_size / 255 / 32;
-                	} else
-			{
-
-		 	   hba[ctlr]->drv[logvol].block_size = block_size;
-                           hba[ctlr]->drv[logvol].nr_blocks = total_size;
-                           hba[ctlr]->drv[logvol].heads = 
-					inq_buff->data_byte[6]; 
-                           hba[ctlr]->drv[logvol].sectors = 
-					inq_buff->data_byte[7]; 
-			   hba[ctlr]->drv[logvol].cylinders = 
-					(inq_buff->data_byte[4] & 0xff) << 8;
-			   hba[ctlr]->drv[logvol].cylinders += 
-                                        inq_buff->data_byte[5];
-			}
-		}
-		else /* Get geometry failed */
-		{
-
-			printk(KERN_WARNING "cciss: reading geometry failed, "
-				"continuing with default geometry\n"); 
-
-			hba[ctlr]->drv[logvol].block_size = block_size;
-			hba[ctlr]->drv[logvol].nr_blocks = total_size;
-			hba[ctlr]->drv[logvol].heads = 255;
-			hba[ctlr]->drv[logvol].sectors = 32; // Sectors per track 
-			hba[ctlr]->drv[logvol].cylinders = total_size / 255 / 32;
-		}
-		printk(KERN_INFO "      heads= %d, sectors= %d, cylinders= %d\n\n",
-			hba[ctlr]->drv[logvol].heads, 
-			hba[ctlr]->drv[logvol].sectors,
-			hba[ctlr]->drv[logvol].cylinders);
+	cciss_read_capacity(ctlr, logvol, size_buff, 1,
+		&total_size, &block_size);
+	cciss_geometry_inquiry(ctlr, logvol, 1, total_size, block_size,
+			inq_buff, &hba[ctlr]->drv[logvol]);
 	hba[ctlr]->drv[logvol].usage_count = 0;
 	++hba[ctlr]->num_luns;
 	/* setup partitions per disk */
         disk = hba[ctlr]->gendisk[logvol];
 	set_capacity(disk, hba[ctlr]->drv[logvol].nr_blocks);
 	add_disk(disk);
-	
+freeret:
 	kfree(ld_buff);
 	kfree(size_buff);
 	kfree(inq_buff);
 	return (logvol);
+mem_msg:
+	printk(KERN_ERR "cciss: out of memory\n");
+free_err:
+	logvol = -1;
+	goto freeret;
 }
 /*
  *   Wait polling for a command to complete.
  *   The memory mapped FIFO is polled for the completion.
- *   Used only at init time, interrupts disabled.
+ *   Used only at init time, interrupts from the HBA are disabled.
  */
 static unsigned long pollcomplete(int ctlr)
 {
-        unsigned long done;
-        int i;
+	unsigned long done;
+	int i;
 
-        /* Wait (up to 2 seconds) for a command to complete */
+	/* Wait (up to 20 seconds) for a command to complete */
 
-        for (i = 200000; i > 0; i--) {
-                done = hba[ctlr]->access.command_completed(hba[ctlr]);
-                if (done == FIFO_EMPTY) {
-                        udelay(10);     /* a short fixed delay */
-                } else
-                        return (done);
-        }
-        /* Invalid address to tell caller we ran out of time */
-        return 1;
+	for (i = 20 * HZ; i > 0; i--) {
+		done = hba[ctlr]->access.command_completed(hba[ctlr]);
+		if (done == FIFO_EMPTY) {
+			set_current_state(TASK_UNINTERRUPTIBLE);
+			schedule_timeout(1);
+		} else
+			return (done);
+	}
+	/* Invalid address to tell caller we ran out of time */
+	return 1;
 }
 /*
  * Send a command to the controller, and wait for it to complete.  
@@ -2174,83 +2164,10 @@
 		ld_buff->LUN[i][0], ld_buff->LUN[i][1],ld_buff->LUN[i][2], 
 		ld_buff->LUN[i][3], hba[cntl_num]->drv[i].LunID);
 #endif /* CCISS_DEBUG */
-
-	  	memset(size_buff, 0, sizeof(ReadCapdata_struct));
-	  	return_code = sendcmd(CCISS_READ_CAPACITY, cntl_num, size_buff, 
-				sizeof( ReadCapdata_struct), 1, i, 0, NULL );
-	  	if (return_code == IO_OK)
-		{
-			total_size = (0xff & 
-				(unsigned int)(size_buff->total_size[0])) << 24;
-			total_size |= (0xff & 
-				(unsigned int)(size_buff->total_size[1])) << 16;
-			total_size |= (0xff & 
-				(unsigned int)(size_buff->total_size[2])) << 8;
-			total_size |= (0xff & (unsigned int)
-				(size_buff->total_size[3])); 
-			total_size++; // command returns highest block address
-
-			block_size = (0xff & 
-				(unsigned int)(size_buff->block_size[0])) << 24;
-                	block_size |= (0xff & 
-				(unsigned int)(size_buff->block_size[1])) << 16;
-                	block_size |= (0xff & 
-				(unsigned int)(size_buff->block_size[2])) << 8;
-                	block_size |= (0xff & 
-				(unsigned int)(size_buff->block_size[3]));
-		} else /* read capacity command failed */ 
-		{
-			printk(KERN_WARNING "cciss: read capacity failed\n");
-			total_size = 0;
-			block_size = BLOCK_SIZE;
-		}	
-		printk(KERN_INFO "      blocks= %d block_size= %d\n", 
-					total_size, block_size);
-
-		/* Execute the command to read the disk geometry */
-		memset(inq_buff, 0, sizeof(InquiryData_struct));
-		return_code = sendcmd(CISS_INQUIRY, cntl_num, inq_buff,
-                	sizeof(InquiryData_struct), 1, i ,0xC1, NULL );
-	  	if (return_code == IO_OK)
-		{
-			if(inq_buff->data_byte[8] == 0xFF)
-			{
-			   printk(KERN_WARNING "cciss: reading geometry failed, volume does not support reading geometry\n");
-
-                           hba[cntl_num]->drv[i].block_size = block_size;
-                           hba[cntl_num]->drv[i].nr_blocks = total_size;
-                           hba[cntl_num]->drv[i].heads = 255;
-                           hba[cntl_num]->drv[i].sectors = 32; // Sectors per track
-                           hba[cntl_num]->drv[i].cylinders = total_size / 255 / 32;                	} else
-			{
-
-		 	   hba[cntl_num]->drv[i].block_size = block_size;
-                           hba[cntl_num]->drv[i].nr_blocks = total_size;
-                           hba[cntl_num]->drv[i].heads = 
-					inq_buff->data_byte[6]; 
-                           hba[cntl_num]->drv[i].sectors = 
-					inq_buff->data_byte[7]; 
-			   hba[cntl_num]->drv[i].cylinders = 
-					(inq_buff->data_byte[4] & 0xff) << 8;
-			   hba[cntl_num]->drv[i].cylinders += 
-                                        inq_buff->data_byte[5];
-			}
-		}
-		else /* Get geometry failed */
-		{
-			printk(KERN_WARNING "cciss: reading geometry failed, continuing with default geometry\n"); 
-
-			hba[cntl_num]->drv[i].block_size = block_size;
-			hba[cntl_num]->drv[i].nr_blocks = total_size;
-			hba[cntl_num]->drv[i].heads = 255;
-			hba[cntl_num]->drv[i].sectors = 32; // Sectors per track 
-			hba[cntl_num]->drv[i].cylinders = total_size / 255 / 32;
-		}
-		printk(KERN_INFO "      heads= %d, sectors= %d, cylinders= %d\n\n",
-			hba[cntl_num]->drv[i].heads, 
-			hba[cntl_num]->drv[i].sectors,
-			hba[cntl_num]->drv[i].cylinders);
-
+		cciss_read_capacity(cntl_num, i, size_buff, 0,
+			&total_size, &block_size);
+		cciss_geometry_inquiry(cntl_num, i, 0, total_size, block_size,
+			inq_buff, &hba[cntl_num]->drv[i]);
 	}
 	kfree(ld_buff);
 	kfree(size_buff);
@@ -2408,7 +2325,7 @@
 
 	cciss_getgeometry(i);
 
-	cciss_find_non_disk_devices(i);	/* find our tape drives, if any */
+	cciss_scsi_setup(i);
 
 	/* Turn the interrupts on so we can service requests */
 	hba[i]->access.set_intr_mask(hba[i], CCISS_INTR_ON);
@@ -2446,9 +2363,6 @@
 		set_capacity(disk, drv->nr_blocks);
 		add_disk(disk);
 	}
-
-	cciss_register_scsi(i, 1);  /* hook ourself into SCSI subsystem */
-
 	return(1);
 }
 
diff -Nru a/drivers/block/cciss_scsi.c b/drivers/block/cciss_scsi.c
--- a/drivers/block/cciss_scsi.c	Mon Feb 17 14:57:27 2003
+++ b/drivers/block/cciss_scsi.c	Mon Feb 17 14:57:27 2003
@@ -89,8 +89,10 @@
    working even with the SCSI system.  It's so 
    scsi_unregister_host will differentiate the controllers. 
    When register_scsi_module is called, each host template is 
-   customized (name change) in cciss_register_scsi() 
-   (that's called from cciss.c:cciss_init_one()) */
+   customized (name change) in cciss_register_scsi() (that's
+   called from cciss_engage_scsi, called from
+   cciss.c:cciss_proc_write(), on "engage scsi" being received
+   from user space.) */
 
 static 
 Scsi_Host_Template driver_template[MAX_CTLR] =
@@ -199,14 +201,12 @@
 }
 
 static int
-scsi_cmd_stack_setup(int ctlr)
+scsi_cmd_stack_setup(int ctlr, struct cciss_scsi_adapter_data_t *sa)
 {
 	int i;
-	struct cciss_scsi_adapter_data_t *sa;
 	struct cciss_scsi_cmd_stack_t *stk;
 	size_t size;
 
-	sa = (struct cciss_scsi_adapter_data_t *) hba[ctlr]->scsi_ctlr;
 	stk = &sa->cmd_stack; 
 	size = sizeof(struct cciss_scsi_cmd_stack_elem_t) * CMD_STACK_SIZE;
 
@@ -535,126 +535,24 @@
 	return -1;
 }
 
-
 static void 
-cciss_find_non_disk_devices(int cntl_num)
+cciss_scsi_setup(int cntl_num)
 {
-	ReportLunData_struct *ld_buff;
-	InquiryData_struct *inq_buff;
-	int return_code;
-	int i;
-	int listlength = 0;
-	int num_luns;
-	unsigned char scsi3addr[8];
-	unsigned long flags;
-	int reportlunsize = sizeof(*ld_buff) + CISS_MAX_PHYS_LUN * 8;
-
-	hba[cntl_num]->scsi_ctlr = (void *)
-		kmalloc(sizeof(struct cciss_scsi_adapter_data_t),
-			GFP_KERNEL);	
-	if (hba[cntl_num]->scsi_ctlr == NULL)
-		return;
-
-	((struct cciss_scsi_adapter_data_t *) 
-		hba[cntl_num]->scsi_ctlr)->scsi_host = NULL;
-	((struct cciss_scsi_adapter_data_t *) 
-		hba[cntl_num]->scsi_ctlr)->lock = SPIN_LOCK_UNLOCKED;
-	((struct cciss_scsi_adapter_data_t *) 
-		hba[cntl_num]->scsi_ctlr)->registered = 0;
+	struct cciss_scsi_adapter_data_t * shba;
 
-	if (scsi_cmd_stack_setup(cntl_num) != 0) {
-		printk("Trouble, returned non-zero!\n");
-		return;
-	}
-
-	ld_buff = kmalloc(reportlunsize, GFP_KERNEL);
-	if (ld_buff == NULL) {
-		printk(KERN_ERR "cciss: out of memory\n");
-		return;
-	}
-	memset(ld_buff, 0, sizeof(ReportLunData_struct));
-	inq_buff = kmalloc(sizeof( InquiryData_struct), GFP_KERNEL);
-        if (inq_buff == NULL) {
-                printk(KERN_ERR "cciss: out of memory\n");
-                kfree(ld_buff);
-                return;
-        }
-
-	/* Get the physical luns */ 
-	return_code = sendcmd(CISS_REPORT_PHYS, cntl_num, ld_buff, 
-			reportlunsize, 0, 0, 0, NULL );
-
-	if( return_code == IO_OK) {
-		unsigned char *c = &ld_buff->LUNListLength[0];
-		listlength = (c[0] << 24) | (c[1] << 16) | (c[2] << 8) | c[3];
-	} 
-	else {  /* getting report of physical luns failed */
-		printk(KERN_WARNING "cciss: report physical luns"
-			" command failed\n");
-		listlength = 0;
-	}
-
-	CPQ_TAPE_LOCK(cntl_num, flags);
 	ccissscsi[cntl_num].ndevices = 0;
-	num_luns = listlength / 8; // 8 bytes pre entry
-	/* printk("Found %d LUNs\n", num_luns); */
-
-	if (num_luns > CISS_MAX_PHYS_LUN)
-	{
-		printk(KERN_WARNING 
-			"cciss: Maximum physical LUNs (%d) exceeded.  "
-			"%d LUNs ignored.\n", CISS_MAX_PHYS_LUN, 
-			num_luns - CISS_MAX_PHYS_LUN);
-		num_luns = CISS_MAX_PHYS_LUN;
-	}
-
-	for(i=0; i<num_luns; i++) {
-		/* Execute an inquiry to figure the device type */
-		memset(inq_buff, 0, sizeof(InquiryData_struct));
-		memcpy(scsi3addr, ld_buff->LUN[i], 8); /* ugly... */
-		return_code = sendcmd(CISS_INQUIRY, cntl_num, inq_buff,
-                	sizeof(InquiryData_struct), 2, 0 ,0, scsi3addr );
-	  	if (return_code == IO_OK) {
-			if(inq_buff->data_byte[8] == 0xFF)
-			{
-			   printk(KERN_WARNING "cciss: inquiry failed\n");
-                        } else {
-			   int devtype;
-
-			   /* printk("Inquiry...\n");
-			   print_bytes((unsigned char *) inq_buff, 36, 1, 1); */
-			   devtype = (inq_buff->data_byte[0] & 0x1f);
-
-			   switch (devtype)
-			   {
-			    case 0x01: /* sequential access, (tape) */
-			    case 0x08: /* medium changer */
-					  /* this is the only kind of dev */
-					  /* we want to expose here. */
-				if (cciss_scsi_add_entry(cntl_num, -1,
-					(unsigned char *) ld_buff->LUN[i],
-					devtype) != 0) 
-						i=num_luns; // leave loop
-				break;
-			    default: 
-				break;
-			   }
-
-			}
-		}
-		else printk("cciss: inquiry failed.\n");
+	shba = (struct cciss_scsi_adapter_data_t *)
+		kmalloc(sizeof(*shba), GFP_KERNEL);	
+	if (shba == NULL)
+		return;
+	shba->scsi_host = NULL;
+	shba->lock = SPIN_LOCK_UNLOCKED;
+	shba->registered = 0;
+	if (scsi_cmd_stack_setup(cntl_num, shba) != 0) {
+		kfree(shba);
+		shba = NULL;
 	}
-#if 0
-	for (i=0;i<ccissscsi[cntl_num].ndevices;i++)
-		printk("Tape device presented at c%db%dt%dl%d\n", 
-			cntl_num, // <-- this is wrong
-			ccissscsi[cntl_num].dev[i].bus,
-			ccissscsi[cntl_num].dev[i].target,
-			ccissscsi[cntl_num].dev[i].lun);
-#endif			
-	CPQ_TAPE_UNLOCK(cntl_num, flags);
-	kfree(ld_buff);
-	kfree(inq_buff);
+	hba[cntl_num]->scsi_ctlr = (void *) shba;
 	return;
 }
 
@@ -913,7 +811,7 @@
 
 	memset(cp->Request.CDB, 0, sizeof(cp->Request.CDB));
 	memcpy(cp->Request.CDB, cdb, cdblen);
-	cp->Request.Timeout = 1000;		// guarantee completion. 
+	cp->Request.Timeout = 0;
 	cp->Request.CDBLen = cdblen;
 	cp->Request.Type.Type = TYPE_CMD;
 	cp->Request.Type.Attribute = ATTR_SIMPLE;
@@ -1208,6 +1106,12 @@
 		{
 		  case 0x01: /* sequential access, (tape) */
 		  case 0x08: /* medium changer */
+			if (ncurrent >= CCISS_MAX_SCSI_DEVS_PER_HBA) {
+				printk(KERN_INFO "cciss%d: %s ignored, "
+					"too many devices.\n", cntl_num,
+					DEVICETYPE(devtype));
+				break;
+			}
 			memcpy(&currentsd[ncurrent].scsi3addr[0], 
 				&scsi3addr[0], 8);
 			currentsd[ncurrent].devtype = devtype;
@@ -1262,7 +1166,6 @@
 
 	int buflen, datalen;
 	struct Scsi_Host *sh;
-	int found;
 	ctlr_info_t *ci;
 	int cntl_num;
 
@@ -1379,11 +1282,11 @@
 
 	// Get the ptr to our adapter structure (hba[i]) out of cmd->host.
 	// We violate cmd->host privacy here.  (Is there another way?)
-	c = (ctlr_info_t **) &cmd->device->host->hostdata[0];
+	c = (ctlr_info_t **) &cmd->device->host->hostdata[0];	
 	ctlr = (*c)->ctlr;
 
-	rc = lookup_scsi3addr(ctlr, cmd->device->channel, cmd->device->id, cmd->device->lun, 
-			scsi3addr);
+	rc = lookup_scsi3addr(ctlr, cmd->device->channel, cmd->device->id, 
+			cmd->device->lun, scsi3addr);
 	if (rc != 0) {
 		/* the scsi nexus does not match any that we presented... */
 		/* pretend to mid layer that we got selection timeout */
@@ -1428,7 +1331,7 @@
 	
 	// Fill in the request block...
 
-	cp->Request.Timeout = 1000; // guarantee completion
+	cp->Request.Timeout = 0;
 	memset(cp->Request.CDB, 0, sizeof(cp->Request.CDB));
 	if (cmd->cmd_len > sizeof(cp->Request.CDB)) BUG();
 	cp->Request.CDBLen = cmd->cmd_len;
@@ -1531,7 +1434,7 @@
 }
 
 static int 
-cciss_register_scsi(int ctlr, int this_is_init_time)
+cciss_register_scsi(int ctlr)
 {
 	unsigned long flags;
 
@@ -1541,15 +1444,10 @@
 	driver_template[ctlr].module = THIS_MODULE;;
 
 	/* Since this is really a block driver, the SCSI core may not be 
-	   initialized yet, in which case, calling scsi_register_host
-	   would hang.  instead, we will do it later, via /proc filesystem 
+	   initialized at init time, in which case, calling scsi_register_host
+	   would hang.  Instead, we do it later, via /proc filesystem
 	   and rc scripts, when we know SCSI core is good to go. */
 
-	if (this_is_init_time) {
-		CPQ_TAPE_UNLOCK(ctlr, flags);
-		return 0;
-	}
-
 	/* Only register if SCSI devices are detected. */
 	if (ccissscsi[ctlr].ndevices != 0) {
 		((struct cciss_scsi_adapter_data_t *) 
@@ -1583,7 +1481,7 @@
 	}
 	spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags);
 	cciss_update_non_disk_devices(ctlr, -1);
-	cciss_register_scsi(ctlr, 0);
+	cciss_register_scsi(ctlr);
 	return 0;
 }
 
@@ -1607,9 +1505,9 @@
 
 /* If no tape support, then these become defined out of existence */
 
-#define cciss_find_non_disk_devices(cntl_num)
+#define cciss_scsi_setup(cntl_num)
 #define cciss_unregister_scsi(ctlr)
-#define cciss_register_scsi(ctlr, this_is_init_time)
+#define cciss_register_scsi(ctlr)
 #define cciss_proc_tape_report(ctlr, buffer, pos, len)
 
 #endif /* CONFIG_CISS_SCSI_TAPE */
diff -Nru a/drivers/block/deadline-iosched.c b/drivers/block/deadline-iosched.c
--- a/drivers/block/deadline-iosched.c	Mon Feb 17 14:57:28 2003
+++ b/drivers/block/deadline-iosched.c	Mon Feb 17 14:57:28 2003
@@ -98,6 +98,8 @@
 	unsigned long expires;
 };
 
+static inline void deadline_move_to_dispatch(struct deadline_data *dd, struct deadline_rq *drq);
+
 static kmem_cache_t *drq_pool;
 
 #define RQ_DATA(rq)	((struct deadline_rq *) (rq)->elevator_private)
@@ -189,26 +191,22 @@
 	return 0;
 }
 
-static int
+static void
 deadline_add_drq_rb(struct deadline_data *dd, struct deadline_rq *drq)
 {
 	struct deadline_rq *__alias;
 
 	drq->rb_key = rq_rb_key(drq->request);
 
+retry:
 	__alias = __deadline_add_drq_rb(dd, drq);
 	if (!__alias) {
 		rb_insert_color(&drq->rb_node, DRQ_RB_ROOT(dd, drq));
-		return 0;
+		return;
 	}
 
-	/*
-	 * this should not typically happen, but if it does simply chain
-	 * the two requests. then they will be moved to the dispatch list
-	 * at the same time
-	 */
-	list_add(&drq->request->queuelist, &__alias->request->queuelist);
-	return 1;
+	deadline_move_to_dispatch(dd, __alias);
+	goto retry;
 }
 
 static inline void
@@ -276,13 +274,12 @@
 {
 	const int data_dir = rq_data_dir(drq->request);
 
-	if (!deadline_add_drq_rb(dd, drq)) {
-		/*
-		 * set expire time (only used for reads) and add to fifo list
-		 */
-		drq->expires = jiffies + dd->fifo_expire[data_dir];
-		list_add_tail(&drq->fifo, &dd->fifo_list[data_dir]);
-	}
+	deadline_add_drq_rb(dd, drq);
+	/*
+	 * set expire time (only used for reads) and add to fifo list
+	 */
+	drq->expires = jiffies + dd->fifo_expire[data_dir];
+	list_add_tail(&drq->fifo, &dd->fifo_list[data_dir]);
 }
 
 /*
@@ -300,6 +297,9 @@
 		deadline_del_drq_rb(dd, drq);
 	}
 
+	if (q->last_merge == &rq->queuelist)
+		q->last_merge = NULL;
+
 	list_del_init(&rq->queuelist);
 }
 
@@ -425,8 +425,9 @@
 static inline void
 deadline_move_to_dispatch(struct deadline_data *dd, struct deadline_rq *drq)
 {
-	deadline_del_drq_rb(dd, drq);
-	list_del_init(&drq->fifo);
+	request_queue_t *q = drq->request->q;
+
+	deadline_remove_request(q, drq->request);
 	list_add_tail(&drq->request->queuelist, dd->dispatch);
 }
 
diff -Nru a/drivers/block/elevator.c b/drivers/block/elevator.c
--- a/drivers/block/elevator.c	Mon Feb 17 14:57:28 2003
+++ b/drivers/block/elevator.c	Mon Feb 17 14:57:28 2003
@@ -399,7 +399,7 @@
 	elevator_t *e = &q->elevator;
 
 	if (e->elevator_former_req_fn)
-		return e->elevator_latter_req_fn(q, rq);
+		return e->elevator_former_req_fn(q, rq);
 
 	prev = rq->queuelist.prev;
 	if (prev != &q->queue_head && prev != &rq->queuelist)
diff -Nru a/drivers/block/ll_rw_blk.c b/drivers/block/ll_rw_blk.c
--- a/drivers/block/ll_rw_blk.c	Mon Feb 17 14:57:26 2003
+++ b/drivers/block/ll_rw_blk.c	Mon Feb 17 14:57:26 2003
@@ -1358,11 +1358,19 @@
 
 	generic_unplug_device(q);
 	do {
+		int block = 0;
+
 		prepare_to_wait_exclusive(&rl->wait, &wait,
 					TASK_UNINTERRUPTIBLE);
+		spin_lock_irq(q->queue_lock);
 		if (!rl->count)
+			block = 1;
+		spin_unlock_irq(q->queue_lock);
+
+		if (block)
 			io_schedule();
 		finish_wait(&rl->wait, &wait);
+
 		spin_lock_irq(q->queue_lock);
 		rq = get_request(q, rw);
 		spin_unlock_irq(q->queue_lock);
@@ -1596,13 +1604,9 @@
 	DEFINE_WAIT(wait);
 	struct congestion_state *cs = &congestion_states[rw];
 
-	if (!atomic_read(&cs->nr_active_queues))
-		return;
-
 	blk_run_queues();
 	prepare_to_wait(&cs->wqh, &wait, TASK_UNINTERRUPTIBLE);
-	if (atomic_read(&cs->nr_active_queues))
-		io_schedule_timeout(timeout);
+	io_schedule_timeout(timeout);
 	finish_wait(&cs->wqh, &wait);
 }
 
diff -Nru a/drivers/bluetooth/bt3c_cs.c b/drivers/bluetooth/bt3c_cs.c
--- a/drivers/bluetooth/bt3c_cs.c	Mon Feb 17 14:57:28 2003
+++ b/drivers/bluetooth/bt3c_cs.c	Mon Feb 17 14:57:28 2003
@@ -24,18 +24,14 @@
 #include <linux/config.h>
 #include <linux/module.h>
 
-#define __KERNEL_SYSCALLS__
-
 #include <linux/kernel.h>
 #include <linux/kmod.h>
 #include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/types.h>
 #include <linux/sched.h>
-#include <linux/delay.h>
 #include <linux/timer.h>
 #include <linux/errno.h>
-#include <linux/unistd.h>
 #include <linux/ptrace.h>
 #include <linux/ioport.h>
 #include <linux/spinlock.h>
@@ -405,7 +401,6 @@
 
 
 
-
 /* ======================== HCI interface ======================== */
 
 
@@ -489,65 +484,23 @@
 
 
 #define FW_LOADER  "/sbin/bluefw"
-static int errno;
-
-
-static int bt3c_fw_loader_exec(void *dev)
-{
-	char *argv[] = { FW_LOADER, "pccard", dev, NULL };
-	char *envp[] = { "HOME=/", "TERM=linux", "PATH=/sbin:/usr/sbin:/bin:/usr/bin", NULL };
-	int err;
-
-	err = exec_usermodehelper(FW_LOADER, argv, envp);
-	if (err)
-		printk(KERN_WARNING "bt3c_cs: Failed to exec \"%s pccard %s\".\n", FW_LOADER, (char *)dev);
-
-	return err;
-}
 
 
 static int bt3c_firmware_load(bt3c_info_t *info)
 {
-	sigset_t tmpsig;
 	char dev[16];
-	pid_t pid;
-	int result;
+	int err;
 
-	/* Check if root fs is mounted */
-	if (!current->fs->root) {
-		printk(KERN_WARNING "bt3c_cs: Root filesystem is not mounted.\n");
-		return -EPERM;
-	}
+	char *argv[] = { FW_LOADER, "pccard", dev, NULL };
+	char *envp[] = { "HOME=/", "TERM=linux", "PATH=/sbin:/usr/sbin:/bin:/usr/bin", NULL };
 
 	sprintf(dev, "%04x", info->link.io.BasePort1);
 
-	pid = kernel_thread(bt3c_fw_loader_exec, (void *)dev, 0);
-	if (pid < 0) {
-		printk(KERN_WARNING "bt3c_cs: Forking of kernel thread failed (errno=%d).\n", -pid);
-		return pid;
-	}
-
-	/* Block signals, everything but SIGKILL/SIGSTOP */
-	spin_lock_irq(&current->sighand->siglock);
-	tmpsig = current->blocked;
-	siginitsetinv(&current->blocked, sigmask(SIGKILL) | sigmask(SIGSTOP));
-	recalc_sigpending();
-	spin_unlock_irq(&current->sighand->siglock);
-
-	result = waitpid(pid, NULL, __WCLONE);
-
-	/* Allow signals again */
-	spin_lock_irq(&current->sighand->siglock);
-	current->blocked = tmpsig;
-	recalc_sigpending();
-	spin_unlock_irq(&current->sighand->siglock);
-
-	if (result != pid) {
-		printk(KERN_WARNING "bt3c_cs: Waiting for pid %d failed (errno=%d).\n", pid, -result);
-		return -result;
-	}
+	err = call_usermodehelper(FW_LOADER, argv, envp, 1);
+	if (err)
+		printk(KERN_WARNING "bt3c_cs: Failed to run \"%s pccard %s\" (errno=%d).\n", FW_LOADER, dev, err);
 
-	return 0;
+	return err;
 }
 
 
diff -Nru a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c
--- a/drivers/cdrom/cdrom.c	Mon Feb 17 14:57:27 2003
+++ b/drivers/cdrom/cdrom.c	Mon Feb 17 14:57:27 2003
@@ -2542,33 +2542,81 @@
 
 /* Place files in /proc/sys/dev/cdrom */
 ctl_table cdrom_table[] = {
-	{DEV_CDROM_INFO, "info", &cdrom_sysctl_settings.info, 
-		CDROM_STR_SIZE, 0444, NULL, &cdrom_sysctl_info},
-	{DEV_CDROM_AUTOCLOSE, "autoclose", &cdrom_sysctl_settings.autoclose,
-		sizeof(int), 0644, NULL, &cdrom_sysctl_handler },
-	{DEV_CDROM_AUTOEJECT, "autoeject", &cdrom_sysctl_settings.autoeject,
-		sizeof(int), 0644, NULL, &cdrom_sysctl_handler },
-	{DEV_CDROM_DEBUG, "debug", &cdrom_sysctl_settings.debug,
-		sizeof(int), 0644, NULL, &cdrom_sysctl_handler },
-	{DEV_CDROM_LOCK, "lock", &cdrom_sysctl_settings.lock,
-		sizeof(int), 0644, NULL, &cdrom_sysctl_handler },
-	{DEV_CDROM_CHECK_MEDIA, "check_media", &cdrom_sysctl_settings.check,
-		sizeof(int), 0644, NULL, &cdrom_sysctl_handler },
-	{0}
-	};
+	{
+		.ctl_name	= DEV_CDROM_INFO,
+		.procname	= "info",
+		.data		= &cdrom_sysctl_settings.info, 
+		.maxlen		= CDROM_STR_SIZE,
+		.mode		= 0444,
+		.proc_handler	= &cdrom_sysctl_info,
+	},
+	{
+		.ctl_name	= DEV_CDROM_AUTOCLOSE,
+		.procname	= "autoclose",
+		.data		= &cdrom_sysctl_settings.autoclose,
+		.maxlen		= sizeof(int),
+		.mode		= 0644,
+		.proc_handler	= &cdrom_sysctl_handler,
+	},
+	{
+		.ctl_name	= DEV_CDROM_AUTOEJECT,
+		.procname	= "autoeject",
+		.data		= &cdrom_sysctl_settings.autoeject,
+		.maxlen		= sizeof(int),
+		.mode		= 0644,
+		.proc_handler	= &cdrom_sysctl_handler,
+	},
+	{
+		.ctl_name	= DEV_CDROM_DEBUG,
+		.procname	= "debug",
+		.data		= &cdrom_sysctl_settings.debug,
+		.maxlen		= sizeof(int),
+		.mode		= 0644,
+		.proc_handler	= &cdrom_sysctl_handler,
+	},
+	{
+		.ctl_name	= DEV_CDROM_LOCK,
+		.procname	= "lock",
+		.data		= &cdrom_sysctl_settings.lock,
+		.maxlen		= sizeof(int),
+		.mode		= 0644,
+		.proc_handler	= &cdrom_sysctl_handler,
+	},
+	{
+		.ctl_name	= DEV_CDROM_CHECK_MEDIA,
+		.procname	= "check_media",
+		.data		= &cdrom_sysctl_settings.check,
+		.maxlen		= sizeof(int),
+		.mode		= 0644,
+		.proc_handler	= &cdrom_sysctl_handler
+	},
+	{ .ctl_name = 0 }
+};
 
 ctl_table cdrom_cdrom_table[] = {
-	{DEV_CDROM, "cdrom", NULL, 0, 0555, cdrom_table},
-	{0}
-	};
+	{
+		.ctl_name	= DEV_CDROM,
+		.procname	= "cdrom",
+		.maxlen		= 0,
+		.mode		= 0555,
+		.child		= cdrom_table,
+	},
+	{ .ctl_name = 0 }
+};
 
 /* Make sure that /proc/sys/dev is there */
 ctl_table cdrom_root_table[] = {
 #ifdef CONFIG_PROC_FS
-	{CTL_DEV, "dev", NULL, 0, 0555, cdrom_cdrom_table},
+	{
+		.ctl_name	= CTL_DEV,
+		.procname	= "dev",
+		.maxlen		= 0,
+		.mode		= 0555,
+		.child		= cdrom_cdrom_table,
+	},
 #endif /* CONFIG_PROC_FS */
-	{0}
-	};
+	{ .ctl_name = 0 }
+};
 static struct ctl_table_header *cdrom_sysctl_header;
 
 static void cdrom_sysctl_register(void)
diff -Nru a/drivers/char/random.c b/drivers/char/random.c
--- a/drivers/char/random.c	Mon Feb 17 14:57:26 2003
+++ b/drivers/char/random.c	Mon Feb 17 14:57:26 2003
@@ -535,14 +535,14 @@
 	r->extract_count = 0;
 	memset(r->pool, 0, r->poolinfo.POOLBYTES);
 }
-
+#ifdef CONFIG_SYSCTL
 static void free_entropy_store(struct entropy_store *r)
 {
 	if (r->pool)
 		kfree(r->pool);
 	kfree(r);
 }
-
+#endif
 /*
  * This function adds a byte into the entropy "pool".  It does not
  * update the entropy estimate.  The caller should call
diff -Nru a/drivers/char/rio/rioboot.c b/drivers/char/rio/rioboot.c
--- a/drivers/char/rio/rioboot.c	Mon Feb 17 14:57:27 2003
+++ b/drivers/char/rio/rioboot.c	Mon Feb 17 14:57:27 2003
@@ -410,7 +410,7 @@
 		** compatible with the whole Tp family. (lies, damn lies, it'll never
 		** work in a month of Sundays).
 		**
-		** The nfix nyble is the 1s compliment of the nyble value you
+		** The nfix nyble is the 1s complement of the nyble value you
 		** want to load - in this case we wanted 'F' so we nfix loaded '0'.
 		*/
 
diff -Nru a/drivers/char/rtc.c b/drivers/char/rtc.c
--- a/drivers/char/rtc.c	Mon Feb 17 14:57:27 2003
+++ b/drivers/char/rtc.c	Mon Feb 17 14:57:27 2003
@@ -211,19 +211,37 @@
  * sysctl-tuning infrastructure.
  */
 static ctl_table rtc_table[] = {
-    { 1, "max-user-freq", &rtc_max_user_freq, sizeof(int), 0644, NULL,
-      &proc_dointvec, NULL, },
-    { 0, }
+	{
+		.ctl_name	= 1,
+		.procname	= "max-user-freq",
+		.data		= &rtc_max_user_freq,
+		.maxlen		= sizeof(int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec,
+	},
+	{ .ctl_name = 0 }
 };
 
 static ctl_table rtc_root[] = {
-    { 1, "rtc", NULL, 0, 0555, rtc_table, },
-    { 0, }
+	{
+		.ctl_name	= 1,
+		.procname	= "rtc",
+		.maxlen		= 0,
+		.mode		= 0555,
+		.child		= rtc_table,
+	},
+	{ .ctl_name = 0 }
 };
 
 static ctl_table dev_root[] = {
-    { CTL_DEV, "dev", NULL, 0, 0555, rtc_root, },
-    { 0, }
+	{
+		.ctl_name	= CTL_DEV,
+		.procname	= "dev",
+		.maxlen		= 0,
+		.mode		= 0555,
+		.child		= rtc_root,
+	},
+	{ .ctl_name = 0 }
 };
 
 static struct ctl_table_header *sysctl_header;
diff -Nru a/drivers/char/sx.c b/drivers/char/sx.c
--- a/drivers/char/sx.c	Mon Feb 17 14:57:27 2003
+++ b/drivers/char/sx.c	Mon Feb 17 14:57:27 2003
@@ -2233,6 +2233,23 @@
 			return 0; 
 	}
 
+	/* Now we're pretty much convinced that there is an SI board here, 
+	   but to prevent trouble, we'd better double check that we don't
+	   have an SI1 board when we're probing for an SI2 board.... */
+
+	write_sx_byte (board, SI2_ISA_ID_BASE,0x10); 
+	if ( IS_SI1_BOARD(board)) {
+		/* This should be an SI1 board, which has this
+		   location writable... */
+		if (read_sx_byte (board, SI2_ISA_ID_BASE) != 0x10)
+			return 0; 
+	} else {
+		/* This should be an SI2 board, which has the bottom
+		   3 bits non-writable... */
+		if (read_sx_byte (board, SI2_ISA_ID_BASE) == 0x10)
+			return 0; 
+	}
+
 	printheader ();
 
 	printk (KERN_DEBUG "sx: Found an SI board at %lx\n", board->hw_base);
diff -Nru a/drivers/char/tty_io.c b/drivers/char/tty_io.c
--- a/drivers/char/tty_io.c	Mon Feb 17 14:57:27 2003
+++ b/drivers/char/tty_io.c	Mon Feb 17 14:57:27 2003
@@ -2043,7 +2043,7 @@
 /*
  * The default put_char routine if the driver did not define one.
  */
-void tty_default_put_char(struct tty_struct *tty, unsigned char ch)
+static void tty_default_put_char(struct tty_struct *tty, unsigned char ch)
 {
 	tty->driver.write(tty, 0, &ch, 1);
 }
diff -Nru a/drivers/char/vt.c b/drivers/char/vt.c
--- a/drivers/char/vt.c	Mon Feb 17 14:57:28 2003
+++ b/drivers/char/vt.c	Mon Feb 17 14:57:28 2003
@@ -2101,7 +2101,7 @@
 	if (kmsg_redirect && vc_cons_allocated(kmsg_redirect - 1))
 		currcons = kmsg_redirect - 1;
 
-	/* read `x' only after setting currecons properly (otherwise
+	/* read `x' only after setting currcons properly (otherwise
 	   the `x' macro will read the x of the foreground console). */
 	myx = x;
 
@@ -2198,8 +2198,8 @@
  *
  * There are some functions which don't need it.
  *
- * There are some functions which can sleep for arbitrary periods (paste_selection)
- * but we don't need the lock there anyway.
+ * There are some functions which can sleep for arbitrary periods
+ * (paste_selection) but we don't need the lock there anyway.
  *
  * set_selection has locking, and definitely needs it
  */
diff -Nru a/drivers/char/watchdog/wdt285.c b/drivers/char/watchdog/wdt285.c
--- a/drivers/char/watchdog/wdt285.c	Mon Feb 17 14:57:27 2003
+++ b/drivers/char/watchdog/wdt285.c	Mon Feb 17 14:57:27 2003
@@ -37,18 +37,14 @@
  */
 #undef ONLY_TESTING
 
-#define TIMER_MARGIN	60		/* (secs) Default is 1 minute */
-
-#define FCLK	(50*1000*1000)		/* 50MHz */
-
-static int soft_margin = TIMER_MARGIN;	/* in seconds */
-static int timer_alive;
+static unsigned int soft_margin = 60;		/* in seconds */
+static unsigned int reload;
+static unsigned long timer_alive;
 
 #ifdef ONLY_TESTING
 /*
  *	If the timer expires..
  */
-
 static void watchdog_fire(int irq, void *dev_id, struct pt_regs *regs)
 {
 	printk(KERN_CRIT "Watchdog: Would Reboot.\n");
@@ -57,109 +53,134 @@
 }
 #endif
 
+/*
+ *	Refresh the timer.
+ */
 static void watchdog_ping(void)
 {
-	/*
-	 *	Refresh the timer.
-	 */
-	*CSR_TIMER4_LOAD = soft_margin * (FCLK / 256);
+	*CSR_TIMER4_LOAD = reload;
 }
 
 /*
  *	Allow only one person to hold it open
  */
- 
 static int watchdog_open(struct inode *inode, struct file *file)
 {
-	if(timer_alive)
+	int ret;
+
+	if (*CSR_SA110_CNTL & (1 << 13))
 		return -EBUSY;
-	/*
-	 *	Ahead watchdog factor ten, Mr Sulu
-	 */
+
+	if (test_and_set_bit(1, &timer_alive))
+		return -EBUSY;
+
+	reload = soft_margin * (mem_fclk_21285 / 256);
+
 	*CSR_TIMER4_CLR = 0;
 	watchdog_ping();
 	*CSR_TIMER4_CNTL = TIMER_CNTL_ENABLE | TIMER_CNTL_AUTORELOAD 
 		| TIMER_CNTL_DIV256;
+
 #ifdef ONLY_TESTING
-	request_irq(IRQ_TIMER4, watchdog_fire, 0, "watchdog", NULL);
+	ret = request_irq(IRQ_TIMER4, watchdog_fire, 0, "watchdog", NULL);
+	if (ret) {
+		*CSR_TIMER4_CNTL = 0;
+		clear_bit(1, &timer_alive);
+	}
 #else
+	/*
+	 * Setting this bit is irreversible; once enabled, there is
+	 * no way to disable the watchdog.
+	 */
 	*CSR_SA110_CNTL |= 1 << 13;
-	MOD_INC_USE_COUNT;
+
+	ret = 0;
 #endif
-	timer_alive = 1;
-	return 0;
+	return ret;
 }
 
+/*
+ *	Shut off the timer.
+ *	Note: if we really have enabled the watchdog, there
+ *	is no way to turn off.
+ */
 static int watchdog_release(struct inode *inode, struct file *file)
 {
 #ifdef ONLY_TESTING
 	free_irq(IRQ_TIMER4, NULL);
-	timer_alive = 0;
-#else
-	/*
-	 *	It's irreversible!
-	 */
+	clear_bit(1, &timer_alive);
 #endif
 	return 0;
 }
 
-static ssize_t watchdog_write(struct file *file, const char *data, size_t len, loff_t *ppos)
+static ssize_t
+watchdog_write(struct file *file, const char *data, size_t len, loff_t *ppos)
 {
-	/*  Can't seek (pwrite) on this device  */
+	/* Can't seek (pwrite) on this device  */
 	if (ppos != &file->f_pos)
 		return -ESPIPE;
 
 	/*
 	 *	Refresh the timer.
 	 */
-	if(len)
-	{
+	if (len)
 		watchdog_ping();
-		return 1;
-	}
-	return 0;
+
+	return len;
 }
 
-static int watchdog_ioctl(struct inode *inode, struct file *file,
-	unsigned int cmd, unsigned long arg)
-{
-	int i, new_margin;
-	static struct watchdog_info ident=
-	{
-		WDIOF_SETTIMEOUT,
-		0,
-		"Footbridge Watchdog"
-	};
-	switch(cmd)
-	{
-		default:
-			return -ENOTTY;
-		case WDIOC_GETSUPPORT:
-			if(copy_to_user((struct watchdog_info *)arg, &ident, sizeof(ident)))
-				return -EFAULT;
-			return 0;
-		case WDIOC_GETSTATUS:
-		case WDIOC_GETBOOTSTATUS:
-			return put_user(0,(int *)arg);
-		case WDIOC_KEEPALIVE:
-			watchdog_ping();
-			return 0;
-		case WDIOC_SETTIMEOUT:
-			if (get_user(new_margin, (int *)arg))
-				return -EFAULT;
-			/* Arbitrary, can't find the card's limits */
-			if ((new_marg < 0) || (new_margin > 60))
-				return -EINVAL;
-			soft_margin = new_margin;
-			watchdog_ping();
-			/* Fall */
-		case WDIOC_GETTIMEOUT:
-			return put_user(soft_margin, (int *)arg);
+static struct watchdog_info ident = {
+	.options	= WDIOF_SETTIMEOUT,
+	.identity	= "Footbridge Watchdog"
+};
+
+static int
+watchdog_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
+	       unsigned long arg)
+{
+	unsigned int new_margin;
+	int ret = -ENOIOCTLCMD;
+
+	switch(cmd) {
+	case WDIOC_GETSUPPORT:
+		ret = 0;
+		if (copy_to_user((void *)arg, &ident, sizeof(ident)))
+			ret = -EFAULT;
+		break;
+
+	case WDIOC_GETSTATUS:
+	case WDIOC_GETBOOTSTATUS:
+		ret = put_user(0,(int *)arg);
+		break;
+
+	case WDIOC_KEEPALIVE:
+		watchdog_ping();
+		ret = 0;
+		break;
+
+	case WDIOC_SETTIMEOUT:
+		ret = get_user(new_margin, (int *)arg);
+		if (ret)
+			break;
+
+		/* Arbitrary, can't find the card's limits */
+		if (new_margin < 0 || new_margin > 60) {
+			ret = -EINVAL;
+			break;
+		}
+
+		soft_margin = new_margin;
+		reload = soft_margin * (mem_fclk_21285 / 256);
+		watchdog_ping();
+		/* Fall */
+	case WDIOC_GETTIMEOUT:
+		ret = put_user(soft_margin, (int *)arg);
+		break;
 	}
+	return ret;
 }
 
-static struct file_operations watchdog_fops=
-{
+static struct file_operations watchdog_fops = {
 	.owner		= THIS_MODULE,
 	.write		= watchdog_write,
 	.ioctl		= watchdog_ioctl,
@@ -167,11 +188,10 @@
 	.release	= watchdog_release,
 };
 
-static struct miscdevice watchdog_miscdev=
-{
-	WATCHDOG_MINOR,
-	"watchdog",
-	&watchdog_fops
+static struct miscdevice watchdog_miscdev = {
+	.minor		= WATCHDOG_MINOR,
+	.name		= "watchdog",
+	.fops		= &watchdog_fops
 };
 
 static int __init footbridge_watchdog_init(void)
@@ -182,11 +202,12 @@
 		return -ENODEV;
 
 	retval = misc_register(&watchdog_miscdev);
-	if(retval < 0)
+	if (retval < 0)
 		return retval;
 
 	printk("Footbridge Watchdog Timer: 0.01, timer margin: %d sec\n", 
 	       soft_margin);
+
 	if (machine_is_cats())
 		printk("Warning: Watchdog reset may not work on this machine.\n");
 	return 0;
@@ -198,7 +219,7 @@
 }
 
 MODULE_AUTHOR("Phil Blundell <pb@nexus.co.uk>");
-MODULE_DESCRIPTION("21285 watchdog driver");
+MODULE_DESCRIPTION("Footbridge watchdog driver");
 MODULE_LICENSE("GPL");
 
 MODULE_PARM(soft_margin,"i");
diff -Nru a/drivers/char/watchdog/wdt977.c b/drivers/char/watchdog/wdt977.c
--- a/drivers/char/watchdog/wdt977.c	Mon Feb 17 14:57:28 2003
+++ b/drivers/char/watchdog/wdt977.c	Mon Feb 17 14:57:28 2003
@@ -58,7 +58,7 @@
 
 
 /* This is kicking the watchdog by simply re-writing the timeout to reg. 0xF2 */
-int kick_wdog(void)
+static int kick_wdog(void)
 {
 	/*
 	 *	Refresh the timer.
@@ -216,21 +216,20 @@
 
 static ssize_t wdt977_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
 {
-	/*  Can't seek (pwrite) on this device  */
+	/* Can't seek (pwrite) on this device  */
 	if (ppos != &file->f_pos)
 		return -ESPIPE;
 
-	if(count)
-	{
+	if (count) {
 		if (!nowayout) {
 			size_t i;
 
 			/* In case it was set long ago */
 			expect_close = 0;
 
-			for (i = 0; i != len; i++) {
+			for (i = 0; i != count; i++) {
 				char c;
-				if (get_user(c, data + i))
+				if (get_user(c, buf + i))
 					return -EFAULT;
 				if (c == 'V')
 					expect_close = 1;
@@ -238,9 +237,8 @@
 		}
 
 		kick_wdog();
-		return 1;
 	}
-	return 0;
+	return count;
 }
 
 /*
@@ -254,14 +252,15 @@
  *      according to their available features.
  */
 
-static int wdt977_ioctl(struct inode *inode, struct file *file,
-         unsigned int cmd, unsigned long arg)
-{
 static struct watchdog_info ident = {
-	.identity = "Winbond 83977"
+	.options	= WDIOF_SETTIMEOUT,
+	.identity	= "Winbond 83977"
 };
 
-int temp;
+static int wdt977_ioctl(struct inode *inode, struct file *file,
+         unsigned int cmd, unsigned long arg)
+{
+	int temp;
 
 	switch(cmd)
 	{
@@ -337,9 +336,9 @@
 
 static struct miscdevice wdt977_miscdev=
 {
-	WATCHDOG_MINOR,
-	"watchdog",
-	&wdt977_fops
+	.minor		= WATCHDOG_MINOR,
+	.name		= "watchdog",
+	.fops		= &wdt977_fops
 };
 
 static int __init nwwatchdog_init(void)
@@ -360,4 +359,5 @@
 module_init(nwwatchdog_init);
 module_exit(nwwatchdog_exit);
 
+MODULE_DESCRIPTION("W83977AF Watchdog driver");
 MODULE_LICENSE("GPL");
diff -Nru a/drivers/cpufreq/Kconfig b/drivers/cpufreq/Kconfig
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/cpufreq/Kconfig	Mon Feb 17 14:57:28 2003
@@ -0,0 +1,11 @@
+config CPU_FREQ_PROC_INTF
+	tristate "/proc/cpufreq interface (deprecated)"
+	depends on CPU_FREQ && PROC_FS
+	help
+	  This enables the /proc/cpufreq interface for controlling
+	  CPUFreq. Please note that it is recommended to use the sysfs
+	  interface instead (which is built automatically). 
+	  
+	  For details, take a look at linux/Documentation/cpufreq. 
+	  
+	  If in doubt, say N.
diff -Nru a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/cpufreq/Makefile	Mon Feb 17 14:57:28 2003
@@ -0,0 +1,3 @@
+#CPUfreq governors and cross-arch helpers
+obj-$(CONFIG_CPU_FREQ_TABLE)		+= freq_table.o
+obj-$(CONFIG_CPU_FREQ_PROC_INTF)	+= proc_intf.o
diff -Nru a/drivers/cpufreq/freq_table.c b/drivers/cpufreq/freq_table.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/cpufreq/freq_table.c	Mon Feb 17 14:57:28 2003
@@ -0,0 +1,203 @@
+/*
+ * linux/drivers/cpufreq/freq_table.c
+ *
+ * Copyright (C) 2002 - 2003 Dominik Brodowski
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/cpufreq.h>
+
+/*********************************************************************
+ *                     FREQUENCY TABLE HELPERS                       *
+ *********************************************************************/
+
+int cpufreq_frequency_table_cpuinfo(struct cpufreq_policy *policy,
+				    struct cpufreq_frequency_table *table)
+{
+	unsigned int min_freq = ~0;
+	unsigned int max_freq = 0;
+	unsigned int i = 0;
+
+	for (i=0; (table[i].frequency != CPUFREQ_TABLE_END); i++) {
+		unsigned int freq = table[i].frequency;
+		if (freq == CPUFREQ_ENTRY_INVALID)
+			continue;
+		if (freq < min_freq)
+			min_freq = freq;
+		if (freq > max_freq)
+			max_freq = freq;
+	}
+
+	policy->min = policy->cpuinfo.min_freq = min_freq;
+	policy->max = policy->cpuinfo.max_freq = max_freq;
+
+	if (policy->min == ~0)
+		return -EINVAL;
+	else
+		return 0;
+}
+EXPORT_SYMBOL_GPL(cpufreq_frequency_table_cpuinfo);
+
+
+int cpufreq_frequency_table_verify(struct cpufreq_policy *policy,
+				   struct cpufreq_frequency_table *table)
+{
+	unsigned int next_larger = ~0;
+	unsigned int i = 0;
+	unsigned int count = 0;
+
+	if (!cpu_online(policy->cpu))
+		return -EINVAL;
+
+	cpufreq_verify_within_limits(policy, 
+				     policy->cpuinfo.min_freq, 
+				     policy->cpuinfo.max_freq);
+
+	for (i=0; (table[i].frequency != CPUFREQ_TABLE_END); i++) {
+		unsigned int freq = table[i].frequency;
+		if (freq == CPUFREQ_ENTRY_INVALID)
+			continue;
+		if ((freq >= policy->min) && (freq <= policy->max))
+			count++;
+		else if ((next_larger > freq) && (freq > policy->max))
+			next_larger = freq;
+	}
+
+	if (!count)
+		policy->max = next_larger;
+
+	cpufreq_verify_within_limits(policy, 
+				     policy->cpuinfo.min_freq, 
+				     policy->cpuinfo.max_freq);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(cpufreq_frequency_table_verify);
+
+
+int cpufreq_frequency_table_setpolicy(struct cpufreq_policy *policy,
+				      struct cpufreq_frequency_table *table,
+				      unsigned int *index)
+{
+	struct cpufreq_frequency_table optimal = { .index = ~0, };
+	unsigned int i;
+
+	switch (policy->policy) {
+	case CPUFREQ_POLICY_PERFORMANCE:
+		optimal.frequency = 0;
+		break;
+	case CPUFREQ_POLICY_POWERSAVE:
+		optimal.frequency = ~0;
+		break;
+	}
+
+	if (!cpu_online(policy->cpu))
+		return -EINVAL;
+
+	for (i=0; (table[i].frequency != CPUFREQ_TABLE_END); i++) {
+		unsigned int freq = table[i].frequency;
+		if (freq == CPUFREQ_ENTRY_INVALID)
+			continue;
+		if ((freq < policy->min) || (freq > policy->max))
+			continue;
+		switch(policy->policy) {
+		case CPUFREQ_POLICY_PERFORMANCE:
+			if (optimal.frequency <= freq) {
+				optimal.frequency = freq;
+				optimal.index = i;
+			}
+			break;
+		case CPUFREQ_POLICY_POWERSAVE:
+			if (optimal.frequency >= freq) {
+				optimal.frequency = freq;
+				optimal.index = i;
+			}
+			break;
+		}
+	}
+	if (optimal.index > i)
+		return -EINVAL;
+
+	*index = optimal.index;
+	
+	return 0;
+}
+EXPORT_SYMBOL_GPL(cpufreq_frequency_table_setpolicy);
+
+
+int cpufreq_frequency_table_target(struct cpufreq_policy *policy,
+				   struct cpufreq_frequency_table *table,
+				   unsigned int target_freq,
+				   unsigned int relation,
+				   unsigned int *index)
+{
+	struct cpufreq_frequency_table optimal = { .index = ~0, };
+	struct cpufreq_frequency_table suboptimal = { .index = ~0, };
+	unsigned int i;
+
+	switch (relation) {
+	case CPUFREQ_RELATION_H:
+		optimal.frequency = 0;
+		suboptimal.frequency = ~0;
+		break;
+	case CPUFREQ_RELATION_L:
+		optimal.frequency = ~0;
+		suboptimal.frequency = 0;
+		break;
+	}
+
+	if (!cpu_online(policy->cpu))
+		return -EINVAL;
+
+	for (i=0; (table[i].frequency != CPUFREQ_TABLE_END); i++) {
+		unsigned int freq = table[i].frequency;
+		if (freq == CPUFREQ_ENTRY_INVALID)
+			continue;
+		if ((freq < policy->min) || (freq > policy->max))
+			continue;
+		switch(relation) {
+		case CPUFREQ_RELATION_H:
+			if (freq <= target_freq) {
+				if (freq >= optimal.frequency) {
+					optimal.frequency = freq;
+					optimal.index = i;
+				}
+			} else {
+				if (freq <= suboptimal.frequency) {
+					suboptimal.frequency = freq;
+					suboptimal.index = i;
+				}
+			}
+			break;
+		case CPUFREQ_RELATION_L:
+			if (freq >= target_freq) {
+				if (freq <= optimal.frequency) {
+					optimal.frequency = freq;
+					optimal.index = i;
+				}
+			} else {
+				if (freq >= suboptimal.frequency) {
+					suboptimal.frequency = freq;
+					suboptimal.index = i;
+				}
+			}
+			break;
+		}
+	}
+	if (optimal.index > i) {
+		if (suboptimal.index > i)
+			return -EINVAL;
+		*index = suboptimal.index;
+	} else
+		*index = optimal.index;
+	
+	return 0;
+}
+EXPORT_SYMBOL_GPL(cpufreq_frequency_table_target);
+
+
+MODULE_AUTHOR ("Dominik Brodowski <linux@brodo.de>");
+MODULE_DESCRIPTION ("CPUfreq frequency table helpers");
+MODULE_LICENSE ("GPL");
diff -Nru a/drivers/cpufreq/proc_intf.c b/drivers/cpufreq/proc_intf.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/cpufreq/proc_intf.c	Mon Feb 17 14:57:28 2003
@@ -0,0 +1,244 @@
+/*
+ * linux/drivers/cpufreq/proc_intf.c
+ *
+ * Copyright (C) 2002 - 2003 Dominik Brodowski
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/cpufreq.h>
+#include <linux/ctype.h>
+#include <linux/proc_fs.h>
+#include <asm/uaccess.h>
+
+
+/**
+ * cpufreq_parse_policy - parse a policy string
+ * @input_string: the string to parse.
+ * @policy: the policy written inside input_string
+ *
+ * This function parses a "policy string" - something the user echo'es into
+ * /proc/cpufreq or gives as boot parameter - into a struct cpufreq_policy.
+ * If there are invalid/missing entries, they are replaced with current
+ * cpufreq policy.
+ */
+static int cpufreq_parse_policy(char input_string[42], struct cpufreq_policy *policy)
+{
+	unsigned int            min = 0;
+	unsigned int            max = 0;
+	unsigned int            cpu = 0;
+	char			str_governor[16];
+	struct cpufreq_policy   current_policy;
+	unsigned int            result = -EFAULT;
+
+	if (!policy)
+		return -EINVAL;
+
+	policy->min = 0;
+	policy->max = 0;
+	policy->policy = 0;
+	policy->cpu = CPUFREQ_ALL_CPUS;
+
+	if (sscanf(input_string, "%d:%d:%d:%15s", &cpu, &min, &max, str_governor) == 4) 
+	{
+		policy->min = min;
+		policy->max = max;
+		policy->cpu = cpu;
+		result = 0;
+		goto scan_policy;
+	}
+	if (sscanf(input_string, "%d%%%d%%%d%%%15s", &cpu, &min, &max, str_governor) == 4)
+	{
+		if (!cpufreq_get_policy(&current_policy, cpu)) {
+			policy->min = (min * current_policy.cpuinfo.max_freq) / 100;
+			policy->max = (max * current_policy.cpuinfo.max_freq) / 100;
+			policy->cpu = cpu;
+			result = 0;
+			goto scan_policy;
+		}
+	}
+
+	if (sscanf(input_string, "%d:%d:%15s", &min, &max, str_governor) == 3) 
+	{
+		policy->min = min;
+		policy->max = max;
+		result = 0;
+		goto scan_policy;
+	}
+
+	if (sscanf(input_string, "%d%%%d%%%15s", &min, &max, str_governor) == 3)
+	{
+		if (!cpufreq_get_policy(&current_policy, cpu)) {
+			policy->min = (min * current_policy.cpuinfo.max_freq) / 100;
+			policy->max = (max * current_policy.cpuinfo.max_freq) / 100;
+			result = 0;
+			goto scan_policy;
+		}
+	}
+
+	return -EINVAL;
+
+scan_policy:
+	result = cpufreq_parse_governor(str_governor, &policy->policy, &policy->governor);
+
+	return result;
+}
+
+/**
+ * cpufreq_proc_read - read /proc/cpufreq
+ *
+ * This function prints out the current cpufreq policy.
+ */
+static int cpufreq_proc_read (
+	char			*page,
+	char			**start,
+	off_t			off,
+	int 			count,
+	int 			*eof,
+	void			*data)
+{
+	char			*p = page;
+	int			len = 0;
+	struct cpufreq_policy   policy;
+	unsigned int            min_pctg = 0;
+	unsigned int            max_pctg = 0;
+	unsigned int            i = 0;
+
+	if (off != 0)
+		goto end;
+
+	p += sprintf(p, "          minimum CPU frequency  -  maximum CPU frequency  -  policy\n");
+	for (i=0;i<NR_CPUS;i++) {
+		if (!cpu_online(i))
+			continue;
+
+		if (cpufreq_get_policy(&policy, i))
+			continue;
+
+		if (!policy.cpuinfo.max_freq)
+			continue;
+
+		min_pctg = (policy.min * 100) / policy.cpuinfo.max_freq;
+		max_pctg = (policy.max * 100) / policy.cpuinfo.max_freq;
+
+		p += sprintf(p, "CPU%3d    %9d kHz (%3d %%)  -  %9d kHz (%3d %%)  -  ",
+			     i , policy.min, min_pctg, policy.max, max_pctg);
+		switch (policy.policy) {
+		case CPUFREQ_POLICY_POWERSAVE:
+			p += sprintf(p, "powersave\n");
+			break;
+		case CPUFREQ_POLICY_PERFORMANCE:
+			p += sprintf(p, "performance\n");
+			break;
+		case CPUFREQ_POLICY_GOVERNOR:
+			p += snprintf(p, CPUFREQ_NAME_LEN, "%s\n", policy.governor->name);
+			break;
+		default:
+			p += sprintf(p, "INVALID\n");
+			break;
+		}
+	}
+end:
+	len = (p - page);
+	if (len <= off+count) 
+		*eof = 1;
+	*start = page + off;
+	len -= off;
+	if (len>count) 
+		len = count;
+	if (len<0) 
+		len = 0;
+
+	return len;
+}
+
+
+/**
+ * cpufreq_proc_write - handles writing into /proc/cpufreq
+ *
+ * This function calls the parsing script and then sets the policy
+ * accordingly.
+ */
+static int cpufreq_proc_write (
+        struct file		*file,
+        const char		*buffer,
+        unsigned long		count,
+        void			*data)
+{
+	int                     result = 0;
+	char			proc_string[42] = {'\0'};
+	struct cpufreq_policy   policy;
+	unsigned int            i = 0;
+
+
+	if ((count > sizeof(proc_string) - 1))
+		return -EINVAL;
+	
+	if (copy_from_user(proc_string, buffer, count))
+		return -EFAULT;
+	
+	proc_string[count] = '\0';
+
+	result = cpufreq_parse_policy(proc_string, &policy);
+	if (result)
+		return -EFAULT;
+
+	if (policy.cpu == CPUFREQ_ALL_CPUS)
+	{
+		for (i=0; i<NR_CPUS; i++) 
+		{
+			policy.cpu = i;
+			if (cpu_online(i))
+				cpufreq_set_policy(&policy);
+		}
+	} 
+	else
+		cpufreq_set_policy(&policy);
+
+	return count;
+}
+
+
+/**
+ * cpufreq_proc_init - add "cpufreq" to the /proc root directory
+ *
+ * This function adds "cpufreq" to the /proc root directory.
+ */
+static int __init cpufreq_proc_init (void)
+{
+	struct proc_dir_entry *entry = NULL;
+
+        /* are these acceptable values? */
+	entry = create_proc_entry("cpufreq", S_IFREG|S_IRUGO|S_IWUSR, 
+				  &proc_root);
+
+	if (!entry) {
+		printk(KERN_ERR "unable to create /proc/cpufreq entry\n");
+		return -EIO;
+	} else {
+		entry->read_proc = cpufreq_proc_read;
+		entry->write_proc = cpufreq_proc_write;
+	}
+
+	return 0;
+}
+
+
+/**
+ * cpufreq_proc_exit - removes "cpufreq" from the /proc root directory.
+ *
+ * This function removes "cpufreq" from the /proc root directory.
+ */
+static void __exit cpufreq_proc_exit (void)
+{
+	remove_proc_entry("cpufreq", &proc_root);
+	return;
+}
+
+MODULE_AUTHOR ("Dominik Brodowski <linux@brodo.de>");
+MODULE_DESCRIPTION ("CPUfreq /proc/cpufreq interface");
+MODULE_LICENSE ("GPL");
+
+module_init(cpufreq_proc_init);
+module_exit(cpufreq_proc_exit);
diff -Nru a/drivers/eisa/Kconfig b/drivers/eisa/Kconfig
--- a/drivers/eisa/Kconfig	Mon Feb 17 14:57:27 2003
+++ b/drivers/eisa/Kconfig	Mon Feb 17 14:57:27 2003
@@ -1,6 +1,28 @@
 #
-# PCI configuration
+# EISA configuration
 #
+config EISA_PCI_EISA
+	bool "Generic PCI/EISA bridge"
+	depends on PCI && EISA
+	default y
+	---help---
+	  Activate this option if your system contains a PCI to EISA
+	  bridge. If your system have both PCI and EISA slots, you
+	  certainly need this option.
+
+	  When in doubt, say Y.
+
+config EISA_VIRTUAL_ROOT
+	bool "EISA virtual root device"
+	depends on EISA
+	default y
+	---help---
+	  Activate this option if your system only have EISA bus
+	  (no PCI slots). The Alpha Jensen is an example of such
+	  a system.
+
+	  When in doubt, say Y.
+
 config EISA_NAMES
 	bool "EISA device name database"
 	depends on EISA
diff -Nru a/drivers/eisa/Makefile b/drivers/eisa/Makefile
--- a/drivers/eisa/Makefile	Mon Feb 17 14:57:27 2003
+++ b/drivers/eisa/Makefile	Mon Feb 17 14:57:27 2003
@@ -1,6 +1,11 @@
 # Makefile for the Linux device tree
 
-obj-$(CONFIG_EISA)	+= eisa-bus.o
+obj-$(CONFIG_EISA)	        += eisa-bus.o
+obj-${CONFIG_EISA_PCI_EISA}     += pci_eisa.o
+
+# virtual_root.o should be the last EISA root device to initialize,
+# so leave it at the end of the list.
+obj-${CONFIG_EISA_VIRTUAL_ROOT} += virtual_root.o
 
 clean-files:= devlist.h
 
diff -Nru a/drivers/eisa/eisa-bus.c b/drivers/eisa/eisa-bus.c
--- a/drivers/eisa/eisa-bus.c	Mon Feb 17 14:57:27 2003
+++ b/drivers/eisa/eisa-bus.c	Mon Feb 17 14:57:27 2003
@@ -15,6 +15,8 @@
 #include <linux/ioport.h>
 #include <asm/io.h>
 
+#define SLOT_ADDRESS(r,n) (r->bus_base_addr + (0x1000 * n))
+
 #define EISA_DEVINFO(i,s) { .id = { .sig = i }, .name = s }
 
 struct eisa_device_info {
@@ -95,12 +97,6 @@
 	.match = eisa_bus_match,
 };
 
-/* The default EISA device parent (virtual root device). */
-static struct device eisa_bus_root = {
-       .name           = "EISA Bridge",
-       .bus_id         = "eisa",
-};
-
 int eisa_driver_register (struct eisa_driver *edrv)
 {
 	int r;
@@ -109,7 +105,7 @@
 	if ((r = driver_register (&edrv->driver)) < 0)
 		return r;
 
-	return 1;
+	return 0;
 }
 
 void eisa_driver_unregister (struct eisa_driver *edrv)
@@ -125,7 +121,8 @@
 
 static DEVICE_ATTR(signature, S_IRUGO, eisa_show_sig, NULL);
 
-static void __init eisa_register_device (char *sig, int slot)
+static void __init eisa_register_device (struct eisa_root_device *root,
+					 char *sig, int slot)
 {
 	struct eisa_device *edev;
 
@@ -135,11 +132,11 @@
 	memset (edev, 0, sizeof (*edev));
 	memcpy (edev->id.sig, sig, 7);
 	edev->slot = slot;
-	edev->base_addr = 0x1000 * slot;
+	edev->base_addr = SLOT_ADDRESS (root, slot);
 	eisa_name_device (edev);
-	edev->dev.parent = &eisa_bus_root;
+	edev->dev.parent = root->dev;
 	edev->dev.bus = &eisa_bus_type;
-	sprintf (edev->dev.bus_id, "00:%02X", slot);
+	sprintf (edev->dev.bus_id, "%02X:%02X", root->bus_nr, slot);
 
 	/* Don't register resource for slot 0, since this will surely
 	 * fail... :-( */
@@ -150,7 +147,7 @@
 		edev->res.end   = edev->res.start + 0xfff;
 		edev->res.flags = IORESOURCE_IO;
 
-		if (request_resource (&ioport_resource, &edev->res)) {
+		if (request_resource (root->res, &edev->res)) {
 			printk (KERN_WARNING \
 				"Cannot allocate resource for EISA slot %d\n",
 				slot);
@@ -167,16 +164,18 @@
 	device_create_file (&edev->dev, &dev_attr_signature);
 }
 
-static int __init eisa_probe (void)
+static int __init eisa_probe (struct eisa_root_device *root)
 {
         int i, c;
         char *str;
-        unsigned long slot_addr;
+        unsigned long sig_addr;
 
-        printk (KERN_INFO "EISA: Probing bus...\n");
-        for (c = 0, i = 0; i <= EISA_MAX_SLOTS; i++) {
-                slot_addr = (0x1000 * i) + EISA_VENDOR_ID_OFFSET;
-                if ((str = decode_eisa_sig (slot_addr))) {
+        printk (KERN_INFO "EISA: Probing bus %d at %s\n",
+		root->bus_nr, root->dev->name);
+	
+        for (c = 0, i = 0; i <= root->slots; i++) {
+                sig_addr = SLOT_ADDRESS (root, i) + EISA_VENDOR_ID_OFFSET;
+                if ((str = decode_eisa_sig (sig_addr))) {
 			if (!i)
 				printk (KERN_INFO "EISA: Motherboard %s detected\n",
 					str);
@@ -187,7 +186,7 @@
 				c++;
 			}
 
-			eisa_register_device (str, i);
+			eisa_register_device (root, str, i);
                 }
         }
         printk (KERN_INFO "EISA: Detected %d card%s.\n", c, c < 2 ? "" : "s");
@@ -195,20 +194,40 @@
 	return 0;
 }
 
+
+static LIST_HEAD (eisa_root_head);
+
+static int eisa_bus_count;
+
+int eisa_root_register (struct eisa_root_device *root)
+{
+	struct list_head *node;
+	struct eisa_root_device *tmp_root;
+
+	/* Check if this bus base address has been already
+	 * registered. This prevents the virtual root device from
+	 * registering after the real one has, for example... */
+	
+	list_for_each (node, &eisa_root_head) {
+		tmp_root = list_entry (node, struct eisa_root_device, node);
+		if (tmp_root->bus_base_addr == root->bus_base_addr)
+			return -1; /* Space already taken, buddy... */
+	}
+	
+	root->bus_nr = eisa_bus_count++;
+	list_add_tail (&root->node, &eisa_root_head);
+	return eisa_probe (root);
+}
+
 static int __init eisa_init (void)
 {
 	int r;
 	
 	if ((r = bus_register (&eisa_bus_type)))
 		return r;
-	
-	if ((r = device_register (&eisa_bus_root))) {
-		bus_unregister (&eisa_bus_type);
-		return r;
-	}
 
 	printk (KERN_INFO "EISA bus registered\n");
-	return eisa_probe ();
+	return 0;
 }
 
 postcore_initcall (eisa_init);
diff -Nru a/drivers/eisa/pci_eisa.c b/drivers/eisa/pci_eisa.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/eisa/pci_eisa.c	Mon Feb 17 14:57:28 2003
@@ -0,0 +1,64 @@
+/*
+ * Minimalist driver for a generic PCI-to-EISA bridge.
+ *
+ * (C) 2003 Marc Zyngier <maz@wild-wind.fr.eu.org>
+ *
+ * This code is released under the GPL version 2.
+ *
+ * Ivan Kokshaysky <ink@jurassic.park.msu.ru> :
+ * Generalisation from i82375 to PCI_CLASS_BRIDGE_EISA.
+ */
+
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/eisa.h>
+#include <linux/pci.h>
+#include <linux/module.h>
+#include <linux/init.h>
+
+/* There is only *one* pci_eisa device per machine, right ? */
+static struct eisa_root_device pci_eisa_root;
+
+static int __devinit pci_eisa_init (struct pci_dev *pdev,
+				  const struct pci_device_id *ent)
+{
+	int rc;
+
+	if ((rc = pci_enable_device (pdev))) {
+		printk (KERN_ERR "pci_eisa : Could not enable device %s\n",
+			pdev->slot_name);
+		return rc;
+	}
+
+	pci_eisa_root.dev              = &pdev->dev;
+	pci_eisa_root.dev->driver_data = &pci_eisa_root;
+	pci_eisa_root.res	       = pdev->bus->resource[0];
+	pci_eisa_root.bus_base_addr    = pdev->bus->resource[0]->start;
+	pci_eisa_root.slots	       = EISA_MAX_SLOTS;
+
+	if (eisa_root_register (&pci_eisa_root)) {
+		printk (KERN_ERR "pci_eisa : Could not register EISA root\n");
+		return -1;
+	}
+
+	return 0;
+}
+
+static struct pci_device_id pci_eisa_pci_tbl[] = {
+	{ PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
+	  PCI_CLASS_BRIDGE_EISA << 8, 0xffff00, 0 },
+	{ 0, }
+};
+
+static struct pci_driver pci_eisa_driver = {
+	.name		= "pci_eisa",
+	.id_table	= pci_eisa_pci_tbl,
+	.probe		= pci_eisa_init,
+};
+
+static int __init pci_eisa_init_module (void)
+{
+	return pci_module_init (&pci_eisa_driver);
+}
+
+device_initcall(pci_eisa_init_module);
diff -Nru a/drivers/eisa/virtual_root.c b/drivers/eisa/virtual_root.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/eisa/virtual_root.c	Mon Feb 17 14:57:28 2003
@@ -0,0 +1,49 @@
+/*
+ * Virtual EISA root driver.
+ * Acts as a placeholder if we don't have a proper EISA bridge.
+ *
+ * (C) 2003 Marc Zyngier <maz@wild-wind.fr.eu.org>
+ *
+ * This code is released under the GPL version 2.
+ */
+
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/eisa.h>
+#include <linux/module.h>
+#include <linux/init.h>
+
+/* The default EISA device parent (virtual root device). */
+static struct device eisa_root_dev = {
+       .name        = "Virtual EISA Bridge",
+       .bus_id      = "eisa",
+};
+
+static struct eisa_root_device eisa_bus_root = {
+	.dev           = &eisa_root_dev,
+	.bus_base_addr = 0,
+	.res	       = &ioport_resource,
+	.slots	       = EISA_MAX_SLOTS,
+};
+
+static int virtual_eisa_root_init (void)
+{
+	int r;
+	
+        if ((r = device_register (&eisa_root_dev))) {
+                return r;
+        }
+
+	eisa_root_dev.driver_data = &eisa_bus_root;
+
+	if (eisa_root_register (&eisa_bus_root)) {
+		/* A real bridge may have been registered before
+		 * us. So quietly unregister. */
+		device_unregister (&eisa_root_dev);
+		return -1;
+	}
+
+	return 0;
+}
+
+device_initcall (virtual_eisa_root_init);
diff -Nru a/drivers/ide/pci/amd74xx.c b/drivers/ide/pci/amd74xx.c
--- a/drivers/ide/pci/amd74xx.c	Mon Feb 17 14:57:28 2003
+++ b/drivers/ide/pci/amd74xx.c	Mon Feb 17 14:57:28 2003
@@ -311,7 +311,7 @@
 			amd_80w = ((u & 0x3) ? 1 : 0) | ((u & 0xc) ? 2 : 0);
 			for (i = 24; i >= 0; i -= 8)
 				if (((u >> i) & 4) && !(amd_80w & (1 << (1 - (i >> 4))))) {
-					printk(KERN_WARNING "AMD_IDE: Bios didn't set cable bits corectly. Enabling workaround.\n");
+					printk(KERN_WARNING "AMD_IDE: Bios didn't set cable bits correctly. Enabling workaround.\n");
 					amd_80w |= (1 << (1 - (i >> 4)));
 				}
 			break;
diff -Nru a/drivers/ieee1394/Makefile b/drivers/ieee1394/Makefile
--- a/drivers/ieee1394/Makefile	Mon Feb 17 14:57:28 2003
+++ b/drivers/ieee1394/Makefile	Mon Feb 17 14:57:28 2003
@@ -18,6 +18,8 @@
 
 clean-files := oui.c
 
+ieee1394.o: $(ieee1394-objs)
+	$(LD) $(LDFLAGS) -r -o $@ $(ieee1394-objs)
 
 ifeq ($(obj),)
 obj = .
diff -Nru a/drivers/ieee1394/amdtp.c b/drivers/ieee1394/amdtp.c
--- a/drivers/ieee1394/amdtp.c	Mon Feb 17 14:57:27 2003
+++ b/drivers/ieee1394/amdtp.c	Mon Feb 17 14:57:27 2003
@@ -598,6 +598,8 @@
 	struct buffer *b;
 
 	b = kmalloc(sizeof *b + size, SLAB_KERNEL);
+	if (b == NULL)
+		return NULL;
 	b->head = 0;
 	b->tail = 0;
 	b->length = 0;
diff -Nru a/drivers/ieee1394/amdtp.h b/drivers/ieee1394/amdtp.h
--- a/drivers/ieee1394/amdtp.h	Mon Feb 17 14:57:27 2003
+++ b/drivers/ieee1394/amdtp.h	Mon Feb 17 14:57:27 2003
@@ -3,8 +3,8 @@
 #ifndef __AMDTP_H
 #define __AMDTP_H
 
-#include <asm/ioctl.h>
 #include <asm/types.h>
+#include "ieee1394-ioctl.h"
 
 /* The userspace interface for the Audio & Music Data Transmission
  * Protocol driver is really simple. First, open /dev/amdtp, use the
@@ -56,13 +56,6 @@
  *   | lsb | msb | lsb | msb | lsb | msb | lsb | msb | lsb | msb | ...
  *
  */
-
-/* We use '#' for our ioctl magic number because it's cool. */
-
-#define AMDTP_IOC_CHANNEL _IOW('#', 0, sizeof (struct amdtp_ioctl))
-#define AMDTP_IOC_PLUG    _IOW('#', 1, sizeof (struct amdtp_ioctl))
-#define AMDTP_IOC_PING    _IOW('#', 2, sizeof (struct amdtp_ioctl))
-#define AMDTP_IOC_ZAP     _IO('#', 3)
 
 enum {
 	AMDTP_FORMAT_RAW,
diff -Nru a/drivers/ieee1394/dma.c b/drivers/ieee1394/dma.c
--- a/drivers/ieee1394/dma.c	Mon Feb 17 14:57:27 2003
+++ b/drivers/ieee1394/dma.c	Mon Feb 17 14:57:27 2003
@@ -25,9 +25,8 @@
 int  dma_prog_region_alloc(struct dma_prog_region *prog, unsigned long n_bytes, struct pci_dev *dev)
 {
 	/* round up to page size */
-	if(n_bytes % PAGE_SIZE)
-		n_bytes += PAGE_SIZE - (n_bytes & PAGE_SIZE);
-	
+	n_bytes = round_up_to_page(n_bytes);
+
 	prog->n_pages = n_bytes / PAGE_SIZE;
 
 	prog->kvirt = pci_alloc_consistent(dev, prog->n_pages * PAGE_SIZE, &prog->bus_addr);
@@ -47,7 +46,7 @@
 	if(prog->kvirt) {
 		pci_free_consistent(prog->dev, prog->n_pages * PAGE_SIZE, prog->kvirt, prog->bus_addr);
 	}
-	
+
 	prog->kvirt = NULL;
 	prog->dev = NULL;
 	prog->n_pages = 0;
@@ -70,11 +69,10 @@
 	unsigned int i, n_pages;
 
 	/* round up to page size */
-	if(n_bytes % PAGE_SIZE)
-		n_bytes += PAGE_SIZE - (n_bytes & PAGE_SIZE);
-	
+	n_bytes = round_up_to_page(n_bytes);
+
 	n_pages = n_bytes / PAGE_SIZE;
-	
+
 	dma->kvirt = vmalloc_32(n_pages * PAGE_SIZE);
 	if(!dma->kvirt) {
 		printk(KERN_ERR "dma_region_alloc: vmalloc_32() failed\n");
@@ -82,7 +80,7 @@
 	}
 
 	dma->n_pages = n_pages;
-	
+
 	/* Clear the ram out, no junk to the user */
 	memset(dma->kvirt, 0, n_pages * PAGE_SIZE);
 
@@ -114,7 +112,7 @@
 
 	dma->dev = dev;
 	dma->direction = direction;
-	
+
 	return 0;
 
 err:
@@ -148,7 +146,7 @@
 {
 	int i;
 	unsigned long off = offset;
-	
+
 	for(i = 0; i < dma->n_dma_pages; i++) {
 		if(off < sg_dma_len(&dma->sglist[i])) {
 			*rem = off;
@@ -157,14 +155,14 @@
 
 		off -= sg_dma_len(&dma->sglist[i]);
 	}
-	
+
 	panic("dma_region_find: offset %lu beyond end of DMA mapping\n", offset);
 }
 
 dma_addr_t dma_region_offset_to_bus(struct dma_region *dma, unsigned long offset)
 {
 	unsigned long rem;
-	
+
 	struct scatterlist *sg = &dma->sglist[dma_region_find(dma, offset, &rem)];
 	return sg_dma_address(sg) + rem;
 }
@@ -176,10 +174,10 @@
 
 	if(!len)
 		len = 1;
-	
+
 	first = dma_region_find(dma, offset, &rem);
 	last = dma_region_find(dma, offset + len - 1, &rem);
-	
+
 	pci_dma_sync_sg(dma->dev, &dma->sglist[first], last - first + 1, dma->direction);
 }
 
@@ -210,13 +208,13 @@
 }
 
 static struct vm_operations_struct dma_region_vm_ops = {
-	nopage: dma_region_pagefault,
+	.nopage	= dma_region_pagefault,
 };
 
 int dma_region_mmap(struct dma_region *dma, struct file *file, struct vm_area_struct *vma)
 {
 	unsigned long size;
-	
+
 	if(!dma->kvirt)
 		return -EINVAL;
 
@@ -233,6 +231,6 @@
 	vma->vm_private_data = dma;
 	vma->vm_file = file;
 	vma->vm_flags |= VM_RESERVED;
-	
+
 	return 0;
 }
diff -Nru a/drivers/ieee1394/dma.h b/drivers/ieee1394/dma.h
--- a/drivers/ieee1394/dma.h	Mon Feb 17 14:57:28 2003
+++ b/drivers/ieee1394/dma.h	Mon Feb 17 14:57:28 2003
@@ -73,4 +73,12 @@
    relative to the beginning of the dma_region */
 dma_addr_t dma_region_offset_to_bus(struct dma_region *dma, unsigned long offset);
 
+/* round up a number of bytes to be a multiple of the PAGE_SIZE */
+static inline unsigned long round_up_to_page(unsigned long len)
+{
+	if(len % PAGE_SIZE)
+		len += PAGE_SIZE - (len % PAGE_SIZE);
+	return len;
+}
+
 #endif /* IEEE1394_DMA_H */
diff -Nru a/drivers/ieee1394/dv1394.c b/drivers/ieee1394/dv1394.c
--- a/drivers/ieee1394/dv1394.c	Mon Feb 17 14:57:27 2003
+++ b/drivers/ieee1394/dv1394.c	Mon Feb 17 14:57:28 2003
@@ -918,6 +918,7 @@
 	u64 chan_mask;
 	int retval = -EINVAL;
 
+	debug_printk( "dv1394: initialising %d\n", video->id );
 	if(init->api_version != DV1394_API_VERSION)
 		goto err;
 	
@@ -1186,6 +1187,7 @@
 			if( (reg_read(video->ohci, video->ohci_IsoXmitContextControlClear) & (1 << 10)) ||
 			    (reg_read(video->ohci, video->ohci_IsoRcvContextControlClear)  & (1 << 10)) ) {
 				/* still active */
+				debug_printk("dv1394: stop_dma: DMA not stopped yet\n" );
 				mb();
 			} else {
 				debug_printk("dv1394: stop_dma: DMA stopped safely after %d ms\n", i/10);
@@ -1199,7 +1201,9 @@
 			printk(KERN_ERR "dv1394: stop_dma: DMA still going after %d ms!\n", i/10);
 		}
 	}
-
+	else
+		debug_printk("dv1394: stop_dma: already stopped.\n");
+		
 	spin_unlock_irqrestore(&video->spinlock, flags);
 }
 
@@ -1226,7 +1230,8 @@
 		/* disable interrupts for IT context */
 		reg_write(video->ohci, OHCI1394_IsoXmitIntMaskClear, (1 << video->ohci_it_ctx));
 		
-		clear_bit(video->ohci_it_ctx, &video->ohci->it_ctx_usage);
+		/* remove tasklet */
+		ohci1394_unregister_iso_tasklet(video->ohci, &video->it_tasklet);
 		debug_printk("dv1394: IT context %d released\n", video->ohci_it_ctx);
 		video->ohci_it_ctx = -1;
 	}
@@ -1240,23 +1245,14 @@
 		/* disable interrupts for IR context */
 		reg_write(video->ohci, OHCI1394_IsoRecvIntMaskClear, (1 << video->ohci_ir_ctx));
 
-		clear_bit(video->ohci_ir_ctx, &video->ohci->ir_ctx_usage);
+		/* remove tasklet */
+		ohci1394_unregister_iso_tasklet(video->ohci, &video->ir_tasklet);
 		debug_printk("dv1394: IR context %d released\n", video->ohci_ir_ctx);
 		video->ohci_ir_ctx = -1;
 	}
 
 	spin_unlock_irqrestore(&video->spinlock, flags);
 
-	/* remove tasklets */
-	if(video->ohci_it_ctx != -1) {
-		ohci1394_unregister_iso_tasklet(video->ohci, &video->it_tasklet);
-		video->ohci_it_ctx = -1;
-	}
-	if(video->ohci_ir_ctx != -1) {
-		ohci1394_unregister_iso_tasklet(video->ohci, &video->ir_tasklet);
-		video->ohci_ir_ctx = -1;
-	}
-	
 	/* release the ISO channel */
 	if(video->channel != -1) {
 		u64 chan_mask;
@@ -1612,7 +1608,7 @@
 
 	switch(cmd)
 	{
-	case DV1394_SUBMIT_FRAMES: {
+	case DV1394_IOC_SUBMIT_FRAMES: {
 		unsigned int n_submit;
 
 		if( !video_card_initialized(video) ) {
@@ -1666,7 +1662,7 @@
 		break;
 	}
 
-	case DV1394_WAIT_FRAMES: {
+	case DV1394_IOC_WAIT_FRAMES: {
 		unsigned int n_wait;
 
 		if( !video_card_initialized(video) ) {
@@ -1715,7 +1711,7 @@
 		break;
 	}
 
-	case DV1394_RECEIVE_FRAMES: {
+	case DV1394_IOC_RECEIVE_FRAMES: {
 		unsigned int n_recv;
 
 		if( !video_card_initialized(video) ) {
@@ -1748,7 +1744,7 @@
 		break;
 	}
 
-	case DV1394_START_RECEIVE: {
+	case DV1394_IOC_START_RECEIVE: {
 		if( !video_card_initialized(video) ) {
 			ret = do_dv1394_init_default(video);
 			if(ret)
@@ -1765,7 +1761,7 @@
 		break;
 	}
 
-	case DV1394_INIT: {
+	case DV1394_IOC_INIT: {
 		struct dv1394_init init;
 		if(arg == (unsigned long) NULL) {
 			ret = do_dv1394_init_default(video);
@@ -1779,12 +1775,12 @@
 		break;
 	}
 
-	case DV1394_SHUTDOWN:
+	case DV1394_IOC_SHUTDOWN:
 		ret = do_dv1394_shutdown(video, 0);
 		break;
 
 
-        case DV1394_GET_STATUS: {
+        case DV1394_IOC_GET_STATUS: {
 		struct dv1394_status status;
 
 		if( !video_card_initialized(video) ) {
@@ -2346,6 +2342,7 @@
 				dbc = (int) (p->cip_h1 >> 24);
 				if ( video->continuity_counter != -1 && dbc > ((video->continuity_counter + 1) % 256) )
 				{
+					printk(KERN_WARNING "dv1394: discontinuity detected, dropping all frames\n" );
 					video->dropped_frames += video->n_clear_frames + 1;
 					video->first_frame = 0;
 					video->n_clear_frames = 0;
@@ -2364,9 +2361,8 @@
 					video->n_clear_frames++;
 					if (video->n_clear_frames > video->n_frames) {
 						video->dropped_frames++;
-						video->n_clear_frames--;
-						if (video->n_clear_frames < 0)
-							video->n_clear_frames = 0;
+						printk(KERN_WARNING "dv1394: dropped a frame during reception\n" );
+						video->n_clear_frames = video->n_frames-1;
 						video->first_clear_frame = (video->first_clear_frame + 1) % video->n_frames;
 					}
 					if (video->first_clear_frame == -1)
@@ -2375,7 +2371,6 @@
 					/* get the next frame */
 					video->active_frame = (video->active_frame + 1) % video->n_frames;
 					f = video->frames[video->active_frame];
-				
 					irq_printk("   frame received, active_frame = %d, n_clear_frames = %d, first_clear_frame = %d\n",
 						   video->active_frame, video->n_clear_frames, video->first_clear_frame);
 				}
diff -Nru a/drivers/ieee1394/dv1394.h b/drivers/ieee1394/dv1394.h
--- a/drivers/ieee1394/dv1394.h	Mon Feb 17 14:57:28 2003
+++ b/drivers/ieee1394/dv1394.h	Mon Feb 17 14:57:28 2003
@@ -200,48 +200,7 @@
 
 
 /* ioctl() commands */
-
-enum {
-	/* I don't like using 0 as a valid ioctl() */
-	DV1394_INVALID = 0,
-
-
-	/* get the driver ready to transmit video.
-	   pass a struct dv1394_init* as the parameter (see below),
-	   or NULL to get default parameters */
-	DV1394_INIT,
-
-
-	/* stop transmitting video and free the ringbuffer */
-	DV1394_SHUTDOWN,
-
-
-	/* submit N new frames to be transmitted, where
-	   the index of the first new frame is first_clear_buffer,
-	   and the index of the last new frame is
-	   (first_clear_buffer + N) % n_frames */
-	DV1394_SUBMIT_FRAMES,
-
-
-	/* block until N buffers are clear (pass N as the parameter)
-	   Because we re-transmit the last frame on underrun, there
-	   will at most be n_frames - 1 clear frames at any time */
-	DV1394_WAIT_FRAMES,
-
-	/* capture new frames that have been received, where
-	   the index of the first new frame is first_clear_buffer,
-	   and the index of the last new frame is
-	   (first_clear_buffer + N) % n_frames */
-	DV1394_RECEIVE_FRAMES,
-
-
-	DV1394_START_RECEIVE,
-
-
-	/* pass a struct dv1394_status* as the parameter (see below) */
-	DV1394_GET_STATUS,
-};
-
+#include "ieee1394-ioctl.h"
 
 
 enum pal_or_ntsc {
diff -Nru a/drivers/ieee1394/eth1394.c b/drivers/ieee1394/eth1394.c
--- a/drivers/ieee1394/eth1394.c	Mon Feb 17 14:57:27 2003
+++ b/drivers/ieee1394/eth1394.c	Mon Feb 17 14:57:27 2003
@@ -77,7 +77,7 @@
 	printk(KERN_ERR fmt, ## args)
 
 static char version[] __devinitdata =
-	"$Rev: 641 $ Ben Collins <bcollins@debian.org>";
+	"$Rev: 770 $ Ben Collins <bcollins@debian.org>";
 
 /* Our ieee1394 highlevel driver */
 #define ETHER1394_DRIVER_NAME "ether1394"
@@ -368,6 +368,7 @@
 	if (register_netdev (dev)) {
 		ETH1394_PRINT (KERN_ERR, dev->name, "Error registering network driver\n");
 		kfree (dev);
+		kfree (hi);
 		return;
 	}
 
diff -Nru a/drivers/ieee1394/highlevel.c b/drivers/ieee1394/highlevel.c
--- a/drivers/ieee1394/highlevel.c	Mon Feb 17 14:57:28 2003
+++ b/drivers/ieee1394/highlevel.c	Mon Feb 17 14:57:28 2003
@@ -164,17 +164,19 @@
         return retval;
 }
 
-void hpsb_listen_channel(struct hpsb_highlevel *hl, struct hpsb_host *host,
+int hpsb_listen_channel(struct hpsb_highlevel *hl, struct hpsb_host *host,
                          unsigned int channel)
 {
         if (channel > 63) {
                 HPSB_ERR("%s called with invalid channel", __FUNCTION__);
-                return;
+                return -EINVAL;
         }
 
         if (host->iso_listen_count[channel]++ == 0) {
-                host->driver->devctl(host, ISO_LISTEN_CHANNEL, channel);
+                return host->driver->devctl(host, ISO_LISTEN_CHANNEL, channel);
         }
+
+	return 0;
 }
 
 void hpsb_unlisten_channel(struct hpsb_highlevel *hl, struct hpsb_host *host, 
diff -Nru a/drivers/ieee1394/highlevel.h b/drivers/ieee1394/highlevel.h
--- a/drivers/ieee1394/highlevel.h	Mon Feb 17 14:57:27 2003
+++ b/drivers/ieee1394/highlevel.h	Mon Feb 17 14:57:27 2003
@@ -150,8 +150,8 @@
  * Enable or disable receving a certain isochronous channel through the
  * iso_receive op.
  */
-void hpsb_listen_channel(struct hpsb_highlevel *hl, struct hpsb_host *host, 
-                         unsigned int channel);
+int hpsb_listen_channel(struct hpsb_highlevel *hl, struct hpsb_host *host, 
+			unsigned int channel);
 void hpsb_unlisten_channel(struct hpsb_highlevel *hl, struct hpsb_host *host,
                            unsigned int channel);
 
diff -Nru a/drivers/ieee1394/hosts.c b/drivers/ieee1394/hosts.c
--- a/drivers/ieee1394/hosts.c	Mon Feb 17 14:57:27 2003
+++ b/drivers/ieee1394/hosts.c	Mon Feb 17 14:57:27 2003
@@ -38,9 +38,15 @@
         return -1;
 }
 
+static int dummy_isoctl(struct hpsb_iso *iso, enum isoctl_cmd command, unsigned long arg)
+{
+	return -1;
+}
+
 static struct hpsb_host_driver dummy_driver = {
         .transmit_packet = dummy_transmit_packet,
-        .devctl =          dummy_devctl
+        .devctl =          dummy_devctl,
+	.isoctl =          dummy_isoctl
 };
 
 /**
@@ -63,9 +69,11 @@
         spin_lock_irqsave(&hosts_lock, flags);
         list_for_each(lh, &hosts) {
                 if (host == list_entry(lh, struct hpsb_host, host_list)) {
-                        host->driver->devctl(host, MODIFY_USAGE, 1);
-			host->refcount++;
-                        retval = 1;
+			if (host->driver->devctl(host, MODIFY_USAGE, 1)) {
+				host->driver->devctl(host, MODIFY_USAGE, 1);
+				host->refcount++;
+				retval = 1;
+			}
 			break;
         	}
         }
diff -Nru a/drivers/ieee1394/hosts.h b/drivers/ieee1394/hosts.h
--- a/drivers/ieee1394/hosts.h	Mon Feb 17 14:57:27 2003
+++ b/drivers/ieee1394/hosts.h	Mon Feb 17 14:57:27 2003
@@ -108,19 +108,22 @@
 enum isoctl_cmd {
 	/* rawiso API - see iso.h for the meanings of these commands
 	 * INIT = allocate resources
-	 * START = begin transmission/reception (arg: cycle to start on)
+	 * START = begin transmission/reception
 	 * STOP = halt transmission/reception
-	 * QUEUE/RELEASE = produce/consume packets (arg: # of packets)
+	 * QUEUE/RELEASE = produce/consume packets
 	 * SHUTDOWN = deallocate resources
 	 */
-	
+
 	XMIT_INIT,
 	XMIT_START,
 	XMIT_STOP,
 	XMIT_QUEUE,
 	XMIT_SHUTDOWN,
-	
+
 	RECV_INIT,
+	RECV_LISTEN_CHANNEL,   /* multi-channel only */
+	RECV_UNLISTEN_CHANNEL, /* multi-channel only */
+	RECV_SET_CHANNEL_MASK, /* multi-channel only; arg is a *u64 */
 	RECV_START,
 	RECV_STOP,
 	RECV_RELEASE,
@@ -170,11 +173,12 @@
          */
         int (*devctl) (struct hpsb_host *host, enum devctl_cmd command, int arg);
 
-	 /* ISO transmission/reception functions. Return 0 on success, -1 on failure.
-	  * If the low-level driver does not support the new ISO API, set isoctl to NULL.
+	 /* ISO transmission/reception functions. Return 0 on success, -1
+	  * (or -EXXX errno code) on failure. If the low-level driver does not
+	  * support the new ISO API, set isoctl to NULL.
 	  */
-	int (*isoctl) (struct hpsb_iso *iso, enum isoctl_cmd command, int arg);
-	
+	int (*isoctl) (struct hpsb_iso *iso, enum isoctl_cmd command, unsigned long arg);
+
         /* This function is mainly to redirect local CSR reads/locks to the iso
          * management registers (bus manager id, bandwidth available, channels
          * available) to the hardware registers in OHCI.  reg is 0,1,2,3 for bus
diff -Nru a/drivers/ieee1394/ieee1394-ioctl.h b/drivers/ieee1394/ieee1394-ioctl.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/ieee1394/ieee1394-ioctl.h	Mon Feb 17 14:57:28 2003
@@ -0,0 +1,105 @@
+/* Base file for all ieee1394 ioctl's. Linux-1394 has allocated base '#'
+ * with a range of 0x00-0x3f. */
+
+#ifndef __IEEE1394_IOCTL_H
+#define __IEEE1394_IOCTL_H
+
+#include <asm/ioctl.h>
+#include <asm/types.h>
+
+
+/* AMDTP Gets 6 */
+#define AMDTP_IOC_CHANNEL	_IOW('#', 0x00, struct amdtp_ioctl)
+#define AMDTP_IOC_PLUG		_IOW('#', 0x01, struct amdtp_ioctl)
+#define AMDTP_IOC_PING		_IOW('#', 0x02, struct amdtp_ioctl)
+#define AMDTP_IOC_ZAP		_IO ('#', 0x03)
+
+
+/* DV1394 Gets 10 */
+
+/* Get the driver ready to transmit video.  pass a struct dv1394_init* as
+ * the parameter (see below), or NULL to get default parameters */
+#define DV1394_IOC_INIT			_IOW('#', 0x06, struct dv1394_init)
+
+/* Stop transmitting video and free the ringbuffer */
+#define DV1394_IOC_SHUTDOWN		_IO ('#', 0x07)
+
+/* Submit N new frames to be transmitted, where the index of the first new
+ * frame is first_clear_buffer, and the index of the last new frame is
+ * (first_clear_buffer + N) % n_frames */
+#define DV1394_IOC_SUBMIT_FRAMES	_IO ('#', 0x08)
+
+/* Block until N buffers are clear (pass N as the parameter) Because we
+ * re-transmit the last frame on underrun, there will at most be n_frames
+ * - 1 clear frames at any time */
+#define DV1394_IOC_WAIT_FRAMES		_IO ('#', 0x09)
+
+/* Capture new frames that have been received, where the index of the
+ * first new frame is first_clear_buffer, and the index of the last new
+ * frame is (first_clear_buffer + N) % n_frames */
+#define DV1394_IOC_RECEIVE_FRAMES	_IO ('#', 0x0a)
+
+/* Tell card to start receiving DMA */
+#define DV1394_IOC_START_RECEIVE	_IO ('#', 0x0b)
+
+/* Pass a struct dv1394_status* as the parameter */
+#define DV1394_IOC_GET_STATUS		_IOR('#', 0x0c, struct dv1394_status)
+
+
+/* Video1394 Gets 10 */
+
+#define VIDEO1394_IOC_LISTEN_CHANNEL		\
+	_IOWR('#', 0x10, struct video1394_mmap)
+#define VIDEO1394_IOC_UNLISTEN_CHANNEL		\
+	_IOW ('#', 0x11, int)
+#define VIDEO1394_IOC_LISTEN_QUEUE_BUFFER	\
+	_IOW ('#', 0x12, struct video1394_wait)
+#define VIDEO1394_IOC_LISTEN_WAIT_BUFFER	\
+	_IOWR('#', 0x13, struct video1394_wait)
+#define VIDEO1394_IOC_TALK_CHANNEL		\
+	_IOWR('#', 0x14, struct video1394_mmap)
+#define VIDEO1394_IOC_UNTALK_CHANNEL		\
+	_IOW ('#', 0x15, int)
+#define VIDEO1394_IOC_TALK_QUEUE_BUFFER 	\
+	_IOW ('#', 0x16, sizeof (struct video1394_wait) + \
+		sizeof (struct video1394_queue_variable))
+#define VIDEO1394_IOC_TALK_WAIT_BUFFER		\
+	_IOW ('#', 0x17, struct video1394_wait)
+#define VIDEO1394_IOC_LISTEN_POLL_BUFFER	\
+	_IOWR('#', 0x18, struct video1394_wait)
+
+
+/* Raw1394's ISO interface */
+#define RAW1394_IOC_ISO_XMIT_INIT		\
+	_IOW ('#', 0x1a, struct raw1394_iso_status)
+#define RAW1394_IOC_ISO_RECV_INIT		\
+	_IOWR('#', 0x1b, struct raw1394_iso_status)
+#define RAW1394_IOC_ISO_RECV_START		\
+	_IOC (_IOC_WRITE, '#', 0x1c, sizeof(int) * 3)
+#define RAW1394_IOC_ISO_XMIT_START		\
+	_IOC (_IOC_WRITE, '#', 0x1d, sizeof(int) * 2)
+#define RAW1394_IOC_ISO_XMIT_RECV_STOP		\
+	_IO  ('#', 0x1e)
+#define RAW1394_IOC_ISO_GET_STATUS		\
+	_IOR ('#', 0x1f, struct raw1394_iso_status)
+#define RAW1394_IOC_ISO_SHUTDOWN		\
+	_IO  ('#', 0x20)
+#define RAW1394_IOC_ISO_QUEUE_ACTIVITY		\
+	_IO  ('#', 0x21)
+#define RAW1394_IOC_ISO_RECV_LISTEN_CHANNEL	\
+	_IOW ('#', 0x22, unsigned char)
+#define RAW1394_IOC_ISO_RECV_UNLISTEN_CHANNEL	\
+	_IOW ('#', 0x23, unsigned char)
+#define RAW1394_IOC_ISO_RECV_SET_CHANNEL_MASK	\
+	_IOW ('#', 0x24, u64)
+#define RAW1394_IOC_ISO_RECV_PACKETS		\
+	_IOW ('#', 0x25, struct raw1394_iso_packets)
+#define RAW1394_IOC_ISO_RECV_RELEASE_PACKETS	\
+	_IOW ('#', 0x26, unsigned int)
+#define RAW1394_IOC_ISO_XMIT_PACKETS		\
+	_IOW ('#', 0x27, struct raw1394_iso_packets)
+#define RAW1394_IOC_ISO_XMIT_SYNC		\
+	_IO  ('#', 0x28)
+
+
+#endif /* __IEEE1394_IOCTL_H */
diff -Nru a/drivers/ieee1394/ieee1394_core.c b/drivers/ieee1394/ieee1394_core.c
--- a/drivers/ieee1394/ieee1394_core.c	Mon Feb 17 14:57:27 2003
+++ b/drivers/ieee1394/ieee1394_core.c	Mon Feb 17 14:57:27 2003
@@ -1000,7 +1000,7 @@
 			      struct file_operations *file_ops)
 {
 	int retval;
-	
+
 	if( (blocknum < 0) || (blocknum > 15) )
 		return -EINVAL;
 
@@ -1016,7 +1016,7 @@
 		/* block already taken */
 		retval = -EBUSY;
 	}
-	
+
 	write_unlock(&ieee1394_chardevs_lock);
 
 	return retval;
@@ -1027,14 +1027,14 @@
 {
 	if( (blocknum < 0) || (blocknum > 15) )
 		return;
-	
+
 	write_lock(&ieee1394_chardevs_lock);
-	
+
 	if(ieee1394_chardevs[blocknum].file_ops) {
 		ieee1394_chardevs[blocknum].file_ops = NULL;
 		ieee1394_chardevs[blocknum].module = NULL;
 	}
-	
+
 	write_unlock(&ieee1394_chardevs_lock);
 }
 
@@ -1055,7 +1055,7 @@
 {
 	int ret = 0;
        
-	if( (blocknum < 0) || (blocknum > 15) )
+	if ((blocknum < 0) || (blocknum > 15))
 		return ret;
 
 	read_lock(&ieee1394_chardevs_lock);
@@ -1063,15 +1063,15 @@
 	*module = ieee1394_chardevs[blocknum].module;
 	*file_ops = ieee1394_chardevs[blocknum].file_ops;
 
-	if(*file_ops == NULL)
+	if (*file_ops == NULL)
 		goto out;
 
-	if(!try_module_get(*module))
+	if (!try_module_get(*module))
 		goto out;
 
 	/* success! */
 	ret = 1;
-	
+
 out:
 	read_unlock(&ieee1394_chardevs_lock);
 	return ret;
@@ -1101,11 +1101,11 @@
 	  reference count of whatever module file->f_op->owner points
 	  to, immediately after this function returns.
 	*/
-	
+
         /* shift away lower four bits of the minor
 	   to get the index of the ieee1394_driver
 	   we want */
-	
+
 	blocknum = (minor(inode->i_rdev) >> 4) & 0xF;
 
 	/* look up the driver */
@@ -1126,14 +1126,14 @@
 	if(retval == 0) {
 		
 		/* If the open() succeeded, then ieee1394 will be left
-		   with an extra module reference, so we discard it here.
+		 * with an extra module reference, so we discard it here.
+		 *
+		 * The task-specific driver still has the extra reference
+		 * given to it by ieee1394_get_chardev(). This extra
+		 * reference prevents the module from unloading while the
+		 * file is open, and will be dropped by the VFS when the
+		 * file is released. */
 
-		   The task-specific driver still has the extra
-		   reference given to it by ieee1394_get_chardev().
-		   This extra reference prevents the module from
-		   unloading while the file is open, and will be
-		   dropped by the VFS when the file is released.
-		*/
 		module_put(THIS_MODULE);
 	} else {
 		/* point the file's f_ops back to ieee1394. The VFS will then
@@ -1142,11 +1142,10 @@
 		
 		file->f_op = &ieee1394_chardev_ops;
 
-		/* if the open() failed, then we need to drop the
-		   extra reference we gave to the task-specific
-		   driver */
+		/* If the open() failed, then we need to drop the extra
+		 * reference we gave to the task-specific driver. */
+
 		module_put(module);
-	
 	}
 
 	return retval;
@@ -1199,10 +1198,10 @@
 	kmem_cache_destroy(hpsb_packet_cache);
 
 	unregister_chrdev(IEEE1394_MAJOR, "ieee1394");
-	
+
 	/* it's ok to pass a NULL devfs_handle to devfs_unregister */
 	devfs_unregister(ieee1394_devfs_handle);
-	
+
 	remove_proc_entry("ieee1394", proc_bus);
 }
 
@@ -1298,10 +1297,16 @@
 EXPORT_SYMBOL(hpsb_iso_recv_init);
 EXPORT_SYMBOL(hpsb_iso_xmit_start);
 EXPORT_SYMBOL(hpsb_iso_recv_start);
+EXPORT_SYMBOL(hpsb_iso_recv_listen_channel);
+EXPORT_SYMBOL(hpsb_iso_recv_unlisten_channel);
+EXPORT_SYMBOL(hpsb_iso_recv_set_channel_mask);
 EXPORT_SYMBOL(hpsb_iso_stop);
 EXPORT_SYMBOL(hpsb_iso_shutdown);
-EXPORT_SYMBOL(hpsb_iso_xmit_queue_packets);
+EXPORT_SYMBOL(hpsb_iso_xmit_queue_packet);
+EXPORT_SYMBOL(hpsb_iso_xmit_sync);
 EXPORT_SYMBOL(hpsb_iso_recv_release_packets);
 EXPORT_SYMBOL(hpsb_iso_n_ready);
-EXPORT_SYMBOL(hpsb_iso_packet_data);
-EXPORT_SYMBOL(hpsb_iso_packet_info);
+EXPORT_SYMBOL(hpsb_iso_packet_sent);
+EXPORT_SYMBOL(hpsb_iso_packet_received);
+EXPORT_SYMBOL(hpsb_iso_wake);
+
diff -Nru a/drivers/ieee1394/iso.c b/drivers/ieee1394/iso.c
--- a/drivers/ieee1394/iso.c	Mon Feb 17 14:57:28 2003
+++ b/drivers/ieee1394/iso.c	Mon Feb 17 14:57:28 2003
@@ -17,7 +17,8 @@
 	if(!iso->flags & HPSB_ISO_DRIVER_STARTED)
 		return;
 
-	iso->host->driver->isoctl(iso, iso->type == HPSB_ISO_XMIT ? XMIT_STOP : RECV_STOP, 0);
+	iso->host->driver->isoctl(iso, iso->type == HPSB_ISO_XMIT ?
+				  XMIT_STOP : RECV_STOP, 0);
 	iso->flags &= ~HPSB_ISO_DRIVER_STARTED;
 }
 
@@ -25,94 +26,84 @@
 {
 	if(iso->flags & HPSB_ISO_DRIVER_INIT) {
 		hpsb_iso_stop(iso);
-		iso->host->driver->isoctl(iso, iso->type == HPSB_ISO_XMIT ? XMIT_SHUTDOWN : RECV_SHUTDOWN, 0);
+		iso->host->driver->isoctl(iso, iso->type == HPSB_ISO_XMIT ?
+					  XMIT_SHUTDOWN : RECV_SHUTDOWN, 0);
 		iso->flags &= ~HPSB_ISO_DRIVER_INIT;
 	}
-	
-	dma_region_free(&iso->buf);
+
+	dma_region_free(&iso->data_buf);
+	kfree(iso->infos);
 	kfree(iso);
 }
 
 static struct hpsb_iso* hpsb_iso_common_init(struct hpsb_host *host, enum hpsb_iso_type type,
+					     unsigned int data_buf_size,
 					     unsigned int buf_packets,
-					     unsigned int max_packet_size,
 					     int channel,
 					     int irq_interval,
 					     void (*callback)(struct hpsb_iso*))
 {
 	struct hpsb_iso *iso;
-	unsigned int packet_plus_info;
 	int dma_direction;
-	int iso_header_bytes;
-	const int info_bytes = sizeof(struct hpsb_iso_packet_info);
-	
+
 	/* make sure driver supports the ISO API */
 	if(!host->driver->isoctl)
 		return NULL;
 
-	if(type == HPSB_ISO_RECV) {
-		/* when receiving, leave 8 extra bytes in front
-		   of the data payload for the iso header */
-		iso_header_bytes = 8;
-	} else {
-		iso_header_bytes = 0;
-	}
-	
 	/* sanitize parameters */
-	
+
 	if(buf_packets < 2)
 		buf_packets = 2;
-	
+
 	if(irq_interval < 1 || irq_interval > buf_packets / 2)
 		irq_interval = buf_packets / 2;
-	
-	if(max_packet_size + info_bytes + iso_header_bytes > PAGE_SIZE)
+
+	if(channel < -1 || channel >= 64)
+		return NULL;
+
+	/* channel = -1 is OK for multi-channel recv but not for xmit */
+	if(type == HPSB_ISO_XMIT && channel < 0)
 		return NULL;
-	
-	/* size of packet payload plus the per-packet info must be a power of 2
-	   and at most equal to the page size */
-	
-	for(packet_plus_info = 256; packet_plus_info < PAGE_SIZE; packet_plus_info *= 2) {
-		if(packet_plus_info >= (max_packet_size + info_bytes + iso_header_bytes)) {
-			break;
-		}
-	}
 
 	/* allocate and write the struct hpsb_iso */
-	
+
 	iso = kmalloc(sizeof(*iso), SLAB_KERNEL);
 	if(!iso)
 		return NULL;
-	
+
+	/* allocate ringbuffer of packet descriptors */
+	iso->infos = kmalloc(buf_packets * sizeof(struct hpsb_iso_packet_info), SLAB_KERNEL);
+	if(!iso->infos)
+		return NULL;
+
 	iso->type = type;
 	iso->host = host;
 	iso->hostdata = NULL;
 	iso->callback = callback;
+	init_waitqueue_head(&iso->waitq);
 	iso->channel = channel;
 	iso->irq_interval = irq_interval;
-	dma_region_init(&iso->buf);
+	dma_region_init(&iso->data_buf);
+	iso->buf_size = round_up_to_page(data_buf_size);
 	iso->buf_packets = buf_packets;
-	iso->buf_stride = packet_plus_info;
-	iso->max_packet_size = max_packet_size;
-	iso->packet_data_offset = iso_header_bytes;
-	iso->packet_info_offset = iso_header_bytes + max_packet_size;
+	iso->pkt_dma = 0;
 	iso->first_packet = 0;
+	spin_lock_init(&iso->lock);
 
 	if(iso->type == HPSB_ISO_XMIT) {
-		atomic_set(&iso->n_dma_packets, 0);
+		iso->n_ready_packets = iso->buf_packets;
 		dma_direction = PCI_DMA_TODEVICE;
 	} else {
-		atomic_set(&iso->n_dma_packets, iso->buf_packets);
+		iso->n_ready_packets = 0;
 		dma_direction = PCI_DMA_FROMDEVICE;
 	}
-	
+
 	atomic_set(&iso->overflows, 0);
 	iso->flags = 0;
 	iso->prebuffer = 0;
-	
+
 	/* allocate the packet buffer */
-	if(dma_region_alloc(&iso->buf, iso->buf_packets * iso->buf_stride,
-			    host->pdev, dma_direction))
+	if(dma_region_alloc(&iso->data_buf, iso->buf_size, host->pdev, dma_direction))
 		goto err;
 
 	return iso;
@@ -124,26 +115,33 @@
 
 int hpsb_iso_n_ready(struct hpsb_iso* iso)
 {
-	return iso->buf_packets - atomic_read(&iso->n_dma_packets);
+	unsigned long flags;
+	int val;
+
+	spin_lock_irqsave(&iso->lock, flags);
+	val = iso->n_ready_packets;
+	spin_unlock_irqrestore(&iso->lock, flags);
+
+	return val;
 }
-	
+
 
 struct hpsb_iso* hpsb_iso_xmit_init(struct hpsb_host *host,
+				    unsigned int data_buf_size,
 				    unsigned int buf_packets,
-				    unsigned int max_packet_size,
 				    int channel,
 				    int speed,
 				    int irq_interval,
 				    void (*callback)(struct hpsb_iso*))
 {
 	struct hpsb_iso *iso = hpsb_iso_common_init(host, HPSB_ISO_XMIT,
-						    buf_packets, max_packet_size,
+						    data_buf_size, buf_packets,
 						    channel, irq_interval, callback);
 	if(!iso)
 		return NULL;
 
 	iso->speed = speed;
-	
+
 	/* tell the driver to start working */
 	if(host->driver->isoctl(iso, XMIT_INIT, 0))
 		goto err;
@@ -157,14 +155,14 @@
 }
 
 struct hpsb_iso* hpsb_iso_recv_init(struct hpsb_host *host,
+				    unsigned int data_buf_size,
 				    unsigned int buf_packets,
-				    unsigned int max_packet_size,
 				    int channel,
 				    int irq_interval,
 				    void (*callback)(struct hpsb_iso*))
 {
 	struct hpsb_iso *iso = hpsb_iso_common_init(host, HPSB_ISO_RECV,
-						    buf_packets, max_packet_size,
+						    data_buf_size, buf_packets,
 						    channel, irq_interval, callback);
 	if(!iso)
 		return NULL;
@@ -181,6 +179,27 @@
 	return NULL;
 }
 
+int hpsb_iso_recv_listen_channel(struct hpsb_iso *iso, unsigned char channel)
+{
+	if(iso->type != HPSB_ISO_RECV || iso->channel != -1 || channel >= 64)
+		return -EINVAL;
+	return iso->host->driver->isoctl(iso, RECV_LISTEN_CHANNEL, channel);
+}
+
+int hpsb_iso_recv_unlisten_channel(struct hpsb_iso *iso, unsigned char channel)
+{
+       if(iso->type != HPSB_ISO_RECV || iso->channel != -1 || channel >= 64)
+               return -EINVAL;
+       return iso->host->driver->isoctl(iso, RECV_UNLISTEN_CHANNEL, channel);
+}
+
+int hpsb_iso_recv_set_channel_mask(struct hpsb_iso *iso, u64 mask)
+{
+	if(iso->type != HPSB_ISO_RECV || iso->channel != -1)
+		return -EINVAL;
+	return iso->host->driver->isoctl(iso, RECV_SET_CHANNEL_MASK, (unsigned long) &mask);
+}
+
 static int do_iso_xmit_start(struct hpsb_iso *iso, int cycle)
 {
 	int retval = iso->host->driver->isoctl(iso, XMIT_START, cycle);
@@ -195,11 +214,20 @@
 {
 	if(iso->type != HPSB_ISO_XMIT)
 		return -1;
-	
+
 	if(iso->flags & HPSB_ISO_DRIVER_STARTED)
 		return 0;
 
-	if(prebuffer < 1)
+	if(cycle < -1)
+		cycle = -1;
+	else if(cycle >= 8000)
+		cycle %= 8000;
+
+	iso->xmit_cycle = cycle;
+
+	if(prebuffer < 0)
+		prebuffer = iso->buf_packets;
+	else if(prebuffer == 0)
 		prebuffer = 1;
 
 	if(prebuffer > iso->buf_packets)
@@ -207,41 +235,39 @@
 
 	iso->prebuffer = prebuffer;
 
-	if(cycle != -1) {
-		/* pre-fill info->cycle */
-		int pkt = iso->first_packet;
-		int c, i;
-
-		cycle %= 8000;
-
-		c = cycle;
-		for(i = 0; i < iso->buf_packets; i++) {
-			struct hpsb_iso_packet_info *info = hpsb_iso_packet_info(iso, pkt);
-
-			info->cycle = c;
-			
-			c = (c+1) % 8000;
-			pkt = (pkt+1) % iso->buf_packets;
-		}
-	}
-	
-	/* remember the starting cycle; DMA will commence from xmit_queue_packets() */
+	/* remember the starting cycle; DMA will commence from xmit_queue_packets()
+	   once enough packets have been buffered */
 	iso->start_cycle = cycle;
 
 	return 0;
 }
 
-int hpsb_iso_recv_start(struct hpsb_iso *iso, int cycle)
+int hpsb_iso_recv_start(struct hpsb_iso *iso, int cycle, int tag_mask, int sync)
 {
 	int retval = 0;
+	int isoctl_args[3];
 
 	if(iso->type != HPSB_ISO_RECV)
 		return -1;
-	
+
 	if(iso->flags & HPSB_ISO_DRIVER_STARTED)
 		return 0;
 
-	retval = iso->host->driver->isoctl(iso, RECV_START, cycle);
+	if(cycle < -1)
+		cycle = -1;
+	else if(cycle >= 8000)
+		cycle %= 8000;
+
+	isoctl_args[0] = cycle;
+	
+	if(tag_mask < 0)
+		/* match all tags */
+		tag_mask = 0xF;
+	isoctl_args[1] = tag_mask;
+
+	isoctl_args[2] = sync;
+
+	retval = iso->host->driver->isoctl(iso, RECV_START, (unsigned long) &isoctl_args[0]);
 	if(retval)
 		return retval;
 
@@ -249,58 +275,162 @@
 	return retval;
 }
 
-int hpsb_iso_xmit_queue_packets(struct hpsb_iso *iso, unsigned int n_packets)
+/* check to make sure the user has not supplied bogus values of offset/len
+   that would cause the kernel to access memory outside the buffer */
+
+static int hpsb_iso_check_offset_len(struct hpsb_iso *iso,
+				     unsigned int offset, unsigned short len,
+				     unsigned int *out_offset, unsigned short *out_len)
+{
+	if(offset >= iso->buf_size)
+		return -EFAULT;
+
+	/* make sure the packet does not go beyond the end of the buffer */
+	if(offset + len > iso->buf_size)
+		return -EFAULT;
+
+	/* check for wrap-around */
+	if(offset + len < offset)
+		return -EFAULT;
+
+	/* now we can trust 'offset' and 'length' */
+	*out_offset = offset;
+	*out_len = len;
+
+	return 0;
+}
+
+
+int hpsb_iso_xmit_queue_packet(struct hpsb_iso *iso, u32 offset, u16 len, u8 tag, u8 sy)
 {
-	int i, retval;
-	int pkt = iso->first_packet;
+	struct hpsb_iso_packet_info *info;
+	unsigned long flags;
+	int rv;
 
 	if(iso->type != HPSB_ISO_XMIT)
-		return -1;
-	
-	/* check packet sizes for sanity */
-	for(i = 0; i < n_packets; i++) {
-		struct hpsb_iso_packet_info *info = hpsb_iso_packet_info(iso, pkt);
-		if(info->len > iso->max_packet_size) {
-			printk(KERN_ERR "hpsb_iso_xmit_queue_packets: packet too long (%u, max is %u)\n",
-			       info->len, iso->max_packet_size);
-			return -EINVAL;
-		}
-							     
-		pkt = (pkt+1) % iso->buf_packets;
+		return -EINVAL;
+
+	/* is there space in the buffer? */
+	if(iso->n_ready_packets <= 0) {
+		return -EBUSY;
 	}
 
-	retval = iso->host->driver->isoctl(iso, XMIT_QUEUE, n_packets);
-	if(retval)
-		return retval;
+	info = &iso->infos[iso->first_packet];
+
+	/* check for bogus offset/length */
+	if(hpsb_iso_check_offset_len(iso, offset, len, &info->offset, &info->len))
+		return -EFAULT;
+
+	info->tag = tag;
+	info->sy = sy;
+
+	spin_lock_irqsave(&iso->lock, flags);
+
+	rv = iso->host->driver->isoctl(iso, XMIT_QUEUE, (unsigned long) info);
+	if(rv)
+		goto out;
+
+	/* increment cursors */
+	iso->first_packet = (iso->first_packet+1) % iso->buf_packets;
+	iso->xmit_cycle = (iso->xmit_cycle+1) % 8000;
+	iso->n_ready_packets--;
 
 	if(iso->prebuffer != 0) {
-		iso->prebuffer -= n_packets;
+		iso->prebuffer--;
 		if(iso->prebuffer <= 0) {
 			iso->prebuffer = 0;
-			return do_iso_xmit_start(iso,
-						 iso->start_cycle);
+			rv = do_iso_xmit_start(iso, iso->start_cycle);
 		}
 	}
 
-	return 0;
+out:	
+	spin_unlock_irqrestore(&iso->lock, flags);
+	return rv;
+}
+
+int hpsb_iso_xmit_sync(struct hpsb_iso *iso)
+{
+	if(iso->type != HPSB_ISO_XMIT)
+		return -EINVAL;
+
+	return wait_event_interruptible(iso->waitq, hpsb_iso_n_ready(iso) == iso->buf_packets);
+}
+
+void hpsb_iso_packet_sent(struct hpsb_iso *iso, int cycle, int error)
+{
+	unsigned long flags;
+	spin_lock_irqsave(&iso->lock, flags);
+
+	/* predict the cycle of the next packet to be queued */
+
+	/* jump ahead by the number of packets that are already buffered */
+	cycle += iso->buf_packets - iso->n_ready_packets;
+	cycle %= 8000;
+
+	iso->xmit_cycle = cycle;
+	iso->n_ready_packets++;
+	iso->pkt_dma = (iso->pkt_dma + 1) % iso->buf_packets;
+
+	if(iso->n_ready_packets == iso->buf_packets || error != 0) {
+		/* the buffer has run empty! */
+		atomic_inc(&iso->overflows);
+	}
+
+	spin_unlock_irqrestore(&iso->lock, flags);
+}
+
+void hpsb_iso_packet_received(struct hpsb_iso *iso, u32 offset, u16 len,
+			      u16 cycle, u8 channel, u8 tag, u8 sy)
+{
+	unsigned long flags;
+	spin_lock_irqsave(&iso->lock, flags);
+
+	if(iso->n_ready_packets == iso->buf_packets) {
+		/* overflow! */
+		atomic_inc(&iso->overflows);
+	} else {
+		struct hpsb_iso_packet_info *info = &iso->infos[iso->pkt_dma];
+		info->offset = offset;
+		info->len = len;
+		info->cycle = cycle;
+		info->channel = channel;
+		info->tag = tag;
+		info->sy = sy;
+
+		iso->pkt_dma = (iso->pkt_dma+1) % iso->buf_packets;
+		iso->n_ready_packets++;
+	}
+
+	spin_unlock_irqrestore(&iso->lock, flags);
 }
 
 int hpsb_iso_recv_release_packets(struct hpsb_iso *iso, unsigned int n_packets)
 {
+	unsigned long flags;
+	unsigned int i;
+	int rv = 0;
+
 	if(iso->type != HPSB_ISO_RECV)
 		return -1;
-	
-	return iso->host->driver->isoctl(iso, RECV_RELEASE, n_packets);
-}
 
-unsigned char* hpsb_iso_packet_data(struct hpsb_iso *iso, unsigned int pkt)
-{
-	return (iso->buf.kvirt + pkt * iso->buf_stride)
-		+ iso->packet_data_offset;
+	spin_lock_irqsave(&iso->lock, flags);
+	for(i = 0; i < n_packets; i++) {
+		rv = iso->host->driver->isoctl(iso, RECV_RELEASE,
+					       (unsigned long) &iso->infos[iso->first_packet]);
+		if(rv)
+			break;
+
+		iso->first_packet = (iso->first_packet+1) % iso->buf_packets;
+		iso->n_ready_packets--;
+	}
+	spin_unlock_irqrestore(&iso->lock, flags);
+	return rv;
 }
 
-struct hpsb_iso_packet_info* hpsb_iso_packet_info(struct hpsb_iso *iso, unsigned int pkt)
+void hpsb_iso_wake(struct hpsb_iso *iso)
 {
-	return (struct hpsb_iso_packet_info*) ((iso->buf.kvirt + pkt * iso->buf_stride)
-					       + iso->packet_info_offset);
+	wake_up_interruptible(&iso->waitq);
+
+	if(iso->callback)
+		iso->callback(iso);
 }
diff -Nru a/drivers/ieee1394/iso.h b/drivers/ieee1394/iso.h
--- a/drivers/ieee1394/iso.h	Mon Feb 17 14:57:28 2003
+++ b/drivers/ieee1394/iso.h	Mon Feb 17 14:57:28 2003
@@ -17,25 +17,37 @@
 
 /* high-level ISO interface */
 
-/* per-packet data embedded in the ringbuffer */
+/* This API sends and receives isochronous packets on a large,
+   virtually-contiguous kernel memory buffer. The buffer may be mapped
+   into a user-space process for zero-copy transmission and reception.
+
+   There are no explicit boundaries between packets in the buffer. A
+   packet may be transmitted or received at any location. However,
+   low-level drivers may impose certain restrictions on alignment or
+   size of packets. (e.g. in OHCI no packet may cross a page boundary,
+   and packets should be quadlet-aligned)
+*/
+
+/* Packet descriptor - the API maintains a ring buffer of these packet
+   descriptors in kernel memory (hpsb_iso.infos[]).  */
+
 struct hpsb_iso_packet_info {
-	unsigned short len;
-	unsigned short cycle;
-	unsigned char channel; /* recv only */
-	unsigned char tag;
-	unsigned char sy;
-};
+	/* offset of data payload relative to the first byte of the buffer */
+	__u32 offset;
+
+	/* length of the data payload, in bytes (not including the isochronous header) */
+	__u16 len;
 
-/*
- * each packet in the ringbuffer consists of three things:
- * 1. the packet's data payload (no isochronous header)
- * 2. a struct hpsb_iso_packet_info
- * 3. some empty space before the next packet
- *
- * packets are separated by hpsb_iso.buf_stride bytes
- * an even number of packets fit on one page
- * no packet can be larger than one page
- */
+	/* (recv only) the cycle number (mod 8000) on which the packet was received */
+	__u16 cycle;
+
+	/* (recv only) channel on which the packet was received */
+	__u8 channel;
+
+	/* 2-bit 'tag' and 4-bit 'sy' fields of the isochronous header */
+	__u8 tag;
+	__u8 sy;
+};
 
 enum hpsb_iso_type { HPSB_ISO_RECV = 0, HPSB_ISO_XMIT = 1 };
 
@@ -45,48 +57,49 @@
 	/* pointer to low-level driver and its private data */
 	struct hpsb_host *host;
 	void *hostdata;
-	
-	/* function to be called (from interrupt context) when the iso status changes */
+
+	/* a function to be called (from interrupt context) after
+           outgoing packets have been sent, or incoming packets have
+           arrived */
 	void (*callback)(struct hpsb_iso*);
 
+	/* wait for buffer space */
+	wait_queue_head_t waitq;
+
 	int speed; /* SPEED_100, 200, or 400 */
-	int channel;
+	int channel; /* -1 if multichannel */
 
 	/* greatest # of packets between interrupts - controls
 	   the maximum latency of the buffer */
 	int irq_interval;
-	
-	/* the packet ringbuffer */
-	struct dma_region buf;
+
+	/* the buffer for packet data payloads */
+	struct dma_region data_buf;
+
+	/* size of data_buf, in bytes (always a multiple of PAGE_SIZE) */
+	unsigned int buf_size;
+
+	/* ringbuffer of packet descriptors in regular kernel memory */
+	struct hpsb_iso_packet_info *infos;
 
 	/* # of packets in the ringbuffer */
 	unsigned int buf_packets;
 
-	/* offset between successive packets, in bytes -
-	   you can assume that this is a power of 2,
-	   and less than or equal to the page size */	
-	int buf_stride;
-	
-	/* largest possible packet size, in bytes */
-	unsigned int max_packet_size;
-
-	/* offset relative to (buf.kvirt + N*buf_stride) at which
-	   the data payload begins for packet N */
-	int packet_data_offset;
-	
-	/* offset relative to (buf.kvirt + N*buf_stride) at which the
-	   struct hpsb_iso_packet_info is stored for packet N */
-	int packet_info_offset;
+	/* protects packet cursors */
+	spinlock_t lock;
 
 	/* the index of the next packet that will be produced
 	   or consumed by the user */
 	int first_packet;
 
-	/* number of packets owned by the low-level driver and
-	   queued for transmission or reception.
-	   this is related to the number of packets available
-	   to the user process: n_ready = buf_packets - n_dma_packets */	
-	atomic_t n_dma_packets;
+	/* the index of the next packet that will be transmitted
+	   or received by the 1394 hardware */
+	int pkt_dma;
+
+	/* how many packets, starting at first_packet:
+	   (transmit) are ready to be filled with data
+	   (receive)  contain received data */
+	int n_ready_packets;
 
 	/* how many times the buffer has overflowed or underflowed */
 	atomic_t overflows;
@@ -99,8 +112,12 @@
 	/* # of packets left to prebuffer (xmit only) */
 	int prebuffer;
 
-	/* starting cycle (xmit only) */
+	/* starting cycle for DMA (xmit only) */
 	int start_cycle;
+
+	/* cycle at which next packet will be transmitted,
+	   -1 if not known */
+	int xmit_cycle;
 };
 
 /* functions available to high-level drivers (e.g. raw1394) */
@@ -108,30 +125,40 @@
 /* allocate the buffer and DMA context */
 
 struct hpsb_iso* hpsb_iso_xmit_init(struct hpsb_host *host,
+				    unsigned int data_buf_size,
 				    unsigned int buf_packets,
-				    unsigned int max_packet_size,
 				    int channel,
 				    int speed,
 				    int irq_interval,
 				    void (*callback)(struct hpsb_iso*));
 
+/* note: if channel = -1, multi-channel receive is enabled */
 struct hpsb_iso* hpsb_iso_recv_init(struct hpsb_host *host,
+				    unsigned int data_buf_size,
 				    unsigned int buf_packets,
-				    unsigned int max_packet_size,
 				    int channel,
 				    int irq_interval,
 				    void (*callback)(struct hpsb_iso*));
 
+/* multi-channel only */
+int hpsb_iso_recv_listen_channel(struct hpsb_iso *iso, unsigned char channel);
+int hpsb_iso_recv_unlisten_channel(struct hpsb_iso *iso, unsigned char channel);
+int hpsb_iso_recv_set_channel_mask(struct hpsb_iso *iso, u64 mask);
+
 /* start/stop DMA */
 int hpsb_iso_xmit_start(struct hpsb_iso *iso, int start_on_cycle, int prebuffer);
-int hpsb_iso_recv_start(struct hpsb_iso *iso, int start_on_cycle);
+int hpsb_iso_recv_start(struct hpsb_iso *iso, int start_on_cycle, int tag_mask, int sync);
 void hpsb_iso_stop(struct hpsb_iso *iso);
 
 /* deallocate buffer and DMA context */
 void hpsb_iso_shutdown(struct hpsb_iso *iso);
 
-/* N packets have been written to the buffer; queue them for transmission */
-int  hpsb_iso_xmit_queue_packets(struct hpsb_iso *xmit, unsigned int n_packets);
+/* queue a packet for transmission. 'offset' is relative to the beginning of the
+   DMA buffer, where the packet's data payload should already have been placed */
+int hpsb_iso_xmit_queue_packet(struct hpsb_iso *iso, u32 offset, u16 len, u8 tag, u8 sy);
+
+/* wait until all queued packets have been transmitted to the bus */
+int hpsb_iso_xmit_sync(struct hpsb_iso *iso);
 
 /* N packets have been read out of the buffer, re-use the buffer space */
 int  hpsb_iso_recv_release_packets(struct hpsb_iso *recv, unsigned int n_packets);
@@ -139,10 +166,19 @@
 /* returns # of packets ready to send or receive */
 int hpsb_iso_n_ready(struct hpsb_iso *iso);
 
-/* returns a pointer to the payload of packet 'pkt' */
-unsigned char* hpsb_iso_packet_data(struct hpsb_iso *iso, unsigned int pkt);
+/* the following are callbacks available to low-level drivers */
+
+/* call after a packet has been transmitted to the bus (interrupt context is OK)
+   'cycle' is the _exact_ cycle the packet was sent on
+   'error' should be non-zero if some sort of error occurred when sending the packet
+*/
+void hpsb_iso_packet_sent(struct hpsb_iso *iso, int cycle, int error);
+
+/* call after a packet has been received (interrupt context OK) */
+void hpsb_iso_packet_received(struct hpsb_iso *iso, u32 offset, u16 len,
+			      u16 cycle, u8 channel, u8 tag, u8 sy);
 
-/* returns a pointer to the info struct of packet 'pkt' */
-struct hpsb_iso_packet_info* hpsb_iso_packet_info(struct hpsb_iso *iso, unsigned int pkt);
+/* call to wake waiting processes after buffer space has opened up. */
+void hpsb_iso_wake(struct hpsb_iso *iso);
 
 #endif /* IEEE1394_ISO_H */
diff -Nru a/drivers/ieee1394/nodemgr.c b/drivers/ieee1394/nodemgr.c
--- a/drivers/ieee1394/nodemgr.c	Mon Feb 17 14:57:27 2003
+++ b/drivers/ieee1394/nodemgr.c	Mon Feb 17 14:57:27 2003
@@ -786,7 +786,7 @@
 #ifdef CONFIG_IEEE1394_VERBOSEDEBUG
 	HPSB_DEBUG("NodeMgr: %s %s %016Lx", argv[0], verb, (long long unsigned)ud->ne->guid);
 #endif
-	value = call_usermodehelper(argv[0], argv, envp);
+	value = call_usermodehelper(argv[0], argv, envp, 0);
 	kfree(buf);
 	kfree(envp);
 	if (value != 0)
@@ -1089,8 +1089,7 @@
 
 static void nodemgr_remove_node(struct node_entry *ne)
 {
-	HPSB_DEBUG("%s removed: Node[" NODE_BUS_FMT "]  GUID[%016Lx]  [%s]",
-		   (ne->host->node_id == ne->nodeid) ? "Host" : "Device",
+	HPSB_DEBUG("Device removed: Node[" NODE_BUS_FMT "]  GUID[%016Lx]  [%s]",
 		   NODE_BUS_ARGS(ne->nodeid), (unsigned long long)ne->guid,
 		   ne->vendor_name ?: "Unknown");
 
diff -Nru a/drivers/ieee1394/ohci1394.c b/drivers/ieee1394/ohci1394.c
--- a/drivers/ieee1394/ohci1394.c	Mon Feb 17 14:57:28 2003
+++ b/drivers/ieee1394/ohci1394.c	Mon Feb 17 14:57:28 2003
@@ -160,7 +160,7 @@
 printk(level "%s_%d: " fmt "\n" , OHCI1394_DRIVER_NAME, card , ## args)
 
 static char version[] __devinitdata =
-	"$Rev: 675 $ Ben Collins <bcollins@debian.org>";
+	"$Rev: 762 $ Ben Collins <bcollins@debian.org>";
 
 /* Module Parameters */
 MODULE_PARM(phys_dma,"i");
@@ -170,6 +170,15 @@
 static void dma_trm_tasklet(unsigned long data);
 static void dma_trm_reset(struct dma_trm_ctx *d);
 
+static int alloc_dma_rcv_ctx(struct ti_ohci *ohci, struct dma_rcv_ctx *d,
+			     enum context_type type, int ctx, int num_desc,
+			     int buf_size, int split_buf_size, int context_base);
+static void free_dma_rcv_ctx(struct dma_rcv_ctx *d);
+
+static int alloc_dma_trm_ctx(struct ti_ohci *ohci, struct dma_trm_ctx *d,
+			     enum context_type type, int ctx, int num_desc,
+			     int context_base);
+
 static void ohci1394_pci_remove(struct pci_dev *pdev);
 
 #ifndef __LITTLE_ENDIAN
@@ -311,7 +320,7 @@
 
 	/* SelfID Ok, reset error counter. */
 	ohci->self_id_errors = 0;
-	
+
 	size = ((self_id_count & 0x00001FFC) >> 2) - 1;
 	q++;
 
@@ -373,12 +382,12 @@
 		      "Running dma failed because Node ID == 63");
 		return -1;
 	}
-	
+
 	/* Run the dma context */
 	reg_write(ohci, reg, 0x8000);
-	
+
 	if (msg) PRINT(KERN_DEBUG, ohci->id, "%s", msg);
-	
+
 	return 0;
 }
 
@@ -415,10 +424,28 @@
         d->buf_ind = 0;
         d->buf_offset = 0;
 
+	if(d->type == DMA_CTX_ISO) {
+		/* Clear contextControl */
+		reg_write(ohci, d->ctrlClear, 0xffffffff);
+
+		/* Set bufferFill, isochHeader, multichannel for IR context */
+		reg_write(ohci, d->ctrlSet, 0xd0000000);
+			
+		/* Set the context match register to match on all tags */
+		reg_write(ohci, d->ctxtMatch, 0xf0000000);
+
+		/* Clear the multi channel mask high and low registers */
+		reg_write(ohci, OHCI1394_IRMultiChanMaskHiClear, 0xffffffff);
+		reg_write(ohci, OHCI1394_IRMultiChanMaskLoClear, 0xffffffff);
+
+		/* Set up isoRecvIntMask to generate interrupts */
+		reg_write(ohci, OHCI1394_IsoRecvIntMaskSet, 1 << d->ctx);
+	}
+
 	/* Tell the controller where the first AR program is */
 	reg_write(ohci, d->cmdPtr, d->prg_bus[0] | 0x1);
 
-	/* Run AR context */
+	/* Run context */
 	reg_write(ohci, d->ctrlSet, 0x00008000);
 
 	DBGMSG(ohci->id, "Receive DMA ctx=%d initialized", d->ctx);
@@ -439,6 +466,11 @@
 	INIT_LIST_HEAD(&d->fifo_list);
 	INIT_LIST_HEAD(&d->pending_list);
 
+	if(d->type == DMA_CTX_ISO) {
+		/* enable interrupts */
+		reg_write(ohci, OHCI1394_IsoXmitIntMaskSet, 1 << d->ctx);
+	}
+
 	DBGMSG(ohci->id, "Transmit DMA ctx=%d initialized", d->ctx);
 }
 
@@ -450,7 +482,7 @@
 
 	reg_write(ohci, reg, 0xffffffff);
 	tmp = reg_read(ohci, reg);
-	
+
 	DBGMSG(ohci->id,"Iso contexts reg: %08x implemented: %08x", reg, tmp);
 
 	/* Count the number of contexts */
@@ -515,12 +547,6 @@
 	/* Don't accept phy packets into AR request context */ 
 	reg_write(ohci, OHCI1394_LinkControlClear, 0x00000400);
 
-	/* Set bufferFill, isochHeader, multichannel for IR context */
-	reg_write(ohci, OHCI1394_IsoRcvContextControlSet, 0xd0000000);
-			
-	/* Set the context match register to match on all tags */
-	reg_write(ohci, OHCI1394_IsoRcvContextMatch, 0xf0000000);
-
 	/* Clear the interrupt mask */
 	reg_write(ohci, OHCI1394_IsoRecvIntMaskClear, 0xffffffff);
 	reg_write(ohci, OHCI1394_IsoRecvIntEventClear, 0xffffffff);
@@ -529,10 +555,6 @@
 	reg_write(ohci, OHCI1394_IsoXmitIntMaskClear, 0xffffffff);
 	reg_write(ohci, OHCI1394_IsoXmitIntEventClear, 0xffffffff);
 
-	/* Clear the multi channel mask high and low registers */
-	reg_write(ohci, OHCI1394_IRMultiChanMaskHiClear, 0xffffffff);
-	reg_write(ohci, OHCI1394_IRMultiChanMaskLoClear, 0xffffffff);
-
 	/* Initialize AR dma */
 	initialize_dma_rcv_ctx(&ohci->ar_req_context, 0);
 	initialize_dma_rcv_ctx(&ohci->ar_resp_context, 0);
@@ -541,19 +563,6 @@
 	initialize_dma_trm_ctx(&ohci->at_req_context);
 	initialize_dma_trm_ctx(&ohci->at_resp_context);
 
-	/* Initialize IR dma */
-	initialize_dma_rcv_ctx(&ohci->ir_context, 1);
-
-        /* Initialize IT dma */
-        initialize_dma_trm_ctx(&ohci->it_context);
-
-	/* Set up isoRecvIntMask to generate interrupts for context 0
-	   (thanks to Michael Greger for seeing that I forgot this) */
-	reg_write(ohci, OHCI1394_IsoRecvIntMaskSet, 0x00000001);
-
-	/* Set up isoXmitIntMask to generate interrupts for context 0 */
-	reg_write(ohci, OHCI1394_IsoXmitIntMaskSet, 0x00000001);
-
 	/* 
 	 * Accept AT requests from all nodes. This probably 
 	 * will have to be controlled from the subsystem
@@ -598,7 +607,7 @@
 }
 
 /* 
- * Insert a packet in the AT DMA fifo and generate the DMA prg
+ * Insert a packet in the DMA fifo and generate the DMA prg
  * FIXME: rewrite the program in order to accept packets crossing
  *        page boundaries.
  *        check also that a single dma descriptor doesn't cross a 
@@ -757,8 +766,8 @@
 }
 
 /*
- * This function fills the AT FIFO with the (eventual) pending packets
- * and runs or wakes up the AT DMA prg if necessary.
+ * This function fills the FIFO with the (eventual) pending packets
+ * and runs or wakes up the DMA prg if necessary.
  *
  * The function MUST be called with the d->lock held.
  */ 
@@ -774,7 +783,7 @@
 	idx = d->prg_ind;
 	z = (p->data_size) ? 3 : 2;
 
-	/* insert the packets into the at dma fifo */
+	/* insert the packets into the dma fifo */
 	while (d->free_prgs > 0 && !list_empty(&d->pending_list)) {
 		struct hpsb_packet *p = driver_packet(d->pending_list.next);
 		list_del(&p->driver_list);
@@ -796,13 +805,15 @@
 		/* Wake up the dma context if necessary */
 		if (!(reg_read(ohci, d->ctrlSet) & 0x400)) {
 			DBGMSG(ohci->id,"Waking transmit DMA ctx=%d",d->ctx);
-			reg_write(ohci, d->ctrlSet, 0x1000);
 		}
+
+		/* do this always, to avoid race condition */
+		reg_write(ohci, d->ctrlSet, 0x1000);
 	}
 	return 1;
 }
 
-/* Transmission of an async packet */
+/* Transmission of an async or iso packet */
 static int ohci_transmit(struct hpsb_host *host, struct hpsb_packet *packet)
 {
 	struct ti_ohci *ohci = host->hostdata;
@@ -819,9 +830,33 @@
 	/* Decide wether we have an iso, a request, or a response packet */
 	if (packet->type == hpsb_raw)
 		d = &ohci->at_req_context;
-	else if (packet->tcode == TCODE_ISO_DATA)
-		d = &ohci->it_context;
-	else if (packet->tcode & 0x02)
+	else if (packet->tcode == TCODE_ISO_DATA) {
+		/* The legacy IT DMA context is initialized on first
+		 * use.  However, the alloc cannot be run from
+		 * interrupt context, so we bail out if that is the
+		 * case. I don't see anyone sending ISO packets from
+		 * interrupt context anyway... */
+		
+		if(ohci->it_legacy_context.ohci == NULL) {
+			if(in_interrupt()) {
+				PRINT(KERN_ERR, ohci->id, 
+				      "legacy IT context cannot be initialized during interrupt");
+				return 0;
+			}
+
+			if (alloc_dma_trm_ctx(ohci, &ohci->it_legacy_context,
+					      DMA_CTX_ISO, 0, IT_NUM_DESC,
+					      OHCI1394_IsoXmitContextBase) < 0) {
+				PRINT(KERN_ERR, ohci->id, 
+				      "error initializing legacy IT context");
+				return 0;
+			}
+
+			initialize_dma_trm_ctx(&ohci->it_legacy_context);
+		}
+		
+		d = &ohci->it_legacy_context;
+	} else if (packet->tcode & 0x02)
 		d = &ohci->at_resp_context;
 	else 
 		d = &ohci->at_req_context;
@@ -829,7 +864,7 @@
 	spin_lock_irqsave(&d->lock,flags);
 
 	list_add_tail(&packet->driver_list, &d->pending_list);
-	
+
 	dma_trm_flush(ohci, d);
 
 	spin_unlock_irqrestore(&d->lock,flags);
@@ -898,11 +933,11 @@
 	case GET_CYCLE_COUNTER:
 		retval = reg_read(ohci, OHCI1394_IsochronousCycleTimer);
 		break;
-	
+
 	case SET_CYCLE_COUNTER:
 		reg_write(ohci, OHCI1394_IsochronousCycleTimer, arg);
 		break;
-	
+
 	case SET_BUS_ID:
 		PRINT(KERN_ERR, ohci->id, "devctl command SET_BUS_ID err");
 		break;
@@ -932,12 +967,13 @@
 		break;
 
 	case MODIFY_USAGE:
-                if (arg) {
-                        MOD_INC_USE_COUNT;
-                } else {
-                        MOD_DEC_USE_COUNT;
-                }
-		retval = 1;
+		if (arg) {
+			if (try_module_get(THIS_MODULE))
+				retval = 1;
+		} else {
+			module_put(THIS_MODULE);
+			retval = 1;
+		}
                 break;
 
 	case ISO_LISTEN_CHANNEL:
@@ -962,8 +998,26 @@
 			spin_unlock_irqrestore(&ohci->IR_channel_lock, flags);
 			return -EFAULT;
 		}
-		
+
+		/* activate the legacy IR context */
+		if(ohci->ir_legacy_context.ohci == NULL) {
+			if(alloc_dma_rcv_ctx(ohci, &ohci->ir_legacy_context,
+					     DMA_CTX_ISO, 0, IR_NUM_DESC,
+					     IR_BUF_SIZE, IR_SPLIT_BUF_SIZE,
+					     OHCI1394_IsoRcvContextBase) < 0) {
+				PRINT(KERN_ERR, ohci->id,
+				      "%s: failed to allocate an IR context", 
+				      __FUNCTION__);
+				return -ENOMEM;
+			}
+			ohci->ir_legacy_channels = 0;
+			initialize_dma_rcv_ctx(&ohci->ir_legacy_context, 1);
+
+			DBGMSG(ohci->id, "ISO receive legacy context activated");
+		}
+
 		ohci->ISO_channel_usage |= mask;
+		ohci->ir_legacy_channels |= mask;
 
 		if (arg>31) 
 			reg_write(ohci, OHCI1394_IRMultiChanMaskHiSet, 
@@ -1000,6 +1054,7 @@
 		}
 		
 		ohci->ISO_channel_usage &= ~mask;
+		ohci->ir_legacy_channels &= ~mask;
 
 		if (arg>31) 
 			reg_write(ohci, OHCI1394_IRMultiChanMaskHiClear, 
@@ -1010,6 +1065,11 @@
 
                 spin_unlock_irqrestore(&ohci->IR_channel_lock, flags);
                 DBGMSG(ohci->id, "Listening disabled on channel %d", arg);
+
+		if(ohci->ir_legacy_channels == 0) {
+			free_dma_rcv_ctx(&ohci->ir_legacy_context);
+			DBGMSG(ohci->id, "ISO receive legacy context deactivated");
+		}
                 break;
         }
 	default:
@@ -1024,61 +1084,159 @@
  * rawiso ISO reception            *
  ***********************************/
 
+/*
+  We use either buffer-fill or packet-per-buffer DMA mode. The DMA
+  buffer is split into "blocks" (regions described by one DMA
+  descriptor). Each block must be one page or less in size, and
+  must not cross a page boundary.
+
+  There is one little wrinkle with buffer-fill mode: a packet that
+  starts in the final block may wrap around into the first block. But
+  the user API expects all packets to be contiguous. Our solution is
+  to keep the very last page of the DMA buffer in reserve - if a
+  packet spans the gap, we copy its tail into this page.
+*/
+
 struct ohci_iso_recv {
 	struct ti_ohci *ohci;
 
-	/* memory and PCI mapping for the DMA descriptors */
-	struct dma_prog_region prog;
-	
 	struct ohci1394_iso_tasklet task;
 	int task_active;
 
-	/* index of next packet to arrive */
-	int pkt_dma;
-	
+	enum { BUFFER_FILL_MODE,
+	       PACKET_PER_BUFFER_MODE } dma_mode;
+
+	/* memory and PCI mapping for the DMA descriptors */
+	struct dma_prog_region prog;
+	struct dma_cmd *block; /* = (struct dma_cmd*) prog.virt */
+
+	/* how many DMA blocks fit in the buffer */
+	unsigned int nblocks;
+
+	/* stride of DMA blocks */
+	unsigned int buf_stride;
+
+	/* number of blocks to batch between interrupts */
+	int block_irq_interval;
+
+	/* block that DMA will finish next */
+	int block_dma;
+
+	/* (buffer-fill only) block that the reader will release next */
+	int block_reader;
+
+	/* (buffer-fill only) bytes of buffer the reader has released,
+	   less than one block */
+	int released_bytes;
+
+	/* (buffer-fill only) buffer offset at which the next packet will appear */
+	int dma_offset;
+
+	/* OHCI DMA context control registers */
 	u32 ContextControlSet;
 	u32 ContextControlClear;
 	u32 CommandPtr;
 	u32 ContextMatch;
 };
 
-static void ohci_iso_recv_task(unsigned long data);
+static void ohci_iso_recv_bufferfill_task(unsigned long data);
+static void ohci_iso_recv_packetperbuf_task(unsigned long data);
 static void ohci_iso_recv_stop(struct hpsb_iso *iso);
 static void ohci_iso_recv_shutdown(struct hpsb_iso *iso);
+static int  ohci_iso_recv_start(struct hpsb_iso *iso, int cycle, int tag_mask, int sync);
 static void ohci_iso_recv_program(struct hpsb_iso *iso);
-static int  ohci_iso_recv_start(struct hpsb_iso *iso, int cycle);
-
 
 static int ohci_iso_recv_init(struct hpsb_iso *iso)
 {
+	struct ti_ohci *ohci = iso->host->hostdata;
 	struct ohci_iso_recv *recv;
-	unsigned int prog_size;
 	int ctx;
 	int ret = -ENOMEM;
-	
+
 	recv = kmalloc(sizeof(*recv), SLAB_KERNEL);
 	if(!recv)
 		return -ENOMEM;
 
 	iso->hostdata = recv;
-	recv->ohci = iso->host->hostdata;
+	recv->ohci = ohci;
 	recv->task_active = 0;
-	recv->pkt_dma = iso->first_packet;
-	
 	dma_prog_region_init(&recv->prog);
+	recv->block = NULL;
+
+	/* use buffer-fill mode, unless irq_interval is 1
+	   (note: multichannel requires buffer-fill) */
+
+	if(iso->irq_interval == 1 && iso->channel != -1) {
+		recv->dma_mode = PACKET_PER_BUFFER_MODE;
+	} else {
+		recv->dma_mode = BUFFER_FILL_MODE;
+	}
+
+	/* set nblocks, buf_stride, block_irq_interval */
+
+	if(recv->dma_mode == BUFFER_FILL_MODE) {
+		recv->buf_stride = PAGE_SIZE;
 
-	/* size of DMA program = one INPUT_LAST per packet in the buffer */
-	prog_size = sizeof(struct dma_cmd) * iso->buf_packets;
+		/* one block per page of data in the DMA buffer, minus the final guard page */
+		recv->nblocks = iso->buf_size/PAGE_SIZE - 1;
+		if(recv->nblocks < 3) {
+			DBGMSG(ohci->id, "ohci_iso_recv_init: DMA buffer too small");
+			goto err;
+		}
+
+		/* iso->irq_interval is in packets - translate that to blocks */
+		/* (err, sort of... 1 is always the safest value) */
+		recv->block_irq_interval = iso->irq_interval / recv->nblocks;
+		if(recv->block_irq_interval < 1)
+			recv->block_irq_interval = 1;
+		else if(recv->block_irq_interval*4 > recv->nblocks)
+			recv->block_irq_interval = recv->nblocks/4;
+	} else {
+		int max_packet_size;
+
+		recv->nblocks = iso->buf_packets;
+		recv->block_irq_interval = 1;
+
+		/* choose a buffer stride */
+		/* must be a power of 2, and <= PAGE_SIZE */
+
+		max_packet_size = iso->buf_size / iso->buf_packets;
+
+		for(recv->buf_stride = 8; recv->buf_stride < max_packet_size;
+		    recv->buf_stride *= 2);
 	
-	if(dma_prog_region_alloc(&recv->prog, prog_size, recv->ohci->dev))
+		if(recv->buf_stride*iso->buf_packets > iso->buf_size ||
+		   recv->buf_stride > PAGE_SIZE) {
+			/* this shouldn't happen, but anyway... */
+			DBGMSG(ohci->id, "ohci_iso_recv_init: problem choosing a buffer stride");
+			goto err;
+		}
+	}
+
+	recv->block_reader = 0;
+	recv->released_bytes = 0;
+	recv->block_dma = 0;
+	recv->dma_offset = 0;
+
+	/* size of DMA program = one descriptor per block */
+	if (dma_prog_region_alloc(&recv->prog,
+				 sizeof(struct dma_cmd) * recv->nblocks,
+				 recv->ohci->dev))
 		goto err;
 
-	ohci1394_init_iso_tasklet(&recv->task, OHCI_ISO_RECEIVE,
-				  ohci_iso_recv_task, (unsigned long) iso);
-	
+	recv->block = (struct dma_cmd*) recv->prog.kvirt;
+
+	ohci1394_init_iso_tasklet(&recv->task,
+				  iso->channel == -1 ? OHCI_ISO_MULTICHANNEL_RECEIVE :
+				                       OHCI_ISO_RECEIVE,
+				  recv->dma_mode == BUFFER_FILL_MODE ?
+				  ohci_iso_recv_bufferfill_task :
+				  ohci_iso_recv_packetperbuf_task,
+				  (unsigned long) iso);
+
 	if(ohci1394_register_iso_tasklet(recv->ohci, &recv->task) < 0)
 		goto err;
-	
+
 	recv->task_active = 1;
 
 	/* recv context registers are spaced 32 bytes apart */
@@ -1088,12 +1246,22 @@
 	recv->CommandPtr = OHCI1394_IsoRcvCommandPtr + 32 * ctx;
 	recv->ContextMatch = OHCI1394_IsoRcvContextMatch + 32 * ctx;
 
-	/* enable interrupts */
-	reg_write(recv->ohci, OHCI1394_IsoRecvIntMaskSet, 1 << ctx);
-
+	if(iso->channel == -1) {
+		/* clear multi-channel selection mask */
+		reg_write(recv->ohci, OHCI1394_IRMultiChanMaskHiClear, 0xFFFFFFFF);
+		reg_write(recv->ohci, OHCI1394_IRMultiChanMaskLoClear, 0xFFFFFFFF);
+	}
+		
 	/* write the DMA program */
 	ohci_iso_recv_program(iso);
-	
+
+	DBGMSG(ohci->id, "ohci_iso_recv_init: %s mode, DMA buffer is %lu pages"
+	       " (%u bytes), using %u blocks, buf_stride %u, block_irq_interval %d",
+	       recv->dma_mode == BUFFER_FILL_MODE ?
+	       "buffer-fill" : "packet-per-buffer",
+	       iso->buf_size/PAGE_SIZE, iso->buf_size, 
+	       recv->nblocks, recv->buf_stride, recv->block_irq_interval);
+
 	return 0;
 
 err:
@@ -1104,7 +1272,10 @@
 static void ohci_iso_recv_stop(struct hpsb_iso *iso)
 {
 	struct ohci_iso_recv *recv = iso->hostdata;
-	
+
+	/* disable interrupts */
+	reg_write(recv->ohci, OHCI1394_IsoRecvIntMaskClear, 1 << recv->task.context);
+		
 	/* halt DMA */
 	ohci1394_stop_context(recv->ohci, recv->ContextControlClear, NULL);
 }
@@ -1114,100 +1285,139 @@
 	struct ohci_iso_recv *recv = iso->hostdata;
 
 	if(recv->task_active) {
-		/* halt DMA */
-		ohci1394_stop_context(recv->ohci, recv->ContextControlClear, NULL);
-		
-		/* disable interrupts */
-		reg_write(recv->ohci, OHCI1394_IsoRecvIntMaskClear, 1 << recv->task.context);
-		
+		ohci_iso_recv_stop(iso);
 		ohci1394_unregister_iso_tasklet(recv->ohci, &recv->task);
 		recv->task_active = 0;
 	}
-	
+
 	dma_prog_region_free(&recv->prog);
 	kfree(recv);
 	iso->hostdata = NULL;
 }
 
+/* set up a "gapped" ring buffer DMA program */
 static void ohci_iso_recv_program(struct hpsb_iso *iso)
 {
 	struct ohci_iso_recv *recv = iso->hostdata;
-	
+	int blk;
+
 	/* address of 'branch' field in previous DMA descriptor */
 	u32 *prev_branch = NULL;
 
-	/* start at pkt_dma and go around the whole buffer */
-	int pkt = recv->pkt_dma;
-	int i;
-	
-	for(i = 0; i < iso->buf_packets; i++) {
-		int want_interrupt;
-		unsigned int data_size;
-		
-		/* pointer to the DMA descriptor */
-		struct dma_cmd *il = ((struct dma_cmd*) recv->prog.kvirt) + pkt;
+	for (blk = 0; blk < recv->nblocks; blk++) {
+		/* the DMA descriptor */
+		struct dma_cmd *cmd = &recv->block[blk];
 
 		/* offset of the DMA descriptor relative to the DMA prog buffer */
-		unsigned long prog_offset = pkt * sizeof(struct dma_cmd);
+		unsigned long prog_offset = blk * sizeof(struct dma_cmd);
 
-		/* offset of this bus_cycle within the DMA buffer */
-		unsigned long buf_offset = hpsb_iso_packet_data(iso, pkt) - iso->buf.kvirt;
+		/* offset of this packet's data within the DMA buffer */
+		unsigned long buf_offset = blk * recv->buf_stride;
 
-		/* back up 8 bytes for the iso header */
-		buf_offset -= 8;
-		data_size = iso->max_packet_size + 8;
-
-		/* ask for an interrupt every now and then, and
-		   always interrupt on the final descriptor */
-		
-		if( ((i % iso->irq_interval) == 0) ||
-		    (i == (iso->buf_packets - 1)) ) {
-			want_interrupt = 1;
+		if (recv->dma_mode == BUFFER_FILL_MODE) {
+			cmd->control = 2 << 28; /* INPUT_MORE */
 		} else {
-			want_interrupt = 0;
+			cmd->control = 3 << 28; /* INPUT_LAST */
 		}
-		
-		/* write the DMA descriptor */
-		
-		il->control = 3 << 28; /* INPUT_LAST */
-		il->control |= 8 << 24; /* s = 1, update xferStatus and resCount */
-		if(want_interrupt)
-			il->control |= 3 << 20;
-		il->control |= 0xC << 16; /* enable branch to address */
-		il->control |= data_size;
 
-		il->address = dma_region_offset_to_bus(&iso->buf, buf_offset);
-		il->branchAddress = 0; /* filled in on next loop */
-		il->status = data_size;
+		cmd->control |= 8 << 24; /* s = 1, update xferStatus and resCount */
+
+		/* interrupt on last block, and at intervals */
+		if (blk == recv->nblocks-1 || (blk % recv->block_irq_interval) == 0) {
+			cmd->control |= 3 << 20; /* want interrupt */
+		}
+
+		cmd->control |= 3 << 18; /* enable branch to address */
+		cmd->control |= recv->buf_stride;
+
+		cmd->address = dma_region_offset_to_bus(&iso->data_buf, buf_offset);
+		cmd->branchAddress = 0; /* filled in on next loop */
+		cmd->status = recv->buf_stride;
 
 		/* link the previous descriptor to this one */
-		if(prev_branch) {
+		if (prev_branch) {
 			*prev_branch = dma_prog_region_offset_to_bus(&recv->prog, prog_offset);
 			*prev_branch |= 1; /* set Z=1 */
 		}
 
-		prev_branch = &il->branchAddress;
-
-		pkt = (pkt + 1) % iso->buf_packets;
+		prev_branch = &cmd->branchAddress;
 	}
 
 	/* the final descriptor's branch address and Z should be left at 0 */
 }
 
-static int ohci_iso_recv_start(struct hpsb_iso *iso, int cycle)
+/* listen or unlisten to a specific channel (multi-channel mode only) */
+static void ohci_iso_recv_change_channel(struct hpsb_iso *iso, unsigned char channel, int listen)
+{
+	struct ohci_iso_recv *recv = iso->hostdata;
+	int reg, i;
+
+	if(channel < 32) {
+		reg = listen ? OHCI1394_IRMultiChanMaskLoSet : OHCI1394_IRMultiChanMaskLoClear;
+		i = channel;
+	} else {
+		reg = listen ? OHCI1394_IRMultiChanMaskHiSet : OHCI1394_IRMultiChanMaskHiClear;
+		i = channel - 32;
+	}
+
+	reg_write(recv->ohci, reg, (1 << i));
+
+	/* issue a dummy read to force all PCI writes to be posted immediately */
+	mb();
+	reg_read(recv->ohci, OHCI1394_IsochronousCycleTimer);
+}
+
+static void ohci_iso_recv_set_channel_mask(struct hpsb_iso *iso, u64 mask)
+{
+	struct ohci_iso_recv *recv = iso->hostdata;
+	int i;
+
+	for(i = 0; i < 64; i++) {
+		if(mask & (1ULL << i)) {
+			if(i < 32)
+				reg_write(recv->ohci, OHCI1394_IRMultiChanMaskLoSet, (1 << i));
+			else
+				reg_write(recv->ohci, OHCI1394_IRMultiChanMaskHiSet, (1 << (i-32)));
+		} else {
+			if(i < 32)
+				reg_write(recv->ohci, OHCI1394_IRMultiChanMaskLoClear, (1 << i));
+			else
+				reg_write(recv->ohci, OHCI1394_IRMultiChanMaskHiClear, (1 << (i-32)));
+		}
+	}
+
+	/* issue a dummy read to force all PCI writes to be posted immediately */
+	mb();
+	reg_read(recv->ohci, OHCI1394_IsochronousCycleTimer);
+}
+
+static int ohci_iso_recv_start(struct hpsb_iso *iso, int cycle, int tag_mask, int sync)
 {
 	struct ohci_iso_recv *recv = iso->hostdata;
 	u32 command, contextMatch;
-	
+
 	reg_write(recv->ohci, recv->ContextControlClear, 0xFFFFFFFF);
 	wmb();
 
-	/* use packet-per-buffer mode, and keep ISO headers */
-	reg_write(recv->ohci, recv->ContextControlSet, (1 << 30));
+	/* always keep ISO headers */
+	command = (1 << 30);
+
+	if(recv->dma_mode == BUFFER_FILL_MODE)
+		command |= (1 << 31);
+
+	reg_write(recv->ohci, recv->ContextControlSet, command);
+
+	/* match on specified tags */
+	contextMatch = tag_mask << 28;
+
+	if(iso->channel == -1) {
+		/* enable multichannel reception */
+		reg_write(recv->ohci, recv->ContextControlSet, (1 << 28));
+	} else {
+		/* listen on channel */
+		contextMatch |= iso->channel;
+	}
 
-	/* match on all tags, listen on channel */
-	contextMatch = 0xF0000000 | iso->channel;
-	
 	if(cycle != -1) {
 		u32 seconds;
 		
@@ -1229,15 +1439,29 @@
 		contextMatch |= cycle << 12;
 	}
 
+	if(sync != -1) {
+		/* set sync flag on first DMA descriptor */
+		struct dma_cmd *cmd = &recv->block[recv->block_dma];
+		cmd->control |= DMA_CTL_WAIT;
+
+		/* match sync field */
+		contextMatch |= (sync&0xf)<<8;
+	}
+
 	reg_write(recv->ohci, recv->ContextMatch, contextMatch);
-	
+
 	/* address of first descriptor block */
-	command = dma_prog_region_offset_to_bus(&recv->prog, recv->pkt_dma * sizeof(struct dma_cmd));
+	command = dma_prog_region_offset_to_bus(&recv->prog,
+						recv->block_dma * sizeof(struct dma_cmd));
 	command |= 1; /* Z=1 */
-	
+
 	reg_write(recv->ohci, recv->CommandPtr, command);
+
+	/* enable interrupts */
+	reg_write(recv->ohci, OHCI1394_IsoRecvIntMaskSet, 1 << recv->task.context);
+
 	wmb();
-	
+
 	/* run */
 	reg_write(recv->ohci, recv->ContextControlSet, 0x8000);
 
@@ -1248,7 +1472,8 @@
 
 	/* check RUN */
 	if(!(reg_read(recv->ohci, recv->ContextControlSet) & 0x8000)) {
-		PRINT(KERN_ERR, recv->ohci->id, "Error starting IR DMA (ContextControl 0x%08x)\n",
+		PRINT(KERN_ERR, recv->ohci->id,
+		      "Error starting IR DMA (ContextControl 0x%08x)\n",
 		      reg_read(recv->ohci, recv->ContextControlSet));
 		return -1;
 	}
@@ -1256,62 +1481,253 @@
 	return 0;
 }
 
-static void ohci_iso_recv_release_one(struct hpsb_iso *iso)
+static void ohci_iso_recv_release_block(struct ohci_iso_recv *recv, int block)
 {
-	struct ohci_iso_recv *recv = iso->hostdata;
-
-	/* re-use the DMA descriptor for first_packet */
+	/* re-use the DMA descriptor for the block */
 	/* by linking the previous descriptor to it */
 
-	int next_i = iso->first_packet;
-	int prev_i = (next_i == 0) ? (iso->buf_packets - 1) : (next_i - 1);
-	
-	struct dma_cmd *next = dma_region_i(&recv->prog, struct dma_cmd, next_i);
-	struct dma_cmd *prev = dma_region_i(&recv->prog, struct dma_cmd, prev_i);
+	int next_i = block;
+	int prev_i = (next_i == 0) ? (recv->nblocks - 1) : (next_i - 1);
+
+	struct dma_cmd *next = &recv->block[next_i];
+	struct dma_cmd *prev = &recv->block[prev_i];
 
-	/* 'next' becomes the new end of the DMA chain */
-	next->control |= 3 << 20; /* enable interrupt */
-	next->branchAddress = 0; /* disable branch */
+	/* 'next' becomes the new end of the DMA chain,
+	   so disable branch and enable interrupt */
+	next->branchAddress = 0;
+	next->control |= 3 << 20;
 
 	/* link prev to next */	
-	if(prev_i % iso->irq_interval) {
-		prev->control &= ~(3 << 20); /* no interrupt */
-	} else {
+	prev->branchAddress = dma_prog_region_offset_to_bus(&recv->prog,
+							    sizeof(struct dma_cmd) * next_i)
+		| 1; /* Z=1 */
+
+	/* disable interrupt on previous DMA descriptor, except at intervals */
+	if((prev_i % recv->block_irq_interval) == 0) {
 		prev->control |= 3 << 20; /* enable interrupt */
+	} else {
+		prev->control &= ~(3<<20); /* disable interrupt */
 	}
-	prev->branchAddress = dma_prog_region_offset_to_bus(&recv->prog,
-							    sizeof(struct dma_cmd) * next_i) | 1;
 	wmb();
-	
+
 	/* wake up DMA in case it fell asleep */
 	reg_write(recv->ohci, recv->ContextControlSet, (1 << 12));
+}
+
+static void ohci_iso_recv_bufferfill_release(struct ohci_iso_recv *recv,
+					     struct hpsb_iso_packet_info *info)
+{
+	int len;
+
+	/* release the memory where the packet was */
+	len = info->len;
+
+	/* add the wasted space for padding to 4 bytes */
+	if(len % 4)
+		len += 4 - (len % 4);
 
-	/* advance packet cursors */
-	iso->first_packet = (iso->first_packet+1) % iso->buf_packets;
-	atomic_inc(&iso->n_dma_packets);
+	/* add 8 bytes for the OHCI DMA data format overhead */
+	len += 8;
+
+	recv->released_bytes += len;
+
+	/* have we released enough memory for one block? */
+	while(recv->released_bytes > recv->buf_stride) {
+		ohci_iso_recv_release_block(recv, recv->block_reader);
+		recv->block_reader = (recv->block_reader + 1) % recv->nblocks;
+		recv->released_bytes -= recv->buf_stride;
+	}
 }
 
-static void ohci_iso_recv_release(struct hpsb_iso *iso, int n_packets)
+static inline void ohci_iso_recv_release(struct hpsb_iso *iso, struct hpsb_iso_packet_info *info)
 {
-	int i;
-	for(i = 0; i < n_packets; i++)
-		ohci_iso_recv_release_one(iso);
+	struct ohci_iso_recv *recv = iso->hostdata;
+	if(recv->dma_mode == BUFFER_FILL_MODE) {
+		ohci_iso_recv_bufferfill_release(recv, info);
+	} else {
+		ohci_iso_recv_release_block(recv, info - iso->infos);
+	}
 }
 
-static void ohci_iso_recv_task(unsigned long data)
+/* parse all packets from blocks that have been fully received */
+static void ohci_iso_recv_bufferfill_parse(struct hpsb_iso *iso, struct ohci_iso_recv *recv)
+{
+	int wake = 0;
+	int runaway = 0;
+		
+	while(1) {
+		/* we expect the next parsable packet to begin at recv->dma_offset */
+		/* note: packet layout is as shown in section 10.6.1.1 of the OHCI spec */
+		
+		unsigned int offset;
+		unsigned short len, cycle;
+		unsigned char channel, tag, sy;
+		
+		unsigned char *p = iso->data_buf.kvirt;
+
+		unsigned int this_block = recv->dma_offset/recv->buf_stride;
+
+		/* don't loop indefinitely */
+		if(runaway++ > 100000) {
+			atomic_inc(&iso->overflows);
+			PRINT(KERN_ERR, recv->ohci->id,
+			      "IR DMA error - Runaway during buffer parsing!\n");
+			break;
+		}
+
+		/* stop parsing once we arrive at block_dma (i.e. don't get ahead of DMA) */
+		if(this_block == recv->block_dma)
+			break;
+
+		wake = 1;
+		
+		/* parse data length, tag, channel, and sy */
+		
+		/* note: we keep our own local copies of 'len' and 'offset'
+		   so the user can't mess with them by poking in the mmap area */
+		
+		len = p[recv->dma_offset+2] | (p[recv->dma_offset+3] << 8);
+
+		if(len > 4096) {
+			PRINT(KERN_ERR, recv->ohci->id,
+			      "IR DMA error - bogus 'len' value %u\n", len);
+		}
+		
+		channel = p[recv->dma_offset+1] & 0x3F;
+		tag = p[recv->dma_offset+1] >> 6;
+		sy = p[recv->dma_offset+0] & 0xF;
+
+		/* advance to data payload */
+		recv->dma_offset += 4;
+		
+		/* check for wrap-around */
+		if(recv->dma_offset >= recv->buf_stride*recv->nblocks) {
+			recv->dma_offset -= recv->buf_stride*recv->nblocks;
+		}
+
+		/* dma_offset now points to the first byte of the data payload */
+		offset = recv->dma_offset;
+
+		/* advance to xferStatus/timeStamp */
+		recv->dma_offset += len;
+
+		/* payload is padded to 4 bytes */
+		if(len % 4) { 
+			recv->dma_offset += 4 - (len%4);
+		}
+
+		/* check for wrap-around */
+		if(recv->dma_offset >= recv->buf_stride*recv->nblocks) {
+			/* uh oh, the packet data wraps from the last
+                           to the first DMA block - make the packet
+                           contiguous by copying its "tail" into the
+                           guard page */
+
+			int guard_off = recv->buf_stride*recv->nblocks;
+			int tail_len = len - (guard_off - offset);
+
+			if(tail_len > 0  && tail_len < recv->buf_stride) {
+				memcpy(iso->data_buf.kvirt + guard_off,
+				       iso->data_buf.kvirt,
+				       tail_len);
+			}
+
+			recv->dma_offset -= recv->buf_stride*recv->nblocks;
+		}
+
+		/* parse timestamp */
+		cycle = p[recv->dma_offset+0] | (p[recv->dma_offset+1]<<8);
+		cycle &= 0x1FFF;
+
+		/* advance to next packet */
+		recv->dma_offset += 4;
+
+		/* check for wrap-around */
+		if(recv->dma_offset >= recv->buf_stride*recv->nblocks) {
+			recv->dma_offset -= recv->buf_stride*recv->nblocks;
+		}
+
+		hpsb_iso_packet_received(iso, offset, len, cycle, channel, tag, sy);
+	}
+
+	if(wake)
+		hpsb_iso_wake(iso);
+}
+
+static void ohci_iso_recv_bufferfill_task(unsigned long data)
 {
 	struct hpsb_iso *iso = (struct hpsb_iso*) data;
 	struct ohci_iso_recv *recv = iso->hostdata;
 
+	int loop;
+
+	/* loop over all blocks */
+	for(loop = 0; loop < recv->nblocks; loop++) {
+		
+		/* check block_dma to see if it's done */
+		
+		struct dma_cmd *im = &recv->block[recv->block_dma];
+		
+		/* check the DMA descriptor for new writes to xferStatus */
+		u16 xferstatus = im->status >> 16;
+		
+		/* rescount is the number of bytes *remaining to be written* in the block */
+		u16 rescount = im->status & 0xFFFF;
+
+		unsigned char event = xferstatus & 0x1F;
+
+		if(!event) {
+			/* nothing has happened to this block yet */
+			break;
+		}
+
+		if(event != 0x11) {
+			atomic_inc(&iso->overflows);
+			PRINT(KERN_ERR, recv->ohci->id,
+			      "IR DMA error - OHCI error code 0x%02x\n", event);
+		}
+
+		if(rescount != 0) {
+			/* the card is still writing to this block;
+			   we can't touch it until it's done */
+			break;
+		}
+		
+		/* OK, the block is finished... */
+		
+		/* sync our view of the block */
+		dma_region_sync(&iso->data_buf, recv->block_dma*recv->buf_stride, recv->buf_stride);
+		
+		/* reset the DMA descriptor */
+		im->status = recv->buf_stride;
+
+		/* advance block_dma */
+		recv->block_dma = (recv->block_dma + 1) % recv->nblocks;
+
+		if((recv->block_dma+1) % recv->nblocks == recv->block_reader) {
+			atomic_inc(&iso->overflows);
+			DBGMSG(recv->ohci->id, "ISO reception overflow - "
+			       "ran out of DMA blocks");
+		}
+	}
+
+	/* parse any packets that have arrived */
+	ohci_iso_recv_bufferfill_parse(iso, recv);
+}
+
+static void ohci_iso_recv_packetperbuf_task(unsigned long data)
+{
+	struct hpsb_iso *iso = (struct hpsb_iso*) data;
+	struct ohci_iso_recv *recv = iso->hostdata;
 	int count;
 	int wake = 0;
 	
 	/* loop over the entire buffer */
-	for(count = 0; count < iso->buf_packets; count++) {
+	for(count = 0; count < recv->nblocks; count++) {
 		u32 packet_len = 0;
 		
 		/* pointer to the DMA descriptor */
-		struct dma_cmd *il = ((struct dma_cmd*) recv->prog.kvirt) + recv->pkt_dma;
+		struct dma_cmd *il = ((struct dma_cmd*) recv->prog.kvirt) + iso->pkt_dma;
 
 		/* check the DMA descriptor for new writes to xferStatus */
 		u16 xferstatus = il->status >> 16;
@@ -1329,7 +1745,7 @@
 			
 			/* rescount is the number of bytes *remaining* in the packet buffer,
 			   after the packet was written */
-			packet_len = iso->max_packet_size - rescount;
+			packet_len = recv->buf_stride - rescount;
 
 		} else if(event == 0x02) {
 			PRINT(KERN_ERR, recv->ohci->id, "IR DMA error - packet too long for buffer\n");
@@ -1338,42 +1754,42 @@
 		}
 
 		/* sync our view of the buffer */
-		dma_region_sync(&iso->buf, recv->pkt_dma * iso->buf_stride, iso->buf_stride);
+		dma_region_sync(&iso->data_buf, iso->pkt_dma * recv->buf_stride, recv->buf_stride);
 			
 		/* record the per-packet info */
 		{
 			/* iso header is 8 bytes ahead of the data payload */
-			unsigned char *hdr = hpsb_iso_packet_data(iso, recv->pkt_dma) - 8;
-			
-			struct hpsb_iso_packet_info *info = hpsb_iso_packet_info(iso, recv->pkt_dma);
+			unsigned char *hdr;
+
+			unsigned int offset;
+			unsigned short cycle;
+			unsigned char channel, tag, sy;
+
+			offset = iso->pkt_dma * recv->buf_stride;
+			hdr = iso->data_buf.kvirt + offset;
+
+			/* skip iso header */
+			offset += 8;
+			packet_len -= 8;
 			
-			info->len = packet_len;
-			info->cycle = (hdr[0] | (hdr[1] << 8)) & 0x1FFF;
-			info->channel = hdr[5] & 0x3F;
-			info->tag = hdr[5] >> 6;
-			info->sy = hdr[4] & 0xF;
+			cycle = (hdr[0] | (hdr[1] << 8)) & 0x1FFF;
+			channel = hdr[5] & 0x3F;
+			tag = hdr[5] >> 6;
+			sy = hdr[4] & 0xF;
+
+			hpsb_iso_packet_received(iso, offset, packet_len, cycle, channel, tag, sy);
 		}
 		
-		/* at least one packet came in, so wake up the reader */
-		wake = 1;
-
 		/* reset the DMA descriptor */
-		il->status = iso->max_packet_size;
-
-		/* advance DMA packet cursor */
-		recv->pkt_dma = (recv->pkt_dma + 1) % iso->buf_packets;
+		il->status = recv->buf_stride;
 
-		/* one more packet for the user, one less for us */
-		if(atomic_dec_and_test(&iso->n_dma_packets)) {
-			/* if n_dma_packets reaches zero, we have an overflow */
-			atomic_inc(&iso->overflows);
-		}
+		wake = 1;
+		recv->block_dma = iso->pkt_dma;
 	}
 
 out:
-	if(wake && iso->callback) {
-		iso->callback(iso);
-	}
+	if(wake)
+		hpsb_iso_wake(iso);
 }
 
 
@@ -1386,7 +1802,6 @@
 	struct dma_prog_region prog;
 	struct ohci1394_iso_tasklet task;
 	int task_active;
-	int pkt_dma;
 
 	u32 ContextControlSet;
 	u32 ContextControlClear;
@@ -1415,7 +1830,7 @@
 	unsigned int prog_size;
 	int ctx;
 	int ret = -ENOMEM;
-	
+
 	xmit = kmalloc(sizeof(*xmit), SLAB_KERNEL);
 	if(!xmit)
 		return -ENOMEM;
@@ -1423,21 +1838,20 @@
 	iso->hostdata = xmit;
 	xmit->ohci = iso->host->hostdata;
 	xmit->task_active = 0;
-	xmit->pkt_dma = iso->first_packet;
-	
+
 	dma_prog_region_init(&xmit->prog);
-	
+
 	prog_size = sizeof(struct iso_xmit_cmd) * iso->buf_packets;
-	
+
 	if(dma_prog_region_alloc(&xmit->prog, prog_size, xmit->ohci->dev))
 		goto err;
 
 	ohci1394_init_iso_tasklet(&xmit->task, OHCI_ISO_TRANSMIT,
 				  ohci_iso_xmit_task, (unsigned long) iso);
-	
+
 	if(ohci1394_register_iso_tasklet(xmit->ohci, &xmit->task) < 0)
 		goto err;
-	
+
 	xmit->task_active = 1;
 
 	/* xmit context registers are spaced 16 bytes apart */
@@ -1446,11 +1860,6 @@
 	xmit->ContextControlClear = OHCI1394_IsoXmitContextControlClear + 16 * ctx;
 	xmit->CommandPtr = OHCI1394_IsoXmitCommandPtr + 16 * ctx;
 
-	reg_write(xmit->ohci, xmit->ContextControlClear, 0xFFFFFFFF);
-	
-	/* enable interrupts */
-	reg_write(xmit->ohci, OHCI1394_IsoXmitIntMaskSet, 1 << ctx);
-
 	return 0;
 
 err:
@@ -1461,7 +1870,17 @@
 static void ohci_iso_xmit_stop(struct hpsb_iso *iso)
 {
 	struct ohci_iso_xmit *xmit = iso->hostdata;
-	ohci1394_stop_context(xmit->ohci, xmit->ContextControlClear, NULL);
+
+	/* disable interrupts */
+	reg_write(xmit->ohci, OHCI1394_IsoXmitIntMaskClear, 1 << xmit->task.context);
+
+	/* halt DMA */
+	if(ohci1394_stop_context(xmit->ohci, xmit->ContextControlClear, NULL)) {
+		/* XXX the DMA context will lock up if you try to send too much data! */
+		PRINT(KERN_ERR, xmit->ohci->id,
+		      "you probably exceeded the OHCI card's bandwidth limit - "
+		      "reload the module and reduce xmit bandwidth");
+	}
 }
 
 static void ohci_iso_xmit_shutdown(struct hpsb_iso *iso)
@@ -1469,16 +1888,11 @@
 	struct ohci_iso_xmit *xmit = iso->hostdata;
 
 	if(xmit->task_active) {
-		/* halt DMA */
-		ohci1394_stop_context(xmit->ohci, xmit->ContextControlClear, NULL);
-		
-		/* disable interrupts */
-		reg_write(xmit->ohci, OHCI1394_IsoXmitIntMaskClear, 1 << xmit->task.context);
-		
+		ohci_iso_xmit_stop(iso);
 		ohci1394_unregister_iso_tasklet(xmit->ohci, &xmit->task);
 		xmit->task_active = 0;
 	}
-	
+
 	dma_prog_region_free(&xmit->prog);
 	kfree(xmit);
 	iso->hostdata = NULL;
@@ -1493,9 +1907,10 @@
 
 	/* check the whole buffer if necessary, starting at pkt_dma */
 	for(count = 0; count < iso->buf_packets; count++) {
-		
+		int cycle;
+
 		/* DMA descriptor */
-		struct iso_xmit_cmd *cmd = dma_region_i(&xmit->prog, struct iso_xmit_cmd, xmit->pkt_dma);
+		struct iso_xmit_cmd *cmd = dma_region_i(&xmit->prog, struct iso_xmit_cmd, iso->pkt_dma);
 		
 		/* check for new writes to xferStatus */
 		u16 xferstatus = cmd->output_last.status >> 16;
@@ -1503,70 +1918,68 @@
 
 		if(!event) {
 			/* packet hasn't been sent yet; we are done for now */
-			goto out;
+			break;
 		}
 
-		if(event != 0x11) {
-			PRINT(KERN_ERR, xmit->ohci->id, "IT DMA error - OHCI error code 0x%02x\n", event);
-		}
+		if(event != 0x11)
+			PRINT(KERN_ERR, xmit->ohci->id,
+			      "IT DMA error - OHCI error code 0x%02x\n", event);
 		
 		/* at least one packet went out, so wake up the writer */
 		wake = 1;
 		
-		/* predict the timestamp pkt_dma will have next time around the buffer */
-		{
-			struct hpsb_iso_packet_info* info = hpsb_iso_packet_info(iso, xmit->pkt_dma);
-			unsigned int cycle = cmd->output_last.status & 0x1FFF;
+		/* parse cycle */
+		cycle = cmd->output_last.status & 0x1FFF;
 
-			cycle += iso->buf_packets;
-			while(cycle > 8000)
-				cycle -= 8000;
-			
-			info->cycle = cycle;
-		}
+		/* tell the subsystem the packet has gone out */
+		hpsb_iso_packet_sent(iso, cycle, event != 0x11);
 		
 		/* reset the DMA descriptor for next time */
 		cmd->output_last.status = 0;
-		
-		/* advance packet cursor */
-		xmit->pkt_dma = (xmit->pkt_dma + 1) % iso->buf_packets;
-
-		/* one less packet for us */
-		if(atomic_dec_and_test(&iso->n_dma_packets)) {
-			/* underflow */
-			atomic_inc(&iso->overflows);
-		}
 	}
 
-out:
-	if(wake && iso->callback) {
-		iso->callback(iso);
-	}
+	if(wake)
+		hpsb_iso_wake(iso);
 }
 
-static void ohci_iso_xmit_queue_one(struct hpsb_iso *iso)
+static int ohci_iso_xmit_queue(struct hpsb_iso *iso, struct hpsb_iso_packet_info *info)
 {
 	struct ohci_iso_xmit *xmit = iso->hostdata;
-	struct hpsb_iso_packet_info *info;
+
 	int next_i, prev_i;
 	struct iso_xmit_cmd *next, *prev;
-	
+
+	unsigned int offset;
+	unsigned short len;
+	unsigned char tag, sy;
+
+	/* check that the packet doesn't cross a page boundary
+	   (we could allow this if we added OUTPUT_MORE descriptor support) */
+	if(cross_bound(info->offset, info->len)) {
+		PRINT(KERN_ERR, xmit->ohci->id,
+		      "rawiso xmit: packet %u crosses a page boundary",
+		      iso->first_packet);
+		return -EINVAL;
+	}
+
+	offset = info->offset;
+	len = info->len;
+	tag = info->tag;
+	sy = info->sy;
+
 	/* sync up the card's view of the buffer */
-	dma_region_sync(&iso->buf, iso->first_packet * iso->buf_stride, iso->buf_stride);
+	dma_region_sync(&iso->data_buf, offset, len);
 
 	/* append first_packet to the DMA chain */
 	/* by linking the previous descriptor to it */
 	/* (next will become the new end of the DMA chain) */
-	
+
 	next_i = iso->first_packet;
 	prev_i = (next_i == 0) ? (iso->buf_packets - 1) : (next_i - 1);
-	
+
 	next = dma_region_i(&xmit->prog, struct iso_xmit_cmd, next_i);
 	prev = dma_region_i(&xmit->prog, struct iso_xmit_cmd, prev_i);
 
-	/* retrieve the packet info stashed in the buffer */
-	info = hpsb_iso_packet_info(iso, iso->first_packet);
-	
 	/* set up the OUTPUT_MORE_IMMEDIATE descriptor */
 	memset(next, 0, sizeof(struct iso_xmit_cmd));
 	next->output_more_immediate.control = 0x02000008;
@@ -1574,29 +1987,28 @@
 	/* ISO packet header is embedded in the OUTPUT_MORE_IMMEDIATE */
 
 	/* tcode = 0xA, and sy */
-	next->iso_hdr[0] = 0xA0 | (info->sy & 0xF);
+	next->iso_hdr[0] = 0xA0 | (sy & 0xF);
 
 	/* tag and channel number */
-	next->iso_hdr[1] = (info->tag << 6) | (iso->channel & 0x3F);
+	next->iso_hdr[1] = (tag << 6) | (iso->channel & 0x3F);
 
 	/* transmission speed */
 	next->iso_hdr[2] = iso->speed & 0x7;
 
 	/* payload size */
-	next->iso_hdr[6] = info->len & 0xFF;
-	next->iso_hdr[7] = info->len >> 8;
+	next->iso_hdr[6] = len & 0xFF;
+	next->iso_hdr[7] = len >> 8;
 
 	/* set up the OUTPUT_LAST */
 	next->output_last.control = 1 << 28;
 	next->output_last.control |= 1 << 27; /* update timeStamp */
 	next->output_last.control |= 3 << 20; /* want interrupt */
 	next->output_last.control |= 3 << 18; /* enable branch */
-	next->output_last.control |= info->len;
+	next->output_last.control |= len;
 
 	/* payload bus address */
-	next->output_last.address = dma_region_offset_to_bus(&iso->buf,
-				      hpsb_iso_packet_data(iso, iso->first_packet) - iso->buf.kvirt);
-	
+	next->output_last.address = dma_region_offset_to_bus(&iso->data_buf, offset);
+
 	/* leave branchAddress at zero for now */
 
 	/* re-write the previous DMA descriptor to chain to this one */
@@ -1604,7 +2016,7 @@
 	/* set prev branch address to point to next (Z=3) */
 	prev->output_last.branchAddress =
 		dma_prog_region_offset_to_bus(&xmit->prog, sizeof(struct iso_xmit_cmd) * next_i) | 3;
-	
+
 	/* disable interrupt, unless required by the IRQ interval */
 	if(prev_i % iso->irq_interval) {
 		prev->output_last.control &= ~(3 << 20); /* no interrupt */
@@ -1622,16 +2034,7 @@
 	mb();
 	reg_read(xmit->ohci, OHCI1394_IsochronousCycleTimer);
 
-	/* increment cursors */
-	iso->first_packet = (iso->first_packet+1) % iso->buf_packets;
-	atomic_inc(&iso->n_dma_packets);
-}
-
-static void ohci_iso_xmit_queue(struct hpsb_iso *iso, int n_packets)
-{
-	int i;
-	for(i = 0; i < n_packets; i++)
-		ohci_iso_xmit_queue_one(iso);
+	return 0;
 }
 
 static int ohci_iso_xmit_start(struct hpsb_iso *iso, int cycle)
@@ -1644,7 +2047,7 @@
 
 	/* address and length of first descriptor block (Z=3) */
 	reg_write(xmit->ohci, xmit->CommandPtr,
-		  dma_prog_region_offset_to_bus(&xmit->prog, xmit->pkt_dma * sizeof(struct iso_xmit_cmd)) | 3);
+		  dma_prog_region_offset_to_bus(&xmit->prog, iso->pkt_dma * sizeof(struct iso_xmit_cmd)) | 3);
 
 	/* cycle match */
 	if(cycle != -1) {
@@ -1662,26 +2065,29 @@
 		reg_write(xmit->ohci, xmit->ContextControlSet, 0x80000000 | (start << 16));
 	}
 
+	/* enable interrupts */
+	reg_write(xmit->ohci, OHCI1394_IsoXmitIntMaskSet, 1 << xmit->task.context);
+
 	/* run */
 	reg_write(xmit->ohci, xmit->ContextControlSet, 0x8000);
 	mb();
-	
+
 	/* wait 100 usec to give the card time to go active */
 	udelay(100);
-	
+
 	/* check the RUN bit */
 	if(!(reg_read(xmit->ohci, xmit->ContextControlSet) & 0x8000)) {
 		PRINT(KERN_ERR, xmit->ohci->id, "Error starting IT DMA (ContextControl 0x%08x)\n",
 		      reg_read(xmit->ohci, xmit->ContextControlSet));
 		return -1;
 	}
-	
+
 	return 0;
 }
 
-static int ohci_isoctl(struct hpsb_iso *iso, enum isoctl_cmd cmd, int arg)
+static int ohci_isoctl(struct hpsb_iso *iso, enum isoctl_cmd cmd, unsigned long arg)
 {
-	
+
 	switch(cmd) {
 	case XMIT_INIT:
 		return ohci_iso_xmit_init(iso);
@@ -1691,26 +2097,36 @@
 		ohci_iso_xmit_stop(iso);
 		return 0;
 	case XMIT_QUEUE:
-		ohci_iso_xmit_queue(iso, arg);
-		return 0;
+		return ohci_iso_xmit_queue(iso, (struct hpsb_iso_packet_info*) arg);
 	case XMIT_SHUTDOWN:
 		ohci_iso_xmit_shutdown(iso);
 		return 0;
 
 	case RECV_INIT:
 		return ohci_iso_recv_init(iso);
-	case RECV_START:
-		return ohci_iso_recv_start(iso, arg);
+	case RECV_START: {
+		int *args = (int*) arg;
+		return ohci_iso_recv_start(iso, args[0], args[1], args[2]);
+	}
 	case RECV_STOP:
 		ohci_iso_recv_stop(iso);
 		return 0;
 	case RECV_RELEASE:
-		ohci_iso_recv_release(iso, arg);
+		ohci_iso_recv_release(iso, (struct hpsb_iso_packet_info*) arg);
 		return 0;
 	case RECV_SHUTDOWN:
 		ohci_iso_recv_shutdown(iso);
 		return 0;
-		
+	case RECV_LISTEN_CHANNEL:
+		ohci_iso_recv_change_channel(iso, arg, 1);
+		return 0;
+	case RECV_UNLISTEN_CHANNEL:
+		ohci_iso_recv_change_channel(iso, arg, 0);
+		return 0;
+	case RECV_SET_CHANNEL_MASK:
+		ohci_iso_recv_set_channel_mask(iso, *((u64*) arg));
+		return 0;
+
 	default:
 		PRINT_G(KERN_ERR, "ohci_isoctl cmd %d not implemented yet",
 			cmd);
@@ -1780,7 +2196,7 @@
 
 		if (t->type == OHCI_ISO_TRANSMIT && tx_event & mask)
 			tasklet_schedule(&t->tasklet);
-		if (t->type == OHCI_ISO_RECEIVE && rx_event & mask)
+		else if (rx_event & mask)
 			tasklet_schedule(&t->tasklet);
 	}
 
@@ -1839,7 +2255,7 @@
 
 		for (ctx = 0; ctx < ohci->nb_iso_xmit_ctx; ctx++) {
 			if (reg_read(ohci, OHCI1394_IsoXmitContextControlSet + (16 * ctx)) & 0x800)
-				PRINT(KERN_ERR, ohci->id, "Async Iso Xmit %d Context died: "
+				PRINT(KERN_ERR, ohci->id, "Iso Xmit %d Context died: "
 					"ctrl[%08x] cmdptr[%08x]", ctx,
 					reg_read(ohci, OHCI1394_IsoXmitContextControlSet + (16 * ctx)),
 					reg_read(ohci, OHCI1394_IsoXmitCommandPtr + (16 * ctx)));
@@ -1847,7 +2263,7 @@
 
 		for (ctx = 0; ctx < ohci->nb_iso_rcv_ctx; ctx++) {
 			if (reg_read(ohci, OHCI1394_IsoRcvContextControlSet + (32 * ctx)) & 0x800)
-				PRINT(KERN_ERR, ohci->id, "Async Iso Recv %d Context died: "
+				PRINT(KERN_ERR, ohci->id, "Iso Recv %d Context died: "
 					"ctrl[%08x] cmdptr[%08x] match[%08x]", ctx,
 					reg_read(ohci, OHCI1394_IsoRcvContextControlSet + (32 * ctx)),
 					reg_read(ohci, OHCI1394_IsoRcvCommandPtr + (32 * ctx)),
@@ -2008,8 +2424,8 @@
 			PRINT(KERN_ERR, ohci->id, 
 			      "SelfID received outside of bus reset sequence");
 
-		event &= ~OHCI1394_selfIDComplete;
 selfid_not_valid:
+		event &= ~OHCI1394_selfIDComplete;
 	}
 
 	/* Make sure we handle everything, just in case we accidentally
@@ -2035,8 +2451,10 @@
 		PRINT(KERN_INFO, ohci->id, 
 		      "Waking dma ctx=%d ... processing is probably too slow",
 		      d->ctx);
-		reg_write(ohci, d->ctrlSet, 0x1000);
 	}
+
+	/* do this always, to avoid race condition */
+	reg_write(ohci, d->ctrlSet, 0x1000);
 }
 
 #define cond_le32_to_cpu(data, noswap) \
@@ -2222,7 +2640,7 @@
 	struct ti_ohci *ohci = (struct ti_ohci*)(d->ohci);
 	struct hpsb_packet *packet;
 	unsigned long flags;
-	u32 ack;
+	u32 status, ack;
         size_t datasize;
 
 	spin_lock_irqsave(&d->lock, flags);
@@ -2231,25 +2649,16 @@
 		packet = driver_packet(d->fifo_list.next);
                 datasize = packet->data_size;
 		if (datasize && packet->type != hpsb_raw)
-			ack = le32_to_cpu(
+			status = le32_to_cpu(
 				d->prg_cpu[d->sent_ind]->end.status) >> 16;
 		else 
-			ack = le32_to_cpu(
+			status = le32_to_cpu(
 				d->prg_cpu[d->sent_ind]->begin.status) >> 16;
 
-		if (ack == 0) 
+		if (status == 0) 
 			/* this packet hasn't been sent yet*/
 			break;
 
-		if (!(ack & 0x10)) {
-			/* XXX: This is an OHCI evt_* code. We need to handle
-			 * this specially! For right now, we just fake an
-			 * ackx_send_error. */
-			PRINT(KERN_DEBUG, ohci->id, "Received OHCI evt_* error 0x%x",
-			       ack & 0xf);
-			ack = (ack & 0xffe0) | ACK_BUSY_A;
-		}
-
 #ifdef OHCI1394_DEBUG
 		if (datasize)
 			DBGMSG(ohci->id,
@@ -2261,7 +2670,7 @@
                                         >>4)&0xf,
                                 (le32_to_cpu(d->prg_cpu[d->sent_ind]->data[0])
                                         >>10)&0x3f,
-                                ack&0x1f, (ack>>5)&0x3, 
+                                status&0x1f, (status>>5)&0x3, 
                                 le32_to_cpu(d->prg_cpu[d->sent_ind]->data[3])
                                         >>16,
                                 d->ctx);
@@ -2275,13 +2684,64 @@
                                         >>4)&0xf,
                                 (le32_to_cpu(d->prg_cpu[d->sent_ind]->data[0])
                                         >>10)&0x3f,
-                                ack&0x1f, (ack>>5)&0x3, 
+                                status&0x1f, (status>>5)&0x3, 
                                 le32_to_cpu(d->prg_cpu[d->sent_ind]->data[3]),
                                 d->ctx);
 #endif		
 
+		if (status & 0x10) {
+			ack = status & 0xf;
+		} else {
+			switch (status & 0x1f) {
+			case EVT_NO_STATUS: /* that should never happen */
+			case EVT_RESERVED_A: /* that should never happen */
+			case EVT_LONG_PACKET: /* that should never happen */
+				PRINT(KERN_WARNING, ohci->id, "Received OHCI evt_* error 0x%x", status & 0x1f);
+				ack = ACKX_SEND_ERROR;
+				break;
+			case EVT_MISSING_ACK:
+				ack = ACKX_TIMEOUT;
+				break;
+			case EVT_UNDERRUN:
+				ack = ACKX_SEND_ERROR;
+				break;
+			case EVT_OVERRUN: /* that should never happen */
+				PRINT(KERN_WARNING, ohci->id, "Received OHCI evt_* error 0x%x", status & 0x1f);
+				ack = ACKX_SEND_ERROR;
+				break;
+			case EVT_DESCRIPTOR_READ:
+			case EVT_DATA_READ:
+			case EVT_DATA_WRITE:
+				ack = ACKX_SEND_ERROR;
+				break;
+			case EVT_BUS_RESET: /* that should never happen */
+				PRINT(KERN_WARNING, ohci->id, "Received OHCI evt_* error 0x%x", status & 0x1f);
+				ack = ACKX_SEND_ERROR;
+				break;
+			case EVT_TIMEOUT:
+				ack = ACKX_TIMEOUT;
+				break;
+			case EVT_TCODE_ERR:
+				ack = ACKX_SEND_ERROR;
+				break;
+			case EVT_RESERVED_B: /* that should never happen */
+			case EVT_RESERVED_C: /* that should never happen */
+				PRINT(KERN_WARNING, ohci->id, "Received OHCI evt_* error 0x%x", status & 0x1f);
+				ack = ACKX_SEND_ERROR;
+				break;
+			case EVT_UNKNOWN:
+			case EVT_FLUSHED:
+				ack = ACKX_SEND_ERROR;
+				break;
+			default:
+				PRINT(KERN_ERR, ohci->id, "Unhandled OHCI evt_* error 0x%x", status & 0x1f);
+				ack = ACKX_SEND_ERROR;
+				BUG();
+			}
+		}
+
                 list_del(&packet->driver_list);
-		hpsb_packet_sent(ohci->host, packet, ack & 0xf);
+		hpsb_packet_sent(ohci->host, packet, ack);
 
 		if (datasize) {
 			pci_unmap_single(ohci->dev, 
@@ -2307,13 +2767,18 @@
 		return;
 
 	DBGMSG(d->ohci->id, "Freeing dma_rcv_ctx %d", d->ctx);
-	
-	ohci1394_stop_context(d->ohci, d->ctrlClear, NULL);
 
-	if (d->type == DMA_CTX_ISO)
-		ohci1394_unregister_iso_tasklet(d->ohci, &d->ohci->ir_tasklet);
-	else
-		tasklet_kill(&d->task);
+	if(d->ctrlClear) {
+		ohci1394_stop_context(d->ohci, d->ctrlClear, NULL);
+
+		if (d->type == DMA_CTX_ISO) {
+			/* disable interrupts */
+			reg_write(d->ohci, OHCI1394_IsoRecvIntMaskClear, 1 << d->ctx);
+			ohci1394_unregister_iso_tasklet(d->ohci, &d->ohci->ir_legacy_tasklet);
+		} else {
+			tasklet_kill(&d->task);
+		}
+	}
 
 	if (d->buf_cpu) {
 		for (i=0; i<d->num_desc; i++)
@@ -2358,9 +2823,9 @@
 	d->buf_size = buf_size;
 	d->split_buf_size = split_buf_size;
 
-	d->ctrlSet = context_base + OHCI1394_ContextControlSet;
-	d->ctrlClear = context_base + OHCI1394_ContextControlClear;
-	d->cmdPtr = context_base + OHCI1394_ContextCommandPtr;
+	d->ctrlSet = 0;
+	d->ctrlClear = 0;
+	d->cmdPtr = 0;
 
 	d->buf_cpu = kmalloc(d->num_desc * sizeof(quadlet_t*), GFP_KERNEL);
 	d->buf_bus = kmalloc(d->num_desc * sizeof(dma_addr_t), GFP_KERNEL);
@@ -2428,17 +2893,30 @@
         spin_lock_init(&d->lock);
 
 	if (type == DMA_CTX_ISO) {
-		ohci1394_init_iso_tasklet(&ohci->ir_tasklet, OHCI_ISO_RECEIVE,
+		ohci1394_init_iso_tasklet(&ohci->ir_legacy_tasklet,
+					  OHCI_ISO_MULTICHANNEL_RECEIVE,
 					  dma_rcv_tasklet, (unsigned long) d);
 		if (ohci1394_register_iso_tasklet(ohci,
-						  &ohci->ir_tasklet) < 0) {
+						  &ohci->ir_legacy_tasklet) < 0) {
 			PRINT(KERN_ERR, ohci->id, "No IR DMA context available");
 			free_dma_rcv_ctx(d);
 			return -EBUSY;
 		}
-	}
-	else
+
+		/* the IR context can be assigned to any DMA context
+		 * by ohci1394_register_iso_tasklet */
+		d->ctx = ohci->ir_legacy_tasklet.context;
+		d->ctrlSet = OHCI1394_IsoRcvContextControlSet + 32*d->ctx;
+		d->ctrlClear = OHCI1394_IsoRcvContextControlClear + 32*d->ctx;
+		d->cmdPtr = OHCI1394_IsoRcvCommandPtr + 32*d->ctx;
+		d->ctxtMatch = OHCI1394_IsoRcvContextMatch + 32*d->ctx;
+	} else {
+		d->ctrlSet = context_base + OHCI1394_ContextControlSet;
+		d->ctrlClear = context_base + OHCI1394_ContextControlClear;
+		d->cmdPtr = context_base + OHCI1394_ContextCommandPtr;
+
 		tasklet_init (&d->task, dma_rcv_tasklet, (unsigned long) d);
+	}
 
 	return 0;
 }
@@ -2452,12 +2930,18 @@
 
 	DBGMSG(d->ohci->id, "Freeing dma_trm_ctx %d", d->ctx);
 
-	ohci1394_stop_context(d->ohci, d->ctrlClear, NULL);
+	if(d->ctrlClear) {
+		ohci1394_stop_context(d->ohci, d->ctrlClear, NULL);
 
-	if (d->type == DMA_CTX_ISO)
-		ohci1394_unregister_iso_tasklet(d->ohci, &d->ohci->it_tasklet);
-	else
-		tasklet_kill(&d->task);
+		if (d->type == DMA_CTX_ISO) {
+			/* disable interrupts */
+			reg_write(d->ohci, OHCI1394_IsoXmitIntMaskClear, 1 << d->ctx);
+			ohci1394_unregister_iso_tasklet(d->ohci,
+							&d->ohci->it_legacy_tasklet);
+		} else {
+			tasklet_kill(&d->task);
+		}
+	}
 
 	if (d->prg_cpu) {
 		for (i=0; i<d->num_desc; i++) 
@@ -2486,9 +2970,9 @@
 	d->type = type;
 	d->ctx = ctx;
 	d->num_desc = num_desc;
-	d->ctrlSet = context_base + OHCI1394_ContextControlSet;
-	d->ctrlClear = context_base + OHCI1394_ContextControlClear;
-	d->cmdPtr = context_base + OHCI1394_ContextCommandPtr;
+	d->ctrlSet = 0;
+	d->ctrlClear = 0;
+	d->cmdPtr = 0;
 
 	d->prg_cpu = kmalloc(d->num_desc * sizeof(struct at_dma_prg*), 
 			     GFP_KERNEL);
@@ -2524,17 +3008,26 @@
 
 	/* initialize tasklet */
 	if (type == DMA_CTX_ISO) {
-		ohci1394_init_iso_tasklet(&ohci->it_tasklet, OHCI_ISO_TRANSMIT,
-					  dma_rcv_tasklet, (unsigned long) d);
+		ohci1394_init_iso_tasklet(&ohci->it_legacy_tasklet, OHCI_ISO_TRANSMIT,
+					  dma_trm_tasklet, (unsigned long) d);
 		if (ohci1394_register_iso_tasklet(ohci,
-						  &ohci->it_tasklet) < 0) {
+						  &ohci->it_legacy_tasklet) < 0) {
 			PRINT(KERN_ERR, ohci->id, "No IT DMA context available");
 			free_dma_trm_ctx(d);
 			return -EBUSY;
 		}
-	}
-	else
+
+		/* IT can be assigned to any context by register_iso_tasklet */
+		d->ctx = ohci->it_legacy_tasklet.context;
+		d->ctrlSet = OHCI1394_IsoXmitContextControlSet + 16 * d->ctx;
+		d->ctrlClear = OHCI1394_IsoXmitContextControlClear + 16 * d->ctx;
+		d->cmdPtr = OHCI1394_IsoXmitCommandPtr + 16 * d->ctx;
+	} else {
+		d->ctrlSet = context_base + OHCI1394_ContextControlSet;
+		d->ctrlClear = context_base + OHCI1394_ContextControlClear;
+		d->cmdPtr = context_base + OHCI1394_ContextCommandPtr;
 		tasklet_init (&d->task, dma_trm_tasklet, (unsigned long)d);
+	}
 
 	return 0;
 }
@@ -2739,7 +3232,7 @@
 	struct hpsb_host *host;
 	struct ti_ohci *ohci;	/* shortcut to currently handled device */
 	unsigned long ohci_base;
-	
+
 	if (version_printed++ == 0)
 		PRINT_G(KERN_INFO, "%s", version);
 
@@ -2815,7 +3308,7 @@
 		pci_alloc_consistent(ohci->dev, OHCI1394_SI_DMA_BUF_SIZE,
                       &ohci->selfid_buf_bus);
 	OHCI_DMA_ALLOC("consistent selfid_buf");
-	
+
 	if (ohci->selfid_buf_cpu == NULL)
 		FAIL(-ENOMEM, "Failed to allocate DMA buffer for self-id packets");
 	ohci->init_state = OHCI_INIT_HAVE_SELFID_BUFFER;
@@ -2888,19 +3381,11 @@
 	ohci->ISO_channel_usage = 0;
         spin_lock_init(&ohci->IR_channel_lock);
 
-	/* IR DMA context */
-	if (alloc_dma_rcv_ctx(ohci, &ohci->ir_context,
-			      DMA_CTX_ISO, 0, IR_NUM_DESC,
-			      IR_BUF_SIZE, IR_SPLIT_BUF_SIZE,
-			      OHCI1394_IsoRcvContextBase) < 0)
-		FAIL(-ENOMEM, "Failed to allocate IR context");
+	/* the IR DMA context is allocated on-demand; mark it inactive */
+	ohci->ir_legacy_context.ohci = NULL;
 
-	
-	/* IT DMA context allocation */
-	if (alloc_dma_trm_ctx(ohci, &ohci->it_context,
-			      DMA_CTX_ISO, 0, IT_NUM_DESC,
-			      OHCI1394_IsoXmitContextBase) < 0)
-		FAIL(-ENOMEM, "Failed to allocate IT context");
+	/* same for the IT DMA context */
+	ohci->it_legacy_context.ohci = NULL;
 
 	if (request_irq(dev->irq, ohci_irq_handler, SA_SHIRQ,
 			 OHCI1394_DRIVER_NAME, ohci))
@@ -2945,11 +3430,11 @@
 		free_dma_trm_ctx(&ohci->at_resp_context);
 
 		/* Free IR dma */
-		free_dma_rcv_ctx(&ohci->ir_context);
-		
+		free_dma_rcv_ctx(&ohci->ir_legacy_context);
+
 		/* Free IT dma */
-		free_dma_trm_ctx(&ohci->it_context);
-	
+		free_dma_trm_ctx(&ohci->it_legacy_context);
+
 	case OHCI_INIT_HAVE_SELFID_BUFFER:
 		pci_free_consistent(ohci->dev, OHCI1394_SI_DMA_BUF_SIZE, 
 				    ohci->selfid_buf_cpu,
@@ -3025,7 +3510,7 @@
 /* essentially the only purpose of this code is to allow another
    module to hook into ohci's interrupt handler */
 
-void ohci1394_stop_context(struct ti_ohci *ohci, int reg, char *msg)
+int ohci1394_stop_context(struct ti_ohci *ohci, int reg, char *msg)
 {
 	int i=0;
 
@@ -3037,11 +3522,15 @@
 		i++;
 		if (i>5000) {
 			PRINT(KERN_ERR, ohci->id, 
-			      "Runaway loop while stopping context...");
-			break;
+			      "Runaway loop while stopping context: %s...", msg ? msg : "");
+			return 1;
 		}
+
+		mb();
+		udelay(10);
 	}
 	if (msg) PRINT(KERN_ERR, ohci->id, "%s: dma prg stopped", msg);
+	return 0;
 }
 
 void ohci1394_init_iso_tasklet(struct ohci1394_iso_tasklet *tasklet, int type,
@@ -3067,6 +3556,13 @@
 	else {
 		n = ohci->nb_iso_rcv_ctx;
 		usage = &ohci->ir_ctx_usage;
+
+		/* only one receive context can be multichannel (OHCI sec 10.4.1) */
+		if(tasklet->type == OHCI_ISO_MULTICHANNEL_RECEIVE) {
+			if(test_and_set_bit(0, &ohci->ir_multichannel_used)) {
+				return r;
+			}
+		}
 	}
 
 	spin_lock_irqsave(&ohci->iso_tasklet_list_lock, flags);
@@ -3080,7 +3576,7 @@
 		}
 
 	spin_unlock_irqrestore(&ohci->iso_tasklet_list_lock, flags);
-	
+
 	return r;
 }
 
@@ -3095,8 +3591,13 @@
 
 	if (tasklet->type == OHCI_ISO_TRANSMIT)
 		clear_bit(tasklet->context, &ohci->it_ctx_usage);
-	else
+	else {
 		clear_bit(tasklet->context, &ohci->ir_ctx_usage);
+
+		if(tasklet->type == OHCI_ISO_MULTICHANNEL_RECEIVE) {
+			clear_bit(0, &ohci->ir_multichannel_used);
+		}
+	}
 
 	list_del(&tasklet->link);
 
diff -Nru a/drivers/ieee1394/ohci1394.h b/drivers/ieee1394/ohci1394.h
--- a/drivers/ieee1394/ohci1394.h	Mon Feb 17 14:57:26 2003
+++ b/drivers/ieee1394/ohci1394.h	Mon Feb 17 14:57:26 2003
@@ -109,6 +109,7 @@
 	int ctrlClear;
 	int ctrlSet;
 	int cmdPtr;
+	int ctxtMatch;
 };
 
 /* DMA transmit context */	
@@ -145,7 +146,8 @@
 	struct tasklet_struct tasklet;
 	struct list_head link;
 	int context;
-	enum { OHCI_ISO_TRANSMIT, OHCI_ISO_RECEIVE } type;
+	enum { OHCI_ISO_TRANSMIT, OHCI_ISO_RECEIVE,
+	       OHCI_ISO_MULTICHANNEL_RECEIVE } type;
 };
 
 struct ti_ohci {
@@ -170,7 +172,7 @@
 	/* dma buffer for self-id packets */
         quadlet_t *selfid_buf_cpu;
         dma_addr_t selfid_buf_bus;
-	
+
 	/* buffer for csr config rom */
         quadlet_t *csr_config_rom_cpu; 
         dma_addr_t csr_config_rom_bus; 
@@ -187,18 +189,28 @@
 	struct dma_trm_ctx at_req_context;
 
         /* iso receive */
-	struct dma_rcv_ctx ir_context;
-	struct ohci1394_iso_tasklet ir_tasklet;
-        spinlock_t IR_channel_lock;
 	int nb_iso_rcv_ctx;
 	unsigned long ir_ctx_usage; /* use test_and_set_bit() for atomicity */
+	unsigned long ir_multichannel_used; /* ditto */
+        spinlock_t IR_channel_lock;
+
+	/* iso receive (legacy API) */
+	u64 ir_legacy_channels; /* note: this differs from ISO_channel_usage;
+				   it only accounts for channels listened to
+				   by the legacy API, so that we can know when
+				   it is safe to free the legacy API context */
+
+	struct dma_rcv_ctx ir_legacy_context;
+	struct ohci1394_iso_tasklet ir_legacy_tasklet;
 	
         /* iso transmit */
-	struct dma_trm_ctx it_context;
-	struct ohci1394_iso_tasklet it_tasklet;
 	int nb_iso_xmit_ctx;
 	unsigned long it_ctx_usage; /* use test_and_set_bit() for atomicity */
-	
+
+	/* iso transmit (legacy API) */
+	struct dma_trm_ctx it_legacy_context;
+	struct ohci1394_iso_tasklet it_legacy_tasklet;
+
         u64 ISO_channel_usage;
 
         /* IEEE-1394 part follows */
@@ -213,10 +225,10 @@
 
 	/* Tasklets for iso receive and transmit, used by video1394,
 	 * amdtp and dv1394 */
-	
+
 	struct list_head iso_tasklet_list;
 	spinlock_t iso_tasklet_list_lock;
-	
+
 	/* Swap the selfid buffer? */
 	unsigned int selfid_swap:1;
 	/* Some Apple chipset seem to swap incoming headers for us */
@@ -385,7 +397,7 @@
 
 /* OHCI evt_* error types, table 3-2 of the OHCI 1.1 spec. */
 #define EVT_NO_STATUS		0x0	/* No event status */
-#define EVT_RESERVED		0x1	/* Reserved, not used !!! */
+#define EVT_RESERVED_A		0x1	/* Reserved, not used !!! */
 #define EVT_LONG_PACKET		0x2	/* The revc data was longer than the buf */
 #define EVT_MISSING_ACK		0x3	/* A subaction gap was detected before an ack
 					   arrived, or recv'd ack had a parity error */
@@ -404,6 +416,17 @@
 					   16-bit host memory write */
 #define EVT_BUS_RESET		0x9	/* Identifies a PHY packet in the recv buffer as
 					   being a synthesized bus reset packet */
+#define EVT_TIMEOUT		0xa	/* Indicates that the asynchronous transmit response
+					   packet expired and was not transmitted, or that an
+					   IT DMA context experienced a skip processing overflow */
+#define EVT_TCODE_ERR		0xb	/* A bad tCode is associated with this packet.
+					   The packet was flushed */
+#define EVT_RESERVED_B		0xc	/* Reserved, not used !!! */
+#define EVT_RESERVED_C		0xd	/* Reserved, not used !!! */
+#define EVT_UNKNOWN		0xe	/* An error condition has occurred that cannot be
+					   represented by any other event codes defined herein. */
+#define EVT_FLUSHED		0xf	/* Send by the link side of output FIFO when asynchronous
+					   packets are being flushed due to a bus reset. */
 
 #define OHCI1394_TCODE_PHY               0xE
 
@@ -416,8 +439,8 @@
 void ohci1394_unregister_iso_tasklet(struct ti_ohci *ohci,
 				     struct ohci1394_iso_tasklet *tasklet);
 
-void ohci1394_stop_context      (struct ti_ohci *ohci, int reg, char *msg);
+/* returns zero if successful, one if DMA context is locked up */
+int ohci1394_stop_context      (struct ti_ohci *ohci, int reg, char *msg);
 struct ti_ohci *ohci1394_get_struct(int card_num);
 
 #endif
-
diff -Nru a/drivers/ieee1394/pcilynx.c b/drivers/ieee1394/pcilynx.c
--- a/drivers/ieee1394/pcilynx.c	Mon Feb 17 14:57:27 2003
+++ b/drivers/ieee1394/pcilynx.c	Mon Feb 17 14:57:27 2003
@@ -27,6 +27,7 @@
  *            eeprom via i2c and storing it in config ROM
  *        Reworked code for initiating bus resets
  *            (long, short, with or without hold-off)
+ *        Enhancements in async and iso send code
  */
 
 #include <linux/config.h>
@@ -127,23 +128,20 @@
 }
 
 static struct i2c_algo_bit_data bit_data = {
-	NULL,
-	bit_setsda,
-	bit_setscl,
-	bit_getsda,
-	bit_getscl,
-	5, 5, 100,		/*	waits, timeout */
+	.setsda			= bit_setsda,
+	.setscl			= bit_setscl,
+	.getsda			= bit_getsda,
+	.getscl			= bit_getscl,
+	.udelay			= 5,
+	.mdelay			= 5,
+	.timeout		= 100,
 }; 
 
 static struct i2c_adapter bit_ops = {
-	"PCILynx I2C adapter",
-	0xAA, //FIXME: probably we should get an id in i2c-id.h
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	bit_reg,
-	bit_unreg,
+	.name			= "PCILynx I2C adapter",
+	.id 			= 0xAA, //FIXME: probably we should get an id in i2c-id.h
+	.client_register	= bit_reg,
+	.client_unregister	= bit_unreg,
 };
 
 
@@ -476,7 +474,14 @@
         struct hpsb_packet *packet;
 
         d = (what == hpsb_iso ? &lynx->iso_send : &lynx->async);
+        if (!list_empty(&d->pcl_queue)) {
+                PRINT(KERN_ERR, lynx->id, "trying to queue a new packet in nonempty fifo");
+                BUG();
+        }
+
         packet = driver_packet(d->queue.next);
+        list_del(&packet->driver_list);
+        list_add_tail(&packet->driver_list, &d->pcl_queue);
 
         d->header_dma = pci_map_single(lynx->dev, packet->header,
                                        packet->header_size, PCI_DMA_TODEVICE);
@@ -490,6 +495,7 @@
 
         pcl.next = PCL_NEXT_INVALID;
         pcl.async_error_next = PCL_NEXT_INVALID;
+        pcl.pcl_status = 0;
 #ifdef __BIG_ENDIAN
         pcl.buffer[0].control = packet->speed_code << 14 | packet->header_size;
 #else
@@ -556,7 +562,7 @@
         spin_lock_irqsave(&d->queue_lock, flags);
 
 	list_add_tail(&packet->driver_list, &d->queue);
-	if (d->queue.next == &packet->driver_list)
+	if (list_empty(&d->pcl_queue))
                 send_next(lynx, packet->type);
 
         spin_unlock_irqrestore(&d->queue_lock, flags);
@@ -748,7 +754,44 @@
 		list_splice(&lynx->async.queue, &packet_list);
 		INIT_LIST_HEAD(&lynx->async.queue);
 
-                spin_unlock_irqrestore(&lynx->async.queue_lock, flags);
+                if (list_empty(&lynx->async.pcl_queue)) {
+                        spin_unlock_irqrestore(&lynx->async.queue_lock, flags);
+                        PRINTD(KERN_DEBUG, lynx->id, "no async packet in PCL to cancel");
+                } else {
+                        struct ti_pcl pcl;
+                        u32 ack;
+                        struct hpsb_packet *packet;
+
+                        PRINT(KERN_INFO, lynx->id, "cancelling async packet, that was already in PCL");
+
+                        get_pcl(lynx, lynx->async.pcl, &pcl);
+
+                        packet = driver_packet(lynx->async.pcl_queue.next);
+                        list_del(&packet->driver_list);
+
+                        pci_unmap_single(lynx->dev, lynx->async.header_dma,
+                                         packet->header_size, PCI_DMA_TODEVICE);
+                        if (packet->data_size) {
+                                pci_unmap_single(lynx->dev, lynx->async.data_dma,
+                                                 packet->data_size, PCI_DMA_TODEVICE);
+                        }
+
+                        spin_unlock_irqrestore(&lynx->async.queue_lock, flags);
+
+                        if (pcl.pcl_status & DMA_CHAN_STAT_PKTCMPL) {
+                                if (pcl.pcl_status & DMA_CHAN_STAT_SPECIALACK) {
+                                        ack = (pcl.pcl_status >> 15) & 0xf;
+                                        PRINTD(KERN_INFO, lynx->id, "special ack %d", ack);
+                                        ack = (ack == 1 ? ACKX_TIMEOUT : ACKX_SEND_ERROR);
+                                } else {
+                                        ack = (pcl.pcl_status >> 15) & 0xf;
+                                }
+                        } else {
+                                PRINT(KERN_INFO, lynx->id, "async packet was not completed");
+                                ack = ACKX_ABORTED;
+                        }
+                        hpsb_packet_sent(host, packet, ack);
+                }
 
 		while (!list_empty(&packet_list)) {
 			packet = driver_packet(packet_list.next);
@@ -759,13 +802,14 @@
                 break;
 
         case MODIFY_USAGE:
-                if (arg) {
-                        MOD_INC_USE_COUNT;
-                } else {
-                        MOD_DEC_USE_COUNT;
-                }
+		if (arg) {
+			if (try_module_get(THIS_MODULE))
+				retval = 1;
+		} else {
+			module_put(THIS_MODULE);
+			retval = 1;
+		}
 
-                retval = 1;
                 break;
 
         case ISO_LISTEN_CHANNEL:
@@ -1021,21 +1065,13 @@
         ssize_t retval;
         void *membase;
 
-	if (*offset != off)	/* Check for EOF before we trust wrap */
-		return 0;
-	
-	/* FIXME: Signed wrap is undefined in C - wants fixing up */
-	if (off + count > off)
-		return 0;
-		
-        if ((off + count) > PCILYNX_MAX_MEMORY + 1) {
-                count = PCILYNX_MAX_MEMORY + 1 - off;
+        if ((off + count) > PCILYNX_MAX_MEMORY+1) {
+                count = PCILYNX_MAX_MEMORY+1 - off;
         }
-        if (count == 0) {
-                return 0;
+        if (count == 0 || off > PCILYNX_MAX_MEMORY) {
+                return -ENOSPC;
         }
 
-
         switch (md->type) {
         case rom:
                 membase = md->lynx->local_rom;
@@ -1145,11 +1181,11 @@
         linkint = reg_read(lynx, LINK_INT_STATUS);
         intmask = reg_read(lynx, PCI_INT_STATUS);
 
+        if (!(intmask & PCI_INT_INT_PEND)) return;
+
         PRINTD(KERN_DEBUG, lynx->id, "interrupt: 0x%08x / 0x%08x", intmask,
                linkint);
 
-        if (!(intmask & PCI_INT_INT_PEND)) return;
-
         reg_write(lynx, LINK_INT_STATUS, linkint);
         reg_write(lynx, PCI_INT_STATUS, intmask);
 
@@ -1248,62 +1284,96 @@
         }
 
         if (intmask & PCI_INT_DMA_HLT(CHANNEL_ASYNC_SEND)) {
-                u32 ack;
-                struct hpsb_packet *packet;
-                
+                PRINTD(KERN_DEBUG, lynx->id, "async sent");
                 spin_lock(&lynx->async.queue_lock);
 
-                ack = reg_read(lynx, DMA_CHAN_STAT(CHANNEL_ASYNC_SEND));
-
-		packet = driver_packet(lynx->async.queue.next);
-		list_del(&packet->driver_list);
-
-                pci_unmap_single(lynx->dev, lynx->async.header_dma,
-                                 packet->header_size, PCI_DMA_TODEVICE);
-                if (packet->data_size) {
-                        pci_unmap_single(lynx->dev, lynx->async.data_dma,
-                                         packet->data_size, PCI_DMA_TODEVICE);
-                }
+                if (list_empty(&lynx->async.pcl_queue)) {
+                        spin_unlock(&lynx->async.queue_lock);
+                        PRINT(KERN_WARNING, lynx->id, "async dma halted, but no queued packet (maybe it was cancelled)");
+                } else {
+                        struct ti_pcl pcl;
+                        u32 ack;
+                        struct hpsb_packet *packet;
+
+                        get_pcl(lynx, lynx->async.pcl, &pcl);
+
+                        packet = driver_packet(lynx->async.pcl_queue.next);
+                        list_del(&packet->driver_list);
+
+                        pci_unmap_single(lynx->dev, lynx->async.header_dma,
+                                         packet->header_size, PCI_DMA_TODEVICE);
+                        if (packet->data_size) {
+                                pci_unmap_single(lynx->dev, lynx->async.data_dma,
+                                                 packet->data_size, PCI_DMA_TODEVICE);
+                        }
 
-                if (!list_empty(&lynx->async.queue)) {
-                        send_next(lynx, hpsb_async);
-                }
+                        if (!list_empty(&lynx->async.queue)) {
+                                send_next(lynx, hpsb_async);
+                        }
 
-                spin_unlock(&lynx->async.queue_lock);
+                        spin_unlock(&lynx->async.queue_lock);
 
-                if (ack & DMA_CHAN_STAT_SPECIALACK) {
-                        ack = (ack >> 15) & 0xf;
-                        PRINTD(KERN_INFO, lynx->id, "special ack %d", ack);
-                        ack = (ack == 1 ? ACKX_TIMEOUT : ACKX_SEND_ERROR);
-                } else {
-                        ack = (ack >> 15) & 0xf;
+                        if (pcl.pcl_status & DMA_CHAN_STAT_PKTCMPL) {
+                                if (pcl.pcl_status & DMA_CHAN_STAT_SPECIALACK) {
+                                        ack = (pcl.pcl_status >> 15) & 0xf;
+                                        PRINTD(KERN_INFO, lynx->id, "special ack %d", ack);
+                                        ack = (ack == 1 ? ACKX_TIMEOUT : ACKX_SEND_ERROR);
+                                } else {
+                                        ack = (pcl.pcl_status >> 15) & 0xf;
+                                }
+                        } else {
+                                PRINT(KERN_INFO, lynx->id, "async packet was not completed");
+                                ack = ACKX_SEND_ERROR;
+                        }
+                        hpsb_packet_sent(host, packet, ack);
                 }
-                
-                hpsb_packet_sent(host, packet, ack);
         }
 
         if (intmask & PCI_INT_DMA_HLT(CHANNEL_ISO_SEND)) {
-                struct hpsb_packet *packet;
-
+                PRINTD(KERN_DEBUG, lynx->id, "iso sent");
                 spin_lock(&lynx->iso_send.queue_lock);
 
-		packet = driver_packet(lynx->iso_send.queue.next);
-		list_del(&packet->driver_list);
+                if (list_empty(&lynx->iso_send.pcl_queue)) {
+                        spin_unlock(&lynx->iso_send.queue_lock);
+                        PRINT(KERN_ERR, lynx->id, "iso send dma halted, but no queued packet");
+                } else {
+                        struct ti_pcl pcl;
+                        u32 ack;
+                        struct hpsb_packet *packet;
+
+                        get_pcl(lynx, lynx->iso_send.pcl, &pcl);
+
+                        packet = driver_packet(lynx->iso_send.pcl_queue.next);
+                        list_del(&packet->driver_list);
+
+                        pci_unmap_single(lynx->dev, lynx->iso_send.header_dma,
+                                         packet->header_size, PCI_DMA_TODEVICE);
+                        if (packet->data_size) {
+                                pci_unmap_single(lynx->dev, lynx->iso_send.data_dma,
+                                                 packet->data_size, PCI_DMA_TODEVICE);
+                        }
 
-                pci_unmap_single(lynx->dev, lynx->iso_send.header_dma,
-                                 packet->header_size, PCI_DMA_TODEVICE);
-                if (packet->data_size) {
-                        pci_unmap_single(lynx->dev, lynx->iso_send.data_dma,
-                                         packet->data_size, PCI_DMA_TODEVICE);
-                }
+                        if (!list_empty(&lynx->iso_send.queue)) {
+                                send_next(lynx, hpsb_iso);
+                        }
 
-                if (!list_empty(&lynx->iso_send.queue)) {
-                        send_next(lynx, hpsb_iso);
-                }
+                        spin_unlock(&lynx->iso_send.queue_lock);
 
-                spin_unlock(&lynx->iso_send.queue_lock);
+                        if (pcl.pcl_status & DMA_CHAN_STAT_PKTCMPL) {
+                                if (pcl.pcl_status & DMA_CHAN_STAT_SPECIALACK) {
+                                        ack = (pcl.pcl_status >> 15) & 0xf;
+                                        PRINTD(KERN_INFO, lynx->id, "special ack %d", ack);
+                                        ack = (ack == 1 ? ACKX_TIMEOUT : ACKX_SEND_ERROR);
+                                } else {
+                                        ack = (pcl.pcl_status >> 15) & 0xf;
+                                }
+                        } else {
+                                PRINT(KERN_INFO, lynx->id, "iso send packet was not completed");
+                                ack = ACKX_SEND_ERROR;
+                        }
 
-                hpsb_packet_sent(host, packet, ACK_COMPLETE);
+                        hpsb_packet_sent(host, packet, ack); //FIXME: maybe we should just use ACK_COMPLETE and ACKX_SEND_ERROR
+                }
         }
 
         if (intmask & PCI_INT_DMA_HLT(CHANNEL_ASYNC_RCV)) {
@@ -1605,7 +1675,9 @@
         lynx->phy_reg0 = -1;
 
 	INIT_LIST_HEAD(&lynx->async.queue);
+	INIT_LIST_HEAD(&lynx->async.pcl_queue);
 	INIT_LIST_HEAD(&lynx->iso_send.queue);
+	INIT_LIST_HEAD(&lynx->iso_send.pcl_queue);
 
         pcl.next = pcl_bus(lynx, lynx->rcv_pcl);
         put_pcl(lynx, lynx->rcv_pcl_start, &pcl);
diff -Nru a/drivers/ieee1394/pcilynx.h b/drivers/ieee1394/pcilynx.h
--- a/drivers/ieee1394/pcilynx.h	Mon Feb 17 14:57:26 2003
+++ b/drivers/ieee1394/pcilynx.h	Mon Feb 17 14:57:26 2003
@@ -95,6 +95,7 @@
         struct lynx_send_data {
                 pcl_t pcl_start, pcl;
                 struct list_head queue;
+                struct list_head pcl_queue; /* this queue contains at most one packet */
                 spinlock_t queue_lock;
                 dma_addr_t header_dma, data_dma;
                 int channel;
@@ -514,13 +515,13 @@
 
 static quadlet_t lynx_csr_rom[] = {
 /* bus info block     offset (hex) */
-        _(0x04040000), /* info/CRC length, CRC              400  */
+        _(0x04046aaf), /* info/CRC length, CRC              400  */
         _(0x31333934), /* 1394 magic number                 404  */
         _(0xf064a000), /* misc. settings                    408  */
         _(0x08002850), /* vendor ID, chip ID high           40c  */
         _(0x0000ffff), /* chip ID low                       410  */
 /* root directory */
-        _(0x00090000), /* directory length, CRC             414  */
+        _(0x00095778), /* directory length, CRC             414  */
         _(0x03080028), /* vendor ID (Texas Instr.)          418  */
         _(0x81000008), /* offset to textual ID              41c  */
         _(0x0c000200), /* node capabilities                 420  */
@@ -530,8 +531,8 @@
         _(0x81000014), /* offset to textual ID              430  */
         _(0x09000000), /* node hardware version             434  */
         _(0x81000018), /* offset to textual ID              438  */
-  /* module vendor ID textual */
-        _(0x00070000), /* CRC length, CRC                   43c  */
+/* module vendor ID textual */
+        _(0x00070812), /* CRC length, CRC                   43c  */
         _(0x00000000), /*                                   440  */
         _(0x00000000), /*                                   444  */
         _(0x54455841), /* "Texas Instruments"               448  */
@@ -540,25 +541,25 @@
         _(0x4d454e54), /*                                   454  */
         _(0x53000000), /*                                   458  */
 /* node unique ID leaf */
-        _(0x00020000), /* CRC length, CRC                   45c  */
+        _(0x00022ead), /* CRC length, CRC                   45c  */
         _(0x08002850), /* vendor ID, chip ID high           460  */
         _(0x0000ffff), /* chip ID low                       464  */
 /* module dependent info */
-        _(0x00050000), /* CRC length, CRC                   468  */
+        _(0x0005d837), /* CRC length, CRC                   468  */
         _(0x81000012), /* offset to module textual ID       46c  */
         _(0x81000017), /* textual descriptor                470  */
         _(0x39010000), /* SRAM size                         474  */
         _(0x3a010000), /* AUXRAM size                       478  */
         _(0x3b000000), /* AUX device                        47c  */
 /* module textual ID */
-        _(0x00050000), /* CRC length, CRC                   480  */
+        _(0x000594df), /* CRC length, CRC                   480  */
         _(0x00000000), /*                                   484  */
         _(0x00000000), /*                                   488  */
         _(0x54534231), /* "TSB12LV21"                       48c  */
         _(0x324c5632), /*                                   490  */
         _(0x31000000), /*                                   494  */
 /* part number */
-        _(0x00060000), /* CRC length, CRC                   498  */
+        _(0x00068405), /* CRC length, CRC                   498  */
         _(0x00000000), /*                                   49c  */
         _(0x00000000), /*                                   4a0  */
         _(0x39383036), /* "9806000-0001"                    4a4  */
@@ -566,14 +567,14 @@
         _(0x30303031), /*                                   4ac  */
         _(0x20000001), /*                                   4b0  */
 /* module hardware version textual */
-        _(0x00050000), /* CRC length, CRC                   4b4  */
+        _(0x00056501), /* CRC length, CRC                   4b4  */
         _(0x00000000), /*                                   4b8  */
         _(0x00000000), /*                                   4bc  */
         _(0x5453424b), /* "TSBKPCITST"                      4c0  */
         _(0x50434954), /*                                   4c4  */
         _(0x53540000), /*                                   4c8  */
 /* node hardware version textual */
-        _(0x00050000), /* CRC length, CRC                   4d0  */
+        _(0x0005d805), /* CRC length, CRC                   4d0  */
         _(0x00000000), /*                                   4d4  */
         _(0x00000000), /*                                   4d8  */
         _(0x54534232), /* "TSB21LV03"                       4dc  */
diff -Nru a/drivers/ieee1394/raw1394-private.h b/drivers/ieee1394/raw1394-private.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/ieee1394/raw1394-private.h	Mon Feb 17 14:57:28 2003
@@ -0,0 +1,78 @@
+#ifndef IEEE1394_RAW1394_PRIVATE_H
+#define IEEE1394_RAW1394_PRIVATE_H
+
+/* header for definitions that are private to the raw1394 driver
+   and not visible to user-space */
+
+#define RAW1394_DEVICE_MAJOR      171
+#define RAW1394_DEVICE_NAME       "raw1394"
+
+struct iso_block_store {
+        atomic_t refcount;
+        size_t data_size;
+        quadlet_t data[0];
+};
+
+enum raw1394_iso_state { RAW1394_ISO_INACTIVE = 0,
+			 RAW1394_ISO_RECV = 1,
+			 RAW1394_ISO_XMIT = 2 };
+
+struct file_info {
+        struct list_head list;
+
+        enum { opened, initialized, connected } state;
+        unsigned int protocol_version;
+
+        struct hpsb_host *host;
+
+        struct list_head req_pending;
+        struct list_head req_complete;
+        struct semaphore complete_sem;
+        spinlock_t reqlists_lock;
+        wait_queue_head_t poll_wait_complete;
+
+        struct list_head addr_list;           
+
+        u8 *fcp_buffer;
+
+	/* old ISO API */
+        u64 listen_channels;
+        quadlet_t *iso_buffer;
+        size_t iso_buffer_length;
+
+        u8 notification; /* (busreset-notification) RAW1394_NOTIFY_OFF/ON */
+
+	/* new rawiso API */
+	enum raw1394_iso_state iso_state;
+	struct hpsb_iso *iso_handle;
+};
+
+struct arm_addr {
+        struct list_head addr_list; /* file_info list */
+        u64    start, end;
+        u64    arm_tag;
+        u8     access_rights;
+        u8     notification_options;
+        u8     client_transactions;
+        u64    recvb;
+        u16    rec_length;
+        u8     *addr_space_buffer; /* accessed by read/write/lock */
+};
+
+struct pending_request {
+        struct list_head list;
+        struct file_info *file_info;
+        struct hpsb_packet *packet;
+        struct iso_block_store *ibs;
+        quadlet_t *data;
+        int free_data;
+        struct raw1394_request req;
+};
+
+struct host_info {
+        struct list_head list;
+        struct hpsb_host *host;
+        struct list_head file_info_list;
+};
+
+#endif  /* IEEE1394_RAW1394_PRIVATE_H */
diff -Nru a/drivers/ieee1394/raw1394.c b/drivers/ieee1394/raw1394.c
--- a/drivers/ieee1394/raw1394.c	Mon Feb 17 14:57:26 2003
+++ b/drivers/ieee1394/raw1394.c	Mon Feb 17 14:57:26 2003
@@ -50,7 +50,7 @@
 #include "iso.h"
 #include "ieee1394_transactions.h"
 #include "raw1394.h"
-
+#include "raw1394-private.h"
 
 #if BITS_PER_LONG == 64
 #define int2ptr(x) ((void *)x)
@@ -558,7 +558,7 @@
                                 lh = lh->next;
                         }
                         hi = list_entry(lh, struct host_info, list);
-                        hpsb_ref_host(hi->host);
+                        hpsb_ref_host(hi->host); // XXX Need to handle failure case
                         list_add_tail(&fi->list, &hi->file_info_list);
                         fi->host = hi->host;
                         fi->state = connected;
@@ -603,10 +603,13 @@
                 if (fi->listen_channels & (1ULL << channel)) {
                         req->req.error = RAW1394_ERROR_ALREADY;
                 } else {
-                        fi->listen_channels |= 1ULL << channel;
-                        hpsb_listen_channel(hl_handle, fi->host, channel);
-                        fi->iso_buffer = int2ptr(req->req.recvb);
-                        fi->iso_buffer_length = req->req.length;
+                        if(hpsb_listen_channel(hl_handle, fi->host, channel)) {
+				req->req.error = RAW1394_ERROR_ALREADY;
+			} else {
+				fi->listen_channels |= 1ULL << channel;
+				fi->iso_buffer = int2ptr(req->req.recvb);
+				fi->iso_buffer_length = req->req.length;
+			}
                 }
         } else {
                 /* deallocate channel (one's complement neg) req.misc */
@@ -2004,7 +2007,7 @@
 {
 	struct list_head *lh;
 	struct pending_request *req;
-	
+
 	list_for_each(lh, &fi->req_complete) {
 		req = list_entry(lh, struct pending_request, list);
 		if(req->req.type == RAW1394_REQ_RAWISO_ACTIVITY) {
@@ -2015,59 +2018,63 @@
 	return 0;
 }
 
+/* put a RAWISO_ACTIVITY event in the queue, if one isn't there already */
+static void queue_rawiso_event(struct file_info *fi)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&fi->reqlists_lock, flags);
+
+	/* only one ISO activity event may be in the queue */
+	if(!__rawiso_event_in_queue(fi)) {
+		struct pending_request *req = __alloc_pending_request(SLAB_ATOMIC);
+
+		if(req) {
+			req->file_info = fi;
+			req->req.type = RAW1394_REQ_RAWISO_ACTIVITY;
+			req->req.generation = get_hpsb_generation(fi->host);
+			__queue_complete_req(req);
+		} else {
+			/* on allocation failure, signal an overflow */
+			if(fi->iso_handle) {
+				atomic_inc(&fi->iso_handle->overflows);
+			}
+		}
+	}
+	spin_unlock_irqrestore(&fi->reqlists_lock, flags);
+}
+
 static void rawiso_activity_cb(struct hpsb_iso *iso)
 {
-	unsigned long host_flags;
+	unsigned long flags;
         struct list_head *lh;
         struct host_info *hi;
 
-        spin_lock_irqsave(&host_info_lock, host_flags);
+        spin_lock_irqsave(&host_info_lock, flags);
         hi = find_host_info(iso->host);
-	
+
 	if (hi != NULL) {
 		list_for_each(lh, &hi->file_info_list) {
-			unsigned long reqlist_flags;
 			struct file_info *fi = list_entry(lh, struct file_info, list);
-			
-			spin_lock_irqsave(&fi->reqlists_lock, reqlist_flags);
-
-			/* only one ISO activity event may be in the queue */
-			if(!__rawiso_event_in_queue(fi)) {
-				struct pending_request *req = __alloc_pending_request(SLAB_ATOMIC);
-
-				if(req) {
-					req->file_info = fi;
-					req->req.type = RAW1394_REQ_RAWISO_ACTIVITY;
-					req->req.generation = get_hpsb_generation(iso->host);
-					__queue_complete_req(req);
-				} else {
-					/* on allocation failure, signal an overflow */
-					if(fi->iso_handle) {
-						atomic_inc(&fi->iso_handle->overflows);
-					}
-				}
-			}
-			spin_unlock_irqrestore(&fi->reqlists_lock, reqlist_flags);
+			if(fi->iso_handle == iso)
+				queue_rawiso_event(fi);
 		}
 	}
-	
-	spin_unlock_irqrestore(&host_info_lock, host_flags);
+
+	spin_unlock_irqrestore(&host_info_lock, flags);
 }
 
 /* helper function - gather all the kernel iso status bits for returning to user-space */
 static void raw1394_iso_fill_status(struct hpsb_iso *iso, struct raw1394_iso_status *stat)
 {
+	stat->config.data_buf_size = iso->buf_size;
 	stat->config.buf_packets = iso->buf_packets;
-	stat->config.max_packet_size = iso->max_packet_size;
 	stat->config.channel = iso->channel;
 	stat->config.speed = iso->speed;
 	stat->config.irq_interval = iso->irq_interval;
-	stat->buf_stride = iso->buf_stride;
-	stat->packet_data_offset = iso->packet_data_offset;
-	stat->packet_info_offset = iso->packet_info_offset;
-	stat->first_packet = iso->first_packet;
 	stat->n_packets = hpsb_iso_n_ready(iso);
 	stat->overflows = atomic_read(&iso->overflows);
+	stat->xmit_cycle = iso->xmit_cycle;
 }
 
 static int raw1394_iso_xmit_init(struct file_info *fi, void *uaddr)
@@ -2076,10 +2083,10 @@
 
 	if(copy_from_user(&stat, uaddr, sizeof(stat)))
 		return -EFAULT;
-	
+
 	fi->iso_handle = hpsb_iso_xmit_init(fi->host,
+					    stat.config.data_buf_size,
 					    stat.config.buf_packets,
-					    stat.config.max_packet_size,
 					    stat.config.channel,
 					    stat.config.speed,
 					    stat.config.irq_interval,
@@ -2088,14 +2095,14 @@
 		return -ENOMEM;
 
 	fi->iso_state = RAW1394_ISO_XMIT;
-	
+
 	raw1394_iso_fill_status(fi->iso_handle, &stat);
 	if(copy_to_user(uaddr, &stat, sizeof(stat)))
 		return -EFAULT;
 
 	/* queue an event to get things started */
 	rawiso_activity_cb(fi->iso_handle);
-	
+
 	return 0;
 }
 
@@ -2105,10 +2112,10 @@
 
 	if(copy_from_user(&stat, uaddr, sizeof(stat)))
 		return -EFAULT;
-	
+
 	fi->iso_handle = hpsb_iso_recv_init(fi->host,
+					    stat.config.data_buf_size,
 					    stat.config.buf_packets,
-					    stat.config.max_packet_size,
 					    stat.config.channel,
 					    stat.config.irq_interval,
 					    rawiso_activity_cb);
@@ -2116,7 +2123,7 @@
 		return -ENOMEM;
 
 	fi->iso_state = RAW1394_ISO_RECV;
-	
+
 	raw1394_iso_fill_status(fi->iso_handle, &stat);
 	if(copy_to_user(uaddr, &stat, sizeof(stat)))
 		return -EFAULT;
@@ -2134,7 +2141,72 @@
 
 	/* reset overflow counter */
 	atomic_set(&iso->overflows, 0);
-	
+
+	return 0;
+}
+
+/* copy N packet_infos out of the ringbuffer into user-supplied array */
+static int raw1394_iso_recv_packets(struct file_info *fi, void *uaddr)
+{
+	struct raw1394_iso_packets upackets;
+	unsigned int packet = fi->iso_handle->first_packet;
+	int i;
+
+	if(copy_from_user(&upackets, uaddr, sizeof(upackets)))
+		return -EFAULT;
+
+	if(upackets.n_packets > hpsb_iso_n_ready(fi->iso_handle))
+		return -EINVAL;
+
+	/* ensure user-supplied buffer is accessible and big enough */
+	if(verify_area(VERIFY_WRITE, upackets.infos,
+		       upackets.n_packets * sizeof(struct raw1394_iso_packet_info)))
+		return -EFAULT;
+
+	/* copy the packet_infos out */
+	for(i = 0; i < upackets.n_packets; i++) {
+		if(__copy_to_user(&upackets.infos[i],
+				  &fi->iso_handle->infos[packet],
+				  sizeof(struct raw1394_iso_packet_info)))
+			return -EFAULT;
+		
+		packet = (packet + 1) % fi->iso_handle->buf_packets;
+	}
+
+	return 0;
+}
+
+/* copy N packet_infos from user to ringbuffer, and queue them for transmission */
+static int raw1394_iso_send_packets(struct file_info *fi, void *uaddr)
+{
+	struct raw1394_iso_packets upackets;
+	int i, rv;
+
+	if(copy_from_user(&upackets, uaddr, sizeof(upackets)))
+		return -EFAULT;
+
+	if(upackets.n_packets > hpsb_iso_n_ready(fi->iso_handle))
+		return -EINVAL;
+
+	/* ensure user-supplied buffer is accessible and big enough */
+	if(verify_area(VERIFY_READ, upackets.infos,
+		       upackets.n_packets * sizeof(struct raw1394_iso_packet_info)))
+		return -EFAULT;
+
+	/* copy the infos structs in and queue the packets */
+	for(i = 0; i < upackets.n_packets; i++) {
+		struct raw1394_iso_packet_info info;
+
+		if(__copy_from_user(&info, &upackets.infos[i],
+				    sizeof(struct raw1394_iso_packet_info)))
+			return -EFAULT;
+
+		rv = hpsb_iso_xmit_queue_packet(fi->iso_handle, info.offset,
+						info.len, info.tag, info.sy);
+		if(rv)
+			return rv;
+	}
+
 	return 0;
 }
 
@@ -2142,7 +2214,7 @@
 {
 	if(fi->iso_handle)
 		hpsb_iso_shutdown(fi->iso_handle);
-	
+
 	fi->iso_handle = NULL;
 	fi->iso_state = RAW1394_ISO_INACTIVE;
 }
@@ -2155,20 +2227,20 @@
 	if(fi->iso_state == RAW1394_ISO_INACTIVE)
 		return -EINVAL;
 
-	return dma_region_mmap(&fi->iso_handle->buf, file, vma);
+	return dma_region_mmap(&fi->iso_handle->data_buf, file, vma);
 }
 
 /* ioctl is only used for rawiso operations */
 static int raw1394_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
 {
 	struct file_info *fi = file->private_data;
-	
+
 	switch(fi->iso_state) {
 	case RAW1394_ISO_INACTIVE:
 		switch(cmd) {
-		case RAW1394_ISO_XMIT_INIT:
+		case RAW1394_IOC_ISO_XMIT_INIT:
 			return raw1394_iso_xmit_init(fi, (void*) arg);
-		case RAW1394_ISO_RECV_INIT:
+		case RAW1394_IOC_ISO_RECV_INIT:
 			return raw1394_iso_recv_init(fi, (void*) arg);
 		default:
 			break;
@@ -2176,51 +2248,71 @@
 		break;
 	case RAW1394_ISO_RECV:
 		switch(cmd) {
-		case RAW1394_ISO_RECV_START:
-			return hpsb_iso_recv_start(fi->iso_handle, arg);
-		case RAW1394_ISO_STOP:
+		case RAW1394_IOC_ISO_RECV_START: {
+			/* copy args from user-space */
+			int args[3];
+			if(copy_from_user(&args[0], (void*) arg, sizeof(args)))
+				return -EFAULT;
+			return hpsb_iso_recv_start(fi->iso_handle, args[0], args[1], args[2]);
+		}
+		case RAW1394_IOC_ISO_XMIT_RECV_STOP:
 			hpsb_iso_stop(fi->iso_handle);
 			return 0;
-
-		case RAW1394_ISO_GET_STATUS:
+		case RAW1394_IOC_ISO_RECV_LISTEN_CHANNEL:
+			return hpsb_iso_recv_listen_channel(fi->iso_handle, arg);
+		case RAW1394_IOC_ISO_RECV_UNLISTEN_CHANNEL:
+			return hpsb_iso_recv_unlisten_channel(fi->iso_handle, arg);
+		case RAW1394_IOC_ISO_RECV_SET_CHANNEL_MASK: {
+			/* copy the u64 from user-space */
+			u64 mask;
+			if(copy_from_user(&mask, (void*) arg, sizeof(mask)))
+				return -EFAULT;
+			return hpsb_iso_recv_set_channel_mask(fi->iso_handle, mask);
+		}
+		case RAW1394_IOC_ISO_GET_STATUS:
 			return raw1394_iso_get_status(fi, (void*) arg);
-			
-		case RAW1394_ISO_PRODUCE_CONSUME:
+		case RAW1394_IOC_ISO_RECV_PACKETS:
+			return raw1394_iso_recv_packets(fi, (void*) arg);
+		case RAW1394_IOC_ISO_RECV_RELEASE_PACKETS:
 			return hpsb_iso_recv_release_packets(fi->iso_handle, arg);
-			
-		case RAW1394_ISO_SHUTDOWN:
+		case RAW1394_IOC_ISO_SHUTDOWN:
 			raw1394_iso_shutdown(fi);
 			return 0;
+		case RAW1394_IOC_ISO_QUEUE_ACTIVITY:
+			queue_rawiso_event(fi);
+			return 0;
 		}
 		break;
 	case RAW1394_ISO_XMIT:
 		switch(cmd) {
-		case RAW1394_ISO_XMIT_START: {
+		case RAW1394_IOC_ISO_XMIT_START: {
 			/* copy two ints from user-space */
 			int args[2];
 			if(copy_from_user(&args[0], (void*) arg, sizeof(args)))
 				return -EFAULT;
 			return hpsb_iso_xmit_start(fi->iso_handle, args[0], args[1]);
 		}
-		case RAW1394_ISO_STOP:
+		case RAW1394_IOC_ISO_XMIT_SYNC:
+			return hpsb_iso_xmit_sync(fi->iso_handle);
+		case RAW1394_IOC_ISO_XMIT_RECV_STOP:
 			hpsb_iso_stop(fi->iso_handle);
 			return 0;
-			
-		case RAW1394_ISO_GET_STATUS:
+		case RAW1394_IOC_ISO_GET_STATUS:
 			return raw1394_iso_get_status(fi, (void*) arg);
-			
-		case RAW1394_ISO_PRODUCE_CONSUME:
-			return hpsb_iso_xmit_queue_packets(fi->iso_handle, arg);
-			
-		case RAW1394_ISO_SHUTDOWN:
+		case RAW1394_IOC_ISO_XMIT_PACKETS:
+			return raw1394_iso_send_packets(fi, (void*) arg);
+		case RAW1394_IOC_ISO_SHUTDOWN:
 			raw1394_iso_shutdown(fi);
 			return 0;
+		case RAW1394_IOC_ISO_QUEUE_ACTIVITY:
+			queue_rawiso_event(fi);
+			return 0;
 		}
 		break;
 	default:
 		break;
 	}
-	
+
 	return -EINVAL;
 }
 
@@ -2236,7 +2328,7 @@
                 mask |= POLLIN | POLLRDNORM;
         }
         spin_unlock_irq(&fi->reqlists_lock);
-	
+
         return mask;
 }
 
@@ -2286,7 +2378,7 @@
 
 	if(fi->iso_state != RAW1394_ISO_INACTIVE)
 		raw1394_iso_shutdown(fi);
-	
+
         for (i = 0; i < 64; i++) {
                 if (fi->listen_channels & (1ULL << i)) {
                         hpsb_unlisten_channel(hl_handle, fi->host, i);
diff -Nru a/drivers/ieee1394/raw1394.h b/drivers/ieee1394/raw1394.h
--- a/drivers/ieee1394/raw1394.h	Mon Feb 17 14:57:26 2003
+++ b/drivers/ieee1394/raw1394.h	Mon Feb 17 14:57:26 2003
@@ -1,8 +1,7 @@
 #ifndef IEEE1394_RAW1394_H
 #define IEEE1394_RAW1394_H
 
-#define RAW1394_DEVICE_MAJOR      171
-#define RAW1394_DEVICE_NAME       "raw1394"
+/* header for the raw1394 API that is exported to user-space */
 
 #define RAW1394_KERNELAPI_VERSION 4
 
@@ -94,21 +93,21 @@
 };
 
 typedef struct arm_request {
-        nodeid_t        destination_nodeid;
-        nodeid_t        source_nodeid;
-        nodeaddr_t      destination_offset;
-        u8              tlabel;
-        u8              tcode;
-        u_int8_t        extended_transaction_code;
-        u_int32_t       generation;
-        arm_length_t    buffer_length;
-        byte_t          *buffer;
+        __u16           destination_nodeid;
+        __u16           source_nodeid;
+        __u64           destination_offset;
+        __u8            tlabel;
+        __u8            tcode;
+        __u8            extended_transaction_code;
+        __u32           generation;
+        __u16           buffer_length;
+        __u8            *buffer;
 } *arm_request_t;
 
 typedef struct arm_response {
-        int             response_code;
-        arm_length_t    buffer_length;
-        byte_t          *buffer;
+        __s32           response_code;
+        __u16           buffer_length;
+        __u8            *buffer;
 } *arm_response_t;
 
 typedef struct arm_request_response {
@@ -117,133 +116,59 @@
 } *arm_request_response_t;
 
 /* rawiso API */
-
-/* ioctls */
-#define RAW1394_ISO_XMIT_INIT        1  /* arg: raw1394_iso_status* */
-#define RAW1394_ISO_RECV_INIT        2  /* arg: raw1394_iso_status* */
-#define RAW1394_ISO_RECV_START       3  /* arg: int, starting cycle */
-#define RAW1394_ISO_XMIT_START       8  /* arg: int[2], { starting cycle, prebuffer } */
-#define RAW1394_ISO_STOP             4
-#define RAW1394_ISO_GET_STATUS       5  /* arg: raw1394_iso_status* */
-#define RAW1394_ISO_PRODUCE_CONSUME  6  /* arg: int, # of packets */
-#define RAW1394_ISO_SHUTDOWN         7
+#include "ieee1394-ioctl.h"
 
 /* per-packet metadata embedded in the ringbuffer */
 /* must be identical to hpsb_iso_packet_info in iso.h! */
 struct raw1394_iso_packet_info {
-	unsigned short len;
-	unsigned short cycle;
-	unsigned char channel; /* recv only */
-	unsigned char tag;
-	unsigned char sy;
+	__u32 offset;
+	__u16 len;
+	__u16 cycle;   /* recv only */
+	__u8  channel; /* recv only */
+	__u8  tag;
+	__u8  sy;
+};
+
+/* argument for RAW1394_ISO_RECV/XMIT_PACKETS ioctls */
+struct raw1394_iso_packets {
+	__u32 n_packets;
+	struct raw1394_iso_packet_info *infos;
 };
 
 struct raw1394_iso_config {
-	unsigned int buf_packets;
-	unsigned int max_packet_size;
-	int channel;
-	int speed; /* xmit only */
-	int irq_interval;
+	/* size of packet data buffer, in bytes (will be rounded up to PAGE_SIZE) */
+	__u32 data_buf_size;
+
+	/* # of packets to buffer */
+	__u32 buf_packets;
+
+	/* iso channel (set to -1 for multi-channel recv) */
+	__s32 channel;
+
+	/* xmit only - iso transmission speed */
+	__u8 speed;
+
+	/* max. latency of buffer, in packets (-1 if you don't care) */
+	__s32 irq_interval;
 };
 
 /* argument to RAW1394_ISO_XMIT/RECV_INIT and RAW1394_ISO_GET_STATUS */
 struct raw1394_iso_status {
 	/* current settings */
 	struct raw1394_iso_config config;
-	
-	/* byte offset between successive packets in the buffer */
-	int buf_stride;
-
-	/* byte offset of data payload within each packet */
-	int packet_data_offset;
-	
-	/* byte offset of struct iso_packet_info within each packet */
-	int packet_info_offset;
-
-	/* index of next packet to fill with data (ISO transmission)
-	   or next packet containing data recieved (ISO reception) */
-	unsigned int first_packet;
 
 	/* number of packets waiting to be filled with data (ISO transmission)
 	   or containing data received (ISO reception) */
-	unsigned int n_packets;
+	__u32 n_packets;
 
 	/* approximate number of packets dropped due to overflow or
 	   underflow of the packet buffer (a value of zero guarantees
 	   that no packets have been dropped) */
-	unsigned int overflows;
-};
-
-#ifdef __KERNEL__
+	__u32 overflows;
 
-struct iso_block_store {
-        atomic_t refcount;
-        size_t data_size;
-        quadlet_t data[0];
+	/* cycle number at which next packet will be transmitted;
+	   -1 if not known */
+	__s16 xmit_cycle;
 };
-
-enum raw1394_iso_state { RAW1394_ISO_INACTIVE = 0,
-			 RAW1394_ISO_RECV = 1,
-			 RAW1394_ISO_XMIT = 2 };
-
-struct file_info {
-        struct list_head list;
-
-        enum { opened, initialized, connected } state;
-        unsigned int protocol_version;
-
-        struct hpsb_host *host;
-
-        struct list_head req_pending;
-        struct list_head req_complete;
-        struct semaphore complete_sem;
-        spinlock_t reqlists_lock;
-        wait_queue_head_t poll_wait_complete;
-
-        struct list_head addr_list;           
-
-        u8 *fcp_buffer;
-
-	/* old ISO API */
-        u64 listen_channels;
-        quadlet_t *iso_buffer;
-        size_t iso_buffer_length;
-
-        u8 notification; /* (busreset-notification) RAW1394_NOTIFY_OFF/ON */
-
-	/* new rawiso API */
-	enum raw1394_iso_state iso_state;
-	struct hpsb_iso *iso_handle;
-};
-
-struct arm_addr {
-        struct list_head addr_list; /* file_info list */
-        u64    start, end;
-        u64    arm_tag;
-        u8     access_rights;
-        u8     notification_options;
-        u8     client_transactions;
-        u64    recvb;
-        u16    rec_length;
-        u8     *addr_space_buffer; /* accessed by read/write/lock */
-};
-
-struct pending_request {
-        struct list_head list;
-        struct file_info *file_info;
-        struct hpsb_packet *packet;
-        struct iso_block_store *ibs;
-        quadlet_t *data;
-        int free_data;
-        struct raw1394_request req;
-};
-
-struct host_info {
-        struct list_head list;
-        struct hpsb_host *host;
-        struct list_head file_info_list;
-};
-
-#endif /* __KERNEL__ */
 
 #endif /* IEEE1394_RAW1394_H */
diff -Nru a/drivers/ieee1394/sbp2.c b/drivers/ieee1394/sbp2.c
--- a/drivers/ieee1394/sbp2.c	Mon Feb 17 14:57:27 2003
+++ b/drivers/ieee1394/sbp2.c	Mon Feb 17 14:57:27 2003
@@ -296,6 +296,10 @@
  *		   returns the dead bit in status. Thanks to Chandan (chandan@toad.net) for this one.
  *	04/27/02 - Fix sbp2 login problem on SMP systems, enable real spinlocks by default. (JSG)
  *	06/09/02 - Don't force 36-bute SCSI inquiry, but leave in a define for badly behaved devices. (JSG)   
+ *	02/04/03 - Fixed a SMP deadlock (don't hold sbp2_command_lock while calling sbp2scsi_complete_command).
+ *		   Also save/restore irq flags in sbp2scsi_complete_command  - Sancho Dauskardt <sda@bdit.de>
+ *	02/06/03 - Removed spinlock debugging; use kernel stuff instead (sda)
+ *
  */
 
 
@@ -346,7 +350,7 @@
 #include "sbp2.h"
 
 static char version[] __devinitdata =
-	"$Rev: 697 $ James Goodwin <jamesg@filanet.com>";
+	"$Rev: 779 $ James Goodwin <jamesg@filanet.com>";
 
 /*
  * Module load parameter definitions
@@ -488,19 +492,6 @@
 
 #define SBP2_ERR(fmt, args...)		HPSB_ERR("sbp2: "fmt, ## args)
 
-/*
- * Spinlock debugging stuff.
- */
-#define SBP2_USE_REAL_SPINLOCKS
-
-#ifdef SBP2_USE_REAL_SPINLOCKS
-#define sbp2_spin_lock(lock, flags)	spin_lock_irqsave(lock, flags)	
-#define sbp2_spin_unlock(lock, flags)	spin_unlock_irqrestore(lock, flags);
-static spinlock_t sbp2_host_info_lock = SPIN_LOCK_UNLOCKED;
-#else
-#define sbp2_spin_lock(lock, flags)	do {save_flags(flags); cli();} while (0)	
-#define sbp2_spin_unlock(lock, flags)	do {restore_flags(flags);} while (0)
-#endif
 
 /*
  * Globals
@@ -512,6 +503,8 @@
 
 static LIST_HEAD(sbp2_host_info_list);
 
+static spinlock_t sbp2_host_info_lock = SPIN_LOCK_UNLOCKED;
+
 static struct hpsb_highlevel *sbp2_hl_handle = NULL;
 
 static struct hpsb_highlevel_ops sbp2_hl_ops = {
@@ -686,12 +679,12 @@
 
 	orbs = sbp2_serialize_io ? 2 : SBP2_MAX_COMMAND_ORBS;
         
-	sbp2_spin_lock(&scsi_id->sbp2_command_orb_lock, flags);
+	spin_lock_irqsave(&scsi_id->sbp2_command_orb_lock, flags);
 	for (i = 0; i < orbs; i++) {
 		command = (struct sbp2_command_info *)
 		    kmalloc(sizeof(struct sbp2_command_info), GFP_KERNEL);
 		if (!command) {
-			sbp2_spin_unlock(&scsi_id->sbp2_command_orb_lock, flags);
+			spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags);
 			return(-ENOMEM);
 		}
 		memset(command, '\0', sizeof(struct sbp2_command_info));
@@ -708,7 +701,7 @@
 		INIT_LIST_HEAD(&command->list);
 		list_add_tail(&command->list, &scsi_id->sbp2_command_orb_completed);
 	}
-	sbp2_spin_unlock(&scsi_id->sbp2_command_orb_lock, flags);
+	spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags);
 	return 0;
 }
 
@@ -722,7 +715,7 @@
 	struct sbp2_command_info *command;
 	unsigned long flags;
         
-	sbp2_spin_lock(&scsi_id->sbp2_command_orb_lock, flags);
+	spin_lock_irqsave(&scsi_id->sbp2_command_orb_lock, flags);
 	if (!list_empty(&scsi_id->sbp2_command_orb_completed)) {
 		list_for_each_safe(lh, next, &scsi_id->sbp2_command_orb_completed) {
 			command = list_entry(lh, struct sbp2_command_info, list);
@@ -740,7 +733,7 @@
 			kfree(command);
 		}
 	}
-	sbp2_spin_unlock(&scsi_id->sbp2_command_orb_lock, flags);
+	spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags);
 	return;
 }
 
@@ -755,17 +748,17 @@
 	struct sbp2_command_info *command;
 	unsigned long flags;
 
-	sbp2_spin_lock(&scsi_id->sbp2_command_orb_lock, flags);
+	spin_lock_irqsave(&scsi_id->sbp2_command_orb_lock, flags);
 	if (!list_empty(&scsi_id->sbp2_command_orb_inuse)) {
 		list_for_each(lh, &scsi_id->sbp2_command_orb_inuse) {
 			command = list_entry(lh, struct sbp2_command_info, list);
 			if (command->command_orb_dma == orb) {
-				sbp2_spin_unlock(&scsi_id->sbp2_command_orb_lock, flags);
+				spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags);
 				return (command);
 			}
 		}
 	}
-	sbp2_spin_unlock(&scsi_id->sbp2_command_orb_lock, flags);
+	spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags);
 
 	SBP2_ORB_DEBUG("could not match command orb %x", (unsigned int)orb);
 
@@ -782,17 +775,17 @@
 	struct sbp2_command_info *command;
 	unsigned long flags;
 
-	sbp2_spin_lock(&scsi_id->sbp2_command_orb_lock, flags);
+	spin_lock_irqsave(&scsi_id->sbp2_command_orb_lock, flags);
 	if (!list_empty(&scsi_id->sbp2_command_orb_inuse)) {
 		list_for_each(lh, &scsi_id->sbp2_command_orb_inuse) {
 			command = list_entry(lh, struct sbp2_command_info, list);
 			if (command->Current_SCpnt == SCpnt) {
-				sbp2_spin_unlock(&scsi_id->sbp2_command_orb_lock, flags);
+				spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags);
 				return (command);
 			}
 		}
 	}
-	sbp2_spin_unlock(&scsi_id->sbp2_command_orb_lock, flags);
+	spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags);
 	return(NULL);
 }
 
@@ -809,7 +802,7 @@
 	struct sbp2_command_info *command = NULL;
 	unsigned long flags;
 
-	sbp2_spin_lock(&scsi_id->sbp2_command_orb_lock, flags);
+	spin_lock_irqsave(&scsi_id->sbp2_command_orb_lock, flags);
 	if (!list_empty(&scsi_id->sbp2_command_orb_completed)) {
 		lh = scsi_id->sbp2_command_orb_completed.next;
 		list_del(lh);
@@ -820,7 +813,7 @@
 	} else {
 		SBP2_ERR("sbp2util_allocate_command_orb - No orbs available!");
 	}
-	sbp2_spin_unlock(&scsi_id->sbp2_command_orb_lock, flags);
+	spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags);
 	return (command);
 }
 
@@ -865,11 +858,11 @@
 {
 	unsigned long flags;
 
-	sbp2_spin_lock(&scsi_id->sbp2_command_orb_lock, flags);
+	spin_lock_irqsave(&scsi_id->sbp2_command_orb_lock, flags);
 	list_del(&command->list);
 	sbp2util_free_command_dma(command);
 	list_add_tail(&command->list, &scsi_id->sbp2_command_orb_completed);
-	sbp2_spin_unlock(&scsi_id->sbp2_command_orb_lock, flags);
+	spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags);
 }
 
 
@@ -992,9 +985,9 @@
 	/* Complete any pending commands with busy (so they get
 	 * retried) and remove them from our queue
 	 */
-	sbp2_spin_lock(&hi->sbp2_command_lock, flags);
+	spin_lock_irqsave(&hi->sbp2_command_lock, flags);
 	sbp2scsi_complete_all_commands(hi, scsi_id, DID_BUS_BUSY);
-	sbp2_spin_unlock(&hi->sbp2_command_lock, flags);
+	spin_unlock_irqrestore(&hi->sbp2_command_lock, flags);
 }
 
 /*
@@ -1024,9 +1017,9 @@
 	hi->host = host;
 	hi->sbp2_command_lock = SPIN_LOCK_UNLOCKED;
 
-	sbp2_spin_lock(&sbp2_host_info_lock, flags);
+	spin_lock_irqsave(&sbp2_host_info_lock, flags);
 	list_add_tail(&hi->list, &sbp2_host_info_list);
-	sbp2_spin_unlock(&sbp2_host_info_lock, flags);
+	spin_unlock_irqrestore(&sbp2_host_info_lock, flags);
 
 	/* Register our host with the SCSI stack. */
 	hi->scsi_host = scsi_register (&scsi_driver_template, sizeof(void *));
@@ -1085,7 +1078,7 @@
 
 	SBP2_DEBUG("sbp2_remove_host");
 
-	sbp2_spin_lock(&sbp2_host_info_lock, flags);
+	spin_lock_irqsave(&sbp2_host_info_lock, flags);
 
 	hi = sbp2_find_host_info(host);
 	if (hi != NULL) {
@@ -1095,7 +1088,7 @@
 	else
 		SBP2_ERR("attempt to remove unknown host %p", host);
 
-	sbp2_spin_unlock(&sbp2_host_info_lock, flags);
+	spin_unlock_irqrestore(&sbp2_host_info_lock, flags);
 }
 
 /*
@@ -2521,16 +2514,16 @@
 		return(RCODE_ADDRESS_ERROR);
 	}
 
-	sbp2_spin_lock(&sbp2_host_info_lock, flags);
+	spin_lock_irqsave(&sbp2_host_info_lock, flags);
 	hi = sbp2_find_host_info(host);
-	sbp2_spin_unlock(&sbp2_host_info_lock, flags);
+	spin_unlock_irqrestore(&sbp2_host_info_lock, flags);
 
 	if (!hi) {
 		SBP2_ERR("host info is NULL - this is bad!");
 		return(RCODE_ADDRESS_ERROR);
 	}
 
-	sbp2_spin_lock(&hi->sbp2_command_lock, flags);
+	spin_lock_irqsave(&hi->sbp2_command_lock, flags);
 
 	/*
 	 * Find our scsi_id structure by looking at the status fifo address written to by
@@ -2541,7 +2534,7 @@
 
 	if (!scsi_id) {
 		SBP2_ERR("scsi_id is NULL - device is gone?");
-		sbp2_spin_unlock(&hi->sbp2_command_lock, flags);
+		spin_unlock_irqrestore(&hi->sbp2_command_lock, flags);
 		return(RCODE_ADDRESS_ERROR);
 	}
 
@@ -2605,13 +2598,6 @@
 			}
 
 			SBP2_ORB_DEBUG("completing command orb %p", &command->command_orb);
-
-			/*
-			 * Complete the SCSI command
-			 */
-			SBP2_DEBUG("Completing SCSI command");
-			sbp2scsi_complete_command(hi, scsi_id, scsi_status, SCpnt, command->Current_done);
-			SBP2_ORB_DEBUG("command orb completed");
 		}
 
 		/*
@@ -2635,7 +2621,23 @@
 		}
 	}
 
-	sbp2_spin_unlock(&hi->sbp2_command_lock, flags);
+	spin_unlock_irqrestore(&hi->sbp2_command_lock, flags);
+
+
+	if (SCpnt) {
+
+		/*
+		 * Complete the SCSI command.
+		 *
+		 * Only do it after we've released the sbp2_command_lock,
+		 * as it might otherwise deadlock with the 
+		 * io_request_lock (in sbp2scsi_queuecommand).
+		 */
+		SBP2_DEBUG("Completing SCSI command");
+		sbp2scsi_complete_command(hi, scsi_id, scsi_status, SCpnt, command->Current_done);
+		SBP2_ORB_DEBUG("command orb completed");
+	}
+
 	return(RCODE_COMPLETE);
 }
 
@@ -2715,12 +2717,12 @@
 	/*
 	 * Try and send our SCSI command
 	 */
-	sbp2_spin_lock(&hi->sbp2_command_lock, flags);
+	spin_lock_irqsave(&hi->sbp2_command_lock, flags);
 	if (sbp2_send_command(hi, scsi_id, SCpnt, done)) {
 		SBP2_ERR("Error sending SCSI command");
 		sbp2scsi_complete_command(hi, scsi_id, SBP2_SCSI_STATUS_SELECTION_TIMEOUT, SCpnt, done);
 	}
-	sbp2_spin_unlock(&hi->sbp2_command_lock, flags);
+	spin_unlock_irqrestore(&hi->sbp2_command_lock, flags);
 
 	return(0);
 }
@@ -2761,10 +2763,14 @@
 
 /*
  * This function is called in order to complete a regular SBP-2 command.
+ *
+ * This can be called in interrupt context.
  */
 static void sbp2scsi_complete_command(struct sbp2scsi_host_info *hi, struct scsi_id_instance_data *scsi_id, u32 scsi_status,
 				      Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
 {
+	unsigned long flags;
+
 	SBP2_DEBUG("sbp2scsi_complete_command");
 
 	/*
@@ -2864,13 +2870,13 @@
 	 * Tell scsi stack that we're done with this command
 	 */
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-	spin_lock_irq(&io_request_lock);
+	spin_lock_irqsave(&io_request_lock,flags);
 	done (SCpnt);
-	spin_unlock_irq(&io_request_lock);
+	spin_unlock_irqrestore(&io_request_lock,flags);
 #else
-	spin_lock_irq(hi->scsi_host->host_lock);
+	spin_lock_irqsave(hi->scsi_host->host_lock,flags);
 	done (SCpnt);
-	spin_unlock_irq(hi->scsi_host->host_lock);
+	spin_unlock_irqrestore(hi->scsi_host->host_lock,flags);
 #endif
 
 	return;
@@ -2896,7 +2902,7 @@
 		 * Right now, just return any matching command structures
 		 * to the free pool.
 		 */
-		sbp2_spin_lock(&hi->sbp2_command_lock, flags);
+		spin_lock_irqsave(&hi->sbp2_command_lock, flags);
 		command = sbp2util_find_command_for_SCpnt(scsi_id, SCpnt);
 		if (command) {
 			SBP2_DEBUG("Found command to abort");
@@ -2921,7 +2927,7 @@
 		 */
 		sbp2_agent_reset(hi, scsi_id, 0);
 		sbp2scsi_complete_all_commands(hi, scsi_id, DID_BUS_BUSY);		
-		sbp2_spin_unlock(&hi->sbp2_command_lock, flags);
+		spin_unlock_irqrestore(&hi->sbp2_command_lock, flags);
 	}
 
 	return(SUCCESS);
diff -Nru a/drivers/ieee1394/video1394.c b/drivers/ieee1394/video1394.c
--- a/drivers/ieee1394/video1394.c	Mon Feb 17 14:57:27 2003
+++ b/drivers/ieee1394/video1394.c	Mon Feb 17 14:57:27 2003
@@ -50,6 +50,7 @@
 #include "ieee1394_core.h"
 #include "highlevel.h"
 #include "video1394.h"
+#include "dma.h"
 
 #include "ohci1394.h"
 
@@ -94,9 +95,14 @@
 	unsigned int packet_size;
 	unsigned int left_size;
 	unsigned int nb_cmd;
-	unsigned char *buf;
+
+	struct dma_region dma;
+
+	struct dma_prog_region *prg_reg;
+
         struct dma_cmd **ir_prg;
 	struct it_dma_prg **it_prg;
+
 	unsigned int *buffer_status;
         struct timeval *buffer_time; /* time when the buffer was received */
 	unsigned int *last_used_cmd; /* For ISO Transmit with 
@@ -159,74 +165,6 @@
 static devfs_handle_t devfs_handle;
 static struct hpsb_highlevel *hl_handle = NULL;
 
-/* Code taken from bttv.c */
-
-/*******************************/
-/* Memory management functions */
-/*******************************/
-
-static inline unsigned long kvirt_to_bus(unsigned long adr) 
-{
-	unsigned long kva, ret;
-
-	kva = (unsigned long) page_address(vmalloc_to_page((void *)adr));
-	kva |= adr & (PAGE_SIZE-1); /* restore the offset */
-	ret = virt_to_bus((void *)kva);
-	return ret;
-}
-
-/* Here we want the physical address of the memory.
- * This is used when initializing the contents of the area.
- */
-static inline unsigned long kvirt_to_pa(unsigned long adr) 
-{
-        unsigned long kva, ret;
-
-	kva = (unsigned long) page_address(vmalloc_to_page((void *)adr));
-	kva |= adr & (PAGE_SIZE-1); /* restore the offset */
-	ret = __pa(kva);
-        return ret;
-}
-
-static void * rvmalloc(unsigned long size)
-{
-	void * mem;
-	unsigned long adr;
-
-	size=PAGE_ALIGN(size);
-	mem=vmalloc_32(size);
-	if (mem) 
-	{
-		memset(mem, 0, size); /* Clear the ram out, 
-					 no junk to the user */
-	        adr=(unsigned long) mem;
-		while (size > 0) 
-                {
-			mem_map_reserve(vmalloc_to_page((void *)adr));
-			adr+=PAGE_SIZE;
-			size-=PAGE_SIZE;
-		}
-	}
-	return mem;
-}
-
-static void rvfree(void * mem, unsigned long size)
-{
-        unsigned long adr;
-
-	if (mem) 
-	{
-	        adr=(unsigned long) mem;
-		while ((long) size > 0) 
-                {
-			mem_map_unreserve(vmalloc_to_page((void *)adr));
-			adr+=PAGE_SIZE;
-			size-=PAGE_SIZE;
-		}
-		vfree(mem);
-	}
-}
-/* End of code taken from bttv.c */
 
 static int free_dma_iso_ctx(struct dma_iso_ctx *d)
 {
@@ -238,20 +176,19 @@
 	if (d->iso_tasklet.link.next != NULL)
 		ohci1394_unregister_iso_tasklet(d->ohci, &d->iso_tasklet);
 
-	if (d->buf)
-		rvfree((void *)d->buf, d->num_desc * d->buf_size);
+	dma_region_free(&d->dma);
 
-	if (d->ir_prg) {
-		for (i=0;i<d->num_desc;i++) 
-			if (d->ir_prg[i]) kfree(d->ir_prg[i]);
-		kfree(d->ir_prg);
+	if (d->prg_reg) {
+		for (i = 0; i < d->num_desc; i++)
+			dma_prog_region_free(&d->prg_reg[i]);
+		kfree(d->prg_reg);
 	}
 
-	if (d->it_prg) {
-		for (i=0;i<d->num_desc;i++) 
-			if (d->it_prg[i]) kfree(d->it_prg[i]);
+	if (d->ir_prg)
+		kfree(d->ir_prg);
+
+	if (d->it_prg)
 		kfree(d->it_prg);
-	}
 
 	if (d->buffer_status)
 		kfree(d->buffer_status);
@@ -291,18 +228,17 @@
 	d->frame_size = buf_size;
 	d->buf_size = PAGE_ALIGN(buf_size);
 	d->last_buffer = -1;
-	d->buf = NULL;
-	d->ir_prg = NULL;
 	init_waitqueue_head(&d->waitq);
 
-	d->buf = rvmalloc(d->num_desc * d->buf_size);
+	/* Init the regions for easy cleanup */
+	dma_region_init(&d->dma);
 
-	if (d->buf == NULL) {
+	if (dma_region_alloc(&d->dma, d->num_desc * d->buf_size, ohci->dev,
+			     PCI_DMA_BIDIRECTIONAL)) {
 		PRINT(KERN_ERR, ohci->id, "Failed to allocate dma buffer");
 		free_dma_iso_ctx(d);
 		return NULL;
 	}
-	memset(d->buf, 0, d->num_desc * d->buf_size);
 
 	if (type == OHCI_ISO_RECEIVE)
 		ohci1394_init_iso_tasklet(&d->iso_tasklet, type,
@@ -321,6 +257,17 @@
 	}
 	d->ctx = d->iso_tasklet.context;
 
+	d->prg_reg = kmalloc(d->num_desc * sizeof(struct dma_prog_region),
+			GFP_KERNEL);
+	if (d->prg_reg == NULL) {
+		PRINT(KERN_ERR, ohci->id, "Failed to allocate ir prg regs");
+		free_dma_iso_ctx(d);
+		return NULL;
+	}
+	/* Makes for easier cleanup */
+	for (i = 0; i < d->num_desc; i++)
+		dma_prog_region_init(&d->prg_reg[i]);
+
 	if (type == OHCI_ISO_RECEIVE) {
 		d->ctrlSet = OHCI1394_IsoRcvContextControlSet+32*d->ctx;
 		d->ctrlClear = OHCI1394_IsoRcvContextControlClear+32*d->ctx;
@@ -331,31 +278,27 @@
 				    GFP_KERNEL);
 
 		if (d->ir_prg == NULL) {
-			PRINT(KERN_ERR, ohci->id, 
-			      "Failed to allocate dma ir prg");
+			PRINT(KERN_ERR, ohci->id, "Failed to allocate dma ir prg");
 			free_dma_iso_ctx(d);
 			return NULL;
 		}
 		memset(d->ir_prg, 0, d->num_desc * sizeof(struct dma_cmd *));
-	
+
 		d->nb_cmd = d->buf_size / PAGE_SIZE + 1;
 		d->left_size = (d->frame_size % PAGE_SIZE) ?
 			d->frame_size % PAGE_SIZE : PAGE_SIZE;
  
-		for (i=0;i<d->num_desc;i++) {
-			d->ir_prg[i] = kmalloc(d->nb_cmd * 
-					       sizeof(struct dma_cmd), 
-					       GFP_KERNEL);
-			if (d->ir_prg[i] == NULL) {
-				PRINT(KERN_ERR, ohci->id, 
-				      "Failed to allocate dma ir prg");
+		for (i = 0;i < d->num_desc; i++) {
+			if (dma_prog_region_alloc(&d->prg_reg[i], d->nb_cmd *
+						  sizeof(struct dma_cmd), ohci->dev)) {
+				PRINT(KERN_ERR, ohci->id, "Failed to allocate dma ir prg");
 				free_dma_iso_ctx(d);
 				return NULL;
 			}
+			d->ir_prg[i] = (struct dma_cmd *)d->prg_reg[i].kvirt;
 		}
 
-	}
-	else {  /* OHCI_ISO_TRANSMIT */
+	} else {  /* OHCI_ISO_TRANSMIT */
 		d->ctrlSet = OHCI1394_IsoXmitContextControlSet+16*d->ctx;
 		d->ctrlClear = OHCI1394_IsoXmitContextControlClear+16*d->ctx;
 		d->cmdPtr = OHCI1394_IsoXmitCommandPtr+16*d->ctx;
@@ -386,20 +329,17 @@
 		if (d->frame_size % d->packet_size) {
 			d->nb_cmd++;
 			d->left_size = d->frame_size % d->packet_size;
-		}
-		else
+		} else
 			d->left_size = d->packet_size;
 
-		for (i=0;i<d->num_desc;i++) {
-			d->it_prg[i] = kmalloc(d->nb_cmd * 
-					       sizeof(struct it_dma_prg), 
-					       GFP_KERNEL);
-			if (d->it_prg[i] == NULL) {
-				PRINT(KERN_ERR, ohci->id, 
-				      "Failed to allocate dma it prg");
+		for (i = 0; i < d->num_desc; i++) {
+			if (dma_prog_region_alloc(&d->prg_reg[i], d->nb_cmd *
+						sizeof(struct it_dma_prg), ohci->dev)) {
+				PRINT(KERN_ERR, ohci->id, "Failed to allocate dma it prg");
 				free_dma_iso_ctx(d);
 				return NULL;
 			}
+			d->it_prg[i] = (struct it_dma_prg *)d->prg_reg[i].kvirt;
 		}
 	}
 
@@ -452,7 +392,7 @@
 	int i;
 	d->ir_prg[n][0].status = cpu_to_le32(4);
 	d->ir_prg[n][1].status = cpu_to_le32(PAGE_SIZE-4);
-	for (i=2;i<d->nb_cmd-1;i++)
+	for (i = 2; i < d->nb_cmd - 1; i++)
 		d->ir_prg[n][i].status = cpu_to_le32(PAGE_SIZE);
 	d->ir_prg[n][i].status = cpu_to_le32(d->left_size);
 }
@@ -460,7 +400,8 @@
 static void initialize_dma_ir_prg(struct dma_iso_ctx *d, int n, int flags)
 {
 	struct dma_cmd *ir_prg = d->ir_prg[n];
-	unsigned long buf = (unsigned long)d->buf+n*d->buf_size;
+	struct dma_prog_region *ir_reg = &d->prg_reg[n];
+	unsigned long buf = (unsigned long)d->dma.kvirt + n * d->buf_size;
 	int i;
 
 	/* the first descriptor will read only 4 bytes */
@@ -471,31 +412,37 @@
 	if (flags & VIDEO1394_SYNC_FRAMES)
 		ir_prg[0].control |= cpu_to_le32(DMA_CTL_WAIT);
 
-	ir_prg[0].address = cpu_to_le32(kvirt_to_bus(buf));
-	ir_prg[0].branchAddress =  cpu_to_le32((virt_to_bus(&(ir_prg[1].control)) 
-				    & 0xfffffff0) | 0x1);
+	ir_prg[0].address = cpu_to_le32(dma_region_offset_to_bus(&d->dma, buf -
+				(unsigned long)d->dma.kvirt));
+	ir_prg[0].branchAddress = cpu_to_le32((dma_prog_region_offset_to_bus(ir_reg,
+					1 * sizeof(struct dma_cmd)) & 0xfffffff0) | 0x1);
 
 	/* the second descriptor will read PAGE_SIZE-4 bytes */
 	ir_prg[1].control = cpu_to_le32(DMA_CTL_INPUT_MORE | DMA_CTL_UPDATE |
 		DMA_CTL_BRANCH | (PAGE_SIZE-4));
-	ir_prg[1].address = cpu_to_le32(kvirt_to_bus(buf+4));
-	ir_prg[1].branchAddress =  cpu_to_le32((virt_to_bus(&(ir_prg[2].control)) 
-				    & 0xfffffff0) | 0x1);
+	ir_prg[1].address = cpu_to_le32(dma_region_offset_to_bus(&d->dma, (buf + 4) -
+					(unsigned long)d->dma.kvirt));
+	ir_prg[1].branchAddress = cpu_to_le32((dma_prog_region_offset_to_bus(ir_reg,
+					2 * sizeof(struct dma_cmd)) & 0xfffffff0) | 0x1);
 	
 	for (i=2;i<d->nb_cmd-1;i++) {
 		ir_prg[i].control = cpu_to_le32(DMA_CTL_INPUT_MORE | DMA_CTL_UPDATE | 
 			DMA_CTL_BRANCH | PAGE_SIZE);
-		ir_prg[i].address = cpu_to_le32(kvirt_to_bus(buf+(i-1)*PAGE_SIZE));
-
-		ir_prg[i].branchAddress =  
-			cpu_to_le32((virt_to_bus(&(ir_prg[i+1].control)) 
-			 & 0xfffffff0) | 0x1);
+		ir_prg[i].address = cpu_to_le32(dma_region_offset_to_bus(&d->dma,
+					        (buf+(i-1)*PAGE_SIZE) -
+						(unsigned long)d->dma.kvirt));
+
+		ir_prg[i].branchAddress =
+			cpu_to_le32((dma_prog_region_offset_to_bus(ir_reg,
+				(i + 1) * sizeof(struct dma_cmd)) & 0xfffffff0) | 0x1);
 	}
 
 	/* the last descriptor will generate an interrupt */
 	ir_prg[i].control = cpu_to_le32(DMA_CTL_INPUT_MORE | DMA_CTL_UPDATE | 
 		DMA_CTL_IRQ | DMA_CTL_BRANCH | d->left_size);
-	ir_prg[i].address = cpu_to_le32(kvirt_to_bus(buf+(i-1)*PAGE_SIZE));
+	ir_prg[i].address = cpu_to_le32(dma_region_offset_to_bus(&d->dma,
+					(buf+(i-1)*PAGE_SIZE) -
+					(unsigned long)d->dma.kvirt));
 }
 	
 static void initialize_dma_ir_ctx(struct dma_iso_ctx *d, int tag, int flags)
@@ -574,7 +521,7 @@
 static inline void put_timestamp(struct ti_ohci *ohci, struct dma_iso_ctx * d,
 				 int n)
 {
-	unsigned char* buf = d->buf + n * d->buf_size;
+	unsigned char* buf = d->dma.kvirt + n * d->buf_size;
 	u32 cycleTimer;
 	u32 timeStamp;
 
@@ -603,7 +550,7 @@
 	if (n == -1) {
 	  return;
 	}
-	buf = d->buf + n * d->buf_size;
+	buf = d->dma.kvirt + n * d->buf_size;
 
 	timeStamp += (d->last_used_cmd[n] << 12) & 0xffff;
 
@@ -650,7 +597,8 @@
 static void initialize_dma_it_prg(struct dma_iso_ctx *d, int n, int sync_tag)
 {
 	struct it_dma_prg *it_prg = d->it_prg[n];
-	unsigned long buf = (unsigned long)d->buf+n*d->buf_size;
+	struct dma_prog_region *it_reg = &d->prg_reg[n];
+	unsigned long buf = (unsigned long)d->dma.kvirt + n * d->buf_size;
 	int i;
 	d->last_used_cmd[n] = d->nb_cmd - 1;
 	for (i=0;i<d->nb_cmd;i++) {
@@ -674,18 +622,18 @@
 		it_prg[i].end.control = cpu_to_le32(DMA_CTL_OUTPUT_LAST |
 			    	    	     DMA_CTL_BRANCH);
 		it_prg[i].end.address =
-			cpu_to_le32(kvirt_to_bus(buf+i*d->packet_size));
+			cpu_to_le32(dma_region_offset_to_bus(&d->dma, (buf+i*d->packet_size) -
+						(unsigned long)d->dma.kvirt));
 
 		if (i<d->nb_cmd-1) {
 			it_prg[i].end.control |= cpu_to_le32(d->packet_size);
 			it_prg[i].begin.branchAddress = 
-				cpu_to_le32((virt_to_bus(&(it_prg[i+1].begin.control)) 
-				 & 0xfffffff0) | 0x3);
+				cpu_to_le32((dma_prog_region_offset_to_bus(it_reg, (i + 1) *
+					sizeof(struct it_dma_prg)) & 0xfffffff0) | 0x3);
 			it_prg[i].end.branchAddress = 
-				cpu_to_le32((virt_to_bus(&(it_prg[i+1].begin.control)) 
-				 & 0xfffffff0) | 0x3);
-		}
-		else {
+				cpu_to_le32((dma_prog_region_offset_to_bus(it_reg, (i + 1) *
+					sizeof(struct it_dma_prg)) & 0xfffffff0) | 0x3);
+		} else {
 			/* the last prg generates an interrupt */
 			it_prg[i].end.control |= cpu_to_le32(DMA_CTL_UPDATE | 
 				DMA_CTL_IRQ | d->left_size);
@@ -694,15 +642,6 @@
 			it_prg[i].end.branchAddress = 0;
 		}
 		it_prg[i].end.status = 0;
-
-#if 0
-		printk("%d:%d: %08x-%08x ctrl %08x brch %08x d0 %08x d1 %08x\n",n,i,
-		       virt_to_bus(&(it_prg[i].begin.control)),
-		       virt_to_bus(&(it_prg[i].end.control)),
-		       it_prg[i].end.control,
-		       it_prg[i].end.branchAddress,
-		       it_prg[i].data[0], it_prg[i].data[1]);
-#endif
 	}
 }
 
@@ -711,6 +650,7 @@
 	struct ti_ohci *ohci)
 {
 	struct it_dma_prg *it_prg = d->it_prg[n];
+	struct dma_prog_region *it_reg = &d->prg_reg[n];
 	int i;
 
 #if 0
@@ -732,12 +672,12 @@
 
 		if (i < d->nb_cmd-1 && packet_sizes[i+1] != 0) {
 			it_prg[i].end.control |= cpu_to_le32(size);
-			it_prg[i].begin.branchAddress = 
-				cpu_to_le32((virt_to_bus(&(it_prg[i+1].begin.control)) 
-				 & 0xfffffff0) | 0x3);
-			it_prg[i].end.branchAddress = 
-				cpu_to_le32((virt_to_bus(&(it_prg[i+1].begin.control)) 
-				 & 0xfffffff0) | 0x3);
+			it_prg[i].begin.branchAddress =
+				cpu_to_le32((dma_prog_region_offset_to_bus(it_reg, (i + 1) *
+					sizeof(struct it_dma_prg)) & 0xfffffff0) | 0x3);
+			it_prg[i].end.branchAddress =
+				cpu_to_le32((dma_prog_region_offset_to_bus(it_reg, (i + 1) *
+					sizeof(struct it_dma_prg)) & 0xfffffff0) | 0x3);
 		} else {
 			/* the last prg generates an interrupt */
 			it_prg[i].end.control |= cpu_to_le32(DMA_CTL_UPDATE | 
@@ -769,37 +709,6 @@
 	reg_write(ohci, OHCI1394_IsoXmitIntMaskSet, 1<<d->ctx);
 }
 
-static int do_iso_mmap(struct ti_ohci *ohci, struct dma_iso_ctx *d,
-		       struct vm_area_struct *vma)
-{
-        unsigned long start = vma->vm_start;
-	unsigned long size = vma->vm_end - vma->vm_start;
-        unsigned long page, pos;
-
-        if (size > d->num_desc * d->buf_size) {
-		PRINT(KERN_ERR, ohci->id, 
-		      "iso context %d buf size is different from mmap size", 
-		      d->ctx);
-                return -EINVAL;
-	}
-        if (!d->buf) {
-		PRINT(KERN_ERR, ohci->id, 
-		      "iso context %d is not allocated", d->ctx);
-		return -EINVAL;
-	}
-
-	pos = (unsigned long) d->buf;
-        while (size > 0) {
-                page = kvirt_to_pa(pos);
-                if (remap_page_range_1394(vma, start, page, PAGE_SIZE, PAGE_SHARED))
-                        return -EAGAIN;
-                start += PAGE_SIZE;
-                pos += PAGE_SIZE;
-                size -= PAGE_SIZE;
-        }
-        return 0;
-}
-
 static int video1394_ioctl(struct inode *inode, struct file *file,
 			   unsigned int cmd, unsigned long arg)
 {
@@ -810,8 +719,8 @@
 
 	switch(cmd)
 	{
-	case VIDEO1394_LISTEN_CHANNEL:
-	case VIDEO1394_TALK_CHANNEL:
+	case VIDEO1394_IOC_LISTEN_CHANNEL:
+	case VIDEO1394_IOC_TALK_CHANNEL:
 	{
 		struct video1394_mmap v;
 		u64 mask;
@@ -870,7 +779,7 @@
 			return -EFAULT;
 		}
 
-		if (cmd == VIDEO1394_LISTEN_CHANNEL) {
+		if (cmd == VIDEO1394_IOC_LISTEN_CHANNEL) {
 			d = alloc_dma_iso_ctx(ohci, OHCI_ISO_RECEIVE,
 					      v.nb_buffers, v.buf_size, 
 					      v.channel, 0);
@@ -920,8 +829,8 @@
 
 		return 0;
 	}
-	case VIDEO1394_UNLISTEN_CHANNEL: 
-	case VIDEO1394_UNTALK_CHANNEL:
+	case VIDEO1394_IOC_UNLISTEN_CHANNEL: 
+	case VIDEO1394_IOC_UNTALK_CHANNEL:
 	{
 		int channel;
 		u64 mask;
@@ -945,7 +854,7 @@
 		/* Mark this channel as unused */
 		ohci->ISO_channel_usage &= ~mask;
 
-		if (cmd == VIDEO1394_UNLISTEN_CHANNEL)
+		if (cmd == VIDEO1394_IOC_UNLISTEN_CHANNEL)
 			d = find_ctx(&ctx->context_list, OHCI_ISO_RECEIVE, channel);
 		else
 			d = find_ctx(&ctx->context_list, OHCI_ISO_TRANSMIT, channel);
@@ -957,7 +866,7 @@
 		
 		return 0;
 	}
-	case VIDEO1394_LISTEN_QUEUE_BUFFER:
+	case VIDEO1394_IOC_LISTEN_QUEUE_BUFFER:
 	{
 		struct video1394_wait v;
 		struct dma_iso_ctx *d;
@@ -984,10 +893,10 @@
 		
 		d->buffer_status[v.buffer]=VIDEO1394_BUFFER_QUEUED;
 
-		if (d->last_buffer>=0) 
-			d->ir_prg[d->last_buffer][d->nb_cmd-1].branchAddress = 
-				cpu_to_le32((virt_to_bus(&(d->ir_prg[v.buffer][0].control)) 
-				 & 0xfffffff0) | 0x1);
+		if (d->last_buffer>=0)
+			d->ir_prg[d->last_buffer][d->nb_cmd-1].branchAddress =
+				cpu_to_le32((dma_prog_region_offset_to_bus(&d->prg_reg[v.buffer], 0)
+					& 0xfffffff0) | 0x1);
 
 		d->last_buffer = v.buffer;
 
@@ -1000,9 +909,9 @@
 			DBGMSG(ohci->id, "Starting iso DMA ctx=%d",d->ctx);
 
 			/* Tell the controller where the first program is */
-			reg_write(ohci, d->cmdPtr, 
-				  virt_to_bus(&(d->ir_prg[v.buffer][0]))|0x1);
-			
+			reg_write(ohci, d->cmdPtr,
+				dma_prog_region_offset_to_bus(&d->prg_reg[v.buffer], 0) | 0x1);
+
 			/* Run IR context */
 			reg_write(ohci, d->ctrlSet, 0x8000);
 		}
@@ -1017,8 +926,8 @@
 		return 0;
 		
 	}
-	case VIDEO1394_LISTEN_WAIT_BUFFER:
-	case VIDEO1394_LISTEN_POLL_BUFFER:
+	case VIDEO1394_IOC_LISTEN_WAIT_BUFFER:
+	case VIDEO1394_IOC_LISTEN_POLL_BUFFER:
 	{
 		struct video1394_wait v;
 		struct dma_iso_ctx *d;
@@ -1045,7 +954,7 @@
 			d->buffer_status[v.buffer]=VIDEO1394_BUFFER_FREE;
 			break;
 		case VIDEO1394_BUFFER_QUEUED:
-			if (cmd == VIDEO1394_LISTEN_POLL_BUFFER) {
+			if (cmd == VIDEO1394_IOC_LISTEN_POLL_BUFFER) {
 			    /* for polling, return error code EINTR */
 			    spin_unlock_irqrestore(&d->lock, flags);
 			    return -EINTR;
@@ -1099,7 +1008,7 @@
 
 		return 0;
 	}
-	case VIDEO1394_TALK_QUEUE_BUFFER:
+	case VIDEO1394_IOC_TALK_QUEUE_BUFFER:
 	{
 		struct video1394_wait v;
 		struct video1394_queue_variable qv;
@@ -1142,18 +1051,16 @@
 
 		d->buffer_status[v.buffer]=VIDEO1394_BUFFER_QUEUED;
 
-		if (d->last_buffer>=0) {
+		if (d->last_buffer >= 0) {
 			d->it_prg[d->last_buffer]
-				[ d->last_used_cmd[d->last_buffer]
-					].end.branchAddress = 
-				cpu_to_le32((virt_to_bus(&(d->it_prg[v.buffer][0].begin.control)) 
-				 & 0xfffffff0) | 0x3);
+				[ d->last_used_cmd[d->last_buffer] ].end.branchAddress = 
+					cpu_to_le32((dma_prog_region_offset_to_bus(&d->prg_reg[v.buffer],
+						0) & 0xfffffff0) | 0x3);
 
 			d->it_prg[d->last_buffer]
-				[d->last_used_cmd[d->last_buffer]
-					].begin.branchAddress = 
-				cpu_to_le32((virt_to_bus(&(d->it_prg[v.buffer][0].begin.control)) 
-				 & 0xfffffff0) | 0x3);
+				[ d->last_used_cmd[d->last_buffer] ].begin.branchAddress =
+					cpu_to_le32((dma_prog_region_offset_to_bus(&d->prg_reg[v.buffer],
+						0) & 0xfffffff0) | 0x3);
 			d->next_buffer[d->last_buffer] = v.buffer;
 		}
 		d->last_buffer = v.buffer;
@@ -1170,9 +1077,9 @@
 			put_timestamp(ohci, d, d->last_buffer);
 
 			/* Tell the controller where the first program is */
-			reg_write(ohci, d->cmdPtr, 
-				  virt_to_bus(&(d->it_prg[v.buffer][0]))|0x3);
-			
+			reg_write(ohci, d->cmdPtr,
+				dma_prog_region_offset_to_bus(&d->prg_reg[v.buffer], 0) | 0x3);
+
 			/* Run IT context */
 			reg_write(ohci, d->ctrlSet, 0x8000);
 		}
@@ -1189,7 +1096,7 @@
 		return 0;
 		
 	}
-	case VIDEO1394_TALK_WAIT_BUFFER:
+	case VIDEO1394_IOC_TALK_WAIT_BUFFER:
 	{
 		struct video1394_wait v;
 		struct dma_iso_ctx *d;
@@ -1254,7 +1161,7 @@
 	if (ctx->current_ctx == NULL) {
 		PRINT(KERN_ERR, ctx->video->ohci->id, "Current iso context not set");
 	} else
-		res = do_iso_mmap(ctx->video->ohci, ctx->current_ctx, vma);
+		res = dma_region_mmap(&ctx->current_ctx->dma, file, vma);
 	unlock_kernel();
 
 	return res;
diff -Nru a/drivers/ieee1394/video1394.h b/drivers/ieee1394/video1394.h
--- a/drivers/ieee1394/video1394.h	Mon Feb 17 14:57:27 2003
+++ b/drivers/ieee1394/video1394.h	Mon Feb 17 14:57:27 2003
@@ -21,6 +21,8 @@
 #ifndef _VIDEO_1394_H
 #define _VIDEO_1394_H
 
+#include "ieee1394-ioctl.h"
+
 #define VIDEO1394_DRIVER_NAME "video1394"
 
 #define VIDEO1394_MAX_SIZE 0x4000000
@@ -29,18 +31,6 @@
 	VIDEO1394_BUFFER_FREE = 0,
 	VIDEO1394_BUFFER_QUEUED,
 	VIDEO1394_BUFFER_READY
-};
-
-enum {
-	VIDEO1394_LISTEN_CHANNEL = 0,
-	VIDEO1394_UNLISTEN_CHANNEL,
-	VIDEO1394_LISTEN_QUEUE_BUFFER,
-	VIDEO1394_LISTEN_WAIT_BUFFER,  // wait until buffer is ready
-	VIDEO1394_TALK_CHANNEL,
-	VIDEO1394_UNTALK_CHANNEL,
-	VIDEO1394_TALK_QUEUE_BUFFER,
-	VIDEO1394_TALK_WAIT_BUFFER,
-	VIDEO1394_LISTEN_POLL_BUFFER   // return immediately with -EINTR if not ready
 };
 
 #define VIDEO1394_SYNC_FRAMES          0x00000001
diff -Nru a/drivers/input/input.c b/drivers/input/input.c
--- a/drivers/input/input.c	Mon Feb 17 14:57:27 2003
+++ b/drivers/input/input.c	Mon Feb 17 14:57:27 2003
@@ -383,7 +383,7 @@
 		argv[0], argv[1], envp[0], envp[1], envp[2], envp[3], envp[4]);
 #endif
 
-	value = call_usermodehelper(argv [0], argv, envp);
+	value = call_usermodehelper(argv [0], argv, envp, 0);
 
 	kfree(buf);
 	kfree(envp);
diff -Nru a/drivers/input/serio/sa1111ps2.c b/drivers/input/serio/sa1111ps2.c
--- a/drivers/input/serio/sa1111ps2.c	Mon Feb 17 14:57:27 2003
+++ b/drivers/input/serio/sa1111ps2.c	Mon Feb 17 14:57:27 2003
@@ -9,6 +9,7 @@
  */
 #include <linux/module.h>
 #include <linux/init.h>
+#include <linux/input.h>
 #include <linux/serio.h>
 #include <linux/errno.h>
 #include <linux/interrupt.h>
@@ -339,6 +340,7 @@
 	.drv = {
 		.name		= "sa1111-ps2",
 		.bus		= &sa1111_bus_type,
+		.devclass	= &input_devclass,
 		.probe		= ps2_probe,
 		.remove		= ps2_remove,
 		.suspend	= ps2_suspend,
diff -Nru a/drivers/isdn/hardware/eicon/divasmain.c b/drivers/isdn/hardware/eicon/divasmain.c
--- a/drivers/isdn/hardware/eicon/divasmain.c	Mon Feb 17 14:57:27 2003
+++ b/drivers/isdn/hardware/eicon/divasmain.c	Mon Feb 17 14:57:27 2003
@@ -263,7 +263,7 @@
 		pdpc->card_failed = 0;
 		argv[2] = &adapter[0];
 
-		ret = call_usermodehelper(argv[0], argv, envp);
+		ret = call_usermodehelper(argv[0], argv, envp, 0);
 
 		if (ret) {
 			printk(KERN_ERR
diff -Nru a/drivers/isdn/hisax/amd7930_fn.c b/drivers/isdn/hisax/amd7930_fn.c
--- a/drivers/isdn/hisax/amd7930_fn.c	Mon Feb 17 14:57:27 2003
+++ b/drivers/isdn/hisax/amd7930_fn.c	Mon Feb 17 14:57:27 2003
@@ -176,7 +176,7 @@
 
         cs->dc.amd7930.old_state = cs->dc.amd7930.ph_state;
 
-        /* abort transmit if nessesary */
+        /* abort transmit if necessary */
         if ((message & 0xf0) && (cs->tx_skb)) {
                 wByteAMD(cs, 0x21, 0xC2);
                 wByteAMD(cs, 0x21, 0x02);
diff -Nru a/drivers/mtd/chips/jedec.c b/drivers/mtd/chips/jedec.c
--- a/drivers/mtd/chips/jedec.c	Mon Feb 17 14:57:27 2003
+++ b/drivers/mtd/chips/jedec.c	Mon Feb 17 14:57:27 2003
@@ -754,7 +754,7 @@
 		       size_t *retlen, const u_char *buf)
 {
    /* Does IO to the currently selected chip. It takes the bank addressing
-      base (which is divisable by the chip size) adds the necesary lower bits
+      base (which is divisible by the chip size) adds the necessary lower bits
       of addrshift (interleve index) and then adds the control register index. */
    #define flread(x) map->read8(map,base+(off&((1<<chip->addrshift)-1))+((x)<<chip->addrshift))
    #define flwrite(v,x) map->write8(map,v,base+(off&((1<<chip->addrshift)-1))+((x)<<chip->addrshift))
diff -Nru a/drivers/mtd/maps/sa1100-flash.c b/drivers/mtd/maps/sa1100-flash.c
--- a/drivers/mtd/maps/sa1100-flash.c	Mon Feb 17 14:57:27 2003
+++ b/drivers/mtd/maps/sa1100-flash.c	Mon Feb 17 14:57:27 2003
@@ -773,14 +773,15 @@
 #ifdef CONFIG_SA1100_TRIZEPS
 static struct mtd_partition trizeps_partitions[] = {
 	{
-		.name		= "Bootloader & the kernel",
-		.size		= 0x00200000,
+		.name		= "Bootloader",
+		.size		= 0x00100000,
 		.offset		= 0,
 	}, {
-		.name		= "Data",
-		.size		= 0x00400000,
+		.name		= "Kernel",
+		.size		= 0x00100000,
 		.offset		= MTDPART_OFS_APPEND,
 	}, {
+		.name		= "root",
 		.size		= MTDPART_SIZ_FULL,
 		.offset		= MTDPART_OFS_APPEND,
 	}
@@ -937,7 +938,7 @@
 #ifdef CONFIG_SA1100_TRIZEPS
 	if (machine_is_trizeps()) {
 		*parts       = trizeps_partitions;
-		nb_parts     = ARRAY_SIZE(trizeps_parititons);
+		nb_parts     = ARRAY_SIZE(trizeps_partitions);
 	}
 #endif
 #ifdef CONFIG_SA1100_YOPY
diff -Nru a/drivers/net/3c59x.c b/drivers/net/3c59x.c
--- a/drivers/net/3c59x.c	Mon Feb 17 14:57:26 2003
+++ b/drivers/net/3c59x.c	Mon Feb 17 14:57:26 2003
@@ -1007,6 +1007,7 @@
 /* returns count found (>= 0), or negative on error */
 static int __init vortex_eisa_init (void)
 {
+	int eisa_found = 0;
 	int orig_cards_found = vortex_cards_found;
 
 	/* Now check all slots of the EISA bus. */
@@ -1014,8 +1015,14 @@
 		return 0;
 
 #ifdef CONFIG_EISA
-	if (eisa_driver_register (&vortex_eisa_driver) < 0) {
-		eisa_driver_unregister (&vortex_eisa_driver);
+	if (eisa_driver_register (&vortex_eisa_driver) >= 0) {
+			/* Because of the way EISA bus is probed, we cannot assume
+			 * any device have been found when we exit from
+			 * eisa_driver_register (the bus root driver may not be
+			 * initialized yet). So we blindly assume something was
+			 * found, and let the sysfs magic happend... */
+			
+			eisa_found = 1;
 	}
 #endif
 	
@@ -1025,7 +1032,7 @@
 					  compaq_device_id, vortex_cards_found++);
 	}
 
-	return vortex_cards_found - orig_cards_found;
+	return vortex_cards_found - orig_cards_found + eisa_found;
 }
 
 /* returns count (>= 0), or negative on error */
diff -Nru a/drivers/net/8139too.c b/drivers/net/8139too.c
--- a/drivers/net/8139too.c	Mon Feb 17 14:57:26 2003
+++ b/drivers/net/8139too.c	Mon Feb 17 14:57:26 2003
@@ -1589,7 +1589,7 @@
 	unsigned long timeout;
 
 	daemonize("%s", dev->name);
-	allow_signal(SIGKILL);
+	allow_signal(SIGTERM);
 
 	while (1) {
 		timeout = next_tick;
diff -Nru a/drivers/net/Kconfig b/drivers/net/Kconfig
--- a/drivers/net/Kconfig	Mon Feb 17 14:57:28 2003
+++ b/drivers/net/Kconfig	Mon Feb 17 14:57:28 2003
@@ -1,3 +1,4 @@
+
 #
 # Network device configuration
 #
@@ -213,7 +214,7 @@
 	  the questions about Ethernet network cards. If unsure, say N.
 
 config MII
-	tristate "generic Media Independent Interface device support"
+	tristate "Generic Media Independent Interface device support"
 	depends on NET_ETHERNET
 	help
 	  Most ethernet controllers have MII transceiver either as an external
diff -Nru a/drivers/net/aironet4500_proc.c b/drivers/net/aironet4500_proc.c
--- a/drivers/net/aironet4500_proc.c	Mon Feb 17 14:57:26 2003
+++ b/drivers/net/aironet4500_proc.c	Mon Feb 17 14:57:26 2003
@@ -356,41 +356,160 @@
 
 
 ctl_table awc_exdev_table[] = {
-       {0, NULL, NULL,0, 0400, NULL},
-       {0}
+	{
+	       .ctl_name	= 0,
+	       .maxlen		= 0,
+	       .mode		= 0400,
+       },
+	{ .ctl_name = 0 }
 };
 ctl_table awc_exroot_table[] = {
-        {254, "aironet4500", NULL, 0, 0555, NULL},
-        {0}
+	{
+		.ctl_name	= 254,
+		.procname	= "aironet4500",
+		.maxlen		= 0,
+		.mode		= 0555,
+	},
+	{ .ctl_name = 0 }
 };
 
 ctl_table awc_driver_proc_table[] = {
-        {1, "debug"			, &awc_debug, sizeof(awc_debug), 0600,NULL, proc_dointvec},
-        {2, "bap_sleep"			, &bap_sleep, sizeof(bap_sleep), 0600,NULL, proc_dointvec},
-        {3, "bap_sleep_after_setup"	, &bap_sleep_after_setup, sizeof(bap_sleep_after_setup), 0600,NULL, proc_dointvec},
-        {4, "sleep_before_command"	, &sleep_before_command, sizeof(sleep_before_command), 0600,NULL, proc_dointvec},
-        {5, "bap_sleep_before_write"	, &bap_sleep_before_write, sizeof(bap_sleep_before_write), 0600,NULL, proc_dointvec},
-        {6, "sleep_in_command"		, &sleep_in_command	, sizeof(sleep_in_command), 0600,NULL, proc_dointvec},
-        {7, "both_bap_lock"		, &both_bap_lock	, sizeof(both_bap_lock), 0600,NULL, proc_dointvec},
-        {8, "bap_setup_spinlock"	, &bap_setup_spinlock	, sizeof(bap_setup_spinlock), 0600,NULL, proc_dointvec},
-        {0}
+	{
+		.ctl_name	= 1,
+		.procname	= "debug",
+		.data		= &awc_debug,
+		.maxlen		= sizeof(awc_debug),
+		.mode		= 0600,
+		.proc_handler	= proc_dointvec,
+	},
+	{
+		.ctl_name	= 2,
+		.procname	= "bap_sleep",
+		.data		= &bap_sleep,
+		.maxlen		= sizeof(bap_sleep),
+		.mode		= 0600,
+		.proc_handler	= proc_dointvec,
+	},
+	{
+		.ctl_name	= 3,
+		.procname	= "bap_sleep_after_setup",
+		.data		= &bap_sleep_after_setup,
+		.maxlen		= sizeof(bap_sleep_after_setup),
+		.mode		= 0600,
+		.proc_handler	= proc_dointvec,
+	},
+	{
+		.ctl_name	= 4,
+		.procname	= "sleep_before_command",
+		.data		= &sleep_before_command,
+		.maxlen		= sizeof(sleep_before_command),
+		.mode		= 0600,
+		.proc_handler	= proc_dointvec,
+	},
+	{ 
+		.ctl_name	= 5,
+		.procname	= "bap_sleep_before_write",
+		.data		= &bap_sleep_before_write,
+		.maxlen		= sizeof(bap_sleep_before_write),
+		.mode		= 0600,
+		.proc_handler	= proc_dointvec,
+	},
+	{
+		.ctl_name	= 6,
+		.procname	= "sleep_in_command",
+		.data		= &sleep_in_command,
+		.maxlen		= sizeof(sleep_in_command),
+		.mode		= 0600,
+		.proc_handler	= proc_dointvec,
+	},
+	{
+		.ctl_name	= 7,
+		.procname	= "both_bap_lock",
+		.data		= &both_bap_lock,
+		.maxlen		= sizeof(both_bap_lock),
+		.mode		= 0600,
+		.proc_handler	= proc_dointvec
+	},
+	{
+		.ctl_name	= 8,
+		.procname	= "bap_setup_spinlock",
+		.data		= &bap_setup_spinlock,
+		.maxlen		= sizeof(bap_setup_spinlock),
+		.mode		= 0600,
+		.proc_handler	= proc_dointvec,
+	},
+	{ .ctl_name = 0 }
 };
 
 ctl_table awc_driver_level_ctable[] = {
-        {1, "force_rts_on_shorter"	, NULL, sizeof(int), 0600,NULL, proc_dointvec},
-        {2, "force_tx_rate"		, NULL, sizeof(int), 0600,NULL, proc_dointvec},
-        {3, "ip_tos_reliability_rts"	, NULL, sizeof(int), 0600,NULL, proc_dointvec},
-        {4, "ip_tos_troughput_no_retries", NULL, sizeof(int), 0600,NULL, proc_dointvec},
-        {5, "debug"			, NULL, sizeof(int), 0600,NULL, proc_dointvec},
-        {6, "simple_bridge"		, NULL, sizeof(int), 0600,NULL, proc_dointvec},
-        {7, "p802_11_send"		, NULL, sizeof(int), 0600,NULL, proc_dointvec},
-        {8, "full_stats"		, NULL, sizeof(int), 0600,NULL, proc_dointvec},
-        {0}
+	{
+		.ctl_name	= 1,
+		.procname	= "force_rts_on_shorter",
+		.maxlen		= sizeof(int),
+		.mode		= 0600,
+		.proc_handler	= proc_dointvec,
+	},
+	{
+		.ctl_name	= 2,
+		.procname	= "force_tx_rate",
+		.maxlen		= sizeof(int),
+		.mode		= 0600,
+		.proc_handler	= proc_dointvec,
+	},
+	{
+		.ctl_name	= 3,
+		.procname	= "ip_tos_reliability_rts",
+		.maxlen		= sizeof(int),
+		.mode		= 0600,
+		.proc_handler	= proc_dointvec,
+	},
+	{
+		.ctl_name	= 4,
+		.procname	= "ip_tos_troughput_no_retries",
+		.maxlen		= sizeof(int),
+		.mode		= 0600,
+		.proc_handler	= proc_dointvec,
+	},
+	{
+		.ctl_name	= 5,
+		.procname	= "debug",
+		.maxlen		= sizeof(int),
+		.mode		= 0600,
+		.proc_handler	= proc_dointvec,
+	},
+	{
+		.ctl_name	= 6,
+		.procname	= "simple_bridge",
+		.maxlen		= sizeof(int),
+		.mode		= 0600,
+		.proc_handler	= proc_dointvec,
+	},
+	{
+		.ctl_name	= 7,
+		.procname	= "p802_11_send",
+		.maxlen		= sizeof(int),
+		.mode		= 0600,
+		.proc_handler	= proc_dointvec,
+	},
+	{
+		.ctl_name	= 8,
+		.procname	= "full_stats",
+		.maxlen		= sizeof(int),
+		.mode		= 0600,
+		.proc_handler	= proc_dointvec,
+	},
+	{ .ctl_name = 0 }
 };
 
 ctl_table awc_root_table[] = {
-        {254, "aironet4500", NULL, 0, 0555, awc_driver_proc_table},
-        {0}
+	{
+		.ctl_name	= 254,
+		.procname	= "aironet4500",
+		.maxlen		= 0,
+		.mode		= 0555,
+		.child		= awc_driver_proc_table,
+	},
+	{ .ctl_name = 0 }
 };
 
 struct ctl_table_header * awc_driver_sysctl_header;
diff -Nru a/drivers/net/arcnet/com20020-pci.c b/drivers/net/arcnet/com20020-pci.c
--- a/drivers/net/arcnet/com20020-pci.c	Mon Feb 17 14:57:27 2003
+++ b/drivers/net/arcnet/com20020-pci.c	Mon Feb 17 14:57:27 2003
@@ -1,5 +1,6 @@
 /*
- * Linux ARCnet driver - COM20020 PCI support (Contemporary Controls PCI20)
+ * Linux ARCnet driver - COM20020 PCI support
+ * Contemporary Controls PCI20 and SOHARD SH-ARC PCI
  * 
  * Written 1994-1999 by Avery Pennarun,
  *    based on an ISA version by David Woodhouse.
@@ -86,7 +87,21 @@
 	memset(lp, 0, sizeof(struct arcnet_local));
 	pci_set_drvdata(pdev, dev);
 
-	ioaddr = pci_resource_start(pdev, 2);
+	// SOHARD needs PCI base addr 4
+	if (pdev->vendor==0x10B5) {
+		BUGMSG(D_NORMAL, "SOHARD\n");
+		ioaddr = pci_resource_start(pdev, 4);
+	}
+	else {
+		BUGMSG(D_NORMAL, "Contemporary Controls\n");
+		ioaddr = pci_resource_start(pdev, 2);
+	}
+
+	// Dummy access after Reset
+	// ARCNET controller needs this access to detect bustype
+	outb(0x00,ioaddr+1);
+	inb(ioaddr+1);
+
 	dev->base_addr = ioaddr;
 	dev->irq = pdev->irq;
 	dev->dev_addr[0] = node;
@@ -152,6 +167,7 @@
 	{ 0x1571, 0xa204, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ARC_CAN_10MBIT },
 	{ 0x1571, 0xa205, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ARC_CAN_10MBIT },
 	{ 0x1571, 0xa206, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ARC_CAN_10MBIT },
+	{ 0x10B5, 0x9050, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ARC_CAN_10MBIT },
 	{0,}
 };
 
diff -Nru a/drivers/net/arcnet/com20020.c b/drivers/net/arcnet/com20020.c
--- a/drivers/net/arcnet/com20020.c	Mon Feb 17 14:57:27 2003
+++ b/drivers/net/arcnet/com20020.c	Mon Feb 17 14:57:27 2003
@@ -98,6 +98,10 @@
 	lp->setup = lp->clockm ? 0 : (lp->clockp << 1);
 	lp->setup2 = (lp->clockm << 4) | 8;
 
+	/* CHECK: should we do this for SOHARD cards ? */
+	/* Enable P1Mode for backplane mode */
+	lp->setup = lp->setup | P1MODE;
+
 	SET_SUBADR(SUB_SETUP1);
 	outb(lp->setup, _XREG);
 
@@ -202,7 +206,7 @@
 		return -ENODEV;
 	}
 	/* reserve the I/O region */
-	if (request_region(ioaddr, ARCNET_TOTAL_SIZE, "arcnet (COM20020)")) {
+	if (!request_region(ioaddr, ARCNET_TOTAL_SIZE, "arcnet (COM20020)")) {
 		free_irq(dev->irq, dev);
 		return -EBUSY;
 	}
@@ -300,8 +304,9 @@
 	struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
 	int ioaddr = dev->base_addr;
 
-	if (open)
+	if (open) {
 		MOD_INC_USE_COUNT;
+	}
 	else {
 		/* disable transmitter */
 		lp->config &= ~TXENcfg;
diff -Nru a/drivers/net/arlan-proc.c b/drivers/net/arlan-proc.c
--- a/drivers/net/arlan-proc.c	Mon Feb 17 14:57:27 2003
+++ b/drivers/net/arlan-proc.c	Mon Feb 17 14:57:27 2003
@@ -816,14 +816,18 @@
 
 /* Place files in /proc/sys/dev/arlan */
 #define CTBLN(num,card,nam) \
-        {num , #nam, &(arlan_conf[card].nam), \
-         sizeof(int), 0600, NULL, &proc_dointvec}
+        { .ctl_name = num,\
+          .procname = #nam,\
+          .data = &(arlan_conf[card].nam),\
+          .maxlen = sizeof(int), .mode = 0600, .proc_handler = &proc_dointvec}
 #ifdef ARLAN_DEBUGGING
 
-#define ARLAN_PROC_DEBUG_ENTRIES	{48, "entry_exit_debug", &arlan_entry_and_exit_debug, \
-                sizeof(int), 0600, NULL, &proc_dointvec},\
-	{49, "debug", &arlan_debug, \
-                sizeof(int), 0600, NULL, &proc_dointvec},
+#define ARLAN_PROC_DEBUG_ENTRIES \
+        { .ctl_name = 48, .procname = "entry_exit_debug",\
+          .data = &arlan_entry_and_exit_debug,\
+          .maxlen = sizeof(int), .mode = 0600, .proc_handler = &proc_dointvec},\
+	{ .ctl_name = 49, .procname = "debug", .data = &arlan_debug,\
+          .maxlen = sizeof(int), .mode = 0600, .proc_handler = &proc_dointvec},
 #else 
 #define ARLAN_PROC_DEBUG_ENTRIES
 #endif
@@ -858,8 +862,9 @@
 	CTBLN(27,cardNo, txTimeoutMs),\
 	CTBLN(28,cardNo, waitCardTimeout),\
 	CTBLN(29,cardNo, channelSet), \
-	{30, "name", arlan_conf[cardNo].siteName, \
-                16, 0600, NULL, &proc_dostring},\
+	{.ctl_name = 30, .procname = "name",\
+	 .data = arlan_conf[cardNo].siteName,\
+	 .maxlen = 16, .mode = 0600, .proc_handler = &proc_dostring},\
 	CTBLN(31,cardNo,waitTime),\
 	CTBLN(32,cardNo,lParameter),\
 	CTBLN(33,cardNo,_15),\
@@ -897,22 +902,64 @@
 	ARLAN_SYSCTL_TABLE_TOTAL(0)
 
 #ifdef ARLAN_PROC_SHM_DUMP
-	{150, "arlan0-txRing", &arlan_drive_info,
-	 ARLAN_STR_SIZE, 0400, NULL, &arlan_sysctl_infotxRing},
-	{151, "arlan0-rxRing", &arlan_drive_info,
-	 ARLAN_STR_SIZE, 0400, NULL, &arlan_sysctl_inforxRing},
-	{152, "arlan0-18", &arlan_drive_info,
-	 ARLAN_STR_SIZE, 0400, NULL, &arlan_sysctl_info18},
-	{153, "arlan0-ring", &arlan_drive_info,
-	 ARLAN_STR_SIZE, 0400, NULL, &arlan_sysctl_info161719},
-	{154, "arlan0-shm-cpy", &arlan_drive_info,
-	 ARLAN_STR_SIZE, 0400, NULL, &arlan_sysctl_info},
-#endif
-	{155, "config0", &conf_reset_result, \
-	 100, 0400, NULL, &arlan_configure}, \
-	{156, "reset0", &conf_reset_result, \
-	 100, 0400, NULL, &arlan_sysctl_reset}, \
-	{0}
+	{
+		.ctl_name	= 150,
+		.procname	= "arlan0-txRing",
+		.data		= &arlan_drive_info,
+		.maxlen		= ARLAN_STR_SIZE,
+		.mode		= 0400,
+		.proc_handler	= &arlan_sysctl_infotxRing,
+	},
+	{
+		.ctl_name	= 151,
+		.procname	= "arlan0-rxRing",
+		.data		= &arlan_drive_info,
+		.maxlen		= ARLAN_STR_SIZE,
+		.mode		= 0400,
+		.proc_handler	= &arlan_sysctl_inforxRing,
+	},
+	{
+		.ctl_name	= 152,
+		.procname	= "arlan0-18",
+		.data		= &arlan_drive_info,
+		.maxlen		= ARLAN_STR_SIZE,
+		.mode		= 0400,
+		.proc_handler	= &arlan_sysctl_info18,
+	},
+	{
+		.ctl_name	= 153,
+		.procname	= "arlan0-ring",
+		.data		= &arlan_drive_info,
+		.maxlen		= ARLAN_STR_SIZE,
+		.mode		= 0400,
+		.proc_handler	= &arlan_sysctl_info161719,
+	},
+	{
+		.ctl_name	= 154,
+		.procname	= "arlan0-shm-cpy",
+		.data		= &arlan_drive_info,
+		.maxlen		= ARLAN_STR_SIZE,
+		.mode		= 0400,
+		.proc_handler	= &arlan_sysctl_info,
+	},
+#endif
+	{
+		.ctl_name	= 155,
+		.procname	= "config0",
+		.data		= &conf_reset_result,
+		.maxlen		= 100,
+		.mode		= 0400,
+		.proc_handler	= &arlan_configure
+	},
+	{
+		.ctl_name	= 156,
+		.procname	= "reset0",
+		.data		= &conf_reset_result,
+		.maxlen		= 100,
+		.mode		= 0400,
+		.proc_handler	= &arlan_sysctl_reset,
+	},
+	{ .ctl_name = 0 }
 };
 
 static ctl_table arlan_conf_table1[] =
@@ -921,22 +968,64 @@
 	ARLAN_SYSCTL_TABLE_TOTAL(1)
 
 #ifdef ARLAN_PROC_SHM_DUMP
-	{150, "arlan1-txRing", &arlan_drive_info,
-	 ARLAN_STR_SIZE, 0400, NULL, &arlan_sysctl_infotxRing},
-	{151, "arlan1-rxRing", &arlan_drive_info,
-	 ARLAN_STR_SIZE, 0400, NULL, &arlan_sysctl_inforxRing},
-	{152, "arlan1-18", &arlan_drive_info,
-	 ARLAN_STR_SIZE, 0400, NULL, &arlan_sysctl_info18},
-	{153, "arlan1-ring", &arlan_drive_info,
-	 ARLAN_STR_SIZE, 0400, NULL, &arlan_sysctl_info161719},
-	{154, "arlan1-shm-cpy", &arlan_drive_info,
-	 ARLAN_STR_SIZE, 0400, NULL, &arlan_sysctl_info},
-#endif
-	{155, "config1", &conf_reset_result,
-	 100, 0400, NULL, &arlan_configure},
-	{156, "reset1", &conf_reset_result,
-	 100, 0400, NULL, &arlan_sysctl_reset},
-	{0}
+	{
+		.ctl_name	= 150,
+		.procname	= "arlan1-txRing",
+		.data		= &arlan_drive_info,
+		.maxlen		= ARLAN_STR_SIZE,
+		.mode		= 0400,
+		.proc_handler	= &arlan_sysctl_infotxRing,
+	},
+	{
+		.ctl_name	= 151,
+		.procname	= "arlan1-rxRing",
+		.data		= &arlan_drive_info,
+		.maxlen		= ARLAN_STR_SIZE,
+		.mode		= 0400,
+		.proc_handler	= &arlan_sysctl_inforxRing,
+	},
+	{
+		.ctl_name	= 152,
+		.procname	= "arlan1-18",
+		.data		= &arlan_drive_info,
+		.maxlen		= ARLAN_STR_SIZE,
+		.mode		= 0400,
+		.proc_handler	= &arlan_sysctl_info18,
+	},
+	{
+		.ctl_name	= 153,
+		.procname	= "arlan1-ring",
+		.data		= &arlan_drive_info,
+		.maxlen		= ARLAN_STR_SIZE,
+		.mode		= 0400,
+		.proc_handler	= &arlan_sysctl_info161719,
+	},
+	{
+		.ctl_name	= 154,
+		.procname	= "arlan1-shm-cpy",
+		.data		= &arlan_drive_info,
+		.maxlen		= ARLAN_STR_SIZE,
+		.mode		= 0400,
+		.proc_handler	= &arlan_sysctl_info,
+	},
+#endif
+	{
+		.ctl_name	= 155,
+		.procname	= "config1",
+		.data		= &conf_reset_result,
+		.maxlen		= 100,
+		.mode		= 0400,
+		.proc_handler	= &arlan_configure,
+	},
+	{
+		.ctl_name	= 156,
+		.procname	= "reset1",
+		.data		= &conf_reset_result,
+		.maxlen		= 100,
+		.mode		= 0400,
+		.proc_handler	= &arlan_sysctl_reset,
+	},
+	{ .ctl_name = 0 }
 };
 
 static ctl_table arlan_conf_table2[] =
@@ -945,22 +1034,64 @@
 	ARLAN_SYSCTL_TABLE_TOTAL(2)
 
 #ifdef ARLAN_PROC_SHM_DUMP
-	{150, "arlan2-txRing", &arlan_drive_info,
-	 ARLAN_STR_SIZE, 0400, NULL, &arlan_sysctl_infotxRing},
-	{151, "arlan2-rxRing", &arlan_drive_info,
-	 ARLAN_STR_SIZE, 0400, NULL, &arlan_sysctl_inforxRing},
-	{152, "arlan2-18", &arlan_drive_info,
-	 ARLAN_STR_SIZE, 0400, NULL, &arlan_sysctl_info18},
-	{153, "arlan2-ring", &arlan_drive_info,
-	 ARLAN_STR_SIZE, 0400, NULL, &arlan_sysctl_info161719},
-	{154, "arlan2-shm-cpy", &arlan_drive_info,
-	 ARLAN_STR_SIZE, 0400, NULL, &arlan_sysctl_info},
-#endif
-	{155, "config2", &conf_reset_result,
-	 100, 0400, NULL, &arlan_configure},
-	{156, "reset2", &conf_reset_result,
-	 100, 0400, NULL, &arlan_sysctl_reset},
-	{0}
+	{
+		.ctl_name	= 150,
+		.procname	= "arlan2-txRing",
+		.data		= &arlan_drive_info,
+		.maxlen		= ARLAN_STR_SIZE,
+		.mode		= 0400,
+		.proc_handler	= &arlan_sysctl_infotxRing,
+	},
+	{
+		.ctl_name	= 151,
+		.procname	= "arlan2-rxRing",
+		.data		= &arlan_drive_info,
+		.maxlen		= ARLAN_STR_SIZE,
+		.mode		= 0400,
+		.proc_handler	= &arlan_sysctl_inforxRing,
+	},
+	{
+		.ctl_name	= 152,
+		.procname	= "arlan2-18",
+		.data		= &arlan_drive_info,
+		.maxlen		= ARLAN_STR_SIZE,
+		.mode		= 0400,
+		.proc_handler	= &arlan_sysctl_info18,
+	},
+	{
+		.ctl_name	= 153,
+		.procname	= "arlan2-ring",
+		.data		= &arlan_drive_info,
+		.maxlen		= ARLAN_STR_SIZE,
+		.mode		= 0400,
+		.proc_handler	= &arlan_sysctl_info161719,
+	},
+	{
+		.ctl_name	= 154,
+		.procname	= "arlan2-shm-cpy",
+		.data		= &arlan_drive_info,
+		.maxlen		= ARLAN_STR_SIZE,
+		.mode		= 0400,
+		.proc_handler	= &arlan_sysctl_info,
+	},
+#endif
+	{
+		.ctl_name	= 155,
+		.procname	= "config2",
+		.data		= &conf_reset_result,
+		.maxlen		= 100,
+		.mode		= 0400,
+		.proc_handler	= &arlan_configure,
+	},
+	{
+		.ctl_name	= 156,
+		.procname	= "reset2",
+		.data		= &conf_reset_result,
+		.maxlen		= 100,
+		.mode		= 0400,
+		.proc_handler	= &arlan_sysctl_reset,
+	},
+	{ .ctl_name = 0 }
 };
 
 static ctl_table arlan_conf_table3[] =
@@ -969,47 +1100,113 @@
 	ARLAN_SYSCTL_TABLE_TOTAL(3)
 
 #ifdef ARLAN_PROC_SHM_DUMP
-	{150, "arlan3-txRing", &arlan_drive_info,
-	 ARLAN_STR_SIZE, 0400, NULL, &arlan_sysctl_infotxRing},
-	{151, "arlan3-rxRing", &arlan_drive_info,
-	 ARLAN_STR_SIZE, 0400, NULL, &arlan_sysctl_inforxRing},
-	{152, "arlan3-18", &arlan_drive_info,
-	 ARLAN_STR_SIZE, 0400, NULL, &arlan_sysctl_info18},
-	{153, "arlan3-ring", &arlan_drive_info,
-	 ARLAN_STR_SIZE, 0400, NULL, &arlan_sysctl_info161719},
-	{154, "arlan3-shm-cpy", &arlan_drive_info,
-	 ARLAN_STR_SIZE, 0400, NULL, &arlan_sysctl_info},
-#endif
-	{155, "config3", &conf_reset_result,
-	 100, 0400, NULL, &arlan_configure},
-	{156, "reset3", &conf_reset_result,
-	 100, 0400, NULL, &arlan_sysctl_reset},
-	{0}
+	{
+		.ctl_name	= 150,
+		.procname	= "arlan3-txRing",
+		.data		= &arlan_drive_info,
+		.maxlen		= ARLAN_STR_SIZE,
+		.mode		= 0400,
+		.proc_handler	= &arlan_sysctl_infotxRing,
+	},
+	{
+		.ctl_name	= 151,
+		.procname	= "arlan3-rxRing",
+		.data		= &arlan_drive_info,
+		.maxlen		= ARLAN_STR_SIZE,
+		.mode		= 0400,
+		.proc_handler	= &arlan_sysctl_inforxRing,
+	},
+	{
+		.ctl_name	= 152,
+		.procname	= "arlan3-18",
+		.data		= &arlan_drive_info,
+		.maxlen		= ARLAN_STR_SIZE,
+		.mode		= 0400,
+		.proc_handler	= &arlan_sysctl_info18,
+	},
+	{
+		.ctl_name	= 153,
+		.procname	= "arlan3-ring",
+		.data		= &arlan_drive_info,
+		.maxlen		= ARLAN_STR_SIZE,
+		.mode		= 0400,
+		.proc_handler	= &arlan_sysctl_info161719,
+	},
+	{
+		.ctl_name	= 154,
+		.procname	= "arlan3-shm-cpy",
+		.data		= &arlan_drive_info,
+		.maxlen		= ARLAN_STR_SIZE,
+		.mode		= 0400,
+		.proc_handler	= &arlan_sysctl_info,
+	},
+#endif
+	{
+		.ctl_name	= 155,
+		.procname	= "config3",
+		.data		= &conf_reset_result,
+		.maxlen		= 100,
+		.mode		= 0400,
+		.proc_handler	= &arlan_configure,
+	},
+	{
+		.ctl_name	= 156,
+		.procname	= "reset3",
+		.data		= &conf_reset_result,
+		.maxlen		= 100,
+		.mode		= 0400,
+		.proc_handler	= &arlan_sysctl_reset,
+	},
+	{ .ctl_name = 0 }
 };
 
 
 
 static ctl_table arlan_table[] =
 {
-	{0, "arlan0", NULL, 0, 0600, arlan_conf_table0},
-	{0, "arlan1", NULL, 0, 0600, arlan_conf_table1},
-	{0, "arlan2", NULL, 0, 0600, arlan_conf_table2},
-	{0, "arlan3", NULL, 0, 0600, arlan_conf_table3},
-	{0}
+	{
+		.ctl_name	= 0,
+		.procname	= "arlan0",
+		.maxlen		= 0,
+		.mode		= 0600,
+		.child		= arlan_conf_table0,
+	},
+	{
+		.ctl_name	= 0,
+		.procname	= "arlan1",
+		.maxlen		= 0,
+		.mode		= 0600,
+		.child		= arlan_conf_table1,
+	},
+	{
+		.ctl_name	= 0,
+		.procname	= "arlan2",
+		.maxlen		= 0,
+		.mode		= 0600,
+		.child		= arlan_conf_table2,
+	},
+	{
+		.ctl_name	= 0,
+		.procname	= "arlan3",
+		.maxlen		= 0,
+		.mode		= 0600,
+		.child		= arlan_conf_table3,
+	},
+	{ .ctl_name = 0 }
 };
 
 #else
 
 static ctl_table arlan_table[MAX_ARLANS + 1] =
 {
-	{0}
+	{ .ctl_name = 0 }
 };
 #endif
 #else
 
 static ctl_table arlan_table[MAX_ARLANS + 1] =
 {
-	{0}
+	{ .ctl_name = 0 }
 };
 #endif
 
@@ -1018,8 +1215,14 @@
 
 static ctl_table arlan_root_table[] =
 {
-	{254, "arlan", NULL, 0, 0555, arlan_table},
-	{0}
+	{
+		.ctl_name	= 254,
+		.procname	= "arlan",
+		.maxlen		= 0,
+		.mode		= 0555,
+		.child		= arlan_table,
+	},
+	{ .ctl_name = 0 }
 };
 
 /* Make sure that /proc/sys/dev is there */
diff -Nru a/drivers/net/hamradio/baycom_epp.c b/drivers/net/hamradio/baycom_epp.c
--- a/drivers/net/hamradio/baycom_epp.c	Mon Feb 17 14:57:28 2003
+++ b/drivers/net/hamradio/baycom_epp.c	Mon Feb 17 14:57:28 2003
@@ -369,15 +369,14 @@
 
 static char *envp[] = { "HOME=/", "TERM=linux", "PATH=/usr/bin:/bin", NULL };
 
-static int errno;
-
-static int exec_eppfpga(void *b)
+/* eppconfig: called during ifconfig up to configure the modem */
+static int eppconfig(struct baycom_state *bc)
 {
-	struct baycom_state *bc = (struct baycom_state *)b;
 	char modearg[256];
 	char portarg[16];
-        char *argv[] = { eppconfig_path, "-s", "-p", portarg, "-m", modearg, NULL};
-        int i;
+        char *argv[] = { eppconfig_path, "-s", "-p", portarg, "-m", modearg,
+			 NULL };
+        int ret;
 
 	/* set up arguments */
 	sprintf(modearg, "%sclk,%smodem,fclk=%d,bps=%d,divider=%d%s,extstat",
@@ -388,39 +387,7 @@
 	sprintf(portarg, "%ld", bc->pdev->port->base);
 	printk(KERN_DEBUG "%s: %s -s -p %s -m %s\n", bc_drvname, eppconfig_path, portarg, modearg);
 
-	i = exec_usermodehelper(eppconfig_path, argv, envp);
-	if (i < 0) {
-                printk(KERN_ERR "%s: failed to exec %s -s -p %s -m %s, errno = %d\n",
-                       bc_drvname, eppconfig_path, portarg, modearg, i);
-                return i;
-        }
-        return 0;
-}
-
-
-/* eppconfig: called during ifconfig up to configure the modem */
-
-static int eppconfig(struct baycom_state *bc)
-{
-        int i, pid, r;
-	mm_segment_t fs;
-
-        pid = kernel_thread(exec_eppfpga, bc, CLONE_FS);
-        if (pid < 0) {
-                printk(KERN_ERR "%s: fork failed, errno %d\n", bc_drvname, -pid);
-                return pid;
-        }
-	fs = get_fs();
-        set_fs(KERNEL_DS);      /* Allow i to be in kernel space. */
-	r = waitpid(pid, &i, __WCLONE);
-	set_fs(fs);
-        if (r != pid) {
-                printk(KERN_ERR "%s: waitpid(%d) failed, returning %d\n",
-		       bc_drvname, pid, r);
-		return -1;
-        }
-	printk(KERN_DEBUG "%s: eppfpga returned %d\n", bc_drvname, i);
-	return i;
+	return call_usermodehelper(eppconfig_path, argv, envp, 1);
 }
 
 /* ---------------------------------------------------------------------- */
diff -Nru a/drivers/net/rrunner.c b/drivers/net/rrunner.c
--- a/drivers/net/rrunner.c	Mon Feb 17 14:57:27 2003
+++ b/drivers/net/rrunner.c	Mon Feb 17 14:57:27 2003
@@ -255,6 +255,7 @@
 		iounmap(rr->regs);
 		kfree(dev);
 		pci_release_regions(pdev);
+		pci_disable_device(pdev);
 		pci_set_drvdata(pdev, NULL);
 	}
 }
@@ -1128,14 +1129,12 @@
 	spin_unlock(&rrpriv->lock);
 }
 
-
 static void rr_timer(unsigned long data)
 {
 	struct net_device *dev = (struct net_device *)data;
 	struct rr_private *rrpriv = (struct rr_private *)dev->priv;
 	struct rr_regs *regs = rrpriv->regs;
 	unsigned long flags;
-	int i;
 
 	if (readl(&regs->HostCtrl) & NIC_HALTED){
 		printk("%s: Restarting nic\n", dev->name);
@@ -1143,23 +1142,8 @@
 		memset(rrpriv->info, 0, sizeof(struct rr_info));
 		wmb();
 
-		for (i = 0; i < TX_RING_ENTRIES; i++) {
-			if (rrpriv->tx_skbuff[i]) {
-				rrpriv->tx_ring[i].size = 0;
-				set_rraddr(&rrpriv->tx_ring[i].addr, 0);
-				dev_kfree_skb(rrpriv->tx_skbuff[i]);
-				rrpriv->tx_skbuff[i] = NULL;
-			}
-		}
-
-		for (i = 0; i < RX_RING_ENTRIES; i++) {
-			if (rrpriv->rx_skbuff[i]) {
-				rrpriv->rx_ring[i].size = 0;
-				set_rraddr(&rrpriv->rx_ring[i].addr, 0);
-				dev_kfree_skb(rrpriv->rx_skbuff[i]);
-				rrpriv->rx_skbuff[i] = NULL;
-			}
-		}
+		rr_raz_tx(rrpriv, dev);
+		rr_raz_rx(rrpriv, dev);
 
 		if (rr_init1(dev)) {
 			spin_lock_irqsave(&rrpriv->lock, flags);
@@ -1246,11 +1230,13 @@
 	spin_unlock_irqrestore(&rrpriv->lock, flags);
 
 	if (rrpriv->info) {
-		kfree(rrpriv->info);
+		pci_free_consistent(pdev, sizeof(struct rr_info), rrpriv->info,
+				    rrpriv->info_dma);
 		rrpriv->info = NULL;
 	}
 	if (rrpriv->rx_ctrl) {
-		kfree(rrpriv->rx_ctrl);
+		pci_free_consistent(pdev, sizeof(struct ring_ctrl),
+				    rrpriv->rx_ctrl, rrpriv->rx_ctrl_dma);
 		rrpriv->rx_ctrl = NULL;
 	}
 
@@ -1413,23 +1399,8 @@
 	rrpriv->info->evt_ctrl.pi = 0;
 	rrpriv->rx_ctrl[4].entries = 0;
 
-	for (i = 0; i < TX_RING_ENTRIES; i++) {
-		if (rrpriv->tx_skbuff[i]) {
-			rrpriv->tx_ring[i].size = 0;
-			set_rraddr(&rrpriv->tx_ring[i].addr, 0);
-			dev_kfree_skb(rrpriv->tx_skbuff[i]);
-			rrpriv->tx_skbuff[i] = NULL;
-		}
-	}
-
-	for (i = 0; i < RX_RING_ENTRIES; i++) {
-		if (rrpriv->rx_skbuff[i]) {
-			rrpriv->rx_ring[i].size = 0;
-			set_rraddr(&rrpriv->rx_ring[i].addr, 0);
-			dev_kfree_skb(rrpriv->rx_skbuff[i]);
-			rrpriv->rx_skbuff[i] = NULL;
-		}
-	}
+	rr_raz_tx(rrpriv, dev);
+	rr_raz_rx(rrpriv, dev);
 
 	pci_free_consistent(rrpriv->pci_dev, 256 * sizeof(struct ring_ctrl),
 			    rrpriv->rx_ctrl, rrpriv->rx_ctrl_dma);
diff -Nru a/drivers/net/shaper.c b/drivers/net/shaper.c
--- a/drivers/net/shaper.c	Mon Feb 17 14:57:27 2003
+++ b/drivers/net/shaper.c	Mon Feb 17 14:57:27 2003
@@ -681,7 +681,7 @@
 #ifdef MODULE
 
 MODULE_PARM(shapers, "i");
-MODULE_PARM_DESC(shapers, "Traffic shaper: maximum nuber of shapers");
+MODULE_PARM_DESC(shapers, "Traffic shaper: maximum number of shapers");
 
 #else /* MODULE */
 
diff -Nru a/drivers/net/tokenring/proteon.c b/drivers/net/tokenring/proteon.c
--- a/drivers/net/tokenring/proteon.c	Mon Feb 17 14:57:28 2003
+++ b/drivers/net/tokenring/proteon.c	Mon Feb 17 14:57:28 2003
@@ -322,7 +322,7 @@
  * Calling this on a board that does not support it can be a very
  * dangerous thing.  The Madge board, for instance, will lock your
  * machine hard when this is called.  Luckily, its supported in a
- * seperate driver.  --ASF
+ * separate driver.  --ASF
  */
 static void proteon_read_eeprom(struct net_device *dev)
 {
diff -Nru a/drivers/net/via-rhine.c b/drivers/net/via-rhine.c
--- a/drivers/net/via-rhine.c	Mon Feb 17 14:57:28 2003
+++ b/drivers/net/via-rhine.c	Mon Feb 17 14:57:28 2003
@@ -101,11 +101,18 @@
 	LK1.1.15 (jgarzik):
 	- Use new MII lib helper generic_mii_ioctl
 
+	LK1.1.16 (Roger Luethi)
+	- Etherleak fix
+	- Handle Tx buffer underrun
+	- Fix bugs in full duplex handling
+	- New reset code uses "force reset" cmd on Rhine-II
+	- Various clean ups
+
 */
 
 #define DRV_NAME	"via-rhine"
-#define DRV_VERSION	"1.1.15"
-#define DRV_RELDATE	"November-22-2002"
+#define DRV_VERSION	"1.1.16"
+#define DRV_RELDATE	"February-15-2003"
 
 
 /* A few user-configurable values.
@@ -395,7 +402,7 @@
 	MIIPhyAddr=0x6C, MIIStatus=0x6D, PCIBusConfig=0x6E,
 	MIICmd=0x70, MIIRegAddr=0x71, MIIData=0x72, MACRegEEcsr=0x74,
 	ConfigA=0x78, ConfigB=0x79, ConfigC=0x7A, ConfigD=0x7B,
-	RxMissed=0x7C, RxCRCErrs=0x7E,
+	RxMissed=0x7C, RxCRCErrs=0x7E, MiscCmd=0x81,
 	StickyHW=0x83, WOLcrClr=0xA4, WOLcgClr=0xA7, PwrcsrClr=0xAC,
 };
 
@@ -416,29 +423,15 @@
 /* Bits in the interrupt status/mask registers. */
 enum intr_status_bits {
 	IntrRxDone=0x0001, IntrRxErr=0x0004, IntrRxEmpty=0x0020,
-	IntrTxDone=0x0002, IntrTxError=0x0008, IntrTxUnderrun=0x0010,
+	IntrTxDone=0x0002, IntrTxError=0x0008, IntrTxUnderrun=0x0210,
 	IntrPCIErr=0x0040,
-	IntrStatsMax=0x0080, IntrRxEarly=0x0100, IntrMIIChange=0x0200,
+	IntrStatsMax=0x0080, IntrRxEarly=0x0100,
 	IntrRxOverflow=0x0400, IntrRxDropped=0x0800, IntrRxNoBuf=0x1000,
 	IntrTxAborted=0x2000, IntrLinkChange=0x4000,
 	IntrRxWakeUp=0x8000,
 	IntrNormalSummary=0x0003, IntrAbnormalSummary=0xC260,
 };
 
-/* MII interface, status flags.
-   Not to be confused with the MIIStatus register ... */
-enum mii_status_bits {
-	MIICap100T4			= 0x8000,
-	MIICap10100HdFd		= 0x7800,
-	MIIPreambleSupr		= 0x0040,
-	MIIAutoNegCompleted	= 0x0020,
-	MIIRemoteFault		= 0x0010,
-	MIICapAutoNeg		= 0x0008,
-	MIILink				= 0x0004,
-	MIIJabber			= 0x0002,
-	MIIExtended			= 0x0001
-};
-
 /* The Rx and Tx buffer descriptors. */
 struct rx_desc {
 	s32 rx_status;
@@ -533,30 +526,29 @@
 static struct net_device_stats *via_rhine_get_stats(struct net_device *dev);
 static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
 static int  via_rhine_close(struct net_device *dev);
-static inline void clear_tally_counters(long ioaddr);
-static inline void via_restart_tx(struct net_device *dev);
 
 static void wait_for_reset(struct net_device *dev, int chip_id, char *name)
 {
 	long ioaddr = dev->base_addr;
-	int i;
 
-	/* VT86C100A may need long delay after reset (dlink) */
-	if (chip_id == VT86C100A)
+	udelay(5);
+
+	if (readw(ioaddr + ChipCmd) & CmdReset) {
+		printk(KERN_INFO "%s: Reset did not complete in 5 us. "
+			"Trying harder.\n", name);
+
+		/* Rhine-II needs to be forced sometimes */
+		if (chip_id == VT6102)
+			writeb(0x40, ioaddr + MiscCmd);
+
+		/* VT86C100A may need long delay after reset (dlink) */
+		/* Seen on Rhine-II as well (rl) */
 		udelay(100);
+	}
 
-	i = 0;
-	do {
-		udelay(5);
-		i++;
-		if(i > 2000) {
-			printk(KERN_ERR "%s: reset did not complete in 10 ms.\n", name);
-			break;
-		}
-	} while(readw(ioaddr + ChipCmd) & CmdReset);
 	if (debug > 1)
-		printk(KERN_INFO "%s: reset finished after %d microseconds.\n",
-			   name, 5*i);
+		printk(KERN_INFO "%s: Reset %s.\n", name,
+			(readw(ioaddr + ChipCmd) & CmdReset) ? "failed" : "succeeded");
 }
 
 #ifdef USE_MEM
@@ -742,21 +734,6 @@
 	if (dev->mem_start)
 		option = dev->mem_start;
 
-	/* The lower four bits are the media type. */
-	if (option > 0) {
-		if (option & 0x200)
-			np->mii_if.full_duplex = 1;
-		np->default_port = option & 15;
-	}
-	if (card_idx < MAX_UNITS  &&  full_duplex[card_idx] > 0)
-		np->mii_if.full_duplex = 1;
-
-	if (np->mii_if.full_duplex) {
-		printk(KERN_INFO "%s: Set to forced full duplex, autonegotiation"
-			   " disabled.\n", dev->name);
-		np->mii_if.force_media = 1;
-	}
-
 	/* The chip-specific entries in the device structure. */
 	dev->open = via_rhine_open;
 	dev->hard_start_xmit = via_rhine_start_tx;
@@ -768,11 +745,27 @@
 	dev->watchdog_timeo = TX_TIMEOUT;
 	if (np->drv_flags & ReqTxAlign)
 		dev->features |= NETIF_F_SG|NETIF_F_HW_CSUM;
-	
+
+	/* dev->name not defined before register_netdev()! */
 	i = register_netdev(dev);
 	if (i)
 		goto err_out_unmap;
 
+	/* The lower four bits are the media type. */
+	if (option > 0) {
+		if (option & 0x220)
+			np->mii_if.full_duplex = 1;
+		np->default_port = option & 15;
+	}
+	if (card_idx < MAX_UNITS  &&  full_duplex[card_idx] > 0)
+		np->mii_if.full_duplex = 1;
+
+	if (np->mii_if.full_duplex) {
+		printk(KERN_INFO "%s: Set to forced full duplex, autonegotiation"
+			   " disabled.\n", dev->name);
+		np->mii_if.force_media = 1;
+	}
+
 	printk(KERN_INFO "%s: %s at 0x%lx, ",
 		   dev->name, via_rhine_chip_info[chip_id].name,
 		   (pci_flags & PCI_USES_IO) ? ioaddr : memaddr);
@@ -797,7 +790,7 @@
 					   mdio_read(dev, phy, 5));
 
 				/* set IFF_RUNNING */
-				if (mii_status & MIILink)
+				if (mii_status & BMSR_LSTATUS)
 					netif_carrier_on(dev);
 				else
 					netif_carrier_off(dev);
@@ -1008,6 +1001,7 @@
 	writeb(0x20, ioaddr + TxConfig);
 	np->tx_thresh = 0x20;
 	np->rx_thresh = 0x60;			/* Written in via_rhine_set_rx_mode(). */
+	np->mii_if.full_duplex = 0;
 
 	if (dev->if_port == 0)
 		dev->if_port = np->default_port;
@@ -1021,7 +1015,7 @@
 	writew(IntrRxDone | IntrRxErr | IntrRxEmpty| IntrRxOverflow |
 		   IntrRxDropped | IntrRxNoBuf | IntrTxAborted |
 		   IntrTxDone | IntrTxError | IntrTxUnderrun |
-		   IntrPCIErr | IntrStatsMax | IntrLinkChange | IntrMIIChange,
+		   IntrPCIErr | IntrStatsMax | IntrLinkChange,
 		   ioaddr + IntrEnable);
 
 	np->chip_cmd = CmdStart|CmdTxOn|CmdRxOn|CmdNoTxPoll;
@@ -1175,8 +1169,8 @@
 
 	/* make IFF_RUNNING follow the MII status bit "Link established" */
 	mii_status = mdio_read(dev, np->phys[0], MII_BMSR);
-	if ( (mii_status & MIILink) != (np->mii_status & MIILink) ) {
-		if (mii_status & MIILink)
+	if ( (mii_status & BMSR_LSTATUS) != (np->mii_status & BMSR_LSTATUS) ) {
+		if (mii_status & BMSR_LSTATUS)
 			netif_carrier_on(dev);
 		else
 			netif_carrier_off(dev);
@@ -1326,7 +1320,7 @@
 			via_rhine_tx(dev);
 
 		/* Abnormal error summary/uncommon events handlers. */
-		if (intr_status & (IntrPCIErr | IntrLinkChange | IntrMIIChange |
+		if (intr_status & (IntrPCIErr | IntrLinkChange |
 				   IntrStatsMax | IntrTxError | IntrTxAborted |
 				   IntrTxUnderrun))
 			via_rhine_error(dev, intr_status);
@@ -1414,8 +1408,8 @@
 	int boguscnt = np->dirty_rx + RX_RING_SIZE - np->cur_rx;
 
 	if (debug > 4) {
-		printk(KERN_DEBUG " In via_rhine_rx(), entry %d status %8.8x.\n",
-			   entry, le32_to_cpu(np->rx_head_desc->rx_status));
+		printk(KERN_DEBUG "%s: via_rhine_rx(), entry %d status %8.8x.\n",
+			   dev->name, entry, le32_to_cpu(np->rx_head_desc->rx_status));
 	}
 
 	/* If EOP is set on the next entry, it's a new packet. Send it up. */
@@ -1521,7 +1515,18 @@
 	writew(CmdRxDemand | np->chip_cmd, dev->base_addr + ChipCmd);
 }
 
-static inline void via_restart_tx(struct net_device *dev) {
+/* Clears the "tally counters" for CRC errors and missed frames(?).
+   It has been reported that some chips need a write of 0 to clear
+   these, for others the counters are set to 1 when written to and
+   instead cleared when read. So we clear them both ways ... */
+static inline void clear_tally_counters(const long ioaddr)
+{
+	writel(0, ioaddr + RxMissed);
+	readw(ioaddr + RxCRCErrs);
+	readw(ioaddr + RxMissed);
+}
+
+static inline void via_rhine_restart_tx(struct net_device *dev) {
 	struct netdev_private *np = dev->priv;
 	int entry = np->dirty_tx % TX_RING_SIZE;
 
@@ -1539,7 +1544,7 @@
 
 	spin_lock (&np->lock);
 
-	if (intr_status & (IntrMIIChange | IntrLinkChange)) {
+	if (intr_status & (IntrLinkChange)) {
 		if (readb(ioaddr + MIIStatus) & 0x02) {
 			/* Link failed, restart autonegotiation. */
 			if (np->drv_flags & HasDavicomPhy)
@@ -1557,11 +1562,11 @@
 		np->stats.rx_missed_errors	+= readw(ioaddr + RxMissed);
 		clear_tally_counters(ioaddr);
 	}
-	if (intr_status & IntrTxError) {
+	if (intr_status & IntrTxAborted) {
 		if (debug > 1)
 			printk(KERN_INFO "%s: Abort %4.4x, frame dropped.\n",
 				   dev->name, intr_status);
-		via_restart_tx(dev);
+		via_rhine_restart_tx(dev);
 	}
 	if (intr_status & IntrTxUnderrun) {
 		if (np->tx_thresh < 0xE0)
@@ -1570,9 +1575,9 @@
 			printk(KERN_INFO "%s: Transmitter underrun, Tx "
 				   "threshold now %2.2x.\n",
 				   dev->name, np->tx_thresh);
-		via_restart_tx(dev);
+		via_rhine_restart_tx(dev);
 	}
-	if (intr_status & ~( IntrLinkChange | IntrStatsMax |
+	if (intr_status & ~( IntrLinkChange | IntrStatsMax | IntrTxUnderrun |
  						 IntrTxError | IntrTxAborted | IntrNormalSummary)) {
 		if (debug > 1)
 			printk(KERN_ERR "%s: Something Wicked happened! %4.4x.\n",
@@ -1597,17 +1602,6 @@
 	spin_unlock_irqrestore(&np->lock, flags);
 
 	return &np->stats;
-}
-
-/* Clears the "tally counters" for CRC errors and missed frames(?).
-   It has been reported that some chips need a write of 0 to clear
-   these, for others the counters are set to 1 when written to and
-   instead cleared when read. So we clear them both ways ... */
-static inline void clear_tally_counters(const long ioaddr)
-{
-	writel(0, ioaddr + RxMissed);
-	readw(ioaddr + RxCRCErrs);
-	readw(ioaddr + RxMissed);
 }
 
 static void via_rhine_set_rx_mode(struct net_device *dev)
diff -Nru a/drivers/parisc/eisa.c b/drivers/parisc/eisa.c
--- a/drivers/parisc/eisa.c	Mon Feb 17 14:57:26 2003
+++ b/drivers/parisc/eisa.c	Mon Feb 17 14:57:26 2003
@@ -35,6 +35,7 @@
 #include <linux/pci.h>
 #include <linux/sched.h>
 #include <linux/spinlock.h>
+#include <linux/eisa.h>
 
 #include <asm/byteorder.h>
 #include <asm/io.h>
@@ -61,6 +62,7 @@
 static struct eisa_ba {
 	struct pci_hba_data	hba;
 	unsigned long eeprom_addr;
+	struct eisa_root_device root;
 } eisa_dev;
 
 /* Port ops */
@@ -376,6 +378,18 @@
 	eisa_eeprom_init(eisa_dev.eeprom_addr);
 	eisa_enumerator(eisa_dev.eeprom_addr, &eisa_dev.hba.io_space, &eisa_dev.hba.lmmio_space);
 	init_eisa_pic();
+
+	/* FIXME : Get the number of slots from the enumerator, not a
+	 * hadcoded value. Also don't enumerate the bus twice. */
+	eisa_dev.root.dev = &dev->dev;
+	dev->dev.driver_data = &eisa_dev.root;
+	eisa_dev.root.bus_base_addr = 0;
+	eisa_dev.root.res = &eisa_dev.hba.io_space;
+	eisa_dev.root.slots = EISA_MAX_SLOTS;
+	if (eisa_root_register (&eisa_dev.root)) {
+		printk(KERN_ERR "EISA: Failed to register EISA root\n");
+		return -1;
+	}
 	
 	return 0;
 }
diff -Nru a/drivers/pci/pci.c b/drivers/pci/pci.c
--- a/drivers/pci/pci.c	Mon Feb 17 14:57:27 2003
+++ b/drivers/pci/pci.c	Mon Feb 17 14:57:27 2003
@@ -592,7 +592,7 @@
  * function.  Originally copied from drivers/net/acenic.c.
  * Copyright 1998-2001 by Jes Sorensen, <jes@trained-monkey.org>.
  *
- * RETURNS: An appropriate -ERRNO error value on eror, or zero for success.
+ * RETURNS: An appropriate -ERRNO error value on error, or zero for success.
  */
 static int
 pci_generic_prep_mwi(struct pci_dev *dev)
@@ -634,7 +634,7 @@
  * and then calls @pcibios_set_mwi to do the needed arch specific
  * operations or a generic mwi-prep function.
  *
- * RETURNS: An appriopriate -ERRNO error value on eror, or zero for success.
+ * RETURNS: An appropriate -ERRNO error value on error, or zero for success.
  */
 int
 pci_set_mwi(struct pci_dev *dev)
diff -Nru a/drivers/pci/quirks.c b/drivers/pci/quirks.c
--- a/drivers/pci/quirks.c	Mon Feb 17 14:57:26 2003
+++ b/drivers/pci/quirks.c	Mon Feb 17 14:57:26 2003
@@ -535,6 +535,15 @@
 	}
 }
 
+/* This was originally an Alpha specific thing, but it really fits here.
+ * The i82375 PCI/EISA bridge appears as non-classified. Fix that.
+ */
+
+static void __init quirk_eisa_bridge(struct pci_dev *dev)
+{
+	dev->class = PCI_CLASS_BRIDGE_EISA << 8;
+}
+
 /*
  *  The main table of quirks.
  */
@@ -604,6 +613,7 @@
 
 	{ PCI_FIXUP_FINAL,	PCI_VENDOR_ID_CYRIX,	PCI_DEVICE_ID_CYRIX_PCI_MASTER, quirk_mediagx_master },
 	
+	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82375,	quirk_eisa_bridge },
 
 	{ 0 }
 };
diff -Nru a/drivers/pcmcia/cs.c b/drivers/pcmcia/cs.c
--- a/drivers/pcmcia/cs.c	Mon Feb 17 14:57:27 2003
+++ b/drivers/pcmcia/cs.c	Mon Feb 17 14:57:27 2003
@@ -47,6 +47,7 @@
 #include <linux/proc_fs.h>
 #include <linux/pm.h>
 #include <linux/pci.h>
+#include <linux/device.h>
 #include <asm/system.h>
 #include <asm/irq.h>
 
@@ -308,119 +309,123 @@
 static void unreset_socket(socket_info_t *);
 static void parse_events(void *info, u_int events);
 
-socket_info_t *pcmcia_register_socket (int slot,
-	struct pccard_operations * ss_entry,
-	int use_bus_pm)
-{
-    socket_info_t *s;
-    int i;
+#define to_class_data(dev) dev->class_data
 
-    DEBUG(0, "cs: pcmcia_register_socket(0x%p)\n", ss_entry);
-
-    s = kmalloc(sizeof(struct socket_info_t), GFP_KERNEL);
-    if (!s)
-    	return NULL;
-    memset(s, 0, sizeof(socket_info_t));
-
-    s->ss_entry = ss_entry;
-    s->sock = slot;
-
-    /* base address = 0, map = 0 */
-    s->cis_mem.flags = 0;
-    s->cis_mem.speed = cis_speed;
-    s->use_bus_pm = use_bus_pm;
-    s->erase_busy.next = s->erase_busy.prev = &s->erase_busy;
-    spin_lock_init(&s->lock);
-    
-    for (i = 0; i < sockets; i++)
-	if (socket_table[i] == NULL) break;
-    socket_table[i] = s;
-    if (i == sockets) sockets++;
+/**
+ * pcmcia_register_socket - add a new pcmcia socket device
+ */
+int pcmcia_register_socket(struct device *dev)
+{
+	struct pcmcia_socket_class_data *cls_d = to_class_data(dev);
+	socket_info_t *s_info;
+	unsigned int i, j;
+
+	if (!cls_d)
+		return -EINVAL;
+
+	DEBUG(0, "cs: pcmcia_register_socket(0x%p)\n", cls_d->ops);
+
+	s_info = kmalloc(cls_d->nsock * sizeof(struct socket_info_t), GFP_KERNEL);
+	if (!s_info)
+		return -ENOMEM;
+	memset(s_info, 0, cls_d->nsock * sizeof(socket_info_t));
+
+	/* socket initialization */
+	for (i = 0; i < cls_d->nsock; i++) {
+		socket_info_t *s = &s_info[i];
+
+		cls_d->s_info[i] = s;
+		s->ss_entry = cls_d->ops;
+		s->sock = i;
+
+		/* base address = 0, map = 0 */
+		s->cis_mem.flags = 0;
+		s->cis_mem.speed = cis_speed;
+		s->use_bus_pm = cls_d->use_bus_pm;
+		s->erase_busy.next = s->erase_busy.prev = &s->erase_busy;
+		spin_lock_init(&s->lock);
+    
+		/* TBD: remove usage of socket_table, use class_for_each_dev instead */
+		for (j = 0; j < sockets; j++)
+			if (socket_table[j] == NULL) break;
+		socket_table[j] = s;
+		if (j == sockets) sockets++;
 
-    init_socket(s);
-    ss_entry->inquire_socket(slot, &s->cap);
+		init_socket(s);
+		s->ss_entry->inquire_socket(i, &s->cap);
 #ifdef CONFIG_PROC_FS
-    if (proc_pccard) {
-	char name[3];
-	sprintf(name, "%02d", i);
-	s->proc = proc_mkdir(name, proc_pccard);
-	if (s->proc)
-	    ss_entry->proc_setup(slot, s->proc);
+		if (proc_pccard) {
+			char name[3];
+			sprintf(name, "%02d", j);
+			s->proc = proc_mkdir(name, proc_pccard);
+			if (s->proc)
+				s->ss_entry->proc_setup(i, s->proc);
 #ifdef PCMCIA_DEBUG
-	if (s->proc)
-	    create_proc_read_entry("clients", 0, s->proc,
-				   proc_read_clients, s);
+			if (s->proc)
+				create_proc_read_entry("clients", 0, s->proc,
+				       proc_read_clients, s);
 #endif
-    }
+		}
 #endif
-    return s;
+	}
+	return 0;
 } /* pcmcia_register_socket */
 
-int register_ss_entry(int nsock, struct pccard_operations * ss_entry)
-{
-    int ns;
-
-    DEBUG(0, "cs: register_ss_entry(%d, 0x%p)\n", nsock, ss_entry);
-
-    for (ns = 0; ns < nsock; ns++) {
-	pcmcia_register_socket (ns, ss_entry, 0);
-    }
-    
-    return 0;
-} /* register_ss_entry */
-
-/*====================================================================*/
 
-void pcmcia_unregister_socket(socket_info_t *s)
+/**
+ * pcmcia_unregister_socket - remove a pcmcia socket device
+ */
+void pcmcia_unregister_socket(struct device *dev)
 {
-    int j, socket = -1;
-    client_t *client;
+	struct pcmcia_socket_class_data *cls_d = to_class_data(dev);
+	unsigned int i;
+	int j, socket = -1;
+	client_t *client;
+	socket_info_t *s;
 
-    for (j = 0; j < MAX_SOCK; j++)
-	if (socket_table [j] == s) {
-	    socket = j;
-	    break;
-	}
-    if (socket < 0)
-	return;
+	if (!cls_d)
+		return;
+
+	s = (socket_info_t *) cls_d->s_info;
 
+	for (i = 0; i < cls_d->nsock; i++) {
+		for (j = 0; j < MAX_SOCK; j++)
+			if (socket_table [j] == s) {
+				socket = j;
+				break;
+			}
+		if (socket < 0)
+			continue;
+		
 #ifdef CONFIG_PROC_FS
-    if (proc_pccard) {
-	char name[3];
-	sprintf(name, "%02d", socket);
+		if (proc_pccard) {
+			char name[3];
+			sprintf(name, "%02d", socket);
 #ifdef PCMCIA_DEBUG
-	remove_proc_entry("clients", s->proc);
+			remove_proc_entry("clients", s->proc);
 #endif
-	remove_proc_entry(name, proc_pccard);
-    }
+			remove_proc_entry(name, proc_pccard);
+		}
 #endif
+		
+		shutdown_socket(s);
+		release_cis_mem(s);
+		while (s->clients) {
+			client = s->clients;
+			s->clients = s->clients->next;
+			kfree(client);
+		}
+		s->ss_entry = NULL;
+		socket_table[socket] = NULL;
+		for (j = socket; j < sockets-1; j++)
+			socket_table[j] = socket_table[j+1];
+		sockets--;
 
-    shutdown_socket(s);
-    release_cis_mem(s);
-    while (s->clients) {
-	client = s->clients;
-	s->clients = s->clients->next;
-	kfree(client);
-    }
-    s->ss_entry = NULL;
-    kfree(s);
-
-    socket_table[socket] = NULL;
-    for (j = socket; j < sockets-1; j++)
-	socket_table[j] = socket_table[j+1];
-    sockets--;
+		s++;
+	}
+	kfree(cls_d->s_info);
 } /* pcmcia_unregister_socket */
 
-void unregister_ss_entry(struct pccard_operations * ss_entry)
-{
-    int i;
-
-    for (i = sockets-1; i >= 0; i-- ) {
-	socket_info_t *socket = socket_table[i];
-	if (socket->ss_entry == ss_entry)
-		pcmcia_unregister_socket (socket);
-    }
-} /* unregister_ss_entry */
 
 /*======================================================================
 
@@ -2402,8 +2407,6 @@
 EXPORT_SYMBOL(pcmcia_write_memory);
 
 EXPORT_SYMBOL(dead_socket);
-EXPORT_SYMBOL(register_ss_entry);
-EXPORT_SYMBOL(unregister_ss_entry);
 EXPORT_SYMBOL(CardServices);
 EXPORT_SYMBOL(MTDHelperEntry);
 #ifdef CONFIG_PROC_FS
@@ -2415,16 +2418,26 @@
 EXPORT_SYMBOL(pcmcia_suspend_socket);
 EXPORT_SYMBOL(pcmcia_resume_socket);
 
+struct device_class pcmcia_socket_class = {
+	.name = "pcmcia_socket",
+	.add_device = &pcmcia_register_socket,
+	.remove_device = &pcmcia_unregister_socket,
+};
+EXPORT_SYMBOL(pcmcia_socket_class);
+
+
 static int __init init_pcmcia_cs(void)
 {
     printk(KERN_INFO "%s\n", release);
     printk(KERN_INFO "  %s\n", options);
     DEBUG(0, "%s\n", version);
+    devclass_register(&pcmcia_socket_class);
     if (do_apm)
 	pm_register(PM_SYS_DEV, PM_SYS_PCMCIA, handle_pm_event);
 #ifdef CONFIG_PROC_FS
     proc_pccard = proc_mkdir("pccard", proc_bus);
 #endif
+
     return 0;
 }
 
@@ -2439,9 +2452,10 @@
     if (do_apm)
 	pm_unregister_all(handle_pm_event);
     release_resource_db();
+    devclass_unregister(&pcmcia_socket_class);
 }
 
-module_init(init_pcmcia_cs);
+subsys_initcall(init_pcmcia_cs);
 module_exit(exit_pcmcia_cs);
 
 /*====================================================================*/
diff -Nru a/drivers/pcmcia/hd64465_ss.c b/drivers/pcmcia/hd64465_ss.c
--- a/drivers/pcmcia/hd64465_ss.c	Mon Feb 17 14:57:27 2003
+++ b/drivers/pcmcia/hd64465_ss.c	Mon Feb 17 14:57:27 2003
@@ -38,6 +38,7 @@
 #include <asm/errno.h>
 #include <linux/irq.h>
 #include <linux/workqueue.h>
+#include <linux/device.h>
 
 #include <asm/io.h>
 #include <asm/hd64465.h>
@@ -960,6 +961,10 @@
 	
 	hs_reset_socket(sp, 1);
 
+	printk(KERN_INFO "HD64465 PCMCIA bridge socket %d at 0x%08lx irq %d io window %ldK@0x%08lx\n",
+	    	i, sp->mem_base, sp->irq,
+		sp->io_vma->size>>10, (unsigned long)sp->io_vma->addr);
+
     	return 0;
 }
 
@@ -990,6 +995,24 @@
 	    vfree(sp->io_vma->addr);
 }
 
+static struct pcmcia_socket_class_data hd64465_data = {
+	.nsock = HS_MAX_SOCKETS,
+	.ops = &hs_operations,
+};
+
+static struct device_driver hd64465_driver = {
+	.name = "hd64465-pcmcia",
+	.bus = &platform_bus_type,
+	.devclass = &pcmcia_socket_class,
+};
+
+static struct platform_device hd64465_device = {
+	.name = "hd64465-pcmcia",
+	.id = 0,
+	.dev = {
+		.name = "hd64465-pcmcia",
+	},
+};
 
 static int __init init_hs(void)
 {
@@ -1007,6 +1030,7 @@
 	}
 
 /*	hd64465_io_debug = 1; */
+	register_driver(&hd64465_driver);
 	
 	/* Wake both sockets out of STANDBY mode */
 	/* TODO: wait 15ms */
@@ -1036,34 +1060,24 @@
 	    HD64465_IRQ_PCMCIA0,
 	    HD64465_PCC0_BASE,
 	    HD64465_REG_PCC0ISR);
-	if (i < 0)
-	    return i;
+	if (i < 0) {
+		unregister_driver(&hd64465_driver);
+		return i;
+	}
 	i = hs_init_socket(&hs_sockets[1],
 	    HD64465_IRQ_PCMCIA1,
 	    HD64465_PCC1_BASE,
 	    HD64465_REG_PCC1ISR);
-	if (i < 0)
-	    return i;
-
-/*	hd64465_io_debug = 0; */
-	    
-
-	if (register_ss_entry(HS_MAX_SOCKETS, &hs_operations) != 0) {
-	    for (i=0 ; i<HS_MAX_SOCKETS ; i++)
-		hs_exit_socket(&hs_sockets[i]);
-    	    return -ENODEV;
+	if (i < 0) {
+		unregister_driver(&hd64465_driver);
+		return i;
 	}
 
-	printk(KERN_INFO "HD64465 PCMCIA bridge:\n");
-	for (i=0 ; i<HS_MAX_SOCKETS ; i++) {
-	    hs_socket_t *sp = &hs_sockets[i];
-	    
-	    printk(KERN_INFO "  socket %d at 0x%08lx irq %d io window %ldK@0x%08lx\n",
-	    	i, sp->mem_base, sp->irq,
-		sp->io_vma->size>>10, (unsigned long)sp->io_vma->addr);
-	}
+/*	hd64465_io_debug = 0; */
+	platform_device_register(&hd64465_device);
+	hd64465_device.dev.class_data = &hd64465_data;
 
-    	return 0;
+	return 0;
 }
 
 static void __exit exit_hs(void)
@@ -1078,9 +1092,10 @@
 	 */
 	for (i=0 ; i<HS_MAX_SOCKETS ; i++)
 	    hs_exit_socket(&hs_sockets[i]);
-	unregister_ss_entry(&hs_operations);
+	platform_device_unregister(&hd64465_device);
 	
 	restore_flags(flags);
+	unregister_driver(&hd64465_driver);
 }
 
 module_init(init_hs);
diff -Nru a/drivers/pcmcia/i82092.c b/drivers/pcmcia/i82092.c
--- a/drivers/pcmcia/i82092.c	Mon Feb 17 14:57:28 2003
+++ b/drivers/pcmcia/i82092.c	Mon Feb 17 14:57:28 2003
@@ -16,6 +16,7 @@
 #include <linux/init.h>
 #include <linux/workqueue.h>
 #include <linux/interrupt.h>
+#include <linux/device.h>
 
 #include <pcmcia/cs_types.h>
 #include <pcmcia/ss.h>
@@ -46,6 +47,9 @@
 	.id_table       = i82092aa_pci_ids,
 	.probe          = i82092aa_pci_probe,
 	.remove         = __devexit_p(i82092aa_pci_remove),
+	.driver		= {
+		.devclass = &pcmcia_socket_class,
+	},
 };
 
 
@@ -93,6 +97,7 @@
 {
 	unsigned char configbyte;
 	int i, ret;
+	struct pcmcia_socket_class_data *cls_d;
 	
 	enter("i82092aa_pci_probe");
 	
@@ -150,11 +155,17 @@
 		printk(KERN_ERR "i82092aa: Failed to register IRQ %d, aborting\n", dev->irq);
 		goto err_out_free_res;
 	}
-		 
-	if ((ret = register_ss_entry(socket_count, &i82092aa_operations) != 0)) {
-		printk(KERN_ERR "i82092aa: register_ss_entry() failed\n");
+
+	
+	cls_d = kmalloc(sizeof(*cls_d), GFP_KERNEL);
+	if (!cls_d) {
+		printk(KERN_ERR "i82092aa: kmalloc failed\n");
 		goto err_out_free_irq;
 	}
+	memset(cls_d, 0, sizeof(*cls_d));
+	cls_d->nsock = socket_count;
+	cls_d->ops = &i82092aa_operations;
+	dev->dev.class_data = cls_d;
 
 	leave("i82092aa_pci_probe");
 	return 0;
@@ -173,6 +184,8 @@
 	enter("i82092aa_pci_remove");
 	
 	free_irq(dev->irq, i82092aa_interrupt);
+	if (dev->dev.class_data)
+		kfree(dev->dev.class_data);
 
 	leave("i82092aa_pci_remove");
 }
@@ -903,7 +916,6 @@
 {
 	enter("i82092aa_module_exit");
 	pci_unregister_driver(&i82092aa_pci_drv);
-	unregister_ss_entry(&i82092aa_operations);
 	if (sockets[0].io_base>0)
 			 release_region(sockets[0].io_base, 2);
 	leave("i82092aa_module_exit");
diff -Nru a/drivers/pcmcia/i82365.c b/drivers/pcmcia/i82365.c
--- a/drivers/pcmcia/i82365.c	Mon Feb 17 14:57:28 2003
+++ b/drivers/pcmcia/i82365.c	Mon Feb 17 14:57:28 2003
@@ -48,6 +48,7 @@
 #include <linux/proc_fs.h>
 #include <linux/workqueue.h>
 #include <linux/interrupt.h>
+#include <linux/device.h>
 #include <asm/irq.h>
 #include <asm/io.h>
 #include <asm/bitops.h>
@@ -1583,6 +1584,24 @@
 
 /*====================================================================*/
 
+static struct pcmcia_socket_class_data i82365_data = {
+	.ops = &pcic_operations,
+};
+
+static struct device_driver i82365_driver = {
+	.name = "i82365",
+	.bus = &platform_bus_type,
+	.devclass = &pcmcia_socket_class,
+};
+
+static struct platform_device i82365_device = {
+	.name = "i82365",
+	.id = 0,
+	.dev = {
+		.name = "i82365",
+	},
+};
+
 static int __init init_i82365(void)
 {
     servinfo_t serv;
@@ -1595,6 +1614,7 @@
     DEBUG(0, "%s\n", version);
     printk(KERN_INFO "Intel PCIC probe: ");
     sockets = 0;
+    driver_register(&i82365_driver);
 
 #ifdef CONFIG_ISA
     isa_probe();
@@ -1602,6 +1622,7 @@
 
     if (sockets == 0) {
 	printk("not found.\n");
+	driver_unregister(&i82365_driver);
 	return -ENODEV;
     }
 
@@ -1611,9 +1632,11 @@
 	request_irq(cs_irq, pcic_interrupt, 0, "i82365", pcic_interrupt);
 #endif
     
-    if (register_ss_entry(sockets, &pcic_operations) != 0)
-	printk(KERN_NOTICE "i82365: register_ss_entry() failed\n");
+    platform_device_register(&i82365_device);
 
+    i82365_data.nsock = sockets;
+    i82365_device.dev.class_data = &i82365_data;
+    
     /* Finally, schedule a polling interrupt */
     if (poll_interval != 0) {
 	poll_timer.function = pcic_interrupt_wrapper;
@@ -1633,7 +1656,7 @@
 #ifdef CONFIG_PROC_FS
     for (i = 0; i < sockets; i++) pcic_proc_remove(i);
 #endif
-    unregister_ss_entry(&pcic_operations);
+    platform_device_unregister(&i82365_device);
     if (poll_interval != 0)
 	del_timer_sync(&poll_timer);
 #ifdef CONFIG_ISA
@@ -1649,6 +1672,7 @@
     if (i82365_pnpdev)
     		pnp_disable_dev(i82365_pnpdev);
 #endif
+    driver_unregister(&i82365_driver);
 } /* exit_i82365 */
 
 module_init(init_i82365);
diff -Nru a/drivers/pcmcia/pci_socket.c b/drivers/pcmcia/pci_socket.c
--- a/drivers/pcmcia/pci_socket.c	Mon Feb 17 14:57:28 2003
+++ b/drivers/pcmcia/pci_socket.c	Mon Feb 17 14:57:28 2003
@@ -22,6 +22,7 @@
 #include <linux/sched.h>
 #include <linux/workqueue.h>
 #include <linux/interrupt.h>
+#include <linux/device.h>
 
 #include <pcmcia/ss.h>
 
@@ -30,9 +31,6 @@
 #include "pci_socket.h"
 
 
-extern struct socket_info_t *pcmcia_register_socket (int slot,
-		struct pccard_operations *vtable, int use_bus_pm);
-extern void pcmcia_unregister_socket (struct socket_info_t *socket);
 extern void pcmcia_suspend_socket (struct socket_info_t *socket);
 extern void pcmcia_resume_socket (struct socket_info_t *socket);
 
@@ -189,11 +187,21 @@
 	return err;
 }
 
-void cardbus_register(pci_socket_t *socket)
+int cardbus_register(struct pci_dev *p_dev)
 {
-	int nr = socket - pci_socket_array;
+	pci_socket_t *socket = pci_get_drvdata(p_dev);
+	struct pcmcia_socket_class_data *cls_d;
 
-	socket->pcmcia_socket = pcmcia_register_socket(nr, &pci_socket_operations, 1);
+	if (!socket)
+		return -EINVAL;
+
+	cls_d = &socket->cls_d;
+	cls_d->nsock = 1; /* yenta is 1, no other low-level driver uses
+			     this yet */
+	cls_d->ops = &pci_socket_operations;
+	cls_d->use_bus_pm = 1;
+	p_dev->dev.class_data = cls_d;
+	return 0;
 }
 
 static int __devinit
@@ -213,7 +221,7 @@
 {
 	pci_socket_t *socket = pci_get_drvdata(dev);
 
-	pcmcia_unregister_socket (socket->pcmcia_socket);
+	/* note: we are already unregistered from the cs core */
 	if (socket->op && socket->op->close)
 		socket->op->close(socket);
 	pci_set_drvdata(dev, NULL);
@@ -253,11 +261,14 @@
 	.remove		= __devexit_p(cardbus_remove),
 	.suspend	= cardbus_suspend,
 	.resume		= cardbus_resume,
+	.driver		= {
+		.devclass = &pcmcia_socket_class,
+	},
 };
 
 static int __init pci_socket_init(void)
 {
-	return pci_module_init (&pci_cardbus_driver);
+	return pci_register_driver (&pci_cardbus_driver);
 }
 
 static void __exit pci_socket_exit (void)
diff -Nru a/drivers/pcmcia/pci_socket.h b/drivers/pcmcia/pci_socket.h
--- a/drivers/pcmcia/pci_socket.h	Mon Feb 17 14:57:27 2003
+++ b/drivers/pcmcia/pci_socket.h	Mon Feb 17 14:57:27 2003
@@ -24,6 +24,7 @@
 	struct work_struct tq_task;
 	struct timer_list poll_timer;
 
+	struct pcmcia_socket_class_data cls_d;
 	/* A few words of private data for the low-level driver.. */
 	unsigned int private[8];
 } pci_socket_t;
diff -Nru a/drivers/pcmcia/tcic.c b/drivers/pcmcia/tcic.c
--- a/drivers/pcmcia/tcic.c	Mon Feb 17 14:57:27 2003
+++ b/drivers/pcmcia/tcic.c	Mon Feb 17 14:57:27 2003
@@ -44,6 +44,7 @@
 #include <linux/delay.h>
 #include <linux/proc_fs.h>
 #include <linux/workqueue.h>
+#include <linux/device.h>
 
 #include <asm/io.h>
 #include <asm/bitops.h>
@@ -375,6 +376,24 @@
 
 /*====================================================================*/
 
+static struct pcmcia_socket_class_data tcic_data = {
+	.ops = &tcic_operations,
+};
+
+static struct device_driver tcic_driver = {
+	.name = "tcic-pcmcia",
+	.bus = &platform_bus_type,
+	.devclass = &pcmcia_socket_class,
+};
+
+static struct platform_device tcic_device = {
+	.name = "tcic-pcmcia",
+	.id = 0,
+	.dev = {
+		.name = "tcic-pcmcia",
+	},
+};
+
 static int __init init_tcic(void)
 {
     int i, sock;
@@ -388,12 +407,15 @@
 	       "does not match!\n");
 	return -1;
     }
+
+    driver_register(&tcic_driver);
     
     printk(KERN_INFO "Databook TCIC-2 PCMCIA probe: ");
     sock = 0;
 
     if (!request_region(tcic_base, 16, "tcic-2")) {
 	printk("could not allocate ports,\n ");
+	driver_unregister(&tcic_driver);
 	return -ENODEV;
     }
     else {
@@ -416,6 +438,7 @@
     if (sock == 0) {
 	printk("not found.\n");
 	release_region(tcic_base, 16);
+	driver_unregister(&tcic_driver);
 	return -ENODEV;
     }
 
@@ -429,6 +452,8 @@
 	sockets++;
     }
 
+    platform_device_register(&tcic_device);
+
     switch (socket_table[0].id) {
     case TCIC_ID_DB86082:
 	printk("DB86082"); break;
@@ -499,13 +524,8 @@
     /* jump start interrupt handler, if needed */
     tcic_interrupt(0, NULL, NULL);
 
-    if (register_ss_entry(sockets, &tcic_operations) != 0) {
-	printk(KERN_NOTICE "tcic: register_ss_entry() failed\n");
-	release_region(tcic_base, 16);
-	if (cs_irq != 0)
-	    free_irq(cs_irq, tcic_interrupt);
-	return -ENODEV;
-    }
+    tcic_data.nsock = sockets;
+    tcic_device.dev.class_data = &tcic_data;
 
     return 0;
     
@@ -515,13 +535,14 @@
 
 static void __exit exit_tcic(void)
 {
-    unregister_ss_entry(&tcic_operations);
     del_timer_sync(&poll_timer);
     if (cs_irq != 0) {
 	tcic_aux_setw(TCIC_AUX_SYSCFG, TCIC_SYSCFG_AUTOBUSY|0x0a00);
 	free_irq(cs_irq, tcic_interrupt);
     }
     release_region(tcic_base, 16);
+    platform_device_unregister(&tcic_device);
+    driver_unregister(&tcic_driver);
 } /* exit_tcic */
 
 /*====================================================================*/
diff -Nru a/drivers/pcmcia/yenta.c b/drivers/pcmcia/yenta.c
--- a/drivers/pcmcia/yenta.c	Mon Feb 17 14:57:27 2003
+++ b/drivers/pcmcia/yenta.c	Mon Feb 17 14:57:27 2003
@@ -577,39 +577,6 @@
 	printk("Yenta IRQ list %04x, PCI irq%d\n", socket->cap.irq_mask, socket->cb_irq);
 }
 
-extern void cardbus_register(pci_socket_t *socket);
-
-/*
- * 'Bottom half' for the yenta_open routine. Allocate the interrupt line
- *  and register the socket with the upper layers.
- */
-static void yenta_open_bh(void * data)
-{
-	pci_socket_t * socket = (pci_socket_t *) data;
-
-	/* It's OK to overwrite this now */
-	INIT_WORK(&socket->tq_task, yenta_bh, socket);
-
-	if (!socket->cb_irq || request_irq(socket->cb_irq, yenta_interrupt, SA_SHIRQ, socket->dev->dev.name, socket)) {
-		/* No IRQ or request_irq failed. Poll */
-		socket->cb_irq = 0; /* But zero is a valid IRQ number. */
-		init_timer(&socket->poll_timer);
-		socket->poll_timer.function = yenta_interrupt_wrapper;
-		socket->poll_timer.data = (unsigned long)socket;
-		socket->poll_timer.expires = jiffies + HZ;
-		add_timer(&socket->poll_timer);
-	}
-
-	/* Figure out what the dang thing can do for the PCMCIA layer... */
-	yenta_get_socket_capabilities(socket, isa_interrupts);
-	printk("Socket status: %08x\n", cb_readl(socket, CB_SOCKET_STATE));
-
-	/* Register it with the pcmcia layer.. */
-	cardbus_register(socket);
-
-	MOD_DEC_USE_COUNT;
-}
-
 static void yenta_clear_maps(pci_socket_t *socket)
 {
 	int i;
@@ -881,6 +848,9 @@
 
 #define NR_OVERRIDES (sizeof(cardbus_override)/sizeof(struct cardbus_override_struct))
 
+
+extern int cardbus_register(struct pci_dev *p_dev);
+
 /*
  * Initialize a cardbus controller. Make sure we have a usable
  * interrupt, and that we can map the cardbus area. Fill in the
@@ -932,16 +902,26 @@
 		}
 	}
 
-	/* Get the PCMCIA kernel thread to complete the
-	   initialisation later. We can't do this here,
-	   because, er, because Linus says so :)
-	*/
-	INIT_WORK(&socket->tq_task, yenta_open_bh, socket);
+	/* We must finish initialization here */
 
-	MOD_INC_USE_COUNT;
-	schedule_work(&socket->tq_task);
+	INIT_WORK(&socket->tq_task, yenta_bh, socket);
 
-	return 0;
+	if (!socket->cb_irq || request_irq(socket->cb_irq, yenta_interrupt, SA_SHIRQ, socket->dev->dev.name, socket)) {
+		/* No IRQ or request_irq failed. Poll */
+		socket->cb_irq = 0; /* But zero is a valid IRQ number. */
+		init_timer(&socket->poll_timer);
+		socket->poll_timer.function = yenta_interrupt_wrapper;
+		socket->poll_timer.data = (unsigned long)socket;
+		socket->poll_timer.expires = jiffies + HZ;
+		add_timer(&socket->poll_timer);
+	}
+
+	/* Figure out what the dang thing can do for the PCMCIA layer... */
+	yenta_get_socket_capabilities(socket, isa_interrupts);
+	printk("Socket status: %08x\n", cb_readl(socket, CB_SOCKET_STATE));
+
+	/* Register it with the pcmcia layer.. */
+	return cardbus_register(dev);
 }
 
 /*
diff -Nru a/drivers/pnp/pnpbios/core.c b/drivers/pnp/pnpbios/core.c
--- a/drivers/pnp/pnpbios/core.c	Mon Feb 17 14:57:26 2003
+++ b/drivers/pnp/pnpbios/core.c	Mon Feb 17 14:57:26 2003
@@ -602,7 +602,7 @@
 		info->location_id, info->serial, info->capabilities);
 	envp[i] = 0;
 	
-	value = call_usermodehelper (argv [0], argv, envp);
+	value = call_usermodehelper (argv [0], argv, envp, 0);
 	kfree (buf);
 	kfree (envp);
 	return 0;
diff -Nru a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c
--- a/drivers/s390/block/dasd_eckd.c	Mon Feb 17 14:57:26 2003
+++ b/drivers/s390/block/dasd_eckd.c	Mon Feb 17 14:57:26 2003
@@ -1195,7 +1195,7 @@
 	rc = dasd_sleep_on_immediatly(cqr);
 
 	if (rc == -EIO) {
-		/* Request got an eror or has been timed out. */
+		/* Request got an error or has been timed out. */
 		dasd_eckd_release(bdev, no, args);
 	}
 	dasd_kfree_request(cqr, cqr->device);
@@ -1238,7 +1238,7 @@
 	rc = dasd_sleep_on_immediatly(cqr);
 
 	if (rc == -EIO) {
-		/* Request got an eror or has been timed out. */
+		/* Request got an error or has been timed out. */
 		dasd_eckd_release(bdev, no, args);
 	}
 	dasd_kfree_request(cqr, cqr->device);
diff -Nru a/drivers/scsi/NCR53C9x.c b/drivers/scsi/NCR53C9x.c
--- a/drivers/scsi/NCR53C9x.c	Mon Feb 17 14:57:27 2003
+++ b/drivers/scsi/NCR53C9x.c	Mon Feb 17 14:57:27 2003
@@ -356,7 +356,7 @@
 	Scsi_Cmnd *ptr, *prev;
 
 	for(ptr = *SC, prev = NULL;
-	    ptr && ((ptr->target != target) || (ptr->lun != lun));
+	    ptr && ((ptr->device->id != target) || (ptr->device->lun != lun));
 	    prev = ptr, ptr = (Scsi_Cmnd *) ptr->host_scribble)
 		;
 	if(ptr) {
@@ -946,7 +946,7 @@
 
 static void esp_restore_pointers(struct NCR_ESP *esp, Scsi_Cmnd *sp)
 {
-	struct esp_pointers *ep = &esp->data_pointers[sp->target];
+	struct esp_pointers *ep = &esp->data_pointers[sp->device->id];
 
 	sp->SCp.ptr = ep->saved_ptr;
 	sp->SCp.buffer = ep->saved_buffer;
@@ -956,7 +956,7 @@
 
 static void esp_save_pointers(struct NCR_ESP *esp, Scsi_Cmnd *sp)
 {
-	struct esp_pointers *ep = &esp->data_pointers[sp->target];
+	struct esp_pointers *ep = &esp->data_pointers[sp->device->id];
 
 	ep->saved_ptr = sp->SCp.ptr;
 	ep->saved_buffer = sp->SCp.buffer;
@@ -1037,8 +1037,8 @@
 
 	SDptr = SCptr->device;
 	esp_dev = SDptr->hostdata;
-	lun = SCptr->lun;
-	target = SCptr->target;
+	lun = SCptr->device->lun;
+	target = SCptr->device->id;
 
 	esp->snip = 0;
 	esp->msgout_len = 0;
@@ -1249,7 +1249,7 @@
 	SCpnt->scsi_done = done;
 	SCpnt->SCp.phase = not_issued;
 
-	esp = (struct NCR_ESP *) SCpnt->host->hostdata;
+	esp = (struct NCR_ESP *) SCpnt->device->host->hostdata;
 
 	if(esp->dma_led_on)
 		esp->dma_led_on(esp);
@@ -1285,7 +1285,7 @@
 int esp_command(Scsi_Cmnd *SCpnt)
 {
 #ifdef DEBUG_ESP
-	struct NCR_ESP *esp = (struct NCR_ESP *) SCpnt->host->hostdata;
+	struct NCR_ESP *esp = (struct NCR_ESP *) SCpnt->device->host->hostdata;
 #endif
 
 	ESPLOG(("esp%d: esp_command() called...\n", esp->esp_id));
@@ -1297,7 +1297,7 @@
 {
 	ESPLOG(("[tgt<%02x> lun<%02x> "
 		"pphase<%s> cphase<%s>]",
-		SCptr->target, SCptr->lun,
+		SCptr->device->id, SCptr->device->lun,
 		phase_string(SCptr->SCp.sent_command),
 		phase_string(SCptr->SCp.phase)));
 }
@@ -1358,7 +1358,7 @@
 /* Abort a command.  The host_lock is acquired by caller. */
 int esp_abort(Scsi_Cmnd *SCptr)
 {
-	struct NCR_ESP *esp = (struct NCR_ESP *) SCptr->host->hostdata;
+	struct NCR_ESP *esp = (struct NCR_ESP *) SCptr->device->host->hostdata;
 	struct ESP_regs *eregs = esp->eregs;
 	int don;
 
@@ -1486,7 +1486,7 @@
  */
 int esp_reset(Scsi_Cmnd *SCptr)
 {
-	struct NCR_ESP *esp = (struct NCR_ESP *) SCptr->host->hostdata;
+	struct NCR_ESP *esp = (struct NCR_ESP *) SCptr->device->host->hostdata;
 
 	(void) esp_do_resetbus(esp, esp->eregs);
 
@@ -1716,13 +1716,13 @@
 	if(esp->prev_soff  != esp_dev->sync_max_offset ||
 	   esp->prev_stp   != esp_dev->sync_min_period ||
 	   (esp->erev > esp100a &&
-	    esp->prev_cfg3 != esp->config3[sp->target])) {
+	    esp->prev_cfg3 != esp->config3[sp->device->id])) {
 		esp->prev_soff = esp_dev->sync_max_offset;
 		esp_write(eregs->esp_soff, esp->prev_soff);
 		esp->prev_stp = esp_dev->sync_min_period;
 		esp_write(eregs->esp_stp, esp->prev_stp);
 		if(esp->erev > esp100a) {
-			esp->prev_cfg3 = esp->config3[sp->target];
+			esp->prev_cfg3 = esp->config3[sp->device->id];
 			esp_write(eregs->esp_cfg3, esp->prev_cfg3);
 		} 
 	}
@@ -2117,7 +2117,7 @@
 			esp->esp_id,
 			SCptr->use_sg, SCptr->SCp.ptr, SCptr->SCp.this_residual));
 		ESPLOG(("esp%d: Forcing async for target %d\n", esp->esp_id, 
-			SCptr->target));
+			SCptr->device->id));
 		SCptr->device->borken = 1;
 		esp_dev->sync = 0;
 		bytes_sent = 0;
@@ -2225,7 +2225,7 @@
 
 		if(SCptr->SCp.Status != GOOD &&
 		   SCptr->SCp.Status != CONDITION_GOOD &&
-		   ((1<<SCptr->target) & esp->targets_present) &&
+		   ((1<<SCptr->device->id) & esp->targets_present) &&
 		   esp_dev->sync && esp_dev->sync_max_offset) {
 			/* SCSI standard says that the synchronous capabilities
 			 * should be renegotiated at this point.  Most likely
@@ -2283,21 +2283,21 @@
 	sp = esp->issue_SC;
 	ESPLOG(("esp%d: issue_SC[", esp->esp_id));
 	while(sp) {
-		ESPLOG(("<%02x,%02x>", sp->target, sp->lun));
+		ESPLOG(("<%02x,%02x>", sp->device->id, sp->device->lun));
 		sp = (Scsi_Cmnd *) sp->host_scribble;
 	}
 	ESPLOG(("]\n"));
 	sp = esp->current_SC;
 	ESPLOG(("esp%d: current_SC[", esp->esp_id));
 	while(sp) {
-		ESPLOG(("<%02x,%02x>", sp->target, sp->lun));
+		ESPLOG(("<%02x,%02x>", sp->device->id, sp->device->lun));
 		sp = (Scsi_Cmnd *) sp->host_scribble;
 	}
 	ESPLOG(("]\n"));
 	sp = esp->disconnected_SC;
 	ESPLOG(("esp%d: disconnected_SC[", esp->esp_id));
 	while(sp) {
-		ESPLOG(("<%02x,%02x>", sp->target, sp->lun));
+		ESPLOG(("<%02x,%02x>", sp->device->id, sp->device->lun));
 		sp = (Scsi_Cmnd *) sp->host_scribble;
 	}
 	ESPLOG(("]\n"));
@@ -2617,7 +2617,7 @@
 	 */
 	if(esp->ireg == (ESP_INTR_FDONE | ESP_INTR_BSERV)) {
 		/* target speaks... */
-		esp->targets_present |= (1<<SCptr->target);
+		esp->targets_present |= (1<<SCptr->device->id);
 
 		/* What if the target ignores the sdtr? */
 		if(esp->snip)
@@ -2646,7 +2646,7 @@
 			 * XXX for synchronous transfers.
 			 */
 			ESPLOG(("esp%d: STEP_ASEL for tgt %d\n",
-				esp->esp_id, SCptr->target));
+				esp->esp_id, SCptr->device->id));
 
 		case ESP_STEP_SID:
 			/* Arbitration won, target selected, went
@@ -2763,14 +2763,14 @@
 		if(esp->disconnected_SC)
 			esp_cmd(esp, eregs, ESP_CMD_ESEL);
 
-		if(((1<<SCptr->target) & esp->targets_present) &&
+		if(((1<<SCptr->device->id) & esp->targets_present) &&
 		   esp->seqreg && esp->cur_msgout[0] == EXTENDED_MESSAGE &&
 		   (SCptr->SCp.phase == in_slct_msg ||
 		    SCptr->SCp.phase == in_slct_stop)) {
 			/* shit */
 			esp->snip = 0;
 			ESPLOG(("esp%d: Failed synchronous negotiation for target %d "
-				"lun %d\n", esp->esp_id, SCptr->target, SCptr->lun));
+				"lun %d\n", esp->esp_id, SCptr->device->id, SCptr->device->lun));
 			esp_dev->sync_max_offset = 0;
 			esp_dev->sync_min_period = 0;
 			esp_dev->sync = 1; /* so we don't negotiate again */
@@ -2796,9 +2796,9 @@
 		 * or whenever when we are scanning the bus for targets.
 		 * But first make sure that is really what is happening.
 		 */
-		if(((1<<SCptr->target) & esp->targets_present)) {
+		if(((1<<SCptr->device->id) & esp->targets_present)) {
 			ESPLOG(("esp%d: Warning, live target %d not responding to "
-				"selection.\n", esp->esp_id, SCptr->target));
+				"selection.\n", esp->esp_id, SCptr->device->id));
 
 			/* This _CAN_ happen.  The SCSI standard states that
 			 * the target is to _not_ respond to selection if
@@ -2892,7 +2892,7 @@
 
 	case NOP:
 		ESPLOG(("esp%d: target %d sends a nop\n", esp->esp_id,
-			esp->current_SC->target));
+			esp->current_SC->device->id));
 		return 0;
 
 	case RESTORE_POINTERS:
@@ -2985,7 +2985,7 @@
 		 * sibling call optimization.  -DaveM
 		 */
 		ESPLOG((KERN_INFO "esp%d: target %d ",
-			esp->esp_id, esp->current_SC->target));
+			esp->esp_id, esp->current_SC->device->id));
 		ESPLOG(("[period %dns offset %d %d.%02dMHz ",
 			(int) msg3 * 4, (int) msg4,
 			integer, fraction));
@@ -2993,7 +2993,7 @@
 			(((msg3 * 4) < 200) ? "-II" : "")));
 	} else {
 		ESPLOG((KERN_INFO "esp%d: target %d asynchronous\n",
-			esp->esp_id, esp->current_SC->target));
+			esp->esp_id, esp->current_SC->device->id));
 	}
 }
 
@@ -3070,10 +3070,10 @@
 				else
 					bit = ESP_CONFIG3_FSCSI;
 				if(period < 50)
-					esp->config3[SCptr->target] |= bit;
+					esp->config3[SCptr->device->id] |= bit;
 				else
-					esp->config3[SCptr->target] &= ~bit;
-				esp->prev_cfg3 = esp->config3[SCptr->target];
+					esp->config3[SCptr->device->id] &= ~bit;
+				esp->prev_cfg3 = esp->config3[SCptr->device->id];
 				esp_write(eregs->esp_cfg3, esp->prev_cfg3);
 			}
 			esp->prev_soff = esp_dev->sync_min_period;
@@ -3103,8 +3103,8 @@
 					bit = ESP_CONFIG3_FAST;
 				else
 					bit = ESP_CONFIG3_FSCSI;
-				esp->config3[SCptr->target] &= ~bit;
-				esp->prev_cfg3 = esp->config3[SCptr->target];
+				esp->config3[SCptr->device->id] &= ~bit;
+				esp->prev_cfg3 = esp->config3[SCptr->device->id];
 				esp_write(eregs->esp_cfg3, esp->prev_cfg3);
 			}
 		}
@@ -3493,7 +3493,7 @@
 			 * a nexus is alive on the bus.
 			 */
 			ESPLOG(("esp%d: Forcing async and disabling disconnect for "
-				"target %d\n", esp->esp_id, SCptr->target));
+				"target %d\n", esp->esp_id, SCptr->device->id));
 			SCptr->device->borken = 1; /* foo on you */
 		}
 
diff -Nru a/drivers/scsi/aha1542.c b/drivers/scsi/aha1542.c
--- a/drivers/scsi/aha1542.c	Mon Feb 17 14:57:27 2003
+++ b/drivers/scsi/aha1542.c	Mon Feb 17 14:57:27 2003
@@ -40,6 +40,7 @@
 #include <linux/isapnp.h>
 #include <linux/blk.h>
 #include <linux/mca.h>
+#include <linux/mca-legacy.h>
 
 #include <asm/dma.h>
 #include <asm/system.h>
@@ -597,8 +598,8 @@
 	unchar ahacmd = CMD_START_SCSI;
 	unchar direction;
 	unchar *cmd = (unchar *) SCpnt->cmnd;
-	unchar target = SCpnt->target;
-	unchar lun = SCpnt->lun;
+	unchar target = SCpnt->device->id;
+	unchar lun = SCpnt->device->lun;
 	unsigned long flags;
 	void *buff = SCpnt->request_buffer;
 	int bufflen = SCpnt->request_bufflen;
@@ -608,8 +609,8 @@
 
 	DEB(int i);
 
-	mb = HOSTDATA(SCpnt->host)->mb;
-	ccb = HOSTDATA(SCpnt->host)->ccb;
+	mb = HOSTDATA(SCpnt->device->host)->mb;
+	ccb = HOSTDATA(SCpnt->device->host)->ccb;
 
 	DEB(if (target > 1) {
 	    SCpnt->result = DID_TIME_OUT << 16;
@@ -653,25 +654,25 @@
 	   is how the host adapter will scan for them */
 
 	spin_lock_irqsave(&aha1542_lock, flags);
-	mbo = HOSTDATA(SCpnt->host)->aha1542_last_mbo_used + 1;
+	mbo = HOSTDATA(SCpnt->device->host)->aha1542_last_mbo_used + 1;
 	if (mbo >= AHA1542_MAILBOXES)
 		mbo = 0;
 
 	do {
-		if (mb[mbo].status == 0 && HOSTDATA(SCpnt->host)->SCint[mbo] == NULL)
+		if (mb[mbo].status == 0 && HOSTDATA(SCpnt->device->host)->SCint[mbo] == NULL)
 			break;
 		mbo++;
 		if (mbo >= AHA1542_MAILBOXES)
 			mbo = 0;
-	} while (mbo != HOSTDATA(SCpnt->host)->aha1542_last_mbo_used);
+	} while (mbo != HOSTDATA(SCpnt->device->host)->aha1542_last_mbo_used);
 
-	if (mb[mbo].status || HOSTDATA(SCpnt->host)->SCint[mbo])
+	if (mb[mbo].status || HOSTDATA(SCpnt->device->host)->SCint[mbo])
 		panic("Unable to find empty mailbox for aha1542.\n");
 
-	HOSTDATA(SCpnt->host)->SCint[mbo] = SCpnt;	/* This will effectively prevent someone else from
+	HOSTDATA(SCpnt->device->host)->SCint[mbo] = SCpnt;	/* This will effectively prevent someone else from
 							   screwing with this cdb. */
 
-	HOSTDATA(SCpnt->host)->aha1542_last_mbo_used = mbo;
+	HOSTDATA(SCpnt->device->host)->aha1542_last_mbo_used = mbo;
 	spin_unlock_irqrestore(&aha1542_lock, flags);
 
 #ifdef DEBUG
@@ -762,7 +763,7 @@
 		    aha1542_stat());
 		SCpnt->scsi_done = done;
 		mb[mbo].status = 1;
-		aha1542_out(SCpnt->host->io_port, &ahacmd, 1);	/* start scsi command */
+		aha1542_out(SCpnt->device->host->io_port, &ahacmd, 1);	/* start scsi command */
 		DEB(aha1542_stat());
 	} else
 		printk("aha1542_queuecommand: done can't be NULL\n");
@@ -1356,7 +1357,7 @@
 	 */
 
 	printk(KERN_ERR "aha1542.c: Unable to abort command for target %d\n",
-	       SCpnt->target);
+	       SCpnt->device->id);
 	return FAILED;
 }
 
@@ -1368,36 +1369,36 @@
 {
 	unsigned long flags;
 	struct mailbox *mb;
-	unchar target = SCpnt->target;
-	unchar lun = SCpnt->lun;
+	unchar target = SCpnt->device->id;
+	unchar lun = SCpnt->device->lun;
 	int mbo;
 	struct ccb *ccb;
 	unchar ahacmd = CMD_START_SCSI;
 
-	ccb = HOSTDATA(SCpnt->host)->ccb;
-	mb = HOSTDATA(SCpnt->host)->mb;
+	ccb = HOSTDATA(SCpnt->device->host)->ccb;
+	mb = HOSTDATA(SCpnt->device->host)->mb;
 
 	spin_lock_irqsave(&aha1542_lock, flags);
-	mbo = HOSTDATA(SCpnt->host)->aha1542_last_mbo_used + 1;
+	mbo = HOSTDATA(SCpnt->device->host)->aha1542_last_mbo_used + 1;
 	if (mbo >= AHA1542_MAILBOXES)
 		mbo = 0;
 
 	do {
-		if (mb[mbo].status == 0 && HOSTDATA(SCpnt->host)->SCint[mbo] == NULL)
+		if (mb[mbo].status == 0 && HOSTDATA(SCpnt->device->host)->SCint[mbo] == NULL)
 			break;
 		mbo++;
 		if (mbo >= AHA1542_MAILBOXES)
 			mbo = 0;
-	} while (mbo != HOSTDATA(SCpnt->host)->aha1542_last_mbo_used);
+	} while (mbo != HOSTDATA(SCpnt->device->host)->aha1542_last_mbo_used);
 
-	if (mb[mbo].status || HOSTDATA(SCpnt->host)->SCint[mbo])
+	if (mb[mbo].status || HOSTDATA(SCpnt->device->host)->SCint[mbo])
 		panic("Unable to find empty mailbox for aha1542.\n");
 
-	HOSTDATA(SCpnt->host)->SCint[mbo] = SCpnt;	/* This will effectively
+	HOSTDATA(SCpnt->device->host)->SCint[mbo] = SCpnt;	/* This will effectively
 							   prevent someone else from
 							   screwing with this cdb. */
 
-	HOSTDATA(SCpnt->host)->aha1542_last_mbo_used = mbo;
+	HOSTDATA(SCpnt->device->host)->aha1542_last_mbo_used = mbo;
 	spin_unlock_irqrestore(&aha1542_lock, flags);
 
 	any2scsi(mb[mbo].ccbptr, SCSI_BUF_PA(&ccb[mbo]));	/* This gets trashed for some reason */
@@ -1415,9 +1416,9 @@
 	 * Now tell the 1542 to flush all pending commands for this 
 	 * target 
 	 */
-	aha1542_out(SCpnt->host->io_port, &ahacmd, 1);
+	aha1542_out(SCpnt->device->host->io_port, &ahacmd, 1);
 
-	printk(KERN_WARNING "aha1542.c: Trying device reset for target %d\n", SCpnt->target);
+	printk(KERN_WARNING "aha1542.c: Trying device reset for target %d\n", SCpnt->device->id);
 
 	return SUCCESS;
 
@@ -1467,7 +1468,7 @@
 	 * we do this?  Try this first, and we can add that later
 	 * if it turns out to be useful.
 	 */
-	outb(SCRST, CONTROL(SCpnt->host->io_port));
+	outb(SCRST, CONTROL(SCpnt->device->host->io_port));
 
 	/*
 	 * Wait for the thing to settle down a bit.  Unfortunately
@@ -1476,11 +1477,11 @@
 	 * check for timeout, and if we are doing something like this
 	 * we are pretty desperate anyways.
 	 */
-	spin_unlock_irq(SCpnt->host->host_lock);
+	spin_unlock_irq(SCpnt->device->host->host_lock);
 	scsi_sleep(4 * HZ);
-	spin_lock_irq(SCpnt->host->host_lock);
+	spin_lock_irq(SCpnt->device->host->host_lock);
 
-	WAIT(STATUS(SCpnt->host->io_port),
+	WAIT(STATUS(SCpnt->device->host->io_port),
 	     STATMASK, INIT | IDLE, STST | DIAGF | INVDCMD | DF | CDF);
 
 	/*
@@ -1489,12 +1490,12 @@
 	 * out.  We do not try and restart any commands or anything - 
 	 * the strategy handler takes care of that crap.
 	 */
-	printk(KERN_WARNING "Sent BUS RESET to scsi host %d\n", SCpnt->host->host_no);
+	printk(KERN_WARNING "Sent BUS RESET to scsi host %d\n", SCpnt->device->host->host_no);
 
 	for (i = 0; i < AHA1542_MAILBOXES; i++) {
-		if (HOSTDATA(SCpnt->host)->SCint[i] != NULL) {
+		if (HOSTDATA(SCpnt->device->host)->SCint[i] != NULL) {
 			Scsi_Cmnd *SCtmp;
-			SCtmp = HOSTDATA(SCpnt->host)->SCint[i];
+			SCtmp = HOSTDATA(SCpnt->device->host)->SCint[i];
 
 
 			if (SCtmp->device->soft_reset) {
@@ -1510,8 +1511,8 @@
 				kfree(SCtmp->host_scribble);
 				SCtmp->host_scribble = NULL;
 			}
-			HOSTDATA(SCpnt->host)->SCint[i] = NULL;
-			HOSTDATA(SCpnt->host)->mb[i].status = 0;
+			HOSTDATA(SCpnt->device->host)->SCint[i] = NULL;
+			HOSTDATA(SCpnt->device->host)->mb[i].status = 0;
 		}
 	}
 
@@ -1531,7 +1532,7 @@
 	 * we do this?  Try this first, and we can add that later
 	 * if it turns out to be useful.
 	 */
-	outb(HRST | SCRST, CONTROL(SCpnt->host->io_port));
+	outb(HRST | SCRST, CONTROL(SCpnt->device->host->io_port));
 
 	/*
 	 * Wait for the thing to settle down a bit.  Unfortunately
@@ -1540,18 +1541,18 @@
 	 * check for timeout, and if we are doing something like this
 	 * we are pretty desperate anyways.
 	 */
-	spin_unlock_irq(SCpnt->host->host_lock);
+	spin_unlock_irq(SCpnt->device->host->host_lock);
 	scsi_sleep(4 * HZ);
-	spin_lock_irq(SCpnt->host->host_lock);
+	spin_lock_irq(SCpnt->device->host->host_lock);
 
-	WAIT(STATUS(SCpnt->host->io_port),
+	WAIT(STATUS(SCpnt->device->host->io_port),
 	     STATMASK, INIT | IDLE, STST | DIAGF | INVDCMD | DF | CDF);
 
 	/*
 	 * We need to do this too before the 1542 can interact with
 	 * us again.
 	 */
-	setup_mailboxes(SCpnt->host->io_port, SCpnt->host);
+	setup_mailboxes(SCpnt->device->host->io_port, SCpnt->device->host);
 
 	/*
 	 * Now try to pick up the pieces.  For all pending commands,
@@ -1559,12 +1560,12 @@
 	 * out.  We do not try and restart any commands or anything - 
 	 * the strategy handler takes care of that crap.
 	 */
-	printk(KERN_WARNING "Sent BUS RESET to scsi host %d\n", SCpnt->host->host_no);
+	printk(KERN_WARNING "Sent BUS RESET to scsi host %d\n", SCpnt->device->host->host_no);
 
 	for (i = 0; i < AHA1542_MAILBOXES; i++) {
-		if (HOSTDATA(SCpnt->host)->SCint[i] != NULL) {
+		if (HOSTDATA(SCpnt->device->host)->SCint[i] != NULL) {
 			Scsi_Cmnd *SCtmp;
-			SCtmp = HOSTDATA(SCpnt->host)->SCint[i];
+			SCtmp = HOSTDATA(SCpnt->device->host)->SCint[i];
 
 			if (SCtmp->device->soft_reset) {
 				/*
@@ -1579,8 +1580,8 @@
 				kfree(SCtmp->host_scribble);
 				SCtmp->host_scribble = NULL;
 			}
-			HOSTDATA(SCpnt->host)->SCint[i] = NULL;
-			HOSTDATA(SCpnt->host)->mb[i].status = 0;
+			HOSTDATA(SCpnt->device->host)->SCint[i] = NULL;
+			HOSTDATA(SCpnt->device->host)->mb[i].status = 0;
 		}
 	}
 
diff -Nru a/drivers/scsi/aic7xxx/aic79xx.reg b/drivers/scsi/aic7xxx/aic79xx.reg
--- a/drivers/scsi/aic7xxx/aic79xx.reg	Mon Feb 17 14:57:28 2003
+++ b/drivers/scsi/aic7xxx/aic79xx.reg	Mon Feb 17 14:57:28 2003
@@ -3725,7 +3725,7 @@
 
 	/*
 	 * The minimum number of commands still outstanding required
-	 * to continue coalessing (2's compliment of value).
+	 * to continue coalessing (2's complement of value).
 	 */
 	INT_COALESSING_MINCMDS {
 		size		1
diff -Nru a/drivers/scsi/mca_53c9x.c b/drivers/scsi/mca_53c9x.c
--- a/drivers/scsi/mca_53c9x.c	Mon Feb 17 14:57:27 2003
+++ b/drivers/scsi/mca_53c9x.c	Mon Feb 17 14:57:27 2003
@@ -40,6 +40,7 @@
 #include <linux/blk.h>
 #include <linux/proc_fs.h>
 #include <linux/stat.h>
+#include <linux/mca-legacy.h>
 
 #include "scsi.h"
 #include "hosts.h"
diff -Nru a/drivers/usb/image/scanner.c b/drivers/usb/image/scanner.c
--- a/drivers/usb/image/scanner.c	Mon Feb 17 14:57:27 2003
+++ b/drivers/usb/image/scanner.c	Mon Feb 17 14:57:27 2003
@@ -54,7 +54,7 @@
  *      allocation/registration for linux-2.3.22+.
  *    - Adopted David Brownell's <david-b@pacbell.net> technique for 
  *      assigning bulk endpoints.
- *    - Removed unnessesary #include's
+ *    - Removed unnecessary #include's
  *    - Scanner model now reported via syslog INFO after being detected 
  *      *and* configured.
  *    - Added user specified vendor:product USB ID's which can be passed 
diff -Nru a/drivers/video/Kconfig b/drivers/video/Kconfig
--- a/drivers/video/Kconfig	Mon Feb 17 14:57:26 2003
+++ b/drivers/video/Kconfig	Mon Feb 17 14:57:26 2003
@@ -235,7 +235,7 @@
 
 config FB_OF
 	bool "Open Firmware frame buffer device support"
-	depends on FB && PPC && ALL_PPC
+	depends on FB && (PPC64 || (PPC && ALL_PPC))
 	help
 	  Say Y if you want support with Open Firmware for your graphics
 	  board.
diff -Nru a/fs/befs/ChangeLog b/fs/befs/ChangeLog
--- a/fs/befs/ChangeLog	Mon Feb 17 14:57:26 2003
+++ b/fs/befs/ChangeLog	Mon Feb 17 14:57:26 2003
@@ -102,7 +102,7 @@
 	The option is, simply enough, 'debug'. 
 	(super.c, debug.c) [WD]
 
-* Removed notion of btree handle from btree.c. It was unessisary, as the 
+* Removed notion of btree handle from btree.c. It was unnecessary, as the
 	linux VFS doesn't allow us to keep any state between calls. Updated 
 	dir.c, namei.c befs_fs.h to account for it. [WD]
 
@@ -312,9 +312,9 @@
 ==========
 * Fixed a misunderstanding of the inode fields. 
 	This fixed the problmem with wrong file sizes from du and others.
-	The i_blocks field of the inode struct is not the nuber of blocks for the 
+	The i_blocks field of the inode struct is not the number of blocks for the
 	inode, it is the number of blocks for the file.	Also, i_blksize is not
-	nessisarily the size of the inode, although in  practice it works out.
+	necessarily the size of the inode, although in  practice it works out.
 	Changed to blocksize of filesystem.
 	(fs/befs/inode.c)
 
diff -Nru a/fs/befs/btree.c b/fs/befs/btree.c
--- a/fs/befs/btree.c	Mon Feb 17 14:57:26 2003
+++ b/fs/befs/btree.c	Mon Feb 17 14:57:26 2003
@@ -56,9 +56,9 @@
 /* Note:
  * 
  * The book states 2 confusing things about befs b+trees. First, 
- * it states that the overflow feild of node headers is used by internal nodes 
- * to point to another node that "effectivly continues this one". Here is what 
- * I belive that means. Each key in internal nodes points to another node that
+ * it states that the overflow field of node headers is used by internal nodes
+ * to point to another node that "effectively continues this one". Here is what
+ * I believe that means. Each key in internal nodes points to another node that
  * contains key values less than itself. Inspection reveals that the last key 
  * in the internal node is not the last key in the index. Keys that are 
  * greater than the last key in the internal node go into the overflow node. 
@@ -124,7 +124,7 @@
  * @sup: Buffer in which to place the btree superblock
  *
  * Calls befs_read_datastream to read in the btree superblock and
- * makes sure it is in cpu byteorder, byteswapping if nessisary.
+ * makes sure it is in cpu byteorder, byteswapping if necessary.
  *
  * On success, returns BEFS_OK and *@sup contains the btree superblock,
  * in cpu byte order.
@@ -179,8 +179,8 @@
  * @node_off: Starting offset (in bytes) of the node in @ds
  *
  * Calls befs_read_datastream to read in the indicated btree node and
- * makes sure its header feilds are in cpu byteorder, byteswapping if 
- * nessisary.
+ * makes sure its header fields are in cpu byteorder, byteswapping if
+ * necessary.
  * Note: node->bh must be NULL when this function called first
  * time. Don't forget brelse(node->bh) after last call.
  *
diff -Nru a/fs/befs/datastream.c b/fs/befs/datastream.c
--- a/fs/befs/datastream.c	Mon Feb 17 14:57:28 2003
+++ b/fs/befs/datastream.c	Mon Feb 17 14:57:28 2003
@@ -229,7 +229,7 @@
 	
 	Algorithm:
 	Linear search. Checks each element of array[] to see if it
-	contains the blockno-th filesystem block. This is nessisary
+	contains the blockno-th filesystem block. This is necessary
 	because the block runs map variable amounts of data. Simply
 	keeps a count of the number of blocks searched so far (sum),
 	incrementing this by the length of each block run as we come
diff -Nru a/fs/binfmt_aout.c b/fs/binfmt_aout.c
--- a/fs/binfmt_aout.c	Mon Feb 17 14:57:27 2003
+++ b/fs/binfmt_aout.c	Mon Feb 17 14:57:27 2003
@@ -24,6 +24,7 @@
 #include <linux/binfmts.h>
 #include <linux/personality.h>
 #include <linux/init.h>
+#include <linux/ptrace.h>
 
 #include <asm/system.h>
 #include <asm/uaccess.h>
diff -Nru a/fs/buffer.c b/fs/buffer.c
--- a/fs/buffer.c	Mon Feb 17 14:57:27 2003
+++ b/fs/buffer.c	Mon Feb 17 14:57:27 2003
@@ -2484,6 +2484,12 @@
 	/* Is the page fully outside i_size? (truncate in progress) */
 	offset = inode->i_size & (PAGE_CACHE_SIZE-1);
 	if (page->index >= end_index+1 || !offset) {
+		/*
+		 * The page may have dirty, unmapped buffers.  For example,
+		 * they may have been added in ext3_writepage().  Make them
+		 * freeable here, so the page does not leak.
+		 */
+		block_invalidatepage(page, 0);
 		unlock_page(page);
 		return -EIO;
 	}
diff -Nru a/fs/cifs/CHANGES b/fs/cifs/CHANGES
--- a/fs/cifs/CHANGES	Mon Feb 17 14:57:28 2003
+++ b/fs/cifs/CHANGES	Mon Feb 17 14:57:28 2003
@@ -1,3 +1,42 @@
+Version 0.65
+------------
+Finish fixes to commit write for caching/readahead consistency.  fsx 
+now works to Samba servers.  Fix oops caused when readahead
+was interrupted by a signal.
+
+Version 0.64
+------------
+Fix data corruption (in partial page after truncate) that caused fsx to
+fail to Windows servers.  Cleaned up some extraneous error logging in
+common error paths.  Add generic sendfile support.
+
+Version 0.63
+------------
+Fix memory leak in AllocMidQEntry.
+Finish reconnection logic, so connection with server can be dropped
+(or server rebooted) and the cifs client will reconnect.  
+
+Version 0.62
+------------
+Fix temporary socket leak when bad userid or password specified 
+(or other SMBSessSetup failure).  Increase maximum buffer size to slightly
+over 16K to allow negotiation of up to Samba and Windows server default read 
+sizes.  Add support for readpages
+
+Version 0.61
+------------
+Fix oops when username not passed in on mount.  Extensive fixes and improvements
+to error logging (strip redundant newlines, change debug macros to ensure newline
+passed in and to be more consistent).  Fix writepage wrong file handle problem,
+a readonly file handle could be incorrectly used to attempt to write out
+file updates through the page cache to multiply open files.  This could cause
+the iozone benchmark to fail on the fwrite test. Fix bug mounting two different
+shares to the same Windows server when using different usernames
+(doing this to Samba servers worked but Windows was rejecting it) - now it is
+possible to use different userids when connecting to the same server from a
+Linux client. Fix oops when treeDisconnect called during unmount on
+previously freed socket.
+
 Version 0.60
 ------------
 Fix oops in readpages caused by not setting address space operations in inode in 
diff -Nru a/fs/cifs/TODO b/fs/cifs/TODO
--- a/fs/cifs/TODO	Mon Feb 17 14:57:28 2003
+++ b/fs/cifs/TODO	Mon Feb 17 14:57:28 2003
@@ -1,4 +1,4 @@
-version 0.5.3 October 8th, 2002
+version 0.6.5 February 15, 2003
 
 A Partial List of Known Problems and Missing Features
 =====================================================
@@ -7,7 +7,8 @@
 for visible, important contributions to this module.  Here
 is a partial list of the known problems and missing features:
 
-a) Support for SecurityDescriptors for chmod/chgrp/chown
+a) Support for SecurityDescriptors for chmod/chgrp/chown so
+these can be supported for Windows servers
 
 b) Better pam/winbind integration
 
@@ -16,9 +17,9 @@
 
 d) Kerberos/SPNEGO session setup support - (started)
 
-e)NTLMv2 authentication and MD5-HMAC signing of SMB PDUs - (mostly implemented)
+e) NTLMv2 authentication and MD5-HMAC signing SMB PDUs - (mostly implemented)
 
-f) oplock support (ie safe CIFS distributed file caching) is not complete.
+f) oplock support (ie safe CIFS distributed file caching) is not quite complete.
 In addition Directory entry caching relies on a 1 second timer, rather than 
 using FindNotify or equivalent.  - (started)
 
@@ -28,27 +29,34 @@
 h) quota support
 
 i) support for the Linux 2.5 kernel new feature get_xattr and set_xattr
+which will allow us to expose dos attributes as well as real
+ACLs
 
 j) finish off the mount helper, mount.cifs - (started)
 
-KNOWN BUGS (updated October 8nd, 2002)
+k) finish writepages support (multi-page write behind for improved
+performance) and syncpage
+
+l) hook lower into the sockets api (as NFS/SunRPC does) to avoid the
+extra copy in/out of the socket buffers in some cases.
+
+m) finish support for IPv6
+
+KNOWN BUGS (updated February 15, 2003)
 ====================================
-1) symbolic links (Windows reparse points) are recognized but
+1) existing symbolic links (Windows reparse points) are recognized but
 can not be created remotely. They are implemented for Samba and those that
 support the CIFS Unix extensions but Samba has a bug currently handling
 symlink text beginning with slash
 2) delete of file with read-only attribute set will fail (may be ok)
-3) autoreconnection logic is only partially complete.
-4) there may be a problem with truncating a memmapped file to smaller than 4k with
-the size being reported as exactly 4k.
 
 Misc testing to do
 =================
 1) check out max path names and max path name components against various server
 types.
 
-2) Run POSIX bencharks against cifs
+2) Run dbench
 
-3) Run dbench
+3) Finish FSX testing on SMP now that we workaround the Samba bug
 
-4) Finish FSX testing on SMP now that we workaround the Samba bug
+4) Additional performance testing and optimization
diff -Nru a/fs/cifs/asn1.c b/fs/cifs/asn1.c
--- a/fs/cifs/asn1.c	Mon Feb 17 14:57:26 2003
+++ b/fs/cifs/asn1.c	Mon Feb 17 14:57:26 2003
@@ -458,16 +458,18 @@
 	unsigned int cls, con, tag, oidlen, rc;
 	int use_ntlmssp = FALSE;
 
+    *secType = NTLM; /* BB eventually make Kerberos or NLTMSSP the default */
+
 	/* cifs_dump_mem(" Received SecBlob ", security_blob, length); */
 
 	asn1_open(&ctx, security_blob, length);
 
 	if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
-		cFYI(1, ("\nError decoding negTokenInit header "));
+		cFYI(1, ("Error decoding negTokenInit header "));
 		return 0;
 	} else if ((cls != ASN1_APL) || (con != ASN1_CON)
 		   || (tag != ASN1_EOC)) {
-		cFYI(1, ("\ncls = %d con = %d tag = %d", cls, con, tag));
+		cFYI(1, ("cls = %d con = %d tag = %d", cls, con, tag));
 		return 0;
 	} else {
 		/*      remember to free obj->oid */
@@ -486,51 +488,49 @@
 		}
 
 		if (!rc) {
-			cFYI(1, ("\nError decoding negTokenInit header"));
+			cFYI(1, ("Error decoding negTokenInit header"));
 			return 0;
 		}
 
 		if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
-			cFYI(1, ("\nError decoding negTokenInit "));
+			cFYI(1, ("Error decoding negTokenInit "));
 			return 0;
 		} else if ((cls != ASN1_CTX) || (con != ASN1_CON)
 			   || (tag != ASN1_EOC)) {
-			cFYI(1,
-			     ("\ncls = %d con = %d tag = %d end = %p (%d) exit 0",
+			cFYI(1,("cls = %d con = %d tag = %d end = %p (%d) exit 0",
 			      cls, con, tag, end, *end));
 			return 0;
 		}
 
 		if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
-			cFYI(1, ("\nError decoding negTokenInit "));
+			cFYI(1, ("Error decoding negTokenInit "));
 			return 0;
 		} else if ((cls != ASN1_UNI) || (con != ASN1_CON)
 			   || (tag != ASN1_SEQ)) {
-			cFYI(1,
-			     ("\ncls = %d con = %d tag = %d end = %p (%d) exit 1",
+			cFYI(1,("cls = %d con = %d tag = %d end = %p (%d) exit 1",
 			      cls, con, tag, end, *end));
 			return 0;
 		}
 
 		if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
-			cFYI(1, ("\nError decoding 2nd part of negTokenInit "));
+			cFYI(1, ("Error decoding 2nd part of negTokenInit "));
 			return 0;
 		} else if ((cls != ASN1_CTX) || (con != ASN1_CON)
 			   || (tag != ASN1_EOC)) {
 			cFYI(1,
-			     ("\ncls = %d con = %d tag = %d end = %p (%d) exit 0",
+			     ("cls = %d con = %d tag = %d end = %p (%d) exit 0",
 			      cls, con, tag, end, *end));
 			return 0;
 		}
 
 		if (asn1_header_decode
 		    (&ctx, &sequence_end, &cls, &con, &tag) == 0) {
-			cFYI(1, ("\nError decoding 2nd part of negTokenInit "));
+			cFYI(1, ("Error decoding 2nd part of negTokenInit "));
 			return 0;
 		} else if ((cls != ASN1_UNI) || (con != ASN1_CON)
 			   || (tag != ASN1_SEQ)) {
 			cFYI(1,
-			     ("\ncls = %d con = %d tag = %d end = %p (%d) exit 1",
+			     ("cls = %d con = %d tag = %d end = %p (%d) exit 1",
 			      cls, con, tag, end, *end));
 			return 0;
 		}
@@ -539,13 +539,13 @@
 			rc = asn1_header_decode(&ctx, &end, &cls, &con, &tag);
 			if (!rc) {
 				cFYI(1,
-				     ("\nError 1 decoding negTokenInit header exit 2"));
+				     ("Error 1 decoding negTokenInit header exit 2"));
 				return 0;
 			}
 			if ((tag == ASN1_OJI) && (con == ASN1_PRI)) {
 				asn1_oid_decode(&ctx, end, &oid, &oidlen);
 				cFYI(1,
-				     ("\nOID len = %d oid = 0x%lx 0x%lx 0x%lx 0x%lx",
+				     ("OID len = %d oid = 0x%lx 0x%lx 0x%lx 0x%lx",
 				      oidlen, *oid, *(oid + 1), *(oid + 2),
 				      *(oid + 3)));
 				rc = compare_oid(oid, oidlen, NTLMSSP_OID,
@@ -554,54 +554,53 @@
 				if (rc)
 					use_ntlmssp = TRUE;
 			} else {
-				cFYI(1,
-				     ("\nThis should be an oid what is going on? "));
+				cFYI(1,("This should be an oid what is going on? "));
 			}
 		}
 
 		if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
 			cFYI(1,
-			     ("\nError decoding last part of negTokenInit exit 3"));
+			     ("Error decoding last part of negTokenInit exit 3"));
 			return 0;
 		} else if ((cls != ASN1_CTX) || (con != ASN1_CON)) {	/* tag = 3 indicating mechListMIC */
 			cFYI(1,
-			     ("\nExit 4 cls = %d con = %d tag = %d end = %p (%d)",
+			     ("Exit 4 cls = %d con = %d tag = %d end = %p (%d)",
 			      cls, con, tag, end, *end));
 			return 0;
 		}
 		if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
 			cFYI(1,
-			     ("\nError decoding last part of negTokenInit exit 5"));
+			     ("Error decoding last part of negTokenInit exit 5"));
 			return 0;
 		} else if ((cls != ASN1_UNI) || (con != ASN1_CON)
 			   || (tag != ASN1_SEQ)) {
 			cFYI(1,
-			     ("\nExit 6 cls = %d con = %d tag = %d end = %p (%d)",
+			     ("Exit 6 cls = %d con = %d tag = %d end = %p (%d)",
 			      cls, con, tag, end, *end));
 		}
 
 		if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
 			cFYI(1,
-			     ("\nError decoding last part of negTokenInit exit 7"));
+			     ("Error decoding last part of negTokenInit exit 7"));
 			return 0;
 		} else if ((cls != ASN1_CTX) || (con != ASN1_CON)) {
 			cFYI(1,
-			     ("\nExit 8 cls = %d con = %d tag = %d end = %p (%d)",
+			     ("Exit 8 cls = %d con = %d tag = %d end = %p (%d)",
 			      cls, con, tag, end, *end));
 			return 0;
 		}
 		if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
 			cFYI(1,
-			     ("\nError decoding last part of negTokenInit exit 9"));
+			     ("Error decoding last part of negTokenInit exit 9"));
 			return 0;
 		} else if ((cls != ASN1_UNI) || (con != ASN1_PRI)
 			   || (tag != ASN1_GENSTR)) {
 			cFYI(1,
-			     ("\nExit 10 cls = %d con = %d tag = %d end = %p (%d)",
+			     ("Exit 10 cls = %d con = %d tag = %d end = %p (%d)",
 			      cls, con, tag, end, *end));
 			return 0;
 		}
-		cFYI(1, ("\nNeed to call asn1_octets_decode() function for this %s", ctx.pointer));	/* is this UTF-8 or ASCII? */
+		cFYI(1, ("Need to call asn1_octets_decode() function for this %s", ctx.pointer));	/* is this UTF-8 or ASCII? */
 	}
 
 	/* if (use_kerberos) 
diff -Nru a/fs/cifs/cifs_debug.c b/fs/cifs/cifs_debug.c
--- a/fs/cifs/cifs_debug.c	Mon Feb 17 14:57:27 2003
+++ b/fs/cifs/cifs_debug.c	Mon Feb 17 14:57:27 2003
@@ -39,7 +39,8 @@
 	char *charptr = data;
 	char buf[10], line[80];
 
-	printk("%s: dump of %d bytes of data at 0x%p\n\n", label, length, data);
+	printk(KERN_DEBUG "%s: dump of %d bytes of data at 0x%p\n\n", 
+		label, length, data);
 	for (i = 0; i < length; i += 16) {
 		line[0] = 0;
 		for (j = 0; (j < 4) && (i + j * 4 < length); j++) {
@@ -52,7 +53,7 @@
 			buf[1] = isprint(charptr[i + j]) ? charptr[i + j] : '.';
 			strcat(line, buf);
 		}
-		printk("%s\n", line);
+		printk(KERN_DEBUG "%s\n", line);
 	}
 }
 
@@ -68,7 +69,6 @@
 	int length = 0;
 	char *buf_start = buf;
 
-	printk("\n\nEntering cifs_debug_data_read:  buf=0x%p, beginBuffer=0x%p, offset=%ld, count=%d, eof=%d, data=0x%p\n", buf, *beginBuffer, offset, count, *eof, data);	/* BB remove */
 	length =
 	    sprintf(buf,
 		    "Display Internal CIFS Data Structures for Debugging\n"
@@ -85,17 +85,17 @@
 		ses = list_entry(tmp, struct cifsSesInfo, cifsSessionList);
 		length =
 		    sprintf(buf,
-			    "\n%d) Name: %s  Domain: %s HowManyMounts: %d ServerOS: %s  ServerNOS: %s\n\tCapabilities: 0x%x",
+			    "\n%d) Name: %s  Domain: %s Mounts: %d ServerOS: %s  ServerNOS: %s\n\tCapabilities: 0x%x",
 				i, ses->serverName, ses->serverDomain, atomic_read(&ses->inUse),
 				ses->serverOS, ses->serverNOS, ses->capabilities);
 		buf += length;
 		if(ses->server)
-		buf += sprintf(buf, "\tLocal Users To Same Server: %d ",atomic_read(&ses->server->socketUseCount));
+		buf += sprintf(buf, "\tLocal Users To Same Server: %d ",
+			atomic_read(&ses->server->socketUseCount));
 	}
 	read_unlock(&GlobalSMBSeslock);
 	sprintf(buf, "\n");
 	buf++;
-	printk("\nTotal Buffer so far: %s\n", buf_start);
 
 	length = sprintf(buf, "\nShares: \n");
 	buf += length;
@@ -107,7 +107,7 @@
 		tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
 		length =
 		    sprintf(buf,
-			    "\n%d) %s UseCount: %d on FS: %s with characteristics: 0x%x Attributes: 0x%x\n\tPathComponentLengthMax: %d",
+			    "\n%d) %s Uses: %d on FS: %s with characteristics: 0x%x Attributes: 0x%x\n\tPathComponentMax: %d",
 			    i, tcon->treeName,
 			    atomic_read(&tcon->useCount),
 			    tcon->nativeFileSystem,
diff -Nru a/fs/cifs/cifs_debug.h b/fs/cifs/cifs_debug.h
--- a/fs/cifs/cifs_debug.h	Mon Feb 17 14:57:27 2003
+++ b/fs/cifs/cifs_debug.h	Mon Feb 17 14:57:27 2003
@@ -33,29 +33,35 @@
  */
 #ifdef CIFS_DEBUG
 
+
 /* information message: e.g., configuration, major event */
 extern int cifsFYI;
-#define cFYI(button,prspec)\
-{ if (button && cifsFYI) printk prspec; }
+#define cifsfyi(format,arg...) if (cifsFYI) printk(KERN_DEBUG " " __FILE__ ": " format "\n" "" , ## arg)
+
+#define cFYI(button,prspec) if (button) cifsfyi prspec
+
+#define cifswarn(format, arg...) printk(KERN_WARNING ": " format "\n" , ## arg)
 
 /* debug event message: */
-#define cEVENT(button,prspec)\
-{ if (button) printk prspec; }
+extern int cifsERROR;
+
+#define cEVENT(format,arg...) if (cifsERROR) printk(KERN_EVENT __FILE__ ": " format "\n" , ## arg)
 
 /* error event message: e.g., i/o error */
-extern int cifsERROR;
-#define cERROR(button, prspec)\
-{ if (button && cifsERROR) { printk prspec; if (button > 1) BUG(); } }
+#define cifserror(format,arg...) if (cifsERROR) printk(KERN_ERR " CIFS VFS: " format "\n" "" , ## arg)
+
+#define cERROR(button, prspec) if (button) cifserror prspec
 
 /*
  *	debug OFF
  *	---------
  */
-#else				/* _CIFS_DEBUG */
+#else		/* _CIFS_DEBUG */
 #define cERROR(button,prspec)
-#define cEVENT(button,prspec)
+#define cEVENT(format,arg...)
 #define cFYI(button, prspec)
-#endif				/* _CIFS_DEBUG */
+#define cifserror(format,arg...)
+#endif		/* _CIFS_DEBUG */
 
 /*
  *	statistics
diff -Nru a/fs/cifs/cifs_unicode.c b/fs/cifs/cifs_unicode.c
--- a/fs/cifs/cifs_unicode.c	Mon Feb 17 14:57:28 2003
+++ b/fs/cifs/cifs_unicode.c	Mon Feb 17 14:57:28 2003
@@ -69,7 +69,6 @@
 		}
 	}
 	to[outlen] = 0;
-	cEVENT(0, ("cifs_strfromUCS returning %d - '%s'\n", outlen, to));
 	return outlen;
 }
 
@@ -86,15 +85,13 @@
 	int charlen;
 	int i;
 
-	cEVENT(0, ("cifs_strtoUCS - '%s'\n", from));
-
 	for (i = 0; len && *from; i++, from += charlen, len -= charlen) {
 
 		/* works for 2.4.0 kernel or later */
 		charlen = codepage->char2uni(from, len, &to[i]);
 		if (charlen < 1) {
 			cERROR(1,
-			       ("cifs_strtoUCS: char2uni returned %d.\n",
+			       ("cifs_strtoUCS: char2uni returned %d",
 				charlen));
 			to[i] = cpu_to_le16(0x003f);	/* a question mark */
 			charlen = 1;
@@ -102,8 +99,6 @@
 		to[i] = cpu_to_le16(to[i]);
 
 	}
-
-	cEVENT(0, (" returning %d\n", i));
 
 	to[i] = 0;
 	return i;
diff -Nru a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
--- a/fs/cifs/cifsfs.c	Mon Feb 17 14:57:27 2003
+++ b/fs/cifs/cifsfs.c	Mon Feb 17 14:57:27 2003
@@ -71,12 +71,13 @@
 	if(cifs_sb == NULL)
 		return -ENOMEM;
 	cifs_sb->local_nls = load_nls_default();	/* needed for ASCII cp to Unicode converts */
+
 	rc = cifs_mount(sb, cifs_sb, data, devname);
 
 	if (rc) {
 		if (!silent)
 			cERROR(1,
-			       ("cifs_mount failed w/return code = %d\n", rc));
+			       ("cifs_mount failed w/return code = %d", rc));
 		goto out_mount_failed;
 	}
 
@@ -97,13 +98,10 @@
 	return 0;
 
 out_no_root:
-	cEVENT(1, ("cifs_read_super: get root inode failed\n"));
+	cERROR(1, ("cifs_read_super: get root inode failed"));
 	if (inode)
 		iput(inode);
 
-	if (rc) {
-		cERROR(1, ("cifs_mount failed with no root inode"));
-	}
 out_mount_failed:
 	if(cifs_sb)
 		kfree(cifs_sb);
@@ -116,15 +114,15 @@
 	int rc = 0;
 	struct cifs_sb_info *cifs_sb;
 
-	cFYI(1, ("In cifs_put_super\n"));
+	cFYI(1, ("In cifs_put_super"));
 	cifs_sb = CIFS_SB(sb);
 	if(cifs_sb == NULL) {
-		cFYI(1,("\nEmpty cifs superblock info passed to unmount"));
+		cFYI(1,("Empty cifs superblock info passed to unmount"));
 		return;
 	}
 	rc = cifs_umount(sb, cifs_sb); 
 	if (rc) {
-		cERROR(1, ("cifs_umount failed with return code %d\n", rc));
+		cERROR(1, ("cifs_umount failed with return code %d", rc));
 	}
 	unload_nls(cifs_sb->local_nls);
 	kfree(cifs_sb);
@@ -180,7 +178,8 @@
 	cifs_inode->cifsAttrs = 0x20;	/* default */
 	atomic_set(&cifs_inode->inUse, 0);
 	cifs_inode->time = 0;
-	cifs_inode->clientCanCache = 0;
+    if(oplockEnabled)
+	    cifs_inode->clientCanCacheAll = 1;
 	INIT_LIST_HEAD(&cifs_inode->openFileList);
 	return &cifs_inode->vfs_inode;
 }
@@ -236,7 +235,7 @@
 	int rc;
 	struct super_block *sb = sget(fs_type, NULL, set_anon_super, NULL);
 
-	cFYI(1, ("\nDevname: %s flags: %d ", dev_name, flags));
+	cFYI(1, ("Devname: %s flags: %d ", dev_name, flags));
 
 	if (IS_ERR(sb))
 		return sb;
@@ -277,8 +276,15 @@
 struct inode_operations cifs_file_inode_ops = {
 /*	revalidate:cifs_revalidate, */
 	.setattr = cifs_setattr,
-	.getattr = cifs_getattr,
+	.getattr = cifs_getattr, /* do we need this anymore? */
 	.rename = cifs_rename,
+#ifdef CIFS_XATTR
+	.setxattr = cifs_setxattr,
+	.getxattr = cifs_getxattr,
+	.listxattr = cifs_listxattr,
+	.removexattr = cifs_removexattr,
+	.permission = cifs_permission,
+#endif 
 };
 
 struct inode_operations cifs_symlink_inode_ops = {
@@ -287,16 +293,24 @@
 	/* BB add the following two eventually */
 	/* revalidate: cifs_revalidate,
 	   setattr:    cifs_notify_change, *//* BB do we need notify change */
+#ifdef CIFS_XATTR
+	.setxattr = cifs_setxattr,
+	.getxattr = cifs_getxattr,
+	.listxattr = cifs_listxattr,
+	.removexattr = cifs_removexattr,
+#endif 
 };
 
 struct file_operations cifs_file_ops = {
 	.read = generic_file_read,
-	.write = generic_file_write,
+	.write = generic_file_write, 
 	.open = cifs_open,
 	.release = cifs_close,
 	.lock = cifs_lock,
 	.fsync = cifs_fsync,
+    .flush = cifs_flush,
 	.mmap  = cifs_file_mmap,
+	.sendfile = generic_file_sendfile,
 };
 
 struct file_operations cifs_dir_ops = {
@@ -333,7 +347,7 @@
 cifs_destroy_inodecache(void)
 {
 	if (kmem_cache_destroy(cifs_inode_cachep))
-		printk(KERN_INFO "cifs_inode_cache: error freeing\n");
+		printk(KERN_WARNING "cifs_inode_cache: error freeing\n");
 }
 
 int
@@ -353,7 +367,7 @@
 cifs_destroy_request_bufs(void)
 {
 	if (kmem_cache_destroy(cifs_req_cachep))
-		printk(KERN_INFO
+		printk(KERN_WARNING
 		       "cifs_destroy_request_cache: error not all structures were freed\n");
 }
 
@@ -373,7 +387,7 @@
 cifs_destroy_mids(void)
 {
 	if (kmem_cache_destroy(cifs_mid_cachep))
-		printk(KERN_INFO
+		printk(KERN_WARNING
 		       "cifs_destroy_mids: error not all structures were freed\n");
 }
 
@@ -426,7 +440,7 @@
 static void __exit
 exit_cifs(void)
 {
-	cFYI(0, ("\nIn unregister ie exit_cifs"));
+	cFYI(0, ("In unregister ie exit_cifs"));
 #if CONFIG_PROC_FS
 	cifs_proc_clean();
 #endif
diff -Nru a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h
--- a/fs/cifs/cifsfs.h	Mon Feb 17 14:57:27 2003
+++ b/fs/cifs/cifsfs.h	Mon Feb 17 14:57:27 2003
@@ -74,6 +74,7 @@
 			  size_t write_size, loff_t * poffset);
 extern int cifs_lock(struct file *, int, struct file_lock *);
 extern int cifs_fsync(struct file *, struct dentry *, int);
+extern int cifs_flush(struct file *);
 extern int cifs_file_mmap(struct file * , struct vm_area_struct *);
 extern struct file_operations cifs_dir_ops;
 extern int cifs_dir_open(struct inode *inode, struct file *file);
diff -Nru a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
--- a/fs/cifs/cifsglob.h	Mon Feb 17 14:57:27 2003
+++ b/fs/cifs/cifsglob.h	Mon Feb 17 14:57:27 2003
@@ -27,7 +27,7 @@
 #define MAX_TREE_SIZE 2 + MAX_SERVER_SIZE + 1 + MAX_SHARE_SIZE + 1
 #define MAX_SERVER_SIZE 15
 #define MAX_SHARE_SIZE  64	/* used to be 20 - this should still be enough */
-#define MAX_USERNAME_SIZE 32	/* 22 is to allow for 15 char names + null
+#define MAX_USERNAME_SIZE 32	/* 32 is to allow for 15 char names + null
 				   termination then *2 for unicode versions */
 #define MAX_PASSWORD_SIZE 16
 
@@ -109,6 +109,21 @@
 	struct semaphore tcpSem;
 	struct task_struct *tsk;
 	char server_GUID[16];
+	char secMode;
+	enum securityEnum secType;
+	unsigned int maxReq;	/* Clients should submit no more */
+	/* than maxReq distinct unanswered SMBs to the server when using  */
+	/* multiplexed reads or writes */
+	unsigned int maxBuf;	/* maxBuf specifies the maximum */
+	/* message size the server can send or receive for non-raw SMBs */
+	unsigned int maxRw;	/* maxRw specifies the maximum */
+	/* message size the server can send or receive for */
+	/* SMB_COM_WRITE_RAW or SMB_COM_READ_RAW. */
+	char sessid[4];		/* unique token id for this session */
+	/* (returned on Negotiate */
+	int capabilities; /* allow selective disabling of caps by smb sess */
+	__u16 timeZone;
+	char cryptKey[CIFS_CRYPTO_KEY_SIZE];
 };
 
 /*
@@ -117,12 +132,11 @@
  * has changed. We also hang a list of sessions owned by this user off here. 
  */
 struct cifsUidInfo {
-	struct cifsUidInfo *next1;	/* BB replace with list and atomicize */
-	struct cifsSesInfo *ses;	/* list of sessions *//* BB replace with list and atomicize */
-	struct srSesInfo *sesSR;	/* Save/Restore session list */
+	struct list_head userList;
+	struct list_head sessionList; /* SMB sessions for this user */
 	uid_t linux_uid;
 	char user[MAX_USERNAME_SIZE + 1];	/* ascii name of user */
-	/* BB eventually need ptr into PAM or WinBind info */
+	/* BB may need ptr or callback for PAM or WinBind info */
 };
 
 /*
@@ -135,28 +149,16 @@
 	struct TCP_Server_Info *server;	/* pointer to server info */
 	atomic_t inUse;		/* # of CURRENT users of this ses */
 	enum statusEnum status;
-	int dialectIndex;	/* the negotiated dialect index */
-	char secMode;
-	enum securityEnum secType;
-	unsigned int maxReq;	/* Clients should submit no more */
-	/* than maxReq distinct unanswered SMBs to the server when using  */
-	/* multiplexed reads or writes */
-	unsigned int maxBuf;	/* maxBuf specifies the maximum */
-	/* message size the server can send or receive for non-raw SMBs */
-	unsigned int maxRw;	/* maxRw specifies the maximum */
-	/* message size the server can send or receive for */
-	/* SMB_COM_WRITE_RAW or SMB_COM_READ_RAW. */
-	char sessid[4];		/* unique token id for this session */
-	/* (returned on Negotiate */
 	__u16 ipc_tid;		/* special tid for connection to IPC share */
-	int capabilities;
-	__u16 timeZone;
 	char *serverOS;		/* name of operating system underlying the server */
 	char *serverNOS;	/* name of network operating system that the server is running */
 	char *serverDomain;	/* security realm of server */
 	int Suid;		/* needed for user level security */
+	int capabilities;
 	char serverName[SERVER_NAME_LEN_WITH_NULL * 2];	/* BB make bigger for tcp names - will ipv6 and sctp addresses fit here?? */
-	char userName[MAX_USERNAME_SIZE + 1];	/* BB remove and replace with list of cifsUidInfo structures */
+	char userName[MAX_USERNAME_SIZE + 1];
+    char domainName[MAX_USERNAME_SIZE + 1];
+    char password_with_pad[CIFS_ENCPWD_SIZE];
 };
 
 /*
@@ -172,6 +174,7 @@
 	char *nativeFileSystem;
 	__u16 tid;		/* The 2 byte transaction id */
 	__u16 Flags;		/* optional support bits */
+	enum statusEnum tidStatus;
 	atomic_t useCount;	/* how many mounts (explicit or implicit refer to this share */
 	FILE_SYSTEM_DEVICE_INFO fsDevInfo;
 	FILE_SYSTEM_ATTRIBUTE_INFO fsAttrInfo;	/* note file system name may be truncated - but very unlikely */
@@ -214,11 +217,11 @@
 	struct list_head lockList;
 	/* BB add in lists for dirty pages - i.e. write caching info for oplock */
 	struct list_head openFileList;
-	__u32 cifsAttrs;	/* e.g. DOS archive bit, sparse, compressed, system etc. */
-	atomic_t inUse;		/* num concurrent users (local openers cifs) of file */
+	__u32 cifsAttrs; /* e.g. DOS archive bit, sparse, compressed, system */
+	atomic_t inUse;	 /* num concurrent users (local openers cifs) of file*/
 	unsigned long time;	/* jiffies of last update/check of inode */
-	int clientCanCache:1;	/* oplocked.  We need to extend cases beyond this i.e. what
-			   if file read-only or if file locked? or if file on r/o vol? */
+	int clientCanCacheRead:1; /* read oplock */
+    int clientCanCacheAll:1;  /* read and writebehind oplock */
 	struct inode vfs_inode;
 };
 
diff -Nru a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h
--- a/fs/cifs/cifspdu.h	Mon Feb 17 14:57:28 2003
+++ b/fs/cifs/cifspdu.h	Mon Feb 17 14:57:28 2003
@@ -79,7 +79,7 @@
 /*
  * Starting value for maximum SMB size negotiation
  */
-#define CIFS_MAX_MSGSIZE (4*1024)
+#define CIFS_MAX_MSGSIZE (4*4096)
 
 /*
  * Size of encrypted user password in bytes
diff -Nru a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
--- a/fs/cifs/cifsproto.h	Mon Feb 17 14:57:26 2003
+++ b/fs/cifs/cifsproto.h	Mon Feb 17 14:57:26 2003
@@ -36,8 +36,8 @@
 			unsigned int /* length */ , struct sockaddr *);
 extern unsigned int _GetXid(void);
 extern void _FreeXid(unsigned int);
-#define GetXid() (int)_GetXid(); cFYI(1,("\nCIFS VFS: in %s as Xid: %d with uid: %d",__FUNCTION__, xid,current->fsuid));
-#define FreeXid(curr_xid) {_FreeXid(curr_xid); cFYI(1,("\nCIFS VFS: leaving %s (xid = %d) rc = %d\n",__FUNCTION__,curr_xid,rc));}
+#define GetXid() (int)_GetXid(); cFYI(1,("CIFS VFS: in %s as Xid: %d with uid: %d",__FUNCTION__, xid,current->fsuid));
+#define FreeXid(curr_xid) {_FreeXid(curr_xid); cFYI(1,("CIFS VFS: leaving %s (xid = %d) rc = %d",__FUNCTION__,curr_xid,rc));}
 extern char *build_path_from_dentry(struct dentry *);
 extern char *build_wildcard_path_from_dentry(struct dentry *direntry);
 extern void renew_parental_timestamps(struct dentry *direntry);
@@ -72,28 +72,21 @@
 			const unsigned char *search_path,
 			struct super_block *sb);
 
-extern int CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses,
-			char cryptokey[CIFS_CRYPTO_KEY_SIZE]);
+extern int setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo, 
+			struct nls_table * nls_info);
+extern int CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses);
 extern int CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
-			char *user, char *domain,
 			char *session_key, char *ntlm_session_key,
 			const struct nls_table *);
 extern int CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses,
-			char *user, char *domain,
-			char *SecurityBlob,
-			int SecurityBlobLength,
+			char *SecurityBlob,int SecurityBlobLength,
 			const struct nls_table *);
 extern int CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
-			struct cifsSesInfo *ses,
-			char *domain,
-			char *ntlm_session_key,
-			int  *ntlmv2_flag,
+			struct cifsSesInfo *ses, int  *ntlmv2_flag,
 			const struct nls_table *);
 extern int CIFSNTLMSSPAuthSessSetup(unsigned int xid,
-			struct cifsSesInfo *ses, char *user,
-			char *domain, char *ntlm_session_key,
-			char *lanman_session_key,
-			int ntlmv2_flag,
+			struct cifsSesInfo *ses, char *ntlm_session_key,
+			char *lanman_session_key,int ntlmv2_flag,
 			const struct nls_table *);
 
 extern int CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
@@ -202,7 +195,7 @@
 
 extern int CIFSSMBRead(const int xid, const struct cifsTconInfo *tcon,
 			const int netfid, unsigned int count,
-			const __u64 lseek, unsigned int *nbytes, char *buf);
+			const __u64 lseek, unsigned int *nbytes, char **buf);
 extern int CIFSSMBWrite(const int xid, const struct cifsTconInfo *tcon,
 			const int netfid, const unsigned int count,
 			const __u64 lseek, unsigned int *nbytes,
diff -Nru a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
--- a/fs/cifs/cifssmb.c	Mon Feb 17 14:57:27 2003
+++ b/fs/cifs/cifssmb.c	Mon Feb 17 14:57:27 2003
@@ -49,6 +49,11 @@
 {
 	int rc = 0;
 
+	if(tcon)
+		if(tcon->ses)
+			if(tcon->ses->status == CifsNeedReconnect)
+				setup_session(0, tcon->ses, load_nls_default());
+
 	*request_buf = buf_get();
 	if (request_buf == 0) {
 		return -ENOMEM;
@@ -65,13 +70,20 @@
 }
 
 int
-CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses,
-		 char cryptokey[CIFS_CRYPTO_KEY_SIZE])
+CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
 {
 	NEGOTIATE_REQ *pSMB;
 	NEGOTIATE_RSP *pSMBr;
 	int rc = 0;
 	int bytes_returned;
+	struct TCP_Server_Info * server;
+
+	if(ses->server)
+		server = ses->server;
+	else {
+		rc = -EIO;
+		return rc;
+	}
 
 	rc = smb_init(SMB_COM_NEGOTIATE, 0, 0 /* no tcon yet */ ,
 		      (void **) &pSMB, (void **) &pSMBr);
@@ -81,9 +93,9 @@
 	pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
 	if (extended_security)
 		pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
-    if (sign_CIFS_PDUs) {
-        pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
-    }
+	if (sign_CIFS_PDUs) {
+		pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
+	}
 
 	pSMB->ByteCount = strlen(protocols[0].name) + 1;
 	strncpy(pSMB->DialectsArray, protocols[0].name, 30);	
@@ -95,22 +107,22 @@
 	rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
 	if (rc == 0) {
-		ses->dialectIndex = le16_to_cpu(pSMBr->DialectIndex);
-		ses->secMode = pSMBr->SecurityMode;	
+		server->secMode = pSMBr->SecurityMode;	
+		server->secType = NTLM; /* BB override default for NTLMv2 or krb*/
         /* one byte - no need to convert this or EncryptionKeyLen from le,*/
-		ses->maxReq = le16_to_cpu(pSMBr->MaxMpxCount);
+		server->maxReq = le16_to_cpu(pSMBr->MaxMpxCount);
 		/* probably no need to store and check maxvcs */
-		ses->maxBuf =
+		server->maxBuf =
 		    min(le32_to_cpu(pSMBr->MaxBufferSize),
 			(__u32) CIFS_MAX_MSGSIZE + MAX_CIFS_HDR_SIZE);
-		ses->maxRw = le32_to_cpu(pSMBr->MaxRawSize);
-		cFYI(1, ("\nMax buf = %d ", ses->maxBuf));
-		GETU32(ses->sessid) = le32_to_cpu(pSMBr->SessionKey);
-		ses->capabilities = le32_to_cpu(pSMBr->Capabilities);
-		ses->timeZone = le16_to_cpu(pSMBr->ServerTimeZone);	
+		server->maxRw = le32_to_cpu(pSMBr->MaxRawSize);
+		cFYI(0, ("Max buf = %d ", ses->server->maxBuf));
+		GETU32(ses->server->sessid) = le32_to_cpu(pSMBr->SessionKey);
+		server->capabilities = le32_to_cpu(pSMBr->Capabilities);
+		server->timeZone = le16_to_cpu(pSMBr->ServerTimeZone);	
         /* BB with UTC do we ever need to be using srvr timezone? */
 		if (pSMBr->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) {
-			memcpy(cryptokey, pSMBr->u.EncryptionKey,
+			memcpy(server->cryptKey, pSMBr->u.EncryptionKey,
 			       CIFS_CRYPTO_KEY_SIZE);
 		} else if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC)
 			   && (pSMBr->EncryptionKeyLength == 0)) {
@@ -124,22 +136,22 @@
 			if (pSMBr->ByteCount < 16)
 				rc = -EIO;
 			else if (pSMBr->ByteCount == 16) {
-				ses->secType = RawNTLMSSP;
-				if (ses->server->socketUseCount.counter > 1) {
+				server->secType = RawNTLMSSP;
+				if (server->socketUseCount.counter > 1) {
 					if (memcmp
-					    (ses->server->server_GUID,
-					     pSMBr->u.extended_response.
-					     GUID, 16) != 0) {
+						(server->server_GUID,
+						pSMBr->u.extended_response.
+						GUID, 16) != 0) {
 						cFYI(1,
-						     ("UID of server does not match that of previous connection to same ip address"));
-						memcpy(ses->server->
-						       server_GUID,
-						       pSMBr->u.
-						       extended_response.
-						       GUID, 16);
+							("UID of server does not match that of previous connection to same ip address"));
+						memcpy(server->
+							server_GUID,
+							pSMBr->u.
+							extended_response.
+							GUID, 16);
 					}
 				} else
-					memcpy(ses->server->server_GUID,
+					memcpy(server->server_GUID,
 					       pSMBr->u.extended_response.
 					       GUID, 16);
 			} else {
@@ -147,16 +159,16 @@
 							 extended_response.
 							 SecurityBlob,
 							 pSMBr->ByteCount -
-							 16, &ses->secType);
+							 16, &server->secType);
 			}
 
 		} else
-			ses->capabilities &= ~CAP_EXTENDED_SECURITY;
-        if(sign_CIFS_PDUs == FALSE) {        
-            if(ses->secMode & SECMODE_SIGN_REQUIRED)
-                cERROR(1,("\nServer required CIFS packet signing - enable /proc/fs/cifs/PacketSigningEnabled"));
-            ses->secMode &= ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
-        }
+			server->capabilities &= ~CAP_EXTENDED_SECURITY;
+		if(sign_CIFS_PDUs == FALSE) {        
+			if(server->secMode & SECMODE_SIGN_REQUIRED)
+				cERROR(1,("Server required CIFS packet signing - enable /proc/fs/cifs/PacketSigningEnabled"));
+			server->secMode &= ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
+		}
 	}
 	if (pSMB)
 		buf_release(pSMB);
@@ -171,7 +183,7 @@
 	int rc = 0;
 	int length;
 
-	cFYI(1, ("\nIn tree disconnect"));
+	cFYI(1, ("In tree disconnect"));
 	/*
 	 *  If last user of the connection and
 	 *  connection alive - disconnect it
@@ -192,6 +204,10 @@
 
 /* BB remove (from server) list of shares - but with smp safety  BB */
 /* BB is ses active - do we need to check here - but how? BB */
+    if((tcon->ses == 0) || (tcon->ses->server == 0)) {    
+        up(&tcon->tconSem);
+        return -EIO;
+    }
 
 	rc = smb_init(SMB_COM_TREE_DISCONNECT, 0, tcon,
 		      (void **) &smb_buffer, (void **) &smb_buffer_response);
@@ -218,7 +234,7 @@
 	int rc = 0;
 	int length;
 
-	cFYI(1, ("\nIn SMBLogoff for session disconnect"));
+	cFYI(1, ("In SMBLogoff for session disconnect"));
 
 	if (ses)
 		down(&ses->sesSem);	/* need to add more places where this sem is checked */
@@ -230,7 +246,7 @@
 		up(&ses->sesSem);
 		return -EBUSY;
 	}
-    if(ses->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
+    if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
         pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
 	rc = smb_init(SMB_COM_LOGOFF_ANDX, 2, 0 /* no tcon anymore */ ,
 		      (void **) &pSMB, (void **) &smb_buffer_response);
@@ -278,7 +294,6 @@
 		name_len++;	/* trailing null */
 		name_len *= 2;
 	} else {		/* BB improve the check for buffer overruns BB */
-
 		name_len = strnlen(fileName, 530);
 		name_len++;	/* trailing null */
 		strncpy(pSMB->fileName, fileName, name_len);
@@ -292,7 +307,7 @@
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
 	if (rc) {
-		cERROR(1, ("\nSend error in RMFile = %d\n", rc));
+		cFYI(1, ("Error in RMFile = %d", rc));
 	}
 	if (pSMB)
 		buf_release(pSMB);
@@ -309,7 +324,7 @@
 	int bytes_returned;
 	int name_len;
 
-	cFYI(1, ("\nIn CIFSSMBRmDir"));
+	cFYI(1, ("In CIFSSMBRmDir"));
 
 	rc = smb_init(SMB_COM_DELETE_DIRECTORY, 0, tcon, (void **) &pSMB,
 		      (void **) &pSMBr);
@@ -323,7 +338,6 @@
 		name_len++;	/* trailing null */
 		name_len *= 2;
 	} else {		/* BB improve the check for buffer overruns BB */
-
 		name_len = strnlen(dirName, 530);
 		name_len++;	/* trailing null */
 		strncpy(pSMB->DirName, dirName, name_len);
@@ -336,7 +350,7 @@
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
 	if (rc) {
-		cERROR(1, ("\nSend error in RMDir = %d\n", rc));
+		cFYI(1, ("Error in RMDir = %d", rc));
 	}
 	if (pSMB)
 		buf_release(pSMB);
@@ -353,7 +367,7 @@
 	int bytes_returned;
 	int name_len;
 
-	cFYI(1, ("\nIn CIFSSMBMkDir"));
+	cFYI(1, ("In CIFSSMBMkDir"));
 
 	rc = smb_init(SMB_COM_CREATE_DIRECTORY, 0, tcon, (void **) &pSMB,
 		      (void **) &pSMBr);
@@ -367,7 +381,6 @@
 		name_len++;	/* trailing null */
 		name_len *= 2;
 	} else {		/* BB improve the check for buffer overruns BB */
-
 		name_len = strnlen(name, 530);
 		name_len++;	/* trailing null */
 		strncpy(pSMB->DirName, name, name_len);
@@ -380,7 +393,7 @@
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
 	if (rc) {
-		cERROR(1, ("\nSend error in RMDir = %d\n", rc));
+		cFYI(1, ("Error in Mkdir = %d", rc));
 	}
 	if (pSMB)
 		buf_release(pSMB);
@@ -418,15 +431,17 @@
 		name_len *= 2;
 		pSMB->NameLength = cpu_to_le16(name_len);
 	} else {		/* BB improve the check for buffer overruns BB */
-
 		pSMB->ByteCount = 0;	/* no pad */
 		name_len = strnlen(fileName, 530);
 		name_len++;	/* trailing null */
 		pSMB->NameLength = cpu_to_le16(name_len);
 		strncpy(pSMB->fileName, fileName, name_len);
 	}
-	if (*pOplock)
+	if (*pOplock & REQ_OPLOCK)
 		pSMB->OpenFlags = cpu_to_le32(REQ_OPLOCK);
+	else if (*pOplock & REQ_BATCHOPLOCK) {
+		pSMB->OpenFlags = cpu_to_le32(REQ_BATCHOPLOCK);
+	}
 	pSMB->DesiredAccess = cpu_to_le32(access_flags);
 	pSMB->AllocationSize = 0;
 	pSMB->FileAttributes = ATTR_NORMAL;	/* XP does not handle ATTR_POSIX_SEMANTICS */
@@ -449,7 +464,7 @@
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
 	if (rc) {
-		cERROR(1, ("\nSend error in Open = %d\n", rc));
+		cFYI(1, ("Error in Open = %d", rc));
 	} else {
 		*pOplock = pSMBr->OplockLevel;	/* one byte no need to le_to_cpu */
 		*netfid = pSMBr->Fid;	/* cifs fid stays in le */
@@ -463,17 +478,22 @@
 	return rc;
 }
 
+/* If no buffer passed in, then caller wants to do the copy
+	as in the case of readpages so the SMB buffer must be
+	freed by the caller */
+
 int
 CIFSSMBRead(const int xid, const struct cifsTconInfo *tcon,
 	    const int netfid, const unsigned int count,
-	    const __u64 lseek, unsigned int *nbytes, char *buf)
+	    const __u64 lseek, unsigned int *nbytes, char **buf)
 {
 	int rc = -EACCES;
 	READ_REQ *pSMB = NULL;
 	READ_RSP *pSMBr = NULL;
-	char *pReadData;
+	char *pReadData = NULL;
 	int bytes_returned;
 
+	*nbytes = 0;
 	rc = smb_init(SMB_COM_READ_ANDX, 12, tcon, (void **) &pSMB,
 		      (void **) &pSMBr);
 	if (rc)
@@ -485,7 +505,7 @@
 	pSMB->OffsetHigh = cpu_to_le32(lseek >> 32);
 	pSMB->Remaining = 0;
 	pSMB->MaxCount = cpu_to_le16(min(count,
-					 (tcon->ses->maxBuf -
+					 (tcon->ses->server->maxBuf -
 					  MAX_CIFS_HDR_SIZE) & 0xFFFFFF00));
 	pSMB->MaxCountHigh = 0;
 	pSMB->ByteCount = 0;  /* no need to do le conversion since it is 0 */
@@ -493,14 +513,14 @@
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
 	if (rc) {
-		cERROR(1, ("\nSend error in read = %d\n", rc));
-		*nbytes = 0;
+		cERROR(1, ("Send error in read = %d", rc));
 	} else {
 		pSMBr->DataLength = le16_to_cpu(pSMBr->DataLength);
 		*nbytes = pSMBr->DataLength;
 		/*check that DataLength would not go beyond end of SMB */
 		if ((pSMBr->DataLength > CIFS_MAX_MSGSIZE) 
 				|| (pSMBr->DataLength > count)) {
+			cFYI(1,("bad length %d for count %d",pSMBr->DataLength,count));
 			rc = -EIO;
 			*nbytes = 0;
 		} else {
@@ -508,16 +528,19 @@
 			    (char *) (&pSMBr->hdr.Protocol) +
 			    le16_to_cpu(pSMBr->DataOffset);
 /*			if(rc = copy_to_user(buf, pReadData, pSMBr->DataLength)) {
-				cERROR(1,("\nFaulting on read rc = %d",rc));
+				cERROR(1,("Faulting on read rc = %d",rc));
 				rc = -EFAULT;
 			}*/ /* can not use copy_to_user when using page cache*/
-			memcpy(buf,pReadData,pSMBr->DataLength);
+			if(*buf)
+			    memcpy(*buf,pReadData,pSMBr->DataLength);
 		}
 	}
-
-	if (pSMB)
-		buf_release(pSMB);
-
+	if (pSMB) {
+		if(*buf)
+			buf_release(pSMB);
+		else
+			*buf = (char *)pSMB;
+	}
 	return rc;
 }
 
@@ -542,9 +565,9 @@
 	pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
 	pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
 	pSMB->Remaining = 0;
-	if (count > ((tcon->ses->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFF00))
+	if (count > ((tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFF00))
 		pSMB->DataLengthLow =
-		    (tcon->ses->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFF00;
+		    (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFF00;
 	else
 		pSMB->DataLengthLow = count;
 	pSMB->DataLengthHigh = 0;
@@ -561,7 +584,7 @@
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
 			 (struct smb_hdr *) pSMBr, &bytes_returned, long_op);
 	if (rc) {
-		cERROR(1, ("\nSend error in write = %d\n", rc));
+		cERROR(1, ("Send error in write = %d", rc));
 		*nbytes = 0;
 	} else
 		*nbytes = le16_to_cpu(pSMBr->Count);
@@ -583,7 +606,7 @@
 	LOCK_RSP *pSMBr = NULL;
 	int bytes_returned;
 
-	cFYI(1, ("\nIn CIFSSMBLock"));
+	cFYI(1, ("In CIFSSMBLock"));
 
 	rc = smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB,
 		      (void **) &pSMBr);
@@ -607,7 +630,7 @@
 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
 
 	if (rc) {
-		cERROR(1, ("\nSend error in Lock = %d\n", rc));
+		cERROR(1, ("Send error in Lock = %d", rc));
 	}
 	if (pSMB)
 		buf_release(pSMB);
@@ -622,7 +645,7 @@
 	CLOSE_REQ *pSMB = NULL;
 	CLOSE_RSP *pSMBr = NULL;
 	int bytes_returned;
-	cFYI(1, ("\nIn CIFSSMBClose"));
+	cFYI(1, ("In CIFSSMBClose"));
 
 	rc = smb_init(SMB_COM_CLOSE, 3, tcon, (void **) &pSMB,
 		      (void **) &pSMBr);
@@ -635,7 +658,7 @@
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
 	if (rc) {
-		cERROR(1, ("\nSend error in Close = %d\n", rc));
+		cERROR(1, ("Send error in Close = %d", rc));
 	}
 	if (pSMB)
 		buf_release(pSMB);
@@ -654,7 +677,7 @@
 	int bytes_returned;
 	int name_len, name_len2;
 
-	cFYI(1, ("\nIn CIFSSMBRename"));
+	cFYI(1, ("In CIFSSMBRename"));
 
 	rc = smb_init(SMB_COM_RENAME, 1, tcon, (void **) &pSMB,
 		      (void **) &pSMBr);
@@ -682,7 +705,6 @@
 		name_len2 += 1 /* trailing null */  + 1 /* Signature word */ ;
 		name_len2 *= 2;	/* convert to bytes */
 	} else {		/* BB improve the check for buffer overruns BB */
-
 		name_len = strnlen(fromName, 530);
 		name_len++;	/* trailing null */
 		strncpy(pSMB->OldFileName, fromName, name_len);
@@ -702,7 +724,7 @@
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
 	if (rc) {
-		cFYI(1, ("\nSend error in RMDir = %d\n", rc));
+		cFYI(1, ("Send error in RMDir = %d", rc));
 	}
 	if (pSMB)
 		buf_release(pSMB);
@@ -723,7 +745,7 @@
 	int rc = 0;
 	int bytes_returned = 0;
 
-	cFYI(1, ("\nIn Symlink Unix style"));
+	cFYI(1, ("In Symlink Unix style"));
 
 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
 		      (void **) &pSMBr);
@@ -788,7 +810,7 @@
 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
 	if (rc) {
 		cFYI(1,
-		     ("\nSend error in SetPathInfo (create symlink) = %d\n",
+		     ("Send error in SetPathInfo (create symlink) = %d",
 		      rc));
 	}
 
@@ -810,7 +832,7 @@
 	int rc = 0;
 	int bytes_returned = 0;
 
-	cFYI(1, ("\nIn Create Hard link Unix style"));
+	cFYI(1, ("In Create Hard link Unix style"));
 
 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
 		      (void **) &pSMBr);
@@ -873,7 +895,7 @@
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
 	if (rc) {
-		cFYI(1, ("\nSend error in SetPathInfo (hard link) = %d\n", rc));
+		cFYI(1, ("Send error in SetPathInfo (hard link) = %d", rc));
 	}
 
 	if (pSMB)
@@ -892,7 +914,7 @@
 	int bytes_returned;
 	int name_len, name_len2;
 
-	cFYI(1, ("\nIn CIFSCreateHardLink"));
+	cFYI(1, ("In CIFSCreateHardLink"));
 
 	rc = smb_init(SMB_COM_NT_RENAME, 4, tcon, (void **) &pSMB,
 		      (void **) &pSMBr);
@@ -923,7 +945,6 @@
 		name_len2 += 1 /* trailing null */  + 1 /* Signature word */ ;
 		name_len2 *= 2;	/* convert to bytes */
 	} else {		/* BB improve the check for buffer overruns BB */
-
 		name_len = strnlen(fromName, 530);
 		name_len++;	/* trailing null */
 		strncpy(pSMB->OldFileName, fromName, name_len);
@@ -942,7 +963,7 @@
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
 	if (rc) {
-		cFYI(1, ("\nSend error in hard link (NT rename) = %d\n", rc));
+		cFYI(1, ("Send error in hard link (NT rename) = %d", rc));
 	}
 	if (pSMB)
 		buf_release(pSMB);
@@ -963,7 +984,7 @@
 	int bytes_returned;
 	int name_len;
 
-	cFYI(1, ("\nIn QPathSymLinkInfo (Unix) for path %s", searchName));
+	cFYI(1, ("In QPathSymLinkInfo (Unix) for path %s", searchName));
 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
 		      (void **) &pSMBr);
 	if (rc)
@@ -977,7 +998,6 @@
 		name_len++;	/* trailing null */
 		name_len *= 2;
 	} else {		/* BB improve the check for buffer overruns BB */
-
 		name_len = strnlen(searchName, 530);
 		name_len++;	/* trailing null */
 		strncpy(pSMB->FileName, searchName, name_len);
@@ -1011,7 +1031,7 @@
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
 	if (rc) {
-		cFYI(1, ("\nSend error in QuerySymLinkInfo = %d\n", rc));
+		cFYI(1, ("Send error in QuerySymLinkInfo = %d", rc));
 	} else {		/* decode response */
 		pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
 		pSMBr->DataCount = le16_to_cpu(pSMBr->DataCount);
@@ -1066,7 +1086,7 @@
 	struct smb_com_transaction_ioctl_req * pSMB;
 	struct smb_com_transaction_ioctl_rsp * pSMBr;
 
-	cFYI(1, ("\nIn Windows reparse style QueryLink info for path %s", searchName));
+	cFYI(1, ("In Windows reparse style QueryLink info for path %s", searchName));
 	rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
 		      (void **) &pSMBr);
 	if (rc)
@@ -1093,7 +1113,7 @@
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
 	if (rc) {
-		cFYI(1, ("\nSend error in QueryReparseLinkInfo = %d\n", rc));
+		cFYI(1, ("Send error in QueryReparseLinkInfo = %d", rc));
 	} else {		/* decode response */
 		pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
 		pSMBr->DataCount = le16_to_cpu(pSMBr->DataCount);
@@ -1121,11 +1141,11 @@
 				}
 			} else {
 				rc = -EIO;
-				cFYI(1,("\nInvalid return data count on get reparse info ioctl"));
+				cFYI(1,("Invalid return data count on get reparse info ioctl"));
 			}
 			symlinkinfo[buflen] = 0; /* just in case so the caller
 					does not go off the end of the buffer */
-			cFYI(1,("\nreadlink result - %s ",symlinkinfo));
+			cFYI(1,("readlink result - %s ",symlinkinfo));
 		}
 	}
 	if (pSMB)
@@ -1146,7 +1166,7 @@
 	int bytes_returned;
 	int name_len;
 
-	cFYI(1, ("\nIn QPathInfo path %s", searchName));
+	cFYI(1, ("In QPathInfo path %s", searchName));
 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
 		      (void **) &pSMBr);
 	if (rc)
@@ -1160,7 +1180,6 @@
 		name_len++;	/* trailing null */
 		name_len *= 2;
 	} else {		/* BB improve the check for buffer overruns BB */
-
 		name_len = strnlen(searchName, 530);
 		name_len++;	/* trailing null */
 		strncpy(pSMB->FileName, searchName, name_len);
@@ -1194,7 +1213,7 @@
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
 	if (rc) {
-		cFYI(1, ("\nSend error in QPathInfo = %d\n", rc));
+		cFYI(1, ("Send error in QPathInfo = %d", rc));
 	} else {		/* decode response */
 		pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
 		if ((pSMBr->ByteCount < 40) || (pSMBr->DataOffset > 512))	/* BB also check enough total bytes returned */
@@ -1223,7 +1242,7 @@
 	int bytes_returned;
 	int name_len;
 
-	cFYI(1, ("\nIn QPathInfo (Unix) the path %s", searchName));
+	cFYI(1, ("In QPathInfo (Unix) the path %s", searchName));
 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
 		      (void **) &pSMBr);
 	if (rc)
@@ -1237,7 +1256,6 @@
 		name_len++;	/* trailing null */
 		name_len *= 2;
 	} else {		/* BB improve the check for buffer overruns BB */
-
 		name_len = strnlen(searchName, 530);
 		name_len++;	/* trailing null */
 		strncpy(pSMB->FileName, searchName, name_len);
@@ -1271,7 +1289,7 @@
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
 	if (rc) {
-		cFYI(1, ("\nSend error in QPathInfo = %d\n", rc));
+		cFYI(1, ("Send error in QPathInfo = %d", rc));
 	} else {		/* decode response */
 		pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
 		if ((pSMBr->ByteCount < 40) || (pSMBr->DataOffset > 512))	/* BB also check enough total bytes returned */
@@ -1300,7 +1318,7 @@
 	int bytes_returned;
 	int name_len;
 
-	cFYI(1, ("\nIn FindUnique"));
+	cFYI(1, ("In FindUnique"));
 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
 		      (void **) &pSMBr);
 	if (rc)
@@ -1314,7 +1332,6 @@
 		name_len++;	/* trailing null */
 		name_len *= 2;
 	} else {		/* BB improve the check for buffer overruns BB */
-
 		name_len = strnlen(searchName, 530);
 		name_len++;	/* trailing null */
 		strncpy(pSMB->FileName, searchName, name_len);
@@ -1353,7 +1370,7 @@
 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
 
 	if (rc) {
-		cFYI(1, ("\nSend error in FindFileDirInfo = %d\n", rc));
+		cFYI(1, ("Send error in FindFileDirInfo = %d", rc));
 	} else {		/* decode response */
 
 		/* BB fill in */
@@ -1378,7 +1395,7 @@
 	int bytes_returned;
 	int name_len;
 
-	cFYI(1, ("\nIn FindFirst"));
+	cFYI(1, ("In FindFirst"));
 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
 		      (void **) &pSMBr);
 	if (rc)
@@ -1392,7 +1409,6 @@
 		name_len++;	/* trailing null */
 		name_len *= 2;
 	} else {		/* BB improve the check for buffer overruns BB */
-
 		name_len = strnlen(searchName, 530);
 		name_len++;	/* trailing null */
 		strncpy(pSMB->FileName, searchName, name_len);
@@ -1401,7 +1417,7 @@
 	pSMB->TotalParameterCount = 12 + name_len /* includes null */ ;
 	pSMB->TotalDataCount = 0;	/* no EAs */
 	pSMB->MaxParameterCount = cpu_to_le16(10);
-	pSMB->MaxDataCount = cpu_to_le16((tcon->ses->maxBuf -
+	pSMB->MaxDataCount = cpu_to_le16((tcon->ses->server->maxBuf -
 					  MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
 	pSMB->MaxSetupCount = 0;
 	pSMB->Reserved = 0;
@@ -1441,7 +1457,7 @@
 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
 
 	if (rc) {		/* BB add logic to retry regular search if Unix search rejected unexpectedly by server */
-		cFYI(1, ("\nError in FindFirst = %d\n", rc));
+		cFYI(1, ("Error in FindFirst = %d", rc));
 	} else {		/* decode response */
 		/* BB add safety checks for these memcpys */
 		if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
@@ -1480,7 +1496,7 @@
 	int rc = 0;
 	int bytes_returned;
 
-	cFYI(1, ("\nIn FindNext"));
+	cFYI(1, ("In FindNext"));
 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
 		      (void **) &pSMBr);
 	if (rc)
@@ -1490,7 +1506,7 @@
 	pSMB->TotalDataCount = 0;	/* no EAs */
 	pSMB->MaxParameterCount = cpu_to_le16(8);
 	pSMB->MaxDataCount =
-	    cpu_to_le16((tcon->ses->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
+	    cpu_to_le16((tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
 	pSMB->MaxSetupCount = 0;
 	pSMB->Reserved = 0;
 	pSMB->Flags = 0;
@@ -1533,7 +1549,7 @@
 		if (rc == -EBADF)
 			rc = 0;	/* search probably was closed at end of search above */
 		else
-			cFYI(1, ("\nFindNext returned = %d\n", rc));
+			cFYI(1, ("FindNext returned = %d", rc));
 	} else {		/* decode response */
 		/* BB add safety checks for these memcpys */
 		if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
@@ -1574,7 +1590,7 @@
 	*number_of_UNC_in_array = 0;
 	*targetUNCs = NULL;
 
-	cFYI(1, ("\nIn GetDFSRefer the path %s", searchName));
+	cFYI(1, ("In GetDFSRefer the path %s", searchName));
 	if (ses == NULL)
 		return -ENODEV;
 
@@ -1591,7 +1607,7 @@
 	if (ses->capabilities & CAP_DFS) {
 		pSMB->hdr.Flags2 |= SMBFLG2_DFS;
 	}
-    if(ses->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
+    if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
        pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
 
 	if (ses->capabilities & CAP_UNICODE) {
@@ -1604,7 +1620,6 @@
 		name_len++;	/* trailing null */
 		name_len *= 2;
 	} else {		/* BB improve the check for buffer overruns BB */
-
 		name_len = strnlen(searchName, 530);
 		name_len++;	/* trailing null */
 		strncpy(pSMB->RequestFileName, searchName, name_len);
@@ -1636,7 +1651,7 @@
 	rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
 	if (rc) {
-		cFYI(1, ("\nSend error in GetDFSRefer = %d\n", rc));
+		cFYI(1, ("Send error in GetDFSRefer = %d", rc));
 	} else {		/* decode response */
 /* BB Add logic to parse referrals here */
 	}
@@ -1656,7 +1671,7 @@
 	int rc = 0;
 	int bytes_returned = 0;
 
-	cFYI(1, ("\nIn QFSInfo"));
+	cFYI(1, ("In QFSInfo"));
 
 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
 		      (void **) &pSMBr);
@@ -1689,11 +1704,11 @@
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
 	if (rc) {
-		cERROR(1, ("\nSend error in QFSInfo = %d\n", rc));
+		cERROR(1, ("Send error in QFSInfo = %d", rc));
 	} else {		/* decode response */
 		pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
 		cFYI(1,
-		     ("\nDecoding qfsinfo response.  BCC: %d  Offset %d\n",
+		     ("Decoding qfsinfo response.  BCC: %d  Offset %d",
 		      pSMBr->ByteCount, pSMBr->DataOffset));
 		if ((pSMBr->ByteCount < 24) || (pSMBr->DataOffset > 512))	/* BB also check enough total bytes returned */
 			rc = -EIO;	/* bad smb */
@@ -1711,7 +1726,7 @@
 			FSData->f_bfree = FSData->f_bavail =
 			    le64_to_cpu(response_data->FreeAllocationUnits);
 			cFYI(1,
-			     ("\nBlocks: %ld  Free: %ld Block size %ld\n",
+			     ("Blocks: %ld  Free: %ld Block size %ld",
 			      FSData->f_blocks, FSData->f_bfree,
 			      FSData->f_bsize));
 		}
@@ -1732,7 +1747,7 @@
 	int rc = 0;
 	int bytes_returned = 0;
 
-	cFYI(1, ("\nIn QFSAttributeInfo"));
+	cFYI(1, ("In QFSAttributeInfo"));
 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
 		      (void **) &pSMBr);
 	if (rc)
@@ -1764,7 +1779,7 @@
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
 	if (rc) {
-		cERROR(1, ("\nSend error in QFSAttributeInfo = %d\n", rc));
+		cERROR(1, ("Send error in QFSAttributeInfo = %d", rc));
 	} else {		/* decode response */
 		pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
 		if ((pSMBr->ByteCount < 13) || (pSMBr->DataOffset > 512)) {	/* BB also check enough bytes returned */
@@ -1794,7 +1809,7 @@
 	int rc = 0;
 	int bytes_returned = 0;
 
-	cFYI(1, ("\nIn QFSDeviceInfo"));
+	cFYI(1, ("In QFSDeviceInfo"));
 
 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
 		      (void **) &pSMBr);
@@ -1828,7 +1843,7 @@
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
 	if (rc) {
-		cERROR(1, ("\nSend error in QFSDeviceInfo = %d\n", rc));
+		cERROR(1, ("Send error in QFSDeviceInfo = %d", rc));
 	} else {		/* decode response */
 		pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
 		if ((pSMBr->ByteCount < sizeof (FILE_SYSTEM_DEVICE_INFO))
@@ -1859,7 +1874,7 @@
 	int rc = 0;
 	int bytes_returned = 0;
 
-	cFYI(1, ("\nIn QFSUnixInfo"));
+	cFYI(1, ("In QFSUnixInfo"));
 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
 		      (void **) &pSMBr);
 	if (rc)
@@ -1891,7 +1906,7 @@
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
 	if (rc) {
-		cERROR(1, ("\nSend error in QFSUnixInfo = %d\n", rc));
+		cERROR(1, ("Send error in QFSUnixInfo = %d", rc));
 	} else {		/* decode response */
 		pSMBr->DataOffset = cpu_to_le16(pSMBr->DataOffset);
 		if ((pSMBr->ByteCount < 13) || (pSMBr->DataOffset > 512)) {
@@ -1927,7 +1942,7 @@
 	int rc = 0;
 	int bytes_returned = 0;
 
-	cFYI(1, ("\nIn SetEOF"));
+	cFYI(1, ("In SetEOF"));
 
 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
 		      (void **) &pSMBr);
@@ -1942,7 +1957,6 @@
 		name_len++;	/* trailing null */
 		name_len *= 2;
 	} else {		/* BB improve the check for buffer overruns BB */
-
 		name_len = strnlen(fileName, 530);
 		name_len++;	/* trailing null */
 		strncpy(pSMB->FileName, fileName, name_len);
@@ -1995,7 +2009,7 @@
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
 	if (rc) {
-		cFYI(1, ("\nSetPathInfo (file size) returned %d\n", rc));
+		cFYI(1, ("SetPathInfo (file size) returned %d", rc));
 	}
 
 	if (pSMB)
@@ -2015,7 +2029,7 @@
 	int bytes_returned = 0;
     __u32 tmp;
 
-	cFYI(1, ("\nSetFileSize (via SetFileInfo)"));
+	cFYI(1, ("SetFileSize (via SetFileInfo)"));
 
 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
 		      (void **) &pSMBr);
@@ -2080,7 +2094,7 @@
 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
 	if (rc) {
 		cFYI(1,
-		     ("\nSend error in SetFileInfo (SetFileSize) = %d\n",
+		     ("Send error in SetFileInfo (SetFileSize) = %d",
 		      rc));
 	}
 
@@ -2100,7 +2114,7 @@
 	int bytes_returned = 0;
 	char *data_offset;
 
-	cFYI(1, ("\nIn SetTimes"));
+	cFYI(1, ("In SetTimes"));
 
 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
 		      (void **) &pSMBr);
@@ -2115,7 +2129,6 @@
 		name_len++;	/* trailing null */
 		name_len *= 2;
 	} else {		/* BB improve the check for buffer overruns BB */
-
 		name_len = strnlen(fileName, 530);
 		name_len++;	/* trailing null */
 		strncpy(pSMB->FileName, fileName, name_len);
@@ -2156,7 +2169,7 @@
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
 	if (rc) {
-		cFYI(1, ("\nSetPathInfo (times) returned %d\n", rc));
+		cFYI(1, ("SetPathInfo (times) returned %d", rc));
 	}
 
 	if (pSMB)
@@ -2176,7 +2189,7 @@
 	int bytes_returned = 0;
 	FILE_UNIX_BASIC_INFO *data_offset;
 
-	cFYI(1, ("\nIn SetUID/GID/Mode"));
+	cFYI(1, ("In SetUID/GID/Mode"));
 
 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
 		      (void **) &pSMBr);
@@ -2191,7 +2204,6 @@
 		name_len++;	/* trailing null */
 		name_len *= 2;
 	} else {		/* BB improve the check for buffer overruns BB */
-
 		name_len = strnlen(fileName, 530);
 		name_len++;	/* trailing null */
 		strncpy(pSMB->FileName, fileName, name_len);
@@ -2232,7 +2244,7 @@
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
 	if (rc) {
-		cFYI(1, ("\nSetPathInfo (perms) returned %d\n", rc));
+		cFYI(1, ("SetPathInfo (perms) returned %d", rc));
 	}
 
 	if (pSMB)
diff -Nru a/fs/cifs/connect.c b/fs/cifs/connect.c
--- a/fs/cifs/connect.c	Mon Feb 17 14:57:28 2003
+++ b/fs/cifs/connect.c	Mon Feb 17 14:57:28 2003
@@ -60,22 +60,61 @@
 
 int ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket);
 
+
+	/* 
+	 * cifs tcp session reconnection
+	 * 
+	 * mark tcp session as reconnecting so temporarily locked
+	 * mark all smb sessions as reconnecting for tcp session  (TBD BB)
+	 * reconnect tcp session
+	 * wake up waiters on reconnection? - (not needed currently)
+	 */
+
 int
 cifs_reconnect(struct TCP_Server_Info *server)
 {
 	int rc = 0;
+	struct list_head *tmp;
+	struct cifsSesInfo *ses;
 
-	cFYI(1, ("\nReconnecting tcp session "));
+	server->tcpStatus = CifsNeedReconnect;
+	server->maxBuf = 0;
 
-	/* lock tcp session */
-	/* mark all smb sessions as reconnecting which use this tcp session */
-	/* reconnect tcp session */
-	/* wake up waiters on reconnection */
-	cFYI(1,
-	     ("\nState: 0x%x Flags: 0x%lx", server->ssocket->state,
-	      server->ssocket->flags));
+	cFYI(1, ("Reconnecting tcp session "));
+
+	read_lock(&GlobalSMBSeslock);
+	list_for_each(tmp, &GlobalSMBSessionList) {
+		ses = list_entry(tmp, struct cifsSesInfo, cifsSessionList);
+		if (ses->server) {
+			if (ses->server == server) {
+				ses->status = CifsNeedReconnect;
+			}
+		}
+		/* else tcp and smb sessions need reconnection */
+	}
+	read_unlock(&GlobalSMBSeslock);
+
+	if(server->ssocket) {
+		cFYI(1,("State: 0x%x Flags: 0x%lx", server->ssocket->state,
+			server->ssocket->flags));
+		server->ssocket->ops->shutdown(server->ssocket,SEND_SHUTDOWN);;
+		cFYI(1,("Post shutdown state: 0x%x Flags: 0x%lx", server->ssocket->state,
+			server->ssocket->flags));
+		sock_release(server->ssocket);
+		server->ssocket = NULL;
+	}
+
+	while ((server->tcpStatus != CifsExiting) && (server->tcpStatus != CifsGood))
+	{
+		rc = ipv4_connect(&server->sockAddr, &server->ssocket);
+		if(rc) {
+			set_current_state(TASK_INTERRUPTIBLE);
+			schedule_timeout(3 * HZ);
+		} else {
+			server->tcpStatus = CifsGood;
+		}
+	}
 
-	ipv4_connect(&server->sockAddr, &server->ssocket);
 	return rc;
 }
 
@@ -99,7 +138,7 @@
 	allow_signal(SIGKILL);
 
 	server->tsk = current;	/* save process info to wake at shutdown */
-	cFYI(1, ("\nDemultiplex PID: %d", current->pid));
+	cFYI(1, ("Demultiplex PID: %d", current->pid));
 
 	temp_fs = get_fs();	/* we must turn off socket api parm checking */
 	set_fs(get_ds());
@@ -112,7 +151,7 @@
 
 		if (smb_buffer == NULL) {
 			cERROR(1,
-			       ("\n Error - can not get mem for SMB response buffer "));
+			       ("Can not get mem for SMB response buffer "));
 			return -ENOMEM;
 		}
 		iov.iov_base = smb_buffer;
@@ -130,25 +169,26 @@
 				 MSG_PEEK /* flags see socket.h */ );
 		if (length < 0) {
 			if (length == -ECONNRESET) {
-				cERROR(1, ("\nConnection reset by peer "));
-				/* BB fix call below */
-				/* cifs_reconnect(server);       */
+				cERROR(1, ("Connection reset by peer "));
+				cifs_reconnect(server);
+				csocket = server->ssocket;
+				continue;
 			} else { /* find define for the -512 returned at unmount time */
 				cFYI(1,
-				       ("\nReceived error on sock_recvmsg( peek) with length = %d\n",
+				       ("Received error on sock_recvmsg( peek) with length = %d",
 					length)); 
 			}
 			break;
 		}
 		if (length == 0) {
 			cFYI(1,
-			     ("\nZero length peek received - dead session?? "));
-			/* schedule_timeout(HZ/4); 
-			   continue; */
-			break;
+			     ("Zero length peek received - dead session?"));
+			cifs_reconnect(server);
+			csocket = server->ssocket;
+			continue;
 		}
 		pdu_length = 4 + ntohl(smb_buffer->smb_buf_length);
-		cFYI(1, ("\nPeek length rcvd: %d with smb length: %d", length, pdu_length));	/* BB */
+		cFYI(1, ("Peek length rcvd: %d with smb length: %d", length, pdu_length));	/* BB */
 
 		temp = (char *) smb_buffer;
 		if (length > 3) {
@@ -157,18 +197,18 @@
 				iov.iov_len = 4;
 				length = sock_recvmsg(csocket, &smb_msg, 4, 0);
 				cFYI(0,
-				     ("\nReceived 4 byte keep alive packet "));
+				     ("Received 4 byte keep alive packet "));
 			} else if ((temp[0] == (char) 0x83)
 				   && (length == 5)) {
 				/* we get this from Windows 98 instead of error on SMB negprot response */
 				cERROR(1,
-				       ("\nNegative RFC 1002 Session response. Error = 0x%x",
+				       ("Negative RFC 1002 Session response. Error = 0x%x",
 					temp[4]));
 				break;
 
 			} else if (temp[0] != (char) 0) {
 				cERROR(1,
-				       ("\nUnknown RFC 1001 frame received not 0x00 nor 0x85"));
+				       ("Unknown RFC 1001 frame received not 0x00 nor 0x85"));
 				cifs_dump_mem(" Received Data is: ", temp, length);
 				break;
 			} else {
@@ -182,7 +222,7 @@
 				     (smb_buffer, smb_buffer->Mid))) {
 					cERROR(1,
 					       (KERN_ERR
-						"\nInvalid size or format for SMB found with length %d and pdu_lenght %d\n",
+						"Invalid size or format for SMB found with length %d and pdu_lenght %d",
 						length, pdu_length));
 					/* BB fix by finding next smb signature - and reading off data until next smb ? BB */
 
@@ -200,11 +240,11 @@
 						   iov.iov_len =  pdu_length-total_read; */
 						length = sock_recvmsg(csocket, &smb_msg, 
                                  pdu_length - total_read, 0);
-         /* cERROR(1,("\nFor iovlen %d Length received: %d with total read %d",
+         /* cERROR(1,("For iovlen %d Length received: %d with total read %d",
 						   iov.iov_len, length,total_read));       */
 						if (length == 0) {
 							cERROR(1,
-							       ("\nZero length receive when expecting %d ",
+							       ("Zero length receive when expecting %d ",
 								pdu_length - total_read));
 							/* BB add reconnect here */
 							break;
@@ -215,11 +255,11 @@
 				dump_smb(smb_buffer, length);
 				if (checkSMB
 				    (smb_buffer, smb_buffer->Mid, total_read)) {
-					cERROR(1, ("\n Bad SMB Received "));
+					cERROR(1, ("Bad SMB Received "));
 					continue;
 				}
 
-                task_to_wake = NULL;
+				task_to_wake = NULL;
 				read_lock(&GlobalMid_Lock);
 				list_for_each(tmp, &server->pending_mid_q) {
 					mid_entry = list_entry(tmp, struct
@@ -228,7 +268,7 @@
 
 					if (mid_entry->mid == smb_buffer->Mid) {
 						cFYI(1,
-						     (" Mid 0x%x matched - waking up\n ",mid_entry->mid));
+						     (" Mid 0x%x matched - waking up ",mid_entry->mid));
 						task_to_wake = mid_entry->tsk;
 						mid_entry->resp_buf =
 						    smb_buffer;
@@ -241,17 +281,17 @@
 					smb_buffer = NULL;	/* will be freed by users thread after he is done */
 					wake_up_process(task_to_wake);
 				} else if (is_valid_oplock_break(smb_buffer) == FALSE) {                          
-                	cERROR(1, ("\n No task to wake, unknown frame rcvd!\n"));
-                }
+					cERROR(1, ("No task to wake, unknown frame rcvd!"));
+				}
 			}
 		} else {
 			cFYI(0,
-			     ("\nFrame less than four bytes received  %d bytes long.",
+			     ("Frame less than four bytes received  %d bytes long.",
 			      length));
 			if (length > 0) {
 				length = sock_recvmsg(csocket, &smb_msg, length, 0);	/* throw away junk frame */
 				cFYI(1,
-				     (" with junk  0x%x in it\n",
+				     (" with junk  0x%x in it ",
 				      *(__u32 *) smb_buffer));
 			}
 		}
@@ -280,13 +320,12 @@
 		kfree(server);
 	} else	/* BB need to more gracefully handle the rare negative session 
 			   response case because response will be still outstanding */
-		cERROR(1, ("\nThere are still active MIDs in queue and we are exiting but we can not delete mid_q_entries or TCP_Server_Info structure due to pending requests MEMORY LEAK!!\n "));	/* BB wake up waitors, and/or wait and/or free stale mids and try again? BB */
+		cERROR(1, ("There are still active MIDs in queue and we are exiting but we can not delete mid_q_entries or TCP_Server_Info structure due to pending requests MEMORY LEAK!!"));	/* BB wake up waitors, and/or wait and/or free stale mids and try again? BB */
 /* BB Need to fix bug in error path above - perhaps wait until smb requests
    time out and then free the tcp per server struct BB */
 	read_unlock(&GlobalSMBSeslock);
 
-
-	cFYI(1, ("\nAbout to exit from demultiplex thread\n"));
+	cFYI(1, ("About to exit from demultiplex thread"));
 	return 0;
 }
 
@@ -315,14 +354,14 @@
 			*value++ = '\0';
 		if (strnicmp(data, "user", 4) == 0) {
 			if (!value || !*value) {
-				printk(KERN_ERR
-				       "CIFS: invalid or missing username");
+				printk(KERN_WARNING
+				       "CIFS: invalid or missing username\n");
 				return 1;	/* needs_arg; */
 			}
 			if (strnlen(value, 200) < 200) {
 				vol->username = value;
 			} else {
-				printk(KERN_ERR "CIFS: username too long");
+				printk(KERN_WARNING "CIFS: username too long\n");
 				return 1;
 			}
 		} else if (strnicmp(data, "pass", 4) == 0) {
@@ -331,15 +370,15 @@
 			} else if (strnlen(value, 17) < 17) {
 				vol->password = value;
 			} else {
-				printk(KERN_ERR "CIFS: password too long");
+				printk(KERN_WARNING "CIFS: password too long\n");
 				return 1;
 			}
 		} else if ((strnicmp(data, "unc", 3) == 0)
 			   || (strnicmp(data, "target", 6) == 0)
 			   || (strnicmp(data, "path", 4) == 0)) {
 			if (!value || !*value) {
-				printk(KERN_ERR
-				       "CIFS: invalid path to network resource");
+				printk(KERN_WARNING
+				       "CIFS: invalid path to network resource\n");
 				return 1;	/* needs_arg; */
 			}
 			if (strnlen(value, 300) < 300) {
@@ -348,26 +387,26 @@
 					vol->UNC[0] = '\\';
 					vol->UNC[1] = '\\';
 				} else if (strncmp(vol->UNC, "\\\\", 2) != 0) {	                   
-					printk(KERN_ERR
-					       "CIFS: UNC Path does not begin with // or \\\\");
+					printk(KERN_WARNING
+					       "CIFS: UNC Path does not begin with // or \\\\ \n");
 					return 1;
 				}
 				vol->UNCip = &vol->UNC[2];
 			} else {
-				printk(KERN_ERR "CIFS: UNC name too long");
+				printk(KERN_WARNING "CIFS: UNC name too long\n");
 				return 1;
 			}
 		} else if ((strnicmp(data, "domain", 3) == 0)
 			   || (strnicmp(data, "workgroup", 5) == 0)) {
 			if (!value || !*value) {
-				printk(KERN_ERR "CIFS: invalid domain name");
+				printk(KERN_WARNING "CIFS: invalid domain name\n");
 				return 1;	/* needs_arg; */
 			}
 			if (strnlen(value, 65) < 65) {
 				vol->domainname = value;
-				cFYI(1, ("\nDomain name set"));
+				cFYI(1, ("Domain name set"));
 			} else {
-				printk(KERN_ERR "CIFS: domain name too long");
+				printk(KERN_WARNING "CIFS: domain name too long\n");
 				return 1;
 			}
 		} else if (strnicmp(data, "uid", 3) == 0) {
@@ -395,9 +434,7 @@
 		} else if (strnicmp(data, "rw", 2) == 0) {
 			vol->rw = TRUE;
 		} else
-			printk(KERN_ERR
-			       "CIFS: Unrecognized mount option %s = %s",
-			       data, value);
+			printk(KERN_WARNING "CIFS: Unknown mount option %s\n",data);
 	}
 	if (vol->UNC == NULL) {
 		if (strnlen(devname, 300) < 300) {
@@ -406,13 +443,12 @@
 				vol->UNC[0] = '\\';
 				vol->UNC[1] = '\\';
 			} else if (strncmp(vol->UNC, "\\\\", 2) != 0) {
-				printk(KERN_ERR
-				       "CIFS: UNC Path does not begin with // or \\\\");
+				printk(KERN_WARNING "CIFS: UNC Path does not begin with // or \\\\ \n");
 				return 1;
 			}
 			vol->UNCip = &vol->UNC[2];
 		} else {
-			printk(KERN_ERR "CIFS: UNC name too long");
+			printk(KERN_WARNING "CIFS: UNC name too long\n");
 			return 1;
 		}
 	}
@@ -458,7 +494,7 @@
 
 	read_lock(&GlobalSMBSeslock);
 	list_for_each(tmp, &GlobalTreeConnectionList) {
-		cFYI(1, ("\nNext tcon - "));
+		cFYI(1, ("Next tcon - "));
 		tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
 		if (tcon->ses) {
 			if (tcon->ses->server) {
@@ -472,13 +508,13 @@
 					/* found a match on the TCP session */
 					/* BB check if reconnection needed */
 					cFYI(1,
-					     ("\nMatched ip, old UNC: %s == new: %s ?",
+					     ("Matched ip, old UNC: %s == new: %s ?",
 					      tcon->treeName, uncName));
 					if (strncmp
 					    (tcon->treeName, uncName,
 					     MAX_TREE_SIZE) == 0) {
 						cFYI(1,
-						     ("\nMatched UNC, old user: %s == new: %s ?",
+						     ("Matched UNC, old user: %s == new: %s ?",
 						      tcon->treeName, uncName));
 						if (strncmp
 						    (tcon->ses->userName,
@@ -522,45 +558,118 @@
 				SERVER_NAME_LEN_WITH_NULL * 2), "\\IPC$", 6);
 		rc = CIFSTCon(xid, pSesInfo, temp_unc, NULL, nls_codepage);
 		cFYI(1,
-		     ("\nCIFS Tcon rc = %d ipc_tid = %d\n", rc,
-		      pSesInfo->ipc_tid));
+		     ("CIFS Tcon rc = %d ipc_tid = %d", rc,pSesInfo->ipc_tid));
 		kfree(temp_unc);
 	}
 	if (rc == 0)
 		rc = CIFSGetDFSRefer(xid, pSesInfo, old_path, &referrals,
 				     &num_referrals, nls_codepage);
 
-	return -ENODEV;		/* BB remove and add return rc; */
+	return -ENODEV;	/* BB remove and add return code processing */
 
 }
 
+int setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo, struct nls_table * nls_info)
+{
+	int rc = 0;
+	char session_key[CIFS_SESSION_KEY_SIZE];
+	char ntlm_session_key[CIFS_SESSION_KEY_SIZE];
+	int ntlmv2_flag = FALSE;
+
+	if(pSesInfo->server->maxBuf == 0) /* no need to send on reconnect */
+		rc = CIFSSMBNegotiate(xid, pSesInfo);
+	pSesInfo->capabilities = pSesInfo->server->capabilities;
+	if (!rc) {
+		cFYI(1,("Security Mode: 0x%x Capabilities: 0x%x Time Zone: %d",
+			pSesInfo->server->secMode,
+			pSesInfo->server->capabilities,
+			pSesInfo->server->timeZone));
+		if (extended_security
+				&& (pSesInfo->capabilities & CAP_EXTENDED_SECURITY)
+				&& (pSesInfo->server->secType == NTLMSSP)) {
+			cFYI(1, ("New style sesssetup "));
+			rc = CIFSSpnegoSessSetup(xid, pSesInfo,
+				NULL /* security blob */, 
+				0 /* blob length */,
+				nls_info);
+		} else if (extended_security
+			   && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY)
+			   && (pSesInfo->server->secType == RawNTLMSSP)) {
+			cFYI(1, ("NTLMSSP sesssetup "));
+			rc = CIFSNTLMSSPNegotiateSessSetup(xid,
+						pSesInfo,
+						&ntlmv2_flag,
+						nls_info);
+			if (!rc) {
+				if(ntlmv2_flag) {
+					cFYI(1,("Able to use the more secure NTLM version 2 password hash"));
+			/* SMBNTv2encrypt( ...);  */ /* BB fix this up - 
+			   and note that Samba client equivalent looks wrong */
+				} else
+					SMBNTencrypt(pSesInfo->password_with_pad,
+						pSesInfo->server->cryptKey,ntlm_session_key);
+
+				/* for better security the weaker lanman hash not sent 
+				   in AuthSessSetup so why bother calculating it */
+				/* toUpper(nls_info,
+					password_with_pad);
+				SMBencrypt(password_with_pad,
+					   pSesInfo->server->cryptKey, session_key); */
+
+				rc = CIFSNTLMSSPAuthSessSetup(xid,
+						pSesInfo,
+						ntlm_session_key,
+						session_key,
+						ntlmv2_flag,
+						nls_info);
+			}
+		} else { /* old style NTLM 0.12 session setup */
+			SMBNTencrypt(pSesInfo->password_with_pad,
+				pSesInfo->server->cryptKey,
+				ntlm_session_key);
+			rc = CIFSSessSetup(xid, pSesInfo,
+				session_key,
+				ntlm_session_key,
+				nls_info);
+		}
+		if (rc) {
+			cERROR(1,("Send error in SessSetup = %d",rc));
+		} else {
+			cFYI(1,("CIFS Session Established successfully"));
+			pSesInfo->status = CifsGood;
+		}
+	}
+	return rc;
+}
+
 int
 ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket)
 {
 	int rc = 0;
 
-	rc = sock_create(PF_INET, SOCK_STREAM, IPPROTO_TCP, csocket);
-	if (rc < 0) {
-		cERROR(1, ("Error creating socket. Aborting operation\n"));
-		return rc;
+	if(*csocket == NULL) {
+	    rc = sock_create(PF_INET, SOCK_STREAM, IPPROTO_TCP, csocket);
+	    if (rc < 0) {
+			cERROR(1, ("Error %d creating socket",rc));
+			*csocket = NULL;
+			return rc;
+	    } else {
+			cFYI(1,("Socket created"));
+		}
 	}
 
 	psin_server->sin_family = AF_INET;
 	psin_server->sin_port = htons(CIFS_PORT);
 
 	rc = (*csocket)->ops->connect(*csocket,
-				      (struct sockaddr *) psin_server,
-				      sizeof (struct sockaddr_in), 0
-		/* Is there a way to fix a polling timeout -
-         and find out what more of the flags really mean? */
-	    );
+					(struct sockaddr *) psin_server,
+					sizeof (struct sockaddr_in),0);
 	if (rc < 0) {
 		psin_server->sin_port = htons(RFC1001_PORT);
 		rc = (*csocket)->ops->connect(*csocket, (struct sockaddr *)
-					      psin_server,
-					      sizeof (struct sockaddr_in), 0);
+					      psin_server, sizeof (struct sockaddr_in),0);
 		if (rc < 0) {
-			cFYI(1, ("Error connecting to socket. %d\n", rc));
+			cFYI(1, ("Error connecting to socket. %d", rc));
 			sock_release(*csocket);
 			*csocket = NULL;
 			return rc;
@@ -578,7 +687,7 @@
 	rc = sock_create(PF_INET6, SOCK_STREAM,
 			 IPPROTO_TCP /* IPPROTO_IPV6 ? */ , csocket);
 	if (rc < 0) {
-		cERROR(1, ("Error creating socket. Aborting operation\n"));
+		cERROR(1, ("Error creating socket. Aborting operation"));
 		return rc;
 	}
 
@@ -597,7 +706,7 @@
 					      sizeof (struct sockaddr_in6), 0);
 		if (rc < 0) {
 			cFYI(1,
-			     ("Error connecting to socket (via ipv6). %d\n",
+			     ("Error connecting to socket (via ipv6). %d",
 			      rc));
 			sock_release(*csocket);
 			*csocket = NULL;
@@ -614,8 +723,7 @@
 {
 	int rc = 0;
 	int xid;
-	int ntlmv2_flag = FALSE;
-	struct socket *csocket;
+	struct socket *csocket = NULL;
 	struct sockaddr_in sin_server;
 /*	struct sockaddr_in6 sin_server6; */
 	struct smb_vol volume_info;
@@ -623,35 +731,33 @@
 	struct cifsSesInfo *existingCifsSes = NULL;
 	struct cifsTconInfo *tcon = NULL;
 	struct TCP_Server_Info *srvTcp = NULL;
-	char cryptKey[CIFS_CRYPTO_KEY_SIZE];
-	char session_key[CIFS_SESSION_KEY_SIZE];
-	char ntlm_session_key[CIFS_SESSION_KEY_SIZE];
-	char password_with_pad[CIFS_ENCPWD_SIZE];
 
 	xid = GetXid();
-	cFYI(0, ("\nEntering cifs_mount. Xid: %d with: %s\n", xid, mount_data));
+	cFYI(0, ("Entering cifs_mount. Xid: %d with: %s", xid, mount_data));
 
 	if(parse_mount_options(mount_data, devname, &volume_info)) {
 		FreeXid(xid);
 		return -EINVAL;
 	}
 
-
 	if (volume_info.username) {
-		cFYI(1, ("\nUsername: %s ", volume_info.username));
+		cFYI(1, ("Username: %s ", volume_info.username));
 
 	} else {
-		cERROR(1, ("\nNo username specified "));	
-        /* Could add ways to allow getting user name from alternate locations */
+		cifserror("No username specified ");
+        /* In userspace mount helper we can get user name from alternate
+           locations such as env variables and files on disk */
+		FreeXid(xid);
+		return -EINVAL;
 	}
 
 	if (volume_info.UNC) {
 		sin_server.sin_addr.s_addr = inet_addr(volume_info.UNCip);
-		cFYI(1, ("\nUNC: %s  ", volume_info.UNC));
+		cFYI(1, ("UNC: %s  ", volume_info.UNC));
 	} else {
 		/* BB we could connect to the DFS root? but which server do we ask? */
 		cERROR(1,
-		       ("\nCIFS mount error: No UNC path (e.g. -o unc=//192.168.1.100/public) specified  "));
+		       ("CIFS mount error: No UNC path (e.g. -o unc=//192.168.1.100/public) specified  "));
 		FreeXid(xid);
 		return -EINVAL;
 	}
@@ -660,12 +766,14 @@
 	    find_tcp_session(sin_server.sin_addr.s_addr,
 			     volume_info.username, &srvTcp);
 	if (srvTcp) {
-		cFYI(1, ("\nExisting tcp session with server found "));                
+		cFYI(1, ("Existing tcp session with server found "));                
 	} else {		/* create socket */
 		rc = ipv4_connect(&sin_server, &csocket);
 		if (rc < 0) {
 			cERROR(1,
-			       ("Error connecting to IPv4 socket. Aborting operation\n"));
+			       ("Error connecting to IPv4 socket. Aborting operation"));
+			if(csocket != NULL)
+				sock_release(csocket);
 			FreeXid(xid);
 			return rc;
 		}
@@ -683,6 +791,7 @@
 			srvTcp->ssocket = csocket;
 			init_waitqueue_head(&srvTcp->response_q);
 			INIT_LIST_HEAD(&srvTcp->pending_mid_q);
+			srvTcp->tcpStatus = CifsGood;
 			kernel_thread((void *) (void *)
 				      cifs_demultiplex_thread, srvTcp,
 				      CLONE_FS | CLONE_FILES | CLONE_VM);
@@ -691,113 +800,32 @@
 
 	if (existingCifsSes) {
 		pSesInfo = existingCifsSes;
-		cFYI(1, ("\nExisting smb sess found "));
+		cFYI(1, ("Existing smb sess found "));
 	} else if (!rc) {
-		cFYI(1, ("\nExisting smb sess not found "));
+		cFYI(1, ("Existing smb sess not found "));
 		pSesInfo = sesInfoAlloc();
 		if (pSesInfo == NULL)
 			rc = -ENOMEM;
 		else {
 			pSesInfo->server = srvTcp;
-			pSesInfo->status = CifsGood;
 			sprintf(pSesInfo->serverName, "%u.%u.%u.%u",
 				NIPQUAD(sin_server.sin_addr.s_addr));
 		}
 
-		/* send negotiate protocol smb */
-		if (!rc)
-			rc = CIFSSMBNegotiate(xid, pSesInfo, cryptKey);
-		cFYI(0, ("\nNegotiate rc = %d ", rc));
-		if (!rc) {
-			cFYI(1, ("\nSecurity Mode: %x", pSesInfo->secMode));
-			cFYI(1,
-			     (" Server Capabilities: %x",
-			      pSesInfo->capabilities));
-			cFYI(1,
-			     (" Time Zone: 0x%x %d\n", pSesInfo->timeZone,
-			      pSesInfo->timeZone));
-
-			memset(password_with_pad, 0, CIFS_ENCPWD_SIZE);
+		if (!rc){   
 			if (volume_info.password)
-				strcpy(password_with_pad, volume_info.password);
-
-			if (extended_security
-			    && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY)
-			    && (pSesInfo->secType == NTLMSSP)) {
-				cFYI(1, ("\nNew style sesssetup "));
-				rc = CIFSSpnegoSessSetup(xid, pSesInfo,
-							 volume_info.
-							 username,
-							 volume_info.
-							 domainname, NULL
-							 /* security blob */
-							 , 0	/* blob length */
-							 , cifs_sb->local_nls);
-			} else if (extended_security
-				   && (pSesInfo->
-				       capabilities & CAP_EXTENDED_SECURITY)
-				   && (pSesInfo->secType == RawNTLMSSP)) {
-				cFYI(1, ("\nNTLMSSP sesssetup "));
-				rc = CIFSNTLMSSPNegotiateSessSetup(xid,
-								pSesInfo,
-								cryptKey,
-								volume_info.domainname,
-								&ntlmv2_flag,
-								cifs_sb->local_nls);
-				if (!rc) {
-					if(ntlmv2_flag) {
-						cFYI(1,("\nAble to use the more secure NTLM version 2 password hash"));
-				/* SMBNTv2encrypt( ...);  */ /* BB fix this up - 
-				   and note that Samba client equivalent looks wrong */
-					} else
-						SMBNTencrypt(password_with_pad,cryptKey,ntlm_session_key);
-
-					/* for better security the weaker lanman hash not sent 
-                       in AuthSessSetup so why bother calculating it */
-
-					/* toUpper(cifs_sb->local_nls,
-						password_with_pad);
-					SMBencrypt(password_with_pad,
-						   cryptKey, session_key); */
-
-					rc = CIFSNTLMSSPAuthSessSetup(xid,
-								pSesInfo,
-								volume_info.
-								username,
-								volume_info.domainname,
-								ntlm_session_key,
-								session_key,
-								ntlmv2_flag,
-								      cifs_sb->local_nls);
-				}
-			} else {	/* old style NTLM 0.12 session setup */
-				SMBNTencrypt(password_with_pad, cryptKey,
-					     ntlm_session_key);
-               /* Removed following few lines to not send old style password 
-                  hash ever - for better security */
-			   /* toUpper(cifs_sb->local_nls, password_with_pad);
-				   SMBencrypt(password_with_pad, cryptKey,session_key); */
-
-				rc = CIFSSessSetup(xid, pSesInfo,
-						   volume_info.username,
-						   volume_info.
-						   domainname,
-						   session_key,
-						   ntlm_session_key,
-						   cifs_sb->local_nls);
-			}
-			if (rc) {
-				cERROR(1,
-				       ("\nSend error in SessSetup = %d\n",
-					rc));
-			} else {
-				cFYI(1,
-				     ("CIFS Session Established successfully "));
+				strncpy(pSesInfo->password_with_pad,
+					volume_info.password,CIFS_ENCPWD_SIZE);
+			if (volume_info.username)
 				strncpy(pSesInfo->userName,
-					volume_info.username,
-					MAX_USERNAME_SIZE);
+					volume_info.username,MAX_USERNAME_SIZE);
+			if (volume_info.domainname)
+				strncpy(pSesInfo->domainName,
+					volume_info.domainname,MAX_USERNAME_SIZE);
+
+			rc = setup_session(xid,pSesInfo, cifs_sb->local_nls);
+			if(!rc)
 				atomic_inc(&srvTcp->socketUseCount);
-			}
 		}
 	}
 
@@ -807,7 +835,7 @@
 		    find_unc(sin_server.sin_addr.s_addr, volume_info.UNC,
 			     volume_info.username);
 		if (tcon) {
-			cFYI(1, ("\nFound match on UNC path "));
+			cFYI(1, ("Found match on UNC path "));
 		} else {
 			tcon = tconInfoAlloc();
 			if (tcon == NULL)
@@ -830,7 +858,7 @@
 					rc = CIFSTCon(xid, pSesInfo,
 						      volume_info.UNC,
 						      tcon, cifs_sb->local_nls);
-					cFYI(1, ("\nCIFS Tcon rc = %d\n", rc));
+					cFYI(1, ("CIFS Tcon rc = %d", rc));
 				}
 				if (!rc)
 					atomic_inc(&pSesInfo->inUse);
@@ -838,7 +866,7 @@
 		}
 	}
 	if (pSesInfo->capabilities & CAP_LARGE_FILES) {
-		cFYI(0, ("\nLarge files supported "));
+		cFYI(0, ("Large files supported "));
 		sb->s_maxbytes = (u64) 1 << 63;
 	} else
 		sb->s_maxbytes = (u64) 1 << 31;	/* 2 GB */
@@ -846,19 +874,21 @@
 /* on error free sesinfo and tcon struct if needed */
 	if (rc) {
 		           /* If find_unc succeeded then rc == 0 so we can not end */
-        if (tcon)  /* up here accidently freeing someone elses tcon struct */
+		if (tcon)  /* up here accidently freeing someone elses tcon struct */
 			tconInfoFree(tcon);
 		if (existingCifsSes == 0) {
 			if (pSesInfo) {
 				if (pSesInfo->server) {
-					cFYI(0,
-					     ("\nAbout to check if we need to do SMBLogoff "));
 					if (pSesInfo->Suid)
 						CIFSSMBLogoff(xid, pSesInfo);
-					wake_up_process(pSesInfo->server->tsk);
+					if(pSesInfo->server->tsk)
+						send_sig(SIGINT,pSesInfo->server->tsk,1);
+					else
+						cFYI(1,("Can not wake captive thread on cleanup of failed mount"));
+					set_current_state(TASK_INTERRUPTIBLE);
 					schedule_timeout(HZ / 4);	/* give captive thread time to exit */
 				} else
-					cFYI(1, ("\nNo session or bad tcon"));
+					cFYI(1, ("No session or bad tcon"));
 				sesInfoFree(pSesInfo);
 				/* pSesInfo = NULL; */
 			}
@@ -876,13 +906,12 @@
 	}
 
 	FreeXid(xid);
-
 	return rc;
 }
 
 int
-CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses, char *user,
-	      char *domain, char session_key[CIFS_SESSION_KEY_SIZE],
+CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
+	      char session_key[CIFS_SESSION_KEY_SIZE],
 	      char session_key2[CIFS_SESSION_KEY_SIZE],
 	      const struct nls_table *nls_codepage)
 {
@@ -891,12 +920,14 @@
 	SESSION_SETUP_ANDX *pSMB;
 	SESSION_SETUP_ANDX *pSMBr;
 	char *bcc_ptr;
+	char *user = ses->userName;
+	char *domain = ses->domainName;
 	int rc = 0;
 	int remaining_words = 0;
 	int bytes_returned = 0;
 	int len;
 
-	cFYI(1, ("\nIn sesssetup "));
+	cFYI(1, ("In sesssetup "));
 
 	smb_buffer = buf_get();
 	if (smb_buffer == 0) {
@@ -910,10 +941,10 @@
 			0 /* no tCon exists yet */ , 13 /* wct */ );
 
 	pSMB->req_no_secext.AndXCommand = 0xFF;
-	pSMB->req_no_secext.MaxBufferSize = cpu_to_le16(ses->maxBuf);
-	pSMB->req_no_secext.MaxMpxCount = cpu_to_le16(ses->maxReq);
+	pSMB->req_no_secext.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
+	pSMB->req_no_secext.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
 
-	if(ses->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
+	if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
 		smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
 
 	pSMB->req_no_secext.Capabilities =
@@ -1136,21 +1167,22 @@
 
 int
 CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses,
-		    char *user, char *domain, char *SecurityBlob,
-		    int SecurityBlobLength,
-		    const struct nls_table *nls_codepage)
+		char *SecurityBlob,int SecurityBlobLength,
+		const struct nls_table *nls_codepage)
 {
 	struct smb_hdr *smb_buffer;
 	struct smb_hdr *smb_buffer_response;
 	SESSION_SETUP_ANDX *pSMB;
 	SESSION_SETUP_ANDX *pSMBr;
 	char *bcc_ptr;
+	char *user = ses->userName;
+	char *domain = ses->domainName;
 	int rc = 0;
 	int remaining_words = 0;
 	int bytes_returned = 0;
 	int len;
 
-	cFYI(1, ("\nIn v2 sesssetup "));
+	cFYI(1, ("In v2 sesssetup "));
 
 	smb_buffer = buf_get();
 	if (smb_buffer == 0) {
@@ -1164,10 +1196,10 @@
 			0 /* no tCon exists yet */ , 12 /* wct */ );
 	pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
 	pSMB->req.AndXCommand = 0xFF;
-	pSMB->req.MaxBufferSize = cpu_to_le16(ses->maxBuf);
-	pSMB->req.MaxMpxCount = cpu_to_le16(ses->maxReq);
+	pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
+	pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
 
-	if(ses->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
+	if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
 		smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
 
 	pSMB->req.Capabilities =
@@ -1276,7 +1308,7 @@
 					bcc_ptr +=
 					    pSMBr->resp.SecurityBlobLength;
 					cFYI(1,
-					     ("\nSecurity Blob Length %d ",
+					     ("Security Blob Length %d ",
 					      pSMBr->resp.SecurityBlobLength));
 				}
 
@@ -1394,9 +1426,7 @@
 
 int
 CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
-			      struct cifsSesInfo *ses,
-			      char *challenge_from_server,
-			      char *domain, int * pNTLMv2_flag,
+			      struct cifsSesInfo *ses, int * pNTLMv2_flag,
 			      const struct nls_table *nls_codepage)
 {
 	struct smb_hdr *smb_buffer;
@@ -1404,6 +1434,7 @@
 	SESSION_SETUP_ANDX *pSMB;
 	SESSION_SETUP_ANDX *pSMBr;
 	char *bcc_ptr;
+	char *domain = ses->domainName;
 	int rc = 0;
 	int remaining_words = 0;
 	int bytes_returned = 0;
@@ -1412,7 +1443,7 @@
 	PNEGOTIATE_MESSAGE SecurityBlob;
 	PCHALLENGE_MESSAGE SecurityBlob2;
 
-	cFYI(1, ("\nIn NTLMSSP sesssetup (negotiate) "));
+	cFYI(1, ("In NTLMSSP sesssetup (negotiate) "));
 	*pNTLMv2_flag = FALSE;
 	smb_buffer = buf_get();
 	if (smb_buffer == 0) {
@@ -1429,10 +1460,10 @@
 	pSMB->req.hdr.Flags |= (SMBFLG_CASELESS | SMBFLG_CANONICAL_PATH_FORMAT);
 
 	pSMB->req.AndXCommand = 0xFF;
-	pSMB->req.MaxBufferSize = cpu_to_le16(ses->maxBuf);
-	pSMB->req.MaxMpxCount = cpu_to_le16(ses->maxReq);
+	pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
+	pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
 
-	if(ses->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
+	if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
 		smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
 
 	pSMB->req.Capabilities =
@@ -1555,7 +1586,7 @@
 		SecurityBlob2 = (PCHALLENGE_MESSAGE) bcc_ptr;
 		if (SecurityBlob2->MessageType != NtLmChallenge) {
 			cFYI(1,
-			     ("\nUnexpected NTLMSSP message type received %d",
+			     ("Unexpected NTLMSSP message type received %d",
 			      SecurityBlob2->MessageType));
 		} else if (ses) {
 			ses->Suid = smb_buffer_response->Uid; /* UID left in le format */ 
@@ -1568,13 +1599,13 @@
 					bcc_ptr +=
 					    pSMBr->resp.SecurityBlobLength;
 					cFYI(1,
-					     ("\nSecurity Blob Length %d ",
+					     ("Security Blob Length %d ",
 					      pSMBr->resp.SecurityBlobLength));
 				}
 
-				cFYI(1, ("\nNTLMSSP Challenge rcvd "));
+				cFYI(1, ("NTLMSSP Challenge rcvd "));
 
-				memcpy(challenge_from_server,
+				memcpy(ses->server->cryptKey,
 				       SecurityBlob2->Challenge,
 				       CIFS_CRYPTO_KEY_SIZE);
 				if(SecurityBlob2->NegotiateFlags & NTLMSSP_NEGOTIATE_NTLMV2)
@@ -1722,16 +1753,16 @@
 
 int
 CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
-			 char *user, char *domain,
-			 char *ntlm_session_key,
-			 char *lanman_session_key, int ntlmv2_flag,
-			 const struct nls_table *nls_codepage)
+		char *ntlm_session_key, char *lanman_session_key, int ntlmv2_flag,
+		const struct nls_table *nls_codepage)
 {
 	struct smb_hdr *smb_buffer;
 	struct smb_hdr *smb_buffer_response;
 	SESSION_SETUP_ANDX *pSMB;
 	SESSION_SETUP_ANDX *pSMBr;
 	char *bcc_ptr;
+	char *user = ses->userName;
+	char *domain = ses->domainName;
 	int rc = 0;
 	int remaining_words = 0;
 	int bytes_returned = 0;
@@ -1739,7 +1770,7 @@
 	int SecurityBlobLength = sizeof (AUTHENTICATE_MESSAGE);
 	PAUTHENTICATE_MESSAGE SecurityBlob;
 
-	cFYI(1, ("\nIn NTLMSSPSessSetup (Authenticate)"));
+	cFYI(1, ("In NTLMSSPSessSetup (Authenticate)"));
 
 	smb_buffer = buf_get();
 	if (smb_buffer == 0) {
@@ -1755,12 +1786,12 @@
 	pSMB->req.hdr.Flags |= (SMBFLG_CASELESS | SMBFLG_CANONICAL_PATH_FORMAT);
 	pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
 	pSMB->req.AndXCommand = 0xFF;
-	pSMB->req.MaxBufferSize = cpu_to_le16(ses->maxBuf);
-	pSMB->req.MaxMpxCount = cpu_to_le16(ses->maxReq);
+	pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
+	pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
 
 	pSMB->req.hdr.Uid = ses->Suid;
 
-	if(ses->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
+	if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
 		smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
 
 	pSMB->req.Capabilities =
@@ -1949,7 +1980,7 @@
 		if (pSMBr->resp.Action & GUEST_LOGIN)
 			cFYI(1, (" Guest login"));	/* BB do we want to set anything in SesInfo struct ? */
 /*        if(SecurityBlob2->MessageType != NtLm??){                               
-                 cFYI("\nUnexpected message type on auth response is %d ")); 
+                 cFYI("Unexpected message type on auth response is %d ")); 
         } */
 		if (ses) {
 			cFYI(1,
@@ -1966,12 +1997,12 @@
 					bcc_ptr +=
 					    pSMBr->resp.SecurityBlobLength;
 					cFYI(1,
-					     ("\nSecurity Blob Length %d ",
+					     ("Security Blob Length %d ",
 					      pSMBr->resp.SecurityBlobLength));
 				}
 
 				cFYI(1,
-				     ("\nNTLMSSP response to Authenticate "));
+				     ("NTLMSSP response to Authenticate "));
 
 				if (smb_buffer->Flags2 &= SMBFLG2_UNICODE) {
 					if ((long) (bcc_ptr) % 2) {
@@ -2133,7 +2164,7 @@
 	bcc_ptr = &(pSMB->Password[0]);
 	bcc_ptr++;		/* skip password */
 
-	if(ses->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
+	if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
 		smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
 
 	if (ses->capabilities & CAP_STATUS32) {
@@ -2163,7 +2194,7 @@
 	rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, &length, 0);
 
 	/* if (rc) rc = map_smb_to_linux_error(smb_buffer_response); */
-    /* above now done in SendReceive */
+	/* above now done in SendReceive */
 	if ((rc == 0) && (tcon != NULL)) {
 		tcon->tid = smb_buffer_response->Tid;
 		bcc_ptr = pByteArea(smb_buffer_response);
@@ -2200,7 +2231,7 @@
 			/* else do not bother copying these informational fields */
 		}
 		tcon->Flags = le16_to_cpu(pSMBr->OptionalSupport);
-		cFYI(1, ("\nTcon flags: 0x%x ", tcon->Flags));
+		cFYI(1, ("Tcon flags: 0x%x ", tcon->Flags));
 	} else if ((rc == 0) && tcon == NULL) {
         /* all we need to save for IPC$ connection */
 		ses->ipc_tid = smb_buffer_response->Tid;
@@ -2229,27 +2260,28 @@
 		}
 		tconInfoFree(cifs_sb->tcon);
 		if ((ses) && (ses->server)) {
-			cFYI(1, ("\nAbout to do SMBLogoff "));
+			cFYI(1, ("About to do SMBLogoff "));
 			rc = CIFSSMBLogoff(xid, ses);
 			if (rc == -EBUSY) {
-				/* BB this looks wrong - why is this here? */
 				FreeXid(xid);
 				return 0;
 			}
+			set_current_state(TASK_INTERRUPTIBLE);
 			schedule_timeout(HZ / 4);	/* give captive thread time to exit */
 			if((ses->server) && (ses->server->ssocket)) {            
-				cFYI(1,("\nWaking up socket by sending it signal "));
+				cFYI(1,("Waking up socket by sending it signal "));
 				send_sig(SIGINT,ses->server->tsk,1);
 			}
 		} else
-			cFYI(1, ("\nNo session or bad tcon"));
+			cFYI(1, ("No session or bad tcon"));
 	}
 	/* BB future check active count of tcon and then free if needed BB */
 	cifs_sb->tcon = NULL;
 	if (ses) {
+		set_current_state(TASK_INTERRUPTIBLE);
 		schedule_timeout(HZ / 2);
 		/* if ((ses->server) && (ses->server->ssocket)) {
-               cFYI(1,("\nReleasing socket "));        
+               cFYI(1,("Releasing socket "));        
                sock_release(ses->server->ssocket); 
                kfree(ses->server); 
           } */ 
diff -Nru a/fs/cifs/dir.c b/fs/cifs/dir.c
--- a/fs/cifs/dir.c	Mon Feb 17 14:57:27 2003
+++ b/fs/cifs/dir.c	Mon Feb 17 14:57:27 2003
@@ -54,7 +54,6 @@
 		temp = temp->d_parent;
 	}
 	namelen += 1;		/* allow for trailing null */
-	cFYI(1, ("Final namelength (in build_path): %d ", namelen));	/* BB remove */
 	full_path = kmalloc(namelen, GFP_KERNEL);
 	namelen--;
 	full_path[namelen] = 0;	/* trailing null */
@@ -66,13 +65,13 @@
 			full_path[namelen] = '\\';
 			strncpy(full_path + namelen + 1, temp->d_name.name,
 				temp->d_name.len);
-			cFYI(1, (" name: %s ", full_path + namelen));	/* BB remove */
+			cFYI(0, (" name: %s ", full_path + namelen));
 		}
 		temp = temp->d_parent;
 	}
 	if (namelen != 0)
 		cERROR(1,
-		       ("\nWe did not end path lookup where we expected namelen is %d",
+		       ("We did not end path lookup where we expected namelen is %d",
 			namelen));
 
 	return full_path;
@@ -111,7 +110,7 @@
 	}
 	if (namelen != 0)
 		cERROR(1,
-		       ("\nWe did not end path lookup where we expected namelen is %d",
+		       ("We did not end path lookup where we expected namelen is %d",
 			namelen));
 
 	return full_path;
@@ -124,7 +123,7 @@
 {
 	int rc = -ENOENT;
 	int xid;
-	int oplock = FALSE;	/* no need to oplock when we are not going to read from the file */
+	int oplock = REQ_OPLOCK;
 	__u16 fileHandle;
 	struct cifs_sb_info *cifs_sb;
 	struct cifsTconInfo *pTcon;
@@ -144,7 +143,7 @@
 			 /* 0x20197 was used previously */ , CREATE_NOT_DIR,
 			 &fileHandle, &oplock, cifs_sb->local_nls);
 	if (rc) {
-		cFYI(1, ("\ncifs_create returned 0x%x ", rc));
+		cFYI(1, ("cifs_create returned 0x%x ", rc));
 	} else {
 		if (pTcon->ses->capabilities & CAP_UNIX)
 			rc = cifs_get_inode_info_unix(&newinode, full_path,
@@ -154,14 +153,17 @@
 						 inode->i_sb);
 
 		if (rc != 0) {
-			cFYI(1,
-			     ("\nCreate worked but get_inode_info failed with rc = %d ",
+			cFYI(1,("Create worked but get_inode_info failed with rc = %d",
 			      rc));
 			/* close handle */
 		} else {
 			direntry->d_op = &cifs_dentry_ops;
 			d_instantiate(direntry, newinode);
 		}
+		/* BB check oplock state before deciding to call following */
+/*        if(*oplock)
+            save off handle in inode and dontdoclose */
+        
 		CIFSSMBClose(xid, pTcon, fileHandle);	
         /* BB In the future chain close with the NTCreateX to narrow window */
         
@@ -204,7 +206,7 @@
 		cFYI(1, (" NULL inode in lookup"));
 	}
 	cFYI(1,
-	     (" Full path: %s inode = 0x%p\n", full_path, direntry->d_inode));
+	     (" Full path: %s inode = 0x%p", full_path, direntry->d_inode));
 	if (pTcon->ses->capabilities & CAP_UNIX)
 		rc = cifs_get_inode_info_unix(&newInode, full_path,
 					      parent_dir_inode->i_sb);
@@ -224,7 +226,7 @@
 		d_add(direntry, NULL);
 	} else {
 		cERROR(1,
-		       ("Error 0x%x or (%d decimal) on cifs_get_inode_info in lookup\n",
+		       ("Error 0x%x or (%d decimal) on cifs_get_inode_info in lookup",
 			rc, rc));
 		/* BB special case check for Access Denied - watch security exposure of returning dir info implicitly via different rc if file exists or not but no access BB */
 	}
@@ -251,7 +253,7 @@
 
 	full_path = build_wildcard_path_from_dentry(file->f_dentry);
 
-	cFYI(1, (" inode = 0x%p and full path is %s\n", inode, full_path));
+	cFYI(1, (" inode = 0x%p and full path is %s", inode, full_path));
 
 	if (full_path)
 		kfree(full_path);
@@ -273,7 +275,7 @@
 		}
 	} else {
 		cFYI(1,
-		     ("In cifs_d_revalidate with no inode but name = %s and dentry 0x%p\n",
+		     ("In cifs_d_revalidate with no inode but name = %s and dentry 0x%p",
 		      direntry->d_name.name, direntry));
 	}
 
@@ -286,7 +288,7 @@
 {
 	int rc = 0;
 
-	cFYI(1, ("In cifs d_delete, name = %s\n", direntry->d_name.name));
+	cFYI(1, ("In cifs d_delete, name = %s", direntry->d_name.name));
 
 	return rc;
 }     */
diff -Nru a/fs/cifs/file.c b/fs/cifs/file.c
--- a/fs/cifs/file.c	Mon Feb 17 14:57:26 2003
+++ b/fs/cifs/file.c	Mon Feb 17 14:57:26 2003
@@ -25,6 +25,7 @@
 #include <linux/fcntl.h>
 #include <linux/version.h>
 #include <linux/pagemap.h>
+#include <linux/pagevec.h>
 #include <linux/smp_lock.h>
 #include <asm/div64.h>
 #include "cifsfs.h"
@@ -85,9 +86,11 @@
 	if (file->f_flags & O_CREAT)
 		disposition = FILE_OVERWRITE;
 
+    /* BB first check if file has batch oplock (or oplock ?) */
+
 	/* BB finish adding in oplock support BB */
 	if (oplockEnabled)
-		oplock = TRUE;
+		oplock = REQ_OPLOCK;
 	else
 		oplock = FALSE;
 
@@ -95,8 +98,8 @@
 	rc = CIFSSMBOpen(xid, pTcon, full_path, disposition, desiredAccess,
 			CREATE_NOT_DIR, &netfid, &oplock, cifs_sb->local_nls);
 	if (rc) {
-		cFYI(1, ("\ncifs_open returned 0x%x ", rc));
-		cFYI(1, (" oplock: %d ", oplock));
+		cFYI(1, ("cifs_open returned 0x%x ", rc));
+		cFYI(1, ("oplock: %d ", oplock));
 	} else {
 		file->private_data =
 		    kmalloc(sizeof (struct cifsFileInfo), GFP_KERNEL);
@@ -142,9 +145,7 @@
 	struct cifs_sb_info *cifs_sb;
 	struct cifsTconInfo *pTcon;
 	struct cifsFileInfo *pSMBFile =
-	    (struct cifsFileInfo *) file->private_data;
-
-	cFYI(1, ("\n  inode = 0x%p with ", inode));
+		(struct cifsFileInfo *) file->private_data;
 
 	xid = GetXid();
 
@@ -172,12 +173,12 @@
 	struct cifsFileInfo *pSMBFileStruct =
 	    (struct cifsFileInfo *) file->private_data;
 
-	cFYI(1, ("\nClosedir inode = 0x%p with ", inode));
+	cFYI(1, ("Closedir inode = 0x%p with ", inode));
 
 	xid = GetXid();
 
 	if (pSMBFileStruct) {
-		cFYI(1, ("\nFreeing private data in close dir"));
+		cFYI(1, ("Freeing private data in close dir"));
 		kfree(file->private_data);
 		file->private_data = NULL;
 	}
@@ -202,42 +203,42 @@
 	xid = GetXid();
 
 	cFYI(1,
-	     ("\nLock parm: 0x%x flockflags: 0x%x flocktype: 0x%x start: %lld end: %lld",
+	     ("Lock parm: 0x%x flockflags: 0x%x flocktype: 0x%x start: %lld end: %lld",
 	      cmd, pfLock->fl_flags, pfLock->fl_type, pfLock->fl_start,
 	      pfLock->fl_end));
 
 	if (pfLock->fl_flags & FL_POSIX)
-		cFYI(1, ("\nPosix "));
+		cFYI(1, ("Posix "));
 	if (pfLock->fl_flags & FL_FLOCK)
-		cFYI(1, ("\nFlock "));
+		cFYI(1, ("Flock "));
 	if (pfLock->fl_flags & FL_SLEEP)
-		cFYI(1, ("\nBlocking lock "));
+		cFYI(1, ("Blocking lock "));
 	if (pfLock->fl_flags & FL_ACCESS)
-		cFYI(1, ("\nProcess suspended by mandatory locking "));
+		cFYI(1, ("Process suspended by mandatory locking "));
 	if (pfLock->fl_flags & FL_LEASE)
-		cFYI(1, ("\nLease on file "));
+		cFYI(1, ("Lease on file "));
 	if (pfLock->fl_flags & 0xFFD0)
-		cFYI(1, ("\n Unknown lock flags "));
+		cFYI(1, ("Unknown lock flags "));
 
 	if (pfLock->fl_type == F_WRLCK) {
-		cFYI(1, ("\nF_WRLCK "));
+		cFYI(1, ("F_WRLCK "));
 		numLock = 1;
 	} else if (pfLock->fl_type == F_UNLCK) {
-		cFYI(1, ("\nF_UNLCK "));
+		cFYI(1, ("F_UNLCK "));
 		numUnlock = 1;
 	} else if (pfLock->fl_type == F_RDLCK) {
-		cFYI(1, ("\nF_RDLCK "));
+		cFYI(1, ("F_RDLCK "));
 		lockType |= LOCKING_ANDX_SHARED_LOCK;
 		numLock = 1;
 	} else if (pfLock->fl_type == F_EXLCK) {
-		cFYI(1, ("\nF_EXLCK "));
+		cFYI(1, ("F_EXLCK "));
 		numLock = 1;
 	} else if (pfLock->fl_type == F_SHLCK) {
-		cFYI(1, ("\nF_SHLCK "));
+		cFYI(1, ("F_SHLCK "));
 		lockType |= LOCKING_ANDX_SHARED_LOCK;
 		numLock = 1;
 	} else
-		cFYI(1, ("\nUnknown type of lock "));
+		cFYI(1, ("Unknown type of lock "));
 
 	cifs_sb = CIFS_SB(file->f_dentry->d_sb);
 	pTcon = cifs_sb->tcon;
@@ -265,7 +266,7 @@
 			pfLock->fl_type = F_UNLCK;
 			if (rc != 0)
 				cERROR(1,
-				       ("\nError unlocking previously locked range %d during test of lock ",
+				       ("Error unlocking previously locked range %d during test of lock ",
 					rc));
 			rc = 0;
 
@@ -304,7 +305,7 @@
 	pTcon = cifs_sb->tcon;
 
 	/*cFYI(1,
-	   (" write %d bytes to offset %lld of %s \n", write_size,
+	   (" write %d bytes to offset %lld of %s", write_size,
 	   *poffset, file->f_dentry->d_name.name)); */
 
 	if (file->private_data == NULL) {
@@ -360,6 +361,7 @@
 	struct inode *inode = page->mapping->host;
 	struct cifsInodeInfo *cifsInode;
 	struct cifsFileInfo *open_file = NULL;
+	struct list_head *tmp;
 	int xid;
 
 	xid = GetXid();
@@ -381,32 +383,39 @@
 		return -EFAULT;
 	}
 
-	if((to > PAGE_CACHE_SIZE) || (from > to))
+	offset += (loff_t)from;
+	write_data += from;
+
+	if((to > PAGE_CACHE_SIZE) || (from > to) || (offset > mapping->host->i_size)) {
+		FreeXid(xid);
 		return -EIO;
+	}
 
-        offset += (loff_t)from;
-	write_data += from;
+	/* check to make sure that we are not extending the file */
+    if(mapping->host->i_size - offset < (loff_t)to)
+		to = (unsigned)(mapping->host->i_size - offset); 
+		
 
 	cifsInode = CIFS_I(mapping->host);
-	if(!list_empty(&(cifsInode->openFileList))) {            
-		open_file = list_entry(cifsInode->openFileList.next,
-					   struct cifsFileInfo, flist);           
+	list_for_each(tmp, &cifsInode->openFileList) {            
+		open_file = list_entry(tmp,struct cifsFileInfo, flist);           
 	/* We could check if file is open for writing first */
-		if(open_file->pfile)
+		if((open_file->pfile) && 
+		   ((open_file->pfile->f_flags & O_RDWR) || 
+			(open_file->pfile->f_flags & O_WRONLY))) {
 			bytes_written = cifs_write(open_file->pfile, write_data,
 					   to-from, &offset);
 		/* Does mm or vfs already set times? */
-		inode->i_atime = inode->i_mtime = CURRENT_TIME;	
-		if ((bytes_written > 0) && (offset)) {
-			rc = 0;
-			if (offset > inode->i_size)
-				inode->i_size = offset;
-		} else if(bytes_written < 0) {
-			rc = bytes_written;
+			inode->i_atime = inode->i_mtime = CURRENT_TIME;
+			if ((bytes_written > 0) && (offset)) {
+				rc = 0;
+			} else if(bytes_written < 0) {
+				rc = bytes_written;
+			}
 		}
-		mark_inode_dirty_sync(inode);
-	} else {
-		cFYI(1,("\nNo open files to get file handle from"));
+	}
+	if(open_file == NULL) {
+		cFYI(1,("No writeable filehandles for inode"));
 		rc = -EIO;
 	}
 
@@ -415,15 +424,29 @@
 }
 
 static int
+cifs_writepages(struct address_space *mapping, struct writeback_control *wbc)
+{
+	int rc = -EFAULT;
+	int xid;
+
+	xid = GetXid();
+/* call 16K write then Setpageuptodate */
+	FreeXid(xid);
+	return rc;
+}
+
+static int
 cifs_writepage(struct page* page, struct writeback_control *wbc)
 {
 	int rc = -EFAULT;
 	int xid;
 
 	xid = GetXid();
+/* BB add check for wbc flags */
 	page_cache_get(page);
+	
 	rc = cifs_partialpagewrite(page,0,PAGE_CACHE_SIZE);
-	/* insert call to SetPageToUpdate like function here? */
+	SetPageUptodate(page); /* BB add check for error and Clearuptodate? */
 	unlock_page(page);
 	page_cache_release(page);	
 	FreeXid(xid);
@@ -434,32 +457,47 @@
 cifs_commit_write(struct file *file, struct page *page, unsigned offset,
 		  unsigned to)
 {
-	int xid,rc;
+	int xid;
+	int rc = 0;
+	struct inode *inode = page->mapping->host;
+	loff_t position = ((loff_t)page->index << PAGE_CACHE_SHIFT) + to;
+	struct cifsFileInfo *open_file;
+	struct cifs_sb_info *cifs_sb;
+
 	xid = GetXid();
 
-	if(offset > to)
-		return -EIO;
-	rc = cifs_partialpagewrite(page,offset,to);
+	if (position > inode->i_size){
+		inode->i_size = position;
+		if (file->private_data == NULL) {
+			rc = -EBADF;
+		} else {
+			cifs_sb = CIFS_SB(inode->i_sb);
+			open_file = (struct cifsFileInfo *)file->private_data;
+			rc = CIFSSMBSetFileSize(xid, cifs_sb->tcon, position,
+				open_file->netfid,open_file->pid,FALSE);
+			cFYI(1,(" SetEOF (commit write) rc = %d",rc));
+		}
+    }
+	set_page_dirty(page);
 
 	FreeXid(xid);
 	return rc;
 }
 
-static int
-cifs_prepare_write(struct file *file, struct page *page, unsigned offset,
-		   unsigned to)
-{
-	return 0;	/* eventually add code to flush any incompatible requests */
-}
-
 int
 cifs_fsync(struct file *file, struct dentry *dentry, int datasync)
 {
 	int xid;
 	int rc = 0;
+	struct inode * inode = file->f_dentry->d_inode;
+
 	xid = GetXid();
-	/* BB fill in code to flush write behind buffers - when we start supporting oplock */
-	cFYI(1, (" name: %s datasync: 0x%x ", dentry->d_name.name, datasync));
+
+	cFYI(1, ("Sync file - name: %s datasync: 0x%x ", 
+		dentry->d_name.name, datasync));
+	
+	rc = filemap_fdatawrite(inode->i_mapping);
+
 	FreeXid(xid);
 	return rc;
 }
@@ -473,6 +511,7 @@
 	unsigned int rpages = 0;
 	int rc = 0;
 
+	cFYI(1,("sync page %p",page));
 	mapping = page->mapping;
 	if (!mapping)
 		return 0;
@@ -483,13 +522,39 @@
 /*	fill in rpages then 
     result = cifs_pagein_inode(inode, index, rpages); *//* BB finish */
 
-	cFYI(1, ("\nrpages is %d for sync page of Index %ld ", rpages, index));
+	cFYI(1, ("rpages is %d for sync page of Index %ld ", rpages, index));
 
 	if (rc < 0)
 		return rc;
 	return 0;
 }
 
+/*
+ * As file closes, flush all cached write data for this inode checking
+ * for write behind errors.
+ *
+ */
+int cifs_flush(struct file *file)
+{
+	struct inode * inode = file->f_dentry->d_inode;
+	int rc = 0;
+
+	/* Rather than do the steps manually: */
+	/* lock the inode for writing */
+	/* loop through pages looking for write behind data (dirty pages) */
+	/* coalesce into contiguous 16K (or smaller) chunks to write to server */
+	/* send to server (prefer in parallel) */
+	/* deal with writebehind errors */
+	/* unlock inode for writing */
+	/* filemapfdatawrite appears easier for the time being */
+
+	rc = filemap_fdatawrite(inode->i_mapping);
+	cFYI(1,("Flush inode %p file %p rc %d",inode,file,rc));
+
+	return rc;
+}
+
+
 ssize_t
 cifs_read(struct file * file, char *read_data, size_t read_size,
 	  loff_t * poffset)
@@ -500,6 +565,7 @@
 	struct cifs_sb_info *cifs_sb;
 	struct cifsTconInfo *pTcon;
 	int xid;
+	char * current_offset;
 
 	xid = GetXid();
 	cifs_sb = CIFS_SB(file->f_dentry->d_sb);
@@ -510,12 +576,13 @@
 		return -EBADF;
 	}
 
-	for (total_read = 0; read_size > total_read; total_read += bytes_read) {
+	for (total_read = 0,current_offset=read_data; read_size > total_read;
+				total_read += bytes_read,current_offset+=bytes_read) {
 		rc = CIFSSMBRead(xid, pTcon,
 				 ((struct cifsFileInfo *) file->
 				  private_data)->netfid,
 				 read_size - total_read, *poffset,
-				 &bytes_read, read_data + total_read);
+				 &bytes_read, &current_offset);
 		if (rc || (bytes_read == 0)) {
 			if (total_read) {
 				break;
@@ -531,8 +598,7 @@
 	return total_read;
 }
 
-int
-cifs_file_mmap(struct file * file, struct vm_area_struct * vma)
+int cifs_file_mmap(struct file * file, struct vm_area_struct * vma)
 {
 	struct dentry * dentry = file->f_dentry;
 	int	rc, xid;
@@ -540,7 +606,7 @@
 	xid = GetXid();
 	rc = cifs_revalidate(dentry);
 	if (rc) {
-		cFYI(1,("Validation prior to mmap failed, error=%d\n", rc));
+		cFYI(1,("Validation prior to mmap failed, error=%d", rc));
 		FreeXid(xid);
 		return rc;
 	}
@@ -549,34 +615,157 @@
 	return rc;
 }
 
+static void cifs_copy_cache_pages(struct address_space *mapping, 
+		struct list_head *pages, int bytes_read, 
+		char *data,struct pagevec * plru_pvec)
+{
+	struct page *page;
+	char * target;
+
+	while (bytes_read > 0) {
+		if(list_empty(pages))
+			break;
+		page = list_entry(pages->prev, struct page, list);
+
+		list_del(&page->list);
+		if (add_to_page_cache(page, mapping, page->index, GFP_KERNEL)) {
+			page_cache_release(page);
+            cFYI(1,("Add page cache failed"));
+			continue;
+		}
+
+		page_cache_get(page);
+		target = kmap(page);
+
+		if(PAGE_CACHE_SIZE > bytes_read) {
+			memcpy(target,data,bytes_read);
+			bytes_read = 0;
+		} else {
+			memcpy(target,data,PAGE_CACHE_SIZE);
+			bytes_read -= PAGE_CACHE_SIZE;
+		}
+
+		if (!pagevec_add(plru_pvec, page))
+			__pagevec_lru_add(plru_pvec);
+		flush_dcache_page(page);
+		SetPageUptodate(page);
+		kunmap(page);
+		unlock_page(page);
+		page_cache_release(page);
+		data += PAGE_CACHE_SIZE;
+	}
+	return;
+}
+
+
+static int
+cifs_readpages(struct file *file, struct address_space *mapping,
+		struct list_head *page_list, unsigned num_pages)
+{
+	int rc = -EACCES;
+	int xid,i;
+	loff_t offset;
+	struct page * page;
+	struct cifs_sb_info *cifs_sb;
+	struct cifsTconInfo *pTcon;
+	int bytes_read = 0;
+	unsigned int read_size;
+	char * smb_read_data = 0;
+	struct smb_com_read_rsp * pSMBr;
+	struct pagevec lru_pvec;
+
+	xid = GetXid();
+	if (file->private_data == NULL) {
+		FreeXid(xid);
+		return -EBADF;
+	}
+
+	cifs_sb = CIFS_SB(file->f_dentry->d_sb);
+	pTcon = cifs_sb->tcon;
+
+	pagevec_init(&lru_pvec, 0);
+
+	for(i = 0;i<num_pages;) {
+
+		if(list_empty(page_list)) {
+			break;
+		}
+		page = list_entry(page_list->prev, struct page, list);
+		offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
+		/* for reads over a certain size could initiate async read ahead */
+
+		cFYI(0,("Read %d pages into cache at offset %ld ",
+			num_pages-i, (unsigned long) offset)); 
+		
+		read_size = (num_pages - i) * PAGE_CACHE_SIZE;
+		rc = CIFSSMBRead(xid, pTcon,
+			((struct cifsFileInfo *) file->
+			 private_data)->netfid,
+			 read_size, offset,
+			 &bytes_read, &smb_read_data);
+
+		if ((rc < 0) || (smb_read_data == NULL)) {
+			cFYI(1,("Read error in readpages: %d",rc));
+			/* clean up remaing pages off list */
+			while (!list_empty(page_list) && (i < num_pages)) {
+				page = list_entry(page_list->prev, struct page, list);
+				list_del(&page->list);
+			}
+			break;
+		} else if (bytes_read > 0){
+			pSMBr = (struct smb_com_read_rsp *)smb_read_data;
+			cifs_copy_cache_pages(mapping, page_list, bytes_read,
+				smb_read_data + 4 /* RFC1000 hdr */ +
+				le16_to_cpu(pSMBr->DataOffset), &lru_pvec);
+			i +=  bytes_read >> PAGE_CACHE_SHIFT;
+			if((bytes_read & PAGE_CACHE_MASK) != bytes_read) {
+				cFYI(1,("Partial page %d of %d read to cache",i++,num_pages));
+				break;
+			}
+		} else {
+			cFYI(1,("No bytes read"));
+			break;
+		}
+		if(smb_read_data) {
+			buf_release(smb_read_data);
+            smb_read_data = 0;
+        }
+        bytes_read = 0;
+	}
+
+	pagevec_lru_add(&lru_pvec);
+
+	FreeXid(xid);
+	return rc;
+}
+
 static int
 cifs_readpage(struct file *file, struct page *page)
 {
 	loff_t offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
 	char * read_data;
 	int rc = -EACCES;
-	struct cifs_sb_info *cifs_sb;
-	struct cifsTconInfo *pTcon;
 	int xid;
 
 	xid = GetXid();
-	cifs_sb = CIFS_SB(file->f_dentry->d_sb);
-	pTcon = cifs_sb->tcon;
 
 	if (file->private_data == NULL) {
 		FreeXid(xid);
 		return -EBADF;
 	}
+
+	cFYI(0,("readpage %p at offset %d 0x%x\n",page,(int)offset,(int)offset));
+
 	page_cache_get(page);
 	read_data = kmap(page);
-	/* for reads over a certain size we could initiate async read ahead */
+	/* for reads over a certain size could initiate async read ahead */
 
 	rc = cifs_read(file, read_data, PAGE_CACHE_SIZE, &offset);
 
 	if (rc < 0)
 		goto io_error;
 	else {
-		cFYI(1,("\nBytes read %d ",rc));
+		cFYI(1,("Bytes read %d ",rc));
 	}
 
 	file->f_dentry->d_inode->i_atime = CURRENT_TIME;
@@ -610,38 +799,41 @@
 	cifsInfo->time = jiffies;
 	atomic_inc(&cifsInfo->inUse);	/* inc on every refresh of inode info */
 
-	/* Linux can not store file creation time unfortunately so we ignore it */
+	/* Linux can not store file creation time unfortunately so ignore it */
 	tmp_inode->i_atime =
 	    cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastAccessTime));
 	tmp_inode->i_mtime =
 	    cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastWriteTime));
 	tmp_inode->i_ctime =
 	    cifs_NTtimeToUnix(le64_to_cpu(pfindData->ChangeTime));
-	/* should we treat the dos attribute of read-only as read-only mode bit e.g. 555 */
-	tmp_inode->i_mode = S_IALLUGO & ~(S_ISUID | S_IXGRP);	/* 2767 perms - indicate mandatory locking */
+	/* treat dos attribute of read-only as read-only mode bit e.g. 555? */
+	/* 2767 perms - indicate mandatory locking */
+	tmp_inode->i_mode = S_IALLUGO & ~(S_ISUID | S_IXGRP);
 	cFYI(0,
-	     ("\nCIFS FFIRST: Attributes came in as 0x%x",
+	     ("CIFS FFIRST: Attributes came in as 0x%x",
 	      pfindData->ExtFileAttributes));
 	if (pfindData->ExtFileAttributes & ATTR_REPARSE) {
 		*pobject_type = DT_LNK;
-		tmp_inode->i_mode |= S_IFLNK;	/* BB can this and S_IFREG or S_IFDIR be set at same time as in Windows? */
+		/* BB can this and S_IFREG or S_IFDIR be set as in Windows? */
+		tmp_inode->i_mode |= S_IFLNK;
 	} else if (pfindData->ExtFileAttributes & ATTR_DIRECTORY) {
 		*pobject_type = DT_DIR;
-		tmp_inode->i_mode = S_IRWXUGO;	/* override default perms since we do not lock dirs */
+		/* override default perms since we do not lock dirs */
+		tmp_inode->i_mode = S_IRWXUGO;
 		tmp_inode->i_mode |= S_IFDIR;
 	} else {
 		*pobject_type = DT_REG;
 		tmp_inode->i_mode |= S_IFREG;
 	}/* could add code here - to validate if device or weird share type? */
 
-	/* can not fill in nlink here as in qpathinfo version and in Unx search */
+	/* can not fill in nlink here as in qpathinfo version and Unx search */
 	tmp_inode->i_size = pfindData->EndOfFile;
 	tmp_inode->i_blocks =
 	    do_div(pfindData->AllocationSize, tmp_inode->i_blksize);
 	if (pfindData->AllocationSize < pfindData->EndOfFile)
-		cFYI(1, ("\nServer inconsistency Error: it says allocation size less than end of file "));
+		cFYI(1, ("Possible sparse file: allocation size less than end of file "));
 	cFYI(1,
-	     ("\nCIFS FFIRST: Size %ld and blocks %ld and blocksize %ld",
+	     ("File Size %ld and blocks %ld and blocksize %ld",
 	      (unsigned long) tmp_inode->i_size, tmp_inode->i_blocks,
 	      tmp_inode->i_blksize));
 	if (S_ISREG(tmp_inode->i_mode)) {
@@ -657,7 +849,7 @@
 		cFYI(1, (" Symbolic Link inode "));
 		tmp_inode->i_op = &cifs_symlink_inode_ops;
 	} else {
-		cFYI(1, ("\nInit special inode "));
+		cFYI(1, (" Init special inode "));
 		init_special_inode(tmp_inode, tmp_inode->i_mode,
 				   kdev_t_to_nr(tmp_inode->i_rdev));
 	}
@@ -726,7 +918,7 @@
 		tmp_inode->i_op = &cifs_symlink_inode_ops;
 /* tmp_inode->i_fop = *//* do not need to set to anything */
 	} else {
-		cFYI(1, ("\nInit special inode "));
+		cFYI(1, (" Init special inode "));
 		init_special_inode(tmp_inode, tmp_inode->i_mode,
 				   kdev_t_to_nr(tmp_inode->i_rdev));
 	}
@@ -740,22 +932,21 @@
 	struct cifs_sb_info *cifs_sb;
 	struct cifsTconInfo *pTcon;
 
-	cFYI(1, ("\nFor %s ", qstring->name));
+	cFYI(1, ("For %s ", qstring->name));
 	cifs_sb = CIFS_SB(file->f_dentry->d_sb);
 	pTcon = cifs_sb->tcon;
 
 	qstring->hash = full_name_hash(qstring->name, qstring->len);
 	tmp_dentry = d_lookup(file->f_dentry, qstring);
 	if (tmp_dentry) {
-		cFYI(1, (" existing dentry with inode 0x%p ", tmp_dentry->d_inode));	/* BB remove */
+		cFYI(0, (" existing dentry with inode 0x%p", tmp_dentry->d_inode));
 		*ptmp_inode = tmp_dentry->d_inode;
 		/* BB overwrite the old name? i.e. tmp_dentry->d_name and tmp_dentry->d_name.len ?? */
 	} else {
 		tmp_dentry = d_alloc(file->f_dentry, qstring);
 		*ptmp_inode = new_inode(file->f_dentry->d_sb);
-		cFYI(1, ("\nAlloc new inode %p ", *ptmp_inode));
 		tmp_dentry->d_op = &cifs_dentry_ops;
-		cFYI(1, (" instantiate dentry 0x%p with inode 0x%p ",
+		cFYI(0, (" instantiate dentry 0x%p with inode 0x%p ",
 			 tmp_dentry, *ptmp_inode));
 		d_instantiate(tmp_dentry, *ptmp_inode);
 		d_rehash(tmp_dentry);
@@ -763,8 +954,8 @@
 
 	tmp_dentry->d_time = jiffies;
 	(*ptmp_inode)->i_blksize =
-	    (pTcon->ses->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFE00;
-	cFYI(1, ("\ni_blksize = %ld", (*ptmp_inode)->i_blksize));
+	    (pTcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFE00;
+	cFYI(1, ("i_blksize = %ld", (*ptmp_inode)->i_blksize));
 	*pnew_dentry = tmp_dentry;
 }
 
@@ -836,14 +1027,14 @@
 
 	full_path = build_wildcard_path_from_dentry(file->f_dentry);
 
-	cFYI(1, ("\nFull path: %s start at: %lld ", full_path, file->f_pos));
+	cFYI(1, ("Full path: %s start at: %lld ", full_path, file->f_pos));
 
 	switch ((int) file->f_pos) {
 	case 0:
 		if (filldir
 		    (direntry, ".", 1, file->f_pos,
 		     file->f_dentry->d_inode->i_ino, DT_DIR) < 0) {
-			cERROR(1, ("\nFilldir for current dir failed "));
+			cERROR(1, ("Filldir for current dir failed "));
 			break;
 		}
 		file->f_pos++;
@@ -852,7 +1043,7 @@
 		if (filldir
 		    (direntry, "..", 2, file->f_pos,
 		     file->f_dentry->d_parent->d_inode->i_ino, DT_DIR) < 0) {
-			cERROR(1, ("\nFilldir for parent dir failed "));
+			cERROR(1, ("Filldir for parent dir failed "));
 			break;
 		}
 		file->f_pos++;
@@ -957,13 +1148,13 @@
 		if (file->private_data == NULL) {
 			rc = -EBADF;
 			cFYI(1,
-			     ("\nReaddir on closed srch, pos = %lld",
+			     ("Readdir on closed srch, pos = %lld",
 			      file->f_pos));
 		} else {
 			cifsFile = (struct cifsFileInfo *) file->private_data;
 			if (cifsFile->endOfSearch) {
 				rc = 0;
-				cFYI(1, ("\nEnd of search "));
+				cFYI(1, ("End of search "));
 				break;
 			}
 			searchHandle = cifsFile->netfid;
@@ -1077,17 +1268,28 @@
 
 struct address_space_operations cifs_addr_ops = {
 	.readpage = cifs_readpage,
+	.readpages = cifs_readpages,
 	.writepage = cifs_writepage,
-	.prepare_write = cifs_prepare_write,
+	.prepare_write = simple_prepare_write,
 	.commit_write = cifs_commit_write,
-/*	.sync_page = cifs_sync_page, */
+	.sync_page = cifs_sync_page, 
 };
 
-/* change over to struct below when sync page tested and complete */
-struct address_space_operations cifs_addr_ops2 = {
+struct address_space_operations cifs_addr_ops_writethrough = {
 	.readpage = cifs_readpage,
+	.readpages = cifs_readpages,
 	.writepage = cifs_writepage,
-	.prepare_write = cifs_prepare_write,
+	.prepare_write = simple_prepare_write,
 	.commit_write = cifs_commit_write,
 	.sync_page = cifs_sync_page,
 };
+
+struct address_space_operations cifs_addr_ops_nocache = {
+	.readpage = cifs_readpage,
+	.readpages = cifs_readpages,
+	.writepage = cifs_writepage,
+	.prepare_write = simple_prepare_write,
+	.commit_write = cifs_commit_write,
+	.sync_page = cifs_sync_page,
+};
+
diff -Nru a/fs/cifs/inode.c b/fs/cifs/inode.c
--- a/fs/cifs/inode.c	Mon Feb 17 14:57:26 2003
+++ b/fs/cifs/inode.c	Mon Feb 17 14:57:26 2003
@@ -19,6 +19,7 @@
  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  */
 #include <linux/fs.h>
+#include <linux/buffer_head.h>
 #include <linux/stat.h>
 #include <asm/div64.h>
 #include "cifsfs.h"
@@ -44,7 +45,7 @@
 	xid = GetXid();
 
 	pTcon = cifs_sb->tcon;
-	cFYI(1, ("\nGetting info on %s ", search_path));
+	cFYI(1, (" Getting info on %s ", search_path));
 	/* we could have done a find first instead but this returns more info */
 	rc = CIFSSMBUnixQPathInfo(xid, pTcon, search_path, &findData,
 				  cifs_sb->local_nls);
@@ -85,7 +86,7 @@
 		/* get new inode */
 		if (*pinode == NULL) {
 			*pinode = new_inode(sb);
-			cFYI(1, ("\nAlloc new inode %p ", *pinode));
+			cFYI(1, (" Alloc new inode %p ", *pinode));
 		}
 		inode = *pinode;
 /*        new_inode = iget(parent_dir_inode->i_sb, findData.IndexNumber); */
@@ -93,7 +94,7 @@
 
 		cifsInfo = CIFS_I(inode);
 
-		cFYI(1, ("\nOld time %ld ", cifsInfo->time));
+		cFYI(1, (" Old time %ld ", cifsInfo->time));
 		cifsInfo->time = jiffies;
 		cFYI(1, (" New time %ld ", cifsInfo->time));
 		atomic_inc(&cifsInfo->inUse);	/* inc on every refresh of inode */
@@ -129,12 +130,12 @@
 		findData.EndOfFile = le64_to_cpu(findData.EndOfFile);
 		inode->i_size = findData.EndOfFile;
 		inode->i_blksize =
-		    (pTcon->ses->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFE00;
+		    (pTcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFE00;
 		inode->i_blocks = do_div(findData.NumOfBytes, inode->i_blksize);
 		if (findData.NumOfBytes < findData.EndOfFile)
-			cFYI(1, ("\nServer inconsistency Error: it says allocation size less than end of file "));
+			cFYI(1, ("Server inconsistency Error: it says allocation size less than end of file "));
 		cFYI(1,
-		     ("\nCIFS FFIRST: Size %ld and blocks %ld ",
+		     ("Size %ld and blocks %ld ",
 		      (unsigned long) inode->i_size, inode->i_blocks));
 		if (S_ISREG(inode->i_mode)) {
 			cFYI(1, (" File inode "));
@@ -150,7 +151,7 @@
 			inode->i_op = &cifs_symlink_inode_ops;
 /* tmp_inode->i_fop = *//* do not need to set to anything */
 		} else {
-			cFYI(1, ("\nInit special inode "));
+			cFYI(1, (" Init special inode "));
 			init_special_inode(inode, inode->i_mode,
 					   kdev_t_to_nr(inode->i_rdev));
 		}
@@ -174,7 +175,7 @@
 	xid = GetXid();
 
 	pTcon = cifs_sb->tcon;
-	cFYI(1, ("\nGetting info on %s ", search_path));
+	cFYI(1, (" Getting info on %s ", search_path));
 	/* we could have done a find first instead but this returns more info */
 	rc = CIFSSMBQPathInfo(xid, pTcon, search_path, &findData,
 			      cifs_sb->local_nls);
@@ -214,20 +215,20 @@
 		/* get new inode */
 		if (*pinode == NULL) {
 			*pinode = new_inode(sb);
-			cFYI(1, ("\nAlloc new inode %p ", *pinode));
+			cFYI(1, (" Alloc new inode %p ", *pinode));
 		}
 
 		inode = *pinode;
 		cifsInfo = CIFS_I(inode);
 		findData.Attributes = le32_to_cpu(findData.Attributes);
 		cifsInfo->cifsAttrs = findData.Attributes;
-		cFYI(1, ("\nOld time %ld ", cifsInfo->time));
+		cFYI(1, (" Old time %ld ", cifsInfo->time));
 		cifsInfo->time = jiffies;
 		cFYI(1, (" New time %ld ", cifsInfo->time));
 		atomic_inc(&cifsInfo->inUse);	/* inc on every refresh of inode */
 
 		inode->i_blksize =
-		    (pTcon->ses->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFE00;
+		    (pTcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFE00;
 		/* Linux can not store file creation time unfortunately so we ignore it */
 		inode->i_atime =
 		    cifs_NTtimeToUnix(le64_to_cpu(findData.LastAccessTime));
@@ -239,7 +240,7 @@
 		/* should we treat the dos attribute of read-only as read-only mode bit e.g. 555 */
 		inode->i_mode = S_IALLUGO & ~(S_ISUID | S_IXGRP);	/* 2767 perms indicate mandatory locking - will override for dirs later */
 		cFYI(0,
-		     ("\nAttributes came in as 0x%x\n", findData.Attributes));
+		     (" Attributes came in as 0x%x ", findData.Attributes));
 		if (findData.Attributes & ATTR_REPARSE) {	
    /* Can IFLNK be set as it basically is on windows with IFREG or IFDIR? */
 			inode->i_mode |= S_IFLNK;
@@ -256,7 +257,7 @@
 		inode->i_blocks =
 		    do_div(findData.AllocationSize, inode->i_blksize);
 		cFYI(1,
-		     ("\n Size %ld and blocks %ld ",
+		     (" Size %ld and blocks %ld ",
 		      (unsigned long) inode->i_size, inode->i_blocks));
 		inode->i_nlink = le32_to_cpu(findData.NumberOfLinks);
 
@@ -307,7 +308,7 @@
 	char *full_path = NULL;
 	struct cifsInodeInfo *cifsInode;
 
-	cFYI(1, ("\n cifs_unlink, inode = 0x%p with ", inode));
+	cFYI(1, (" cifs_unlink, inode = 0x%p with ", inode));
 
 	xid = GetXid();
 
@@ -356,7 +357,7 @@
 	char *full_path = NULL;
 	struct inode *newinode = NULL;
 
-	cFYI(1, ("In cifs_mkdir, mode = 0x%x inode = 0x%p\n", mode, inode));
+	cFYI(1, ("In cifs_mkdir, mode = 0x%x inode = 0x%p ", mode, inode));
 
 	xid = GetXid();
 
@@ -367,7 +368,7 @@
 	/* BB add setting the equivalent of mode via CreateX w/ACLs */
 	rc = CIFSSMBMkDir(xid, pTcon, full_path, cifs_sb->local_nls);
 	if (rc) {
-		cFYI(1, ("\ncifs_mkdir returned 0x%x ", rc));
+		cFYI(1, ("cifs_mkdir returned 0x%x ", rc));
 	} else {
 		inode->i_nlink++;
 		if (pTcon->ses->capabilities & CAP_UNIX)
@@ -407,7 +408,7 @@
 	char *full_path = NULL;
 	struct cifsInodeInfo *cifsInode;
 
-	cFYI(1, ("\nn cifs_rmdir, inode = 0x%p with ", inode));
+	cFYI(1, (" cifs_rmdir, inode = 0x%p with ", inode));
 
 	xid = GetXid();
 
@@ -493,7 +494,7 @@
 
 	full_path = build_path_from_dentry(direntry);
 	cFYI(1,
-	     (" full path: %s for inode 0x%p with count %d dentry: 0x%p d_time %ld at time %ld \n",
+	     (" full path: %s for inode 0x%p with count %d dentry: 0x%p d_time %ld at time %ld ",
 	      full_path, direntry->d_inode,
 	      direntry->d_inode->i_count.counter, direntry,
 	      direntry->d_time, jiffies));
@@ -562,7 +563,7 @@
 		full_path = build_path_from_dentry(dirent);
 		rc = CIFSSMBSetEOF(xid, pTcon, full_path, inode->i_size,FALSE,
 				   cifs_sb->local_nls);
-		cFYI(1,("\nSetEOF (truncate) rc = %d",rc));
+		cFYI(1,(" SetEOF (truncate) rc = %d",rc));
 		if(rc == -ETXTBSY) {        
 			cifsInode = CIFS_I(inode);
 			if(!list_empty(&(cifsInode->openFileList))) {            
@@ -572,7 +573,7 @@
 				 rc = CIFSSMBSetFileSize(xid, pTcon, inode->i_size,
 					open_file->netfid,open_file->pid,FALSE);
 			} else {
-				  cFYI(1,("\nNo open files to get file handle from"));
+				  cFYI(1,(" No open files to get file handle from"));
 			}
 		}
 		if (!rc)
@@ -604,7 +605,7 @@
 	xid = GetXid();
 
 	cFYI(1,
-	     ("\nIn cifs_setattr, name = %s attrs->iavalid 0x%x\n",
+	     (" In cifs_setattr, name = %s attrs->iavalid 0x%x ",
 	      direntry->d_name.name, attrs->ia_valid));
 	cifs_sb = CIFS_SB(direntry->d_inode->i_sb);
 	pTcon = cifs_sb->tcon;
@@ -614,12 +615,12 @@
 
 	/* BB check if we need to refresh inode from server now ? BB */
 
-	cFYI(1, ("\nChanging attributes 0x%x", attrs->ia_valid));
+	cFYI(1, (" Changing attributes 0x%x", attrs->ia_valid));
 
 	if (attrs->ia_valid & ATTR_SIZE) {
 		rc = CIFSSMBSetEOF(xid, pTcon, full_path, attrs->ia_size,FALSE,
 				   cifs_sb->local_nls);
-		cFYI(1,("\nSetEOF (setattrs) rc = %d",rc));
+		cFYI(1,(" SetEOF (setattrs) rc = %d",rc));
 
 		if(rc == -ETXTBSY) {
 			if(!list_empty(&(cifsInode->openFileList))) {            
@@ -629,29 +630,30 @@
 				rc = CIFSSMBSetFileSize(xid, pTcon, attrs->ia_size,
 					   open_file->netfid,open_file->pid,FALSE);           
 			} else {
-				cFYI(1,("\nNo open files to get file handle from"));
+				cFYI(1,(" No open files to get file handle from"));
 			}
 		}
-        /*  Set Allocation Size of file - might not even need to call the
-            following but might as well and it does not hurt if it fails */
-		CIFSSMBSetEOF(xid, pTcon, full_path, attrs->ia_size, TRUE, cifs_sb->local_nls);
-		if (rc == 0)
-			vmtruncate(direntry->d_inode, attrs->ia_size);
-		/* BB add special case to handle sharing violation (due to Samba bug)
-		   by calling SetFileInfo to set the sizes */
+        /*  For Allocation Size - do not need to call the following
+            it did not hurt if it fails but why bother */
+	/*	CIFSSMBSetEOF(xid, pTcon, full_path, attrs->ia_size, TRUE, cifs_sb->local_nls);*/
+		if (rc == 0) {
+			rc = vmtruncate(direntry->d_inode, attrs->ia_size);
+			nobh_truncate_page(direntry->d_inode->i_mapping, direntry->d_inode->i_size);
+/*          cFYI(1,("truncate_page to 0x%lx \n",direntry->d_inode->i_size)); */
+		}
 	}
 	if (attrs->ia_valid & ATTR_UID) {
-		cFYI(1, ("\nCIFS - UID changed to %d", attrs->ia_uid));
+		cFYI(1, (" CIFS - UID changed to %d", attrs->ia_uid));
 		uid = attrs->ia_uid;
 		/*        entry->uid = cpu_to_le16(attr->ia_uid); */
 	}
 	if (attrs->ia_valid & ATTR_GID) {
-		cFYI(1, ("\nCIFS - GID changed to %d", attrs->ia_gid));
+		cFYI(1, (" CIFS - GID changed to %d", attrs->ia_gid));
 		gid = attrs->ia_gid;
 		/*      entry->gid = cpu_to_le16(attr->ia_gid); */
 	}
 	if (attrs->ia_valid & ATTR_MODE) {
-		cFYI(1, ("\nCIFS - Mode changed to 0x%x", attrs->ia_mode));
+		cFYI(1, (" CIFS - Mode changed to 0x%x", attrs->ia_mode));
 		mode = attrs->ia_mode;
 		/*      entry->mode = cpu_to_le16(attr->ia_mode); */
 	}
@@ -680,7 +682,7 @@
 
 	if (attrs->ia_valid & ATTR_CTIME) {
 		set_time = TRUE;
-		cFYI(1, ("\nCIFS - CTIME changed ")); /* BB probably do not need */
+		cFYI(1, (" CIFS - CTIME changed ")); /* BB probably do not need */
 		time_buf.ChangeTime =
 		    cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_ctime));
 	} else
@@ -695,7 +697,7 @@
 		rc = CIFSSMBSetTimes(xid, pTcon, full_path, &time_buf,
 				     cifs_sb->local_nls);
 	}
-	cifsInode->time = 0; /* force revalidate to get attributes when needed */
+/*	cifsInode->time = 0; */ /* force revalidate to get attributes when needed */
 
 	if (full_path)
 		kfree(full_path);
@@ -707,7 +709,7 @@
 cifs_delete_inode(struct inode *inode)
 {
 	/* Note: called without the big kernel filelock - remember spinlocks! */
-	cFYI(1, ("In cifs_delete_inode, inode = 0x%p\n", inode));
+	cFYI(1, ("In cifs_delete_inode, inode = 0x%p ", inode));
 	/* may have to add back in when safe distributed caching of
              directories via e.g. FindNotify added */
 }
diff -Nru a/fs/cifs/link.c b/fs/cifs/link.c
--- a/fs/cifs/link.c	Mon Feb 17 14:57:27 2003
+++ b/fs/cifs/link.c	Mon Feb 17 14:57:27 2003
@@ -88,7 +88,7 @@
 
 	xid = GetXid();
 	full_path = build_path_from_dentry(direntry);
-	cFYI(1, ("\nFull path: %s inode = 0x%p\n", full_path, inode));
+	cFYI(1, ("Full path: %s inode = 0x%p", full_path, inode));
 	cifs_sb = CIFS_SB(inode->i_sb);
 	pTcon = cifs_sb->tcon;
 
@@ -136,8 +136,8 @@
 	pTcon = cifs_sb->tcon;
 
 	full_path = build_path_from_dentry(direntry);
-	cFYI(1, ("\nFull path: %s ", full_path));
-	cFYI(1, (" symname is %s\n", symname));
+	cFYI(1, ("Full path: %s ", full_path));
+	cFYI(1, ("symname is %s", symname));
 
 	/* BB what if DFS and this volume is on different share? BB */
 	if (cifs_sb->tcon->ses->capabilities & CAP_UNIX)
@@ -156,7 +156,7 @@
 
 		if (rc != 0) {
 			cFYI(1,
-			     ("\nCreate symlink worked but get_inode_info failed with rc = %d ",
+			     ("Create symlink worked but get_inode_info failed with rc = %d ",
 			      rc));
 		} else {
 			direntry->d_op = &cifs_dentry_ops;
@@ -188,7 +188,7 @@
 	pTcon = cifs_sb->tcon;
 	full_path = build_path_from_dentry(direntry);
 	cFYI(1,
-	     ("\nFull path: %s inode = 0x%p pBuffer = 0x%p buflen = %d\n",
+	     ("Full path: %s inode = 0x%p pBuffer = 0x%p buflen = %d",
 	      full_path, inode, pBuffer, buflen));
 
 /* BB add read reparse point symlink code and Unix extensions symlink code here BB */
diff -Nru a/fs/cifs/misc.c b/fs/cifs/misc.c
--- a/fs/cifs/misc.c	Mon Feb 17 14:57:28 2003
+++ b/fs/cifs/misc.c	Mon Feb 17 14:57:28 2003
@@ -81,7 +81,7 @@
 sesInfoFree(struct cifsSesInfo *buf_to_free)
 {
 	if (buf_to_free == NULL) {
-		cFYI(1, ("\nNull buffer passed to sesInfoFree"));
+		cFYI(1, ("Null buffer passed to sesInfoFree"));
 		return;
 	}
 
@@ -122,7 +122,7 @@
 tconInfoFree(struct cifsTconInfo *buf_to_free)
 {
 	if (buf_to_free == NULL) {
-		cFYI(1, ("\nNull buffer passed to tconInfoFree"));
+		cFYI(1, ("Null buffer passed to tconInfoFree"));
 		return;
 	}
 	write_lock(&GlobalSMBSeslock);
@@ -169,7 +169,7 @@
 {
 
 	if (buf_to_free == NULL) {
-		cFYI(1, ("\nNull buffer passed to buf_release"));
+		cFYI(1, ("Null buffer passed to buf_release"));
 		return;
 	}
 	kmem_cache_free(cifs_req_cachep, buf_to_free);
@@ -225,8 +225,10 @@
 		}
 		if (treeCon->Flags & SMB_SHARE_IS_IN_DFS)
 			buffer->Flags2 |= SMBFLG2_DFS;
-		if(treeCon->ses->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
-			buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
+		if(treeCon->ses->server)
+			if(treeCon->ses->server->secMode & 
+			  (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
+				buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
 	}
 
 /*  endian conversion of flags is now done just before sending */
@@ -248,17 +250,17 @@
 			if(smb->Command == SMB_COM_LOCKING_ANDX)
 				return 0;
 			else
-				cERROR(1, ("\n Rcvd Request not response "));         
+				cERROR(1, ("Rcvd Request not response "));         
 		}
 	} else { /* bad signature or mid */
 		if (*(unsigned int *) smb->Protocol != cpu_to_le32(0x424d53ff))
 			cERROR(1,
-			       ("\nBad protocol string signature header %x ",
+			       ("Bad protocol string signature header %x ",
 				*(unsigned int *) smb->Protocol));
 		if (mid != smb->Mid)
-			cERROR(1, ("\n Mids do not match \n"));
+			cERROR(1, ("Mids do not match"));
 	}
-	cERROR(1, ("\nCIFS: bad smb detected. The Mid=%d\n", smb->Mid));
+	cERROR(1, ("bad smb detected. The Mid=%d", smb->Mid));
 	return 1;
 }
 
@@ -266,13 +268,13 @@
 checkSMB(struct smb_hdr *smb, __u16 mid, int length)
 {
 	cFYI(0,
-	     ("\nEntering checkSMB with Length: %x, smb_buf_length: %x ",
+	     ("Entering checkSMB with Length: %x, smb_buf_length: %x ",
 	      length, ntohl(smb->smb_buf_length)));
 	if ((length < 2 + sizeof (struct smb_hdr))
 	    || (4 + ntohl(smb->smb_buf_length) >
 		CIFS_MAX_MSGSIZE + MAX_CIFS_HDR_SIZE)) {
 		if (length < 2 + sizeof (struct smb_hdr)) {
-			cERROR(1, ("\n Length less than 2 + sizeof smb_hdr "));
+			cERROR(1, ("Length less than 2 + sizeof smb_hdr "));
 			if ((length >= sizeof (struct smb_hdr) - 1)
 			    && (smb->Status.CifsError != 0))
 				return 0;	/* some error cases do not return wct and bcc */
@@ -281,9 +283,9 @@
 		if (4 + ntohl(smb->smb_buf_length) >
 		    CIFS_MAX_MSGSIZE + MAX_CIFS_HDR_SIZE)
 			cERROR(1,
-			       ("\n smb_buf_length greater than CIFS_MAX_MSGSIZE ... "));
+			       ("smb_buf_length greater than CIFS_MAX_MSGSIZE ... "));
 		cERROR(1,
-		       ("CIFS: bad smb detected. Illegal length. The mid=%d\n",
+		       ("bad smb detected. Illegal length. The mid=%d",
 			smb->Mid));
 		return 1;
 	}
@@ -295,51 +297,62 @@
 	    || (4 + ntohl(smb->smb_buf_length) != length)) {
 		return 0;
 	} else {
-		cERROR(1, ("\nCIFS: smbCalcSize %x ", smbCalcSize(smb)));
+		cERROR(1, ("smbCalcSize %x ", smbCalcSize(smb)));
 		cERROR(1,
-		       ("CIFS: bad smb size detected. The Mid=%d\n", smb->Mid));
+		       ("bad smb size detected. The Mid=%d", smb->Mid));
 		return 1;
 	}
 }
 int
 is_valid_oplock_break(struct smb_hdr *buf)
 {    
-       struct smb_com_lock_req * pSMB = (struct smb_com_lock_req *)buf;
-       struct list_head *tmp;
-       struct cifsTconInfo *tcon;
-
-       /* could add check for smb response flag 0x80 */
-       cFYI(1,("\nChecking for oplock break"));    
-       if(pSMB->hdr.Command != SMB_COM_LOCKING_ANDX)
-               return FALSE;
-       if(pSMB->hdr.Flags & SMBFLG_RESPONSE)
-               return FALSE; /* server sends us "request" here */
-       if(pSMB->hdr.WordCount != 8)
-               return FALSE;
-
-       cFYI(1,(" oplock type 0x%d level 0x%d",pSMB->LockType,pSMB->OplockLevel));
-       if(!(pSMB->LockType & LOCKING_ANDX_OPLOCK_RELEASE))
-               return FALSE;    
-
-       /* look up tcon based on tid & uid */
-       read_lock(&GlobalSMBSeslock);
-       list_for_each(tmp, &GlobalTreeConnectionList) {
-               tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
-               if (tcon->tid == buf->Tid)
-                       if(tcon->ses->Suid == buf->Uid) {
-                       /* BB Add following logic: 
-                         2) look up inode from tcon->openFileList->file->f_dentry->d_inode
-                         3) flush dirty pages and cached byte range locks and mark inode
-                         4) depending on break type change to r/o caching or no caching
-                         5) send oplock break response to server */
-                               read_unlock(&GlobalSMBSeslock);
-                               cFYI(1,("\nFound matching connection, process oplock break"));
-                               return TRUE;
-                       }
-       }
-       read_unlock(&GlobalSMBSeslock);
-       cFYI(1,("\nProcessing oplock break for non-existent connection"));
-       return TRUE;
+	struct smb_com_lock_req * pSMB = (struct smb_com_lock_req *)buf;
+	struct list_head *tmp;
+	struct list_head *tmp1;
+	struct cifsTconInfo *tcon;
+	struct cifsFileInfo *netfile;
+
+	/* could add check for smb response flag 0x80 */
+	cFYI(1,("Checking for oplock break"));    
+	if(pSMB->hdr.Command != SMB_COM_LOCKING_ANDX)
+		return FALSE;
+	if(pSMB->hdr.Flags & SMBFLG_RESPONSE)
+		return FALSE; /* server sends us "request" here */
+	if(pSMB->hdr.WordCount != 8)
+		return FALSE;
+
+	cFYI(1,(" oplock type 0x%d level 0x%d",pSMB->LockType,pSMB->OplockLevel));
+	if(!(pSMB->LockType & LOCKING_ANDX_OPLOCK_RELEASE))
+		return FALSE;    
+
+	/* look up tcon based on tid & uid */
+	read_lock(&GlobalSMBSeslock);
+	list_for_each(tmp, &GlobalTreeConnectionList) {
+		tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
+		if (tcon->tid == buf->Tid) {
+			list_for_each(tmp1,&tcon->openFileList){
+				netfile = list_entry(tmp1,struct cifsFileInfo,tlist);
+				if(pSMB->Fid == netfile->netfid) {
+			/* BB Add following logic: 
+			  2) look up inode from tcon->openFileList->file->f_dentry->d_inode
+			  3) flush dirty pages and cached byte range locks and mark inode
+			  4) depending on break type change to r/o caching or no caching
+                  cifsinode->clientCanCacheAll = 0
+              5)  inode->i_data.a_ops = &cifs_addr_ops_writethrough;
+			  6) send oplock break response to server */
+					read_unlock(&GlobalSMBSeslock);
+					cFYI(1,("Matching file id, processing oplock break"));
+					return TRUE;
+				}
+			}
+			read_unlock(&GlobalSMBSeslock);
+			cFYI(1,("No matching file for oplock break on connection"));
+			return TRUE;
+		}
+	}
+	read_unlock(&GlobalSMBSeslock);
+	cFYI(1,("Can not process oplock break for non-existent connection"));
+	return TRUE;
 }
 
 void
@@ -355,7 +368,7 @@
 	buffer = (unsigned char *) smb_buf;
 	for (i = 0, j = 0; i < smb_buf_length; i++, j++) {
 		if (i % 8 == 0) {	/* we have reached the beginning of line  */
-			printk("\n| ");
+			printk(KERN_DEBUG "| ");
 			j = 0;
 		}
 		printk("%0#4x ", buffer[i]);
@@ -367,7 +380,7 @@
 
 		if (i % 8 == 7) {	/* we have reached end of line, time to print ascii */
 			debug_line[16] = 0;
-			printk(" | %s", debug_line);
+			printk(" | %s\n", debug_line);
 		}
 	}
 	for (; j < 8; j++) {
@@ -375,6 +388,6 @@
 		debug_line[2 * j] = ' ';
 		debug_line[1 + (2 * j)] = ' ';
 	}
-	printk(" | %s\n", debug_line);
+	printk( " | %s\n", debug_line);
 	return;
 }
diff -Nru a/fs/cifs/netmisc.c b/fs/cifs/netmisc.c
--- a/fs/cifs/netmisc.c	Mon Feb 17 14:57:28 2003
+++ b/fs/cifs/netmisc.c	Mon Feb 17 14:57:28 2003
@@ -753,12 +753,11 @@
 {
 	int idx = 0;
 
-	printk("\nStatus code returned: 0x%08x ", status_code);
-
 	while (nt_errs[idx].nt_errstr != NULL) {
 		if (((nt_errs[idx].nt_errcode) & 0xFFFFFF) ==
 		    (status_code & 0xFFFFFF)) {
-			printk(nt_errs[idx].nt_errstr);
+			printk(KERN_NOTICE "Status code returned 0x%08x %s\n",
+				   status_code,nt_errs[idx].nt_errstr);
 		}
 		idx++;
 	}
@@ -815,11 +814,8 @@
 	}
 
 	/* old style errors */
-	cFYI(1, (" !!Mapping smb error code %d ", smberrcode));
-	/* DOS class smb error codes - map DOS */
-
-	/* BB special case reconnect tid and reconnect uid here? */
 
+	/* DOS class smb error codes - map DOS */
 	if (smberrclass == ERRDOS) {	/* one byte field no need to byte reverse */
 		for (i = 0;
 		     i <
@@ -849,10 +845,7 @@
 	}
 	/* else ERRHRD class errors or junk  - return EIO */
 
-	/* BB get smb->error_class and code lookup in table if ERR_STATUS is not
-	   set in this frame else translate newer NT Status code - in both cases 
-	   change to equivalent posix error BB */
-	cFYI(1, (" to POSIX err %d !!", rc));
+	cFYI(1, (" !!Mapping smb error code %d to POSIX err %d !!", smberrcode,rc));
 
 	/* generic corrective action e.g. reconnect SMB session on ERRbaduid could be added */
 
diff -Nru a/fs/cifs/smbencrypt.c b/fs/cifs/smbencrypt.c
--- a/fs/cifs/smbencrypt.c	Mon Feb 17 14:57:27 2003
+++ b/fs/cifs/smbencrypt.c	Mon Feb 17 14:57:27 2003
@@ -305,7 +305,7 @@
 
 	if (new_pw_len > 512) {
 		cERROR(1,
-		       ("CIFS make_oem_passwd_hash: new password is too long.\n"));
+		       ("CIFS make_oem_passwd_hash: new password is too long."));
 		return FALSE;
 	}
 
diff -Nru a/fs/cifs/transport.c b/fs/cifs/transport.c
--- a/fs/cifs/transport.c	Mon Feb 17 14:57:27 2003
+++ b/fs/cifs/transport.c	Mon Feb 17 14:57:27 2003
@@ -40,10 +40,9 @@
 
 /* BB add spinlock to protect midq for each session BB */
 	if (ses == NULL) {
-		cERROR(1, ("\nNull session passed in to AllocMidQEntry "));
+		cERROR(1, ("Null session passed in to AllocMidQEntry "));
 		return NULL;
 	}
-	temp = kmalloc(sizeof (struct mid_q_entry), GFP_KERNEL);
 	temp = (struct mid_q_entry *) kmem_cache_alloc(cifs_mid_cachep,
 						       SLAB_KERNEL);
 	if (temp == NULL)
@@ -53,21 +52,19 @@
 		temp->mid = smb_buffer->Mid;	/* always LE */
 		temp->pid = current->pid;
 		temp->command = smb_buffer->Command;
-		cFYI(1, ("\nFor smb_command %d", temp->command));
+		cFYI(1, ("For smb_command %d", temp->command));
 		do_gettimeofday(&temp->when_sent);
 		temp->ses = ses;
 		temp->tsk = current;
 	}
-	if (ses->status == CifsGood) {
+	if (ses->server->tcpStatus == CifsGood) {
 		write_lock(&GlobalMid_Lock);
 		list_add_tail(&temp->qhead, &ses->server->pending_mid_q);
 		atomic_inc(&midCount);
 		temp->midState = MID_REQUEST_ALLOCATED;
 		write_unlock(&GlobalMid_Lock);
-	} else {		/* BB add reconnect code here BB */
-
-		cERROR(1,
-		       ("\nNeed to reconnect after session died to server\n"));
+	} else {		/* could add more reconnect code here BB */
+		cERROR(1,("Need to reconnect after session died to server"));
 		if (temp)
 			kmem_cache_free(cifs_mid_cachep, temp);
 		return NULL;
@@ -121,7 +118,7 @@
         sign_smb(smb_buffer); */ /* BB enable when signing tested more */
 
 	smb_buffer->smb_buf_length = cpu_to_be32(smb_buffer->smb_buf_length);
-	cFYI(1, ("\nSending smb of length %d ", smb_buf_length));
+	cFYI(1, ("Sending smb of length %d ", smb_buf_length));
 	dump_smb(smb_buffer, smb_buf_length + 4);
 
 	temp_fs = get_fs();	/* we must turn off socket api parm checking */
@@ -132,7 +129,7 @@
 
 	if (rc < 0) {
 		cERROR(1,
-		       ("\nError %d sending data on socket to server.\n", rc));
+		       ("Error %d sending data on socket to server.", rc));
 	} else
 		rc = 0;
 
@@ -154,7 +151,7 @@
 		return -EIO;	/* reconnect should be done, if possible, in AllocMidQEntry */
 	if (in_buf->smb_buf_length > CIFS_MAX_MSGSIZE + MAX_CIFS_HDR_SIZE) {
 		cERROR(1,
-		       ("\nIllegal length, greater than maximum frame, %d ",
+		       ("Illegal length, greater than maximum frame, %d ",
 			in_buf->smb_buf_length));
 		DeleteMidQEntry(midQ);
 		return -EIO;
@@ -163,27 +160,21 @@
 	rc = smb_send(ses->server->ssocket, in_buf, in_buf->smb_buf_length,
 		      (struct sockaddr *) &(ses->server->sockAddr));
 
-	if (long_op > 1)	/* writes past end of file can take a looooooong time */
+	if (long_op > 1) /* writes past end of file can take looooong time */
 		timeout = 300 * HZ;
 	else if (long_op == 1)
 		timeout = 60 * HZ;
 	else
 		timeout = 15 * HZ;
-	/* wait for 15 seconds or until woken up due to response arriving or due to 
-	   last connection to this server being unmounted */
-
-	/* timeout = interruptible_sleep_on_timeout(&ses->server->response_q,timeout); */
-	/* Replace above line with wait_event to get rid of sleep_on per lk guidelines */
+	/* wait for 15 seconds or until woken up due to response arriving or 
+	   due to last connection to this server being unmounted */
 
 	timeout = wait_event_interruptible_timeout(ses->server->response_q,
 				midQ->
 				midState & MID_RESPONSE_RECEIVED,
 				timeout);
-	cFYI(1,
-	     (" with timeout %ld and Out_buf: %p  midQ->resp_buf: %p ", timeout,
-	      out_buf, midQ->resp_buf));
 	if (signal_pending(current)) {
-		cERROR(1, (KERN_ERR "\nCIFS: caught signal"));
+		cERROR(1, ("CIFS: caught signal"));
 		DeleteMidQEntry(midQ);
 		return -EINTR;
 	} else {
@@ -198,11 +189,11 @@
 
 	if (timeout == 0) {
 		cFYI(1,
-		     ("\nTimeout on receive. Assume response SMB is invalid.\n"));
+		     ("Timeout on receive. Assume response SMB is invalid."));
 		rc = -ETIMEDOUT;
 	} else if (receive_len > CIFS_MAX_MSGSIZE + MAX_CIFS_HDR_SIZE) {
 		cERROR(1,
-		       ("\nFrame too large received.  Length: %d  Xid: %d\n",
+		       ("Frame too large received.  Length: %d  Xid: %d",
 			receive_len, xid));
 		rc = -EIO;
 	} else {		/* rcvd frame is ok */
@@ -215,7 +206,6 @@
 			/* convert the length back to a form that we can use */
 
 			dump_smb(out_buf, 92);
-
 			out_buf->smb_buf_length =
 			    be32_to_cpu(out_buf->smb_buf_length);
 			if (out_buf->smb_buf_length > 12)
diff -Nru a/fs/dcache.c b/fs/dcache.c
--- a/fs/dcache.c	Mon Feb 17 14:57:26 2003
+++ b/fs/dcache.c	Mon Feb 17 14:57:26 2003
@@ -49,12 +49,30 @@
 static unsigned int d_hash_shift;
 static struct list_head *dentry_hashtable;
 static LIST_HEAD(dentry_unused);
+static int max_dentries;
+static void * hashtable_end;
+
+static inline int is_bucket(void * addr)
+{
+	return ((addr < (void *)dentry_hashtable)
+			|| (addr > hashtable_end) ? 0 : 1);
+}	
 
 /* Statistics gathering. */
 struct dentry_stat_t dentry_stat = {
 	.age_limit = 45,
 };
 
+static void d_callback(void *arg)
+{
+	struct dentry * dentry = (struct dentry *)arg;
+
+	if (dname_external(dentry)) {
+		kfree(dentry->d_qstr);
+	}
+	kmem_cache_free(dentry_cache, dentry); 
+}
+
 /*
  * no dcache_lock, please.  The caller must decrement dentry_stat.nr_dentry
  * inside dcache_lock.
@@ -63,9 +81,7 @@
 {
 	if (dentry->d_op && dentry->d_op->d_release)
 		dentry->d_op->d_release(dentry);
-	if (dname_external(dentry)) 
-		kfree(dentry->d_name.name);
-	kmem_cache_free(dentry_cache, dentry); 
+ 	call_rcu(&dentry->d_rcu, d_callback, dentry);
 }
 
 /*
@@ -126,9 +142,13 @@
 	if (!atomic_dec_and_lock(&dentry->d_count, &dcache_lock))
 		return;
 
-	/* dput on a free dentry? */
-	if (!list_empty(&dentry->d_lru))
-		BUG();
+	spin_lock(&dentry->d_lock);
+	if (atomic_read(&dentry->d_count)) {
+		spin_unlock(&dentry->d_lock);
+		spin_unlock(&dcache_lock);
+		return;
+	}
+			
 	/*
 	 * AV: ->d_delete() is _NOT_ allowed to block now.
 	 */
@@ -139,8 +159,12 @@
 	/* Unreachable? Get rid of it */
  	if (d_unhashed(dentry))
 		goto kill_it;
-	list_add(&dentry->d_lru, &dentry_unused);
-	dentry_stat.nr_unused++;
+  	if (list_empty(&dentry->d_lru)) {
+  		dentry->d_vfs_flags &= ~DCACHE_REFERENCED;
+  		list_add(&dentry->d_lru, &dentry_unused);
+  		dentry_stat.nr_unused++;
+  	}
+ 	spin_unlock(&dentry->d_lock);
 	dentry->d_vfs_flags |= DCACHE_REFERENCED;
 	spin_unlock(&dcache_lock);
 	return;
@@ -150,7 +174,16 @@
 
 kill_it: {
 		struct dentry *parent;
-		list_del(&dentry->d_child);
+
+		/* If dentry was on d_lru list
+		 * delete it from there
+		 */
+  		if (!list_empty(&dentry->d_lru)) {
+  			list_del(&dentry->d_lru);
+  			dentry_stat.nr_unused--;
+  		}
+  		list_del(&dentry->d_child);
+ 		spin_unlock(&dentry->d_lock);
 		dentry_stat.nr_dentry--;	/* For d_free, below */
 		/* drops the lock, at that point nobody can reach this dentry */
 		dentry_iput(dentry);
@@ -222,6 +255,7 @@
 static inline struct dentry * __dget_locked(struct dentry *dentry)
 {
 	atomic_inc(&dentry->d_count);
+	dentry->d_vfs_flags |= DCACHE_REFERENCED;
 	if (atomic_read(&dentry->d_count) == 1) {
 		dentry_stat.nr_unused--;
 		list_del_init(&dentry->d_lru);
@@ -289,8 +323,8 @@
 		struct dentry *dentry = list_entry(tmp, struct dentry, d_alias);
 		if (!atomic_read(&dentry->d_count)) {
 			__dget_locked(dentry);
+			__d_drop(dentry);
 			spin_unlock(&dcache_lock);
-			d_drop(dentry);
 			dput(dentry);
 			goto restart;
 		}
@@ -310,6 +344,7 @@
 
 	__d_drop(dentry);
 	list_del(&dentry->d_child);
+ 	spin_unlock(&dentry->d_lock);
 	dentry_stat.nr_dentry--;	/* For d_free, below */
 	dentry_iput(dentry);
 	parent = dentry->d_parent;
@@ -343,18 +378,24 @@
 		if (tmp == &dentry_unused)
 			break;
 		list_del_init(tmp);
+ 		dentry_stat.nr_unused--;
 		dentry = list_entry(tmp, struct dentry, d_lru);
 
+ 		spin_lock(&dentry->d_lock);
 		/* If the dentry was recently referenced, don't free it. */
 		if (dentry->d_vfs_flags & DCACHE_REFERENCED) {
 			dentry->d_vfs_flags &= ~DCACHE_REFERENCED;
-			list_add(&dentry->d_lru, &dentry_unused);
+
+			/* don't add non zero d_count dentries 
+			 * back to d_lru list
+			 */
+ 			if (!atomic_read(&dentry->d_count)) {
+ 				list_add(&dentry->d_lru, &dentry_unused);
+ 				dentry_stat.nr_unused++;
+ 			}
+ 			spin_unlock(&dentry->d_lock);
 			continue;
 		}
-		dentry_stat.nr_unused--;
-
-		/* Unused dentry with a count? */
-		BUG_ON(atomic_read(&dentry->d_count));
 		prune_one_dentry(dentry);
 	}
 	spin_unlock(&dcache_lock);
@@ -414,10 +455,13 @@
 		dentry = list_entry(tmp, struct dentry, d_lru);
 		if (dentry->d_sb != sb)
 			continue;
-		if (atomic_read(&dentry->d_count))
-			continue;
 		dentry_stat.nr_unused--;
 		list_del_init(tmp);
+		spin_lock(&dentry->d_lock);
+		if (atomic_read(&dentry->d_count)) {
+			spin_unlock(&dentry->d_lock);
+			continue;
+		}
 		prune_one_dentry(dentry);
 		goto repeat;
 	}
@@ -497,8 +541,12 @@
 		struct list_head *tmp = next;
 		struct dentry *dentry = list_entry(tmp, struct dentry, d_child);
 		next = tmp->next;
+		list_del_init(&dentry->d_lru);
+
+		/* don't add non zero d_count dentries 
+		 * back to d_lru list
+		 */
 		if (!atomic_read(&dentry->d_count)) {
-			list_del(&dentry->d_lru);
 			list_add(&dentry->d_lru, dentry_unused.prev);
 			found++;
 		}
@@ -551,6 +599,9 @@
  *
  * Prune the dentries that are anonymous
  *
+ * parsing d_hash list does not read_barrier_depends() as it
+ * done under dcache_lock.
+ *
  */
 void shrink_dcache_anon(struct list_head *head)
 {
@@ -561,8 +612,12 @@
 		spin_lock(&dcache_lock);
 		list_for_each(lp, head) {
 			struct dentry *this = list_entry(lp, struct dentry, d_hash);
+			list_del(&this->d_lru);
+
+			/* don't add non zero d_count dentries 
+			 * back to d_lru list
+			 */
 			if (!atomic_read(&this->d_count)) {
-				list_del(&this->d_lru);
 				list_add_tail(&this->d_lru, &dentry_unused);
 				found++;
 			}
@@ -630,28 +685,39 @@
 {
 	char * str;
 	struct dentry *dentry;
+	struct qstr * qstr;
 
 	dentry = kmem_cache_alloc(dentry_cache, GFP_KERNEL); 
 	if (!dentry)
 		return NULL;
 
 	if (name->len > DNAME_INLINE_LEN-1) {
-		str = kmalloc(NAME_ALLOC_LEN(name->len), GFP_KERNEL);
-		if (!str) {
+		qstr = kmalloc(sizeof(*qstr) + NAME_ALLOC_LEN(name->len), 
+				GFP_KERNEL);  
+		if (!qstr) {
 			kmem_cache_free(dentry_cache, dentry); 
 			return NULL;
 		}
-	} else
-		str = dentry->d_iname; 
+		qstr->name = qstr->name_str;
+		qstr->len = name->len;
+		qstr->hash = name->hash;
+		dentry->d_qstr = qstr;
+		str = qstr->name_str;
+	} else  {
+		dentry->d_qstr = &dentry->d_name;
+		str = dentry->d_iname;
+	}	
 
 	memcpy(str, name->name, name->len);
 	str[name->len] = 0;
 
 	atomic_set(&dentry->d_count, 1);
-	dentry->d_vfs_flags = 0;
+	dentry->d_vfs_flags = DCACHE_UNHASHED;
+	dentry->d_lock = SPIN_LOCK_UNLOCKED;
 	dentry->d_flags = 0;
 	dentry->d_inode = NULL;
 	dentry->d_parent = NULL;
+	dentry->d_move_count = 0;
 	dentry->d_sb = NULL;
 	dentry->d_name.name = str;
 	dentry->d_name.len = name->len;
@@ -660,6 +726,7 @@
 	dentry->d_fsdata = NULL;
 	dentry->d_mounted = 0;
 	dentry->d_cookie = NULL;
+	dentry->d_bucket = NULL;
 	INIT_LIST_HEAD(&dentry->d_hash);
 	INIT_LIST_HEAD(&dentry->d_lru);
 	INIT_LIST_HEAD(&dentry->d_subdirs);
@@ -785,12 +852,16 @@
 		res = tmp;
 		tmp = NULL;
 		if (res) {
+			spin_lock(&res->d_lock);
 			res->d_sb = inode->i_sb;
 			res->d_parent = res;
 			res->d_inode = inode;
+			res->d_bucket = d_hash(res, res->d_name.hash);
 			res->d_flags |= DCACHE_DISCONNECTED;
+			res->d_vfs_flags &= ~DCACHE_UNHASHED;
 			list_add(&res->d_alias, &inode->i_dentry);
 			list_add(&res->d_hash, &inode->i_sb->s_anon);
+			spin_unlock(&res->d_lock);
 		}
 		inode = NULL; /* don't drop reference */
 	}
@@ -855,50 +926,92 @@
  * the dentry is found its reference count is incremented and the dentry
  * is returned. The caller must use d_put to free the entry when it has
  * finished using it. %NULL is returned on failure.
+ *
+ * d_lookup is now, dcache_lock free. The hash list is protected using RCU.
+ * Memory barriers are used while updating and doing lockless traversal. 
+ * To avoid races with d_move while rename is happening, d_move_count is 
+ * used. 
+ *
+ * Overflows in memcmp(), while d_move, are avoided by keeping the length
+ * and name pointer in one structure pointed by d_qstr.
+ *
+ * rcu_read_lock() and rcu_read_unlock() are used to disable preemption while
+ * lookup is going on.
+ *
+ * d_lru list is not updated, which can leave non-zero d_count dentries
+ * around in d_lru list.
  */
- 
-struct dentry * d_lookup(struct dentry * parent, struct qstr * name)
-{
-	struct dentry * dentry;
-	spin_lock(&dcache_lock);
-	dentry = __d_lookup(parent,name);
-	if (dentry)
-		__dget_locked(dentry);
-	spin_unlock(&dcache_lock);
-	return dentry;
-}
 
-struct dentry * __d_lookup(struct dentry * parent, struct qstr * name)  
+struct dentry * d_lookup(struct dentry * parent, struct qstr * name)
 {
-
 	unsigned int len = name->len;
 	unsigned int hash = name->hash;
 	const unsigned char *str = name->name;
 	struct list_head *head = d_hash(parent,hash);
+	struct dentry *found = NULL;
 	struct list_head *tmp;
+	int lookup_count = 0;
 
-	tmp = head->next;
-	for (;;) {
-		struct dentry * dentry = list_entry(tmp, struct dentry, d_hash);
-		if (tmp == head)
+	rcu_read_lock();
+	
+	/* lookup is terminated when flow reaches any bucket head */
+	for(tmp = head->next; !is_bucket(tmp); tmp = tmp->next) {
+		struct dentry *dentry; 
+		unsigned long move_count;
+		struct qstr * qstr;
+		
+		smp_read_barrier_depends();
+		dentry = list_entry(tmp, struct dentry, d_hash);
+
+		/* if lookup ends up in a different bucket 
+		 * due to concurrent rename, fail it
+		 */
+		if (unlikely(dentry->d_bucket != head))
 			break;
-		tmp = tmp->next;
+
+		/* to avoid race if dentry keep coming back to original
+		 * bucket due to double moves
+		 */
+		if (unlikely(++lookup_count > max_dentries))
+			break;
+
+		/*
+		 * We must take a snapshot of d_move_count followed by
+		 * read memory barrier before any search key comparison 
+		 */
+		move_count = dentry->d_move_count;
+		smp_rmb();
+
 		if (dentry->d_name.hash != hash)
 			continue;
 		if (dentry->d_parent != parent)
 			continue;
+
+		qstr = dentry->d_qstr;
+		smp_read_barrier_depends();
 		if (parent->d_op && parent->d_op->d_compare) {
-			if (parent->d_op->d_compare(parent, &dentry->d_name, name))
+			if (parent->d_op->d_compare(parent, qstr, name))
 				continue;
 		} else {
-			if (dentry->d_name.len != len)
+			if (qstr->len != len)
 				continue;
-			if (memcmp(dentry->d_name.name, str, len))
+			if (memcmp(qstr->name, str, len))
 				continue;
 		}
-		return dentry;
-	}
-	return NULL;
+		spin_lock(&dentry->d_lock);
+		/*
+		 * If dentry is moved, fail the lookup
+		 */ 
+		if (unlikely(move_count != dentry->d_move_count)) 
+			break;
+		if (!d_unhashed(dentry))
+			found = dget(dentry);
+		spin_unlock(&dentry->d_lock);
+		break;
+ 	}
+ 	rcu_read_unlock();
+
+ 	return found;
 }
 
 /**
@@ -936,8 +1049,11 @@
 	spin_lock(&dcache_lock);
 	lhp = base = d_hash(dparent, dentry->d_name.hash);
 	while ((lhp = lhp->next) != base) {
+		/* read_barrier_depends() not required for d_hash list
+		 * as it is parsed under dcache_lock
+		 */
 		if (dentry == list_entry(lhp, struct dentry, d_hash)) {
-			__dget_locked(dentry);
+			dget(dentry);
 			spin_unlock(&dcache_lock);
 			return 1;
 		}
@@ -974,17 +1090,18 @@
 	 * Are we the only user?
 	 */
 	spin_lock(&dcache_lock);
+	spin_lock(&dentry->d_lock);
 	if (atomic_read(&dentry->d_count) == 1) {
+		spin_unlock(&dentry->d_lock);
 		dentry_iput(dentry);
 		return;
 	}
-	spin_unlock(&dcache_lock);
 
-	/*
-	 * If not, just drop the dentry and let dput
-	 * pick up the tab..
-	 */
-	d_drop(dentry);
+	if (!d_unhashed(dentry))
+		__d_drop(dentry);
+
+	spin_unlock(&dentry->d_lock);
+	spin_unlock(&dcache_lock);
 }
 
 /**
@@ -997,9 +1114,11 @@
 void d_rehash(struct dentry * entry)
 {
 	struct list_head *list = d_hash(entry->d_parent, entry->d_name.hash);
-	if (!d_unhashed(entry)) BUG();
 	spin_lock(&dcache_lock);
-	list_add(&entry->d_hash, list);
+ 	if (!list_empty(&entry->d_hash) && !d_unhashed(entry)) BUG();
+ 	entry->d_vfs_flags &= ~DCACHE_UNHASHED;
+	entry->d_bucket = list;
+ 	list_add_rcu(&entry->d_hash, list);
 	spin_unlock(&dcache_lock);
 }
 
@@ -1021,16 +1140,25 @@
 static inline void switch_names(struct dentry * dentry, struct dentry * target)
 {
 	const unsigned char *old_name, *new_name;
+	struct qstr *old_qstr, *new_qstr;
 
 	memcpy(dentry->d_iname, target->d_iname, DNAME_INLINE_LEN); 
+	old_qstr = target->d_qstr;
 	old_name = target->d_name.name;
+	new_qstr = dentry->d_qstr;
 	new_name = dentry->d_name.name;
-	if (old_name == target->d_iname)
+	if (old_name == target->d_iname) {
 		old_name = dentry->d_iname;
-	if (new_name == dentry->d_iname)
+		old_qstr = &dentry->d_name;
+	}
+	if (new_name == dentry->d_iname) {
 		new_name = target->d_iname;
+		new_qstr = &target->d_name;
+	}
 	target->d_name.name = new_name;
 	dentry->d_name.name = old_name;
+	target->d_qstr = new_qstr;
+	dentry->d_qstr = old_qstr;
 }
 
 /*
@@ -1057,15 +1185,21 @@
  * Update the dcache to reflect the move of a file name. Negative
  * dcache entries should not be moved in this way.
  */
-  
+
 void d_move(struct dentry * dentry, struct dentry * target)
 {
 	if (!dentry->d_inode)
 		printk(KERN_WARNING "VFS: moving negative dcache entry\n");
 
 	spin_lock(&dcache_lock);
-	/* Move the dentry to the target hash queue */
-	list_move(&dentry->d_hash, &target->d_hash);
+	spin_lock(&dentry->d_lock);
+
+	/* Move the dentry to the target hash queue, if on different bucket */
+	if (dentry->d_bucket != target->d_bucket) {
+		dentry->d_bucket = target->d_bucket;
+		list_del_rcu(&dentry->d_hash);
+		list_add_rcu(&dentry->d_hash, &target->d_hash);
+	}
 
 	/* Unhash the target: dput() will then get rid of it */
 	__d_drop(target);
@@ -1075,6 +1209,7 @@
 
 	/* Switch the names.. */
 	switch_names(dentry, target);
+	smp_wmb();
 	do_switch(dentry->d_name.len, target->d_name.len);
 	do_switch(dentry->d_name.hash, target->d_name.hash);
 	/* ... and switch the parents */
@@ -1092,6 +1227,8 @@
 	write_unlock(&dparent_lock);
 
 	list_add(&dentry->d_child, &dentry->d_parent->d_subdirs);
+	dentry->d_move_count++;
+	spin_unlock(&dentry->d_lock);
 	spin_unlock(&dcache_lock);
 }
 
@@ -1384,6 +1521,9 @@
 	if (!dentry_cache)
 		panic("Cannot create dentry cache");
 	
+	/* approximate maximum number of dentries in one hash bucket */
+	max_dentries = (mempages * (PAGE_SIZE / sizeof(struct dentry)));
+
 	set_shrinker(DEFAULT_SEEKS, shrink_dcache_memory);
 
 #if PAGE_SHIFT < 13
@@ -1414,6 +1554,8 @@
 
 	if (!dentry_hashtable)
 		panic("Failed to allocate dcache hash table\n");
+
+	hashtable_end = dentry_hashtable + nr_hash;
 
 	d = dentry_hashtable;
 	i = nr_hash;
diff -Nru a/fs/direct-io.c b/fs/direct-io.c
--- a/fs/direct-io.c	Mon Feb 17 14:57:27 2003
+++ b/fs/direct-io.c	Mon Feb 17 14:57:27 2003
@@ -57,7 +57,7 @@
 	struct inode *inode;
 	int rw;
 	unsigned blkbits;		/* doesn't change */
-	unsigned blkfactor;		/* When we're using an aligment which
+	unsigned blkfactor;		/* When we're using an alignment which
 					   is finer than the filesystem's soft
 					   blocksize, this specifies how much
 					   finer.  blkfactor=2 means 1/4-block
@@ -754,7 +754,15 @@
 do_holes:
 			/* Handle holes */
 			if (!buffer_mapped(map_bh)) {
-				char *kaddr = kmap_atomic(page, KM_USER0);
+				char *kaddr;
+
+				if (dio->block_in_file >=
+						dio->inode->i_size>>blkbits) {
+					/* We hit eof */
+					page_cache_release(page);
+					goto out;
+				}
+				kaddr = kmap_atomic(page, KM_USER0);
 				memset(kaddr + (block_in_page << blkbits),
 						0, 1 << blkbits);
 				flush_dcache_page(page);
@@ -927,20 +935,24 @@
 			ret = dio->result;	/* Bytes written */
 		finished_one_bio(dio);		/* This can free the dio */
 		blk_run_queues();
-		goto out;
+	} else {
+		finished_one_bio(dio);
+		ret2 = dio_await_completion(dio);
+		if (ret == 0)
+			ret = ret2;
+		if (ret == 0)
+			ret = dio->page_errors;
+		if (ret == 0 && dio->result) {
+			ret = dio->result;
+			/*
+			 * Adjust the return value if the read crossed a
+			 * non-block-aligned EOF.
+			 */
+			if (rw == READ && (offset + ret > inode->i_size))
+				ret = inode->i_size - offset;
+		}
+		kfree(dio);
 	}
-
-	finished_one_bio(dio);
-	ret2 = dio_await_completion(dio);
-	if (ret == 0)
-		ret = ret2;
-	if (ret == 0)
-		ret = dio->page_errors;
-
-	if (dio->result)
-		ret = dio->result;
-	kfree(dio);
-out:
 	return ret;
 }
 
diff -Nru a/fs/ext2/Makefile b/fs/ext2/Makefile
--- a/fs/ext2/Makefile	Mon Feb 17 14:57:28 2003
+++ b/fs/ext2/Makefile	Mon Feb 17 14:57:28 2003
@@ -8,7 +8,7 @@
 	     ioctl.o namei.o super.o symlink.o
 
 ifeq ($(CONFIG_EXT2_FS_XATTR),y)
-ext2-objs += xattr.o xattr_user.o
+ext2-objs += xattr.o xattr_user.o xattr_trusted.o
 endif
 
 ifeq ($(CONFIG_EXT2_FS_POSIX_ACL),y)
diff -Nru a/fs/ext2/acl.c b/fs/ext2/acl.c
--- a/fs/ext2/acl.c	Mon Feb 17 14:57:28 2003
+++ b/fs/ext2/acl.c	Mon Feb 17 14:57:28 2003
@@ -419,28 +419,28 @@
  */
 static size_t
 ext2_xattr_list_acl_access(char *list, struct inode *inode,
-			   const char *name, int name_len)
+			   const char *name, int name_len, int flags)
 {
-	const size_t len = sizeof(XATTR_NAME_ACL_ACCESS)-1;
+	const size_t size = sizeof(XATTR_NAME_ACL_ACCESS);
 
 	if (!test_opt(inode->i_sb, POSIX_ACL))
 		return 0;
 	if (list)
-		memcpy(list, XATTR_NAME_ACL_ACCESS, len);
-	return len;
+		memcpy(list, XATTR_NAME_ACL_ACCESS, size);
+	return size;
 }
 
 static size_t
 ext2_xattr_list_acl_default(char *list, struct inode *inode,
-			    const char *name, int name_len)
+			    const char *name, int name_len, int flags)
 {
-	const size_t len = sizeof(XATTR_NAME_ACL_DEFAULT)-1;
+	const size_t size = sizeof(XATTR_NAME_ACL_DEFAULT);
 
 	if (!test_opt(inode->i_sb, POSIX_ACL))
 		return 0;
 	if (list)
-		memcpy(list, XATTR_NAME_ACL_DEFAULT, len);
-	return len;
+		memcpy(list, XATTR_NAME_ACL_DEFAULT, size);
+	return size;
 }
 
 static int
@@ -465,7 +465,7 @@
 
 static int
 ext2_xattr_get_acl_access(struct inode *inode, const char *name,
-			  void *buffer, size_t size)
+			  void *buffer, size_t size, int flags)
 {
 	if (strcmp(name, "") != 0)
 		return -EINVAL;
@@ -474,7 +474,7 @@
 
 static int
 ext2_xattr_get_acl_default(struct inode *inode, const char *name,
-			   void *buffer, size_t size)
+			   void *buffer, size_t size, int flags)
 {
 	if (strcmp(name, "") != 0)
 		return -EINVAL;
@@ -482,7 +482,8 @@
 }
 
 static int
-ext2_xattr_set_acl(struct inode *inode, int type, const void *value, size_t size)
+ext2_xattr_set_acl(struct inode *inode, int type, const void *value,
+		   size_t size)
 {
 	struct posix_acl *acl;
 	int error;
diff -Nru a/fs/ext2/xattr.c b/fs/ext2/xattr.c
--- a/fs/ext2/xattr.c	Mon Feb 17 14:57:27 2003
+++ b/fs/ext2/xattr.c	Mon Feb 17 14:57:27 2003
@@ -199,7 +199,7 @@
  */
 ssize_t
 ext2_getxattr(struct dentry *dentry, const char *name,
-	      void *buffer, size_t size)
+	      void *buffer, size_t size, int flags)
 {
 	struct ext2_xattr_handler *handler;
 	struct inode *inode = dentry->d_inode;
@@ -207,7 +207,7 @@
 	handler = ext2_xattr_resolve_name(&name);
 	if (!handler)
 		return -EOPNOTSUPP;
-	return handler->get(inode, name, buffer, size);
+	return handler->get(inode, name, buffer, size, flags);
 }
 
 /*
@@ -217,9 +217,9 @@
  * BKL held [before 2.5.x]
  */
 ssize_t
-ext2_listxattr(struct dentry *dentry, char *buffer, size_t size)
+ext2_listxattr(struct dentry *dentry, char *buffer, size_t size, int flags)
 {
-	return ext2_xattr_list(dentry->d_inode, buffer, size);
+	return ext2_xattr_list(dentry->d_inode, buffer, size, flags);
 }
 
 /*
@@ -250,7 +250,7 @@
  * BKL held [before 2.5.x]
  */
 int
-ext2_removexattr(struct dentry *dentry, const char *name)
+ext2_removexattr(struct dentry *dentry, const char *name, int flags)
 {
 	struct ext2_xattr_handler *handler;
 	struct inode *inode = dentry->d_inode;
@@ -258,7 +258,7 @@
 	handler = ext2_xattr_resolve_name(&name);
 	if (!handler)
 		return -EOPNOTSUPP;
-	return handler->set(inode, name, NULL, 0, XATTR_REPLACE);
+	return handler->set(inode, name, NULL, 0, flags | XATTR_REPLACE);
 }
 
 /*
@@ -371,7 +371,8 @@
  * used / required on success.
  */
 int
-ext2_xattr_list(struct inode *inode, char *buffer, size_t buffer_size)
+ext2_xattr_list(struct inode *inode, char *buffer, size_t buffer_size,
+		int flags)
 {
 	struct buffer_head *bh = NULL;
 	struct ext2_xattr_entry *entry;
@@ -409,10 +410,9 @@
 			goto bad_block;
 
 		handler = ext2_xattr_handler(entry->e_name_index);
-		if (handler) {
+		if (handler)
 			size += handler->list(NULL, inode, entry->e_name,
-					      entry->e_name_len) + 1;
-		}
+					      entry->e_name_len, flags);
 	}
 
 	if (ext2_xattr_cache_insert(bh))
@@ -433,11 +433,9 @@
 		struct ext2_xattr_handler *handler;
 		
 		handler = ext2_xattr_handler(entry->e_name_index);
-		if (handler) {
+		if (handler)
 			buf += handler->list(buf, inode, entry->e_name,
-					     entry->e_name_len);
-			*buf++ = '\0';
-		}
+					     entry->e_name_len, flags);
 	}
 	error = size;
 
@@ -1095,27 +1093,35 @@
 {
 	int	err;
 	
-	err = ext2_xattr_register(EXT2_XATTR_INDEX_USER, &ext2_xattr_user_handler);
+	err = ext2_xattr_register(EXT2_XATTR_INDEX_USER,
+				  &ext2_xattr_user_handler);
 	if (err)
 		return err;
+	err = ext2_xattr_register(EXT2_XATTR_INDEX_TRUSTED,
+				  &ext2_xattr_trusted_handler);
+	if (err)
+		goto out;
 #ifdef CONFIG_EXT2_FS_POSIX_ACL
 	err = init_ext2_acl();
 	if (err)
-		goto out;
+		goto out1;
 #endif
 	ext2_xattr_cache = mb_cache_create("ext2_xattr", NULL,
 		sizeof(struct mb_cache_entry) +
 		sizeof(struct mb_cache_entry_index), 1, 6);
 	if (!ext2_xattr_cache) {
 		err = -ENOMEM;
-		goto out1;
+		goto out2;
 	}
 	return 0;
-out1:
+out2:
 #ifdef CONFIG_EXT2_FS_POSIX_ACL
 	exit_ext2_acl();
-out:
+out1:
 #endif
+	ext2_xattr_unregister(EXT2_XATTR_INDEX_TRUSTED,
+			      &ext2_xattr_trusted_handler);
+out:
 	ext2_xattr_unregister(EXT2_XATTR_INDEX_USER,
 			      &ext2_xattr_user_handler);
 	return err;
@@ -1128,5 +1134,8 @@
 #ifdef CONFIG_EXT2_FS_POSIX_ACL
 	exit_ext2_acl();
 #endif
-	ext2_xattr_unregister(EXT2_XATTR_INDEX_USER, &ext2_xattr_user_handler);
+	ext2_xattr_unregister(EXT2_XATTR_INDEX_TRUSTED,
+			      &ext2_xattr_trusted_handler);
+	ext2_xattr_unregister(EXT2_XATTR_INDEX_USER,
+			      &ext2_xattr_user_handler);
 }
diff -Nru a/fs/ext2/xattr.h b/fs/ext2/xattr.h
--- a/fs/ext2/xattr.h	Mon Feb 17 14:57:26 2003
+++ b/fs/ext2/xattr.h	Mon Feb 17 14:57:26 2003
@@ -21,6 +21,7 @@
 #define EXT2_XATTR_INDEX_USER			1
 #define EXT2_XATTR_INDEX_POSIX_ACL_ACCESS	2
 #define EXT2_XATTR_INDEX_POSIX_ACL_DEFAULT	3
+#define EXT2_XATTR_INDEX_TRUSTED		4
 
 struct ext2_xattr_header {
 	__u32	h_magic;	/* magic number for identification */
@@ -57,9 +58,9 @@
 struct ext2_xattr_handler {
 	char *prefix;
 	size_t (*list)(char *list, struct inode *inode, const char *name,
-		       int name_len);
+		       int name_len, int flags);
 	int (*get)(struct inode *inode, const char *name, void *buffer,
-		   size_t size);
+		   size_t size, int flags);
 	int (*set)(struct inode *inode, const char *name, const void *buffer,
 		   size_t size, int flags);
 };
@@ -68,12 +69,12 @@
 extern void ext2_xattr_unregister(int, struct ext2_xattr_handler *);
 
 extern int ext2_setxattr(struct dentry *, const char *, const void *, size_t, int);
-extern ssize_t ext2_getxattr(struct dentry *, const char *, void *, size_t);
-extern ssize_t ext2_listxattr(struct dentry *, char *, size_t);
-extern int ext2_removexattr(struct dentry *, const char *);
+extern ssize_t ext2_getxattr(struct dentry *, const char *, void *, size_t, int);
+extern ssize_t ext2_listxattr(struct dentry *, char *, size_t, int);
+extern int ext2_removexattr(struct dentry *, const char *, int);
 
 extern int ext2_xattr_get(struct inode *, int, const char *, void *, size_t);
-extern int ext2_xattr_list(struct inode *, char *, size_t);
+extern int ext2_xattr_list(struct inode *, char *, size_t, int flags);
 extern int ext2_xattr_set(struct inode *, int, const char *, const void *, size_t, int);
 
 extern void ext2_xattr_delete_inode(struct inode *);
@@ -132,4 +133,5 @@
 # endif  /* CONFIG_EXT2_FS_XATTR */
 
 extern struct ext2_xattr_handler ext2_xattr_user_handler;
+extern struct ext2_xattr_handler ext2_xattr_trusted_handler;
 
diff -Nru a/fs/ext2/xattr_trusted.c b/fs/ext2/xattr_trusted.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/fs/ext2/xattr_trusted.c	Mon Feb 17 14:57:28 2003
@@ -0,0 +1,63 @@
+/*
+ * linux/fs/ext2/xattr_trusted.c
+ * Handler for trusted extended attributes.
+ *
+ * Copyright (C) 2003 by Andreas Gruenbacher, <a.gruenbacher@computer.org>
+ */
+
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/fs.h>
+#include <linux/smp_lock.h>
+#include <linux/ext2_fs.h>
+#include "xattr.h"
+
+#define XATTR_TRUSTED_PREFIX "trusted."
+
+static size_t
+ext2_xattr_trusted_list(char *list, struct inode *inode,
+			const char *name, int name_len, int flags)
+{
+	const int prefix_len = sizeof(XATTR_TRUSTED_PREFIX)-1;
+
+	if (!((flags & XATTR_KERNEL_CONTEXT) || capable(CAP_SYS_ADMIN)))
+		return 0;
+
+	if (list) {
+		memcpy(list, XATTR_TRUSTED_PREFIX, prefix_len);
+		memcpy(list+prefix_len, name, name_len);
+		list[prefix_len + name_len] = '\0';
+	}
+	return prefix_len + name_len + 1;
+}
+
+static int
+ext2_xattr_trusted_get(struct inode *inode, const char *name,
+		       void *buffer, size_t size, int flags)
+{
+	if (strcmp(name, "") == 0)
+		return -EINVAL;
+	if (!((flags & XATTR_KERNEL_CONTEXT) || capable(CAP_SYS_ADMIN)))
+		return -EPERM;
+	return ext2_xattr_get(inode, EXT2_XATTR_INDEX_TRUSTED, name,
+			      buffer, size);
+}
+
+static int
+ext2_xattr_trusted_set(struct inode *inode, const char *name,
+		       const void *value, size_t size, int flags)
+{
+	if (strcmp(name, "") == 0)
+		return -EINVAL;
+	if (!((flags & XATTR_KERNEL_CONTEXT) || capable(CAP_SYS_ADMIN)))
+		return -EPERM;
+	return ext2_xattr_set(inode, EXT2_XATTR_INDEX_TRUSTED, name,
+			      value, size, flags);
+}
+
+struct ext2_xattr_handler ext2_xattr_trusted_handler = {
+	.prefix	= XATTR_TRUSTED_PREFIX,
+	.list	= ext2_xattr_trusted_list,
+	.get	= ext2_xattr_trusted_get,
+	.set	= ext2_xattr_trusted_set,
+};
diff -Nru a/fs/ext2/xattr_user.c b/fs/ext2/xattr_user.c
--- a/fs/ext2/xattr_user.c	Mon Feb 17 14:57:27 2003
+++ b/fs/ext2/xattr_user.c	Mon Feb 17 14:57:27 2003
@@ -19,38 +19,41 @@
 
 static size_t
 ext2_xattr_user_list(char *list, struct inode *inode,
-		     const char *name, int name_len)
+		     const char *name, int name_len, int flags)
 {
 	const int prefix_len = sizeof(XATTR_USER_PREFIX)-1;
 
-	if (!test_opt(inode->i_sb, XATTR_USER))
+	if (!(flags & XATTR_KERNEL_CONTEXT) &&
+	    !test_opt(inode->i_sb, XATTR_USER))
 		return 0;
 
 	if (list) {
 		memcpy(list, XATTR_USER_PREFIX, prefix_len);
 		memcpy(list+prefix_len, name, name_len);
+		list[prefix_len + name_len] = '\0';
 	}
-	return prefix_len + name_len;
+	return prefix_len + name_len + 1;
 }
 
 static int
 ext2_xattr_user_get(struct inode *inode, const char *name,
-		    void *buffer, size_t size)
+		    void *buffer, size_t size, int flags)
 {
-	int error;
-
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
-	if (!test_opt(inode->i_sb, XATTR_USER))
-		return -EOPNOTSUPP;
+	if (!(flags & XATTR_KERNEL_CONTEXT)) {
+		int error;
+
+		if (!test_opt(inode->i_sb, XATTR_USER))
+			return -EOPNOTSUPP;
 #ifdef CONFIG_EXT2_FS_POSIX_ACL
-	error = ext2_permission_locked(inode, MAY_READ);
+		error = ext2_permission_locked(inode, MAY_READ);
 #else
-	error = permission(inode, MAY_READ);
+		error = permission(inode, MAY_READ);
 #endif
-	if (error)
-		return error;
-
+		if (error)
+			return error;
+	}
 	return ext2_xattr_get(inode, EXT2_XATTR_INDEX_USER, name,
 			      buffer, size);
 }
@@ -59,23 +62,24 @@
 ext2_xattr_user_set(struct inode *inode, const char *name,
 		    const void *value, size_t size, int flags)
 {
-	int error;
-
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
-	if (!test_opt(inode->i_sb, XATTR_USER))
-		return -EOPNOTSUPP;
 	if ( !S_ISREG(inode->i_mode) &&
 	    (!S_ISDIR(inode->i_mode) || inode->i_mode & S_ISVTX))
 		return -EPERM;
+	if (!(flags & XATTR_KERNEL_CONTEXT)) {
+		int error;
+
+		if (!test_opt(inode->i_sb, XATTR_USER))
+			return -EOPNOTSUPP;
 #ifdef CONFIG_EXT2_FS_POSIX_ACL
-	error = ext2_permission_locked(inode, MAY_WRITE);
+		error = ext2_permission_locked(inode, MAY_WRITE);
 #else
-	error = permission(inode, MAY_WRITE);
+		error = permission(inode, MAY_WRITE);
 #endif
-	if (error)
-		return error;
-  
+		if (error)
+			return error;
+	}
 	return ext2_xattr_set(inode, EXT2_XATTR_INDEX_USER, name,
 			      value, size, flags);
 }
diff -Nru a/fs/ext3/Makefile b/fs/ext3/Makefile
--- a/fs/ext3/Makefile	Mon Feb 17 14:57:26 2003
+++ b/fs/ext3/Makefile	Mon Feb 17 14:57:26 2003
@@ -8,7 +8,7 @@
 		ioctl.o namei.o super.o symlink.o hash.o
 
 ifeq ($(CONFIG_EXT3_FS_XATTR),y)
-ext3-objs += xattr.o xattr_user.o
+ext3-objs += xattr.o xattr_user.o xattr_trusted.o
 endif
 
 ifeq ($(CONFIG_EXT3_FS_POSIX_ACL),y)
diff -Nru a/fs/ext3/acl.c b/fs/ext3/acl.c
--- a/fs/ext3/acl.c	Mon Feb 17 14:57:27 2003
+++ b/fs/ext3/acl.c	Mon Feb 17 14:57:27 2003
@@ -431,28 +431,28 @@
  */
 static size_t
 ext3_xattr_list_acl_access(char *list, struct inode *inode,
-			   const char *name, int name_len)
+			   const char *name, int name_len, int flags)
 {
-	const size_t len = sizeof(XATTR_NAME_ACL_ACCESS)-1;
+	const size_t size = sizeof(XATTR_NAME_ACL_ACCESS);
 
 	if (!test_opt(inode->i_sb, POSIX_ACL))
 		return 0;
 	if (list)
-		memcpy(list, XATTR_NAME_ACL_ACCESS, len);
-	return len;
+		memcpy(list, XATTR_NAME_ACL_ACCESS, size);
+	return size;
 }
 
 static size_t
 ext3_xattr_list_acl_default(char *list, struct inode *inode,
-			    const char *name, int name_len)
+			    const char *name, int name_len, int flags)
 {
-	const size_t len = sizeof(XATTR_NAME_ACL_DEFAULT)-1;
+	const size_t size = sizeof(XATTR_NAME_ACL_DEFAULT);
 
 	if (!test_opt(inode->i_sb, POSIX_ACL))
 		return 0;
 	if (list)
-		memcpy(list, XATTR_NAME_ACL_DEFAULT, len);
-	return len;
+		memcpy(list, XATTR_NAME_ACL_DEFAULT, size);
+	return size;
 }
 
 static int
@@ -477,7 +477,7 @@
 
 static int
 ext3_xattr_get_acl_access(struct inode *inode, const char *name,
-			  void *buffer, size_t size)
+			  void *buffer, size_t size, int flags)
 {
 	if (strcmp(name, "") != 0)
 		return -EINVAL;
@@ -486,7 +486,7 @@
 
 static int
 ext3_xattr_get_acl_default(struct inode *inode, const char *name,
-			   void *buffer, size_t size)
+			   void *buffer, size_t size, int flags)
 {
 	if (strcmp(name, "") != 0)
 		return -EINVAL;
@@ -494,7 +494,8 @@
 }
 
 static int
-ext3_xattr_set_acl(struct inode *inode, int type, const void *value, size_t size)
+ext3_xattr_set_acl(struct inode *inode, int type, const void *value,
+		   size_t size)
 {
 	handle_t *handle;
 	struct posix_acl *acl;
diff -Nru a/fs/ext3/balloc.c b/fs/ext3/balloc.c
--- a/fs/ext3/balloc.c	Mon Feb 17 14:57:26 2003
+++ b/fs/ext3/balloc.c	Mon Feb 17 14:57:26 2003
@@ -503,7 +503,8 @@
 	
 got_block:
 
-	ext3_debug("using block group %d(%d)\n", i, gdp->bg_free_blocks_count);
+	ext3_debug("using block group %d(%d)\n",
+			group_no, gdp->bg_free_blocks_count);
 
 	/* Make sure we use undo access for the bitmap, because it is
            critical that we do the frozen_data COW on bitmap buffers in
@@ -658,7 +659,7 @@
 		bitmap_count += x;
 	}
 	brelse(bitmap_bh);
-	printk("ext3_count_free_blocks: stored = %lu, computed = %lu, %lu\n",
+	printk("ext3_count_free_blocks: stored = %u, computed = %lu, %lu\n",
 	       le32_to_cpu(es->s_free_blocks_count), desc_count, bitmap_count);
 	unlock_super(sb);
 	return bitmap_count;
diff -Nru a/fs/ext3/ialloc.c b/fs/ext3/ialloc.c
--- a/fs/ext3/ialloc.c	Mon Feb 17 14:57:27 2003
+++ b/fs/ext3/ialloc.c	Mon Feb 17 14:57:27 2003
@@ -704,7 +704,7 @@
 		bitmap_count += x;
 	}
 	brelse(bitmap_bh);
-	printk("ext3_count_free_inodes: stored = %lu, computed = %lu, %lu\n",
+	printk("ext3_count_free_inodes: stored = %u, computed = %lu, %lu\n",
 		le32_to_cpu(es->s_free_inodes_count), desc_count, bitmap_count);
 	unlock_super(sb);
 	return desc_count;
diff -Nru a/fs/ext3/inode.c b/fs/ext3/inode.c
--- a/fs/ext3/inode.c	Mon Feb 17 14:57:27 2003
+++ b/fs/ext3/inode.c	Mon Feb 17 14:57:27 2003
@@ -263,12 +263,12 @@
 static int ext3_alloc_block (handle_t *handle,
 			struct inode * inode, unsigned long goal, int *err)
 {
-#ifdef EXT3FS_DEBUG
-	static unsigned long alloc_hits = 0, alloc_attempts = 0;
-#endif
 	unsigned long result;
 
 #ifdef EXT3_PREALLOCATE
+#ifdef EXT3FS_DEBUG
+	static unsigned long alloc_hits = 0, alloc_attempts = 0;
+#endif
 	struct ext3_inode_info *ei = EXT3_I(inode);
 	/* Writer: ->i_prealloc* */
 	if (ei->i_prealloc_count &&
@@ -1357,14 +1357,21 @@
 	handle = ext3_journal_current_handle();
 	lock_kernel();
 
-	/* And attach them to the current transaction */
+	/*
+	 * And attach them to the current transaction.  But only if 
+	 * block_write_full_page() succeeded.  Otherwise they are unmapped,
+	 * and generally junk.
+	 */
 	if (order_data) {
-		err = walk_page_buffers(handle, page_bufs,
-			0, PAGE_CACHE_SIZE, NULL, ext3_journal_dirty_data);
+		if (ret == 0) {
+			err = walk_page_buffers(handle, page_bufs,
+				0, PAGE_CACHE_SIZE, NULL,
+				ext3_journal_dirty_data);
+			if (!ret)
+				ret = err;
+		}
 		walk_page_buffers(handle, page_bufs, 0,
 				PAGE_CACHE_SIZE, NULL, bput_one);
-		if (!ret)
-			ret = err;
 	}
 
 	err = ext3_journal_stop(handle, inode);
diff -Nru a/fs/ext3/xattr.c b/fs/ext3/xattr.c
--- a/fs/ext3/xattr.c	Mon Feb 17 14:57:27 2003
+++ b/fs/ext3/xattr.c	Mon Feb 17 14:57:27 2003
@@ -195,7 +195,7 @@
  */
 ssize_t
 ext3_getxattr(struct dentry *dentry, const char *name,
-	      void *buffer, size_t size)
+	      void *buffer, size_t size, int flags)
 {
 	struct ext3_xattr_handler *handler;
 	struct inode *inode = dentry->d_inode;
@@ -203,7 +203,7 @@
 	handler = ext3_xattr_resolve_name(&name);
 	if (!handler)
 		return -EOPNOTSUPP;
-	return handler->get(inode, name, buffer, size);
+	return handler->get(inode, name, buffer, size, flags);
 }
 
 /*
@@ -212,9 +212,9 @@
  * dentry->d_inode->i_sem down
  */
 ssize_t
-ext3_listxattr(struct dentry *dentry, char *buffer, size_t size)
+ext3_listxattr(struct dentry *dentry, char *buffer, size_t size, int flags)
 {
-	return ext3_xattr_list(dentry->d_inode, buffer, size);
+	return ext3_xattr_list(dentry->d_inode, buffer, size, flags);
 }
 
 /*
@@ -243,7 +243,7 @@
  * dentry->d_inode->i_sem down
  */
 int
-ext3_removexattr(struct dentry *dentry, const char *name)
+ext3_removexattr(struct dentry *dentry, const char *name, int flags)
 {
 	struct ext3_xattr_handler *handler;
 	struct inode *inode = dentry->d_inode;
@@ -251,7 +251,7 @@
 	handler = ext3_xattr_resolve_name(&name);
 	if (!handler)
 		return -EOPNOTSUPP;
-	return handler->set(inode, name, NULL, 0, XATTR_REPLACE);
+	return handler->set(inode, name, NULL, 0, flags | XATTR_REPLACE);
 }
 
 /*
@@ -364,7 +364,8 @@
  * used / required on success.
  */
 int
-ext3_xattr_list(struct inode *inode, char *buffer, size_t buffer_size)
+ext3_xattr_list(struct inode *inode, char *buffer, size_t buffer_size,
+		int flags)
 {
 	struct buffer_head *bh = NULL;
 	struct ext3_xattr_entry *entry;
@@ -402,10 +403,9 @@
 			goto bad_block;
 
 		handler = ext3_xattr_handler(entry->e_name_index);
-		if (handler) {
+		if (handler)
 			size += handler->list(NULL, inode, entry->e_name,
-					      entry->e_name_len) + 1;
-		}
+					      entry->e_name_len, flags);
 	}
 
 	if (ext3_xattr_cache_insert(bh))
@@ -426,11 +426,9 @@
 		struct ext3_xattr_handler *handler;
 
 		handler = ext3_xattr_handler(entry->e_name_index);
-		if (handler) {
+		if (handler)
 			buf += handler->list(buf, inode, entry->e_name,
-					     entry->e_name_len);
-			*buf++ = '\0';
-		}
+					     entry->e_name_len, flags);
 	}
 	error = size;
 
@@ -848,7 +846,7 @@
 	       const void *value, size_t value_len, int flags)
 {
 	handle_t *handle;
-	int error;
+	int error, error2;
 
 	lock_kernel();
 	handle = ext3_journal_start(inode, EXT3_XATTR_TRANS_BLOCKS);
@@ -857,10 +855,10 @@
 	else
 		error = ext3_xattr_set_handle(handle, inode, name_index, name,
 					      value, value_len, flags);
-	ext3_journal_stop(handle, inode);
+	error2 = ext3_journal_stop(handle, inode);
 	unlock_kernel();
 
-	return error;
+	return error ? error : error2;
 }
 
 /*
@@ -1135,27 +1133,35 @@
 {
 	int	err;
 	
-	err = ext3_xattr_register(EXT3_XATTR_INDEX_USER, &ext3_xattr_user_handler);
+	err = ext3_xattr_register(EXT3_XATTR_INDEX_USER,
+				  &ext3_xattr_user_handler);
 	if (err)
 		return err;
+	err = ext3_xattr_register(EXT3_XATTR_INDEX_TRUSTED,
+				  &ext3_xattr_trusted_handler);
+	if (err)
+		goto out;
 #ifdef CONFIG_EXT3_FS_POSIX_ACL
 	err = init_ext3_acl();
 	if (err)
-		goto out;
+		goto out1;
 #endif
 	ext3_xattr_cache = mb_cache_create("ext3_xattr", NULL,
 		sizeof(struct mb_cache_entry) +
 		sizeof(struct mb_cache_entry_index), 1, 6);
 	if (!ext3_xattr_cache) {
 		err = -ENOMEM;
-		goto out1;
+		goto out2;
 	}
 	return 0;
-out1:
+out2:
 #ifdef CONFIG_EXT3_FS_POSIX_ACL
 	exit_ext3_acl();
-out:
+out1:
 #endif
+	ext3_xattr_unregister(EXT3_XATTR_INDEX_TRUSTED,
+			      &ext3_xattr_trusted_handler);
+out:
 	ext3_xattr_unregister(EXT3_XATTR_INDEX_USER,
 			      &ext3_xattr_user_handler);
 	return err;
@@ -1170,5 +1176,8 @@
 #ifdef CONFIG_EXT3_FS_POSIX_ACL
 	exit_ext3_acl();
 #endif
-	ext3_xattr_unregister(EXT3_XATTR_INDEX_USER, &ext3_xattr_user_handler);
+	ext3_xattr_unregister(EXT3_XATTR_INDEX_TRUSTED,
+			      &ext3_xattr_trusted_handler);
+	ext3_xattr_unregister(EXT3_XATTR_INDEX_USER,
+			      &ext3_xattr_user_handler);
 }
diff -Nru a/fs/ext3/xattr.h b/fs/ext3/xattr.h
--- a/fs/ext3/xattr.h	Mon Feb 17 14:57:28 2003
+++ b/fs/ext3/xattr.h	Mon Feb 17 14:57:28 2003
@@ -20,6 +20,7 @@
 #define EXT3_XATTR_INDEX_USER			1
 #define EXT3_XATTR_INDEX_POSIX_ACL_ACCESS	2
 #define EXT3_XATTR_INDEX_POSIX_ACL_DEFAULT	3
+#define EXT3_XATTR_INDEX_TRUSTED		4
 
 struct ext3_xattr_header {
 	__u32	h_magic;	/* magic number for identification */
@@ -56,9 +57,9 @@
 struct ext3_xattr_handler {
 	char *prefix;
 	size_t (*list)(char *list, struct inode *inode, const char *name,
-		       int name_len);
+		       int name_len, int flags);
 	int (*get)(struct inode *inode, const char *name, void *buffer,
-		   size_t size);
+		   size_t size, int flags);
 	int (*set)(struct inode *inode, const char *name, const void *buffer,
 		   size_t size, int flags);
 };
@@ -67,12 +68,12 @@
 extern void ext3_xattr_unregister(int, struct ext3_xattr_handler *);
 
 extern int ext3_setxattr(struct dentry *, const char *, const void *, size_t, int);
-extern ssize_t ext3_getxattr(struct dentry *, const char *, void *, size_t);
-extern ssize_t ext3_listxattr(struct dentry *, char *, size_t);
-extern int ext3_removexattr(struct dentry *, const char *);
+extern ssize_t ext3_getxattr(struct dentry *, const char *, void *, size_t, int);
+extern ssize_t ext3_listxattr(struct dentry *, char *, size_t, int);
+extern int ext3_removexattr(struct dentry *, const char *, int);
 
 extern int ext3_xattr_get(struct inode *, int, const char *, void *, size_t);
-extern int ext3_xattr_list(struct inode *, char *, size_t);
+extern int ext3_xattr_list(struct inode *, char *, size_t, int flags);
 extern int ext3_xattr_set(struct inode *, int, const char *, const void *, size_t, int);
 extern int ext3_xattr_set_handle(handle_t *, struct inode *, int, const char *, const void *, size_t, int);
 
@@ -139,3 +140,4 @@
 # endif  /* CONFIG_EXT3_FS_XATTR */
 
 extern struct ext3_xattr_handler ext3_xattr_user_handler;
+extern struct ext3_xattr_handler ext3_xattr_trusted_handler;
diff -Nru a/fs/ext3/xattr_trusted.c b/fs/ext3/xattr_trusted.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/fs/ext3/xattr_trusted.c	Mon Feb 17 14:57:28 2003
@@ -0,0 +1,64 @@
+/*
+ * linux/fs/ext3/xattr_trusted.c
+ * Handler for trusted extended attributes.
+ *
+ * Copyright (C) 2003 by Andreas Gruenbacher, <a.gruenbacher@computer.org>
+ */
+
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/fs.h>
+#include <linux/smp_lock.h>
+#include <linux/ext3_jbd.h>
+#include <linux/ext3_fs.h>
+#include "xattr.h"
+
+#define XATTR_TRUSTED_PREFIX "trusted."
+
+static size_t
+ext3_xattr_trusted_list(char *list, struct inode *inode,
+			const char *name, int name_len, int flags)
+{
+	const int prefix_len = sizeof(XATTR_TRUSTED_PREFIX)-1;
+
+	if (!((flags & XATTR_KERNEL_CONTEXT) || capable(CAP_SYS_ADMIN)))
+		return 0;
+
+	if (list) {
+		memcpy(list, XATTR_TRUSTED_PREFIX, prefix_len);
+		memcpy(list+prefix_len, name, name_len);
+		list[prefix_len + name_len] = '\0';
+	}
+	return prefix_len + name_len + 1;
+}
+
+static int
+ext3_xattr_trusted_get(struct inode *inode, const char *name,
+		       void *buffer, size_t size, int flags)
+{
+	if (strcmp(name, "") == 0)
+		return -EINVAL;
+	if (!((flags & XATTR_KERNEL_CONTEXT) || capable(CAP_SYS_ADMIN)))
+		return -EPERM;
+	return ext3_xattr_get(inode, EXT3_XATTR_INDEX_TRUSTED, name,
+			      buffer, size);
+}
+
+static int
+ext3_xattr_trusted_set(struct inode *inode, const char *name,
+		       const void *value, size_t size, int flags)
+{
+	if (strcmp(name, "") == 0)
+		return -EINVAL;
+	if (!((flags & XATTR_KERNEL_CONTEXT) || capable(CAP_SYS_ADMIN)))
+		return -EPERM;
+	return ext3_xattr_set(inode, EXT3_XATTR_INDEX_TRUSTED, name,
+			      value, size, flags);
+}
+
+struct ext3_xattr_handler ext3_xattr_trusted_handler = {
+	.prefix	= XATTR_TRUSTED_PREFIX,
+	.list	= ext3_xattr_trusted_list,
+	.get	= ext3_xattr_trusted_get,
+	.set	= ext3_xattr_trusted_set,
+};
diff -Nru a/fs/ext3/xattr_user.c b/fs/ext3/xattr_user.c
--- a/fs/ext3/xattr_user.c	Mon Feb 17 14:57:26 2003
+++ b/fs/ext3/xattr_user.c	Mon Feb 17 14:57:26 2003
@@ -21,38 +21,41 @@
 
 static size_t
 ext3_xattr_user_list(char *list, struct inode *inode,
-		     const char *name, int name_len)
+		     const char *name, int name_len, int flags)
 {
 	const int prefix_len = sizeof(XATTR_USER_PREFIX)-1;
 
-	if (!test_opt(inode->i_sb, XATTR_USER))
+	if (!(flags & XATTR_KERNEL_CONTEXT) &&
+	    !test_opt(inode->i_sb, XATTR_USER))
 		return 0;
 
 	if (list) {
 		memcpy(list, XATTR_USER_PREFIX, prefix_len);
 		memcpy(list+prefix_len, name, name_len);
+		list[prefix_len + name_len] = '\0';
 	}
-	return prefix_len + name_len;
+	return prefix_len + name_len + 1;
 }
 
 static int
 ext3_xattr_user_get(struct inode *inode, const char *name,
-		    void *buffer, size_t size)
+		    void *buffer, size_t size, int flags)
 {
-	int error;
-
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
-	if (!test_opt(inode->i_sb, XATTR_USER))
-		return -EOPNOTSUPP;
+	if (!(flags & XATTR_KERNEL_CONTEXT)) {
+		int error;
+
+		if (!test_opt(inode->i_sb, XATTR_USER))
+			return -EOPNOTSUPP;
 #ifdef CONFIG_EXT3_FS_POSIX_ACL
-	error = ext3_permission_locked(inode, MAY_READ);
+		error = ext3_permission_locked(inode, MAY_READ);
 #else
-	error = permission(inode, MAY_READ);
+		error = permission(inode, MAY_READ);
 #endif
-	if (error)
-		return error;
-
+		if (error)
+			return error;
+	}
 	return ext3_xattr_get(inode, EXT3_XATTR_INDEX_USER, name,
 			      buffer, size);
 }
@@ -61,26 +64,26 @@
 ext3_xattr_user_set(struct inode *inode, const char *name,
 		    const void *value, size_t size, int flags)
 {
-	int error;
-
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
-	if (!test_opt(inode->i_sb, XATTR_USER))
-		return -EOPNOTSUPP;
 	if ( !S_ISREG(inode->i_mode) &&
 	    (!S_ISDIR(inode->i_mode) || inode->i_mode & S_ISVTX))
 		return -EPERM;
+	if (!(flags & XATTR_KERNEL_CONTEXT)) {
+		int error;
+
+		if (!test_opt(inode->i_sb, XATTR_USER))
+			return -EOPNOTSUPP;
 #ifdef CONFIG_EXT3_FS_POSIX_ACL
-	error = ext3_permission_locked(inode, MAY_WRITE);
+		error = ext3_permission_locked(inode, MAY_WRITE);
 #else
-	error = permission(inode, MAY_WRITE);
+		error = permission(inode, MAY_WRITE);
 #endif
-	if (error)
-		return error;
-  
+		if (error)
+			return error;
+	}
 	return ext3_xattr_set(inode, EXT3_XATTR_INDEX_USER, name,
 			      value, size, flags);
-
 }
 
 struct ext3_xattr_handler ext3_xattr_user_handler = {
diff -Nru a/fs/jfs/jfs_debug.h b/fs/jfs/jfs_debug.h
--- a/fs/jfs/jfs_debug.h	Mon Feb 17 14:57:27 2003
+++ b/fs/jfs/jfs_debug.h	Mon Feb 17 14:57:27 2003
@@ -89,8 +89,7 @@
 /* error event message: e.g., i/o error */
 #define jfs_err(fmt, arg...) do {			\
 	if (jfsloglevel >= JFS_LOGLEVEL_ERR)		\
-		printk(KERN_ERR "%s:%d " fmt "\n",	\
-		       __FILE__, __LINE__, ## arg);	\
+		printk(KERN_ERR fmt "\n", ## arg);	\
 } while (0)
 
 /*
diff -Nru a/fs/jfs/jfs_logmgr.c b/fs/jfs/jfs_logmgr.c
--- a/fs/jfs/jfs_logmgr.c	Mon Feb 17 14:57:27 2003
+++ b/fs/jfs/jfs_logmgr.c	Mon Feb 17 14:57:27 2003
@@ -97,7 +97,7 @@
 #define LOGGC_LOCK_INIT(log)	spin_lock_init(&(log)->gclock)
 #define LOGGC_LOCK(log)		spin_lock_irq(&(log)->gclock)
 #define LOGGC_UNLOCK(log)	spin_unlock_irq(&(log)->gclock)
-#define LOGGC_WAKEUP(tblk)	wake_up(&(tblk)->gcwait)
+#define LOGGC_WAKEUP(tblk)	wake_up_all(&(tblk)->gcwait)
 
 /*
  *	log sync serialization (per log)
@@ -511,7 +511,6 @@
 			tblk->bp = log->bp;
 			tblk->pn = log->page;
 			tblk->eor = log->eor;
-			init_waitqueue_head(&tblk->gcwait);
 
 			/* enqueue transaction to commit queue */
 			tblk->cqnext = NULL;
@@ -831,6 +830,12 @@
 		tblk->flag &= ~tblkGC_QUEUE;
 		tblk->cqnext = 0;
 
+		if (tblk == log->flush_tblk) {
+			/* we can stop flushing the log now */
+			clear_bit(log_FLUSH, &log->flag);
+			log->flush_tblk = NULL;
+		}
+
 		jfs_info("lmPostGC: tblk = 0x%p, flag = 0x%x", tblk,
 			 tblk->flag);
 
@@ -843,10 +848,10 @@
 			/* state transition: COMMIT -> COMMITTED */
 			tblk->flag |= tblkGC_COMMITTED;
 
-			if (tblk->flag & tblkGC_READY) {
+			if (tblk->flag & tblkGC_READY)
 				log->gcrtc--;
-				LOGGC_WAKEUP(tblk);
-			}
+
+			LOGGC_WAKEUP(tblk);
 		}
 
 		/* was page full before pageout ?
@@ -892,6 +897,7 @@
 	else {
 		log->cflag &= ~logGC_PAGEOUT;
 		clear_bit(log_FLUSH, &log->flag);
+		WARN_ON(log->flush_tblk);
 	}
 
 	//LOGGC_UNLOCK(log);
@@ -1307,7 +1313,8 @@
 
 	INIT_LIST_HEAD(&log->synclist);
 
-	log->cqueue.head = log->cqueue.tail = 0;
+	log->cqueue.head = log->cqueue.tail = NULL;
+	log->flush_tblk = NULL;
 
 	log->count = 0;
 
@@ -1395,38 +1402,78 @@
  *
  * FUNCTION:	initiate write of any outstanding transactions to the journal
  *		and optionally wait until they are all written to disk
+ *
+ *		wait == 0  flush until latest txn is committed, don't wait
+ *		wait == 1  flush until latest txn is committed, wait
+ *		wait > 1   flush until all txn's are complete, wait
  */
 void jfs_flush_journal(struct jfs_log *log, int wait)
 {
 	int i;
+	struct tblock *target;
 
 	jfs_info("jfs_flush_journal: log:0x%p wait=%d", log, wait);
 
-	/*
-	 * This ensures that we will keep writing to the journal as long
-	 * as there are unwritten commit records
-	 */
-	set_bit(log_FLUSH, &log->flag);
-
-	/*
-	 * Initiate I/O on outstanding transactions
-	 */
 	LOGGC_LOCK(log);
-	if (log->cqueue.head && !(log->cflag & logGC_PAGEOUT)) {
-		log->cflag |= logGC_PAGEOUT;
-		lmGCwrite(log, 0);
+
+	target = log->cqueue.head;
+
+	if (target) {
+		/*
+		 * This ensures that we will keep writing to the journal as long
+		 * as there are unwritten commit records
+		 */
+
+		if (test_bit(log_FLUSH, &log->flag)) {
+			/*
+			 * We're already flushing.
+			 * if flush_tblk is NULL, we are flushing everything,
+			 * so leave it that way.  Otherwise, update it to the
+			 * latest transaction
+			 */
+			if (log->flush_tblk)
+				log->flush_tblk = target;
+		} else {
+			/* Only flush until latest transaction is committed */
+			log->flush_tblk = target;
+			set_bit(log_FLUSH, &log->flag);
+
+			/*
+			 * Initiate I/O on outstanding transactions
+			 */
+			if (!(log->cflag & logGC_PAGEOUT)) {
+				log->cflag |= logGC_PAGEOUT;
+				lmGCwrite(log, 0);
+			}
+		}
+	}
+	if ((wait > 1) || test_bit(log_SYNCBARRIER, &log->flag)) {
+		/* Flush until all activity complete */
+		set_bit(log_FLUSH, &log->flag);
+		log->flush_tblk = NULL;
+	}
+
+	if (wait && target && !(target->flag & tblkGC_COMMITTED)) {
+		DECLARE_WAITQUEUE(__wait, current);
+
+		add_wait_queue(&target->gcwait, &__wait);
+		set_current_state(TASK_UNINTERRUPTIBLE);
+		LOGGC_UNLOCK(log);
+		schedule();
+		current->state = TASK_RUNNING;
+		LOGGC_LOCK(log);
+		remove_wait_queue(&target->gcwait, &__wait);
 	}
 	LOGGC_UNLOCK(log);
 
-	if (!wait)
+	if (wait < 2)
 		return;
 
+	/*
+	 * If there was recent activity, we may need to wait
+	 * for the lazycommit thread to catch up
+	 */
 	if (log->cqueue.head || !list_empty(&log->synclist)) {
-		/*
-		 * If there was very recent activity, we may need to wait
-		 * for the lazycommit thread to catch up
-		 */
-
 		for (i = 0; i < 800; i++) {	/* Too much? */
 			current->state = TASK_INTERRUPTIBLE;
 			schedule_timeout(HZ / 4);
@@ -1437,7 +1484,6 @@
 	}
 	assert(log->cqueue.head == NULL);
 	assert(list_empty(&log->synclist));
-
 	clear_bit(log_FLUSH, &log->flag);
 }
 
@@ -1467,7 +1513,7 @@
 
 	jfs_info("lmLogShutdown: log:0x%p", log);
 
-	jfs_flush_journal(log, 1);
+	jfs_flush_journal(log, 2);
 
 	/*
 	 * We need to make sure all of the "written" metapages
diff -Nru a/fs/jfs/jfs_logmgr.h b/fs/jfs/jfs_logmgr.h
--- a/fs/jfs/jfs_logmgr.h	Mon Feb 17 14:57:27 2003
+++ b/fs/jfs/jfs_logmgr.h	Mon Feb 17 14:57:27 2003
@@ -403,6 +403,7 @@
 		struct tblock *head;
 		struct tblock *tail;
 	} cqueue;
+	struct tblock *flush_tblk; /* tblk we're waiting on for flush */
 	int gcrtc;		/* 4: GC_READY transaction count */
 	struct tblock *gclrt;	/* 4: latest GC_READY transaction */
 	spinlock_t gclock;	/* 4: group commit lock */
diff -Nru a/fs/jfs/jfs_txnmgr.c b/fs/jfs/jfs_txnmgr.c
--- a/fs/jfs/jfs_txnmgr.c	Mon Feb 17 14:57:27 2003
+++ b/fs/jfs/jfs_txnmgr.c	Mon Feb 17 14:57:27 2003
@@ -2741,8 +2741,7 @@
 	if (tblk->flag & tblkGC_READY)
 		log->gcrtc--;
 
-	if (tblk->flag & tblkGC_READY)
-		wake_up(&tblk->gcwait);	// LOGGC_WAKEUP
+	wake_up_all(&tblk->gcwait);	// LOGGC_WAKEUP
 
 	/*
 	 * Can't release log->gclock until we've tested tblk->flag
diff -Nru a/fs/jfs/jfs_umount.c b/fs/jfs/jfs_umount.c
--- a/fs/jfs/jfs_umount.c	Mon Feb 17 14:57:27 2003
+++ b/fs/jfs/jfs_umount.c	Mon Feb 17 14:57:27 2003
@@ -69,7 +69,7 @@
 		/*
 		 * Wait for outstanding transactions to be written to log: 
 		 */
-		jfs_flush_journal(log, 1);
+		jfs_flush_journal(log, 2);
 
 	/*
 	 * close fileset inode allocation map (aka fileset inode)
@@ -149,7 +149,7 @@
 	 *
 	 * remove file system from log active file system list.
 	 */
-	jfs_flush_journal(log, 1);
+	jfs_flush_journal(log, 2);
 
 	/*
 	 * Make sure all metadata makes it to disk
diff -Nru a/fs/jfs/jfs_xattr.h b/fs/jfs/jfs_xattr.h
--- a/fs/jfs/jfs_xattr.h	Mon Feb 17 14:57:28 2003
+++ b/fs/jfs/jfs_xattr.h	Mon Feb 17 14:57:28 2003
@@ -57,8 +57,8 @@
 extern int jfs_setxattr(struct dentry *, const char *, const void *, size_t,
 			int);
 extern ssize_t __jfs_getxattr(struct inode *, const char *, void *, size_t);
-extern ssize_t jfs_getxattr(struct dentry *, const char *, void *, size_t);
-extern ssize_t jfs_listxattr(struct dentry *, char *, size_t);
-extern int jfs_removexattr(struct dentry *, const char *);
+extern ssize_t jfs_getxattr(struct dentry *, const char *, void *, size_t, int);
+extern ssize_t jfs_listxattr(struct dentry *, char *, size_t, int);
+extern int jfs_removexattr(struct dentry *, const char *, int);
 
 #endif	/* H_JFS_XATTR */
diff -Nru a/fs/jfs/xattr.c b/fs/jfs/xattr.c
--- a/fs/jfs/xattr.c	Mon Feb 17 14:57:27 2003
+++ b/fs/jfs/xattr.c	Mon Feb 17 14:57:27 2003
@@ -962,12 +962,13 @@
 }
 
 ssize_t jfs_getxattr(struct dentry *dentry, const char *name, void *data,
-		     size_t buf_size)
+		     size_t buf_size, int flags)
 {
 	return __jfs_getxattr(dentry->d_inode, name, data, buf_size);
 }
 
-ssize_t jfs_listxattr(struct dentry * dentry, char *data, size_t buf_size)
+ssize_t jfs_listxattr(struct dentry * dentry, char *data, size_t buf_size,
+		      int flags)
 {
 	struct inode *inode = dentry->d_inode;
 	char *buffer;
@@ -1013,7 +1014,7 @@
 	return size;
 }
 
-int jfs_removexattr(struct dentry *dentry, const char *name)
+int jfs_removexattr(struct dentry *dentry, const char *name, int flags)
 {
 	return __jfs_setxattr(dentry->d_inode, name, 0, 0, XATTR_REPLACE);
 }
diff -Nru a/fs/locks.c b/fs/locks.c
--- a/fs/locks.c	Mon Feb 17 14:57:28 2003
+++ b/fs/locks.c	Mon Feb 17 14:57:28 2003
@@ -652,63 +652,6 @@
 	return 0;
 }
 
-int locks_mandatory_locked(struct inode *inode)
-{
-	fl_owner_t owner = current->files;
-	struct file_lock *fl;
-
-	/*
-	 * Search the lock list for this inode for any POSIX locks.
-	 */
-	lock_kernel();
-	for (fl = inode->i_flock; fl != NULL; fl = fl->fl_next) {
-		if (!IS_POSIX(fl))
-			continue;
-		if (fl->fl_owner != owner)
-			break;
-	}
-	unlock_kernel();
-	return fl ? -EAGAIN : 0;
-}
-
-int locks_mandatory_area(int read_write, struct inode *inode,
-			 struct file *filp, loff_t offset,
-			 size_t count)
-{
-	struct file_lock fl;
-	int error;
-
-	fl.fl_owner = current->files;
-	fl.fl_pid = current->tgid;
-	fl.fl_file = filp;
-	fl.fl_flags = FL_POSIX | FL_ACCESS | FL_SLEEP;
-	fl.fl_type = (read_write == FLOCK_VERIFY_WRITE) ? F_WRLCK : F_RDLCK;
-	fl.fl_start = offset;
-	fl.fl_end = offset + count - 1;
-
-	for (;;) {
-		error = posix_lock_file(filp, &fl);
-		if (error != -EAGAIN)
-			break;
-		error = wait_event_interruptible(fl.fl_wait, !fl.fl_next);
-		if (!error) {
-			/*
-			 * If we've been sleeping someone might have
-			 * changed the permissions behind our back.
-			 */
-			if ((inode->i_mode & (S_ISGID | S_IXGRP)) == S_ISGID)
-				continue;
-		}
-
-		lock_kernel();
-		locks_delete_block(&fl);
-		unlock_kernel();
-		break;
-	}
-
-	return error;
-}
-
 /* Try to create a FLOCK lock on filp. We always insert new FLOCK locks
  * at the head of the list, but that's secret knowledge known only to
  * flock_lock_file and posix_lock_file.
@@ -770,32 +713,13 @@
 	return error;
 }
 
-/**
- *	posix_lock_file:
- *	@filp: The file to apply the lock to
- *	@caller: The lock to be applied
- *	@wait: 1 to retry automatically, 0 to return -EAGAIN
- *
- * Add a POSIX style lock to a file.
- * We merge adjacent locks whenever possible. POSIX locks are sorted by owner
- * task, then by starting address
- *
- * Kai Petzke writes:
- * To make freeing a lock much faster, we keep a pointer to the lock before the
- * actual one. But the real gain of the new coding was, that lock_it() and
- * unlock_it() became one function.
- *
- * To all purists: Yes, I use a few goto's. Just pass on to the next function.
- */
-
-int posix_lock_file(struct file *filp, struct file_lock *request)
+static int __posix_lock_file(struct inode *inode, struct file_lock *request)
 {
 	struct file_lock *fl;
 	struct file_lock *new_fl, *new_fl2;
 	struct file_lock *left = NULL;
 	struct file_lock *right = NULL;
 	struct file_lock **before;
-	struct inode * inode = filp->f_dentry->d_inode;
 	int error, added = 0;
 
 	/*
@@ -804,9 +728,6 @@
 	 */
 	new_fl = locks_alloc_lock(0);
 	new_fl2 = locks_alloc_lock(0);
-	error = -ENOLCK; /* "no luck" */
-	if (!(new_fl && new_fl2))
-		goto out_nolock;
 
 	lock_kernel();
 	if (request->fl_type != F_UNLCK) {
@@ -829,9 +750,14 @@
   	}
 
 	/* If we're just looking for a conflict, we're done. */
+	error = 0;
 	if (request->fl_flags & FL_ACCESS)
 		goto out;
 
+	error = -ENOLCK; /* "no luck" */
+	if (!(new_fl && new_fl2))
+		goto out;
+
 	/*
 	 * We've allocated the new locks in advance, so there are no
 	 * errors possible (and no blocking operations) from here on.
@@ -952,9 +878,8 @@
 		left->fl_end = request->fl_start - 1;
 		locks_wake_up_blocks(left);
 	}
-out:
+ out:
 	unlock_kernel();
-out_nolock:
 	/*
 	 * Free any unused locks.
 	 */
@@ -965,6 +890,102 @@
 	return error;
 }
 
+/**
+ * posix_lock_file - Apply a POSIX-style lock to a file
+ * @filp: The file to apply the lock to
+ * @fl: The lock to be applied
+ *
+ * Add a POSIX style lock to a file.
+ * We merge adjacent & overlapping locks whenever possible.
+ * POSIX locks are sorted by owner task, then by starting address
+ */
+int posix_lock_file(struct file *filp, struct file_lock *fl)
+{
+	return __posix_lock_file(filp->f_dentry->d_inode, fl);
+}
+
+/**
+ * locks_mandatory_locked - Check for an active lock
+ * @inode: the file to check
+ *
+ * Searches the inode's list of locks to find any POSIX locks which conflict.
+ * This function is called from locks_verify_locked() only.
+ */
+int locks_mandatory_locked(struct inode *inode)
+{
+	fl_owner_t owner = current->files;
+	struct file_lock *fl;
+
+	/*
+	 * Search the lock list for this inode for any POSIX locks.
+	 */
+	lock_kernel();
+	for (fl = inode->i_flock; fl != NULL; fl = fl->fl_next) {
+		if (!IS_POSIX(fl))
+			continue;
+		if (fl->fl_owner != owner)
+			break;
+	}
+	unlock_kernel();
+	return fl ? -EAGAIN : 0;
+}
+
+/**
+ * locks_mandatory_area - Check for a conflicting lock
+ * @read_write: %FLOCK_VERIFY_WRITE for exclusive access, %FLOCK_VERIFY_READ
+ *		for shared
+ * @inode: the file to check
+ * @file: how the file was opened (if it was)
+ * @offset: start of area to check
+ * @count: length of area to check
+ *
+ * Searches the inode's list of locks to find any POSIX locks which conflict.
+ * This function is called from locks_verify_area() and
+ * locks_verify_truncate().
+ */
+int locks_mandatory_area(int read_write, struct inode *inode,
+			 struct file *filp, loff_t offset,
+			 size_t count)
+{
+	struct file_lock fl;
+	int error;
+
+	locks_init_lock(&fl);
+	fl.fl_owner = current->files;
+	fl.fl_pid = current->tgid;
+	fl.fl_file = filp;
+	fl.fl_flags = FL_POSIX | FL_ACCESS;
+	if (filp && !(filp->f_flags & O_NONBLOCK))
+		fl.fl_flags |= FL_SLEEP;
+	fl.fl_type = (read_write == FLOCK_VERIFY_WRITE) ? F_WRLCK : F_RDLCK;
+	fl.fl_start = offset;
+	fl.fl_end = offset + count - 1;
+
+	for (;;) {
+		error = __posix_lock_file(inode, &fl);
+		if (error != -EAGAIN)
+			break;
+		if (!(fl.fl_flags & FL_SLEEP))
+			break;
+		error = wait_event_interruptible(fl.fl_wait, !fl.fl_next);
+		if (!error) {
+			/*
+			 * If we've been sleeping someone might have
+			 * changed the permissions behind our back.
+			 */
+			if ((inode->i_mode & (S_ISGID | S_IXGRP)) == S_ISGID)
+				continue;
+		}
+
+		lock_kernel();
+		locks_delete_block(&fl);
+		unlock_kernel();
+		break;
+	}
+
+	return error;
+}
+
 /* We already had a lease on this file; just change its type */
 static int lease_modify(struct file_lock **before, int arg)
 {
@@ -1460,7 +1481,7 @@
 	}
 
 	for (;;) {
-		error = posix_lock_file(filp, file_lock);
+		error = __posix_lock_file(inode, file_lock);
 		if ((error != -EAGAIN) || (cmd == F_SETLK))
 			break;
 		error = wait_event_interruptible(file_lock->fl_wait,
@@ -1600,7 +1621,7 @@
 	}
 
 	for (;;) {
-		error = posix_lock_file(filp, file_lock);
+		error = __posix_lock_file(inode, file_lock);
 		if ((error != -EAGAIN) || (cmd == F_SETLK64))
 			break;
 		error = wait_event_interruptible(file_lock->fl_wait,
diff -Nru a/fs/namei.c b/fs/namei.c
--- a/fs/namei.c	Mon Feb 17 14:57:27 2003
+++ b/fs/namei.c	Mon Feb 17 14:57:27 2003
@@ -286,27 +286,6 @@
 	return dentry;
 }
 
-/*for fastwalking*/
-static inline void unlock_nd(struct nameidata *nd)
-{
-	struct vfsmount *mnt = nd->old_mnt;
-	struct dentry *dentry = nd->old_dentry;
-	mntget(nd->mnt);
-	dget_locked(nd->dentry);
-	nd->old_mnt = NULL;
-	nd->old_dentry = NULL;
-	spin_unlock(&dcache_lock);
-	dput(dentry);
-	mntput(mnt);
-}
-
-static inline void lock_nd(struct nameidata *nd)
-{
-	spin_lock(&dcache_lock);
-	nd->old_mnt = nd->mnt;
-	nd->old_dentry = nd->dentry;
-}
-
 /*
  * Short-cut version of permission(), for calling by
  * path_walk(), when dcache lock is held.  Combines parts
@@ -451,11 +430,18 @@
 {
 	int res = 0;
 	while (d_mountpoint(*dentry)) {
-		struct vfsmount *mounted = lookup_mnt(*mnt, *dentry);
-		if (!mounted)
+		struct vfsmount *mounted;
+		spin_lock(&dcache_lock);
+		mounted = lookup_mnt(*mnt, *dentry);
+		if (!mounted) {
+			spin_unlock(&dcache_lock);
 			break;
-		*mnt = mounted;
-		*dentry = mounted->mnt_root;
+		}
+		*mnt = mntget(mounted);
+		spin_unlock(&dcache_lock);
+		dput(*dentry);
+		mntput(mounted->mnt_parent);
+		*dentry = dget(mounted->mnt_root);
 		res = 1;
 	}
 	return res;
@@ -488,17 +474,32 @@
 {
 	while(1) {
 		struct vfsmount *parent;
+		struct dentry *old = *dentry;
+
+                read_lock(&current->fs->lock);
 		if (*dentry == current->fs->root &&
-		    *mnt == current->fs->rootmnt)
+		    *mnt == current->fs->rootmnt) {
+                        read_unlock(&current->fs->lock);
 			break;
+		}
+                read_unlock(&current->fs->lock);
+		spin_lock(&dcache_lock);
 		if (*dentry != (*mnt)->mnt_root) {
-			*dentry = (*dentry)->d_parent;
+			*dentry = dget((*dentry)->d_parent);
+			spin_unlock(&dcache_lock);
+			dput(old);
 			break;
 		}
-		parent=(*mnt)->mnt_parent;
-		if (parent == *mnt)
+		parent = (*mnt)->mnt_parent;
+		if (parent == *mnt) {
+			spin_unlock(&dcache_lock);
 			break;
-		*dentry=(*mnt)->mnt_mountpoint;
+		}
+		mntget(parent);
+		*dentry = dget((*mnt)->mnt_mountpoint);
+		spin_unlock(&dcache_lock);
+		dput(old);
+		mntput(*mnt);
 		*mnt = parent;
 	}
 	follow_mount(mnt, dentry);
@@ -515,14 +516,13 @@
  *  It _is_ time-critical.
  */
 static int do_lookup(struct nameidata *nd, struct qstr *name,
-		     struct path *path, struct path *cached_path,
-		     int flags)
+		     struct path *path, int flags)
 {
 	struct vfsmount *mnt = nd->mnt;
-	struct dentry *dentry = __d_lookup(nd->dentry, name);
+	struct dentry *dentry = d_lookup(nd->dentry, name);
 
 	if (!dentry)
-		goto dcache_miss;
+		goto need_lookup;
 	if (dentry->d_op && dentry->d_op->d_revalidate)
 		goto need_revalidate;
 done:
@@ -530,36 +530,21 @@
 	path->dentry = dentry;
 	return 0;
 
-dcache_miss:
-	unlock_nd(nd);
-
 need_lookup:
 	dentry = real_lookup(nd->dentry, name, LOOKUP_CONTINUE);
 	if (IS_ERR(dentry))
 		goto fail;
-	mntget(mnt);
-relock:
-	dput(cached_path->dentry);
-	mntput(cached_path->mnt);
-	cached_path->mnt = mnt;
-	cached_path->dentry = dentry;
-	lock_nd(nd);
 	goto done;
 
 need_revalidate:
-	mntget(mnt);
-	dget_locked(dentry);
-	unlock_nd(nd);
 	if (dentry->d_op->d_revalidate(dentry, flags))
-		goto relock;
+		goto done;
 	if (d_invalidate(dentry))
-		goto relock;
+		goto done;
 	dput(dentry);
-	mntput(mnt);
 	goto need_lookup;
 
 fail:
-	lock_nd(nd);
 	return PTR_ERR(dentry);
 }
 
@@ -573,7 +558,7 @@
  */
 int link_path_walk(const char * name, struct nameidata *nd)
 {
-	struct path next, pinned = {NULL, NULL};
+	struct path next;
 	struct inode *inode;
 	int err;
 	unsigned int lookup_flags = nd->flags;
@@ -594,10 +579,8 @@
 		unsigned int c;
 
 		err = exec_permission_lite(inode);
-		if (err == -EAGAIN) {
-			unlock_nd(nd);
+		if (err == -EAGAIN) { 
 			err = permission(inode, MAY_EXEC);
-			lock_nd(nd);
 		}
  		if (err)
 			break;
@@ -648,7 +631,7 @@
 				break;
 		}
 		/* This does the actual lookups.. */
-		err = do_lookup(nd, &this, &next, &pinned, LOOKUP_CONTINUE);
+		err = do_lookup(nd, &this, &next, LOOKUP_CONTINUE);
 		if (err)
 			break;
 		/* Check mountpoints.. */
@@ -657,21 +640,18 @@
 		err = -ENOENT;
 		inode = next.dentry->d_inode;
 		if (!inode)
-			break;
+			goto out_dput;
 		err = -ENOTDIR; 
 		if (!inode->i_op)
-			break;
+			goto out_dput;
 
 		if (inode->i_op->follow_link) {
 			mntget(next.mnt);
-			dget_locked(next.dentry);
-			unlock_nd(nd);
 			err = do_follow_link(next.dentry, nd);
 			dput(next.dentry);
 			mntput(next.mnt);
 			if (err)
 				goto return_err;
-			lock_nd(nd);
 			err = -ENOENT;
 			inode = nd->dentry->d_inode;
 			if (!inode)
@@ -680,6 +660,7 @@
 			if (!inode->i_op)
 				break;
 		} else {
+			dput(nd->dentry);
 			nd->mnt = next.mnt;
 			nd->dentry = next.dentry;
 		}
@@ -711,7 +692,7 @@
 			if (err < 0)
 				break;
 		}
-		err = do_lookup(nd, &this, &next, &pinned, 0);
+		err = do_lookup(nd, &this, &next, 0);
 		if (err)
 			break;
 		follow_mount(&next.mnt, &next.dentry);
@@ -719,16 +700,14 @@
 		if ((lookup_flags & LOOKUP_FOLLOW)
 		    && inode && inode->i_op && inode->i_op->follow_link) {
 			mntget(next.mnt);
-			dget_locked(next.dentry);
-			unlock_nd(nd);
 			err = do_follow_link(next.dentry, nd);
 			dput(next.dentry);
 			mntput(next.mnt);
 			if (err)
 				goto return_err;
 			inode = nd->dentry->d_inode;
-			lock_nd(nd);
 		} else {
+			dput(nd->dentry);
 			nd->mnt = next.mnt;
 			nd->dentry = next.dentry;
 		}
@@ -751,23 +730,19 @@
 		else if (this.len == 2 && this.name[1] == '.')
 			nd->last_type = LAST_DOTDOT;
 return_base:
-		unlock_nd(nd);
-		dput(pinned.dentry);
-		mntput(pinned.mnt);
 		return 0;
+out_dput:
+		dput(next.dentry);
+		break;
 	}
-	unlock_nd(nd);
 	path_release(nd);
 return_err:
-	dput(pinned.dentry);
-	mntput(pinned.mnt);
 	return err;
 }
 
 int path_walk(const char * name, struct nameidata *nd)
 {
 	current->total_link_count = 0;
-	lock_nd(nd);
 	return link_path_walk(name, nd);
 }
 
@@ -855,28 +830,24 @@
 {
 	nd->last_type = LAST_ROOT; /* if there are only slashes... */
 	nd->flags = flags;
+
+	read_lock(&current->fs->lock);
 	if (*name=='/') {
-		read_lock(&current->fs->lock);
 		if (current->fs->altroot && !(nd->flags & LOOKUP_NOALT)) {
 			nd->mnt = mntget(current->fs->altrootmnt);
 			nd->dentry = dget(current->fs->altroot);
 			read_unlock(&current->fs->lock);
 			if (__emul_lookup_dentry(name,nd))
 				return 0;
-		} else {
-			read_unlock(&current->fs->lock);
 		}
-		spin_lock(&dcache_lock);
-		nd->mnt = current->fs->rootmnt;
-		nd->dentry = current->fs->root;
+		nd->mnt = mntget(current->fs->rootmnt);
+		nd->dentry = dget(current->fs->root);
 	}
 	else{
-		spin_lock(&dcache_lock);
-		nd->mnt = current->fs->pwdmnt;
-		nd->dentry = current->fs->pwd;
+		nd->mnt = mntget(current->fs->pwdmnt);
+		nd->dentry = dget(current->fs->pwd);
 	}
-	nd->old_mnt = NULL;
-	nd->old_dentry = NULL;
+	read_unlock(&current->fs->lock);
 	current->total_link_count = 0;
 	return link_path_walk(name, nd);
 }
@@ -2129,7 +2100,6 @@
 			/* weird __emul_prefix() stuff did it */
 			goto out;
 	}
-	lock_nd(nd);
 	res = link_path_walk(link, nd);
 out:
 	if (current->link_count || res || nd->last_type!=LAST_NORM)
diff -Nru a/fs/namespace.c b/fs/namespace.c
--- a/fs/namespace.c	Mon Feb 17 14:57:27 2003
+++ b/fs/namespace.c	Mon Feb 17 14:57:27 2003
@@ -892,12 +892,10 @@
 	struct dentry *old_root;
 	struct vfsmount *old_rootmnt;
 	write_lock(&fs->lock);
-	spin_lock(&dcache_lock);
 	old_root = fs->root;
 	old_rootmnt = fs->rootmnt;
 	fs->rootmnt = mntget(mnt);
 	fs->root = dget(dentry);
-	spin_unlock(&dcache_lock);
 	write_unlock(&fs->lock);
 	if (old_root) {
 		dput(old_root);
@@ -916,12 +914,10 @@
 	struct vfsmount *old_pwdmnt;
 
 	write_lock(&fs->lock);
-	spin_lock(&dcache_lock);
 	old_pwd = fs->pwd;
 	old_pwdmnt = fs->pwdmnt;
 	fs->pwdmnt = mntget(mnt);
 	fs->pwd = dget(dentry);
-	spin_unlock(&dcache_lock);
 	write_unlock(&fs->lock);
 
 	if (old_pwd) {
diff -Nru a/fs/proc/array.c b/fs/proc/array.c
--- a/fs/proc/array.c	Mon Feb 17 14:57:27 2003
+++ b/fs/proc/array.c	Mon Feb 17 14:57:27 2003
@@ -180,51 +180,74 @@
 	return buffer;
 }
 
+static char * render_sigset_t(const char *header, sigset_t *set, char *buffer)
+{
+	int i, len;
+
+	len = strlen(header);
+	memcpy(buffer, header, len);
+	buffer += len;
+
+	i = _NSIG;
+	do {
+		int x = 0;
+
+		i -= 4;
+		if (sigismember(set, i+1)) x |= 1;
+		if (sigismember(set, i+2)) x |= 2;
+		if (sigismember(set, i+3)) x |= 4;
+		if (sigismember(set, i+4)) x |= 8;
+		*buffer++ = (x < 10 ? '0' : 'a' - 10) + x;
+	} while (i >= 4);
+
+	*buffer++ = '\n';
+	*buffer = 0;
+	return buffer;
+}
+
 static void collect_sigign_sigcatch(struct task_struct *p, sigset_t *ign,
 				    sigset_t *catch)
 {
 	struct k_sigaction *k;
 	int i;
 
-	sigemptyset(ign);
-	sigemptyset(catch);
+	k = p->sighand->action;
+	for (i = 1; i <= _NSIG; ++i, ++k) {
+		if (k->sa.sa_handler == SIG_IGN)
+			sigaddset(ign, i);
+		else if (k->sa.sa_handler != SIG_DFL)
+			sigaddset(catch, i);
+	}
+}
+
+static inline char * task_sig(struct task_struct *p, char *buffer)
+{
+	sigset_t pending, shpending, blocked, ignored, caught;
+
+	sigemptyset(&pending);
+	sigemptyset(&shpending);
+	sigemptyset(&blocked);
+	sigemptyset(&ignored);
+	sigemptyset(&caught);
 
+	/* Gather all the data with the appropriate locks held */
 	read_lock(&tasklist_lock);
 	if (p->sighand) {
 		spin_lock_irq(&p->sighand->siglock);
-		k = p->sighand->action;
-		for (i = 1; i <= _NSIG; ++i, ++k) {
-			if (k->sa.sa_handler == SIG_IGN)
-				sigaddset(ign, i);
-			else if (k->sa.sa_handler != SIG_DFL)
-				sigaddset(catch, i);
-		}
+		pending = p->pending.signal;
+		shpending = p->signal->shared_pending.signal;
+		blocked = p->blocked;
+		collect_sigign_sigcatch(p, &ignored, &caught);
 		spin_unlock_irq(&p->sighand->siglock);
 	}
 	read_unlock(&tasklist_lock);
-}
-
-static inline char * task_sig(struct task_struct *p, char *buffer)
-{
-	sigset_t ign, catch;
-
-	buffer += sprintf(buffer, "SigPnd:\t");
-	buffer = render_sigset_t(&p->pending.signal, buffer);
-	*buffer++ = '\n';
-	buffer += sprintf(buffer, "ShdPnd:\t");
-	buffer = render_sigset_t(&p->signal->shared_pending.signal, buffer);
-	*buffer++ = '\n';
-	buffer += sprintf(buffer, "SigBlk:\t");
-	buffer = render_sigset_t(&p->blocked, buffer);
-	*buffer++ = '\n';
 
-	collect_sigign_sigcatch(p, &ign, &catch);
-	buffer += sprintf(buffer, "SigIgn:\t");
-	buffer = render_sigset_t(&ign, buffer);
-	*buffer++ = '\n';
-	buffer += sprintf(buffer, "SigCgt:\t"); /* Linux 2.0 uses "SigCgt" */
-	buffer = render_sigset_t(&catch, buffer);
-	*buffer++ = '\n';
+	/* render them all */
+	buffer = render_sigset_t("SigPnd:\t", &pending, buffer);
+	buffer = render_sigset_t("ShdPnd:\t", &shpending, buffer);
+	buffer = render_sigset_t("SigBlk:\t", &blocked, buffer);
+	buffer = render_sigset_t("SigIgn:\t", &ignored, buffer);
+	buffer = render_sigset_t("SigCgt:\t", &caught, buffer);
 
 	return buffer;
 }
@@ -293,7 +316,15 @@
 
 	wchan = get_wchan(task);
 
-	collect_sigign_sigcatch(task, &sigign, &sigcatch);
+	sigemptyset(&sigign);
+	sigemptyset(&sigcatch);
+	read_lock(&tasklist_lock);
+	if (task->sighand) {
+		spin_lock_irq(&task->sighand->siglock);
+		collect_sigign_sigcatch(task, &sigign, &sigcatch);
+		spin_unlock_irq(&task->sighand->siglock);
+	}
+	read_unlock(&tasklist_lock);		
 
 	/* scale priority and nice values from timeslices to -20..20 */
 	/* to make it look like a "normal" Unix priority/nice value  */
diff -Nru a/fs/proc/base.c b/fs/proc/base.c
--- a/fs/proc/base.c	Mon Feb 17 14:57:27 2003
+++ b/fs/proc/base.c	Mon Feb 17 14:57:27 2003
@@ -31,6 +31,7 @@
 #include <linux/kallsyms.h>
 #include <linux/mount.h>
 #include <linux/security.h>
+#include <linux/ptrace.h>
 
 /*
  * For hysterical raisins we keep the same inumbers as in the old procfs.
diff -Nru a/fs/proc/proc_misc.c b/fs/proc/proc_misc.c
--- a/fs/proc/proc_misc.c	Mon Feb 17 14:57:27 2003
+++ b/fs/proc/proc_misc.c	Mon Feb 17 14:57:27 2003
@@ -356,7 +356,7 @@
 	}
 	len += sprintf(page + len, "intr %u", sum);
 
-#if !defined(CONFIG_ARCH_S390)
+#if !defined(CONFIG_ARCH_S390) && !defined(CONFIG_PPC64)
 	for (i = 0 ; i < NR_IRQS ; i++)
 		len += sprintf(page + len, " %u", kstat_irqs(i));
 #endif
diff -Nru a/fs/xattr.c b/fs/xattr.c
--- a/fs/xattr.c	Mon Feb 17 14:57:27 2003
+++ b/fs/xattr.c	Mon Feb 17 14:57:27 2003
@@ -160,7 +160,7 @@
 		if (error)
 			goto out;
 		down(&d->d_inode->i_sem);
-		error = d->d_inode->i_op->getxattr(d, kname, kvalue, size);
+		error = d->d_inode->i_op->getxattr(d, kname, kvalue, size, 0);
 		up(&d->d_inode->i_sem);
 	}
 
@@ -233,7 +233,7 @@
 		if (error)
 			goto out;
 		down(&d->d_inode->i_sem);
-		error = d->d_inode->i_op->listxattr(d, klist, size);
+		error = d->d_inode->i_op->listxattr(d, klist, size, 0);
 		up(&d->d_inode->i_sem);
 	}
 
@@ -308,7 +308,7 @@
 		if (error)
 			goto out;
 		down(&d->d_inode->i_sem);
-		error = d->d_inode->i_op->removexattr(d, kname);
+		error = d->d_inode->i_op->removexattr(d, kname, 0);
 		up(&d->d_inode->i_sem);
 	}
 out:
diff -Nru a/fs/xfs/linux/xfs_iops.c b/fs/xfs/linux/xfs_iops.c
--- a/fs/xfs/linux/xfs_iops.c	Mon Feb 17 14:57:27 2003
+++ b/fs/xfs/linux/xfs_iops.c	Mon Feb 17 14:57:27 2003
@@ -640,7 +640,8 @@
 	struct dentry	*dentry,
 	const char	*name,
 	void		*data,
-	size_t		size)
+	size_t		size,
+	int		flags)
 {
 	ssize_t		error;
 	int		xflags = 0;
@@ -697,7 +698,8 @@
 linvfs_listxattr(
 	struct dentry		*dentry,
 	char			*data,
-	size_t			size)
+	size_t			size,
+	int			flags)
 {
 	ssize_t			error;
 	int			result = 0;
@@ -741,7 +743,8 @@
 STATIC int
 linvfs_removexattr(
 	struct dentry	*dentry,
-	const char	*name)
+	const char	*name,
+	int		flags)
 {
 	int		error;
 	int		xflags = 0;
diff -Nru a/include/asm-alpha/io.h b/include/asm-alpha/io.h
--- a/include/asm-alpha/io.h	Mon Feb 17 14:57:28 2003
+++ b/include/asm-alpha/io.h	Mon Feb 17 14:57:28 2003
@@ -462,6 +462,9 @@
 #define eth_io_copy_and_sum(skb,src,len,unused) \
   memcpy_fromio((skb)->data,(src),(len))
 
+#define isa_eth_io_copy_and_sum(skb,src,len,unused) \
+  isa_memcpy_fromio((skb)->data,(src),(len))
+
 static inline int
 check_signature(unsigned long io_addr, const unsigned char *signature,
 		int length)
diff -Nru a/include/asm-alpha/unistd.h b/include/asm-alpha/unistd.h
--- a/include/asm-alpha/unistd.h	Mon Feb 17 14:57:27 2003
+++ b/include/asm-alpha/unistd.h	Mon Feb 17 14:57:27 2003
@@ -348,7 +348,8 @@
 #define __NR_remap_file_pages		410
 #define __NR_set_tid_address		411
 #define __NR_restart_syscall		412
-#define NR_SYSCALLS			413
+#define __NR_fadvise64			413
+#define NR_SYSCALLS			414
 
 #if defined(__GNUC__)
 
diff -Nru a/include/asm-arm/arch-iop310/serial.h b/include/asm-arm/arch-iop310/serial.h
--- a/include/asm-arm/arch-iop310/serial.h	Mon Feb 17 14:57:28 2003
+++ b/include/asm-arm/arch-iop310/serial.h	Mon Feb 17 14:57:28 2003
@@ -24,8 +24,8 @@
 
 #define STD_SERIAL_PORT_DEFNS			\
        /* UART CLK      PORT        IRQ        FLAGS        */			\
-	{ 0, BASE_BAUD, 0xfe810000, IRQ_UART2, STD_COM_FLAGS },  /* ttyS0 */	\
-	{ 0, BASE_BAUD, 0xfe800000, IRQ_UART1, STD_COM_FLAGS }  /* ttyS1 */
+	{ 0, BASE_BAUD, IQ80310_UART2, IRQ_UART2, STD_COM_FLAGS },  /* ttyS0 */	\
+	{ 0, BASE_BAUD, IQ80310_UART1, IRQ_UART1, STD_COM_FLAGS }  /* ttyS1 */
 
 #endif // CONFIG_ARCH_IQ80310
 
diff -Nru a/include/asm-arm/arch-pxa/time.h b/include/asm-arm/arch-pxa/time.h
--- a/include/asm-arm/arch-pxa/time.h	Mon Feb 17 14:57:27 2003
+++ b/include/asm-arm/arch-pxa/time.h	Mon Feb 17 14:57:27 2003
@@ -53,7 +53,7 @@
 	int next_match;
 
 	/* Loop until we get ahead of the free running timer.
-	 * This ensures an exact clock tick count and time acuracy.
+	 * This ensures an exact clock tick count and time accuracy.
 	 * IRQs are disabled inside the loop to ensure coherence between
 	 * lost_ticks (updated in do_timer()) and the match reg value, so we
 	 * can use do_gettimeofday() from interrupt handlers.
diff -Nru a/include/asm-arm/arch-sa1100/time.h b/include/asm-arm/arch-sa1100/time.h
--- a/include/asm-arm/arch-sa1100/time.h	Mon Feb 17 14:57:28 2003
+++ b/include/asm-arm/arch-sa1100/time.h	Mon Feb 17 14:57:28 2003
@@ -67,7 +67,7 @@
  * We will be entered with IRQs enabled.
  *
  * Loop until we get ahead of the free running timer.
- * This ensures an exact clock tick count and time acuracy.
+ * This ensures an exact clock tick count and time accuracy.
  * IRQs are disabled inside the loop to ensure coherence between
  * lost_ticks (updated in do_timer()) and the match reg value, so we
  * can use do_gettimeofday() from interrupt handlers.
diff -Nru a/include/asm-arm/mach/irq.h b/include/asm-arm/mach/irq.h
--- a/include/asm-arm/mach/irq.h	Mon Feb 17 14:57:27 2003
+++ b/include/asm-arm/mach/irq.h	Mon Feb 17 14:57:27 2003
@@ -33,9 +33,12 @@
 	 */
 	void (*unmask)(unsigned int);
 	/*
-	 * Re-run the IRQ
+	 * Ask the hardware to re-trigger the IRQ.
+	 * Note: This method _must_ _not_ call the interrupt handler.
+	 * If you are unable to retrigger the interrupt, do not
+	 * provide a function, or if you do, return non-zero.
 	 */
-	void (*rerun)(unsigned int);
+	int (*retrigger)(unsigned int);
 	/*
 	 * Set the type of the IRQ.
 	 */
@@ -50,6 +53,7 @@
 	irq_handler_t	handle;
 	struct irqchip	*chip;
 	struct irqaction *action;
+	struct list_head pend;
 	unsigned int	disable_depth;
 
 	unsigned int	triggered: 1;		/* IRQ has occurred	      */
diff -Nru a/include/asm-arm/proc-armv/processor.h b/include/asm-arm/proc-armv/processor.h
--- a/include/asm-arm/proc-armv/processor.h	Mon Feb 17 14:57:28 2003
+++ b/include/asm-arm/proc-armv/processor.h	Mon Feb 17 14:57:28 2003
@@ -23,7 +23,7 @@
 #define KERNEL_STACK_SIZE	PAGE_SIZE
 
 #define INIT_EXTRA_THREAD_INFO						\
-	.cpu_domain	= domain_val(DOMAIN_USER, DOMAIN_CLIENT) |	\
+	.cpu_domain	= domain_val(DOMAIN_USER, DOMAIN_MANAGER) |	\
 			  domain_val(DOMAIN_KERNEL, DOMAIN_MANAGER) |	\
 			  domain_val(DOMAIN_IO, DOMAIN_CLIENT)
 
diff -Nru a/include/asm-arm/proc-armv/system.h b/include/asm-arm/proc-armv/system.h
--- a/include/asm-arm/proc-armv/system.h	Mon Feb 17 14:57:26 2003
+++ b/include/asm-arm/proc-armv/system.h	Mon Feb 17 14:57:26 2003
@@ -14,9 +14,14 @@
 
 #define set_cr(x)					\
 	__asm__ __volatile__(				\
-	"mcr	p15, 0, %0, c1, c0	@ set CR"	\
+	"mcr	p15, 0, %0, c1, c0, 0	@ set CR"	\
 	: : "r" (x))
 
+#define get_cr(x)					\
+	__asm__ __volatile__(				\
+	"mrc	p15, 0, %0, c1, c0, 0	@ get CR"	\
+	: "=r" (x))
+
 #define CR_M	(1 << 0)	/* MMU enable				*/
 #define CR_A	(1 << 1)	/* Alignment abort enable		*/
 #define CR_C	(1 << 2)	/* Dcache enable			*/
@@ -24,9 +29,9 @@
 #define CR_P	(1 << 4)	/* 32-bit exception handler		*/
 #define CR_D	(1 << 5)	/* 32-bit data address range		*/
 #define CR_L	(1 << 6)	/* Implementation defined		*/
-#define CD_B	(1 << 7)	/* Big endian				*/
+#define CR_B	(1 << 7)	/* Big endian				*/
 #define CR_S	(1 << 8)	/* System MMU protection		*/
-#define CD_R	(1 << 9)	/* ROM MMU protection			*/
+#define CR_R	(1 << 9)	/* ROM MMU protection			*/
 #define CR_F	(1 << 10)	/* Implementation defined		*/
 #define CR_Z	(1 << 11)	/* Implementation defined		*/
 #define CR_I	(1 << 12)	/* Icache enable			*/
diff -Nru a/include/asm-arm/signal.h b/include/asm-arm/signal.h
--- a/include/asm-arm/signal.h	Mon Feb 17 14:57:27 2003
+++ b/include/asm-arm/signal.h	Mon Feb 17 14:57:27 2003
@@ -184,9 +184,7 @@
 
 #ifdef __KERNEL__
 #include <asm/sigcontext.h>
-
-#define HAVE_ARCH_GET_SIGNAL_TO_DELIVER
-
+#define ptrace_signal_deliver(regs, cookie) do { } while (0)
 #endif
 
 #endif
diff -Nru a/include/asm-i386/module.h b/include/asm-i386/module.h
--- a/include/asm-i386/module.h	Mon Feb 17 14:57:26 2003
+++ b/include/asm-i386/module.h	Mon Feb 17 14:57:26 2003
@@ -12,39 +12,39 @@
 
 #ifdef CONFIG_M386
 #define MODULE_PROC_FAMILY "386 "
-#elif CONFIG_M486
+#elif defined CONFIG_M486
 #define MODULE_PROC_FAMILY "486 "
-#elif CONFIG_M586
+#elif defined CONFIG_M586
 #define MODULE_PROC_FAMILY "586 "
-#elif CONFIG_M586TSC
+#elif defined CONFIG_M586TSC
 #define MODULE_PROC_FAMILY "586TSC "
-#elif CONFIG_M586MMX
+#elif defined CONFIG_M586MMX
 #define MODULE_PROC_FAMILY "586MMX "
-#elif CONFIG_M686
+#elif defined CONFIG_M686
 #define MODULE_PROC_FAMILY "686 "
-#elif CONFIG_MPENTIUMII
+#elif defined CONFIG_MPENTIUMII
 #define MODULE_PROC_FAMILY "PENTIUMII "
-#elif CONFIG_MPENTIUMIII
+#elif defined CONFIG_MPENTIUMIII
 #define MODULE_PROC_FAMILY "PENTIUMIII "
-#elif CONFIG_MPENTIUM4
+#elif defined CONFIG_MPENTIUM4
 #define MODULE_PROC_FAMILY "PENTIUM4 "
-#elif CONFIG_MK6
+#elif defined CONFIG_MK6
 #define MODULE_PROC_FAMILY "K6 "
-#elif CONFIG_MK7
+#elif defined CONFIG_MK7
 #define MODULE_PROC_FAMILY "K7 "
-#elif CONFIG_MK8
+#elif defined CONFIG_MK8
 #define MODULE_PROC_FAMILY "K8 "
-#elif CONFIG_MELAN
+#elif defined CONFIG_MELAN
 #define MODULE_PROC_FAMILY "ELAN "
-#elif CONFIG_MCRUSOE
+#elif defined CONFIG_MCRUSOE
 #define MODULE_PROC_FAMILY "CRUSOE "
-#elif CONFIG_MWINCHIPC6
+#elif defined CONFIG_MWINCHIPC6
 #define MODULE_PROC_FAMILY "WINCHIPC6 "
-#elif CONFIG_MWINCHIP2
+#elif defined CONFIG_MWINCHIP2
 #define MODULE_PROC_FAMILY "WINCHIP2 "
-#elif CONFIG_MWINCHIP3D
+#elif defined CONFIG_MWINCHIP3D
 #define MODULE_PROC_FAMILY "WINCHIP3D "
-#elif CONFIG_MCYRIXIII
+#elif defined CONFIG_MCYRIXIII
 #define MODULE_PROC_FAMILY "CYRIXIII "
 #elif CONFIG_MVIAC3_2
 #define MODULE_PROC_FAMILY "VIAC3-2 "
diff -Nru a/include/asm-i386/page.h b/include/asm-i386/page.h
--- a/include/asm-i386/page.h	Mon Feb 17 14:57:27 2003
+++ b/include/asm-i386/page.h	Mon Feb 17 14:57:27 2003
@@ -39,7 +39,7 @@
 /*
  * These are used to make use of C type-checking..
  */
-#if CONFIG_X86_PAE
+#ifdef CONFIG_X86_PAE
 typedef struct { unsigned long pte_low, pte_high; } pte_t;
 typedef struct { unsigned long long pmd; } pmd_t;
 typedef struct { unsigned long long pgd; } pgd_t;
diff -Nru a/include/asm-i386/pgtable.h b/include/asm-i386/pgtable.h
--- a/include/asm-i386/pgtable.h	Mon Feb 17 14:57:28 2003
+++ b/include/asm-i386/pgtable.h	Mon Feb 17 14:57:28 2003
@@ -39,7 +39,7 @@
  * newer 3-level PAE-mode page tables.
  */
 #ifndef __ASSEMBLY__
-#if CONFIG_X86_PAE
+#ifdef CONFIG_X86_PAE
 # include <asm/pgtable-3level.h>
 #else
 # include <asm/pgtable-2level.h>
@@ -79,7 +79,7 @@
 #define VMALLOC_START	(((unsigned long) high_memory + 2*VMALLOC_OFFSET-1) & \
 						~(VMALLOC_OFFSET-1))
 #define VMALLOC_VMADDR(x) ((unsigned long)(x))
-#if CONFIG_HIGHMEM
+#ifdef CONFIG_HIGHMEM
 # define VMALLOC_END	(PKMAP_BASE-2*PAGE_SIZE)
 #else
 # define VMALLOC_END	(FIXADDR_START-2*PAGE_SIZE)
diff -Nru a/include/asm-i386/processor.h b/include/asm-i386/processor.h
--- a/include/asm-i386/processor.h	Mon Feb 17 14:57:26 2003
+++ b/include/asm-i386/processor.h	Mon Feb 17 14:57:26 2003
@@ -483,7 +483,7 @@
 	__asm__ __volatile__ ("prefetchnta (%0)" : : "r"(x));
 }
 
-#elif CONFIG_X86_USE_3DNOW
+#elif defined CONFIG_X86_USE_3DNOW
 
 #define ARCH_HAS_PREFETCH
 #define ARCH_HAS_PREFETCHW
diff -Nru a/include/asm-i386/semaphore.h b/include/asm-i386/semaphore.h
--- a/include/asm-i386/semaphore.h	Mon Feb 17 14:57:27 2003
+++ b/include/asm-i386/semaphore.h	Mon Feb 17 14:57:27 2003
@@ -45,12 +45,12 @@
 	atomic_t count;
 	int sleepers;
 	wait_queue_head_t wait;
-#if WAITQUEUE_DEBUG
+#ifdef WAITQUEUE_DEBUG
 	long __magic;
 #endif
 };
 
-#if WAITQUEUE_DEBUG
+#ifdef WAITQUEUE_DEBUG
 # define __SEM_DEBUG_INIT(name) \
 		, (int)&(name).__magic
 #else
@@ -81,7 +81,7 @@
 	atomic_set(&sem->count, val);
 	sem->sleepers = 0;
 	init_waitqueue_head(&sem->wait);
-#if WAITQUEUE_DEBUG
+#ifdef WAITQUEUE_DEBUG
 	sem->__magic = (int)&sem->__magic;
 #endif
 }
@@ -113,7 +113,7 @@
  */
 static inline void down(struct semaphore * sem)
 {
-#if WAITQUEUE_DEBUG
+#ifdef WAITQUEUE_DEBUG
 	CHECK_MAGIC(sem->__magic);
 #endif
 	might_sleep();
@@ -139,7 +139,7 @@
 {
 	int result;
 
-#if WAITQUEUE_DEBUG
+#ifdef WAITQUEUE_DEBUG
 	CHECK_MAGIC(sem->__magic);
 #endif
 	might_sleep();
@@ -167,7 +167,7 @@
 {
 	int result;
 
-#if WAITQUEUE_DEBUG
+#ifdef WAITQUEUE_DEBUG
 	CHECK_MAGIC(sem->__magic);
 #endif
 
@@ -195,7 +195,7 @@
  */
 static inline void up(struct semaphore * sem)
 {
-#if WAITQUEUE_DEBUG
+#ifdef WAITQUEUE_DEBUG
 	CHECK_MAGIC(sem->__magic);
 #endif
 	__asm__ __volatile__(
diff -Nru a/include/asm-ia64/sn/ioerror.h b/include/asm-ia64/sn/ioerror.h
--- a/include/asm-ia64/sn/ioerror.h	Mon Feb 17 14:57:28 2003
+++ b/include/asm-ia64/sn/ioerror.h	Mon Feb 17 14:57:28 2003
@@ -108,7 +108,7 @@
  *        we have a single structure, and the appropriate fields get filled in
  *        at each layer.
  *      - This provides a way to dump all error related information in any layer
- *        of erorr handling (debugging aid).
+ *        of error handling (debugging aid).
  *
  * A second possibility is to allow each layer to define its own error
  * data structure, and fill in the proper fields. This has the advantage
diff -Nru a/include/asm-ia64/sn/router.h b/include/asm-ia64/sn/router.h
--- a/include/asm-ia64/sn/router.h	Mon Feb 17 14:57:27 2003
+++ b/include/asm-ia64/sn/router.h	Mon Feb 17 14:57:27 2003
@@ -500,7 +500,7 @@
 
 	/*
 	 * Everything below here is for kernel use only and may change at	
-	 * at any time with or without a change in teh revision number
+	 * at any time with or without a change in the revision number
 	 *
 	 * Any pointers or things that come and go with DEBUG must go at
  	 * the bottom of the structure, below the user stuff.
diff -Nru a/include/asm-m68knommu/mcfne.h b/include/asm-m68knommu/mcfne.h
--- a/include/asm-m68knommu/mcfne.h	Mon Feb 17 14:57:28 2003
+++ b/include/asm-m68knommu/mcfne.h	Mon Feb 17 14:57:28 2003
@@ -261,7 +261,7 @@
 
 /*
  *	Lastly the interrupt set up code...
- *	Minor diferences between the different board types.
+ *	Minor differences between the different board types.
  */
 
 #if defined(CONFIG_M5206) && defined(CONFIG_ARNEWSH)
diff -Nru a/include/asm-mips64/sn/launch.h b/include/asm-mips64/sn/launch.h
--- a/include/asm-mips64/sn/launch.h	Mon Feb 17 14:57:28 2003
+++ b/include/asm-mips64/sn/launch.h	Mon Feb 17 14:57:28 2003
@@ -52,7 +52,7 @@
 /*
  * The launch routine is called only if the complement address is correct.
  *
- * Before control is transferred to a routine, the compliment address
+ * Before control is transferred to a routine, the complement address
  * is zeroed (invalidated) to prevent an accidental call from a spurious
  * interrupt.
  *
diff -Nru a/include/asm-mips64/sn/nmi.h b/include/asm-mips64/sn/nmi.h
--- a/include/asm-mips64/sn/nmi.h	Mon Feb 17 14:57:27 2003
+++ b/include/asm-mips64/sn/nmi.h	Mon Feb 17 14:57:27 2003
@@ -42,7 +42,7 @@
  * The NMI routine is called only if the complement address is
  * correct.
  *
- * Before control is transferred to a routine, the compliment address
+ * Before control is transferred to a routine, the complement address
  * is zeroed (invalidated) to prevent an accidental call from a spurious
  * interrupt.
  *
diff -Nru a/include/asm-ppc/gt64260.h b/include/asm-ppc/gt64260.h
--- a/include/asm-ppc/gt64260.h	Mon Feb 17 14:57:27 2003
+++ b/include/asm-ppc/gt64260.h	Mon Feb 17 14:57:27 2003
@@ -6,7 +6,7 @@
  * Author: Mark A. Greer <mgreer@mvista.com>
  *
  * 2001 (c) MontaVista, Software, Inc.  This file is licensed under
- * the terms of the GNU General Public License version 2.1.  This program
+ * the terms of the GNU General Public License version 2.  This program
  * is licensed "as is" without any warranty of any kind, whether express
  * or implied.
  */
diff -Nru a/include/asm-ppc/gt64260_defs.h b/include/asm-ppc/gt64260_defs.h
--- a/include/asm-ppc/gt64260_defs.h	Mon Feb 17 14:57:28 2003
+++ b/include/asm-ppc/gt64260_defs.h	Mon Feb 17 14:57:28 2003
@@ -6,7 +6,7 @@
  * Author: Mark A. Greer <mgreer@mvista.com>
  *
  * 2001 (c) MontaVista, Software, Inc.  This file is licensed under
- * the terms of the GNU General Public License version 2.1.  This program
+ * the terms of the GNU General Public License version 2.  This program
  * is licensed "as is" without any warranty of any kind, whether express
  * or implied.
  */
diff -Nru a/include/asm-ppc/harrier.h b/include/asm-ppc/harrier.h
--- a/include/asm-ppc/harrier.h	Mon Feb 17 14:57:26 2003
+++ b/include/asm-ppc/harrier.h	Mon Feb 17 14:57:26 2003
@@ -7,7 +7,7 @@
  *         dale.farnsworth@mvista.com
  *
  * 2001 (c) MontaVista, Software, Inc.  This file is licensed under
- * the terms of the GNU General Public License version 2.1.  This program
+ * the terms of the GNU General Public License version 2.  This program
  * is licensed "as is" without any warranty of any kind, whether express
  * or implied.
  */
diff -Nru a/include/asm-ppc/ibm403.h b/include/asm-ppc/ibm403.h
--- a/include/asm-ppc/ibm403.h	Mon Feb 17 14:57:26 2003
+++ b/include/asm-ppc/ibm403.h	Mon Feb 17 14:57:26 2003
@@ -2,7 +2,7 @@
  * Authors: Armin Kuster <akuster@mvista.com> and Tom Rini <trini@mvista.com>
  *
  * 2001 (c) MontaVista, Software, Inc.  This file is licensed under
- * the terms of the GNU General Public License version 2.1.  This program
+ * the terms of the GNU General Public License version 2.  This program
  * is licensed "as is" without any warranty of any kind, whether express
  * or implied.
  */
diff -Nru a/include/asm-ppc/ibm405.h b/include/asm-ppc/ibm405.h
--- a/include/asm-ppc/ibm405.h	Mon Feb 17 14:57:26 2003
+++ b/include/asm-ppc/ibm405.h	Mon Feb 17 14:57:26 2003
@@ -2,7 +2,7 @@
  * Author: Armin Kuster <akuster@mvista.com>
  *
  * 2002 (c) MontaVista, Software, Inc.  This file is licensed under
- * the terms of the GNU General Public License version 2.1.  This program
+ * the terms of the GNU General Public License version 2.  This program
  * is licensed "as is" without any warranty of any kind, whether express
  * or implied.
  */
diff -Nru a/include/asm-ppc/ibm_ocp_pci.h b/include/asm-ppc/ibm_ocp_pci.h
--- a/include/asm-ppc/ibm_ocp_pci.h	Mon Feb 17 14:57:28 2003
+++ b/include/asm-ppc/ibm_ocp_pci.h	Mon Feb 17 14:57:28 2003
@@ -2,7 +2,7 @@
  * Author: Armin Kuster <akuster@mvista.com>
  *
  * 2001-2002 (c) MontaVista, Software, Inc.  This file is licensed under
- * the terms of the GNU General Public License version 2.1.  This program
+ * the terms of the GNU General Public License version 2.  This program
  * is licensed "as is" without any warranty of any kind, whether express
  * or implied.
  */
diff -Nru a/include/asm-ppc/mpc10x.h b/include/asm-ppc/mpc10x.h
--- a/include/asm-ppc/mpc10x.h	Mon Feb 17 14:57:27 2003
+++ b/include/asm-ppc/mpc10x.h	Mon Feb 17 14:57:27 2003
@@ -8,7 +8,7 @@
  *         mgreer@mvista.com
  *
  * 2001 (c) MontaVista, Software, Inc.  This file is licensed under
- * the terms of the GNU General Public License version 2.1.  This program
+ * the terms of the GNU General Public License version 2.  This program
  * is licensed "as is" without any warranty of any kind, whether express
  * or implied.
  */
diff -Nru a/include/asm-ppc/ppc405_dma.h b/include/asm-ppc/ppc405_dma.h
--- a/include/asm-ppc/ppc405_dma.h	Mon Feb 17 14:57:27 2003
+++ b/include/asm-ppc/ppc405_dma.h	Mon Feb 17 14:57:27 2003
@@ -2,7 +2,7 @@
  * Author: Pete Popov <ppopov@mvista.com>
  *
  * 2000 (c) MontaVista, Software, Inc.  This file is licensed under
- * the terms of the GNU General Public License version 2.1.  This program
+ * the terms of the GNU General Public License version 2.  This program
  * is licensed "as is" without any warranty of any kind, whether express
  * or implied.
  *
diff -Nru a/include/asm-ppc/pplus.h b/include/asm-ppc/pplus.h
--- a/include/asm-ppc/pplus.h	Mon Feb 17 14:57:27 2003
+++ b/include/asm-ppc/pplus.h	Mon Feb 17 14:57:27 2003
@@ -7,7 +7,7 @@
  *         mgreer@mvista.com
  *
  * 2001 (c) MontaVista, Software, Inc.  This file is licensed under
- * the terms of the GNU General Public License version 2.1.  This program
+ * the terms of the GNU General Public License version 2.  This program
  * is licensed "as is" without any warranty of any kind, whether express
  * or implied.
  */
diff -Nru a/include/asm-ppc/rtc.h b/include/asm-ppc/rtc.h
--- a/include/asm-ppc/rtc.h	Mon Feb 17 14:57:26 2003
+++ b/include/asm-ppc/rtc.h	Mon Feb 17 14:57:26 2003
@@ -4,7 +4,7 @@
  * Author: Tom Rini <trini@mvista.com>
  *
  * 2002 (c) MontaVista, Software, Inc.  This file is licensed under
- * the terms of the GNU General Public License version 2.1.  This program
+ * the terms of the GNU General Public License version 2.  This program
  * is licensed "as is" without any warranty of any kind, whether express
  * or implied.
  *
diff -Nru a/include/asm-ppc/todc.h b/include/asm-ppc/todc.h
--- a/include/asm-ppc/todc.h	Mon Feb 17 14:57:28 2003
+++ b/include/asm-ppc/todc.h	Mon Feb 17 14:57:28 2003
@@ -8,7 +8,7 @@
  *         mgreer@mvista.com
  *
  * 2001 (c) MontaVista, Software, Inc.  This file is licensed under
- * the terms of the GNU General Public License version 2.1.  This program
+ * the terms of the GNU General Public License version 2.  This program
  * is licensed "as is" without any warranty of any kind, whether express
  * or implied.
  */
diff -Nru a/include/asm-ppc/unistd.h b/include/asm-ppc/unistd.h
--- a/include/asm-ppc/unistd.h	Mon Feb 17 14:57:27 2003
+++ b/include/asm-ppc/unistd.h	Mon Feb 17 14:57:27 2003
@@ -236,6 +236,8 @@
 #define __NR_io_getevents	229
 #define __NR_io_submit		230
 #define __NR_io_cancel		231
+#define __NR_set_tid_address	232
+#define __NR_fadvise64		233
 #define __NR_exit_group		234
 #define __NR_lookup_dcookie	235
 #define __NR_epoll_create	236
diff -Nru a/include/asm-ppc64/rtas.h b/include/asm-ppc64/rtas.h
--- a/include/asm-ppc64/rtas.h	Mon Feb 17 14:57:28 2003
+++ b/include/asm-ppc64/rtas.h	Mon Feb 17 14:57:28 2003
@@ -168,5 +168,13 @@
 
 extern struct proc_dir_entry *rtas_proc_dir;
 
+/* Some RTAS ops require a data buffer and that buffer must be < 4G.
+ * Rather than having a memory allocator, just use this buffer
+ * (get the lock first), make the RTAS call.  Copy the data instead
+ * of holding the buffer for long.
+ */
+#define RTAS_DATA_BUF_SIZE 1024
+extern spinlock_t rtas_data_buf_lock;
+extern char rtas_data_buf[RTAS_DATA_BUF_SIZE];
 
 #endif /* _PPC64_RTAS_H */
diff -Nru a/include/asm-ppc64/unistd.h b/include/asm-ppc64/unistd.h
--- a/include/asm-ppc64/unistd.h	Mon Feb 17 14:57:26 2003
+++ b/include/asm-ppc64/unistd.h	Mon Feb 17 14:57:26 2003
@@ -242,7 +242,8 @@
 #define __NR_io_getevents	229
 #define __NR_io_submit		230
 #define __NR_io_cancel		231
-/* 223 + 224 currently unused */
+#define __NR_set_tid_address	232
+#define __NR_fadvise64		233
 #define __NR_exit_group		234
 #define __NR_lookup_dcookie	235
 #define __NR_sys_epoll_create	236
diff -Nru a/include/asm-sparc64/ptrace.h b/include/asm-sparc64/ptrace.h
--- a/include/asm-sparc64/ptrace.h	Mon Feb 17 14:57:27 2003
+++ b/include/asm-sparc64/ptrace.h	Mon Feb 17 14:57:27 2003
@@ -268,7 +268,7 @@
 #define PTRACE_SETFPAREGS         21
 
 /* There are for debugging 64-bit processes, either from a 32 or 64 bit
- * parent.  Thus their compliments are for debugging 32-bit processes only.
+ * parent.  Thus their complements are for debugging 32-bit processes only.
  */
 
 #define PTRACE_GETREGS64	  22
diff -Nru a/include/linux/com20020.h b/include/linux/com20020.h
--- a/include/linux/com20020.h	Mon Feb 17 14:57:26 2003
+++ b/include/linux/com20020.h	Mon Feb 17 14:57:26 2003
@@ -32,7 +32,7 @@
 void com20020_remove(struct net_device *dev);
 
 /* The number of low I/O ports used by the card. */
-#define ARCNET_TOTAL_SIZE 9
+#define ARCNET_TOTAL_SIZE 8
 
 /* various register addresses */
 #define _INTMASK  (ioaddr+0)	/* writable */
@@ -59,6 +59,8 @@
 
 /* in SETUP register */
 #define PROMISCset	0x10	/* enable RCV_ALL */
+#define P1MODE		0x80    /* enable P1-MODE for Backplane */
+#define SLOWARB		0x01    /* enable Slow Arbitration for >=5Mbps */
 
 /* COM2002x */
 #define SUB_TENTATIVE	0	/* tentative node ID */
diff -Nru a/include/linux/cpufreq.h b/include/linux/cpufreq.h
--- a/include/linux/cpufreq.h	Mon Feb 17 14:57:27 2003
+++ b/include/linux/cpufreq.h	Mon Feb 17 14:57:27 2003
@@ -205,6 +205,8 @@
 int cpufreq_restore(void);
 #endif
 
+/* the proc_intf.c needs this */
+int cpufreq_parse_governor (char *str_governor, unsigned int *policy, struct cpufreq_governor **governor);
 
 #ifdef CONFIG_CPU_FREQ_24_API
 /*********************************************************************
@@ -297,6 +299,7 @@
 
 #endif /* CONFIG_CPU_FREQ_24_API */
 
+
 /*********************************************************************
  *                     FREQUENCY TABLE HELPERS                       *
  *********************************************************************/
@@ -310,6 +313,7 @@
 				    * order */
 };
 
+#if defined(CONFIG_CPU_FREQ_TABLE) || defined(CONFIG_CPU_FREQ_TABLE_MODULE)
 int cpufreq_frequency_table_cpuinfo(struct cpufreq_policy *policy,
 				    struct cpufreq_frequency_table *table);
 
@@ -325,5 +329,7 @@
 				   unsigned int target_freq,
 				   unsigned int relation,
 				   unsigned int *index);
+
+#endif /* CONFIG_CPU_FREQ_TABLE */
 
 #endif /* _LINUX_CPUFREQ_H */
diff -Nru a/include/linux/dcache.h b/include/linux/dcache.h
--- a/include/linux/dcache.h	Mon Feb 17 14:57:28 2003
+++ b/include/linux/dcache.h	Mon Feb 17 14:57:28 2003
@@ -7,6 +7,7 @@
 #include <linux/list.h>
 #include <linux/spinlock.h>
 #include <linux/cache.h>
+#include <linux/rcupdate.h>
 #include <asm/bug.h>
 
 struct vfsmount;
@@ -30,6 +31,7 @@
 	const unsigned char * name;
 	unsigned int len;
 	unsigned int hash;
+	char name_str[0];
 };
 
 struct dentry_stat_t {
@@ -72,21 +74,26 @@
  
 struct dentry {
 	atomic_t d_count;
+	unsigned long d_vfs_flags;	/* moved here to be on same cacheline */
+	spinlock_t d_lock;		/* per dentry lock */
 	unsigned int d_flags;
+	unsigned long d_move_count;	/* to indicated moved dentry while lockless lookup */
 	struct inode  * d_inode;	/* Where the name belongs to - NULL is negative */
 	struct dentry * d_parent;	/* parent directory */
+	struct list_head * d_bucket;	/* lookup hash bucket */
 	struct list_head d_hash;	/* lookup hash list */
-	struct list_head d_lru;		/* d_count = 0 LRU list */
+	struct list_head d_lru;		/* LRU list */
 	struct list_head d_child;	/* child of parent list */
 	struct list_head d_subdirs;	/* our children */
 	struct list_head d_alias;	/* inode alias list */
 	int d_mounted;
 	struct qstr d_name;
+	struct qstr * d_qstr;		/* quick str ptr used in lockless lookup and concurrent d_move */
 	unsigned long d_time;		/* used by d_revalidate */
 	struct dentry_operations  *d_op;
 	struct super_block * d_sb;	/* The root of the dentry tree */
-	unsigned long d_vfs_flags;
 	void * d_fsdata;		/* fs-specific data */
+ 	struct rcu_head d_rcu;
 	struct dcookie_struct * d_cookie; /* cookie, if any */
 	unsigned char d_iname[DNAME_INLINE_LEN_MIN]; /* small names */
 } ____cacheline_aligned;
@@ -139,6 +146,7 @@
       */
 
 #define DCACHE_REFERENCED	0x0008  /* Recently used, don't discard. */
+#define DCACHE_UNHASHED		0x0010	
 
 extern spinlock_t dcache_lock;
 extern rwlock_t dparent_lock;
@@ -162,7 +170,8 @@
 
 static __inline__ void __d_drop(struct dentry * dentry)
 {
-	list_del_init(&dentry->d_hash);
+	dentry->d_vfs_flags |= DCACHE_UNHASHED;
+	list_del_rcu(&dentry->d_hash);
 }
 
 static __inline__ void d_drop(struct dentry * dentry)
@@ -229,7 +238,6 @@
 
 /* appendix may either be NULL or be used for transname suffixes */
 extern struct dentry * d_lookup(struct dentry *, struct qstr *);
-extern struct dentry * __d_lookup(struct dentry *, struct qstr *);
 
 /* validate "insecure" dentry pointer */
 extern int d_validate(struct dentry *, struct dentry *);
@@ -254,9 +262,8 @@
 static __inline__ struct dentry * dget(struct dentry *dentry)
 {
 	if (dentry) {
-		if (!atomic_read(&dentry->d_count))
-			BUG();
 		atomic_inc(&dentry->d_count);
+		dentry->d_vfs_flags |= DCACHE_REFERENCED;
 	}
 	return dentry;
 }
@@ -272,7 +279,7 @@
  
 static __inline__ int d_unhashed(struct dentry *dentry)
 {
-	return list_empty(&dentry->d_hash);
+	return (dentry->d_vfs_flags & DCACHE_UNHASHED);
 }
 
 extern void dput(struct dentry *);
diff -Nru a/include/linux/eisa.h b/include/linux/eisa.h
--- a/include/linux/eisa.h	Mon Feb 17 14:57:28 2003
+++ b/include/linux/eisa.h	Mon Feb 17 14:57:28 2003
@@ -24,7 +24,8 @@
 };
 
 /* There is not much we can say about an EISA device, apart from
- * signature, slot number, and base address */
+ * signature, slot number, and base address. */
+
 struct eisa_device {
 	struct eisa_device_id id;
 	int                   slot;
@@ -56,5 +57,19 @@
 {
         edev->dev.driver_data = data;
 }
+
+/* The EISA root device. There's rumours about machines with multiple
+ * busses (PA-RISC ?), so we try to handle that. */
+
+struct eisa_root_device {
+	struct list_head node;
+	struct device   *dev;	 /* Pointer to bridge device */
+	struct resource *res;
+	unsigned long    bus_base_addr;
+	int		 slots;  /* Max slot number */
+	int              bus_nr; /* Set by eisa_root_register */
+};
+
+int eisa_root_register (struct eisa_root_device *root);
 
 #endif
diff -Nru a/include/linux/fs.h b/include/linux/fs.h
--- a/include/linux/fs.h	Mon Feb 17 14:57:27 2003
+++ b/include/linux/fs.h	Mon Feb 17 14:57:27 2003
@@ -743,9 +743,9 @@
 	int (*setattr) (struct dentry *, struct iattr *);
 	int (*getattr) (struct vfsmount *mnt, struct dentry *, struct kstat *);
 	int (*setxattr) (struct dentry *, const char *,const void *,size_t,int);
-	ssize_t (*getxattr) (struct dentry *, const char *, void *, size_t);
-	ssize_t (*listxattr) (struct dentry *, char *, size_t);
-	int (*removexattr) (struct dentry *, const char *);
+	ssize_t (*getxattr) (struct dentry *, const char *, void *, size_t,int);
+	ssize_t (*listxattr) (struct dentry *, char *, size_t, int);
+	int (*removexattr) (struct dentry *, const char *, int);
 };
 
 struct seq_file;
@@ -1195,6 +1195,8 @@
 extern int file_read_actor(read_descriptor_t * desc, struct page *page, unsigned long offset, unsigned long size);
 extern int file_send_actor(read_descriptor_t * desc, struct page *page, unsigned long offset, unsigned long size);
 extern ssize_t generic_file_read(struct file *, char *, size_t, loff_t *);
+int generic_write_checks(struct inode *inode, struct file *file,
+			loff_t *pos, size_t *count, int isblk);
 extern ssize_t generic_file_write(struct file *, const char *, size_t, loff_t *);
 extern ssize_t generic_file_aio_read(struct kiocb *, char *, size_t, loff_t);
 extern ssize_t generic_file_aio_write(struct kiocb *, const char *, size_t, loff_t);
diff -Nru a/include/linux/futex.h b/include/linux/futex.h
--- a/include/linux/futex.h	Mon Feb 17 14:57:27 2003
+++ b/include/linux/futex.h	Mon Feb 17 14:57:27 2003
@@ -6,6 +6,6 @@
 #define FUTEX_WAKE (1)
 #define FUTEX_FD (2)
 
-extern asmlinkage int sys_futex(unsigned long uaddr, int op, int val, struct timespec *utime);
+extern asmlinkage long sys_futex(u32 *uaddr, int op, int val, struct timespec *utime);
 
 #endif
diff -Nru a/include/linux/kmod.h b/include/linux/kmod.h
--- a/include/linux/kmod.h	Mon Feb 17 14:57:27 2003
+++ b/include/linux/kmod.h	Mon Feb 17 14:57:27 2003
@@ -21,6 +21,7 @@
 
 #include <linux/config.h>
 #include <linux/errno.h>
+#include <linux/compiler.h>
 
 #ifdef CONFIG_KMOD
 extern int request_module(const char * name);
@@ -29,8 +30,7 @@
 #endif
 
 #define try_then_request_module(x, mod) ((x) ?: request_module(mod), (x))
-extern int exec_usermodehelper(char *program_path, char *argv[], char *envp[]);
-extern int call_usermodehelper(char *path, char *argv[], char *envp[]);
+extern int call_usermodehelper(char *path, char *argv[], char *envp[], int wait);
 
 #ifdef CONFIG_HOTPLUG
 extern char hotplug_path [];
diff -Nru a/include/linux/mod_devicetable.h b/include/linux/mod_devicetable.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/include/linux/mod_devicetable.h	Mon Feb 17 14:57:28 2003
@@ -0,0 +1,117 @@
+/*
+ * Device tables which are exported to userspace via
+ * scripts/table2alias.c.  You must keep that file in sync with this
+ * header.
+ */
+
+#ifndef LINUX_MOD_DEVICETABLE_H
+#define LINUX_MOD_DEVICETABLE_H
+
+#ifdef __KERNEL__
+#include <linux/types.h>
+typedef unsigned long kernel_ulong_t;
+#endif
+
+#define PCI_ANY_ID (~0)
+
+struct pci_device_id {
+	__u32 vendor, device;		/* Vendor and device ID or PCI_ANY_ID*/
+	__u32 subvendor, subdevice;	/* Subsystem ID's or PCI_ANY_ID */
+	__u32 class, class_mask;	/* (class,subclass,prog-if) triplet */
+	kernel_ulong_t driver_data;	/* Data private to the driver */
+};
+
+/*
+ * Device table entry for "new style" table-driven USB drivers.
+ * User mode code can read these tables to choose which modules to load.
+ * Declare the table as a MODULE_DEVICE_TABLE.
+ *
+ * A probe() parameter will point to a matching entry from this table.
+ * Use the driver_info field for each match to hold information tied
+ * to that match:  device quirks, etc.
+ *
+ * Terminate the driver's table with an all-zeroes entry.
+ * Use the flag values to control which fields are compared.
+ */
+
+/**
+ * struct usb_device_id - identifies USB devices for probing and hotplugging
+ * @match_flags: Bit mask controlling of the other fields are used to match
+ *	against new devices.  Any field except for driver_info may be used,
+ *	although some only make sense in conjunction with other fields.
+ *	This is usually set by a USB_DEVICE_*() macro, which sets all
+ *	other fields in this structure except for driver_info.
+ * @idVendor: USB vendor ID for a device; numbers are assigned
+ *	by the USB forum to its members.
+ * @idProduct: Vendor-assigned product ID.
+ * @bcdDevice_lo: Low end of range of vendor-assigned product version numbers.
+ *	This is also used to identify individual product versions, for
+ *	a range consisting of a single device.
+ * @bcdDevice_hi: High end of version number range.  The range of product
+ *	versions is inclusive.
+ * @bDeviceClass: Class of device; numbers are assigned
+ *	by the USB forum.  Products may choose to implement classes,
+ *	or be vendor-specific.  Device classes specify behavior of all
+ *	the interfaces on a devices.
+ * @bDeviceSubClass: Subclass of device; associated with bDeviceClass.
+ * @bDeviceProtocol: Protocol of device; associated with bDeviceClass.
+ * @bInterfaceClass: Class of interface; numbers are assigned
+ *	by the USB forum.  Products may choose to implement classes,
+ *	or be vendor-specific.  Interface classes specify behavior only
+ *	of a given interface; other interfaces may support other classes.
+ * @bInterfaceSubClass: Subclass of interface; associated with bInterfaceClass.
+ * @bInterfaceProtocol: Protocol of interface; associated with bInterfaceClass.
+ * @driver_info: Holds information used by the driver.  Usually it holds
+ *	a pointer to a descriptor understood by the driver, or perhaps
+ *	device flags.
+ *
+ * In most cases, drivers will create a table of device IDs by using
+ * USB_DEVICE(), or similar macros designed for that purpose.
+ * They will then export it to userspace using MODULE_DEVICE_TABLE(),
+ * and provide it to the USB core through their usb_driver structure.
+ *
+ * See the usb_match_id() function for information about how matches are
+ * performed.  Briefly, you will normally use one of several macros to help
+ * construct these entries.  Each entry you provide will either identify
+ * one or more specific products, or will identify a class of products
+ * which have agreed to behave the same.  You should put the more specific
+ * matches towards the beginning of your table, so that driver_info can
+ * record quirks of specific products.
+ */
+struct usb_device_id {
+	/* which fields to match against? */
+	__u16		match_flags;
+
+	/* Used for product specific matches; range is inclusive */
+	__u16		idVendor;
+	__u16		idProduct;
+	__u16		bcdDevice_lo;
+	__u16		bcdDevice_hi;
+
+	/* Used for device class matches */
+	__u8		bDeviceClass;
+	__u8		bDeviceSubClass;
+	__u8		bDeviceProtocol;
+
+	/* Used for interface class matches */
+	__u8		bInterfaceClass;
+	__u8		bInterfaceSubClass;
+	__u8		bInterfaceProtocol;
+
+	/* not matched against */
+	kernel_ulong_t	driver_info;
+};
+
+/* Some useful macros to use to create struct usb_device_id */
+#define USB_DEVICE_ID_MATCH_VENDOR		0x0001
+#define USB_DEVICE_ID_MATCH_PRODUCT		0x0002
+#define USB_DEVICE_ID_MATCH_DEV_LO		0x0004
+#define USB_DEVICE_ID_MATCH_DEV_HI		0x0008
+#define USB_DEVICE_ID_MATCH_DEV_CLASS		0x0010
+#define USB_DEVICE_ID_MATCH_DEV_SUBCLASS	0x0020
+#define USB_DEVICE_ID_MATCH_DEV_PROTOCOL	0x0040
+#define USB_DEVICE_ID_MATCH_INT_CLASS		0x0080
+#define USB_DEVICE_ID_MATCH_INT_SUBCLASS	0x0100
+#define USB_DEVICE_ID_MATCH_INT_PROTOCOL	0x0200
+
+#endif /* LINUX_MOD_DEVICETABLE_H */
diff -Nru a/include/linux/module.h b/include/linux/module.h
--- a/include/linux/module.h	Mon Feb 17 14:57:28 2003
+++ b/include/linux/module.h	Mon Feb 17 14:57:28 2003
@@ -57,13 +57,14 @@
 	       unsigned long value);
 
 #ifdef MODULE
+#define ___module_cat(a,b) a ## b
+#define __module_cat(a,b) ___module_cat(a,b)
+/* For userspace: you can also call me... */
+#define MODULE_ALIAS(alias)					\
+	static const char __module_cat(__alias_,__LINE__)[]	\
+		__attribute__((section(".modinfo"),unused)) = "alias=" alias
 
-/* For replacement modutils, use an alias not a pointer. */
 #define MODULE_GENERIC_TABLE(gtype,name)			\
-static const unsigned long __module_##gtype##_size		\
-  __attribute__ ((unused)) = sizeof(struct gtype##_id);		\
-static const struct gtype##_id * __module_##gtype##_table	\
-  __attribute__ ((unused)) = name;				\
 extern const struct gtype##_id __mod_##gtype##_table		\
   __attribute__ ((unused, alias(__stringify(name))))
 
@@ -103,6 +104,7 @@
 
 #else  /* !MODULE */
 
+#define MODULE_ALIAS(alias)
 #define MODULE_GENERIC_TABLE(gtype,name)
 #define THIS_MODULE ((struct module *)0)
 #define MOD_INC_USE_COUNT	do { } while (0)
diff -Nru a/include/linux/namei.h b/include/linux/namei.h
--- a/include/linux/namei.h	Mon Feb 17 14:57:27 2003
+++ b/include/linux/namei.h	Mon Feb 17 14:57:27 2003
@@ -11,8 +11,6 @@
 	struct qstr	last;
 	unsigned int	flags;
 	int		last_type;
-	struct dentry	*old_dentry;
-	struct vfsmount	*old_mnt;
 };
 
 /*
diff -Nru a/include/linux/pagemap.h b/include/linux/pagemap.h
--- a/include/linux/pagemap.h	Mon Feb 17 14:57:26 2003
+++ b/include/linux/pagemap.h	Mon Feb 17 14:57:26 2003
@@ -8,6 +8,7 @@
 #include <linux/fs.h>
 #include <linux/list.h>
 #include <linux/highmem.h>
+#include <asm/uaccess.h>
 
 /*
  * The page cache can done in larger chunks than
@@ -122,4 +123,49 @@
 }
 
 extern void end_page_writeback(struct page *page);
+
+/*
+ * Fault a userspace page into pagetables.  Return non-zero on a fault.
+ *
+ * FIXME: this assumes that two userspace pages are always sufficient.  That's
+ * not true if PAGE_CACHE_SIZE > PAGE_SIZE.
+ */
+static inline int fault_in_pages_writeable(char *uaddr, int size)
+{
+	int ret;
+
+	/*
+	 * Writing zeroes into userspace here is OK, because we know that if
+	 * the zero gets there, we'll be overwriting it.
+	 */
+	ret = __put_user(0, uaddr);
+	if (ret == 0) {
+		char *end = uaddr + size - 1;
+
+		/*
+		 * If the page was already mapped, this will get a cache miss
+		 * for sure, so try to avoid doing it.
+		 */
+		if (((unsigned long)uaddr & PAGE_MASK) !=
+				((unsigned long)end & PAGE_MASK))
+		 	ret = __put_user(0, end);
+	}
+	return ret;
+}
+
+static inline void fault_in_pages_readable(const char *uaddr, int size)
+{
+	volatile char c;
+	int ret;
+
+	ret = __get_user(c, (char *)uaddr);
+	if (ret == 0) {
+		const char *end = uaddr + size - 1;
+
+		if (((unsigned long)uaddr & PAGE_MASK) !=
+				((unsigned long)end & PAGE_MASK))
+		 	__get_user(c, (char *)end);
+	}
+}
+
 #endif /* _LINUX_PAGEMAP_H */
diff -Nru a/include/linux/pci.h b/include/linux/pci.h
--- a/include/linux/pci.h	Mon Feb 17 14:57:27 2003
+++ b/include/linux/pci.h	Mon Feb 17 14:57:27 2003
@@ -17,6 +17,8 @@
 #ifndef LINUX_PCI_H
 #define LINUX_PCI_H
 
+#include <linux/mod_devicetable.h>
+
 /*
  * Under PCI, each device has 256 bytes of configuration address space,
  * of which the first 64 bytes are standardized as follows:
@@ -359,8 +361,6 @@
 #define DEVICE_COUNT_DMA	2
 #define DEVICE_COUNT_RESOURCE	12
 
-#define PCI_ANY_ID (~0)
-
 /*
  * The pci_dev structure is used to describe PCI devices.
  */
@@ -489,13 +489,6 @@
 	unsigned long io_start, io_end;
 	unsigned long mem_start, mem_end;
 	unsigned long prefetch_start, prefetch_end;
-};
-
-struct pci_device_id {
-	unsigned int vendor, device;		/* Vendor and device ID or PCI_ANY_ID */
-	unsigned int subvendor, subdevice;	/* Subsystem ID's or PCI_ANY_ID */
-	unsigned int class, class_mask;		/* (class,subclass,prog-if) triplet */
-	unsigned long driver_data;		/* Data private to the driver */
 };
 
 struct pci_driver {
diff -Nru a/include/linux/ptrace.h b/include/linux/ptrace.h
--- a/include/linux/ptrace.h	Mon Feb 17 14:57:26 2003
+++ b/include/linux/ptrace.h	Mon Feb 17 14:57:26 2003
@@ -3,8 +3,6 @@
 /* ptrace.h */
 /* structs and defines to help the user use the ptrace system call. */
 
-#include <linux/compiler.h>
-
 /* has the defines to get at the registers. */
 
 #define PTRACE_TRACEME		   0
@@ -38,6 +36,8 @@
 #define PTRACE_O_TRACEVFORKDONE	0x00000020
 #define PTRACE_O_TRACEEXIT	0x00000040
 
+#define PTRACE_O_MASK		0x0000007f
+
 /* Wait extended result codes for the above trace options.  */
 #define PTRACE_EVENT_FORK	1
 #define PTRACE_EVENT_VFORK	2
@@ -47,7 +47,27 @@
 #define PTRACE_EVENT_EXIT	6
 
 #include <asm/ptrace.h>
-#include <linux/sched.h>
+
+#ifdef __KERNEL__
+/*
+ * Ptrace flags
+ */
+
+#define PT_PTRACED	0x00000001
+#define PT_DTRACE	0x00000002	/* delayed trace (used on m68k, i386) */
+#define PT_TRACESYSGOOD	0x00000004
+#define PT_PTRACE_CAP	0x00000008	/* ptracer can follow suid-exec */
+#define PT_TRACE_FORK	0x00000010
+#define PT_TRACE_VFORK	0x00000020
+#define PT_TRACE_CLONE	0x00000040
+#define PT_TRACE_EXEC	0x00000080
+#define PT_TRACE_VFORK_DONE	0x00000100
+#define PT_TRACE_EXIT	0x00000200
+
+#define PT_TRACE_MASK	0x000003f4
+
+#include <linux/compiler.h>		/* For unlikely.  */
+#include <linux/sched.h>		/* For struct task_struct.  */
 
 extern int ptrace_readdata(struct task_struct *tsk, unsigned long src, char *dst, int len);
 extern int ptrace_writedata(struct task_struct *tsk, char * src, unsigned long dst, int len);
@@ -58,11 +78,11 @@
 extern int ptrace_request(struct task_struct *child, long request, long addr, long data);
 extern void ptrace_notify(int exit_code);
 extern void __ptrace_link(struct task_struct *child,
-				struct task_struct *new_parent);
+			  struct task_struct *new_parent);
 extern void __ptrace_unlink(struct task_struct *child);
 
 static inline void ptrace_link(struct task_struct *child,
-				struct task_struct *new_parent)
+			       struct task_struct *new_parent)
 {
 	if (unlikely(child->ptrace))
 		__ptrace_link(child, new_parent);
@@ -72,5 +92,6 @@
 	if (unlikely(child->ptrace))
 		__ptrace_unlink(child);
 }
+#endif
 
 #endif
diff -Nru a/include/linux/rtc.h b/include/linux/rtc.h
--- a/include/linux/rtc.h	Mon Feb 17 14:57:26 2003
+++ b/include/linux/rtc.h	Mon Feb 17 14:57:26 2003
@@ -57,8 +57,8 @@
 	int pll_value;      /* get/set correction value */
 	int pll_max;        /* max +ve (faster) adjustment value */
 	int pll_min;        /* max -ve (slower) adjustment value */
-	int pll_posmult;    /* factor for +ve corection */
-	int pll_negmult;    /* factor for -ve corection */
+	int pll_posmult;    /* factor for +ve correction */
+	int pll_negmult;    /* factor for -ve correction */
 	long pll_clock;     /* base PLL frequency */
 };
 
diff -Nru a/include/linux/sched.h b/include/linux/sched.h
--- a/include/linux/sched.h	Mon Feb 17 14:57:26 2003
+++ b/include/linux/sched.h	Mon Feb 17 14:57:26 2003
@@ -446,21 +446,6 @@
 #define PF_FSTRANS	0x00020000	/* inside a filesystem transaction */
 #define PF_KSWAPD	0x00040000	/* I am kswapd */
 
-/*
- * Ptrace flags
- */
-
-#define PT_PTRACED	0x00000001
-#define PT_DTRACE	0x00000002	/* delayed trace (used on m68k, i386) */
-#define PT_TRACESYSGOOD	0x00000004
-#define PT_PTRACE_CAP	0x00000008	/* ptracer can follow suid-exec */
-#define PT_TRACE_FORK	0x00000010
-#define PT_TRACE_VFORK	0x00000020
-#define PT_TRACE_CLONE	0x00000040
-#define PT_TRACE_EXEC	0x00000080
-#define PT_TRACE_VFORK_DONE	0x00000100
-#define PT_TRACE_EXIT	0x00000200
-
 #if CONFIG_SMP
 extern void set_cpus_allowed(task_t *p, unsigned long new_mask);
 #else
diff -Nru a/include/linux/signal.h b/include/linux/signal.h
--- a/include/linux/signal.h	Mon Feb 17 14:57:27 2003
+++ b/include/linux/signal.h	Mon Feb 17 14:57:27 2003
@@ -151,8 +151,6 @@
 	}
 }
 
-extern char * render_sigset_t(sigset_t *set, char *buffer);
-
 /* Some extensions for manipulating the low 32 signals in particular.  */
 
 static inline void sigaddsetmask(sigset_t *set, unsigned long mask)
diff -Nru a/include/linux/usb.h b/include/linux/usb.h
--- a/include/linux/usb.h	Mon Feb 17 14:57:27 2003
+++ b/include/linux/usb.h	Mon Feb 17 14:57:27 2003
@@ -1,6 +1,7 @@
 #ifndef __LINUX_USB_H
 #define __LINUX_USB_H
 
+#include <linux/mod_devicetable.h>
 #include <linux/usb_ch9.h>
 
 #define USB_MAJOR			180
@@ -313,99 +314,6 @@
 }
 
 /*-------------------------------------------------------------------------*/
-
-/*
- * Device table entry for "new style" table-driven USB drivers.
- * User mode code can read these tables to choose which modules to load.
- * Declare the table as a MODULE_DEVICE_TABLE.
- *
- * A probe() parameter will point to a matching entry from this table.
- * Use the driver_info field for each match to hold information tied
- * to that match:  device quirks, etc.
- *
- * Terminate the driver's table with an all-zeroes entry.
- * Use the flag values to control which fields are compared.
- */
-
-/**
- * struct usb_device_id - identifies USB devices for probing and hotplugging
- * @match_flags: Bit mask controlling of the other fields are used to match
- *	against new devices.  Any field except for driver_info may be used,
- *	although some only make sense in conjunction with other fields.
- *	This is usually set by a USB_DEVICE_*() macro, which sets all
- *	other fields in this structure except for driver_info.
- * @idVendor: USB vendor ID for a device; numbers are assigned
- *	by the USB forum to its members.
- * @idProduct: Vendor-assigned product ID.
- * @bcdDevice_lo: Low end of range of vendor-assigned product version numbers.
- *	This is also used to identify individual product versions, for
- *	a range consisting of a single device.
- * @bcdDevice_hi: High end of version number range.  The range of product
- *	versions is inclusive.
- * @bDeviceClass: Class of device; numbers are assigned
- *	by the USB forum.  Products may choose to implement classes,
- *	or be vendor-specific.  Device classes specify behavior of all
- *	the interfaces on a devices.
- * @bDeviceSubClass: Subclass of device; associated with bDeviceClass.
- * @bDeviceProtocol: Protocol of device; associated with bDeviceClass.
- * @bInterfaceClass: Class of interface; numbers are assigned
- *	by the USB forum.  Products may choose to implement classes,
- *	or be vendor-specific.  Interface classes specify behavior only
- *	of a given interface; other interfaces may support other classes.
- * @bInterfaceSubClass: Subclass of interface; associated with bInterfaceClass.
- * @bInterfaceProtocol: Protocol of interface; associated with bInterfaceClass.
- * @driver_info: Holds information used by the driver.  Usually it holds
- *	a pointer to a descriptor understood by the driver, or perhaps
- *	device flags.
- *
- * In most cases, drivers will create a table of device IDs by using
- * USB_DEVICE(), or similar macros designed for that purpose.
- * They will then export it to userspace using MODULE_DEVICE_TABLE(),
- * and provide it to the USB core through their usb_driver structure.
- *
- * See the usb_match_id() function for information about how matches are
- * performed.  Briefly, you will normally use one of several macros to help
- * construct these entries.  Each entry you provide will either identify
- * one or more specific products, or will identify a class of products
- * which have agreed to behave the same.  You should put the more specific
- * matches towards the beginning of your table, so that driver_info can
- * record quirks of specific products.
- */
-struct usb_device_id {
-	/* which fields to match against? */
-	__u16		match_flags;
-
-	/* Used for product specific matches; range is inclusive */
-	__u16		idVendor;
-	__u16		idProduct;
-	__u16		bcdDevice_lo;
-	__u16		bcdDevice_hi;
-
-	/* Used for device class matches */
-	__u8		bDeviceClass;
-	__u8		bDeviceSubClass;
-	__u8		bDeviceProtocol;
-
-	/* Used for interface class matches */
-	__u8		bInterfaceClass;
-	__u8		bInterfaceSubClass;
-	__u8		bInterfaceProtocol;
-
-	/* not matched against */
-	unsigned long	driver_info;
-};
-
-/* Some useful macros to use to create struct usb_device_id */
-#define USB_DEVICE_ID_MATCH_VENDOR		0x0001
-#define USB_DEVICE_ID_MATCH_PRODUCT		0x0002
-#define USB_DEVICE_ID_MATCH_DEV_LO		0x0004
-#define USB_DEVICE_ID_MATCH_DEV_HI		0x0008
-#define USB_DEVICE_ID_MATCH_DEV_CLASS		0x0010
-#define USB_DEVICE_ID_MATCH_DEV_SUBCLASS	0x0020
-#define USB_DEVICE_ID_MATCH_DEV_PROTOCOL	0x0040
-#define USB_DEVICE_ID_MATCH_INT_CLASS		0x0080
-#define USB_DEVICE_ID_MATCH_INT_SUBCLASS	0x0100
-#define USB_DEVICE_ID_MATCH_INT_PROTOCOL	0x0200
 
 #define USB_DEVICE_ID_MATCH_DEVICE		(USB_DEVICE_ID_MATCH_VENDOR | USB_DEVICE_ID_MATCH_PRODUCT)
 #define USB_DEVICE_ID_MATCH_DEV_RANGE		(USB_DEVICE_ID_MATCH_DEV_LO | USB_DEVICE_ID_MATCH_DEV_HI)
diff -Nru a/include/linux/vermagic.h b/include/linux/vermagic.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/include/linux/vermagic.h	Mon Feb 17 14:57:28 2003
@@ -0,0 +1,23 @@
+#include <linux/version.h>
+#include <linux/module.h>
+
+/* Simply sanity version stamp for modules. */
+#ifdef CONFIG_SMP
+#define MODULE_VERMAGIC_SMP "SMP "
+#else
+#define MODULE_VERMAGIC_SMP ""
+#endif
+#ifdef CONFIG_PREEMPT
+#define MODULE_VERMAGIC_PREEMPT "preempt "
+#else
+#define MODULE_VERMAGIC_PREEMPT ""
+#endif
+#ifndef MODULE_ARCH_VERMAGIC
+#define MODULE_ARCH_VERMAGIC ""
+#endif
+
+#define VERMAGIC_STRING 						\
+	UTS_RELEASE " "							\
+	MODULE_VERMAGIC_SMP MODULE_VERMAGIC_PREEMPT 			\
+	MODULE_ARCH_VERMAGIC 						\
+	"gcc-" __stringify(__GNUC__) "." __stringify(__GNUC_MINOR__)
diff -Nru a/include/linux/wireless.h b/include/linux/wireless.h
--- a/include/linux/wireless.h	Mon Feb 17 14:57:27 2003
+++ b/include/linux/wireless.h	Mon Feb 17 14:57:27 2003
@@ -294,7 +294,7 @@
 #define IW_PRIV_TYPE_FLOAT	0x5000	/* struct iw_freq */
 #define IW_PRIV_TYPE_ADDR	0x6000	/* struct sockaddr */
 
-#define IW_PRIV_SIZE_FIXED	0x0800	/* Variable or fixed nuber of args */
+#define IW_PRIV_SIZE_FIXED	0x0800	/* Variable or fixed number of args */
 
 #define IW_PRIV_SIZE_MASK	0x07FF	/* Max number of those args */
 
diff -Nru a/include/linux/xattr.h b/include/linux/xattr.h
--- a/include/linux/xattr.h	Mon Feb 17 14:57:27 2003
+++ b/include/linux/xattr.h	Mon Feb 17 14:57:27 2003
@@ -9,7 +9,8 @@
 #ifndef _LINUX_XATTR_H
 #define _LINUX_XATTR_H
 
-#define XATTR_CREATE	0x1	/* set value, fail if attr already exists */
-#define XATTR_REPLACE	0x2	/* set value, fail if attr does not exist */
+#define XATTR_CREATE		0x1	/* fail if attr already exists */
+#define XATTR_REPLACE		0x2	/* fail if attr does not exist */
+#define XATTR_KERNEL_CONTEXT	0x4	/* called from kernel context */
 
 #endif	/* _LINUX_XATTR_H */
diff -Nru a/include/pcmcia/ss.h b/include/pcmcia/ss.h
--- a/include/pcmcia/ss.h	Mon Feb 17 14:57:28 2003
+++ b/include/pcmcia/ss.h	Mon Feb 17 14:57:28 2003
@@ -31,6 +31,7 @@
 #define _LINUX_SS_H
 
 #include <pcmcia/cs_types.h>
+#include <linux/device.h>
 
 /* Definitions for card status flags for GetStatus */
 #define SS_WRPROT	0x0001
@@ -142,7 +143,16 @@
 /*
  *  Calls to set up low-level "Socket Services" drivers
  */
-extern int register_ss_entry(int nsock, struct pccard_operations *ops);
-extern void unregister_ss_entry(struct pccard_operations *ops);
+
+#define MAX_SOCKETS_PER_DEV 8
+
+struct pcmcia_socket_class_data {
+	unsigned int nsock;			/* number of sockets */
+	struct pccard_operations *ops;		/* see above */
+	void *s_info[MAX_SOCKETS_PER_DEV];	/* socket_info_t */
+	unsigned int use_bus_pm;
+};
+
+extern struct device_class pcmcia_socket_class;
 
 #endif /* _LINUX_SS_H */
diff -Nru a/include/sound/ac97_codec.h b/include/sound/ac97_codec.h
--- a/include/sound/ac97_codec.h	Mon Feb 17 14:57:27 2003
+++ b/include/sound/ac97_codec.h	Mon Feb 17 14:57:27 2003
@@ -291,4 +291,14 @@
 void snd_ac97_resume(ac97_t *ac97);
 #endif
 
+enum { AC97_TUNE_HP_ONLY, AC97_TUNE_SWAP_HP };
+
+struct ac97_quirk {
+	unsigned short vendor;
+	unsigned short device;
+	int type;
+};
+
+int snd_ac97_tune_hardware(ac97_t *ac97, struct pci_dev *pci, struct ac97_quirk *quirk);
+
 #endif /* __SOUND_AC97_CODEC_H */
diff -Nru a/include/sound/pcm.h b/include/sound/pcm.h
--- a/include/sound/pcm.h	Mon Feb 17 14:57:27 2003
+++ b/include/sound/pcm.h	Mon Feb 17 14:57:27 2003
@@ -281,6 +281,13 @@
 	unsigned int mask;
 } snd_pcm_hw_constraint_list_t;
 
+struct snd_pcm_dma_buffer {
+	unsigned char *area;
+	dma_addr_t addr;
+	unsigned long bytes;
+	void *private_data; /* for allocator */
+};
+
 struct _snd_pcm_runtime {
 	/* -- Status -- */
 	snd_pcm_substream_t *trigger_master;
@@ -355,6 +362,7 @@
 	unsigned char *dma_area;	/* DMA area */
 	dma_addr_t dma_addr;		/* physical bus address (not accessible from main CPU) */
 	unsigned long dma_bytes;	/* size of DMA area */
+	void *dma_private;		/* private DMA data for the memory allocator */
 
 #if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE)
 	/* -- OSS things -- */
@@ -371,9 +379,7 @@
 	int stream;			/* stream (direction) */
 	size_t buffer_bytes_max;	/* limit ring buffer size */
 	int dma_type;			
-	void *dma_area;
-	dma_addr_t dma_addr;
-	size_t dma_bytes;
+	struct snd_pcm_dma_buffer dma_buffer;
 	size_t dma_max;
 	void *dma_private;
 	/* -- hardware operations -- */
@@ -815,7 +821,7 @@
 int snd_pcm_capture_xrun_check(snd_pcm_substream_t *substream);
 int snd_pcm_playback_xrun_asap(snd_pcm_substream_t *substream);
 int snd_pcm_capture_xrun_asap(snd_pcm_substream_t *substream);
-void snd_pcm_playback_silence(snd_pcm_substream_t *substream);
+void snd_pcm_playback_silence(snd_pcm_substream_t *substream, snd_pcm_uframes_t new_hw_ptr);
 int snd_pcm_playback_ready(snd_pcm_substream_t *substream);
 int snd_pcm_capture_ready(snd_pcm_substream_t *substream);
 long snd_pcm_playback_ready_jiffies(snd_pcm_substream_t *substream);
diff -Nru a/include/sound/pcm_sgbuf.h b/include/sound/pcm_sgbuf.h
--- a/include/sound/pcm_sgbuf.h	Mon Feb 17 14:57:28 2003
+++ b/include/sound/pcm_sgbuf.h	Mon Feb 17 14:57:28 2003
@@ -54,15 +54,13 @@
 	return sgbuf->table[offset >> PAGE_SHIFT].addr + offset % PAGE_SIZE;
 }
 
-struct snd_sg_buf *snd_pcm_sgbuf_init(struct pci_dev *pci);
-void snd_pcm_sgbuf_delete(struct snd_sg_buf *sgbuf);
-void *snd_pcm_sgbuf_alloc_pages(struct snd_sg_buf *sgbuf, size_t size);
-int snd_pcm_sgbuf_free_pages(struct snd_sg_buf *sgbuf, void *vmaddr);
+void *snd_pcm_sgbuf_alloc_pages(struct pci_dev *pci, size_t size, struct snd_pcm_dma_buffer *dmab);
+int snd_pcm_sgbuf_free_pages(struct snd_pcm_dma_buffer *dmab);
 
-int snd_pcm_lib_preallocate_sg_pages(struct pci_dev *pci, snd_pcm_substream_t *substream);
-int snd_pcm_lib_preallocate_sg_pages_for_all(struct pci_dev *pci, snd_pcm_t *pcm);
+int snd_pcm_lib_preallocate_sg_pages(struct pci_dev *pci, snd_pcm_substream_t *substream, size_t size, size_t max);
+int snd_pcm_lib_preallocate_sg_pages_for_all(struct pci_dev *pci, snd_pcm_t *pcm, size_t size, size_t max);
 
-#define _snd_pcm_substream_sgbuf(substream) ((substream)->dma_private)
+#define _snd_pcm_substream_sgbuf(substream) ((substream)->runtime->dma_private)
 #define snd_pcm_substream_sgbuf(substream) snd_magic_cast(snd_pcm_sgbuf_t, _snd_pcm_substream_sgbuf(substream), return -ENXIO)
 
 struct page *snd_pcm_sgbuf_ops_page(snd_pcm_substream_t *substream, unsigned long offset);
diff -Nru a/include/sound/version.h b/include/sound/version.h
--- a/include/sound/version.h	Mon Feb 17 14:57:27 2003
+++ b/include/sound/version.h	Mon Feb 17 14:57:27 2003
@@ -1,3 +1,3 @@
 /* include/version.h.  Generated by configure.  */
 #define CONFIG_SND_VERSION "0.9.0rc7"
-#define CONFIG_SND_DATE " (Sun Feb 09 18:00:12 2003 UTC)"
+#define CONFIG_SND_DATE " (Sat Feb 15 15:01:21 2003 UTC)"
diff -Nru a/init/Makefile b/init/Makefile
--- a/init/Makefile	Mon Feb 17 14:57:27 2003
+++ b/init/Makefile	Mon Feb 17 14:57:27 2003
@@ -3,7 +3,6 @@
 #
 
 obj-y			:= main.o version.o do_mounts.o initramfs.o
-obj-$(CONFIG_MODULES)	+= vermagic.o
 
 # files to be removed upon make clean
 clean-files := ../include/linux/compile.h
diff -Nru a/init/vermagic.c b/init/vermagic.c
--- a/init/vermagic.c	Mon Feb 17 14:57:28 2003
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,22 +0,0 @@
-#include <linux/version.h>
-#include <linux/module.h>
-
-/* Simply sanity version stamp for modules. */
-#ifdef CONFIG_SMP
-#define MODULE_VERMAGIC_SMP "SMP "
-#else
-#define MODULE_VERMAGIC_SMP ""
-#endif
-#ifdef CONFIG_PREEMPT
-#define MODULE_VERMAGIC_PREEMPT "preempt "
-#else
-#define MODULE_VERMAGIC_PREEMPT ""
-#endif
-#ifndef MODULE_ARCH_VERMAGIC
-#define MODULE_ARCH_VERMAGIC ""
-#endif
-
-const char vermagic[] __attribute__((section("__vermagic"))) =
-       UTS_RELEASE " "
-       MODULE_VERMAGIC_SMP MODULE_VERMAGIC_PREEMPT MODULE_ARCH_VERMAGIC
-       "gcc-" __stringify(__GNUC__) "." __stringify(__GNUC_MINOR__);
diff -Nru a/kernel/compat.c b/kernel/compat.c
--- a/kernel/compat.c	Mon Feb 17 14:57:27 2003
+++ b/kernel/compat.c	Mon Feb 17 14:57:27 2003
@@ -16,6 +16,8 @@
 #include <linux/errno.h>
 #include <linux/time.h>
 #include <linux/signal.h>
+#include <linux/sched.h>	/* for MAX_SCHEDULE_TIMEOUT */
+#include <linux/futex.h>	/* for FUTEX_WAIT */
 
 #include <asm/uaccess.h>
 
@@ -207,4 +209,20 @@
 	if (ret == 0)
 		ret = put_user(s, oset);
 	return ret;
+}
+
+extern long do_futex(unsigned long, int, int, unsigned long);
+
+asmlinkage long compat_sys_futex(u32 *uaddr, int op, int val,
+		struct compat_timespec *utime)
+{
+	struct timespec t;
+	unsigned long timeout = MAX_SCHEDULE_TIMEOUT;
+
+	if ((op == FUTEX_WAIT) && utime) {
+		if (get_compat_timespec(&t, utime))
+			return -EFAULT;
+		timeout = timespec_to_jiffies(&t) + 1;
+	}
+	return do_futex((unsigned long)uaddr, op, val, timeout);
 }
diff -Nru a/kernel/cpufreq.c b/kernel/cpufreq.c
--- a/kernel/cpufreq.c	Mon Feb 17 14:57:27 2003
+++ b/kernel/cpufreq.c	Mon Feb 17 14:57:27 2003
@@ -23,12 +23,6 @@
 #include <linux/device.h>
 #include <linux/slab.h>
 
-#ifdef CONFIG_CPU_FREQ_PROC_INTF
-#include <linux/ctype.h>
-#include <linux/proc_fs.h>
-#include <asm/uaccess.h>
-#endif
-
 #ifdef CONFIG_CPU_FREQ_24_API
 #include <linux/proc_fs.h>
 #include <linux/sysctl.h>
@@ -77,7 +71,7 @@
 /**
  * cpufreq_parse_governor - parse a governor string
  */
-static int cpufreq_parse_governor (char *str_governor, unsigned int *policy, struct cpufreq_governor **governor)
+int cpufreq_parse_governor (char *str_governor, unsigned int *policy, struct cpufreq_governor **governor)
 {
 	if (!strnicmp(str_governor, "performance", CPUFREQ_NAME_LEN)) {
 		*policy = CPUFREQ_POLICY_PERFORMANCE;
@@ -103,6 +97,7 @@
 	}
 	return -EINVAL;
 }
+EXPORT_SYMBOL_GPL(cpufreq_parse_governor);
 
 
 /* forward declarations */
@@ -430,241 +425,6 @@
 
 
 /*********************************************************************
- *                      /proc/cpufreq INTERFACE                      *
- *********************************************************************/
-
-#ifdef CONFIG_CPU_FREQ_PROC_INTF
-
-/**
- * cpufreq_parse_policy - parse a policy string
- * @input_string: the string to parse.
- * @policy: the policy written inside input_string
- *
- * This function parses a "policy string" - something the user echo'es into
- * /proc/cpufreq or gives as boot parameter - into a struct cpufreq_policy.
- * If there are invalid/missing entries, they are replaced with current
- * cpufreq policy.
- */
-static int cpufreq_parse_policy(char input_string[42], struct cpufreq_policy *policy)
-{
-	unsigned int            min = 0;
-	unsigned int            max = 0;
-	unsigned int            cpu = 0;
-	char			str_governor[16];
-	struct cpufreq_policy   current_policy;
-	unsigned int            result = -EFAULT;
-
-	if (!policy)
-		return -EINVAL;
-
-	policy->min = 0;
-	policy->max = 0;
-	policy->policy = 0;
-	policy->cpu = CPUFREQ_ALL_CPUS;
-
-	if (sscanf(input_string, "%d:%d:%d:%15s", &cpu, &min, &max, str_governor) == 4) 
-	{
-		policy->min = min;
-		policy->max = max;
-		policy->cpu = cpu;
-		result = 0;
-		goto scan_policy;
-	}
-	if (sscanf(input_string, "%d%%%d%%%d%%%15s", &cpu, &min, &max, str_governor) == 4)
-	{
-		if (!cpufreq_get_policy(&current_policy, cpu)) {
-			policy->min = (min * current_policy.cpuinfo.max_freq) / 100;
-			policy->max = (max * current_policy.cpuinfo.max_freq) / 100;
-			policy->cpu = cpu;
-			result = 0;
-			goto scan_policy;
-		}
-	}
-
-	if (sscanf(input_string, "%d:%d:%15s", &min, &max, str_governor) == 3) 
-	{
-		policy->min = min;
-		policy->max = max;
-		result = 0;
-		goto scan_policy;
-	}
-
-	if (sscanf(input_string, "%d%%%d%%%15s", &min, &max, str_governor) == 3)
-	{
-		if (!cpufreq_get_policy(&current_policy, cpu)) {
-			policy->min = (min * current_policy.cpuinfo.max_freq) / 100;
-			policy->max = (max * current_policy.cpuinfo.max_freq) / 100;
-			result = 0;
-			goto scan_policy;
-		}
-	}
-
-	return -EINVAL;
-
-scan_policy:
-	result = cpufreq_parse_governor(str_governor, &policy->policy, &policy->governor);
-
-	return result;
-}
-
-/**
- * cpufreq_proc_read - read /proc/cpufreq
- *
- * This function prints out the current cpufreq policy.
- */
-static int cpufreq_proc_read (
-	char			*page,
-	char			**start,
-	off_t			off,
-	int 			count,
-	int 			*eof,
-	void			*data)
-{
-	char			*p = page;
-	int			len = 0;
-	struct cpufreq_policy   policy;
-	unsigned int            min_pctg = 0;
-	unsigned int            max_pctg = 0;
-	unsigned int            i = 0;
-
-	if (off != 0)
-		goto end;
-
-	p += sprintf(p, "          minimum CPU frequency  -  maximum CPU frequency  -  policy\n");
-	for (i=0;i<NR_CPUS;i++) {
-		if (!cpu_online(i))
-			continue;
-
-		if (cpufreq_get_policy(&policy, i))
-			continue;
-
-		if (!policy.cpuinfo.max_freq)
-			continue;
-
-		min_pctg = (policy.min * 100) / policy.cpuinfo.max_freq;
-		max_pctg = (policy.max * 100) / policy.cpuinfo.max_freq;
-
-		p += sprintf(p, "CPU%3d    %9d kHz (%3d %%)  -  %9d kHz (%3d %%)  -  ",
-			     i , policy.min, min_pctg, policy.max, max_pctg);
-		switch (policy.policy) {
-		case CPUFREQ_POLICY_POWERSAVE:
-			p += sprintf(p, "powersave\n");
-			break;
-		case CPUFREQ_POLICY_PERFORMANCE:
-			p += sprintf(p, "performance\n");
-			break;
-		case CPUFREQ_POLICY_GOVERNOR:
-			p += snprintf(p, CPUFREQ_NAME_LEN, "%s\n", policy.governor->name);
-			break;
-		default:
-			p += sprintf(p, "INVALID\n");
-			break;
-		}
-	}
-end:
-	len = (p - page);
-	if (len <= off+count) 
-		*eof = 1;
-	*start = page + off;
-	len -= off;
-	if (len>count) 
-		len = count;
-	if (len<0) 
-		len = 0;
-
-	return len;
-}
-
-
-/**
- * cpufreq_proc_write - handles writing into /proc/cpufreq
- *
- * This function calls the parsing script and then sets the policy
- * accordingly.
- */
-static int cpufreq_proc_write (
-        struct file		*file,
-        const char		*buffer,
-        unsigned long		count,
-        void			*data)
-{
-	int                     result = 0;
-	char			proc_string[42] = {'\0'};
-	struct cpufreq_policy   policy;
-	unsigned int            i = 0;
-
-
-	if ((count > sizeof(proc_string) - 1))
-		return -EINVAL;
-	
-	if (copy_from_user(proc_string, buffer, count))
-		return -EFAULT;
-	
-	proc_string[count] = '\0';
-
-	result = cpufreq_parse_policy(proc_string, &policy);
-	if (result)
-		return -EFAULT;
-
-	if (policy.cpu == CPUFREQ_ALL_CPUS)
-	{
-		for (i=0; i<NR_CPUS; i++) 
-		{
-			policy.cpu = i;
-			if (cpu_online(i))
-				cpufreq_set_policy(&policy);
-		}
-	} 
-	else
-		cpufreq_set_policy(&policy);
-
-	return count;
-}
-
-
-/**
- * cpufreq_proc_init - add "cpufreq" to the /proc root directory
- *
- * This function adds "cpufreq" to the /proc root directory.
- */
-static unsigned int cpufreq_proc_init (void)
-{
-	struct proc_dir_entry *entry = NULL;
-
-        /* are these acceptable values? */
-	entry = create_proc_entry("cpufreq", S_IFREG|S_IRUGO|S_IWUSR, 
-				  &proc_root);
-
-	if (!entry) {
-		printk(KERN_ERR "unable to create /proc/cpufreq entry\n");
-		return -EIO;
-	} else {
-		entry->read_proc = cpufreq_proc_read;
-		entry->write_proc = cpufreq_proc_write;
-	}
-
-	return 0;
-}
-
-
-/**
- * cpufreq_proc_exit - removes "cpufreq" from the /proc root directory.
- *
- * This function removes "cpufreq" from the /proc root directory.
- */
-static void cpufreq_proc_exit (void)
-{
-	remove_proc_entry("cpufreq", &proc_root);
-	return;
-}
-#else
-#define cpufreq_proc_init() do {} while(0)
-#define cpufreq_proc_exit() do {} while(0)
-#endif /* CONFIG_CPU_FREQ_PROC_INTF */
-
-
-
-/*********************************************************************
  *                      /proc/sys/cpu/ INTERFACE                     *
  *********************************************************************/
 
@@ -1485,8 +1245,6 @@
 	
 	up(&cpufreq_driver_sem);
 
-	cpufreq_proc_init();
-
 #ifdef CONFIG_CPU_FREQ_24_API
 	cpufreq_sysctl_init();
 #endif
@@ -1516,8 +1274,6 @@
 		return -EINVAL;
 	}
 
-	cpufreq_proc_exit();
-
 #ifdef CONFIG_CPU_FREQ_24_API
 	cpufreq_sysctl_exit();
 #endif
@@ -1582,191 +1338,3 @@
 #else
 #define cpufreq_restore() do {} while (0)
 #endif /* CONFIG_PM */
-
-
-/*********************************************************************
- *                     FREQUENCY TABLE HELPERS                       *
- *********************************************************************/
-
-int cpufreq_frequency_table_cpuinfo(struct cpufreq_policy *policy,
-				    struct cpufreq_frequency_table *table)
-{
-	unsigned int min_freq = ~0;
-	unsigned int max_freq = 0;
-	unsigned int i = 0;
-
-	for (i=0; (table[i].frequency != CPUFREQ_TABLE_END); i++) {
-		unsigned int freq = table[i].frequency;
-		if (freq == CPUFREQ_ENTRY_INVALID)
-			continue;
-		if (freq < min_freq)
-			min_freq = freq;
-		if (freq > max_freq)
-			max_freq = freq;
-	}
-
-	policy->min = policy->cpuinfo.min_freq = min_freq;
-	policy->max = policy->cpuinfo.max_freq = max_freq;
-
-	if (policy->min == ~0)
-		return -EINVAL;
-	else
-		return 0;
-}
-EXPORT_SYMBOL_GPL(cpufreq_frequency_table_cpuinfo);
-
-
-int cpufreq_frequency_table_verify(struct cpufreq_policy *policy,
-				   struct cpufreq_frequency_table *table)
-{
-	unsigned int next_larger = ~0;
-	unsigned int i = 0;
-	unsigned int count = 0;
-
-	if (!cpu_online(policy->cpu))
-		return -EINVAL;
-
-	cpufreq_verify_within_limits(policy, 
-				     policy->cpuinfo.min_freq, 
-				     policy->cpuinfo.max_freq);
-
-	for (i=0; (table[i].frequency != CPUFREQ_TABLE_END); i++) {
-		unsigned int freq = table[i].frequency;
-		if (freq == CPUFREQ_ENTRY_INVALID)
-			continue;
-		if ((freq >= policy->min) && (freq <= policy->max))
-			count++;
-		else if ((next_larger > freq) && (freq > policy->max))
-			next_larger = freq;
-	}
-
-	if (!count)
-		policy->max = next_larger;
-
-	cpufreq_verify_within_limits(policy, 
-				     policy->cpuinfo.min_freq, 
-				     policy->cpuinfo.max_freq);
-
-	return 0;
-}
-EXPORT_SYMBOL_GPL(cpufreq_frequency_table_verify);
-
-
-int cpufreq_frequency_table_setpolicy(struct cpufreq_policy *policy,
-				      struct cpufreq_frequency_table *table,
-				      unsigned int *index)
-{
-	struct cpufreq_frequency_table optimal = { .index = ~0, };
-	unsigned int i;
-
-	switch (policy->policy) {
-	case CPUFREQ_POLICY_PERFORMANCE:
-		optimal.frequency = 0;
-		break;
-	case CPUFREQ_POLICY_POWERSAVE:
-		optimal.frequency = ~0;
-		break;
-	}
-
-	if (!cpu_online(policy->cpu))
-		return -EINVAL;
-
-	for (i=0; (table[i].frequency != CPUFREQ_TABLE_END); i++) {
-		unsigned int freq = table[i].frequency;
-		if (freq == CPUFREQ_ENTRY_INVALID)
-			continue;
-		if ((freq < policy->min) || (freq > policy->max))
-			continue;
-		switch(policy->policy) {
-		case CPUFREQ_POLICY_PERFORMANCE:
-			if (optimal.frequency <= freq) {
-				optimal.frequency = freq;
-				optimal.index = i;
-			}
-			break;
-		case CPUFREQ_POLICY_POWERSAVE:
-			if (optimal.frequency >= freq) {
-				optimal.frequency = freq;
-				optimal.index = i;
-			}
-			break;
-		}
-	}
-	if (optimal.index > i)
-		return -EINVAL;
-
-	*index = optimal.index;
-	
-	return 0;
-}
-EXPORT_SYMBOL_GPL(cpufreq_frequency_table_setpolicy);
-
-int cpufreq_frequency_table_target(struct cpufreq_policy *policy,
-				   struct cpufreq_frequency_table *table,
-				   unsigned int target_freq,
-				   unsigned int relation,
-				   unsigned int *index)
-{
-	struct cpufreq_frequency_table optimal = { .index = ~0, };
-	struct cpufreq_frequency_table suboptimal = { .index = ~0, };
-	unsigned int i;
-
-	switch (relation) {
-	case CPUFREQ_RELATION_H:
-		optimal.frequency = 0;
-		suboptimal.frequency = ~0;
-		break;
-	case CPUFREQ_RELATION_L:
-		optimal.frequency = ~0;
-		suboptimal.frequency = 0;
-		break;
-	}
-
-	if (!cpu_online(policy->cpu))
-		return -EINVAL;
-
-	for (i=0; (table[i].frequency != CPUFREQ_TABLE_END); i++) {
-		unsigned int freq = table[i].frequency;
-		if (freq == CPUFREQ_ENTRY_INVALID)
-			continue;
-		if ((freq < policy->min) || (freq > policy->max))
-			continue;
-		switch(relation) {
-		case CPUFREQ_RELATION_H:
-			if (freq <= target_freq) {
-				if (freq >= optimal.frequency) {
-					optimal.frequency = freq;
-					optimal.index = i;
-				}
-			} else {
-				if (freq <= suboptimal.frequency) {
-					suboptimal.frequency = freq;
-					suboptimal.index = i;
-				}
-			}
-			break;
-		case CPUFREQ_RELATION_L:
-			if (freq >= target_freq) {
-				if (freq <= optimal.frequency) {
-					optimal.frequency = freq;
-					optimal.index = i;
-				}
-			} else {
-				if (freq >= suboptimal.frequency) {
-					suboptimal.frequency = freq;
-					suboptimal.index = i;
-				}
-			}
-			break;
-		}
-	}
-	if (optimal.index > i) {
-		if (suboptimal.index > i)
-			return -EINVAL;
-		*index = suboptimal.index;
-	} else
-		*index = optimal.index;
-	
-	return 0;
-}
-EXPORT_SYMBOL_GPL(cpufreq_frequency_table_target);
diff -Nru a/kernel/dma.c b/kernel/dma.c
--- a/kernel/dma.c	Mon Feb 17 14:57:27 2003
+++ b/kernel/dma.c	Mon Feb 17 14:57:27 2003
@@ -98,6 +98,22 @@
 
 } /* free_dma */
 
+#else
+
+int request_dma(unsigned int dmanr, const char *device_id)
+{
+	return -EINVAL;
+}
+
+void free_dma(unsigned int dmanr)
+{
+}
+
+#endif
+
+#ifdef CONFIG_PROC_FS
+
+#ifdef MAX_DMA_CHANNELS
 static int proc_dma_show(struct seq_file *m, void *v)
 {
 	int i;
@@ -110,27 +126,14 @@
 	}
 	return 0;
 }
-
 #else
-
-int request_dma(unsigned int dmanr, const char *device_id)
-{
-	return -EINVAL;
-}
-
-void free_dma(unsigned int dmanr)
-{
-}
-
 static int proc_dma_show(struct seq_file *m, void *v)
 {
 	seq_puts(m, "No DMA\n");
 	return 0;
 }
+#endif /* MAX_DMA_CHANNELS */
 
-#endif
-
-#ifdef CONFIG_PROC_FS
 static int proc_dma_open(struct inode *inode, struct file *file)
 {
 	char *buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
diff -Nru a/kernel/exit.c b/kernel/exit.c
--- a/kernel/exit.c	Mon Feb 17 14:57:28 2003
+++ b/kernel/exit.c	Mon Feb 17 14:57:28 2003
@@ -694,10 +694,8 @@
 	 * only has special meaning to our real parent.
 	 */
 	if (tsk->exit_signal != -1) {
-		if (tsk->parent == tsk->real_parent)
-			do_notify_parent(tsk, tsk->exit_signal);
-		else
-			do_notify_parent(tsk, SIGCHLD);
+		int signal = tsk->parent == tsk->real_parent ? tsk->exit_signal : SIGCHLD;
+		do_notify_parent(tsk, signal);
 	}
 
 	tsk->state = TASK_ZOMBIE;
@@ -731,8 +729,10 @@
 
 	profile_exit_task(tsk);
  
-	if (unlikely(current->ptrace & PT_TRACE_EXIT))
+	if (unlikely(current->ptrace & PT_TRACE_EXIT)) {
+		current->ptrace_message = code;
 		ptrace_notify((PTRACE_EVENT_EXIT << 8) | SIGTRAP);
+	}
 
 	acct_process(code);
 	__exit_mm(tsk);
diff -Nru a/kernel/fork.c b/kernel/fork.c
--- a/kernel/fork.c	Mon Feb 17 14:57:26 2003
+++ b/kernel/fork.c	Mon Feb 17 14:57:26 2003
@@ -427,7 +427,7 @@
 		complete(vfork_done);
 	}
 	if (tsk->clear_child_tid && atomic_read(&mm->mm_users) > 1) {
-		int * tidptr = tsk->clear_child_tid;
+		u32 * tidptr = tsk->clear_child_tid;
 		tsk->clear_child_tid = NULL;
 
 		/*
@@ -435,7 +435,7 @@
 		 * not set up a proper pointer then tough luck.
 		 */
 		put_user(0, tidptr);
-		sys_futex((unsigned long)tidptr, FUTEX_WAKE, 1, NULL);
+		sys_futex(tidptr, FUTEX_WAKE, 1, NULL);
 	}
 }
 
diff -Nru a/kernel/futex.c b/kernel/futex.c
--- a/kernel/futex.c	Mon Feb 17 14:57:27 2003
+++ b/kernel/futex.c	Mon Feb 17 14:57:27 2003
@@ -315,23 +315,6 @@
 	return ret;
 }
 
-static inline int futex_wait_utime(unsigned long uaddr,
-		      int offset,
-		      int val,
-		      struct timespec* utime)
-{
-	unsigned long time = MAX_SCHEDULE_TIMEOUT;
-
-	if (utime) {
-		struct timespec t;
-		if (copy_from_user(&t, utime, sizeof(t)) != 0)
-			return -EFAULT;
-		time = timespec_to_jiffies(&t) + 1;
-	}
-
-	return futex_wait(uaddr, offset, val, time);
-}
-
 static int futex_close(struct inode *inode, struct file *filp)
 {
 	struct futex_q *q = filp->private_data;
@@ -437,7 +420,7 @@
 	return ret;
 }
 
-asmlinkage int sys_futex(unsigned long uaddr, int op, int val, struct timespec *utime)
+long do_futex(unsigned long uaddr, int op, int val, unsigned long timeout)
 {
 	unsigned long pos_in_page;
 	int ret;
@@ -445,12 +428,12 @@
 	pos_in_page = uaddr % PAGE_SIZE;
 
 	/* Must be "naturally" aligned */
-	if (pos_in_page % sizeof(int))
+	if (pos_in_page % sizeof(u32))
 		return -EINVAL;
 
 	switch (op) {
 	case FUTEX_WAIT:
-		ret = futex_wait_utime(uaddr, pos_in_page, val, utime);
+		ret = futex_wait(uaddr, pos_in_page, val, timeout);
 		break;
 	case FUTEX_WAKE:
 		ret = futex_wake(uaddr, pos_in_page, val);
@@ -463,6 +446,19 @@
 		ret = -EINVAL;
 	}
 	return ret;
+}
+
+asmlinkage long sys_futex(u32 *uaddr, int op, int val, struct timespec *utime)
+{
+	struct timespec t;
+	unsigned long timeout = MAX_SCHEDULE_TIMEOUT;
+
+	if ((op == FUTEX_WAIT) && utime) {
+		if (copy_from_user(&t, utime, sizeof(t)) != 0)
+			return -EFAULT;
+		timeout = timespec_to_jiffies(&t) + 1;
+	}
+	return do_futex((unsigned long)uaddr, op, val, timeout);
 }
 
 static struct super_block *
diff -Nru a/kernel/kmod.c b/kernel/kmod.c
--- a/kernel/kmod.c	Mon Feb 17 14:57:27 2003
+++ b/kernel/kmod.c	Mon Feb 17 14:57:27 2003
@@ -14,8 +14,10 @@
 
 	Unblock all signals when we exec a usermode process.
 	Shuu Yamaguchi <shuu@wondernetworkresources.com> December 2000
-*/
 
+	call_usermodehelper wait flag, and remove exec_usermodehelper.
+	Rusty Russell <rusty@rustcorp.com.au>  Jan 2003
+*/
 #define __KERNEL_SYSCALLS__
 
 #include <linux/config.h>
@@ -31,112 +33,11 @@
 #include <linux/workqueue.h>
 #include <linux/security.h>
 #include <linux/mount.h>
+#include <linux/kernel.h>
 #include <asm/uaccess.h>
 
 extern int max_threads, system_running;
 
-static inline void
-use_init_fs_context(void)
-{
-	struct fs_struct *our_fs, *init_fs;
-	struct dentry *root, *pwd;
-	struct vfsmount *rootmnt, *pwdmnt;
-	struct namespace *our_ns, *init_ns;
-
-	/*
-	 * Make modprobe's fs context be a copy of init's.
-	 *
-	 * We cannot use the user's fs context, because it
-	 * may have a different root than init.
-	 * Since init was created with CLONE_FS, we can grab
-	 * its fs context from "init_task".
-	 *
-	 * The fs context has to be a copy. If it is shared
-	 * with init, then any chdir() call in modprobe will
-	 * also affect init and the other threads sharing
-	 * init_task's fs context.
-	 *
-	 * We created the exec_modprobe thread without CLONE_FS,
-	 * so we can update the fields in our fs context freely.
-	 */
-
-	init_fs = init_task.fs;
-	init_ns = init_task.namespace;
-	get_namespace(init_ns);
-	our_ns = current->namespace;
-	current->namespace = init_ns;
-	put_namespace(our_ns);
-	read_lock(&init_fs->lock);
-	rootmnt = mntget(init_fs->rootmnt);
-	root = dget(init_fs->root);
-	pwdmnt = mntget(init_fs->pwdmnt);
-	pwd = dget(init_fs->pwd);
-	read_unlock(&init_fs->lock);
-
-	/* FIXME - unsafe ->fs access */
-	our_fs = current->fs;
-	our_fs->umask = init_fs->umask;
-	set_fs_root(our_fs, rootmnt, root);
-	set_fs_pwd(our_fs, pwdmnt, pwd);
-	write_lock(&our_fs->lock);
-	if (our_fs->altroot) {
-		struct vfsmount *mnt = our_fs->altrootmnt;
-		struct dentry *dentry = our_fs->altroot;
-		our_fs->altrootmnt = NULL;
-		our_fs->altroot = NULL;
-		write_unlock(&our_fs->lock);
-		dput(dentry);
-		mntput(mnt);
-	} else 
-		write_unlock(&our_fs->lock);
-	dput(root);
-	mntput(rootmnt);
-	dput(pwd);
-	mntput(pwdmnt);
-}
-
-int exec_usermodehelper(char *program_path, char *argv[], char *envp[])
-{
-	int i;
-	struct task_struct *curtask = current;
-
-	set_special_pids(1, 1);
-
-	use_init_fs_context();
-
-	/* Prevent parent user process from sending signals to child.
-	   Otherwise, if the modprobe program does not exist, it might
-	   be possible to get a user defined signal handler to execute
-	   as the super user right after the execve fails if you time
-	   the signal just right.
-	*/
-	flush_signals(curtask);
-	flush_signal_handlers(curtask);
-	spin_lock_irq(&curtask->sighand->siglock);
-	sigemptyset(&curtask->blocked);
-	recalc_sigpending();
-	spin_unlock_irq(&curtask->sighand->siglock);
-
-	for (i = 0; i < curtask->files->max_fds; i++ ) {
-		if (curtask->files->fd[i]) close(i);
-	}
-
-	switch_uid(INIT_USER);
-
-	/* Give kmod all effective privileges.. */
-	curtask->euid = curtask->fsuid = 0;
-	curtask->egid = curtask->fsgid = 0;
-	security_task_kmod_set_label();
-
-	/* Allow execve args to be in kernel space. */
-	set_fs(KERNEL_DS);
-
-	/* Go, go, go... */
-	if (execve(program_path, argv, envp) < 0)
-		return -errno;
-	return 0;
-}
-
 #ifdef CONFIG_KMOD
 
 /*
@@ -144,29 +45,6 @@
 */
 char modprobe_path[256] = "/sbin/modprobe";
 
-static int exec_modprobe(void * module_name)
-{
-	static char * envp[] = { "HOME=/", "TERM=linux", "PATH=/sbin:/usr/sbin:/bin:/usr/bin", NULL };
-	char *argv[] = { modprobe_path, "--", (char*)module_name, NULL };
-	int ret;
-
-	if (!system_running)
-		return -EBUSY;
-
-	ret = exec_usermodehelper(modprobe_path, argv, envp);
-	if (ret) {
-		static unsigned long last;
-		unsigned long now = jiffies;
-		if (now - last > HZ) {
-			last = now;
-			printk(KERN_DEBUG
-			       "kmod: failed to exec %s -s -k %s, errno = %d\n",
-			       modprobe_path, (char*) module_name, errno);
-		}
-	}
-	return ret;
-}
-
 /**
  * request_module - try to load a kernel module
  * @module_name: Name of module
@@ -180,24 +58,18 @@
  * If module auto-loading support is disabled then this function
  * becomes a no-operation.
  */
-int request_module(const char * module_name)
+int request_module(const char *module_name)
 {
-	pid_t pid;
-	int waitpid_result;
-	sigset_t tmpsig;
-	int i, ret;
+	unsigned int max_modprobes;
+	int ret;
+	char *argv[] = { modprobe_path, "--", (char*)module_name, NULL };
+	static char *envp[] = { "HOME=/",
+				"TERM=linux",
+				"PATH=/sbin:/usr/sbin:/bin:/usr/bin",
+				NULL };
 	static atomic_t kmod_concurrent = ATOMIC_INIT(0);
 #define MAX_KMOD_CONCURRENT 50	/* Completely arbitrary value - KAO */
 	static int kmod_loop_msg;
-	unsigned long saved_policy = current->policy;
-
-	current->policy = SCHED_NORMAL;
-	/* Don't allow request_module() when the system isn't set up */
-	if ( ! system_running ) {
-		printk(KERN_ERR "request_module[%s]: not ready\n", module_name);
-		ret = -EPERM;
-		goto out;
-	}
 
 	/* If modprobe needs a service that is in a module, we get a recursive
 	 * loop.  Limit the number of running kmod threads to max_threads/2 or
@@ -207,61 +79,44 @@
 	 * process tables to get the command line, proc_pid_cmdline is static
 	 * and it is not worth changing the proc code just to handle this case. 
 	 * KAO.
+	 *
+
+	 * "trace the ppid" is simple, but will fail if someone's
+	 * parent exits.  I think this is as good as it gets. --RR
 	 */
-	i = max_threads/2;
-	if (i > MAX_KMOD_CONCURRENT)
-		i = MAX_KMOD_CONCURRENT;
+	max_modprobes = min(max_threads/2, MAX_KMOD_CONCURRENT);
 	atomic_inc(&kmod_concurrent);
-	if (atomic_read(&kmod_concurrent) > i) {
+	if (atomic_read(&kmod_concurrent) > max_modprobes) {
+		/* We may be blaming an innocent here, but unlikely */
 		if (kmod_loop_msg++ < 5)
 			printk(KERN_ERR
-			       "kmod: runaway modprobe loop assumed and stopped\n");
+			       "request_module: runaway loop modprobe %s\n",
+			       module_name);
 		atomic_dec(&kmod_concurrent);
-		ret = -ENOMEM;
-		goto out;
+		return -ENOMEM;
 	}
 
-	pid = kernel_thread(exec_modprobe, (void*) module_name, 0);
-	if (pid < 0) {
-		printk(KERN_ERR "request_module[%s]: fork failed, errno %d\n", module_name, -pid);
-		atomic_dec(&kmod_concurrent);
-		ret = pid;
-		goto out;
+	ret = call_usermodehelper(modprobe_path, argv, envp, 1);
+	if (ret != 0) {
+		static unsigned long last;
+		unsigned long now = jiffies;
+		if (now - last > HZ) {
+			last = now;
+			printk(KERN_DEBUG
+			       "request_module: failed %s -- %s. error = %d\n",
+			       modprobe_path, module_name, ret);
+		}
 	}
-
-	/* Block everything but SIGKILL/SIGSTOP */
-	spin_lock_irq(&current->sighand->siglock);
-	tmpsig = current->blocked;
-	siginitsetinv(&current->blocked, sigmask(SIGKILL) | sigmask(SIGSTOP));
-	recalc_sigpending();
-	spin_unlock_irq(&current->sighand->siglock);
-
-	waitpid_result = waitpid(pid, NULL, __WCLONE);
 	atomic_dec(&kmod_concurrent);
-
-	/* Allow signals again.. */
-	spin_lock_irq(&current->sighand->siglock);
-	current->blocked = tmpsig;
-	recalc_sigpending();
-	spin_unlock_irq(&current->sighand->siglock);
-
-	if (waitpid_result != pid) {
-		printk(KERN_ERR "request_module[%s]: waitpid(%d,...) failed, errno %d\n",
-		       module_name, pid, -waitpid_result);
-	}
-	ret = 0;
-out:
-	current->policy = saved_policy;
 	return ret;
 }
 #endif /* CONFIG_KMOD */
 
-
 #ifdef CONFIG_HOTPLUG
 /*
 	hotplug path is set via /proc/sys
 	invoked by hotplug-aware bus drivers,
-	with exec_usermodehelper and some thread-spawner
+	with call_usermodehelper
 
 	argv [0] = hotplug_path;
 	argv [1] = "usb", "scsi", "pci", "network", etc;
@@ -285,7 +140,8 @@
 	char *path;
 	char **argv;
 	char **envp;
-	pid_t retval;
+	int wait;
+	int retval;
 };
 
 /*
@@ -298,13 +154,30 @@
 
 	retval = -EPERM;
 	if (current->fs->root)
-		retval = exec_usermodehelper(sub_info->path, sub_info->argv, sub_info->envp);
+		retval = execve(sub_info->path, sub_info->argv,sub_info->envp);
 
 	/* Exec failed? */
-	sub_info->retval = (pid_t)retval;
+	sub_info->retval = retval;
 	do_exit(0);
 }
 
+/* Keventd can't block, but this (a child) can. */
+static int wait_for_helper(void *data)
+{
+	struct subprocess_info *sub_info = data;
+	pid_t pid;
+
+	pid = kernel_thread(____call_usermodehelper, sub_info,
+			    CLONE_VFORK | SIGCHLD);
+	if (pid < 0)
+		sub_info->retval = pid;
+	else
+		sys_wait4(pid, (unsigned int *)&sub_info->retval, 0, NULL);
+
+	complete(sub_info->complete);
+	return 0;
+}
+
 /*
  * This is run by keventd.
  */
@@ -313,14 +186,21 @@
 	struct subprocess_info *sub_info = data;
 	pid_t pid;
 
-	/*
-	 * CLONE_VFORK: wait until the usermode helper has execve'd successfully
-	 * We need the data structures to stay around until that is done.
-	 */
-	pid = kernel_thread(____call_usermodehelper, sub_info, CLONE_VFORK | SIGCHLD);
-	if (pid < 0)
+	/* CLONE_VFORK: wait until the usermode helper has execve'd
+	 * successfully We need the data structures to stay around
+	 * until that is done.  */
+	if (sub_info->wait)
+		pid = kernel_thread(wait_for_helper, sub_info,
+				    CLONE_KERNEL | SIGCHLD);
+	else
+		pid = kernel_thread(____call_usermodehelper, sub_info,
+				    CLONE_VFORK | SIGCHLD);
+
+	if (pid < 0) {
 		sub_info->retval = pid;
-	complete(sub_info->complete);
+		complete(sub_info->complete);
+	} else if (!sub_info->wait)
+		complete(sub_info->complete);
 }
 
 /**
@@ -328,15 +208,17 @@
  * @path: pathname for the application
  * @argv: null-terminated argument list
  * @envp: null-terminated environment list
+ * @wait: wait for the application to finish and return status.
  *
- * Runs a user-space application.  The application is started asynchronously.  It
- * runs as a child of keventd.  It runs with full root capabilities.  keventd silently
- * reaps the child when it exits.
+ * Runs a user-space application.  The application is started
+ * asynchronously if wait is not set, and runs as a child of keventd.
+ * (ie. it runs with full root capabilities).
  *
- * Must be called from process context.  Returns zero on success, else a negative
- * error code.
+ * Must be called from process context.  Returns a negative error code
+ * if program was not execed successfully, or (exitcode << 8 + signal)
+ * of the application (0 if wait is not set).
  */
-int call_usermodehelper(char *path, char **argv, char **envp)
+int call_usermodehelper(char *path, char **argv, char **envp, int wait)
 {
 	DECLARE_COMPLETION(done);
 	struct subprocess_info sub_info = {
@@ -344,6 +226,7 @@
 		.path		= path,
 		.argv		= argv,
 		.envp		= envp,
+		.wait		= wait,
 		.retval		= 0,
 	};
 	DECLARE_WORK(work, __call_usermodehelper, &sub_info);
@@ -381,7 +264,6 @@
 	up(&dev_probe_sem);
 }
 
-EXPORT_SYMBOL(exec_usermodehelper);
 EXPORT_SYMBOL(call_usermodehelper);
 
 #ifdef CONFIG_KMOD
diff -Nru a/kernel/module.c b/kernel/module.c
--- a/kernel/module.c	Mon Feb 17 14:57:27 2003
+++ b/kernel/module.c	Mon Feb 17 14:57:27 2003
@@ -30,6 +30,7 @@
 #include <linux/moduleparam.h>
 #include <linux/errno.h>
 #include <linux/err.h>
+#include <linux/vermagic.h>
 #include <asm/uaccess.h>
 #include <asm/semaphore.h>
 #include <asm/pgalloc.h>
@@ -725,6 +726,8 @@
 }
 #endif /* CONFIG_OBSOLETE_MODPARM */
 
+static const char vermagic[] = VERMAGIC_STRING;
+
 #ifdef CONFIG_MODVERSIONS
 static int check_version(Elf_Shdr *sechdrs,
 			 unsigned int versindex,
@@ -768,6 +771,18 @@
 	return 1;
 }
 
+static inline int check_modstruct_version(Elf_Shdr *sechdrs,
+					  unsigned int versindex,
+					  struct module *mod)
+{
+	unsigned int i;
+	struct kernel_symbol_group *ksg;
+
+	if (!__find_symbol("struct_module", &ksg, &i, 1))
+		BUG();
+	return check_version(sechdrs, versindex, "struct_module", mod, ksg, i);
+}
+
 /* First part is kernel version, which we ignore. */
 static inline int same_magic(const char *amagic, const char *bmagic)
 {
@@ -786,6 +801,13 @@
 	return 1;
 }
 
+static inline int check_modstruct_version(Elf_Shdr *sechdrs,
+					  unsigned int versindex,
+					  struct module *mod)
+{
+	return 1;
+}
+
 static inline int same_magic(const char *amagic, const char *bmagic)
 {
 	return strcmp(amagic, bmagic) == 0;
@@ -1036,9 +1058,6 @@
 	}
 }
 
-/* From init/vermagic.o */
-extern char vermagic[];
-
 /* Allocate and load the module: note that size of section 0 is always
    zero, and we rely on this for optional sections. */
 static struct module *load_module(void *umod,
@@ -1185,6 +1204,12 @@
 	}
 	mod = (void *)sechdrs[modindex].sh_addr;
 
+	/* Check module struct version now, before we try to use module. */
+	if (!check_modstruct_version(sechdrs, versindex, mod)) {
+		err = -ENOEXEC;
+		goto free_hdr;
+	}
+
 	/* This is allowed: modprobe --force will invalidate it. */
 	if (!vmagindex) {
 		tainted |= TAINT_FORCED_MODULE;
@@ -1455,9 +1480,9 @@
 
 	/* At worse, next value is at end of module */
 	if (within(addr, mod->module_init, mod->init_size))
-		nextval = (unsigned long)mod->module_core+mod->core_size;
+		nextval = (unsigned long)mod->module_init + mod->init_size;
 	else 
-		nextval = (unsigned long)mod->module_init+mod->init_size;
+		nextval = (unsigned long)mod->module_core + mod->core_size;
 
 	/* Scan for closest preceeding symbol, and next symbol. (ELF
            starts real symbols at 1). */
@@ -1630,3 +1655,9 @@
 }
 
 __initcall(symbols_init);
+
+#ifdef CONFIG_MODVERSIONS
+/* Generate the signature for struct module here, too, for modversions. */
+void struct_module(struct module *mod) { return; }
+EXPORT_SYMBOL(struct_module);
+#endif
diff -Nru a/kernel/ptrace.c b/kernel/ptrace.c
--- a/kernel/ptrace.c	Mon Feb 17 14:57:28 2003
+++ b/kernel/ptrace.c	Mon Feb 17 14:57:28 2003
@@ -252,49 +252,30 @@
 
 static int ptrace_setoptions(struct task_struct *child, long data)
 {
+	child->ptrace &= ~PT_TRACE_MASK;
+
 	if (data & PTRACE_O_TRACESYSGOOD)
 		child->ptrace |= PT_TRACESYSGOOD;
-	else
-		child->ptrace &= ~PT_TRACESYSGOOD;
 
 	if (data & PTRACE_O_TRACEFORK)
 		child->ptrace |= PT_TRACE_FORK;
-	else
-		child->ptrace &= ~PT_TRACE_FORK;
 
 	if (data & PTRACE_O_TRACEVFORK)
 		child->ptrace |= PT_TRACE_VFORK;
-	else
-		child->ptrace &= ~PT_TRACE_VFORK;
 
 	if (data & PTRACE_O_TRACECLONE)
 		child->ptrace |= PT_TRACE_CLONE;
-	else
-		child->ptrace &= ~PT_TRACE_CLONE;
 
 	if (data & PTRACE_O_TRACEEXEC)
 		child->ptrace |= PT_TRACE_EXEC;
-	else
-		child->ptrace &= ~PT_TRACE_EXEC;
 
 	if (data & PTRACE_O_TRACEVFORKDONE)
 		child->ptrace |= PT_TRACE_VFORK_DONE;
-	else
-		child->ptrace &= ~PT_TRACE_VFORK_DONE;
 
 	if (data & PTRACE_O_TRACEEXIT)
 		child->ptrace |= PT_TRACE_EXIT;
-	else
-		child->ptrace &= ~PT_TRACE_EXIT;
-
-	if ((data & (PTRACE_O_TRACESYSGOOD | PTRACE_O_TRACEFORK
-		    | PTRACE_O_TRACEVFORK | PTRACE_O_TRACECLONE
-		    | PTRACE_O_TRACEEXEC | PTRACE_O_TRACEEXIT
-		    | PTRACE_O_TRACEVFORKDONE))
-	    != data)
-		return -EINVAL;
 
-	return 0;
+	return (data & ~PTRACE_O_MASK) ? -EINVAL : 0;
 }
 
 static int ptrace_getsiginfo(struct task_struct *child, long data)
diff -Nru a/kernel/sched.c b/kernel/sched.c
--- a/kernel/sched.c	Mon Feb 17 14:57:28 2003
+++ b/kernel/sched.c	Mon Feb 17 14:57:28 2003
@@ -2095,21 +2095,6 @@
 	}
 }
 
-char * render_sigset_t(sigset_t *set, char *buffer)
-{
-	int i = _NSIG, x;
-	do {
-		i -= 4, x = 0;
-		if (sigismember(set, i+1)) x |= 1;
-		if (sigismember(set, i+2)) x |= 2;
-		if (sigismember(set, i+3)) x |= 4;
-		if (sigismember(set, i+4)) x |= 8;
-		*buffer++ = (x < 10 ? '0' : 'a' - 10) + x;
-	} while (i >= 4);
-	*buffer = 0;
-	return buffer;
-}
-
 void show_state(void)
 {
 	task_t *g, *p;
diff -Nru a/kernel/signal.c b/kernel/signal.c
--- a/kernel/signal.c	Mon Feb 17 14:57:27 2003
+++ b/kernel/signal.c	Mon Feb 17 14:57:27 2003
@@ -19,6 +19,7 @@
 #include <linux/tty.h>
 #include <linux/binfmts.h>
 #include <linux/security.h>
+#include <linux/ptrace.h>
 #include <asm/param.h>
 #include <asm/uaccess.h>
 #include <asm/siginfo.h>
@@ -1108,21 +1109,31 @@
  * These are for backward compatibility with the rest of the kernel source.
  */
 
+/*
+ * XXX should probably nix these interfaces and update the kernel
+ * to specify explicitly whether the signal is a group signal or
+ * specific to a thread.
+ */
 int
 send_sig_info(int sig, struct siginfo *info, struct task_struct *p)
 {
 	int ret;
 
-	/* XXX should nix these interfaces and update the kernel */
+	/*
+	 * We need the tasklist lock even for the specific
+	 * thread case (when we don't need to follow the group
+	 * lists) in order to avoid races with "p->sighand"
+	 * going away or changing from under us.
+	 */
+	read_lock(&tasklist_lock);  
 	if (T(sig, SIG_KERNEL_BROADCAST_MASK)) {
-		read_lock(&tasklist_lock);
 		ret = group_send_sig_info(sig, info, p);
-		read_unlock(&tasklist_lock);
 	} else {
 		spin_lock_irq(&p->sighand->siglock);
 		ret = specific_send_sig_info(sig, info, p);
 		spin_unlock_irq(&p->sighand->siglock);
 	}
+	read_unlock(&tasklist_lock);
 	return ret;
 }
 
diff -Nru a/lib/crc32.c b/lib/crc32.c
--- a/lib/crc32.c	Mon Feb 17 14:57:26 2003
+++ b/lib/crc32.c	Mon Feb 17 14:57:26 2003
@@ -87,55 +87,51 @@
 {
 # if CRC_LE_BITS == 8
 	const u32      *b =(u32 *)p;
-	const u32      *e;
-	/* load data 32 bits wide, xor data 32 bits wide. */
+	const u32      *tab = crc32table_le;
 
-	crc = __cpu_to_le32(crc);
-	/* Align it */
-	for ( ; ((long)b)&3 && len ; len--){
-# ifdef __LITTLE_ENDIAN
-		crc = (crc>>8) ^ crc32table_le[ (crc ^ *((u8 *)b)++) & 0xff ];
-# else
-		crc = (crc<<8) ^ crc32table_le[ crc>>24 ^ *((u8 *)b)++ ];
-# endif
-	}
-	e = (u32 *) ( (u8 *)b + (len & ~7));
-	while (b < e) {
-		crc ^= *b++;
-# ifdef __LITTLE_ENDIAN
-		crc = (crc>>8) ^ crc32table_le[ crc & 0xff ];
-		crc = (crc>>8) ^ crc32table_le[ crc & 0xff ];
-		crc = (crc>>8) ^ crc32table_le[ crc & 0xff ];
-		crc = (crc>>8) ^ crc32table_le[ crc & 0xff ];
-# else
-		crc = (crc<<8) ^ crc32table_le[ crc >> 24 ];
-		crc = (crc<<8) ^ crc32table_le[ crc >> 24 ];
-		crc = (crc<<8) ^ crc32table_le[ crc >> 24 ];
-		crc = (crc<<8) ^ crc32table_le[ crc >> 24 ];
-# endif
-		crc ^= *b++;
 # ifdef __LITTLE_ENDIAN
-		crc = (crc>>8) ^ crc32table_le[ crc & 0xff ];
-		crc = (crc>>8) ^ crc32table_le[ crc & 0xff ];
-		crc = (crc>>8) ^ crc32table_le[ crc & 0xff ];
-		crc = (crc>>8) ^ crc32table_le[ crc & 0xff ];
+#  define DO_CRC crc = (crc>>8) ^ tab[ crc & 255 ]
+#  define ENDIAN_SHIFT 0
 # else
-		crc = (crc<<8) ^ crc32table_le[ crc >> 24 ];
-		crc = (crc<<8) ^ crc32table_le[ crc >> 24 ];
-		crc = (crc<<8) ^ crc32table_le[ crc >> 24 ];
-		crc = (crc<<8) ^ crc32table_le[ crc >> 24 ];
+#  define DO_CRC crc = (crc<<8) ^ tab[ crc >> 24 ]
+#  define ENDIAN_SHIFT 24
 # endif
+
+	crc = __cpu_to_le32(crc);
+	/* Align it */
+	if(unlikely(((long)b)&3 && len)){
+		do {
+			crc ^= *((u8 *)b)++ << ENDIAN_SHIFT;
+			DO_CRC;
+		} while ((--len) && ((long)b)&3 );
+	}
+	if(likely(len >= 4)){
+		/* load data 32 bits wide, xor data 32 bits wide. */
+		size_t save_len = len & 3;
+	        len = len >> 2;
+		--b; /* use pre increment below(*++b) for speed */
+		do {
+			crc ^= *++b;
+			DO_CRC;
+			DO_CRC;
+			DO_CRC;
+			DO_CRC;
+		} while (--len);
+		b++; /* point to next byte(s) */
+		len = save_len;
 	}
 	/* And the last few bytes */
-	e = (u32 *)((u8 *)b + (len & 7));
-	while (b < e){
-# ifdef __LITTLE_ENDIAN
-		crc = (crc>>8) ^ crc32table_le[ (crc ^ *((u8 *)b)++) & 0xff ];
-# else
-		crc = (crc<<8) ^ crc32table_le[ crc>>24 ^ *((u8 *)b)++ ];
-# endif
+	if(len){
+		do {
+			crc ^= *((u8 *)b)++ << ENDIAN_SHIFT;
+			DO_CRC;
+		} while (--len);
 	}
-	return __le32_to_cpu(crc) ;
+
+	return __le32_to_cpu(crc);
+#undef ENDIAN_SHIFT
+#undef DO_CRC
+
 # elif CRC_LE_BITS == 4
 	while (len--) {
 		crc ^= *p++;
@@ -196,55 +192,50 @@
 {
 # if CRC_BE_BITS == 8
 	const u32      *b =(u32 *)p;
-	const u32      *e;
-	/* load data 32 bits wide, xor data 32 bits wide. */
+	const u32      *tab = crc32table_be;
 
-	crc = __cpu_to_be32(crc);
-	/* Align it */
-	for ( ; ((long)b)&3 && len ; len--){
-# ifdef __LITTLE_ENDIAN
-		crc = (crc>>8) ^ crc32table_be[ (crc ^ *((u8 *)b)++) & 0xff ];
-# else
-		crc = (crc<<8) ^ crc32table_be[ crc>>24 ^ *((u8 *)b)++ ];
-# endif
-	}
-	e = (u32 *) ( (u8 *)b + (len & ~7));
-	while (b < e) {
-		crc ^= *b++;
-# ifdef __LITTLE_ENDIAN
-		crc = (crc>>8) ^ crc32table_be[ crc & 0xff ];
-		crc = (crc>>8) ^ crc32table_be[ crc & 0xff ];
-		crc = (crc>>8) ^ crc32table_be[ crc & 0xff ];
-		crc = (crc>>8) ^ crc32table_be[ crc & 0xff ];
-# else
-		crc = (crc<<8) ^ crc32table_be[ crc >> 24 ];
-		crc = (crc<<8) ^ crc32table_be[ crc >> 24 ];
-		crc = (crc<<8) ^ crc32table_be[ crc >> 24 ];
-		crc = (crc<<8) ^ crc32table_be[ crc >> 24 ];
-# endif
-		crc ^= *b++;
 # ifdef __LITTLE_ENDIAN
-		crc = (crc>>8) ^ crc32table_be[ crc & 0xff ];
-		crc = (crc>>8) ^ crc32table_be[ crc & 0xff ];
-		crc = (crc>>8) ^ crc32table_be[ crc & 0xff ];
-		crc = (crc>>8) ^ crc32table_be[ crc & 0xff ];
+#  define DO_CRC crc = (crc>>8) ^ tab[ crc & 255 ]
+#  define ENDIAN_SHIFT 24
 # else
-		crc = (crc<<8) ^ crc32table_be[ crc >> 24 ];
-		crc = (crc<<8) ^ crc32table_be[ crc >> 24 ];
-		crc = (crc<<8) ^ crc32table_be[ crc >> 24 ];
-		crc = (crc<<8) ^ crc32table_be[ crc >> 24 ];
+#  define DO_CRC crc = (crc<<8) ^ tab[ crc >> 24 ]
+#  define ENDIAN_SHIFT 0
 # endif
+
+	crc = __cpu_to_be32(crc);
+	/* Align it */
+	if(unlikely(((long)b)&3 && len)){
+		do {
+			crc ^= *((u8 *)b)++ << ENDIAN_SHIFT;
+			DO_CRC;
+		} while ((--len) && ((long)b)&3 );
+	}
+	if(likely(len >= 4)){
+		/* load data 32 bits wide, xor data 32 bits wide. */
+		size_t save_len = len & 3;
+	        len = len >> 2;
+		--b; /* use pre increment below(*++b) for speed */
+		do {
+			crc ^= *++b;
+			DO_CRC;
+			DO_CRC;
+			DO_CRC;
+			DO_CRC;
+		} while (--len);
+		b++; /* point to next byte(s) */
+		len = save_len;
 	}
 	/* And the last few bytes */
-	e = (u32 *)((u8 *)b + (len & 7));
-	while (b < e){
-# ifdef __LITTLE_ENDIAN
-		crc = (crc>>8) ^ crc32table_be[ (crc ^ *((u8 *)b)++) & 0xff ];
-# else
-		crc = (crc<<8) ^ crc32table_be[ crc>>24 ^ *((u8 *)b)++ ];
-# endif
-	}
-	return __be32_to_cpu(crc) ;
+	if(len){
+		do {
+			crc ^= *((u8 *)b)++ << ENDIAN_SHIFT;
+			DO_CRC;
+		} while (--len);
+	}
+	return __be32_to_cpu(crc);
+#undef ENDIAN_SHIFT
+#undef DO_CRC
+
 # elif CRC_BE_BITS == 4
 	while (len--) {
 		crc ^= *p++ << 24;
diff -Nru a/lib/radix-tree.c b/lib/radix-tree.c
--- a/lib/radix-tree.c	Mon Feb 17 14:57:27 2003
+++ b/lib/radix-tree.c	Mon Feb 17 14:57:27 2003
@@ -46,6 +46,8 @@
 #define RADIX_TREE_INDEX_BITS  (8 /* CHAR_BIT */ * sizeof(unsigned long))
 #define RADIX_TREE_MAX_PATH (RADIX_TREE_INDEX_BITS/RADIX_TREE_MAP_SHIFT + 2)
 
+static unsigned long height_to_maxindex[RADIX_TREE_MAX_PATH];
+
 /*
  * Radix tree node cache.
  */
@@ -126,12 +128,7 @@
  */
 static inline unsigned long radix_tree_maxindex(unsigned int height)
 {
-	unsigned int tmp = height * RADIX_TREE_MAP_SHIFT;
-	unsigned long index = (~0UL >> (RADIX_TREE_INDEX_BITS - tmp - 1)) >> 1;
-
-	if (tmp >= RADIX_TREE_INDEX_BITS)
-		index = ~0UL;
-	return index;
+	return height_to_maxindex[height];
 }
 
 /*
@@ -401,6 +398,24 @@
 	memset(node, 0, sizeof(struct radix_tree_node));
 }
 
+static __init unsigned long __maxindex(unsigned int height)
+{
+	unsigned int tmp = height * RADIX_TREE_MAP_SHIFT;
+	unsigned long index = (~0UL >> (RADIX_TREE_INDEX_BITS - tmp - 1)) >> 1;
+
+	if (tmp >= RADIX_TREE_INDEX_BITS)
+		index = ~0UL;
+	return index;
+}
+
+static __init void radix_tree_init_maxindex(void)
+{
+	unsigned int i;
+
+	for (i = 0; i < ARRAY_SIZE(height_to_maxindex); i++)
+		height_to_maxindex[i] = __maxindex(i);
+}
+
 void __init radix_tree_init(void)
 {
 	radix_tree_node_cachep = kmem_cache_create("radix_tree_node",
@@ -408,4 +423,5 @@
 			0, radix_tree_node_ctor, NULL);
 	if (!radix_tree_node_cachep)
 		panic ("Failed to create radix_tree_node cache\n");
+	radix_tree_init_maxindex();
 }
diff -Nru a/mm/filemap.c b/mm/filemap.c
--- a/mm/filemap.c	Mon Feb 17 14:57:27 2003
+++ b/mm/filemap.c	Mon Feb 17 14:57:27 2003
@@ -678,50 +678,6 @@
 	UPDATE_ATIME(inode);
 }
 
-/*
- * Fault a userspace page into pagetables.  Return non-zero on a fault.
- *
- * FIXME: this assumes that two userspace pages are always sufficient.  That's
- * not true if PAGE_CACHE_SIZE > PAGE_SIZE.
- */
-static inline int fault_in_pages_writeable(char *uaddr, int size)
-{
-	int ret;
-
-	/*
-	 * Writing zeroes into userspace here is OK, because we know that if
-	 * the zero gets there, we'll be overwriting it.
-	 */
-	ret = __put_user(0, uaddr);
-	if (ret == 0) {
-		char *end = uaddr + size - 1;
-
-		/*
-		 * If the page was already mapped, this will get a cache miss
-		 * for sure, so try to avoid doing it.
-		 */
-		if (((unsigned long)uaddr & PAGE_MASK) !=
-				((unsigned long)end & PAGE_MASK))
-		 	ret = __put_user(0, end);
-	}
-	return ret;
-}
-
-static void fault_in_pages_readable(const char *uaddr, int size)
-{
-	volatile char c;
-	int ret;
-
-	ret = __get_user(c, (char *)uaddr);
-	if (ret == 0) {
-		const char *end = uaddr + size - 1;
-
-		if (((unsigned long)uaddr & PAGE_MASK) !=
-				((unsigned long)end & PAGE_MASK))
-		 	__get_user(c, (char *)end);
-	}
-}
-
 int file_read_actor(read_descriptor_t *desc, struct page *page,
 			unsigned long offset, unsigned long size)
 {
@@ -805,13 +761,8 @@
 			goto out; /* skip atime */
 		size = inode->i_size;
 		if (pos < size) {
-			if (pos + count > size) {
-				count = size - pos;
-				nr_segs = iov_shorten((struct iovec *)iov,
-							nr_segs, count);
-			}
 			retval = generic_file_direct_IO(READ, iocb,
-					iov, pos, nr_segs);
+						iov, pos, nr_segs);
 			if (retval >= 0 && !is_sync_kiocb(iocb))
 				retval = -EIOCBQUEUED;
 			if (retval > 0)
@@ -1530,6 +1481,91 @@
 	*basep = base;
 }
 
+/*
+ * Performs necessary checks before doing a write
+ *
+ * Can adjust writing position aor amount of bytes to write.
+ * Returns appropriate error code that caller should return or
+ * zero in case that write should be allowed.
+ */
+inline int generic_write_checks(struct inode *inode,
+		struct file *file, loff_t *pos, size_t *count, int isblk)
+{
+	unsigned long limit = current->rlim[RLIMIT_FSIZE].rlim_cur;
+
+        if (unlikely(*pos < 0))
+                return -EINVAL;
+
+        if (unlikely(file->f_error)) {
+                int err = file->f_error;
+                file->f_error = 0;
+                return err;
+        }
+
+	if (!isblk) {
+		/* FIXME: this is for backwards compatibility with 2.4 */
+		if (file->f_flags & O_APPEND)
+                        *pos = inode->i_size;
+
+		if (limit != RLIM_INFINITY) {
+			if (*pos >= limit) {
+				send_sig(SIGXFSZ, current, 0);
+				return -EFBIG;
+			}
+			if (*pos > 0xFFFFFFFFULL || *count > limit-(u32)*pos) {
+				/* send_sig(SIGXFSZ, current, 0); */
+				*count = limit - (u32)*pos;
+			}
+		}
+	}
+
+	/*
+	 * LFS rule
+	 */
+	if (unlikely(*pos + *count > MAX_NON_LFS &&
+				!(file->f_flags & O_LARGEFILE))) {
+		if (*pos >= MAX_NON_LFS) {
+			send_sig(SIGXFSZ, current, 0);
+			return -EFBIG;
+		}
+		if (*count > MAX_NON_LFS - (u32)*pos) {
+			/* send_sig(SIGXFSZ, current, 0); */
+			*count = MAX_NON_LFS - (u32)*pos;
+		}
+	}
+
+	/*
+	 * Are we about to exceed the fs block limit ?
+	 *
+	 * If we have written data it becomes a short write.  If we have
+	 * exceeded without writing data we send a signal and return EFBIG.
+	 * Linus frestrict idea will clean these up nicely..
+	 */
+	if (likely(!isblk)) {
+		if (unlikely(*pos >= inode->i_sb->s_maxbytes)) {
+			if (*count || *pos > inode->i_sb->s_maxbytes) {
+				send_sig(SIGXFSZ, current, 0);
+				return -EFBIG;
+			}
+			/* zero-length writes at ->s_maxbytes are OK */
+		}
+
+		if (unlikely(*pos + *count > inode->i_sb->s_maxbytes))
+			*count = inode->i_sb->s_maxbytes - *pos;
+	} else {
+		if (bdev_read_only(inode->i_bdev))
+			return -EPERM;
+		if (*pos >= inode->i_size) {
+			if (*count || *pos > inode->i_size)
+				return -ENOSPC;
+		}
+
+		if (*pos + *count > inode->i_size)
+			*count = inode->i_size - *pos;
+	}
+	return 0;
+}
+EXPORT_SYMBOL(generic_write_checks);
 
 /*
  * Write to a file through the page cache. 
@@ -1550,12 +1586,11 @@
 	size_t ocount;		/* original count */
 	size_t count;		/* after file limit checks */
 	struct inode 	*inode = mapping->host;
-	unsigned long	limit = current->rlim[RLIMIT_FSIZE].rlim_cur;
-	const int	isblk = S_ISBLK(inode->i_mode);
 	long		status = 0;
 	loff_t		pos;
 	struct page	*page;
 	struct page	*cached_page = NULL;
+	const int	isblk = S_ISBLK(inode->i_mode);
 	ssize_t		written;
 	ssize_t		err;
 	size_t		bytes;
@@ -1584,95 +1619,20 @@
 		ocount -= iv->iov_len;	/* This segment is no good */
 		break;
 	}
-	count = ocount;
 
+	count = ocount;
 	pos = *ppos;
-	if (unlikely(pos < 0))
-		return -EINVAL;
+	pagevec_init(&lru_pvec, 0);
 
 	/* We can write back this queue in page reclaim */
 	current->backing_dev_info = mapping->backing_dev_info;
-
-	pagevec_init(&lru_pvec, 0);
-
-	if (unlikely(file->f_error)) {
-		err = file->f_error;
-		file->f_error = 0;
-		goto out;
-	}
-
 	written = 0;
 
-	if (!isblk) {
-		/* FIXME: this is for backwards compatibility with 2.4 */
-		if (file->f_flags & O_APPEND)
-			pos = inode->i_size;
-
-		if (limit != RLIM_INFINITY) {
-			if (pos >= limit) {
-				send_sig(SIGXFSZ, current, 0);
-				err = -EFBIG;
-				goto out;
-			}
-			if (pos > 0xFFFFFFFFULL || count > limit - (u32)pos) {
-				/* send_sig(SIGXFSZ, current, 0); */
-				count = limit - (u32)pos;
-			}
-		}
-	}
-
-	/*
-	 * LFS rule
-	 */
-	if (unlikely(pos + count > MAX_NON_LFS &&
-				!(file->f_flags & O_LARGEFILE))) {
-		if (pos >= MAX_NON_LFS) {
-			send_sig(SIGXFSZ, current, 0);
-			err = -EFBIG;
-			goto out;
-		}
-		if (count > MAX_NON_LFS - (u32)pos) {
-			/* send_sig(SIGXFSZ, current, 0); */
-			count = MAX_NON_LFS - (u32)pos;
-		}
-	}
-
-	/*
-	 * Are we about to exceed the fs block limit ?
-	 *
-	 * If we have written data it becomes a short write.  If we have
-	 * exceeded without writing data we send a signal and return EFBIG.
-	 * Linus frestrict idea will clean these up nicely..
-	 */
-	if (likely(!isblk)) {
-		if (unlikely(pos >= inode->i_sb->s_maxbytes)) {
-			if (count || pos > inode->i_sb->s_maxbytes) {
-				send_sig(SIGXFSZ, current, 0);
-				err = -EFBIG;
-				goto out;
-			}
-			/* zero-length writes at ->s_maxbytes are OK */
-		}
-
-		if (unlikely(pos + count > inode->i_sb->s_maxbytes))
-			count = inode->i_sb->s_maxbytes - pos;
-	} else {
-		if (bdev_read_only(inode->i_bdev)) {
-			err = -EPERM;
-			goto out;
-		}
-		if (pos >= inode->i_size) {
-			if (count || pos > inode->i_size) {
-				err = -ENOSPC;
-				goto out;
-			}
-		}
+	err = generic_write_checks(inode, file, &pos, &count, isblk);
+	if (err)
+		goto out;
 
-		if (pos + count > inode->i_size)
-			count = inode->i_size - pos;
-	}
 
-	err = 0;
 	if (count == 0)
 		goto out;
 
diff -Nru a/mm/page-writeback.c b/mm/page-writeback.c
--- a/mm/page-writeback.c	Mon Feb 17 14:57:27 2003
+++ b/mm/page-writeback.c	Mon Feb 17 14:57:27 2003
@@ -301,7 +301,7 @@
 		writeback_inodes(&wbc);
 		if (wbc.nr_to_write > 0) {
 			if (wbc.encountered_congestion)
-				blk_congestion_wait(WRITE, HZ);
+				blk_congestion_wait(WRITE, HZ/10);
 			else
 				break;	/* All the old data is written */
 		}
diff -Nru a/mm/slab.c b/mm/slab.c
--- a/mm/slab.c	Mon Feb 17 14:57:28 2003
+++ b/mm/slab.c	Mon Feb 17 14:57:28 2003
@@ -438,7 +438,6 @@
 /* internal cache of cache description objs */
 static kmem_cache_t cache_cache = {
 	.lists		= LIST3_INIT(cache_cache.lists),
-	/* Allow for boot cpu != 0 */
 	.batchcount	= 1,
 	.limit		= BOOT_CPUCACHE_ENTRIES,
 	.objsize	= sizeof(kmem_cache_t),
diff -Nru a/mm/vmscan.c b/mm/vmscan.c
--- a/mm/vmscan.c	Mon Feb 17 14:57:27 2003
+++ b/mm/vmscan.c	Mon Feb 17 14:57:27 2003
@@ -835,7 +835,7 @@
 		wakeup_bdflush(total_scanned);
 
 		/* Take a nap, wait for some writeback to complete */
-		blk_congestion_wait(WRITE, HZ/4);
+		blk_congestion_wait(WRITE, HZ/10);
 		shrink_slab(total_scanned, gfp_mask);
 	}
 	if (gfp_mask & __GFP_FS)
@@ -904,7 +904,7 @@
 		}
 		if (all_zones_ok)
 			break;
-		blk_congestion_wait(WRITE, HZ/4);
+		blk_congestion_wait(WRITE, HZ/10);
 	}
 	return nr_pages - to_free;
 }
diff -Nru a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
--- a/net/bluetooth/hci_core.c	Mon Feb 17 14:57:27 2003
+++ b/net/bluetooth/hci_core.c	Mon Feb 17 14:57:27 2003
@@ -114,7 +114,7 @@
 	envp[3] = astr;
 	envp[4] = NULL;
 	
-	return call_usermodehelper(argv[0], argv, envp);
+	return call_usermodehelper(argv[0], argv, envp, 0);
 }
 #else
 #define hci_run_hotplug(A...)
diff -Nru a/net/core/dev.c b/net/core/dev.c
--- a/net/core/dev.c	Mon Feb 17 14:57:27 2003
+++ b/net/core/dev.c	Mon Feb 17 14:57:27 2003
@@ -2942,6 +2942,6 @@
 	envp [i++] = action_str;
 	envp [i] = 0;
 
-	return call_usermodehelper(argv [0], argv, envp);
+	return call_usermodehelper(argv [0], argv, envp, 0);
 }
 #endif
diff -Nru a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c
--- a/net/ipv4/ip_gre.c	Mon Feb 17 14:57:28 2003
+++ b/net/ipv4/ip_gre.c	Mon Feb 17 14:57:28 2003
@@ -454,7 +454,7 @@
 			/* Impossible event. */
 			return;
 		case ICMP_FRAG_NEEDED:
-			/* And it is the only really necesary thing :-) */
+			/* And it is the only really necessary thing :-) */
 			rel_info = ntohs(skb->h.icmph->un.frag.mtu);
 			if (rel_info < grehlen+68)
 				return;
diff -Nru a/net/ipv4/ipip.c b/net/ipv4/ipip.c
--- a/net/ipv4/ipip.c	Mon Feb 17 14:57:28 2003
+++ b/net/ipv4/ipip.c	Mon Feb 17 14:57:28 2003
@@ -383,7 +383,7 @@
 			/* Impossible event. */
 			return;
 		case ICMP_FRAG_NEEDED:
-			/* And it is the only really necesary thing :-) */
+			/* And it is the only really necessary thing :-) */
 			rel_info = ntohs(skb->h.icmph->un.frag.mtu);
 			if (rel_info < hlen+68)
 				return;
diff -Nru a/net/sched/sch_cbq.c b/net/sched/sch_cbq.c
--- a/net/sched/sch_cbq.c	Mon Feb 17 14:57:26 2003
+++ b/net/sched/sch_cbq.c	Mon Feb 17 14:57:26 2003
@@ -797,7 +797,7 @@
 			   That is not all.
 			   To maintain the rate allocated to the class,
 			   we add to undertime virtual clock,
-			   necesary to complete transmitted packet.
+			   necessary to complete transmitted packet.
 			   (len/phys_bandwidth has been already passed
 			   to the moment of cbq_update)
 			 */
diff -Nru a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
--- a/net/sunrpc/clnt.c	Mon Feb 17 14:57:27 2003
+++ b/net/sunrpc/clnt.c	Mon Feb 17 14:57:27 2003
@@ -67,7 +67,6 @@
 rpc_setup_pipedir(struct rpc_clnt *clnt, char *dir_name)
 {
 	static uint32_t clntid;
-	int maxlen = sizeof(clnt->cl_pathname);
 	int error;
 
 	if (dir_name == NULL)
diff -Nru a/scripts/Makefile b/scripts/Makefile
--- a/scripts/Makefile	Mon Feb 17 14:57:27 2003
+++ b/scripts/Makefile	Mon Feb 17 14:57:27 2003
@@ -8,11 +8,26 @@
 # docproc: 	 Preprocess .tmpl file in order to generate .sgml documentation
 # conmakehash:	 Create arrays for initializing the kernel console tables
 
-host-progs    := fixdep split-include conmakehash docproc kallsyms
-build-targets := $(host-progs)
+host-progs    := fixdep split-include conmakehash docproc kallsyms modpost \
+		 mk_elfconfig
+build-targets := $(host-progs) empty.o
+
+modpost-objs  := modpost.o file2alias.o
 
 # Let clean descend into subdirs
 subdir-	:= lxdialog kconfig
 
 # fixdep is needed to compile other host programs
-$(addprefix $(obj)/,$(filter-out fixdep,$(host-progs))): $(obj)/fixdep
+$(addprefix $(obj)/,$(filter-out fixdep,$(build-targets))): $(obj)/fixdep
+
+# dependencies on generated files need to be listed explicitly
+
+$(obj)/modpost.o $(obj)/file2alias.o: $(obj)/elfconfig.h
+
+quiet_cmd_elfconfig = MKELF   $@
+      cmd_elfconfig = $(obj)/mk_elfconfig < $< > $@
+
+$(obj)/elfconfig.h: $(obj)/empty.o $(obj)/mk_elfconfig FORCE
+	$(call if_changed,elfconfig)
+
+targets += $(obj)/elfconfig.h
diff -Nru a/scripts/Makefile.build b/scripts/Makefile.build
--- a/scripts/Makefile.build	Mon Feb 17 14:57:28 2003
+++ b/scripts/Makefile.build	Mon Feb 17 14:57:28 2003
@@ -49,15 +49,12 @@
 endif
 endif
 
-ifdef CONFIG_MODVERSIONS
-modules := $(obj-m)
-touch-module = @echo $(@:.o=.ko) > .tmp_versions/$(@F:.o=.mod)
-else
-modules := $(obj-m:.o=.ko)
-endif
+# We keep a list of all modules in $(MODVERDIR)
+
+touch-module = @echo $(@:.o=.ko) > $(MODVERDIR)/$(@F:.o=.mod)
 
 __build: $(if $(KBUILD_BUILTIN),$(O_TARGET) $(L_TARGET) $(EXTRA_TARGETS)) \
-	 $(if $(KBUILD_MODULES),$(modules)) \
+	 $(if $(KBUILD_MODULES),$(obj-m)) \
 	 $(subdir-ym) $(build-targets)
 	@:
 
@@ -155,6 +152,8 @@
 quiet_cmd_cc_o_c = CC $(quiet_modtag)  $@
 cmd_cc_o_c       = $(CC) $(c_flags) -c -o $@ $<
 
+# Built-in and composite module parts
+
 %.o: %.c FORCE
 ifdef CONFIG_MODVERSIONS
 	$(call if_changed_rule,vcc_o_c)
@@ -162,13 +161,14 @@
 	$(call if_changed_dep,cc_o_c)
 endif
 
-# For modversioning, we need to special case single-part modules
-# to mark them in $(MODVERDIR)
+# Single-part modules are special since we need to mark them in $(MODVERDIR)
 
-ifdef CONFIG_MODVERSIONS
 $(single-used-m): %.o: %.c FORCE
 	$(touch-module)
+ifdef CONFIG_MODVERSIONS
 	$(call if_changed_rule,vcc_o_c)
+else
+	$(call if_changed_dep,cc_o_c)
 endif
 
 quiet_cmd_cc_lst_c = MKLST   $@
@@ -199,7 +199,8 @@
 %.o: %.S FORCE
 	$(call if_changed_dep,as_o_S)
 
-targets += $(real-objs-y) $(real-objs-m) $(EXTRA_TARGETS) $(MAKECMDGOALS)
+targets += $(real-objs-y) $(real-objs-m) $(EXTRA_TARGETS) $(MAKECMDGOALS) \
+	   $(build-targets)
 
 # Build the compiled-in targets
 # ---------------------------------------------------------------------------
@@ -266,29 +267,6 @@
 	$(call if_changed,link_multi-m)
 
 targets += $(multi-used-y) $(multi-used-m)
-
-#
-# Rule to link modules ( .o -> .ko )
-#
-
-# With CONFIG_MODVERSIONS, generation of the final .ko is handled
-# by scripts/Makefile.modver
-ifndef CONFIG_MODVERSIONS
-
-quiet_cmd_link_module = LD [M]  $@
-cmd_link_module = $(LD) $(ld_flags) $(LDFLAGS_MODULE) -o $@ $< init/vermagic.o
-
-# Don't rebuilt vermagic.o unless we actually are in the init/ dir
-ifneq ($(obj),init)
-init/vermagic.o: ;
-endif
-
-$(single-used-m:.o=.ko) $(multi-used-m:.o=.ko): %.ko: %.o init/vermagic.o FORCE
-	$(call if_changed,link_module)
-
-targets += $(single-used-m:.o=.ko) $(multi-used-m:.o=.ko)
-
-endif
 
 # Compile programs on the host
 # ===========================================================================
diff -Nru a/scripts/Makefile.modinst b/scripts/Makefile.modinst
--- a/scripts/Makefile.modinst	Mon Feb 17 14:57:27 2003
+++ b/scripts/Makefile.modinst	Mon Feb 17 14:57:27 2003
@@ -2,33 +2,38 @@
 # Installing modules
 # ==========================================================================
 
-src := $(obj)
+.PHONY: __modinst
+__modinst:
 
-.PHONY: modules_install
-modules_install:
+include scripts/Makefile.lib
 
-include .config
+#
 
-include $(obj)/Makefile
+__modules := $(shell cat /dev/null $(wildcard $(MODVERDIR)/*.mod))
+modules := $(patsubst %.o,%.ko,$(wildcard $(__modules:.ko=.o)))
 
-include scripts/Makefile.lib
+ifneq ($(filter-out $(modules),$(__modules)),)
+  $(warning *** Uh-oh, you have stale module entries. You messed with SUBDIRS, do not complain if something goes wrong.)
+endif
+
+.PHONY: $(modules)
+__modinst: $(modules)
+	@:
 
-# ==========================================================================
+# Modules built within the kernel tree
 
-quiet_cmd_modules_install = INSTALL $(obj-m:.o=.ko)
-      cmd_modules_install = mkdir -p $(MODLIB)/kernel/$(obj); \
-			    cp $(obj-m:.o=.ko) $(MODLIB)/kernel/$(obj)
+quiet_cmd_modules_install = INSTALL $@
+      cmd_modules_install = mkdir -p $(MODLIB)/kernel/$(@D); \
+			    cp $@ $(MODLIB)/kernel/$(@D)
 
-modules_install: $(subdir-ym)
-ifneq ($(obj-m:.o=.ko),)
+$(filter-out ../% /%,$(modules)):
 	$(call cmd,modules_install)
-else
-	@:
-endif
 
-# Descending
-# ---------------------------------------------------------------------------
+# Modules built outside just go into extra
+
+quiet_cmd_modules_install_extra = INSTALL $(obj-m:.o=.ko)
+      cmd_modules_install_extra = mkdir -p $(MODLIB)/extra; \
+			    	  cp $@ $(MODLIB)/extra
 
-.PHONY: $(subdir-ym)
-$(subdir-ym):
-	$(Q)$(MAKE) -rR -f scripts/Makefile.modinst obj=$@
+$(filter     ../% /%,$(modules)):
+	$(call cmd,modules_install_extra)
diff -Nru a/scripts/Makefile.modpost b/scripts/Makefile.modpost
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/scripts/Makefile.modpost	Mon Feb 17 14:57:28 2003
@@ -0,0 +1,81 @@
+# ===========================================================================
+# Module versions
+# ===========================================================================
+
+.PHONY: __modversions
+__modversions:
+
+include .config
+include scripts/Makefile.lib
+
+#
+
+__modules := $(shell cat /dev/null $(wildcard $(MODVERDIR)/*.mod))
+modules := $(patsubst %.o,%.ko,$(wildcard $(__modules:.ko=.o)))
+
+ifneq ($(filter-out $(modules),$(__modules)),)
+  $(warning *** Uh-oh, you have stale module entries. You messed with SUBDIRS,)
+  $(warning     do not complain if something goes wrong.)
+endif
+
+__modversions: $(modules)
+	@:
+
+# The final module link
+
+quiet_cmd_ld_ko_o = LD [M]  $@
+      cmd_ld_ko_o = $(LD) $(LDFLAGS) $(LDFLAGS_MODULE) -o $@ 		\
+			  $(filter-out FORCE,$^)
+
+$(modules): %.ko :%.o %.mod.o FORCE
+	$(call if_changed,ld_ko_o)
+
+targets += $(modules)
+
+# Compile version info for unresolved symbols
+
+quiet_cmd_cc_o_c = CC      $@
+      cmd_cc_o_c = $(CC) $(CFLAGS) $(CFLAGS_MODULE) -c -o $@ $<
+
+#	We have a fake dependency on compile.h to make sure that we
+#	notice if the compiler version changes under us.
+
+$(modules:.ko=.mod.o): %.mod.o: %.mod.c include/linux/compile.h FORCE
+	$(call if_changed,cc_o_c)
+
+targets += $(modules:.ko=.mod.o)
+
+# All the .mod.c files are generated using the helper "modpost"
+
+.PHONY: __modpost
+
+$(modules:.ko=.mod.c): __modpost ;
+
+# Extract all checksums for all exported symbols
+
+quiet_cmd_modpost = MODPOST
+      cmd_modpost = scripts/modpost $^
+
+__modpost: $(wildcard vmlinux) $(modules:.ko=.o)
+	$(call if_changed,modpost)
+
+targets += __modpost
+
+# Add FORCE to the prequisites of a target to force it to be always rebuilt.
+# ---------------------------------------------------------------------------
+
+.PHONY: FORCE
+
+FORCE:
+
+# Read all saved command lines and dependencies for the $(targets) we
+# may be building above, using $(if_changed{,_dep}). As an
+# optimization, we don't need to read them if the target does not
+# exist, we will rebuild anyway in that case.
+
+targets := $(wildcard $(sort $(targets)))
+cmd_files := $(wildcard $(foreach f,$(targets),$(dir $(f)).$(notdir $(f)).cmd))
+
+ifneq ($(cmd_files),)
+  include $(cmd_files)
+endif
diff -Nru a/scripts/Makefile.modver b/scripts/Makefile.modver
--- a/scripts/Makefile.modver	Mon Feb 17 14:57:27 2003
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,105 +0,0 @@
-# ===========================================================================
-# Module versions
-# ===========================================================================
-
-.PHONY: __modversions
-__modversions:
-
-include scripts/Makefile.lib
-
-#
-
-__modules := $(shell cat /dev/null $(wildcard $(MODVERDIR)/*.mod))
-modules := $(patsubst %.o,%.ko,$(wildcard $(__modules:.ko=.o)))
-
-ifneq ($(filter-out $(modules),$(__modules)),)
-  $(warning *** Uh-oh, you have stale module entries. You messed with SUBDIRS,)
-  $(warning     do not complain if something goes wrong.)
-endif
-
-__modversions: $(modules)
-	@:
-
-# The final module link
-
-quiet_cmd_ld_ko_o = LD [M]  $@
-      cmd_ld_ko_o = $(LD) $(LDFLAGS) $(LDFLAGS_MODULE) -o $@ 		\
-			  $(filter-out FORCE,$^)
-
-init/vermagic.o: ;
-
-$(modules): %.ko :%.o %.ver.o init/vermagic.o FORCE
-	$(call if_changed,ld_ko_o)
-
-targets += $(modules)
-
-# Compile version info for unresolved symbols
-
-quiet_cmd_cc_o_c = CC      $@
-      cmd_cc_o_c = $(CC) $(CFLAGS) -c -o $@ $<
-
-$(modules:.ko=.ver.o): %.ver.o: %.ver.c FORCE
-	$(call if_changed,cc_o_c)
-
-targets += $(modules:.ko=.ver.o)
-
-# Generate C source with version info for unresolved symbols
-
-define rule_mkver_o_c
-	echo '  MKVER   $@';						\
-	( echo "#include <linux/module.h>";				\
-	  echo "";							\
-	  echo "static const struct modversion_info ____versions[]";	\
-	  echo "__attribute__((section(\"__versions\"))) = {"; 	\
-	  for sym in `nm -u $<`; do					\
-		grep "\"$$sym\"" .tmp_all-versions			\
-		|| echo "*** Warning: $(<:.o=.ko): \"$$sym\" unresolved!" >&2;\
-	  done;								\
-	  echo "};";							\
-	) > $@
-endef
-
-$(modules:.ko=.ver.c): %.ver.c: %.o .tmp_all-versions FORCE
-	$(call if_changed_rule,mkver_o_c)
-
-targets += $(modules:.ko=.ver.c))
-
-# Extract all checksums for all exported symbols
-
-export-objs := $(shell for m in vmlinux $(modules:.ko=.o); do objdump -h $$m | grep -q __ksymtab && echo $$m; done)
-
-cmd_gen-all-versions = mksyms $(export-objs)
-define rule_gen-all-versions
-	echo '  MKSYMS  $@';						\
-	for mod in $(export-objs); do					\
-		modname=`basename $$mod`;				\
-		nm $$mod 						\
-		| grep ' __crc_'					\
-		| sed "s/\([^ ]*\) A __crc_\(.*\)/{ 0x\1, \"\2\" }, \/* $$modname *\//g;s/.* w __crc_\(.*\)/{ 0x0       , \"\1\" }, \/* $$modname *\//g"; \
-	done > $@;							\
-	echo 'cmd_$@ := $(cmd_$(1))' > $(@D)/.$(@F).cmd
-endef
-
-.tmp_all-versions: $(export-objs) FORCE
-	$(call if_changed_rule,gen-all-versions)
-
-targets += .tmp_all-versions
-
-# Add FORCE to the prequisites of a target to force it to be always rebuilt.
-# ---------------------------------------------------------------------------
-
-.PHONY: FORCE
-
-FORCE:
-
-# Read all saved command lines and dependencies for the $(targets) we
-# may be building above, using $(if_changed{,_dep}). As an
-# optimization, we don't need to read them if the target does not
-# exist, we will rebuild anyway in that case.
-
-targets := $(wildcard $(sort $(targets)))
-cmd_files := $(wildcard $(foreach f,$(targets),$(dir $(f)).$(notdir $(f)).cmd))
-
-ifneq ($(cmd_files),)
-  include $(cmd_files)
-endif
diff -Nru a/scripts/empty.c b/scripts/empty.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/scripts/empty.c	Mon Feb 17 14:57:28 2003
@@ -0,0 +1 @@
+/* empty file to figure out endianness / word size */
diff -Nru a/scripts/file2alias.c b/scripts/file2alias.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/scripts/file2alias.c	Mon Feb 17 14:57:28 2003
@@ -0,0 +1,178 @@
+/* Simple code to turn various tables in an ELF file into alias definitions.
+ * This deals with kernel datastructures where they should be
+ * dealt with: in the kernel source.
+ *
+ * Copyright 2002-2003  Rusty Russell, IBM Corporation
+ *           2003       Kai Germaschewski
+ *           
+ *
+ * This software may be used and distributed according to the terms
+ * of the GNU General Public License, incorporated herein by reference.
+ */
+
+#include "modpost.h"
+
+/* We use the ELF typedefs, since we can't rely on stdint.h being present. */
+
+#if KERNEL_ELFCLASS == ELFCLASS32
+typedef Elf32_Addr     kernel_ulong_t;
+#else
+typedef Elf64_Addr     kernel_ulong_t;
+#endif
+
+typedef Elf32_Word     __u32;
+typedef Elf32_Half     __u16;
+typedef unsigned char  __u8;
+
+/* Big exception to the "don't include kernel headers into userspace, which
+ * even potentially has different endianness and word sizes, since 
+ * we handle those differences explicitly below */
+#include "../include/linux/mod_devicetable.h"
+
+#define ADD(str, sep, cond, field)                              \
+do {                                                            \
+        strcat(str, sep);                                       \
+        if (cond)                                               \
+                sprintf(str + strlen(str),                      \
+                        sizeof(field) == 1 ? "%02X" :           \
+                        sizeof(field) == 2 ? "%04X" :           \
+                        sizeof(field) == 4 ? "%08X" : "",       \
+                        field);                                 \
+        else                                                    \
+                sprintf(str + strlen(str), "*");                \
+} while(0)
+
+/* Looks like "usb:vNpNdlNdhNdcNdscNdpNicNiscNipN" */
+static int do_usb_entry(const char *filename,
+			struct usb_device_id *id, char *alias)
+{
+	id->match_flags = TO_NATIVE(id->match_flags);
+	id->idVendor = TO_NATIVE(id->idVendor);
+	id->idProduct = TO_NATIVE(id->idProduct);
+	id->bcdDevice_lo = TO_NATIVE(id->bcdDevice_lo);
+	id->bcdDevice_hi = TO_NATIVE(id->bcdDevice_hi);
+
+	strcpy(alias, "usb:");
+	ADD(alias, "v", id->match_flags&USB_DEVICE_ID_MATCH_VENDOR,
+	    id->idVendor);
+	ADD(alias, "p", id->match_flags&USB_DEVICE_ID_MATCH_PRODUCT,
+	    id->idProduct);
+	ADD(alias, "dl", id->match_flags&USB_DEVICE_ID_MATCH_DEV_LO,
+	    id->bcdDevice_lo);
+	ADD(alias, "dh", id->match_flags&USB_DEVICE_ID_MATCH_DEV_HI,
+	    id->bcdDevice_hi);
+	ADD(alias, "dc", id->match_flags&USB_DEVICE_ID_MATCH_DEV_CLASS,
+	    id->bDeviceClass);
+	ADD(alias, "dsc",
+	    id->match_flags&USB_DEVICE_ID_MATCH_DEV_SUBCLASS,
+	    id->bDeviceSubClass);
+	ADD(alias, "dp",
+	    id->match_flags&USB_DEVICE_ID_MATCH_DEV_PROTOCOL,
+	    id->bDeviceProtocol);
+	ADD(alias, "ic",
+	    id->match_flags&USB_DEVICE_ID_MATCH_INT_CLASS,
+	    id->bInterfaceClass);
+	ADD(alias, "isc",
+	    id->match_flags&USB_DEVICE_ID_MATCH_INT_SUBCLASS,
+	    id->bInterfaceSubClass);
+	ADD(alias, "ip",
+	    id->match_flags&USB_DEVICE_ID_MATCH_INT_PROTOCOL,
+	    id->bInterfaceProtocol);
+	return 1;
+}
+
+/* Looks like: pci:vNdNsvNsdNcN. */
+static int do_pci_entry(const char *filename,
+			struct pci_device_id *id, char *alias)
+{
+	id->vendor = TO_NATIVE(id->vendor);
+	id->device = TO_NATIVE(id->device);
+	id->subvendor = TO_NATIVE(id->subvendor);
+	id->subdevice = TO_NATIVE(id->subdevice);
+	id->class = TO_NATIVE(id->class);
+	id->class_mask = TO_NATIVE(id->class_mask);
+
+	strcpy(alias, "pci:");
+	ADD(alias, "v", id->vendor != PCI_ANY_ID, id->vendor);
+	ADD(alias, "d", id->device != PCI_ANY_ID, id->device);
+	ADD(alias, "sv", id->subvendor != PCI_ANY_ID, id->subvendor);
+	ADD(alias, "sd", id->subdevice != PCI_ANY_ID, id->subdevice);
+	if (id->class_mask != 0 && id->class_mask != ~0) {
+		fprintf(stderr,
+			"*** Warning: Can't handle class_mask in %s:%04X\n",
+			filename, id->class_mask);
+		return 0;
+	}
+	ADD(alias, "c", id->class_mask == ~0, id->class);
+	return 1;
+}
+
+/* Ignore any prefix, eg. v850 prepends _ */
+static inline int sym_is(const char *symbol, const char *name)
+{
+	const char *match;
+
+	match = strstr(symbol, name);
+	if (!match)
+		return 0;
+	return match[strlen(symbol)] == '\0';
+}
+
+static void do_table(void *symval, unsigned long size,
+		     unsigned long id_size,
+		     void *function,
+		     struct module *mod)
+{
+	unsigned int i;
+	char alias[500];
+	int (*do_entry)(const char *, void *entry, char *alias) = function;
+
+	if (size % id_size || size < id_size) {
+		fprintf(stderr, "*** Warning: %s ids %lu bad size "
+			"(each on %lu)\n", mod->name, size, id_size);
+	}
+	/* Leave last one: it's the terminator. */
+	size -= id_size;
+
+	for (i = 0; i < size; i += id_size) {
+		if (do_entry(mod->name, symval+i, alias)) {
+			/* Always end in a wildcard, for future extension */
+			if (alias[strlen(alias)-1] != '*')
+				strcat(alias, "*");
+			buf_printf(&mod->dev_table_buf,
+				   "MODULE_ALIAS(\"%s\");\n", alias);
+		}
+	}
+}
+
+/* Create MODULE_ALIAS() statements.
+ * At this time, we cannot write the actual output C source yet,
+ * so we write into the mod->dev_table_buf buffer. */
+void handle_moddevtable(struct module *mod, struct elf_info *info,
+			Elf_Sym *sym, const char *symname)
+{
+	void *symval;
+
+	/* We're looking for a section relative symbol */
+	if (!sym->st_shndx || sym->st_shndx >= info->hdr->e_shnum)
+		return;
+
+	symval = (void *)info->hdr
+		+ info->sechdrs[sym->st_shndx].sh_offset
+		+ sym->st_value;
+
+	if (sym_is(symname, "__mod_pci_device_table"))
+		do_table(symval, sym->st_size, sizeof(struct pci_device_id),
+			 do_pci_entry, mod);
+	else if (sym_is(symname, "__mod_usb_device_table"))
+		do_table(symval, sym->st_size, sizeof(struct usb_device_id),
+			 do_usb_entry, mod);
+}
+
+/* Now add out buffered information to the generated C source */
+void add_moddevtable(struct buffer *buf, struct module *mod)
+{
+	buf_printf(buf, "\n");
+	buf_write(buf, mod->dev_table_buf.p, mod->dev_table_buf.pos);
+	free(mod->dev_table_buf.p);
+}
diff -Nru a/scripts/mk_elfconfig.c b/scripts/mk_elfconfig.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/scripts/mk_elfconfig.c	Mon Feb 17 14:57:28 2003
@@ -0,0 +1,57 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <elf.h>
+
+int
+main(int argc, char **argv)
+{
+	unsigned char ei[EI_NIDENT];	
+	union { short s; char c[2]; } endian_test;
+
+	if (fread(ei, 1, EI_NIDENT, stdin) != EI_NIDENT) {
+		fprintf(stderr, "Error: input truncated\n");
+		return 1;
+	}
+	if (memcmp(ei, ELFMAG, SELFMAG) != 0) {
+		fprintf(stderr, "Error: not ELF\n");
+		return 1;
+	}
+	switch (ei[EI_CLASS]) {
+	case ELFCLASS32:
+		printf("#define KERNEL_ELFCLASS ELFCLASS32\n");
+		break;
+	case ELFCLASS64:
+		printf("#define KERNEL_ELFCLASS ELFCLASS64\n");
+		break;
+	default:
+		abort();
+	}
+	switch (ei[EI_DATA]) {
+	case ELFDATA2LSB:
+		printf("#define KERNEL_ELFDATA ELFDATA2LSB\n");
+		break;
+	case ELFDATA2MSB:
+		printf("#define KERNEL_ELFDATA ELFDATA2MSB\n");
+		break;
+	default:
+		abort();
+	}
+
+	if (sizeof(unsigned long) == 4) {
+		printf("#define HOST_ELFCLASS ELFCLASS32\n");
+	} else if (sizeof(unsigned long) == 8) {
+		printf("#define HOST_ELFCLASS ELFCLASS64\n");
+	}
+
+	endian_test.s = 0x0102;
+	if (memcmp(endian_test.c, "\x01\x02", 2) == 0)
+		printf("#define HOST_ELFDATA ELFDATA2MSB\n");
+	else if (memcmp(endian_test.c, "\x02\x01", 2) == 0)
+		printf("#define HOST_ELFDATA ELFDATA2LSB\n");
+	else
+		abort();
+
+	return 0;
+}
+
diff -Nru a/scripts/modpost.c b/scripts/modpost.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/scripts/modpost.c	Mon Feb 17 14:57:28 2003
@@ -0,0 +1,541 @@
+/* Postprocess module symbol versions
+ *
+ * Copyright 2003       Kai Germaschewski
+ *           2002-2003  Rusty Russell, IBM Corporation
+ *
+ * Based in part on module-init-tools/depmod.c,file2alias
+ *
+ * This software may be used and distributed according to the terms
+ * of the GNU General Public License, incorporated herein by reference.
+ *
+ * Usage: modpost vmlinux module1.o module2.o ...
+ */
+
+#include "modpost.h"
+
+/* Are we using CONFIG_MODVERSIONS? */
+int modversions = 0;
+/* Do we have vmlinux? */
+int have_vmlinux = 0;
+
+void
+fatal(const char *fmt, ...)
+{
+	va_list arglist;
+
+	fprintf(stderr, "FATAL: ");
+
+	va_start(arglist, fmt);
+	vfprintf(stderr, fmt, arglist);
+	va_end(arglist);
+
+	exit(1);
+}
+
+void
+warn(const char *fmt, ...)
+{
+	va_list arglist;
+
+	fprintf(stderr, "WARNING: ");
+
+	va_start(arglist, fmt);
+	vfprintf(stderr, fmt, arglist);
+	va_end(arglist);
+}
+
+#define NOFAIL(ptr)	do_nofail((ptr), __FILE__, __LINE__, #ptr)
+
+void *do_nofail(void *ptr, const char *file, int line, const char *expr)
+{
+	if (!ptr) {
+		fatal("Memory allocation failure %s line %d: %s.\n",
+		      file, line, expr);
+	}
+	return ptr;
+}
+
+/* A list of all modules we processed */
+
+static struct module *modules;
+
+struct module *
+new_module(char *modname)
+{
+	struct module *mod;
+	char *p;
+	
+	/* strip trailing .o */
+	p = strstr(modname, ".o");
+	if (p)
+		*p = 0;
+
+	mod = NOFAIL(malloc(sizeof(*mod)));
+	memset(mod, 0, sizeof(*mod));
+	mod->name = modname;
+
+	/* add to list */
+	mod->next = modules;
+	modules = mod;
+
+	return mod;
+}
+
+/* A hash of all exported symbols,
+ * struct symbol is also used for lists of unresolved symbols */
+
+#define SYMBOL_HASH_SIZE 1024
+
+struct symbol {
+	struct symbol *next;
+	struct module *module;
+	unsigned int crc;
+	int crc_valid;
+	char name[0];
+};
+
+static struct symbol *symbolhash[SYMBOL_HASH_SIZE];
+
+/* This is based on the hash agorithm from gdbm, via tdb */
+static inline unsigned int tdb_hash(const char *name)
+{
+	unsigned value;	/* Used to compute the hash value.  */
+	unsigned   i;	/* Used to cycle through random values. */
+
+	/* Set the initial value from the key size. */
+	for (value = 0x238F13AF * strlen(name), i=0; name[i]; i++)
+		value = (value + (((unsigned char *)name)[i] << (i*5 % 24)));
+
+	return (1103515243 * value + 12345);
+}
+
+/* Allocate a new symbols for use in the hash of exported symbols or
+ * the list of unresolved symbols per module */
+
+struct symbol *
+alloc_symbol(const char *name)
+{
+	struct symbol *s = NOFAIL(malloc(sizeof(*s) + strlen(name) + 1));
+
+	memset(s, 0, sizeof(*s));
+	strcpy(s->name, name);
+	return s;
+}
+
+/* For the hash of exported symbols */
+
+void
+new_symbol(const char *name, struct module *module, unsigned int *crc)
+{
+	unsigned int hash;
+	struct symbol *new = alloc_symbol(name);
+
+	new->module = module;
+	if (crc) {
+		new->crc = *crc;
+		new->crc_valid = 1;
+	}
+
+	hash = tdb_hash(name) % SYMBOL_HASH_SIZE;
+	new->next = symbolhash[hash];
+	symbolhash[hash] = new;
+}
+
+struct symbol *
+find_symbol(const char *name)
+{
+	struct symbol *s;
+
+	/* For our purposes, .foo matches foo.  PPC64 needs this. */
+	if (name[0] == '.')
+		name++;
+
+	for (s = symbolhash[tdb_hash(name) % SYMBOL_HASH_SIZE]; s; s=s->next) {
+		if (strcmp(s->name, name) == 0)
+			return s;
+	}
+	return NULL;
+}
+
+/* Add an exported symbol - it may have already been added without a
+ * CRC, in this case just update the CRC */
+void
+add_exported_symbol(const char *name, struct module *module, unsigned int *crc)
+{
+	struct symbol *s = find_symbol(name);
+
+	if (!s) {
+		new_symbol(name, modules, crc);
+		return;
+	}
+	if (crc) {
+		s->crc = *crc;
+		s->crc_valid = 1;
+	}
+}
+
+void *
+grab_file(const char *filename, unsigned long *size)
+{
+	struct stat st;
+	void *map;
+	int fd;
+
+	fd = open(filename, O_RDONLY);
+	if (fd < 0) {
+		perror(filename);
+		abort();
+	}
+	if (fstat(fd, &st) != 0) {
+		perror(filename);
+		abort();
+	}
+
+	*size = st.st_size;
+	map = mmap(NULL, *size, PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0);
+	if (mmap == MAP_FAILED) {
+		perror(filename);
+		abort();
+	}
+	close(fd);
+	return map;
+}
+
+void
+parse_elf(struct elf_info *info, const char *filename)
+{
+	unsigned int i;
+	Elf_Ehdr *hdr = info->hdr;
+	Elf_Shdr *sechdrs;
+	Elf_Sym  *sym;
+
+	hdr = grab_file(filename, &info->size);
+	info->hdr = hdr;
+	if (info->size < sizeof(*hdr))
+		goto truncated;
+
+	/* Fix endianness in ELF header */
+	hdr->e_shoff    = TO_NATIVE(hdr->e_shoff);
+	hdr->e_shstrndx = TO_NATIVE(hdr->e_shstrndx);
+	hdr->e_shnum    = TO_NATIVE(hdr->e_shnum);
+	sechdrs = (void *)hdr + hdr->e_shoff;
+	info->sechdrs = sechdrs;
+
+	/* Fix endianness in section headers */
+	for (i = 0; i < hdr->e_shnum; i++) {
+		sechdrs[i].sh_type   = TO_NATIVE(sechdrs[i].sh_type);
+		sechdrs[i].sh_offset = TO_NATIVE(sechdrs[i].sh_offset);
+		sechdrs[i].sh_size   = TO_NATIVE(sechdrs[i].sh_size);
+		sechdrs[i].sh_link   = TO_NATIVE(sechdrs[i].sh_link);
+	}
+	/* Find symbol table. */
+	for (i = 1; i < hdr->e_shnum; i++) {
+		if (sechdrs[i].sh_offset > info->size)
+			goto truncated;
+		if (sechdrs[i].sh_type != SHT_SYMTAB)
+			continue;
+
+		info->symtab_start = (void *)hdr + sechdrs[i].sh_offset;
+		info->symtab_stop  = (void *)hdr + sechdrs[i].sh_offset 
+			                         + sechdrs[i].sh_size;
+		info->strtab       = (void *)hdr + 
+			             sechdrs[sechdrs[i].sh_link].sh_offset;
+	}
+	if (!info->symtab_start) {
+		fprintf(stderr, "modpost: %s no symtab?\n", filename);
+		abort();
+	}
+	/* Fix endianness in symbols */
+	for (sym = info->symtab_start; sym < info->symtab_stop; sym++) {
+		sym->st_shndx = TO_NATIVE(sym->st_shndx);
+		sym->st_name  = TO_NATIVE(sym->st_name);
+		sym->st_value = TO_NATIVE(sym->st_value);
+		sym->st_size  = TO_NATIVE(sym->st_size);
+	}
+	return;
+
+ truncated:
+	fprintf(stderr, "modpost: %s is truncated.\n", filename);
+	abort();
+}
+
+void
+parse_elf_finish(struct elf_info *info)
+{
+	munmap(info->hdr, info->size);
+}
+
+void
+handle_modversions(struct module *mod, struct elf_info *info,
+		   Elf_Sym *sym, const char *symname)
+{
+	struct symbol *s;
+	unsigned int crc;
+
+	switch (sym->st_shndx) {
+	case SHN_COMMON:
+		fprintf(stderr, "*** Warning: \"%s\" [%s] is COMMON symbol\n",
+			symname, mod->name);
+		break;
+	case SHN_ABS:
+		/* CRC'd symbol */
+		if (memcmp(symname, "__crc_", 6) == 0) {
+			crc = (unsigned int) sym->st_value;
+			add_exported_symbol(symname+6, mod, &crc);
+			modversions = 1;
+		}
+		break;
+	case SHN_UNDEF:
+		/* undefined symbol */
+		if (ELF_ST_BIND(sym->st_info) != STB_GLOBAL)
+			break;
+		
+		s = alloc_symbol(symname);
+		/* add to list */
+		s->next = mod->unres;
+		mod->unres = s;
+		break;
+	default:
+		/* All exported symbols */
+		if (memcmp(symname, "__ksymtab_", 10) == 0) {
+			add_exported_symbol(symname+10, mod, NULL);
+		}
+		break;
+	}
+}
+
+void
+read_symbols(char *modname)
+{
+	const char *symname;
+	struct module *mod;
+	struct elf_info info = { };
+	struct symbol *s;
+	Elf_Sym *sym;
+
+	/* When there's no vmlinux, don't print warnings about
+	 * unresolved symbols (since there'll be too many ;) */
+	if (strcmp(modname, "vmlinux") == 0)
+		have_vmlinux = 1;
+
+	parse_elf(&info, modname);
+
+	mod = new_module(modname);
+
+	for (sym = info.symtab_start; sym < info.symtab_stop; sym++) {
+		symname = info.strtab + sym->st_name;
+
+		handle_modversions(mod, &info, sym, symname);
+		handle_moddevtable(mod, &info, sym, symname);
+	}
+	parse_elf_finish(&info);
+
+	/* Our trick to get versioning for struct_module - it's
+	 * never passed as an argument to an exported function, so
+	 * the automatic versioning doesn't pick it up, but it's really
+	 * important anyhow */
+	if (modversions) {
+		s = alloc_symbol("struct_module");
+		/* add to list */
+		s->next = mod->unres;
+		mod->unres = s;
+	}
+}
+
+#define SZ 500
+
+/* We first write the generated file into memory using the
+ * following helper, then compare to the file on disk and
+ * only update the later if anything changed */
+
+void __attribute__((format(printf, 2, 3)))
+buf_printf(struct buffer *buf, const char *fmt, ...)
+{
+	char tmp[SZ];
+	int len;
+	va_list ap;
+	
+	va_start(ap, fmt);
+	len = vsnprintf(tmp, SZ, fmt, ap);
+	if (buf->size - buf->pos < len + 1) {
+		buf->size += 128;
+		buf->p = realloc(buf->p, buf->size);
+	}
+	strncpy(buf->p + buf->pos, tmp, len + 1);
+	buf->pos += len;
+	va_end(ap);
+}
+
+void
+buf_write(struct buffer *buf, const char *s, int len)
+{
+	if (buf->size - buf->pos < len) {
+		buf->size += len;
+		buf->p = realloc(buf->p, buf->size);
+	}
+	strncpy(buf->p + buf->pos, s, len);
+	buf->pos += len;
+}
+
+/* Header for the generated file */
+
+void
+add_header(struct buffer *b)
+{
+	buf_printf(b, "#include <linux/module.h>\n");
+	buf_printf(b, "#include <linux/vermagic.h>\n");
+	buf_printf(b, "\n");
+	buf_printf(b, "const char vermagic[]\n");
+	buf_printf(b, "__attribute__((section(\"__vermagic\"))) =\n");
+	buf_printf(b, "VERMAGIC_STRING;\n");
+}
+
+/* Record CRCs for unresolved symbols */
+
+void
+add_versions(struct buffer *b, struct module *mod)
+{
+	struct symbol *s, *exp;
+
+	for (s = mod->unres; s; s = s->next) {
+		exp = find_symbol(s->name);
+		if (!exp || exp->module == mod) {
+			if (have_vmlinux)
+				fprintf(stderr, "*** Warning: \"%s\" [%s.ko] "
+				"undefined!\n",	s->name, mod->name);
+			continue;
+		}
+		s->module = exp->module;
+		s->crc_valid = exp->crc_valid;
+		s->crc = exp->crc;
+	}
+
+	if (!modversions)
+		return;
+
+	buf_printf(b, "\n");
+	buf_printf(b, "static const struct modversion_info ____versions[]\n");
+	buf_printf(b, "__attribute__((section(\"__versions\"))) = {\n");
+
+	for (s = mod->unres; s; s = s->next) {
+		if (!s->module) {
+			continue;
+		}
+		if (!s->crc_valid) {
+			fprintf(stderr, "*** Warning: \"%s\" [%s.ko] "
+				"has no CRC!\n",
+				s->name, mod->name);
+			continue;
+		}
+		buf_printf(b, "\t{ %#8x, \"%s\" },\n", s->crc, s->name);
+	}
+
+	buf_printf(b, "};\n");
+}
+
+void
+add_depends(struct buffer *b, struct module *mod, struct module *modules)
+{
+	struct symbol *s;
+	struct module *m;
+	int first = 1;
+
+	for (m = modules; m; m = m->next) {
+		if (strcmp(m->name, "vmlinux") == 0)
+			m->seen = 1;
+		else 
+			m->seen = 0;
+	}
+
+	buf_printf(b, "\n");
+	buf_printf(b, "static const char __module_depends[]\n");
+	buf_printf(b, "__attribute__((section(\".modinfo\"))) =\n");
+	buf_printf(b, "\"depends=");
+	for (s = mod->unres; s; s = s->next) {
+		if (!s->module)
+			continue;
+
+		if (s->module->seen)
+			continue;
+
+		s->module->seen = 1;
+		buf_printf(b, "%s%s", first ? "" : ",",
+			   strrchr(s->module->name, '/') + 1);
+		first = 0;
+	}
+	buf_printf(b, "\";\n");
+}
+
+void
+write_if_changed(struct buffer *b, const char *fname)
+{
+	char *tmp;
+	FILE *file;
+	struct stat st;
+
+	file = fopen(fname, "r");
+	if (!file)
+		goto write;
+
+	if (fstat(fileno(file), &st) < 0)
+		goto close_write;
+
+	if (st.st_size != b->pos)
+		goto close_write;
+
+	tmp = NOFAIL(malloc(b->pos));
+	if (fread(tmp, 1, b->pos, file) != b->pos)
+		goto free_write;
+
+	if (memcmp(tmp, b->p, b->pos) != 0)
+		goto free_write;
+
+	free(tmp);
+	fclose(file);
+	return;
+
+ free_write:
+	free(tmp);
+ close_write:
+	fclose(file);
+ write:
+	file = fopen(fname, "w");
+	if (!file) {
+		perror(fname);
+		exit(1);
+	}
+	if (fwrite(b->p, 1, b->pos, file) != b->pos) {
+		perror(fname);
+		exit(1);
+	}
+	fclose(file);
+}
+
+int
+main(int argc, char **argv)
+{
+	struct module *mod;
+	struct buffer buf = { };
+	char fname[SZ];
+
+	for (; argv[1]; argv++) {
+		read_symbols(argv[1]);
+	}
+
+	for (mod = modules; mod; mod = mod->next) {
+		if (strcmp(mod->name, "vmlinux") == 0)
+			continue;
+
+		buf.pos = 0;
+
+		add_header(&buf);
+		add_versions(&buf, mod);
+		add_depends(&buf, mod, modules);
+		add_moddevtable(&buf, mod);
+
+		sprintf(fname, "%s.mod.c", mod->name);
+		write_if_changed(&buf, fname);
+	}
+	return 0;
+}
+
diff -Nru a/scripts/modpost.h b/scripts/modpost.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/scripts/modpost.h	Mon Feb 17 14:57:28 2003
@@ -0,0 +1,86 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <elf.h>
+
+#include "elfconfig.h"
+
+#if KERNEL_ELFCLASS == ELFCLASS32
+
+#define Elf_Ehdr    Elf32_Ehdr 
+#define Elf_Shdr    Elf32_Shdr 
+#define Elf_Sym     Elf32_Sym
+#define ELF_ST_BIND ELF32_ST_BIND
+
+#else
+
+#define Elf_Ehdr    Elf64_Ehdr 
+#define Elf_Shdr    Elf64_Shdr 
+#define Elf_Sym     Elf64_Sym
+#define ELF_ST_BIND ELF64_ST_BIND
+
+#endif
+
+#if KERNEL_ELFDATA != HOST_ELFDATA
+
+static void __endian(const void *src, void *dest, unsigned int size)
+{
+	unsigned int i;
+	for (i = 0; i < size; i++)
+		((unsigned char*)dest)[i] = ((unsigned char*)src)[size - i-1];
+}
+
+
+
+#define TO_NATIVE(x)						\
+({								\
+	typeof(x) __x;						\
+	__endian(&(x), &(__x), sizeof(__x));			\
+	__x;							\
+})
+
+#else /* endianness matches */
+
+#define TO_NATIVE(x) (x)
+
+#endif
+
+struct buffer {
+	char *p;
+	int pos;
+	int size;
+};
+
+void __attribute__((format(printf, 2, 3)))
+buf_printf(struct buffer *buf, const char *fmt, ...);
+
+void
+buf_write(struct buffer *buf, const char *s, int len);
+
+struct module {
+	struct module *next;
+	const char *name;
+	struct symbol *unres;
+	int seen;
+	struct buffer dev_table_buf;
+};
+
+struct elf_info {
+	unsigned long size;
+	Elf_Ehdr     *hdr;
+	Elf_Shdr     *sechdrs;
+	Elf_Sym      *symtab_start;
+	Elf_Sym      *symtab_stop;
+	const char   *strtab;
+};
+
+void handle_moddevtable(struct module *mod, struct elf_info *info,
+			Elf_Sym *sym, const char *symname);
+
+void add_moddevtable(struct buffer *buf, struct module *mod);
diff -Nru a/security/capability.c b/security/capability.c
--- a/security/capability.c	Mon Feb 17 14:57:27 2003
+++ b/security/capability.c	Mon Feb 17 14:57:27 2003
@@ -18,6 +18,7 @@
 #include <linux/smp_lock.h>
 #include <linux/skbuff.h>
 #include <linux/netlink.h>
+#include <linux/ptrace.h>
 
 int cap_capable (struct task_struct *tsk, int cap)
 {
diff -Nru a/sound/arm/sa11xx-uda1341.c b/sound/arm/sa11xx-uda1341.c
--- a/sound/arm/sa11xx-uda1341.c	Mon Feb 17 14:57:26 2003
+++ b/sound/arm/sa11xx-uda1341.c	Mon Feb 17 14:57:26 2003
@@ -7,7 +7,7 @@
  * 
  * History:
  *
- * 2002-03-13	Tomas Kasparek	Initial release - based on h3600-uda1341.c from OSS
+ * 2002-03-13   Tomas Kasparek  initial release - based on h3600-uda1341.c from OSS
  * 2002-03-20   Tomas Kasparek  playback over ALSA is working
  * 2002-03-28   Tomas Kasparek  playback over OSS emulation is working
  * 2002-03-29   Tomas Kasparek  basic capture is working (native ALSA)
@@ -15,7 +15,7 @@
  * 2002-04-04   Tomas Kasparek  better rates handling (allow non-standard rates)
  */
 
-/* $Id: sa11xx-uda1341.c,v 1.6 2002/12/04 18:52:05 perex Exp $ */
+/* $Id: sa11xx-uda1341.c,v 1.7 2003/02/13 19:19:18 perex Exp $ */
 
 #include <sound/driver.h>
 #include <linux/module.h>
@@ -444,7 +444,7 @@
 		DEBUG(KERN_DEBUG "----> period done <----\n");
 #ifdef DEBUG_MODE
 		printk(KERN_DEBUG "  dma_area:");
-		buf = s->stream->runtime->dma_addr +
+		buf = (char *)s->stream->runtime->dma_addr +
 			((s->sent_periods - 1 ) *
 			 (s->stream->runtime->period_size << SHIFT_16_STEREO));
 		for (i=0; i < 32; i++) {
diff -Nru a/sound/core/hwdep.c b/sound/core/hwdep.c
--- a/sound/core/hwdep.c	Mon Feb 17 14:57:26 2003
+++ b/sound/core/hwdep.c	Mon Feb 17 14:57:26 2003
@@ -334,7 +334,7 @@
 	if ((err = snd_register_device(SNDRV_DEVICE_TYPE_HWDEP,
 				       hwdep->card, hwdep->device,
 				       &snd_hwdep_reg, name)) < 0) {
-		snd_printk(KERN_ERR "unable to register hardware dependant device %i:%i\n",
+		snd_printk(KERN_ERR "unable to register hardware dependent device %i:%i\n",
 			   hwdep->card->number, hwdep->device);
 		snd_hwdep_devices[idx] = NULL;
 		up(&register_mutex);
diff -Nru a/sound/core/isadma.c b/sound/core/isadma.c
--- a/sound/core/isadma.c	Mon Feb 17 14:57:28 2003
+++ b/sound/core/isadma.c	Mon Feb 17 14:57:28 2003
@@ -96,5 +96,5 @@
 	if (result > size)
 		snd_printk(KERN_ERR "pointer (0x%x) for DMA #%ld is greater than transfer size (0x%x)\n", result, dma, size);
 #endif
-	return result >= size ? 0 : result;
+	return result >= size ? 0 : size - result;
 }
diff -Nru a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c
--- a/sound/core/oss/pcm_oss.c	Mon Feb 17 14:57:28 2003
+++ b/sound/core/oss/pcm_oss.c	Mon Feb 17 14:57:28 2003
@@ -256,7 +256,7 @@
 {
 	snd_interval_t *it;
 	snd_pcm_hw_params_t *save;
-	unsigned int rate;
+	unsigned int rate, prev;
 
 	save = kmalloc(sizeof(*save), GFP_KERNEL);
 	if (save == NULL)
@@ -280,7 +280,10 @@
 			}
 			*params = *save;
 		}
+		prev = rate;
 		rate += best_rate;
+		if (rate <= prev)
+			break;
 	}
 
 	/* not found, use the nearest rate */
diff -Nru a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c
--- a/sound/core/pcm_lib.c	Mon Feb 17 14:57:27 2003
+++ b/sound/core/pcm_lib.c	Mon Feb 17 14:57:27 2003
@@ -30,35 +30,67 @@
 #include <sound/pcm_params.h>
 #include <sound/timer.h>
 
-void snd_pcm_playback_silence(snd_pcm_substream_t *substream)
+/*
+ * fill ring buffer with silence
+ * runtime->silenced_start: starting pointer to silence area
+ * runtime->silenced_size: size filled with silence
+ * runtime->silence_threshold: threshold from application
+ * runtime->silence_size: maximal size from application
+ *
+ * when runtime->silence_size >= runtime->boundary - fill processed area with silence immediately
+ */
+void snd_pcm_playback_silence(snd_pcm_substream_t *substream, snd_pcm_uframes_t new_hw_ptr)
 {
 	snd_pcm_runtime_t *runtime = substream->runtime;
 	snd_pcm_uframes_t frames, ofs, transfer;
-	snd_pcm_sframes_t noise_dist;
-	if (runtime->silenced_start != runtime->control->appl_ptr) {
-		snd_pcm_sframes_t n = runtime->control->appl_ptr - runtime->silenced_start;
-		if (n < 0)
-			n += runtime->boundary;
-		if ((snd_pcm_uframes_t)n < runtime->silenced_size)
-			runtime->silenced_size -= n;
-		else
+
+	if (runtime->silence_size < runtime->boundary) {
+		snd_pcm_sframes_t noise_dist, n;
+		if (runtime->silenced_start != runtime->control->appl_ptr) {
+			n = runtime->control->appl_ptr - runtime->silenced_start;
+			if (n < 0)
+				n += runtime->boundary;
+			if ((snd_pcm_uframes_t)n < runtime->silenced_size)
+				runtime->silenced_size -= n;
+			else
+				runtime->silenced_size = 0;
+			runtime->silenced_start = runtime->control->appl_ptr;
+		}
+		if (runtime->silenced_size == runtime->buffer_size)
+			return;
+		snd_assert(runtime->silenced_size <= runtime->buffer_size, return);
+		noise_dist = snd_pcm_playback_hw_avail(runtime) + runtime->silenced_size;
+		if (noise_dist > (snd_pcm_sframes_t) runtime->silence_threshold)
+			return;
+		frames = runtime->silence_threshold - noise_dist;
+		if (frames > runtime->silence_size)
+			frames = runtime->silence_size;
+	} else {
+		if (new_hw_ptr == ULONG_MAX) {	/* initialization */
 			runtime->silenced_size = 0;
-		runtime->silenced_start = runtime->control->appl_ptr;
+			runtime->silenced_start = runtime->control->appl_ptr;
+		} else {
+			ofs = runtime->status->hw_ptr;
+			frames = new_hw_ptr - ofs;
+			if ((snd_pcm_sframes_t)frames < 0)
+				frames += runtime->boundary;
+			runtime->silenced_size -= frames;
+			if ((snd_pcm_sframes_t)runtime->silenced_size < 0) {
+				runtime->silenced_size = 0;
+				runtime->silenced_start = (ofs + frames) - runtime->buffer_size;
+			} else {
+				runtime->silenced_start = ofs - runtime->silenced_size;
+			}
+			if ((snd_pcm_sframes_t)runtime->silenced_start < 0)
+				runtime->silenced_start += runtime->boundary;
+		}
+		frames = runtime->buffer_size;
 	}
-	if (runtime->silenced_size == runtime->buffer_size)
+	snd_assert(frames >= runtime->silenced_size, return);
+	frames -= runtime->silenced_size;
+	if (frames == 0)
 		return;
-	snd_assert(runtime->silenced_size <= runtime->buffer_size, return);
-	noise_dist = snd_pcm_playback_hw_avail(runtime) + runtime->silenced_size;
-	if (noise_dist > (snd_pcm_sframes_t) runtime->silence_threshold)
-		return;
-	frames = runtime->silence_threshold - noise_dist;
-	if (frames < runtime->silence_size)
-		frames = runtime->silence_size;
-	if (runtime->silenced_size + frames > runtime->buffer_size)
-		frames = runtime->buffer_size - runtime->silenced_size;
-	ofs = runtime->silenced_start % runtime->buffer_size + runtime->silenced_size;
-	if (ofs >= runtime->buffer_size)
-		ofs -= runtime->buffer_size;
+	ofs = (runtime->silenced_start + runtime->silenced_size) % runtime->buffer_size;
 	while (frames > 0) {
 		transfer = ofs + frames > runtime->buffer_size ? runtime->buffer_size - ofs : frames;
 		if (runtime->access == SNDRV_PCM_ACCESS_RW_INTERLEAVED ||
@@ -88,9 +120,10 @@
 				}
 			}
 		}
+		runtime->silenced_size += transfer;
 		frames -= transfer;
+		ofs = 0;
 	}
-	runtime->silenced_size += frames;
 }
 
 int snd_pcm_update_hw_ptr_interrupt(snd_pcm_substream_t *substream)
@@ -128,16 +161,13 @@
 			runtime->hw_ptr_base = 0;
 		new_hw_ptr = runtime->hw_ptr_base + pos;
 	}
-	runtime->status->hw_ptr = new_hw_ptr;
-	runtime->hw_ptr_interrupt = new_hw_ptr - (runtime->hw_ptr_base + pos) % runtime->period_size;
 
-#if 0
-	if (hw_ptr_interrupt == runtime->boundary)
-		hw_ptr_interrupt = 0;
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK &&
+	    runtime->silence_size > 0)
+		snd_pcm_playback_silence(substream, new_hw_ptr);
 
-	if (runtime->hw_ptr_interrupt != hw_ptr_interrupt)
-		snd_printd("Lost interrupt: hw_ptr = %d expected %d\n", runtime->hw_ptr_interrupt, hw_ptr_interrupt);
-#endif
+	runtime->status->hw_ptr = new_hw_ptr;
+	runtime->hw_ptr_interrupt = new_hw_ptr - new_hw_ptr % runtime->period_size;
 
 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
 		avail = snd_pcm_playback_avail(runtime);
@@ -153,9 +183,6 @@
 	}
 	if (avail >= runtime->control->avail_min)
 		wake_up(&runtime->sleep);
-	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK &&
-	    runtime->silence_size > 0)
-		snd_pcm_playback_silence(substream);
 	return 0;
 }
 
@@ -167,6 +194,7 @@
 	snd_pcm_uframes_t old_hw_ptr, new_hw_ptr;
 	snd_pcm_uframes_t avail;
 	snd_pcm_sframes_t delta;
+
 	old_hw_ptr = runtime->status->hw_ptr;
 	pos = substream->ops->pointer(substream);
 	if (runtime->tstamp_mode & SNDRV_PCM_TSTAMP_MMAP)
@@ -192,6 +220,9 @@
 			runtime->hw_ptr_base = 0;
 		new_hw_ptr = runtime->hw_ptr_base + pos;
 	}
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK &&
+	    runtime->silence_size > 0)
+		snd_pcm_playback_silence(substream, new_hw_ptr);
 	runtime->status->hw_ptr = new_hw_ptr;
 
 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
@@ -208,9 +239,6 @@
 	}
 	if (avail >= runtime->control->avail_min)
 		wake_up(&runtime->sleep);
-	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK &&
-	    runtime->silence_size > 0)
-		snd_pcm_playback_silence(substream);
 	return 0;
 }
 
@@ -1901,7 +1929,9 @@
 	u_int64_t n;
 	u_int32_t r;
 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-		if (runtime->silence_size > 0 &&
+		if (runtime->silence_size >= runtime->boundary) {
+			frames = 1;
+		} else if (runtime->silence_size > 0 &&
 		    runtime->silenced_size < runtime->buffer_size) {
 			snd_pcm_sframes_t noise_dist;
 			noise_dist = snd_pcm_playback_hw_avail(runtime) + runtime->silenced_size;
diff -Nru a/sound/core/pcm_memory.c b/sound/core/pcm_memory.c
--- a/sound/core/pcm_memory.c	Mon Feb 17 14:57:27 2003
+++ b/sound/core/pcm_memory.c	Mon Feb 17 14:57:27 2003
@@ -47,35 +47,34 @@
  * allocate pages on the specified bus
  */
 static int alloc_pcm_pages(snd_pcm_substream_t *substream, size_t size,
-			   void **dma_area, dma_addr_t *dma_addr)
+			   struct snd_pcm_dma_buffer *dmab)
 {
 	switch (substream->dma_type) {
 	case SNDRV_PCM_DMA_TYPE_CONTINUOUS:
-		*dma_area = snd_malloc_pages(size, (unsigned int)((unsigned long)substream->dma_private & 0xffffffff));
-		*dma_addr = 0UL;		/* not valid */
+		dmab->area = snd_malloc_pages(size, (unsigned int)((unsigned long)substream->dma_private & 0xffffffff));
+		dmab->addr = 0UL;		/* not valid */
 		break;
 #ifdef CONFIG_ISA
 	case SNDRV_PCM_DMA_TYPE_ISA:
-		*dma_area = snd_malloc_isa_pages(size, dma_addr); 
+		dmab->area = snd_malloc_isa_pages(size, &dmab->addr);
 		break;
 #endif
 #ifdef CONFIG_PCI
 	case SNDRV_PCM_DMA_TYPE_PCI:
-		*dma_area = snd_malloc_pci_pages((struct pci_dev *)substream->dma_private, size, dma_addr);
+		dmab->area = snd_malloc_pci_pages((struct pci_dev *)substream->dma_private, size, &dmab->addr);
 		break;
 	case SNDRV_PCM_DMA_TYPE_PCI_SG:
-		*dma_area = snd_pcm_sgbuf_alloc_pages((struct snd_sg_buf *)substream->dma_private, size);
-		*dma_addr = 0;
+		snd_pcm_sgbuf_alloc_pages((struct pci_dev *)substream->dma_private, size, dmab);
 		break;
 #endif
 #ifdef CONFIG_SBUS
 	case SNDRV_PCM_DMA_TYPE_SBUS:
-		*dma_area = snd_malloc_sbus_pages((struct sbus_dev *)substream->dma_private, size, dma_addr);
+		dmab->area = snd_malloc_sbus_pages((struct sbus_dev *)substream->dma_private, size, &dmab->addr);
 		break;
 #endif
 	default:
-		*dma_area = NULL;
-		*dma_addr = 0;
+		dmab->area = NULL;
+		dmab->addr = 0;
 		return -ENXIO;
 	}
 	return 0;
@@ -87,55 +86,53 @@
  *
  * the minimum size is snd_minimum_buffer.  it should be power of 2.
  */
-static void *alloc_pcm_pages_fallback(snd_pcm_substream_t *substream,
-				      size_t size, dma_addr_t *addrp,
-				      size_t *res_size)
+static int alloc_pcm_pages_fallback(snd_pcm_substream_t *substream,
+				    size_t size,
+				    struct snd_pcm_dma_buffer *dmab)
 {
-	void *res;
-
-	snd_assert(size > 0, return NULL);
-	snd_assert(res_size != NULL, return NULL);
+	int err;
+	snd_assert(size > 0, return -EINVAL);
 	do {
-		if (alloc_pcm_pages(substream, size, &res, addrp) < 0)
-			return NULL;
-		if (res) {
-			*res_size = size;
-			return res;
+		if ((err = alloc_pcm_pages(substream, size, dmab)) < 0)
+			return err;
+		if (dmab->area) {
+			dmab->bytes = size;
+			return 0;
 		}
 		size >>= 1;
 	} while (size >= snd_minimum_buffer);
-	*res_size = 0; /* tell error */
-	return NULL;
+	dmab->bytes = 0; /* tell error */
+	return 0;
 }
 
 /*
  * release the pages on the specified bus
  */
-static void free_pcm_pages(snd_pcm_substream_t *substream, size_t size,
-			   void *dma_area, dma_addr_t dma_addr)
+static void free_pcm_pages(snd_pcm_substream_t *substream,
+			   struct snd_pcm_dma_buffer *dmab)
 {
 	switch (substream->dma_type) {
 	case SNDRV_PCM_DMA_TYPE_CONTINUOUS:
-		snd_free_pages(dma_area, size);
+		snd_free_pages(dmab->area, dmab->bytes);
 		break;
 #ifdef CONFIG_ISA
 	case SNDRV_PCM_DMA_TYPE_ISA:
-		snd_free_isa_pages(size, dma_area, dma_addr);
+		snd_free_isa_pages(dmab->bytes, dmab->area, dmab->addr);
 		break;
 #endif
 #ifdef CONFIG_PCI
 	case SNDRV_PCM_DMA_TYPE_PCI:
 		snd_free_pci_pages((struct pci_dev *)substream->dma_private,
-				   size, dma_area, dma_addr);
+				   dmab->bytes, dmab->area, dmab->addr);
 		break;
 	case SNDRV_PCM_DMA_TYPE_PCI_SG:
-		snd_pcm_sgbuf_free_pages((struct snd_sg_buf *)substream->dma_private, dma_area);
+		snd_pcm_sgbuf_free_pages(dmab);
 		break;
 #endif
 #ifdef CONFIG_SBUS
 	case SNDRV_PCM_DMA_TYPE_SBUS:
 		snd_free_sbus_pages((struct sbus_dev *)substream->dma_private,
-				    size, dma_area, dma_addr);
+				    dmab->bytes, dmab->area, dmab->addr);
 		break;
 #endif
 	}
@@ -146,11 +143,10 @@
  */
 static void snd_pcm_lib_preallocate_dma_free(snd_pcm_substream_t *substream)
 {
-	if (substream->dma_area == NULL)
+	if (substream->dma_buffer.area == NULL)
 		return;
-	free_pcm_pages(substream, substream->dma_bytes,
-		       substream->dma_area, substream->dma_addr);
-	substream->dma_area = NULL;
+	free_pcm_pages(substream, &substream->dma_buffer);
+	substream->dma_buffer.area = NULL;
 }
 
 /**
@@ -168,10 +164,6 @@
 		snd_info_unregister(substream->proc_prealloc_entry);
 		substream->proc_prealloc_entry = NULL;
 	}
-#ifdef CONFIG_PCI
-	if (substream->dma_type == SNDRV_PCM_DMA_TYPE_PCI_SG)
-		snd_pcm_sgbuf_delete((struct snd_sg_buf *)substream->dma_private);
-#endif
 	substream->dma_type = SNDRV_PCM_DMA_TYPE_UNKNOWN;
 	return 0;
 }
@@ -204,7 +196,7 @@
 					      snd_info_buffer_t *buffer)
 {
 	snd_pcm_substream_t *substream = (snd_pcm_substream_t *)entry->private_data;
-	snd_iprintf(buffer, "%lu\n", (unsigned long) substream->dma_bytes / 1024);
+	snd_iprintf(buffer, "%lu\n", (unsigned long) substream->dma_buffer.bytes / 1024);
 }
 
 /*
@@ -218,8 +210,7 @@
 	snd_pcm_substream_t *substream = (snd_pcm_substream_t *)entry->private_data;
 	char line[64], str[64];
 	size_t size;
-	void *dma_area;
-	dma_addr_t dma_addr;
+	struct snd_pcm_dma_buffer new_dmab;
 
 	if (substream->runtime) {
 		buffer->error = -EBUSY;
@@ -232,26 +223,22 @@
 			buffer->error = -EINVAL;
 			return;
 		}
-		if (substream->dma_bytes == size)
+		if (substream->dma_buffer.bytes == size)
 			return;
+		memset(&new_dmab, 0, sizeof(new_dmab));
 		if (size > 0) {
-			if (alloc_pcm_pages(substream, size, &dma_area, &dma_addr) < 0) {
-				dma_area = NULL;
-				dma_addr = 0UL;
-			}
-			if (dma_area == NULL) {
+
+			if (alloc_pcm_pages(substream, size, &new_dmab) < 0 ||
+			    new_dmab.area == NULL) {
 				buffer->error = -ENOMEM;
 				return;
 			}
 			substream->buffer_bytes_max = size;
 		} else {
-			dma_area = NULL;
 			substream->buffer_bytes_max = UINT_MAX;
 		}
 		snd_pcm_lib_preallocate_dma_free(substream);
-		substream->dma_area = dma_area;
-		substream->dma_addr = dma_addr;
-		substream->dma_bytes = size;
+		substream->dma_buffer = new_dmab;
 	} else {
 		buffer->error = -EINVAL;
 	}
@@ -263,18 +250,14 @@
 static int snd_pcm_lib_preallocate_pages1(snd_pcm_substream_t *substream,
 					  size_t size, size_t max)
 {
-	size_t rsize = 0;
-	void *dma_area = NULL;
-	dma_addr_t dma_addr = 0UL;
 	snd_info_entry_t *entry;
 
+	memset(&substream->dma_buffer, 0, sizeof(substream->dma_buffer));
 	if (size > 0 && preallocate_dma && substream->number < maximum_substreams)
-		dma_area = alloc_pcm_pages_fallback(substream, size, &dma_addr, &rsize);
-	substream->dma_area = dma_area;
-	substream->dma_addr = dma_addr;
-	substream->dma_bytes = rsize;
-	if (rsize > 0)
-		substream->buffer_bytes_max = rsize;
+		alloc_pcm_pages_fallback(substream, size, &substream->dma_buffer);
+
+	if (substream->dma_buffer.bytes > 0)
+		substream->buffer_bytes_max = substream->dma_buffer.bytes;
 	substream->dma_max = max;
 	if ((entry = snd_info_create_card_entry(substream->pcm->card, "prealloc", substream->proc_root)) != NULL) {
 		entry->c.text.read_size = 64;
@@ -396,31 +379,32 @@
 int snd_pcm_lib_malloc_pages(snd_pcm_substream_t *substream, size_t size)
 {
 	snd_pcm_runtime_t *runtime;
-	void *dma_area = NULL;
-	dma_addr_t dma_addr = 0UL;
+	struct snd_pcm_dma_buffer dmab;
 
 	snd_assert(substream->dma_type != SNDRV_PCM_DMA_TYPE_UNKNOWN, return -EINVAL);
 	snd_assert(substream != NULL, return -EINVAL);
 	runtime = substream->runtime;
 	snd_assert(runtime != NULL, return -EINVAL);	
+
 	if (runtime->dma_area != NULL) {
 		/* perphaps, we might free the large DMA memory region
 		   to save some space here, but the actual solution
 		   costs us less time */
 		if (runtime->dma_bytes >= size)
 			return 0;	/* ok, do not change */
-      		snd_pcm_lib_free_pages(substream);
+		snd_pcm_lib_free_pages(substream);
 	}
-	if (substream->dma_area != NULL && substream->dma_bytes >= size) {
-		dma_area = substream->dma_area;
-		dma_addr = substream->dma_addr;
+	if (substream->dma_buffer.area != NULL && substream->dma_buffer.bytes >= size) {
+		dmab = substream->dma_buffer;
 	} else {
-		alloc_pcm_pages(substream, size, &dma_area, &dma_addr);
+		memset(&dmab, 0, sizeof(dmab));
+		alloc_pcm_pages(substream, size, &dmab);
 	}
-	if (! dma_area)
+	if (! dmab.area)
 		return -ENOMEM;
-	runtime->dma_area = dma_area;
-	runtime->dma_addr = dma_addr;
+	runtime->dma_area = dmab.area;
+	runtime->dma_addr = dmab.addr;
+	runtime->dma_private = dmab.private_data;
 	runtime->dma_bytes = size;
 	return 1;			/* area was changed */
 }
@@ -442,12 +426,19 @@
 	snd_assert(runtime != NULL, return -EINVAL);
 	if (runtime->dma_area == NULL)
 		return 0;
-	if (runtime->dma_area != substream->dma_area)
-		free_pcm_pages(substream, runtime->dma_bytes,
-			       runtime->dma_area, runtime->dma_addr);
+	if (runtime->dma_area != substream->dma_buffer.area) {
+		struct snd_pcm_dma_buffer dmab;
+		memset(&dmab, 0, sizeof(dmab));
+		dmab.area = runtime->dma_area;
+		dmab.addr = runtime->dma_addr;
+		dmab.bytes = runtime->dma_bytes;
+		dmab.private_data = runtime->dma_private;
+		free_pcm_pages(substream, &dmab);
+	}
 	runtime->dma_area = NULL;
 	runtime->dma_addr = 0UL;
 	runtime->dma_bytes = 0;
+	runtime->dma_private = NULL;
 	return 0;
 }
 
@@ -553,3 +544,56 @@
 }
 
 #endif /* CONFIG_SBUS */
+
+
+#ifdef CONFIG_PCI
+/**
+ * snd_pcm_lib_preallocate_sg_pages - initialize SG-buffer for the PCI bus
+ *
+ * @pci: pci device
+ * @substream: substream to assign the buffer
+ * @size: the requested pre-allocation size in bytes
+ * @max: max. buffer size acceptable for the changes via proc file
+ *
+ * Initializes SG-buffer for the PCI bus.
+ *
+ * Returns zero if successful, or a negative error code on failure.
+ */
+int snd_pcm_lib_preallocate_sg_pages(struct pci_dev *pci,
+				     snd_pcm_substream_t *substream,
+				     size_t size, size_t max)
+{
+	substream->dma_type = SNDRV_PCM_DMA_TYPE_PCI_SG;
+	substream->dma_private = pci;
+	return snd_pcm_lib_preallocate_pages1(substream, size, max);
+}
+
+/*
+ * FIXME: the function name is too long for docbook!
+ *
+ * snd_pcm_lib_preallocate_sg_pages_for_all - initialize SG-buffer for the PCI bus (all substreams)
+ * @pci: pci device
+ * @pcm: pcm to assign the buffer
+ * @size: the requested pre-allocation size in bytes
+ * @max: max. buffer size acceptable for the changes via proc file
+ *
+ * Initialize the SG-buffer to all substreams of the given pcm for the
+ * PCI bus.
+ *
+ * Returns zero if successful, or a negative error code on failure.
+ */
+int snd_pcm_lib_preallocate_sg_pages_for_all(struct pci_dev *pci,
+					     snd_pcm_t *pcm,
+					     size_t size, size_t max)
+{
+	snd_pcm_substream_t *substream;
+	int stream, err;
+
+	for (stream = 0; stream < 2; stream++)
+		for (substream = pcm->streams[stream].substream; substream; substream = substream->next)
+			if ((err = snd_pcm_lib_preallocate_sg_pages(pci, substream, size, max)) < 0)
+				return err;
+	return 0;
+}
+
+#endif /* CONFIG_PCI */
diff -Nru a/sound/core/pcm_native.c b/sound/core/pcm_native.c
--- a/sound/core/pcm_native.c	Mon Feb 17 14:57:27 2003
+++ b/sound/core/pcm_native.c	Mon Feb 17 14:57:27 2003
@@ -458,7 +458,8 @@
 	if (params->xfer_align == 0 ||
 	    params->xfer_align % runtime->min_align != 0)
 		return -EINVAL;
-	if (params->silence_threshold + params->silence_size > runtime->buffer_size)
+	if ((params->silence_threshold != 0 || params->silence_size < runtime->boundary) &&
+	    (params->silence_threshold + params->silence_size > runtime->buffer_size))
 		return -EINVAL;
 	spin_lock_irq(&runtime->lock);
 	runtime->tstamp_mode = params->tstamp_mode;
@@ -478,7 +479,7 @@
 			snd_pcm_tick_set(substream, 0);
 		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK &&
 		    runtime->silence_size > 0)
-			snd_pcm_playback_silence(substream);
+			snd_pcm_playback_silence(substream, ULONG_MAX);
 		wake_up(&runtime->sleep);
 	}
 	spin_unlock_irq(&runtime->lock);
@@ -671,7 +672,7 @@
 	runtime->status->state = SNDRV_PCM_STATE_RUNNING;
 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK &&
 	    runtime->silence_size > 0)
-		snd_pcm_playback_silence(substream);
+		snd_pcm_playback_silence(substream, ULONG_MAX);
 	if (runtime->sleep_min)
 		snd_pcm_tick_prepare(substream);
 }
@@ -938,9 +939,11 @@
 	int err = substream->ops->ioctl(substream, SNDRV_PCM_IOCTL1_RESET, 0);
 	if (err < 0)
 		return err;
-	snd_assert(runtime->status->hw_ptr < runtime->buffer_size, );
+	// snd_assert(runtime->status->hw_ptr < runtime->buffer_size, );
 	runtime->hw_ptr_base = 0;
 	runtime->hw_ptr_interrupt = runtime->status->hw_ptr - runtime->status->hw_ptr % runtime->period_size;
+	runtime->silenced_start = runtime->status->hw_ptr;
+	runtime->silenced_size = 0;
 	return 0;
 }
 
@@ -948,7 +951,9 @@
 {
 	snd_pcm_runtime_t *runtime = substream->runtime;
 	runtime->control->appl_ptr = runtime->status->hw_ptr;
-	
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK &&
+	    runtime->silence_size > 0)
+		snd_pcm_playback_silence(substream, ULONG_MAX);
 }
 
 static int snd_pcm_reset(snd_pcm_substream_t *substream)
diff -Nru a/sound/core/pcm_sgbuf.c b/sound/core/pcm_sgbuf.c
--- a/sound/core/pcm_sgbuf.c	Mon Feb 17 14:57:28 2003
+++ b/sound/core/pcm_sgbuf.c	Mon Feb 17 14:57:28 2003
@@ -32,60 +32,32 @@
 #define sgbuf_align_table(tbl)	((((tbl) + SGBUF_TBL_ALIGN - 1) / SGBUF_TBL_ALIGN) * SGBUF_TBL_ALIGN)
 
 
-/*
- * snd_pcm_sgbuf_new - constructor of the sgbuf instance
- * @pci: pci device pointer
- *
- * Initializes the SG-buffer instance to be assigned to
- * substream->dma_private.
- * 
- * Returns the pointer of the instance, or NULL at error.
- */
-struct snd_sg_buf *snd_pcm_sgbuf_new(struct pci_dev *pci)
-{
-	struct snd_sg_buf *sgbuf;
-
-	sgbuf = snd_magic_kcalloc(snd_pcm_sgbuf_t, 0, GFP_KERNEL);
-	if (! sgbuf)
-		return NULL;
-	sgbuf->pci = pci;
-	sgbuf->pages = 0;
-	sgbuf->tblsize = 0;
-
-	return sgbuf;
-}
-
-/*
- * snd_pcm_sgbuf_delete - destructor of sgbuf instance
- * @sgbuf: the SG-buffer instance
- *
- * Destructor Releaes all pages and free the sgbuf instance.
- */
-void snd_pcm_sgbuf_delete(struct snd_sg_buf *sgbuf)
-{
-	snd_pcm_sgbuf_free_pages(sgbuf, NULL);
-	snd_magic_kfree(sgbuf);
-}
-
 /**
  * snd_pcm_sgbuf_alloc_pages - allocate the pages for the SG buffer
- * @sgbuf: the sgbuf instance
+ * @pci: the pci device pointer
  * @size: the requested buffer size in bytes
+ * @dmab: the dma-buffer record to store
  *
- * Allocates the buffer pages for the given size and updates the
- * sg buffer table.  The pages are mapped to the virtually continuous
- * memory.
+ * Initializes the SG-buffer table and allocates the buffer pages
+ * for the given size.
+ * The pages are mapped to the virtually continuous memory.
  *
  * This function is usually called from snd_pcm_lib_malloc_pages().
  *
  * Returns the mapped virtual address of the buffer if allocation was
  * successful, or NULL at error.
  */
-void *snd_pcm_sgbuf_alloc_pages(struct snd_sg_buf *sgbuf, size_t size)
+void *snd_pcm_sgbuf_alloc_pages(struct pci_dev *pci, size_t size, struct snd_pcm_dma_buffer *dmab)
 {
+	struct snd_sg_buf *sgbuf;
 	unsigned int i, pages;
-	void *vmaddr;
 
+	dmab->area = NULL;
+	dmab->addr = 0;
+	dmab->private_data = sgbuf = snd_magic_kcalloc(snd_pcm_sgbuf_t, 0, GFP_KERNEL);
+	if (! sgbuf)
+		return NULL;
+	sgbuf->pci = pci;
 	pages = snd_pcm_sgbuf_pages(size);
 	sgbuf->tblsize = sgbuf_align_table(pages);
 	sgbuf->table = snd_kcalloc(sizeof(*sgbuf->table) * sgbuf->tblsize, GFP_KERNEL);
@@ -109,46 +81,43 @@
 	}
 
 	sgbuf->size = size;
-	vmaddr = vmap(sgbuf->page_table, sgbuf->pages);
-	if (! vmaddr)
+	dmab->area = vmap(sgbuf->page_table, sgbuf->pages);
+	if (! dmab->area)
 		goto _failed;
-	return vmaddr;
+	return dmab->area;
 
  _failed:
-	snd_pcm_sgbuf_free_pages(sgbuf, NULL); /* free the table */
+	snd_pcm_sgbuf_free_pages(dmab); /* free the table */
 	return NULL;
 }
 
 /**
  * snd_pcm_sgbuf_free_pages - free the sg buffer
- * @sgbuf: the sgbuf instance
- * @vmaddr: the mapped virtual address
+ * @dmab: dma buffer record
  *
- * Releases the pages and the mapped tables.
+ * Releases the pages and the SG-buffer table.
  *
  * This function is called usually from snd_pcm_lib_free_pages().
  *
  * Returns zero if successful, or a negative error code on failure.
  */
-int snd_pcm_sgbuf_free_pages(struct snd_sg_buf *sgbuf, void *vmaddr)
+int snd_pcm_sgbuf_free_pages(struct snd_pcm_dma_buffer *dmab)
 {
-	if (vmaddr)
-		vunmap(vmaddr);
+	struct snd_sg_buf *sgbuf = snd_magic_cast(snd_pcm_sgbuf_t, dmab->private_data, return -EINVAL);
+	int i;
+
+	for (i = 0; i < sgbuf->pages; i++)
+		snd_free_pci_page(sgbuf->pci, sgbuf->table[i].buf, sgbuf->table[i].addr);
+	if (dmab->area)
+		vunmap(dmab->area);
+	dmab->area = NULL;
 
-	while (sgbuf->pages > 0) {
-		sgbuf->pages--;
-		snd_free_pci_page(sgbuf->pci, sgbuf->table[sgbuf->pages].buf,
-				   sgbuf->table[sgbuf->pages].addr);
-	}
 	if (sgbuf->table)
 		kfree(sgbuf->table);
-	sgbuf->table = NULL;
 	if (sgbuf->page_table)
 		kfree(sgbuf->page_table);
-	sgbuf->page_table = NULL;
-	sgbuf->tblsize = 0;
-	sgbuf->pages = 0;
-	sgbuf->size = 0;
+	snd_magic_kfree(sgbuf);
+	dmab->private_data = NULL;
 	
 	return 0;
 }
@@ -163,62 +132,12 @@
  */
 struct page *snd_pcm_sgbuf_ops_page(snd_pcm_substream_t *substream, unsigned long offset)
 {
-	struct snd_sg_buf *sgbuf = snd_magic_cast(snd_pcm_sgbuf_t, substream->dma_private, return NULL);
+	struct snd_sg_buf *sgbuf = snd_magic_cast(snd_pcm_sgbuf_t, _snd_pcm_substream_sgbuf(substream), return NULL);
 
 	unsigned int idx = offset >> PAGE_SHIFT;
 	if (idx >= (unsigned int)sgbuf->pages)
 		return NULL;
 	return sgbuf->page_table[idx];
-}
-
-
-/**
- * snd_pcm_lib_preallocate_sg_pages - initialize SG-buffer for the PCI bus
- *
- * @pci: pci device
- * @substream: substream to assign the buffer
- *
- * Initializes SG-buffer for the PCI bus.
- *
- * Returns zero if successful, or a negative error code on failure.
- */
-int snd_pcm_lib_preallocate_sg_pages(struct pci_dev *pci,
-				     snd_pcm_substream_t *substream)
-{
-	if ((substream->dma_private = snd_pcm_sgbuf_new(pci)) == NULL)
-		return -ENOMEM;
-	substream->dma_type = SNDRV_PCM_DMA_TYPE_PCI_SG;
-	substream->dma_area = 0;
-	substream->dma_addr = 0;
-	substream->dma_bytes = 0;
-	substream->buffer_bytes_max = UINT_MAX;
-	substream->dma_max = 0;
-	return 0;
-}
-
-/*
- * FIXME: the function name is too long for docbook!
- *
- * snd_pcm_lib_preallocate_sg_pages_for_all - initialize SG-buffer for the PCI bus (all substreams)
- * @pci: pci device
- * @pcm: pcm to assign the buffer
- *
- * Initialize the SG-buffer to all substreams of the given pcm for the
- * PCI bus.
- *
- * Returns zero if successful, or a negative error code on failure.
- */
-int snd_pcm_lib_preallocate_sg_pages_for_all(struct pci_dev *pci,
-					     snd_pcm_t *pcm)
-{
-	snd_pcm_substream_t *substream;
-	int stream, err;
-
-	for (stream = 0; stream < 2; stream++)
-		for (substream = pcm->streams[stream].substream; substream; substream = substream->next)
-			if ((err = snd_pcm_lib_preallocate_sg_pages(pci, substream)) < 0)
-				return err;
-	return 0;
 }
 
 
diff -Nru a/sound/core/seq/seq_device.c b/sound/core/seq/seq_device.c
--- a/sound/core/seq/seq_device.c	Mon Feb 17 14:57:27 2003
+++ b/sound/core/seq/seq_device.c	Mon Feb 17 14:57:27 2003
@@ -19,7 +19,7 @@
  *
  *----------------------------------------------------------------
  *
- * This device handler seperates the card driver module from sequencer
+ * This device handler separates the card driver module from sequencer
  * stuff (sequencer core, synth drivers, etc), so that user can avoid
  * to spend unnecessary resources e.g. if he needs only listening to
  * MP3s.
diff -Nru a/sound/core/seq/seq_midi_emul.c b/sound/core/seq/seq_midi_emul.c
--- a/sound/core/seq/seq_midi_emul.c	Mon Feb 17 14:57:28 2003
+++ b/sound/core/seq/seq_midi_emul.c	Mon Feb 17 14:57:28 2003
@@ -60,7 +60,7 @@
 
 
 /*
- * Process an event in a driver independant way.  This means dealing
+ * Process an event in a driver independent way.  This means dealing
  * with RPN, NRPN, SysEx etc that are defined for common midi applications
  * such as GM, GS and XG.
  * There modes that this module will run in are:
@@ -258,7 +258,7 @@
 }
 
 /*
- * Do all driver independant operations for this controler and pass
+ * Do all driver independent operations for this controler and pass
  * events that need to take place immediately to the driver.
  */
 static void
diff -Nru a/sound/core/timer.c b/sound/core/timer.c
--- a/sound/core/timer.c	Mon Feb 17 14:57:27 2003
+++ b/sound/core/timer.c	Mon Feb 17 14:57:27 2003
@@ -1298,7 +1298,7 @@
 {
 	snd_timer_user_t *tu;
 	long result = 0;
-	int  err = 0;
+	int err = 0;
 	
 	tu = snd_magic_cast(snd_timer_user_t, file->private_data, return -ENXIO);
 	spin_lock_irq(&tu->qlock);
@@ -1307,7 +1307,6 @@
 			wait_queue_t wait;
 
 			if ((file->f_flags & O_NONBLOCK) != 0 || result > 0) {
-				spin_unlock_irq(&tu->qlock);
 				err = -EAGAIN;
 				break;
 			}
diff -Nru a/sound/drivers/mtpav.c b/sound/drivers/mtpav.c
--- a/sound/drivers/mtpav.c	Mon Feb 17 14:57:28 2003
+++ b/sound/drivers/mtpav.c	Mon Feb 17 14:57:28 2003
@@ -135,6 +135,7 @@
 	u8 number;
 	u8 hwport;
 	u8 mode;
+	u8 running_status;
 	snd_rawmidi_substream_t *input;
 	snd_rawmidi_substream_t *output;
 } mtpav_port_t;
@@ -301,6 +302,11 @@
 {
 	u8 outbyte;
 
+	// Get the outbyte first, so we can emulate running status if
+	// necessary
+	if (snd_rawmidi_transmit(substream, &outbyte, 1) != 1)
+		return;
+
 	// send port change command if necessary
 
 	if (port->hwport != mtp_card->outmidihwport) {
@@ -310,12 +316,18 @@
 		snd_mtpav_send_byte(mtp_card, port->hwport);
 		//snd_printk("new outport: 0x%x\n", (unsigned int) port->hwport);
 
+		if (!(outbyte & 0x80) && port->running_status)
+			snd_mtpav_send_byte(mtp_card, port->running_status);
 	}
 
 	// send data
 
-	while (snd_rawmidi_transmit(substream, &outbyte, 1) == 1)
+	do {
+		if (outbyte & 0x80)
+			port->running_status = outbyte;
+		
 		snd_mtpav_send_byte(mtp_card, outbyte);
+	} while (snd_rawmidi_transmit(substream, &outbyte, 1) == 1);
 }
 
 static void snd_mtpav_output_write(snd_rawmidi_substream_t * substream)
@@ -682,7 +694,7 @@
 
 static mtpav_t *new_mtpav(void)
 {
-	mtpav_t *ncrd = (mtpav_t *) snd_kcalloc(sizeof(mtpav_t), GFP_KERNEL);
+	mtpav_t *ncrd = (mtpav_t *) snd_magic_kcalloc(mtpav_t, 0, GFP_KERNEL);
 	if (ncrd != NULL) {
 		spin_lock_init(&ncrd->spinlock);
 
@@ -715,8 +727,7 @@
 		release_resource(crd->res_port);
 		kfree_nocheck(crd->res_port);
 	}
-	if (crd != NULL)
-		kfree(crd);
+	snd_magic_kfree(crd);
 }
 
 /*
diff -Nru a/sound/i2c/l3/uda1341.c b/sound/i2c/l3/uda1341.c
--- a/sound/i2c/l3/uda1341.c	Mon Feb 17 14:57:27 2003
+++ b/sound/i2c/l3/uda1341.c	Mon Feb 17 14:57:27 2003
@@ -9,14 +9,15 @@
  *
  * History:
  *
- * 2002-03-13	Tomas Kasparek	Initial release - based on uda1341.c from OSS
+ * 2002-03-13   Tomas Kasparek  initial release - based on uda1341.c from OSS
  * 2002-03-28   Tomas Kasparek  basic mixer is working (volume, bass, treble)
- * 2002-03-30   Tomas Kasparek  Proc filesystem support, complete mixer and DSP
+ * 2002-03-30   Tomas Kasparek  proc filesystem support, complete mixer and DSP
  *                              features support
- * 2002-04-12	Tomas Kasparek	Proc interface update, code cleanup
+ * 2002-04-12	Tomas Kasparek	proc interface update, code cleanup
+ * 2002-05-12   Tomas Kasparek  another code cleanup
  */
 
-/* $Id: uda1341.c,v 1.6 2003/01/07 10:36:28 tiwai Exp $ */
+/* $Id: uda1341.c,v 1.7 2003/02/13 19:19:19 perex Exp $ */
 
 #include <sound/driver.h>
 #include <linux/module.h>
@@ -25,7 +26,6 @@
 #include <linux/slab.h>
 #include <linux/errno.h>
 #include <linux/ioctl.h>
-#include <linux/errno.h>
 
 #include <asm/uaccess.h>
 
@@ -422,7 +422,7 @@
 #define UDA1341_SINGLE(xname, where, reg, shift, mask, invert) \
 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .info = snd_uda1341_info_single, \
   .get = snd_uda1341_get_single, .put = snd_uda1341_put_single, \
-  .private_value = where | reg << 5 | (shift << 9) | (mask << 12) | (invert << 18) \
+  .private_value = where | (reg << 5) | (shift << 9) | (mask << 12) | (invert << 18) \
 }
 
 static int snd_uda1341_info_single(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
@@ -484,7 +484,7 @@
 #define UDA1341_ENUM(xname, where, reg, shift, mask, invert) \
 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .info = snd_uda1341_info_enum, \
   .get = snd_uda1341_get_enum, .put = snd_uda1341_put_enum, \
-  .private_value = where | reg << 5 | (shift << 9) | (mask << 12) | (invert << 18) \
+  .private_value = where | (reg << 5) | (shift << 9) | (mask << 12) | (invert << 18) \
 }
 
 static int snd_uda1341_info_enum(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
diff -Nru a/sound/isa/cs423x/cs4231_lib.c b/sound/isa/cs423x/cs4231_lib.c
--- a/sound/isa/cs423x/cs4231_lib.c	Mon Feb 17 14:57:27 2003
+++ b/sound/isa/cs423x/cs4231_lib.c	Mon Feb 17 14:57:27 2003
@@ -392,26 +392,34 @@
 #if 0
 	printk("(2) timeout = %i, jiffies = %li\n", timeout, jiffies);
 #endif
-	time = HZ / 4;
+	timeout = HZ / 4 / 2;
+	time = 2;
 	while (snd_cs4231_in(chip, CS4231_TEST_INIT) & CS4231_CALIB_IN_PROGRESS) {
-		if (time <= 0) {
+		set_current_state(TASK_INTERRUPTIBLE);
+		time = schedule_timeout(time);
+		if (time > 0)
+			continue;
+		time = 2;
+		if (--timeout < 0) {
 			snd_printk("mce_down - auto calibration time out (2)\n");
 			return;
 		}
-		set_current_state(TASK_INTERRUPTIBLE);
-		time = schedule_timeout(time);
 	}
 #if 0
 	printk("(3) jiffies = %li\n", jiffies);
 #endif
-	time = HZ / 10;
+	timeout = HZ / 10 / 2;
+	time = 2;
 	while (cs4231_inb(chip, CS4231P(REGSEL)) & CS4231_INIT) {
-		if (time <= 0) {
+		set_current_state(TASK_INTERRUPTIBLE);		
+		time = schedule_timeout(time);
+		if (time > 0)
+			continue;
+		time = 2;
+		if (--timeout < 0) {
 			snd_printk(KERN_ERR "mce_down - auto calibration time out (3)\n");
 			return;
 		}
-		set_current_state(TASK_INTERRUPTIBLE);		
-		time = schedule_timeout(time);
 	}
 #if 0
 	printk("(4) jiffies = %li\n", jiffies);
@@ -575,6 +583,7 @@
 			snd_cs4231_out(chip, CS4231_ALT_FEATURE_1, chip->image[CS4231_ALT_FEATURE_1] | 0x10);
 			snd_cs4231_out(chip, CS4231_PLAYBK_FORMAT, chip->image[CS4231_PLAYBK_FORMAT] = pdfr);
 			snd_cs4231_out(chip, CS4231_ALT_FEATURE_1, chip->image[CS4231_ALT_FEATURE_1] &= ~0x10);
+			udelay(100); /* Fixes audible clicks at least on GUS MAX */
 			full_calib = 0;
 		}
 		spin_unlock_irqrestore(&chip->reg_lock, flags);
@@ -1455,6 +1464,7 @@
 	case CS4231_HW_CS4232:	return "CS4232";
 	case CS4231_HW_CS4232A:	return "CS4232A";
 	case CS4231_HW_CS4235:	return "CS4235";
+	case CS4231_HW_CS4236:  return "CS4236";
 	case CS4231_HW_CS4236B: return "CS4236B";
 	case CS4231_HW_CS4237B: return "CS4237B";
 	case CS4231_HW_CS4238B: return "CS4238B";
diff -Nru a/sound/isa/cs423x/cs4236.c b/sound/isa/cs423x/cs4236.c
--- a/sound/isa/cs423x/cs4236.c	Mon Feb 17 14:57:26 2003
+++ b/sound/isa/cs423x/cs4236.c	Mon Feb 17 14:57:26 2003
@@ -188,6 +188,8 @@
 	ISAPNP_CS4232('C','S','C',0x1a32,0x0000,0x0010,0x0003),
 	/* HP Omnibook 5500 onboard */
 	ISAPNP_CS4232('C','S','C',0x4232,0x0000,0x0002,0x0003),
+	/* Unnamed CS4236 card (Made in Taiwan) */
+	ISAPNP_CS4232('C','S','C',0x4236,0x0000,0x0010,0x0003),
 	/* Turtle Beach TBS-2000 (CS4232) */
 	ISAPNP_CS4232('C','S','C',0x7532,0x0000,0x0010,0xb006),
 	/* Turtle Beach Tropez Plus (CS4232) */
diff -Nru a/sound/isa/cs423x/cs4236_lib.c b/sound/isa/cs423x/cs4236_lib.c
--- a/sound/isa/cs423x/cs4236_lib.c	Mon Feb 17 14:57:27 2003
+++ b/sound/isa/cs423x/cs4236_lib.c	Mon Feb 17 14:57:27 2003
@@ -282,7 +282,9 @@
 	}
 	if ((err = snd_cs4231_create(card, port, cport, irq, dma1, dma2, hardware, hwshare, &chip)) < 0)
 		return err;
+
 	if (!(chip->hardware & CS4231_HW_CS4236B_MASK)) {
+	        snd_printk("CS4236+: MODE3 and extended registers not available, hardware=0x%lx\n",chip->hardware);
 		snd_device_free(card, chip);
 		return -ENODEV;
 	}
diff -Nru a/sound/isa/gus/interwave.c b/sound/isa/gus/interwave.c
--- a/sound/isa/gus/interwave.c	Mon Feb 17 14:57:27 2003
+++ b/sound/isa/gus/interwave.c	Mon Feb 17 14:57:27 2003
@@ -109,7 +109,7 @@
 MODULE_PARM_SYNTAX(dma2, SNDRV_DMA_DESC);
 MODULE_PARM(joystick_dac, "1-" __MODULE_STRING(SNDRV_CARDS) "i");
 MODULE_PARM_DESC(joystick_dac, "Joystick DAC level 0.59V-4.52V or 0.389V-2.98V for InterWave driver.");
-MODULE_PARM_SYNTAX(snd_joystic_dac, SNDRV_ENABLED ",allows:{{0,31}}");
+MODULE_PARM_SYNTAX(joystick_dac, SNDRV_ENABLED ",allows:{{0,31}}");
 MODULE_PARM(midi, "1-" __MODULE_STRING(SNDRV_CARDS) "i");
 MODULE_PARM_DESC(midi, "MIDI UART enable for InterWave driver.");
 MODULE_PARM_SYNTAX(midi, SNDRV_ENABLED "," SNDRV_ENABLE_DESC);
diff -Nru a/sound/isa/sb/emu8000_pcm.c b/sound/isa/sb/emu8000_pcm.c
--- a/sound/isa/sb/emu8000_pcm.c	Mon Feb 17 14:57:28 2003
+++ b/sound/isa/sb/emu8000_pcm.c	Mon Feb 17 14:57:28 2003
@@ -592,7 +592,7 @@
 		return -ENOMEM;
 	rec->offset = EMU8000_DRAM_OFFSET + (rec->block->offset >> 1); /* in word */
 	/* at least dma_bytes must be set for non-interleaved mode */
-	subs->dma_bytes = params_buffer_bytes(hw_params);
+	subs->dma_buffer.bytes = params_buffer_bytes(hw_params);
 
 	return 0;
 }
diff -Nru a/sound/oss/trident.c b/sound/oss/trident.c
--- a/sound/oss/trident.c	Mon Feb 17 14:57:28 2003
+++ b/sound/oss/trident.c	Mon Feb 17 14:57:28 2003
@@ -223,7 +223,7 @@
 
 #define NR_HW_CH		32
 
-/* maxinum nuber of AC97 codecs connected, AC97 2.0 defined 4, but 7018 and 4D-NX only
+/* maximum number of AC97 codecs connected, AC97 2.0 defined 4, but 7018 and 4D-NX only
    have 2 SDATA_IN lines (currently) */
 #define NR_AC97		2	
 
diff -Nru a/sound/pci/ac97/ac97_codec.c b/sound/pci/ac97/ac97_codec.c
--- a/sound/pci/ac97/ac97_codec.c	Mon Feb 17 14:57:27 2003
+++ b/sound/pci/ac97/ac97_codec.c	Mon Feb 17 14:57:27 2003
@@ -87,6 +87,7 @@
 };
 
 static const ac97_codec_id_t snd_ac97_codec_ids[] = {
+{ 0x014b0502, 0xffffffff, "NM256AV",		NULL }, // FIXME: which real one?
 { 0x414b4d00, 0xffffffff, "AK4540",		NULL },
 { 0x414b4d01, 0xffffffff, "AK4542",		NULL },
 { 0x414b4d02, 0xffffffff, "AK4543",		NULL },
@@ -1252,6 +1253,10 @@
 			return 0;
 		break;
 	}
+
+	if (ac97->limited_regs && test_bit(reg, ac97->reg_accessed))
+		return 1; /* allow without check */
+
 	val = snd_ac97_read(ac97, reg);
 	if (!(val & mask)) {
 		/* nothing seems to be here - mute flag is not set */
@@ -1887,7 +1892,7 @@
 		udelay(50);
 		if (ac97_reset_wait(ac97, HZ/2, 0) < 0 &&
 		    ac97_reset_wait(ac97, HZ/2, 1) < 0) {
-			snd_printk("AC'97 %d:%d does not respond - RESET [REC_GAIN = 0x%x]\n", ac97->num, ac97->addr, err);
+			snd_printk("AC'97 %d:%d does not respond - RESET\n", ac97->num, ac97->addr);
 			snd_ac97_free(ac97);
 			return -ENXIO;
 		}
@@ -2418,6 +2423,80 @@
 
 
 /*
+ */
+static int remove_ctl(ac97_t *ac97, const char *name)
+{
+	snd_ctl_elem_id_t id;
+	memset(&id, 0, sizeof(id));
+	strcpy(id.name, name);
+	return snd_ctl_remove_id(ac97->card, &id);
+}
+
+static int rename_ctl(ac97_t *ac97, const char *src, const char *dst)
+{
+	snd_ctl_elem_id_t sid, did;
+	memset(&sid, 0, sizeof(sid));
+	strcpy(sid.name, src);
+	memset(&did, 0, sizeof(did));
+	strcpy(did.name, dst);
+	return snd_ctl_rename_id(ac97->card, &sid, &did);
+}
+
+static int swap_headphone(ac97_t *ac97, int remove_master)
+{
+	/* FIXME: error checks.. */
+	if (remove_master) {
+		remove_ctl(ac97, "Master Playback Switch");
+		remove_ctl(ac97, "Master Playback Volume");
+	} else {
+		rename_ctl(ac97, "Master Playback Switch", "Line-Out Playback Switch");
+		rename_ctl(ac97, "Master Playback Volume", "Line-Out Playback Volume");
+	}
+	rename_ctl(ac97, "Headphone Playback Switch", "Master Playback Switch");
+	rename_ctl(ac97, "Headphone Playback Volume", "Master Playback Volume");
+	return 0;
+}
+
+
+/**
+ * snd_ac97_tune_hardware - tune up the hardware
+ * @ac97: the ac97 instance
+ * @pci: pci device
+ * @quirk: quirk list
+ *
+ * Do some workaround for each pci device, such as renaming of the
+ * headphone (true line-out) control as "Master".
+ * The quirk-list must be terminated with a zero-filled entry.
+ *
+ * Returns zero if successful, or a negative error code on failure.
+ */
+
+int snd_ac97_tune_hardware(ac97_t *ac97, struct pci_dev *pci, struct ac97_quirk *quirk)
+{
+	unsigned short vendor, device;
+	struct ac97_quirk *q;
+
+	pci_read_config_word(pci, PCI_SUBSYSTEM_VENDOR_ID, &vendor);
+	pci_read_config_word(pci, PCI_SUBSYSTEM_ID, &device);
+
+	for (; quirk->vendor; quirk++) {
+		if (quirk->vendor == vendor && quirk->device == device) {
+			snd_printdd("ac97 quirk for %04x:%04x\n", vendor, device);
+			switch (quirk->type) {
+			case AC97_TUNE_HP_ONLY:
+				return swap_headphone(ac97, 1);
+			case AC97_TUNE_SWAP_HP:
+				return swap_headphone(ac97, 0);
+			}
+			snd_printk(KERN_ERR "invalid quirk type %d\n", quirk->type);
+			return -EINVAL;
+		}
+	}
+	return 0;
+}
+
+
+/*
  *  Exported symbols
  */
 
@@ -2428,6 +2507,7 @@
 EXPORT_SYMBOL(snd_ac97_update_bits);
 EXPORT_SYMBOL(snd_ac97_mixer);
 EXPORT_SYMBOL(snd_ac97_set_rate);
+EXPORT_SYMBOL(snd_ac97_tune_hardware);
 #ifdef CONFIG_PM
 EXPORT_SYMBOL(snd_ac97_resume);
 #endif
diff -Nru a/sound/pci/ali5451/ali5451.c b/sound/pci/ali5451/ali5451.c
--- a/sound/pci/ali5451/ali5451.c	Mon Feb 17 14:57:28 2003
+++ b/sound/pci/ali5451/ali5451.c	Mon Feb 17 14:57:28 2003
@@ -79,7 +79,7 @@
 #endif
 
 /*
- *  Constants defination
+ *  Constants definition
  */
 
 #ifndef PCI_VENDOR_ID_ALI
diff -Nru a/sound/pci/cs46xx/cs46xx_lib.c b/sound/pci/cs46xx/cs46xx_lib.c
--- a/sound/pci/cs46xx/cs46xx_lib.c	Mon Feb 17 14:57:26 2003
+++ b/sound/pci/cs46xx/cs46xx_lib.c	Mon Feb 17 14:57:26 2003
@@ -677,6 +677,7 @@
 {
 	/* cs46xx_t *chip = snd_pcm_substream_chip(substream); */
 	snd_pcm_runtime_t *runtime = substream->runtime;
+	snd_pcm_uframes_t appl_ptr = runtime->control->appl_ptr;
 	snd_pcm_sframes_t diff;
 	cs46xx_pcm_t * cpcm;
 	int buffer_size;
@@ -685,14 +686,14 @@
 
 	buffer_size = runtime->period_size * CS46XX_FRAGS << cpcm->shift;
 
-	diff = runtime->control->appl_ptr - cpcm->appl_ptr;
+	diff = appl_ptr - cpcm->appl_ptr;
 	if (diff) {
 		if (diff < -(snd_pcm_sframes_t) (runtime->boundary / 2))
 			diff += runtime->boundary;
-		cpcm->sw_ready += diff << cpcm->shift;
+		frames += diff;
 	}
 	cpcm->sw_ready += frames << cpcm->shift;
-	cpcm->appl_ptr = runtime->control->appl_ptr + frames;
+	cpcm->appl_ptr = appl_ptr + frames;
 	while (cpcm->hw_ready < buffer_size && 
 	       cpcm->sw_ready > 0) {
 		size_t hw_to_end = buffer_size - cpcm->hw_data;
@@ -724,15 +725,16 @@
 {
 	cs46xx_t *chip = snd_pcm_substream_chip(substream);
 	snd_pcm_runtime_t *runtime = substream->runtime;
-	snd_pcm_sframes_t diff = runtime->control->appl_ptr - chip->capt.appl_ptr;
+	snd_pcm_uframes_t appl_ptr = runtime->control->appl_ptr;
+	snd_pcm_sframes_t diff = appl_ptr - chip->capt.appl_ptr;
 	int buffer_size = runtime->period_size * CS46XX_FRAGS << chip->capt.shift;
 	if (diff) {
 		if (diff < -(snd_pcm_sframes_t) (runtime->boundary / 2))
 			diff += runtime->boundary;
-		chip->capt.sw_ready -= diff << chip->capt.shift;
+		frames += diff;
 	}
 	chip->capt.sw_ready -= frames << chip->capt.shift;
-	chip->capt.appl_ptr = runtime->control->appl_ptr + frames;
+	chip->capt.appl_ptr = appl_ptr + frames;
 	while (chip->capt.hw_ready > 0 && 
 	       chip->capt.sw_ready < (int)chip->capt.sw_bufsize) {
 		size_t hw_to_end = buffer_size - chip->capt.hw_data;
diff -Nru a/sound/pci/cs46xx/dsp_spos_scb_lib.c b/sound/pci/cs46xx/dsp_spos_scb_lib.c
--- a/sound/pci/cs46xx/dsp_spos_scb_lib.c	Mon Feb 17 14:57:28 2003
+++ b/sound/pci/cs46xx/dsp_spos_scb_lib.c	Mon Feb 17 14:57:28 2003
@@ -1543,7 +1543,7 @@
 	/* dont touch anything if SPDIF is open */
 	if ( ins->spdif_status_out & DSP_SPDIF_STATUS_PLAYBACK_OPEN) {
 		/* when cs46xx_iec958_post_close(...) is called it
-		   will call this function if necesary depending on
+		   will call this function if necessary depending on
 		   this bit */
 		ins->spdif_status_out |= DSP_SPDIF_STATUS_OUTPUT_ENABLED;
 
diff -Nru a/sound/pci/emu10k1/emufx.c b/sound/pci/emu10k1/emufx.c
--- a/sound/pci/emu10k1/emufx.c	Mon Feb 17 14:57:27 2003
+++ b/sound/pci/emu10k1/emufx.c	Mon Feb 17 14:57:27 2003
@@ -532,7 +532,7 @@
 	if (diff) {
 		if (diff < -(snd_pcm_sframes_t) (runtime->boundary / 2))
 			diff += runtime->boundary;
-		pcm->sw_ready += diff;
+		frames += diff;
 	}
 	pcm->sw_ready += frames;
 	pcm->appl_ptr = appl_ptr + frames;
diff -Nru a/sound/pci/emu10k1/emupcm.c b/sound/pci/emu10k1/emupcm.c
--- a/sound/pci/emu10k1/emupcm.c	Mon Feb 17 14:57:26 2003
+++ b/sound/pci/emu10k1/emupcm.c	Mon Feb 17 14:57:26 2003
@@ -993,7 +993,7 @@
 	emu->pcm = pcm;
 
 	for (substream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream; substream; substream = substream->next)
-		if ((err = snd_pcm_lib_preallocate_sg_pages(emu->pci, substream)) < 0)
+		if ((err = snd_pcm_lib_preallocate_sg_pages(emu->pci, substream, 64*1024, 64*1024)) < 0)
 			return err;
 
 	for (substream = pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream; substream; substream = substream->next)
diff -Nru a/sound/pci/emu10k1/memory.c b/sound/pci/emu10k1/memory.c
--- a/sound/pci/emu10k1/memory.c	Mon Feb 17 14:57:28 2003
+++ b/sound/pci/emu10k1/memory.c	Mon Feb 17 14:57:28 2003
@@ -232,7 +232,7 @@
 static int is_valid_page(dma_addr_t addr)
 {
 	if (addr & ~0x7fffffffUL) {
-		snd_printk("max memory size is 2GB!!\n");
+		snd_printk("max memory size is 2GB (addr = 0x%lx)!!\n", (unsigned long)addr);
 		return 0;
 	}
 	if (addr & (EMUPAGESIZE-1)) {
@@ -312,8 +312,18 @@
 	 */
 	idx = 0;
 	for (page = blk->first_page; page <= blk->last_page; page++, idx++) {
-		dma_addr_t addr = sgbuf->table[idx].addr;
+		dma_addr_t addr;
+#ifdef CONFIG_SND_DEBUG
+		if (idx >= sgbuf->pages) {
+			printk(KERN_ERR "emu: pages overflow! (%d-%d) for %d\n",
+			       blk->first_page, blk->last_page, sgbuf->pages);
+			up(&hdr->block_mutex);
+			return NULL;
+		}
+#endif
+		addr = sgbuf->table[idx].addr;
 		if (! is_valid_page(addr)) {
+			printk(KERN_ERR "emu: failure page = %d\n", idx);
 			up(&hdr->block_mutex);
 			return NULL;
 		}
diff -Nru a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c
--- a/sound/pci/intel8x0.c	Mon Feb 17 14:57:27 2003
+++ b/sound/pci/intel8x0.c	Mon Feb 17 14:57:27 2003
@@ -2011,12 +2011,12 @@
 		return; /* specified in module option */
 
 	subs = chip->pcm->streams[0].substream;
-	if (! subs || subs->dma_bytes < INTEL8X0_TESTBUF_SIZE) {
+	if (! subs || subs->dma_buffer.bytes < INTEL8X0_TESTBUF_SIZE) {
 		snd_printk("no playback buffer allocated - aborting measure ac97 clock\n");
 		return;
 	}
 	ichdev = &chip->ichd[ICHD_PCMOUT];
-	ichdev->physbuf = subs->dma_addr;
+	ichdev->physbuf = subs->dma_buffer.addr;
 	ichdev->size = chip->ichd[ICHD_PCMOUT].fragsize = INTEL8X0_TESTBUF_SIZE;
 	ichdev->substream = NULL; /* don't process interrupts */
 
diff -Nru a/sound/pci/maestro3.c b/sound/pci/maestro3.c
--- a/sound/pci/maestro3.c	Mon Feb 17 14:57:27 2003
+++ b/sound/pci/maestro3.c	Mon Feb 17 14:57:27 2003
@@ -2542,13 +2542,9 @@
 	chip->pci = pci;
 	chip->irq = -1;
 
-#ifndef LINUX_2_2
-	subsystem_vendor = pci->subsystem_vendor;
-	subsystem_device = pci->subsystem_device;
-#else
 	pci_read_config_word(pci, PCI_SUBSYSTEM_VENDOR_ID, &subsystem_vendor);
 	pci_read_config_word(pci, PCI_SUBSYSTEM_ID, &subsystem_device);
-#endif
+
 	for (quirk = m3_quirk_list; quirk->vendor; quirk++) {
 		if (subsystem_vendor == quirk->vendor &&
 		    subsystem_device == quirk->device) {
diff -Nru a/sound/pci/nm256/nm256.c b/sound/pci/nm256/nm256.c
--- a/sound/pci/nm256/nm256.c	Mon Feb 17 14:57:28 2003
+++ b/sound/pci/nm256/nm256.c	Mon Feb 17 14:57:28 2003
@@ -1199,7 +1199,7 @@
 		AC97_PC_BEEP, AC97_PHONE, AC97_MIC, AC97_LINE,
 		AC97_VIDEO, AC97_AUX, AC97_PCM, AC97_REC_SEL,
 		AC97_REC_GAIN, AC97_GENERAL_PURPOSE, AC97_3D_CONTROL,
-		AC97_EXTENDED_ID, AC97_EXTENDED_STATUS,
+		AC97_EXTENDED_ID,
 		AC97_VENDOR_ID1, AC97_VENDOR_ID2,
 		-1
 	};
diff -Nru a/sound/pci/rme9652/hdsp.c b/sound/pci/rme9652/hdsp.c
--- a/sound/pci/rme9652/hdsp.c	Mon Feb 17 14:57:27 2003
+++ b/sound/pci/rme9652/hdsp.c	Mon Feb 17 14:57:27 2003
@@ -2981,6 +2981,8 @@
 	
 	switch (rev & 0xff) {
 	case 0xa:
+	case 0xb:
+	case 0x64:
 		/* hdsp_initialize_firmware() will reset this */
 		hdsp->card_name = "RME Hammerfall DSP";
 		break;
diff -Nru a/sound/pci/trident/trident_main.c b/sound/pci/trident/trident_main.c
--- a/sound/pci/trident/trident_main.c	Mon Feb 17 14:57:27 2003
+++ b/sound/pci/trident/trident_main.c	Mon Feb 17 14:57:27 2003
@@ -2175,7 +2175,7 @@
 	trident->pcm = pcm;
 
 	if (trident->tlb.entries)
-		snd_pcm_lib_preallocate_sg_pages_for_all(trident->pci, pcm);
+		snd_pcm_lib_preallocate_sg_pages_for_all(trident->pci, pcm, 64*1024, 128*1024);
 	else
 		snd_pcm_lib_preallocate_pci_pages_for_all(trident->pci, pcm, 64*1024, 128*1024);
 
@@ -2230,7 +2230,7 @@
 	trident->foldback = foldback;
 
 	if (trident->tlb.entries)
-		snd_pcm_lib_preallocate_sg_pages_for_all(trident->pci, foldback);
+		snd_pcm_lib_preallocate_sg_pages_for_all(trident->pci, foldback, 0, 128*1024);
 	else
 		snd_pcm_lib_preallocate_pci_pages_for_all(trident->pci, foldback, 64*1024, 128*1024);
 
@@ -2274,7 +2274,7 @@
 	trident->spdif = spdif;
 
 	if (trident->tlb.entries)
-		snd_pcm_lib_preallocate_sg_pages_for_all(trident->pci, spdif);
+		snd_pcm_lib_preallocate_sg_pages_for_all(trident->pci, spdif, 64*1024, 128*1024);
 	else
 		snd_pcm_lib_preallocate_pci_pages_for_all(trident->pci, spdif, 64*1024, 128*1024);
 
diff -Nru a/sound/pci/via82xx.c b/sound/pci/via82xx.c
--- a/sound/pci/via82xx.c	Mon Feb 17 14:57:28 2003
+++ b/sound/pci/via82xx.c	Mon Feb 17 14:57:28 2003
@@ -1193,7 +1193,7 @@
 	/* capture */
 	init_viadev(chip, chip->capture_devno, VIA_REG_CAPTURE_8233_STATUS, 1);
 
-	if ((err = snd_pcm_lib_preallocate_sg_pages_for_all(chip->pci, pcm)) < 0)
+	if ((err = snd_pcm_lib_preallocate_sg_pages_for_all(chip->pci, pcm, 64*1024, 128*1024)) < 0)
 		return err;
 
 	/* PCM #1:  multi-channel playback and 2nd capture */
@@ -1209,7 +1209,7 @@
 	/* set up capture */
 	init_viadev(chip, chip->capture_devno + 1, VIA_REG_CAPTURE_8233_STATUS + 0x10, 1);
 
-	if ((err = snd_pcm_lib_preallocate_sg_pages_for_all(chip->pci, pcm)) < 0)
+	if ((err = snd_pcm_lib_preallocate_sg_pages_for_all(chip->pci, pcm, 64*1024, 128*1024)) < 0)
 		return err;
 
 	return 0;
@@ -1242,7 +1242,7 @@
 	/* capture */
 	init_viadev(chip, chip->capture_devno, VIA_REG_CAPTURE_8233_STATUS, 1);
 
-	if ((err = snd_pcm_lib_preallocate_sg_pages_for_all(chip->pci, pcm)) < 0)
+	if ((err = snd_pcm_lib_preallocate_sg_pages_for_all(chip->pci, pcm, 64*1024, 128*1024)) < 0)
 		return err;
 
 	/* PCM #1:  DXS3 playback (for spdif) */
@@ -1255,7 +1255,7 @@
 	/* set up playback */
 	init_viadev(chip, chip->playback_devno, 0x30, 0);
 
-	if ((err = snd_pcm_lib_preallocate_sg_pages_for_all(chip->pci, pcm)) < 0)
+	if ((err = snd_pcm_lib_preallocate_sg_pages_for_all(chip->pci, pcm, 64*1024, 128*1024)) < 0)
 		return err;
 
 	return 0;
@@ -1284,7 +1284,7 @@
 	init_viadev(chip, 0, VIA_REG_PLAYBACK_STATUS, 0);
 	init_viadev(chip, 1, VIA_REG_CAPTURE_STATUS, 1);
 
-	if ((err = snd_pcm_lib_preallocate_sg_pages_for_all(chip->pci, pcm)) < 0)
+	if ((err = snd_pcm_lib_preallocate_sg_pages_for_all(chip->pci, pcm, 64*1024, 128*1024)) < 0)
 		return err;
 
 	return 0;
@@ -1437,6 +1437,11 @@
 	chip->ac97 = NULL;
 }
 
+static struct ac97_quirk ac97_quirks[] = {
+	{ 0x1106, 0x4161, AC97_TUNE_HP_ONLY }, /* ASRock K7VT2 */
+	{ } /* terminator */
+};
+
 static int __devinit snd_via82xx_mixer_new(via82xx_t *chip)
 {
 	ac97_t ac97;
@@ -1452,6 +1457,8 @@
 	if ((err = snd_ac97_mixer(chip->card, &ac97, &chip->ac97)) < 0)
 		return err;
 
+	snd_ac97_tune_hardware(&chip->ac97, chip->pci, ac97_quirks);
+
 	if (chip->chip_type != TYPE_VIA686) {
 		/* use slot 10/11 */
 		snd_ac97_update_bits(chip->ac97, AC97_EXTENDED_STATUS, 0x03 << 4, 0x03 << 4);
@@ -1862,7 +1869,7 @@
 				break;
 			}
 		}
-		if (chip_type == VIA_REV_8233A)
+		if (chip_type == TYPE_VIA8233A)
 			strcpy(card->driver, "VIA8233A");
 		else
 			strcpy(card->driver, "VIA8233");
@@ -1884,7 +1891,7 @@
 		    (err = snd_via686_init_misc(chip, dev)) < 0)
 			goto __error;
 	} else {
-		if (chip_type == VIA_REV_8233A) {
+		if (chip_type == TYPE_VIA8233A) {
 			if ((err = snd_via8233a_pcm_new(chip)) < 0)
 				goto __error;
 		} else {
diff -Nru a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c
--- a/sound/usb/usbaudio.c	Mon Feb 17 14:57:27 2003
+++ b/sound/usb/usbaudio.c	Mon Feb 17 14:57:27 2003
@@ -2236,10 +2236,49 @@
 	return 0;
 }
 
+
+/*
+ * boot quirks
+ */
+
+#define EXTIGY_FIRMWARE_SIZE_OLD 794
+#define EXTIGY_FIRMWARE_SIZE_NEW 483
+
+static int snd_usb_boot_quirk(struct usb_device *dev,
+			      struct usb_interface *intf,
+			      const snd_usb_audio_quirk_t *quirk)
+{
+	struct usb_host_config *config = dev->actconfig;
+
+	/* FIXME: we need to handle composite type quirks later.. */
+	switch (quirk->type) {
+	case QUIRK_BOOT_EXTIGY:
+		snd_printdd(KERN_INFO "extigy_boot: boot length = %d\n", get_cfg_desc(config)->wTotalLength);
+		if (get_cfg_desc(config)->wTotalLength == EXTIGY_FIRMWARE_SIZE_OLD ||
+		    get_cfg_desc(config)->wTotalLength == EXTIGY_FIRMWARE_SIZE_NEW) {
+			/* Send message to force it to reconnect with full interface. */
+			usb_control_msg(dev, usb_sndctrlpipe(dev,0),
+					0x10, 0x43, 0x0001, 0x000a, NULL, 0, HZ);
+			usb_get_device_descriptor(dev);
+			usb_set_configuration(dev, get_cfg_desc(config)->bConfigurationValue);
+			return -ENODEV; /* quit this anyway */
+		}
+		return 0;
+	}
+	return 0;
+}
+
+
+/*
+ * audio-interface quirks
+ */
 static int snd_usb_create_quirk(snd_usb_audio_t *chip,
 				struct usb_interface *iface,
 				const snd_usb_audio_quirk_t *quirk)
 {
+	if (quirk->type & QUIRK_BOOT_MASK)
+		return 1; /* continue as the normal device */
+
 	switch (quirk->type) {
 	case QUIRK_MIDI_FIXED_ENDPOINT:
 	case QUIRK_MIDI_YAMAHA:
@@ -2417,7 +2456,7 @@
 {
 	struct usb_host_config *config = dev->actconfig;
 	const snd_usb_audio_quirk_t *quirk = (const snd_usb_audio_quirk_t *)usb_id->driver_info;
-	int i;
+	int i, err;
 	snd_card_t *card;
 	snd_usb_audio_t *chip;
 	struct usb_host_interface *alts;
@@ -2434,6 +2473,12 @@
 		goto __err_val;
 	}
 
+	if (quirk) {
+		/* try to check the boot quirk */
+		if (snd_usb_boot_quirk(dev, intf, quirk) < 0)
+			goto __err_val;
+	}
+
 	/*
 	 * found a config.  now register to ALSA
 	 */
@@ -2478,8 +2523,15 @@
 		}
 	}
 
-	if (!quirk) {
-		/* USB audio interface */
+	err = 1; /* continue */
+	if (quirk) {
+		/* need some special handlings */
+		if ((err = snd_usb_create_quirk(chip, intf, quirk)) < 0)
+			goto __error;
+	}
+
+	if (err > 0) {
+		/* create normal USB audio interfaces */
 		unsigned char *buffer;
 		unsigned int index;
 		int buflen;
@@ -2494,10 +2546,6 @@
 			goto __error;
 		}
 		kfree(buffer);
-	} else {
-		/* USB midi interface */
-		if (snd_usb_create_quirk(chip, intf, quirk) < 0)
-			goto __error;
 	}
 
 	/* we are allowed to call snd_card_register() many times */
diff -Nru a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h
--- a/sound/usb/usbaudio.h	Mon Feb 17 14:57:27 2003
+++ b/sound/usb/usbaudio.h	Mon Feb 17 14:57:27 2003
@@ -154,6 +154,9 @@
 #define QUIRK_COMPOSITE			3
 #define QUIRK_AUDIO_FIXED_ENDPOINT	4
 
+#define QUIRK_BOOT_MASK			0x80
+#define QUIRK_BOOT_EXTIGY		(QUIRK_BOOT_MASK | 0)
+
 typedef struct snd_usb_audio_quirk snd_usb_audio_quirk_t;
 typedef struct snd_usb_midi_endpoint_info snd_usb_midi_endpoint_info_t;
 
diff -Nru a/sound/usb/usbquirks.h b/sound/usb/usbquirks.h
--- a/sound/usb/usbquirks.h	Mon Feb 17 14:57:27 2003
+++ b/sound/usb/usbquirks.h	Mon Feb 17 14:57:27 2003
@@ -691,4 +691,20 @@
 	}
 },
 
+/*
+ * Boot-up quirks
+ */
+/* Extigy needs to send a vendor-specific control to boot up the
+ * correct interface
+ */
+{
+	USB_DEVICE(0x041e, 0x3000),
+	.driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
+		.vendor_name = "CreativeLabs",
+		.product_name = "Sound Blaster Extigy",
+		.ifnum = QUIRK_ANY_INTERFACE,
+		.type = QUIRK_BOOT_EXTIGY
+	}
+},
+
 #undef USB_DEVICE_VENDOR_SPEC
