## Automatically generated incremental diff
## From:   linux-2.5.63-bk7
## To:     linux-2.5.64
## Robot:  $Id: make-incremental-diff,v 1.11 2002/02/20 02:59:33 hpa Exp $

diff -urN linux-2.5.63-bk7/Documentation/ioctl-number.txt linux-2.5.64/Documentation/ioctl-number.txt
--- linux-2.5.63-bk7/Documentation/ioctl-number.txt	Mon Feb 24 11:05:45 2003
+++ linux-2.5.64/Documentation/ioctl-number.txt	Mon Mar 31 12:22:14 2003
@@ -72,6 +72,7 @@
 		linux/blkpg.h
 0x20	all	drivers/cdrom/cm206.h
 0x22	all	scsi/sg.h
+'#'	00-3F	IEEE 1394 Subsystem	Block for the entire subsystem
 '1'	00-1F	<linux/timepps.h>	PPS kit from Ulrich Windl
 					<ftp://ftp.de.kernel.org/pub/linux/daemons/ntp/PPS/>
 '6'	00-10	<asm-i386/processor.h>	Intel IA32 microcode update driver
diff -urN linux-2.5.63-bk7/Makefile linux-2.5.64/Makefile
--- linux-2.5.63-bk7/Makefile	Mon Mar 31 12:22:10 2003
+++ linux-2.5.64/Makefile	Mon Mar 31 12:22:14 2003
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 5
-SUBLEVEL = 63
-EXTRAVERSION = bk7
+SUBLEVEL = 64
+EXTRAVERSION =
 
 # *DOCUMENTATION*
 # To see a list of typical targets execute "make help"
diff -urN linux-2.5.63-bk7/arch/sparc64/kernel/setup.c linux-2.5.64/arch/sparc64/kernel/setup.c
--- linux-2.5.63-bk7/arch/sparc64/kernel/setup.c	Mon Feb 24 11:05:15 2003
+++ linux-2.5.64/arch/sparc64/kernel/setup.c	Mon Mar 31 12:22:19 2003
@@ -688,6 +688,7 @@
 	sparc64_cpus = kmalloc(NR_CPUS * sizeof(struct cpu), GFP_KERNEL);
 	if (!sparc64_cpus)
 		return -ENOMEM;
+	memset(sparc64_cpus, 0, NR_CPUS * sizeof(struct cpu));
 	for (i = 0; i < NR_CPUS; i++) {
 		if (cpu_possible(i))
 			register_cpu(&sparc64_cpus[i], i, NULL);
diff -urN linux-2.5.63-bk7/drivers/base/Makefile linux-2.5.64/drivers/base/Makefile
--- linux-2.5.63-bk7/drivers/base/Makefile	Mon Feb 24 11:05:40 2003
+++ linux-2.5.64/drivers/base/Makefile	Mon Mar 31 12:22:20 2003
@@ -2,7 +2,7 @@
 
 obj-y			:= core.o sys.o interface.o power.o bus.o \
 			   driver.o class.o intf.o platform.o \
-			   cpu.o firmware.o
+			   cpu.o firmware.o init.o
 obj-$(CONFIG_NUMA)	+= node.o  memblk.o
 obj-y			+= fs/
 obj-$(CONFIG_HOTPLUG)	+= hotplug.o
diff -urN linux-2.5.63-bk7/drivers/base/bus.c linux-2.5.64/drivers/base/bus.c
--- linux-2.5.63-bk7/drivers/base/bus.c	Mon Mar 31 12:22:10 2003
+++ linux-2.5.64/drivers/base/bus.c	Mon Mar 31 12:22:20 2003
@@ -544,12 +544,11 @@
 	subsystem_unregister(&bus->subsys);
 }
 
-static int __init bus_subsys_init(void)
+int __init buses_init(void)
 {
 	return subsystem_register(&bus_subsys);
 }
 
-core_initcall(bus_subsys_init);
 
 EXPORT_SYMBOL(bus_for_each_dev);
 EXPORT_SYMBOL(bus_for_each_drv);
diff -urN linux-2.5.63-bk7/drivers/base/class.c linux-2.5.64/drivers/base/class.c
--- linux-2.5.63-bk7/drivers/base/class.c	Mon Mar 31 12:22:10 2003
+++ linux-2.5.64/drivers/base/class.c	Mon Mar 31 12:22:20 2003
@@ -266,13 +266,11 @@
 	subsystem_unregister(&cls->subsys);
 }
 
-static int __init class_subsys_init(void)
+int __init classes_init(void)
 {
 	return subsystem_register(&class_subsys);
 }
 
-core_initcall(class_subsys_init);
-
 EXPORT_SYMBOL(devclass_create_file);
 EXPORT_SYMBOL(devclass_remove_file);
 EXPORT_SYMBOL(devclass_register);
diff -urN linux-2.5.63-bk7/drivers/base/core.c linux-2.5.64/drivers/base/core.c
--- linux-2.5.63-bk7/drivers/base/core.c	Mon Mar 31 12:22:10 2003
+++ linux-2.5.64/drivers/base/core.c	Mon Mar 31 12:22:20 2003
@@ -309,13 +309,11 @@
 	put_device(dev);
 }
 
-static int __init device_subsys_init(void)
+int __init devices_init(void)
 {
 	return subsystem_register(&devices_subsys);
 }
 
-core_initcall(device_subsys_init);
-
 EXPORT_SYMBOL(device_initialize);
 EXPORT_SYMBOL(device_add);
 EXPORT_SYMBOL(device_register);
diff -urN linux-2.5.63-bk7/drivers/base/cpu.c linux-2.5.64/drivers/base/cpu.c
--- linux-2.5.63-bk7/drivers/base/cpu.c	Mon Feb 24 11:05:15 2003
+++ linux-2.5.64/drivers/base/cpu.c	Mon Mar 31 12:22:20 2003
@@ -46,9 +46,8 @@
 }
 
 
-static int __init register_cpu_type(void)
+int __init cpu_dev_init(void)
 {
 	devclass_register(&cpu_devclass);
 	return driver_register(&cpu_driver);
 }
-postcore_initcall(register_cpu_type);
diff -urN linux-2.5.63-bk7/drivers/base/firmware.c linux-2.5.64/drivers/base/firmware.c
--- linux-2.5.63-bk7/drivers/base/firmware.c	Mon Feb 24 11:05:33 2003
+++ linux-2.5.64/drivers/base/firmware.c	Mon Mar 31 12:22:20 2003
@@ -19,12 +19,10 @@
 	subsystem_unregister(s);
 }
 
-static int __init firmware_init(void)
+int __init firmware_init(void)
 {
 	return subsystem_register(&firmware_subsys);
 }
 
-core_initcall(firmware_init);
-
 EXPORT_SYMBOL(firmware_register);
 EXPORT_SYMBOL(firmware_unregister);
diff -urN linux-2.5.63-bk7/drivers/base/hotplug.c linux-2.5.64/drivers/base/hotplug.c
--- linux-2.5.63-bk7/drivers/base/hotplug.c	Mon Feb 24 11:05:05 2003
+++ linux-2.5.64/drivers/base/hotplug.c	Mon Mar 31 12:22:20 2003
@@ -17,6 +17,8 @@
 #include <linux/err.h>
 #include <linux/kmod.h>
 #include <linux/interrupt.h>
+#include <linux/sched.h>
+#include <linux/string.h>
 #include "base.h"
 #include "fs/fs.h"
 
diff -urN linux-2.5.63-bk7/drivers/base/init.c linux-2.5.64/drivers/base/init.c
--- linux-2.5.63-bk7/drivers/base/init.c	Wed Dec 31 16:00:00 1969
+++ linux-2.5.64/drivers/base/init.c	Mon Mar 31 12:22:20 2003
@@ -0,0 +1,34 @@
+
+#include <linux/device.h>
+#include <linux/init.h>
+
+extern int devices_init(void);
+extern int buses_init(void);
+extern int classes_init(void);
+extern int firmware_init(void);
+extern int platform_bus_init(void);
+extern int sys_bus_init(void);
+extern int cpu_dev_init(void);
+
+/**
+ *	driver_init - initialize driver model.
+ *
+ *	Call the driver model init functions to initialize their
+ *	subsystems. Called early from init/main.c.
+ */
+
+void __init driver_init(void)
+{
+	/* These are the core pieces */
+	devices_init();
+	buses_init();
+	classes_init();
+	firmware_init();
+
+	/* These are also core pieces, but must come after the 
+	 * core core pieces.
+	 */
+	platform_bus_init();
+	sys_bus_init();
+	cpu_dev_init();
+}
diff -urN linux-2.5.63-bk7/drivers/base/platform.c linux-2.5.64/drivers/base/platform.c
--- linux-2.5.63-bk7/drivers/base/platform.c	Mon Feb 24 11:05:09 2003
+++ linux-2.5.64/drivers/base/platform.c	Mon Mar 31 12:22:20 2003
@@ -41,9 +41,29 @@
 	if (pdev)
 		device_unregister(&pdev->dev);
 }
-	
+
+
+/**
+ *	platform_match - bind platform device to platform driver.
+ *	@dev:	device.
+ *	@drv:	driver.
+ *
+ *	Platform device IDs are assumed to be encoded like this: 
+ *	"<name><instance>", where <name> is a short description of the 
+ *	type of device, like "pci" or "floppy", and <instance> is the 
+ *	enumerated instance of the device, like '0' or '42'.
+ *	Driver IDs are simply "<name>". 
+ *	So, extract the <name> from the device, and compare it against 
+ *	the name of the driver. Return whether they match or not.
+ */
+
 static int platform_match(struct device * dev, struct device_driver * drv)
 {
+	char name[BUS_ID_SIZE];
+
+	if (sscanf(dev->bus_id,"%s",name))
+		return (strcmp(name,drv->name) == 0);
+
 	return 0;
 }
 
@@ -52,13 +72,11 @@
 	.match		= platform_match,
 };
 
-static int __init platform_bus_init(void)
+int __init platform_bus_init(void)
 {
 	device_register(&legacy_bus);
 	return bus_register(&platform_bus_type);
 }
 
-postcore_initcall(platform_bus_init);
-
 EXPORT_SYMBOL(platform_device_register);
 EXPORT_SYMBOL(platform_device_unregister);
diff -urN linux-2.5.63-bk7/drivers/base/sys.c linux-2.5.64/drivers/base/sys.c
--- linux-2.5.63-bk7/drivers/base/sys.c	Mon Feb 24 11:05:04 2003
+++ linux-2.5.64/drivers/base/sys.c	Mon Mar 31 12:22:20 2003
@@ -138,13 +138,12 @@
 	.name		= "system",
 };
 
-static int sys_bus_init(void)
+int __init sys_bus_init(void)
 {
 	bus_register(&system_bus_type);
 	return device_register(&system_bus);
 }
 
-postcore_initcall(sys_bus_init);
 EXPORT_SYMBOL(system_bus_type);
 EXPORT_SYMBOL(sys_device_register);
 EXPORT_SYMBOL(sys_device_unregister);
diff -urN linux-2.5.63-bk7/drivers/ieee1394/Makefile linux-2.5.64/drivers/ieee1394/Makefile
--- linux-2.5.63-bk7/drivers/ieee1394/Makefile	Mon Feb 24 11:06:01 2003
+++ linux-2.5.64/drivers/ieee1394/Makefile	Mon Mar 31 12:22:20 2003
@@ -18,13 +18,6 @@
 
 clean-files := oui.c
 
-ieee1394.o: $(ieee1394-objs)
-	$(LD) $(LDFLAGS) -r -o $@ $(ieee1394-objs)
-
-ifeq ($(obj),)
-obj = .
-endif
-
 $(obj)/oui.o: $(obj)/oui.c
 $(obj)/oui.c: $(obj)/oui.db $(obj)/oui2c.sh
 	$(CONFIG_SHELL) $(obj)/oui2c.sh < $(obj)/oui.db > $(obj)/oui.c
diff -urN linux-2.5.63-bk7/drivers/ieee1394/amdtp.c linux-2.5.64/drivers/ieee1394/amdtp.c
--- linux-2.5.63-bk7/drivers/ieee1394/amdtp.c	Mon Mar 31 12:22:10 2003
+++ linux-2.5.64/drivers/ieee1394/amdtp.c	Mon Mar 31 12:22:20 2003
@@ -74,6 +74,8 @@
 #include <linux/pci.h>
 #include <linux/interrupt.h>
 #include <linux/poll.h>
+#include <linux/ioctl32.h>
+#include <linux/compat.h>
 #include <asm/uaccess.h>
 #include <asm/atomic.h>
 
@@ -1262,8 +1264,11 @@
 
 static int __init amdtp_init_module (void)
 {
-	if (ieee1394_register_chardev(IEEE1394_MINOR_BLOCK_AMDTP,
-				      THIS_MODULE, &amdtp_fops)) {
+	int ret;
+
+	ret = ieee1394_register_chardev(IEEE1394_MINOR_BLOCK_AMDTP,
+					THIS_MODULE, &amdtp_fops);
+	if (ret) {
 		HPSB_ERR("amdtp: unable to get minor device block");
  		return -EIO;
  	}
@@ -1276,6 +1281,15 @@
 		return -EIO;
 	}
 
+#ifdef CONFIG_COMPAT
+	ret = register_ioctl32_conversion(AMDTP_IOC_CHANNEL, NULL);
+	ret |= register_ioctl32_conversion(AMDTP_IOC_PLUG, NULL);
+	ret |= register_ioctl32_conversion(AMDTP_IOC_PING, NULL);
+	ret |= register_ioctl32_conversion(AMDTP_IOC_ZAP, NULL);
+	if (ret)
+		HPSB_ERR("amdtp: Error registering ioctl32 translations");
+#endif
+
 	HPSB_INFO("Loaded AMDTP driver");
 
 	return 0;
@@ -1283,6 +1297,17 @@
 
 static void __exit amdtp_exit_module (void)
 {
+#ifdef CONFIG_COMPAT
+	int ret;
+
+	ret = unregister_ioctl32_conversion(AMDTP_IOC_CHANNEL);
+	ret |= unregister_ioctl32_conversion(AMDTP_IOC_PLUG);
+	ret |= unregister_ioctl32_conversion(AMDTP_IOC_PING);
+	ret |= unregister_ioctl32_conversion(AMDTP_IOC_ZAP);
+	if (ret)
+		HPSB_ERR("amdtp: Error unregistering ioctl32 translations");
+#endif
+
         hpsb_unregister_highlevel(amdtp_highlevel);
         ieee1394_unregister_chardev(IEEE1394_MINOR_BLOCK_AMDTP);
 
diff -urN linux-2.5.63-bk7/drivers/ieee1394/dma.c linux-2.5.64/drivers/ieee1394/dma.c
--- linux-2.5.63-bk7/drivers/ieee1394/dma.c	Mon Feb 24 11:05:32 2003
+++ linux-2.5.64/drivers/ieee1394/dma.c	Mon Mar 31 12:22:20 2003
@@ -10,6 +10,7 @@
 #include <linux/module.h>
 #include <linux/vmalloc.h>
 #include <linux/slab.h>
+#include <linux/mm.h>
 #include "dma.h"
 
 /* dma_prog_region */
diff -urN linux-2.5.63-bk7/drivers/ieee1394/dv1394.c linux-2.5.64/drivers/ieee1394/dv1394.c
--- linux-2.5.63-bk7/drivers/ieee1394/dv1394.c	Mon Feb 24 11:05:38 2003
+++ linux-2.5.64/drivers/ieee1394/dv1394.c	Mon Mar 31 12:22:20 2003
@@ -111,6 +111,8 @@
 #include <linux/wrapper.h>
 #include <linux/vmalloc.h>
 #include <linux/string.h>
+#include <linux/ioctl32.h>
+#include <linux/compat.h>
 
 #include "ieee1394.h"
 #include "ieee1394_types.h"
@@ -2701,7 +2703,7 @@
 	struct ti_ohci *ohci;
 	struct video_card *video = NULL;
 	unsigned long flags;
-	struct list_head *lh;
+	struct list_head *lh, *templh;
 	char buf[32];
 	int	n;
 	
@@ -2715,7 +2717,7 @@
 	/* find the corresponding video_cards */
 	spin_lock_irqsave(&dv1394_cards_lock, flags);
 	if(!list_empty(&dv1394_cards)) {
-		list_for_each(lh, &dv1394_cards) {
+		list_for_each_safe(lh, templh, &dv1394_cards) {
 			video = list_entry(lh, struct video_card, list);
 			if((video->id >> 2) == ohci->id)
 				dv1394_un_init(video);
@@ -2907,6 +2909,98 @@
 	.host_reset =   dv1394_host_reset,
 };
 
+#ifdef CONFIG_COMPAT
+
+#define DV1394_IOC32_INIT       _IOW('#', 0x06, struct dv1394_init32)
+#define DV1394_IOC32_GET_STATUS _IOR('#', 0x0c, struct dv1394_status32)
+
+struct dv1394_init32 {
+	u32 api_version;
+	u32 channel;
+	u32 n_frames;
+	u32 format;
+	u32 cip_n;
+	u32 cip_d;
+	u32 syt_offset;
+};
+
+struct dv1394_status32 {
+	struct dv1394_init32 init;
+	s32 active_frame;
+	u32 first_clear_frame;
+	u32 n_clear_frames;
+	u32 dropped_frames;
+};
+
+static int handle_dv1394_init(unsigned int fd, unsigned int cmd, unsigned long arg,
+			      struct file *file)
+{
+	struct dv1394_init32 dv32;
+	struct dv1394_init dv;
+	mm_segment_t old_fs;
+	int ret;
+
+	if (file->f_op->ioctl != dv1394_ioctl)
+		return -EFAULT;
+
+	if (copy_from_user(&dv32, (void *)arg, sizeof(dv32)))
+		return -EFAULT;
+
+	dv.api_version = dv32.api_version;
+	dv.channel = dv32.channel;
+	dv.n_frames = dv32.n_frames;
+	dv.format = dv32.format;
+	dv.cip_n = (unsigned long)dv32.cip_n;
+	dv.cip_d = (unsigned long)dv32.cip_d;
+	dv.syt_offset = dv32.syt_offset;
+
+	old_fs = get_fs();
+	set_fs(KERNEL_DS);
+	ret = dv1394_ioctl(file->f_dentry->d_inode, file,
+			   DV1394_IOC_INIT, (unsigned long)&dv);
+	set_fs(old_fs);
+
+	return ret;
+}
+
+static int handle_dv1394_get_status(unsigned int fd, unsigned int cmd, unsigned long arg,
+				    struct file *file)
+{
+	struct dv1394_status32 dv32;
+	struct dv1394_status dv;
+	mm_segment_t old_fs;
+	int ret;
+
+	if (file->f_op->ioctl != dv1394_ioctl)
+		return -EFAULT;
+
+	old_fs = get_fs();
+	set_fs(KERNEL_DS);
+	ret = dv1394_ioctl(file->f_dentry->d_inode, file,
+			   DV1394_IOC_GET_STATUS, (unsigned long)&dv);
+	set_fs(old_fs);
+
+	if (!ret) {
+		dv32.init.api_version = dv.init.api_version;
+		dv32.init.channel = dv.init.channel;
+		dv32.init.n_frames = dv.init.n_frames;
+		dv32.init.format = dv.init.format;
+		dv32.init.cip_n = (u32)dv.init.cip_n;
+		dv32.init.cip_d = (u32)dv.init.cip_d;
+		dv32.init.syt_offset = dv.init.syt_offset;
+		dv32.active_frame = dv.active_frame;
+		dv32.first_clear_frame = dv.first_clear_frame;
+		dv32.n_clear_frames = dv.n_clear_frames;
+		dv32.dropped_frames = dv.dropped_frames;
+
+		if (copy_to_user((struct dv1394_status32 *)arg, &dv32, sizeof(dv32)))
+			ret = -EFAULT;
+	}
+
+	return ret;
+}
+#endif /* CONFIG_COMPAT */
+
 
 /*** KERNEL MODULE HANDLERS ************************************************/
 
@@ -2917,6 +3011,20 @@
 
 static void __exit dv1394_exit_module(void)
 {
+#ifdef CONFIG_COMPAT
+	int ret;
+
+	ret = unregister_ioctl32_conversion(DV1394_IOC_SHUTDOWN);
+	ret |= unregister_ioctl32_conversion(DV1394_IOC_SUBMIT_FRAMES);
+	ret |= unregister_ioctl32_conversion(DV1394_IOC_WAIT_FRAMES);
+	ret |= unregister_ioctl32_conversion(DV1394_IOC_RECEIVE_FRAMES);
+	ret |= unregister_ioctl32_conversion(DV1394_IOC_START_RECEIVE);
+	ret |= unregister_ioctl32_conversion(DV1394_IOC32_INIT);
+	ret |= unregister_ioctl32_conversion(DV1394_IOC32_GET_STATUS);
+	if (ret)
+		printk(KERN_ERR "dv1394: Error unregistering ioctl32 translations\n");
+#endif
+
 	hpsb_unregister_highlevel (hl_handle);
 	ieee1394_unregister_chardev(IEEE1394_MINOR_BLOCK_DV1394);
 #ifdef CONFIG_DEVFS_FS
@@ -2929,14 +3037,18 @@
 
 static int __init dv1394_init_module(void)
 {
-	if (ieee1394_register_chardev(IEEE1394_MINOR_BLOCK_DV1394,
-				      THIS_MODULE, &dv1394_fops)) {
+	int ret;
+
+	ret = ieee1394_register_chardev(IEEE1394_MINOR_BLOCK_DV1394,
+					THIS_MODULE, &dv1394_fops);
+	if (ret) {
 		printk(KERN_ERR "dv1394: unable to register character device\n");
 		return -EIO;
 	}
 
 #ifdef CONFIG_DEVFS_FS
-	if (dv1394_devfs_add_dir("dv", NULL, NULL) < 0) {
+	ret = dv1394_devfs_add_dir("dv", NULL, NULL);
+	if (ret < 0) {
 		printk(KERN_ERR "dv1394: unable to create /dev/ieee1394/dv\n");
 		ieee1394_unregister_chardev(IEEE1394_MINOR_BLOCK_DV1394);
 		return -ENOMEM;
@@ -2944,7 +3056,8 @@
 #endif
 
 #ifdef CONFIG_PROC_FS
-	if (dv1394_procfs_add_dir("dv",NULL,NULL) < 0) {
+	ret = dv1394_procfs_add_dir("dv",NULL,NULL);
+	if (ret < 0) {
 		printk(KERN_ERR "dv1394: unable to create /proc/bus/ieee1394/dv\n");
 		ieee1394_unregister_chardev(IEEE1394_MINOR_BLOCK_DV1394);
 #ifdef CONFIG_DEVFS_FS
@@ -2967,9 +3080,23 @@
 		return -ENOMEM;
 	}
 
+#ifdef CONFIG_COMPAT
+	/* First compatible ones */
+	ret = register_ioctl32_conversion(DV1394_IOC_SHUTDOWN, NULL);
+	ret |= register_ioctl32_conversion(DV1394_IOC_SUBMIT_FRAMES, NULL);
+	ret |= register_ioctl32_conversion(DV1394_IOC_WAIT_FRAMES, NULL);
+	ret |= register_ioctl32_conversion(DV1394_IOC_RECEIVE_FRAMES, NULL);
+	ret |= register_ioctl32_conversion(DV1394_IOC_START_RECEIVE, NULL);
+
+	/* These need to be handled by translation */
+	ret |= register_ioctl32_conversion(DV1394_IOC32_INIT, handle_dv1394_init);
+	ret |= register_ioctl32_conversion(DV1394_IOC32_GET_STATUS, handle_dv1394_get_status);
+	if (ret)
+		printk(KERN_ERR "dv1394: Error registering ioctl32 translations\n");
+#endif
+
 	return 0;
 }
 
 module_init(dv1394_init_module);
 module_exit(dv1394_exit_module);
-
diff -urN linux-2.5.63-bk7/drivers/ieee1394/eth1394.c linux-2.5.64/drivers/ieee1394/eth1394.c
--- linux-2.5.63-bk7/drivers/ieee1394/eth1394.c	Mon Mar 31 12:22:10 2003
+++ linux-2.5.64/drivers/ieee1394/eth1394.c	Mon Mar 31 12:22:20 2003
@@ -65,6 +65,7 @@
 #include "ieee1394_transactions.h"
 #include "ieee1394.h"
 #include "highlevel.h"
+#include "iso.h"
 #include "eth1394.h"
 
 #define ETH1394_PRINT_G(level, fmt, args...) \
@@ -77,7 +78,7 @@
 	printk(KERN_ERR fmt, ## args)
 
 static char version[] __devinitdata =
-	"$Rev: 770 $ Ben Collins <bcollins@debian.org>";
+	"$Rev: 806 $ Ben Collins <bcollins@debian.org>";
 
 /* Our ieee1394 highlevel driver */
 #define ETHER1394_DRIVER_NAME "ether1394"
@@ -101,6 +102,9 @@
 MODULE_DESCRIPTION("IEEE 1394 IPv4 Driver (IPv4-over-1394 as per RFC 2734)");
 MODULE_LICENSE("GPL");
 
+static void ether1394_iso(struct hpsb_iso *iso);
+
+
 /* Find our host_info struct for a given host pointer. Must be called
  * under spinlock.  */
 static inline struct host_info *find_host_info (struct hpsb_host *host)
@@ -178,15 +182,26 @@
  * XXX: This is where we need to create a list of skb's for fragmented
  * packets.  */
 static inline void ether1394_encapsulate (struct sk_buff *skb, struct net_device *dev,
-			    int proto)
+                                          int proto, struct packet_task *ptask)
 {
 	union eth1394_hdr *hdr =
 		(union eth1394_hdr *)skb_push (skb, hdr_type_len[ETH1394_HDR_LF_UF]);
 
+	hdr->words.word1 = 0;
 	hdr->common.lf = ETH1394_HDR_LF_UF;
 	hdr->words.word1 = htons(hdr->words.word1);
 	hdr->uf.ether_type = proto;
 
+	/* Set the transmission type for the packet.  Right now only ARP
+	 * packets are sent via GASP.  IP broadcast and IP multicast are not
+	 * yet supported properly, they too should use GASP. */
+	switch(proto) {
+	case __constant_htons(ETH_P_ARP):
+		ptask->tx_type = ETH1394_GASP;
+		break;
+	default:
+		ptask->tx_type = ETH1394_WRREQ;
+	}
 	return;
 }
 
@@ -199,14 +214,14 @@
 {
 	struct eth1394_priv *priv =
 		(struct eth1394_priv *)(dev->priv);
-	u16 phy_id = priv->host->node_id & NODE_MASK;
+	u16 phy_id = NODEID_TO_NODE(priv->host->node_id);
 
 	unsigned char *arp_ptr = (unsigned char *)skb->data;
 	struct eth1394_arp *arp1394 = (struct eth1394_arp *)skb->data;
 	unsigned char arp_data[2*(dev->addr_len+4)];
 
 	/* Copy the main data that we need */
-	arp_ptr = memcpy (arp_data, arp_ptr + sizeof(struct arphdr), sizeof (arp_data));
+	memcpy (arp_data, arp_ptr + sizeof(struct arphdr), sizeof (arp_data));
 
 	/* Extend the buffer enough for our new header */
 	skb_put (skb, sizeof (struct eth1394_arp) -
@@ -214,7 +229,7 @@
 
 #define PROCESS_MEMBER(ptr,val,len) \
   memcpy (val, ptr, len); ptr += len
-	arp_ptr += arp1394->hw_addr_len;
+	arp_ptr = arp_data + arp1394->hw_addr_len;
 	PROCESS_MEMBER (arp_ptr, &arp1394->sip, arp1394->ip_addr_len);
 	arp_ptr += arp1394->hw_addr_len;
 	PROCESS_MEMBER (arp_ptr, &arp1394->tip, arp1394->ip_addr_len);
@@ -279,7 +294,8 @@
 {
 	unsigned long flags;
 	struct eth1394_priv *priv = (struct eth1394_priv *)dev->priv;
-	int phy_id = priv->host->node_id & NODE_MASK;
+	int phy_id = NODEID_TO_NODE(priv->host->node_id);
+	struct hpsb_host *host = priv->host;
 
 	spin_lock_irqsave (&priv->lock, flags);
 
@@ -289,20 +305,23 @@
 	memset (priv->fifo_hi, 0, sizeof (priv->fifo_hi));
 	memset (priv->fifo_lo, 0, sizeof (priv->fifo_lo));
 
+	priv->bc_state = ETHER1394_BC_CHECK;
+
 	/* Register our limits now */
-	ether1394_register_limits (phy_id, (be32_to_cpu(priv->host->csr.rom[2]) >> 12) & 0xf,
-				   priv->host->speed_map[(phy_id << 6) + phy_id],
-				   (u64)(((u64)be32_to_cpu(priv->host->csr.rom[3]) << 32) |
-				   be32_to_cpu(priv->host->csr.rom[4])),
+	ether1394_register_limits (phy_id, (be32_to_cpu(host->csr.rom[2]) >> 12) & 0xf,
+				   host->speed_map[(phy_id << 6) + phy_id],
+				   (u64)(((u64)be32_to_cpu(host->csr.rom[3]) << 32) |
+				   be32_to_cpu(host->csr.rom[4])),
 				   ETHER1394_REGION_ADDR >> 32,
 				   ETHER1394_REGION_ADDR & 0xffffffff, priv);
 
 	/* We'll use our max_rec as the default mtu */
 	if (set_mtu)
-		dev->mtu = (1 << (priv->max_rec[phy_id] + 1)) - sizeof (union eth1394_hdr);
+		dev->mtu = (1 << (priv->max_rec[phy_id] + 1)) - /* mtu = max_rec - */
+			(sizeof (union eth1394_hdr) + 8);	/* (hdr + GASP) */
 
 	/* Set our hardware address while we're at it */
-	*(nodeid_t *)dev->dev_addr = htons (priv->host->node_id);
+	*(nodeid_t *)dev->dev_addr = htons (host->node_id);
 
 	spin_unlock_irqrestore (&priv->lock, flags);
 }
@@ -383,6 +402,15 @@
 	list_add_tail (&hi->list, &host_info_list);
 	spin_unlock_irq (&host_info_lock);
 
+	/* Ignore validity in hopes that it will be set in the future.  It'll
+	 * check it on transmit. */
+	priv->broadcast_channel = host->csr.broadcast_channel & 0x3f;
+
+	priv->iso = hpsb_iso_recv_init(host, 8 * 4096, 8, priv->broadcast_channel,
+				       1, ether1394_iso);
+	if (priv->iso == NULL) {
+		priv->bc_state = ETHER1394_BC_CLOSED;
+	}
 	return;
 
 out:
@@ -396,11 +424,14 @@
 /* Remove a card from our list */
 static void ether1394_remove_host (struct hpsb_host *host)
 {
+	struct eth1394_priv *priv;
 	struct host_info *hi;
 
 	spin_lock_irq (&host_info_lock);
 	hi = find_host_info (host);
 	if (hi != NULL) {
+		priv = (struct eth1394_priv *)hi->dev->priv;
+		priv->bc_state = ETHER1394_BC_CLOSED;
 		unregister_netdev (hi->dev);
 		kfree (hi->dev);
 		list_del (&hi->list);
@@ -480,7 +511,7 @@
 	 * about the sending machine.  */
 	if (hdr->uf.ether_type == __constant_htons (ETH_P_ARP)) {
 		unsigned long flags;
-		u16 phy_id = srcid & NODE_MASK;
+		u16 phy_id = NODEID_TO_NODE(srcid);
 		struct eth1394_priv *priv =
 			(struct eth1394_priv *)dev->priv;
 		struct eth1394_arp arp1394;
@@ -498,7 +529,7 @@
 		spin_unlock_irqrestore (&priv->lock, flags);
 
 #define PROCESS_MEMBER(ptr,val,len) \
-  ptr = memcpy (ptr, val, len) + len
+  memcpy (ptr, val, len); ptr += len
                 PROCESS_MEMBER (arp_ptr, src_hw, dev->addr_len);
                 PROCESS_MEMBER (arp_ptr, &arp1394.sip, 4);
                 PROCESS_MEMBER (arp_ptr, dest_hw, dev->addr_len);
@@ -591,6 +622,104 @@
 	return RCODE_COMPLETE;
 }
 
+static void ether1394_iso(struct hpsb_iso *iso)
+{
+	struct sk_buff *skb;
+	quadlet_t *data;
+	char *buf;
+	int flags;
+	struct net_device *dev = ether1394_find_dev(iso->host);
+	struct eth1394_priv *priv;
+	unsigned int len;
+	u32 specifier_id;
+	u16 source_id;
+	int i;
+	int nready;
+
+	if (dev == NULL) {
+		ETH1394_PRINT_G (KERN_ERR, "Could not find net device for host %s\n",
+				 iso->host->driver->name);
+		return;
+	}
+
+	nready = hpsb_iso_n_ready(iso);
+	for(i = 0; i < nready; i++) {
+		struct hpsb_iso_packet_info *info = &iso->infos[iso->first_packet + i];
+		data = (quadlet_t*) (iso->data_buf.kvirt + info->offset);
+
+		/* skip over GASP header */
+		buf = (char *)data + 8;
+		len = info->len - 8;
+
+		specifier_id = (((be32_to_cpu(data[0]) & 0xffff) << 8) |
+				((be32_to_cpu(data[1]) & 0xff000000) >> 24));
+		source_id = be32_to_cpu(data[0]) >> 16;
+
+		priv = (struct eth1394_priv *)dev->priv;
+
+		if (info->channel != priv->broadcast_channel ||
+		    specifier_id != ETHER1394_GASP_SPECIFIER_ID) {
+			/* This packet is not for us */
+			continue;
+		}
+
+		/* A packet has been received by the ieee1394 bus. Build an skbuff
+		 * around it so we can pass it to the high level network layer. */
+		skb = dev_alloc_skb (len + dev->hard_header_len + 15);
+		if (!skb) {
+			HPSB_PRINT (KERN_ERR, "ether1394 rx: low on mem\n");
+			priv->stats.rx_dropped++;
+			break;
+		}
+
+		skb_reserve(skb, (dev->hard_header_len + 15) & ~15);
+
+		memcpy (skb_put (skb, len), buf, len);
+
+		/* Write metadata, and then pass to the receive level */
+		skb->dev = dev;
+		skb->ip_summed = CHECKSUM_UNNECESSARY;	/* don't check it */
+
+		/* Parse the encapsulation header. This actually does the job of
+		 * converting to an ethernet frame header, aswell as arp
+		 * conversion if needed. ARP conversion is easier in this
+		 * direction, since we are using ethernet as our backend.  */
+		skb->protocol = ether1394_parse_encap (skb, dev, source_id,
+						       LOCAL_BUS | ALL_NODES);
+
+		spin_lock_irqsave (&priv->lock, flags);
+		if (!skb->protocol) {
+			priv->stats.rx_errors++;
+			priv->stats.rx_dropped++;
+			dev_kfree_skb_any(skb);
+			goto bad_proto;
+		}
+
+		netif_stop_queue(dev);
+		if (netif_rx (skb) == NET_RX_DROP) {
+			priv->stats.rx_errors++;
+			priv->stats.rx_dropped++;
+			goto bad_proto;
+		}
+
+		/* Statistics */
+		priv->stats.rx_packets++;
+		priv->stats.rx_bytes += skb->len;
+
+	bad_proto:
+		spin_unlock_irqrestore (&priv->lock, flags);
+	}
+
+	hpsb_iso_recv_release_packets(iso, i);
+
+	netif_start_queue(dev);
+	
+	dev->last_rx = jiffies;
+
+	return;
+}
+
+
 /* This function is our scheduled write */
 static void hpsb_write_sched (void *__ptask)
 {
@@ -598,13 +727,26 @@
 	struct sk_buff *skb = ptask->skb;
 	struct net_device *dev = ptask->skb->dev;
 	struct eth1394_priv *priv = (struct eth1394_priv *)dev->priv;
-        unsigned long flags;
+	unsigned long flags;
+	int status;
+ 
+	if (ptask->tx_type == ETH1394_GASP) {
+		status  = hpsb_send_gasp(priv->host, priv->broadcast_channel,
+					 get_hpsb_generation(priv->host),
+					 (quadlet_t *)skb->data, skb->len,
+					 ETHER1394_GASP_SPECIFIER_ID,
+					 ETHER1394_GASP_VERSION);
+	} else {
+		status = hpsb_write(priv->host, ptask->dest_node,
+				    get_hpsb_generation(priv->host),
+				    ptask->addr, (quadlet_t *)skb->data,
+				    skb->len);
+	}
+
 
 	/* Statistics */
 	spin_lock_irqsave (&priv->lock, flags);
-	if (!hpsb_write(priv->host, ptask->dest_node,
-			get_hpsb_generation(priv->host),
-			ptask->addr, (quadlet_t *)skb->data, skb->len)) {
+	if (!status) {
 		priv->stats.tx_bytes += skb->len;
 		priv->stats.tx_packets++;
 	} else {
@@ -636,6 +778,67 @@
 	struct packet_task *ptask = NULL;
 	int ret = 0;
 
+	spin_lock_irqsave (&priv->lock, flags);
+	if (priv->bc_state == ETHER1394_BC_CLOSED) {
+		ETH1394_PRINT(KERN_ERR, dev->name,
+			      "Cannot send packet, no broadcast channel available.");
+		ret = -EAGAIN;
+		goto fail;
+	}
+
+	/* First time sending?  Need a broadcast channel for ARP and for
+	 * listening on */
+	if (priv->bc_state == ETHER1394_BC_CHECK) {
+		quadlet_t bc;
+
+		/* Get the local copy of the broadcast channel and check its
+		 * validity (the IRM should validate it for us) */
+
+		bc = priv->host->csr.broadcast_channel;
+
+		if ((bc & 0xc0000000) != 0xc0000000) {
+			/* broadcast channel not validated yet */
+			ETH1394_PRINT(KERN_WARNING, dev->name,
+				      "Error BROADCAST_CHANNEL register valid "
+				      "bit not set, can't send IP traffic\n");
+			hpsb_iso_shutdown(priv->iso);
+			priv->bc_state = ETHER1394_BC_CLOSED;
+			ret = -EAGAIN;
+			spin_unlock_irqrestore (&priv->lock, flags);
+			goto fail;
+		}
+		if (priv->broadcast_channel != (bc & 0x3f)) {
+			/* This really shouldn't be possible, but just in case
+			 * the IEEE 1394 spec changes regarding broadcast
+			 * channels in the future. */
+			hpsb_iso_shutdown(priv->iso);
+
+			priv->broadcast_channel = bc & 0x3f;
+			ETH1394_PRINT(KERN_WARNING, dev->name,
+				      "Changing to broadcast channel %d...\n",
+				      priv->broadcast_channel);
+
+			priv->iso = hpsb_iso_recv_init(priv->host, 8 * 4096,
+						       8, priv->broadcast_channel,
+						       1, ether1394_iso);
+			if (priv->iso == NULL) {
+				ret = -EAGAIN;
+				goto fail;
+			}
+		}
+		if (hpsb_iso_recv_start(priv->iso, -1, (1 << 3), -1) < 0) {
+			ETH1394_PRINT(KERN_ERR, dev->name,
+				      "Could not start async reception\n");
+			hpsb_iso_shutdown(priv->iso);
+			priv->bc_state = ETHER1394_BC_CLOSED;
+			ret = -EAGAIN;
+			spin_unlock_irqrestore (&priv->lock, flags);
+			goto fail;
+		}
+		priv->bc_state = ETHER1394_BC_OPENED;
+	}
+	spin_unlock_irqrestore (&priv->lock, flags);
+
 	if ((skb = skb_share_check (skb, kmflags)) == NULL) {
 		ret = -ENOMEM;
 		goto fail;
@@ -654,8 +857,14 @@
 	if (proto == __constant_htons (ETH_P_ARP))
 		ether1394_arp_to_1394arp (skb, dev);
 
+	ptask = kmem_cache_alloc(packet_task_cache, kmflags);
+	if (ptask == NULL) {
+		ret = -ENOMEM;
+		goto fail;
+	}
+
 	/* Now add our encapsulation header */
-	ether1394_encapsulate (skb, dev, proto);
+	ether1394_encapsulate (skb, dev, proto, ptask);
 
 	/* TODO: The above encapsulate function needs to recognize when a
 	 * packet needs to be split for a specified node. It should create
@@ -667,19 +876,13 @@
 	 * need this hack.  */
 
 	spin_lock_irqsave (&priv->lock, flags);
-	addr = (u64)priv->fifo_hi[dest_node & NODE_MASK] << 32 |
-		priv->fifo_lo[dest_node & NODE_MASK];
+	addr = (u64)priv->fifo_hi[NODEID_TO_NODE(dest_node)] << 32 |
+		priv->fifo_lo[NODEID_TO_NODE(dest_node)];
 	spin_unlock_irqrestore (&priv->lock, flags);
 
 	if (!addr)
 		addr = ETHER1394_REGION_ADDR;
 
-	ptask = kmem_cache_alloc(packet_task_cache, kmflags);
-	if (ptask == NULL) {
-		ret = -ENOMEM;
-		goto fail;
-	}
-
 	ptask->skb = skb;
 	ptask->addr = addr;
 	ptask->dest_node = dest_node;
@@ -702,7 +905,7 @@
 		netif_wake_queue (dev);
 	spin_unlock_irqrestore (&priv->lock, flags);
 
-	return ret;
+	return 0;  /* returning non-zero causes serious problems */
 }
 
 /* Function for incoming 1394 packets */
@@ -738,6 +941,19 @@
 
 static void __exit ether1394_exit_module (void)
 {
+	struct list_head *lh;
+	struct host_info *hi;
+	struct eth1394_priv *priv;
+
+	lh = host_info_list.next;
+	while (lh != &host_info_list) {
+		hi = list_entry (lh, struct host_info, list);
+		priv = (struct eth1394_priv*)hi->dev->priv;
+		if (priv->bc_state != ETHER1394_BC_CLOSED) {
+			hpsb_iso_shutdown(priv->iso);
+		}
+		lh = lh->next;
+	}
 	hpsb_unregister_highlevel (hl_handle);
 	kmem_cache_destroy(packet_task_cache);
 }
diff -urN linux-2.5.63-bk7/drivers/ieee1394/eth1394.h linux-2.5.64/drivers/ieee1394/eth1394.h
--- linux-2.5.63-bk7/drivers/ieee1394/eth1394.h	Mon Feb 24 11:05:42 2003
+++ linux-2.5.64/drivers/ieee1394/eth1394.h	Mon Mar 31 12:22:20 2003
@@ -30,9 +30,16 @@
 #define ETHER1394_REGION_ADDR		0xfffff0200000ULL
 #define ETHER1394_REGION_ADDR_END	(ETHER1394_REGION_ADDR + ETHER1394_REGION_ADDR_LEN)
 
+/* GASP identifier numbers for IPv4 over IEEE 1394 */
+#define ETHER1394_GASP_SPECIFIER_ID	0x00005E
+#define ETHER1394_GASP_VERSION		1
+
 /* Node set == 64 */
 #define NODE_SET			(ALL_NODES + 1)
 
+enum eth1394_bc_states { ETHER1394_BC_CLOSED, ETHER1394_BC_OPENED,
+			 ETHER1394_BC_CHECK };
+
 /* Private structure for our ethernet driver */
 struct eth1394_priv {
 	struct net_device_stats stats;	/* Device stats			 */
@@ -43,6 +50,9 @@
 	u32 fifo_lo[ALL_NODES];		/* 32bit lo fifo offset per node */
 	u64 eui[ALL_NODES];		/* EUI-64 per node		 */
 	spinlock_t lock;		/* Private lock			 */
+	int broadcast_channel;		/* Async stream Broadcast Channel */
+	enum eth1394_bc_states bc_state; /* broadcast channel state	 */
+	struct hpsb_iso *iso;		/* Async stream recv handle	 */
 };
 
 struct host_info {
@@ -51,12 +61,15 @@
 	struct net_device *dev;
 };
 
+typedef enum {ETH1394_GASP, ETH1394_WRREQ} eth1394_tx_type;
+
 /* This is our task struct. It's used for the packet complete callback.  */
 struct packet_task {
 	struct sk_buff *skb;	/* Socket buffer we are sending */
 	nodeid_t dest_node;	/* Destination of the packet */
 	u64 addr;		/* Address */
 	struct hpsb_queue_struct tq;	/* The task */
+	eth1394_tx_type tx_type;	/* Send data via GASP or Write Req. */
 };
 
 /* IP1394 headers */
diff -urN linux-2.5.63-bk7/drivers/ieee1394/hosts.c linux-2.5.64/drivers/ieee1394/hosts.c
--- linux-2.5.63-bk7/drivers/ieee1394/hosts.c	Mon Feb 24 11:05:16 2003
+++ linux-2.5.64/drivers/ieee1394/hosts.c	Mon Mar 31 12:22:20 2003
@@ -71,9 +71,6 @@
         list_for_each(lh, &hosts) {
                 if (host == list_entry(lh, struct hpsb_host, host_list)) {
 			if (try_module_get(host->driver->owner)) {
-				/* we're doing this twice and don't seem
-				   to undo it..  --hch */
-				(void)try_module_get(host->driver->owner);
 				host->refcount++;
 				retval = 1;
 			}
diff -urN linux-2.5.63-bk7/drivers/ieee1394/ieee1394-ioctl.h linux-2.5.64/drivers/ieee1394/ieee1394-ioctl.h
--- linux-2.5.63-bk7/drivers/ieee1394/ieee1394-ioctl.h	Mon Feb 24 11:05:07 2003
+++ linux-2.5.64/drivers/ieee1394/ieee1394-ioctl.h	Mon Mar 31 12:22:20 2003
@@ -4,8 +4,8 @@
 #ifndef __IEEE1394_IOCTL_H
 #define __IEEE1394_IOCTL_H
 
-#include <asm/ioctl.h>
-#include <asm/types.h>
+#include <linux/ioctl.h>
+#include <linux/types.h>
 
 
 /* AMDTP Gets 6 */
@@ -91,7 +91,7 @@
 #define RAW1394_IOC_ISO_RECV_UNLISTEN_CHANNEL	\
 	_IOW ('#', 0x23, unsigned char)
 #define RAW1394_IOC_ISO_RECV_SET_CHANNEL_MASK	\
-	_IOW ('#', 0x24, u64)
+	_IOW ('#', 0x24, __u64)
 #define RAW1394_IOC_ISO_RECV_PACKETS		\
 	_IOW ('#', 0x25, struct raw1394_iso_packets)
 #define RAW1394_IOC_ISO_RECV_RELEASE_PACKETS	\
diff -urN linux-2.5.63-bk7/drivers/ieee1394/ieee1394_core.c linux-2.5.64/drivers/ieee1394/ieee1394_core.c
--- linux-2.5.63-bk7/drivers/ieee1394/ieee1394_core.c	Mon Feb 24 11:05:12 2003
+++ linux-2.5.64/drivers/ieee1394/ieee1394_core.c	Mon Mar 31 12:22:20 2003
@@ -361,7 +361,7 @@
                 host->topology_map[host->selfid_count++] = sid;
         } else {
                 HPSB_NOTICE("Spurious SelfID packet (0x%08x) received from bus %d",
-			    sid, (host->node_id & BUS_MASK) >> 6);
+			    sid, NODEID_TO_BUS(host->node_id));
         }
 }
 
@@ -396,9 +396,6 @@
         /* irm_id is kept up to date by check_selfids() */
         if (host->irm_id == host->node_id) {
                 host->is_irm = 1;
-                host->is_busmgr = 1;
-                host->busmgr_id = host->node_id;
-                host->csr.bus_manager_id = host->node_id;
         } else {
                 host->is_busmgr = 0;
                 host->is_irm = 0;
@@ -535,8 +532,8 @@
 
         if (packet->type == hpsb_async && packet->node_id != ALL_NODES) {
                 packet->speed_code =
-                        host->speed_map[(host->node_id & NODE_MASK) * 64
-                                       + (packet->node_id & NODE_MASK)];
+                        host->speed_map[NODEID_TO_NODE(host->node_id) * 64
+                                       + NODEID_TO_NODE(packet->node_id)];
         }
 
 #ifdef CONFIG_IEEE1394_VERBOSEDEBUG
@@ -748,7 +745,7 @@
 					addr, 4, flags);
 
                 if (!write_acked
-                    && (((data[0] >> 16) & NODE_MASK) != NODE_MASK)
+                    && (NODEID_TO_NODE(data[0] >> 16) != NODE_MASK)
                     && (rcode >= 0)) {
                         /* not a broadcast write, reply */
                         PREP_REPLY_PACKET(0);
@@ -763,7 +760,7 @@
 					addr, data[3]>>16, flags);
 
                 if (!write_acked
-                    && (((data[0] >> 16) & NODE_MASK) != NODE_MASK)
+                    && (NODEID_TO_NODE(data[0] >> 16) != NODE_MASK)
                     && (rcode >= 0)) {
                         /* not a broadcast write, reply */
                         PREP_REPLY_PACKET(0);
@@ -1248,6 +1245,7 @@
 EXPORT_SYMBOL(hpsb_write);
 EXPORT_SYMBOL(hpsb_lock);
 EXPORT_SYMBOL(hpsb_lock64);
+EXPORT_SYMBOL(hpsb_send_gasp);
 EXPORT_SYMBOL(hpsb_packet_success);
 
 /** highlevel.c **/
diff -urN linux-2.5.63-bk7/drivers/ieee1394/ieee1394_transactions.c linux-2.5.64/drivers/ieee1394/ieee1394_transactions.c
--- linux-2.5.63-bk7/drivers/ieee1394/ieee1394_transactions.c	Mon Feb 24 11:05:15 2003
+++ linux-2.5.64/drivers/ieee1394/ieee1394_transactions.c	Mon Mar 31 12:22:20 2003
@@ -98,6 +98,17 @@
         packet->speed_code = SPEED_100; /* Force speed to be 100Mbps */
 }
 
+static void fill_async_stream_packet(struct hpsb_packet *packet, int length,
+				     int channel, int tag, int sync)
+{
+	packet->header[0] = (length << 16) | (tag << 14) | (channel << 8)
+		| (TCODE_STREAM_DATA << 4) | sync;
+
+	packet->header_size = 4;
+	packet->data_size = length;
+	packet->type = hpsb_async;
+	packet->tcode = TCODE_ISO_DATA;
+}
 
 /**
  * hpsb_get_tlabel - allocate a transaction label
@@ -495,7 +506,6 @@
 }
 
 
-/* We need a hpsb_lock64 function for the 64 bit equivalent.  Probably. */
 int hpsb_lock(struct hpsb_host *host, nodeid_t node, unsigned int generation,
 	      u64 addr, int extcode, quadlet_t *data, quadlet_t arg)
 {
@@ -558,3 +568,58 @@
 
         return retval;
 }
+
+int hpsb_send_gasp(struct hpsb_host *host, int channel, unsigned int generation,
+		   quadlet_t *buffer, size_t length, u32 specifier_id,
+		   unsigned int version)
+{
+#ifdef CONFIG_IEEE1394_VERBOSEDEBUG
+	int i;
+#endif
+
+	struct hpsb_packet *packet;
+	int retval = 0;
+	u16 specifier_id_hi = (specifier_id & 0x00ffff00) >> 8;
+	u8 specifier_id_lo = specifier_id & 0xff;
+
+#ifdef CONFIG_IEEE1394_VERBOSEDEBUG
+	HPSB_DEBUG("Send GASP: channel = %d, length = %d", channel, length);
+#endif
+
+	length += 8;
+
+	packet = alloc_hpsb_packet(length + (length % 4 ? 4 - (length % 4) : 0));
+	if (!packet)
+		return -ENOMEM;
+
+	if (length % 4) {
+		packet->data[length / 4] = 0;
+	}
+
+	packet->host = host;
+	fill_async_stream_packet(packet, length, channel, 3, 0);
+        
+	packet->data[0] = cpu_to_be32((host->node_id << 16) | specifier_id_hi);
+	packet->data[1] = cpu_to_be32((specifier_id_lo << 24) | (version & 0x00ffffff));
+
+	memcpy(&(packet->data[2]), buffer, length - 4);
+
+#ifdef CONFIG_IEEE1394_VERBOSEDEBUG
+	HPSB_DEBUG("GASP: packet->header_size = %d", packet->header_size);
+	HPSB_DEBUG("GASP: packet->data_size = %d", packet->data_size);
+
+	for(i=0; i<(packet->data_size/4); i++)
+		HPSB_DEBUG("GASP: data[%d]: 0x%08x", i*4, be32_to_cpu(packet->data[i]));
+#endif
+
+	packet->generation = generation;
+
+	packet->no_waiter = 1;
+
+	if (!hpsb_send_packet(packet)) {
+		free_hpsb_packet(packet);
+		retval = -EINVAL;
+	}
+
+	return retval;
+}
diff -urN linux-2.5.63-bk7/drivers/ieee1394/ieee1394_transactions.h linux-2.5.64/drivers/ieee1394/ieee1394_transactions.h
--- linux-2.5.63-bk7/drivers/ieee1394/ieee1394_transactions.h	Mon Feb 24 11:05:14 2003
+++ linux-2.5.64/drivers/ieee1394/ieee1394_transactions.h	Mon Mar 31 12:22:20 2003
@@ -55,5 +55,8 @@
 	      u64 addr, int extcode, quadlet_t *data, quadlet_t arg);
 int hpsb_lock64(struct hpsb_host *host, nodeid_t node, unsigned int generation,
 		u64 addr, int extcode, octlet_t *data, octlet_t arg);
+int hpsb_send_gasp(struct hpsb_host *host, int channel, unsigned int generation,
+                   quadlet_t *buffer, size_t length, u32 specifier_id,
+                   unsigned int version);
 
 #endif /* _IEEE1394_TRANSACTIONS_H */
diff -urN linux-2.5.63-bk7/drivers/ieee1394/ieee1394_types.h linux-2.5.64/drivers/ieee1394/ieee1394_types.h
--- linux-2.5.63-bk7/drivers/ieee1394/ieee1394_types.h	Mon Feb 24 11:05:39 2003
+++ linux-2.5.64/drivers/ieee1394/ieee1394_types.h	Mon Mar 31 12:22:20 2003
@@ -97,14 +97,17 @@
 typedef u16 arm_length_t;
 
 #define BUS_MASK  0xffc0
+#define BUS_SHIFT 6
 #define NODE_MASK 0x003f
 #define LOCAL_BUS 0xffc0
 #define ALL_NODES 0x003f
 
+#define NODEID_TO_BUS(nodeid)	((nodeid & BUS_MASK) >> BUS_SHIFT)
+#define NODEID_TO_NODE(nodeid)	(nodeid & NODE_MASK)
+
 /* Can be used to consistently print a node/bus ID. */
-#define NODE_BUS_FMT    "%02d:%04d"
-#define NODE_BUS_ARGS(nodeid) \
-	(nodeid & NODE_MASK), ((nodeid & BUS_MASK) >> 6)
+#define NODE_BUS_FMT		"%02d:%04d"
+#define NODE_BUS_ARGS(nodeid)	NODEID_TO_NODE(nodeid), NODEID_TO_BUS(nodeid)
 
 #define HPSB_PRINT(level, fmt, args...) printk(level "ieee1394: " fmt "\n" , ## args)
 
diff -urN linux-2.5.63-bk7/drivers/ieee1394/nodemgr.c linux-2.5.64/drivers/ieee1394/nodemgr.c
--- linux-2.5.63-bk7/drivers/ieee1394/nodemgr.c	Mon Feb 24 11:05:34 2003
+++ linux-2.5.64/drivers/ieee1394/nodemgr.c	Mon Mar 31 12:22:20 2003
@@ -1210,6 +1210,52 @@
 	return;
 }
 
+/* Because we are a 1394a-2000 compliant IRM, we need to inform all the other
+ * nodes of the broadcast channel.  (Really we're only setting the validity
+ * bit). */
+static void nodemgr_do_irm_duties(struct hpsb_host *host)
+{
+	quadlet_t bc;
+        
+	if (!host->is_irm)
+		return;
+
+	host->csr.broadcast_channel |= 0x40000000;  /* set validity bit */
+
+	bc = cpu_to_be32(host->csr.broadcast_channel);
+
+	hpsb_write(host, LOCAL_BUS | ALL_NODES, get_hpsb_generation(host),
+		   (CSR_REGISTER_BASE | CSR_BROADCAST_CHANNEL),
+		   &bc,
+		   sizeof(quadlet_t));
+}
+
+/* We need to ensure that if we are not the IRM, that the IRM node is capable of
+ * everything we can do, otherwise issue a bus reset and try to become the IRM
+ * ourselves. */
+static int nodemgr_check_root_capability(struct hpsb_host *host)
+{
+	quadlet_t bc;
+	int status;
+
+	if (host->is_irm)
+		return 1;
+
+	status = hpsb_read(host, LOCAL_BUS | (host->irm_id),
+			   get_hpsb_generation(host),
+			   (CSR_REGISTER_BASE | CSR_BROADCAST_CHANNEL),
+			   &bc, sizeof(quadlet_t));
+
+	if (status < 0 || !(be32_to_cpu(bc) & 0x80000000)) {
+		/* The root node does not have a valid BROADCAST_CHANNEL
+		 * register and we do, so reset the bus with force_root set */
+		HPSB_INFO("Remote root is not IRM capable, resetting...");
+		hpsb_reset_bus(host, LONG_RESET_FORCE_ROOT);
+		return 0;
+	}
+	return 1;
+}
+
 static int nodemgr_host_thread(void *__hi)
 {
 	struct host_info *hi = (struct host_info *)__hi;
@@ -1217,12 +1263,21 @@
 	/* No userlevel access needed */
 	daemonize("knodemgrd");
 	allow_signal(SIGTERM);
-
+	
 	/* Sit and wait for a signal to probe the nodes on the bus. This
 	 * happens when we get a bus reset. */
 	while (!down_interruptible(&hi->reset_sem) &&
 	       !down_interruptible(&nodemgr_serialize)) {
+
+		if (!nodemgr_check_root_capability(hi->host)) {
+			/* Do nothing, we are resetting */
+			up(&nodemgr_serialize);
+			continue;
+		}
+
 		nodemgr_node_probe(hi->host);
+		nodemgr_do_irm_duties(hi->host);
+
 		up(&nodemgr_serialize);
 	}
 #ifdef CONFIG_IEEE1394_VERBOSEDEBUG
diff -urN linux-2.5.63-bk7/drivers/ieee1394/ohci1394.c linux-2.5.64/drivers/ieee1394/ohci1394.c
--- linux-2.5.63-bk7/drivers/ieee1394/ohci1394.c	Mon Mar 31 12:22:10 2003
+++ linux-2.5.64/drivers/ieee1394/ohci1394.c	Mon Mar 31 12:22:20 2003
@@ -31,9 +31,9 @@
  *
  * Things implemented, but still in test phase:
  * . Iso Transmit
+ * . Async Stream Packets Transmit (Receive done via Iso interface)
  * 
  * Things not implemented:
- * . Async Stream Packets
  * . DMA error recovery
  *
  * Known bugs:
@@ -160,7 +160,7 @@
 printk(level "%s_%d: " fmt "\n" , OHCI1394_DRIVER_NAME, card , ## args)
 
 static char version[] __devinitdata =
-	"$Rev: 762 $ Ben Collins <bcollins@debian.org>";
+	"$Rev: 801 $ Ben Collins <bcollins@debian.org>";
 
 /* Module Parameters */
 MODULE_PARM(phys_dma,"i");
@@ -649,18 +649,31 @@
                 } else {
                         d->prg_cpu[idx]->data[0] = packet->speed_code<<16 |
                                 (packet->header[0] & 0xFFFF);
-                        d->prg_cpu[idx]->data[1] =
-                                (packet->header[1] & 0xFFFF) | 
-                                (packet->header[0] & 0xFFFF0000);
-                        d->prg_cpu[idx]->data[2] = packet->header[2];
-                        d->prg_cpu[idx]->data[3] = packet->header[3];
+
+			if (packet->tcode == TCODE_ISO_DATA) {
+				/* Sending an async stream packet */
+				d->prg_cpu[idx]->data[1] = packet->header[0] & 0xFFFF0000;
+			} else {
+				/* Sending a normal async request or response */
+				d->prg_cpu[idx]->data[1] =
+					(packet->header[1] & 0xFFFF) | 
+					(packet->header[0] & 0xFFFF0000);
+				d->prg_cpu[idx]->data[2] = packet->header[2];
+				d->prg_cpu[idx]->data[3] = packet->header[3];
+			}
 			packet_swab(d->prg_cpu[idx]->data, packet->tcode);
                 }
 
                 if (packet->data_size) { /* block transmit */
-                        d->prg_cpu[idx]->begin.control =
-                                cpu_to_le32(DMA_CTL_OUTPUT_MORE |
-					    DMA_CTL_IMMEDIATE | 0x10);
+			if (packet->tcode == TCODE_STREAM_DATA){
+				d->prg_cpu[idx]->begin.control =
+					cpu_to_le32(DMA_CTL_OUTPUT_MORE |
+						    DMA_CTL_IMMEDIATE | 0x8);
+			} else {
+				d->prg_cpu[idx]->begin.control =
+					cpu_to_le32(DMA_CTL_OUTPUT_MORE |
+						    DMA_CTL_IMMEDIATE | 0x10);
+			}
                         d->prg_cpu[idx]->end.control =
                                 cpu_to_le32(DMA_CTL_OUTPUT_LAST |
 					    DMA_CTL_IRQ | 
@@ -830,7 +843,7 @@
 	/* Decide whether 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) {
+	else if ((packet->tcode == TCODE_ISO_DATA) && (packet->type == hpsb_iso)) {
 		/* 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
@@ -856,7 +869,7 @@
 		}
 		
 		d = &ohci->it_legacy_context;
-	} else if (packet->tcode & 0x02)
+	} else if ((packet->tcode & 0x02) && (packet->tcode != TCODE_ISO_DATA))
 		d = &ohci->at_resp_context;
 	else 
 		d = &ohci->at_req_context;
@@ -1295,6 +1308,8 @@
 	u32 *prev_branch = NULL;
 
 	for (blk = 0; blk < recv->nblocks; blk++) {
+		u32 control;
+
 		/* the DMA descriptor */
 		struct dma_cmd *cmd = &recv->block[blk];
 
@@ -1305,29 +1320,29 @@
 		unsigned long buf_offset = blk * recv->buf_stride;
 
 		if (recv->dma_mode == BUFFER_FILL_MODE) {
-			cmd->control = 2 << 28; /* INPUT_MORE */
+			control = 2 << 28; /* INPUT_MORE */
 		} else {
-			cmd->control = 3 << 28; /* INPUT_LAST */
+			control = 3 << 28; /* INPUT_LAST */
 		}
 
-		cmd->control |= 8 << 24; /* s = 1, update xferStatus and resCount */
+		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 */
+			control |= 3 << 20; /* want interrupt */
 		}
 
-		cmd->control |= 3 << 18; /* enable branch to address */
-		cmd->control |= recv->buf_stride;
+		control |= 3 << 18; /* enable branch to address */
+		control |= recv->buf_stride;
 
-		cmd->address = dma_region_offset_to_bus(&iso->data_buf, buf_offset);
+		cmd->control = cpu_to_le32(control);
+		cmd->address = cpu_to_le32(dma_region_offset_to_bus(&iso->data_buf, buf_offset));
 		cmd->branchAddress = 0; /* filled in on next loop */
-		cmd->status = recv->buf_stride;
+		cmd->status = cpu_to_le32(recv->buf_stride);
 
 		/* link the previous descriptor to this one */
 		if (prev_branch) {
-			*prev_branch = dma_prog_region_offset_to_bus(&recv->prog, prog_offset);
-			*prev_branch |= 1; /* set Z=1 */
+			*prev_branch = cpu_to_le32(dma_prog_region_offset_to_bus(&recv->prog, prog_offset) | 1);
 		}
 
 		prev_branch = &cmd->branchAddress;
@@ -1485,18 +1500,18 @@
 	/* 'next' becomes the new end of the DMA chain,
 	   so disable branch and enable interrupt */
 	next->branchAddress = 0;
-	next->control |= 3 << 20;
+	next->control |= cpu_to_le32(3 << 20);
 
 	/* link prev to next */	
-	prev->branchAddress = dma_prog_region_offset_to_bus(&recv->prog,
-							    sizeof(struct dma_cmd) * next_i)
-		| 1; /* Z=1 */
+	prev->branchAddress = cpu_to_le32(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 */
+		prev->control |= cpu_to_le32(3 << 20); /* enable interrupt */
 	} else {
-		prev->control &= ~(3<<20); /* disable interrupt */
+		prev->control &= cpu_to_le32(~(3<<20)); /* disable interrupt */
 	}
 	wmb();
 
@@ -1720,8 +1735,8 @@
 		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;
-		u16 rescount = il->status & 0xFFFF;
+		u16 xferstatus = le32_to_cpu(il->status) >> 16;
+		u16 rescount = le32_to_cpu(il->status) & 0xFFFF;
 
 		unsigned char event = xferstatus & 0x1F;
 
@@ -1903,7 +1918,7 @@
 		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;
+		u16 xferstatus = le32_to_cpu(cmd->output_last.status) >> 16;
 		u8  event = xferstatus & 0x1F;
 
 		if(!event) {
@@ -1919,7 +1934,7 @@
 		wake = 1;
 		
 		/* parse cycle */
-		cycle = cmd->output_last.status & 0x1FFF;
+		cycle = le32_to_cpu(cmd->output_last.status) & 0x1FFF;
 
 		/* tell the subsystem the packet has gone out */
 		hpsb_iso_packet_sent(iso, cycle, event != 0x11);
@@ -1972,7 +1987,7 @@
 
 	/* set up the OUTPUT_MORE_IMMEDIATE descriptor */
 	memset(next, 0, sizeof(struct iso_xmit_cmd));
-	next->output_more_immediate.control = 0x02000008;
+	next->output_more_immediate.control = cpu_to_le32(0x02000008);
 
 	/* ISO packet header is embedded in the OUTPUT_MORE_IMMEDIATE */
 
@@ -1990,28 +2005,28 @@
 	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 |= len;
+	next->output_last.control = cpu_to_le32(1 << 28);
+	next->output_last.control |= cpu_to_le32(1 << 27); /* update timeStamp */
+	next->output_last.control |= cpu_to_le32(3 << 20); /* want interrupt */
+	next->output_last.control |= cpu_to_le32(3 << 18); /* enable branch */
+	next->output_last.control |= cpu_to_le32(len);
 
 	/* payload bus address */
-	next->output_last.address = dma_region_offset_to_bus(&iso->data_buf, offset);
+	next->output_last.address = cpu_to_le32(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 */
 
 	/* 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;
+	prev->output_last.branchAddress = cpu_to_le32(
+		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 */
+		prev->output_last.control &= cpu_to_le32(~(3 << 20)); /* no interrupt */
 	} else {
-		prev->output_last.control |= 3 << 20; /* enable interrupt */
+		prev->output_last.control |= cpu_to_le32(3 << 20); /* enable interrupt */
 	}
 
 	wmb();
@@ -3473,10 +3488,10 @@
 
 static struct pci_device_id ohci1394_pci_tbl[] __devinitdata = {
 	{
-		.class = 		PCI_CLASS_FIREWIRE_OHCI,
-		.class_mask = 	0x00ffffff,
-		.vendor =		PCI_ANY_ID,
-		.device =		PCI_ANY_ID,
+		.class = 	PCI_CLASS_FIREWIRE_OHCI,
+		.class_mask = 	~0,
+		.vendor =	PCI_ANY_ID,
+		.device =	PCI_ANY_ID,
 		.subvendor =	PCI_ANY_ID,
 		.subdevice =	PCI_ANY_ID,
 	},
diff -urN linux-2.5.63-bk7/drivers/ieee1394/raw1394.c linux-2.5.64/drivers/ieee1394/raw1394.c
--- linux-2.5.63-bk7/drivers/ieee1394/raw1394.c	Mon Mar 31 12:22:10 2003
+++ linux-2.5.64/drivers/ieee1394/raw1394.c	Mon Mar 31 12:22:20 2003
@@ -238,7 +238,7 @@
                 list_del(&hi->list);
                 host_count--;
                 /* 
-                   FIXME: addressranges should be removed 
+                   FIXME: address ranges should be removed 
                    and fileinfo states should be initialized
                    (including setting generation to 
                    internal-generation ...)
@@ -281,8 +281,8 @@
                                         req->req.misc = (host->node_id << 16)
                                                 | host->node_count;
                                         if (fi->protocol_version > 3) {
-                                                req->req.misc |= ((host->irm_id
-                                                                   & NODE_MASK) << 8);
+                                                req->req.misc |= (NODEID_TO_NODE(host->irm_id)
+                                                                  << 8);
                                         }
 
                                         queue_complete_req(req);
@@ -571,8 +571,7 @@
                         req->req.misc = (fi->host->node_id << 16) 
                                 | fi->host->node_count;
                         if (fi->protocol_version > 3) {
-                                req->req.misc |=
-                                        (fi->host->irm_id & NODE_MASK) << 8;
+                                req->req.misc |= NODEID_TO_NODE(fi->host->irm_id) << 8;
                         }
                 } else {
                         req->req.error = RAW1394_ERROR_INVALID_ARG;
diff -urN linux-2.5.63-bk7/drivers/ieee1394/sbp2.c linux-2.5.64/drivers/ieee1394/sbp2.c
--- linux-2.5.63-bk7/drivers/ieee1394/sbp2.c	Mon Feb 24 11:05:09 2003
+++ linux-2.5.64/drivers/ieee1394/sbp2.c	Mon Mar 31 12:22:21 2003
@@ -27,30 +27,6 @@
  * driver. It also registers as a SCSI lower-level driver in order to accept
  * SCSI commands for transport using SBP-2.
  *
- *
- * Driver Loading:
- *
- * Currently, the SBP-2 driver is supported only as a module. Because the 
- * Linux SCSI stack is not Plug-N-Play aware, module load order is 
- * important. Assuming the SCSI core drivers are either built into the 
- * kernel or already loaded as modules, you should load the IEEE-1394 modules 
- * in the following order:
- *
- * 	ieee1394 (e.g. insmod ieee1394)
- *	ohci1394 (e.g. insmod ohci1394)
- *	sbp2 (e.g. insmod sbp2)
- *
- * The SBP-2 driver will attempt to discover any attached SBP-2 devices when first
- * loaded, or after any IEEE-1394 bus reset (e.g. a hot-plug). It will then print 
- * out a debug message indicating if it was able to discover a SBP-2 device.
- *
- * Currently, the SBP-2 driver will catch any attached SBP-2 devices during the
- * initial scsi bus scan (when the driver is first loaded). To add or remove
- * SBP-2 devices "after" this initial scan (i.e. if you plug-in or un-plug a 
- * device after the SBP-2 driver is loaded), you must either use the scsi procfs
- * add-single-device, remove-single-device, or a shell script such as 
- * rescan-scsi-bus.sh.
- *
  * The easiest way to add/detect new SBP-2 devices is to run the shell script
  * rescan-scsi-bus.sh (or re-load the SBP-2 driver). This script may be 
  * found at:
@@ -136,14 +112,6 @@
  *	- Error Handling: SCSI aborts and bus reset requests are handled somewhat
  *	  but the code needs additional debugging.
  *
- *	- Module: The SBP-2 driver is currently only supported as a module. It would not take
- *	  much work to allow it to be compiled into the kernel, but you'd have to 
- *	  add some init code to the kernel to support this... and modules are much
- *	  more flexible anyway.   ;-)
- *
- *	- Hot-plugging: Interaction with the SCSI stack and support for hot-plugging could
- *	  stand some improvement.
- *
  *
  * History:
  *
@@ -295,10 +263,11 @@
  *	04/23/02 - Fix for Sony CD-ROM drives. Only send fetch agent reset to sbp2 device if it
  *		   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)   
+ *	06/09/02 - Don't force 36-byte 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)
+ *	02/10/03 - Adopt to new hot-plug aware SCSI inferface (hch@lst.de)
  *
  */
 
@@ -350,7 +319,7 @@
 #include "sbp2.h"
 
 static char version[] __devinitdata =
-	"$Rev: 779 $ James Goodwin <jamesg@filanet.com>";
+	"$Rev: 797 $ James Goodwin <jamesg@filanet.com>";
 
 /*
  * Module load parameter definitions
@@ -497,6 +466,15 @@
  * Globals
  */
 
+static void sbp2scsi_complete_all_commands(struct sbp2scsi_host_info *hi,
+					   struct scsi_id_instance_data *scsi_id,
+					   u32 status);
+
+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 *));
+	
 static Scsi_Host_Template scsi_driver_template;
 
 static u8 sbp2_speedto_maxrec[] = { 0x7, 0x8, 0x9 };
@@ -822,7 +800,7 @@
 {
 	struct sbp2scsi_host_info *hi;
 	
-	hi = (struct sbp2scsi_host_info *) command->Current_SCpnt->device->host->hostdata[0];
+	hi = (struct sbp2scsi_host_info *)&command->Current_SCpnt->device->host->hostdata;
 
 	if (hi == NULL) {
 		printk(KERN_ERR "%s: hi == NULL\n", __FUNCTION__);
@@ -871,59 +849,6 @@
  * IEEE-1394 core driver stack related section
  *********************************************/
 
-/*
- * This function is called at SCSI init in order to register our driver
- * with the IEEE-1394 stack.
- */
-int sbp2_init(void)
-{
-	SBP2_DEBUG("sbp2_init");
-
-	/*
-	 * Register our high level driver with 1394 stack
-	 */
-	sbp2_hl_handle = hpsb_register_highlevel(SBP2_DEVICE_NAME, &sbp2_hl_ops);
-
-	if (sbp2_hl_handle == NULL) {
-		SBP2_ERR("sbp2 failed to register with ieee1394 highlevel");
-		return(-ENOMEM);
-	}
-
-	/*
-	 * Register our sbp2 status address space...
-	 */
-	hpsb_register_addrspace(sbp2_hl_handle, &sbp2_ops, SBP2_STATUS_FIFO_ADDRESS,
-				SBP2_STATUS_FIFO_ADDRESS + 
-				SBP2_STATUS_FIFO_ENTRY_TO_OFFSET(SBP2SCSI_MAX_SCSI_IDS+1));
-
-	/*
-	 * Handle data movement if physical dma is not enabled/supported on host controller
-	 */
-#ifdef CONFIG_IEEE1394_SBP2_PHYS_DMA
-	hpsb_register_addrspace(sbp2_hl_handle, &sbp2_physdma_ops, 0x0ULL, 0xfffffffcULL);
-#endif
-
-	hpsb_register_protocol(&sbp2_driver);
-
-	return 0;
-}
-
-/*
- * This function is called from cleanup module, or during shut-down, in
- * order to unregister our driver.
- */
-void sbp2_cleanup(void)
-{
-	SBP2_DEBUG("sbp2_cleanup");
-
-	hpsb_unregister_protocol(&sbp2_driver);
-
-	if (sbp2_hl_handle) {
-		hpsb_unregister_highlevel(sbp2_hl_handle);
-		sbp2_hl_handle = NULL;
-	}
-}
-
 static int sbp2_probe(struct unit_directory *ud)
 {
 	struct sbp2scsi_host_info *hi;
@@ -999,35 +924,44 @@
 {
 	struct sbp2scsi_host_info *hi;
 	unsigned long flags;
+	struct Scsi_Host *scsi_host;
 
 	SBP2_DEBUG("sbp2_add_host");
 
-	/* Allocate some memory for our host info structure */
-	hi = (struct sbp2scsi_host_info *)kmalloc(sizeof(struct sbp2scsi_host_info),
-						  in_interrupt() ? SLAB_ATOMIC : SLAB_KERNEL);
-
-	if (hi == NULL) {
-		SBP2_ERR("out of memory in sbp2_add_host");
+	/* Register our host with the SCSI stack. */
+	scsi_host = scsi_register (&scsi_driver_template, sizeof(struct sbp2scsi_host_info));
+	if (!scsi_host) {
+		SBP2_ERR("failed to register scsi host");
 		return;
 	}
 
-	/* Initialize some host stuff */
+	hi = (struct sbp2scsi_host_info *)&scsi_host->hostdata;
 	memset(hi, 0, sizeof(struct sbp2scsi_host_info));
+
+	hi->scsi_host = scsi_host;
 	INIT_LIST_HEAD(&hi->list);
 	hi->host = host;
 	hi->sbp2_command_lock = SPIN_LOCK_UNLOCKED;
+	hi->scsi_host->max_id = SBP2SCSI_MAX_SCSI_IDS;
 
 	spin_lock_irqsave(&sbp2_host_info_lock, flags);
 	list_add_tail(&hi->list, &sbp2_host_info_list);
 	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 *));
-	if (hi->scsi_host) {
-		hi->scsi_host->hostdata[0] = (unsigned long)hi;
-		hi->scsi_host->max_id = SBP2SCSI_MAX_SCSI_IDS;
+	/*
+	 * XXX(hch): Hopefully the ieee1394 code will be converted
+	 * to the driver model at some point.  Until that happens
+	 * we'll have to pass in NULL here.
+	 */
+	if (scsi_add_host(hi->scsi_host, NULL)) {
+		SBP2_ERR("failed to add scsi host");
+
+		spin_lock_irqsave(&sbp2_host_info_lock, flags);
+		list_del(&hi->list);
+		spin_unlock_irqrestore(&sbp2_host_info_lock, flags);
+
+		scsi_unregister(hi->scsi_host);
 	}
-	scsi_driver_template.present++;
 
 	return;
 }
@@ -1079,16 +1013,15 @@
 	SBP2_DEBUG("sbp2_remove_host");
 
 	spin_lock_irqsave(&sbp2_host_info_lock, flags);
-
 	hi = sbp2_find_host_info(host);
-	if (hi != NULL) {
+	if (hi)
 		list_del(&hi->list);
-		kfree(hi);
-	}
-	else
-		SBP2_ERR("attempt to remove unknown host %p", host);
-
 	spin_unlock_irqrestore(&sbp2_host_info_lock, flags);
+
+	if (hi) {
+		scsi_remove_host(hi->scsi_host);
+		scsi_unregister(hi->scsi_host);
+	}
 }
 
 /*
@@ -1098,6 +1031,7 @@
 static int sbp2_start_device(struct sbp2scsi_host_info *hi, struct unit_directory *ud)
 {
 	struct scsi_id_instance_data *scsi_id = NULL;
+	struct scsi_device *sdev;
 	struct node_entry *ne;
 	int i;
 
@@ -1203,7 +1137,7 @@
 	/*
 	 * Find an empty spot to stick our scsi id instance data. 
 	 */
-	for (i = 0; i < SBP2SCSI_MAX_SCSI_IDS; i++) {
+	for (i = 0; i < hi->scsi_host->max_id; i++) {
 		if (!hi->scsi_id[i]) {
 			hi->scsi_id[i] = scsi_id;
 			scsi_id->id = i;
@@ -1224,7 +1158,7 @@
 	/*
 	 * Make sure we are not out of space
 	 */
-	if (i == SBP2SCSI_MAX_SCSI_IDS) {
+	if (i == hi->scsi_host->max_id) {
 		SBP2_ERR("No slots left for SBP-2 device");
 		sbp2_remove_device(hi, scsi_id);
 		return -EBUSY;
@@ -1256,6 +1190,13 @@
 	 */
 	sbp2_max_speed_and_size(hi, scsi_id);
 
+	/* Add this device to the scsi layer now */
+	sdev = scsi_add_device(hi->scsi_host, 0, scsi_id->id, 0);
+	if (IS_ERR(sdev)) {
+		SBP2_ERR("scsi_add_device failed");
+		return PTR_ERR(sdev);
+	}
+
 	return 0;
 }
 
@@ -1265,13 +1206,21 @@
 static void sbp2_remove_device(struct sbp2scsi_host_info *hi, 
 			       struct scsi_id_instance_data *scsi_id)
 {
+	struct scsi_device *sdev = scsi_find_device(hi->scsi_host, 0, scsi_id->id, 0);
+
 	SBP2_DEBUG("sbp2_remove_device");
 
 	/* Complete any pending commands with selection timeout */
 	sbp2scsi_complete_all_commands(hi, scsi_id, DID_NO_CONNECT);
-       			
+
+	/* Remove it from the scsi layer now */
+	if (scsi_remove_device(sdev))
+		SBP2_ERR("scsi_remove_device failed");
+
 	sbp2util_remove_command_orb_pool(scsi_id, hi);
 
+	hi->scsi_id[scsi_id->id] = NULL;
+
 	if (scsi_id->login_response) {
 		pci_free_consistent(hi->host->pdev,
 				    sizeof(struct sbp2_login_response),
@@ -1305,7 +1254,7 @@
 	}
 
 	SBP2_DEBUG("SBP-2 device removed, SCSI ID = %d", scsi_id->id);
-	hi->scsi_id[scsi_id->id] = NULL;
+
 	kfree(scsi_id);
 }
 
@@ -1793,8 +1742,8 @@
 	SBP2_DEBUG("sbp2_max_speed_and_size");
 
 	/* Initial setting comes from the hosts speed map */
-	scsi_id->speed_code = hi->host->speed_map[(hi->host->node_id & NODE_MASK) * 64
-						  + (scsi_id->ne->nodeid & NODE_MASK)];
+	scsi_id->speed_code = hi->host->speed_map[NODEID_TO_NODE(hi->host->node_id) * 64
+						  + NODEID_TO_NODE(scsi_id->ne->nodeid)];
 
 	/* Bump down our speed if the user requested it */
 	if (scsi_id->speed_code > sbp2_max_speed) {
@@ -2661,7 +2610,7 @@
 	/*
 	 * Pull our host info and scsi id instance data from the scsi command
 	 */
-	hi = (struct sbp2scsi_host_info *) SCpnt->device->host->hostdata[0];
+	hi = (struct sbp2scsi_host_info *) &SCpnt->device->host->hostdata;
 
 	if (!hi) {
 		SBP2_ERR("sbp2scsi_host_info is NULL - this is bad!");
@@ -2766,8 +2715,10 @@
  *
  * 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 *))
+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;
 
@@ -2888,7 +2839,7 @@
  */
 static int sbp2scsi_abort (Scsi_Cmnd *SCpnt) 
 {
-	struct sbp2scsi_host_info *hi = (struct sbp2scsi_host_info *) SCpnt->device->host->hostdata[0];
+	struct sbp2scsi_host_info *hi = (struct sbp2scsi_host_info *)&SCpnt->device->host->hostdata;
 	struct scsi_id_instance_data *scsi_id = hi->scsi_id[SCpnt->device->id];
 	struct sbp2_command_info *command;
 	unsigned long flags;
@@ -2938,7 +2889,7 @@
  */
 static int sbp2scsi_reset (Scsi_Cmnd *SCpnt) 
 {
-	struct sbp2scsi_host_info *hi = (struct sbp2scsi_host_info *) SCpnt->device->host->hostdata[0];
+	struct sbp2scsi_host_info *hi = (struct sbp2scsi_host_info *)&SCpnt->device->host->hostdata;
 	struct scsi_id_instance_data *scsi_id = hi->scsi_id[SCpnt->device->id];
 
 	SBP2_ERR("reset requested");
@@ -2951,93 +2902,81 @@
 	return(SUCCESS);
 }
 
-/*
- * Called by scsi stack to get bios parameters (used by fdisk, and at boot).
- */
-#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,43)
-static int sbp2scsi_biosparam (struct scsi_device *sdev,
-                struct block_device *dev, sector_t capacity, int geom[])
+static const char *sbp2scsi_info (struct Scsi_Host *host)
 {
-#else
-static int sbp2scsi_biosparam (Scsi_Disk *disk, kdev_t dev, int geom[])
+        return "SCSI emulation for for IEEE-1394 Storage Devices";
+}
+
+/* Called for contents of procfs */
+#define SPRINTF(args...) \
+        do { if (pos < buffer+length) pos += sprintf(pos, ## args); } while (0)
+
+static int sbp2scsi_proc_info(char *buffer, char **start, off_t offset,
+			      int length, int hostno, int inout)
 {
-        unsigned capacity = disk->capacity;
-#endif
-	int heads, sectors, cylinders;
+	Scsi_Device *scd;
+	struct Scsi_Host *host;
+	struct sbp2scsi_host_info *hi;
+	char *pos = buffer;
 
-	SBP2_DEBUG("Request for bios parameters");
+	/* if someone is sending us data, just throw it away */
+	if (inout)
+		return length;
 
-	heads = 64;
-	sectors = 32;
-	cylinders = (int)capacity / (heads * sectors);
+	host = scsi_host_hn_get(hostno);
+	if (!host)  /* if we couldn't find it, we return an error */
+		return -ESRCH;
 
-	if (cylinders > 1024) {
-		heads = 255;
-		sectors = 63;
-		cylinders = (int)capacity / (heads * sectors);
-	}
+	hi = sbp2_find_host_info_scsi(host);
+	if (!hi) /* shouldn't happen, but... */
+		return -ESRCH;
 
-	geom[0] = heads;
-	geom[1] = sectors;
-	geom[2] = cylinders;
+	SPRINTF("Host scsi%d             : SBP-2 IEEE-1394 (%s)\n", hostno,
+		hi->host->driver->name);
+	SPRINTF("Driver version         : %s\n", version);
 
-	return(0);
-}
+	SPRINTF("\nModule options         :\n");
+	SPRINTF("  sbp2_max_speed       : %s\n", hpsb_speedto_str[sbp2_max_speed]);
+	SPRINTF("  sbp2_max_sectors     : %d\n", sbp2_max_sectors);
+	SPRINTF("  sbp2_serialize_io    : %s\n", sbp2_serialize_io ? "yes" : "no");
+	SPRINTF("  sbp2_exclusive_login : %s\n", sbp2_exclusive_login ? "yes" : "no");
 
-/*
- * Called by scsi stack after scsi driver is registered
- */
-static int sbp2scsi_detect (Scsi_Host_Template *tpnt) 
-{
-	SBP2_DEBUG("sbp2scsi_detect");
+	SPRINTF("\nAttached devices       : %s\n", !list_empty(&host->my_devices) ?
+		"" : "none");
 
-	/*
-	 * Call sbp2_init to register with the ieee1394 stack. This
-	 * results in a callback to sbp2_add_host for each ieee1394
-	 * host controller currently registered, and for each of those
-	 * we register a scsi host with the scsi stack.
-	 */
-	
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-	spin_unlock_irq(&io_request_lock);
-	sbp2_init();
-	spin_lock_irq(&io_request_lock);
-#else
-	sbp2_init();
-#endif
+	list_for_each_entry (scd, &host->my_devices, siblings) {
+		int i;
 
-	/* We return the number of hosts registered. */
-	return scsi_driver_template.present;
-}
+		SPRINTF("  [Channel: %02d, Id: %02d, Lun: %02d]  ", scd->channel,
+			scd->id, scd->lun);
+		SPRINTF("%s ", (scd->type < MAX_SCSI_DEVICE_CODE) ?
+			scsi_device_types[(short) scd->type] : "Unknown device");
 
+		for (i = 0; (i < 8) && (scd->vendor[i] >= 0x20); i++)
+			SPRINTF("%c", scd->vendor[i]);
 
-/*
- * Called for contents of procfs
- */
-static const char *sbp2scsi_info (struct Scsi_Host *host)
-{
-	struct sbp2scsi_host_info *hi = sbp2_find_host_info_scsi(host);
-	static char info[1024];
+		SPRINTF(" ");
 
-	if (!hi) /* shouldn't happen, but... */
-        	return "IEEE-1394 SBP-2 protocol driver";
+		for (i = 0; (i < 16) && (scd->model[i] >= 0x20); i++)
+			SPRINTF("%c", scd->model[i]);
+
+		SPRINTF("\n");
+	}
 
-	sprintf(info, "IEEE-1394 SBP-2 protocol driver (host: %s)\n%s\n"
-		"SBP-2 module load options:\n"
-		"- Max speed supported: %s\n"
-		"- Max sectors per I/O supported: %d\n"
-                "- Serialized I/O (debug): %s\n"
-		"- Exclusive login: %s",
-		hi->host->driver->name,
-		version,
-		hpsb_speedto_str[sbp2_max_speed],
-		sbp2_max_sectors,
-		sbp2_serialize_io ? "yes" : "no",
-		sbp2_exclusive_login ? "yes" : "no");
+	SPRINTF("\n");
 
-	return info;
-}
+	/* release the reference count on this host */
+	scsi_host_put(host);
+	/* Calculate start of next buffer, and return value. */
+	*start = buffer + offset;
 
+	if ((pos - buffer) < offset)
+		return (0);
+	else if ((pos - buffer - offset) < length)
+		return (pos - buffer - offset);
+	else
+		return (length);
+}
 
 MODULE_AUTHOR("James Goodwin <jamesg@filanet.com>");
 MODULE_DESCRIPTION("IEEE-1394 SBP-2 protocol driver");
@@ -3046,25 +2985,23 @@
 
 /* SCSI host template */
 static Scsi_Host_Template scsi_driver_template = {
-	.name =			"IEEE-1394 SBP-2 protocol driver",
-	.info =			sbp2scsi_info,
-	.detect =		sbp2scsi_detect,
-	.queuecommand =		sbp2scsi_queuecommand,
-	.eh_abort_handler =	sbp2scsi_abort,
-	.eh_device_reset_handler =sbp2scsi_reset,
-	.eh_bus_reset_handler =	sbp2scsi_reset,
-	.eh_host_reset_handler =sbp2scsi_reset,
-	.bios_param =		sbp2scsi_biosparam,
-	.this_id =		-1,
-	.sg_tablesize =		SG_ALL,
-	.use_clustering =	ENABLE_CLUSTERING,
-	.cmd_per_lun =		SBP2_MAX_CMDS_PER_LUN,
-	.can_queue = 		SBP2_MAX_SCSI_QUEUE,
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-	.use_new_eh_code =	TRUE,
-#endif
-	.emulated =		1,
-	.proc_name =		SBP2_DEVICE_NAME,
+	.module =			THIS_MODULE,
+	.name =				"SBP-2 IEEE-1394",
+	.proc_name =			SBP2_DEVICE_NAME,
+	.info =				sbp2scsi_info,
+	.proc_info =			sbp2scsi_proc_info,
+	.queuecommand =			sbp2scsi_queuecommand,
+	.eh_abort_handler =		sbp2scsi_abort,
+	.eh_device_reset_handler =	sbp2scsi_reset,
+	.eh_bus_reset_handler =		sbp2scsi_reset,
+	.eh_host_reset_handler =	sbp2scsi_reset,
+	.this_id =			-1,
+	.sg_tablesize =			SG_ALL,
+	.use_clustering =		ENABLE_CLUSTERING,
+	.cmd_per_lun =			SBP2_MAX_CMDS_PER_LUN,
+	.can_queue = 			SBP2_MAX_SCSI_QUEUE,
+	.emulated =			1,
+	.highmem_io =			1,
 };
 
 static int sbp2_module_init(void)
@@ -3084,23 +3021,36 @@
 	 */
 	scsi_driver_template.max_sectors = sbp2_max_sectors;
 
+
 	/*
-	 * Ideally we would register our scsi_driver_template with the
-	 * scsi stack and after that register with the ieee1394 stack
-	 * and process the add_host callbacks. However, the detect
-	 * function in the scsi host template requires that we find at
-	 * least one host, so we "nest" the registrations by calling
-	 * sbp2_init from the detect function.
-	 */
-	scsi_driver_template.module = THIS_MODULE;
-	if (SCSI_REGISTER_HOST(&scsi_driver_template) ||
-	    !scsi_driver_template.present) {
-		SBP2_ERR("Please load the lower level IEEE-1394 driver "
-			 "(e.g. ohci1394) before sbp2...");
-		sbp2_cleanup();
-		return -ENODEV;
+	 * Register our high level driver with 1394 stack
+	 */
+	sbp2_hl_handle = hpsb_register_highlevel(SBP2_DEVICE_NAME,
+						 &sbp2_hl_ops);
+	if (!sbp2_hl_handle) {
+		SBP2_ERR("sbp2 failed to register with ieee1394 highlevel");
+		return(-ENOMEM);
 	}
 
+	/*
+	 * Register our sbp2 status address space...
+	 */
+	hpsb_register_addrspace(sbp2_hl_handle, &sbp2_ops,
+				SBP2_STATUS_FIFO_ADDRESS,
+				SBP2_STATUS_FIFO_ADDRESS + 
+				SBP2_STATUS_FIFO_ENTRY_TO_OFFSET(
+					SBP2SCSI_MAX_SCSI_IDS+1));
+
+	/*
+	 * Handle data movement if physical dma is not enabled/supported
+	 * on host controller
+	 */
+#ifdef CONFIG_IEEE1394_SBP2_PHYS_DMA
+	hpsb_register_addrspace(sbp2_hl_handle, &sbp2_physdma_ops,
+			0x0ULL, 0xfffffffcULL);
+#endif
+
+	hpsb_register_protocol(&sbp2_driver);
 	return 0;
 }
 
@@ -3108,17 +3058,9 @@
 {
 	SBP2_DEBUG("sbp2_module_exit");
 
-	/*
-	 * On module unload we unregister with the ieee1394 stack
-	 * which results in remove_host callbacks for all ieee1394
-	 * host controllers.  In the callbacks we unregister the
-	 * corresponding scsi hosts.
-	 */
-	sbp2_cleanup();
-
-	if (SCSI_UNREGISTER_HOST(&scsi_driver_template))
-		SBP2_ERR("sbp2_module_exit: couldn't unregister scsi driver");
-
+	hpsb_unregister_protocol(&sbp2_driver);
+	if (sbp2_hl_handle)
+		hpsb_unregister_highlevel(sbp2_hl_handle);
 }
 
 module_init(sbp2_module_init);
diff -urN linux-2.5.63-bk7/drivers/ieee1394/sbp2.h linux-2.5.64/drivers/ieee1394/sbp2.h
--- linux-2.5.63-bk7/drivers/ieee1394/sbp2.h	Mon Feb 24 11:05:11 2003
+++ linux-2.5.64/drivers/ieee1394/sbp2.h	Mon Mar 31 12:22:21 2003
@@ -22,15 +22,6 @@
 #ifndef SBP2_H
 #define SBP2_H
 
-/* Some compatibility code */
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-#define SCSI_REGISTER_HOST(tmpl)	scsi_register_module(MODULE_SCSI_HA, tmpl)
-#define SCSI_UNREGISTER_HOST(tmpl)	scsi_unregister_module(MODULE_SCSI_HA, tmpl)
-#else
-#define SCSI_REGISTER_HOST(tmpl)	scsi_register_host(tmpl)
-#define SCSI_UNREGISTER_HOST(tmpl)	scsi_unregister_host(tmpl)
-#endif
-
 #define SBP2_DEVICE_NAME		"sbp2"
 
 /*
@@ -442,8 +433,6 @@
 static void sbp2_add_host(struct hpsb_host *host);
 static struct sbp2scsi_host_info *sbp2_find_host_info(struct hpsb_host *host);
 static void sbp2_remove_host(struct hpsb_host *host);
-int sbp2_init(void);
-void sbp2_cleanup(void);
 static int sbp2_probe(struct unit_directory *ud);
 static void sbp2_disconnect(struct unit_directory *ud);
 static void sbp2_update(struct unit_directory *ud);
@@ -487,23 +476,4 @@
 static int sbp2_set_busy_timeout(struct sbp2scsi_host_info *hi, struct scsi_id_instance_data *scsi_id);
 static int sbp2_max_speed_and_size(struct sbp2scsi_host_info *hi, struct scsi_id_instance_data *scsi_id);
 
-/*
- * Scsi interface related prototypes
- */
-static int sbp2scsi_detect (Scsi_Host_Template *tpnt);
-static const char *sbp2scsi_info (struct Scsi_Host *host);
-void sbp2scsi_setup(char *str, int *ints);
-#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,44)
-static int sbp2scsi_biosparam (struct scsi_device *sdev, struct block_device *dev, sector_t capacity, int geom[]);
-#else
-static int sbp2scsi_biosparam (Scsi_Disk *disk, kdev_t dev, int geom[]);
-#endif
-static int sbp2scsi_abort (Scsi_Cmnd *SCpnt); 
-static int sbp2scsi_reset (Scsi_Cmnd *SCpnt); 
-static int sbp2scsi_queuecommand (Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *));
-static void sbp2scsi_complete_all_commands(struct sbp2scsi_host_info *hi, struct scsi_id_instance_data *scsi_id, 
-					   u32 status);
-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 *));
-
 #endif /* SBP2_H */
diff -urN linux-2.5.63-bk7/drivers/ieee1394/video1394.c linux-2.5.64/drivers/ieee1394/video1394.c
--- linux-2.5.63-bk7/drivers/ieee1394/video1394.c	Mon Feb 24 11:05:10 2003
+++ linux-2.5.64/drivers/ieee1394/video1394.c	Mon Mar 31 12:22:21 2003
@@ -43,6 +43,8 @@
 #include <linux/vmalloc.h>
 #include <linux/timex.h>
 #include <linux/mm.h>
+#include <linux/ioctl32.h>
+#include <linux/compat.h>
 
 #include "ieee1394.h"
 #include "ieee1394_types.h"
@@ -1338,24 +1340,152 @@
 MODULE_SUPPORTED_DEVICE(VIDEO1394_DRIVER_NAME);
 MODULE_LICENSE("GPL");
 
+#ifdef CONFIG_COMPAT
+
+#define VIDEO1394_IOC32_LISTEN_QUEUE_BUFFER     \
+	_IOW ('#', 0x12, struct video1394_wait32)
+#define VIDEO1394_IOC32_LISTEN_WAIT_BUFFER      \
+	_IOWR('#', 0x13, struct video1394_wait32)
+#define VIDEO1394_IOC32_TALK_WAIT_BUFFER        \
+	_IOW ('#', 0x17, struct video1394_wait32)
+#define VIDEO1394_IOC32_LISTEN_POLL_BUFFER      \
+	_IOWR('#', 0x18, struct video1394_wait32)
+
+struct video1394_wait32 {
+	u32 channel;
+	u32 buffer;
+	struct compat_timeval filltime;
+};
+
+static int video1394_wr_wait32(unsigned int fd, unsigned int cmd, unsigned long arg,
+			       struct file *file)
+{
+        struct video1394_wait32 wait32;
+        struct video1394_wait wait;
+        mm_segment_t old_fs;
+        int ret;
+
+	if (file->f_op->ioctl != video1394_ioctl)
+		return -EFAULT;
+
+        if (copy_from_user(&wait32, (void *)arg, sizeof(wait32)))
+                return -EFAULT;
+
+        wait.channel = wait32.channel;
+        wait.buffer = wait32.buffer;
+        wait.filltime.tv_sec = (time_t)wait32.filltime.tv_sec;
+        wait.filltime.tv_usec = (suseconds_t)wait32.filltime.tv_usec;
+
+        old_fs = get_fs();
+        set_fs(KERNEL_DS);
+        if (cmd == VIDEO1394_IOC32_LISTEN_WAIT_BUFFER)
+		ret = video1394_ioctl(file->f_dentry->d_inode, file,
+				      VIDEO1394_IOC_LISTEN_WAIT_BUFFER,
+				      (unsigned long) &wait);
+        else
+		ret = video1394_ioctl(file->f_dentry->d_inode, file,
+				      VIDEO1394_IOC_LISTEN_POLL_BUFFER,
+				      (unsigned long) &wait);
+        set_fs(old_fs);
+
+        if (!ret) {
+                wait32.channel = wait.channel;
+                wait32.buffer = wait.buffer;
+                wait32.filltime.tv_sec = (int)wait.filltime.tv_sec;
+                wait32.filltime.tv_usec = (int)wait.filltime.tv_usec;
+
+                if (copy_to_user((struct video1394_wait32 *)arg, &wait32, sizeof(wait32)))
+                        ret = -EFAULT;
+        }
+
+        return ret;
+}
+
+static int video1394_w_wait32(unsigned int fd, unsigned int cmd, unsigned long arg,
+			      struct file *file)
+{
+        struct video1394_wait32 wait32;
+        struct video1394_wait wait;
+        mm_segment_t old_fs;
+        int ret;
+
+	if (file->f_op->ioctl != video1394_ioctl)
+		return -EFAULT;
+
+        if (copy_from_user(&wait32, (void *)arg, sizeof(wait32)))
+                return -EFAULT;
+
+        wait.channel = wait32.channel;
+        wait.buffer = wait32.buffer;
+        wait.filltime.tv_sec = (time_t)wait32.filltime.tv_sec;
+        wait.filltime.tv_usec = (suseconds_t)wait32.filltime.tv_usec;
+
+        old_fs = get_fs();
+        set_fs(KERNEL_DS);
+        if (cmd == VIDEO1394_IOC32_LISTEN_QUEUE_BUFFER)
+		ret = video1394_ioctl(file->f_dentry->d_inode, file,
+				      VIDEO1394_IOC_LISTEN_QUEUE_BUFFER,
+				      (unsigned long) &wait);
+        else
+		ret = video1394_ioctl(file->f_dentry->d_inode, file,
+				      VIDEO1394_IOC_TALK_WAIT_BUFFER,
+				      (unsigned long) &wait);
+        set_fs(old_fs);
+
+        return ret;
+}
+
+static int video1394_queue_buf32(unsigned int fd, unsigned int cmd, unsigned long arg,
+				 struct file *file)
+{
+	if (file->f_op->ioctl != video1394_ioctl)
+		return -EFAULT;
+
+        return -EFAULT;
+
+	return video1394_ioctl(file->f_dentry->d_inode, file,
+				VIDEO1394_IOC_TALK_QUEUE_BUFFER, arg);
+}
+
+#endif /* CONFIG_COMPAT */
+
 static void __exit video1394_exit_module (void)
 {
+#ifdef CONFIG_COMPAT
+	int ret;
+
+	ret = unregister_ioctl32_conversion(VIDEO1394_IOC_LISTEN_CHANNEL);
+	ret |= unregister_ioctl32_conversion(VIDEO1394_IOC_UNLISTEN_CHANNEL);
+	ret |= unregister_ioctl32_conversion(VIDEO1394_IOC_TALK_CHANNEL);
+	ret |= unregister_ioctl32_conversion(VIDEO1394_IOC_UNTALK_CHANNEL);
+	ret |= unregister_ioctl32_conversion(VIDEO1394_IOC32_LISTEN_QUEUE_BUFFER);
+	ret |= unregister_ioctl32_conversion(VIDEO1394_IOC32_LISTEN_WAIT_BUFFER);
+	ret |= unregister_ioctl32_conversion(VIDEO1394_IOC_TALK_QUEUE_BUFFER);
+	ret |= unregister_ioctl32_conversion(VIDEO1394_IOC32_TALK_WAIT_BUFFER);
+	ret |= unregister_ioctl32_conversion(VIDEO1394_IOC32_LISTEN_POLL_BUFFER);
+	if (ret)
+		PRINT_G(KERN_INFO, "Error unregistering ioctl32 translations");
+#endif
+
 	hpsb_unregister_highlevel (hl_handle);
 
 	devfs_unregister(devfs_handle);
 	ieee1394_unregister_chardev(IEEE1394_MINOR_BLOCK_VIDEO1394);
-	
+
 	PRINT_G(KERN_INFO, "Removed " VIDEO1394_DRIVER_NAME " module");
 }
 
 static int __init video1394_init_module (void)
 {
-	if (ieee1394_register_chardev(IEEE1394_MINOR_BLOCK_VIDEO1394,
-				      THIS_MODULE, &video1394_fops)) {
+	int ret;
+
+	ret = ieee1394_register_chardev(IEEE1394_MINOR_BLOCK_VIDEO1394,
+					THIS_MODULE, &video1394_fops);
+	if (ret) {
 		PRINT_G(KERN_ERR, "video1394: unable to get minor device block");
- 		return -EIO;
- 	}
-	
+		return -EIO;
+        }
+
 	devfs_handle = devfs_mk_dir(NULL, VIDEO1394_DRIVER_NAME, NULL);
 
 	hl_handle = hpsb_register_highlevel (VIDEO1394_DRIVER_NAME, &hl_ops);
@@ -1366,9 +1496,32 @@
 		return -ENOMEM;
 	}
 
+#ifdef CONFIG_COMPAT
+	/* First the compatible ones */
+	ret = register_ioctl32_conversion(VIDEO1394_IOC_LISTEN_CHANNEL, NULL);
+	ret |= register_ioctl32_conversion(VIDEO1394_IOC_UNLISTEN_CHANNEL, NULL);
+	ret |= register_ioctl32_conversion(VIDEO1394_IOC_TALK_CHANNEL, NULL);
+	ret |= register_ioctl32_conversion(VIDEO1394_IOC_UNTALK_CHANNEL, NULL);
+
+	/* These need translation */
+	ret |= register_ioctl32_conversion(VIDEO1394_IOC32_LISTEN_QUEUE_BUFFER,
+				    video1394_w_wait32);
+	ret |= register_ioctl32_conversion(VIDEO1394_IOC32_LISTEN_WAIT_BUFFER,
+				    video1394_wr_wait32);
+	ret |= register_ioctl32_conversion(VIDEO1394_IOC_TALK_QUEUE_BUFFER,
+				    video1394_queue_buf32);
+	ret |= register_ioctl32_conversion(VIDEO1394_IOC32_TALK_WAIT_BUFFER,
+				    video1394_w_wait32);
+	ret |= register_ioctl32_conversion(VIDEO1394_IOC32_LISTEN_POLL_BUFFER,
+				    video1394_wr_wait32);
+	if (ret)
+		PRINT_G(KERN_INFO, "Error registering ioctl32 translations");
+#endif
+
 	PRINT_G(KERN_INFO, "Installed " VIDEO1394_DRIVER_NAME " module");
 	return 0;
 }
 
+
 module_init(video1394_init_module);
 module_exit(video1394_exit_module);
diff -urN linux-2.5.63-bk7/drivers/pnp/interface.c linux-2.5.64/drivers/pnp/interface.c
--- linux-2.5.63-bk7/drivers/pnp/interface.c	Mon Feb 24 11:05:10 2003
+++ linux-2.5.64/drivers/pnp/interface.c	Mon Mar 31 12:22:22 2003
@@ -13,6 +13,7 @@
 #include <linux/types.h>
 #include <linux/stat.h>
 #include <linux/ctype.h>
+#include <linux/slab.h>
 #include <asm/uaccess.h>
 
 #include "base.h"
diff -urN linux-2.5.63-bk7/fs/dcache.c linux-2.5.64/fs/dcache.c
--- linux-2.5.63-bk7/fs/dcache.c	Mon Mar 31 12:22:11 2003
+++ linux-2.5.64/fs/dcache.c	Mon Mar 31 12:22:24 2003
@@ -47,16 +47,8 @@
 
 static unsigned int d_hash_mask;
 static unsigned int d_hash_shift;
-static struct list_head *dentry_hashtable;
+static struct hlist_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 = {
@@ -292,6 +284,7 @@
 	while (next != head) {
 		tmp = next;
 		next = tmp->next;
+		prefetch(next);
 		alias = list_entry(tmp, struct dentry, d_alias);
  		if (!d_unhashed(alias)) {
 			if (alias->d_flags & DCACHE_DISCONNECTED)
@@ -378,6 +371,7 @@
 		if (tmp == &dentry_unused)
 			break;
 		list_del_init(tmp);
+		prefetch(dentry_unused.prev);
  		dentry_stat.nr_unused--;
 		dentry = list_entry(tmp, struct dentry, d_lru);
 
@@ -603,15 +597,15 @@
  * done under dcache_lock.
  *
  */
-void shrink_dcache_anon(struct list_head *head)
+void shrink_dcache_anon(struct hlist_head *head)
 {
-	struct list_head *lp;
+	struct hlist_node *lp;
 	int found;
 	do {
 		found = 0;
 		spin_lock(&dcache_lock);
-		list_for_each(lp, head) {
-			struct dentry *this = list_entry(lp, struct dentry, d_hash);
+		hlist_for_each(lp, head) {
+			struct dentry *this = hlist_entry(lp, struct dentry, d_hash);
 			list_del(&this->d_lru);
 
 			/* don't add non zero d_count dentries 
@@ -727,7 +721,7 @@
 	dentry->d_mounted = 0;
 	dentry->d_cookie = NULL;
 	dentry->d_bucket = NULL;
-	INIT_LIST_HEAD(&dentry->d_hash);
+	INIT_HLIST_NODE(&dentry->d_hash);
 	INIT_LIST_HEAD(&dentry->d_lru);
 	INIT_LIST_HEAD(&dentry->d_subdirs);
 	INIT_LIST_HEAD(&dentry->d_alias);
@@ -797,7 +791,7 @@
 	return res;
 }
 
-static inline struct list_head * d_hash(struct dentry * parent, unsigned long hash)
+static inline struct hlist_head * d_hash(struct dentry * parent, unsigned long hash)
 {
 	hash += (unsigned long) parent / L1_CACHE_BYTES;
 	hash = hash ^ (hash >> D_HASHBITS);
@@ -860,7 +854,7 @@
 			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);
+			hlist_add_head(&res->d_hash, &inode->i_sb->s_anon);
 			spin_unlock(&res->d_lock);
 		}
 		inode = NULL; /* don't drop reference */
@@ -947,21 +941,21 @@
 	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 hlist_head *head = d_hash(parent,hash);
 	struct dentry *found = NULL;
-	struct list_head *tmp;
-	int lookup_count = 0;
+	struct hlist_node *node;
 
 	rcu_read_lock();
 	
-	/* lookup is terminated when flow reaches any bucket head */
-	for(tmp = head->next; !is_bucket(tmp); tmp = tmp->next) {
+	hlist_for_each (node, head) { 
 		struct dentry *dentry; 
 		unsigned long move_count;
 		struct qstr * qstr;
 		
+		prefetch(node->next);
+
 		smp_read_barrier_depends();
-		dentry = list_entry(tmp, struct dentry, d_hash);
+		dentry = hlist_entry(node, struct dentry, d_hash);
 
 		/* if lookup ends up in a different bucket 
 		 * due to concurrent rename, fail it
@@ -969,12 +963,6 @@
 		if (unlikely(dentry->d_bucket != head))
 			break;
 
-		/* 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 
@@ -1034,7 +1022,8 @@
 	unsigned long dent_addr = (unsigned long) dentry;
 	unsigned long min_addr = PAGE_OFFSET;
 	unsigned long align_mask = 0x0F;
-	struct list_head *base, *lhp;
+	struct hlist_head *base;
+	struct hlist_node *lhp;
 
 	if (dent_addr < min_addr)
 		goto out;
@@ -1050,12 +1039,13 @@
 		goto out;
 
 	spin_lock(&dcache_lock);
-	lhp = base = d_hash(dparent, dentry->d_name.hash);
-	while ((lhp = lhp->next) != base) {
+	base = d_hash(dparent, dentry->d_name.hash);
+	hlist_for_each(lhp,base) { 
+		prefetch(lhp->next);
 		/* 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)) {
+		if (dentry == hlist_entry(lhp, struct dentry, d_hash)) {
 			__dget_locked(dentry);
 			spin_unlock(&dcache_lock);
 			return 1;
@@ -1116,12 +1106,11 @@
  
 void d_rehash(struct dentry * entry)
 {
-	struct list_head *list = d_hash(entry->d_parent, entry->d_name.hash);
+	struct hlist_head *list = d_hash(entry->d_parent, entry->d_name.hash);
 	spin_lock(&dcache_lock);
- 	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);
+ 	hlist_add_head_rcu(&entry->d_hash, list);
 	spin_unlock(&dcache_lock);
 }
 
@@ -1174,10 +1163,6 @@
  * We could be nicer about the deleted file, and let it show
  * up under the name it got deleted rather than the name that
  * deleted it.
- *
- * Careful with the hash switch. The hash switch depends on
- * the fact that any list-entry can be a head of the list.
- * Think about it.
  */
  
 /**
@@ -1200,8 +1185,8 @@
 	/* 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);
+		hlist_del_rcu(&dentry->d_hash);
+		hlist_add_head_rcu(&dentry->d_hash, target->d_bucket);
 	}
 
 	/* Unhash the target: dput() will then get rid of it */
@@ -1284,6 +1269,7 @@
 			continue;
 		}
 		parent = dentry->d_parent;
+		prefetch(parent);
 		namelen = dentry->d_name.len;
 		buflen -= namelen + 1;
 		if (buflen < 0)
@@ -1503,7 +1489,7 @@
 
 static void __init dcache_init(unsigned long mempages)
 {
-	struct list_head *d;
+	struct hlist_head *d;
 	unsigned long order;
 	unsigned int nr_hash;
 	int i;
@@ -1524,15 +1510,12 @@
 	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
 	mempages >>= (13 - PAGE_SHIFT);
 #endif
-	mempages *= sizeof(struct list_head);
+	mempages *= sizeof(struct hlist_head);
 	for (order = 0; ((1UL << order) << PAGE_SHIFT) < mempages; order++)
 		;
 
@@ -1540,7 +1523,7 @@
 		unsigned long tmp;
 
 		nr_hash = (1UL << order) * PAGE_SIZE /
-			sizeof(struct list_head);
+			sizeof(struct hlist_head);
 		d_hash_mask = (nr_hash - 1);
 
 		tmp = nr_hash;
@@ -1548,7 +1531,7 @@
 		while ((tmp >>= 1UL) != 0UL)
 			d_hash_shift++;
 
-		dentry_hashtable = (struct list_head *)
+		dentry_hashtable = (struct hlist_head *)
 			__get_free_pages(GFP_ATOMIC, order);
 	} while (dentry_hashtable == NULL && --order >= 0);
 
@@ -1558,12 +1541,10 @@
 	if (!dentry_hashtable)
 		panic("Failed to allocate dcache hash table\n");
 
-	hashtable_end = dentry_hashtable + nr_hash;
-
 	d = dentry_hashtable;
 	i = nr_hash;
 	do {
-		INIT_LIST_HEAD(d);
+		INIT_HLIST_HEAD(d);
 		d++;
 		i--;
 	} while (i);
diff -urN linux-2.5.63-bk7/fs/filesystems.c linux-2.5.64/fs/filesystems.c
--- linux-2.5.63-bk7/fs/filesystems.c	Mon Feb 24 11:05:40 2003
+++ linux-2.5.64/fs/filesystems.c	Mon Mar 31 12:22:25 2003
@@ -9,6 +9,7 @@
 #include <linux/fs.h>
 #include <linux/slab.h>
 #include <linux/kmod.h>
+#include <linux/init.h>
 #include <linux/module.h>
 #include <asm/uaccess.h>
 
@@ -58,6 +59,38 @@
 	return p;
 }
 
+
+/* define fs_subsys */
+static decl_subsys(fs, NULL);
+
+static int register_fs_subsys(struct file_system_type * fs)
+{
+	struct subsystem *sub = &fs->subsys;
+
+	snprintf(sub->kset.kobj.name, KOBJ_NAME_LEN, "%s", fs->name);
+	subsys_set_kset(fs, fs_subsys);
+	return subsystem_register(sub);
+}
+
+static int unlink_fs(struct file_system_type * fs)
+{
+	struct file_system_type ** tmp;
+
+	write_lock(&file_systems_lock);
+	tmp = &file_systems;
+	while (*tmp) {
+		if (fs == *tmp) {
+			*tmp = fs->next;
+			fs->next = NULL;
+			write_unlock(&file_systems_lock);
+			return 0;
+		}
+		tmp = &(*tmp)->next;
+	}
+	write_unlock(&file_systems_lock);
+	return -EINVAL;
+}
+
 /**
  *	register_filesystem - register a new filesystem
  *	@fs: the file system structure
@@ -88,6 +121,14 @@
 	else
 		*p = fs;
 	write_unlock(&file_systems_lock);
+
+	if (!res) {
+		/* we implicitly possess reference to @fs during registration,
+		 * so it cannot be unregister from under us. */
+		if (register_fs_subsys(fs))
+			printk(KERN_WARNING "Failed to register '%s' in sysfs\n",
+			       fs->name);
+	}
 	return res;
 }
 
@@ -105,21 +146,44 @@
  
 int unregister_filesystem(struct file_system_type * fs)
 {
-	struct file_system_type ** tmp;
+	int res;
 
-	write_lock(&file_systems_lock);
-	tmp = &file_systems;
-	while (*tmp) {
-		if (fs == *tmp) {
-			*tmp = fs->next;
-			fs->next = NULL;
-			write_unlock(&file_systems_lock);
-			return 0;
-		}
-		tmp = &(*tmp)->next;
-	}
-	write_unlock(&file_systems_lock);
-	return -EINVAL;
+	res = unlink_fs(fs);
+	if (!res)
+		subsystem_unregister(&fs->subsys);
+	return res;
+}
+
+extern int sysfs_init(void);
+
+/**
+ *	fs_subsys_init - initialize sysfs and fs subsystem.
+ *
+ *	In order to register filesystems in sysfs, it has to be 
+ *	initialized. Also, we need the base fs filesystem, so the 
+ *	registered filesystems have a home.
+ *	
+ *	During sysfs_init(), the registration of sysfs into itself
+ *	will fail, since it's not mounted yet. To make sure that 
+ *	sysfs does show up, we re-register sysfs's embedded subsystem,
+ *	which will get added, since sysfs is now mounted.
+ */
+
+void __init fs_subsys_init(void)
+{
+	struct file_system_type ** p;
+
+	/* make sure sysfs is up and running */
+	sysfs_init();
+
+	/* register fs_subsys */
+	subsystem_register(&fs_subsys);
+
+	p = find_filesystem("sysfs");
+
+	if (p)
+		/* make sure it's registered */
+		register_fs_subsys(*p);
 }
 
 static int fs_index(const char * __name)
diff -urN linux-2.5.63-bk7/fs/fs-writeback.c linux-2.5.64/fs/fs-writeback.c
--- linux-2.5.63-bk7/fs/fs-writeback.c	Mon Feb 24 11:06:03 2003
+++ linux-2.5.64/fs/fs-writeback.c	Mon Mar 31 12:22:25 2003
@@ -90,7 +90,7 @@
 		 * Only add valid (hashed) inodes to the superblock's
 		 * dirty list.  Add blockdev inodes as well.
 		 */
-		if (list_empty(&inode->i_hash) && !S_ISBLK(inode->i_mode))
+		if (hlist_unhashed(&inode->i_hash) && !S_ISBLK(inode->i_mode))
 			goto out;
 
 		/*
diff -urN linux-2.5.63-bk7/fs/hugetlbfs/inode.c linux-2.5.64/fs/hugetlbfs/inode.c
--- linux-2.5.63-bk7/fs/hugetlbfs/inode.c	Mon Feb 24 11:05:43 2003
+++ linux-2.5.64/fs/hugetlbfs/inode.c	Mon Mar 31 12:22:25 2003
@@ -189,7 +189,7 @@
 
 static void hugetlbfs_delete_inode(struct inode *inode)
 {
-	list_del_init(&inode->i_hash);
+	hlist_del_init(&inode->i_hash);
 	list_del_init(&inode->i_list);
 	inode->i_state |= I_FREEING;
 	inodes_stat.nr_inodes--;
@@ -208,7 +208,7 @@
 {
 	struct super_block *super_block = inode->i_sb;
 
-	if (list_empty(&inode->i_hash))
+	if (hlist_unhashed(&inode->i_hash))
 		goto out_truncate;
 
 	if (!(inode->i_state & (I_DIRTY|I_LOCK))) {
@@ -223,7 +223,7 @@
 
 	/* write_inode_now() ? */
 	inodes_stat.nr_unused--;
-	list_del_init(&inode->i_hash);
+	hlist_del_init(&inode->i_hash);
 out_truncate:
 	list_del_init(&inode->i_list);
 	inode->i_state |= I_FREEING;
diff -urN linux-2.5.63-bk7/fs/inode.c linux-2.5.64/fs/inode.c
--- linux-2.5.63-bk7/fs/inode.c	Mon Mar 31 12:22:11 2003
+++ linux-2.5.64/fs/inode.c	Mon Mar 31 12:22:25 2003
@@ -69,8 +69,8 @@
 
 LIST_HEAD(inode_in_use);
 LIST_HEAD(inode_unused);
-static struct list_head *inode_hashtable;
-static LIST_HEAD(anon_hash_chain); /* for inodes with NULL i_sb */
+static struct hlist_head *inode_hashtable;
+static HLIST_HEAD(anon_hash_chain); /* for inodes with NULL i_sb */
 
 /*
  * A simple spinlock to protect the list manipulations.
@@ -172,7 +172,7 @@
 void inode_init_once(struct inode *inode)
 {
 	memset(inode, 0, sizeof(*inode));
-	INIT_LIST_HEAD(&inode->i_hash);
+	INIT_HLIST_NODE(&inode->i_hash);
 	INIT_LIST_HEAD(&inode->i_data.clean_pages);
 	INIT_LIST_HEAD(&inode->i_data.dirty_pages);
 	INIT_LIST_HEAD(&inode->i_data.locked_pages);
@@ -294,7 +294,7 @@
 			continue;
 		invalidate_inode_buffers(inode);
 		if (!atomic_read(&inode->i_count)) {
-			list_del_init(&inode->i_hash);
+			hlist_del_init(&inode->i_hash);
 			list_del(&inode->i_list);
 			list_add(&inode->i_list, dispose);
 			inode->i_state |= I_FREEING;
@@ -435,7 +435,7 @@
 			if (!can_unuse(inode))
 				continue;
 		}
-		list_del_init(&inode->i_hash);
+		hlist_del_init(&inode->i_hash);
 		list_move(&inode->i_list, &freeable);
 		inode->i_state |= I_FREEING;
 		nr_pruned++;
@@ -476,50 +476,42 @@
  * by hand after calling find_inode now! This simplifies iunique and won't
  * add any additional branch in the common code.
  */
-static struct inode * find_inode(struct super_block * sb, struct list_head *head, int (*test)(struct inode *, void *), void *data)
+static struct inode * find_inode(struct super_block * sb, struct hlist_head *head, int (*test)(struct inode *, void *), void *data)
 {
-	struct list_head *tmp;
-	struct inode * inode;
+	struct hlist_node *node;
+	struct inode * inode = NULL;
 
-	tmp = head;
-	for (;;) {
-		tmp = tmp->next;
-		inode = NULL;
-		if (tmp == head)
-			break;
-		inode = list_entry(tmp, struct inode, i_hash);
+	hlist_for_each (node, head) { 
+		prefetch(node->next);
+		inode = hlist_entry(node, struct inode, i_hash);
 		if (inode->i_sb != sb)
 			continue;
 		if (!test(inode, data))
 			continue;
 		break;
 	}
-	return inode;
+	return node ? inode : NULL;
 }
 
 /*
  * find_inode_fast is the fast path version of find_inode, see the comment at
  * iget_locked for details.
  */
-static struct inode * find_inode_fast(struct super_block * sb, struct list_head *head, unsigned long ino)
+static struct inode * find_inode_fast(struct super_block * sb, struct hlist_head *head, unsigned long ino)
 {
-	struct list_head *tmp;
-	struct inode * inode;
+	struct hlist_node *node;
+	struct inode * inode = NULL;
 
-	tmp = head;
-	for (;;) {
-		tmp = tmp->next;
-		inode = NULL;
-		if (tmp == head)
-			break;
-		inode = list_entry(tmp, struct inode, i_hash);
+	hlist_for_each (node, head) {
+		prefetch(node->next);
+		inode = list_entry(node, struct inode, i_hash);
 		if (inode->i_ino != ino)
 			continue;
 		if (inode->i_sb != sb)
 			continue;
 		break;
 	}
-	return inode;
+	return node ? inode : NULL;
 }
 
 /**
@@ -569,7 +561,7 @@
  * We no longer cache the sb_flags in i_flags - see fs.h
  *	-- rmk@arm.uk.linux.org
  */
-static struct inode * get_new_inode(struct super_block *sb, struct list_head *head, int (*test)(struct inode *, void *), int (*set)(struct inode *, void *), void *data)
+static struct inode * get_new_inode(struct super_block *sb, struct hlist_head *head, int (*test)(struct inode *, void *), int (*set)(struct inode *, void *), void *data)
 {
 	struct inode * inode;
 
@@ -586,7 +578,7 @@
 
 			inodes_stat.nr_inodes++;
 			list_add(&inode->i_list, &inode_in_use);
-			list_add(&inode->i_hash, head);
+			hlist_add_head(&inode->i_hash, head);
 			inode->i_state = I_LOCK|I_NEW;
 			spin_unlock(&inode_lock);
 
@@ -619,7 +611,7 @@
  * get_new_inode_fast is the fast path version of get_new_inode, see the
  * comment at iget_locked for details.
  */
-static struct inode * get_new_inode_fast(struct super_block *sb, struct list_head *head, unsigned long ino)
+static struct inode * get_new_inode_fast(struct super_block *sb, struct hlist_head *head, unsigned long ino)
 {
 	struct inode * inode;
 
@@ -634,7 +626,7 @@
 			inode->i_ino = ino;
 			inodes_stat.nr_inodes++;
 			list_add(&inode->i_list, &inode_in_use);
-			list_add(&inode->i_hash, head);
+			hlist_add_head(&inode->i_hash, head);
 			inode->i_state = I_LOCK|I_NEW;
 			spin_unlock(&inode_lock);
 
@@ -686,7 +678,7 @@
 {
 	static ino_t counter = 0;
 	struct inode *inode;
-	struct list_head * head;
+	struct hlist_head * head;
 	ino_t res;
 	spin_lock(&inode_lock);
 retry:
@@ -740,7 +732,7 @@
  * Note, @test is called with the inode_lock held, so can't sleep.
  */
 static inline struct inode *ifind(struct super_block *sb,
-		struct list_head *head, int (*test)(struct inode *, void *),
+		struct hlist_head *head, int (*test)(struct inode *, void *),
 		void *data)
 {
 	struct inode *inode;
@@ -772,7 +764,7 @@
  * Otherwise NULL is returned.
  */
 static inline struct inode *ifind_fast(struct super_block *sb,
-		struct list_head *head, unsigned long ino)
+		struct hlist_head *head, unsigned long ino)
 {
 	struct inode *inode;
 
@@ -810,7 +802,7 @@
 struct inode *ilookup5(struct super_block *sb, unsigned long hashval,
 		int (*test)(struct inode *, void *), void *data)
 {
-	struct list_head *head = inode_hashtable + hash(sb, hashval);
+	struct hlist_head *head = inode_hashtable + hash(sb, hashval);
 
 	return ifind(sb, head, test, data);
 }
@@ -832,7 +824,7 @@
  */
 struct inode *ilookup(struct super_block *sb, unsigned long ino)
 {
-	struct list_head *head = inode_hashtable + hash(sb, ino);
+	struct hlist_head *head = inode_hashtable + hash(sb, ino);
 
 	return ifind_fast(sb, head, ino);
 }
@@ -864,7 +856,7 @@
 		int (*test)(struct inode *, void *),
 		int (*set)(struct inode *, void *), void *data)
 {
-	struct list_head *head = inode_hashtable + hash(sb, hashval);
+	struct hlist_head *head = inode_hashtable + hash(sb, hashval);
 	struct inode *inode;
 
 	inode = ifind(sb, head, test, data);
@@ -897,7 +889,7 @@
  */
 struct inode *iget_locked(struct super_block *sb, unsigned long ino)
 {
-	struct list_head *head = inode_hashtable + hash(sb, ino);
+	struct hlist_head *head = inode_hashtable + hash(sb, ino);
 	struct inode *inode;
 
 	inode = ifind_fast(sb, head, ino);
@@ -923,11 +915,11 @@
  
 void __insert_inode_hash(struct inode *inode, unsigned long hashval)
 {
-	struct list_head *head = &anon_hash_chain;
+	struct hlist_head *head = &anon_hash_chain;
 	if (inode->i_sb)
 		head = inode_hashtable + hash(inode->i_sb, hashval);
 	spin_lock(&inode_lock);
-	list_add(&inode->i_hash, head);
+	hlist_add_head(&inode->i_hash, head);
 	spin_unlock(&inode_lock);
 }
 
@@ -941,7 +933,7 @@
 void remove_inode_hash(struct inode *inode)
 {
 	spin_lock(&inode_lock);
-	list_del_init(&inode->i_hash);
+	hlist_del_init(&inode->i_hash);
 	spin_unlock(&inode_lock);
 }
 
@@ -949,7 +941,7 @@
 {
 	struct super_operations *op = inode->i_sb->s_op;
 
-	list_del_init(&inode->i_hash);
+	hlist_del_init(&inode->i_hash);
 	list_del_init(&inode->i_list);
 	inode->i_state|=I_FREEING;
 	inodes_stat.nr_inodes--;
@@ -978,7 +970,7 @@
 {
 	struct super_block *sb = inode->i_sb;
 
-	if (!list_empty(&inode->i_hash)) {
+	if (!hlist_unhashed(&inode->i_hash)) {
 		if (!(inode->i_state & (I_DIRTY|I_LOCK))) {
 			list_del(&inode->i_list);
 			list_add(&inode->i_list, &inode_unused);
@@ -990,7 +982,7 @@
 		write_inode_now(inode, 1);
 		spin_lock(&inode_lock);
 		inodes_stat.nr_unused--;
-		list_del_init(&inode->i_hash);
+		hlist_del_init(&inode->i_hash);
 	}
 	list_del_init(&inode->i_list);
 	inode->i_state|=I_FREEING;
@@ -1236,7 +1228,7 @@
  */
 void __init inode_init(unsigned long mempages)
 {
-	struct list_head *head;
+	struct hlist_head *head;
 	unsigned long order;
 	unsigned int nr_hash;
 	int i;
@@ -1253,7 +1245,7 @@
 		unsigned long tmp;
 
 		nr_hash = (1UL << order) * PAGE_SIZE /
-			sizeof(struct list_head);
+			sizeof(struct hlist_head);
 		i_hash_mask = (nr_hash - 1);
 
 		tmp = nr_hash;
@@ -1261,7 +1253,7 @@
 		while ((tmp >>= 1UL) != 0UL)
 			i_hash_shift++;
 
-		inode_hashtable = (struct list_head *)
+		inode_hashtable = (struct hlist_head *)
 			__get_free_pages(GFP_ATOMIC, order);
 	} while (inode_hashtable == NULL && --order >= 0);
 
@@ -1274,7 +1266,7 @@
 	head = inode_hashtable;
 	i = nr_hash;
 	do {
-		INIT_LIST_HEAD(head);
+		INIT_HLIST_HEAD(head);
 		head++;
 		i--;
 	} while (i);
diff -urN linux-2.5.63-bk7/fs/namespace.c linux-2.5.64/fs/namespace.c
--- linux-2.5.63-bk7/fs/namespace.c	Mon Feb 24 11:05:36 2003
+++ linux-2.5.64/fs/namespace.c	Mon Mar 31 12:22:25 2003
@@ -26,6 +26,7 @@
 extern struct vfsmount *do_kern_mount(const char *type, int flags, char *name, void *data);
 extern int do_remount_sb(struct super_block *sb, int flags, void * data);
 extern int __init init_rootfs(void);
+extern int __init fs_subsys_init(void);
 
 static struct list_head *mount_hashtable;
 static int hash_mask, hash_bits;
@@ -1132,6 +1133,7 @@
 		d++;
 		i--;
 	} while (i);
+	fs_subsys_init();
 	init_rootfs();
 	init_mount_tree();
 }
diff -urN linux-2.5.63-bk7/fs/super.c linux-2.5.64/fs/super.c
--- linux-2.5.63-bk7/fs/super.c	Mon Feb 24 11:05:31 2003
+++ linux-2.5.64/fs/super.c	Mon Mar 31 12:22:25 2003
@@ -63,7 +63,7 @@
 		INIT_LIST_HEAD(&s->s_io);
 		INIT_LIST_HEAD(&s->s_files);
 		INIT_LIST_HEAD(&s->s_instances);
-		INIT_LIST_HEAD(&s->s_anon);
+		INIT_HLIST_HEAD(&s->s_anon);
 		init_rwsem(&s->s_umount);
 		sema_init(&s->s_lock, 1);
 		down_write(&s->s_umount);
diff -urN linux-2.5.63-bk7/fs/sysfs/bin.c linux-2.5.64/fs/sysfs/bin.c
--- linux-2.5.63-bk7/fs/sysfs/bin.c	Mon Mar 31 12:22:11 2003
+++ linux-2.5.64/fs/sysfs/bin.c	Mon Mar 31 12:22:25 2003
@@ -226,6 +226,7 @@
 int sysfs_remove_bin_file(struct kobject * kobj, struct bin_attribute * attr)
 {
 	sysfs_hash_and_remove(kobj->dentry,attr->attr.name);
+	return 0;
 }
 
 EXPORT_SYMBOL(sysfs_create_bin_file);
diff -urN linux-2.5.63-bk7/fs/sysfs/mount.c linux-2.5.64/fs/sysfs/mount.c
--- linux-2.5.63-bk7/fs/sysfs/mount.c	Mon Mar 31 12:22:11 2003
+++ linux-2.5.64/fs/sysfs/mount.c	Mon Mar 31 12:22:25 2003
@@ -7,6 +7,7 @@
 #include <linux/fs.h>
 #include <linux/mount.h>
 #include <linux/pagemap.h>
+#include <linux/init.h>
 
 #include "sysfs.h"
 
@@ -65,7 +66,7 @@
 	.kill_sb	= kill_litter_super,
 };
 
-static int __init sysfs_init(void)
+int __init sysfs_init(void)
 {
 	int err;
 
@@ -80,5 +81,3 @@
 	}
 	return err;
 }
-
-core_initcall(sysfs_init);
diff -urN linux-2.5.63-bk7/include/linux/dcache.h linux-2.5.64/include/linux/dcache.h
--- linux-2.5.63-bk7/include/linux/dcache.h	Mon Mar 31 12:22:11 2003
+++ linux-2.5.64/include/linux/dcache.h	Mon Mar 31 12:22:26 2003
@@ -76,25 +76,25 @@
 	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;		/* 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 int d_flags;
+	int d_mounted;
 	void * d_fsdata;		/* fs-specific data */
  	struct rcu_head d_rcu;
 	struct dcookie_struct * d_cookie; /* cookie, if any */
+	unsigned long d_move_count;	/* to indicated moved dentry while lockless lookup */
+	struct qstr * d_qstr;		/* quick str ptr used in lockless lookup and concurrent d_move */
+	struct dentry * d_parent;	/* parent directory */
+	struct qstr d_name;
+	struct hlist_node d_hash;	/* lookup hash list */	
+	struct hlist_head * d_bucket;	/* lookup hash bucket */
 	unsigned char d_iname[DNAME_INLINE_LEN_MIN]; /* small names */
 } ____cacheline_aligned;
 
@@ -171,7 +171,7 @@
 static __inline__ void __d_drop(struct dentry * dentry)
 {
 	dentry->d_vfs_flags |= DCACHE_UNHASHED;
-	list_del_rcu(&dentry->d_hash);
+	hlist_del_rcu(&dentry->d_hash);
 }
 
 static __inline__ void d_drop(struct dentry * dentry)
@@ -198,7 +198,7 @@
 extern struct dentry * d_splice_alias(struct inode *, struct dentry *);
 extern void shrink_dcache_sb(struct super_block *);
 extern void shrink_dcache_parent(struct dentry *);
-extern void shrink_dcache_anon(struct list_head *);
+extern void shrink_dcache_anon(struct hlist_head *);
 extern int d_invalidate(struct dentry *);
 
 /* only used at mount-time */
diff -urN linux-2.5.63-bk7/include/linux/fs.h linux-2.5.64/include/linux/fs.h
--- linux-2.5.63-bk7/include/linux/fs.h	Mon Mar 31 12:22:11 2003
+++ linux-2.5.64/include/linux/fs.h	Mon Mar 31 12:22:26 2003
@@ -18,6 +18,7 @@
 #include <linux/stat.h>
 #include <linux/cache.h>
 #include <linux/radix-tree.h>
+#include <linux/kobject.h>
 #include <asm/atomic.h>
 
 struct iovec;
@@ -353,7 +354,7 @@
 };
 
 struct inode {
-	struct list_head	i_hash;
+	struct hlist_node	i_hash;
 	struct list_head	i_list;
 	struct list_head	i_dentry;
 	unsigned long		i_ino;
@@ -601,7 +602,7 @@
 
 	struct list_head	s_dirty;	/* dirty inodes */
 	struct list_head	s_io;		/* parked for writeback */
-	struct list_head	s_anon;		/* anonymous dentries for (nfs) exporting */
+	struct hlist_head	s_anon;		/* anonymous dentries for (nfs) exporting */
 	struct list_head	s_files;
 
 	struct block_device	*s_bdev;
@@ -610,6 +611,7 @@
 
 	char s_id[32];				/* Informational name */
 
+	struct kobject           kobj;          /* anchor for sysfs */
 	void 			*s_fs_info;	/* Filesystem private info */
 
 	/*
@@ -913,6 +915,7 @@
 
 struct file_system_type {
 	const char *name;
+	struct subsystem subsys;
 	int fs_flags;
 	struct super_block *(*get_sb) (struct file_system_type *, int, char *, void *);
 	void (*kill_sb) (struct super_block *);
diff -urN linux-2.5.63-bk7/include/linux/list.h linux-2.5.64/include/linux/list.h
--- linux-2.5.63-bk7/include/linux/list.h	Mon Feb 24 11:05:33 2003
+++ linux-2.5.64/include/linux/list.h	Mon Mar 31 12:22:26 2003
@@ -319,6 +319,98 @@
 	for (pos = (head)->next, n = pos->next; pos != (head); \
 		pos = n, ({ read_barrier_depends(); 0;}), n = pos->next)
 
+/* 
+ * Double linked lists with a single pointer list head. 
+ * Mostly useful for hash tables where the two pointer list head is 
+ * too wasteful.
+ * You lose the ability to access the tail in O(1).
+ */ 
+
+struct hlist_head { 
+	struct hlist_node *first; 
+}; 
+
+struct hlist_node { 
+	struct hlist_node *next, **pprev; 
+}; 
+
+#define HLIST_HEAD_INIT { .first = NULL } 
+#define HLIST_HEAD(name) struct hlist_head name = {  .first = NULL }
+#define INIT_HLIST_HEAD(ptr) ((ptr)->first = NULL) 
+#define INIT_HLIST_NODE(ptr) ((ptr)->next = NULL, (ptr)->pprev = NULL)
+
+static __inline__ int hlist_unhashed(struct hlist_node *h) 
+{ 
+	return !h->pprev;
+} 
+
+static __inline__ int hlist_empty(struct hlist_head *h) 
+{ 
+	return !h->first;
+} 
+
+static __inline__ void __hlist_del(struct hlist_node *n) 
+{
+	struct hlist_node *next = n->next;
+	struct hlist_node **pprev = n->pprev;
+	*pprev = next;  
+	if (next) 
+		next->pprev = pprev;
+}  
+
+static __inline__ void hlist_del(struct hlist_node *n)
+{
+	if (n->pprev)
+		__hlist_del(n);
+}
+
+#define hlist_del_rcu hlist_del  /* list_del_rcu is identical too? */
+
+static __inline__ void hlist_del_init(struct hlist_node *n) 
+{
+	if (n->pprev)  {
+		__hlist_del(n);
+		INIT_HLIST_NODE(n);
+	}
+}  
+
+static __inline__ void hlist_add_head(struct hlist_node *n, struct hlist_head *h) 
+{ 
+	struct hlist_node *first = h->first;
+	n->next = first; 
+	if (first) 
+		first->pprev = &n->next;
+	h->first = n; 
+	n->pprev = &h->first; 
+} 
+
+static __inline__ void hlist_add_head_rcu(struct hlist_node *n, struct hlist_head *h) 
+{ 
+	struct hlist_node *first = h->first;
+	n->next = first;
+	n->pprev = &h->first; 
+	smp_wmb();
+	if (first) 
+		first->pprev = &n->next;
+	h->first = n; 
+} 
+
+/* next must be != NULL */
+static __inline__ void hlist_add_before(struct hlist_node *n, struct hlist_node *next)
+{
+	n->pprev = next->pprev;
+	n->next = next; 
+	next->pprev = &n->next; 
+	*(n->pprev) = n;
+}
+
+#define hlist_entry(ptr, type, member) container_of(ptr,type,member)
+
+/* Cannot easily do prefetch unfortunately */
+#define hlist_for_each(pos, head) \
+	for (pos = (head)->first; pos; \
+	     pos = pos->next) 
+
 #else
 #warning "don't include kernel headers in userspace"
 #endif /* __KERNEL__ */
diff -urN linux-2.5.63-bk7/init/main.c linux-2.5.64/init/main.c
--- linux-2.5.63-bk7/init/main.c	Mon Feb 24 11:05:11 2003
+++ linux-2.5.64/init/main.c	Mon Mar 31 12:22:26 2003
@@ -71,6 +71,7 @@
 extern void radix_tree_init(void);
 extern void free_initmem(void);
 extern void populate_rootfs(void);
+extern void driver_init(void);
 
 #ifdef CONFIG_TC
 extern void tc_init(void);
@@ -476,6 +477,8 @@
  */
 static void __init do_basic_setup(void)
 {
+	driver_init();
+
 #ifdef CONFIG_SYSCTL
 	sysctl_init();
 #endif
diff -urN linux-2.5.63-bk7/net/sunrpc/rpc_pipe.c linux-2.5.64/net/sunrpc/rpc_pipe.c
--- linux-2.5.63-bk7/net/sunrpc/rpc_pipe.c	Mon Feb 24 11:05:14 2003
+++ linux-2.5.64/net/sunrpc/rpc_pipe.c	Mon Mar 31 12:22:27 2003
@@ -479,7 +479,7 @@
 rpc_depopulate(struct dentry *parent)
 {
 	struct inode *dir = parent->d_inode;
-	LIST_HEAD(head);
+	HLIST_HEAD(head);
 	struct list_head *pos, *next;
 	struct dentry *dentry;
 
@@ -490,12 +490,12 @@
 		if (!d_unhashed(dentry)) {
 			dget_locked(dentry);
 			__d_drop(dentry);
-			list_add(&dentry->d_hash, &head);
+			hlist_add_head(&dentry->d_hash, &head);
 		}
 	}
 	spin_unlock(&dcache_lock);
-	while (!list_empty(&head)) {
-		dentry = list_entry(head.next, struct dentry, d_hash);
+	while (!hlist_empty(&head)) {
+		dentry = list_entry(head.first, struct dentry, d_hash);
 		/* Private list, so no dcache_lock needed and use __d_drop */
 		__d_drop(dentry);
 		if (dentry->d_inode) {
