diff -Nru a/Makefile b/Makefile
--- a/Makefile	Sun Jun 22 11:30:18 2003
+++ b/Makefile	Mon Jun 23 12:09:46 2003
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 5
 SUBLEVEL = 73
-EXTRAVERSION =
+EXTRAVERSION = -bk1
 
 # *DOCUMENTATION*
 # To see a list of typical targets execute "make help"
diff -Nru a/arch/sparc/kernel/process.c b/arch/sparc/kernel/process.c
--- a/arch/sparc/kernel/process.c	Mon May 19 17:27:22 2003
+++ b/arch/sparc/kernel/process.c	Sun Jun 22 19:34:14 2003
@@ -287,17 +287,14 @@
 	       rw->ins[4], rw->ins[5], rw->ins[6], rw->ins[7]);
 }
 
-void show_trace_task(struct task_struct *tsk)
+void show_stack(struct task_struct *tsk, unsigned long *_ksp)
 {
 	unsigned long pc, fp;
 	unsigned long task_base = (unsigned long) tsk;
 	struct reg_window *rw;
 	int count = 0;
 
-	if (!tsk)
-		return;
-
-	fp = tsk->thread_info->ksp;
+	fp = (unsigned long) _ksp;
 	do {
 		/* Bogus frame pointer? */
 		if (fp < (task_base + sizeof(struct task_struct)) ||
@@ -309,6 +306,13 @@
 		fp = rw->ins[6];
 	} while (++count < 16);
 	printk("\n");
+}
+
+void show_trace_task(struct task_struct *tsk)
+{
+	if (tsk)
+		show_stack(tsk,
+			   (unsigned long *) tsk->thread_info->ksp);
 }
 
 /*
diff -Nru a/arch/sparc/kernel/systbls.S b/arch/sparc/kernel/systbls.S
--- a/arch/sparc/kernel/systbls.S	Sat Mar  8 11:39:01 2003
+++ b/arch/sparc/kernel/systbls.S	Sun Jun 22 19:57:50 2003
@@ -64,9 +64,9 @@
 /*215*/	.long sys_ipc, sys_sigreturn, sys_clone, sys_nis_syscall, sys_adjtimex
 /*220*/	.long sys_sigprocmask, sys_ni_syscall, sys_delete_module, sys_ni_syscall, sys_getpgid
 /*225*/	.long sys_bdflush, sys_sysfs, sys_nis_syscall, sys_setfsuid16, sys_setfsgid16
-/*230*/	.long sys_select, sys_time, sys_nis_syscall, sys_stime, sys_nis_syscall
+/*230*/	.long sys_select, sys_time, sys_nis_syscall, sys_stime, sys_statfs64
 					  /* "We are the Knights of the Forest of Ni!!" */
-/*235*/	.long sys_nis_syscall, sys_llseek, sys_mlock, sys_munlock, sys_mlockall
+/*235*/	.long sys_fstatfs64, sys_llseek, sys_mlock, sys_munlock, sys_mlockall
 /*240*/	.long sys_munlockall, sys_sched_setparam, sys_sched_getparam, sys_sched_setscheduler, sys_sched_getscheduler
 /*245*/	.long sys_sched_yield, sys_sched_get_priority_max, sys_sched_get_priority_min, sys_sched_rr_get_interval, sys_nanosleep
 /*250*/	.long sparc_mremap, sys_sysctl, sys_getsid, sys_fdatasync, sys_nfsservctl
diff -Nru a/arch/sparc64/kernel/systbls.S b/arch/sparc64/kernel/systbls.S
--- a/arch/sparc64/kernel/systbls.S	Thu May 29 03:03:01 2003
+++ b/arch/sparc64/kernel/systbls.S	Sun Jun 22 19:57:50 2003
@@ -65,8 +65,8 @@
 	.word sys32_ipc, sys32_sigreturn, sys_clone, sys_nis_syscall, sys32_adjtimex
 /*220*/	.word compat_sys_sigprocmask, sys_ni_syscall, sys32_delete_module, sys_ni_syscall, sys_getpgid
 	.word sys32_bdflush, sys32_sysfs, sys_nis_syscall, sys32_setfsuid16, sys32_setfsgid16
-/*230*/	.word sys32_select, sys_time, sys_nis_syscall, sys_stime, sys_ni_syscall
-	.word sys_ni_syscall, sys_llseek, sys_mlock, sys_munlock, sys_mlockall
+/*230*/	.word sys32_select, sys_time, sys_nis_syscall, sys_stime, sys_statfs64
+	.word sys_fstatfs64, sys_llseek, sys_mlock, sys_munlock, sys_mlockall
 /*240*/	.word sys_munlockall, sys_sched_setparam, sys_sched_getparam, sys_sched_setscheduler, sys_sched_getscheduler
 	.word sys_sched_yield, sys_sched_get_priority_max, sys_sched_get_priority_min, sys32_sched_rr_get_interval, compat_sys_nanosleep
 /*250*/	.word sys32_mremap, sys32_sysctl, sys_getsid, sys_fdatasync, sys32_nfsservctl
@@ -124,11 +124,8 @@
 	.word sys_ipc, sys_nis_syscall, sys_clone, sys_nis_syscall, sys_adjtimex
 /*220*/	.word sys_nis_syscall, sys_ni_syscall, sys_delete_module, sys_ni_syscall, sys_getpgid
 	.word sys_bdflush, sys_sysfs, sys_nis_syscall, sys_setfsuid, sys_setfsgid
-
-	/* 234 and 235 were for the hugetlb syscalls.  They can be reused */
-
-/*230*/	.word sys_select, sys_nis_syscall, sys_nis_syscall, sys_stime, sys_nis_syscall
-	.word sys_nis_syscall, sys_llseek, sys_mlock, sys_munlock, sys_mlockall
+/*230*/	.word sys_select, sys_nis_syscall, sys_nis_syscall, sys_stime, sys_statfs64
+	.word sys_fstatfs64, sys_llseek, sys_mlock, sys_munlock, sys_mlockall
 /*240*/	.word sys_munlockall, sys_sched_setparam, sys_sched_getparam, sys_sched_setscheduler, sys_sched_getscheduler
 	.word sys_sched_yield, sys_sched_get_priority_max, sys_sched_get_priority_min, sys_sched_rr_get_interval, sys_nanosleep
 /*250*/	.word sys64_mremap, sys_sysctl, sys_getsid, sys_fdatasync, sys_nfsservctl
diff -Nru a/arch/sparc64/kernel/traps.c b/arch/sparc64/kernel/traps.c
--- a/arch/sparc64/kernel/traps.c	Thu Mar 27 13:56:45 2003
+++ b/arch/sparc64/kernel/traps.c	Sun Jun 22 19:34:14 2003
@@ -1569,12 +1569,15 @@
 	printk("\n");
 }
 
-void show_trace_raw(struct thread_info *tp, unsigned long ksp)
+void show_stack(struct task_struct *tsk, unsigned long *_ksp)
 {
-	unsigned long pc, fp, thread_base;
+	unsigned long pc, fp, thread_base, ksp;
+	struct thread_info *tp = tsk->thread_info;
 	struct reg_window *rw;
 	int count = 0;
 
+	ksp = (unsigned long) _ksp;
+
 	if (tp == current_thread_info())
 		flushw_all();
 
@@ -1596,17 +1599,17 @@
 void show_trace_task(struct task_struct *tsk)
 {
 	if (tsk)
-		show_trace_raw(tsk->thread_info,
-			       tsk->thread_info->ksp);
+		show_stack(tsk,
+			   (unsigned long *) tsk->thread_info->ksp);
 }
 
 void dump_stack(void)
 {
-	unsigned long ksp;
+	unsigned long *ksp;
 
 	__asm__ __volatile__("mov	%%fp, %0"
 			     : "=r" (ksp));
-	show_trace_raw(current_thread_info(), ksp);
+	show_stack(current, ksp);
 }
 
 void die_if_kernel(char *str, struct pt_regs *regs)
diff -Nru a/arch/sparc64/mm/fault.c b/arch/sparc64/mm/fault.c
--- a/arch/sparc64/mm/fault.c	Sun Jan  5 21:46:46 2003
+++ b/arch/sparc64/mm/fault.c	Sun Jun 22 19:34:14 2003
@@ -149,16 +149,14 @@
 	die_if_kernel("Oops", regs);
 }
 
-extern void show_trace_raw(struct thread_info *, unsigned long);
-
 static void bad_kernel_pc(struct pt_regs *regs)
 {
-	unsigned long ksp;
+	unsigned long *ksp;
 
 	printk(KERN_CRIT "OOPS: Bogus kernel PC [%016lx] in fault handler\n",
 	       regs->tpc);
 	__asm__("mov %%sp, %0" : "=r" (ksp));
-	show_trace_raw(current_thread_info(), ksp);
+	show_stack(current, ksp);
 	unhandled_fault(regs->tpc, current, regs);
 }
 
diff -Nru a/arch/sparc64/solaris/fs.c b/arch/sparc64/solaris/fs.c
--- a/arch/sparc64/solaris/fs.c	Tue Dec 31 17:36:12 2002
+++ b/arch/sparc64/solaris/fs.c	Sun Jun 22 18:49:10 2003
@@ -390,7 +390,7 @@
 
 static int report_statvfs(struct vfsmount *mnt, struct inode *inode, u32 buf)
 {
-	struct statfs s;
+	struct kstatfs s;
 	int error;
 	struct sol_statvfs *ss = (struct sol_statvfs *)A(buf);
 
@@ -424,7 +424,7 @@
 
 static int report_statvfs64(struct vfsmount *mnt, struct inode *inode, u32 buf)
 {
-	struct statfs s;
+	struct kstatfs s;
 	int error;
 	struct sol_statvfs64 *ss = (struct sol_statvfs64 *)A(buf);
 			
diff -Nru a/drivers/block/loop.c b/drivers/block/loop.c
--- a/drivers/block/loop.c	Wed Jun 11 19:54:11 2003
+++ b/drivers/block/loop.c	Sun Jun 22 20:44:06 2003
@@ -2,7 +2,7 @@
  *  linux/drivers/block/loop.c
  *
  *  Written by Theodore Ts'o, 3/29/93
- * 
+ *
  * Copyright 1993 by Theodore Ts'o.  Redistribution of this file is
  * permitted under the GNU General Public License.
  *
@@ -21,12 +21,12 @@
  * Loadable modules and other fixes by AK, 1998
  *
  * Make real block number available to downstream transfer functions, enables
- * CBC (and relatives) mode encryption requiring unique IVs per data block. 
+ * CBC (and relatives) mode encryption requiring unique IVs per data block.
  * Reed H. Petty, rhp@draper.net
  *
  * Maximum number of loop devices now dynamic via max_loop module parameter.
  * Russell Kroll <rkroll@exploits.org> 19990701
- * 
+ *
  * Maximum number of loop devices when compiled-in now selectable by passing
  * max_loop=<1-255> to the kernel on boot.
  * Erik I. Bolsų, <eriki@himolde.no>, Oct 31, 1999
@@ -40,19 +40,19 @@
  * Heinz Mauelshagen <mge@sistina.com>, Feb 2002
  *
  * Still To Fix:
- * - Advisory locking is ignored here. 
- * - Should use an own CAP_* category instead of CAP_SYS_ADMIN 
+ * - Advisory locking is ignored here.
+ * - Should use an own CAP_* category instead of CAP_SYS_ADMIN
  *
  * WARNING/FIXME:
  * - The block number as IV passing to low level transfer functions is broken:
  *   it passes the underlying device's block number instead of the
- *   offset. This makes it change for a given block when the file is 
- *   moved/restored/copied and also doesn't work over NFS. 
+ *   offset. This makes it change for a given block when the file is
+ *   moved/restored/copied and also doesn't work over NFS.
  * AV, Feb 12, 2000: we pass the logical block number now. It fixes the
  *   problem above. Encryption modules that used to rely on the old scheme
  *   should just call ->i_mapping->bmap() to calculate the physical block
  *   number.
- */ 
+ */
 
 #include <linux/config.h>
 #include <linux/module.h>
@@ -60,12 +60,10 @@
 #include <linux/sched.h>
 #include <linux/fs.h>
 #include <linux/file.h>
-#include <linux/bio.h>
 #include <linux/stat.h>
 #include <linux/errno.h>
 #include <linux/major.h>
 #include <linux/wait.h>
-#include <linux/blk.h>
 #include <linux/blkpg.h>
 #include <linux/init.h>
 #include <linux/devfs_fs_kernel.h>
@@ -127,24 +125,25 @@
 	return 0;
 }
 
-struct loop_func_table none_funcs = { 
+struct loop_func_table none_funcs = {
 	.number = LO_CRYPT_NONE,
 	.transfer = transfer_none,
 }; 	
 
-struct loop_func_table xor_funcs = { 
+struct loop_func_table xor_funcs = {
 	.number = LO_CRYPT_XOR,
 	.transfer = transfer_xor,
 	.init = xor_status
 }; 	
 
-/* xfer_funcs[0] is special - its release function is never called */ 
+/* xfer_funcs[0] is special - its release function is never called */
 struct loop_func_table *xfer_funcs[MAX_LO_CRYPT] = {
 	&none_funcs,
-	&xor_funcs  
+	&xor_funcs
 };
 
-static int figure_loop_size(struct loop_device *lo)
+static int
+figure_loop_size(struct loop_device *lo)
 {
 	loff_t size = lo->lo_backing_file->f_dentry->d_inode->i_mapping->host->i_size;
 	sector_t x;
@@ -154,15 +153,17 @@
 	 */
 	size = (size - lo->lo_offset) >> 9;
 	x = (sector_t)size;
+
 	if ((loff_t)x != size)
 		return -EFBIG;
 
-	set_capacity(disks[lo->lo_number], size);
+	set_capacity(disks[lo->lo_number], x);
 	return 0;					
 }
 
-static inline int lo_do_transfer(struct loop_device *lo, int cmd, char *rbuf,
-				 char *lbuf, int size, sector_t rblock)
+static inline int
+lo_do_transfer(struct loop_device *lo, int cmd, char *rbuf,
+	       char *lbuf, int size, sector_t rblock)
 {
 	if (!lo->transfer)
 		return 0;
@@ -614,9 +615,12 @@
 
 	daemonize("loop%d", lo->lo_number);
 
-	current->flags |= PF_IOTHREAD;	/* loop can be used in an encrypted device
-					   hence, it mustn't be stopped at all because it could
-					   be indirectly used during suspension */
+	/*
+	 * loop can be used in an encrypted device,
+	 * hence, it mustn't be stopped at all
+	 * because it could be indirectly used during suspension
+	 */
+	current->flags |= PF_IOTHREAD;
 
 	set_user_nice(current, -20);
 
@@ -771,36 +775,42 @@
 	return error;
 }
 
-static int loop_release_xfer(struct loop_device *lo)
+static int
+loop_release_xfer(struct loop_device *lo)
 {
-	int err = 0; 
-	if (lo->lo_encrypt_type) {
-		struct loop_func_table *xfer= xfer_funcs[lo->lo_encrypt_type]; 
-		if (xfer && xfer->release)
-			err = xfer->release(lo); 
-		if (xfer && xfer->unlock)
-			xfer->unlock(lo); 
-		lo->lo_encrypt_type = 0;
+	int err = 0;
+	struct loop_func_table *xfer = lo->lo_encryption;
+
+	if (xfer) {
+		if (xfer->release)
+			err = xfer->release(lo);
+		lo->transfer = NULL;
+		lo->lo_encryption = NULL;
+		module_put(xfer->owner);
 	}
 	return err;
 }
 
 static int
-loop_init_xfer(struct loop_device *lo, int type, const struct loop_info64 *i)
+loop_init_xfer(struct loop_device *lo, struct loop_func_table *xfer,
+	       const struct loop_info64 *i)
 {
-	int err = 0; 
-	if (type) {
-		struct loop_func_table *xfer = xfer_funcs[type]; 
+	int err = 0;
+
+	if (xfer) {
+		struct module *owner = xfer->owner;
+
+		if (!try_module_get(owner))
+			return -EINVAL;
 		if (xfer->init)
 			err = xfer->init(lo, i);
-		if (!err) { 
-			lo->lo_encrypt_type = type;
-			if (xfer->lock)
-				xfer->lock(lo);
-		}
+		if (err)
+			module_put(owner);
+		else
+			lo->lo_encryption = xfer;
 	}
 	return err;
-}  
+}
 
 static int loop_clr_fd(struct loop_device *lo, struct block_device *bdev)
 {
@@ -809,9 +819,11 @@
 
 	if (lo->lo_state != Lo_bound)
 		return -ENXIO;
+
 	if (lo->lo_refcnt > 1)	/* we needed one fd for the ioctl */
 		return -EBUSY;
-	if (filp==NULL)
+
+	if (filp == NULL)
 		return -EINVAL;
 
 	spin_lock_irq(&lo->lo_lock);
@@ -828,7 +840,7 @@
 	lo->transfer = NULL;
 	lo->ioctl = NULL;
 	lo->lo_device = NULL;
-	lo->lo_encrypt_type = 0;
+	lo->lo_encryption = NULL;
 	lo->lo_offset = 0;
 	lo->lo_encrypt_key_size = 0;
 	lo->lo_flags = 0;
@@ -849,49 +861,55 @@
 loop_set_status(struct loop_device *lo, const struct loop_info64 *info)
 {
 	int err;
-	unsigned int type;
-	loff_t offset;
+	struct loop_func_table *xfer;
 
-	if (lo->lo_encrypt_key_size && lo->lo_key_owner != current->uid && 
+	if (lo->lo_encrypt_key_size && lo->lo_key_owner != current->uid &&
 	    !capable(CAP_SYS_ADMIN))
 		return -EPERM;
 	if (lo->lo_state != Lo_bound)
 		return -ENXIO;
 	if ((unsigned int) info->lo_encrypt_key_size > LO_KEY_SIZE)
 		return -EINVAL;
-	type = info->lo_encrypt_type; 
-	if (type >= MAX_LO_CRYPT || xfer_funcs[type] == NULL)
-		return -EINVAL;
-	if (type == LO_CRYPT_XOR && info->lo_encrypt_key_size == 0)
-		return -EINVAL;
 
 	err = loop_release_xfer(lo);
-	if (!err) 
-		err = loop_init_xfer(lo, type, info);
+	if (err)
+		return err;
 
-	offset = lo->lo_offset;
-	if (offset != info->lo_offset) {
-		lo->lo_offset = info->lo_offset;
-		if (figure_loop_size(lo)){
-			err = -EFBIG;
-			lo->lo_offset = offset;
-		}
-	}
+	if (info->lo_encrypt_type) {
+		unsigned int type = info->lo_encrypt_type;
+
+		if (type >= MAX_LO_CRYPT)
+			return -EINVAL;
+		xfer = xfer_funcs[type];
+		if (xfer == NULL)
+			return -EINVAL;
+	} else
+		xfer = NULL;
 
+	err = loop_init_xfer(lo, xfer, info);
 	if (err)
-		return err;	
+		return err;
+
+	if (lo->lo_offset != info->lo_offset) {
+		lo->lo_offset = info->lo_offset;
+		if (figure_loop_size(lo))
+			return -EFBIG;
+	}
 
 	strlcpy(lo->lo_name, info->lo_name, LO_NAME_SIZE);
 
-	lo->transfer = xfer_funcs[type]->transfer;
-	lo->ioctl = xfer_funcs[type]->ioctl;
+	if (!xfer)
+		xfer = &none_funcs;
+	lo->transfer = xfer->transfer;
+	lo->ioctl = xfer->ioctl;
+
 	lo->lo_encrypt_key_size = info->lo_encrypt_key_size;
 	lo->lo_init[0] = info->lo_init[0];
 	lo->lo_init[1] = info->lo_init[1];
 	if (info->lo_encrypt_key_size) {
-		memcpy(lo->lo_encrypt_key, info->lo_encrypt_key, 
+		memcpy(lo->lo_encrypt_key, info->lo_encrypt_key,
 		       info->lo_encrypt_key_size);
-		lo->lo_key_owner = current->uid; 
+		lo->lo_key_owner = current->uid;
 	}	
 
 	return 0;
@@ -917,7 +935,8 @@
 	info->lo_offset = lo->lo_offset;
 	info->lo_flags = lo->lo_flags;
 	strlcpy(info->lo_name, lo->lo_name, LO_NAME_SIZE);
-	info->lo_encrypt_type = lo->lo_encrypt_type;
+	info->lo_encrypt_type =
+		lo->lo_encryption ? lo->lo_encryption->number : 0;
 	if (lo->lo_encrypt_key_size && capable(CAP_SYS_ADMIN)) {
 		info->lo_encrypt_key_size = lo->lo_encrypt_key_size;
 		memcpy(info->lo_encrypt_key, lo->lo_encrypt_key,
@@ -1060,30 +1079,22 @@
 static int lo_open(struct inode *inode, struct file *file)
 {
 	struct loop_device *lo = inode->i_bdev->bd_disk->private_data;
-	int type;
 
 	down(&lo->lo_ctl_mutex);
-
-	type = lo->lo_encrypt_type; 
-	if (type && xfer_funcs[type] && xfer_funcs[type]->lock)
-		xfer_funcs[type]->lock(lo);
 	lo->lo_refcnt++;
 	up(&lo->lo_ctl_mutex);
+
 	return 0;
 }
 
 static int lo_release(struct inode *inode, struct file *file)
 {
 	struct loop_device *lo = inode->i_bdev->bd_disk->private_data;
-	int type;
 
 	down(&lo->lo_ctl_mutex);
-	type = lo->lo_encrypt_type;
 	--lo->lo_refcnt;
-	if (xfer_funcs[type] && xfer_funcs[type]->unlock)
-		xfer_funcs[type]->unlock(lo);
-
 	up(&lo->lo_ctl_mutex);
+
 	return 0;
 }
 
@@ -1103,34 +1114,41 @@
 
 int loop_register_transfer(struct loop_func_table *funcs)
 {
-	if ((unsigned)funcs->number > MAX_LO_CRYPT || xfer_funcs[funcs->number])
+	unsigned int n = funcs->number;
+
+	if (n >= MAX_LO_CRYPT || xfer_funcs[n])
 		return -EINVAL;
-	xfer_funcs[funcs->number] = funcs;
-	return 0; 
+	xfer_funcs[n] = funcs;
+	return 0;
 }
 
 int loop_unregister_transfer(int number)
 {
-	struct loop_device *lo; 
+	unsigned int n = number;
+	struct loop_device *lo;
+	struct loop_func_table *xfer;
 
-	if ((unsigned)number >= MAX_LO_CRYPT)
-		return -EINVAL; 
-	for (lo = &loop_dev[0]; lo < &loop_dev[max_loop]; lo++) { 
-		int type = lo->lo_encrypt_type;
-		if (type == number) { 
-			xfer_funcs[type]->release(lo);
-			lo->transfer = NULL; 
-			lo->lo_encrypt_type = 0; 
-		}
+	if (n == 0 || n >= MAX_LO_CRYPT || (xfer = xfer_funcs[n]) == NULL)
+		return -EINVAL;
+
+	xfer_funcs[n] = NULL;
+
+	for (lo = &loop_dev[0]; lo < &loop_dev[max_loop]; lo++) {
+		down(&lo->lo_ctl_mutex);
+
+		if (lo->lo_encryption == xfer)
+			loop_release_xfer(lo);
+
+		up(&lo->lo_ctl_mutex);
 	}
-	xfer_funcs[number] = NULL; 
-	return 0; 
+
+	return 0;
 }
 
 EXPORT_SYMBOL(loop_register_transfer);
 EXPORT_SYMBOL(loop_unregister_transfer);
 
-int __init loop_init(void) 
+int __init loop_init(void)
 {
 	int	i;
 
@@ -1190,9 +1208,10 @@
 	return -ENOMEM;
 }
 
-void loop_exit(void) 
+void loop_exit(void)
 {
 	int i;
+
 	for (i = 0; i < max_loop; i++) {
 		del_gendisk(disks[i]);
 		put_disk(disks[i]);
diff -Nru a/drivers/block/nbd.c b/drivers/block/nbd.c
--- a/drivers/block/nbd.c	Fri Jun  6 04:40:53 2003
+++ b/drivers/block/nbd.c	Sun Jun 22 18:13:08 2003
@@ -28,6 +28,9 @@
  *   the transmit lock. <steve@chygwyn.com>
  * 02-10-11 Allow hung xmit to be aborted via SIGKILL & various fixes.
  *   <Paul.Clements@SteelEye.com> <James.Bottomley@SteelEye.com>
+ * 03-06-22 Make nbd work with new linux 2.5 block layer design. This fixes
+ *   memory corruption from module removal and possible memory corruption
+ *   from sending/receiving disk data. <ldl@aros.net>
  *
  * possible FIXME: make set_sock / set_blksize / set_size / do_it one syscall
  * why not: would need verify_area and friends, would share yet another 
@@ -63,6 +66,16 @@
 
 static struct nbd_device nbd_dev[MAX_NBD];
 
+/*
+ * Use just one lock (or at most 1 per NIC). Two arguments for this:
+ * 1. Each NIC is essentially a synchronization point for all servers
+ *    accessed through that NIC so there's no need to have more locks
+ *    than NICs anyway.
+ * 2. More locks lead to more "Dirty cache line bouncing" which will slow
+ *    down each lock to the point where they're actually slower than just
+ *    a single lock.
+ * Thanks go to Jens Axboe and Al Viro for their LKML emails explaining this!
+ */
 static spinlock_t nbd_lock = SPIN_LOCK_UNLOCKED;
 
 #define DEBUG( s )
@@ -168,6 +181,17 @@
 	return result;
 }
 
+static inline int sock_send_bvec(struct socket *sock, struct bio_vec *bvec,
+		int flags)
+{
+	int result;
+	void *kaddr = kmap(bvec->bv_page);
+	result = nbd_xmit(1, sock, kaddr + bvec->bv_offset, bvec->bv_len,
+			flags);
+	kunmap(bvec->bv_page);
+	return result;
+}
+
 #define FAIL( s ) { printk( KERN_ERR "NBD: " s "(result %d)\n", result ); goto error_out; }
 
 void nbd_send_req(struct nbd_device *lo, struct request *req)
@@ -209,7 +233,7 @@
 				if ((i < (bio->bi_vcnt - 1)) || bio->bi_next)
 					flags = MSG_MORE;
 				DEBUG("data, ");
-				result = nbd_xmit(1, sock, page_address(bvec->bv_page) + bvec->bv_offset, bvec->bv_len, flags);
+				result = sock_send_bvec(sock, bvec, flags);
 				if (result <= 0)
 					FAIL("Send data failed.");
 			}
@@ -244,6 +268,16 @@
 	return NULL;
 }
 
+static inline int sock_recv_bvec(struct socket *sock, struct bio_vec *bvec)
+{
+	int result;
+	void *kaddr = kmap(bvec->bv_page);
+	result = nbd_xmit(0, sock, kaddr + bvec->bv_offset, bvec->bv_len,
+			MSG_WAITALL);
+	kunmap(bvec->bv_page);
+	return result;
+}
+
 #define HARDFAIL( s ) { printk( KERN_ERR "NBD: " s "(result %d)\n", result ); lo->harderror = result; return NULL; }
 struct request *nbd_read_stat(struct nbd_device *lo)
 		/* NULL returned = something went wrong, inform userspace       */ 
@@ -251,10 +285,11 @@
 	int result;
 	struct nbd_reply reply;
 	struct request *req;
+	struct socket *sock = lo->sock;
 
 	DEBUG("reading control, ");
 	reply.magic = 0;
-	result = nbd_xmit(0, lo->sock, (char *) &reply, sizeof(reply), MSG_WAITALL);
+	result = nbd_xmit(0, sock, (char *) &reply, sizeof(reply), MSG_WAITALL);
 	if (result <= 0)
 		HARDFAIL("Recv control failed.");
 	req = nbd_find_request(lo, reply.handle);
@@ -268,14 +303,17 @@
 		FAIL("Other side returned error.");
 
 	if (nbd_cmd(req) == NBD_CMD_READ) {
-		struct bio *bio = req->bio;
+		int i;
+		struct bio *bio;
 		DEBUG("data, ");
-		do {
-			result = nbd_xmit(0, lo->sock, bio_data(bio), bio->bi_size, MSG_WAITALL);
-			if (result <= 0)
-				HARDFAIL("Recv data failed.");
-			bio = bio->bi_next;
-		} while(bio);
+		rq_for_each_bio(bio, req) {
+			struct bio_vec *bvec;
+			bio_for_each_segment(bvec, bio, i) {
+				result = sock_recv_bvec(sock, bvec);
+				if (result <= 0)
+					HARDFAIL("Recv data failed.");
+			}
+		}
 	}
 	DEBUG("done.\n");
 	return req;
@@ -538,8 +576,6 @@
  *  (Just smiley confuses emacs :-)
  */
 
-static struct request_queue nbd_queue;
-
 static int __init nbd_init(void)
 {
 	int err = -ENOMEM;
@@ -555,6 +591,17 @@
 		if (!disk)
 			goto out;
 		nbd_dev[i].disk = disk;
+		/*
+		 * The new linux 2.5 block layer implementation requires
+		 * every gendisk to have its very own request_queue struct.
+		 * These structs are big so we dynamically allocate them.
+		 */
+		disk->queue = kmalloc(sizeof(struct request_queue), GFP_KERNEL);
+		if (!disk->queue) {
+			put_disk(disk);
+			goto out;
+		}
+		blk_init_queue(disk->queue, do_nbd_request, &nbd_lock);
 	}
 
 	if (register_blkdev(NBD_MAJOR, "nbd")) {
@@ -564,7 +611,6 @@
 #ifdef MODULE
 	printk("nbd: registered device at major %d\n", NBD_MAJOR);
 #endif
-	blk_init_queue(&nbd_queue, do_nbd_request, &nbd_lock);
 	devfs_mk_dir("nbd");
 	for (i = 0; i < MAX_NBD; i++) {
 		struct gendisk *disk = nbd_dev[i].disk;
@@ -582,7 +628,6 @@
 		disk->first_minor = i;
 		disk->fops = &nbd_fops;
 		disk->private_data = &nbd_dev[i];
-		disk->queue = &nbd_queue;
 		sprintf(disk->disk_name, "nbd%d", i);
 		sprintf(disk->devfs_name, "nbd/%d", i);
 		set_capacity(disk, 0x3ffffe);
@@ -591,8 +636,10 @@
 
 	return 0;
 out:
-	while (i--)
+	while (i--) {
+		kfree(nbd_dev[i].disk->queue);
 		put_disk(nbd_dev[i].disk);
+	}
 	return err;
 }
 
@@ -600,12 +647,22 @@
 {
 	int i;
 	for (i = 0; i < MAX_NBD; i++) {
-		del_gendisk(nbd_dev[i].disk);
-		put_disk(nbd_dev[i].disk);
+		struct gendisk *disk = nbd_dev[i].disk;
+		if (disk) {
+			if (disk->queue) {
+				blk_cleanup_queue(disk->queue);
+				kfree(disk->queue);
+				disk->queue = NULL;
+			}
+			del_gendisk(disk);
+			put_disk(disk);
+		}
 	}
 	devfs_remove("nbd");
-	blk_cleanup_queue(&nbd_queue);
 	unregister_blkdev(NBD_MAJOR, "nbd");
+#ifdef MODULE
+	printk("nbd: unregistered device at major %d\n", NBD_MAJOR);
+#endif
 }
 
 module_init(nbd_init);
diff -Nru a/drivers/mtd/afs.c b/drivers/mtd/afs.c
--- a/drivers/mtd/afs.c	Wed May 28 08:01:01 2003
+++ b/drivers/mtd/afs.c	Mon Jun 23 05:18:11 2003
@@ -21,7 +21,7 @@
    This is access code for flashes using ARM's flash partitioning 
    standards.
 
-   $Id: afs.c,v 1.11 2003/05/16 17:08:24 dwmw2 Exp $
+   $Id: afs.c,v 1.12 2003/06/13 15:31:06 rmk Exp $
 
 ======================================================================*/
 
@@ -76,17 +76,19 @@
 		return ret;
 	}
 
+	ret = 1;
+
 	/*
 	 * Does it contain the magic number?
 	 */
 	if (fs.signature != 0xa0ffff9f)
-		ret = 1;
+		ret = 0;
 
 	/*
 	 * Don't touch the SIB.
 	 */
 	if (fs.type == 2)
-		ret = 1;
+		ret = 0;
 
 	*iis_start = fs.image_info_base & mask;
 	*img_start = fs.image_start & mask;
@@ -96,14 +98,14 @@
 	 * be located after the footer structure.
 	 */
 	if (*iis_start >= ptr)
-		ret = 1;
+		ret = 0;
 
 	/*
 	 * Check the start of this image.  The image
 	 * data can not be located after this block.
 	 */
 	if (*img_start > off)
-		ret = 1;
+		ret = 0;
 
 	return ret;
 }
@@ -152,7 +154,7 @@
 		ret = afs_read_footer(mtd, &img_ptr, &iis_ptr, off, mask);
 		if (ret < 0)
 			break;
-		if (ret == 1)
+		if (ret == 0)
 			continue;
 
 		ret = afs_read_iis(mtd, &iis, iis_ptr);
@@ -185,7 +187,7 @@
 		ret = afs_read_footer(mtd, &img_ptr, &iis_ptr, off, mask);
 		if (ret < 0)
 			break;
-		if (ret == 1)
+		if (ret == 0)
 			continue;
 
 		/* Read the image info block */
diff -Nru a/drivers/mtd/chips/amd_flash.c b/drivers/mtd/chips/amd_flash.c
--- a/drivers/mtd/chips/amd_flash.c	Wed May 28 08:01:01 2003
+++ b/drivers/mtd/chips/amd_flash.c	Mon Jun 23 05:34:03 2003
@@ -3,7 +3,7 @@
  *
  * Author: Jonas Holmberg <jonas.holmberg@axis.com>
  *
- * $Id: amd_flash.c,v 1.22 2003/05/28 13:47:19 dwmw2 Exp $
+ * $Id: amd_flash.c,v 1.23 2003/06/12 09:24:13 dwmw2 Exp $
  *
  * Copyright (c) 2001 Axis Communications AB
  *
@@ -19,6 +19,7 @@
 #include <linux/slab.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
+#include <linux/init.h>
 #include <linux/mtd/map.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/flashchip.h>
diff -Nru a/drivers/mtd/chips/cfi_cmdset_0001.c b/drivers/mtd/chips/cfi_cmdset_0001.c
--- a/drivers/mtd/chips/cfi_cmdset_0001.c	Wed May 28 08:01:01 2003
+++ b/drivers/mtd/chips/cfi_cmdset_0001.c	Mon Jun 23 05:34:03 2003
@@ -4,7 +4,7 @@
  *
  * (C) 2000 Red Hat. GPL'd
  *
- * $Id: cfi_cmdset_0001.c,v 1.123 2003/05/28 12:51:48 dwmw2 Exp $
+ * $Id: cfi_cmdset_0001.c,v 1.126 2003/06/23 07:45:48 dwmw2 Exp $
  *
  * 
  * 10/10/2000	Nicolas Pitre <nico@cam.org>
@@ -936,7 +936,7 @@
 	struct cfi_private *cfi = map->fldrv_priv;
 	cfi_word status, status_OK;
 	unsigned long cmd_adr, timeo;
-	int wbufsize, z, ret=0;
+	int wbufsize, z, ret=0, bytes, words;
 
 	wbufsize = CFIDEV_INTERLEAVE << cfi->cfiq->MaxBufWriteSize;
 	adr += chip->start;
@@ -995,10 +995,13 @@
 	}
 
 	/* Write length of data to come */
-	cfi_write(map, CMD(len/CFIDEV_BUSWIDTH-1), cmd_adr );
+	bytes = len & (CFIDEV_BUSWIDTH-1);
+	words = len / CFIDEV_BUSWIDTH;
+	cfi_write(map, CMD(words - !bytes), cmd_adr );
 
 	/* Write data */
-	for (z = 0; z < len; z += CFIDEV_BUSWIDTH) {
+	z = 0;
+	while(z < words * CFIDEV_BUSWIDTH) {
 		if (cfi_buswidth_is_1()) {
 			map_write8 (map, *((__u8*)buf)++, adr+z);
 		} else if (cfi_buswidth_is_2()) {
@@ -1011,6 +1014,26 @@
 			ret = -EINVAL;
 			goto out;
 		}
+		z += CFIDEV_BUSWIDTH;
+	}
+	if (bytes) {
+		int i = 0, n = 0;
+		u_char tmp_buf[8], *tmp_p = tmp_buf;
+
+		while (bytes--)
+			tmp_buf[i++] = buf[n++];
+		while (i < CFIDEV_BUSWIDTH)
+			tmp_buf[i++] = 0xff;
+		if (cfi_buswidth_is_2()) {
+			map_write16 (map, *((__u16*)tmp_p)++, adr+z);
+		} else if (cfi_buswidth_is_4()) {
+			map_write32 (map, *((__u32*)tmp_p)++, adr+z);
+		} else if (cfi_buswidth_is_8()) {
+			map_write64 (map, *((__u64*)tmp_p)++, adr+z);
+		} else {
+			ret = -EINVAL;
+			goto out;
+		}
 	}
 	/* GO GO GO */
 	cfi_write(map, CMD(0xd0), cmd_adr);
@@ -1119,12 +1142,12 @@
 	}
 
 	/* Write buffer is worth it only if more than one word to write... */
-	while(len > CFIDEV_BUSWIDTH) {
+	while(len) {
 		/* We must not cross write block boundaries */
 		int size = wbufsize - (ofs & (wbufsize-1));
 
 		if (size > len)
-			size = len & ~(CFIDEV_BUSWIDTH-1);
+			size = len;
 		ret = do_write_buffer(map, &cfi->chips[chipnum], 
 				      ofs, buf, size);
 		if (ret)
@@ -1142,17 +1165,6 @@
 				return 0;
 		}
 	}
-
-	/* ... and write the remaining bytes */
-	if (len > 0) {
-		size_t local_retlen;
-		ret = cfi_intelext_write_words(mtd, ofs + (chipnum << cfi->chipshift),
-					       len, &local_retlen, buf);
-		if (ret)
-			return ret;
-		(*retlen) += local_retlen;
-	}
-
 	return 0;
 }
 
@@ -1423,6 +1435,7 @@
 			 * with the chip now anyway.
 			 */
 		}
+		spin_unlock(chip->mutex);
 	}
 
 	/* Unlock the chips again */
diff -Nru a/drivers/mtd/devices/doc2000.c b/drivers/mtd/devices/doc2000.c
--- a/drivers/mtd/devices/doc2000.c	Wed May 28 08:01:02 2003
+++ b/drivers/mtd/devices/doc2000.c	Mon Jun 23 05:34:03 2003
@@ -4,7 +4,7 @@
  * (c) 1999 Machine Vision Holdings, Inc.
  * (c) 1999, 2000 David Woodhouse <dwmw2@infradead.org>
  *
- * $Id: doc2000.c,v 1.52 2003/05/20 21:03:07 dwmw2 Exp $
+ * $Id: doc2000.c,v 1.53 2003/06/11 09:45:19 dwmw2 Exp $
  */
 
 #include <linux/kernel.h>
@@ -553,6 +553,7 @@
 
 	mtd->type = MTD_NANDFLASH;
 	mtd->flags = MTD_CAP_NANDFLASH;
+	mtd->ecctype = MTD_ECC_RS_DiskOnChip;
 	mtd->size = 0;
 	mtd->erasesize = 0;
 	mtd->oobblock = 512;
diff -Nru a/drivers/mtd/devices/doc2001.c b/drivers/mtd/devices/doc2001.c
--- a/drivers/mtd/devices/doc2001.c	Wed May 28 08:01:02 2003
+++ b/drivers/mtd/devices/doc2001.c	Mon Jun 23 05:34:04 2003
@@ -4,7 +4,7 @@
  * (c) 1999 Machine Vision Holdings, Inc.
  * (c) 1999, 2000 David Woodhouse <dwmw2@infradead.org>
  *
- * $Id: doc2001.c,v 1.40 2003/05/20 21:03:07 dwmw2 Exp $
+ * $Id: doc2001.c,v 1.41 2003/06/11 09:45:19 dwmw2 Exp $
  */
 
 #include <linux/kernel.h>
@@ -359,9 +359,10 @@
 
 	mtd->type = MTD_NANDFLASH;
 	mtd->flags = MTD_CAP_NANDFLASH;
+	mtd->ecctype = MTD_ECC_RS_DiskOnChip;
 	mtd->size = 0;
 
-	/* FIXME: erase size is not always 8kB */
+	/* FIXME: erase size is not always 8KiB */
 	mtd->erasesize = 0x2000;
 
 	mtd->oobblock = 512;
diff -Nru a/drivers/mtd/devices/doc2001plus.c b/drivers/mtd/devices/doc2001plus.c
--- a/drivers/mtd/devices/doc2001plus.c	Wed May 28 08:01:09 2003
+++ b/drivers/mtd/devices/doc2001plus.c	Mon Jun 23 05:34:04 2003
@@ -6,7 +6,7 @@
  * (c) 1999 Machine Vision Holdings, Inc.
  * (c) 1999, 2000 David Woodhouse <dwmw2@infradead.org>
  *
- * $Id: doc2001plus.c,v 1.4 2003/05/23 11:28:46 dwmw2 Exp $
+ * $Id: doc2001plus.c,v 1.5 2003/06/11 09:45:19 dwmw2 Exp $
  */
 
 #include <linux/kernel.h>
@@ -458,6 +458,7 @@
 
 	mtd->type = MTD_NANDFLASH;
 	mtd->flags = MTD_CAP_NANDFLASH;
+	mtd->ecctype = MTD_ECC_RS_DiskOnChip;
 	mtd->size = 0;
 
 	mtd->erasesize = 0;
diff -Nru a/drivers/mtd/ftl.c b/drivers/mtd/ftl.c
--- a/drivers/mtd/ftl.c	Wed May 28 08:01:02 2003
+++ b/drivers/mtd/ftl.c	Mon Jun 23 05:40:41 2003
@@ -1,5 +1,5 @@
 /* This version ported to the Linux-MTD system by dwmw2@infradead.org
- * $Id: ftl.c,v 1.50 2003/05/21 10:49:47 dwmw2 Exp $
+ * $Id: ftl.c,v 1.51 2003/06/23 12:00:08 dwmw2 Exp $
  *
  * Fixes: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
  * - fixes some leaks on failure in build_maps and ftl_notify_add, cleanups
@@ -984,37 +984,20 @@
     return 0;
 } /* ftl_write */
 
-/*======================================================================
-
-    IOCTL calls for getting device parameters.
-
-======================================================================*/
-
-static int ftl_ioctl(struct mtd_blktrans_dev *dev, struct inode *inode, 
-		     struct file *file, u_int cmd, u_long arg)
+static int ftl_getgeo(struct mtd_blktrans_dev *dev, struct hd_geometry *geo)
 {
-    struct hd_geometry *geo = (struct hd_geometry *)arg;
-    partition_t *part = (void *)dev;
-    u_long sect;
-
-    switch (cmd) {
-    case HDIO_GETGEO:
-	/* Sort of arbitrary: round size down to 4K boundary */
-	sect = le32_to_cpu(part->header.FormattedSize)/SECTOR_SIZE;
-	if (put_user(1, (char *)&geo->heads) ||
-	    put_user(8, (char *)&geo->sectors) ||
-	    put_user((sect>>3), (short *)&geo->cylinders) ||
-	    put_user(0, (u_long *)&geo->start))
-		return -EFAULT;
+	partition_t *part = (void *)dev;
+	u_long sect;
 
-    case BLKFLSBUF:
-	    return 0;
-    }
-    return -ENOTTY;
-} /* ftl_ioctl */
+	/* Sort of arbitrary: round size down to 4KiB boundary */
+	sect = le32_to_cpu(part->header.FormattedSize)/SECTOR_SIZE;
 
+	geo->heads = 1;
+	geo->sectors = 8;
+	geo->cylinders = sect >> 3;
 
-/*======================================================================*/
+	return 0;
+}
 
 static int ftl_readsect(struct mtd_blktrans_dev *dev,
 			      unsigned long block, char *buf)
@@ -1102,7 +1085,7 @@
 	.part_bits	= PART_BITS,
 	.readsect	= ftl_readsect,
 	.writesect	= ftl_writesect,
-	.ioctl		= ftl_ioctl,
+	.getgeo		= ftl_getgeo,
 	.add_mtd	= ftl_add_mtd,
 	.remove_dev	= ftl_remove_dev,
 	.owner		= THIS_MODULE,
@@ -1110,7 +1093,7 @@
 
 int init_ftl(void)
 {
-	DEBUG(0, "$Id: ftl.c,v 1.50 2003/05/21 10:49:47 dwmw2 Exp $\n");
+	DEBUG(0, "$Id: ftl.c,v 1.51 2003/06/23 12:00:08 dwmw2 Exp $\n");
 
 	return register_mtd_blktrans(&ftl_tr);
 }
diff -Nru a/drivers/mtd/inftlcore.c b/drivers/mtd/inftlcore.c
--- a/drivers/mtd/inftlcore.c	Wed May 28 08:01:11 2003
+++ b/drivers/mtd/inftlcore.c	Mon Jun 23 05:40:41 2003
@@ -7,7 +7,7 @@
  * (c) 1999 Machine Vision Holdings, Inc.
  * Author: David Woodhouse <dwmw2@infradead.org>
  *
- * $Id: inftlcore.c,v 1.9 2003/05/23 11:41:47 dwmw2 Exp $
+ * $Id: inftlcore.c,v 1.11 2003/06/23 12:00:08 dwmw2 Exp $
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -113,7 +113,7 @@
 			(long)inftl->sectors );
 	}
 
-	if (add_mtd_blktrans_dev) {
+	if (add_mtd_blktrans_dev(&inftl->mbd)) {
 		if (inftl->PUtable)
 			kfree(inftl->PUtable);
 		if (inftl->VUtable)
@@ -835,35 +835,22 @@
 	return 0;
 }
 
-
-static int inftl_ioctl(struct mtd_blktrans_dev *dev,
-		     struct inode *inode, struct file *file, 
-		     unsigned int cmd, unsigned long arg)
+static int inftl_getgeo(struct mtd_blktrans_dev *dev, struct hd_geometry *geo)
 {
 	struct NFTLrecord *nftl = (void *)dev;
 
-	switch (cmd) {
-	case HDIO_GETGEO: {
-		struct hd_geometry g;
-
-		g.heads = nftl->heads;
-		g.sectors = nftl->sectors;
-		g.cylinders = nftl->cylinders;
-		g.start = 0;
-		return copy_to_user((void *)arg, &g, sizeof g) ? -EFAULT : 0;
-	}
+	geo->heads = nftl->heads;
+	geo->sectors = nftl->sectors;
+	geo->cylinders = nftl->cylinders;
 
-	default:
-		return -ENOTTY;
-	}
+	return 0;
 }
 
-
 struct mtd_blktrans_ops inftl_tr = {
 	.name		= "inftl",
 	.major		= INFTL_MAJOR,
 	.part_bits	= INFTL_PARTN_BITS,
-	.ioctl		= inftl_ioctl,
+	.getgeo		= inftl_getgeo,
 	.readsect	= inftl_readblock,
 	.writesect	= inftl_writeblock,
 	.add_mtd	= inftl_add_mtd,
@@ -875,7 +862,7 @@
 
 int __init init_inftl(void)
 {
-	printk(KERN_INFO "INFTL: inftlcore.c $Revision: 1.9 $, "
+	printk(KERN_INFO "INFTL: inftlcore.c $Revision: 1.11 $, "
 		"inftlmount.c %s\n", inftlmountrev);
 
 	return register_mtd_blktrans(&inftl_tr);
diff -Nru a/drivers/mtd/inftlmount.c b/drivers/mtd/inftlmount.c
--- a/drivers/mtd/inftlmount.c	Wed May 28 08:01:12 2003
+++ b/drivers/mtd/inftlmount.c	Mon Jun 23 05:34:04 2003
@@ -8,7 +8,7 @@
  * Author: Fabrice Bellard (fabrice.bellard@netgem.com) 
  * Copyright (C) 2000 Netgem S.A.
  *
- * $Id: inftlmount.c,v 1.9 2003/05/23 11:35:07 dwmw2 Exp $
+ * $Id: inftlmount.c,v 1.11 2003/06/23 07:39:21 dwmw2 Exp $
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -25,7 +25,6 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
-#define __NO_VERSION__
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <asm/errno.h>
@@ -42,7 +41,7 @@
 #include <linux/mtd/inftl.h>
 #include <linux/mtd/compatmac.h>
 
-char inftlmountrev[]="$Revision: 1.9 $";
+char inftlmountrev[]="$Revision: 1.11 $";
 
 /*
  * find_boot_record: Find the INFTL Media Header and its Spare copy which
@@ -242,7 +241,7 @@
 			}
 			if ((ip->lastUnit - ip->firstUnit + 1) < ip->virtualUnits) {
 				printk(KERN_WARNING "INFTL: Media Header "
-					"Parition %d sanity check failed\n"
+					"Partition %d sanity check failed\n"
 					"    firstUnit %d : lastUnit %d  >  "
 					"virtualUnits %d\n", i, ip->lastUnit,
 					ip->firstUnit, ip->Reserved0);
@@ -250,7 +249,7 @@
 			}
 			if (ip->Reserved1 != 0) {
 				printk(KERN_WARNING "INFTL: Media Header "
-					"Parition %d sanity check failed: "
+					"Partition %d sanity check failed: "
 					"Reserved1 %d != 0\n",
 					i, ip->Reserved1);
 				return -1;
@@ -261,7 +260,7 @@
 		}
 
 		if (i >= 4) {
-			printk(KERN_WARNING "INFTL: Media Header Parition "
+			printk(KERN_WARNING "INFTL: Media Header Partition "
 				"sanity check failed:\n       No partition "
 				"marked as Disk Partition\n");
 			return -1;
@@ -630,7 +629,7 @@
 			if (prev_block < s->nb_blocks)
 				prev_block += s->firstEUN;
 
-			/* Already explored paritial chain? */
+			/* Already explored partial chain? */
 			if (s->PUtable[block] != BLOCK_NOTEXPLORED) {
 				/* Check if chain for this logical */
 				if (logical_block == first_logical_block) {
diff -Nru a/drivers/mtd/maps/Kconfig b/drivers/mtd/maps/Kconfig
--- a/drivers/mtd/maps/Kconfig	Wed May 28 08:56:01 2003
+++ b/drivers/mtd/maps/Kconfig	Mon Jun 23 05:34:05 2003
@@ -1,5 +1,5 @@
 # drivers/mtd/maps/Kconfig
-# $Id: Kconfig,v 1.11 2003/05/28 15:16:56 dwmw2 Exp $
+# $Id: Kconfig,v 1.12 2003/06/23 07:38:11 dwmw2 Exp $
 
 menu "Mapping drivers for chip access"
 	depends on MTD!=n
@@ -476,7 +476,7 @@
 
 config MTD_UCLINUX
 	tristate "Generic uClinux RAM/ROM filesystem support"
-	depends on MTD_PARTITIONS
+	depends on MTD_PARTITIONS && !MMU
 	help
 	  Map driver to support image based filesystems for uClinux.
 
diff -Nru a/drivers/mtd/maps/arctic-mtd.c b/drivers/mtd/maps/arctic-mtd.c
--- a/drivers/mtd/maps/arctic-mtd.c	Wed May 28 08:01:13 2003
+++ b/drivers/mtd/maps/arctic-mtd.c	Mon Jun 23 05:34:05 2003
@@ -1,5 +1,5 @@
 /*
- * $Id: arctic-mtd.c,v 1.8 2003/05/21 12:45:17 dwmw2 Exp $
+ * $Id: arctic-mtd.c,v 1.10 2003/06/02 16:37:59 trini Exp $
  * 
  * drivers/mtd/maps/arctic-mtd.c MTD mappings and partition tables for 
  *                              IBM 405LP Arctic boards.
@@ -45,18 +45,23 @@
 #include <asm/ibm4xx.h>
 
 /*
- * fe000000 -- ff9fffff  Arctic FFS (26MB)
- * ffa00000 -- fff5ffff  kernel (5.504MB)
- * fff60000 -- ffffffff  firmware (640KB)
+ * 0 : 0xFE00 0000 - 0xFEFF FFFF : Filesystem 1 (16MiB)
+ * 1 : 0xFF00 0000 - 0xFF4F FFFF : kernel (5.12MiB)
+ * 2 : 0xFF50 0000 - 0xFFF5 FFFF : Filesystem 2 (10.624MiB) (if non-XIP)
+ * 3 : 0xFFF6 0000 - 0xFFFF FFFF : PIBS Firmware (640KiB)
  */
 
-#define ARCTIC_FFS_SIZE		0x01a00000 /* 26 M */
-#define ARCTIC_FIRMWARE_SIZE	0x000a0000 /* 640K */
+#define FFS1_SIZE	0x01000000 /* 16MiB */
+#define KERNEL_SIZE	0x00500000 /* 5.12MiB */
+#define FFS2_SIZE	0x00a60000 /* 10.624MiB */
+#define FIRMWARE_SIZE	0x000a0000 /* 640KiB */
 
-#define NAME     "Arctic Linux Flash"
-#define PADDR    SUBZERO_BOOTFLASH_PADDR
-#define SIZE     SUBZERO_BOOTFLASH_SIZE
-#define BUSWIDTH 2
+
+#define NAME     	"Arctic Linux Flash"
+#define PADDR    	SUBZERO_BOOTFLASH_PADDR
+#define BUSWIDTH	2
+#define SIZE		SUBZERO_BOOTFLASH_SIZE
+#define PARTITIONS	4
 
 /* Flash memories on these boards are memory resources, accessed big-endian. */
 
@@ -73,17 +78,19 @@
 
 static struct mtd_info *arctic_mtd;
 
-static struct mtd_partition arctic_partitions[3] = {
-	{ .name		= "Arctic FFS",
-	  .size		= ARCTIC_FFS_SIZE,
+static struct mtd_partition arctic_partitions[PARTITIONS] = {
+	{ .name		= "Filesystem",
+	  .size		= FFS1_SIZE,
 	  .offset	= 0,},
-	{ .name		= "Kernel",
-	  .size		= SUBZERO_BOOTFLASH_SIZE - ARCTIC_FFS_SIZE -
-	  		  ARCTIC_FIRMWARE_SIZE,
-	  .offset	= ARCTIC_FFS_SIZE,},
+        { .name		= "Kernel",
+	  .size		= KERNEL_SIZE,
+	  .offset	= FFS1_SIZE,},
+	{ .name		= "Filesystem",
+	  .size		= FFS2_SIZE,
+	  .offset	= FFS1_SIZE + KERNEL_SIZE,},
 	{ .name		= "Firmware",
-	  .size		= ARCTIC_FIRMWARE_SIZE,
-	  .offset	= SUBZERO_BOOTFLASH_SIZE - ARCTIC_FIRMWARE_SIZE,},
+	  .size		= FIRMWARE_SIZE,
+	  .offset	= SUBZERO_BOOTFLASH_SIZE - FIRMWARE_SIZE,},
 };
 
 static int __init
@@ -107,7 +114,7 @@
 
 	arctic_mtd->owner = THIS_MODULE;
 
-	return add_mtd_partitions(arctic_mtd, arctic_partitions, 3);
+	return add_mtd_partitions(arctic_mtd, arctic_partitions, PARTITIONS);
 }
 
 static void __exit
diff -Nru a/drivers/mtd/maps/ebony.c b/drivers/mtd/maps/ebony.c
--- a/drivers/mtd/maps/ebony.c	Wed May 28 08:01:15 2003
+++ b/drivers/mtd/maps/ebony.c	Mon Jun 23 05:34:05 2003
@@ -1,5 +1,5 @@
 /*
- * $Id: ebony.c,v 1.7 2003/05/21 12:45:18 dwmw2 Exp $
+ * $Id: ebony.c,v 1.8 2003/06/23 11:48:18 dwmw2 Exp $
  * 
  * Mapping for Ebony user flash
  *
@@ -60,8 +60,6 @@
 	}
 };
 
-#define NB_OF(x)  (sizeof(x)/sizeof(x[0]))
-
 int __init init_ebony(void)
 {
 	u8 fpga0_reg;
@@ -109,7 +107,7 @@
 	if (flash) {
 		flash->owner = THIS_MODULE;
 		add_mtd_partitions(flash, ebony_small_partitions,
-					NB_OF(ebony_small_partitions));
+					ARRAY_SIZE(ebony_small_partitions));
 	} else {
 		printk("map probe failed for flash\n");
 		return -ENXIO;
@@ -131,7 +129,7 @@
 	if (flash) {
 		flash->owner = THIS_MODULE;
 		add_mtd_partitions(flash, ebony_large_partitions,
-					NB_OF(ebony_large_partitions));
+					ARRAY_SIZE(ebony_large_partitions));
 	} else {
 		printk("map probe failed for flash\n");
 		return -ENXIO;
diff -Nru a/drivers/mtd/maps/edb7312.c b/drivers/mtd/maps/edb7312.c
--- a/drivers/mtd/maps/edb7312.c	Wed May 28 08:01:03 2003
+++ b/drivers/mtd/maps/edb7312.c	Mon Jun 23 05:34:06 2003
@@ -1,5 +1,5 @@
 /*
- * $Id: edb7312.c,v 1.8 2003/05/21 12:45:18 dwmw2 Exp $
+ * $Id: edb7312.c,v 1.9 2003/06/23 11:48:18 dwmw2 Exp $
  *
  * Handle mapping of the NOR flash on Cogent EDB7312 boards
  *
@@ -67,7 +67,6 @@
 	},
 };
 
-#define NB_OF(x) (sizeof (x) / sizeof (x[0]))
 static const char *probes[] = { "RedBoot", "cmdlinepart", NULL };
 
 #endif
@@ -109,7 +108,7 @@
 		if (mtd_parts_nb == 0)
 		{
 			mtd_parts = static_partitions;
-			mtd_parts_nb = NB_OF(static_partitions);
+			mtd_parts_nb = ARRAY_SIZE(static_partitions);
 			part_type = "static";
 		}
 #endif
diff -Nru a/drivers/mtd/maps/elan-104nc.c b/drivers/mtd/maps/elan-104nc.c
--- a/drivers/mtd/maps/elan-104nc.c	Wed May 28 08:01:03 2003
+++ b/drivers/mtd/maps/elan-104nc.c	Mon Jun 23 05:34:06 2003
@@ -16,7 +16,7 @@
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
 
-   $Id: elan-104nc.c,v 1.17 2003/05/21 15:15:07 dwmw2 Exp $
+   $Id: elan-104nc.c,v 1.18 2003/06/23 07:37:02 dwmw2 Exp $
 
 The ELAN-104NC has up to 8 Mibyte of Intel StrataFlash (28F320/28F640) in x16
 mode.  This drivers uses the CFI probe and Intel Extended Command Set drivers.
@@ -223,30 +223,19 @@
 	}
 
 	iounmap((void *)iomapadr);
-	release_region(PAGE_IO,PAGE_IO_SIZE);
 }
 
 int __init init_elan_104nc(void)
 {
-	/* Urg! We use I/O port 0x22 without request_region()ing it */
-	/*
-	if (check_region(PAGE_IO,PAGE_IO_SIZE) != 0) {
-		printk( KERN_ERR"%s: IO ports 0x%x-0x%x in use\n",
-			elan_104nc_map.name,
-			PAGE_IO, PAGE_IO+PAGE_IO_SIZE-1 );
-		return -EAGAIN;
-	}
-	*/
+	/* Urg! We use I/O port 0x22 without request_region()ing it,
+	   because it's already allocated to the PIC. */
+
   	iomapadr = (unsigned long)ioremap(WINDOW_START, WINDOW_LENGTH);
 	if (!iomapadr) {
 		printk( KERN_ERR"%s: failed to ioremap memory region\n",
 			elan_104nc_map.name );
 		return -EIO;
 	}
-
-	/*
-	request_region( PAGE_IO, PAGE_IO_SIZE, "ELAN-104NC flash" );
-	*/
 
 	printk( KERN_INFO"%s: IO:0x%x-0x%x MEM:0x%x-0x%x\n",
 		elan_104nc_map.name,
diff -Nru a/drivers/mtd/maps/impa7.c b/drivers/mtd/maps/impa7.c
--- a/drivers/mtd/maps/impa7.c	Wed May 28 08:01:03 2003
+++ b/drivers/mtd/maps/impa7.c	Mon Jun 23 05:34:06 2003
@@ -1,5 +1,5 @@
 /*
- * $Id: impa7.c,v 1.8 2003/05/21 12:45:18 dwmw2 Exp $
+ * $Id: impa7.c,v 1.9 2003/06/23 11:47:43 dwmw2 Exp $
  *
  * Handle mapping of the NOR flash on implementa A7 boards
  *
@@ -66,12 +66,11 @@
 	},
 };
 
-#define NB_OF(x) (sizeof (x) / sizeof (x[0]))
+static int mtd_parts_nb[NUM_FLASHBANKS];
+static struct mtd_partition *mtd_parts[NUM_FLASHBANKS];
 
 #endif
 
-static int                   mtd_parts_nb = 0;
-static struct mtd_partition *mtd_parts    = 0;
 static const char *probes[] = { "cmdlinepart", NULL };
 
 int __init init_impa7(void)
@@ -84,7 +83,6 @@
 	  { WINDOW_ADDR0, WINDOW_SIZE0 },
 	  { WINDOW_ADDR1, WINDOW_SIZE1 },
         };
-	char mtdid[10];
 	int devicesfound = 0;
 
 	for(i=0; i<NUM_FLASHBANKS; i++)
@@ -107,42 +105,34 @@
 			impa7_mtd[i] = do_map_probe(*type, &impa7_map[i]);
 		}
 
-		if (impa7_mtd[i]) 
-		{
+		if (impa7_mtd[i]) {
 			impa7_mtd[i]->owner = THIS_MODULE;
-			add_mtd_device(impa7_mtd[i]);
 			devicesfound++;
 #ifdef CONFIG_MTD_PARTITIONS
-			mtd_parts_nb = parse_mtd_partitions(impa7_mtd[i], 
-							    probes,
-							    &mtd_parts, 
-							    0);
-			if (mtd_parts_nb > 0)
-			  part_type = "command line";
-#endif
-			if (mtd_parts_nb <= 0)
-			{
-				mtd_parts = static_partitions;
-				mtd_parts_nb = NB_OF(static_partitions);
+			mtd_parts_nb[i] = parse_mtd_partitions(impa7_mtd[i], 
+							       probes,
+							       &mtd_parts[i], 
+							       0);
+			if (mtd_parts_nb[i] > 0) {
+				part_type = "command line";
+			} else {
+				mtd_parts[i] = static_partitions;
+				mtd_parts_nb[i] = ARRAY_SIZE(static_partitions);
 				part_type = "static";
 			}
-			if (mtd_parts_nb <= 0)
-			{
-				printk(KERN_NOTICE MSG_PREFIX 
-				       "no partition info available\n");
-			}
-			else
-			{
-				printk(KERN_NOTICE MSG_PREFIX
-				       "using %s partition definition\n", 
-				       part_type);
-				add_mtd_partitions(impa7_mtd[i], 
-						   mtd_parts, mtd_parts_nb);
-			}
+
+			printk(KERN_NOTICE MSG_PREFIX
+			       "using %s partition definition\n", 
+			       part_type);
+			add_mtd_partitions(impa7_mtd[i], 
+					   mtd_parts[i], mtd_parts_nb[i]);
+#else
+			add_mtd_device(impa7_mtd[i]);
+
 #endif
 		}
 		else 
-		  iounmap((void *)impa7_map[i].virt);
+			iounmap((void *)impa7_map[i].virt);
 	}
 	return devicesfound == 0 ? -ENXIO : 0;
 }
@@ -150,15 +140,14 @@
 static void __exit cleanup_impa7(void)
 {
 	int i;
-	for (i=0; i<NUM_FLASHBANKS; i++) 
-	{
-		if (impa7_mtd[i]) 
-		{
+	for (i=0; i<NUM_FLASHBANKS; i++) {
+		if (impa7_mtd[i]) {
+#ifdef CONFIG_MTD_PARTITIONS
+			del_mtd_partitions(impa7_mtd[i]);
+#else
 			del_mtd_device(impa7_mtd[i]);
+#endif
 			map_destroy(impa7_mtd[i]);
-		}
-		if (impa7_map[i].virt)
-		{
 			iounmap((void *)impa7_map[i].virt);
 			impa7_map[i].virt = 0;
 		}
diff -Nru a/drivers/mtd/maps/iq80310.c b/drivers/mtd/maps/iq80310.c
--- a/drivers/mtd/maps/iq80310.c	Wed May 28 08:01:03 2003
+++ b/drivers/mtd/maps/iq80310.c	Mon Jun 23 05:34:06 2003
@@ -1,5 +1,5 @@
 /*
- * $Id: iq80310.c,v 1.16 2003/05/21 15:15:07 dwmw2 Exp $
+ * $Id: iq80310.c,v 1.17 2003/06/23 11:48:18 dwmw2 Exp $
  *
  * Mapping for the Intel XScale IQ80310 evaluation board
  *
@@ -57,8 +57,6 @@
 	}
 };
 
-#define NB_OF(x)  (sizeof(x)/sizeof(x[0]))
-
 static struct mtd_info *mymtd;
 static struct mtd_partition *parsed_parts;
 static const char *probes[] = { "RedBoot", "cmdlinepart", NULL };
@@ -94,7 +92,7 @@
 		nb_parts = parsed_nr_parts;
 	} else {
 		parts = iq80310_partitions;
-		nb_parts = NB_OF(iq80310_partitions);
+		nb_parts = ARRAY_SIZE(iq80310_partitions);
 	}
 	add_mtd_partitions(mymtd, parts, nb_parts);
 	return 0;
diff -Nru a/drivers/mtd/maps/lubbock-flash.c b/drivers/mtd/maps/lubbock-flash.c
--- a/drivers/mtd/maps/lubbock-flash.c	Wed May 28 08:01:18 2003
+++ b/drivers/mtd/maps/lubbock-flash.c	Mon Jun 23 05:34:07 2003
@@ -1,5 +1,5 @@
 /*
- * $Id: lubbock-flash.c,v 1.8 2003/05/21 12:45:19 dwmw2 Exp $
+ * $Id: lubbock-flash.c,v 1.9 2003/06/23 11:48:18 dwmw2 Exp $
  *
  * Map driver for the Lubbock developer platform.
  *
@@ -52,8 +52,6 @@
 	}
 };
 
-#define NB_OF(x)  (sizeof(x)/sizeof(x[0]))
-
 static struct mtd_info *mymtds[2];
 static struct mtd_partition *parsed_parts[2];
 static int nr_parsed_parts[2];
@@ -116,7 +114,7 @@
 			add_mtd_partitions(mymtds[i], parsed_parts[i], nr_parsed_parts[i]);
 		} else if (!i) {
 			printk("Using static partitions on %s\n", lubbock_maps[i].name);
-			add_mtd_partitions(mymtds[i], lubbock_partitions, NB_OF(lubbock_partitions));
+			add_mtd_partitions(mymtds[i], lubbock_partitions, ARRAY_SIZE(lubbock_partitions));
 		} else {
 			printk("Registering %s as whole device\n", lubbock_maps[i].name);
 			add_mtd_device(mymtds[i]);
diff -Nru a/drivers/mtd/maps/pb1xxx-flash.c b/drivers/mtd/maps/pb1xxx-flash.c
--- a/drivers/mtd/maps/pb1xxx-flash.c	Wed May 28 08:01:20 2003
+++ b/drivers/mtd/maps/pb1xxx-flash.c	Mon Jun 23 05:34:07 2003
@@ -3,7 +3,7 @@
  * 
  * (C) 2001 Pete Popov <ppopov@mvista.com>
  * 
- * $Id: pb1xxx-flash.c,v 1.8 2003/05/21 12:45:19 dwmw2 Exp $
+ * $Id: pb1xxx-flash.c,v 1.9 2003/06/23 11:48:18 dwmw2 Exp $
  */
 
 #include <linux/config.h>
@@ -131,9 +131,6 @@
 #error Unsupported board
 #endif
 
-
-#define NB_OF(x)  (sizeof(x)/sizeof(x[0]))
-
 static struct mtd_partition *parsed_parts;
 static struct mtd_info *mymtd;
 
@@ -151,7 +148,7 @@
 	 */
 	part_type = "static";
 	parts = pb1xxx_partitions;
-	nb_parts = NB_OF(pb1xxx_partitions);
+	nb_parts = ARRAY_SIZE(pb1xxx_partitions);
 	pb1xxx_map.size = flash_size;
 
 	/*
diff -Nru a/drivers/mtd/maps/tqm8xxl.c b/drivers/mtd/maps/tqm8xxl.c
--- a/drivers/mtd/maps/tqm8xxl.c	Wed May 28 08:01:04 2003
+++ b/drivers/mtd/maps/tqm8xxl.c	Mon Jun 23 05:34:07 2003
@@ -2,7 +2,7 @@
  * Handle mapping of the flash memory access routines 
  * on TQM8xxL based devices.
  *
- * $Id: tqm8xxl.c,v 1.8 2003/05/21 12:45:20 dwmw2 Exp $
+ * $Id: tqm8xxl.c,v 1.9 2003/06/23 11:48:18 dwmw2 Exp $
  *
  * based on rpxlite.c
  *
@@ -110,8 +110,6 @@
 };
 #endif
 
-#define NB_OF(x)  (sizeof(x)/sizeof(x[0]))
-
 int __init init_tqm_mtd(void)
 {
 	int idx = 0, ret = 0;
@@ -198,11 +196,11 @@
 	 */
 	part_banks[0].mtd_part = tqm8xxl_partitions;
 	part_banks[0].type = "Static image";
-	part_banks[0].nums = NB_OF(tqm8xxl_partitions);
+	part_banks[0].nums = ARRAY_SIZE(tqm8xxl_partitions);
 
 	part_banks[1].mtd_part = tqm8xxl_fs_partitions;
 	part_banks[1].type = "Static file system";
-	part_banks[1].nums = NB_OF(tqm8xxl_fs_partitions);
+	part_banks[1].nums = ARRAY_SIZE(tqm8xxl_fs_partitions);
 
 	for(idx = 0; idx < num_banks ; idx++) {
 		if (part_banks[idx].nums == 0) {
diff -Nru a/drivers/mtd/mtd_blkdevs.c b/drivers/mtd/mtd_blkdevs.c
--- a/drivers/mtd/mtd_blkdevs.c	Wed May 28 08:01:23 2003
+++ b/drivers/mtd/mtd_blkdevs.c	Mon Jun 23 06:35:33 2003
@@ -1,5 +1,5 @@
 /*
- * $Id: mtd_blkdevs.c,v 1.12 2003/05/21 01:00:59 dwmw2 Exp $
+ * $Id: mtd_blkdevs.c,v 1.16 2003/06/23 13:34:43 dwmw2 Exp $
  *
  * (C) 2003 David Woodhouse <dwmw2@infradead.org>
  *
@@ -18,8 +18,10 @@
 #include <linux/blk.h>
 #include <linux/blkpg.h>
 #include <linux/spinlock.h>
+#include <linux/hdreg.h>
 #include <linux/init.h>
 #include <asm/semaphore.h>
+#include <asm/uaccess.h>
 #include <linux/devfs_fs_kernel.h>
 
 static LIST_HEAD(blktrans_majors);
@@ -46,7 +48,7 @@
 	nsect = req->current_nr_sectors;
 	buf = req->buffer;
 
-	if (!req->flags & REQ_CMD)
+	if (!(req->flags & REQ_CMD))
 		return 0;
 
 	if (block + nsect > get_capacity(req->rq_disk))
@@ -93,14 +95,14 @@
 	recalc_sigpending();
 	spin_unlock_irq(&current->sighand->siglock);
 
+	spin_lock_irq(rq->queue_lock);
+		
 	while (!tr->blkcore_priv->exiting) {
 		struct request *req;
 		struct mtd_blktrans_dev *dev;
 		int res = 0;
 		DECLARE_WAITQUEUE(wait, current);
 
-		spin_lock_irq(rq->queue_lock);
-
 		req = elv_next_request(rq);
 
 		if (!req) {
@@ -112,6 +114,8 @@
 			schedule();
 			remove_wait_queue(&tr->blkcore_priv->thread_wq, &wait);
 
+			spin_lock_irq(rq->queue_lock);
+
 			continue;
 		}
 
@@ -159,7 +163,7 @@
 	dev->mtd->usecount++;
 
 	ret = 0;
-	if (tr->open && (ret = tr->open(dev, i, f))) {
+	if (tr->open && (ret = tr->open(dev))) {
 		dev->mtd->usecount--;
 		module_put(dev->mtd->owner);
 	out_tr:
@@ -179,7 +183,7 @@
 	tr = dev->tr;
 
 	if (tr->release)
-		ret = tr->release(dev, i, f);
+		ret = tr->release(dev);
 
 	if (!ret) {
 		dev->mtd->usecount--;
@@ -194,21 +198,33 @@
 static int blktrans_ioctl(struct inode *inode, struct file *file, 
 			      unsigned int cmd, unsigned long arg)
 {
-	struct mtd_blktrans_dev *dev;
-	struct mtd_blktrans_ops *tr;
-	int ret = -ENOTTY;
-
-	dev = inode->i_bdev->bd_disk->private_data;
-	tr = dev->tr;
+	struct mtd_blktrans_dev *dev = inode->i_bdev->bd_disk->private_data;
+	struct mtd_blktrans_ops *tr = dev->tr;
 
-	if (tr->ioctl)
-		ret = tr->ioctl(dev, inode, file, cmd, arg);
-
-	if (ret == -ENOTTY && (cmd == BLKROSET || cmd == BLKFLSBUF)) {
+	switch (cmd) {
+	case BLKFLSBUF:
+		if (tr->flush)
+			return tr->flush(dev);
 		/* The core code did the work, we had nothing to do. */
-		ret = 0;
+		return 0;
+
+	case HDIO_GETGEO:
+		if (tr->getgeo) {
+			struct hd_geometry g;
+
+			memset(&g, 0, sizeof(g));
+			int ret = tr->getgeo(dev, &g);
+			if (ret)
+				return ret;
+
+			g.start = get_start_sect(inode->i_bdev);
+			if (copy_to_user((void *)arg, &g, sizeof(g)))
+				return -EFAULT;
+			return 0;
+		} /* else */
+	default:
+		return -ENOTTY;
 	}
-	return ret;
 }
 
 struct block_device_operations mtd_blktrans_ops = {
@@ -328,8 +344,6 @@
 	if (mtd->type == MTD_ABSENT)
 		return;
 
-	printk("%s:%s %d: count %d\n", __FILE__, __func__, __LINE__, atomic_read(&mtd_table_mutex.count));
-
 	list_for_each(this, &blktrans_majors) {
 		struct mtd_blktrans_ops *tr = list_entry(this, struct mtd_blktrans_ops, list);
 
@@ -391,8 +405,6 @@
 
 	INIT_LIST_HEAD(&tr->devs);
 	list_add(&tr->list, &blktrans_majors);
-
-	printk("%s:%s %d: count %d\n", __FILE__, __func__, __LINE__, atomic_read(&mtd_table_mutex.count));
 
 	for (i=0; i<MAX_MTD_DEVICES; i++) {
 		if (mtd_table[i] && mtd_table[i]->type != MTD_ABSENT)
diff -Nru a/drivers/mtd/mtdblock.c b/drivers/mtd/mtdblock.c
--- a/drivers/mtd/mtdblock.c	Wed May 28 08:01:04 2003
+++ b/drivers/mtd/mtdblock.c	Mon Jun 23 05:40:42 2003
@@ -1,7 +1,7 @@
 /* 
  * Direct MTD block device access
  *
- * $Id: mtdblock.c,v 1.61 2003/05/21 10:49:38 dwmw2 Exp $
+ * $Id: mtdblock.c,v 1.63 2003/06/23 12:00:08 dwmw2 Exp $
  *
  * (C) 2000-2003 Nicolas Pitre <nico@cam.org>
  * (C) 1999-2003 David Woodhouse <dwmw2@infradead.org>
@@ -248,11 +248,19 @@
 			      unsigned long block, char *buf)
 {
 	struct mtdblk_dev *mtdblk = mtdblks[dev->devnum];
+	if (unlikely(!mtdblk->cache_data)) {
+		mtdblk->cache_data = vmalloc(mtdblk->mtd->erasesize);
+		if (!mtdblk->cache_data)
+			return -EINTR;
+		/* -EINTR is not really correct, but it is the best match
+		 * documented in man 2 write for all cases.  We could also
+		 * return -EAGAIN sometimes, but why bother?
+		 */
+	}
 	return do_cached_write(mtdblk, block<<9, 512, buf);
 }
 
-static int mtdblock_open(struct mtd_blktrans_dev *mbd, 
-			 struct inode *inode, struct file *file)
+static int mtdblock_open(struct mtd_blktrans_dev *mbd)
 {
 	struct mtdblk_dev *mtdblk;
 	struct mtd_info *mtd = mbd->mtd;
@@ -279,11 +287,7 @@
 	if ((mtdblk->mtd->flags & MTD_CAP_RAM) != MTD_CAP_RAM &&
 	    mtdblk->mtd->erasesize) {
 		mtdblk->cache_size = mtdblk->mtd->erasesize;
-		mtdblk->cache_data = vmalloc(mtdblk->mtd->erasesize);
-		if (!mtdblk->cache_data) {
-			kfree(mtdblk);
-			return -ENOMEM;
-		}
+		mtdblk->cache_data = NULL;
 	}
 
 	mtdblks[dev] = mtdblk;
@@ -293,17 +297,13 @@
 	return 0;
 }
 
-static int mtdblock_release(struct mtd_blktrans_dev *mbd,
-				  struct inode *inode, struct file *file)
+static int mtdblock_release(struct mtd_blktrans_dev *mbd)
 {
-	int dev;
-	struct mtdblk_dev *mtdblk;
+	int dev = mbd->devnum;
+	struct mtdblk_dev *mtdblk = mtdblks[dev];
 
    	DEBUG(MTD_DEBUG_LEVEL1, "mtdblock_release\n");
 
-	dev = minor(inode->i_rdev);
-	mtdblk = mtdblks[dev];
-
 	down(&mtdblk->cache_sem);
 	write_cached_data(mtdblk);
 	up(&mtdblk->cache_sem);
@@ -321,27 +321,17 @@
 	return 0;
 }  
 
-
-static int mtdblock_ioctl(struct mtd_blktrans_dev *dev, 
-			  struct inode * inode, struct file * file,
-			  unsigned int cmd, unsigned long arg)
+static int mtdblock_flush(struct mtd_blktrans_dev *dev)
 {
-	struct mtdblk_dev *mtdblk;
-
-	mtdblk = mtdblks[minor(inode->i_rdev)];
+	struct mtdblk_dev *mtdblk = mtdblks[dev->devnum];
 
-	switch (cmd) {
-	case BLKFLSBUF:
-		down(&mtdblk->cache_sem);
-		write_cached_data(mtdblk);
-		up(&mtdblk->cache_sem);
-		if (mtdblk->mtd->sync)
-			mtdblk->mtd->sync(mtdblk->mtd);
-		return 0;
+	down(&mtdblk->cache_sem);
+	write_cached_data(mtdblk);
+	up(&mtdblk->cache_sem);
 
-	default:
-		return -ENOTTY;
-	}
+	if (mtdblk->mtd->sync)
+		mtdblk->mtd->sync(mtdblk->mtd);
+	return 0;
 }
 
 static void mtdblock_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd)
@@ -376,7 +366,7 @@
 	.major		= 31,
 	.part_bits	= 0,
 	.open		= mtdblock_open,
-	.ioctl		= mtdblock_ioctl,
+	.flush		= mtdblock_flush,
 	.release	= mtdblock_release,
 	.readsect	= mtdblock_readsect,
 	.writesect	= mtdblock_writesect,
diff -Nru a/drivers/mtd/mtdblock_ro.c b/drivers/mtd/mtdblock_ro.c
--- a/drivers/mtd/mtdblock_ro.c	Wed May 28 08:01:05 2003
+++ b/drivers/mtd/mtdblock_ro.c	Mon Jun 23 05:40:42 2003
@@ -1,11 +1,12 @@
 /*
- * $Id: mtdblock_ro.c,v 1.17 2003/05/18 19:27:27 dwmw2 Exp $
+ * $Id: mtdblock_ro.c,v 1.18 2003/06/23 12:00:08 dwmw2 Exp $
  *
  * (C) 2003 David Woodhouse <dwmw2@infradead.org>
  *
  * Simple read-only (writable only for RAM) mtdblock driver
  */
 
+#include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/blktrans.h>
diff -Nru a/drivers/mtd/mtdpart.c b/drivers/mtd/mtdpart.c
--- a/drivers/mtd/mtdpart.c	Wed May 28 08:01:05 2003
+++ b/drivers/mtd/mtdpart.c	Mon Jun 23 05:34:08 2003
@@ -5,7 +5,7 @@
  *
  * This code is GPL
  *
- * $Id: mtdpart.c,v 1.39 2003/05/21 15:15:03 dwmw2 Exp $
+ * $Id: mtdpart.c,v 1.41 2003/06/18 14:53:02 dwmw2 Exp $
  *
  * 	02-21-2002	Thomas Gleixner <gleixner@autronix.de>
  *			added support for read_oob, write_oob
@@ -120,7 +120,7 @@
 			size_t *retlen, u_char *buf)
 {
 	struct mtd_part *part = PART(mtd);
-	return part->master->read_user_prot_reg (part->master, from, 
+	return part->master->read_fact_prot_reg (part->master, from, 
 					len, retlen, buf);
 }
 
diff -Nru a/drivers/mtd/nand/autcpu12.c b/drivers/mtd/nand/autcpu12.c
--- a/drivers/mtd/nand/autcpu12.c	Wed May 28 08:01:24 2003
+++ b/drivers/mtd/nand/autcpu12.c	Mon Jun 23 05:34:08 2003
@@ -6,7 +6,7 @@
  *  Derived from drivers/mtd/spia.c
  * 	 Copyright (C) 2000 Steven J. Hill (sjhill@realitydiluted.com)
  * 
- * $Id: autcpu12.c,v 1.10 2003/04/20 07:24:40 gleixner Exp $
+ * $Id: autcpu12.c,v 1.11 2003/06/04 17:04:09 gleixner Exp $
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -28,6 +28,7 @@
  */
 
 #include <linux/slab.h>
+#include <linux/init.h>
 #include <linux/module.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/nand.h>
diff -Nru a/drivers/mtd/nand/nand.c b/drivers/mtd/nand/nand.c
--- a/drivers/mtd/nand/nand.c	Wed May 28 08:01:05 2003
+++ b/drivers/mtd/nand/nand.c	Mon Jun 23 05:34:08 2003
@@ -124,9 +124,15 @@
  +		a structure, which will be supplied by a filesystem driver
  *		If NULL is given, then the defaults (none or defaults
  *		supplied by ioctl (MEMSETOOBSEL) are used.
- *		For partitions the partition defaults are used (mtdpart.c)		
+ *		For partitions the partition defaults are used (mtdpart.c)
+ *
+ *  06-04-2003  tglx: fix compile errors and fix write verify problem for
+ *		some chips, which need either a delay between the readback
+ *		and the next write command or have the CE removed. The
+ *		CE disable/enable is much faster than a 20us delay and
+ *		it should work on all available chips.
  *	
- * $Id: nand.c,v 1.45 2003/05/20 21:01:30 dwmw2 Exp $
+ * $Id: nand.c,v 1.46 2003/06/04 17:10:36 gleixner Exp $
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -141,6 +147,7 @@
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/nand.h>
 #include <linux/mtd/nand_ecc.h>
+#include <linux/mtd/compatmac.h>
 #include <linux/interrupt.h>
 #include <asm/io.h>
 
@@ -510,6 +517,13 @@
 			}
 		}
 	}
+	/* 
+	 * Terminate the read command. This is faster than sending a reset command or 
+	 * applying a 20us delay before issuing the next programm sequence.
+	 * This is not a problem for all chips, but I have found a bunch of them.
+	 */
+	nand_deselect();
+	nand_select();
 #endif
 	return 0;
 }
diff -Nru a/drivers/mtd/nftlcore.c b/drivers/mtd/nftlcore.c
--- a/drivers/mtd/nftlcore.c	Wed May 28 08:01:05 2003
+++ b/drivers/mtd/nftlcore.c	Mon Jun 23 05:40:43 2003
@@ -1,7 +1,7 @@
 /* Linux driver for NAND Flash Translation Layer      */
 /* (c) 1999 Machine Vision Holdings, Inc.             */
 /* Author: David Woodhouse <dwmw2@infradead.org>      */
-/* $Id: nftlcore.c,v 1.92 2003/05/23 11:41:47 dwmw2 Exp $ */
+/* $Id: nftlcore.c,v 1.94 2003/06/23 12:00:08 dwmw2 Exp $ */
 
 /*
   The contents of this file are distributed under the GNU General
@@ -101,7 +101,7 @@
 			(long)nftl->sectors );
 	}
 
-	if (add_mtd_blktrans_dev) {
+	if (add_mtd_blktrans_dev(&nftl->mbd)) {
 		if (nftl->ReplUnitTable)
 			kfree(nftl->ReplUnitTable);
 		if (nftl->EUNtable)
@@ -699,29 +699,17 @@
 	return 0;
 }
 
-static int nftl_ioctl(struct mtd_blktrans_dev *dev,
-		     struct inode * inode, struct file * file, 
-		     unsigned int cmd, unsigned long arg)
+static int nftl_getgeo(struct mtd_blktrans_dev *dev,  struct hd_geometry *geo)
 {
 	struct NFTLrecord *nftl = (void *)dev;
 
-	switch (cmd) {
-	case HDIO_GETGEO: {
-		struct hd_geometry g;
-
-		g.heads = nftl->heads;
-		g.sectors = nftl->sectors;
-		g.cylinders = nftl->cylinders;
-		g.start = 0;
-		return copy_to_user((void *)arg, &g, sizeof g) ? -EFAULT : 0;
-	}
+	geo->heads = nftl->heads;
+	geo->sectors = nftl->sectors;
+	geo->cylinders = nftl->cylinders;
 
-	default:
-		return -ENOTTY;
-	}
+	return 0;
 }
 
-
 /****************************************************************************
  *
  * Module stuff
@@ -733,7 +721,7 @@
 	.name		= "nftl",
 	.major		= NFTL_MAJOR,
 	.part_bits	= NFTL_PARTN_BITS,
-	.ioctl		= nftl_ioctl,
+	.getgeo		= nftl_getgeo,
 	.readsect	= nftl_readblock,
 #ifdef CONFIG_NFTL_RW
 	.writesect	= nftl_writeblock,
@@ -747,7 +735,7 @@
 
 int __init init_nftl(void)
 {
-	printk(KERN_INFO "NFTL driver: nftlcore.c $Revision: 1.92 $, nftlmount.c %s\n", nftlmountrev);
+	printk(KERN_INFO "NFTL driver: nftlcore.c $Revision: 1.94 $, nftlmount.c %s\n", nftlmountrev);
 
 	return register_mtd_blktrans(&nftl_tr);
 }
diff -Nru a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
--- a/drivers/usb/host/ehci-hcd.c	Mon Jun 16 11:00:43 2003
+++ b/drivers/usb/host/ehci-hcd.c	Wed Jun 18 21:50:06 2003
@@ -974,7 +974,7 @@
 /* EHCI spec says PCI is required. */
 
 /* PCI driver selection metadata; PCI hotplugging uses this */
-static const struct pci_device_id __devinitdata pci_ids [] = { {
+static struct pci_device_id __devinitdata pci_ids [] = { {
 
 	/* handle any USB 2.0 EHCI controller */
 
diff -Nru a/fs/jffs2/dir.c b/fs/jffs2/dir.c
--- a/fs/jffs2/dir.c	Wed May 28 08:01:06 2003
+++ b/fs/jffs2/dir.c	Mon Jun 23 05:42:27 2003
@@ -7,7 +7,7 @@
  *
  * For licensing information, see the file 'LICENCE' in this directory.
  *
- * $Id: dir.c,v 1.76 2003/05/26 09:50:38 dwmw2 Exp $
+ * $Id: dir.c,v 1.77 2003/06/05 14:42:24 dwmw2 Exp $
  *
  */
 
@@ -356,7 +356,7 @@
 	up(&f->sem);
 
 	/* Work out where to put the dirent node now. */
-	writtenlen = (writtenlen+3)&~3;
+	writtenlen = PAD(writtenlen);
 	phys_ofs += writtenlen;
 	alloclen -= writtenlen;
 
@@ -653,7 +653,7 @@
 	up(&f->sem);
 
 	/* Work out where to put the dirent node now. */
-	writtenlen = (writtenlen+3)&~3;
+	writtenlen = PAD(writtenlen);
 	phys_ofs += writtenlen;
 	alloclen -= writtenlen;
 
diff -Nru a/fs/jffs2/fs.c b/fs/jffs2/fs.c
--- a/fs/jffs2/fs.c	Wed May 28 08:01:06 2003
+++ b/fs/jffs2/fs.c	Mon Jun 23 06:03:49 2003
@@ -22,7 +22,7 @@
 #include <linux/vfs.h>
 #include "nodelist.h"
 
-int jffs2_statfs(struct super_block *sb, struct statfs *buf)
+int jffs2_statfs(struct super_block *sb, struct kstatfs *buf)
 {
 	struct jffs2_sb_info *c = JFFS2_SB_INFO(sb);
 	unsigned long avail;
diff -Nru a/fs/jffs2/os-linux.h b/fs/jffs2/os-linux.h
--- a/fs/jffs2/os-linux.h	Wed May 28 08:01:06 2003
+++ b/fs/jffs2/os-linux.h	Mon Jun 23 06:03:50 2003
@@ -123,7 +123,7 @@
 #define jffs2_flash_write_oob(c, ofs, len, retlen, buf) ((c)->mtd->write_oob((c)->mtd, ofs, len, retlen, buf))
 #define jffs2_flash_read_oob(c, ofs, len, retlen, buf) ((c)->mtd->read_oob((c)->mtd, ofs, len, retlen, buf))
 
-struct statfs;
+struct kstatfs;
 
 /* wbuf.c */
 int jffs2_flash_writev(struct jffs2_sb_info *c, const struct iovec *vecs, unsigned long count, loff_t to, size_t *retlen);
@@ -169,7 +169,7 @@
 void jffs2_clear_inode (struct inode *);
 struct inode *jffs2_new_inode (struct inode *dir_i, int mode,
 			       struct jffs2_raw_inode *ri);
-int jffs2_statfs (struct super_block *, struct statfs *);
+int jffs2_statfs (struct super_block *, struct kstatfs *);
 void jffs2_write_super (struct super_block *);
 int jffs2_remount_fs (struct super_block *, int *, char *);
 int jffs2_do_fill_super(struct super_block *sb, void *data, int silent);
diff -Nru a/fs/jffs2/scan.c b/fs/jffs2/scan.c
--- a/fs/jffs2/scan.c	Wed May 28 08:01:06 2003
+++ b/fs/jffs2/scan.c	Mon Jun 23 05:42:27 2003
@@ -7,7 +7,7 @@
  *
  * For licensing information, see the file 'LICENCE' in this directory.
  *
- * $Id: scan.c,v 1.99 2003/04/28 10:17:17 dwmw2 Exp $
+ * $Id: scan.c,v 1.100 2003/06/05 14:42:24 dwmw2 Exp $
  *
  */
 #include <linux/kernel.h>
@@ -354,7 +354,7 @@
 
 		if (ofs & 3) {
 			printk(KERN_WARNING "Eep. ofs 0x%08x not word-aligned!\n", ofs);
-			ofs = (ofs+3)&~3;
+			ofs = PAD(ofs);
 			continue;
 		}
 		if (ofs == prevofs) {
diff -Nru a/include/asm-sparc/unistd.h b/include/asm-sparc/unistd.h
--- a/include/asm-sparc/unistd.h	Mon Dec 30 04:45:30 2002
+++ b/include/asm-sparc/unistd.h	Sun Jun 22 19:57:50 2003
@@ -250,6 +250,8 @@
 #define __NR_time               231 /* Linux Specific                              */
 /* #define __NR_oldstat         232    Linux Specific                              */
 #define __NR_stime              233 /* Linux Specific                              */
+#define __NR_statfs64           234 /* Linux Specific                              */
+#define __NR_fstatfs64          235 /* Linux Specific                              */
 #define __NR__llseek            236 /* Linux Specific                              */
 #define __NR_mlock              237
 #define __NR_munlock            238
@@ -270,6 +272,11 @@
 #define __NR_fdatasync          253
 #define __NR_nfsservctl         254
 #define __NR_aplib              255
+/* WARNING: You MAY NOT add syscall numbers larger than 255, since
+ *          all of the syscall tables in the Sparc kernel are
+ *          sized to have 256 entries (starting at zero).  Therefore
+ *          find a free slot in the 0-255 range.
+ */
 
 #define _syscall0(type,name) \
 type name(void) \
diff -Nru a/include/asm-sparc64/compat.h b/include/asm-sparc64/compat.h
--- a/include/asm-sparc64/compat.h	Mon May 19 23:31:53 2003
+++ b/include/asm-sparc64/compat.h	Sun Jun 22 18:46:36 2003
@@ -92,7 +92,8 @@
 	int		f_ffree;
 	compat_fsid_t	f_fsid;
 	int		f_namelen;	/* SunOS ignores this field. */
-	int		f_spare[6];
+	int		f_frsize;
+	int		f_spare[5];
 };
 
 #define COMPAT_RLIM_INFINITY 0x7fffffff
diff -Nru a/include/asm-sparc64/unistd.h b/include/asm-sparc64/unistd.h
--- a/include/asm-sparc64/unistd.h	Tue Jan 28 10:58:25 2003
+++ b/include/asm-sparc64/unistd.h	Sun Jun 22 19:57:50 2003
@@ -252,8 +252,8 @@
 #endif
 /* #define __NR_oldstat         232    Linux Specific                              */
 #define __NR_stime              233 /* Linux Specific                              */
-/* #define __NR_UNUSED          234 */
-/* #define __NR_UNUSED          235 */
+#define __NR_statfs64           234 /* Linux Specific                              */
+#define __NR_fstatfs64          235 /* Linux Specific                              */
 #define __NR__llseek            236 /* Linux Specific                              */
 #define __NR_mlock              237
 #define __NR_munlock            238
@@ -274,6 +274,11 @@
 #define __NR_fdatasync          253
 #define __NR_nfsservctl         254
 #define __NR_aplib              255
+/* WARNING: You MAY NOT add syscall numbers larger than 255, since
+ *          all of the syscall tables in the Sparc64 kernel are
+ *          sized to have 256 entries (starting at zero).  Therefore
+ *          find a free slot in the 0-255 range.
+ */
 
 #define _syscall0(type,name) \
 type name(void) \
diff -Nru a/include/linux/loop.h b/include/linux/loop.h
--- a/include/linux/loop.h	Tue Jun 10 05:54:30 2003
+++ b/include/linux/loop.h	Sun Jun 22 20:42:22 2003
@@ -14,6 +14,9 @@
 #define LO_KEY_SIZE	32
 
 #ifdef __KERNEL__
+#include <linux/bio.h>
+#include <linux/blk.h>
+#include <linux/spinlock.h>
 
 /* Possible states of device */
 enum {
@@ -22,18 +25,20 @@
 	Lo_rundown,
 };
 
+struct loop_func_table;
+
 struct loop_device {
 	int		lo_number;
 	int		lo_refcnt;
 	int		lo_offset;
-	int		lo_encrypt_type;
-	int		lo_encrypt_key_size;
 	int		lo_flags;
 	int		(*transfer)(struct loop_device *, int cmd,
 				    char *raw_buf, char *loop_buf, int size,
 				    sector_t real_block);
 	char		lo_name[LO_NAME_SIZE];
 	char		lo_encrypt_key[LO_KEY_SIZE];
+	int		lo_encrypt_key_size;
+	struct loop_func_table *lo_encryption;
 	__u32           lo_init[2];
 	uid_t		lo_key_owner;	/* Who set the key */
 	int		(*ioctl)(struct loop_device *, int cmd, 
@@ -129,9 +134,7 @@
 	/* release is called from loop_unregister_transfer or clr_fd */
 	int (*release)(struct loop_device *); 
 	int (*ioctl)(struct loop_device *, int cmd, unsigned long arg);
-	/* lock and unlock manage the module use counts */ 
-	void (*lock)(struct loop_device *);
-	void (*unlock)(struct loop_device *);
+	struct module *owner;
 }; 
 
 int loop_register_transfer(struct loop_func_table *funcs);
diff -Nru a/include/linux/mtd/blktrans.h b/include/linux/mtd/blktrans.h
--- a/include/linux/mtd/blktrans.h	Wed May 28 08:01:26 2003
+++ b/include/linux/mtd/blktrans.h	Mon Jun 23 05:40:43 2003
@@ -1,5 +1,5 @@
 /*
- * $Id: blktrans.h,v 1.4 2003/05/21 01:01:32 dwmw2 Exp $
+ * $Id: blktrans.h,v 1.5 2003/06/23 12:00:08 dwmw2 Exp $
  *
  * (C) 2003 David Woodhouse <dwmw2@infradead.org>
  *
@@ -12,6 +12,7 @@
 
 #include <asm/semaphore.h>
 
+struct hd_geometry;
 struct mtd_info;
 struct mtd_blktrans_ops;
 struct file;
@@ -42,17 +43,13 @@
 	int (*writesect)(struct mtd_blktrans_dev *dev,
 		     unsigned long block, char *buffer);
 
-	/* HDIO_GETGEO and HDIO_GETGEO_BIG are the only non-private
-	   ioctls which are expected to be passed through */
-	int (*ioctl)(struct mtd_blktrans_dev *dev,
-		     struct inode * inode, struct file * file, 
-		     unsigned int cmd, unsigned long arg);
+	/* Block layer ioctls */
+	int (*getgeo)(struct mtd_blktrans_dev *dev, struct hd_geometry *geo);
+	int (*flush)(struct mtd_blktrans_dev *dev);
 
 	/* Called with mtd_table_mutex held; no race with add/remove */
-	int (*open)(struct mtd_blktrans_dev *dev, 
-		 struct inode *i, struct file *f);
-	int (*release)(struct mtd_blktrans_dev *dev,
-		    struct inode *i, struct file *f);
+	int (*open)(struct mtd_blktrans_dev *dev);
+	int (*release)(struct mtd_blktrans_dev *dev);
 
 	/* Called on {de,}registration and on subsequent addition/removal
 	   of devices, with mtd_table_mutex held. */
diff -Nru a/include/linux/mtd/doc2000.h b/include/linux/mtd/doc2000.h
--- a/include/linux/mtd/doc2000.h	Wed May 28 08:01:07 2003
+++ b/include/linux/mtd/doc2000.h	Mon Jun 23 05:34:09 2003
@@ -2,7 +2,7 @@
 /* Linux driver for Disk-On-Chip 2000       */
 /* (c) 1999 Machine Vision Holdings, Inc.   */
 /* Author: David Woodhouse <dwmw2@mvhi.com> */
-/* $Id: doc2000.h,v 1.16 2003/05/23 11:29:33 dwmw2 Exp $ */
+/* $Id: doc2000.h,v 1.17 2003/06/12 01:20:46 gerg Exp $ */
 
 #ifndef __MTD_DOC2000_H__
 #define __MTD_DOC2000_H__
@@ -44,7 +44,7 @@
 #define DoC_Mplus_AccessStatus		0x1008
 #define DoC_Mplus_DeviceSelect		0x1008
 #define DoC_Mplus_Configuration		0x100a
-#define DoC_Mplus_OutputControl		0x1002
+#define DoC_Mplus_OutputControl		0x100c
 #define DoC_Mplus_FlashControl		0x1020
 #define DoC_Mplus_FlashSelect 		0x1022
 #define DoC_Mplus_FlashCmd		0x1024
diff -Nru a/kernel/workqueue.c b/kernel/workqueue.c
--- a/kernel/workqueue.c	Fri Jun 20 13:16:22 2003
+++ b/kernel/workqueue.c	Sun Jun 22 20:39:57 2003
@@ -275,6 +275,7 @@
 	INIT_LIST_HEAD(&cwq->worklist);
 	init_waitqueue_head(&cwq->more_work);
 	init_waitqueue_head(&cwq->work_done);
+	init_completion(&cwq->exit);
 
 	init_completion(&startup.done);
 	startup.cwq = cwq;
@@ -320,10 +321,7 @@
 
 	cwq = wq->cpu_wq + cpu;
 	if (cwq->thread) {
-		printk("Cleaning up workqueue thread for %i\n", cpu);
-		/* Initiate an exit and wait for it: */
-		init_completion(&cwq->exit);
-		wmb(); /* Thread must see !cwq->thread after completion init */
+		/* Tell thread to exit and wait for it. */
 		cwq->thread = NULL;
 		wake_up(&cwq->more_work);
 
