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

diff -urN linux-2.5.70-bk1/Documentation/filesystems/fat_cvf.txt linux-2.5.70-bk2/Documentation/filesystems/fat_cvf.txt
--- linux-2.5.70-bk1/Documentation/filesystems/fat_cvf.txt	2003-05-26 18:00:44.000000000 -0700
+++ linux-2.5.70-bk2/Documentation/filesystems/fat_cvf.txt	1969-12-31 16:00:00.000000000 -0800
@@ -1,210 +0,0 @@
-This is the main documentation for the CVF-FAT filesystem extension.  18Nov1998
-
-
-Table of Contents:
-
-1. The idea of CVF-FAT
-2. Restrictions
-3. Mount options
-4. Description of the CVF-FAT interface
-5. CVF Modules
-
-------------------------------------------------------------------------------
-
-
-1. The idea of CVF-FAT
-------------------------------------------------------------------------------
-
-CVF-FAT is a FAT filesystem extension that provides a generic interface for
-Compressed Volume Files in FAT partitions. Popular CVF software, for
-example, are Microsoft's Doublespace/Drivespace and Stac's Stacker.
-Using the CVF-FAT interface, it is possible to load a module that handles
-all the low-level disk access that has to do with on-the-fly compression
-and decompression. Any other part of FAT filesystem access is still handled
-by the FAT, MSDOS or VFAT or even UMSDOS driver.
-
-CVF access works by redirecting certain low-level routines from the FAT
-driver to a loadable, CVF-format specific module. This module must fake
-a normal FAT filesystem to the FAT driver while doing all the extra stuff
-like compression and decompression silently.
-
-
-2. Restrictions
-------------------------------------------------------------------------------
-
-- BMAP problems
-
-  CVF filesystems cannot do bmap. It's impossible in principle. Thus
-  all actions that require bmap do not work (swapping, writable mmapping).
-  Read-only mmapping works because the FAT driver has a hack for this
-  situation :) Well, writable mmapping should now work using the readpage
-  interface function which has been hacked into the FAT driver just for 
-  CVF-FAT :)
-  
-- attention, DOSEmu users 
-
-  You may have to unmount all CVF partitions before running DOSEmu depending 
-  on your configuration. If DOSEmu is configured to use wholedisk or 
-  partition access (this is often the case to let DOSEmu access 
-  compressed partitions) there's a risk of destroying your compressed 
-  partitions or crashing your system because of confused drivers.
-  
-  Note that it is always safe to redirect the compressed partitions with 
-  lredir or emufs.sys. Refer to the DOSEmu documentation for details.
-
-
-3. Mount options
-------------------------------------------------------------------------------
-
-The CVF-FAT extension currently adds the following options to the FAT
-driver's standard options:
-
-  cvf_format=xxx
-    Forces the driver to use the CVF module "xxx" instead of auto-detection.
-    Without this option, the CVF-FAT interface asks all currently loaded
-    CVF modules whether they recognize the CVF. Therefore, this option is
-    only necessary if the CVF format is not recognized correctly
-    because of bugs or incompatibilities in the CVF modules. (It skips
-    the detect_cvf call.) "xxx" may be the text "none" (without the quotes)
-    to inhibit using any of the loaded CVF modules, just in case a CVF
-    module insists on mounting plain FAT filesystems by misunderstanding.
-    "xxx" may also be the text "autoload", which has a special meaning for
-    a module loader, but does not skip auto-detection.
-
-    If the kernel supports kmod, the cvf_format=xxx option also controls
-    on-demand CVF module loading. Without this option, nothing is loaded
-    on demand. With cvf_format=xxx, a module "xxx" is requested automatically
-    before mounting the compressed filesystem (unless "xxx" is "none"). In 
-    case there is a difference between the CVF format name and the module 
-    name, setup aliases in your modules configuration. If the string "xxx" 
-    is "autoload", a non-existent module "cvf_autoload" is requested which 
-    can be used together with a special modules configuration (alias and 
-    pre-install statements) in order to load more than one CVF module, let 
-    them detect automatically which kind of CVF is to be mounted, and only 
-    keep the "right" module in memory. For examples please refer to the 
-    dmsdos documentation (ftp and http addresses see below).
-
-  cvf_options=yyy
-    Option string passed to the CVF module. I.e. only the "yyy" is passed
-    (without the quotes). The documentation for each CVF module should 
-    explain it since it is interpreted only by the CVF module. Note that 
-    the string must not contain a comma (",") - this would lead to 
-    misinterpretation by the FAT driver, which would recognize the text 
-    after a comma as a FAT driver option and might get confused or print 
-    strange error messages. The documentation for the CVF module should 
-    offer a different separation symbol, for example the dot "." or the
-    plus sign "+", which is only valid inside the string "yyy".
-
-
-4. Description of the CVF-FAT interface
-------------------------------------------------------------------------------
-
-Assuming you want to write your own CVF module, you need to write a lot of
-interface functions. Most of them are covered in the kernel documentation
-you can find on the net, and thus won't be described here. They have been
-marked with "[...]" :-) Take a look at include/linux/fat_cvf.h.
-
-struct cvf_format
-{ int cvf_version;
-  char* cvf_version_text;
-  unsigned long int flags;
-  int (*detect_cvf) (struct super_block*sb);
-  int (*mount_cvf) (struct super_block*sb,char*options);
-  int (*unmount_cvf) (struct super_block*sb);
-  [...]
-  void (*zero_out_cluster) (struct inode*, int clusternr);
-}
-
-This structure defines the capabilities of a CVF module. It must be filled
-out completely by a CVF module. Consider it as a kind of form that is used
-to introduce the module to the FAT/CVF-FAT driver.
-
-It contains...
-  - cvf_version:
-      A version id which must be unique. Choose one.
-  - cvf_version_text:
-      A human readable version string that should be one short word 
-      describing the CVF format the module implements. This text is used
-      for the cvf_format option. This name must also be unique.
-  - flags:
-      Bit coded flags, currently only used for a readpage/mmap hack that 
-      provides both mmap and readpage functionality. If CVF_USE_READPAGE
-      is set, mmap is set to generic_file_mmap and readpage is caught
-      and redirected to the cvf_readpage function. If it is not set,
-      readpage is set to generic_readpage and mmap is caught and redirected
-      to cvf_mmap. (If you want writable mmap use the readpage interface.)
-  - detect_cvf:
-      A function that is called to decide whether the filesystem is a CVF of
-      the type the module supports. The detect_cvf function must return 0
-      for "NO, I DON'T KNOW THIS GARBAGE" or anything >0 for "YES, THIS IS
-      THE KIND OF CVF I SUPPORT". The function must maintain the module
-      usage counters for safety, i.e. do MOD_INC_USE_COUNT at the beginning
-      and MOD_DEC_USE_COUNT at the end. The function *must not* assume that
-      successful recognition would lead to a call of the mount_cvf function
-      later. 
-  - mount_cvf:
-      A function that sets up some values or initializes something additional
-      to what has to be done when a CVF is mounted. This is called at the
-      end of fat_read_super and must return 0 on success. Definitely, this
-      function must increment the module usage counter by MOD_INC_USE_COUNT.
-      This mount_cvf function is also responsible for interpreting a CVF
-      module specific option string (the "yyy" from the FAT mount option
-      "cvf_options=yyy") which cannot contain a comma (use for example the
-      dot "." as option separator symbol).
-  - unmount_cvf:
-      A function that is called when the filesystem is unmounted. Most likely
-      it only frees up some memory and calls MOD_DEC_USE_COUNT. The return
-      value might be ignored (it currently is ignored).
-  - [...]:
-      All other interface functions are "caught" FAT driver functions, i.e.
-      are executed by the FAT driver *instead* of the original FAT driver
-      functions. NULL means use the original FAT driver functions instead.
-      If you really want "no action", write a function that does nothing and 
-      hang it in instead.
-  - zero_out_cluster:
-      The zero_out_cluster function is called when the fat driver wants to
-      zero out a (new) cluster. This is important for directories (mkdir).
-      If it is NULL, the FAT driver defaults to overwriting the whole
-      cluster with zeros. Note that clusternr is absolute, not relative
-      to the provided inode.
-
-Notes:
-  1. The cvf_bmap function should be ignored. It really should never
-     get called from somewhere. I recommend redirecting it to a panic
-     or fatal error message so bugs show up immediately.
-  2. The cvf_writepage function is ignored. This is because the fat
-     driver doesn't support it. This might change in future. I recommend
-     setting it to NULL (i.e use default).
-
-int register_cvf_format(struct cvf_format*cvf_format);
-  If you have just set up a variable containing the above structure,
-  call this function to introduce your CVF format to the FAT/CVF-FAT
-  driver. This is usually done in init_module. Be sure to check the
-  return value. Zero means success, everything else causes a kernel
-  message printed in the syslog describing the error that occurred.
-  Typical errors are:
-    - a module with the same version id is already registered or 
-    - too many CVF formats. Hack fs/fat/cvf.c if you need more.
-
-int unregister_cvf_format(struct cvf_format*cvf_format);
-  This is usually called in cleanup_module. Return value =0 means
-  success. An error only occurs if you try to unregister a CVF format
-  that has not been previously registered. The code uses the version id
-  to distinguish the modules, so be sure to keep it unique.
-
-5. CVF Modules
-------------------------------------------------------------------------------
-
-Refer to the dmsdos module (the successor of the dmsdos filesystem) for a
-sample implementation.  It can currently be found at
-
-  ftp://fb9nt.uni-duisburg.de/pub/linux/dmsdos/dmsdos-x.y.z.tgz
-  ftp://sunsite.unc.edu/pub/Linux/system/Filesystems/dosfs/dmsdos-x.y.z.tgz
-  ftp://ftp.uni-stuttgart.de/pub/systems/linux/local/system/dmsdos-x.y.z.tgz
-
-(where x.y.z is to be replaced with the actual version number). Full
-documentation about dmsdos is included in the dmsdos package, but can also
-be found at
-
-  http://fb9nt.uni-duisburg.de/mitarbeiter/gockel/software/dmsdos/index.html
-  http://www.yk.rim.or.jp/~takafumi/dmsdos/index.html (in Japanese).
diff -urN linux-2.5.70-bk1/Makefile linux-2.5.70-bk2/Makefile
--- linux-2.5.70-bk1/Makefile	2003-05-28 04:36:58.000000000 -0700
+++ linux-2.5.70-bk2/Makefile	2003-05-28 04:37:02.000000000 -0700
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 5
 SUBLEVEL = 70
-EXTRAVERSION = -bk1
+EXTRAVERSION = -bk2
 
 # *DOCUMENTATION*
 # To see a list of typical targets execute "make help"
diff -urN linux-2.5.70-bk1/arch/alpha/kernel/pci.c linux-2.5.70-bk2/arch/alpha/kernel/pci.c
--- linux-2.5.70-bk1/arch/alpha/kernel/pci.c	2003-05-26 18:00:22.000000000 -0700
+++ linux-2.5.70-bk2/arch/alpha/kernel/pci.c	2003-05-28 04:37:02.000000000 -0700
@@ -102,7 +102,7 @@
 {
 	unsigned int class = dev->class >> 8;
 
-	if (class == PCI_CLASS_BRIDGE_ISA || class == PCI_CLASS_BRIDGE_ISA) {
+	if (class == PCI_CLASS_BRIDGE_ISA || class == PCI_CLASS_BRIDGE_EISA) {
 		dev->dma_mask = MAX_ISA_DMA_ADDRESS - 1;
 		isa_bridge = dev;
 	}
diff -urN linux-2.5.70-bk1/arch/alpha/kernel/ptrace.c linux-2.5.70-bk2/arch/alpha/kernel/ptrace.c
--- linux-2.5.70-bk1/arch/alpha/kernel/ptrace.c	2003-05-26 18:00:56.000000000 -0700
+++ linux-2.5.70-bk2/arch/alpha/kernel/ptrace.c	2003-05-28 04:37:02.000000000 -0700
@@ -366,8 +366,8 @@
 		ret = -EIO;
 		if ((unsigned long) data > _NSIG)
 			break;
-		/* Set single stepping.  */
-		ptrace_set_bpt(child);
+		/* Mark single stepping.  */
+		child->thread_info->bpt_nsaved = -1;
 		clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
 		wake_up_process(child);
 		child->exit_code = data;
diff -urN linux-2.5.70-bk1/arch/alpha/kernel/signal.c linux-2.5.70-bk2/arch/alpha/kernel/signal.c
--- linux-2.5.70-bk1/arch/alpha/kernel/signal.c	2003-05-26 18:00:39.000000000 -0700
+++ linux-2.5.70-bk2/arch/alpha/kernel/signal.c	2003-05-28 04:37:02.000000000 -0700
@@ -619,7 +619,10 @@
 	if (!oldset)
 		oldset = &current->blocked;
 
+	/* This lets the debugger run, ... */
 	signr = get_signal_to_deliver(&info, regs, NULL);
+	/* ... so re-check the single stepping. */
+	single_stepping |= ptrace_cancel_bpt(current);
 
 	if (signr > 0) {
 		/* Whee!  Actually deliver the signal.  */
diff -urN linux-2.5.70-bk1/arch/alpha/kernel/smp.c linux-2.5.70-bk2/arch/alpha/kernel/smp.c
--- linux-2.5.70-bk1/arch/alpha/kernel/smp.c	2003-05-26 18:00:27.000000000 -0700
+++ linux-2.5.70-bk2/arch/alpha/kernel/smp.c	2003-05-28 04:37:02.000000000 -0700
@@ -417,12 +417,7 @@
 	/* Don't care about the contents of regs since we'll never
 	   reschedule the forked task. */
 	struct pt_regs regs;
-	int pid;
-	pid = do_fork(CLONE_VM|CLONE_IDLETASK, 0, &regs, 0, NULL, NULL);
-	if (pid < 0)
-		return NULL;
-
-	return find_task_by_pid (pid);
+	return copy_process(CLONE_VM|CLONE_IDLETASK, 0, &regs, 0, NULL, NULL);
 }
 
 /*
@@ -441,9 +436,11 @@
 	   wish.  We can't use kernel_thread since we must avoid
 	   rescheduling the child.  */
 	idle = fork_by_hand();
-	if (!idle)
+	if (IS_ERR(idle))
 		panic("failed fork for CPU %d", cpuid);
 
+	wake_up_forked_process(idle);
+
 	init_idle(idle, cpuid);
 	unhash_process(idle);
 
diff -urN linux-2.5.70-bk1/arch/m68knommu/platform/68VZ328/de2/config.c linux-2.5.70-bk2/arch/m68knommu/platform/68VZ328/de2/config.c
--- linux-2.5.70-bk1/arch/m68knommu/platform/68VZ328/de2/config.c	2003-05-26 18:00:26.000000000 -0700
+++ linux-2.5.70-bk2/arch/m68knommu/platform/68VZ328/de2/config.c	2003-05-28 04:37:02.000000000 -0700
@@ -118,7 +118,7 @@
 
 static void init_hardware(void)
 {
-#if CONFIG_DIRECT_IO_ACCESS
+#ifdef CONFIG_DIRECT_IO_ACCESS
 	SCR = 0x10;					/* allow user access to internal registers */
 #endif
 
diff -urN linux-2.5.70-bk1/arch/v850/as85ep1-rom.ld linux-2.5.70-bk2/arch/v850/as85ep1-rom.ld
--- linux-2.5.70-bk1/arch/v850/as85ep1-rom.ld	2003-05-26 18:00:38.000000000 -0700
+++ linux-2.5.70-bk2/arch/v850/as85ep1-rom.ld	2003-05-28 04:37:02.000000000 -0700
@@ -1,9 +1,6 @@
 /* Linker script for the NEC AS85EP1 V850E evaluation board
    (CONFIG_V850E_AS85EP1), with kernel in ROM (CONFIG_ROM_KERNEL).  */
 
-/* Note, all symbols are prefixed with an extra `_' for compatibility with
-   the existing linux sources.  */
-
 MEMORY {
 	/* 4MB of flash ROM.  */
 	ROM   : ORIGIN = 0,          LENGTH = 0x00400000
@@ -12,7 +9,7 @@
 	SRAM  : ORIGIN = 0x00400000, LENGTH = 0x00100000
 
 	/* About 58MB of DRAM.  This can actually be at one of two
-	   positions, determined by jump JP3; we have to use the first
+	   positions, determined by jumper JP3; we have to use the first
 	   position because the second is partially out of processor
 	   instruction addressing range (though in the second position
 	   there's actually 64MB available).  */
diff -urN linux-2.5.70-bk1/arch/v850/kernel/entry.S linux-2.5.70-bk2/arch/v850/kernel/entry.S
--- linux-2.5.70-bk1/arch/v850/kernel/entry.S	2003-05-26 18:00:57.000000000 -0700
+++ linux-2.5.70-bk2/arch/v850/kernel/entry.S	2003-05-28 04:37:02.000000000 -0700
@@ -29,28 +29,28 @@
 #define CSYM	C_SYMBOL_NAME
 
 
-/* The offset of the struct pt_regs in a `state save frame' on the stack.  */
+/* The offset of the struct pt_regs in a state-save-frame on the stack.  */
 #define PTO	STATE_SAVE_PT_OFFSET
 
 
-/* Save argument registers to the struct pt_regs pointed to by EP.  */
+/* Save argument registers to the state-save-frame pointed to by EP.  */
 #define SAVE_ARG_REGS							      \
 	sst.w	r6, PTO+PT_GPR(6)[ep];					      \
 	sst.w	r7, PTO+PT_GPR(7)[ep];					      \
 	sst.w	r8, PTO+PT_GPR(8)[ep];					      \
 	sst.w	r9, PTO+PT_GPR(9)[ep]
-/* Restore argument registers from the struct pt_regs pointed to by EP.  */
+/* Restore argument registers from the state-save-frame pointed to by EP.  */
 #define RESTORE_ARG_REGS						      \
 	sld.w	PTO+PT_GPR(6)[ep], r6;					      \
 	sld.w	PTO+PT_GPR(7)[ep], r7;					      \
 	sld.w	PTO+PT_GPR(8)[ep], r8;					      \
 	sld.w	PTO+PT_GPR(9)[ep], r9
 
-/* Save value return registers to the struct pt_regs pointed to by EP.  */
+/* Save value return registers to the state-save-frame pointed to by EP.  */
 #define SAVE_RVAL_REGS							      \
 	sst.w	r10, PTO+PT_GPR(10)[ep];				      \
 	sst.w	r11, PTO+PT_GPR(11)[ep]
-/* Restore value return registers from the struct pt_regs pointed to by EP.  */
+/* Restore value return registers from the state-save-frame pointed to by EP.  */
 #define RESTORE_RVAL_REGS						      \
 	sld.w	PTO+PT_GPR(10)[ep], r10;				      \
 	sld.w	PTO+PT_GPR(11)[ep], r11
@@ -81,13 +81,13 @@
 	sld.w	PTO+PT_GPR(18)[ep], r18;				      \
 	sld.w	PTO+PT_GPR(19)[ep], r19
 
-/* Save `call clobbered' registers to the struct pt_regs pointed to by EP.  */
+/* Save `call clobbered' registers to the state-save-frame pointed to by EP.  */
 #define SAVE_CALL_CLOBBERED_REGS					      \
 	SAVE_CALL_CLOBBERED_REGS_BEFORE_ARGS;				      \
 	SAVE_ARG_REGS;							      \
 	SAVE_RVAL_REGS;							      \
 	SAVE_CALL_CLOBBERED_REGS_AFTER_RVAL
-/* Restore `call clobbered' registers from the struct pt_regs pointed to
+/* Restore `call clobbered' registers from the state-save-frame pointed to
    by EP.  */
 #define RESTORE_CALL_CLOBBERED_REGS					      \
 	RESTORE_CALL_CLOBBERED_REGS_BEFORE_ARGS;			      \
@@ -96,19 +96,19 @@
 	RESTORE_CALL_CLOBBERED_REGS_AFTER_RVAL
 
 /* Save `call clobbered' registers except for the return-value registers
-   to the struct pt_regs pointed to by EP.  */
+   to the state-save-frame pointed to by EP.  */
 #define SAVE_CALL_CLOBBERED_REGS_NO_RVAL				      \
 	SAVE_CALL_CLOBBERED_REGS_BEFORE_ARGS;				      \
 	SAVE_ARG_REGS;							      \
 	SAVE_CALL_CLOBBERED_REGS_AFTER_RVAL
 /* Restore `call clobbered' registers except for the return-value registers
-   from the struct pt_regs pointed to by EP.  */
+   from the state-save-frame pointed to by EP.  */
 #define RESTORE_CALL_CLOBBERED_REGS_NO_RVAL				      \
 	RESTORE_CALL_CLOBBERED_REGS_BEFORE_ARGS;			      \
 	RESTORE_ARG_REGS;						      \
 	RESTORE_CALL_CLOBBERED_REGS_AFTER_RVAL
 
-/* Save `call saved' registers to the struct pt_regs pointed to by EP.  */
+/* Save `call saved' registers to the state-save-frame pointed to by EP.  */
 #define SAVE_CALL_SAVED_REGS						      \
 	sst.w	r2, PTO+PT_GPR(2)[ep];					      \
 	sst.w	r20, PTO+PT_GPR(20)[ep];				      \
@@ -121,7 +121,7 @@
 	sst.w	r27, PTO+PT_GPR(27)[ep];				      \
 	sst.w	r28, PTO+PT_GPR(28)[ep];				      \
 	sst.w	r29, PTO+PT_GPR(29)[ep]
-/* Restore `call saved' registers from the struct pt_regs pointed to by EP.  */
+/* Restore `call saved' registers from the state-save-frame pointed to by EP.  */
 #define RESTORE_CALL_SAVED_REGS						      \
 	sld.w	PTO+PT_GPR(2)[ep], r2;					      \
 	sld.w	PTO+PT_GPR(20)[ep], r20;				      \
@@ -136,12 +136,12 @@
 	sld.w	PTO+PT_GPR(29)[ep], r29
 
 
-/* Save the PC stored in the special register SAVEREG to the struct pt_regs
+/* Save the PC stored in the special register SAVEREG to the state-save-frame
    pointed to by EP.  r19 is clobbered.  */
 #define SAVE_PC(savereg)						      \
 	stsr	SR_ ## savereg, r19;					      \
 	sst.w	r19, PTO+PT_PC[ep]
-/* Restore the PC from the struct pt_regs pointed to by EP, to the special
+/* Restore the PC from the state-save-frame pointed to by EP, to the special
    register SAVEREG.  LP is clobbered (it is used as a scratch register
    because the POP_STATE macro restores it, and this macro is usually used
    inside POP_STATE).  */
@@ -149,11 +149,11 @@
 	sld.w	PTO+PT_PC[ep], lp;					      \
 	ldsr	lp, SR_ ## savereg
 /* Save the PSW register stored in the special register SAVREG to the
-   struct pt_regs pointed to by EP r19 is clobbered.  */
+   state-save-frame pointed to by EP.  r19 is clobbered.  */
 #define SAVE_PSW(savereg)						      \
 	stsr	SR_ ## savereg, r19;					      \
 	sst.w	r19, PTO+PT_PSW[ep]
-/* Restore the PSW register from the struct pt_regs pointed to by EP, to
+/* Restore the PSW register from the state-save-frame pointed to by EP, to
    the special register SAVEREG.  LP is clobbered (it is used as a scratch
    register because the POP_STATE macro restores it, and this macro is
    usually used inside POP_STATE).  */
@@ -161,7 +161,7 @@
 	sld.w	PTO+PT_PSW[ep], lp;					      \
 	ldsr	lp, SR_ ## savereg
 
-/* Save CTPC/CTPSW/CTBP registers to the struct pt_regs pointed to by REG.  
+/* Save CTPC/CTPSW/CTBP registers to the state-save-frame pointed to by REG.
    r19 is clobbered.  */
 #define SAVE_CT_REGS							      \
 	stsr	SR_CTPC, r19;						      \
@@ -170,7 +170,7 @@
 	sst.w	r19, PTO+PT_CTPSW[ep];					      \
 	stsr	SR_CTBP, r19;						      \
 	sst.w	r19, PTO+PT_CTBP[ep]
-/* Restore CTPC/CTPSW/CTBP registers from the struct pt_regs pointed to by EP.
+/* Restore CTPC/CTPSW/CTBP registers from the state-save-frame pointed to by EP.
    LP is clobbered (it is used as a scratch register because the POP_STATE
    macro restores it, and this macro is usually used inside POP_STATE).  */
 #define RESTORE_CT_REGS							      \
@@ -182,10 +182,11 @@
 	ldsr	lp, SR_CTBP
 
 
-/* Push register state, except for the stack pointer, on the stack in the form
-   of a struct pt_regs, in preparation for a system call.  This macro makes
-   sure that `special' registers, system registers; TYPE identifies the set of
-   extra registers to be saved as well.  EP is clobbered.  */
+/* Push register state, except for the stack pointer, on the stack in the
+   form of a state-save-frame (plus some extra padding), in preparation for
+   a system call.  This macro makes sure that the EP, GP, and LP
+   registers are saved, and TYPE identifies the set of extra registers to
+   be saved as well.  Also copies (the new value of) SP to EP.  */
 #define PUSH_STATE(type)						      \
 	addi	-STATE_SAVE_SIZE, sp, sp; /* Make room on the stack.  */      \
 	st.w	ep, PTO+PT_GPR(GPR_EP)[sp];				      \
@@ -193,8 +194,8 @@
 	sst.w	gp, PTO+PT_GPR(GPR_GP)[ep];				      \
 	sst.w	lp, PTO+PT_GPR(GPR_LP)[ep];				      \
 	type ## _STATE_SAVER
-/* Pop a register state, except for the stack pointer, from the struct pt_regs
-   on the stack.  */
+/* Pop a register state pushed by PUSH_STATE, except for the stack pointer,
+   from the the stack.  */
 #define POP_STATE(type)							      \
 	mov	sp, ep;							      \
 	type ## _STATE_RESTORER;					      \
@@ -205,7 +206,7 @@
 
 
 /* Switch to the kernel stack if necessary, and push register state on the
-   stack in the form of a struct pt_regs.  Also load the current task
+   stack in the form of a state-save-frame.  Also load the current task
    pointer if switching from user mode.  The stack-pointer (r3) should have
    already been saved to the memory location SP_SAVE_LOC (the reason for
    this is that the interrupt vectors may be beyond a 22-bit signed offset
@@ -234,25 +235,30 @@
 	sst.w	syscall_num, PTO+PT_CUR_SYSCALL[ep]
 
 
-/* Save register state not normally saved by PUSH_STATE for TYPE.  */
+/* Save register state not normally saved by PUSH_STATE for TYPE, to the
+   state-save-frame on the stack; also copies SP to EP.  r19 may be trashed. */
 #define SAVE_EXTRA_STATE(type)						      \
-        mov	sp, ep;							      \
+	mov	sp, ep;							      \
 	type ## _EXTRA_STATE_SAVER
-/* Restore register state not normally restored by POP_STATE for TYPE.  */
+/* Restore register state not normally restored by POP_STATE for TYPE,
+   from the state-save-frame on the stack; also copies SP to EP.
+   r19 may be trashed.  */
 #define RESTORE_EXTRA_STATE(type)					      \
-        mov	sp, ep;							      \
+	mov	sp, ep;							      \
 	type ## _EXTRA_STATE_RESTORER
 
-/* Save any call-clobbered registers not normally saved by PUSH_STATE
-   for TYPE.  */
-#define SAVE_EXTRA_STATE_FOR_FUNCALL(type)				      \
-        mov	sp, ep;							      \
-	type ## _FUNCALL_EXTRA_STATE_SAVER
-/* Restore any call-clobbered registers not normally restored by POP_STATE for
-   TYPE.  */
-#define RESTORE_EXTRA_STATE_FOR_FUNCALL(type)				      \
-        mov	sp, ep;							      \
-	type ## _FUNCALL_EXTRA_STATE_RESTORER
+/* Save any call-clobbered registers not normally saved by PUSH_STATE for
+   TYPE, to the state-save-frame on the stack.
+   EP may be trashed, but is not guaranteed to contain a copy of SP
+   (unlike after most SAVE_... macros).  r19 may be trashed.  */
+#define SAVE_EXTRA_STATE_FOR_SCHEDULE(type)				      \
+	type ## _SCHEDULE_EXTRA_STATE_SAVER
+/* Restore any call-clobbered registers not normally restored by
+   POP_STATE for TYPE, to the state-save-frame on the stack.
+   EP may be trashed, but is not guaranteed to contain a copy of SP
+   (unlike after most RESTORE_... macros).  r19 may be trashed.  */
+#define RESTORE_EXTRA_STATE_FOR_SCHEDULE(type)				      \
+	type ## _SCHEDULE_EXTRA_STATE_RESTORER
 
 
 /* These are extra_state_saver/restorer values for a user trap.  Note
@@ -263,36 +269,48 @@
    caller of the syscall function should have saved them.  */
 
 #define TRAP_RET reti
-/* Traps don't save call-clobbered registers (but do still save arg regs).  */
+/* Traps don't save call-clobbered registers (but do still save arg regs).
+   We preserve PSw to keep long-term state, namely interrupt status (for traps
+   from kernel-mode), and the single-step flag (for user traps).  */
 #define TRAP_STATE_SAVER						      \
 	SAVE_ARG_REGS;							      \
-	SAVE_PC(EIPC)
+	SAVE_PC(EIPC);							      \
+	SAVE_PSW(EIPSW)
 /* When traps return, they just leave call-clobbered registers (except for arg
-   regs) with whatever value they have from the kernel.  */
+   regs) with whatever value they have from the kernel.  Traps don't preserve
+   the PSW, but we zero EIPSW to ensure it doesn't contain anything dangerous
+   (in particular, the single-step flag).  */
 #define TRAP_STATE_RESTORER						      \
 	RESTORE_ARG_REGS;						      \
-	RESTORE_PC(EIPC)
+	RESTORE_PC(EIPC);						      \
+	RESTORE_PSW(EIPSW)
 /* Save registers not normally saved by traps.  We need to save r12, even
    though it's nominally call-clobbered, because it's used when restarting
    a system call (the signal-handling path uses SAVE_EXTRA_STATE, and
-   expects r12 to be restored when the trap returns).  Similarly, we must
-   save the PSW, so that it's at least in a known state in the the pt_regs
-   structure.  */
+   expects r12 to be restored when the trap returns).  */
 #define TRAP_EXTRA_STATE_SAVER						      \
 	SAVE_RVAL_REGS;							      \
 	sst.w	r12, PTO+PT_GPR(12)[ep];				      \
 	SAVE_CALL_SAVED_REGS;						      \
-	SAVE_PSW(EIPSW);						      \
 	SAVE_CT_REGS
 #define TRAP_EXTRA_STATE_RESTORER					      \
 	RESTORE_RVAL_REGS;						      \
 	sld.w	PTO+PT_GPR(12)[ep], r12;				      \
 	RESTORE_CALL_SAVED_REGS;					      \
-	RESTORE_PSW(EIPSW);						      \
 	RESTORE_CT_REGS
-#define TRAP_FUNCALL_EXTRA_STATE_SAVER					      \
+/* Save registers prior to calling scheduler (just before trap returns).
+   We have to save the return-value registers to preserve the trap's return
+   value.  Note that ..._SCHEDULE_EXTRA_STATE_SAVER, unlike most ..._SAVER
+   macros, is required to setup EP itself if EP is needed (this is because
+   in many cases, the macro is empty).  */
+#define TRAP_SCHEDULE_EXTRA_STATE_SAVER					      \
+	mov sp, ep;							      \
 	SAVE_RVAL_REGS
-#define TRAP_FUNCALL_EXTRA_STATE_RESTORER				      \
+/* Note that ..._SCHEDULE_EXTRA_STATE_RESTORER, unlike most ..._RESTORER
+   macros, is required to setup EP itself if EP is needed (this is because
+   in many cases, the macro is empty).  */
+#define TRAP_SCHEDULE_EXTRA_STATE_RESTORER				      \
+	mov sp, ep;							      \
 	RESTORE_RVAL_REGS
 
 /* Register saving/restoring for maskable interrupts.  */
@@ -311,8 +329,8 @@
 #define IRQ_EXTRA_STATE_RESTORER					      \
 	RESTORE_CALL_SAVED_REGS;					      \
 	RESTORE_CT_REGS
-#define IRQ_FUNCALL_EXTRA_STATE_SAVER       /* nothing */
-#define IRQ_FUNCALL_EXTRA_STATE_RESTORER    /* nothing */
+#define IRQ_SCHEDULE_EXTRA_STATE_SAVER	     /* nothing */
+#define IRQ_SCHEDULE_EXTRA_STATE_RESTORER    /* nothing */
 
 /* Register saving/restoring for non-maskable interrupts.  */
 #define NMI_RET reti
@@ -330,8 +348,8 @@
 #define NMI_EXTRA_STATE_RESTORER					      \
 	RESTORE_CALL_SAVED_REGS;					      \
 	RESTORE_CT_REGS
-#define NMI_FUNCALL_EXTRA_STATE_SAVER       /* nothing */
-#define NMI_FUNCALL_EXTRA_STATE_RESTORER    /* nothing */
+#define NMI_SCHEDULE_EXTRA_STATE_SAVER	     /* nothing */
+#define NMI_SCHEDULE_EXTRA_STATE_RESTORER    /* nothing */
 
 /* Register saving/restoring for debug traps.  */
 #define DBTRAP_RET .long 0x014607E0 /* `dbret', but gas doesn't support it. */
@@ -349,8 +367,8 @@
 #define DBTRAP_EXTRA_STATE_RESTORER					      \
 	RESTORE_CALL_SAVED_REGS;					      \
 	RESTORE_CT_REGS
-#define DBTRAP_FUNCALL_EXTRA_STATE_SAVER       /* nothing */
-#define DBTRAP_FUNCALL_EXTRA_STATE_RESTORER    /* nothing */
+#define DBTRAP_SCHEDULE_EXTRA_STATE_SAVER	/* nothing */
+#define DBTRAP_SCHEDULE_EXTRA_STATE_RESTORER	/* nothing */
 
 /* Register saving/restoring for a context switch.  We don't need to save
    too many registers, because context-switching looks like a function call
@@ -372,14 +390,14 @@
 	RESTORE_CT_REGS
 
 
-/* Restore register state from the struct pt_regs on the stack, switch back
+/* Restore register state from the state-save-frame on the stack, switch back
    to the user stack if necessary, and return from the trap/interrupt.
    EXTRA_STATE_RESTORER is a sequence of assembly language statements to
    restore anything not restored by this macro.  Only registers not saved by
    the C compiler are restored (that is, R3(sp), R4(gp), R31(lp), and
    anything restored by EXTRA_STATE_RESTORER).  */
 #define RETURN(type)							      \
-        ld.b	PTO+PT_KERNEL_MODE[sp], r19;				      \
+	ld.b	PTO+PT_KERNEL_MODE[sp], r19;				      \
 	di;				/* Disable interrupts */	      \
 	cmp	r19, r0;		/* See if returning to kernel mode, */\
 	bne	2f;			/* ... if so, skip resched &c.  */    \
@@ -390,33 +408,34 @@
 	ld.w	TI_FLAGS[r18], r19;					      \
 	andi	_TIF_NEED_RESCHED, r19, r0;				      \
 	bnz	3f;			/* Call the scheduler.  */	      \
-	andi	_TIF_SIGPENDING, r19, r0;				      \
-	bnz	4f;			/* Signals to handle, handle them */  \
+5:	andi	_TIF_SIGPENDING, r19, r18;				      \
+	ld.w	TASK_PTRACE[CURRENT_TASK], r19; /* ptrace flags */	      \
+	or	r18, r19;		/* see if either is non-zero */	      \
+	bnz	4f;			/* if so, handle them */	      \
 									      \
-/* Return to user state.  */					   	      \
+/* Return to user state.  */						      \
 1:	st.b	r0, KM;			/* Now officially in user state. */   \
 									      \
 /* Final return.  The stack-pointer fiddling is not needed when returning     \
    to kernel-mode, but they don't hurt, and this way we can share the	      \
-   (somtimes rather lengthy) POP_STATE macro.  */			      \
+   (sometimes rather lengthy) POP_STATE macro.  */			      \
 2:	POP_STATE(type);						      \
 	st.w	sp, KSP;		/* Save the kernel stack pointer. */  \
-	ld.w    PT_GPR(GPR_SP)-PT_SIZE[sp], sp; /* Restore stack pointer. */  \
+	ld.w	PT_GPR(GPR_SP)-PT_SIZE[sp], sp; /* Restore stack pointer. */  \
 	type ## _RET;			/* Return from the trap/interrupt. */ \
 									      \
 /* Call the scheduler before returning from a syscall/trap. */		      \
-3:	SAVE_EXTRA_STATE_FOR_FUNCALL(type); /* Prepare for funcall. */	      \
-	jarl	CSYM(schedule), lp;	/* Call scheduler */		      \
+3:	SAVE_EXTRA_STATE_FOR_SCHEDULE(type); /* Prepare to call scheduler. */ \
+	jarl	call_scheduler, lp;	/* Call scheduler */		      \
 	di;				/* The scheduler enables interrupts */\
-	RESTORE_EXTRA_STATE_FOR_FUNCALL(type);				      \
+	RESTORE_EXTRA_STATE_FOR_SCHEDULE(type);				      \
 	GET_CURRENT_THREAD(r18);					      \
 	ld.w	TI_FLAGS[r18], r19;					      \
-	andi	_TIF_SIGPENDING, r19, r0;				      \
-	bz	1b;			/* No signals, return.  */	      \
-	/* Signals to handle, fall through to handle them.  */		      \
+	br	5b;			/* Continue with return path. */      \
 									      \
-/* Handle a signal return.  */						      \
-4:      /* Not all registers are saved by the normal trap/interrupt entry     \
+/* Handle a signal or ptraced process return.				      \
+   r18 should be non-zero if there are pending signals.  */		      \
+4:	/* Not all registers are saved by the normal trap/interrupt entry     \
 	   points (for instance, call-saved registers (because the normal     \
 	   C-compiler calling sequence in the kernel makes sure they're	      \
 	   preserved), and call-clobbered registers in the case of	      \
@@ -424,12 +443,9 @@
 	   complete register state.  Here we save anything not saved by	      \
 	   the normal entry sequence, so that it may be safely restored	      \
 	   (in a possibly modified form) after do_signal returns.  */	      \
-        SAVE_EXTRA_STATE(type);		/* Save state not saved by entry. */  \
-	movea	PTO, sp, r6;		/* Arg 1: struct pt_regs *regs */     \
-	mov	r0, r7;			/* Arg 2: sigset_t *oldset */	      \
-	jarl	CSYM(do_signal), lp;	/* Handle any signals */	      \
-	di;				/* sig handling enables interrupts */ \
-        RESTORE_EXTRA_STATE(type);	/* Restore extra regs.  */	      \
+	SAVE_EXTRA_STATE(type);		/* Save state not saved by entry. */  \
+	jarl	handle_signal_or_ptrace_return, lp;			      \
+	RESTORE_EXTRA_STATE(type);	/* Restore extra regs.  */	      \
 	br	1b
 
 
@@ -471,7 +487,7 @@
  *   Return value in r10
  */
 G_ENTRY(trap):
-	SAVE_STATE (TRAP, r12, ENTRY_SP) // Save registers. 
+	SAVE_STATE (TRAP, r12, ENTRY_SP) // Save registers.
 	stsr	SR_ECR, r19		// Find out which trap it was.
 	ei				// Enable interrupts.
 	mov	hilo(ret_from_trap), lp	// where the trap should return
@@ -481,12 +497,12 @@
 	// numbers into the (0-31) << 2 range we want, (3) set the flags.
 	shl	27, r19			// chop off all high bits
 	shr	25, r19			// scale back down and then << 2
-	bnz	2f			// See if not trap 0. 
+	bnz	2f			// See if not trap 0.
 
-	// Trap 0 is a `short' system call, skip general trap table. 
-	MAKE_SYS_CALL			// Jump to the syscall function. 
+	// Trap 0 is a `short' system call, skip general trap table.
+	MAKE_SYS_CALL			// Jump to the syscall function.
 
-2:	// For other traps, use a table lookup. 
+2:	// For other traps, use a table lookup.
 	mov	hilo(CSYM(trap_table)), r18
 	add	r19, r18
 	ld.w	0[r18], r18
@@ -505,6 +521,7 @@
 	RETURN(TRAP)
 END(ret_from_trap)
 
+
 /* This the initial entry point for a new child thread, with an appropriate
    stack in place that makes it look the the child is in the middle of an
    syscall.  This function is actually `returned to' from switch_thread
@@ -538,7 +555,7 @@
 	mov	hilo(ret_from_long_syscall), lp
 
 	MAKE_SYS_CALL			// Jump to the syscall function.
-END(syscall_long)	
+END(syscall_long)
 
 /* Entry point used to return from a long syscall.  Only needed to restore
    r13/r14 if the general trap mechanism doesnt' do so.  */
@@ -554,11 +571,14 @@
 
 L_ENTRY(sys_fork_wrapper):
 #ifdef CONFIG_MMU
-	addi	SIGCHLD, r0, r6		// Arg 0: flags
+	addi	SIGCHLD, r0, r6		   // Arg 0: flags
 	ld.w	PTO+PT_GPR(GPR_SP)[sp], r7 // Arg 1: child SP (use parent's)
-	movea	PTO, sp, r8		// Arg 2: parent context
-	mov	hilo(CSYM(fork_common)), r18// Where the real work gets done
-	br	save_extra_state_tramp	// Save state and go there
+	movea	PTO, sp, r8		   // Arg 2: parent context
+	mov	r0, r9			   // Arg 3/4/5: 0
+	st.w	r0, 16[sp]
+	st.w	r0, 20[sp]
+	mov	hilo(CSYM(do_fork)), r18   // Where the real work gets done
+	br	save_extra_state_tramp	   // Save state and go there
 #else
 	// fork almost works, enough to trick you into looking elsewhere :-(
 	addi	-EINVAL, r0, r10
@@ -569,18 +589,24 @@
 L_ENTRY(sys_vfork_wrapper):
 	addi	CLONE_VFORK | CLONE_VM | SIGCHLD, r0, r6 // Arg 0: flags
 	ld.w	PTO+PT_GPR(GPR_SP)[sp], r7 // Arg 1: child SP (use parent's)
-	movea	PTO, sp, r8		// Arg 2: parent context
-	mov	hilo(CSYM(fork_common)), r18// Where the real work gets done
-	br	save_extra_state_tramp	// Save state and go there
+	movea	PTO, sp, r8		   // Arg 2: parent context
+	mov	r0, r9			   // Arg 3/4/5: 0
+	st.w	r0, 16[sp]
+	st.w	r0, 20[sp]
+	mov	hilo(CSYM(do_fork)), r18   // Where the real work gets done
+	br	save_extra_state_tramp	   // Save state and go there
 END(sys_vfork_wrapper)
 
 L_ENTRY(sys_clone_wrapper):
-	ld.w	PTO+PT_GPR(GPR_SP)[sp], r19 // parent's stack pointer
-        cmp	r7, r0			// See if child SP arg (arg 1) is 0.
-	cmov	z, r19, r7, r7		// ... and use the parent's if so. 
-	movea	PTO, sp, r8		// Arg 2: parent context
-	mov	hilo(CSYM(fork_common)), r18// Where the real work gets done
-	br	save_extra_state_tramp	// Save state and go there
+	ld.w	PTO+PT_GPR(GPR_SP)[sp], r19// parent's stack pointer
+	cmp	r7, r0			   // See if child SP arg (arg 1) is 0.
+	cmov	z, r19, r7, r7		   // ... and use the parent's if so.
+	movea	PTO, sp, r8		   // Arg 2: parent context
+	mov	r0, r9			   // Arg 3/4/5: 0
+	st.w	r0, 16[sp]
+	st.w	r0, 20[sp]
+	mov	hilo(CSYM(do_fork)), r18   // Where the real work gets done
+	br	save_extra_state_tramp	   // Save state and go there
 END(sys_clone_wrapper)
 
 
@@ -598,8 +624,8 @@
 END(sys_sigsuspend_wrapper)
 L_ENTRY(sys_rt_sigsuspend_wrapper):
 	movea	PTO, sp, r8		// add user context as 3rd arg
-	mov	hilo(CSYM(sys_rt_sigsuspend)), r18	// syscall function
-	jarl	save_extra_state_tramp, lp	// Save state and do it
+	mov	hilo(CSYM(sys_rt_sigsuspend)), r18 // syscall function
+	jarl	save_extra_state_tramp, lp	   // Save state and do it
 	br	restore_extra_regs_and_ret_from_trap
 END(sys_rt_sigsuspend_wrapper)
 
@@ -610,10 +636,9 @@
 	br	restore_extra_regs_and_ret_from_trap
 END(sys_sigreturn_wrapper)
 L_ENTRY(sys_rt_sigreturn_wrapper):
-        SAVE_EXTRA_STATE(TRAP)		// Save state not saved by entry.
 	movea	PTO, sp, r6		// add user context as 1st arg
-	mov	hilo(CSYM(sys_rt_sigreturn)), r18	// syscall function
-	jarl	save_extra_state_tramp, lp	// Save state and do it
+	mov	hilo(CSYM(sys_rt_sigreturn)), r18// syscall function
+	jarl	save_extra_state_tramp, lp	 // Save state and do it
 	br	restore_extra_regs_and_ret_from_trap
 END(sys_rt_sigreturn_wrapper)
 
@@ -637,7 +662,7 @@
  * indirect jump).
  */
 G_ENTRY(irq):
-	SAVE_STATE (IRQ, r0, ENTRY_SP)	// Save registers. 
+	SAVE_STATE (IRQ, r0, ENTRY_SP)	// Save registers.
 
 	stsr	SR_ECR, r6		// Find out which interrupt it was.
 	movea	PTO, sp, r7		// User regs are arg2
@@ -657,7 +682,7 @@
 	RETURN(IRQ)
 END(irq)
 
-	
+
 /*
  * Debug trap / illegal-instruction exception
  *
@@ -668,22 +693,50 @@
  * indirect jump).
  */
 G_ENTRY(dbtrap):
-	SAVE_STATE (DBTRAP, r0, ENTRY_SP)// Save registers. 
+	SAVE_STATE (DBTRAP, r0, ENTRY_SP)// Save registers.
+
+	/* First see if we came from kernel mode; if so, the dbtrap
+	   instruction has a special meaning, to set the DIR (`debug
+	   information register') register.  This is because the DIR register
+	   can _only_ be manipulated/read while in `debug mode,' and debug
+	   mode is only active while we're inside the dbtrap handler.  The
+	   exact functionality is:  { DIR = (DIR | r6) & ~r7; return DIR; }. */
+	ld.b	PTO+PT_KERNEL_MODE[sp], r19
+	cmp	r19, r0
+	bz	1f
+
+	stsr	SR_DIR, r10
+	or	r6, r10
+	not	r7, r7
+	and	r7, r10
+	ldsr	r10, SR_DIR
+	stsr	SR_DIR, r10		// Confirm the value we set
+	st.w	r10, PTO+PT_GPR(10)[sp]	// return it
+	br	3f
+
+1:	ei				// Enable interrupts.
+
+	/* The default signal type we raise.  */
+	mov	SIGTRAP, r6
+
+	/* See if it's a single-step trap.  */
+	stsr	SR_DBPSW, r19
+	andi	0x0800, r19, r19
+	bnz	2f
 
 	/* Look to see if the preceding instruction was is a dbtrap or not,
 	   to decide which signal we should use.  */
 	stsr	SR_DBPC, r19		// PC following trapping insn
 	ld.hu	-2[r19], r19
-	mov	SIGTRAP, r6
 	ori	0xf840, r0, r20		// DBTRAP insn
 	cmp	r19, r20		// Was this trap caused by DBTRAP?
 	cmov	ne, SIGILL, r6, r6	// Choose signal appropriately
 
 	/* Raise the desired signal.  */
-	mov	CURRENT_TASK, r7	// Arg 1: task
-	jarl	CSYM(force_sig), lp	// tail call
+2:	mov	CURRENT_TASK, r7	// Arg 1: task
+	jarl	CSYM(send_sig), lp	// tail call
 
-	RETURN(DBTRAP)
+3:	RETURN(DBTRAP)
 END(dbtrap)
 
 
@@ -725,9 +778,93 @@
 
 
 /*
+ * Invoke the scheduler, called from the trap/irq kernel exit path.
+ *
+ * This basically just calls `schedule', but also arranges for extra
+ * registers to be saved for ptrace'd processes, so ptrace can modify them.
+ */
+L_ENTRY(call_scheduler):
+	ld.w	TASK_PTRACE[CURRENT_TASK], r19	// See if task is ptrace'd
+	cmp	r19, r0
+	bnz	1f			// ... yes, do special stuff
+	jr	CSYM(schedule)		// ... no, just tail-call scheduler
+
+	// Save extra regs for ptrace'd task.  We want to save anything
+	// that would otherwise only be `implicitly' saved by the normal
+	// compiler calling-convention.
+1:	mov	sp, ep			// Setup EP for SAVE_CALL_SAVED_REGS
+	SAVE_CALL_SAVED_REGS		// Save call-saved registers to stack
+	mov	lp, r20			// Save LP in a callee-saved register
+
+	jarl	CSYM(schedule), lp	// Call scheduler
+
+	mov	r20, lp
+	mov	sp, ep			// We can't rely on EP after return
+	RESTORE_CALL_SAVED_REGS		// Restore (possibly modified) regs
+	jmp	[lp]			// Return to the return path
+END(call_scheduler)
+
+
+/*
+ * This is an out-of-line handler for two special cases during the kernel
+ * trap/irq exit sequence:
+ *
+ *  (1) If r18 is non-zero then a signal needs to be handled, which is
+ *	done, and then the caller returned to.
+ *
+ *  (2) If r18 is non-zero then we're returning to a ptraced process, which
+ *	has several special cases -- single-stepping and trap tracing, both
+ *	of which require using the `dbret' instruction to exit the kernel
+ *	instead of the normal `reti' (this is because the CPU not correctly
+ *	single-step after a reti).  In this case, of course, this handler
+ *	never returns to the caller.
+ *
+ * In either case, all registers should have been saved to the current
+ * state-save-frame on the stack, except for callee-saved registers.
+ *
+ * [These two different cases are combined merely to avoid bloating the
+ * macro-inlined code, not because they really make much sense together!]
+ */
+L_ENTRY(handle_signal_or_ptrace_return):
+	cmp	r18, r0			// See if handling a signal
+	bz	1f			// ... nope, go do ptrace return
+
+	// Handle a signal
+	mov	lp, r20			// Save link-pointer
+	mov	r10, r21		// Save return-values (for trap)
+	mov	r11, r22
+
+	movea	PTO, sp, r6		// Arg 1: struct pt_regs *regs
+	mov	r0, r7			// Arg 2: sigset_t *oldset
+	jarl	CSYM(do_signal), lp	// Handle the signal
+	di				// sig handling enables interrupts
+
+	mov	r20, lp			// Restore link-pointer
+	mov	r21, r10		// Restore return-values (for trap)
+	mov	r22, r11
+	ld.w	TASK_PTRACE[CURRENT_TASK], r19  // check ptrace flags too
+	cmp	r19, r0
+	bnz	1f			// ... some set, so look more
+2:	jmp	[lp]			// ... none set, so return normally
+
+	// ptrace return
+1:	ld.w	PTO+PT_PSW[sp], r19	// Look at user-processes's flags
+	andi	0x0800, r19, r19	// See if single-step flag is set
+	bz	2b			// ... nope, return normally
+
+	// Return as if from a dbtrap insn
+	st.b	r0, KM			// Now officially in user state.
+	POP_STATE(DBTRAP)		// Restore regs
+	st.w	sp, KSP			// Save the kernel stack pointer.
+	ld.w	PT_GPR(GPR_SP)-PT_SIZE[sp], sp // Restore user stack pointer.
+	DBTRAP_RET			// Return from the trap/interrupt.
+END(handle_signal_or_ptrace_return)
+
+
+/*
  * This is where we switch between two threads.  The arguments are:
  *   r6 -- pointer to the struct thread for the `current' process
- *   r7 -- pointer to the struct thread for the `new' process.  
+ *   r7 -- pointer to the struct thread for the `new' process.
  * when this function returns, it will return to the new thread.
  */
 C_ENTRY(switch_thread):
@@ -754,8 +891,8 @@
 
 	.align 4
 C_DATA(trap_table):
-	.long bad_trap_wrapper		// trap 0, doesn't use trap table. 
-	.long syscall_long		// trap 1, `long' syscall. 
+	.long bad_trap_wrapper		// trap 0, doesn't use trap table.
+	.long syscall_long		// trap 1, `long' syscall.
 	.long bad_trap_wrapper
 	.long bad_trap_wrapper
 	.long bad_trap_wrapper
@@ -774,7 +911,7 @@
 
 
 	.section .rodata
-	
+
 	.align 4
 C_DATA(sys_call_table):
 	.long CSYM(sys_restart_syscall)	// 0
@@ -835,7 +972,7 @@
 	.long CSYM(sys_fcntl)		// 55
 	.long CSYM(sys_ni_syscall)	// was: mpx
 	.long CSYM(sys_setpgid)
-	.long CSYM(sys_ni_syscall) 	// was: ulimit
+	.long CSYM(sys_ni_syscall)	// was: ulimit
 	.long CSYM(sys_ni_syscall)
 	.long CSYM(sys_umask)		// 60
 	.long CSYM(sys_chroot)
@@ -875,7 +1012,7 @@
 	.long CSYM(sys_fchown)		// 95
 	.long CSYM(sys_getpriority)
 	.long CSYM(sys_setpriority)
-	.long CSYM(sys_ni_syscall) 	// was: profil
+	.long CSYM(sys_ni_syscall)	// was: profil
 	.long CSYM(sys_statfs)
 	.long CSYM(sys_fstatfs)		// 100
 	.long CSYM(sys_ni_syscall)	// i386: ioperm
@@ -900,7 +1037,7 @@
 	.long sys_clone_wrapper		// 120
 	.long CSYM(sys_setdomainname)
 	.long CSYM(sys_newuname)
-	.long CSYM(sys_ni_syscall)	// i386: modify_ldt, m68k: cacheflush 
+	.long CSYM(sys_ni_syscall)	// i386: modify_ldt, m68k: cacheflush
 	.long CSYM(sys_adjtimex)
 	.long CSYM(sys_ni_syscall)	// 125 - sys_mprotect
 	.long CSYM(sys_sigprocmask)
@@ -937,7 +1074,7 @@
 	.long CSYM(sys_sched_getscheduler)
 	.long CSYM(sys_sched_yield)
 	.long CSYM(sys_sched_get_priority_max)
-	.long CSYM(sys_sched_get_priority_min)  // 160
+	.long CSYM(sys_sched_get_priority_min)	// 160
 	.long CSYM(sys_sched_rr_get_interval)
 	.long CSYM(sys_nanosleep)
 	.long CSYM(sys_ni_syscall)	// sys_mremap
diff -urN linux-2.5.70-bk1/arch/v850/kernel/head.S linux-2.5.70-bk2/arch/v850/kernel/head.S
--- linux-2.5.70-bk1/arch/v850/kernel/head.S	2003-05-26 18:00:23.000000000 -0700
+++ linux-2.5.70-bk2/arch/v850/kernel/head.S	2003-05-28 04:37:02.000000000 -0700
@@ -39,7 +39,7 @@
 	cmp	r19, r20
 	bne	1f			// Guard was not active
 
-	// If we get here, the reset guard was active.	Load up some
+	// If we get here, the reset guard was active.  Load up some
 	// interesting values as arguments, and jump to the handler.
 	st.w	r0, RESET_GUARD		// Allow further resets to succeed
 	mov	lp, r6			// Arg 0: return address
@@ -53,7 +53,7 @@
 
 1:	st.w	r20, RESET_GUARD	// Turn on reset guard
 #endif /* CONFIG_RESET_GUARD */
-  
+
 	// Setup a temporary stack for doing pre-initialization function calls.
 	// 
 	// We can't use the initial kernel stack, because (1) it may be
diff -urN linux-2.5.70-bk1/arch/v850/kernel/irq.c linux-2.5.70-bk2/arch/v850/kernel/irq.c
--- linux-2.5.70-bk1/arch/v850/kernel/irq.c	2003-05-26 18:00:46.000000000 -0700
+++ linux-2.5.70-bk2/arch/v850/kernel/irq.c	2003-05-28 04:37:02.000000000 -0700
@@ -1,7 +1,7 @@
 /*
  * arch/v850/kernel/irq.c -- High-level interrupt handling
  *
- *  Copyright (C) 2001,02,03  NEC Corporation
+ *  Copyright (C) 2001,02,03  NEC Electronics Corporation
  *  Copyright (C) 2001,02,03  Miles Bader <miles@gnu.org>
  *  Copyright (C) 1994-2000  Ralf Baechle
  *  Copyright (C) 1992  Linus Torvalds
@@ -35,7 +35,7 @@
  * Special irq handlers.
  */
 
-void no_action(int cpl, void *dev_id, struct pt_regs *regs) { }
+irqreturn_t no_action(int cpl, void *dev_id, struct pt_regs *regs) { }
 
 /*
  * Generic no controller code
@@ -352,7 +352,7 @@
  */
  
 int request_irq(unsigned int irq, 
-		void (*handler)(int, void *, struct pt_regs *),
+		irqreturn_t (*handler)(int, void *, struct pt_regs *),
 		unsigned long irqflags, 
 		const char * devname,
 		void *dev_id)
diff -urN linux-2.5.70-bk1/arch/v850/kernel/ma.c linux-2.5.70-bk2/arch/v850/kernel/ma.c
--- linux-2.5.70-bk1/arch/v850/kernel/ma.c	2003-05-26 18:00:24.000000000 -0700
+++ linux-2.5.70-bk2/arch/v850/kernel/ma.c	2003-05-28 04:37:02.000000000 -0700
@@ -1,8 +1,8 @@
 /*
  * arch/v850/kernel/ma.c -- V850E/MA series of cpu chips
  *
- *  Copyright (C) 2001,02  NEC Corporation
- *  Copyright (C) 2001,02  Miles Bader <miles@gnu.org>
+ *  Copyright (C) 2001,02,03  NEC Electronics Corporation
+ *  Copyright (C) 2001,02,03  Miles Bader <miles@gnu.org>
  *
  * This file is subject to the terms and conditions of the GNU General
  * Public License.  See the file COPYING in the main directory of this
diff -urN linux-2.5.70-bk1/arch/v850/kernel/mach.h linux-2.5.70-bk2/arch/v850/kernel/mach.h
--- linux-2.5.70-bk1/arch/v850/kernel/mach.h	2003-05-26 18:01:00.000000000 -0700
+++ linux-2.5.70-bk2/arch/v850/kernel/mach.h	2003-05-28 04:37:02.000000000 -0700
@@ -1,8 +1,8 @@
 /*
  * arch/v850/kernel/mach.h -- Machine-dependent functions used by v850 port
  *
- *  Copyright (C) 2001,02  NEC Corporation
- *  Copyright (C) 2001,02  Miles Bader <miles@gnu.org>
+ *  Copyright (C) 2001,02,03  NEC Electronics Corporation
+ *  Copyright (C) 2001,02,03  Miles Bader <miles@gnu.org>
  *
  * This file is subject to the terms and conditions of the GNU General
  * Public License.  See the file COPYING in the main directory of this
diff -urN linux-2.5.70-bk1/arch/v850/kernel/process.c linux-2.5.70-bk2/arch/v850/kernel/process.c
--- linux-2.5.70-bk1/arch/v850/kernel/process.c	2003-05-26 18:00:24.000000000 -0700
+++ linux-2.5.70-bk2/arch/v850/kernel/process.c	2003-05-28 04:37:02.000000000 -0700
@@ -1,7 +1,7 @@
 /*
  * arch/v850/kernel/process.c -- Arch-dependent process handling
  *
- *  Copyright (C) 2001,02,03  NEC Corporation
+ *  Copyright (C) 2001,02,03  NEC Electronics Corporation
  *  Copyright (C) 2001,02,03  Miles Bader <miles@gnu.org>
  *
  * This file is subject to the terms and conditions of the GNU General
@@ -200,14 +200,6 @@
 	return error;
 }
 
-/* This is the common part of the various fork-like system calls (which
-   are in entry.S).  */
-int fork_common (int flags, unsigned long new_sp, struct pt_regs *regs)
-{
-	struct task_struct *p = do_fork (flags, new_sp, regs, 0, 0, 0);
-	return IS_ERR (p) ? PTR_ERR (p) : p->pid;
-}
-
 
 /*
  * These bracket the sleeping functions..
diff -urN linux-2.5.70-bk1/arch/v850/kernel/ptrace.c linux-2.5.70-bk2/arch/v850/kernel/ptrace.c
--- linux-2.5.70-bk1/arch/v850/kernel/ptrace.c	2003-05-26 18:00:40.000000000 -0700
+++ linux-2.5.70-bk2/arch/v850/kernel/ptrace.c	2003-05-28 04:37:02.000000000 -0700
@@ -1,8 +1,8 @@
 /*
  * arch/v850/kernel/ptrace.c -- `ptrace' system call
  *
- *  Copyright (C) 2002  NEC Corporation
- *  Copyright (C) 2002  Miles Bader <miles@gnu.org>
+ *  Copyright (C) 2002,03  NEC Electronics Corporation
+ *  Copyright (C) 2002,03  Miles Bader <miles@gnu.org>
  *
  * Derived from arch/mips/kernel/ptrace.c:
  *
@@ -29,6 +29,89 @@
 #include <asm/processor.h>
 #include <asm/uaccess.h>
 
+/* Returns the address where the register at REG_OFFS in P is stashed away.  */
+static v850_reg_t *reg_save_addr (unsigned reg_offs, struct task_struct *t)
+{
+	struct pt_regs *regs;
+
+	/* Three basic cases:
+
+	   (1) A register normally saved before calling the scheduler, is
+	       available in the kernel entry pt_regs structure at the top
+	       of the kernel stack.  The kernel trap/irq exit path takes
+	       care to save/restore almost all registers for ptrace'd
+	       processes.
+
+	   (2) A call-clobbered register, where the process P entered the
+	       kernel via [syscall] trap, is not stored anywhere; that's
+	       OK, because such registers are not expected to be preserved
+	       when the trap returns anyway (so we don't actually bother to
+	       test for this case).
+
+	   (3) A few registers not used at all by the kernel, and so
+	       normally never saved except by context-switches, are in the
+	       context switch state.  */
+
+	if (reg_offs == PT_CTPC || reg_offs == PT_CTPSW || reg_offs == PT_CTBP)
+		/* Register saved during context switch.  */
+		regs = thread_saved_regs (t);
+	else
+		/* Register saved during kernel entry (or not available).  */
+		regs = task_regs (t);
+
+	return (v850_reg_t *)((char *)regs + reg_offs);
+}
+
+/* Set the bits SET and clear the bits CLEAR in the v850e DIR
+   (`debug information register').  Returns the new value of DIR.  */
+static inline v850_reg_t set_dir (v850_reg_t set, v850_reg_t clear)
+{
+	register v850_reg_t rval asm ("r10");
+	register v850_reg_t arg0 asm ("r6") = set;
+	register v850_reg_t arg1 asm ("r7") = clear;
+
+	/* The dbtrap handler has exactly this functionality when called
+	   from kernel mode.  0xf840 is a `dbtrap' insn.  */
+	asm (".short 0xf840" : "=r" (rval) : "r" (arg0), "r" (arg1));
+
+	return rval;
+}
+
+/* Makes sure hardware single-stepping is (globally) enabled.
+   Returns true if successful.  */
+static inline int enable_single_stepping (void)
+{
+	static int enabled = 0;	/* Remember whether we already did it.  */
+	if (! enabled) {
+		/* Turn on the SE (`single-step enable') bit, 0x100, in the
+		   DIR (`debug information register').  This may fail if a
+		   processor doesn't support it or something.  We also try
+		   to clear bit 0x40 (`INI'), which is necessary to use the
+		   debug stuff on the v850e2; on the v850e, clearing 0x40
+		   shouldn't cause any problem.  */
+		v850_reg_t dir = set_dir (0x100, 0x40);
+		/* Make sure it really got set.  */
+		if (dir & 0x100)
+			enabled = 1;
+	}
+	return enabled;
+}
+
+/* Try to set CHILD's single-step flag to VAL.  Returns true if successful.  */
+static int set_single_step (struct task_struct *t, int val)
+{
+	v850_reg_t *psw_addr = reg_save_addr(PT_PSW, t);
+	if (val) {
+		/* Make sure single-stepping is enabled.  */
+		if (! enable_single_stepping ())
+			return 0;
+		/* Set T's single-step flag.  */
+		*psw_addr |= 0x800;
+	} else
+		*psw_addr &= ~0x800;
+	return 1;
+}
+
 int sys_ptrace(long request, long pid, long addr, long data)
 {
 	struct task_struct *child;
@@ -36,12 +119,6 @@
 
 	lock_kernel();
 
-#if 0
-	printk("ptrace(r=%d,pid=%d,addr=%08lx,data=%08lx)\n",
-	       (int) request, (int) pid, (unsigned long) addr,
-	       (unsigned long) data);
-#endif
-
 	if (request == PTRACE_TRACEME) {
 		/* are we already being traced? */
 		if (current->ptrace & PT_PTRACED) {
@@ -81,31 +158,15 @@
 		goto out_tsk;
 
 	switch (request) {
-	case PTRACE_PEEKTEXT: /* read word at location addr. */ 
-	case PTRACE_PEEKDATA:{
-		unsigned long tmp;
-		int copied;
+		unsigned long val, copied;
 
-		copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0);
+	case PTRACE_PEEKTEXT: /* read word at location addr. */
+	case PTRACE_PEEKDATA:
+		copied = access_process_vm(child, addr, &val, sizeof(val), 0);
 		rval = -EIO;
-		if (copied != sizeof(tmp))
+		if (copied != sizeof(val))
 			break;
-		rval = put_user(tmp,(unsigned long *) data);
-
-		goto out;
-		}
-
-	/* Read the word at location addr in the USER area.  */
-	case PTRACE_PEEKUSR: 
-		if (addr >= 0 && addr < PT_SIZE && (addr & 0x3) == 0) {
-			struct pt_regs *regs = task_regs (child);
-			unsigned long val =
-				*(unsigned long *)((char *)regs + addr);
-			rval = put_user (val, (unsigned long *)data);
-		} else {
-			rval = 0;
-			rval = -EIO;			
-		}
+		rval = put_user(val, (unsigned long *)data);
 		goto out;
 
 	case PTRACE_POKETEXT: /* write the word at location addr. */
@@ -117,35 +178,62 @@
 		rval = -EIO;
 		goto out;
 
+	/* Read/write the word at location ADDR in the registers.  */
+	case PTRACE_PEEKUSR:
 	case PTRACE_POKEUSR:
-		if (addr >= 0 && addr < PT_SIZE && (addr & 0x3) == 0) {
-			struct pt_regs *regs = task_regs (child);
-			unsigned long *loc =
-				(unsigned long *)((char *)regs + addr);
-			*loc = data;
-		} else {
-			rval = 0;
-			rval = -EIO;			
-		}
+		rval = 0;
+		if (addr >= PT_SIZE && request == PTRACE_PEEKUSR) {
+			/* Special requests that don't actually correspond
+			   to offsets in struct pt_regs.  */
+			if (addr == PT_TEXT_ADDR)
+				val = child->mm->start_code;
+			else if (addr == PT_DATA_ADDR)
+				val = child->mm->start_data;
+			else if (addr == PT_TEXT_LEN)
+				val = child->mm->end_code
+					- child->mm->start_code;
+			else
+				rval = -EIO;
+		} else if (addr >= 0 && addr < PT_SIZE && (addr & 0x3) == 0) {
+			v850_reg_t *reg_addr = reg_save_addr(addr, child);
+			if (request == PTRACE_PEEKUSR)
+				val = *reg_addr;
+			else
+				*reg_addr = data;
+		} else
+			rval = -EIO;
+
+		if (rval == 0 && request == PTRACE_PEEKUSR)
+			rval = put_user (val, (unsigned long *)data);
 		goto out;
 
-	case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */
-	case PTRACE_CONT: /* rvaltart after signal. */
+	/* Continue and stop at next (return from) syscall */
+	case PTRACE_SYSCALL:
+	/* Restart after a signal.  */
+	case PTRACE_CONT:
+	/* Execute a single instruction. */
+	case PTRACE_SINGLESTEP:
 		rval = -EIO;
 		if ((unsigned long) data > _NSIG)
 			break;
+
+		/* Turn CHILD's single-step flag on or off.  */
+		if (! set_single_step (child, request == PTRACE_SINGLESTEP))
+			break;
+
 		if (request == PTRACE_SYSCALL)
 			set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
 		else
 			clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
+
 		child->exit_code = data;
 		wake_up_process(child);
 		rval = 0;
 		break;
 
 	/*
-	 * make the child exit.  Best I can do is send it a sigkill. 
-	 * perhaps it should be put in the status that it wants to 
+	 * make the child exit.  Best I can do is send it a sigkill.
+	 * perhaps it should be put in the status that it wants to
 	 * exit.
 	 */
 	case PTRACE_KILL:
@@ -157,6 +245,7 @@
 		break;
 
 	case PTRACE_DETACH: /* detach a process that was attached. */
+		set_single_step (child, 0);  /* Clear single-step flag */
 		rval = ptrace_detach(child, data);
 		break;
 
@@ -181,7 +270,7 @@
 	/* The 0x80 provides a way for the tracing parent to distinguish
 	   between a syscall stop and SIGTRAP delivery */
 	current->exit_code = SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
-	                                ? 0x80 : 0);
+					? 0x80 : 0);
 	current->state = TASK_STOPPED;
 	notify_parent(current, SIGCHLD);
 	schedule();
diff -urN linux-2.5.70-bk1/arch/v850/kernel/rte_cb_leds.c linux-2.5.70-bk2/arch/v850/kernel/rte_cb_leds.c
--- linux-2.5.70-bk1/arch/v850/kernel/rte_cb_leds.c	2003-05-26 18:00:23.000000000 -0700
+++ linux-2.5.70-bk2/arch/v850/kernel/rte_cb_leds.c	2003-05-28 04:37:02.000000000 -0700
@@ -1,8 +1,8 @@
 /*
  * include/asm-v850/rte_cb_leds.c -- Midas lab RTE-CB board LED device support
  *
- *  Copyright (C) 2002  NEC Corporation
- *  Copyright (C) 2002  Miles Bader <miles@gnu.org>
+ *  Copyright (C) 2002,03  NEC Electronics Corporation
+ *  Copyright (C) 2002,03  Miles Bader <miles@gnu.org>
  *
  * This file is subject to the terms and conditions of the GNU General
  * Public License.  See the file COPYING in the main directory of this
@@ -14,6 +14,7 @@
 #include <linux/config.h>
 #include <linux/init.h>
 #include <linux/spinlock.h>
+#include <linux/fs.h>
 #include <linux/miscdevice.h>
 
 #include <asm/uaccess.h>
diff -urN linux-2.5.70-bk1/arch/v850/kernel/rte_cb_multi.c linux-2.5.70-bk2/arch/v850/kernel/rte_cb_multi.c
--- linux-2.5.70-bk1/arch/v850/kernel/rte_cb_multi.c	2003-05-26 18:00:28.000000000 -0700
+++ linux-2.5.70-bk2/arch/v850/kernel/rte_cb_multi.c	2003-05-28 04:37:02.000000000 -0700
@@ -2,7 +2,7 @@
  * include/asm-v850/rte_multi.c -- Support for Multi debugger monitor ROM
  * 	on Midas lab RTE-CB series of evaluation boards
  *
- *  Copyright (C) 2001,02,03  NEC Corporation
+ *  Copyright (C) 2001,02,03  NEC Electronics Corporation
  *  Copyright (C) 2001,02,03  Miles Bader <miles@gnu.org>
  *
  * This file is subject to the terms and conditions of the GNU General
diff -urN linux-2.5.70-bk1/arch/v850/kernel/rte_ma1_cb.c linux-2.5.70-bk2/arch/v850/kernel/rte_ma1_cb.c
--- linux-2.5.70-bk1/arch/v850/kernel/rte_ma1_cb.c	2003-05-26 18:00:46.000000000 -0700
+++ linux-2.5.70-bk2/arch/v850/kernel/rte_ma1_cb.c	2003-05-28 04:37:02.000000000 -0700
@@ -1,7 +1,7 @@
 /*
  * arch/v850/kernel/rte_ma1_cb.c -- Midas labs RTE-V850E/MA1-CB board
  *
- *  Copyright (C) 2001,02,03  NEC Corporation
+ *  Copyright (C) 2001,02,03  NEC Electronics Corporation
  *  Copyright (C) 2001,02,03  Miles Bader <miles@gnu.org>
  *
  * This file is subject to the terms and conditions of the GNU General
diff -urN linux-2.5.70-bk1/arch/v850/vmlinux.lds.S linux-2.5.70-bk2/arch/v850/vmlinux.lds.S
--- linux-2.5.70-bk1/arch/v850/vmlinux.lds.S	2003-05-26 18:00:41.000000000 -0700
+++ linux-2.5.70-bk2/arch/v850/vmlinux.lds.S	2003-05-28 04:37:02.000000000 -0700
@@ -105,9 +105,9 @@
 #define RAMK_INIT_CONTENTS_NO_END					      \
 		. = ALIGN (4096) ;					      \
 		__init_start = . ;					      \
-			_sinittext = .;					      \
+			__sinittext = .;				      \
 			*(.init.text)	/* 2.5 convention */		      \
-			_einittext = .;					      \
+			__einittext = .;				      \
 			*(.init.data)					      \
 			*(.text.init)	/* 2.4 convention */		      \
 			*(.data.init)					      \
diff -urN linux-2.5.70-bk1/arch/x86_64/kernel/reboot.c linux-2.5.70-bk2/arch/x86_64/kernel/reboot.c
--- linux-2.5.70-bk1/arch/x86_64/kernel/reboot.c	2003-05-26 18:00:47.000000000 -0700
+++ linux-2.5.70-bk2/arch/x86_64/kernel/reboot.c	2003-05-28 04:37:02.000000000 -0700
@@ -124,7 +124,7 @@
 {
 	int i;
 
-#if CONFIG_SMP
+#ifdef CONFIG_SMP
 	smp_halt(); 
 #endif
 
diff -urN linux-2.5.70-bk1/crypto/sha512.c linux-2.5.70-bk2/crypto/sha512.c
--- linux-2.5.70-bk1/crypto/sha512.c	2003-05-26 18:00:58.000000000 -0700
+++ linux-2.5.70-bk2/crypto/sha512.c	2003-05-28 04:37:02.000000000 -0700
@@ -48,33 +48,33 @@
 }
 
 const u64 sha512_K[80] = {
-        0x428a2f98d728ae22, 0x7137449123ef65cd, 0xb5c0fbcfec4d3b2f,
-        0xe9b5dba58189dbbc, 0x3956c25bf348b538, 0x59f111f1b605d019,
-        0x923f82a4af194f9b, 0xab1c5ed5da6d8118, 0xd807aa98a3030242,
-        0x12835b0145706fbe, 0x243185be4ee4b28c, 0x550c7dc3d5ffb4e2,
-        0x72be5d74f27b896f, 0x80deb1fe3b1696b1, 0x9bdc06a725c71235,
-        0xc19bf174cf692694, 0xe49b69c19ef14ad2, 0xefbe4786384f25e3,
-        0x0fc19dc68b8cd5b5, 0x240ca1cc77ac9c65, 0x2de92c6f592b0275,
-        0x4a7484aa6ea6e483, 0x5cb0a9dcbd41fbd4, 0x76f988da831153b5,
-        0x983e5152ee66dfab, 0xa831c66d2db43210, 0xb00327c898fb213f,
-        0xbf597fc7beef0ee4, 0xc6e00bf33da88fc2, 0xd5a79147930aa725,
-        0x06ca6351e003826f, 0x142929670a0e6e70, 0x27b70a8546d22ffc,
-        0x2e1b21385c26c926, 0x4d2c6dfc5ac42aed, 0x53380d139d95b3df,
-        0x650a73548baf63de, 0x766a0abb3c77b2a8, 0x81c2c92e47edaee6,
-        0x92722c851482353b, 0xa2bfe8a14cf10364, 0xa81a664bbc423001,
-        0xc24b8b70d0f89791, 0xc76c51a30654be30, 0xd192e819d6ef5218,
-        0xd69906245565a910, 0xf40e35855771202a, 0x106aa07032bbd1b8,
-        0x19a4c116b8d2d0c8, 0x1e376c085141ab53, 0x2748774cdf8eeb99,
-        0x34b0bcb5e19b48a8, 0x391c0cb3c5c95a63, 0x4ed8aa4ae3418acb,
-        0x5b9cca4f7763e373, 0x682e6ff3d6b2b8a3, 0x748f82ee5defb2fc,
-        0x78a5636f43172f60, 0x84c87814a1f0ab72, 0x8cc702081a6439ec,
-        0x90befffa23631e28, 0xa4506cebde82bde9, 0xbef9a3f7b2c67915,
-        0xc67178f2e372532b, 0xca273eceea26619c, 0xd186b8c721c0c207,
-        0xeada7dd6cde0eb1e, 0xf57d4f7fee6ed178, 0x06f067aa72176fba,
-        0x0a637dc5a2c898a6, 0x113f9804bef90dae, 0x1b710b35131c471b,
-        0x28db77f523047d84, 0x32caab7b40c72493, 0x3c9ebe0a15c9bebc,
-        0x431d67c49c100d4c, 0x4cc5d4becb3e42b6, 0x597f299cfc657e2a,
-        0x5fcb6fab3ad6faec, 0x6c44198c4a475817,
+        0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL, 0xb5c0fbcfec4d3b2fULL,
+        0xe9b5dba58189dbbcULL, 0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL,
+        0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL, 0xd807aa98a3030242ULL,
+        0x12835b0145706fbeULL, 0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL,
+        0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL, 0x9bdc06a725c71235ULL,
+        0xc19bf174cf692694ULL, 0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL,
+        0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL, 0x2de92c6f592b0275ULL,
+        0x4a7484aa6ea6e483ULL, 0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL,
+        0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL, 0xb00327c898fb213fULL,
+        0xbf597fc7beef0ee4ULL, 0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL,
+        0x06ca6351e003826fULL, 0x142929670a0e6e70ULL, 0x27b70a8546d22ffcULL,
+        0x2e1b21385c26c926ULL, 0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL,
+        0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL, 0x81c2c92e47edaee6ULL,
+        0x92722c851482353bULL, 0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL,
+        0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL, 0xd192e819d6ef5218ULL,
+        0xd69906245565a910ULL, 0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL,
+        0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL, 0x2748774cdf8eeb99ULL,
+        0x34b0bcb5e19b48a8ULL, 0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL,
+        0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL, 0x748f82ee5defb2fcULL,
+        0x78a5636f43172f60ULL, 0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL,
+        0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL, 0xbef9a3f7b2c67915ULL,
+        0xc67178f2e372532bULL, 0xca273eceea26619cULL, 0xd186b8c721c0c207ULL,
+        0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL, 0x06f067aa72176fbaULL,
+        0x0a637dc5a2c898a6ULL, 0x113f9804bef90daeULL, 0x1b710b35131c471bULL,
+        0x28db77f523047d84ULL, 0x32caab7b40c72493ULL, 0x3c9ebe0a15c9bebcULL,
+        0x431d67c49c100d4cULL, 0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL,
+        0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL,
 };
 
 #define e0(x)       (RORu64(x,28) ^ RORu64(x,34) ^ RORu64(x,39))
@@ -83,24 +83,24 @@
 #define s1(x)       (RORu64(x,19) ^ RORu64(x,61) ^ (x >> 6))
 
 /* H* initial state for SHA-512 */
-#define H0         0x6a09e667f3bcc908
-#define H1         0xbb67ae8584caa73b
-#define H2         0x3c6ef372fe94f82b
-#define H3         0xa54ff53a5f1d36f1
-#define H4         0x510e527fade682d1
-#define H5         0x9b05688c2b3e6c1f
-#define H6         0x1f83d9abfb41bd6b
-#define H7         0x5be0cd19137e2179
+#define H0         0x6a09e667f3bcc908ULL
+#define H1         0xbb67ae8584caa73bULL
+#define H2         0x3c6ef372fe94f82bULL
+#define H3         0xa54ff53a5f1d36f1ULL
+#define H4         0x510e527fade682d1ULL
+#define H5         0x9b05688c2b3e6c1fULL
+#define H6         0x1f83d9abfb41bd6bULL
+#define H7         0x5be0cd19137e2179ULL
 
 /* H'* initial state for SHA-384 */
-#define HP0 0xcbbb9d5dc1059ed8
-#define HP1 0x629a292a367cd507
-#define HP2 0x9159015a3070dd17
-#define HP3 0x152fecd8f70e5939
-#define HP4 0x67332667ffc00b31
-#define HP5 0x8eb44a8768581511
-#define HP6 0xdb0c2e0d64f98fa7
-#define HP7 0x47b5481dbefa4fa4
+#define HP0 0xcbbb9d5dc1059ed8ULL
+#define HP1 0x629a292a367cd507ULL
+#define HP2 0x9159015a3070dd17ULL
+#define HP3 0x152fecd8f70e5939ULL
+#define HP4 0x67332667ffc00b31ULL
+#define HP5 0x8eb44a8768581511ULL
+#define HP6 0xdb0c2e0d64f98fa7ULL
+#define HP7 0x47b5481dbefa4fa4ULL
 
 static inline void LOAD_OP(int I, u64 *W, const u8 *input)
 {
diff -urN linux-2.5.70-bk1/drivers/block/ll_rw_blk.c linux-2.5.70-bk2/drivers/block/ll_rw_blk.c
--- linux-2.5.70-bk1/drivers/block/ll_rw_blk.c	2003-05-26 18:00:23.000000000 -0700
+++ linux-2.5.70-bk2/drivers/block/ll_rw_blk.c	2003-05-28 04:37:02.000000000 -0700
@@ -413,11 +413,12 @@
 {
 	struct blk_queue_tag *bqt = q->queue_tags;
 
-	if (unlikely(bqt == NULL || bqt->max_depth < tag))
+	if (unlikely(bqt == NULL || tag >= bqt->real_max_depth))
 		return NULL;
 
 	return bqt->tag_index[tag];
 }
+
 /**
  * blk_queue_free_tags - release tag maintenance info
  * @q:  the request queue for the device
@@ -448,39 +449,28 @@
 	q->queue_flags &= ~(1 << QUEUE_FLAG_QUEUED);
 }
 
-/**
- * blk_queue_init_tags - initialize the queue tag info
- * @q:  the request queue for the device
- * @depth:  the maximum queue depth supported
- **/
-int blk_queue_init_tags(request_queue_t *q, int depth)
+static int init_tag_map(struct blk_queue_tag *tags, int depth)
 {
-	struct blk_queue_tag *tags;
 	int bits, i;
 
 	if (depth > (queue_nr_requests*2)) {
 		depth = (queue_nr_requests*2);
-		printk("blk_queue_init_tags: adjusted depth to %d\n", depth);
+		printk(KERN_ERR "%s: adjusted depth to %d\n", __FUNCTION__, depth);
 	}
 
-	tags = kmalloc(sizeof(struct blk_queue_tag),GFP_ATOMIC);
-	if (!tags)
-		goto fail;
-
 	tags->tag_index = kmalloc(depth * sizeof(struct request *), GFP_ATOMIC);
 	if (!tags->tag_index)
-		goto fail_index;
+		goto fail;
 
 	bits = (depth / BLK_TAGS_PER_LONG) + 1;
 	tags->tag_map = kmalloc(bits * sizeof(unsigned long), GFP_ATOMIC);
 	if (!tags->tag_map)
-		goto fail_map;
+		goto fail;
 
 	memset(tags->tag_index, 0, depth * sizeof(struct request *));
 	memset(tags->tag_map, 0, bits * sizeof(unsigned long));
-	INIT_LIST_HEAD(&tags->busy_list);
-	tags->busy = 0;
 	tags->max_depth = depth;
+	tags->real_max_depth = bits * BITS_PER_LONG;
 
 	/*
 	 * set the upper bits if the depth isn't a multiple of the word size
@@ -488,22 +478,89 @@
 	for (i = depth; i < bits * BLK_TAGS_PER_LONG; i++)
 		__set_bit(i, tags->tag_map);
 
+	return 0;
+fail:
+	kfree(tags->tag_index);
+	return -ENOMEM;
+}
+
+
+/**
+ * blk_queue_init_tags - initialize the queue tag info
+ * @q:  the request queue for the device
+ * @depth:  the maximum queue depth supported
+ **/
+int blk_queue_init_tags(request_queue_t *q, int depth)
+{
+	struct blk_queue_tag *tags;
+
+	tags = kmalloc(sizeof(struct blk_queue_tag),GFP_ATOMIC);
+	if (!tags)
+		goto fail;
+
+	if (init_tag_map(tags, depth))
+		goto fail;
+
+	INIT_LIST_HEAD(&tags->busy_list);
+	tags->busy = 0;
+
 	/*
 	 * assign it, all done
 	 */
 	q->queue_tags = tags;
 	q->queue_flags |= (1 << QUEUE_FLAG_QUEUED);
 	return 0;
-
-fail_map:
-	kfree(tags->tag_index);
-fail_index:
-	kfree(tags);
 fail:
+	kfree(tags);
 	return -ENOMEM;
 }
 
 /**
+ * blk_queue_resize_tags - change the queueing depth
+ * @q:  the request queue for the device
+ * @new_depth: the new max command queueing depth
+ *
+ *  Notes:
+ *    Must be called with the queue lock held.
+ **/
+int blk_queue_resize_tags(request_queue_t *q, int new_depth)
+{
+	struct blk_queue_tag *bqt = q->queue_tags;
+	struct request **tag_index;
+	unsigned long *tag_map;
+	int bits, max_depth;
+
+	if (!bqt)
+		return -ENXIO;
+
+	/*
+	 * don't bother sizing down
+	 */
+	if (new_depth <= bqt->real_max_depth) {
+		bqt->max_depth = new_depth;
+		return 0;
+	}
+
+	/*
+	 * save the old state info, so we can copy it back
+	 */
+	tag_index = bqt->tag_index;
+	tag_map = bqt->tag_map;
+	max_depth = bqt->real_max_depth;
+
+	if (init_tag_map(bqt, new_depth))
+		return -ENOMEM;
+
+	memcpy(bqt->tag_index, tag_index, max_depth * sizeof(struct request *));
+	bits = max_depth / BLK_TAGS_PER_LONG;
+	memcpy(bqt->tag_map, bqt->tag_map, bits * sizeof(unsigned long));
+
+	kfree(tag_index);
+	kfree(tag_map);
+	return 0;
+}
+
+/**
  * blk_queue_end_tag - end tag operations for a request
  * @q:  the request queue for the device
  * @tag:  the tag that has completed
@@ -524,7 +581,7 @@
 
 	BUG_ON(tag == -1);
 
-	if (unlikely(tag >= bqt->max_depth))
+	if (unlikely(tag >= bqt->real_max_depth))
 		return;
 
 	if (unlikely(!__test_and_clear_bit(tag, bqt->tag_map))) {
diff -urN linux-2.5.70-bk1/drivers/ide/ide-cd.c linux-2.5.70-bk2/drivers/ide/ide-cd.c
--- linux-2.5.70-bk1/drivers/ide/ide-cd.c	2003-05-26 18:00:39.000000000 -0700
+++ linux-2.5.70-bk2/drivers/ide/ide-cd.c	2003-05-28 04:37:02.000000000 -0700
@@ -2993,12 +2993,6 @@
 	long block = (long)rq->hard_sector / (hard_sect >> 9);
 	unsigned long blocks = rq->hard_nr_sectors / (hard_sect >> 9);
 
-	BUG_ON(sizeof(rq->hard_sector) > 4 && (rq->hard_sector >> 32));
-
-	if (rq->hard_nr_sectors != rq->nr_sectors) {
-		printk(KERN_ERR "ide-cd: hard_nr_sectors differs from nr_sectors! %lu %lu\n",
-				rq->nr_sectors, rq->hard_nr_sectors);
-	}
 	memset(rq->cmd, 0, sizeof(rq->cmd));
 
 	if (rq_data_dir(rq) == READ)
diff -urN linux-2.5.70-bk1/drivers/net/setup.c linux-2.5.70-bk2/drivers/net/setup.c
--- linux-2.5.70-bk1/drivers/net/setup.c	2003-05-26 18:00:58.000000000 -0700
+++ linux-2.5.70-bk2/drivers/net/setup.c	2003-05-28 04:37:02.000000000 -0700
@@ -15,7 +15,6 @@
 extern int fec_enet_init(void); 
 extern int sdla_setup(void); 
 extern int sdla_c_setup(void); 
-extern int lmc_setup(void);
 
 /*
  *	Devices in this list must do new style probing. That is they must
@@ -45,9 +44,6 @@
 #if defined(CONFIG_FEC_ENET)
         {fec_enet_init, 0},
 #endif
-#if defined(CONFIG_LANMEDIA)
-	{lmc_setup, 0},
-#endif
 	{NULL, 0},
 };
 
diff -urN linux-2.5.70-bk1/drivers/net/sunqe.c linux-2.5.70-bk2/drivers/net/sunqe.c
--- linux-2.5.70-bk1/drivers/net/sunqe.c	2003-05-26 18:00:38.000000000 -0700
+++ linux-2.5.70-bk2/drivers/net/sunqe.c	2003-05-28 04:37:02.000000000 -0700
@@ -124,7 +124,6 @@
 		qb->qe_rxd[i].rx_flags =
 			(RXD_OWN | ((RXD_PKT_SZ) & RXD_LENGTH));
 	}
-	return IRQ_HANDLED;
 }
 
 static int qe_init(struct sunqe *qep, int from_irq)
diff -urN linux-2.5.70-bk1/drivers/net/wan/lmc/lmc_main.c linux-2.5.70-bk2/drivers/net/wan/lmc/lmc_main.c
--- linux-2.5.70-bk1/drivers/net/wan/lmc/lmc_main.c	2003-05-28 04:36:58.000000000 -0700
+++ linux-2.5.70-bk2/drivers/net/wan/lmc/lmc_main.c	2003-05-28 04:37:02.000000000 -0700
@@ -1876,9 +1876,7 @@
     return (struct net_device_stats *) &sc->stats;
 }
 
-#ifdef MODULE
-
-int init_module (void) /*fold00*/
+static int __init init_lmc(void)
 {
     printk ("lmc: module loaded\n");
 
@@ -1889,7 +1887,7 @@
     return 0;
 }
 
-void cleanup_module (void) /*fold00*/
+static void __exit exit_lmc(void)
 {
     struct net_device *dev, *next;
     lmc_softc_t *sc;
@@ -1931,7 +1929,9 @@
     Lmc_root_dev = NULL;
     printk ("lmc module unloaded\n");
 }
-#endif
+
+module_init(init_lmc);
+module_exit(exit_lmc);
 
 unsigned lmc_mii_readreg (lmc_softc_t * const sc, unsigned devaddr, unsigned regno) /*fold00*/
 {
diff -urN linux-2.5.70-bk1/drivers/usb/media/pwc-if.c linux-2.5.70-bk2/drivers/usb/media/pwc-if.c
--- linux-2.5.70-bk1/drivers/usb/media/pwc-if.c	2003-05-26 18:00:45.000000000 -0700
+++ linux-2.5.70-bk2/drivers/usb/media/pwc-if.c	2003-05-28 04:37:02.000000000 -0700
@@ -1804,7 +1804,7 @@
 	}
 	memcpy(vdev, &pwc_template, sizeof(pwc_template));
 	strcpy(vdev->name, name);
-	SET_MODULE_OWNER(vdev);
+	vdev->owner = THIS_MODULE;
 	pdev->vdev = vdev;
 	vdev->priv = pdev;
 
diff -urN linux-2.5.70-bk1/drivers/video/i810/i810.h linux-2.5.70-bk2/drivers/video/i810/i810.h
--- linux-2.5.70-bk1/drivers/video/i810/i810.h	2003-05-26 18:00:57.000000000 -0700
+++ linux-2.5.70-bk2/drivers/video/i810/i810.h	2003-05-28 04:37:02.000000000 -0700
@@ -203,8 +203,8 @@
 #define LOCKUP                      8
 
 struct gtt_data {
-	agp_memory *i810_fb_memory;
-	agp_memory *i810_cursor_memory;
+	struct agp_memory *i810_fb_memory;
+	struct agp_memory *i810_cursor_memory;
 };
 
 struct mode_registers {
diff -urN linux-2.5.70-bk1/drivers/video/i810/i810_main.c linux-2.5.70-bk2/drivers/video/i810/i810_main.c
--- linux-2.5.70-bk1/drivers/video/i810/i810_main.c	2003-05-26 18:00:28.000000000 -0700
+++ linux-2.5.70-bk2/drivers/video/i810/i810_main.c	2003-05-28 04:37:02.000000000 -0700
@@ -1926,11 +1926,6 @@
 #ifndef MODULE
 int __init i810fb_init(void)
 {
-	if (agp_init()) {
-		printk("i810fb_init: cannot initialize agpgart\n");
-		return -ENODEV;
-	}
-
 	if (agp_intel_init()) {
 		printk("i810fb_init: cannot initialize intel agpgart\n");
 		return -ENODEV;
diff -urN linux-2.5.70-bk1/drivers/video/i810/i810_main.h linux-2.5.70-bk2/drivers/video/i810/i810_main.h
--- linux-2.5.70-bk1/drivers/video/i810/i810_main.h	2003-05-26 18:00:41.000000000 -0700
+++ linux-2.5.70-bk2/drivers/video/i810/i810_main.h	2003-05-28 04:37:02.000000000 -0700
@@ -111,7 +111,6 @@
 /* Initialization */
 static void i810fb_release_resource       (struct fb_info *info, struct i810fb_par *par);
 extern int __init agp_intel_init(void);
-extern int __init agp_init(void);
 
 
 /* Video Timings */
diff -urN linux-2.5.70-bk1/drivers/video/sis/sis_main.c linux-2.5.70-bk2/drivers/video/sis/sis_main.c
--- linux-2.5.70-bk1/drivers/video/sis/sis_main.c	2003-05-26 18:00:43.000000000 -0700
+++ linux-2.5.70-bk2/drivers/video/sis/sis_main.c	2003-05-28 04:37:02.000000000 -0700
@@ -2868,8 +2868,8 @@
 	unsigned long *write_port = 0;
 	SIS_CMDTYPE    cmd_type;
 #ifndef AGPOFF
-	agp_kern_info  *agp_info;
-	agp_memory     *agp;
+	struct agp_kern_info  *agp_info;
+	struct agp_memory     *agp;
 	u32            agp_phys;
 #endif
 #endif
@@ -2946,8 +2946,8 @@
 
 #ifndef AGPOFF
 	if (sisfb_queuemode == AGP_CMD_QUEUE) {
-		agp_info = vmalloc(sizeof(agp_kern_info));
-		memset((void*)agp_info, 0x00, sizeof(agp_kern_info));
+		agp_info = vmalloc(sizeof(*agp_info));
+		memset((void*)agp_info, 0x00, sizeof(*agp_info));
 		agp_copy_info(agp_info);
 
 		agp_backend_acquire();
diff -urN linux-2.5.70-bk1/fs/char_dev.c linux-2.5.70-bk2/fs/char_dev.c
--- linux-2.5.70-bk1/fs/char_dev.c	2003-05-26 18:00:28.000000000 -0700
+++ linux-2.5.70-bk2/fs/char_dev.c	2003-05-28 04:37:02.000000000 -0700
@@ -89,6 +89,8 @@
 	if (cd == NULL)
 		return ERR_PTR(-ENOMEM);
 
+	memset(cd, 0, sizeof(struct char_device_struct));
+
 	write_lock_irq(&chrdevs_lock);
 
 	/* temporary */
diff -urN linux-2.5.70-bk1/fs/cifs/cifsfs.c linux-2.5.70-bk2/fs/cifs/cifsfs.c
--- linux-2.5.70-bk1/fs/cifs/cifsfs.c	2003-05-26 18:00:40.000000000 -0700
+++ linux-2.5.70-bk2/fs/cifs/cifsfs.c	2003-05-28 04:37:02.000000000 -0700
@@ -94,13 +94,17 @@
 	sb->s_blocksize_bits = 14;	/* default 2**14 = CIFS_MAX_MSGSIZE */
 	inode = iget(sb, ROOT_I);
 
-	if (!inode)
+	if (!inode) {
+		rc = -ENOMEM;
 		goto out_no_root;
+	}
 
 	sb->s_root = d_alloc_root(inode);
 
-	if (!sb->s_root)
+	if (!sb->s_root) {
+		rc = -ENOMEM;
 		goto out_no_root;
+	}
 
 	return 0;
 
@@ -114,7 +118,7 @@
 		unload_nls(cifs_sb->local_nls);	
 	if(cifs_sb)
 		kfree(cifs_sb);
-	return -EINVAL;
+	return rc;
 }
 
 void
@@ -332,7 +336,7 @@
 	.release = cifs_close,
 	.lock = cifs_lock,
 	.fsync = cifs_fsync,
-    .flush = cifs_flush,
+	.flush = cifs_flush,
 	.mmap  = cifs_file_mmap,
 	.sendfile = generic_file_sendfile,
 };
diff -urN linux-2.5.70-bk1/fs/cifs/connect.c linux-2.5.70-bk2/fs/cifs/connect.c
--- linux-2.5.70-bk1/fs/cifs/connect.c	2003-05-26 18:00:57.000000000 -0700
+++ linux-2.5.70-bk2/fs/cifs/connect.c	2003-05-28 04:37:02.000000000 -0700
@@ -346,6 +346,7 @@
 {
 	char *value;
 	char *data;
+	int  temp_len;
 
 	memset(vol,0,sizeof(struct smb_vol));
 	vol->linux_uid = current->uid;	/* current->euid instead? */
@@ -398,8 +399,9 @@
 				       "CIFS: invalid path to network resource\n");
 				return 1;	/* needs_arg; */
 			}
-			if (strnlen(value, 300) < 300) {
-				vol->UNC = value;
+			if ((temp_len = strnlen(value, 300)) < 300) {
+				vol->UNC = kmalloc(GFP_KERNEL, temp_len);
+				strcpy(vol->UNC,value);
 				if (strncmp(vol->UNC, "//", 2) == 0) {
 					vol->UNC[0] = '\\';
 					vol->UNC[1] = '\\';
@@ -472,8 +474,9 @@
 			printk(KERN_WARNING "CIFS: Missing UNC name for mount target\n");
 			return 1;
 		}
-		if (strnlen(devname, 300) < 300) {
-			vol->UNC = devname;
+		if ((temp_len = strnlen(devname, 300)) < 300) {
+			vol->UNC = kmalloc(GFP_KERNEL, temp_len);
+			strcpy(vol->UNC,devname);
 			if (strncmp(vol->UNC, "//", 2) == 0) {
 				vol->UNC[0] = '\\';
 				vol->UNC[1] = '\\';
@@ -812,6 +815,8 @@
 	cFYI(1, ("Entering cifs_mount. Xid: %d with: %s", xid, mount_data));
 
 	if (parse_mount_options(mount_data, devname, &volume_info)) {
+		if(volume_info.UNC)
+			kfree(volume_info.UNC);
 		FreeXid(xid);
 		return -EINVAL;
 	}
@@ -852,6 +857,8 @@
 			       ("Error connecting to IPv4 socket. Aborting operation"));
 			if(csocket != NULL)
 				sock_release(csocket);
+			if(volume_info.UNC)
+				kfree(volume_info.UNC);
 			FreeXid(xid);
 			return rc;
 		}
@@ -860,6 +867,8 @@
 		if (srvTcp == NULL) {
 			rc = -ENOMEM;
 			sock_release(csocket);
+			if(volume_info.UNC)
+				kfree(volume_info.UNC);
 			FreeXid(xid);
 			return rc;
 		} else {
@@ -943,6 +952,8 @@
 								 "",
 								 cifs_sb->
 								 local_nls);
+					if(volume_info.UNC)
+						kfree(volume_info.UNC);
 					FreeXid(xid);
 					return -ENODEV;
 				} else {
@@ -995,7 +1006,8 @@
 		if (tcon->ses->capabilities & CAP_UNIX)
 			CIFSSMBQFSUnixInfo(xid, tcon, cifs_sb->local_nls);
 	}
-
+	if(volume_info.UNC)
+		kfree(volume_info.UNC);
 	FreeXid(xid);
 	return rc;
 }
@@ -2293,7 +2305,7 @@
 		length = strnlen(bcc_ptr, BCC(smb_buffer_response) - 2);
         /* skip service field (NB: this field is always ASCII) */
 		bcc_ptr += length + 1;	
-        strncpy(tcon->treeName, tree, MAX_TREE_SIZE);
+		strncpy(tcon->treeName, tree, MAX_TREE_SIZE);
 		if (smb_buffer->Flags2 &= SMBFLG2_UNICODE) {
 			length = UniStrnlen((wchar_t *) bcc_ptr, 512);
 			if (((long) bcc_ptr + (2 * length)) -
diff -urN linux-2.5.70-bk1/fs/cifs/netmisc.c linux-2.5.70-bk2/fs/cifs/netmisc.c
--- linux-2.5.70-bk1/fs/cifs/netmisc.c	2003-05-26 18:00:56.000000000 -0700
+++ linux-2.5.70-bk2/fs/cifs/netmisc.c	2003-05-28 04:37:02.000000000 -0700
@@ -46,7 +46,7 @@
 const struct smb_to_posix_error mapping_table_ERRDOS[] = {
 	{ERRbadfunc, -EINVAL},
 	{ERRbadfile, -ENOENT},
-	{ERRbadpath, -ENOENT},
+	{ERRbadpath, -ENOTDIR},
 	{ERRnofids, -EMFILE},
 	{ERRnoaccess, -EACCES},
 	{ERRbadfid, -EBADF},
@@ -63,26 +63,29 @@
 	{ERRnofiles, -ENOENT},
 	{ERRbadshare, -ETXTBSY},
 	{ERRlock, -EACCES},
-	{ERRfilexists, -EINVAL},
+	{ERRunsup, -EINVAL},
+	{ERRnosuchshare,-ENXIO},
+	{ERRfilexists, -EEXIST},
 	{ERRinvparm, -EINVAL},
 	{ERRdiskfull, -ENOSPC},
-	{ERRinvnum, -EINVAL},
+	{ERRinvname, -ENOENT},
 	{ERRdirnotempty, -ENOTEMPTY},
 	{ERRnotlocked, -ENOLCK},
 	{ERRalreadyexists, -EEXIST},
 	{ERRmoredata, -EOVERFLOW},
 	{ErrQuota, -EDQUOT},
 	{ErrNotALink, -ENOLINK},
+	{ERRnetlogonNotStarted,-ENOPROTOOPT},
 	{0, 0}
 };
 
 const struct smb_to_posix_error mapping_table_ERRSRV[] = {
 	{ERRerror, -EIO},
-	{ERRbadpw, -EACCES},
+	{ERRbadpw, -EPERM},
 	{ERRbadtype, -EREMOTE},
 	{ERRaccess, -EACCES},
 	{ERRinvtid, -ENXIO},
-	{ERRinvnetname, -ENOENT},
+	{ERRinvnetname, -ENODEV},
 	{ERRinvdevice, -ENXIO},
 	{ERRqfull, -ENOSPC},
 	{ERRqtoobig, -ENOSPC},
@@ -617,7 +620,7 @@
 	ERRHRD, ERRgeneral, NT_STATUS_EVENTLOG_CANT_START}, {
 	ERRDOS, ERRnoaccess, NT_STATUS_TRUST_FAILURE}, {
 	ERRHRD, ERRgeneral, NT_STATUS_MUTANT_LIMIT_EXCEEDED}, {
-	ERRDOS, 2455, NT_STATUS_NETLOGON_NOT_STARTED}, {
+	ERRDOS, ERRnetlogonNotStarted, NT_STATUS_NETLOGON_NOT_STARTED}, {
 	ERRSRV, 2239, NT_STATUS_ACCOUNT_EXPIRED}, {
 	ERRHRD, ERRgeneral, NT_STATUS_POSSIBLE_DEADLOCK}, {
 	ERRHRD, ERRgeneral, NT_STATUS_NETWORK_CREDENTIAL_CONFLICT}, {
diff -urN linux-2.5.70-bk1/fs/cifs/smberr.h linux-2.5.70-bk2/fs/cifs/smberr.h
--- linux-2.5.70-bk1/fs/cifs/smberr.h	2003-05-26 18:00:42.000000000 -0700
+++ linux-2.5.70-bk2/fs/cifs/smberr.h	2003-05-28 04:37:02.000000000 -0700
@@ -59,7 +59,7 @@
 #define ERRfilexists 80		/* The file named in the request already exists. */
 #define ERRinvparm   87
 #define ERRdiskfull  112
-#define ERRinvnum    123
+#define ERRinvname   123
 #define ERRdirnotempty 145
 #define ERRnotlocked   158
 #define ERRalreadyexists 183
@@ -109,4 +109,5 @@
 #define ERRbadclient      2240
 #define ERRbadLogonTime   2241
 #define ERRpasswordExpired 2242
+#define ERRnetlogonNotStarted 2455
 #define ERRnosupport       0xFFFF
diff -urN linux-2.5.70-bk1/fs/fat/cache.c linux-2.5.70-bk2/fs/fat/cache.c
--- linux-2.5.70-bk1/fs/fat/cache.c	2003-05-26 18:00:47.000000000 -0700
+++ linux-2.5.70-bk2/fs/fat/cache.c	2003-05-28 04:37:02.000000000 -0700
@@ -12,9 +12,6 @@
 #include <linux/msdos_fs.h>
 #include <linux/buffer_head.h>
 
-static struct fat_cache *fat_cache,cache[FAT_CACHE];
-static spinlock_t fat_cache_lock = SPIN_LOCK_UNLOCKED;
-
 int __fat_access(struct super_block *sb, int nr, int new_value)
 {
 	struct msdos_sb_info *sbi = MSDOS_SB(sb);
@@ -133,148 +130,163 @@
 	return next;
 }
 
-void fat_cache_init(void)
+void fat_cache_init(struct super_block *sb)
 {
-	static int initialized;
+	struct msdos_sb_info *sbi = MSDOS_SB(sb);
 	int count;
 
-	spin_lock(&fat_cache_lock);
-	if (initialized) {
-		spin_unlock(&fat_cache_lock);
-		return;
-	}
-	fat_cache = &cache[0];
-	for (count = 0; count < FAT_CACHE; count++) {
-		cache[count].sb = NULL;
-		cache[count].next = count == FAT_CACHE-1 ? NULL :
-		    &cache[count+1];
+	spin_lock_init(&sbi->cache_lock);
+
+	for (count = 0; count < FAT_CACHE_NR - 1; count++) {
+		sbi->cache_array[count].start_cluster = 0;
+		sbi->cache_array[count].next = &sbi->cache_array[count + 1];
 	}
-	initialized = 1;
-	spin_unlock(&fat_cache_lock);
+	sbi->cache_array[count].start_cluster = 0;
+	sbi->cache_array[count].next = NULL;
+	sbi->cache = sbi->cache_array;
 }
 
-
-void fat_cache_lookup(struct inode *inode,int cluster,int *f_clu,int *d_clu)
+void fat_cache_lookup(struct inode *inode, int cluster, int *f_clu, int *d_clu)
 {
+	struct msdos_sb_info *sbi = MSDOS_SB(inode->i_sb);
 	struct fat_cache *walk;
-	int first = MSDOS_I(inode)->i_start;
+	int first;
 
+	BUG_ON(cluster == 0);
+	
+	first = MSDOS_I(inode)->i_start;
 	if (!first)
 		return;
-	spin_lock(&fat_cache_lock);
-	for (walk = fat_cache; walk; walk = walk->next)
-		if (inode->i_sb == walk->sb
-		    && walk->start_cluster == first
+
+	spin_lock(&sbi->cache_lock);
+
+	if (MSDOS_I(inode)->disk_cluster &&
+	    MSDOS_I(inode)->file_cluster <= cluster) {
+		*d_clu = MSDOS_I(inode)->disk_cluster;
+		*f_clu = MSDOS_I(inode)->file_cluster;
+	}
+
+	for (walk = sbi->cache; walk; walk = walk->next) {
+		if (walk->start_cluster == first
 		    && walk->file_cluster <= cluster
 		    && walk->file_cluster > *f_clu) {
 			*d_clu = walk->disk_cluster;
+			*f_clu = walk->file_cluster;
 #ifdef DEBUG
-printk("cache hit: %d (%d)\n",walk->file_cluster,*d_clu);
+			printk("cache hit: %d (%d)\n", *f_clu, *d_clu);
 #endif
-			if ((*f_clu = walk->file_cluster) == cluster) { 
-				spin_unlock(&fat_cache_lock);
-				return;
-			}
+			if (*f_clu == cluster)
+				goto out;
 		}
-	spin_unlock(&fat_cache_lock);
+	}
 #ifdef DEBUG
-printk("cache miss\n");
+	printk("cache miss\n");
 #endif
+out:
+	spin_unlock(&sbi->cache_lock);
 }
 
-
 #ifdef DEBUG
-static void list_cache(void)
+static void list_cache(struct super_block *sb)
 {
+	struct msdos_sb_info *sbi = MSDOS_SB(sb);
 	struct fat_cache *walk;
 
-	for (walk = fat_cache; walk; walk = walk->next) {
-		if (walk->sb)
-			printk("<%s,%d>(%d,%d) ", walk->sb->s_id,
+	for (walk = sbi->cache; walk; walk = walk->next) {
+		if (walk->start_cluster)
+			printk("<%s,%d>(%d,%d) ", sb->s_id,
 			       walk->start_cluster, walk->file_cluster,
 			       walk->disk_cluster);
-		else printk("-- ");
+		else
+			printk("-- ");
 	}
 	printk("\n");
 }
 #endif
 
-
-void fat_cache_add(struct inode *inode,int f_clu,int d_clu)
+/*
+ * Cache invalidation occurs rarely, thus the LRU chain is not updated. It
+ * fixes itself after a while.
+ */
+static void __fat_cache_inval_inode(struct inode *inode)
 {
-	struct fat_cache *walk,*last;
+	struct fat_cache *walk;
 	int first = MSDOS_I(inode)->i_start;
+	MSDOS_I(inode)->file_cluster = MSDOS_I(inode)->disk_cluster = 0;
+	for (walk = MSDOS_SB(inode->i_sb)->cache; walk; walk = walk->next)
+		if (walk->start_cluster == first)
+			walk->start_cluster = 0;
+}
+
+void fat_cache_inval_inode(struct inode *inode)
+{
+	struct msdos_sb_info *sbi = MSDOS_SB(inode->i_sb);
+	spin_lock(&sbi->cache_lock);
+	__fat_cache_inval_inode(inode);
+	spin_unlock(&sbi->cache_lock);
+}
+
+void fat_cache_add(struct inode *inode, int f_clu, int d_clu)
+{
+	struct msdos_sb_info *sbi = MSDOS_SB(inode->i_sb);
+	struct fat_cache *walk, *last;
+	int first, prev_f_clu, prev_d_clu;
+
+	first = MSDOS_I(inode)->i_start;
+	if (!first)
+		return;
 
 	last = NULL;
-	spin_lock(&fat_cache_lock);
-	for (walk = fat_cache; walk->next; walk = (last = walk)->next)
-		if (inode->i_sb == walk->sb
-		    && walk->start_cluster == first
-		    && walk->file_cluster == f_clu) {
+	spin_lock(&sbi->cache_lock);
+
+	if (MSDOS_I(inode)->file_cluster == f_clu)
+		goto out;
+	else {
+		prev_f_clu = MSDOS_I(inode)->file_cluster;
+		prev_d_clu = MSDOS_I(inode)->disk_cluster;
+		MSDOS_I(inode)->file_cluster = f_clu;
+		MSDOS_I(inode)->disk_cluster = d_clu;
+		if (prev_f_clu == 0)
+			goto out;
+		f_clu = prev_f_clu;
+		d_clu = prev_d_clu;
+	}
+	
+	for (walk = sbi->cache; walk->next; walk = (last = walk)->next) {
+		if (walk->start_cluster == first &&
+		    walk->file_cluster == f_clu) {
 			if (walk->disk_cluster != d_clu) {
 				printk(KERN_ERR "FAT: cache corruption"
 				       " (ino %lu)\n", inode->i_ino);
-				spin_unlock(&fat_cache_lock);
-				fat_cache_inval_inode(inode);
-				return;
+				__fat_cache_inval_inode(inode);
+				goto out;
 			}
+			if (last == NULL)
+				goto out;
+
 			/* update LRU */
-			if (last == NULL) {
-				spin_unlock(&fat_cache_lock);
-				return;
-			}
 			last->next = walk->next;
-			walk->next = fat_cache;
-			fat_cache = walk;
+			walk->next = sbi->cache;
+			sbi->cache = walk;
 #ifdef DEBUG
-list_cache();
+			list_cache();
 #endif
-			spin_unlock(&fat_cache_lock);
-			return;
+			goto out;
 		}
-	walk->sb = inode->i_sb;
+	}
 	walk->start_cluster = first;
 	walk->file_cluster = f_clu;
 	walk->disk_cluster = d_clu;
 	last->next = NULL;
-	walk->next = fat_cache;
-	fat_cache = walk;
-	spin_unlock(&fat_cache_lock);
+	walk->next = sbi->cache;
+	sbi->cache = walk;
 #ifdef DEBUG
-list_cache();
+	list_cache();
 #endif
+out:
+	spin_unlock(&sbi->cache_lock);
 }
 
-
-/* Cache invalidation occurs rarely, thus the LRU chain is not updated. It
-   fixes itself after a while. */
-
-void fat_cache_inval_inode(struct inode *inode)
-{
-	struct fat_cache *walk;
-	int first = MSDOS_I(inode)->i_start;
-
-	spin_lock(&fat_cache_lock);
-	for (walk = fat_cache; walk; walk = walk->next)
-		if (walk->sb == inode->i_sb
-		    && walk->start_cluster == first)
-			walk->sb = NULL;
-	spin_unlock(&fat_cache_lock);
-}
-
-
-void fat_cache_inval_dev(struct super_block *sb)
-{
-	struct fat_cache *walk;
-
-	spin_lock(&fat_cache_lock);
-	for (walk = fat_cache; walk; walk = walk->next)
-		if (walk->sb == sb)
-			walk->sb = 0;
-	spin_unlock(&fat_cache_lock);
-}
-
-
 static int fat_get_cluster(struct inode *inode, int cluster)
 {
 	struct super_block *sb = inode->i_sb;
@@ -302,32 +314,36 @@
 	return nr;
 }
 
-int fat_bmap(struct inode *inode, int sector)
+int fat_bmap(struct inode *inode, sector_t sector, sector_t *phys)
 {
 	struct super_block *sb = inode->i_sb;
 	struct msdos_sb_info *sbi = MSDOS_SB(sb);
-	int cluster, offset, last_block;
+	sector_t last_block;
+	int cluster, offset;
 
+	*phys = 0;
 	if ((sbi->fat_bits != 32) &&
 	    (inode->i_ino == MSDOS_ROOT_INO || (S_ISDIR(inode->i_mode) &&
 	     !MSDOS_I(inode)->i_start))) {
-		if (sector >= sbi->dir_entries >> sbi->dir_per_block_bits)
-			return 0;
-		return sector + sbi->dir_start;
+		if (sector < (sbi->dir_entries >> sbi->dir_per_block_bits))
+			*phys = sector + sbi->dir_start;
+		return 0;
 	}
 	last_block = (MSDOS_I(inode)->mmu_private + (sb->s_blocksize - 1))
 		>> sb->s_blocksize_bits;
 	if (sector >= last_block)
 		return 0;
 
-	cluster = sector / sbi->cluster_size;
-	offset  = sector % sbi->cluster_size;
+	cluster = sector >> (sbi->cluster_bits - sb->s_blocksize_bits);
+	offset  = sector & (sbi->cluster_size - 1);
 	cluster = fat_get_cluster(inode, cluster);
 	if (cluster < 0)
 		return cluster;
-	else if (!cluster)
-		return 0;
-	return (cluster - 2) * sbi->cluster_size + sbi->data_start + offset;
+	else if (cluster) {
+		*phys = ((sector_t)cluster - 2) * sbi->cluster_size
+			+ sbi->data_start + offset;
+	}
+	return 0;
 }
 
 
diff -urN linux-2.5.70-bk1/fs/fat/dir.c linux-2.5.70-bk2/fs/fat/dir.c
--- linux-2.5.70-bk1/fs/fat/dir.c	2003-05-26 18:00:21.000000000 -0700
+++ linux-2.5.70-bk2/fs/fat/dir.c	2003-05-28 04:37:02.000000000 -0700
@@ -191,11 +191,11 @@
 	int uni_xlate = MSDOS_SB(sb)->options.unicode_xlate;
 	int utf8 = MSDOS_SB(sb)->options.utf8;
 	unsigned short opt_shortname = MSDOS_SB(sb)->options.shortname;
-	int ino, chl, i, j, last_u, res = 0;
-	loff_t cpos = 0;
+	int chl, i, j, last_u, res = 0;
+	loff_t i_pos, cpos = 0;
 
 	while(1) {
-		if (fat_get_entry(inode,&cpos,&bh,&de,&ino) == -1)
+		if (fat_get_entry(inode,&cpos,&bh,&de,&i_pos) == -1)
 			goto EODir;
 parse_record:
 		long_slots = 0;
@@ -246,7 +246,7 @@
 				if (ds->id & 0x40) {
 					unicode[offset + 13] = 0;
 				}
-				if (fat_get_entry(inode,&cpos,&bh,&de,&ino)<0)
+				if (fat_get_entry(inode,&cpos,&bh,&de,&i_pos)<0)
 					goto EODir;
 				if (slot == 0)
 					break;
@@ -358,14 +358,15 @@
 	int utf8 = MSDOS_SB(sb)->options.utf8;
 	int nocase = MSDOS_SB(sb)->options.nocase;
 	unsigned short opt_shortname = MSDOS_SB(sb)->options.shortname;
-	int ino, inum, chi, chl, i, i2, j, last, last_u, dotoffset = 0;
-	loff_t cpos;
+	unsigned long inum;
+	int chi, chl, i, i2, j, last, last_u, dotoffset = 0;
+	loff_t i_pos, cpos;
 	int ret = 0;
 	
 	lock_kernel();
 
 	cpos = filp->f_pos;
-/* Fake . and .. for the root directory. */
+	/* Fake . and .. for the root directory. */
 	if (inode->i_ino == MSDOS_ROOT_INO) {
 		while (cpos < 2) {
 			if (filldir(dirent, "..", cpos+1, cpos, MSDOS_ROOT_INO, DT_DIR) < 0)
@@ -387,7 +388,7 @@
  	bh = NULL;
 GetNew:
 	long_slots = 0;
-	if (fat_get_entry(inode,&cpos,&bh,&de,&ino) == -1)
+	if (fat_get_entry(inode,&cpos,&bh,&de,&i_pos) == -1)
 		goto EODir;
 	/* Check for long filename entry */
 	if (isvfat) {
@@ -445,7 +446,7 @@
 			if (ds->id & 0x40) {
 				unicode[offset + 13] = 0;
 			}
-			if (fat_get_entry(inode,&cpos,&bh,&de,&ino) == -1)
+			if (fat_get_entry(inode,&cpos,&bh,&de,&i_pos) == -1)
 				goto EODir;
 			if (slot == 0)
 				break;
@@ -533,7 +534,7 @@
 	else if (!memcmp(de->name,MSDOS_DOTDOT,11)) {
 		inum = parent_ino(filp->f_dentry);
 	} else {
-		struct inode *tmp = fat_iget(sb, ino);
+		struct inode *tmp = fat_iget(sb, i_pos);
 		if (tmp) {
 			inum = tmp->i_ino;
 			iput(tmp);
@@ -591,23 +592,23 @@
 	return fat_readdirx(inode, filp, dirent, filldir, 0, 0);
 }
 
-static int vfat_ioctl_fill(
-	void * buf,
-	const char * name,
-	int name_len,
-	loff_t offset,
-	ino_t ino,
-	unsigned int d_type)
+struct fat_ioctl_filldir_callback {
+	struct dirent __user *dirent;
+	int result;
+};
+
+static int fat_ioctl_filldir(void *__buf, const char * name, int name_len,
+			     loff_t offset, ino_t ino, unsigned int d_type)
 {
-	struct dirent *d1 = (struct dirent *)buf;
-	struct dirent *d2 = d1 + 1;
+	struct fat_ioctl_filldir_callback *buf = __buf;
+	struct dirent __user *d1 = buf->dirent;
+	struct dirent __user *d2 = d1 + 1;
 	int len, slen;
 	int dotdir;
 
-	get_user(len, &d1->d_reclen);
-	if (len != 0) {
-		return -1;
-	}
+	if (buf->result)
+		return -EINVAL;
+	buf->result++;
 
 	if ((name_len == 1 && name[0] == '.') ||
 	    (name_len == 2 && name[0] == '.' && name[1] == '.')) {
@@ -618,73 +619,79 @@
 		len = strlen(name);
 	}
 	if (len != name_len) {
-		copy_to_user(d2->d_name, name, len);
-		put_user(0, d2->d_name + len);
-		put_user(len, &d2->d_reclen);
-		put_user(ino, &d2->d_ino);
-		put_user(offset, &d2->d_off);
 		slen = name_len - len;
-		copy_to_user(d1->d_name, name+len+1, slen);
-		put_user(0, d1->d_name+slen);
-		put_user(slen, &d1->d_reclen);
+		if (copy_to_user(d2->d_name, name, len)		||
+		    put_user(0, d2->d_name + len)		||
+		    put_user(len, &d2->d_reclen)		||
+		    put_user(ino, &d2->d_ino)			||
+		    put_user(offset, &d2->d_off)		||
+		    copy_to_user(d1->d_name, name+len+1, slen)	||
+		    put_user(0, d1->d_name+slen)		||
+		    put_user(slen, &d1->d_reclen))
+			goto efault;
 	} else {
-		put_user(0, d2->d_name);
-		put_user(0, &d2->d_reclen);
-		copy_to_user(d1->d_name, name, len);
-		put_user(0, d1->d_name+len);
-		put_user(len, &d1->d_reclen);
+		if (put_user(0, d2->d_name)			||
+		    put_user(0, &d2->d_reclen)			||
+		    copy_to_user(d1->d_name, name, len)		||
+		    put_user(0, d1->d_name+len)			||
+		    put_user(len, &d1->d_reclen))
+			goto efault;
 	}
-
 	return 0;
+efault:
+	buf->result = -EFAULT;
+	return -EFAULT;
 }
 
 int fat_dir_ioctl(struct inode * inode, struct file * filp,
 		  unsigned int cmd, unsigned long arg)
 {
-	int err;
+	struct fat_ioctl_filldir_callback buf;
+	struct dirent __user *d1 = (struct dirent *)arg;
+	int ret, shortname, both;
+
+	if (!access_ok(VERIFY_WRITE, d1, sizeof(struct dirent[2])))
+		return -EFAULT;
 	/*
-	 * We want to provide an interface for Samba to be able
-	 * to get the short filename for a given long filename.
-	 * Samba should use this ioctl instead of readdir() to
-	 * get the information it needs.
+	 * Yes, we don't need this put_user() absolutely. However old
+	 * code didn't return the right value. So, app use this value,
+	 * in order to check whether it is EOF.
 	 */
+	if (put_user(0, &d1->d_reclen))
+		return -EFAULT;
+
+	buf.dirent = d1;
+	buf.result = 0;
 	switch (cmd) {
-	case VFAT_IOCTL_READDIR_BOTH: {
-		struct dirent *d1 = (struct dirent *)arg;
-		err = verify_area(VERIFY_WRITE, d1, sizeof(struct dirent[2]));
-		if (err)
-			return err;
-		put_user(0, &d1->d_reclen);
-		return fat_readdirx(inode,filp,(void *)arg,
-				    vfat_ioctl_fill, 0, 1);
-	}
-	case VFAT_IOCTL_READDIR_SHORT: {
-		struct dirent *d1 = (struct dirent *)arg;
-		put_user(0, &d1->d_reclen);
-		err = verify_area(VERIFY_WRITE, d1, sizeof(struct dirent[2]));
-		if (err)
-			return err;
-		return fat_readdirx(inode,filp,(void *)arg,
-				    vfat_ioctl_fill, 1, 1);
-	}
+	case VFAT_IOCTL_READDIR_SHORT:
+		shortname = 1;
+		both = 1;
+		break;
+	case VFAT_IOCTL_READDIR_BOTH:
+		shortname = 0;
+		both = 1;
+		break;
 	default:
 		return -EINVAL;
 	}
-
-	return 0;
+	ret = fat_readdirx(inode, filp, &buf, fat_ioctl_filldir,
+			   shortname, both);
+	if (ret >= 0)
+		ret = buf.result;
+	return ret;
 }
 
 /***** See if directory is empty */
 int fat_dir_empty(struct inode *dir)
 {
-	loff_t pos;
+	loff_t pos, i_pos;
 	struct buffer_head *bh;
 	struct msdos_dir_entry *de;
-	int ino,result = 0;
+	int result = 0;
 
 	pos = 0;
 	bh = NULL;
-	while (fat_get_entry(dir,&pos,&bh,&de,&ino) > -1) {
+	while (fat_get_entry(dir,&pos,&bh,&de,&i_pos) > -1) {
 		/* Ignore vfat longname entries */
 		if (de->attr == ATTR_EXT)
 			continue;
@@ -703,7 +710,7 @@
 /* This assumes that size of cluster is above the 32*slots */
 
 int fat_add_entries(struct inode *dir,int slots, struct buffer_head **bh,
-		  struct msdos_dir_entry **de, int *ino)
+		  struct msdos_dir_entry **de, loff_t *i_pos)
 {
 	struct super_block *sb = dir->i_sb;
 	loff_t offset, curr;
@@ -713,7 +720,7 @@
 	offset = curr = 0;
 	*bh = NULL;
 	row = 0;
-	while (fat_get_entry(dir, &curr, bh, de, ino) > -1) {
+	while (fat_get_entry(dir, &curr, bh, de, i_pos) > -1) {
 		/* check the maximum size of directory */
 		if (curr >= FAT_MAX_DIR_SIZE) {
 			brelse(*bh);
@@ -735,7 +742,7 @@
 		return PTR_ERR(new_bh);
 	brelse(new_bh);
 	do {
-		fat_get_entry(dir, &curr, bh, de, ino);
+		fat_get_entry(dir, &curr, bh, de, i_pos);
 	} while (++row < slots);
 
 	return offset;
diff -urN linux-2.5.70-bk1/fs/fat/file.c linux-2.5.70-bk2/fs/fat/file.c
--- linux-2.5.70-bk1/fs/fat/file.c	2003-05-26 18:00:26.000000000 -0700
+++ linux-2.5.70-bk2/fs/fat/file.c	2003-05-28 04:37:02.000000000 -0700
@@ -32,11 +32,12 @@
 		  struct buffer_head *bh_result, int create)
 {
 	struct super_block *sb = inode->i_sb;
-	unsigned long phys;
+	sector_t phys;
+	int err;
 
-	phys = fat_bmap(inode, iblock);
-	if (phys < 0)
-		return phys;
+	err = fat_bmap(inode, iblock, &phys);
+	if (err)
+		return err;
 	if (phys) {
 		map_bh(bh_result, sb, phys);
 		return 0;
@@ -55,9 +56,9 @@
 			return error;
 	}
 	MSDOS_I(inode)->mmu_private += sb->s_blocksize;
-	phys = fat_bmap(inode, iblock);
-	if (phys < 0)
-		return phys;
+	err = fat_bmap(inode, iblock, &phys);
+	if (err)
+		return err;
 	if (!phys)
 		BUG();
 	set_buffer_new(bh_result);
diff -urN linux-2.5.70-bk1/fs/fat/inode.c linux-2.5.70-bk2/fs/fat/inode.c
--- linux-2.5.70-bk1/fs/fat/inode.c	2003-05-26 18:00:39.000000000 -0700
+++ linux-2.5.70-bk2/fs/fat/inode.c	2003-05-28 04:37:02.000000000 -0700
@@ -60,17 +60,17 @@
 	}
 }
 
-static inline unsigned long fat_hash(struct super_block *sb, int i_pos)
+static inline unsigned long fat_hash(struct super_block *sb, loff_t i_pos)
 {
 	unsigned long tmp = (unsigned long)i_pos | (unsigned long) sb;
 	tmp = tmp + (tmp >> FAT_HASH_BITS) + (tmp >> FAT_HASH_BITS * 2);
 	return tmp & FAT_HASH_MASK;
 }
 
-void fat_attach(struct inode *inode, int i_pos)
+void fat_attach(struct inode *inode, loff_t i_pos)
 {
 	spin_lock(&fat_inode_lock);
-	MSDOS_I(inode)->i_location = i_pos;
+	MSDOS_I(inode)->i_pos = i_pos;
 	list_add(&MSDOS_I(inode)->i_fat_hash,
 		fat_inode_hashtable + fat_hash(inode->i_sb, i_pos));
 	spin_unlock(&fat_inode_lock);
@@ -79,12 +79,12 @@
 void fat_detach(struct inode *inode)
 {
 	spin_lock(&fat_inode_lock);
-	MSDOS_I(inode)->i_location = 0;
+	MSDOS_I(inode)->i_pos = 0;
 	list_del_init(&MSDOS_I(inode)->i_fat_hash);
 	spin_unlock(&fat_inode_lock);
 }
 
-struct inode *fat_iget(struct super_block *sb, int i_pos)
+struct inode *fat_iget(struct super_block *sb, loff_t i_pos)
 {
 	struct list_head *p = fat_inode_hashtable + fat_hash(sb, i_pos);
 	struct list_head *walk;
@@ -96,7 +96,7 @@
 		i = list_entry(walk, struct msdos_inode_info, i_fat_hash);
 		if (i->vfs_inode.i_sb != sb)
 			continue;
-		if (i->i_location != i_pos)
+		if (i->i_pos != i_pos)
 			continue;
 		inode = igrab(&i->vfs_inode);
 		if (inode)
@@ -109,11 +109,11 @@
 static int fat_fill_inode(struct inode *inode, struct msdos_dir_entry *de);
 
 struct inode *fat_build_inode(struct super_block *sb,
-				struct msdos_dir_entry *de, int ino, int *res)
+			struct msdos_dir_entry *de, loff_t i_pos, int *res)
 {
 	struct inode *inode;
 	*res = 0;
-	inode = fat_iget(sb, ino);
+	inode = fat_iget(sb, i_pos);
 	if (inode)
 		goto out;
 	inode = new_inode(sb);
@@ -128,7 +128,7 @@
 		inode = NULL;
 		goto out;
 	}
-	fat_attach(inode, ino);
+	fat_attach(inode, i_pos);
 	insert_inode_hash(inode);
 out:
 	return inode;
@@ -160,7 +160,6 @@
 	struct msdos_sb_info *sbi = MSDOS_SB(sb);
 
 	fat_clusters_flush(sb);
-	fat_cache_inval_dev(sb);
 	if (sbi->nls_disk) {
 		unload_nls(sbi->nls_disk);
 		sbi->nls_disk = NULL;
@@ -500,7 +499,7 @@
 	struct msdos_sb_info *sbi = MSDOS_SB(sb);
 	int error;
 
-	MSDOS_I(inode)->i_location = 0;
+	MSDOS_I(inode)->i_pos = 0;
 	inode->i_uid = sbi->options.fs_uid;
 	inode->i_gid = sbi->options.fs_gid;
 	inode->i_version++;
@@ -537,9 +536,10 @@
  *  0/  i_ino - for fast, reliable lookup if still in the cache
  *  1/  i_generation - to see if i_ino is still valid
  *          bit 0 == 0 iff directory
- *  2/  i_location - if ino has changed, but still in cache
- *  3/  i_logstart - to semi-verify inode found at i_location
- *  4/  parent->i_logstart - maybe used to hunt for the file on disc
+ *  2/  i_pos - if ino has changed, but still in cache (hi)
+ *  3/  i_pos - if ino has changed, but still in cache (low)
+ *  4/  i_logstart - to semi-verify inode found at i_location
+ *  5/  parent->i_logstart - maybe used to hunt for the file on disc
  *
  */
 
@@ -551,7 +551,7 @@
 
 	if (fhtype != 3)
 		return ERR_PTR(-ESTALE);
-	if (len < 5)
+	if (len < 6)
 		return ERR_PTR(-ESTALE);
 
 	return sb->s_export_op->find_exported_dentry(sb, fh, NULL, acceptable, context);
@@ -570,13 +570,15 @@
 		inode = NULL;
 	}
 	if (!inode) {
-		/* try 2 - see if i_location is in F-d-c
+		loff_t i_pos = ((loff_t)fh[2] << 32) | fh[3];
+
+		/* try 2 - see if i_pos is in F-d-c
 		 * require i_logstart to be the same
 		 * Will fail if you truncate and then re-write
 		 */
 
-		inode = fat_iget(sb, fh[2]);
-		if (inode && MSDOS_I(inode)->i_logstart != fh[3]) {
+		inode = fat_iget(sb, i_pos);
+		if (inode && MSDOS_I(inode)->i_logstart != fh[4]) {
 			iput(inode);
 			inode = NULL;
 		}
@@ -616,15 +618,16 @@
 	int len = *lenp;
 	struct inode *inode =  de->d_inode;
 	
-	if (len < 5)
+	if (len < 6)
 		return 255; /* no room */
-	*lenp = 5;
+	*lenp = 6;
 	fh[0] = inode->i_ino;
 	fh[1] = inode->i_generation;
-	fh[2] = MSDOS_I(inode)->i_location;
-	fh[3] = MSDOS_I(inode)->i_logstart;
+	fh[2] = (__u32)(MSDOS_I(inode)->i_pos >> 32);
+	fh[3] = (__u32)MSDOS_I(inode)->i_pos;
+	fh[4] = MSDOS_I(inode)->i_logstart;
 	spin_lock(&de->d_lock);
-	fh[4] = MSDOS_I(de->d_parent->d_inode)->i_logstart;
+	fh[5] = MSDOS_I(de->d_parent->d_inode)->i_logstart;
 	spin_unlock(&de->d_lock);
 	return 3;
 }
@@ -635,15 +638,15 @@
 	struct msdos_dir_entry *de = NULL;
 	struct dentry *parent = NULL;
 	int res;
-	int ino = 0;
+	loff_t i_pos = 0;
 	struct inode *inode;
 
 	lock_kernel();
-	res = fat_scan(child->d_inode, MSDOS_DOTDOT, &bh, &de, &ino);
+	res = fat_scan(child->d_inode, MSDOS_DOTDOT, &bh, &de, &i_pos);
 
 	if (res < 0)
 		goto out;
-	inode = fat_build_inode(child->d_sb, de, ino, &res);
+	inode = fat_build_inode(child->d_sb, de, i_pos, &res);
 	if (res)
 		goto out;
 	if (!inode)
@@ -762,7 +765,7 @@
 	if (!parse_options(data, isvfat, &debug, &sbi->options))
 		goto out_fail;
 
-	fat_cache_init();
+	fat_cache_init(sb);
 	/* set up enough so that it can read an inode */
 	init_MUTEX(&sbi->fat_lock);
 
@@ -1098,7 +1101,8 @@
 	struct msdos_sb_info *sbi = MSDOS_SB(sb);
 	int error;
 
-	MSDOS_I(inode)->i_location = 0;
+	MSDOS_I(inode)->file_cluster = MSDOS_I(inode)->disk_cluster = 0;
+	MSDOS_I(inode)->i_pos = 0;
 	inode->i_uid = sbi->options.fs_uid;
 	inode->i_gid = sbi->options.fs_gid;
 	inode->i_version++;
@@ -1112,10 +1116,9 @@
 		inode->i_fop = &fat_dir_operations;
 
 		MSDOS_I(inode)->i_start = CF_LE_W(de->start);
-		if (sbi->fat_bits == 32) {
-			MSDOS_I(inode)->i_start |=
-				(CF_LE_W(de->starthi) << 16);
-		}
+		if (sbi->fat_bits == 32)
+			MSDOS_I(inode)->i_start |= (CF_LE_W(de->starthi) << 16);
+
 		MSDOS_I(inode)->i_logstart = MSDOS_I(inode)->i_start;
 		error = fat_calc_dir_size(inode);
 		if (error < 0)
@@ -1131,10 +1134,9 @@
 		    	? S_IRUGO|S_IWUGO : S_IRWXUGO)
 		    & ~sbi->options.fs_fmask) | S_IFREG;
 		MSDOS_I(inode)->i_start = CF_LE_W(de->start);
-		if (sbi->fat_bits == 32) {
-			MSDOS_I(inode)->i_start |=
-				(CF_LE_W(de->starthi) << 16);
-		}
+		if (sbi->fat_bits == 32)
+			MSDOS_I(inode)->i_start |= (CF_LE_W(de->starthi) << 16);
+
 		MSDOS_I(inode)->i_logstart = MSDOS_I(inode)->i_start;
 		inode->i_size = CF_LE_L(de->size);
 	        inode->i_op = &fat_file_inode_operations;
@@ -1168,22 +1170,22 @@
 	struct super_block *sb = inode->i_sb;
 	struct buffer_head *bh;
 	struct msdos_dir_entry *raw_entry;
-	unsigned int i_pos;
+	loff_t i_pos;
 
 retry:
-	i_pos = MSDOS_I(inode)->i_location;
+	i_pos = MSDOS_I(inode)->i_pos;
 	if (inode->i_ino == MSDOS_ROOT_INO || !i_pos) {
 		return;
 	}
 	lock_kernel();
 	if (!(bh = sb_bread(sb, i_pos >> MSDOS_SB(sb)->dir_per_block_bits))) {
-		fat_fs_panic(sb, "unable to read i-node block (ino %lu)",
+		fat_fs_panic(sb, "unable to read i-node block (i_pos %llu)",
 			     i_pos);
 		unlock_kernel();
 		return;
 	}
 	spin_lock(&fat_inode_lock);
-	if (i_pos != MSDOS_I(inode)->i_location) {
+	if (i_pos != MSDOS_I(inode)->i_pos) {
 		spin_unlock(&fat_inode_lock);
 		brelse(bh);
 		unlock_kernel();
diff -urN linux-2.5.70-bk1/fs/fat/misc.c linux-2.5.70-bk2/fs/fat/misc.c
--- linux-2.5.70-bk1/fs/fat/misc.c	2003-05-26 18:00:56.000000000 -0700
+++ linux-2.5.70-bk2/fs/fat/misc.c	2003-05-28 04:37:02.000000000 -0700
@@ -178,9 +178,9 @@
 struct buffer_head *fat_extend_dir(struct inode *inode)
 {
 	struct super_block *sb = inode->i_sb;
-	int nr, sector, last_sector;
 	struct buffer_head *bh, *res = NULL;
-	int cluster_size = MSDOS_SB(sb)->cluster_size;
+	int nr, cluster_size = MSDOS_SB(sb)->cluster_size;
+	sector_t sector, last_sector;
 
 	if (MSDOS_SB(sb)->fat_bits != 32) {
 		if (inode->i_ino == MSDOS_ROOT_INO)
@@ -191,7 +191,7 @@
 	if (nr < 0)
 		return ERR_PTR(nr);
 	
-	sector = MSDOS_SB(sb)->data_start + (nr - 2) * cluster_size;
+	sector = ((sector_t)nr - 2) * cluster_size + MSDOS_SB(sb)->data_start;
 	last_sector = sector + cluster_size;
 	for ( ; sector < last_sector; sector++) {
 		if ((bh = sb_getblk(sb, sector))) {
@@ -289,11 +289,13 @@
  */
 
 int fat__get_entry(struct inode *dir, loff_t *pos,struct buffer_head **bh,
-    struct msdos_dir_entry **de, int *ino)
+		   struct msdos_dir_entry **de, loff_t *i_pos)
 {
 	struct super_block *sb = dir->i_sb;
 	struct msdos_sb_info *sbi = MSDOS_SB(sb);
-	int sector, offset, iblock;
+	sector_t phys, iblock;
+	loff_t offset;
+	int err;
 
 next:
 	offset = *pos;
@@ -302,14 +304,14 @@
 
 	*bh = NULL;
 	iblock = *pos >> sb->s_blocksize_bits;
-	sector = fat_bmap(dir, iblock);
-	if (sector <= 0)
+	err = fat_bmap(dir, iblock, &phys);
+	if (err || !phys)
 		return -1;	/* beyond EOF or error */
 
-	*bh = sb_bread(sb, sector);
+	*bh = sb_bread(sb, phys);
 	if (*bh == NULL) {
-		printk(KERN_ERR "FAT: Directory bread(block %d) failed\n",
-		       sector);
+		printk(KERN_ERR "FAT: Directory bread(block %llu) failed\n",
+		       phys);
 		/* skip this block */
 		*pos = (iblock + 1) << sb->s_blocksize_bits;
 		goto next;
@@ -318,7 +320,7 @@
 	offset &= sb->s_blocksize - 1;
 	*pos += sizeof(struct msdos_dir_entry);
 	*de = (struct msdos_dir_entry *)((*bh)->b_data + offset);
-	*ino = (sector << sbi->dir_per_block_bits) + (offset >> MSDOS_DIR_BITS);
+	*i_pos = ((loff_t)phys << sbi->dir_per_block_bits) + (offset >> MSDOS_DIR_BITS);
 
 	return 0;
 }
@@ -357,7 +359,7 @@
     done = !IS_FREE(data[entry].name) \
       && ( \
            ( \
-             (MSDOS_SB(sb)->fat_bits != 32) ? 0 : (CF_LE_W(data[entry].starthi) << 16) \
+             (sbi->fat_bits != 32) ? 0 : (CF_LE_W(data[entry].starthi) << 16) \
            ) \
            | CF_LE_W(data[entry].start) \
          ) == *number;
@@ -374,35 +376,38 @@
 	    (*number)++; \
     }
 
-static int raw_scan_sector(struct super_block *sb,int sector,const char *name,
-    int *number,int *ino,struct buffer_head **res_bh,
-    struct msdos_dir_entry **res_de)
+static int raw_scan_sector(struct super_block *sb, sector_t sector,
+			   const char *name, int *number, loff_t *i_pos,
+			   struct buffer_head **res_bh,
+			   struct msdos_dir_entry **res_de)
 {
+	struct msdos_sb_info *sbi = MSDOS_SB(sb);
 	struct buffer_head *bh;
 	struct msdos_dir_entry *data;
 	int entry,start,done;
 
-	if (!(bh = sb_bread(sb,sector)))
+	if (!(bh = sb_bread(sb, sector)))
 		return -EIO;
 	data = (struct msdos_dir_entry *) bh->b_data;
-	for (entry = 0; entry < MSDOS_SB(sb)->dir_per_block; entry++) {
+	for (entry = 0; entry < sbi->dir_per_block; entry++) {
 /* RSS_COUNT:  if (data[entry].name == name) done=true else done=false. */
 		if (name) {
 			RSS_NAME
 		} else {
-			if (!ino) RSS_COUNT
+			if (!i_pos) RSS_COUNT
 			else {
 				if (number) RSS_START
 				else RSS_FREE
 			}
 		}
 		if (done) {
-			if (ino)
-				*ino = sector * MSDOS_SB(sb)->dir_per_block + entry;
+			if (i_pos) {
+				*i_pos = ((loff_t)sector << sbi->dir_per_block_bits) + entry;
+			}
 			start = CF_LE_W(data[entry].start);
-			if (MSDOS_SB(sb)->fat_bits == 32) {
+			if (sbi->fat_bits == 32)
 				start |= (CF_LE_W(data[entry].starthi) << 16);
-			}
+
 			if (!res_bh)
 				brelse(bh);
 			else {
@@ -422,16 +427,19 @@
  * requested entry is found or the end of the directory is reached.
  */
 
-static int raw_scan_root(struct super_block *sb,const char *name,int *number,int *ino,
-    struct buffer_head **res_bh,struct msdos_dir_entry **res_de)
+static int raw_scan_root(struct super_block *sb, const char *name,
+			 int *number, loff_t *i_pos,
+			 struct buffer_head **res_bh,
+			 struct msdos_dir_entry **res_de)
 {
 	int count,cluster;
 
 	for (count = 0;
 	     count < MSDOS_SB(sb)->dir_entries / MSDOS_SB(sb)->dir_per_block;
 	     count++) {
-		if ((cluster = raw_scan_sector(sb,MSDOS_SB(sb)->dir_start+count,
-					       name,number,ino,res_bh,res_de)) >= 0)
+		cluster = raw_scan_sector(sb, MSDOS_SB(sb)->dir_start + count,
+					  name, number, i_pos, res_bh, res_de);
+		if (cluster >= 0)
 			return cluster;
 	}
 	return -ENOENT;
@@ -443,24 +451,29 @@
  * requested entry is found or the end of the directory is reached.
  */
 
-static int raw_scan_nonroot(struct super_block *sb,int start,const char *name,
-    int *number,int *ino,struct buffer_head **res_bh,struct msdos_dir_entry
-    **res_de)
+static int raw_scan_nonroot(struct super_block *sb, int start, const char *name,
+			    int *number, loff_t *i_pos,
+			    struct buffer_head **res_bh,
+			    struct msdos_dir_entry **res_de)
 {
+	struct msdos_sb_info *sbi = MSDOS_SB(sb);
 	int count, cluster;
 	unsigned long dir_size = 0;
+	sector_t sector;
 
 #ifdef DEBUG
 	printk("raw_scan_nonroot: start=%d\n",start);
 #endif
 	do {
-		for (count = 0; count < MSDOS_SB(sb)->cluster_size; count++) {
-			if ((cluster = raw_scan_sector(sb,(start-2)*
-			    MSDOS_SB(sb)->cluster_size+MSDOS_SB(sb)->data_start+
-			    count,name,number,ino,res_bh,res_de)) >= 0)
+		for (count = 0; count < sbi->cluster_size; count++) {
+			sector = ((sector_t)start - 2) * sbi->cluster_size
+				+ count + sbi->data_start;
+			cluster = raw_scan_sector(sb, sector, name, number,
+						  i_pos, res_bh, res_de);
+			if (cluster >= 0)
 				return cluster;
 		}
-		dir_size += 1 << MSDOS_SB(sb)->cluster_bits;
+		dir_size += 1 << sbi->cluster_bits;
 		if (dir_size > FAT_MAX_DIR_SIZE) {
 			fat_fs_panic(sb, "Directory %d: "
 				     "exceeded the maximum size of directory",
@@ -492,13 +505,13 @@
  */
 
 static int raw_scan(struct super_block *sb, int start, const char *name,
-    int *number, int *ino, struct buffer_head **res_bh,
-    struct msdos_dir_entry **res_de)
+		    loff_t *i_pos, struct buffer_head **res_bh,
+		    struct msdos_dir_entry **res_de)
 {
 	if (start)
-		return raw_scan_nonroot(sb,start,name,number,ino,res_bh,res_de);
+		return raw_scan_nonroot(sb,start,name,NULL,i_pos,res_bh,res_de);
 	else
-		return raw_scan_root(sb,name,number,ino,res_bh,res_de);
+		return raw_scan_root(sb,name,NULL,i_pos,res_bh,res_de);
 }
 
 /*
@@ -507,19 +520,21 @@
  */
 int fat_subdirs(struct inode *dir)
 {
-	int count;
+	struct msdos_sb_info *sbi = MSDOS_SB(dir->i_sb);
+	int number;
 
-	count = 0;
-	if ((dir->i_ino == MSDOS_ROOT_INO) &&
-	    (MSDOS_SB(dir->i_sb)->fat_bits != 32)) {
-		(void) raw_scan_root(dir->i_sb,NULL,&count,NULL,NULL,NULL);
-	} else {
-		if ((dir->i_ino != MSDOS_ROOT_INO) &&
-		    !MSDOS_I(dir)->i_start) return 0; /* in mkdir */
-		else (void) raw_scan_nonroot(dir->i_sb,MSDOS_I(dir)->i_start,
-		    NULL,&count,NULL,NULL,NULL);
+	number = 0;
+	if ((dir->i_ino == MSDOS_ROOT_INO) && (sbi->fat_bits != 32))
+		raw_scan_root(dir->i_sb, NULL, &number, NULL, NULL, NULL);
+	else {
+		if ((dir->i_ino != MSDOS_ROOT_INO) && !MSDOS_I(dir)->i_start)
+			return 0; /* in mkdir */
+		else {
+			raw_scan_nonroot(dir->i_sb, MSDOS_I(dir)->i_start,
+					 NULL, &number, NULL, NULL, NULL);
+		}
 	}
-	return count;
+	return number;
 }
 
 
@@ -528,12 +543,12 @@
  * for an empty directory slot (name is NULL). Returns an error code or zero.
  */
 
-int fat_scan(struct inode *dir,const char *name,struct buffer_head **res_bh,
-    struct msdos_dir_entry **res_de,int *ino)
+int fat_scan(struct inode *dir, const char *name, struct buffer_head **res_bh,
+	     struct msdos_dir_entry **res_de, loff_t *i_pos)
 {
 	int res;
 
-	res = raw_scan(dir->i_sb,MSDOS_I(dir)->i_start,
-		       name, NULL, ino, res_bh, res_de);
-	return res<0 ? res : 0;
+	res = raw_scan(dir->i_sb, MSDOS_I(dir)->i_start, name, i_pos,
+		       res_bh, res_de);
+	return (res < 0) ? res : 0;
 }
diff -urN linux-2.5.70-bk1/fs/msdos/namei.c linux-2.5.70-bk2/fs/msdos/namei.c
--- linux-2.5.70-bk1/fs/msdos/namei.c	2003-05-26 18:01:03.000000000 -0700
+++ linux-2.5.70-bk2/fs/msdos/namei.c	2003-05-28 04:37:02.000000000 -0700
@@ -112,8 +112,9 @@
 }
 
 /***** Locates a directory entry.  Uses unformatted name. */
-static int msdos_find(struct inode *dir,const char *name,int len,
-    struct buffer_head **bh,struct msdos_dir_entry **de,int *ino)
+static int msdos_find(struct inode *dir, const char *name, int len,
+		      struct buffer_head **bh, struct msdos_dir_entry **de,
+		      loff_t *i_pos)
 {
 	int res;
 	char dotsOK;
@@ -123,7 +124,7 @@
 	res = msdos_format_name(name,len, msdos_name,&MSDOS_SB(dir->i_sb)->options);
 	if (res < 0)
 		return -ENOENT;
-	res = fat_scan(dir,msdos_name,bh,de,ino);
+	res = fat_scan(dir, msdos_name, bh, de, i_pos);
 	if (!res && dotsOK) {
 		if (name[0]=='.') {
 			if (!((*de)->attr & ATTR_HIDDEN))
@@ -134,7 +135,6 @@
 		}
 	}
 	return res;
-
 }
 
 /*
@@ -199,19 +199,19 @@
 	struct inode *inode = NULL;
 	struct msdos_dir_entry *de;
 	struct buffer_head *bh = NULL;
-	int ino,res;
+	loff_t i_pos;
+	int res;
 	
 	dentry->d_op = &msdos_dentry_operations;
 
 	lock_kernel();
 	res = msdos_find(dir, dentry->d_name.name, dentry->d_name.len, &bh,
-			&de, &ino);
-
+			 &de, &i_pos);
 	if (res == -ENOENT)
 		goto add;
 	if (res < 0)
 		goto out;
-	inode = fat_build_inode(sb, de, ino, &res);
+	inode = fat_build_inode(sb, de, i_pos, &res);
 	if (res)
 		goto out;
 add:
@@ -231,12 +231,11 @@
 static int msdos_add_entry(struct inode *dir, const char *name,
 			   struct buffer_head **bh,
 			   struct msdos_dir_entry **de,
-			   int *ino,
-			   int is_dir, int is_hid)
+			   loff_t *i_pos, int is_dir, int is_hid)
 {
 	int res;
 
-	res = fat_add_entries(dir, 1, bh, de, ino);
+	res = fat_add_entries(dir, 1, bh, de, i_pos);
 	if (res < 0)
 		return res;
 
@@ -268,7 +267,8 @@
 	struct buffer_head *bh;
 	struct msdos_dir_entry *de;
 	struct inode *inode;
-	int ino,res,is_hid;
+	loff_t i_pos;
+	int res, is_hid;
 	char msdos_name[MSDOS_NAME];
 
 	lock_kernel();
@@ -280,18 +280,18 @@
 	}
 	is_hid = (dentry->d_name.name[0]=='.') && (msdos_name[0]!='.');
 	/* Have to do it due to foo vs. .foo conflicts */
-	if (fat_scan(dir,msdos_name,&bh,&de,&ino) >= 0) {
+	if (fat_scan(dir, msdos_name, &bh, &de, &i_pos) >= 0) {
 		brelse(bh);
 		unlock_kernel();
 		return -EINVAL;
  	}
 	inode = NULL;
-	res = msdos_add_entry(dir, msdos_name, &bh, &de, &ino, 0, is_hid);
+	res = msdos_add_entry(dir, msdos_name, &bh, &de, &i_pos, 0, is_hid);
 	if (res) {
 		unlock_kernel();
 		return res;
 	}
-	inode = fat_build_inode(dir->i_sb, de, ino, &res);
+	inode = fat_build_inode(dir->i_sb, de, i_pos, &res);
 	brelse(bh);
 	if (!inode) {
 		unlock_kernel();
@@ -308,14 +308,15 @@
 int msdos_rmdir(struct inode *dir, struct dentry *dentry)
 {
 	struct inode *inode = dentry->d_inode;
-	int res,ino;
+	loff_t i_pos;
+	int res;
 	struct buffer_head *bh;
 	struct msdos_dir_entry *de;
 
 	bh = NULL;
 	lock_kernel();
 	res = msdos_find(dir, dentry->d_name.name, dentry->d_name.len,
-				&bh, &de, &ino);
+			 &bh, &de, &i_pos);
 	if (res < 0)
 		goto rmdir_done;
 	/*
@@ -351,7 +352,7 @@
 	struct inode *inode;
 	int res,is_hid;
 	char msdos_name[MSDOS_NAME];
-	int ino;
+	loff_t i_pos;
 
 	lock_kernel();
 	res = msdos_format_name(dentry->d_name.name,dentry->d_name.len,
@@ -362,13 +363,13 @@
 	}
 	is_hid = (dentry->d_name.name[0]=='.') && (msdos_name[0]!='.');
 	/* foo vs .foo situation */
-	if (fat_scan(dir,msdos_name,&bh,&de,&ino) >= 0)
+	if (fat_scan(dir, msdos_name, &bh, &de, &i_pos) >= 0)
 		goto out_exist;
 
-	res = msdos_add_entry(dir, msdos_name, &bh, &de, &ino, 1, is_hid);
+	res = msdos_add_entry(dir, msdos_name, &bh, &de, &i_pos, 1, is_hid);
 	if (res)
 		goto out_unlock;
-	inode = fat_build_inode(dir->i_sb, de, ino, &res);
+	inode = fat_build_inode(dir->i_sb, de, i_pos, &res);
 	if (!inode) {
 		brelse(bh);
 		goto out_unlock;
@@ -414,14 +415,15 @@
 int msdos_unlink( struct inode *dir, struct dentry *dentry)
 {
 	struct inode *inode = dentry->d_inode;
-	int res,ino;
+	loff_t i_pos;
+	int res;
 	struct buffer_head *bh;
 	struct msdos_dir_entry *de;
 
 	bh = NULL;
 	lock_kernel();
 	res = msdos_find(dir, dentry->d_name.name, dentry->d_name.len,
-			&bh, &de, &ino);
+			 &bh, &de, &i_pos);
 	if (res < 0)
 		goto unlink_done;
 
@@ -443,12 +445,12 @@
     struct dentry *old_dentry,
     struct inode *new_dir,char *new_name, struct dentry *new_dentry,
     struct buffer_head *old_bh,
-    struct msdos_dir_entry *old_de, int old_ino, int is_hid)
+    struct msdos_dir_entry *old_de, loff_t old_i_pos, int is_hid)
 {
 	struct buffer_head *new_bh=NULL,*dotdot_bh=NULL;
 	struct msdos_dir_entry *new_de,*dotdot_de;
 	struct inode *old_inode,*new_inode;
-	int new_ino,dotdot_ino;
+	loff_t new_i_pos, dotdot_i_pos;
 	int error;
 	int is_dir;
 
@@ -456,7 +458,8 @@
 	new_inode = new_dentry->d_inode;
 	is_dir = S_ISDIR(old_inode->i_mode);
 
-	if (fat_scan(new_dir,new_name,&new_bh,&new_de,&new_ino)>=0 &&!new_inode)
+	if (fat_scan(new_dir, new_name, &new_bh, &new_de, &new_i_pos) >= 0
+	    && !new_inode)
 		goto degenerate_case;
 	if (is_dir) {
 		if (new_inode) {
@@ -465,7 +468,7 @@
 				goto out;
 		}
 		error = fat_scan(old_inode, MSDOS_DOTDOT, &dotdot_bh,
-				&dotdot_de, &dotdot_ino);
+				&dotdot_de, &dotdot_i_pos);
 		if (error < 0) {
 			printk(KERN_WARNING
 				"MSDOS: %s/%s, get dotdot failed, ret=%d\n",
@@ -476,7 +479,7 @@
 	}
 	if (!new_bh) {
 		error = msdos_add_entry(new_dir, new_name, &new_bh, &new_de,
-					&new_ino, is_dir, is_hid);
+					&new_i_pos, is_dir, is_hid);
 		if (error)
 			goto out;
 	}
@@ -489,7 +492,7 @@
 	old_de->name[0] = DELETED_FLAG;
 	mark_buffer_dirty(old_bh);
 	fat_detach(old_inode);
-	fat_attach(old_inode, new_ino);
+	fat_attach(old_inode, new_i_pos);
 	if (is_hid)
 		MSDOS_I(old_inode)->i_attrs |= ATTR_HIDDEN;
 	else
@@ -544,8 +547,8 @@
 {
 	struct buffer_head *old_bh;
 	struct msdos_dir_entry *old_de;
-	int old_ino, error;
-	int is_hid,old_hid; /* if new file and old file are hidden */
+	loff_t old_i_pos;
+	int error, is_hid, old_hid; /* if new file and old file are hidden */
 	char old_msdos_name[MSDOS_NAME], new_msdos_name[MSDOS_NAME];
 
 	lock_kernel();
@@ -562,13 +565,13 @@
 
 	is_hid  = (new_dentry->d_name.name[0]=='.') && (new_msdos_name[0]!='.');
 	old_hid = (old_dentry->d_name.name[0]=='.') && (old_msdos_name[0]!='.');
-	error = fat_scan(old_dir, old_msdos_name, &old_bh, &old_de, &old_ino);
+	error = fat_scan(old_dir, old_msdos_name, &old_bh, &old_de, &old_i_pos);
 	if (error < 0)
 		goto rename_done;
 
 	error = do_msdos_rename(old_dir, old_msdos_name, old_dentry,
 				new_dir, new_msdos_name, new_dentry,
-				old_bh, old_de, (ino_t)old_ino, is_hid);
+				old_bh, old_de, old_i_pos, is_hid);
 	brelse(old_bh);
 
 rename_done:
diff -urN linux-2.5.70-bk1/fs/proc/inode.c linux-2.5.70-bk2/fs/proc/inode.c
--- linux-2.5.70-bk1/fs/proc/inode.c	2003-05-26 18:00:56.000000000 -0700
+++ linux-2.5.70-bk2/fs/proc/inode.c	2003-05-28 04:37:02.000000000 -0700
@@ -61,8 +61,6 @@
 	struct proc_dir_entry *de;
 	struct task_struct *tsk;
 
-	inode->i_state = I_CLEAR;
-
 	/* Let go of any associated process */
 	tsk = PROC_I(inode)->task;
 	if (tsk)
@@ -75,6 +73,7 @@
 			module_put(de->owner);
 		de_put(de);
 	}
+	clear_inode(inode);
 }
 
 struct vfsmount *proc_mnt;
diff -urN linux-2.5.70-bk1/fs/vfat/namei.c linux-2.5.70-bk2/fs/vfat/namei.c
--- linux-2.5.70-bk1/fs/vfat/namei.c	2003-05-26 18:00:42.000000000 -0700
+++ linux-2.5.70-bk2/fs/vfat/namei.c	2003-05-28 04:37:02.000000000 -0700
@@ -317,9 +317,10 @@
 {
 	struct msdos_dir_entry *de;
 	struct buffer_head *bh = NULL;
-	int ino,res;
+	loff_t i_pos;
+	int res;
 
-	res = fat_scan(dir,name,&bh,&de,&ino);
+	res = fat_scan(dir, name, &bh, &de, &i_pos);
 	brelse(bh);
 	if (res < 0)
 		return -ENOENT;
@@ -781,7 +782,7 @@
 	int res, len;
 	struct msdos_dir_entry *dummy_de;
 	struct buffer_head *dummy_bh;
-	int dummy_ino;
+	loff_t dummy_i_pos;
 
 	dir_slots = (struct msdos_dir_slot *)
 	       kmalloc(sizeof(struct msdos_dir_slot) * MSDOS_SLOTS, GFP_KERNEL);
@@ -797,7 +798,7 @@
 		goto cleanup;
 
 	/* build the empty directory entry of number of slots */
-	offset = fat_add_entries(dir, slots, &dummy_bh, &dummy_de, &dummy_ino);
+	offset = fat_add_entries(dir, slots, &dummy_bh, &dummy_de, &dummy_i_pos);
 	if (offset < 0) {
 		res = offset;
 		goto cleanup;
@@ -807,7 +808,7 @@
 	/* Now create the new entry */
 	*bh = NULL;
 	for (slot = 0; slot < slots; slot++) {
-		if (fat_get_entry(dir, &offset, bh, de, &sinfo_out->ino) < 0) {
+		if (fat_get_entry(dir, &offset, bh, de, &sinfo_out->i_pos) < 0) {
 			res = -EIO;
 			goto cleanup;
 		}
@@ -852,7 +853,7 @@
 			&offset,&sinfo->longname_offset);
 	if (res>0) {
 		sinfo->long_slots = res-1;
-		if (fat_get_entry(dir,&offset,last_bh,last_de,&sinfo->ino)>=0)
+		if (fat_get_entry(dir,&offset,last_bh,last_de,&sinfo->i_pos)>=0)
 			return 0;
 		res = -EIO;
 	} 
@@ -882,7 +883,7 @@
 		table++;
 		goto error;
 	}
-	inode = fat_build_inode(dir->i_sb, de, sinfo.ino, &res);
+	inode = fat_build_inode(dir->i_sb, de, sinfo.i_pos, &res);
 	brelse(bh);
 	if (res) {
 		unlock_kernel();
@@ -926,7 +927,7 @@
 		unlock_kernel();
 		return res;
 	}
-	inode = fat_build_inode(sb, de, sinfo.ino, &res);
+	inode = fat_build_inode(sb, de, sinfo.i_pos, &res);
 	brelse(bh);
 	if (!inode) {
 		unlock_kernel();
@@ -945,8 +946,8 @@
 static void vfat_remove_entry(struct inode *dir,struct vfat_slot_info *sinfo,
      struct buffer_head *bh, struct msdos_dir_entry *de)
 {
-	loff_t offset;
-	int i,ino;
+	loff_t offset, i_pos;
+	int i;
 
 	/* remove the shortname */
 	dir->i_mtime = CURRENT_TIME;
@@ -958,7 +959,7 @@
 	/* remove the longname */
 	offset = sinfo->longname_offset; de = NULL;
 	for (i = sinfo->long_slots; i > 0; --i) {
-		if (fat_get_entry(dir, &offset, &bh, &de, &ino) < 0)
+		if (fat_get_entry(dir, &offset, &bh, &de, &i_pos) < 0)
 			continue;
 		de->name[0] = DELETED_FLAG;
 		de->attr = ATTR_NONE;
@@ -1040,7 +1041,7 @@
 		unlock_kernel();
 		return res;
 	}
-	inode = fat_build_inode(sb, de, sinfo.ino, &res);
+	inode = fat_build_inode(sb, de, sinfo.i_pos, &res);
 	if (!inode)
 		goto out;
 	inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
@@ -1078,7 +1079,7 @@
 {
 	struct buffer_head *old_bh,*new_bh,*dotdot_bh;
 	struct msdos_dir_entry *old_de,*new_de,*dotdot_de;
-	int dotdot_ino;
+	loff_t dotdot_i_pos;
 	struct inode *old_inode, *new_inode;
 	int res, is_dir;
 	struct vfat_slot_info old_sinfo,sinfo;
@@ -1094,13 +1095,13 @@
 	is_dir = S_ISDIR(old_inode->i_mode);
 
 	if (is_dir && (res = fat_scan(old_inode,MSDOS_DOTDOT,&dotdot_bh,
-				&dotdot_de,&dotdot_ino)) < 0)
+				&dotdot_de,&dotdot_i_pos)) < 0)
 		goto rename_done;
 
 	if (new_dentry->d_inode) {
 		res = vfat_find(new_dir,&new_dentry->d_name,&sinfo,&new_bh,
 				&new_de);
-		if (res < 0 || MSDOS_I(new_inode)->i_location != sinfo.ino) {
+		if (res < 0 || MSDOS_I(new_inode)->i_pos != sinfo.i_pos) {
 			/* WTF??? Cry and fail. */
 			printk(KERN_WARNING "vfat_rename: fs corrupted\n");
 			goto rename_done;
@@ -1124,7 +1125,7 @@
 	vfat_remove_entry(old_dir,&old_sinfo,old_bh,old_de);
 	old_bh=NULL;
 	fat_detach(old_inode);
-	fat_attach(old_inode, sinfo.ino);
+	fat_attach(old_inode, sinfo.i_pos);
 	mark_inode_dirty(old_inode);
 
 	old_dir->i_version++;
diff -urN linux-2.5.70-bk1/include/asm-alpha/bitops.h linux-2.5.70-bk2/include/asm-alpha/bitops.h
--- linux-2.5.70-bk1/include/asm-alpha/bitops.h	2003-05-26 18:00:40.000000000 -0700
+++ linux-2.5.70-bk2/include/asm-alpha/bitops.h	2003-05-28 04:37:02.000000000 -0700
@@ -233,7 +233,7 @@
 }
 
 static inline int
-test_bit(int nr, volatile void * addr)
+test_bit(int nr, const volatile void * addr)
 {
 	return (1UL & (((const int *) addr)[nr >> 5] >> (nr & 31))) != 0UL;
 }
diff -urN linux-2.5.70-bk1/include/asm-v850/bitops.h linux-2.5.70-bk2/include/asm-v850/bitops.h
--- linux-2.5.70-bk1/include/asm-v850/bitops.h	2003-05-26 18:00:41.000000000 -0700
+++ linux-2.5.70-bk2/include/asm-v850/bitops.h	2003-05-28 04:37:02.000000000 -0700
@@ -1,8 +1,8 @@
 /*
  * include/asm-v850/bitops.h -- Bit operations
  *
- *  Copyright (C) 2001,02  NEC Corporation
- *  Copyright (C) 2001,02  Miles Bader <miles@gnu.org>
+ *  Copyright (C) 2001,02,03  NEC Electronics Corporation
+ *  Copyright (C) 2001,02,03  Miles Bader <miles@gnu.org>
  *  Copyright (C) 1992  Linus Torvalds.
  *
  * This file is subject to the terms and conditions of the GNU General
@@ -133,7 +133,7 @@
                 "m" (*((const char *)(addr) + ((nr) >> 3))));		\
      __test_bit_res;							\
   })
-extern __inline__ int __test_bit (int nr, void *addr)
+extern __inline__ int __test_bit (int nr, const void *addr)
 {
 	int res;
 	__asm__ ("tst1 %1, [%2]; setf nz, %0"
diff -urN linux-2.5.70-bk1/include/asm-v850/nb85e_cache.h linux-2.5.70-bk2/include/asm-v850/nb85e_cache.h
--- linux-2.5.70-bk1/include/asm-v850/nb85e_cache.h	2003-05-26 18:00:40.000000000 -0700
+++ linux-2.5.70-bk2/include/asm-v850/nb85e_cache.h	2003-05-28 04:37:02.000000000 -0700
@@ -35,7 +35,7 @@
 #define L1_CACHE_BYTES				NB85E_CACHE_LINE_SIZE
 
 
-#ifndef __ASSEMBLY__
+#if defined(__KERNEL__) && !defined(__ASSEMBLY__)
 
 /* Set caching params via the BHC and DCC registers.  */
 void nb85e_cache_enable (u16 bhc, u16 dcc);
@@ -73,6 +73,6 @@
 #define flush_icache_user_range	nb85e_cache_flush_icache_user_range
 #define flush_cache_sigtramp	nb85e_cache_flush_sigtramp
 
-#endif /* !__ASSEMBLY__ */
+#endif /* __KERNEL__ && !__ASSEMBLY__ */
 
 #endif /* __V850_NB85E_CACHE_H__ */
diff -urN linux-2.5.70-bk1/include/asm-v850/sim.h linux-2.5.70-bk2/include/asm-v850/sim.h
--- linux-2.5.70-bk1/include/asm-v850/sim.h	2003-05-26 18:00:25.000000000 -0700
+++ linux-2.5.70-bk2/include/asm-v850/sim.h	2003-05-28 04:37:02.000000000 -0700
@@ -1,8 +1,8 @@
 /*
  * include/asm-v850/sim.h -- Machine-dependent defs for GDB v850e simulator
  *
- *  Copyright (C) 2001,02  NEC Corporation
- *  Copyright (C) 2001,02  Miles Bader <miles@gnu.org>
+ *  Copyright (C) 2001,02,03  NEC Electronics Corporation
+ *  Copyright (C) 2001,02,03  Miles Bader <miles@gnu.org>
  *
  * This file is subject to the terms and conditions of the GNU General
  * Public License.  See the file COPYING in the main directory of this
diff -urN linux-2.5.70-bk1/include/linux/blkdev.h linux-2.5.70-bk2/include/linux/blkdev.h
--- linux-2.5.70-bk1/include/linux/blkdev.h	2003-05-26 18:00:26.000000000 -0700
+++ linux-2.5.70-bk2/include/linux/blkdev.h	2003-05-28 04:37:02.000000000 -0700
@@ -179,7 +179,8 @@
 	unsigned long *tag_map;		/* bit map of free/busy tags */
 	struct list_head busy_list;	/* fifo list of busy tags */
 	int busy;			/* current depth */
-	int max_depth;
+	int max_depth;			/* what we will send to device */
+	int real_max_depth;		/* what the array can hold */
 };
 
 struct request_queue
@@ -452,6 +453,7 @@
 extern void blk_queue_end_tag(request_queue_t *, struct request *);
 extern int blk_queue_init_tags(request_queue_t *, int);
 extern void blk_queue_free_tags(request_queue_t *);
+extern int blk_queue_resize_tags(request_queue_t *, int);
 extern void blk_queue_invalidate_tags(request_queue_t *);
 extern void blk_congestion_wait(int rw, long timeout);
 
diff -urN linux-2.5.70-bk1/include/linux/msdos_fs.h linux-2.5.70-bk2/include/linux/msdos_fs.h
--- linux-2.5.70-bk1/include/linux/msdos_fs.h	2003-05-26 18:00:46.000000000 -0700
+++ linux-2.5.70-bk2/include/linux/msdos_fs.h	2003-05-28 04:37:02.000000000 -0700
@@ -27,8 +27,6 @@
 
 #define MSDOS_SUPER_MAGIC 0x4d44 /* MD */
 
-#define FAT_CACHE    8 /* FAT cache size */
-
 #define ATTR_NONE    0 /* no attribute bits */
 #define ATTR_RO      1  /* read-only */
 #define ATTR_HIDDEN  2  /* hidden */
@@ -178,7 +176,7 @@
 struct vfat_slot_info {
 	int long_slots;		       /* number of long slots in filename */
 	loff_t longname_offset;	       /* dir offset for longname start */
-	int ino;		       /* ino for the file */
+	loff_t i_pos;		       /* on-disk position of directory entry */
 };
 
 /* Convert attribute bits and a mask to the UNIX mode. */
@@ -204,14 +202,6 @@
 	return container_of(inode, struct msdos_inode_info, vfs_inode);
 }
 
-struct fat_cache {
-	struct super_block *sb; /* fs in question.  NULL means unused */
-	int start_cluster; /* first cluster of the chain. */
-	int file_cluster; /* cluster number in the file. */
-	int disk_cluster; /* cluster number on disk. */
-	struct fat_cache *next; /* next cache entry */
-};
-
 static inline void fat16_towchar(wchar_t *dst, const __u8 *src, size_t len)
 {
 #ifdef __BIG_ENDIAN
@@ -241,13 +231,12 @@
 /* fat/cache.c */
 extern int fat_access(struct super_block *sb, int nr, int new_value);
 extern int __fat_access(struct super_block *sb, int nr, int new_value);
-extern int fat_bmap(struct inode *inode, int sector);
-extern void fat_cache_init(void);
+extern int fat_bmap(struct inode *inode, sector_t sector, sector_t *phys);
+extern void fat_cache_init(struct super_block *sb);
 extern void fat_cache_lookup(struct inode *inode, int cluster, int *f_clu,
 			     int *d_clu);
 extern void fat_cache_add(struct inode *inode, int f_clu, int d_clu);
 extern void fat_cache_inval_inode(struct inode *inode);
-extern void fat_cache_inval_dev(struct super_block *sb);
 extern int fat_free(struct inode *inode, int skip);
 
 /* fat/dir.c */
@@ -259,7 +248,7 @@
 			 unsigned int cmd, unsigned long arg);
 extern int fat_dir_empty(struct inode *dir);
 extern int fat_add_entries(struct inode *dir, int slots, struct buffer_head **bh,
-			   struct msdos_dir_entry **de, int *ino);
+			struct msdos_dir_entry **de, loff_t *i_pos);
 extern int fat_new_dir(struct inode *dir, struct inode *parent, int is_vfat);
 
 /* fat/file.c */
@@ -271,11 +260,11 @@
 
 /* fat/inode.c */
 extern void fat_hash_init(void);
-extern void fat_attach(struct inode *inode, int i_pos);
+extern void fat_attach(struct inode *inode, loff_t i_pos);
 extern void fat_detach(struct inode *inode);
-extern struct inode *fat_iget(struct super_block *sb, int i_pos);
+extern struct inode *fat_iget(struct super_block *sb, loff_t i_pos);
 extern struct inode *fat_build_inode(struct super_block *sb,
-				     struct msdos_dir_entry *de, int ino, int *res);
+			struct msdos_dir_entry *de, loff_t i_pos, int *res);
 extern void fat_delete_inode(struct inode *inode);
 extern void fat_clear_inode(struct inode *inode);
 extern void fat_put_super(struct super_block *sb);
@@ -295,26 +284,27 @@
 extern int date_dos2unix(unsigned short time, unsigned short date);
 extern void fat_date_unix2dos(int unix_date, unsigned short *time,
 			      unsigned short *date);
-extern int fat__get_entry(struct inode *dir, loff_t *pos, struct buffer_head **bh,
-			  struct msdos_dir_entry **de, int *ino);
+extern int fat__get_entry(struct inode *dir, loff_t *pos,
+			  struct buffer_head **bh,
+			  struct msdos_dir_entry **de, loff_t *i_pos);
 static __inline__ int fat_get_entry(struct inode *dir, loff_t *pos,
 				    struct buffer_head **bh,
-				    struct msdos_dir_entry **de, int *ino)
+				    struct msdos_dir_entry **de, loff_t *i_pos)
 {
 	/* Fast stuff first */
 	if (*bh && *de &&
 	    (*de - (struct msdos_dir_entry *)(*bh)->b_data) < MSDOS_SB(dir->i_sb)->dir_per_block - 1) {
 		*pos += sizeof(struct msdos_dir_entry);
 		(*de)++;
-		(*ino)++;
+		(*i_pos)++;
 		return 0;
 	}
-	return fat__get_entry(dir,pos,bh,de,ino);
+	return fat__get_entry(dir, pos, bh, de, i_pos);
 }
 extern int fat_subdirs(struct inode *dir);
 extern int fat_scan(struct inode *dir, const char *name,
 		    struct buffer_head **res_bh,
-		    struct msdos_dir_entry **res_de, int *ino);
+		    struct msdos_dir_entry **res_de, loff_t *i_pos);
 
 /* msdos/namei.c  - these are for Umsdos */
 extern struct dentry *msdos_lookup(struct inode *dir, struct dentry *);
diff -urN linux-2.5.70-bk1/include/linux/msdos_fs_i.h linux-2.5.70-bk2/include/linux/msdos_fs_i.h
--- linux-2.5.70-bk1/include/linux/msdos_fs_i.h	2003-05-26 18:01:00.000000000 -0700
+++ linux-2.5.70-bk2/include/linux/msdos_fs_i.h	2003-05-28 04:37:02.000000000 -0700
@@ -8,12 +8,16 @@
  */
 
 struct msdos_inode_info {
+	/* cache of lastest accessed cluster */
+	int file_cluster;	/* cluster number in the file. */
+	int disk_cluster;	/* cluster number on disk. */
+
 	loff_t mmu_private;
 	int i_start;	/* first cluster or 0 */
 	int i_logstart;	/* logical first cluster */
 	int i_attrs;	/* unused attribute bits */
 	int i_ctime_ms;	/* unused change time in milliseconds */
-	int i_location;	/* on-disk position of directory entry or 0 */
+	loff_t i_pos;	/* on-disk position of directory entry or 0 */
 	struct list_head i_fat_hash;	/* hash by i_location */
 	struct inode vfs_inode;
 };
diff -urN linux-2.5.70-bk1/include/linux/msdos_fs_sb.h linux-2.5.70-bk2/include/linux/msdos_fs_sb.h
--- linux-2.5.70-bk1/include/linux/msdos_fs_sb.h	2003-05-26 18:00:40.000000000 -0700
+++ linux-2.5.70-bk2/include/linux/msdos_fs_sb.h	2003-05-28 04:37:02.000000000 -0700
@@ -26,6 +26,15 @@
 		 nocase:1;	  /* Does this need case conversion? 0=need case conversion*/
 };
 
+#define FAT_CACHE_NR	8 /* number of FAT cache */
+
+struct fat_cache {
+	int start_cluster; /* first cluster of the chain. */
+	int file_cluster; /* cluster number in the file. */
+	int disk_cluster; /* cluster number on disk. */
+	struct fat_cache *next; /* next cache entry */
+};
+
 struct msdos_sb_info {
 	unsigned short cluster_size; /* sectors/cluster */
 	unsigned short cluster_bits; /* sectors/cluster */
@@ -47,6 +56,9 @@
 	void *dir_ops;		     /* Opaque; default directory operations */
 	int dir_per_block;	     /* dir entries per block */
 	int dir_per_block_bits;	     /* log2(dir_per_block) */
+
+	spinlock_t cache_lock;
+	struct fat_cache cache_array[FAT_CACHE_NR], *cache;
 };
 
 #endif
diff -urN linux-2.5.70-bk1/include/linux/wanrouter.h linux-2.5.70-bk2/include/linux/wanrouter.h
--- linux-2.5.70-bk1/include/linux/wanrouter.h	2003-05-26 18:00:27.000000000 -0700
+++ linux-2.5.70-bk2/include/linux/wanrouter.h	2003-05-28 04:37:03.000000000 -0700
@@ -534,7 +534,8 @@
 
 
 /* Public Data */
-extern struct wan_device *router_devlist;	/* list of registered devices */
+/* list of registered devices */
+extern struct wan_device *wanrouter_router_devlist;
 
 #endif	/* __KERNEL__ */
 #endif	/* _ROUTER_H */
diff -urN linux-2.5.70-bk1/kernel/sched.c linux-2.5.70-bk2/kernel/sched.c
--- linux-2.5.70-bk1/kernel/sched.c	2003-05-26 18:00:46.000000000 -0700
+++ linux-2.5.70-bk2/kernel/sched.c	2003-05-28 04:37:03.000000000 -0700
@@ -501,7 +501,7 @@
 			}
 			success = 1;
 		}
-#if CONFIG_SMP
+#ifdef CONFIG_SMP
 	       	else
 			if (unlikely(kick) && task_running(rq, p) && (p->thread_info->cpu != smp_processor_id()))
 				smp_send_reschedule(p->thread_info->cpu);
diff -urN linux-2.5.70-bk1/net/ipv4/esp.c linux-2.5.70-bk2/net/ipv4/esp.c
--- linux-2.5.70-bk1/net/ipv4/esp.c	2003-05-26 18:00:41.000000000 -0700
+++ linux-2.5.70-bk2/net/ipv4/esp.c	2003-05-28 04:37:03.000000000 -0700
@@ -567,7 +567,7 @@
 	.no_policy	=	1,
 };
 
-int __init esp4_init(void)
+static int __init esp4_init(void)
 {
 	struct xfrm_decap_state decap;
 
@@ -578,7 +578,6 @@
 		decap_data_too_small();
 	}
 
-	esp_type.owner = THIS_MODULE;
 	if (xfrm_register_type(&esp_type, AF_INET) < 0) {
 		printk(KERN_INFO "ip esp init: can't add xfrm type\n");
 		return -EAGAIN;
diff -urN linux-2.5.70-bk1/net/ipv4/ipcomp.c linux-2.5.70-bk2/net/ipv4/ipcomp.c
--- linux-2.5.70-bk1/net/ipv4/ipcomp.c	2003-05-26 18:00:56.000000000 -0700
+++ linux-2.5.70-bk2/net/ipv4/ipcomp.c	2003-05-28 04:37:03.000000000 -0700
@@ -382,9 +382,9 @@
 	goto out;
 }
 
-static struct xfrm_type ipcomp_type =
-{
+static struct xfrm_type ipcomp_type = {
 	.description	= "IPCOMP4",
+	.owner		= THIS_MODULE,
 	.proto	     	= IPPROTO_COMP,
 	.init_state	= ipcomp_init_state,
 	.destructor	= ipcomp_destroy,
@@ -400,7 +400,6 @@
 
 static int __init ipcomp4_init(void)
 {
-	ipcomp_type.owner = THIS_MODULE;
 	if (xfrm_register_type(&ipcomp_type, AF_INET) < 0) {
 		printk(KERN_INFO "ipcomp init: can't add xfrm type\n");
 		return -EAGAIN;
diff -urN linux-2.5.70-bk1/net/ipv4/xfrm4_tunnel.c linux-2.5.70-bk2/net/ipv4/xfrm4_tunnel.c
--- linux-2.5.70-bk1/net/ipv4/xfrm4_tunnel.c	2003-05-26 18:00:23.000000000 -0700
+++ linux-2.5.70-bk2/net/ipv4/xfrm4_tunnel.c	2003-05-28 04:37:03.000000000 -0700
@@ -215,6 +215,7 @@
 
 static struct xfrm_type ipip_type = {
 	.description	= "IPIP",
+	.owner		= THIS_MODULE,
 	.proto	     	= IPPROTO_IPIP,
 	.init_state	= ipip_init_state,
 	.destructor	= ipip_destroy,
@@ -229,7 +230,6 @@
 
 static int __init ipip_init(void)
 {
-	ipip_type.owner = THIS_MODULE;
 	if (xfrm_register_type(&ipip_type, AF_INET) < 0) {
 		printk(KERN_INFO "ipip init: can't add xfrm type\n");
 		return -EAGAIN;
diff -urN linux-2.5.70-bk1/net/ipv6/addrconf.c linux-2.5.70-bk2/net/ipv6/addrconf.c
--- linux-2.5.70-bk1/net/ipv6/addrconf.c	2003-05-26 18:00:58.000000000 -0700
+++ linux-2.5.70-bk2/net/ipv6/addrconf.c	2003-05-28 04:37:03.000000000 -0700
@@ -33,6 +33,8 @@
  *	Yuji SEKIYA @USAGI		:	Don't assign a same IPv6
  *						address on a same interface.
  *	YOSHIFUJI Hideaki @USAGI	:	ARCnet support
+ *	YOSHIFUJI Hideaki @USAGI	:	convert /proc/net/if_inet6 to
+ *						seq_file.
  */
 
 #include <linux/config.h>
@@ -76,6 +78,9 @@
 
 #include <asm/uaccess.h>
 
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+
 #define IPV6_MAX_ADDRESSES 16
 
 /* Set to 3 to get tracing... */
@@ -2090,57 +2095,141 @@
 }
 
 #ifdef CONFIG_PROC_FS
-static int iface_proc_info(char *buffer, char **start, off_t offset,
-			   int length)
+struct if6_iter_state {
+	int bucket;
+};
+
+static inline struct inet6_ifaddr *if6_get_bucket(struct seq_file *seq, loff_t *pos)
 {
-	struct inet6_ifaddr *ifp;
 	int i;
-	int len = 0;
-	off_t pos=0;
-	off_t begin=0;
+	struct inet6_ifaddr *ifa = NULL;
+	loff_t l = *pos;
+	struct if6_iter_state *state = seq->private;
+
+	for (; state->bucket < IN6_ADDR_HSIZE; ++state->bucket)
+		for (i = 0, ifa = inet6_addr_lst[state->bucket]; ifa; ++i, ifa=ifa->lst_next) {
+			if (l--)
+				continue;
+			*pos = i;
+			goto out;
+		}
+out:
+	return ifa;
+}
 
-	for (i=0; i < IN6_ADDR_HSIZE; i++) {
-		read_lock_bh(&addrconf_hash_lock);
-		for (ifp=inet6_addr_lst[i]; ifp; ifp=ifp->lst_next) {
-			int j;
+static void *if6_seq_start(struct seq_file *seq, loff_t *pos)
+{
+	read_lock_bh(&addrconf_hash_lock);
+	return *pos ? if6_get_bucket(seq, pos) : (void *)1;
+}
 
-			for (j=0; j<16; j++) {
-				sprintf(buffer + len, "%02x",
-					ifp->addr.s6_addr[j]);
-				len += 2;
-			}
+static void *if6_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+{
+	struct inet6_ifaddr *ifa;
+	struct if6_iter_state *state;
 
-			len += sprintf(buffer + len,
-				       " %02x %02x %02x %02x %8s\n",
-				       ifp->idev->dev->ifindex,
-				       ifp->prefix_len,
-				       ifp->scope,
-				       ifp->flags,
-				       ifp->idev->dev->name);
-			pos=begin+len;
-			if(pos<offset) {
-				len=0;
-				begin=pos;
-			}
-			if(pos>offset+length) {
-				read_unlock_bh(&addrconf_hash_lock);
-				goto done;
-			}
-		}
-		read_unlock_bh(&addrconf_hash_lock);
+	if (v == (void *)1) {
+		ifa = if6_get_bucket(seq, pos);
+		goto out;
 	}
 
-done:
+	state = seq->private;
+
+	ifa = v;
+	ifa = ifa->lst_next;
+	if (ifa)
+		goto out;
+
+	if (++state->bucket >= IN6_ADDR_HSIZE)
+		goto out;
+
+	*pos = 0;
+	ifa = if6_get_bucket(seq, pos);
+out:
+	++*pos;
+	return ifa;
+}
+
+static inline void if6_iface_seq_show(struct seq_file *seq, struct inet6_ifaddr *ifp)
+{
+	seq_printf(seq,
+		   "%04x%04x%04x%04x%04x%04x%04x%04x %02x %02x %02x %02x %8s\n",
+		   NIP6(ifp->addr),
+		   ifp->idev->dev->ifindex,
+		   ifp->prefix_len,
+		   ifp->scope,
+		   ifp->flags,
+		   ifp->idev->dev->name);
+}
+
+static int if6_seq_show(struct seq_file *seq, void *v)
+{
+	if (v == (void *)1)
+		return 0;
+	else
+		if6_iface_seq_show(seq, v);
+	return 0;
+}
+
+static void if6_seq_stop(struct seq_file *seq, void *v)
+{
+	read_unlock_bh(&addrconf_hash_lock);
+}
+
+static struct seq_operations if6_seq_ops = {
+	.start	= if6_seq_start,
+	.next	= if6_seq_next,
+	.show	= if6_seq_show,
+	.stop	= if6_seq_stop,
+};
+
+static int if6_seq_open(struct inode *inode, struct file *file)
+{
+	struct seq_file *seq;
+	int rc = -ENOMEM;
+	struct if6_iter_state *s = kmalloc(sizeof(*s), GFP_KERNEL);
+
+	if (!s)
+		goto out;
+	memset(s, 0, sizeof(*s));
 
-	*start=buffer+(offset-begin);
-	len-=(offset-begin);
-	if(len>length)
-		len=length;
-	if(len<0)
-		len=0;
-	return len;
+	rc = seq_open(file, &if6_seq_ops);
+	if (rc)
+		goto out_kfree;
+
+	seq = file->private_data;
+	seq->private = s;
+out:
+	return rc;
+out_kfree:
+	kfree(s);
+	goto out;
 }
 
+static struct file_operations if6_fops = {
+	.owner		= THIS_MODULE,
+	.open		= if6_seq_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= seq_release_private,
+};
+
+int __init if6_proc_init(void)
+{
+	struct proc_dir_entry *p;
+	int rc = 0;
+
+	p = create_proc_entry("if_inet6", S_IRUGO, proc_net);
+	if (p)
+		p->proc_fops = &if6_fops;
+	else
+		rc = -ENOMEM;
+	return rc;
+}
+void if6_proc_exit(void)
+{
+	proc_net_remove("if_inet6");
+}
 #endif	/* CONFIG_PROC_FS */
 
 /*
@@ -2727,10 +2816,6 @@
 	rtnl_unlock();
 #endif
 
-#ifdef CONFIG_PROC_FS
-	proc_net_create("if_inet6", 0, iface_proc_info);
-#endif
-	
 	addrconf_verify(0);
 	rtnetlink_links[PF_INET6] = inet6_rtnetlink_table;
 #ifdef CONFIG_SYSCTL
diff -urN linux-2.5.70-bk1/net/ipv6/af_inet6.c linux-2.5.70-bk2/net/ipv6/af_inet6.c
--- linux-2.5.70-bk1/net/ipv6/af_inet6.c	2003-05-26 18:00:41.000000000 -0700
+++ linux-2.5.70-bk2/net/ipv6/af_inet6.c	2003-05-28 04:37:03.000000000 -0700
@@ -75,18 +75,16 @@
 
 #ifdef CONFIG_PROC_FS
 extern int raw6_proc_init(void);
-extern int raw6_proc_exit(void);
-
+extern void raw6_proc_exit(void);
 extern int tcp6_proc_init(void);
 extern void tcp6_proc_exit(void);
-
 extern int udp6_proc_init(void);
 extern void udp6_proc_exit(void);
-
 extern int ipv6_misc_proc_init(void);
-extern int ipv6_misc_proc_exit(void);
-
+extern void ipv6_misc_proc_exit(void);
 extern int anycast6_get_info(char *, char **, off_t, int);
+extern int if6_proc_init(void);
+extern void if6_proc_exit(void);
 #endif
 
 #ifdef CONFIG_SYSCTL
@@ -799,6 +797,8 @@
 
 	if (!proc_net_create("anycast6", 0, anycast6_get_info))
 		goto proc_anycast6_fail;
+	if (if6_proc_init())
+		goto proc_if6_fail;
 #endif
 	ipv6_netdev_notif_init();
 	ipv6_packet_init();
@@ -820,6 +820,8 @@
 	return 0;
 
 #ifdef CONFIG_PROC_FS
+proc_if6_fail:
+	proc_net_remove("anycast6");
 proc_anycast6_fail:
 	ipv6_misc_proc_exit();
 proc_misc6_fail:
@@ -852,11 +854,12 @@
 	/* First of all disallow new sockets creation. */
 	sock_unregister(PF_INET6);
 #ifdef CONFIG_PROC_FS
-	raw6_proc_exit();
-	proc_net_remove("tcp6");
-	proc_net_remove("udp6");
-	ipv6_misc_proc_exit();
-	proc_net_remove("anycast6");
+	if6_proc_exit();
+ 	proc_net_remove("anycast6");
+ 	ipv6_misc_proc_exit();
+ 	udp6_proc_exit();
+ 	tcp6_proc_exit();
+ 	raw6_proc_exit();
 #endif
 	/* Cleanup code parts. */
 	sit_cleanup();
diff -urN linux-2.5.70-bk1/net/ipv6/icmp.c linux-2.5.70-bk2/net/ipv6/icmp.c
--- linux-2.5.70-bk1/net/ipv6/icmp.c	2003-05-26 18:00:27.000000000 -0700
+++ linux-2.5.70-bk2/net/ipv6/icmp.c	2003-05-28 04:37:03.000000000 -0700
@@ -263,7 +263,7 @@
 void icmpv6_send(struct sk_buff *skb, int type, int code, __u32 info, 
 		 struct net_device *dev)
 {
-	struct inet6_dev *idev;
+	struct inet6_dev *idev = NULL;
 	struct ipv6hdr *hdr = skb->nh.ipv6h;
 	struct sock *sk = icmpv6_socket->sk;
 	struct ipv6_pinfo *np = inet6_sk(sk);
@@ -384,7 +384,7 @@
 				hlimit, NULL, &fl, (struct rt6_info*)dst, MSG_DONTWAIT);
 	if (err) {
 		ip6_flush_pending_frames(sk);
-		goto out;
+		goto out_put;
 	}
 	err = icmpv6_push_pending_frames(sk, &fl, &tmp_hdr, len + sizeof(struct icmp6hdr));
 	__skb_push(skb, plen);
@@ -393,6 +393,7 @@
 		ICMP6_INC_STATS_OFFSET_BH(idev, Icmp6OutDestUnreachs, type - ICMPV6_DEST_UNREACH);
 	ICMP6_INC_STATS_BH(idev, Icmp6OutMsgs);
 
+out_put:
 	if (likely(idev != NULL))
 		in6_dev_put(idev);
 out:
@@ -455,13 +456,14 @@
 
 	if (err) {
 		ip6_flush_pending_frames(sk);
-		goto out;
+		goto out_put;
 	}
 	err = icmpv6_push_pending_frames(sk, &fl, &tmp_hdr, skb->len + sizeof(struct icmp6hdr));
 
         ICMP6_INC_STATS_BH(idev, Icmp6OutEchoReplies);
         ICMP6_INC_STATS_BH(idev, Icmp6OutMsgs);
 
+out_put: 
 	if (likely(idev != NULL))
 		in6_dev_put(idev);
 out: 
diff -urN linux-2.5.70-bk1/net/ipv6/ndisc.c linux-2.5.70-bk2/net/ipv6/ndisc.c
--- linux-2.5.70-bk1/net/ipv6/ndisc.c	2003-05-26 18:00:41.000000000 -0700
+++ linux-2.5.70-bk2/net/ipv6/ndisc.c	2003-05-28 04:37:03.000000000 -0700
@@ -431,23 +431,21 @@
 
 	len = sizeof(struct icmp6hdr) + sizeof(struct in6_addr);
 
-	rt = ip6_dst_alloc();
-	if (!rt) 
-		return;
-
 	/* for anycast or proxy, solicited_addr != src_addr */
 	ifp = ipv6_get_ifaddr(solicited_addr, dev);
  	if (ifp) {
 		src_addr = solicited_addr;
 		in6_ifa_put(ifp);
 	} else {
-		if (ipv6_dev_get_saddr(dev, daddr, &tmpaddr, 0)) {
-			dst_free(dst);
+		if (ipv6_dev_get_saddr(dev, daddr, &tmpaddr, 0))
 			return;
-		}
 		src_addr = &tmpaddr;
 	}
 
+	rt = ip6_dst_alloc();
+	if (!rt) 
+		return;
+
 	ndisc_flow_init(&fl, NDISC_NEIGHBOUR_ADVERTISEMENT, src_addr, daddr);
 	ndisc_rt_init(rt, dev, neigh);	
 
diff -urN linux-2.5.70-bk1/net/ipv6/proc.c linux-2.5.70-bk2/net/ipv6/proc.c
--- linux-2.5.70-bk1/net/ipv6/proc.c	2003-05-26 18:00:38.000000000 -0700
+++ linux-2.5.70-bk2/net/ipv6/proc.c	2003-05-28 04:37:03.000000000 -0700
@@ -299,11 +299,10 @@
 	goto out;
 }
 
-int ipv6_misc_proc_exit(void)
+void ipv6_misc_proc_exit(void)
 {
 	proc_net_remove("sockstat6");
 	proc_net_remove("dev_snmp6");
 	proc_net_remove("snmp6");
-	return 0;
 }
 
diff -urN linux-2.5.70-bk1/net/wanrouter/wanproc.c linux-2.5.70-bk2/net/wanrouter/wanproc.c
--- linux-2.5.70-bk1/net/wanrouter/wanproc.c	2003-05-26 18:00:39.000000000 -0700
+++ linux-2.5.70-bk2/net/wanrouter/wanproc.c	2003-05-28 04:37:03.000000000 -0700
@@ -87,7 +87,8 @@
 	lock_kernel();
 	if (!l--)
 		return (void *)1;
-	for (wandev = router_devlist; l-- && wandev; wandev = wandev->next)
+	for (wandev = wanrouter_router_devlist; l-- && wandev;
+	     wandev = wandev->next)
 		;
 	return wandev;
 }
@@ -96,7 +97,7 @@
 {
 	struct wan_device *wandev = v;
 	(*pos)++;
-	return (v == (void *)1) ? router_devlist : wandev->next;
+	return (v == (void *)1) ? wanrouter_router_devlist : wandev->next;
 }
 
 static void r_stop(struct seq_file *m, void *v)
