diff -Nru a/Documentation/eisa.txt b/Documentation/eisa.txt
--- a/Documentation/eisa.txt	Mon Apr 21 09:21:26 2003
+++ b/Documentation/eisa.txt	Fri Jul  4 00:44:46 2003
@@ -46,12 +46,14 @@
 to this device, as well as some parameters for probing purposes.
 
 struct eisa_root_device {
-        struct list_head node;
-        struct device   *dev;    /* Pointer to bridge device */
-        struct resource *res;
-        unsigned long    bus_base_addr;
-        int              slots;  /* Max slot number */
-        int              bus_nr; /* Set by eisa_root_register */
+	struct device   *dev;	 /* Pointer to bridge device */
+	struct resource *res;
+	unsigned long    bus_base_addr;
+	int		 slots;  /* Max slot number */
+	int		 force_probe; /* Probe even when no slot 0 */
+	u64		 dma_mask; /* from bridge device */
+	int              bus_nr; /* Set by eisa_root_register */
+	struct resource  eisa_root_res;	/* ditto */
 };
 
 node          : used for eisa_root_register internal purpose
@@ -59,6 +61,8 @@
 res           : root device I/O resource
 bus_base_addr : slot 0 address on this bus
 slots	      : max slot number to probe
+force_probe   : Probe even when slot 0 is empty (no EISA mainboard)
+dma_mask      : Default DMA mask. Usualy the bridge device dma_mask.
 bus_nr	      : unique bus id, set by eisa_root_register
 
 ** Driver :
@@ -87,7 +91,7 @@
 		  Documentation/driver-model/driver.txt. Only .name,
 		  .probe and .remove members are mandatory.
 
-An example is the 3c509 driver :
+An example is the 3c59x driver :
 
 static struct eisa_device_id vortex_eisa_ids[] = {
 	{ "TCM5920", EISA_3C592_OFFSET },
@@ -116,15 +120,20 @@
 struct eisa_device {
         struct eisa_device_id id;
         int                   slot;
-        unsigned long         base_addr;
-        struct resource       res;
+	int                   state;
+	unsigned long         base_addr;
+	struct resource       res[EISA_MAX_RESOURCES];
+	u64                   dma_mask;
         struct device         dev; /* generic device */
 };
 
 id	: EISA id, as read from device. id.driver_data is set from the
 	  matching driver EISA id.
 slot	: slot number which the device was detected on
-res	: I/O resource allocated to this device
+state   : set of flags indicating the state of the device. Current
+	  flags are EISA_CONFIG_ENABLED and EISA_CONFIG_FORCED.
+res	: set of four 256 bytes I/O regions allocated to this device
+dma_mask: DMA mask set from the parent device.
 dev	: generic device (see Documentation/driver-model/device.txt)
 
 You can get the 'struct eisa_device' from 'struct device' using the
@@ -140,6 +149,32 @@
 
 Gets the pointer previously stored into the device's driver_data area.
 
+int eisa_get_region_index (void *addr);
+
+Returns the region number (0 <= x < EISA_MAX_RESOURCES) of a given
+address.
+
+** Kernel parameters :
+
+eisa_bus.enable_dev :
+
+A comma-separated list of slots to be enabled, even if the firmware
+set the card as disabled. The driver must be able to properly
+initialize the device in such conditions.
+
+eisa_bus.disable_dev :
+
+A comma-separated list of slots to be enabled, even if the firmware
+set the card as enabled. The driver won't be called to handle this
+device.
+
+virtual_root.force_probe :
+
+Force the probing code to probe EISA slots even when it cannot find an
+EISA compliant mainboard (nothing appears on slot 0). Defaultd to 0
+(don't force), and set to 1 (force probing) when either
+CONFIG_ALPHA_JENSEN or CONFIG_EISA_VLB_PRIMING are set.
+
 ** Random notes :
 
 Converting an EISA driver to the new API mostly involves *deleting*
@@ -156,10 +191,13 @@
 expect to have explored the whole machine when they exit their probe
 routine.
 
+For example, switching your favorite EISA SCSI card to the "hotplug"
+model is "the right thing"(tm).
+
 ** Thanks :
 
 I'd like to thank the following people for their help :
 - Xavier Benigni for lending me a wonderful Alpha Jensen,
 - James Bottomley, Jeff Garzik for getting this stuff into the kernel,
 - Andries Brouwer for contributing numerous EISA ids,
-- Catrin Jones for coping with too many machines at home
+- Catrin Jones for coping with far too many machines at home.
diff -Nru a/Documentation/filesystems/Locking b/Documentation/filesystems/Locking
--- a/Documentation/filesystems/Locking	Sun May 25 20:03:27 2003
+++ b/Documentation/filesystems/Locking	Fri Jul  4 22:16:53 2003
@@ -68,8 +68,8 @@
 permission:	no
 getattr:	no
 setxattr:	yes
-getxattr:	yes
-listxattr:	yes
+getxattr:	no
+listxattr:	no
 removexattr:	yes
 	Additionally, ->rmdir(), ->unlink() and ->rename() have ->i_sem on
 victim.
@@ -318,7 +318,7 @@
 ioctl:		yes	(see below)
 mmap:		no
 open:		maybe	(see below)
-flush:		yes
+flush:		no
 release:	no
 fsync:		yes	(see below)
 fasync:		yes	(see below)
diff -Nru a/Documentation/pci.txt b/Documentation/pci.txt
--- a/Documentation/pci.txt	Tue Jun 24 15:30:22 2003
+++ b/Documentation/pci.txt	Wed Jul  2 18:11:39 2003
@@ -7,14 +7,14 @@
 Different PCI devices have different requirements and different bugs --
 because of this, the PCI support layer in Linux kernel is not as trivial
 as one would wish. This short pamphlet tries to help all potential driver
-authors to find their way through the deep forests of PCI handling.
+authors find their way through the deep forests of PCI handling.
 
 
 0. Structure of PCI drivers
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~
 There exist two kinds of PCI drivers: new-style ones (which leave most of
 probing for devices to the PCI layer and support online insertion and removal
-of devices [thus supporting PCI, hot-pluggable PCI and CardBus in single
+of devices [thus supporting PCI, hot-pluggable PCI and CardBus in a single
 driver]) and old-style ones which just do all the probing themselves. Unless
 you have a very good reason to do so, please don't use the old way of probing
 in any new code. After the driver finds the devices it wishes to operate
@@ -174,7 +174,7 @@
 the latency timer value if it's set to something bogus by the BIOS.
 
    If you want to use the PCI Memory-Write-Invalidate transaction,
-call pci_set_mwi().  This enables bit PCI_COMMAND bit for Mem-Wr-Inval
+call pci_set_mwi().  This enables the PCI_COMMAND bit for Mem-Wr-Inval
 and also ensures that the cache line size register is set correctly.
 Make sure to check the return value of pci_set_mwi(), not all architectures
 may support Memory-Write-Invalidate.
@@ -236,7 +236,7 @@
 7. Miscellaneous hints
 ~~~~~~~~~~~~~~~~~~~~~~
 When displaying PCI slot names to the user (for example when a driver wants
-to tell the user what card has it found), please use pci_dev->slot_name
+to tell the user what card has it found), please use pci_name(pci_dev)
 for this purpose.
 
 Always refer to the PCI devices by a pointer to the pci_dev structure.
@@ -247,6 +247,10 @@
 
 If you're going to use PCI bus mastering DMA, take a look at
 Documentation/DMA-mapping.txt.
+
+Don't try to turn on Fast Back to Back writes in your driver.  All devices
+on the bus need to be capable of doing it, so this is something which needs
+to be handled by platform and generic code, not individual drivers.
 
 
 8. Obsolete functions
diff -Nru a/MAINTAINERS b/MAINTAINERS
--- a/MAINTAINERS	Wed Jun 25 16:30:58 2003
+++ b/MAINTAINERS	Sun Jul  6 16:40:01 2003
@@ -245,6 +245,21 @@
 L:	linux-atalk@lists.netspace.org
 S:	Maintained
 
+ARM26 ARCHITECTURE
+P:	Ian Molton
+M:	spyro@f2s.com
+S:	Maintained
+
+ARM26/ARCHIMEDES
+P:	Ian Molton
+M:	spyro@f2s.com
+S:	Maintained
+
+ARM26/A5000
+P:	John Appleby
+M:	john@dnsworld.co.uk
+S:	Maintained
+
 ARM MFM AND FLOPPY DRIVERS
 P:	Dave Gilbert
 M:	linux@treblig.org
@@ -1265,8 +1280,8 @@
 S:	Maintained
 
 NETWORK BLOCK DEVICE
-P:	Pavel Machek
-M:	pavel@atrey.karlin.mff.cuni.cz
+P:	Paul Clements
+M:	Paul.Clements@steeleye.com
 S:	Maintained
 
 NETWORK DEVICE DRIVERS
diff -Nru a/Makefile b/Makefile
--- a/Makefile	Wed Jul  2 11:16:44 2003
+++ b/Makefile	Tue Jul  8 04:39:01 2003
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 5
 SUBLEVEL = 74
-EXTRAVERSION =
+EXTRAVERSION = -bk6
 
 # *DOCUMENTATION*
 # To see a list of typical targets execute "make help"
diff -Nru a/arch/alpha/mm/numa.c b/arch/alpha/mm/numa.c
--- a/arch/alpha/mm/numa.c	Sun Apr 20 09:14:40 2003
+++ b/arch/alpha/mm/numa.c	Wed Jul  2 21:20:53 2003
@@ -338,7 +338,7 @@
 
 		lmem_map = node_mem_map(nid);
 		pfn = NODE_DATA(nid)->node_start_pfn;
-		for (i = 0; i < node_size(nid); i++, pfn++)
+		for (i = 0; i < node_spanned_pages(nid); i++, pfn++)
 			if (page_is_ram(pfn) && PageReserved(lmem_map+i))
 				reservedpages++;
 	}
@@ -372,7 +372,7 @@
 	printk("Free swap:       %6dkB\n",nr_swap_pages<<(PAGE_SHIFT-10));
 	for (nid = 0; nid < numnodes; nid++) {
 		struct page * lmem_map = node_mem_map(nid);
-		i = node_size(nid);
+		i = node_spanned_pages(nid);
 		while (i-- > 0) {
 			total++;
 			if (PageReserved(lmem_map+i))
diff -Nru a/arch/arm/mm/init.c b/arch/arm/mm/init.c
--- a/arch/arm/mm/init.c	Wed May 28 06:36:31 2003
+++ b/arch/arm/mm/init.c	Wed Jul  2 21:20:53 2003
@@ -79,7 +79,7 @@
 		struct page *page, *end;
 
 		page = NODE_MEM_MAP(node);
-		end  = page + NODE_DATA(node)->node_size;
+		end  = page + NODE_DATA(node)->node_spanned_pages;
 
 		do {
 			total++;
@@ -576,7 +576,7 @@
 	for (node = 0; node < numnodes; node++) {
 		pg_data_t *pgdat = NODE_DATA(node);
 
-		if (pgdat->node_size != 0)
+		if (pgdat->node_spanned_pages != 0)
 			totalram_pages += free_all_bootmem_node(pgdat);
 	}
 
diff -Nru a/arch/arm26/Config.help b/arch/arm26/Config.help
--- a/arch/arm26/Config.help	Wed Jun  4 04:15:45 2003
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,387 +0,0 @@
-CONFIG_ARM
-  The ARM series is a line of low-power-consumption RISC chip designs
-  licensed by ARM ltd and targeted at embedded applications.
-
-CONFIG_IDE
-  If you say Y here, your kernel will be able to manage low cost mass
-  storage units such as ATA/(E)IDE and ATAPI units. The most common
-  cases are IDE hard drives and ATAPI CD-ROM drives.
-
-  If your system is pure SCSI and doesn't use these interfaces, you
-  can say N here.
-
-  Integrated Disk Electronics (IDE aka ATA-1) is a connecting standard
-  for mass storage units such as hard disks. It was designed by
-  Western Digital and Compaq Computer in 1984. It was then named
-  ST506. Quite a number of disks use the IDE interface.
-
-  AT Attachment (ATA) is the superset of the IDE specifications.
-  ST506 was also called ATA-1.
-
-  Fast-IDE is ATA-2 (also named Fast ATA), Enhanced IDE (EIDE) is
-  ATA-3. It provides support for larger disks (up to 8.4GB by means of
-  the LBA standard), more disks (4 instead of 2) and for other mass
-  storage units such as tapes and cdrom. UDMA/33 (aka UltraDMA/33) is
-  ATA-4 and provides faster (and more CPU friendly) transfer modes
-  than previous PIO (Programmed processor Input/Output) from previous
-  ATA/IDE standards by means of fast DMA controllers.
-
-  ATA Packet Interface (ATAPI) is a protocol used by EIDE tape and
-  CD-ROM drives, similar in many respects to the SCSI protocol.
-
-  SMART IDE (Self Monitoring, Analysis and Reporting Technology) was
-  designed in order to prevent data corruption and disk crash by
-  detecting pre hardware failure conditions (heat, access time, and
-  the like...). Disks built since June 1995 may follow this standard.
-  The kernel itself don't manage this; however there are quite a
-  number of user programs such as smart that can query the status of
-  SMART parameters disk.
-
-  If you want to compile this driver as a module ( = code which can be
-  inserted in and removed from the running kernel whenever you want),
-  say M here and read <file:Documentation/modules.txt>. The module
-  will be called ide.o.
-
-  For further information, please read <file:Documentation/ide.txt>.
-
-  If unsure, say Y.
-
-CONFIG_ISA
-  Find out whether you have ISA slots on your motherboard.  ISA is the
-  name of a bus system, i.e. the way the CPU talks to the other stuff
-  inside your box.  Other bus systems are PCI, EISA, MicroChannel
-  (MCA) or VESA.  ISA is an older system, now being displaced by PCI;
-  newer boards don't support it.  If you have ISA, say Y, otherwise N.
-
-CONFIG_PREEMPT
-  This option reduces the latency of the kernel when reacting to
-  real-time or interactive events by allowing a low priority process to
-  be preempted even if it is in kernel mode executing a system call.
-  This allows applications to run more reliably even when the system is
-  under load.
-
-  Say Y here if you are building a kernel for a desktop, embedded
-  or real-time system.  Say N if you are unsure.
-
-CONFIG_MCA
-  MicroChannel Architecture is found in some IBM PS/2 machines and
-  laptops.  It is a bus system similar to PCI or ISA. See
-  <file:Documentation/mca.txt> (and especially the web page given
-  there) before attempting to build an MCA bus kernel.
-
-CONFIG_EISA
-  The Extended Industry Standard Architecture (EISA) bus was
-  developed as an open alternative to the IBM MicroChannel bus.
-
-  The EISA bus provided some of the features of the IBM MicroChannel
-  bus while maintaining backward compatibility with cards made for
-  the older ISA bus.  The EISA bus saw limited use between 1988 and
-  1995 when it was made obsolete by the PCI bus.
-
-  Say Y here if you are building a kernel for an EISA-based machine.
-
-  Otherwise, say N.
-
-CONFIG_HOTPLUG
-  Say Y here if you want to plug devices into your computer while
-  the system is running, and be able to use them quickly.  In many
-  cases, the devices can likewise be unplugged at any time too.
-
-  One well known example of this is PCMCIA- or PC-cards, credit-card
-  size devices such as network cards, modems or hard drives which are
-  plugged into slots found on all modern laptop computers.  Another
-  example, used on modern desktops as well as laptops, is USB.
-
-  Enable HOTPLUG and KMOD, and build a modular kernel.  Get agent
-  software (at <http://linux-hotplug.sourceforge.net/>) and install it.
-  Then your kernel will automatically call out to a user mode "policy
-  agent" (/sbin/hotplug) to load modules and set up software needed
-  to use devices as you hotplug them.
-
-CONFIG_KCORE_ELF
-  If you enabled support for /proc file system then the file
-  /proc/kcore will contain the kernel core image. This can be used
-  in gdb:
-
-  $ cd /usr/src/linux ; gdb vmlinux /proc/kcore
-
-  You have two choices here: ELF and A.OUT. Selecting ELF will make
-  /proc/kcore appear in ELF core format as defined by the Executable
-  and Linking Format specification. Selecting A.OUT will choose the
-  old "a.out" format which may be necessary for some old versions
-  of binutils or on some architectures.
-
-  This is especially useful if you have compiled the kernel with the
-  "-g" option to preserve debugging information. It is mainly used
-  for examining kernel data structures on the live kernel so if you
-  don't understand what this means or are not a kernel hacker, just
-  leave it at its default value ELF.
-
-CONFIG_KCORE_AOUT
-  Not necessary unless you're using a very out-of-date binutils
-  version.  You probably want KCORE_ELF.
-
-CONFIG_BINFMT_ELF
-  ELF (Executable and Linkable Format) is a format for libraries and
-  executables used across different architectures and operating
-  systems. Saying Y here will enable your kernel to run ELF binaries
-  and enlarge it by about 13 KB. ELF support under Linux has now all
-  but replaced the traditional Linux a.out formats (QMAGIC and ZMAGIC)
-  because it is portable (this does *not* mean that you will be able
-  to run executables from different architectures or operating systems
-  however) and makes building run-time libraries very easy. Many new
-  executables are distributed solely in ELF format. You definitely
-  want to say Y here.
-
-  Information about ELF is contained in the ELF HOWTO available from
-  <http://www.linuxdoc.org/docs.html#howto>.
-
-  If you find that after upgrading from Linux kernel 1.2 and saying Y
-  here, you still can't run any ELF binaries (they just crash), then
-  you'll have to install the newest ELF runtime libraries, including
-  ld.so (check the file <file:Documentation/Changes> for location and
-  latest version).
-
-  If you want to compile this as a module ( = code which can be
-  inserted in and removed from the running kernel whenever you want),
-  say M here and read <file:Documentation/modules.txt>.  The module
-  will be called binfmt_elf.o. Saying M or N here is dangerous because
-  some crucial programs on your system might be in ELF format.
-
-CONFIG_BINFMT_AOUT
-  A.out (Assembler.OUTput) is a set of formats for libraries and
-  executables used in the earliest versions of UNIX. Linux used the
-  a.out formats QMAGIC and ZMAGIC until they were replaced with the
-  ELF format.
-
-  As more and more programs are converted to ELF, the use for a.out
-  will gradually diminish. If you disable this option it will reduce
-  your kernel by one page. This is not much and by itself does not
-  warrant removing support. However its removal is a good idea if you
-  wish to ensure that absolutely none of your programs will use this
-  older executable format. If you don't know what to answer at this
-  point then answer Y. If someone told you "You need a kernel with
-  QMAGIC support" then you'll have to say Y here. You may answer M to
-  compile a.out support as a module and later load the module when you
-  want to use a program or library in a.out format. The module will be
-  called binfmt_aout.o. Saying M or N here is dangerous though,
-  because some crucial programs on your system might still be in A.OUT
-  format.
-
-CONFIG_BINFMT_MISC
-  If you say Y here, it will be possible to plug wrapper-driven binary
-  formats into the kernel. You will like this especially when you use
-  programs that need an interpreter to run like Java, Python or
-  Emacs-Lisp. It's also useful if you often run DOS executables under
-  the Linux DOS emulator DOSEMU (read the DOSEMU-HOWTO, available from
-  <http://www.linuxdoc.org/docs.html#howto>). Once you have
-  registered such a binary class with the kernel, you can start one of
-  those programs simply by typing in its name at a shell prompt; Linux
-  will automatically feed it to the correct interpreter.
-
-  You can do other nice things, too. Read the file
-  <file:Documentation/binfmt_misc.txt> to learn how to use this
-  feature, and <file:Documentation/java.txt> for information about how
-  to include Java support.
-
-  You must say Y to "/proc file system support" (CONFIG_PROC_FS) to
-  use this part of the kernel.
-
-  You may say M here for module support and later load the module when
-  you have use for it; the module is called binfmt_misc.o. If you
-  don't know what to answer at this point, say Y.
-
-CONFIG_SCSI
-  If you want to use a SCSI hard disk, SCSI tape drive, SCSI CD-ROM or
-  any other SCSI device under Linux, say Y and make sure that you know
-  the name of your SCSI host adapter (the card inside your computer
-  that "speaks" the SCSI protocol, also called SCSI controller),
-  because you will be asked for it.
-
-  You also need to say Y here if you want support for the parallel
-  port version of the 100 MB IOMEGA ZIP drive.
-
-  This driver is also available as a module ( = code which can be
-  inserted in and removed from the running kernel whenever you want).
-  The module will be called scsi_mod.o.  If you want to compile it as
-  a module, say M here and read <file:Documentation/modules.txt> and
-  <file:Documentation/scsi.txt>.  However, do not compile this as a
-  module if your root file system (the one containing the directory /)
-  is located on a SCSI device.
-
-CONFIG_NETDEVICES
-  You can say N here if you don't intend to connect your Linux box to
-  any other computer at all or if all your connections will be over a
-  telephone line with a modem either via UUCP (UUCP is a protocol to
-  forward mail and news between unix hosts over telephone lines; read
-  the UUCP-HOWTO, available from
-  <http://www.linuxdoc.org/docs.html#howto>) or dialing up a shell
-  account or a BBS, even using term (term is a program which gives you
-  almost full Internet connectivity if you have a regular dial up
-  shell account on some Internet connected Unix computer. Read
-  <http://www.bart.nl/~patrickr/term-howto/Term-HOWTO.html>).
-
-  You'll have to say Y if your computer contains a network card that
-  you want to use under Linux (make sure you know its name because you
-  will be asked for it and read the Ethernet-HOWTO (especially if you
-  plan to use more than one network card under Linux)) or if you want
-  to use SLIP (Serial Line Internet Protocol is the protocol used to
-  send Internet traffic over telephone lines or null modem cables) or
-  CSLIP (compressed SLIP) or PPP (Point to Point Protocol, a better
-  and newer replacement for SLIP) or PLIP (Parallel Line Internet
-  Protocol is mainly used to create a mini network by connecting the
-  parallel ports of two local machines) or AX.25/KISS (protocol for
-  sending Internet traffic over amateur radio links).
-
-  Make sure to read the NET-3-HOWTO. Eventually, you will have to read
-  Olaf Kirch's excellent and free book "Network Administrator's
-  Guide", to be found in <http://www.linuxdoc.org/docs.html#guide>. If
-  unsure, say Y.
-
-CONFIG_MAGIC_SYSRQ
-  If you say Y here, you will have some control over the system even
-  if the system crashes for example during kernel debugging (e.g., you
-  will be able to flush the buffer cache to disk, reboot the system
-  immediately or dump some status information). This is accomplished
-  by pressing various keys while holding SysRq (Alt+PrintScreen). It
-  also works on a serial console (on PC hardware at least), if you
-  send a BREAK and then within 5 seconds a command keypress. The
-  keys are documented in <file:Documentation/sysrq.txt>. Don't say Y
-  unless you really know what this hack does.
-
-CONFIG_ARCH_ARCA5K
-  This selects support for 'ARM26' CPUs (ARM 2 and 3)
-
-CONFIG_ARCH_A5K
-  Say Y here to to support the Acorn A5000.  Linux can support the
-  internal IDE disk and CD-ROM interface, serial and parallel port,
-  and the floppy drive.  Note that on some A5000s the floppy is
-  plugged into the wrong socket on the motherboard.
-
-CONFIG_ARCH_ARC
-  The Acorn Archimedes was an personal computer based on an 8MHz ARM2
-  processor, released in 1987.  It supported 512K of RAM and 2 800K
-  floppy disks.  Picture and more detailed specifications at
-  <http://www.computingmuseum.com/museum/archi.htm>.
-
-CONFIG_PAGESIZE_16
-  Say Y here if your Archimedes or A5000 system has only 2MB of
-  memory, otherwise say N.  The resulting kernel will not run on a
-  machine with 4MB of memory.
-
-CONFIG_FPE_NWFPE
-  Say Y to include the NWFPE floating point emulator in the kernel.
-  This is necessary to run most binaries. Linux does not currently
-  support floating point hardware so you need to say Y here even if
-  your machine has an FPA or floating point co-processor podule.
-
-  It is also possible to say M to build the emulator as a module
-  (nwfpe.o) or indeed to leave it out altogether. However, unless you
-  know what you are doing this can easily render your machine
-  unbootable. Saying Y is the safe option.
-
-  You may say N here if you are going to load the Acorn FPEmulator
-  early in the bootup.
-
-CONFIG_FPE_FASTFPE
-  Say Y here to include the FAST floating point emulator in the kernel.
-  This is an experimental much faster emulator which now also has full
-  precision for the mantissa.  It does not support any exceptions.
-  It is very simple, and approximately 3-6 times faster than NWFPE.
-
-  It should be sufficient for most programs.  It may be not suitable
-  for scientific calculations, but you have to check this for yourself.
-  If you do not feel you need a faster FP emulation you should better
-  choose NWFPE.
-
-  It is also possible to say M to build the emulator as a module
-  (fastfpe.o).  But keep in mind that you should only load the FP
-  emulator early in the bootup.  You should never change from NWFPE to
-  FASTFPE or vice versa in an active system!
-
-CONFIG_DEBUG_ERRORS
-  This option controls verbose debugging information which can be
-  printed when the kernel detects an internal error. This debugging
-  information is useful to kernel hackers when tracking down problems,
-  but mostly meaningless to other people. It's safe to say Y unless
-  you are concerned with the code size or don't want to see these
-  messages.
-
-CONFIG_NO_FRAME_POINTER
-  If you say Y here, the resulting kernel will be slightly smaller and
-  faster. However, when a problem occurs with the kernel, the
-  information that is reported is severely limited. Most people
-  should say N here.
-
-CONFIG_DEBUG_USER
-  When a user program crashes due to an exception, the kernel can
-  print a brief message explaining what the problem was. This is
-  sometimes helpful for debugging but serves no purpose on a
-  production system. Most people should say N here.
-
-CONFIG_DEBUG_INFO
-  Say Y here to include source-level debugging information in the
-  `vmlinux' binary image. This is handy if you want to use gdb or
-  addr2line to debug the kernel. It has no impact on the in-memory
-  footprint of the running kernel but it can increase the amount of
-  time and disk space needed for compilation of the kernel. If in
-  doubt say N.
-
-CONFIG_DEBUG_LL
-  Say Y here to include definitions of printascii, printchar, printhex
-  in the kernel.  This is helpful if you are debugging code that
-  executes before the console is initialized.
-
-CONFIG_NO_PGT_CACHE
-  Normally the kernel maintains a `quicklist' of preallocated
-  pagetable structures in order to increase performance. On machines
-  with very few pages this may however be a loss. Say Y here to
-  disable the pgtable cache.
-
-CONFIG_ARTHUR
-  Say Y here to include the kernel code necessary if you want to run
-  Acorn RISC OS/Arthur binaries under Linux. This code is still very
-  experimental; if this sounds frightening, say N and sleep in peace.
-  You can also say M here to compile this support as a module (which
-  will be called arthur.o).
-
-CONFIG_CMDLINE
-  On some architectures (EBSA110 and CATS), there is currently no way
-  for the boot loader to pass arguments to the kernel. For these
-  architectures, you should supply some command-line options at build
-  time by entering them here. As a minimum, you should specify the
-  memory size and the root device (e.g., mem=64M root=/dev/nfs).
-
-CONFIG_DEBUG_KERNEL
-  Say Y here if you are developing drivers or trying to debug and
-  identify kernel problems.
-
-CONFIG_DEBUG_SLAB
-  Say Y here to have the kernel do limited verification on memory
-  allocation as well as poisoning memory on free to catch use of freed
-  memory.
-
-CONFIG_DEBUG_SPINLOCK
-  Say Y here and build SMP to catch missing spinlock initialization
-  and certain other kinds of spinlock errors commonly made.  This is
-  best used in conjunction with the NMI watchdog so that spinlock
-  deadlocks are also debuggable.
-
-CONFIG_DEBUG_BUGVERBOSE
-  Say Y here to make BUG() panics output the file name and line number
-  of the BUG call as well as the EIP and oops trace.  This aids
-  debugging but costs about 70-100K of memory.
-
-CONFIG_ZBOOT_ROM
-  Say Y here if you intend to execute your compressed kernel image (zImage)
-  directly from ROM or flash.  If unsure, say N.
-
-CONFIG_ZBOOT_ROM_TEXT
-  The base address for zImage.  Unless you have special requirements, you
-  should not change this value.
-
-CONFIG_ZBOOT_ROM_BSS
-  The base address of 64KiB of read/write memory, which must be available
-  while the decompressor is running.  Unless you have special requirements,
-  you should not change this value.
-
diff -Nru a/arch/arm26/Kconfig b/arch/arm26/Kconfig
--- a/arch/arm26/Kconfig	Tue Jun 24 22:21:45 2003
+++ b/arch/arm26/Kconfig	Sun Jul  6 16:40:01 2003
@@ -8,15 +8,8 @@
 config ARM
 	bool
 	default y
-	help
-	  The ARM series is a line of low-power-consumption RISC chip designs
-	  licensed by ARM ltd and targeted at embedded applications and
-	  handhelds such as the Compaq IPAQ.  ARM-based PCs are no longer
-	  manufactured, but  legacy ARM-based PC hardware remains popular in
-	  Europe.  There is an ARM Linux project with a web page at
-	  <http://www.arm.linux.org.uk/>.
 
-config ARCH_ARCA5K
+config ARM26
 	bool
 	default y
 
@@ -67,25 +60,25 @@
 
 config ARCH_ARC
         bool "Archimedes"
-        depends on ARCH_ARCA5K
         help
-          The Acorn Archimedes was an personal computer based on an 8K ARM2
-          processor, released in 1987.  It supported 512K of RAM and 2 800K
-          floppy disks.  Picture and more detailed specifications at
-          <http://www.computingmuseum.com/museum/archi.htm>.
+          Say Y to support the Acorn Archimedes.
+	  
+	  The Acorn Archimedes was an personal computer based on an 8MHz ARM2
+          processor, released in 1987.  It supported up to 16MB of RAM in
+	  later models and floppy, harddisc, ethernet etc.
 
 config ARCH_A5K
         bool "A5000"
-        depends on ARCH_ARCA5K
         help
-          Say Y here to to support the Acorn A5000.  Linux can support the
+          Say Y here to to support the Acorn A5000.
+	  
+	  Linux can support the
           internal IDE disk and CD-ROM interface, serial and parallel port,
           and the floppy drive.  Note that on some A5000s the floppy is
           plugged into the wrong socket on the motherboard.
 
 config PAGESIZE_16
-        bool "2MB physical memory"
-        depends on ARCH_ARCA5K
+        bool "2MB physical memory (broken)"
         help
           Say Y here if your Archimedes or A5000 system has only 2MB of
           memory, otherwise say N.  The resulting kernel will not run on a
@@ -186,81 +179,7 @@
 
 endchoice
 
-config BINFMT_AOUT
-	tristate "Kernel support for a.out binaries"
-	---help---
-	  A.out (Assembler.OUTput) is a set of formats for libraries and
-	  executables used in the earliest versions of UNIX. Linux used the
-	  a.out formats QMAGIC and ZMAGIC until they were replaced with the
-	  ELF format.
-
-	  As more and more programs are converted to ELF, the use for a.out
-	  will gradually diminish. If you disable this option it will reduce
-	  your kernel by one page. This is not much and by itself does not
-	  warrant removing support. However its removal is a good idea if you
-	  wish to ensure that absolutely none of your programs will use this
-	  older executable format. If you don't know what to answer at this
-	  point then answer Y. If someone told you "You need a kernel with
-	  QMAGIC support" then you'll have to say Y here. You may answer M to
-	  compile a.out support as a module and later load the module when you
-	  want to use a program or library in a.out format. The module will be
-	  called binfmt_aout. Saying M or N here is dangerous though,
-	  because some crucial programs on your system might still be in A.OUT
-	  format.
-
-config BINFMT_ELF
-	tristate "Kernel support for ELF binaries"
-	---help---
-	  ELF (Executable and Linkable Format) is a format for libraries and
-	  executables used across different architectures and operating
-	  systems. Saying Y here will enable your kernel to run ELF binaries
-	  and enlarge it by about 13 KB. ELF support under Linux has now all
-	  but replaced the traditional Linux a.out formats (QMAGIC and ZMAGIC)
-	  because it is portable (this does *not* mean that you will be able
-	  to run executables from different architectures or operating systems
-	  however) and makes building run-time libraries very easy. Many new
-	  executables are distributed solely in ELF format. You definitely
-	  want to say Y here.
-
-	  Information about ELF is contained in the ELF HOWTO available from
-	  <http://www.linuxdoc.org/docs.html#howto>.
-
-	  If you find that after upgrading from Linux kernel 1.2 and saying Y
-	  here, you still can't run any ELF binaries (they just crash), then
-	  you'll have to install the newest ELF runtime libraries, including
-	  ld.so (check the file <file:Documentation/Changes> for location and
-	  latest version).
-
-	  If you want to compile this as a module ( = code which can be
-	  inserted in and removed from the running kernel whenever you want),
-	  say M here and read <file:Documentation/modules.txt>.  The module
-	  will be called binfmt_elf. Saying M or N here is dangerous because
-	  some crucial programs on your system might be in ELF format.
-
-config BINFMT_MISC
-	tristate "Kernel support for MISC binaries"
-	---help---
-	  If you say Y here, it will be possible to plug wrapper-driven binary
-	  formats into the kernel. You will like this especially when you use
-	  programs that need an interpreter to run like Java, Python or
-	  Emacs-Lisp. It's also useful if you often run DOS executables under
-	  the Linux DOS emulator DOSEMU (read the DOSEMU-HOWTO, available from
-	  <http://www.linuxdoc.org/docs.html#howto>). Once you have
-	  registered such a binary class with the kernel, you can start one of
-	  those programs simply by typing in its name at a shell prompt; Linux
-	  will automatically feed it to the correct interpreter.
-
-	  You can do other nice things, too. Read the file
-	  <file:Documentation/binfmt_misc.txt> to learn how to use this
-	  feature, and <file:Documentation/java.txt> for information about how
-	  to include Java support.
-
-	  You must say Y to "/proc file system support" (CONFIG_PROC_FS) to
-	  use this part of the kernel.
-
-	  You may say M here for module support and later load the module when
-	  you have use for it; the module is called binfmt_misc. If you
-	  don't know what to answer at this point, say Y.
+source "fs/Kconfig.binfmt"
 
 config PREEMPT
 	bool "Preemptible Kernel (EXPERIMENTAL)"
@@ -311,58 +230,7 @@
 
 source "net/irda/Kconfig"
 
-menu "ATA/ATAPI/MFM/RLL support"
-
-config IDE
-	tristate "ATA/ATAPI/MFM/RLL support"
-	---help---
-	  If you say Y here, your kernel will be able to manage low cost mass
-	  storage units such as ATA/(E)IDE and ATAPI units. The most common
-	  cases are IDE hard drives and ATAPI CD-ROM drives.
-
-	  If your system is pure SCSI and doesn't use these interfaces, you
-	  can say N here.
-
-	  Integrated Disk Electronics (IDE aka ATA-1) is a connecting standard
-	  for mass storage units such as hard disks. It was designed by
-	  Western Digital and Compaq Computer in 1984. It was then named
-	  ST506. Quite a number of disks use the IDE interface.
-
-	  AT Attachment (ATA) is the superset of the IDE specifications.
-	  ST506 was also called ATA-1.
-
-	  Fast-IDE is ATA-2 (also named Fast ATA), Enhanced IDE (EIDE) is
-	  ATA-3. It provides support for larger disks (up to 8.4GB by means of
-	  the LBA standard), more disks (4 instead of 2) and for other mass
-	  storage units such as tapes and cdrom. UDMA/33 (aka UltraDMA/33) is
-	  ATA-4 and provides faster (and more CPU friendly) transfer modes
-	  than previous PIO (Programmed processor Input/Output) from previous
-	  ATA/IDE standards by means of fast DMA controllers.
-
-	  ATA Packet Interface (ATAPI) is a protocol used by EIDE tape and
-	  CD-ROM drives, similar in many respects to the SCSI protocol.
-
-	  SMART IDE (Self Monitoring, Analysis and Reporting Technology) was
-	  designed in order to prevent data corruption and disk crash by
-	  detecting pre hardware failure conditions (heat, access time, and
-	  the like...). Disks built since June 1995 may follow this standard.
-	  The kernel itself don't manage this; however there are quite a
-	  number of user programs such as smart that can query the status of
-	  SMART parameters disk.
-
-	  If you want to compile this driver as a module ( = code which can be
-	  inserted in and removed from the running kernel whenever you want),
-	  say M here and read <file:Documentation/modules.txt>. The module
-	  will be called ide.
-
-	  For further information, please read <file:Documentation/ide.txt>.
-
-	  If unsure, say Y.
-
 source "drivers/ide/Kconfig"
-
-endmenu
-
 
 source "drivers/scsi/Kconfig"
 
diff -Nru a/arch/arm26/config.in b/arch/arm26/config.in
--- a/arch/arm26/config.in	Wed Jun  4 04:15:45 2003
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,151 +0,0 @@
-#
-# For a description of the syntax of this configuration file,
-# see Documentation/kbuild/config-language.txt.
-#
-mainmenu_name "Linux Kernel Configuration"
-
-define_bool CONFIG_ARM y
-define_bool CONFIG_EISA n
-define_bool CONFIG_SBUS n
-define_bool CONFIG_MCA n
-define_bool CONFIG_UID16 y
-define_bool CONFIG_RWSEM_GENERIC_SPINLOCK y
-define_bool CONFIG_RWSEM_XCHGADD_ALGORITHM n
-define_bool CONFIG_GENERIC_BUST_SPINLOCK n
-define_bool CONFIG_GENERIC_ISA_DMA n
-
-source init/Config.in
-
-mainmenu_option next_comment
-comment 'System Type'
-
-define_bool CONFIG_ARCH_ARCA5K
-bool '  Archimedes' CONFIG_ARCH_ARC
-bool '  A5000' CONFIG_ARCH_A5K
-
-# Definitions to make life easier
-define_bool CONFIG_ARCH_ACORN y
-define_bool CONFIG_CPU_32 n
-define_bool CONFIG_CPU_26 y
-bool '2MB physical memory' CONFIG_PAGESIZE_16
-
-endmenu
-
-mainmenu_option next_comment
-comment 'General setup'
-
-define_bool CONFIG_FIQ y
-
-# Compressed boot loader in ROM.  Yes, we really want to ask about
-# TEXT and BSS so we preserve their values in the config files.
-bool 'Compressed boot loader in ROM/flash' CONFIG_ZBOOT_ROM
-hex 'Compressed ROM boot loader base address' CONFIG_ZBOOT_ROM_TEXT 0
-hex 'Compressed ROM boot loader BSS address' CONFIG_ZBOOT_ROM_BSS 0
-
-comment 'At least one math emulation must be selected'
-define_bool CONFIG_FPE_NWFPE y
-choice 'Kernel core (/proc/kcore) format' \
-	"ELF		CONFIG_KCORE_ELF	\
-	 A.OUT		CONFIG_KCORE_AOUT" ELF
-tristate 'Kernel support for a.out binaries' CONFIG_BINFMT_AOUT
-tristate 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF
-tristate 'Kernel support for MISC binaries' CONFIG_BINFMT_MISC
-string 'Default kernel command string' CONFIG_CMDLINE ""
-
-define_bool CONFIG_ALIGNMENT_TRAP n
-endmenu
-
-source drivers/parport/Config.in
-source drivers/pnp/Config.in
-source drivers/block/Config.in
-source drivers/md/Config.in
-source drivers/acorn/block/Config.in
-
-if [ "$CONFIG_NET" = "y" ]; then
-   source net/Config.in
-
-   mainmenu_option next_comment
-   comment 'Network device support'
-
-   bool 'Network device support' CONFIG_NETDEVICES
-   if [ "$CONFIG_NETDEVICES" = "y" ]; then
-      source drivers/net/Config.in
-   fi
-   endmenu
-fi
-
-mainmenu_option next_comment
-comment 'ATA/ATAPI/MFM/RLL support'
-
-tristate 'ATA/ATAPI/MFM/RLL support' CONFIG_IDE
-
-if [ "$CONFIG_IDE" != "n" ]; then
-  source drivers/ide/Config.in
-else
-  define_bool CONFIG_BLK_DEV_HD n
-fi
-endmenu
-
-mainmenu_option next_comment
-comment 'SCSI support'
-
-tristate 'SCSI support' CONFIG_SCSI
-endmenu
-
-source drivers/isdn/Config.in
-
-#
-# input before char - char/joystick depends on it. As does USB.
-#
-source drivers/input/Config.in
-
-source drivers/char/Config.in
-if [ "$CONFIG_BUSMOUSE" = "y" ]; then
-   define_bool CONFIG_KBDMOUSE y
-fi
-
-source drivers/media/Config.in
-
-source fs/Config.in
-
-if [ "$CONFIG_VT" = "y" ]; then
-   mainmenu_option next_comment
-   comment 'Console drivers'
-   source drivers/video/Config.in
-   endmenu
-fi
-
-mainmenu_option next_comment
-comment 'Sound'
-
-tristate 'Sound card support' CONFIG_SOUND
-if [ "$CONFIG_SOUND" != "n" ]; then
-   source sound/Config.in
-fi
-endmenu
-
-source drivers/misc/Config.in
-source drivers/usb/Config.in
-
-mainmenu_option next_comment
-comment 'Kernel hacking'
-
-# Always compile kernel with framepointer (until 2.4 real comes out)
-# Bug reports aren't much use without this.
-bool 'Compile kernel without frame pointer' CONFIG_NO_FRAME_POINTER
-bool 'Verbose user fault messages' CONFIG_DEBUG_USER
-bool 'Include debugging information in kernel binary' CONFIG_DEBUG_INFO
-
-bool 'Kernel debugging' CONFIG_DEBUG_KERNEL
-dep_bool '  Debug memory allocations' CONFIG_DEBUG_SLAB $CONFIG_DEBUG_KERNEL
-dep_bool '  Magic SysRq key' CONFIG_MAGIC_SYSRQ $CONFIG_DEBUG_KERNEL
-dep_bool '  Spinlock debugging' CONFIG_DEBUG_SPINLOCK $CONFIG_DEBUG_KERNEL
-dep_bool '  Wait queue debugging' CONFIG_DEBUG_WAITQ $CONFIG_DEBUG_KERNEL
-dep_bool '  Verbose BUG() reporting (adds 70K)' CONFIG_DEBUG_BUGVERBOSE $CONFIG_DEBUG_KERNEL
-dep_bool '  Verbose kernel error messages' CONFIG_DEBUG_ERRORS $CONFIG_DEBUG_KERNEL
-# These options are only for real kernel hackers who want to get their hands dirty. 
-dep_bool '  Kernel low-level debugging functions' CONFIG_DEBUG_LL $CONFIG_DEBUG_KERNEL
-endmenu
-
-source security/Config.in
-source lib/Config.in
diff -Nru a/arch/arm26/kernel/Makefile b/arch/arm26/kernel/Makefile
--- a/arch/arm26/kernel/Makefile	Wed Jun  4 04:15:45 2003
+++ b/arch/arm26/kernel/Makefile	Sun Jul  6 16:40:01 2003
@@ -6,7 +6,7 @@
 
 # Object file lists.
 
-obj-y		:= arch.o compat.o dma.o entry.o irq.o   \
+obj-y		:= compat.o dma.o entry.o irq.o   \
 		   process.o ptrace.o semaphore.o setup.o signal.o sys_arm.o \
 		   time.o traps.o ecard.o time-acorn.o dma.o \
 		   ecard.o fiq.o time.o
diff -Nru a/arch/arm26/kernel/arch.c b/arch/arm26/kernel/arch.c
--- a/arch/arm26/kernel/arch.c	Wed Jun  4 04:15:45 2003
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,30 +0,0 @@
-/* 
- *  linux/arch/arm/kernel/arch.c
- *
- *  Architecture specific fixups.
- */
-#include <linux/config.h>
-#include <linux/init.h>
-#include <linux/types.h>
-
-#include <asm/elf.h>
-#include <asm/setup.h>
-#include <asm/mach-types.h>
-#include <asm/arch.h>
-#include <asm/page.h>
-
-unsigned int vram_size;
-
-
-unsigned int memc_ctrl_reg;
-unsigned int number_mfm_drives;
-
-static int __init parse_tag_acorn(const struct tag *tag)
-{
-	memc_ctrl_reg = tag->u.acorn.memc_control_reg;
-	number_mfm_drives = tag->u.acorn.adfsdrives;
-	return 0;
-}
-
-__tagtable(ATAG_ACORN, parse_tag_acorn);
-
diff -Nru a/arch/arm26/kernel/asm-offsets.c b/arch/arm26/kernel/asm-offsets.c
--- a/arch/arm26/kernel/asm-offsets.c	Wed Jun  4 04:15:45 2003
+++ b/arch/arm26/kernel/asm-offsets.c	Sun Jul  6 16:40:01 2003
@@ -1,7 +1,7 @@
 /*
  * Copyright (C) 1995-2001 Russell King
  *               2001-2002 Keith Owens
- *               2003-?    Ian Molton
+ *               2003      Ian Molton
  *     
  * Generate definitions needed by assembly language modules.
  * This code generates raw asm output which is post-processed to extract
diff -Nru a/arch/arm26/kernel/compat.c b/arch/arm26/kernel/compat.c
--- a/arch/arm26/kernel/compat.c	Wed Jun  4 04:15:45 2003
+++ b/arch/arm26/kernel/compat.c	Sun Jul  6 16:42:49 2003
@@ -26,7 +26,7 @@
 #include <asm/mach-types.h>
 #include <asm/page.h>
 
-#include <asm/arch.h>
+//#include <asm/arch.h>
 //#include <asm/mach/irq.h>
 
 /*
diff -Nru a/arch/arm26/kernel/dma.c b/arch/arm26/kernel/dma.c
--- a/arch/arm26/kernel/dma.c	Wed Jun  4 04:15:45 2003
+++ b/arch/arm26/kernel/dma.c	Sun Jul  6 16:40:01 2003
@@ -2,7 +2,7 @@
  *  linux/arch/arm/kernel/dma.c
  *
  *  Copyright (C) 1995-2000 Russell King
- *                2003-?    Ian Molton
+ *                2003      Ian Molton
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
diff -Nru a/arch/arm26/kernel/ecard.c b/arch/arm26/kernel/ecard.c
--- a/arch/arm26/kernel/ecard.c	Wed Jun  4 04:15:45 2003
+++ b/arch/arm26/kernel/ecard.c	Sun Jul  6 16:40:01 2003
@@ -11,9 +11,8 @@
  *  Find all installed expansion cards, and handle interrupts from them.
  *
  *  Created from information from Acorns RiscOS3 PRMs
- *
- *  08-Dec-1996	RMK	Added code for the 9'th expansion card - the ether
- *			podule slot.
+ *  15-Jun-2003 IM      Modified from ARM32 (RiscPC capable) version
+ *  10-Jan-1999	RMK	Run loaders in a simulated RISC OS environment.
  *  06-May-1997	RMK	Added blacklist for cards whose loader doesn't work.
  *  12-Sep-1997	RMK	Created new handling of interrupt enables/disables
  *			- cards can now register their own routine to control
@@ -21,10 +20,7 @@
  *  29-Sep-1997	RMK	Expansion card interrupt hardware not being re-enabled
  *			on reset from Linux. (Caused cards not to respond
  *			under RiscOS without hard reset).
- *  15-Feb-1998	RMK	Added DMA support
- *  12-Sep-1998	RMK	Added EASI support
- *  10-Jan-1999	RMK	Run loaders in a simulated RISC OS environment.
- *  17-Apr-1999	RMK	Support for EASI Type C cycles.
+ *
  */
 #define ECARD_C
 
@@ -527,8 +523,7 @@
 {
 	char *start = buffer;
 
-	buffer += sprintf(buffer, "  %d: %s ", ec->slot_no,
-			  ec->type == ECARD_EASI ? "EASI" : "    ");
+	buffer += sprintf(buffer, "  %d: ", ec->slot_no);
 
 	if (ec->cid.id == 0) {
 		struct in_chunk_dir incd;
@@ -674,7 +669,7 @@
 	memset(ec, 0, sizeof(ecard_t));
 
 	ec->slot_no	= slot;
-	ec->type	= type;
+	ec->type        = type;
 	ec->irq		= NO_IRQ;
 	ec->fiq		= NO_IRQ;
 	ec->dma		= NO_DMA;
@@ -770,9 +765,8 @@
 
 	printk("Probing expansion cards\n");
 
-	for (slot = 0; slot < 8; slot ++) {
-		if (ecard_probe(slot, ECARD_EASI) == -ENODEV)
-			ecard_probe(slot, ECARD_IOC);
+	for (slot = 0; slot < 4; slot ++) {
+		ecard_probe(slot, ECARD_IOC);
 	}
 
 	irqhw = ecard_probeirqhw();
diff -Nru a/arch/arm26/kernel/irq.c b/arch/arm26/kernel/irq.c
--- a/arch/arm26/kernel/irq.c	Wed Jun  4 04:15:45 2003
+++ b/arch/arm26/kernel/irq.c	Sun Jul  6 16:40:01 2003
@@ -41,7 +41,7 @@
  * not be set too low to prevent false triggering.  Conversely, if it
  * is set too high, then you could miss a stuck IRQ.
  *
- * Maybe we ought to set a timer and re-enable the IRQ at a later time?
+ * FIXME Maybe we ought to set a timer and re-enable the IRQ at a later time?
  */
 #define MAX_IRQ_CNT	100000
 
@@ -49,7 +49,6 @@
 static spinlock_t irq_controller_lock = SPIN_LOCK_UNLOCKED;
 
 struct irqdesc irq_desc[NR_IRQS];
-void (*init_arch_irq)(void) __initdata = NULL;
 
 /*
  * Dummy mask/unmask handler
@@ -88,7 +87,6 @@
 {
 	struct irqdesc *desc = irq_desc + irq;
 	unsigned long flags;
-
 	spin_lock_irqsave(&irq_controller_lock, flags);
 	if (!desc->depth++)
 		desc->enabled = 0;
@@ -114,7 +112,7 @@
 	spin_lock_irqsave(&irq_controller_lock, flags);
 	if (unlikely(!desc->depth)) {
 		printk("enable_irq(%u) unbalanced from %p\n", irq,
-			__builtin_return_address(0));
+			__builtin_return_address(0)); //FIXME bum addresses reported - why?
 	} else if (!--desc->depth) {
 		desc->probing = 0;
 		desc->enabled = 1;
@@ -187,7 +185,6 @@
 	unsigned int status;
 
 	spin_unlock(&irq_controller_lock);
-
 	if (!(action->flags & SA_INTERRUPT))
 		local_irq_enable();
 
@@ -700,6 +697,6 @@
 	for (irq = 0, desc = irq_desc; irq < NR_IRQS; irq++, desc++)
 		*desc = bad_irq_desc;
 
-	init_arch_irq();
+	arc_init_irq();
 	init_dma();
 }
diff -Nru a/arch/arm26/kernel/process.c b/arch/arm26/kernel/process.c
--- a/arch/arm26/kernel/process.c	Wed Jun  4 04:15:45 2003
+++ b/arch/arm26/kernel/process.c	Sun Jul  6 16:40:01 2003
@@ -227,7 +227,9 @@
 #define ll_alloc_task_struct()	((struct thread_info *)get_page_8k(GFP_KERNEL))
 #define ll_free_task_struct(p)  free_page_8k((unsigned long)(p))
 
-struct thread_info *alloc_thread_info(void)
+//FIXME - do we use *task param below looks like we dont, which is ok?
+//FIXME - if EXTRA_TASK_STRUCT is zero we can optimise the below away permanently. *IF* its supposed to be zero.
+struct thread_info *alloc_thread_info(struct task_struct *task)
 {
 	struct thread_info *thread = NULL;
 
diff -Nru a/arch/arm26/kernel/setup.c b/arch/arm26/kernel/setup.c
--- a/arch/arm26/kernel/setup.c	Wed Jun  4 04:15:45 2003
+++ b/arch/arm26/kernel/setup.c	Sun Jul  6 16:40:01 2003
@@ -30,7 +30,6 @@
 #include <asm/mach-types.h>
 #include <asm/tlbflush.h>
 
-#include <asm/arch.h>
 #include <asm/irqchip.h>
 
 #ifndef MEM_SIZE
@@ -66,6 +65,8 @@
 unsigned int system_serial_low;
 unsigned int system_serial_high;
 unsigned int elf_hwcap;
+unsigned int memc_ctrl_reg;
+unsigned int number_mfm_drives;
 
 struct processor processor;
 
@@ -147,33 +148,6 @@
 	cpu_proc_init();
 }
 
-static struct machine_desc * __init setup_machine(unsigned int nr)
-{
-	extern struct machine_desc __arch_info_begin, __arch_info_end;
-	struct machine_desc *list;
-
-	/*
-	 * locate architecture in the list of supported architectures.
-	 */
-	for (list = &__arch_info_begin; list < &__arch_info_end; list++)
-		if (list->nr == nr)
-			break;
-
-	/*
-	 * If the architecture type is not recognised, then we
-	 * can co nothing...
-	 */
-	if (list >= &__arch_info_end) {
-		printk("Architecture configuration botched (nr %d), unable "
-		       "to continue.\n", nr);
-		while (1);
-	}
-
-	printk("Machine: %s\n", list->name);
-
-	return list;
-}
-
 /*
  * Initial parsing of the command line.  We need to pick out the
  * memory size.  We look for mem=size@start, where start and size
@@ -239,7 +213,7 @@
 }
 
 static void __init
-request_standard_resources(struct meminfo *mi, struct machine_desc *mdesc)
+request_standard_resources(struct meminfo *mi)
 {
 	struct resource *res;
 	int i;
@@ -274,22 +248,18 @@
 			request_resource(res, &kernel_data);
 	}
 
-	if (mdesc->video_start) {
+/*	FIXME - needed? if (mdesc->video_start) {
 		video_ram.start = mdesc->video_start;
 		video_ram.end   = mdesc->video_end;
 		request_resource(&iomem_resource, &video_ram);
-	}
+	}*/
 
 	/*
 	 * Some machines don't have the possibility of ever
-	 * possessing lp0, lp1 or lp2
+	 * possessing lp1 or lp2
 	 */
-	if (mdesc->reserve_lp0)
+	if (0)  /* FIXME - need to do this for A5k at least */
 		request_resource(&ioport_resource, &lp0);
-	if (mdesc->reserve_lp1)
-		request_resource(&ioport_resource, &lp1);
-	if (mdesc->reserve_lp2)
-		request_resource(&ioport_resource, &lp2);
 }
 
 /*
@@ -359,6 +329,15 @@
 __tagtable(ATAG_VIDEOTEXT, parse_tag_videotext);
 #endif
 
+static int __init parse_tag_acorn(const struct tag *tag)
+{
+        memc_ctrl_reg = tag->u.acorn.memc_control_reg;
+        number_mfm_drives = tag->u.acorn.adfsdrives;
+        return 0;
+}
+
+__tagtable(ATAG_ACORN, parse_tag_acorn);
+
 static int __init parse_tag_ramdisk(const struct tag *tag)
 {
 	setup_ramdisk((tag->u.ramdisk.flags & 1) == 0,
@@ -467,15 +446,18 @@
 void __init setup_arch(char **cmdline_p)
 {
 	struct tag *tags = (struct tag *)&init_tags;
-	struct machine_desc *mdesc;
 	char *from = default_command_line;
 
 	setup_processor();
-	mdesc = setup_machine(machine_arch_type);
-	machine_name = mdesc->name;
+	if(machine_arch_type == MACH_TYPE_A5K)
+		machine_name = "A5000";
+	else if(machine_arch_type == MACH_TYPE_ARCHIMEDES)
+		machine_name = "Archimedes";
+	else
+		machine_name = "UNKNOWN";
 
-	if (mdesc->param_offset)
-		tags = (struct tag *)mdesc->param_offset; //FIXME - ugly?
+	//FIXME - this may need altering when we get ROM images working
+	tags = (struct tag *)0x0207c000;
 
 	/*
 	 * If we have the old style parameters, convert them to
@@ -501,12 +483,7 @@
 	parse_cmdline(&meminfo, cmdline_p, from);
 	bootmem_init(&meminfo);
 	paging_init(&meminfo);
-	request_standard_resources(&meminfo, mdesc);
-
-	/*
-	 * Set up various architecture-specific pointers
-	 */
-	init_arch_irq = mdesc->init_irq;
+	request_standard_resources(&meminfo);
 
 #ifdef CONFIG_VT
 #if defined(CONFIG_DUMMY_CONSOLE)
diff -Nru a/arch/arm26/kernel/traps.c b/arch/arm26/kernel/traps.c
--- a/arch/arm26/kernel/traps.c	Sat Jun  7 13:19:02 2003
+++ b/arch/arm26/kernel/traps.c	Sun Jul  6 16:40:01 2003
@@ -175,6 +175,11 @@
 	}
 }
 
+/* FIXME - this is probably wrong.. */
+void show_stack(struct task_struct *task, unsigned long *sp) {
+	dump_mem("Stack: ", (unsigned long)sp, 8192+(unsigned long)task->thread_info);
+}
+
 spinlock_t die_lock = SPIN_LOCK_UNLOCKED;
 
 /*
@@ -497,7 +502,7 @@
 	die_if_kernel("unknown data abort code", regs, instr);
 }
 
-void __bug(const char *file, int line, void *data)
+volatile void __bug(const char *file, int line, void *data)
 {
 	printk(KERN_CRIT"kernel BUG at %s:%d!", file, line);
 	if (data)
diff -Nru a/arch/arm26/lib/Makefile b/arch/arm26/lib/Makefile
--- a/arch/arm26/lib/Makefile	Wed Jun  4 04:15:45 2003
+++ b/arch/arm26/lib/Makefile	Sun Jul  6 16:40:01 2003
@@ -4,9 +4,7 @@
 # Copyright (C) 1995-2000 Russell King
 #
 
-L_TARGET	:= lib.a
-
-obj-y		:= backtrace.o changebit.o csumipv6.o csumpartial.o   \
+lib-y		:= backtrace.o changebit.o csumipv6.o csumpartial.o   \
 		   csumpartialcopy.o csumpartialcopyuser.o clearbit.o \
 		   copy_page.o delay.o findbit.o memchr.o memcpy.o    \
 		   memset.o memzero.o setbit.o    \
@@ -16,15 +14,12 @@
 		   ucmpdi2.o udivdi3.o lib1funcs.o ecard.o io-acorn.o \
 		   floppydma.o io-readsb.o io-writesb.o io-writesl.o  \
 		   uaccess-kernel.o uaccess-user.o io-readsw-armv3.o  \
-		   io-writesw-armv3.o io-readsl-armv3.o
-
-obj-m		:=
-obj-n		:=
-
-obj-$(CONFIG_VT)+= kbd.o
+		   io-writesw-armv3.o io-readsl-armv3.o ecard.o       \
+		   io-acorn.o floppydma.o
 
-obj-y		+= ecard.o io-acorn.o floppydma.o
+lib-n		:=
 
+lib-$(CONFIG_VT)+= kbd.o
 
 csumpartialcopy.o: csumpartialcopygeneric.S
 csumpartialcopyuser.o: csumpartialcopygeneric.S
diff -Nru a/arch/arm26/machine/Makefile b/arch/arm26/machine/Makefile
--- a/arch/arm26/machine/Makefile	Wed Jun  4 04:15:45 2003
+++ b/arch/arm26/machine/Makefile	Sun Jul  6 16:40:01 2003
@@ -4,7 +4,7 @@
 
 # Object file lists.
 
-obj-y			:= arch.o dma.o irq.o oldlatches.o \
+obj-y			:= dma.o irq.o oldlatches.o \
 			   small_page.o
 
 extra-y 		:= head.o
diff -Nru a/arch/arm26/machine/arch.c b/arch/arm26/machine/arch.c
--- a/arch/arm26/machine/arch.c	Wed Jun  4 04:15:45 2003
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,36 +0,0 @@
-/*
- *  linux/arch/arm26/mach-arc/arch.c
- *
- *  Copyright (C) 1998-2001 Russell King
- *  Copyright (C) 2003 Ian Molton
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- *  Architecture specific fixups.
- */
-#include <linux/config.h>
-#include <linux/tty.h>
-#include <linux/init.h>
-
-#include <asm/mach-types.h>
-#include <asm/hardware.h>
-#include <asm/page.h>
-#include <asm/setup.h>
-
-#include <asm/map.h>
-#include <asm/arch.h>
-
-extern void arc_init_irq(void);
-
-#ifdef CONFIG_ARCH_ARC
-MACHINE_START(ARCHIMEDES, "Acorn-Archimedes")
-#elif defined(CONFIG_ARCH_A5K)
-MACHINE_START(A5K, "Acorn-A5000")
-#endif
-	MAINTAINER("Ian Molton")
-	BOOT_PARAMS(0x0207c000)
-	INITIRQ(arc_init_irq)
-MACHINE_END
-
diff -Nru a/arch/arm26/machine/irq.c b/arch/arm26/machine/irq.c
--- a/arch/arm26/machine/irq.c	Wed Jun  4 04:15:45 2003
+++ b/arch/arm26/machine/irq.c	Sun Jul  6 16:40:01 2003
@@ -73,7 +73,6 @@
 static void arc_mask_irq_b(unsigned int irq)
 {
 	unsigned int val, mask;
-
 	mask = 1 << (irq & 7);
 	val = ioc_readb(IOC_IRQMASKB);
 	ioc_writeb(val & ~mask, IOC_IRQMASKB);
@@ -94,7 +93,7 @@
         .unmask = arc_unmask_irq_b,
 };
 
-/* FIXME - JMA none of these functions are used in arm26
+/* FIXME - JMA none of these functions are used in arm26 currently
 static void arc_mask_irq_fiq(unsigned int irq)
 {
 	unsigned int val, mask;
@@ -124,6 +123,7 @@
 {
 	unsigned int irq, flags;
 
+	/* Disable all IOC interrupt sources */
 	ioc_writeb(0, IOC_IRQMASKA);
 	ioc_writeb(0, IOC_IRQMASKB);
 	ioc_writeb(0, IOC_FIQMASK);
diff -Nru a/arch/arm26/mm/init.c b/arch/arm26/mm/init.c
--- a/arch/arm26/mm/init.c	Wed Jun  4 04:15:46 2003
+++ b/arch/arm26/mm/init.c	Sun Jul  6 17:01:11 2003
@@ -32,7 +32,7 @@
 #include <asm/setup.h>
 #include <asm/tlb.h>
 
-#include <asm/arch.h>
+//#include <asm/arch.h>
 #include <asm/map.h>
 
 #define TABLE_SIZE	PTRS_PER_PTE * sizeof(pte_t))
@@ -68,7 +68,7 @@
 
 
 	page = NODE_MEM_MAP(0);
-	end  = page + NODE_DATA(0)->node_size;
+	end  = page + NODE_DATA(0)->node_spanned_pages;
 
 	do {
 		total++;
@@ -353,7 +353,7 @@
 	max_mapnr   = virt_to_page(high_memory) - mem_map;
 
 	/* this will put all unused low memory onto the freelists */
-	if (pgdat->node_size != 0)
+	if (pgdat->node_spanned_pages != 0)
 		totalram_pages += free_all_bootmem_node(pgdat);
 
 	printk(KERN_INFO "Memory:");
diff -Nru a/arch/arm26/mm/mm-memc.c b/arch/arm26/mm/mm-memc.c
--- a/arch/arm26/mm/mm-memc.c	Thu Jun  5 16:15:01 2003
+++ b/arch/arm26/mm/mm-memc.c	Sun Jul  6 16:40:01 2003
@@ -70,11 +70,9 @@
 
 pgd_t *get_pgd_slow(struct mm_struct *mm)
 {
-	void *pg2k;
 	pgd_t *new_pgd, *init_pgd;
 	pmd_t *new_pmd, *init_pmd;
 	pte_t *new_pte, *init_pte;
-	struct mm_struct bob;
 
 	new_pgd = alloc_pgd_table();
 	if (!new_pgd)
diff -Nru a/arch/cris/mm/tlb.c b/arch/cris/mm/tlb.c
--- a/arch/cris/mm/tlb.c	Tue Feb 25 02:40:27 2003
+++ b/arch/cris/mm/tlb.c	Sun Jul  6 18:51:59 2003
@@ -283,7 +283,7 @@
 
 void 
 switch_mm(struct mm_struct *prev, struct mm_struct *next,
-	  struct task_struct *tsk, int cpu)
+	  struct task_struct *tsk)
 {
 	/* make sure we have a context */
 
diff -Nru a/arch/i386/Kconfig b/arch/i386/Kconfig
--- a/arch/i386/Kconfig	Thu Jun 26 23:05:44 2003
+++ b/arch/i386/Kconfig	Wed Jul  2 21:19:42 2003
@@ -1339,6 +1339,14 @@
 	  best used in conjunction with the NMI watchdog so that spinlock
 	  deadlocks are also debuggable.
 
+config DEBUG_PAGEALLOC
+	bool "Page alloc debugging"
+	depends on DEBUG_KERNEL
+	help
+	  Unmap pages from the kernel linear mapping after free_pages().
+	  This results in a large slowdown, but helps to find certain types
+	  of memory corruptions.
+
 config DEBUG_HIGHMEM
 	bool "Highmem debugging"
 	depends on DEBUG_KERNEL && HIGHMEM
diff -Nru a/arch/i386/kernel/cpu/common.c b/arch/i386/kernel/cpu/common.c
--- a/arch/i386/kernel/cpu/common.c	Sun Mar 23 07:55:48 2003
+++ b/arch/i386/kernel/cpu/common.c	Sun Jul  6 18:51:59 2003
@@ -430,6 +430,14 @@
 	rise_init_cpu();
 	nexgen_init_cpu();
 	umc_init_cpu();
+
+#ifdef CONFIG_DEBUG_PAGEALLOC
+	/* pse is not compatible with on-the-fly unmapping,
+	 * disable it even if the cpus claim to support it.
+	 */
+	clear_bit(X86_FEATURE_PSE, boot_cpu_data.x86_capability);
+	disable_pse = 1;
+#endif
 }
 /*
  * cpu_init() initializes state that is per-CPU. Some data is already
@@ -487,7 +495,7 @@
 	current->active_mm = &init_mm;
 	if (current->mm)
 		BUG();
-	enter_lazy_tlb(&init_mm, current, cpu);
+	enter_lazy_tlb(&init_mm, current);
 
 	load_esp0(t, thread->esp0);
 	set_tss_desc(cpu,t);
diff -Nru a/arch/i386/kernel/cpu/cpufreq/powernow-k7.c b/arch/i386/kernel/cpu/cpufreq/powernow-k7.c
--- a/arch/i386/kernel/cpu/cpufreq/powernow-k7.c	Sun Jun 15 09:11:36 2003
+++ b/arch/i386/kernel/cpu/cpufreq/powernow-k7.c	Fri Jul  4 11:56:18 2003
@@ -268,8 +268,8 @@
 		change_VID(vid);
 	} else {
 		/* Going up, so change VID first */
-		change_VID(fid);
-		change_FID(vid);
+		change_VID(vid);
+		change_FID(fid);
 	}
 	
 
diff -Nru a/arch/i386/kernel/entry.S b/arch/i386/kernel/entry.S
--- a/arch/i386/kernel/entry.S	Fri Jun 20 13:16:06 2003
+++ b/arch/i386/kernel/entry.S	Mon Jul  7 12:36:55 2003
@@ -876,5 +876,6 @@
  	.long sys_clock_nanosleep
 	.long sys_statfs64
 	.long sys_fstatfs64	
+	.long sys_tgkill
  
 nr_syscalls=(.-sys_call_table)/4
diff -Nru a/arch/i386/kernel/io_apic.c b/arch/i386/kernel/io_apic.c
--- a/arch/i386/kernel/io_apic.c	Thu Jun 26 21:46:00 2003
+++ b/arch/i386/kernel/io_apic.c	Wed Jul  2 21:21:32 2003
@@ -35,6 +35,7 @@
 #include <asm/io.h>
 #include <asm/smp.h>
 #include <asm/desc.h>
+#include <asm/timer.h>
 
 #include <mach_apic.h>
 
@@ -2052,7 +2053,6 @@
  */
 static inline void check_timer(void)
 {
-	extern int timer_ack;
 	int pin1, pin2;
 	int vector;
 
diff -Nru a/arch/i386/kernel/irq.c b/arch/i386/kernel/irq.c
--- a/arch/i386/kernel/irq.c	Thu Jun  5 23:36:33 2003
+++ b/arch/i386/kernel/irq.c	Sun Jul  6 21:03:14 2003
@@ -416,7 +416,6 @@
 	 * handled by some other CPU. (or is disabled)
 	 */
 	int irq = regs.orig_eax & 0xff; /* high bits used in ret_from_ code  */
-	int cpu = smp_processor_id();
 	irq_desc_t *desc = irq_desc + irq;
 	struct irqaction * action;
 	unsigned int status;
@@ -437,7 +436,7 @@
 		}
 	}
 #endif
-	kstat_cpu(cpu).irqs[irq]++;
+	kstat_this_cpu.irqs[irq]++;
 	spin_lock(&desc->lock);
 	desc->handler->ack(irq);
 	/*
diff -Nru a/arch/i386/kernel/time.c b/arch/i386/kernel/time.c
--- a/arch/i386/kernel/time.c	Mon Jun 16 12:48:20 2003
+++ b/arch/i386/kernel/time.c	Wed Jul  2 21:21:32 2003
@@ -80,8 +80,7 @@
 spinlock_t i8253_lock = SPIN_LOCK_UNLOCKED;
 EXPORT_SYMBOL(i8253_lock);
 
-extern struct timer_opts timer_none;
-struct timer_opts* timer = &timer_none;
+struct timer_opts *cur_timer = &timer_none;
 
 /*
  * This version of gettimeofday has microsecond resolution
@@ -93,14 +92,14 @@
 	unsigned long usec, sec;
 
 	do {
+		unsigned long lost;
+
 		seq = read_seqbegin(&xtime_lock);
 
-		usec = timer->get_offset();
-		{
-			unsigned long lost = jiffies - wall_jiffies;
-			if (lost)
-				usec += lost * (1000000 / HZ);
-		}
+		usec = cur_timer->get_offset();
+		lost = jiffies - wall_jiffies;
+		if (lost)
+			usec += lost * (1000000 / HZ);
 		sec = xtime.tv_sec;
 		usec += (xtime.tv_nsec / 1000);
 	} while (read_seqretry(&xtime_lock, seq));
@@ -126,7 +125,7 @@
 	 * wall time.  Discover what correction gettimeofday() would have
 	 * made, and then undo it!
 	 */
-	tv->tv_nsec -= timer->get_offset() * NSEC_PER_USEC;
+	tv->tv_nsec -= cur_timer->get_offset() * NSEC_PER_USEC;
 	tv->tv_nsec -= (jiffies - wall_jiffies) * TICK_NSEC;
 
 	while (tv->tv_nsec < 0) {
@@ -180,7 +179,7 @@
  */
 unsigned long long monotonic_clock(void)
 {
-	return timer->monotonic_clock();
+	return cur_timer->monotonic_clock();
 }
 EXPORT_SYMBOL(monotonic_clock);
 
@@ -189,7 +188,8 @@
  * timer_interrupt() needs to keep up the real-time clock,
  * as well as call the "do_timer()" routine every clocktick
  */
-static inline void do_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static inline void do_timer_interrupt(int irq, void *dev_id,
+					struct pt_regs *regs)
 {
 #ifdef CONFIG_X86_IO_APIC
 	if (timer_ack) {
@@ -259,7 +259,7 @@
 	 */
 	write_seqlock(&xtime_lock);
 
-	timer->mark_offset();
+	cur_timer->mark_offset();
  
 	do_timer_interrupt(irq, NULL, regs);
 
@@ -301,16 +301,13 @@
 
 device_initcall(time_init_device);
 
-
 void __init time_init(void)
 {
-	
 	xtime.tv_sec = get_cmos_time();
 	wall_to_monotonic.tv_sec = -xtime.tv_sec;
 	xtime.tv_nsec = (INITIAL_JIFFIES % HZ) * (NSEC_PER_SEC / HZ);
 	wall_to_monotonic.tv_nsec = -xtime.tv_nsec;
 
-
-	timer = select_timer();
+	cur_timer = select_timer();
 	time_init_hook();
 }
diff -Nru a/arch/i386/kernel/timers/timer.c b/arch/i386/kernel/timers/timer.c
--- a/arch/i386/kernel/timers/timer.c	Sun May 25 17:00:00 2003
+++ b/arch/i386/kernel/timers/timer.c	Wed Jul  2 21:21:34 2003
@@ -3,12 +3,6 @@
 #include <linux/string.h>
 #include <asm/timer.h>
 
-/* list of externed timers */
-extern struct timer_opts timer_pit;
-extern struct timer_opts timer_tsc;
-#ifdef CONFIG_X86_CYCLONE_TIMER
-extern struct timer_opts timer_cyclone;
-#endif
 /* list of timers, ordered by preference, NULL terminated */
 static struct timer_opts* timers[] = {
 #ifdef CONFIG_X86_CYCLONE_TIMER
@@ -28,6 +22,15 @@
 	return 1;
 }
 __setup("clock=", clock_setup);
+
+
+/* The chosen timesource has been found to be bad.
+ * Fall back to a known good timesource (the PIT)
+ */
+void clock_fallback(void)
+{
+	cur_timer = &timer_pit;
+}
 
 /* iterates through the list of timers, returning the first 
  * one that initializes successfully.
diff -Nru a/arch/i386/kernel/timers/timer_cyclone.c b/arch/i386/kernel/timers/timer_cyclone.c
--- a/arch/i386/kernel/timers/timer_cyclone.c	Mon Apr 21 08:11:07 2003
+++ b/arch/i386/kernel/timers/timer_cyclone.c	Thu Jul  3 17:52:12 2003
@@ -11,6 +11,7 @@
 #include <linux/timex.h>
 #include <linux/errno.h>
 #include <linux/string.h>
+#include <linux/jiffies.h>
 
 #include <asm/timer.h>
 #include <asm/io.h>
@@ -18,7 +19,6 @@
 #include <asm/fixmap.h>
 
 extern spinlock_t i8253_lock;
-extern unsigned long jiffies;
 extern unsigned long calibrate_tsc(void);
 
 /* Number of usecs that the last interrupt was delayed */
@@ -88,7 +88,7 @@
 	 * between cyclone and pit reads (as noted when 
 	 * usec delta is > 90% # of usecs/tick)
 	 */
-	if (abs(delay - delay_at_last_interrupt) > (900000/HZ)) 
+	if (lost && abs(delay - delay_at_last_interrupt) > (900000/HZ))
 		jiffies++;
 }
 
diff -Nru a/arch/i386/kernel/timers/timer_tsc.c b/arch/i386/kernel/timers/timer_tsc.c
--- a/arch/i386/kernel/timers/timer_tsc.c	Mon Apr 21 08:11:07 2003
+++ b/arch/i386/kernel/timers/timer_tsc.c	Thu Jul  3 17:52:12 2003
@@ -9,6 +9,7 @@
 #include <linux/errno.h>
 #include <linux/cpufreq.h>
 #include <linux/string.h>
+#include <linux/jiffies.h>
 
 #include <asm/timer.h>
 #include <asm/io.h>
@@ -21,7 +22,6 @@
 int tsc_disable __initdata = 0;
 
 extern spinlock_t i8253_lock;
-extern unsigned long jiffies;
 
 static int use_tsc;
 /* Number of usecs that the last interrupt was delayed */
@@ -124,6 +124,7 @@
 	int countmp;
 	static int count1 = 0;
 	unsigned long long this_offset, last_offset;
+	static int lost_count = 0;
 	
 	write_lock(&monotonic_lock);
 	last_offset = ((unsigned long long)last_tsc_high<<32)|last_tsc_low;
@@ -178,9 +179,19 @@
 	delta += delay_at_last_interrupt;
 	lost = delta/(1000000/HZ);
 	delay = delta%(1000000/HZ);
-	if (lost >= 2)
+	if (lost >= 2) {
 		jiffies += lost-1;
 
+		/* sanity check to ensure we're not always loosing ticks */
+		if (lost_count++ > 100) {
+			printk(KERN_WARNING "Loosing too many ticks!\n");
+			printk(KERN_WARNING "TSC cannot be used as a timesource."
+					" (Are you running with SpeedStep?)\n");
+			printk(KERN_WARNING "Falling back to a sane timesource.\n");
+			clock_fallback();
+		}
+	} else
+		lost_count = 0;
 	/* update the monotonic base value */
 	this_offset = ((unsigned long long)last_tsc_high<<32)|last_tsc_low;
 	monotonic_base += cycles_2_ns(this_offset - last_offset);
@@ -194,7 +205,7 @@
 	 * between tsc and pit reads (as noted when 
 	 * usec delta is > 90% # of usecs/tick)
 	 */
-	if (abs(delay - delay_at_last_interrupt) > (900000/HZ))
+	if (lost && abs(delay - delay_at_last_interrupt) > (900000/HZ))
 		jiffies++;
 }
 
diff -Nru a/arch/i386/lib/delay.c b/arch/i386/lib/delay.c
--- a/arch/i386/lib/delay.c	Tue Feb 18 06:41:35 2003
+++ b/arch/i386/lib/delay.c	Wed Jul  2 21:21:32 2003
@@ -25,7 +25,7 @@
 
 void __delay(unsigned long loops)
 {
-	timer->delay(loops);
+	cur_timer->delay(loops);
 }
 
 inline void __const_udelay(unsigned long xloops)
diff -Nru a/arch/i386/mm/pageattr.c b/arch/i386/mm/pageattr.c
--- a/arch/i386/mm/pageattr.c	Sun Mar  2 18:13:32 2003
+++ b/arch/i386/mm/pageattr.c	Wed Jul  2 21:19:42 2003
@@ -13,6 +13,10 @@
 #include <asm/processor.h>
 #include <asm/tlbflush.h>
 
+static spinlock_t cpa_lock = SPIN_LOCK_UNLOCKED;
+static struct list_head df_list = LIST_HEAD_INIT(df_list);
+
+
 static inline pte_t *lookup_address(unsigned long address) 
 { 
 	pgd_t *pgd = pgd_offset_k(address); 
@@ -31,10 +35,15 @@
 { 
 	int i; 
 	unsigned long addr;
-	struct page *base = alloc_pages(GFP_KERNEL, 0);
+	struct page *base;
 	pte_t *pbase;
+
+	spin_unlock_irq(&cpa_lock);
+	base = alloc_pages(GFP_KERNEL, 0);
+	spin_lock_irq(&cpa_lock);
 	if (!base) 
 		return NULL;
+
 	address = __pa(address);
 	addr = address & LARGE_PAGE_MASK; 
 	pbase = (pte_t *)page_address(base);
@@ -87,7 +96,7 @@
 }
 
 static int
-__change_page_attr(struct page *page, pgprot_t prot, struct page **oldpage) 
+__change_page_attr(struct page *page, pgprot_t prot)
 { 
 	pte_t *kpte; 
 	unsigned long address;
@@ -123,7 +132,7 @@
 	}
 
 	if (cpu_has_pse && (atomic_read(&kpte_page->count) == 1)) { 
-		*oldpage = kpte_page;
+		list_add(&kpte_page->list, &df_list);
 		revert_page(kpte_page, address);
 	} 
 	return 0;
@@ -134,12 +143,6 @@
 	on_each_cpu(flush_kernel_map, NULL, 1, 1);
 }
 
-struct deferred_page { 
-	struct deferred_page *next; 
-	struct page *fpage;
-}; 
-static struct deferred_page *df_list; /* protected by init_mm.mmap_sem */
-
 /*
  * Change the page attributes of an page in the linear mapping.
  *
@@ -156,47 +159,54 @@
 int change_page_attr(struct page *page, int numpages, pgprot_t prot)
 {
 	int err = 0; 
-	struct page *fpage; 
 	int i; 
+	unsigned long flags;
 
-	down_write(&init_mm.mmap_sem);
+	spin_lock_irqsave(&cpa_lock, flags);
 	for (i = 0; i < numpages; i++, page++) { 
-		fpage = NULL;
-		err = __change_page_attr(page, prot, &fpage); 
+		err = __change_page_attr(page, prot);
 		if (err) 
 			break; 
-		if (fpage) { 
-			struct deferred_page *df;
-			df = kmalloc(sizeof(struct deferred_page), GFP_KERNEL); 
-			if (!df) {
-				flush_map();
-				__free_page(fpage);
-			} else { 
-				df->next = df_list;
-				df->fpage = fpage;				
-				df_list = df;
-			} 			
-		} 
 	} 	
-	up_write(&init_mm.mmap_sem); 
+	spin_unlock_irqrestore(&cpa_lock, flags);
 	return err;
 }
 
 void global_flush_tlb(void)
 { 
-	struct deferred_page *df, *next_df;
+	LIST_HEAD(l);
+	struct list_head* n;
 
-	down_read(&init_mm.mmap_sem);
-	df = xchg(&df_list, NULL);
-	up_read(&init_mm.mmap_sem);
+	BUG_ON(irqs_disabled());
+
+	spin_lock_irq(&cpa_lock);
+	list_splice_init(&df_list, &l);
+	spin_unlock_irq(&cpa_lock);
 	flush_map();
-	for (; df; df = next_df) { 
-		next_df = df->next;
-		if (df->fpage) 
-			__free_page(df->fpage);
-		kfree(df);
-	} 
+	n = l.next;
+	while (n != &l) {
+		struct page *pg = list_entry(n, struct page, list);
+		n = n->next;
+		__free_page(pg);
+	}
 } 
+
+#ifdef CONFIG_DEBUG_PAGEALLOC
+void kernel_map_pages(struct page *page, int numpages, int enable)
+{
+	if (PageHighMem(page))
+		return;
+	/* the return value is ignored - the calls cannot fail,
+	 * large pages are disabled at boot time.
+	 */
+	change_page_attr(page, numpages, enable ? PAGE_KERNEL : __pgprot(0));
+	/* we should perform an IPI and flush all tlbs,
+	 * but that can deadlock->flush only current cpu.
+	 */
+	__flush_tlb_all();
+}
+EXPORT_SYMBOL(kernel_map_pages);
+#endif
 
 EXPORT_SYMBOL(change_page_attr);
 EXPORT_SYMBOL(global_flush_tlb);
diff -Nru a/arch/i386/mm/pgtable.c b/arch/i386/mm/pgtable.c
--- a/arch/i386/mm/pgtable.c	Mon May 12 11:11:38 2003
+++ b/arch/i386/mm/pgtable.c	Wed Jul  2 21:20:53 2003
@@ -34,7 +34,7 @@
 	show_free_areas();
 	printk("Free swap:       %6dkB\n",nr_swap_pages<<(PAGE_SHIFT-10));
 	for_each_pgdat(pgdat) {
-		for (i = 0; i < pgdat->node_size; ++i) {
+		for (i = 0; i < pgdat->node_spanned_pages; ++i) {
 			page = pgdat->node_mem_map + i;
 			total++;
 			if (PageHighMem(page))
diff -Nru a/arch/i386/pci/direct.c b/arch/i386/pci/direct.c
--- a/arch/i386/pci/direct.c	Mon Jun 23 17:12:27 2003
+++ b/arch/i386/pci/direct.c	Wed Jul  2 18:11:41 2003
@@ -177,7 +177,7 @@
  * This should be close to trivial, but it isn't, because there are buggy
  * chipsets (yes, you guessed it, by Intel and Compaq) that have no class ID.
  */
-static int __devinit pci_sanity_check(struct pci_raw_ops *o)
+static int __init pci_sanity_check(struct pci_raw_ops *o)
 {
 	u32 x = 0;
 	int devfn;
diff -Nru a/arch/i386/pci/irq.c b/arch/i386/pci/irq.c
--- a/arch/i386/pci/irq.c	Thu Jun 19 14:58:11 2003
+++ b/arch/i386/pci/irq.c	Thu Jul  3 12:49:14 2003
@@ -102,13 +102,12 @@
 #endif
 		busmap[e->bus] = 1;
 	}
-	for(i=1; i<256; i++)
-		/*
-		 *  It might be a secondary bus, but in this case its parent is already
-		 *  known (ascending bus order) and therefore pci_scan_bus returns immediately.
-		 */
-		if (busmap[i] && pci_scan_bus(i, &pci_root_ops, NULL))
+	for(i = 1; i < 256; i++) {
+		if (!busmap[i] || pci_find_bus(0, i))
+			continue;
+		if (pci_scan_bus(i, &pci_root_ops, NULL))
 			printk(KERN_INFO "PCI: Discovered primary peer bus %02x [IRQ]\n", i);
+	}
 	pcibios_last_bus = -1;
 }
 
@@ -196,15 +195,16 @@
 /*
  * The VIA pirq rules are nibble-based, like ALI,
  * but without the ugly irq number munging.
+ * However, PIRQD is in the upper instead of lower 4 bits.
  */
 static int pirq_via_get(struct pci_dev *router, struct pci_dev *dev, int pirq)
 {
-	return read_config_nybble(router, 0x55, pirq);
+	return read_config_nybble(router, 0x55, pirq == 4 ? 5 : pirq);
 }
 
 static int pirq_via_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq)
 {
-	write_config_nybble(router, 0x55, pirq, irq);
+	write_config_nybble(router, 0x55, pirq == 4 ? 5 : pirq, irq);
 	return 1;
 }
 
diff -Nru a/arch/i386/pci/legacy.c b/arch/i386/pci/legacy.c
--- a/arch/i386/pci/legacy.c	Thu Jun 19 14:58:11 2003
+++ b/arch/i386/pci/legacy.c	Wed Jul  2 19:45:28 2003
@@ -11,40 +11,26 @@
  */
 static void __devinit pcibios_fixup_peer_bridges(void)
 {
-	int n;
-	struct pci_bus *bus;
-	struct pci_dev *dev;
-	u16 l;
+	int n, devfn;
 
 	if (pcibios_last_bus <= 0 || pcibios_last_bus >= 0xff)
 		return;
 	DBG("PCI: Peer bridge fixup\n");
 
-	bus = kmalloc(sizeof(*bus), GFP_ATOMIC);
-	dev = kmalloc(sizeof(*dev), GFP_ATOMIC);
-	if (!bus || !dev) {
-		printk(KERN_ERR "Out of memory in %s\n", __FUNCTION__);
-		goto exit;
-	}
-
 	for (n=0; n <= pcibios_last_bus; n++) {
-		if (pci_bus_exists(&pci_root_buses, n))
+		u32 l;
+		if (pci_find_bus(0, n))
 			continue;
-		bus->number = n;
-		bus->ops = &pci_root_ops;
-		dev->bus = bus;
-		for (dev->devfn=0; dev->devfn<256; dev->devfn += 8)
-			if (!pci_read_config_word(dev, PCI_VENDOR_ID, &l) &&
+		for (devfn = 0; devfn < 256; devfn += 8) {
+			if (!raw_pci_ops->read(0, n, devfn, PCI_VENDOR_ID, 2, &l) &&
 			    l != 0x0000 && l != 0xffff) {
 				DBG("Found device at %02x:%02x [%04x]\n", n, dev->devfn, l);
 				printk(KERN_INFO "PCI: Discovered peer bus %02x\n", n);
 				pci_scan_bus(n, &pci_root_ops, NULL);
 				break;
 			}
+		}
 	}
-exit:
-	kfree(dev);
-	kfree(bus);
 }
 
 static int __init pci_legacy_init(void)
diff -Nru a/arch/ia64/ia32/binfmt_elf32.c b/arch/ia64/ia32/binfmt_elf32.c
--- a/arch/ia64/ia32/binfmt_elf32.c	Mon Jun 16 17:03:24 2003
+++ b/arch/ia64/ia32/binfmt_elf32.c	Wed Jul  2 21:22:38 2003
@@ -13,6 +13,7 @@
 
 #include <linux/types.h>
 #include <linux/mm.h>
+#include <linux/security.h>
 
 #include <asm/param.h>
 #include <asm/signal.h>
@@ -177,7 +178,7 @@
 	if (!mpnt)
 		return -ENOMEM;
 
-	if (!vm_enough_memory((IA32_STACK_TOP - (PAGE_MASK & (unsigned long) bprm->p))>>PAGE_SHIFT)) {
+	if (security_vm_enough_memory((IA32_STACK_TOP - (PAGE_MASK & (unsigned long) bprm->p))>>PAGE_SHIFT)) {
 		kmem_cache_free(vm_area_cachep, mpnt);
 		return -ENOMEM;
 	}
diff -Nru a/arch/ia64/kernel/sys_ia64.c b/arch/ia64/kernel/sys_ia64.c
--- a/arch/ia64/kernel/sys_ia64.c	Tue Jun 10 14:00:47 2003
+++ b/arch/ia64/kernel/sys_ia64.c	Wed Jul  2 21:22:38 2003
@@ -100,7 +100,6 @@
 asmlinkage unsigned long
 ia64_brk (unsigned long brk)
 {
-	extern int vm_enough_memory (long pages);
 	unsigned long rlim, retval, newbrk, oldbrk;
 	struct mm_struct *mm = current->mm;
 
diff -Nru a/arch/ia64/mm/init.c b/arch/ia64/mm/init.c
--- a/arch/ia64/mm/init.c	Tue Jun 17 23:50:17 2003
+++ b/arch/ia64/mm/init.c	Wed Jul  2 21:20:53 2003
@@ -232,7 +232,7 @@
 		printk("Free swap:       %6dkB\n", nr_swap_pages<<(PAGE_SHIFT-10));
 		for_each_pgdat(pgdat) {
 			printk("Node ID: %d\n", pgdat->node_id);
-			for(i = 0; i < pgdat->node_size; i++) {
+			for(i = 0; i < pgdat->node_spanned_pages; i++) {
 				if (PageReserved(pgdat->node_mem_map+i))
 					reserved++;
 				else if (PageSwapCache(pgdat->node_mem_map+i))
@@ -240,7 +240,7 @@
 				else if (page_count(pgdat->node_mem_map + i))
 					shared += page_count(pgdat->node_mem_map + i) - 1;
 			}
-			printk("\t%d pages of RAM\n", pgdat->node_size);
+			printk("\t%d pages of RAM\n", pgdat->node_spanned_pages);
 			printk("\t%d reserved pages\n", reserved);
 			printk("\t%d pages shared\n", shared);
 			printk("\t%d pages swap cached\n", cached);
diff -Nru a/arch/m68knommu/Kconfig b/arch/m68knommu/Kconfig
--- a/arch/m68knommu/Kconfig	Thu Jun 26 23:08:12 2003
+++ b/arch/m68knommu/Kconfig	Wed Jul  2 18:17:14 2003
@@ -222,21 +222,17 @@
 	  Support for the Arcturus Networks uDsimm module.
 
 config DRAGEN2
-	bool "Dragen Engine II board support"
+	bool "DragenEngine II board support"
 	depends on M68VZ328
 	help
-	  Support for the Dragen Engine II board.
+	  Support for the DragenEngine II board.
 
-config HWADDR_FROMEEPROM
-	bool "  Read ETH address from EEPROM"
-	depends on DRAGEN2
+config DIRECT_IO_ACCESS
+	bool "  Allow user to access IO directly"
+	depends on (UCSIMM || UCDIMM || DRAGEN2)
 	help
-	  Use MAC address from EEPROM.
-
-config HWADDR_OFFSET
-	int "  Offset from start of EEPROM"
-	default "2"
-	depends on HWADDR_FROMEEPROM
+	  Disable the CPU internal registers protection in user mode,
+          to allow a user application to read/write them.
 
 config INIT_LCD
 	bool "  Initialize LCD"
@@ -246,7 +242,7 @@
 
 config MEMORY_RESERVE
 	int "  Memory reservation (MiB)"
-	depends on (UCSIMM || UCDIMM || DRAGEN2)
+	depends on (UCSIMM || UCDIMM)
 	help
 	  Reserve certain memory regions on 68x328 based boards.
 
diff -Nru a/arch/m68knommu/platform/5282/config.c b/arch/m68knommu/platform/5282/config.c
--- a/arch/m68knommu/platform/5282/config.c	Thu May  8 15:47:43 2003
+++ b/arch/m68knommu/platform/5282/config.c	Wed Jul  2 18:17:16 2003
@@ -62,7 +62,7 @@
 {
 	mcf_disableall();
 
-#if defined(CONFIG_BOOTPARAM)
+#ifdef CONFIG_BOOTPARAM
 	strncpy(commandp, CONFIG_BOOTPARAM_STRING, size);
 	commandp[size-1] = 0;
 #else
diff -Nru a/arch/m68knommu/platform/5307/CLEOPATRA/crt0_ram.S b/arch/m68knommu/platform/5307/CLEOPATRA/crt0_ram.S
--- a/arch/m68knommu/platform/5307/CLEOPATRA/crt0_ram.S	Fri Nov  1 07:19:55 2002
+++ b/arch/m68knommu/platform/5307/CLEOPATRA/crt0_ram.S	Wed Jul  2 18:17:16 2003
@@ -127,6 +127,7 @@
 	movc  %d0,%CACR
 
 
+#ifdef CONFIG_ROMFS_FS
 	/*
 	 *	Move ROM filesystem above bss :-)
 	 */
@@ -147,6 +148,12 @@
 	move.l	%d0, -(%a1)
 	cmp.l	%a0, %a2			/* Check if at end */
 	bne	_copy_romfs
+
+#else /* CONFIG_ROMFS_FS */
+	lea.l	_ebss, %a1
+	move.l	%a1, _ramstart
+#endif /* CONFIG_ROMFS_FS */
+
 
 	/*
 	 *	Zero out the bss region.
diff -Nru a/arch/m68knommu/platform/5307/MOTOROLA/crt0_ram.S b/arch/m68knommu/platform/5307/MOTOROLA/crt0_ram.S
--- a/arch/m68knommu/platform/5307/MOTOROLA/crt0_ram.S	Fri Nov  1 07:19:55 2002
+++ b/arch/m68knommu/platform/5307/MOTOROLA/crt0_ram.S	Wed Jul  2 18:17:16 2003
@@ -110,6 +110,8 @@
 	movc  %d0,%CACR
 	nop
 
+
+#ifdef CONFIG_ROMFS_FS
 	/*
 	 *	Move ROM filesystem above bss :-)
 	 */
@@ -130,6 +132,12 @@
 	move.l	%d0, -(%a1)
 	cmp.l	%a0, %a2			/* Check if at end */
 	bne	_copy_romfs
+
+#else /* CONFIG_ROMFS_FS */
+	lea.l	_ebss, %a1
+	move.l	%a1, _ramstart
+#endif /* CONFIG_ROMFS_FS */
+
 
 	/*
 	 *	Zero out the bss region.
diff -Nru a/arch/m68knommu/platform/5307/MP3/crt0_ram.S b/arch/m68knommu/platform/5307/MP3/crt0_ram.S
--- a/arch/m68knommu/platform/5307/MP3/crt0_ram.S	Fri Nov  1 07:19:55 2002
+++ b/arch/m68knommu/platform/5307/MP3/crt0_ram.S	Wed Jul  2 18:17:17 2003
@@ -124,6 +124,8 @@
 	movec	%d0,%CACR
 	nop
 
+
+#ifdef CONFIG_ROMFS_FS
 	/*
 	 *	Move ROM filesystem above bss :-)
 	 */
@@ -144,6 +146,12 @@
 	move.l	%d0, -(%a1)
 	cmp.l	%a0, %a2			/* Check if at end */
 	bne	_copy_romfs
+
+#else /* CONFIG_ROMFS_FS */
+	lea.l	_ebss, %a1
+	move.l	%a1, _ramstart
+#endif /* CONFIG_ROMFS_FS */
+
 
 	/*
 	 *	Zero out the bss region.
diff -Nru a/arch/m68knommu/platform/5307/NETtel/crt0_ram.S b/arch/m68knommu/platform/5307/NETtel/crt0_ram.S
--- a/arch/m68knommu/platform/5307/NETtel/crt0_ram.S	Fri Nov  1 07:19:55 2002
+++ b/arch/m68knommu/platform/5307/NETtel/crt0_ram.S	Wed Jul  2 18:17:17 2003
@@ -147,6 +147,8 @@
 	movec	%d0,%CACR
 	nop
 
+
+#ifdef CONFIG_ROMFS_FS
 	/*
 	 *	Move ROM filesystem above bss :-)
 	 */
@@ -167,6 +169,12 @@
 	move.l	%d0, -(%a1)
 	cmp.l	%a0, %a2			/* Check if at end */
 	bne	_copy_romfs
+
+#else /* CONFIG_ROMFS_FS */
+	lea.l	_ebss, %a1
+	move.l	%a1, _ramstart
+#endif /* CONFIG_ROMFS_FS */
+
 
 	/*
 	 *	Zero out the bss region.
diff -Nru a/arch/m68knommu/platform/68328/ints.c b/arch/m68knommu/platform/68328/ints.c
--- a/arch/m68knommu/platform/68328/ints.c	Sun May 25 21:46:26 2003
+++ b/arch/m68knommu/platform/68328/ints.c	Wed Jul  2 18:17:17 2003
@@ -81,6 +81,7 @@
 /* irq node variables for the 32 (potential) on chip sources */
 static irq_node_t int_irq_list[NR_IRQS];
 
+#if !defined(CONFIG_DRAGEN2)
 asm ("
 	.global _start, __ramend
 	.section .romvec
@@ -102,6 +103,7 @@
 ignore: rte
 
 ");
+#endif
 
 /*
  * This function should be called during kernel startup to initialize
@@ -204,7 +206,7 @@
 			seq_printf(p, "  ");
 		seq_printf(p, "%s\n", int_irq_list[i].devname);
 	}
-	seq_printf(p, "   : %10u   spurious", num_spurious);
+	seq_printf(p, "   : %10u   spurious\n", num_spurious);
 
 	return 0;
 }
diff -Nru a/arch/m68knommu/platform/68360/config.c b/arch/m68knommu/platform/68360/config.c
--- a/arch/m68knommu/platform/68360/config.c	Fri Nov  1 07:19:55 2002
+++ b/arch/m68knommu/platform/68360/config.c	Wed Jul  2 18:17:17 2003
@@ -205,9 +205,4 @@
   mach_hwclk           = NULL;
   mach_set_clock_mmss  = NULL;
   mach_reset           = BSP_reset;
-
-  //Kendrick's Change
-  mach_trap_init        = M68360_init_IRQ;
-
-  config_M68360_irq();
 }
diff -Nru a/arch/m68knommu/platform/68VZ328/de2/config.c b/arch/m68knommu/platform/68VZ328/de2/config.c
--- a/arch/m68knommu/platform/68VZ328/de2/config.c	Tue May 27 06:56:10 2003
+++ b/arch/m68knommu/platform/68VZ328/de2/config.c	Wed Jul  2 18:17:17 2003
@@ -36,7 +36,7 @@
 #define TICKS_PER_JIFFY 41450
 
 static void
-dragen2_sched_init(void (*timer_routine) (int, void *, struct pt_regs *))
+dragen2_sched_init(irqreturn_t (*timer_routine) (int, void *, struct pt_regs *))
 {
 	/* disable timer 1 */
 	TCTL = 0;
@@ -183,14 +183,20 @@
 #endif
 }
 
-void config_BSP(char *command, int len)
+void config_BSP(char *command, int size)
 {
 	printk("68VZ328 DragonBallVZ support (c) 2001 Lineo, Inc.\n");
-	command[0] = '\0';			/* no specific boot option */
+
+#if defined(CONFIG_BOOTPARAM)
+	strncpy(command, CONFIG_BOOTPARAM_STRING, size);
+	command[size-1] = 0;
+#else
+	memset(command, 0, size);
+#endif
 
 	init_hardware();
 
-	mach_sched_init = dragen2_sched_init;
+	mach_sched_init = (void *)dragen2_sched_init;
 	mach_tick = dragen2_tick;
 	mach_gettimeoffset = dragen2_gettimeoffset;
 	mach_reset = dragen2_reset;
diff -Nru a/arch/m68knommu/vmlinux.lds.S b/arch/m68knommu/vmlinux.lds.S
--- a/arch/m68knommu/vmlinux.lds.S	Wed Jun 11 17:40:05 2003
+++ b/arch/m68knommu/vmlinux.lds.S	Wed Jul  2 18:17:14 2003
@@ -277,7 +277,9 @@
 		__con_initcall_start = .;
 		*(.con_initcall.init)
 		__con_initcall_end = .;
-		SECURITY_INIT
+		__security_initcall_start = .;
+		*(.security_initcall.init)
+		__security_initcall_end = .;
 		. = ALIGN(4);
 		__initramfs_start = .;
 		*(.init.ramfs)
diff -Nru a/arch/mips/kernel/sysirix.c b/arch/mips/kernel/sysirix.c
--- a/arch/mips/kernel/sysirix.c	Sun Jun 15 16:54:33 2003
+++ b/arch/mips/kernel/sysirix.c	Wed Jul  2 21:22:38 2003
@@ -28,6 +28,7 @@
 #include <linux/vfs.h>
 #include <linux/namei.h>
 #include <linux/socket.h>
+#include <linux/security.h>
 
 #include <asm/ptrace.h>
 #include <asm/page.h>
@@ -527,8 +528,6 @@
 	return get_seconds();
 }
 
-int vm_enough_memory(long pages);
-
 /*
  * IRIX is completely broken... it returns 0 on success, otherwise
  * ENOMEM.
@@ -585,7 +584,7 @@
 	/*
 	 * Check if we have enough memory..
 	 */
-	if (!vm_enough_memory((newbrk-oldbrk) >> PAGE_SHIFT)) {
+	if (security_vm_enough_memory((newbrk-oldbrk) >> PAGE_SHIFT)) {
 		ret = -ENOMEM;
 		goto out;
 	}
diff -Nru a/arch/parisc/kernel/smp.c b/arch/parisc/kernel/smp.c
--- a/arch/parisc/kernel/smp.c	Tue May 27 08:27:16 2003
+++ b/arch/parisc/kernel/smp.c	Sun Jul  6 18:51:59 2003
@@ -456,7 +456,7 @@
 	current->active_mm = &init_mm;
 	if(current->mm)
 		BUG();
-	enter_lazy_tlb(&init_mm, current, cpunum);
+	enter_lazy_tlb(&init_mm, current);
 
 	init_IRQ();   /* make sure no IRQ's are enabled or pending */
 }
diff -Nru a/arch/ppc/Kconfig b/arch/ppc/Kconfig
--- a/arch/ppc/Kconfig	Thu Jun 26 23:08:27 2003
+++ b/arch/ppc/Kconfig	Wed Jul  2 17:44:13 2003
@@ -450,9 +450,6 @@
 config SPRUCE
 	bool "IBM-Spruce"
 
-config MENF1
-	bool "MEN-F1"
-
 config LOPEC
 	bool "Motorola-LoPEC"
 
@@ -473,6 +470,10 @@
 
 config SANDPOINT
 	bool "Motorola-Sandpoint"
+	help
+	  Select SANDPOINT if configuring for a Motorola Sandpoint X3
+	  or X3(b).
+	  X3 (any flavor).
 
 config ADIR
 	bool "SBS-Adirondack"
@@ -490,9 +491,6 @@
 	  series Single Board Computer.  More information is available at:
 	  <http://www.synergymicro.com/PressRel/97_10_15.html>.
 
-config ZX4500
-	bool "Zynx-ZX4500"
-
 endchoice
 
 config PPC_CHRP
@@ -500,6 +498,11 @@
 	depends on PPC_MULTIPLATFORM
 	default y
 
+config PPC_GEN550
+	bool
+	depends on SANDPOINT
+	default y
+
 config PPC_PMAC
 	bool
 	depends on PPC_MULTIPLATFORM
@@ -515,10 +518,6 @@
 	depends on PPC_PMAC || PPC_CHRP
 	default y
 
-config SANDPOINT_X3
-	bool "Sandpoint X3"
-	depends on SANDPOINT
-
 config FORCE
 	bool
 	depends on 6xx && !8260 && (PCORE || POWERPMC250)
@@ -526,7 +525,7 @@
 
 config EPIC_SERIAL_MODE
 	bool
-	depends on 6xx && !8260 && (LOPEC || SANDPOINT_X3)
+	depends on 6xx && !8260 && (LOPEC || SANDPOINT)
 	default y
 
 config WILLOW
@@ -536,7 +535,7 @@
 
 config MPC10X_STORE_GATHERING
 	bool "Enable MPC10x store gathering"
-	depends on FORCE || MENF1 || SANDPOINT || ZX4500
+	depends on FORCE || SANDPOINT
 
 config GT64260
 	bool
@@ -1528,7 +1527,7 @@
 
 config SERIAL_TEXT_DEBUG
 	bool "Support for early boot texts over serial port"
-	depends on 4xx || GT64260 || LOPEC || MCPN765 || PPLUS || PRPMC800 || SANDPOINT || ZX4500
+	depends on 4xx || GT64260 || LOPEC || MCPN765 || PPLUS || PRPMC800 || SANDPOINT
 
 config OCP
 	bool
diff -Nru a/arch/ppc/boot/common/Makefile b/arch/ppc/boot/common/Makefile
--- a/arch/ppc/boot/common/Makefile	Sun Jun  8 01:12:26 2003
+++ b/arch/ppc/boot/common/Makefile	Sat Jun 28 11:06:53 2003
@@ -8,7 +8,8 @@
 # Tom Rini	January 2001
 #
 
-lib-y					:= string.o util.o misc-common.o
+lib-y					:= string.o util.o misc-common.o \
+						serial_stub.o
 lib-$(CONFIG_PPC_PREP)			+= mpc10x_memory.o
 lib-$(CONFIG_LOPEC)			+= mpc10x_memory.o
 lib-$(CONFIG_PAL4)			+= cpc700_memory.o
diff -Nru a/arch/ppc/boot/common/ns16550.c b/arch/ppc/boot/common/ns16550.c
--- a/arch/ppc/boot/common/ns16550.c	Sun Sep 15 21:51:57 2002
+++ b/arch/ppc/boot/common/ns16550.c	Sat Jun 28 11:06:53 2003
@@ -95,8 +95,3 @@
 {
 	return ((inb(com_port + (UART_LSR << shift)) & UART_LSR_DR) != 0);
 }
-
-void
-serial_close(unsigned long com_port)
-{
-}
diff -Nru a/arch/ppc/boot/common/serial_stub.c b/arch/ppc/boot/common/serial_stub.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/arch/ppc/boot/common/serial_stub.c	Sat Jun 28 01:07:35 2003
@@ -0,0 +1,28 @@
+/*
+ * arch/ppc/boot/common/serial_stub.c
+ *
+ * This is a few stub routines to make the boot code cleaner looking when
+ * there is no serial port support doesn't need to be closed, for example.
+ *
+ * Author: Tom Rini <trini@mvista.com>
+ *
+ * 2003 (c) MontaVista, Software, Inc.  This file is licensed under the terms
+ * of the GNU General Public License version 2.  This program is licensed "as
+ * is" without any warranty of any kind, whether express or implied.
+ */
+
+void __attribute__ ((weak))
+serial_fixups(void)
+{
+}
+
+unsigned long __attribute__ ((weak))
+serial_init(int chan, void *ignored)
+{
+	return 0;
+}
+
+void __attribute__ ((weak))
+serial_close(unsigned long com_port)
+{
+}
diff -Nru a/arch/ppc/boot/simple/Makefile b/arch/ppc/boot/simple/Makefile
--- a/arch/ppc/boot/simple/Makefile	Tue May 20 22:06:52 2003
+++ b/arch/ppc/boot/simple/Makefile	Tue Jul  1 17:01:18 2003
@@ -47,28 +47,20 @@
 ifeq ($(CONFIG_EBONY),y)
 ZIMAGE				:= zImage-TREE
 ZIMAGEINITRD			:= zImage.initrd-TREE
-EXTRA				:= direct.o
 END				:= ebony
 ENTRYPOINT			:= 0x01000000
 TFTPIMAGE			:= /tftpboot/zImage.$(END)
 endif
 ifeq ($(CONFIG_EV64260),y)
-EXTRA				:= direct.o misc-ev64260.o
+EXTRA				:= misc-ev64260.o
 TFTPIMAGE			:= /tftpboot/zImage.ev64260
 endif
 ifeq ($(CONFIG_GEMINI),y)
 ZIMAGE				:= zImage-STRIPELF
 ZIMAGEINITRD			:= zImage.initrd-STRIPELF
-EXTRA				:= direct.o
 END				:= gemini
 TFTPIMAGE			:= /tftpboot/zImage.$(END)
 endif
-ifeq ($(CONFIG_MENF1),y)
-ZIMAGE				:= zImage-MENF1
-ZIMAGEINITRD			:= zImage.initrd-MENF1
-EXTRA				:= chrpmap.o
-TFTPIMAGE			:= /tftpboot/zImage.menf1
-endif
 ifeq ($(CONFIG_K2),y)
 EXTRA				:= legacy.o
 TFTPIMAGE			:= /tftpboot/zImage.k2
@@ -78,7 +70,6 @@
 ifeq ($(CONFIG_MCPN765)$(CONFIG_MVME5100)$(CONFIG_PRPMC750)$(CONFIG_PRPMC800)$(CONFIG_LOPEC)$(CONFIG_PPLUS),y)
 ZIMAGE				:= zImage-PPLUS
 ZIMAGEINITRD			:= zImage.initrd-PPLUS
-EXTRA				:= direct.o
 TFTPIMAGE			:= /tftpboot/zImage.pplus
 ZNETBOOT			:= zImage.pplus
 ZNETBOOTRD			:= zImage.initrd.pplus
@@ -86,9 +77,6 @@
 ifeq ($(CONFIG_PPLUS),y)
 EXTRA				:= legacy.o
 endif
-ifeq ($(CONFIG_PAL4),y)
-EXTRA				:= direct.o
-endif
 ifeq ($(CONFIG_PCORE)$(CONFIG_POWERPMC250),y)
 ZIMAGE				:= zImage-STRIPELF
 ZIMAGEINITRD			:= zImage.initrd-STRIPELF
@@ -96,30 +84,17 @@
 END				:= pcore
 TFTPIMAGE			:= /tftpboot/zImage.$(END)
 endif
-# The PowerPMC 250 needs the dummy serial_fixups()
-ifeq ($(CONFIG_POWERPMC250),y)
-EXTRA				:= direct.o
-endif
 ifeq ($(CONFIG_SANDPOINT),y)
-EXTRA				:= direct.o
 TFTPIMAGE			:= /tftpboot/zImage.sandpoint
 endif
 ifeq ($(CONFIG_SPRUCE),y)
 ZIMAGE				:= zImage-TREE
 ZIMAGEINITRD			:= zImage.initrd-TREE
-EXTRA				:= direct.o
 END				:= spruce
 ENTRYPOINT			:= 0x00800000
 MISC				:= misc-spruce.o
 TFTPIMAGE			:= /tftpboot/zImage.$(END)
 endif
-ifeq ($(CONFIG_ZX4500),y)
-ZIMAGE				:= zImage-STRIPELF
-ZIMAGEINITRD			:= zImage.initrd-STRIPELF
-EXTRA				:= direct.o
-END				:= zx4500
-TFTPIMAGE			:= /tftpboot/zImage.$(END)
-endif
 ifeq ($(CONFIG_SMP),y)
 TFTPIMAGE			+= .smp
 endif
@@ -220,12 +195,6 @@
 $(images)/zImage.initrd-TREE: $(obj)/zvmlinux.initrd $(MKTREE)
 	$(MKTREE) $(obj)/zvmlinux.initrd $(images)/zImage.initrd.$(END) \
 		$(ENTRYPOINT)
-
-$(images)/zImage-MENF1: $(obj)/zvmlinux $(MKPREP)
-	$(MKPREP) -pbp $(obj)/zvmlinux $(images)/zImage.menf1
-
-$(images)/zImage.initrd-MENF1: $(obj)/zvmlinux.initrd $(MKPREP)
-	$(MKPREP) -pbp $(obj)/zvmlinux.initrd $(images)/zImage.initrd.menf1
 
 $(images)/zImage-PPLUS: $(obj)/zvmlinux $(MKPREP) $(MKBUGBOOT)
 	$(MKPREP) -pbp $(obj)/zvmlinux $(images)/zImage.pplus
diff -Nru a/arch/ppc/boot/simple/direct.S b/arch/ppc/boot/simple/direct.S
--- a/arch/ppc/boot/simple/direct.S	Tue May 14 16:45:03 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,15 +0,0 @@
-/*
- * arch/ppc/boot/simple/direct.S
- *
- * Author: Tom Rini <trini@mvista.com>
- *
- * This is an empty function for machines which use SERIAL_IO_MEM
- * and don't need ISA_io set to anything but 0, or perform any other
- * serial fixups.
- */
-
-	.text
-
-	.globl serial_fixups
-serial_fixups:
-	blr
diff -Nru a/arch/ppc/boot/simple/m8260_tty.c b/arch/ppc/boot/simple/m8260_tty.c
--- a/arch/ppc/boot/simple/m8260_tty.c	Sun Sep 15 21:51:57 2002
+++ b/arch/ppc/boot/simple/m8260_tty.c	Sat Jun 28 11:06:53 2003
@@ -311,8 +311,3 @@
 
 	return(!(rbdf->cbd_sc & BD_SC_EMPTY));
 }
-
-void
-serial_close(unsigned long com_port)
-{
-}
diff -Nru a/arch/ppc/boot/simple/m8xx_tty.c b/arch/ppc/boot/simple/m8xx_tty.c
--- a/arch/ppc/boot/simple/m8xx_tty.c	Sun Sep 15 21:51:57 2002
+++ b/arch/ppc/boot/simple/m8xx_tty.c	Sat Jun 28 11:06:53 2003
@@ -288,8 +288,3 @@
 
 	return(!(rbdf->cbd_sc & BD_SC_EMPTY));
 }
-
-void
-serial_close(unsigned long com_port)
-{
-}
diff -Nru a/arch/ppc/configs/adir_defconfig b/arch/ppc/configs/adir_defconfig
--- a/arch/ppc/configs/adir_defconfig	Thu Jun 12 00:32:33 2003
+++ b/arch/ppc/configs/adir_defconfig	Tue Jul  1 17:01:18 2003
@@ -55,7 +55,6 @@
 # CONFIG_POWERPMC250 is not set
 # CONFIG_EV64260 is not set
 # CONFIG_SPRUCE is not set
-# CONFIG_MENF1 is not set
 # CONFIG_LOPEC is not set
 # CONFIG_MCPN765 is not set
 # CONFIG_MVME5100 is not set
@@ -67,7 +66,6 @@
 # CONFIG_K2 is not set
 # CONFIG_PAL4 is not set
 # CONFIG_GEMINI is not set
-# CONFIG_ZX4500 is not set
 # CONFIG_SMP is not set
 # CONFIG_PREEMPT is not set
 # CONFIG_ALTIVEC is not set
diff -Nru a/arch/ppc/configs/apus_defconfig b/arch/ppc/configs/apus_defconfig
--- a/arch/ppc/configs/apus_defconfig	Thu Jun 12 00:32:33 2003
+++ b/arch/ppc/configs/apus_defconfig	Tue Jul  1 17:01:18 2003
@@ -56,7 +56,6 @@
 # CONFIG_POWERPMC250 is not set
 # CONFIG_EV64260 is not set
 # CONFIG_SPRUCE is not set
-# CONFIG_MENF1 is not set
 # CONFIG_LOPEC is not set
 # CONFIG_MCPN765 is not set
 # CONFIG_MVME5100 is not set
@@ -68,7 +67,6 @@
 # CONFIG_K2 is not set
 # CONFIG_PAL4 is not set
 # CONFIG_GEMINI is not set
-# CONFIG_ZX4500 is not set
 # CONFIG_SMP is not set
 # CONFIG_PREEMPT is not set
 # CONFIG_ALTIVEC is not set
diff -Nru a/arch/ppc/configs/common_defconfig b/arch/ppc/configs/common_defconfig
--- a/arch/ppc/configs/common_defconfig	Thu Jun 12 00:32:33 2003
+++ b/arch/ppc/configs/common_defconfig	Tue Jul  1 17:01:18 2003
@@ -56,7 +56,6 @@
 # CONFIG_POWERPMC250 is not set
 # CONFIG_EV64260 is not set
 # CONFIG_SPRUCE is not set
-# CONFIG_MENF1 is not set
 # CONFIG_LOPEC is not set
 # CONFIG_MCPN765 is not set
 # CONFIG_MVME5100 is not set
@@ -68,7 +67,6 @@
 # CONFIG_K2 is not set
 # CONFIG_PAL4 is not set
 # CONFIG_GEMINI is not set
-# CONFIG_ZX4500 is not set
 CONFIG_PPC_CHRP=y
 CONFIG_PPC_PMAC=y
 CONFIG_PPC_PREP=y
diff -Nru a/arch/ppc/configs/ev64260_defconfig b/arch/ppc/configs/ev64260_defconfig
--- a/arch/ppc/configs/ev64260_defconfig	Thu Jun 12 00:32:33 2003
+++ b/arch/ppc/configs/ev64260_defconfig	Tue Jul  1 17:01:18 2003
@@ -55,7 +55,6 @@
 # CONFIG_POWERPMC250 is not set
 CONFIG_EV64260=y
 # CONFIG_SPRUCE is not set
-# CONFIG_MENF1 is not set
 # CONFIG_LOPEC is not set
 # CONFIG_MCPN765 is not set
 # CONFIG_MVME5100 is not set
@@ -67,7 +66,6 @@
 # CONFIG_K2 is not set
 # CONFIG_PAL4 is not set
 # CONFIG_GEMINI is not set
-# CONFIG_ZX4500 is not set
 CONFIG_GT64260=y
 CONFIG_SERIAL_CONSOLE_BAUD=115200
 # CONFIG_SMP is not set
diff -Nru a/arch/ppc/configs/gemini_defconfig b/arch/ppc/configs/gemini_defconfig
--- a/arch/ppc/configs/gemini_defconfig	Thu Jun 12 00:32:33 2003
+++ b/arch/ppc/configs/gemini_defconfig	Tue Jul  1 17:01:18 2003
@@ -55,7 +55,6 @@
 # CONFIG_POWERPMC250 is not set
 # CONFIG_EV64260 is not set
 # CONFIG_SPRUCE is not set
-# CONFIG_MENF1 is not set
 # CONFIG_LOPEC is not set
 # CONFIG_MCPN765 is not set
 # CONFIG_MVME5100 is not set
@@ -67,7 +66,6 @@
 # CONFIG_K2 is not set
 # CONFIG_PAL4 is not set
 CONFIG_GEMINI=y
-# CONFIG_ZX4500 is not set
 # CONFIG_SMP is not set
 # CONFIG_PREEMPT is not set
 CONFIG_ALTIVEC=y
diff -Nru a/arch/ppc/configs/ibmchrp_defconfig b/arch/ppc/configs/ibmchrp_defconfig
--- a/arch/ppc/configs/ibmchrp_defconfig	Thu Jun 12 00:32:33 2003
+++ b/arch/ppc/configs/ibmchrp_defconfig	Tue Jul  1 17:01:18 2003
@@ -55,7 +55,6 @@
 # CONFIG_POWERPMC250 is not set
 # CONFIG_EV64260 is not set
 # CONFIG_SPRUCE is not set
-# CONFIG_MENF1 is not set
 # CONFIG_LOPEC is not set
 # CONFIG_MCPN765 is not set
 # CONFIG_MVME5100 is not set
@@ -67,7 +66,6 @@
 # CONFIG_K2 is not set
 # CONFIG_PAL4 is not set
 # CONFIG_GEMINI is not set
-# CONFIG_ZX4500 is not set
 CONFIG_PPC_CHRP=y
 CONFIG_PPC_PMAC=y
 CONFIG_PPC_PREP=y
diff -Nru a/arch/ppc/configs/k2_defconfig b/arch/ppc/configs/k2_defconfig
--- a/arch/ppc/configs/k2_defconfig	Thu Jun 12 00:32:33 2003
+++ b/arch/ppc/configs/k2_defconfig	Tue Jul  1 17:01:18 2003
@@ -55,7 +55,6 @@
 # CONFIG_POWERPMC250 is not set
 # CONFIG_EV64260 is not set
 # CONFIG_SPRUCE is not set
-# CONFIG_MENF1 is not set
 # CONFIG_LOPEC is not set
 # CONFIG_MCPN765 is not set
 # CONFIG_MVME5100 is not set
@@ -67,7 +66,6 @@
 CONFIG_K2=y
 # CONFIG_PAL4 is not set
 # CONFIG_GEMINI is not set
-# CONFIG_ZX4500 is not set
 # CONFIG_CPC710_DATA_GATHERING is not set
 # CONFIG_SMP is not set
 # CONFIG_PREEMPT is not set
diff -Nru a/arch/ppc/configs/lopec_defconfig b/arch/ppc/configs/lopec_defconfig
--- a/arch/ppc/configs/lopec_defconfig	Thu Jun 12 00:32:33 2003
+++ b/arch/ppc/configs/lopec_defconfig	Tue Jul  1 17:01:18 2003
@@ -55,7 +55,6 @@
 # CONFIG_POWERPMC250 is not set
 # CONFIG_EV64260 is not set
 # CONFIG_SPRUCE is not set
-# CONFIG_MENF1 is not set
 CONFIG_LOPEC=y
 # CONFIG_MCPN765 is not set
 # CONFIG_MVME5100 is not set
@@ -67,7 +66,6 @@
 # CONFIG_K2 is not set
 # CONFIG_PAL4 is not set
 # CONFIG_GEMINI is not set
-# CONFIG_ZX4500 is not set
 CONFIG_EPIC_SERIAL_MODE=y
 # CONFIG_SMP is not set
 # CONFIG_PREEMPT is not set
diff -Nru a/arch/ppc/configs/mcpn765_defconfig b/arch/ppc/configs/mcpn765_defconfig
--- a/arch/ppc/configs/mcpn765_defconfig	Thu Jun 12 00:32:33 2003
+++ b/arch/ppc/configs/mcpn765_defconfig	Tue Jul  1 17:01:18 2003
@@ -50,7 +50,6 @@
 # CONFIG_POWERPMC250 is not set
 # CONFIG_EV64260 is not set
 # CONFIG_SPRUCE is not set
-# CONFIG_MENF1 is not set
 # CONFIG_LOPEC is not set
 CONFIG_MCPN765=y
 # CONFIG_MVME5100 is not set
@@ -62,7 +61,6 @@
 # CONFIG_K2 is not set
 # CONFIG_PAL4 is not set
 # CONFIG_GEMINI is not set
-# CONFIG_ZX4500 is not set
 # CONFIG_SMP is not set
 # CONFIG_PREEMPT is not set
 CONFIG_ALTIVEC=y
diff -Nru a/arch/ppc/configs/menf1_defconfig b/arch/ppc/configs/menf1_defconfig
--- a/arch/ppc/configs/menf1_defconfig	Thu Jun 12 00:32:33 2003
+++ b/arch/ppc/configs/menf1_defconfig	Tue Jul  1 16:50:27 2003
@@ -67,7 +67,6 @@
 # CONFIG_K2 is not set
 # CONFIG_PAL4 is not set
 # CONFIG_GEMINI is not set
-# CONFIG_ZX4500 is not set
 CONFIG_MPC10X_STORE_GATHERING=y
 # CONFIG_SMP is not set
 # CONFIG_PREEMPT is not set
diff -Nru a/arch/ppc/configs/mvme5100_defconfig b/arch/ppc/configs/mvme5100_defconfig
--- a/arch/ppc/configs/mvme5100_defconfig	Thu Jun 12 00:32:33 2003
+++ b/arch/ppc/configs/mvme5100_defconfig	Tue Jul  1 17:01:18 2003
@@ -55,7 +55,6 @@
 # CONFIG_POWERPMC250 is not set
 # CONFIG_EV64260 is not set
 # CONFIG_SPRUCE is not set
-# CONFIG_MENF1 is not set
 # CONFIG_LOPEC is not set
 # CONFIG_MCPN765 is not set
 CONFIG_MVME5100=y
@@ -67,7 +66,6 @@
 # CONFIG_K2 is not set
 # CONFIG_PAL4 is not set
 # CONFIG_GEMINI is not set
-# CONFIG_ZX4500 is not set
 # CONFIG_MVME5100_IPMC761_PRESENT is not set
 # CONFIG_SMP is not set
 # CONFIG_PREEMPT is not set
diff -Nru a/arch/ppc/configs/pcore_defconfig b/arch/ppc/configs/pcore_defconfig
--- a/arch/ppc/configs/pcore_defconfig	Thu Jun 12 00:32:33 2003
+++ b/arch/ppc/configs/pcore_defconfig	Tue Jul  1 17:01:18 2003
@@ -55,7 +55,6 @@
 # CONFIG_POWERPMC250 is not set
 # CONFIG_EV64260 is not set
 # CONFIG_SPRUCE is not set
-# CONFIG_MENF1 is not set
 # CONFIG_LOPEC is not set
 # CONFIG_MCPN765 is not set
 # CONFIG_MVME5100 is not set
@@ -67,7 +66,6 @@
 # CONFIG_K2 is not set
 # CONFIG_PAL4 is not set
 # CONFIG_GEMINI is not set
-# CONFIG_ZX4500 is not set
 CONFIG_FORCE=y
 # CONFIG_MPC10X_STORE_GATHERING is not set
 # CONFIG_SMP is not set
diff -Nru a/arch/ppc/configs/pmac_defconfig b/arch/ppc/configs/pmac_defconfig
--- a/arch/ppc/configs/pmac_defconfig	Thu Jun 12 00:32:33 2003
+++ b/arch/ppc/configs/pmac_defconfig	Tue Jul  1 17:01:18 2003
@@ -57,7 +57,6 @@
 # CONFIG_POWERPMC250 is not set
 # CONFIG_EV64260 is not set
 # CONFIG_SPRUCE is not set
-# CONFIG_MENF1 is not set
 # CONFIG_LOPEC is not set
 # CONFIG_MCPN765 is not set
 # CONFIG_MVME5100 is not set
@@ -69,7 +68,6 @@
 # CONFIG_K2 is not set
 # CONFIG_PAL4 is not set
 # CONFIG_GEMINI is not set
-# CONFIG_ZX4500 is not set
 CONFIG_PPC_CHRP=y
 CONFIG_PPC_PMAC=y
 CONFIG_PPC_PREP=y
diff -Nru a/arch/ppc/configs/power3_defconfig b/arch/ppc/configs/power3_defconfig
--- a/arch/ppc/configs/power3_defconfig	Thu Jun 12 00:32:33 2003
+++ b/arch/ppc/configs/power3_defconfig	Tue Jul  1 17:01:18 2003
@@ -55,7 +55,6 @@
 # CONFIG_POWERPMC250 is not set
 # CONFIG_EV64260 is not set
 # CONFIG_SPRUCE is not set
-# CONFIG_MENF1 is not set
 # CONFIG_LOPEC is not set
 # CONFIG_MCPN765 is not set
 # CONFIG_MVME5100 is not set
@@ -67,7 +66,6 @@
 # CONFIG_K2 is not set
 # CONFIG_PAL4 is not set
 # CONFIG_GEMINI is not set
-# CONFIG_ZX4500 is not set
 CONFIG_PPC_CHRP=y
 CONFIG_PPC_PMAC=y
 CONFIG_PPC_PREP=y
diff -Nru a/arch/ppc/configs/pplus_defconfig b/arch/ppc/configs/pplus_defconfig
--- a/arch/ppc/configs/pplus_defconfig	Thu Jun 12 00:32:33 2003
+++ b/arch/ppc/configs/pplus_defconfig	Tue Jul  1 17:01:18 2003
@@ -55,7 +55,6 @@
 # CONFIG_POWERPMC250 is not set
 # CONFIG_EV64260 is not set
 # CONFIG_SPRUCE is not set
-# CONFIG_MENF1 is not set
 # CONFIG_LOPEC is not set
 # CONFIG_MCPN765 is not set
 # CONFIG_MVME5100 is not set
@@ -67,7 +66,6 @@
 # CONFIG_K2 is not set
 # CONFIG_PAL4 is not set
 # CONFIG_GEMINI is not set
-# CONFIG_ZX4500 is not set
 # CONFIG_SMP is not set
 # CONFIG_PREEMPT is not set
 # CONFIG_ALTIVEC is not set
diff -Nru a/arch/ppc/configs/prpmc750_defconfig b/arch/ppc/configs/prpmc750_defconfig
--- a/arch/ppc/configs/prpmc750_defconfig	Thu Jun 12 00:32:34 2003
+++ b/arch/ppc/configs/prpmc750_defconfig	Tue Jul  1 17:01:18 2003
@@ -55,7 +55,6 @@
 # CONFIG_POWERPMC250 is not set
 # CONFIG_EV64260 is not set
 # CONFIG_SPRUCE is not set
-# CONFIG_MENF1 is not set
 # CONFIG_LOPEC is not set
 # CONFIG_MCPN765 is not set
 # CONFIG_MVME5100 is not set
@@ -67,7 +66,6 @@
 # CONFIG_K2 is not set
 # CONFIG_PAL4 is not set
 # CONFIG_GEMINI is not set
-# CONFIG_ZX4500 is not set
 # CONFIG_SMP is not set
 # CONFIG_PREEMPT is not set
 # CONFIG_ALTIVEC is not set
diff -Nru a/arch/ppc/configs/prpmc800_defconfig b/arch/ppc/configs/prpmc800_defconfig
--- a/arch/ppc/configs/prpmc800_defconfig	Thu Jun 12 00:32:34 2003
+++ b/arch/ppc/configs/prpmc800_defconfig	Tue Jul  1 17:01:18 2003
@@ -55,7 +55,6 @@
 # CONFIG_POWERPMC250 is not set
 # CONFIG_EV64260 is not set
 # CONFIG_SPRUCE is not set
-# CONFIG_MENF1 is not set
 # CONFIG_LOPEC is not set
 # CONFIG_MCPN765 is not set
 # CONFIG_MVME5100 is not set
@@ -67,7 +66,6 @@
 # CONFIG_K2 is not set
 # CONFIG_PAL4 is not set
 # CONFIG_GEMINI is not set
-# CONFIG_ZX4500 is not set
 # CONFIG_SMP is not set
 # CONFIG_PREEMPT is not set
 # CONFIG_ALTIVEC is not set
diff -Nru a/arch/ppc/configs/sandpoint_defconfig b/arch/ppc/configs/sandpoint_defconfig
--- a/arch/ppc/configs/sandpoint_defconfig	Thu Jun 12 00:32:34 2003
+++ b/arch/ppc/configs/sandpoint_defconfig	Wed Jul  2 17:44:13 2003
@@ -55,7 +55,6 @@
 # CONFIG_POWERPMC250 is not set
 # CONFIG_EV64260 is not set
 # CONFIG_SPRUCE is not set
-# CONFIG_MENF1 is not set
 # CONFIG_LOPEC is not set
 # CONFIG_MCPN765 is not set
 # CONFIG_MVME5100 is not set
@@ -67,8 +66,7 @@
 # CONFIG_K2 is not set
 # CONFIG_PAL4 is not set
 # CONFIG_GEMINI is not set
-# CONFIG_ZX4500 is not set
-CONFIG_SANDPOINT_X3=y
+CONFIG_PPC_GEN550=y
 CONFIG_EPIC_SERIAL_MODE=y
 # CONFIG_MPC10X_STORE_GATHERING is not set
 # CONFIG_SMP is not set
@@ -84,8 +82,8 @@
 CONFIG_PCI=y
 CONFIG_PCI_DOMAINS=y
 CONFIG_KCORE_ELF=y
-CONFIG_BINFMT_ELF=y
 CONFIG_KERNEL_ELF=y
+CONFIG_BINFMT_ELF=y
 CONFIG_BINFMT_MISC=m
 # CONFIG_PCI_LEGACY_PROC is not set
 # CONFIG_PCI_NAMES is not set
@@ -118,6 +116,11 @@
 CONFIG_BOOT_LOAD=0x00800000
 
 #
+# Generic Driver Options
+#
+# CONFIG_FW_LOADER is not set
+
+#
 # Memory Technology Devices (MTD)
 #
 # CONFIG_MTD is not set
@@ -147,7 +150,7 @@
 # CONFIG_MD is not set
 
 #
-# ATA/IDE/MFM/RLL support
+# ATA/ATAPI/MFM/RLL support
 #
 CONFIG_IDE=y
 
@@ -166,6 +169,7 @@
 CONFIG_BLK_DEV_IDECD=y
 # CONFIG_BLK_DEV_IDEFLOPPY is not set
 # CONFIG_IDE_TASK_IOCTL is not set
+CONFIG_IDE_TASKFILE_IO=y
 
 #
 # IDE chipset support/bugfixes
@@ -173,7 +177,7 @@
 # CONFIG_BLK_DEV_IDEPCI is not set
 
 #
-# SCSI support
+# SCSI device support
 #
 # CONFIG_SCSI is not set
 
@@ -292,6 +296,7 @@
 # CONFIG_AMD8111_ETH is not set
 # CONFIG_ADAPTEC_STARFIRE is not set
 # CONFIG_B44 is not set
+# CONFIG_TC35815 is not set
 # CONFIG_DGRS is not set
 # CONFIG_EEPRO100 is not set
 CONFIG_E100=y
@@ -413,11 +418,6 @@
 # CONFIG_LOGO is not set
 
 #
-# Old CD-ROM drivers (not SCSI, not IDE)
-#
-# CONFIG_CD_NO_IDESCSI is not set
-
-#
 # Input device support
 #
 CONFIG_INPUT=y
@@ -443,6 +443,7 @@
 CONFIG_SERIO_I8042=y
 # CONFIG_SERIO_SERPORT is not set
 # CONFIG_SERIO_CT82C710 is not set
+# CONFIG_SERIO_PCIPS2 is not set
 
 #
 # Input Device Drivers
@@ -731,6 +732,7 @@
 #
 # USB Network adaptors
 #
+# CONFIG_USB_AX8817X is not set
 # CONFIG_USB_CATC is not set
 # CONFIG_USB_KAWETH is not set
 # CONFIG_USB_PEGASUS is not set
diff -Nru a/arch/ppc/configs/spruce_defconfig b/arch/ppc/configs/spruce_defconfig
--- a/arch/ppc/configs/spruce_defconfig	Thu Jun 12 00:32:34 2003
+++ b/arch/ppc/configs/spruce_defconfig	Tue Jul  1 17:01:18 2003
@@ -55,7 +55,6 @@
 # CONFIG_POWERPMC250 is not set
 # CONFIG_EV64260 is not set
 CONFIG_SPRUCE=y
-# CONFIG_MENF1 is not set
 # CONFIG_LOPEC is not set
 # CONFIG_MCPN765 is not set
 # CONFIG_MVME5100 is not set
@@ -67,7 +66,6 @@
 # CONFIG_K2 is not set
 # CONFIG_PAL4 is not set
 # CONFIG_GEMINI is not set
-# CONFIG_ZX4500 is not set
 # CONFIG_SPRUCE_BAUD_33M is not set
 # CONFIG_SMP is not set
 # CONFIG_PREEMPT is not set
diff -Nru a/arch/ppc/configs/zx4500_defconfig b/arch/ppc/configs/zx4500_defconfig
--- a/arch/ppc/configs/zx4500_defconfig	Thu Jun 12 00:32:34 2003
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,560 +0,0 @@
-#
-# Automatically generated make config: don't edit
-#
-CONFIG_MMU=y
-CONFIG_RWSEM_XCHGADD_ALGORITHM=y
-CONFIG_HAVE_DEC_LOCK=y
-
-#
-# Code maturity level options
-#
-CONFIG_EXPERIMENTAL=y
-
-#
-# General setup
-#
-CONFIG_SWAP=y
-CONFIG_SYSVIPC=y
-# CONFIG_BSD_PROCESS_ACCT is not set
-CONFIG_SYSCTL=y
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_EMBEDDED=y
-CONFIG_FUTEX=y
-# CONFIG_EPOLL is not set
-
-#
-# Loadable module support
-#
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-# CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
-# CONFIG_MODVERSIONS is not set
-CONFIG_KMOD=y
-
-#
-# Platform support
-#
-CONFIG_PPC=y
-CONFIG_PPC32=y
-CONFIG_6xx=y
-# CONFIG_40x is not set
-# CONFIG_POWER3 is not set
-# CONFIG_8xx is not set
-
-#
-# IBM 4xx options
-#
-# CONFIG_8260 is not set
-CONFIG_GENERIC_ISA_DMA=y
-CONFIG_PPC_STD_MMU=y
-# CONFIG_PPC_MULTIPLATFORM is not set
-# CONFIG_APUS is not set
-# CONFIG_WILLOW_2 is not set
-# CONFIG_PCORE is not set
-# CONFIG_POWERPMC250 is not set
-# CONFIG_EV64260 is not set
-# CONFIG_SPRUCE is not set
-# CONFIG_MENF1 is not set
-# CONFIG_LOPEC is not set
-# CONFIG_MCPN765 is not set
-# CONFIG_MVME5100 is not set
-# CONFIG_PPLUS is not set
-# CONFIG_PRPMC750 is not set
-# CONFIG_PRPMC800 is not set
-# CONFIG_SANDPOINT is not set
-# CONFIG_ADIR is not set
-# CONFIG_K2 is not set
-# CONFIG_PAL4 is not set
-# CONFIG_GEMINI is not set
-CONFIG_ZX4500=y
-# CONFIG_MPC10X_STORE_GATHERING is not set
-# CONFIG_SMP is not set
-# CONFIG_PREEMPT is not set
-# CONFIG_ALTIVEC is not set
-# CONFIG_TAU is not set
-# CONFIG_CPU_FREQ is not set
-
-#
-# General setup
-#
-# CONFIG_HIGHMEM is not set
-CONFIG_PCI=y
-CONFIG_PCI_DOMAINS=y
-CONFIG_KCORE_ELF=y
-CONFIG_BINFMT_ELF=y
-CONFIG_KERNEL_ELF=y
-CONFIG_BINFMT_MISC=y
-# CONFIG_PCI_LEGACY_PROC is not set
-CONFIG_PCI_NAMES=y
-# CONFIG_HOTPLUG is not set
-
-#
-# Parallel port support
-#
-# CONFIG_PARPORT is not set
-CONFIG_PPC601_SYNC_FIX=y
-# CONFIG_CMDLINE_BOOL is not set
-
-#
-# Advanced setup
-#
-# CONFIG_ADVANCED_OPTIONS is not set
-
-#
-# Default settings for advanced configuration options are used
-#
-CONFIG_HIGHMEM_START=0xfe000000
-CONFIG_LOWMEM_SIZE=0x30000000
-CONFIG_KERNEL_START=0xc0000000
-CONFIG_TASK_SIZE=0x80000000
-CONFIG_BOOT_LOAD=0x00800000
-
-#
-# Memory Technology Devices (MTD)
-#
-# CONFIG_MTD is not set
-
-#
-# Plug and Play support
-#
-# CONFIG_PNP is not set
-
-#
-# Block devices
-#
-# CONFIG_BLK_DEV_FD is not set
-# CONFIG_BLK_CPQ_DA is not set
-# CONFIG_BLK_CPQ_CISS_DA is not set
-# CONFIG_BLK_DEV_DAC960 is not set
-# CONFIG_BLK_DEV_UMEM is not set
-CONFIG_BLK_DEV_LOOP=y
-CONFIG_BLK_DEV_NBD=y
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_SIZE=16384
-CONFIG_BLK_DEV_INITRD=y
-
-#
-# Multi-device support (RAID and LVM)
-#
-# CONFIG_MD is not set
-
-#
-# ATA/IDE/MFM/RLL support
-#
-# CONFIG_IDE is not set
-
-#
-# SCSI support
-#
-# CONFIG_SCSI is not set
-
-#
-# Fusion MPT device support
-#
-
-#
-# IEEE 1394 (FireWire) support (EXPERIMENTAL)
-#
-# CONFIG_IEEE1394 is not set
-
-#
-# I2O device support
-#
-# CONFIG_I2O is not set
-
-#
-# Networking support
-#
-CONFIG_NET=y
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-# CONFIG_PACKET_MMAP is not set
-# CONFIG_NETLINK_DEV is not set
-# CONFIG_NETFILTER is not set
-CONFIG_UNIX=y
-# CONFIG_NET_KEY is not set
-CONFIG_INET=y
-# CONFIG_IP_MULTICAST is not set
-# CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-CONFIG_IP_PNP_BOOTP=y
-# CONFIG_IP_PNP_RARP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_ARPD is not set
-# CONFIG_INET_ECN is not set
-CONFIG_SYN_COOKIES=y
-# CONFIG_INET_AH is not set
-# CONFIG_INET_ESP is not set
-# CONFIG_INET_IPCOMP is not set
-# CONFIG_IPV6 is not set
-# CONFIG_XFRM_USER is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-CONFIG_IPV6_SCTP__=y
-# CONFIG_IP_SCTP is not set
-# CONFIG_ATM is not set
-# CONFIG_VLAN_8021Q is not set
-# CONFIG_LLC is not set
-# CONFIG_DECNET is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_NET_DIVERT is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-# CONFIG_NET_FASTROUTE is not set
-# CONFIG_NET_HW_FLOWCONTROL is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-CONFIG_NETDEVICES=y
-
-#
-# ARCnet devices
-#
-# CONFIG_ARCNET is not set
-# CONFIG_DUMMY is not set
-# CONFIG_BONDING is not set
-# CONFIG_EQUALIZER is not set
-# CONFIG_TUN is not set
-# CONFIG_ETHERTAP is not set
-
-#
-# Ethernet (10 or 100Mbit)
-#
-CONFIG_NET_ETHERNET=y
-# CONFIG_MII is not set
-# CONFIG_OAKNET is not set
-# CONFIG_HAPPYMEAL is not set
-# CONFIG_SUNGEM is not set
-# CONFIG_NET_VENDOR_3COM is not set
-
-#
-# Tulip family network device support
-#
-# CONFIG_NET_TULIP is not set
-# CONFIG_HP100 is not set
-CONFIG_NET_PCI=y
-# CONFIG_PCNET32 is not set
-# CONFIG_AMD8111_ETH is not set
-# CONFIG_ADAPTEC_STARFIRE is not set
-# CONFIG_B44 is not set
-# CONFIG_DGRS is not set
-CONFIG_EEPRO100=y
-# CONFIG_EEPRO100_PIO is not set
-# CONFIG_E100 is not set
-# CONFIG_FEALNX is not set
-# CONFIG_NATSEMI is not set
-# CONFIG_NE2K_PCI is not set
-# CONFIG_8139CP is not set
-# CONFIG_8139TOO is not set
-# CONFIG_SIS900 is not set
-# CONFIG_EPIC100 is not set
-# CONFIG_SUNDANCE is not set
-# CONFIG_TLAN is not set
-# CONFIG_VIA_RHINE is not set
-
-#
-# Ethernet (1000 Mbit)
-#
-# CONFIG_ACENIC is not set
-# CONFIG_DL2K is not set
-# CONFIG_E1000 is not set
-# CONFIG_NS83820 is not set
-# CONFIG_HAMACHI is not set
-# CONFIG_YELLOWFIN is not set
-# CONFIG_R8169 is not set
-# CONFIG_SK98LIN is not set
-# CONFIG_TIGON3 is not set
-
-#
-# Ethernet (10000 Mbit)
-#
-# CONFIG_IXGB is not set
-# CONFIG_FDDI is not set
-# CONFIG_HIPPI is not set
-# CONFIG_PPP is not set
-# CONFIG_SLIP is not set
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
-
-#
-# Token Ring devices (depends on LLC=y)
-#
-# CONFIG_RCPCI is not set
-# CONFIG_SHAPER is not set
-
-#
-# Wan interfaces
-#
-# CONFIG_WAN is not set
-
-#
-# Amateur Radio support
-#
-# CONFIG_HAMRADIO is not set
-
-#
-# IrDA (infrared) support
-#
-# CONFIG_IRDA is not set
-
-#
-# ISDN subsystem
-#
-# CONFIG_ISDN_BOOL is not set
-
-#
-# Graphics support
-#
-# CONFIG_FB is not set
-
-#
-# Old CD-ROM drivers (not SCSI, not IDE)
-#
-# CONFIG_CD_NO_IDESCSI is not set
-
-#
-# Input device support
-#
-# CONFIG_INPUT is not set
-
-#
-# Userland interfaces
-#
-
-#
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-# CONFIG_SERIO is not set
-
-#
-# Input Device Drivers
-#
-
-#
-# Macintosh device drivers
-#
-
-#
-# Character devices
-#
-# CONFIG_SERIAL_NONSTANDARD is not set
-
-#
-# Serial drivers
-#
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-# CONFIG_SERIAL_8250_EXTENDED is not set
-
-#
-# Non-8250 serial port support
-#
-CONFIG_SERIAL_CORE=y
-CONFIG_SERIAL_CORE_CONSOLE=y
-CONFIG_UNIX98_PTYS=y
-CONFIG_UNIX98_PTY_COUNT=256
-
-#
-# I2C support
-#
-# CONFIG_I2C is not set
-
-#
-# I2C Hardware Sensors Mainboard support
-#
-
-#
-# I2C Hardware Sensors Chip support
-#
-# CONFIG_I2C_SENSOR is not set
-
-#
-# Mice
-#
-# CONFIG_BUSMOUSE is not set
-# CONFIG_QIC02_TAPE is not set
-
-#
-# IPMI
-#
-# CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
-# CONFIG_WATCHDOG is not set
-# CONFIG_NVRAM is not set
-CONFIG_GEN_RTC=y
-# CONFIG_GEN_RTC_X is not set
-# CONFIG_DTLK is not set
-# CONFIG_R3964 is not set
-# CONFIG_APPLICOM is not set
-
-#
-# Ftape, the floppy tape device driver
-#
-# CONFIG_FTAPE is not set
-# CONFIG_AGP is not set
-# CONFIG_DRM is not set
-# CONFIG_RAW_DRIVER is not set
-# CONFIG_HANGCHECK_TIMER is not set
-
-#
-# Multimedia devices
-#
-# CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-# CONFIG_DVB is not set
-
-#
-# File systems
-#
-CONFIG_EXT2_FS=y
-# CONFIG_EXT2_FS_XATTR is not set
-CONFIG_EXT3_FS=y
-CONFIG_EXT3_FS_XATTR=y
-# CONFIG_EXT3_FS_POSIX_ACL is not set
-# CONFIG_EXT3_FS_SECURITY is not set
-CONFIG_JBD=y
-# CONFIG_JBD_DEBUG is not set
-CONFIG_FS_MBCACHE=y
-# CONFIG_REISERFS_FS is not set
-# CONFIG_JFS_FS is not set
-# CONFIG_XFS_FS is not set
-# CONFIG_MINIX_FS is not set
-# CONFIG_ROMFS_FS is not set
-# CONFIG_QUOTA is not set
-# CONFIG_AUTOFS_FS is not set
-# CONFIG_AUTOFS4_FS is not set
-
-#
-# CD-ROM/DVD Filesystems
-#
-CONFIG_ISO9660_FS=y
-# CONFIG_JOLIET is not set
-# CONFIG_ZISOFS is not set
-# CONFIG_UDF_FS is not set
-
-#
-# DOS/FAT/NT Filesystems
-#
-# CONFIG_FAT_FS is not set
-# CONFIG_NTFS_FS is not set
-
-#
-# Pseudo filesystems
-#
-CONFIG_PROC_FS=y
-CONFIG_DEVFS_FS=y
-# CONFIG_DEVFS_MOUNT is not set
-# CONFIG_DEVFS_DEBUG is not set
-CONFIG_DEVPTS_FS=y
-# CONFIG_DEVPTS_FS_XATTR is not set
-CONFIG_TMPFS=y
-CONFIG_RAMFS=y
-
-#
-# Miscellaneous filesystems
-#
-# CONFIG_ADFS_FS is not set
-# CONFIG_AFFS_FS is not set
-# CONFIG_HFS_FS is not set
-# CONFIG_BEFS_FS is not set
-# CONFIG_BFS_FS is not set
-# CONFIG_EFS_FS is not set
-# CONFIG_CRAMFS is not set
-# CONFIG_VXFS_FS is not set
-# CONFIG_HPFS_FS is not set
-# CONFIG_QNX4FS_FS is not set
-# CONFIG_SYSV_FS is not set
-# CONFIG_UFS_FS is not set
-
-#
-# Network File Systems
-#
-CONFIG_NFS_FS=y
-# CONFIG_NFS_V3 is not set
-# CONFIG_NFS_V4 is not set
-CONFIG_NFSD=y
-# CONFIG_NFSD_V3 is not set
-# CONFIG_NFSD_TCP is not set
-CONFIG_ROOT_NFS=y
-CONFIG_LOCKD=y
-CONFIG_EXPORTFS=y
-CONFIG_SUNRPC=y
-# CONFIG_SUNRPC_GSS is not set
-# CONFIG_SMB_FS is not set
-# CONFIG_CIFS is not set
-# CONFIG_NCP_FS is not set
-# CONFIG_CODA_FS is not set
-# CONFIG_INTERMEZZO_FS is not set
-# CONFIG_AFS_FS is not set
-
-#
-# Partition Types
-#
-# CONFIG_PARTITION_ADVANCED is not set
-CONFIG_MSDOS_PARTITION=y
-
-#
-# Sound
-#
-# CONFIG_SOUND is not set
-
-#
-# USB support
-#
-# CONFIG_USB is not set
-# CONFIG_USB_GADGET is not set
-
-#
-# Bluetooth support
-#
-# CONFIG_BT is not set
-
-#
-# Library routines
-#
-# CONFIG_CRC32 is not set
-
-#
-# Kernel hacking
-#
-# CONFIG_DEBUG_KERNEL is not set
-# CONFIG_KALLSYMS is not set
-CONFIG_SERIAL_TEXT_DEBUG=y
-
-#
-# Security options
-#
-# CONFIG_SECURITY is not set
-
-#
-# Cryptographic options
-#
-# CONFIG_CRYPTO is not set
diff -Nru a/arch/ppc/defconfig b/arch/ppc/defconfig
--- a/arch/ppc/defconfig	Thu Jun 12 00:32:34 2003
+++ b/arch/ppc/defconfig	Tue Jul  1 17:01:18 2003
@@ -56,7 +56,6 @@
 # CONFIG_POWERPMC250 is not set
 # CONFIG_EV64260 is not set
 # CONFIG_SPRUCE is not set
-# CONFIG_MENF1 is not set
 # CONFIG_LOPEC is not set
 # CONFIG_MCPN765 is not set
 # CONFIG_MVME5100 is not set
@@ -68,7 +67,6 @@
 # CONFIG_K2 is not set
 # CONFIG_PAL4 is not set
 # CONFIG_GEMINI is not set
-# CONFIG_ZX4500 is not set
 CONFIG_PPC_CHRP=y
 CONFIG_PPC_PMAC=y
 CONFIG_PPC_PREP=y
diff -Nru a/arch/ppc/kernel/ppc-stub.c b/arch/ppc/kernel/ppc-stub.c
--- a/arch/ppc/kernel/ppc-stub.c	Wed Mar 12 11:52:59 2003
+++ b/arch/ppc/kernel/ppc-stub.c	Mon Jun 30 10:10:33 2003
@@ -851,14 +851,4 @@
 	putpacket(buffer);
 
 	return 1;
- }
-
-#if defined(CONFIG_6xx) || defined(CONFIG_POWER3)
-
-/* This is used on arches which don't have a serial driver that maps
- * the ports for us */
-void
-kgdb_map_scc(void)
-{
 }
-#endif
diff -Nru a/arch/ppc/kernel/ppc_ksyms.c b/arch/ppc/kernel/ppc_ksyms.c
--- a/arch/ppc/kernel/ppc_ksyms.c	Sat Jun  7 02:18:01 2003
+++ b/arch/ppc/kernel/ppc_ksyms.c	Tue Jul  1 10:57:22 2003
@@ -272,8 +272,10 @@
 #ifdef CONFIG_NVRAM
 EXPORT_SYMBOL(nvram_read_byte);
 EXPORT_SYMBOL(nvram_write_byte);
+#ifdef CONFIG_PPC_PMAC
 EXPORT_SYMBOL(pmac_xpram_read);
 EXPORT_SYMBOL(pmac_xpram_write);
+#endif
 #endif /* CONFIG_NVRAM */
 EXPORT_SYMBOL(to_tm);
 
diff -Nru a/arch/ppc/kernel/setup.c b/arch/ppc/kernel/setup.c
--- a/arch/ppc/kernel/setup.c	Wed Jun  4 20:07:16 2003
+++ b/arch/ppc/kernel/setup.c	Mon Jun 30 10:10:33 2003
@@ -619,6 +619,8 @@
 	if (strstr(cmd_line, "nokgdb"))
 		printk("kgdb default breakpoint deactivated on command line\n");
 	else {
+		if (ppc_md.progress)
+			ppc_md.progress("setup_arch: kgdb breakpoint", 0x4000);
 		printk("kgdb default breakpoint activated\n");
 		breakpoint();
 	}
diff -Nru a/arch/ppc/platforms/Makefile b/arch/ppc/platforms/Makefile
--- a/arch/ppc/platforms/Makefile	Wed Jun  4 19:11:18 2003
+++ b/arch/ppc/platforms/Makefile	Wed Jul  2 17:44:14 2003
@@ -43,9 +43,8 @@
 obj-$(CONFIG_PPLUS)		+= pplus_pci.o pplus_setup.o
 obj-$(CONFIG_PRPMC750)		+= prpmc750_setup.o prpmc750_pci.o
 obj-$(CONFIG_PRPMC800)		+= prpmc800_setup.o prpmc800_pci.o
-obj-$(CONFIG_SANDPOINT)		+= sandpoint_setup.o sandpoint_pci.o
+obj-$(CONFIG_SANDPOINT)		+= sandpoint.o
 obj-$(CONFIG_SPRUCE)		+= spruce_setup.o spruce_pci.o
-obj-$(CONFIG_ZX4500)		+= zx4500_setup.o zx4500_pci.o
 
 ifeq ($(CONFIG_SMP),y)
 obj-$(CONFIG_PPC_PMAC)		+= pmac_smp.o
diff -Nru a/arch/ppc/platforms/menf1.h b/arch/ppc/platforms/menf1.h
--- a/arch/ppc/platforms/menf1.h	Tue Feb 11 15:48:53 2003
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,24 +0,0 @@
-/*
- * arch/ppc/platforms/menf1.h
- * 
- * Definitions for MEN F1 board support
- *
- * Author: Matt Porter <mporter@mvista.com>
- *
- * 2001 (c) MontaVista, Software, Inc.  This file is licensed under
- * the terms of the GNU General Public License version 2.  This program
- * is licensed "as is" without any warranty of any kind, whether express
- * or implied.
- */
-
-#ifndef __PPC_PLATFORMS_MENF1_H
-#define __PPC_PLATFORMS_MENF1_H
-
-#define MENF1_NVRAM_AS0			0x70
-#define MENF1_NVRAM_AS1			0x72
-#define MENF1_NVRAM_DATA		0x71    
-
-#define	MENF1_IDE0_BASE_ADDR		0x1f0
-#define MENF1_IDE1_BASE_ADDR		0x170
-
-#endif /* __PPC_PLATFORMS_MENF1_H */
diff -Nru a/arch/ppc/platforms/menf1_pci.c b/arch/ppc/platforms/menf1_pci.c
--- a/arch/ppc/platforms/menf1_pci.c	Tue Feb 11 15:48:53 2003
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,98 +0,0 @@
-/*
- * arch/ppc/platforms/menf1_pci.c
- * 
- * PCI support for MEN F1
- *
- * Author: Matt Porter <mporter@mvista.com>
- *
- * 2001 (c) MontaVista, Software, Inc.  This file is licensed under
- * the terms of the GNU General Public License version 2.  This program
- * is licensed "as is" without any warranty of any kind, whether express
- * or implied.
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-#include <linux/slab.h>
-
-#include <asm/byteorder.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/uaccess.h>
-#include <asm/machdep.h>
-#include <asm/pci-bridge.h>
-#include <asm/mpc10x.h>
-
-#include "menf1.h"
-
-#undef DEBUG
-#ifdef DEBUG
-#define DBG(x...) printk(x)
-#else
-#define DBG(x...)
-#endif /* DEBUG */ 
-
-static inline int __init
-menf1_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
-{
-	static char pci_irq_table[][4] =
-	/*
-	 *      PCI IDSEL/INTPIN->INTLINE
-	 *      A       B       C       D
-	 */ 
-	{
-		{10,	11,	7,	9},	/* IDSEL 26 - PCMIP 0 */
-		{0,	0,	0,	0},	/* IDSEL 27 - M5229 IDE */
-		{0,	0,	0,	0},	/* IDSEL 28 - M7101 PMU */
-		{9,	10,	11,	7},	/* IDSEL 29 - PCMIP 1 */
-		{10,	11,	7,	9},	/* IDSEL 30 - P2P Bridge */
-	};
-	const long min_idsel = 26, max_idsel = 30, irqs_per_slot = 4;
-	return PCI_IRQ_TABLE_LOOKUP;
-};
-
-static int
-menf1_exclude_device(u_char bus, u_char devfn)
-{
-	if ((bus == 0) && (devfn == 0xe0)) {
-		return PCIBIOS_DEVICE_NOT_FOUND;
-	}
-	else {
-		return PCIBIOS_SUCCESSFUL;
-	}
-}
-
-void __init
-menf1_find_bridges(void)
-{
-	struct pci_controller* hose;
-
-	hose = pcibios_alloc_controller();
-	if (!hose)
-		return;
-
-	hose->first_busno = 0;
-	hose->last_busno = 0xff;
-
-	ppc_md.pci_exclude_device = menf1_exclude_device;
-
-	mpc10x_bridge_init(hose,
-			MPC10X_MEM_MAP_B,
-			MPC10X_MEM_MAP_B,
-			MPC10X_MAPB_EUMB_BASE);
-
-	hose->last_busno = pciauto_bus_scan(hose, hose->first_busno);
-
-	{
-		/* Add ISA bus wait states */
-		unsigned char isa_control;
-
-		early_read_config_byte(hose, 0, 0x90, 0x43, &isa_control);
-		isa_control |= 0x33;
-		early_write_config_byte(hose, 0, 0x90, 0x43, isa_control);
-	}
-
-	ppc_md.pci_swizzle = common_swizzle;
-	ppc_md.pci_map_irq = menf1_map_irq;
-}
diff -Nru a/arch/ppc/platforms/menf1_setup.c b/arch/ppc/platforms/menf1_setup.c
--- a/arch/ppc/platforms/menf1_setup.c	Sun Apr 20 09:14:40 2003
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,283 +0,0 @@
-/*
- * arch/ppc/platforms/menf1_setup.c
- *
- * Board setup routines for MEN F1
- *
- * Author: Matt Porter <mporter@mvista.com>
- *
- * 2001 (c) MontaVista, Software, Inc.  This file is licensed under
- * the terms of the GNU General Public License version 2.  This program
- * is licensed "as is" without any warranty of any kind, whether express
- * or implied.
- */
-
-#include <linux/config.h>
-#include <linux/stddef.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/errno.h>
-#include <linux/reboot.h>
-#include <linux/pci.h>
-#include <linux/kdev_t.h>
-#include <linux/types.h>
-#include <linux/major.h>
-#include <linux/initrd.h>
-#include <linux/console.h>
-#include <linux/delay.h>
-#include <linux/ide.h>
-#include <linux/irq.h>
-#include <linux/seq_file.h>
-#include <linux/root_dev.h>
-
-#include <asm/system.h>
-#include <asm/pgtable.h>
-#include <asm/page.h>
-#include <asm/dma.h>
-#include <asm/io.h>
-#include <asm/machdep.h>
-#include <asm/time.h>
-#include <asm/i8259.h>
-#include <asm/mpc10x.h>
-#include <asm/todc.h>
-#include <asm/bootinfo.h>
-
-#include "menf1.h"
-
-extern void menf1_find_bridges(void);
-extern unsigned long loops_per_jiffy;
-
-/* Dummy variable to satisfy mpc10x_common.o */
-void *OpenPIC_Addr;
-
-static int
-menf1_show_cpuinfo(struct seq_file *m)
-{
-	seq_printf(m, "machine\t\t: MEN F1\n");
-
-	return 0;
-}
-
-static void __init
-menf1_setup_arch(void)
-{
-	/* init to some ~sane value until calibrate_delay() runs */
-	loops_per_jiffy = 50000000/HZ;
-
-	/* Lookup PCI host bridges */
-	menf1_find_bridges();
-
-#ifdef CONFIG_BLK_DEV_INITRD
-        if (initrd_start)
-                ROOT_DEV = Root_RAM0;
-        else
-#endif
-#ifdef CONFIG_ROOT_NFS
-		ROOT_DEV = Root_NFS;
-#else
-		ROOT_DEV = Root_HDA2;
-#endif
-
-#ifdef CONFIG_DUMMY_CONSOLE
-	conswitchp = &dummy_con;
-#endif
-
-	printk("MEN F1 port (C) 2001 MontaVista Software, Inc. (source@mvista.com)\n");
-}
-
-static void
-menf1_restart(char *cmd)
-{
-
-       int     picr1;
-       struct pci_dev *pdev;
-
-	local_irq_disable();
-
-	/*
-	 * Firmware doesn't like re-entry using Map B (CHRP), so make sure the
-	 * PCI bridge is using MAP A (PReP).
-	 */
-
-	pdev = pci_find_slot(0, PCI_DEVFN(0,0));
-
-	while(pdev == NULL); /* paranoia */
-
-	pci_read_config_dword(pdev, MPC10X_CFG_PICR1_REG, &picr1);
-
-	picr1 = (picr1 & ~MPC10X_CFG_PICR1_ADDR_MAP_MASK) |
-		MPC10X_CFG_PICR1_ADDR_MAP_A;
-
-	pci_write_config_dword(pdev, MPC10X_CFG_PICR1_REG, picr1);
-
-	asm volatile("sync");
-
-	/* SRR0 has system reset vector, SRR1 has default MSR value */
-	/* rfi restores MSR from SRR1 and sets the PC to the SRR0 value */
-	__asm__ __volatile__
-	("\n\
-	lis     3,0xfff0
-	ori     3,3,0x0100
-	mtspr   26,3
-	li      3,0
-	mtspr   27,3
-	rfi
-	");
-	while(1);
-}
-
-static void
-menf1_halt(void)
-{
-	local_irq_disable();
-	while (1);
-}
-
-static void
-menf1_power_off(void)
-{
-	menf1_halt();
-}
-
-static void __init
-menf1_init_IRQ(void)
-{
-	int i;
-
-	for ( i = 0 ; i < NUM_8259_INTERRUPTS  ; i++ )
-		irq_desc[i].handler = &i8259_pic;
-	i8259_init(NULL);
-}
-
-/*
- * Set BAT 3 to map 0xF0000000.
- */
-static __inline__ void
-menf1_set_bat(void)
-{
-	static int	mapping_set = 0;
-
-	if (!mapping_set)
-	{
-
-		/* wait for all outstanding memory accesses to complete */
-		mb();
-
-		/* setup DBATs */
-		mtspr(DBAT3U, 0xf0001ffe);
-		mtspr(DBAT3L, 0xf000002a);
-
-		/* wait for updates */
-		mb();
-
-		mapping_set = 1;
-	}
-	return;
-}
-
-static unsigned long __init
-menf1_find_end_of_memory(void)
-{
-	/* Cover the I/O with a BAT */
-	menf1_set_bat();
-
-	/* Read the memory size from the MPC107 SMC */
-	return mpc10x_get_mem_size(MPC10X_MEM_MAP_B);
-}
-
-static void __init
-menf1_map_io(void)
-{
-        io_block_mapping(0xfe000000, 0xfe000000, 0x02000000, _PAGE_IO);
-}
-
-#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
-/* IDE functions */
-
-static void __init
-menf1_ide_init_hwif_ports (hw_regs_t *hw, unsigned long data_port,
-		unsigned long ctrl_port, int *irq)
-{
-	unsigned long reg = data_port;
-	int i = 8;
-
-	for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) {
-		hw->io_ports[i] = reg;
-		reg += 1;
-	}
-	if (ctrl_port)
-		hw->io_ports[IDE_CONTROL_OFFSET] = ctrl_port;
-	else
-		hw->io_ports[IDE_CONTROL_OFFSET] =
-			hw->io_ports[IDE_DATA_OFFSET] + 0x206;
-
-	if (irq != NULL)
-		*irq = 0;
-}
-
-static int
-menf1_ide_default_irq(unsigned long base)
-{
-	if (base == MENF1_IDE0_BASE_ADDR)
-		return 14;
-	else if (base == MENF1_IDE1_BASE_ADDR)
-		return 15;
-	else
-		return 0;
-}
-
-static unsigned long
-menf1_ide_default_io_base(int index)
-{
-	if (index == 0)
-		return MENF1_IDE0_BASE_ADDR;
-	else if (index == 1)
-		return MENF1_IDE1_BASE_ADDR;
-	else
-		return 0;
-}
-#endif
-
-TODC_ALLOC();
-
-void __init
-platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
-	      unsigned long r6, unsigned long r7)
-{
-	parse_bootinfo(find_bootinfo());
-
-	isa_io_base = MPC10X_MAPB_ISA_IO_BASE;
-	isa_mem_base = MPC10X_MAPB_ISA_MEM_BASE;
-	pci_dram_offset = MPC10X_MAPB_DRAM_OFFSET;
-
-	ppc_md.setup_arch	= menf1_setup_arch;
-	ppc_md.show_cpuinfo	= menf1_show_cpuinfo;
-	ppc_md.init_IRQ		= menf1_init_IRQ;
-	ppc_md.get_irq		= i8259_irq;
-
-	ppc_md.find_end_of_memory = menf1_find_end_of_memory;
-	ppc_md.setup_io_mappings = menf1_map_io;
-
-	ppc_md.restart		= menf1_restart;
-	ppc_md.power_off	= menf1_power_off;
-	ppc_md.halt		= menf1_halt;
-
-	TODC_INIT(TODC_TYPE_MK48T59,
-		  MENF1_NVRAM_AS0,
-		  MENF1_NVRAM_AS1,
-		  MENF1_NVRAM_DATA,
-		  7);
-
-	ppc_md.time_init	= todc_time_init;
-	ppc_md.get_rtc_time	= todc_get_rtc_time;
-	ppc_md.set_rtc_time	= todc_set_rtc_time;
-	ppc_md.calibrate_decr	= todc_calibrate_decr;
-
-	ppc_md.nvram_read_val   = todc_m48txx_read_val;
-	ppc_md.nvram_write_val  = todc_m48txx_write_val;
-
-#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
-	ppc_ide_md.default_io_base = menf1_ide_default_io_base;
-	ppc_ide_md.default_irq = menf1_ide_default_irq;
-	ppc_ide_md.ide_init_hwif = menf1_ide_init_hwif_ports;
-#endif
-}
diff -Nru a/arch/ppc/platforms/sandpoint.c b/arch/ppc/platforms/sandpoint.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/arch/ppc/platforms/sandpoint.c	Tue Jul  1 10:56:46 2003
@@ -0,0 +1,719 @@
+/*
+ * arch/ppc/platforms/sandpoint_setup.c
+ *
+ * Board setup routines for the Motorola SPS Sandpoint Test Platform.
+ *
+ * Author: Mark A. Greer
+ *	 mgreer@mvista.com
+ *
+ * 2000-2003 (c) MontaVista Software, Inc.  This file is licensed under
+ * the terms of the GNU General Public License version 2.  This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+/*
+ * This file adds support for the Motorola SPS Sandpoint Test Platform.
+ * These boards have a PPMC slot for the processor so any combination
+ * of cpu and host bridge can be attached.  This port is for an 8240 PPMC
+ * module from Motorola SPS and other closely related cpu/host bridge
+ * combinations (e.g., 750/755/7400 with MPC107 host bridge).
+ * The sandpoint itself has a Windbond 83c553 (PCI-ISA bridge, 2 DMA ctlrs, 2
+ * cascaded 8259 interrupt ctlrs, 8254 Timer/Counter, and an IDE ctlr), a
+ * National 87308 (RTC, 2 UARTs, Keyboard & mouse ctlrs, and a floppy ctlr),
+ * and 4 PCI slots (only 2 of which are usable; the other 2 are keyed for 3.3V
+ * but are really 5V).
+ *
+ * The firmware on the sandpoint is called DINK (not my acronym :).  This port
+ * depends on DINK to do some basic initialization (e.g., initialize the memory
+ * ctlr) and to ensure that the processor is using MAP B (CHRP map).
+ *
+ * The switch settings for the Sandpoint board MUST be as follows:
+ * 	S3: down
+ * 	S4: up
+ * 	S5: up
+ * 	S6: down
+ *
+ * 'down' is in the direction from the PCI slots towards the PPMC slot;
+ * 'up' is in the direction from the PPMC slot towards the PCI slots.
+ * Be careful, the way the sandpoint board is installed in XT chasses will
+ * make the directions reversed.
+ *
+ * Since Motorola listened to our suggestions for improvement, we now have
+ * the Sandpoint X3 board.  All of the PCI slots are available, it uses
+ * the serial interrupt interface (just a hardware thing we need to
+ * configure properly).
+ *
+ * Use the default X3 switch settings.  The interrupts are then:
+ *		EPIC	Source
+ *		  0	SIOINT 		(8259, active low)
+ *		  1	PCI #1
+ *		  2	PCI #2
+ *		  3	PCI #3
+ *		  4	PCI #4
+ *		  7	Winbond INTC	(IDE interrupt)
+ *		  8	Winbond INTD	(IDE interrupt)
+ *
+ *
+ * Motorola has finally released a version of DINK32 that correctly
+ * (seemingly) initalizes the memory controller correctly, regardless
+ * of the amount of memory in the system.  Once a method of determining
+ * what version of DINK initializes the system for us, if applicable, is
+ * found, we can hopefully stop hardcoding 32MB of RAM.
+ *
+ * It is important to note that this code only supports the Sandpoint X3
+ * (all flavors) platform, and it does not support the X2 anymore.  Code
+ * that at one time worked on the X2 can be found at:
+ * ftp://source.mvista.com/pub/linuxppc/obsolete/sandpoint/
+ */
+
+#include <linux/config.h>
+#include <linux/stddef.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/reboot.h>
+#include <linux/pci.h>
+#include <linux/kdev_t.h>
+#include <linux/major.h>
+#include <linux/initrd.h>
+#include <linux/console.h>
+#include <linux/delay.h>
+#include <linux/irq.h>
+#include <linux/ide.h>
+#include <linux/seq_file.h>
+#include <linux/root_dev.h>
+#include <linux/serial.h>
+#include <linux/tty.h>	/* for linux/serial_core.h */
+#include <linux/serial_core.h>
+
+#include <asm/system.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <asm/time.h>
+#include <asm/dma.h>
+#include <asm/io.h>
+#include <asm/machdep.h>
+#include <asm/prom.h>
+#include <asm/smp.h>
+#include <asm/vga.h>
+#include <asm/open_pic.h>
+#include <asm/i8259.h>
+#include <asm/todc.h>
+#include <asm/bootinfo.h>
+#include <asm/mpc10x.h>
+#include <asm/pci-bridge.h>
+
+#include "sandpoint.h"
+
+extern void gen550_progress(char *, unsigned short);
+extern void gen550_init(int, struct uart_port *);
+
+unsigned char __res[sizeof(bd_t)];
+
+static void sandpoint_halt(void);
+
+/*
+ * Define all of the IRQ senses and polarities.  Taken from the
+ * Sandpoint X3 User's manual.
+ */
+static u_char sandpoint_openpic_initsenses[] __initdata = {
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* 0: SIOINT */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* 2: PCI Slot 1 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* 3: PCI Slot 2 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* 4: PCI Slot 3 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* 5: PCI Slot 4 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* 8: IDE (INT C) */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE)	/* 9: IDE (INT D) */
+};
+
+/*
+ * Motorola SPS Sandpoint interrupt routing.
+ */
+static inline int
+sandpoint_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
+{
+	static char pci_irq_table[][4] =
+	/*
+	 *	PCI IDSEL/INTPIN->INTLINE
+	 * 	   A   B   C   D
+	 */
+	{
+		{ 16,  0,  0,  0 },	/* IDSEL 11 - i8259 on Winbond */
+		{  0,  0,  0,  0 },	/* IDSEL 12 - unused */
+		{ 18, 21, 20, 19 },	/* IDSEL 13 - PCI slot 1 */
+		{ 19, 18, 21, 20 },	/* IDSEL 14 - PCI slot 2 */
+		{ 20, 19, 18, 21 },	/* IDSEL 15 - PCI slot 3 */
+		{ 21, 20, 19, 18 },	/* IDSEL 16 - PCI slot 4 */
+	};
+
+	const long min_idsel = 11, max_idsel = 16, irqs_per_slot = 4;
+	return PCI_IRQ_TABLE_LOOKUP;
+}
+
+static void __init
+sandpoint_setup_winbond_83553(struct pci_controller *hose)
+{
+	int		devfn;
+
+	/*
+	 * Route IDE interrupts directly to the 8259's IRQ 14 & 15.
+	 * We can't route the IDE interrupt to PCI INTC# or INTD# because those
+	 * woule interfere with the PMC's INTC# and INTD# lines.
+	 */
+	/*
+	 * Winbond Fcn 0
+	 */
+	devfn = PCI_DEVFN(11,0);
+
+	early_write_config_byte(hose,
+				0,
+				devfn,
+				0x43, /* IDE Interrupt Routing Control */
+				0xef);
+	early_write_config_word(hose,
+				0,
+				devfn,
+				0x44, /* PCI Interrupt Routing Control */
+				0x0000);
+
+	/* Want ISA memory cycles to be forwarded to PCI bus */
+	early_write_config_byte(hose,
+				0,
+				devfn,
+				0x48, /* ISA-to-PCI Addr Decoder Control */
+				0xf0);
+
+	/* Enable RTC and Keyboard address locations.  */
+	early_write_config_byte(hose,
+				0,
+				devfn,
+				0x4d,	/* Chip Select Control Register */
+				0x00);
+
+	/* Enable Port 92.  */
+	early_write_config_byte(hose,
+				0,
+				devfn,
+				0x4e,	/* AT System Control Register */
+				0x06);
+	/*
+	 * Winbond Fcn 1
+	 */
+	devfn = PCI_DEVFN(11,1);
+
+	/* Put IDE controller into native mode. */
+	early_write_config_byte(hose,
+				0,
+				devfn,
+				0x09,	/* Programming interface Register */
+				0x8f);
+
+	/* Init IRQ routing, enable both ports, disable fast 16 */
+	early_write_config_dword(hose,
+				0,
+				devfn,
+				0x40,	/* IDE Control/Status Register */
+				0x00ff0011);
+	return;
+}
+
+static void __init
+sandpoint_find_bridges(void)
+{
+	struct pci_controller	*hose;
+
+	hose = pcibios_alloc_controller();
+
+	if (!hose)
+		return;
+
+	hose->first_busno = 0;
+	hose->last_busno = 0xff;
+
+	if (mpc10x_bridge_init(hose,
+			       MPC10X_MEM_MAP_B,
+			       MPC10X_MEM_MAP_B,
+			       MPC10X_MAPB_EUMB_BASE) == 0) {
+
+		/* Do early winbond init, then scan PCI bus */
+		sandpoint_setup_winbond_83553(hose);
+		hose->last_busno = pciauto_bus_scan(hose, hose->first_busno);
+
+		ppc_md.pcibios_fixup = NULL;
+		ppc_md.pcibios_fixup_bus = NULL;
+		ppc_md.pci_swizzle = common_swizzle;
+		ppc_md.pci_map_irq = sandpoint_map_irq;
+	}
+	else {
+		if (ppc_md.progress)
+			ppc_md.progress("Bridge init failed", 0x100);
+		printk("Host bridge init failed\n");
+	}
+
+	return;
+}
+
+#if defined(CONFIG_SERIAL_8250) && \
+	(defined(CONFIG_KGDB) || defined(CONFIG_SERIAL_TEXT_DEBUG))
+static void __init
+sandpoint_early_serial_map(void)
+{
+	struct uart_port serial_req;
+
+	/* Setup serial port access */
+	memset(&serial_req, 0, sizeof(serial_req));
+	serial_req.uartclk = UART_CLK;
+	serial_req.irq = 4;
+	serial_req.flags = STD_COM_FLAGS;
+	serial_req.iotype = SERIAL_IO_MEM;
+	serial_req.membase = (u_char *)SANDPOINT_SERIAL_0;
+
+	gen550_init(0, &serial_req);
+
+	if (early_serial_setup(&serial_req) != 0)
+		printk(KERN_ERR "Early serial init of port 0 failed\n");
+
+	/* Assume early_serial_setup() doesn't modify serial_req */
+	serial_req.line = 1;
+	serial_req.irq = 3; /* XXXX */
+	serial_req.membase = (u_char *)SANDPOINT_SERIAL_1;
+
+	gen550_init(1, &serial_req);
+
+	if (early_serial_setup(&serial_req) != 0)
+		printk(KERN_ERR "Early serial init of port 1 failed\n");
+}
+#endif
+
+static void __init
+sandpoint_setup_arch(void)
+{
+	loops_per_jiffy = 100000000 / HZ;
+
+#ifdef CONFIG_BLK_DEV_INITRD
+	if (initrd_start)
+		ROOT_DEV = Root_RAM0;
+	else
+#endif
+#ifdef	CONFIG_ROOT_NFS
+		ROOT_DEV = Root_NFS;
+#else
+		ROOT_DEV = Root_HDA1;
+#endif
+
+	/* Lookup PCI host bridges */
+	sandpoint_find_bridges();
+
+#ifdef CONFIG_DUMMY_CONSOLE
+	conswitchp = &dummy_con;
+#endif
+
+	printk(KERN_INFO "Motorola SPS Sandpoint Test Platform\n");
+	printk(KERN_INFO "Port by MontaVista Software, Inc. (source@mvista.com)\n");
+
+	/* DINK32 12.3 and below do not correctly enable any caches.
+	 * We will do this now with good known values.  Future versions
+	 * of DINK32 are supposed to get this correct.
+	 */
+	if (cur_cpu_spec[0]->cpu_features & CPU_FTR_SPEC7450)
+		/* 745x is different.  We only want to pass along enable. */
+		_set_L2CR(L2CR_L2E);
+	else if (cur_cpu_spec[0]->cpu_features & CPU_FTR_L2CR)
+		/* All modules have 1MB of L2.  We also assume that an
+		 * L2 divisor of 3 will work.
+		 */
+		_set_L2CR(L2CR_L2E | L2CR_L2SIZ_1MB | L2CR_L2CLK_DIV3
+				| L2CR_L2RAM_PIPE | L2CR_L2OH_1_0 | L2CR_L2DF);
+#if 0
+	/* Untested right now. */
+	if (cur_cpu_spec[0]->cpu_features & CPU_FTR_L3CR) {
+		/* Magic value. */
+		_set_L3CR(0x8f032000);
+	}
+#endif
+}
+
+#define	SANDPOINT_87308_CFG_ADDR		0x15c
+#define	SANDPOINT_87308_CFG_DATA		0x15d
+
+#define	SANDPOINT_87308_CFG_INB(addr, byte) {				\
+	outb((addr), SANDPOINT_87308_CFG_ADDR);				\
+	(byte) = inb(SANDPOINT_87308_CFG_DATA);				\
+}
+
+#define	SANDPOINT_87308_CFG_OUTB(addr, byte) {				\
+	outb((addr), SANDPOINT_87308_CFG_ADDR);				\
+	outb((byte), SANDPOINT_87308_CFG_DATA);				\
+}
+
+#define SANDPOINT_87308_SELECT_DEV(dev_num) {				\
+	SANDPOINT_87308_CFG_OUTB(0x07, (dev_num));			\
+}
+
+#define	SANDPOINT_87308_DEV_ENABLE(dev_num) {				\
+	SANDPOINT_87308_SELECT_DEV(dev_num);				\
+	SANDPOINT_87308_CFG_OUTB(0x30, 0x01);				\
+}
+
+/*
+ * Initialize the ISA devices on the Nat'l PC87308VUL SuperIO chip.
+ */
+static int __init
+sandpoint_setup_natl_87308(void)
+{
+	u_char	reg;
+
+	/*
+	 * Enable all the devices on the Super I/O chip.
+	 */
+	SANDPOINT_87308_SELECT_DEV(0x00); /* Select kbd logical device */
+	SANDPOINT_87308_CFG_OUTB(0xf0, 0x00); /* Set KBC clock to 8 Mhz */
+	SANDPOINT_87308_DEV_ENABLE(0x00); /* Enable keyboard */
+	SANDPOINT_87308_DEV_ENABLE(0x01); /* Enable mouse */
+	SANDPOINT_87308_DEV_ENABLE(0x02); /* Enable rtc */
+	SANDPOINT_87308_DEV_ENABLE(0x03); /* Enable fdc (floppy) */
+	SANDPOINT_87308_DEV_ENABLE(0x04); /* Enable parallel */
+	SANDPOINT_87308_DEV_ENABLE(0x05); /* Enable UART 2 */
+	SANDPOINT_87308_CFG_OUTB(0xf0, 0x82); /* Enable bank select regs */
+	SANDPOINT_87308_DEV_ENABLE(0x06); /* Enable UART 1 */
+	SANDPOINT_87308_CFG_OUTB(0xf0, 0x82); /* Enable bank select regs */
+
+	/* Set up floppy in PS/2 mode */
+	outb(0x09, SIO_CONFIG_RA);
+	reg = inb(SIO_CONFIG_RD);
+	reg = (reg & 0x3F) | 0x40;
+	outb(reg, SIO_CONFIG_RD);
+	outb(reg, SIO_CONFIG_RD);	/* Have to write twice to change! */
+
+	return 0;
+}
+
+arch_initcall(sandpoint_setup_natl_87308);
+
+/*
+ * Fix IDE interrupts.
+ */
+static int __init
+sandpoint_fix_winbond_83553(void)
+{
+	/* Make all 8259 interrupt level sensitive */
+	outb(0xf8, 0x4d0);
+	outb(0xde, 0x4d1);
+
+	return 0;
+}
+
+arch_initcall(sandpoint_fix_winbond_83553);
+
+static int __init
+sandpoint_request_io(void)
+{
+	request_region(0x00,0x20,"dma1");
+	request_region(0x20,0x20,"pic1");
+	request_region(0x40,0x20,"timer");
+	request_region(0x80,0x10,"dma page reg");
+	request_region(0xa0,0x20,"pic2");
+	request_region(0xc0,0x20,"dma2");
+
+	return 0;
+}
+
+arch_initcall(sandpoint_request_io);
+
+/*
+ * Interrupt setup and service.  Interrrupts on the Sandpoint come
+ * from the four PCI slots plus the 8259 in the Winbond Super I/O (SIO).
+ * The 8259 is cascaded from EPIC IRQ0, IRQ1-4 map to PCI slots 1-4,
+ * IDE is on EPIC 7 and 8.
+ */
+static void __init
+sandpoint_init_IRQ(void)
+{
+	int i;
+
+	OpenPIC_InitSenses = sandpoint_openpic_initsenses;
+	OpenPIC_NumInitSenses = sizeof(sandpoint_openpic_initsenses);
+
+	/*
+	 * We need to tell openpic_set_sources where things actually are.
+	 * mpc10x_common will setup OpenPIC_Addr at ioremap(EUMB phys base +
+	 * EPIC offset (0x40000));  The EPIC IRQ Register Address Map -
+	 * Interrupt Source Configuration Registers gives these numbers
+	 * as offsets starting at 0x50200, we need to adjust occordinly.
+	 */
+	/* Map serial interrupts 0-15 */
+	openpic_set_sources(0, 16, OpenPIC_Addr + 0x10200);
+
+	openpic_init(NUM_8259_INTERRUPTS);
+
+	/*
+	 * openpic_init() has set up irq_desc[16-31] to be openpic
+	 * interrupts.  We need to set irq_desc[0-15] to be i8259
+	 * interrupts.
+	 */
+	for(i=0; i < NUM_8259_INTERRUPTS; i++)
+		irq_desc[i].handler = &i8259_pic;
+
+	/*
+	 * The EPIC allows for a read in the range of 0xFEF00000 ->
+	 * 0xFEFFFFFF to generate a PCI interrupt-acknowledge transaction.
+	 */
+	i8259_init(0xfef00000);
+}
+
+static u32
+sandpoint_irq_canonicalize(u32 irq)
+{
+	if (irq == 2)
+		return 9;
+	else
+		return irq;
+}
+
+static unsigned long __init
+sandpoint_find_end_of_memory(void)
+{
+	bd_t *bp = (bd_t *)__res;
+
+	if (bp->bi_memsize)
+		return bp->bi_memsize;
+
+	/* DINK32 13.0 correctly initalizes things, so iff you use
+	 * this you _should_ be able to change this instead of a
+	 * hardcoded value. */
+#if 0
+	return mpc10x_get_mem_size(MPC10X_MEM_MAP_B);
+#else
+	return 32*1024*1024;
+#endif
+}
+
+static void __init
+sandpoint_map_io(void)
+{
+	io_block_mapping(0xfe000000, 0xfe000000, 0x02000000, _PAGE_IO);
+}
+
+static void
+sandpoint_restart(char *cmd)
+{
+	local_irq_disable();
+
+	/* Set exception prefix high - to the firmware */
+	_nmask_and_or_msr(0, MSR_IP);
+
+	/* Reset system via Port 92 */
+	outb(0x00, 0x92);
+	outb(0x01, 0x92);
+	for(;;);	/* Spin until reset happens */
+}
+
+static void
+sandpoint_power_off(void)
+{
+	local_irq_disable();
+	for(;;);	/* No way to shut power off with software */
+	/* NOTREACHED */
+}
+
+static void
+sandpoint_halt(void)
+{
+	sandpoint_power_off();
+	/* NOTREACHED */
+}
+
+static int
+sandpoint_show_cpuinfo(struct seq_file *m)
+{
+	seq_printf(m, "vendor\t\t: Motorola SPS\n");
+	seq_printf(m, "machine\t\t: Sandpoint\n");
+
+	return 0;
+}
+
+#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
+/*
+ * IDE support.
+ */
+static int		sandpoint_ide_ports_known = 0;
+static unsigned long	sandpoint_ide_regbase[MAX_HWIFS];
+static unsigned long	sandpoint_ide_ctl_regbase[MAX_HWIFS];
+static unsigned long	sandpoint_idedma_regbase;
+
+static void
+sandpoint_ide_probe(void)
+{
+	struct pci_dev *pdev = pci_find_device(PCI_VENDOR_ID_WINBOND,
+			PCI_DEVICE_ID_WINBOND_82C105, NULL);
+
+	if (pdev) {
+		sandpoint_ide_regbase[0]=pdev->resource[0].start;
+		sandpoint_ide_regbase[1]=pdev->resource[2].start;
+		sandpoint_ide_ctl_regbase[0]=pdev->resource[1].start;
+		sandpoint_ide_ctl_regbase[1]=pdev->resource[3].start;
+		sandpoint_idedma_regbase=pdev->resource[4].start;
+	}
+
+	sandpoint_ide_ports_known = 1;
+}
+
+static int
+sandpoint_ide_default_irq(unsigned long base)
+{
+	if (sandpoint_ide_ports_known == 0)
+		sandpoint_ide_probe();
+
+	if (base == sandpoint_ide_regbase[0])
+		return SANDPOINT_IDE_INT0;
+	else if (base == sandpoint_ide_regbase[1])
+		return SANDPOINT_IDE_INT1;
+	else
+		return 0;
+}
+
+static unsigned long
+sandpoint_ide_default_io_base(int index)
+{
+	if (sandpoint_ide_ports_known == 0)
+		sandpoint_ide_probe();
+
+	return sandpoint_ide_regbase[index];
+}
+
+static void __init
+sandpoint_ide_init_hwif_ports(hw_regs_t *hw, unsigned long data_port,
+		unsigned long ctrl_port, int *irq)
+{
+	unsigned long reg = data_port;
+	uint	alt_status_base;
+	int	i;
+
+	for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) {
+		hw->io_ports[i] = reg++;
+	}
+
+	if (data_port == sandpoint_ide_regbase[0]) {
+		alt_status_base = sandpoint_ide_ctl_regbase[0] + 2;
+		hw->irq = 14;
+	}
+	else if (data_port == sandpoint_ide_regbase[1]) {
+		alt_status_base = sandpoint_ide_ctl_regbase[1] + 2;
+		hw->irq = 15;
+	}
+	else {
+		alt_status_base = 0;
+		hw->irq = 0;
+	}
+
+	if (ctrl_port) {
+		hw->io_ports[IDE_CONTROL_OFFSET] = ctrl_port;
+	} else {
+		hw->io_ports[IDE_CONTROL_OFFSET] = alt_status_base;
+	}
+
+	if (irq != NULL) {
+		*irq = hw->irq;
+	}
+}
+#endif
+
+/*
+ * Set BAT 3 to map 0xf8000000 to end of physical memory space 1-to-1.
+ */
+static __inline__ void
+sandpoint_set_bat(void)
+{
+	unsigned long bat3u, bat3l;
+
+	__asm__ __volatile__(
+			" lis %0,0xf800\n	\
+			ori %1,%0,0x002a\n	\
+			ori %0,%0,0x0ffe\n	\
+			mtspr 0x21e,%0\n	\
+			mtspr 0x21f,%1\n	\
+			isync\n			\
+			sync "
+			: "=r" (bat3u), "=r" (bat3l));
+}
+
+TODC_ALLOC();
+
+void __init
+platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
+		unsigned long r6, unsigned long r7)
+{
+	parse_bootinfo(find_bootinfo());
+
+	/* ASSUMPTION:  If both r3 (bd_t pointer) and r6 (cmdline pointer)
+	 * are non-zero, then we should use the board info from the bd_t
+	 * structure and the cmdline pointed to by r6 instead of the
+	 * information from birecs, if any.  Otherwise, use the information
+	 * from birecs as discovered by the preceeding call to
+	 * parse_bootinfo().  This rule should work with both PPCBoot, which
+	 * uses a bd_t board info structure, and the kernel boot wrapper,
+	 * which uses birecs.
+	 */
+	if (r3 && r6) {
+		/* copy board info structure */
+		memcpy( (void *)__res,(void *)(r3+KERNELBASE), sizeof(bd_t) );
+		/* copy command line */
+		*(char *)(r7+KERNELBASE) = 0;
+		strcpy(cmd_line, (char *)(r6+KERNELBASE));
+	}
+
+#ifdef CONFIG_BLK_DEV_INITRD
+	/* take care of initrd if we have one */
+	if (r4) {
+		initrd_start = r4 + KERNELBASE;
+		initrd_end = r5 + KERNELBASE;
+	}
+#endif /* CONFIG_BLK_DEV_INITRD */
+
+	/* Map in board regs, etc. */
+	sandpoint_set_bat();
+
+	isa_io_base = MPC10X_MAPB_ISA_IO_BASE;
+	isa_mem_base = MPC10X_MAPB_ISA_MEM_BASE;
+	pci_dram_offset = MPC10X_MAPB_DRAM_OFFSET;
+	ISA_DMA_THRESHOLD = 0x00ffffff;
+	DMA_MODE_READ = 0x44;
+	DMA_MODE_WRITE = 0x48;
+
+	ppc_md.setup_arch = sandpoint_setup_arch;
+	ppc_md.show_cpuinfo = sandpoint_show_cpuinfo;
+	ppc_md.irq_canonicalize = sandpoint_irq_canonicalize;
+	ppc_md.init_IRQ = sandpoint_init_IRQ;
+	ppc_md.get_irq = openpic_get_irq;
+
+	ppc_md.restart = sandpoint_restart;
+	ppc_md.power_off = sandpoint_power_off;
+	ppc_md.halt = sandpoint_halt;
+
+	ppc_md.find_end_of_memory = sandpoint_find_end_of_memory;
+	ppc_md.setup_io_mappings = sandpoint_map_io;
+
+	TODC_INIT(TODC_TYPE_PC97307, 0x70, 0x00, 0x71, 8);
+	ppc_md.time_init = todc_time_init;
+	ppc_md.set_rtc_time = todc_set_rtc_time;
+	ppc_md.get_rtc_time = todc_get_rtc_time;
+	ppc_md.calibrate_decr = todc_calibrate_decr;
+
+	ppc_md.nvram_read_val = todc_mc146818_read_val;
+	ppc_md.nvram_write_val = todc_mc146818_write_val;
+
+#if defined(CONFIG_SERIAL_8250) && \
+	(defined(CONFIG_KGDB) || defined(CONFIG_SERIAL_TEXT_DEBUG))
+	sandpoint_early_serial_map();
+#ifdef CONFIG_SERIAL_TEXT_DEBUG
+	ppc_md.progress = gen550_progress;
+#endif
+#endif
+
+#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
+	ppc_ide_md.default_irq = sandpoint_ide_default_irq;
+	ppc_ide_md.default_io_base = sandpoint_ide_default_io_base;
+	ppc_ide_md.ide_init_hwif = sandpoint_ide_init_hwif_ports;
+#endif
+}
diff -Nru a/arch/ppc/platforms/sandpoint.h b/arch/ppc/platforms/sandpoint.h
--- a/arch/ppc/platforms/sandpoint.h	Tue Feb 11 15:48:53 2003
+++ b/arch/ppc/platforms/sandpoint.h	Tue Jul  1 10:56:46 2003
@@ -6,7 +6,7 @@
  * Author: Mark A. Greer
  *         mgreer@mvista.com
  *
- * 2000-2001 (c) MontaVista, Software, Inc.  This file is licensed under
+ * 2000-2003 (c) MontaVista, Software, Inc.  This file is licensed under
  * the terms of the GNU General Public License version 2.  This program
  * is licensed "as is" without any warranty of any kind, whether express
  * or implied.
@@ -19,8 +19,8 @@
 #ifndef __PPC_PLATFORMS_SANDPOINT_H
 #define __PPC_PLATFORMS_SANDPOINT_H
 
-#ifdef CONFIG_SANDPOINT_X3
-#define SANDPOINT_SIO_SLOT      0	/* Cascaded from EPIC IRQ 0 */
+#include <asm/ppcboot.h>
+
 #if 0
 /* The Sandpoint X3 allows the IDE interrupt to be directly connected
  * from the Windbond (PCI INTC or INTD) to the serial EPIC.  Someday
@@ -28,27 +28,13 @@
  * initialization than change it to route the different interrupts :-).
  *	-- Dan
  */
-#define SANDPOINT_IDE_INT0	23	/* EPIC 7 */
-#define SANDPOINT_IDE_INT1	24	/* EPIC 8 */
-#else
-#define SANDPOINT_IDE_INT0	14	/* 8259 Test */
-#define SANDPOINT_IDE_INT1	15	/* 8259 Test */
-#endif
+#define SANDPOINT_IDE_INT0		23	/* EPIC 7 */
+#define SANDPOINT_IDE_INT1		24	/* EPIC 8 */
 #else
- /*
-  * Define the PCI slot that the 8259 is sharing interrupts with.
-  * Valid values are 1 (PCI slot 2) and 2 (PCI slot 3).
-  */
-#define SANDPOINT_SIO_SLOT      1
-
-/* ...and for the IDE from the 8259....
-*/
-#define SANDPOINT_IDE_INT0	14
-#define SANDPOINT_IDE_INT1	15
+#define SANDPOINT_IDE_INT0		14	/* 8259 Test */
+#define SANDPOINT_IDE_INT1		15	/* 8259 Test */
 #endif
 
-#define	SANDPOINT_SIO_IRQ	(SANDPOINT_SIO_SLOT + NUM_8259_INTERRUPTS)
-
 /*
  * The sandpoint boards have processor modules that either have an 8240 or
  * an MPC107 host bridge on them.  These bridges have an IDSEL line that allows
@@ -62,7 +48,33 @@
  */
 #define SANDPOINT_HOST_BRIDGE_IDSEL     12
 
+/*
+ * Serial defines.
+ */
+#define SANDPOINT_SERIAL_0		0xfe0003f8
+#define SANDPOINT_SERIAL_1		0xfe0002f8
+
+#define RS_TABLE_SIZE  2
+
+/* Rate for the 1.8432 Mhz clock for the onboard serial chip */
+#define BASE_BAUD			( 1843200 / 16 )
+#define UART_CLK			1843200
+
+#ifdef CONFIG_SERIAL_DETECT_IRQ
+#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF|ASYNC_SKIP_TEST|ASYNC_AUTO_IRQ)
+#else
+#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF|ASYNC_SKIP_TEST)
+#endif
+
+#define STD_SERIAL_PORT_DFNS \
+        { 0, BASE_BAUD, SANDPOINT_SERIAL_0, 4, STD_COM_FLAGS, /* ttyS0 */ \
+		iomem_base: (u8 *)SANDPOINT_SERIAL_0,			  \
+		io_type: SERIAL_IO_MEM },				  \
+        { 0, BASE_BAUD, SANDPOINT_SERIAL_1, 3, STD_COM_FLAGS, /* ttyS1 */ \
+		iomem_base: (u8 *)SANDPOINT_SERIAL_1,			  \
+		io_type: SERIAL_IO_MEM },
 
-void sandpoint_find_bridges(void);
+#define SERIAL_PORT_DFNS \
+        STD_SERIAL_PORT_DFNS
 
 #endif /* __PPC_PLATFORMS_SANDPOINT_H */
diff -Nru a/arch/ppc/platforms/sandpoint_pci.c b/arch/ppc/platforms/sandpoint_pci.c
--- a/arch/ppc/platforms/sandpoint_pci.c	Tue Feb 11 15:48:53 2003
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,181 +0,0 @@
-/*
- * arch/ppc/platforms/sandpoint_pci.c
- * 
- * PCI setup routines for the Motorola SPS Sandpoint Test Platform
- *
- * Author: Mark A. Greer
- *         mgreer@mvista.com
- *
- * 2000-2001 (c) MontaVista, Software, Inc.  This file is licensed under
- * the terms of the GNU General Public License version 2.  This program
- * is licensed "as is" without any warranty of any kind, whether express
- * or implied.
- */
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-#include <linux/slab.h>
-
-#include <asm/byteorder.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/uaccess.h>
-#include <asm/machdep.h>
-#include <asm/pci-bridge.h>
-#include <asm/mpc10x.h>
-
-#include "sandpoint.h"
-
-/*
- * Motorola SPS Sandpoint interrupt routing.
- */
-static inline int
-sandpoint_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
-{
-	static char pci_irq_table[][4] =
-	/*
-	 *	PCI IDSEL/INTPIN->INTLINE 
-	 * 	   A   B   C   D
-	 */
-	{
-		{ SANDPOINT_SIO_IRQ,
-		       0,  0,  0 },	/* IDSEL 11 - i8259 on Winbond */
-		{  0,  0,  0,  0 },	/* IDSEL 12 - unused */
-#ifdef CONFIG_SANDPOINT_X3
-#if 0	/* This is what it _should_ look like -- Dan */
-		{ 17, 20, 19, 18 },	/* IDSEL 13 - PCI slot 1 */
-		{ 18, 17, 20, 19 },	/* IDSEL 14 - PCI slot 2 */
-		{ 19, 18, 17, 20 },	/* IDSEL 15 - PCI slot 3 */
-		{ 20, 19, 18, 17 },	/* IDSEL 16 - PCI slot 4 */
-#else
-		{ 18, 21, 20, 19 },	/* IDSEL 13 - PCI slot 1 */
-		{ 19, 18, 21, 20 },	/* IDSEL 14 - PCI slot 2 */
-		{ 20, 19, 18, 21 },	/* IDSEL 15 - PCI slot 3 */
-		{ 21, 20, 19, 18 },	/* IDSEL 16 - PCI slot 4 */
-#endif
-#else
-		{ 16, 19, 18, 17 },	/* IDSEL 13 - PCI slot 1 */
-		{ 17, 16, 19, 18 },	/* IDSEL 14 - PCI slot 2 */
-		{ 18, 17, 16, 19 },	/* IDSEL 15 - PCI slot 3 */
-		{ 19, 18, 17, 16 },	/* IDSEL 16 - PCI slot 4 */
-#endif
-	};
-
-	const long min_idsel = 11, max_idsel = 16, irqs_per_slot = 4;
-	return PCI_IRQ_TABLE_LOOKUP;
-}
-
-static void __init
-sandpoint_setup_winbond_83553(struct pci_controller *hose)
-{
-	int		devfn;
-
-	/*
-	 * Route IDE interrupts directly to the 8259's IRQ 14 & 15.
-	 * We can't route the IDE interrupt to PCI INTC# or INTD# because those
-	 * woule interfere with the PMC's INTC# and INTD# lines.
-	 */
-	/*
-	 * Winbond Fcn 0
-	 */
-	devfn = PCI_DEVFN(11,0);
-
-	early_write_config_byte(hose,
-				0,
-				devfn,
-				0x43, /* IDE Interrupt Routing Control */
-				0xef);
-	early_write_config_word(hose,
-				0,
-				devfn,
-				0x44, /* PCI Interrupt Routing Control */
-				0x0000);
-
-	/* Want ISA memory cycles to be forwarded to PCI bus */
-	early_write_config_byte(hose,
-				0,
-				devfn,
-				0x48, /* ISA-to-PCI Addr Decoder Control */
-				0xf0);
-
-	/* Enable RTC and Keyboard address locations.  */
-	early_write_config_byte(hose,
-				0,
-				devfn,
-				0x4d,	/* Chip Select Control Register */
-				0x00);
-
-	/* Enable Port 92.  */
-	early_write_config_byte(hose,
-				0,
-				devfn,
-				0x4e,	/* AT System Control Register */
-				0x06);
-	/*
-	 * Winbond Fcn 1
-	 */
-	devfn = PCI_DEVFN(11,1);
-
-	/* Put IDE controller into native mode. */
-	early_write_config_byte(hose,
-				0,
-				devfn,
-				0x09,	/* Programming interface Register */
-				0x8f);
-
-	/* Init IRQ routing, enable both ports, disable fast 16 */
-	early_write_config_dword(hose,
-				0,
-				devfn,
-				0x40,	/* IDE Control/Status Register */
-				0x00ff0011);
-	return;
-}
-
-static int                     
-sandpoint_exclude_device(u_char bus, u_char devfn)
-{
-	if ((bus == 0) && (PCI_SLOT(devfn) == SANDPOINT_HOST_BRIDGE_IDSEL)) {
-		return PCIBIOS_DEVICE_NOT_FOUND;
-	}
-	else {
-		return PCIBIOS_SUCCESSFUL;
-	}
-}
-
-void __init
-sandpoint_find_bridges(void)
-{
-	struct pci_controller	*hose;
-
-	hose = pcibios_alloc_controller();
-
-	if (!hose)
-		return;
-
-	hose->first_busno = 0;
-	hose->last_busno = 0xff;
-
-	if (mpc10x_bridge_init(hose,
-			       MPC10X_MEM_MAP_B,
-			       MPC10X_MEM_MAP_B,
-			       MPC10X_MAPB_EUMB_BASE) == 0) {
-
-		/* Do early winbond init, then scan PCI bus */
-		sandpoint_setup_winbond_83553(hose);
-		ppc_md.pci_exclude_device = sandpoint_exclude_device;
-		hose->last_busno = pciauto_bus_scan(hose, hose->first_busno);
-
-		ppc_md.pcibios_fixup = NULL;
-		ppc_md.pcibios_fixup_bus = NULL;
-		ppc_md.pci_swizzle = common_swizzle;
-		ppc_md.pci_map_irq = sandpoint_map_irq;
-	}
-	else {
-		if (ppc_md.progress)
-			ppc_md.progress("Bridge init failed", 0x100);
-		printk("Host bridge init failed\n");
-	}
-
-	return;
-}
diff -Nru a/arch/ppc/platforms/sandpoint_serial.h b/arch/ppc/platforms/sandpoint_serial.h
--- a/arch/ppc/platforms/sandpoint_serial.h	Tue Feb 11 15:48:53 2003
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,49 +0,0 @@
-/*
- * include/asm-ppc/sandpoint_serial.h
- * 
- * Definitions for Motorola SPS Sandpoint Test Platform
- *
- * Author: Mark A. Greer
- *         mgreer@mvista.com
- *
- * 2001 (c) MontaVista, Software, Inc.  This file is licensed under
- * the terms of the GNU General Public License version 2.  This program
- * is licensed "as is" without any warranty of any kind, whether express
- * or implied.
- */
-
-#ifndef __ASMPPC_SANDPOINT_SERIAL_H
-#define __ASMPPC_SANDPOINT_SERIAL_H
-
-#include <linux/config.h>
-
-#define SANDPOINT_SERIAL_0		0xfe0003f8
-#define SANDPOINT_SERIAL_1		0xfe0002f8
-
-#ifdef CONFIG_SERIAL_MANY_PORTS
-#define RS_TABLE_SIZE  64
-#else
-#define RS_TABLE_SIZE  2
-#endif
-
-/* Rate for the 1.8432 Mhz clock for the onboard serial chip */
-#define BASE_BAUD ( 1843200 / 16 )
-
-#ifdef CONFIG_SERIAL_DETECT_IRQ
-#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF|ASYNC_SKIP_TEST|ASYNC_AUTO_IRQ)
-#else
-#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF|ASYNC_SKIP_TEST)
-#endif
-
-#define STD_SERIAL_PORT_DFNS \
-        { 0, BASE_BAUD, SANDPOINT_SERIAL_0, 4, STD_COM_FLAGS, /* ttyS0 */ \
-		iomem_base: (u8 *)SANDPOINT_SERIAL_0,			  \
-		io_type: SERIAL_IO_MEM },				  \
-        { 0, BASE_BAUD, SANDPOINT_SERIAL_1, 3, STD_COM_FLAGS, /* ttyS1 */ \
-		iomem_base: (u8 *)SANDPOINT_SERIAL_1,			  \
-		io_type: SERIAL_IO_MEM },
-
-#define SERIAL_PORT_DFNS \
-        STD_SERIAL_PORT_DFNS
-
-#endif /* __ASMPPC_SANDPOINT_SERIAL_H */
diff -Nru a/arch/ppc/platforms/sandpoint_setup.c b/arch/ppc/platforms/sandpoint_setup.c
--- a/arch/ppc/platforms/sandpoint_setup.c	Wed Apr 23 00:49:34 2003
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,643 +0,0 @@
-/*
- * arch/ppc/platforms/sandpoint_setup.c
- * 
- * Board setup routines for the Motorola SPS Sandpoint Test Platform.
- *
- * Author: Mark A. Greer
- *         mgreer@mvista.com
- *
- * 2000-2002 (c) MontaVista, Software, Inc.  This file is licensed under
- * the terms of the GNU General Public License version 2.  This program
- * is licensed "as is" without any warranty of any kind, whether express
- * or implied.
- */
-
-/*
- * This file adds support for the Motorola SPS Sandpoint Test Platform.
- * These boards have a PPMC slot for the processor so any combination
- * of cpu and host bridge can be attached.  This port is for an 8240 PPMC
- * module from Motorola SPS and other closely related cpu/host bridge
- * combinations (e.g., 750/755/7400 with MPC107 host bridge).
- * The sandpoint itself has a Windbond 83c553 (PCI-ISA bridge, 2 DMA ctlrs, 2
- * cascaded 8259 interrupt ctlrs, 8254 Timer/Counter, and an IDE ctlr), a
- * National 87308 (RTC, 2 UARTs, Keyboard & mouse ctlrs, and a floppy ctlr),
- * and 4 PCI slots (only 2 of which are usable; the other 2 are keyed for 3.3V
- * but are really 5V).
- *
- * The firmware on the sandpoint is called DINK (not my acronym :).  This port
- * depends on DINK to do some basic initialization (e.g., initialize the memory
- * ctlr) and to ensure that the processor is using MAP B (CHRP map).
- *
- * The switch settings for the Sandpoint board MUST be as follows:
- * 	S3: down
- * 	S4: up
- * 	S5: up
- * 	S6: down
- *
- * 'down' is in the direction from the PCI slots towards the PPMC slot;
- * 'up' is in the direction from the PPMC slot towards the PCI slots.
- * Be careful, the way the sandpoint board is installed in XT chasses will
- * make the directions reversed.
- *
- * Since Motorola listened to our suggestions for improvement, we now have
- * the Sandpoint X3 board.  All of the PCI slots are available, it uses
- * the serial interrupt interface (just a hardware thing we need to
- * configure properly).
- *
- * Use the default X3 switch settings.  The interrupts are then:
- *		EPIC	Source
- *		  0	SIOINT 		(8259, active low)
- *		  1	PCI #1
- *		  2	PCI #2
- *		  3	PCI #3
- *		  4	PCI #4
- *		  7	Winbond INTC	(IDE interrupt)
- *		  8	Winbond INTD	(IDE interrupt)
- *
- */
-#include <linux/config.h>
-#include <linux/stddef.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/errno.h>
-#include <linux/reboot.h>
-#include <linux/pci.h>
-#include <linux/kdev_t.h>
-#include <linux/major.h>
-#include <linux/initrd.h>
-#include <linux/console.h>
-#include <linux/delay.h>
-#include <linux/irq.h>
-#include <linux/ide.h>
-#include <linux/seq_file.h>
-#include <linux/root_dev.h>
-
-#include <asm/system.h>
-#include <asm/pgtable.h>
-#include <asm/page.h>
-#include <asm/time.h>
-#include <asm/dma.h>
-#include <asm/io.h>
-#include <asm/machdep.h>
-#include <asm/prom.h>
-#include <asm/smp.h>
-#include <asm/vga.h>
-#include <asm/open_pic.h>
-#include <asm/i8259.h>
-#include <asm/todc.h>
-#include <asm/bootinfo.h>
-#include <asm/mpc10x.h>
-#include <asm/pci-bridge.h>
-
-#include "sandpoint.h"
-
-extern u_int openpic_irq(void);
-extern void openpic_eoi(void);
-
-static void	sandpoint_halt(void);
-
-
-/*
- * *** IMPORTANT ***
- *
- * The first 16 entries of 'sandpoint_openpic_initsenses[]' are there and
- * initialized to 0 on purpose.  DO NOT REMOVE THEM as the 'offset' parameter
- * of 'openpic_init()' does not work for the sandpoint because the 8259
- * interrupt is NOT routed to the EPIC's IRQ 0 AND the EPIC's IRQ 0's offset is
- * the same as a normal openpic's IRQ 16 offset.
- */
-static u_char sandpoint_openpic_initsenses[] __initdata = {
-	0,	/* 0-15 not used by EPCI but by 8259 (std PC-type IRQs) */
-	0,	/* 1 */
-	0,	/* 2 */
-	0,	/* 3 */
-	0,	/* 4 */
-	0,	/* 5 */
-	0,	/* 6 */
-	0,	/* 7 */
-	0,	/* 8 */
-	0,	/* 9 */
-	0,	/* 10 */
-	0,	/* 11 */
-	0,	/* 12 */
-	0,	/* 13 */
-	0,	/* 14 */
-	0,	/* 15 */
-#ifdef CONFIG_SANDPOINT_X3
-	1,	/* 16: EPIC IRQ 0: Active Low -- SIOINT (8259) */
- 0, /* AACK!  Shouldn't need this.....see sandpoint_pci.c for more info */
-	1,	/* 17: EPIC IRQ 1: Active Low -- PCI Slot 1 */
-	1,	/* 18: EPIC IRQ 2: Active Low -- PCI Slot 2 */
-	1,	/* 19: EPIC IRQ 3: Active Low -- PCI Slot 3 */
-	1,	/* 20: EPIC IRQ 4: Active Low -- PCI Slot 4 */
-	0,	/* 21 -- Unused */
-	0,	/* 22 -- Unused */
-	1,	/* 23 -- IDE (Winbond INT C)  */
-	1,	/* 24 -- IDE (Winbond INT D)  */
-		/* 35 - 31 (EPIC 9 - 15) Unused */
-#else
-	1,	/* 16: EPIC IRQ 0: Active Low -- PCI intrs */
-	1,	/* 17: EPIC IRQ 1: Active Low -- PCI (possibly 8259) intrs */
-	1,	/* 18: EPIC IRQ 2: Active Low -- PCI (possibly 8259) intrs  */
-	1	/* 19: EPIC IRQ 3: Active Low -- PCI intrs */
-		/* 20: EPIC IRQ 4: Not used */
-#endif
-};
-
-static void __init
-sandpoint_setup_arch(void)
-{
-	loops_per_jiffy = 100000000 / HZ;
-
-#ifdef CONFIG_BLK_DEV_INITRD
-	if (initrd_start)
-		ROOT_DEV = Root_RAM0;
-	else
-#endif
-#ifdef	CONFIG_ROOT_NFS
-		ROOT_DEV = Root_NFS;
-#else
-		ROOT_DEV = Root_HDA1;
-#endif
-
-	/* Lookup PCI host bridges */
-	sandpoint_find_bridges();
-
-#ifdef CONFIG_DUMMY_CONSOLE
-	conswitchp = &dummy_con;
-#endif
-
-	printk("Motorola SPS Sandpoint Test Platform\n");
-	printk("Sandpoint port (MontaVista Software, Inc. (source@mvista.com))\n");
-
-	/* The Sandpoint rom doesn't enable any caches.  Do that now.
-	 * The 7450 portion will also set up the L3s once I get enough
-	 * information do do so.  If the processor running doesn't have
-	 * and L2, the _set_L2CR is a no-op.
-	 */
-	if (cur_cpu_spec[0]->cpu_features & CPU_FTR_SPEC7450) {
-		/* Just enable L2, the bits are different from others.
-		*/
-		_set_L2CR(L2CR_L2E);
-	}
-	else {
-		/* The magic number for Sandpoint/74xx PrPMCs.
-		*/
-		_set_L2CR(0xbd014000);
-	}
-}
-
-#define	SANDPOINT_87308_CFG_ADDR		0x15c
-#define	SANDPOINT_87308_CFG_DATA		0x15d
-
-#define	SANDPOINT_87308_CFG_INB(addr, byte) {				\
-	outb((addr), SANDPOINT_87308_CFG_ADDR);				\
-	(byte) = inb(SANDPOINT_87308_CFG_DATA);				\
-}
-
-#define	SANDPOINT_87308_CFG_OUTB(addr, byte) {				\
-	outb((addr), SANDPOINT_87308_CFG_ADDR);				\
-	outb((byte), SANDPOINT_87308_CFG_DATA);				\
-}
-
-#define SANDPOINT_87308_SELECT_DEV(dev_num) {				\
-	SANDPOINT_87308_CFG_OUTB(0x07, (dev_num));			\
-}
-
-#define	SANDPOINT_87308_DEV_ENABLE(dev_num) {				\
-	SANDPOINT_87308_SELECT_DEV(dev_num);				\
-	SANDPOINT_87308_CFG_OUTB(0x30, 0x01);				\
-}
-
-/*
- * Initialize the ISA devices on the Nat'l PC87308VUL SuperIO chip.
- */
-static void __init
-sandpoint_setup_natl_87308(void)
-{
-	u_char	reg;
-
-	/*
-	 * Enable all the devices on the Super I/O chip.
-	 */
-	SANDPOINT_87308_SELECT_DEV(0x00); /* Select kbd logical device */
-	SANDPOINT_87308_CFG_OUTB(0xf0, 0x00); /* Set KBC clock to 8 Mhz */
-	SANDPOINT_87308_DEV_ENABLE(0x00); /* Enable keyboard */
-	SANDPOINT_87308_DEV_ENABLE(0x01); /* Enable mouse */
-	SANDPOINT_87308_DEV_ENABLE(0x02); /* Enable rtc */
-	SANDPOINT_87308_DEV_ENABLE(0x03); /* Enable fdc (floppy) */
-	SANDPOINT_87308_DEV_ENABLE(0x04); /* Enable parallel */
-	SANDPOINT_87308_DEV_ENABLE(0x05); /* Enable UART 2 */
-	SANDPOINT_87308_CFG_OUTB(0xf0, 0x82); /* Enable bank select regs */
-	SANDPOINT_87308_DEV_ENABLE(0x06); /* Enable UART 1 */
-	SANDPOINT_87308_CFG_OUTB(0xf0, 0x82); /* Enable bank select regs */
-
-	/* Set up floppy in PS/2 mode */
-	outb(0x09, SIO_CONFIG_RA);
-	reg = inb(SIO_CONFIG_RD);
-	reg = (reg & 0x3F) | 0x40;
-	outb(reg, SIO_CONFIG_RD);
-	outb(reg, SIO_CONFIG_RD);       /* Have to write twice to change! */
-
-	return;
-}
-
-/*
- * Fix IDE interrupts.
- */
-static void __init
-sandpoint_fix_winbond_83553(void)
-{
-	/* Make all 8259 interrupt level sensitive */
-	outb(0xf8, 0x4d0);
-	outb(0xde, 0x4d1);
-
-	return;
-}
-
-static void __init
-sandpoint_init2(void)
-{
-	/* Do Sandpoint board specific initialization.  */
-	sandpoint_fix_winbond_83553();
-	sandpoint_setup_natl_87308();
-
-	request_region(0x00,0x20,"dma1");
-	request_region(0x20,0x20,"pic1");
-	request_region(0x40,0x20,"timer");
-	request_region(0x80,0x10,"dma page reg");
-	request_region(0xa0,0x20,"pic2");
-	request_region(0xc0,0x20,"dma2");
-
-	return;
-}
-
-/*
- * Interrupt setup and service.  Interrrupts on the Sandpoint come
- * from the four PCI slots plus the 8259 in the Winbond Super I/O (SIO).
- * These interrupts are sent to one of four IRQs on the EPIC.
- * The SIO shares its interrupt with either slot 2 or slot 3 (INTA#).
- * Slot numbering is confusing.  Sometimes in the documentation they
- * use 0,1,2,3 and others 1,2,3,4.  We will use slots 1,2,3,4 and
- * map this to IRQ 16, 17, 18, 19.
- * For Sandpoint X3, this has been better designed.  The 8259 is
- * cascaded from EPIC IRQ0, IRQ1-4 map to PCI slots 1-4, IDE is on
- * EPIC 7 and 8.
- */
-static void __init
-sandpoint_init_IRQ(void)
-{
-	int i;
-
-	/*
-	 * 3 things cause us to jump through some hoops:
-	 *   1) the EPIC on the 8240 & 107 are not full-blown openpic pic's
-	 *   2) the 8259 is NOT cascaded on the openpic IRQ 0
-	 *   3) the 8259 shares its interrupt line with some PCI interrupts.
-	 *
-	 * What we'll do is set up the 8259 to be level sensitive, active low
-	 * just like a PCI device.  Then, when an interrupt on the IRQ that is
-	 * shared with the 8259 comes in, we'll take a peek at the 8259 to see
-	 * it its generating an interrupt.  If it is, we'll handle the 8259
-	 * interrupt.  Otherwise, we'll handle it just like a normal PCI
-	 * interrupt.  This does give the 8259 interrupts a higher priority
-	 * than the EPIC ones--hopefully, not a problem.
-	 */
-	OpenPIC_InitSenses = sandpoint_openpic_initsenses;
-	OpenPIC_NumInitSenses = sizeof(sandpoint_openpic_initsenses);
-
-	openpic_init(1, 0, NULL, -1);
-
-	/*
-	 * openpic_init() has set up irq_desc[0-23] to be openpic
-	 * interrupts.  We need to set irq_desc[0-15] to be 8259 interrupts.
-	 * We then need to request and enable the 8259 irq.
-	 */
-	for(i=0; i < NUM_8259_INTERRUPTS; i++) 
-		irq_desc[i].handler = &i8259_pic;
-
-	if (request_irq(SANDPOINT_SIO_IRQ, no_action, SA_INTERRUPT,
-			"8259 cascade to EPIC", NULL)) {
-	
-		printk("Unable to get OpenPIC IRQ %d for cascade\n",
-			SANDPOINT_SIO_IRQ);
-	}
-
-	i8259_init(NULL);
-}
-
-static int
-sandpoint_get_irq(struct pt_regs *regs)
-{
-        int	irq, cascade_irq;
-
-	irq = openpic_irq();
-
-	if (irq == SANDPOINT_SIO_IRQ) {
-		cascade_irq = i8259_irq(regs);
-
-		if (cascade_irq != -1) {
-			irq = cascade_irq;
-			openpic_eoi();
-		}
-	}
-	else if (irq == OPENPIC_VEC_SPURIOUS) {
-		irq = -1;
-	}
-
-	return irq;
-}
-
-static u32
-sandpoint_irq_canonicalize(u32 irq)
-{
-	if (irq == 2)
-	{
-		return 9;
-	}
-	else
-	{
-		return irq;
-	}
-}
-
-static ulong __init
-sandpoint_find_end_of_memory(void)
-{
-	ulong	size = 0;
-
-#if 0	/* Leave out until DINK sets mem ctlr correctly */
-	size = mpc10x_get_mem_size(MPC10X_MEM_MAP_B);
-#else
-	size = 32*1024*1024;
-#endif
-
-	return size;
-}
-
-static void __init
-sandpoint_map_io(void)
-{
-	io_block_mapping(0xfe000000, 0xfe000000, 0x02000000, _PAGE_IO);
-}
-
-/*
- * Due to Sandpoint X2 errata, the Port 92 will not work.
- */
-static void
-sandpoint_restart(char *cmd)
-{
-	local_irq_disable();
-
-	/* Set exception prefix high - to the firmware */
-	_nmask_and_or_msr(0, MSR_IP);
-
-	/* Reset system via Port 92 */
-	outb(0x00, 0x92);
-	outb(0x01, 0x92);
-	for(;;);	/* Spin until reset happens */
-}
-
-static void
-sandpoint_power_off(void)
-{
-	local_irq_disable();
-	for(;;);  /* No way to shut power off with software */
-	/* NOTREACHED */
-}
-
-static void
-sandpoint_halt(void)
-{
-	sandpoint_power_off();
-	/* NOTREACHED */
-}
-
-static int
-sandpoint_show_cpuinfo(struct seq_file *m)
-{
-	uint pvid;
-
-	pvid = mfspr(PVR);
-
-	seq_printf(m, "vendor\t\t: Motorola SPS\n");
-	seq_printf(m, "machine\t\t: Sandpoint\n");
-	seq_printf(m, "processor\t: PVID: 0x%x, vendor: %s\n",
-			pvid, (pvid & (1<<15) ? "IBM" : "Motorola"));
-
-	return 0;
-}
-
-#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
-/*
- * IDE support.
- */
-static int		sandpoint_ide_ports_known = 0;
-static unsigned long	sandpoint_ide_regbase[MAX_HWIFS];
-static unsigned long	sandpoint_ide_ctl_regbase[MAX_HWIFS];
-static unsigned long	sandpoint_idedma_regbase;
-
-static void
-sandpoint_ide_probe(void)
-{
-        struct pci_dev *pdev = pci_find_device(PCI_VENDOR_ID_WINBOND,
-					       PCI_DEVICE_ID_WINBOND_82C105,
-					       NULL);
-
-        if(pdev) {
-                sandpoint_ide_regbase[0]=pdev->resource[0].start;
-                sandpoint_ide_regbase[1]=pdev->resource[2].start;
-                sandpoint_ide_ctl_regbase[0]=pdev->resource[1].start;
-                sandpoint_ide_ctl_regbase[1]=pdev->resource[3].start;
-                sandpoint_idedma_regbase=pdev->resource[4].start;
-        }
-
-        sandpoint_ide_ports_known = 1;
-	return;
-}
-
-static int
-sandpoint_ide_default_irq(unsigned long base)
-{
-        if (sandpoint_ide_ports_known == 0)
-	        sandpoint_ide_probe();
-
-	if (base == sandpoint_ide_regbase[0])
-		return SANDPOINT_IDE_INT0;
-	else if (base == sandpoint_ide_regbase[1])
-		return SANDPOINT_IDE_INT1;
-	else
-		return 0;
-}
-
-static unsigned long
-sandpoint_ide_default_io_base(int index)
-{
-        if (sandpoint_ide_ports_known == 0)
-	        sandpoint_ide_probe();
-
-	return sandpoint_ide_regbase[index];
-}
-
-static void __init
-sandpoint_ide_init_hwif_ports(hw_regs_t *hw, unsigned long data_port,
-			      unsigned long ctrl_port, int *irq)
-{
-	unsigned long reg = data_port;
-	uint	alt_status_base;
-	int	i;
-
-	for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) {
-		hw->io_ports[i] = reg++;
-	}
-
-	if (data_port == sandpoint_ide_regbase[0]) {
-		alt_status_base = sandpoint_ide_ctl_regbase[0] + 2;
-		hw->irq = 14;
-	}
-	else if (data_port == sandpoint_ide_regbase[1]) {
-		alt_status_base = sandpoint_ide_ctl_regbase[1] + 2;
-		hw->irq = 15;
-	}
-	else {
-		alt_status_base = 0;
-		hw->irq = 0;
-	}
-
-	if (ctrl_port) {
-		hw->io_ports[IDE_CONTROL_OFFSET] = ctrl_port;
-	} else {
-		hw->io_ports[IDE_CONTROL_OFFSET] = alt_status_base;
-	}
-
-	if (irq != NULL) {
-		*irq = hw->irq;
-	}
-
-	return;
-}
-#endif
-
-/*
- * Set BAT 3 to map 0xf8000000 to end of physical memory space 1-to-1.
- */
-static __inline__ void
-sandpoint_set_bat(void)
-{
-	unsigned long   bat3u, bat3l;
-	static int	mapping_set = 0;
-
-	if (!mapping_set) {
-
-		__asm__ __volatile__(
-		" lis %0,0xf800\n \
-		  ori %1,%0,0x002a\n \
-		  ori %0,%0,0x0ffe\n \
-		  mtspr 0x21e,%0\n \
-		  mtspr 0x21f,%1\n \
-		  isync\n \
-		  sync "
-		  : "=r" (bat3u), "=r" (bat3l));
-
-		mapping_set = 1;
-	}
-
-	return;
-}
-
-#ifdef	CONFIG_SERIAL_TEXT_DEBUG
-#include <linux/serialP.h>
-#include <linux/serial_reg.h>
-#include <asm/serial.h>
-
-static struct serial_state rs_table[RS_TABLE_SIZE] = {
-	SERIAL_PORT_DFNS	/* Defined in <asm/serial.h> */
-};
-
-static void
-sandpoint_progress(char *s, unsigned short hex)
-{
-	volatile char c;
-	volatile unsigned long com_port;
-	u16 shift;
-
-	com_port = rs_table[0].port;
-	shift = rs_table[0].iomem_reg_shift;
-
-	while ((c = *s++) != 0) {
-		while ((*((volatile unsigned char *)com_port +
-				(UART_LSR << shift)) & UART_LSR_THRE) == 0)
-		                ;
-	        *(volatile unsigned char *)com_port = c;
-		
-		if (c == '\n') {
-			while ((*((volatile unsigned char *)com_port +
-				(UART_LSR << shift)) & UART_LSR_THRE) == 0)
-					;
-	        	*(volatile unsigned char *)com_port = '\r';
-		}
-	}
-}
-#endif	/* CONFIG_SERIAL_TEXT_DEBUG */
-
-__init void sandpoint_setup_pci_ptrs(void);
-
-TODC_ALLOC();
-
-void __init
-platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
-	      unsigned long r6, unsigned long r7)
-{
-	parse_bootinfo(find_bootinfo());
-
-	/* Map in board regs, etc. */
-	sandpoint_set_bat();
-
-	isa_io_base = MPC10X_MAPB_ISA_IO_BASE;
-	isa_mem_base = MPC10X_MAPB_ISA_MEM_BASE;
-	pci_dram_offset = MPC10X_MAPB_DRAM_OFFSET;
-	ISA_DMA_THRESHOLD = 0x00ffffff;
-	DMA_MODE_READ = 0x44;
-	DMA_MODE_WRITE = 0x48;
-
-	ppc_md.setup_arch = sandpoint_setup_arch;
-	ppc_md.show_cpuinfo = sandpoint_show_cpuinfo;
-	ppc_md.irq_canonicalize = sandpoint_irq_canonicalize;
-	ppc_md.init_IRQ = sandpoint_init_IRQ;
-	ppc_md.get_irq = sandpoint_get_irq;
-	ppc_md.init = sandpoint_init2;
-
-	ppc_md.restart = sandpoint_restart;
-	ppc_md.power_off = sandpoint_power_off;
-	ppc_md.halt = sandpoint_halt;
-
-	ppc_md.find_end_of_memory = sandpoint_find_end_of_memory;
-	ppc_md.setup_io_mappings = sandpoint_map_io;
-
-	TODC_INIT(TODC_TYPE_PC97307, 0x70, 0x00, 0x71, 8);
-	ppc_md.time_init = todc_time_init;
-	ppc_md.set_rtc_time = todc_set_rtc_time;
-	ppc_md.get_rtc_time = todc_get_rtc_time;
-	ppc_md.calibrate_decr = todc_calibrate_decr;
-
-	ppc_md.nvram_read_val = todc_mc146818_read_val;
-	ppc_md.nvram_write_val = todc_mc146818_write_val;
-
-	ppc_md.heartbeat = NULL;
-	ppc_md.heartbeat_reset = 0;
-	ppc_md.heartbeat_count = 0;
-
-#ifdef	CONFIG_SERIAL_TEXT_DEBUG
-	ppc_md.progress = sandpoint_progress;
-#else	/* !CONFIG_SERIAL_TEXT_DEBUG */
-	ppc_md.progress = NULL;
-#endif	/* CONFIG_SERIAL_TEXT_DEBUG */
-
-#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
-        ppc_ide_md.default_irq = sandpoint_ide_default_irq;
-        ppc_ide_md.default_io_base = sandpoint_ide_default_io_base;
-        ppc_ide_md.ide_init_hwif = sandpoint_ide_init_hwif_ports;
-#endif
-
-	return;
-}
diff -Nru a/arch/ppc/platforms/zx4500.h b/arch/ppc/platforms/zx4500.h
--- a/arch/ppc/platforms/zx4500.h	Tue Feb 11 15:48:53 2003
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,68 +0,0 @@
-/* * arch/ppc/platforms/zx4500.h
- * 
- * Board setup routines for Znyx ZX4500 cPCI board.
- *
- * Author: Mark A. Greer
- *         mgreer@mvista.com
- *
- * 2000-2001 (c) MontaVista, Software, Inc.  This file is licensed under
- * the terms of the GNU General Public License version 2.  This program
- * is licensed "as is" without any warranty of any kind, whether express
- * or implied.
- */
-#ifndef	__PPC_PLATFORMS_ZX4500_H_
-#define	__PPC_PLATFORMS_ZX4500_H_
-
-/*
- * Define the addresses of CPLD registers in CLPD area.
- */
-#define	ZX4500_CPLD_BOARD_ID		0xff800001
-#define	ZX4500_CPLD_REV			0xff800002
-#define	ZX4500_CPLD_RESET		0xff800011
-#define	ZX4500_CPLD_PHY1		0xff800014
-#define	ZX4500_CPLD_PHY2		0xff800015
-#define	ZX4500_CPLD_PHY3		0xff800016
-#define	ZX4500_CPLD_SYSCTL		0xff800017
-#define	ZX4500_CPLD_EXT_FLASH		0xff800018
-#define	ZX4500_CPLD_DUAL1		0xff800019
-#define	ZX4500_CPLD_DUAL2		0xff80001A
-#define	ZX4500_CPLD_STATUS		0xff800030
-#define	ZX4500_CPLD_STREAM		0xff800032
-#define	ZX4500_CPLD_PHY1_LED		0xff800034
-#define	ZX4500_CPLD_PHY2_LED		0xff800035
-#define	ZX4500_CPLD_PHY3_LED		0xff800036
-#define	ZX4500_CPLD_PHY1_LNK		0xff80003C
-#define	ZX4500_CPLD_PHY2_LNK		0xff80003D
-#define	ZX4500_CPLD_PHY3_LNK		0xff80003E
-
-#define	ZX4500_CPLD_RESET_SOFT		0x01	/* Soft Reset */
-#define	ZX4500_CPLD_RESET_XBUS		0x40	/* Reset entire board */
-
-#define	ZX4500_CPLD_SYSCTL_PMC		0x01	/* Enable INTA/B/C/D from PMC */
-#define	ZX4500_CPLD_SYSCTL_BCM		0x04	/* Enable INTA from BCM */
-#define	ZX4500_CPLD_SYSCTL_SINTA	0x08	/* Enable SINTA from 21554 */
-#define	ZX4500_CPLD_SYSCTL_WD		0x20	/* Enable Watchdog Timer */
-#define	ZX4500_CPLD_SYSCTL_PMC_TRI	0x80	/* Tri-state PMC EREADY */
-
-#define	ZX4500_CPLD_DUAL2_LED_PULL	0x01	/* Pull LED */
-#define	ZX4500_CPLD_DUAL2_LED_EXT_FAULT	0x02	/* External Fault LED */
-#define	ZX4500_CPLD_DUAL2_LED_INT_FAULT	0x04	/* Internal Fault LED */
-#define	ZX4500_CPLD_DUAL2_LED_OK	0x08	/* OK LED */
-#define	ZX4500_CPLD_DUAL2_LED_CLK	0x10	/* CLK LED */
-
-/*
- * Defines related to boot string stored in flash.
- */
-#define	ZX4500_BOOT_STRING_ADDR		0xfff7f000
-#define	ZX4500_BOOT_STRING_LEN		80
-
-/*
- * Define the IDSEL that the PCI bus side of the 8240 is connected to.
- * This IDSEL must not be selected from the 8240 processor side.
- */
-#define	ZX4500_HOST_BRIDGE_IDSEL	20
-
-
-void zx4500_find_bridges(void);
-
-#endif	/* __PPC_PLATFORMS_ZX4500_H_ */
diff -Nru a/arch/ppc/platforms/zx4500_pci.c b/arch/ppc/platforms/zx4500_pci.c
--- a/arch/ppc/platforms/zx4500_pci.c	Tue Feb 11 15:48:53 2003
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,138 +0,0 @@
-/*
- * arch/ppc/platforms/zx4500_pci.c
- * 
- * PCI setup routines for Znyx ZX4500 cPCI boards.
- *
- * Author: Mark A. Greer
- *         mgreer@mvista.com
- *
- * 2000-2001 (c) MontaVista, Software, Inc.  This file is licensed under
- * the terms of the GNU General Public License version 2.  This program
- * is licensed "as is" without any warranty of any kind, whether express
- * or implied.
- */
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-#include <linux/slab.h>
-
-#include <asm/byteorder.h>
-#include <asm/io.h>
-#include <asm/uaccess.h>
-#include <asm/machdep.h>
-#include <asm/mpc10x.h>
-#include <asm/pci-bridge.h>
-
-#include "zx4500.h"
-
-/*
- * Znyx ZX4500 interrupt routes.
- */
-static inline int
-zx4500_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
-{
-	static char pci_irq_table[][4] =
-	/*
-	 *	PCI IDSEL/INTPIN->INTLINE 
-	 * 	   A   B   C   D
-	 */
-	{
-		{ 19,  0,  0,  0 },	/* IDSEL 21 - 21554 PCI-cPCI bridge */
-		{ 18,  0,  0,  0 },	/* IDSEL 22 - BCM5600 INTA */
-		{ 16, 20, 16, 20 },	/* IDSEL 23 - PPMC Slot */
-	};
-
-	const long min_idsel = 21, max_idsel = 23, irqs_per_slot = 4;
-	return PCI_IRQ_TABLE_LOOKUP;
-}
-
-void __init
-zx4500_board_init(struct pci_controller *hose)
-{
-	uint	val;
-	u_char	sysctl;
-
-	/*
-	 * CPLD Registers are mapped in by BAT 3 in zx4500_setup_arch().
-	 *
-	 * Turn off all interrupts routed through the CPLD.
-	 * Also, turn off watchdog timer and drive PMC EREADY low.
-	 */
-	sysctl = in_8((volatile u_char *)ZX4500_CPLD_SYSCTL);
-	sysctl &= ~(ZX4500_CPLD_SYSCTL_PMC |
-		    ZX4500_CPLD_SYSCTL_BCM |
-		    ZX4500_CPLD_SYSCTL_SINTA |
-		    ZX4500_CPLD_SYSCTL_WD |
-		    ZX4500_CPLD_SYSCTL_PMC_TRI);
-	out_8((volatile u_char *)ZX4500_CPLD_SYSCTL, sysctl);
-
-	/*
-	 * Kludge the size that BAR2 of the 21554 asks for
-	 * (i.e., set Upstream I/O or Memory 0 Setup Register).
-	 * Old versions of SROM wants 1 GB which is too large, make it ask
-	 * for 256 MB.
-	 */
-	early_read_config_dword(hose, 0, PCI_DEVFN(21,0), 0xc4, &val);
-
-	if (val != 0) {
-		early_write_config_dword(hose,
-					 0,
-					 PCI_DEVFN(21,0),
-					 0xc4,
-					 val | 0xf0000000);
-	}
-
-	return;
-}
-
-static int                     
-zx4500_exclude_device(u_char bus, u_char devfn)
-{
-	if ((bus == 0) && (PCI_SLOT(devfn) == ZX4500_HOST_BRIDGE_IDSEL)) {
-		return PCIBIOS_DEVICE_NOT_FOUND;
-	}
-	else {
-		return PCIBIOS_SUCCESSFUL;
-	}
-}
-
-void __init
-zx4500_find_bridges(void)
-{
-	struct pci_controller	*hose;
-
-	hose = pcibios_alloc_controller();
-
-	if (!hose)
-		return;
-
-	hose->first_busno = 0;
-	hose->last_busno = 0xff;
-
-	if (mpc10x_bridge_init(hose,
-			       MPC10X_MEM_MAP_B,
-			       MPC10X_MEM_MAP_B,
-			       MPC10X_MAPB_EUMB_BASE) == 0) {
-
-		hose->mem_resources[0].end = 0xffffffff;
-	
-		/* Initialize the board */
-		zx4500_board_init(hose);
-
-		/* scan PCI bus */
-		ppc_md.pci_exclude_device = zx4500_exclude_device;
-		hose->last_busno = pciauto_bus_scan(hose, hose->first_busno);
-
-		ppc_md.pcibios_fixup = NULL;
-		ppc_md.pcibios_fixup_bus = NULL;
-		ppc_md.pci_swizzle = common_swizzle;
-		ppc_md.pci_map_irq = zx4500_map_irq;
-	}
-	else {
-		if (ppc_md.progress)
-			ppc_md.progress("Bridge init failed", 0x100);
-		printk("Host bridge init failed\n");
-	}
-
-	return;
-}
diff -Nru a/arch/ppc/platforms/zx4500_serial.h b/arch/ppc/platforms/zx4500_serial.h
--- a/arch/ppc/platforms/zx4500_serial.h	Tue Feb 11 15:48:53 2003
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,46 +0,0 @@
-/*
- * arch/ppc/platforms/zx4500_serial.h
- * 
- * Definitions for Znyx ZX4500 board support
- *
- * Author: Mark A. Greer
- *         mgreer@mvista.com
- *
- * 2000-2001 (c) MontaVista, Software, Inc.  This file is licensed under
- * the terms of the GNU General Public License version 2.  This program
- * is licensed "as is" without any warranty of any kind, whether express
- * or implied.
- */
-
-#ifndef __ASMPPC_ZX4500_SERIAL_H
-#define __ASMPPC_ZX4500_SERIAL_H
-
-#include <linux/config.h>
-
-/* Define the UART base address (only 1 UART) */
-#define ZX4500_SERIAL_1			0xff880000
-
-#ifdef CONFIG_SERIAL_MANY_PORTS
-#define RS_TABLE_SIZE  64
-#else
-#define RS_TABLE_SIZE  1
-#endif
-
-/* Rate for the 1.8432 Mhz clock for the onboard serial chip */
-#define BASE_BAUD ( 1843200 / 16 )
-
-#ifdef CONFIG_SERIAL_DETECT_IRQ
-#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF|ASYNC_SKIP_TEST|ASYNC_AUTO_IRQ)
-#else
-#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF|ASYNC_SKIP_TEST)
-#endif
-
-#define STD_SERIAL_PORT_DFNS \
-        { 0, BASE_BAUD, ZX4500_SERIAL_1, 17, STD_COM_FLAGS, /* ttyS0 */	\
-		iomem_base: (u8 *)ZX4500_SERIAL_1,			\
-		io_type: SERIAL_IO_MEM },
-
-#define SERIAL_PORT_DFNS \
-        STD_SERIAL_PORT_DFNS
-
-#endif /* __ASMPPC_ZX4500_SERIAL_H */
diff -Nru a/arch/ppc/platforms/zx4500_setup.c b/arch/ppc/platforms/zx4500_setup.c
--- a/arch/ppc/platforms/zx4500_setup.c	Sun May 25 17:00:00 2003
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,359 +0,0 @@
-/*
- * arch/ppc/platforms/zx4500_setup.c
- *
- * Board setup routines for Znyx ZX4500 family of cPCI boards.
- *
- * Author: Mark A. Greer
- *         mgreer@mvista.com
- *
- * 2000-2001 (c) MontaVista, Software, Inc.  This file is licensed under
- * the terms of the GNU General Public License version 2.  This program
- * is licensed "as is" without any warranty of any kind, whether express
- * or implied.
- */
-
-/*
- * This file adds support for the Znyx ZX4500 series of cPCI boards.
- * These boards have an 8240, UART on the processor bus, a PPMC slot (for now
- * the card in this slot can _not_ be a monarch), Broadcom BCM5600, and an
- * Intel 21554 bridge.
- *
- * Currently, this port assumes that the 8240 is the master and performs PCI
- * arbitration, etc.  It is also assumed that the 8240 is wired to come up
- * using memory MAP B (CHRP map).
- *
- * Note: This board port will not work properly as it is.  You must apply the
- *	 patch that is at ftp://ftp.mvista.com/pub/Area51/zx4500/zx_patch_2_5
- */
-#include <linux/config.h>
-#include <linux/stddef.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/errno.h>
-#include <linux/reboot.h>
-#include <linux/pci.h>
-#include <linux/kdev_t.h>
-#include <linux/types.h>
-#include <linux/major.h>
-#include <linux/initrd.h>
-#include <linux/console.h>
-#include <linux/delay.h>
-#include <linux/irq.h>
-#include <linux/seq_file.h>
-#include <linux/root_dev.h>
-
-#include <asm/system.h>
-#include <asm/pgtable.h>
-#include <asm/page.h>
-#include <asm/dma.h>
-#include <asm/io.h>
-#include <asm/machdep.h>
-#include <asm/prom.h>
-#include <asm/time.h>
-#include <asm/open_pic.h>
-#include <asm/mpc10x.h>
-#include <asm/pci-bridge.h>
-#include <asm/bootinfo.h>
-
-#include "zx4500.h"
-
-static u_char zx4500_openpic_initsenses[] __initdata = {
-	0,	/* 0-15 are not used on an 8240 EPIC */
-	0,	/* 1 */
-	0,	/* 2 */
-	0,	/* 3 */
-	0,	/* 4 */
-	0,	/* 5 */
-	0,	/* 6 */
-	0,	/* 7 */
-	0,	/* 8 */
-	0,	/* 9 */
-	0,	/* 10 */
-	0,	/* 11 */
-	0,	/* 12 */
-	0,	/* 13 */
-	0,	/* 14 */
-	0,	/* 15 */
-	1,	/* 16: EPIC IRQ 0: Active Low -- PMC #INTA & #INTC */
-	1,	/* 17: EPIC IRQ 1: Active Low -- UART */
-	1,	/* 18: EPIC IRQ 2: Active Low -- BCM5600 #INTA */
-	1,	/* 19: EPIC IRQ 3: Active Low -- 21554 #SINTA */
-	1,	/* 20: EPIC IRQ 4: Active Low -- PMC #INTB & #INTD */
-};
-
-
-static void __init
-zx4500_setup_arch(void)
-{
-	char		boot_string[ZX4500_BOOT_STRING_LEN + 1];
-	char		*boot_arg;
-	extern char	cmd_line[];
-
-
-	loops_per_jiffy = 50000000 / HZ;
-
-#ifdef CONFIG_BLK_DEV_INITRD
-	if (initrd_start)
-		ROOT_DEV = Root_RAM0;
-	else
-#endif
-#if	defined(CONFIG_ROOT_NFS)
-		ROOT_DEV = Root_NFS;
-#else
-		ROOT_DEV = Root_SDA1;
-#endif
-
-	/* Get boot string from flash */
-	strlcpy(boot_string,
-		(char *)ZX4500_BOOT_STRING_ADDR,
-		sizeof(boot_string));
-	boot_string[ZX4500_BOOT_STRING_LEN] = '\0';
-
-	/* Can be delimited by 0xff */
-	boot_arg = strchr(boot_string, 0xff);
-
-	if (boot_arg != NULL) {
-		*boot_arg = '\0';
-	}
-
-	/* First 3 chars must be 'dev'.  If not, ignore. */
-	if (!strncmp(boot_string, "dev", 3)) {
-		/* skip 'dev?' and any blanks after it */
-		boot_arg = strchr(boot_string, ' ');
-
-		if (boot_arg != NULL) {
-			while (*boot_arg == ' ') boot_arg++;
-			strcat(cmd_line, " ");
-			strcat(cmd_line, boot_arg);
-		}
-	}
-
-	/* nothing but serial consoles... */
-	printk("Znyx ZX4500 Series High Performance Switch\n");
-	printk("ZX4500 port (C) 2000, 2001 MontaVista Software, Inc. (source@mvista.com)\n");
-
-	/* Lookup PCI host bridge */
-	zx4500_find_bridges();
-
-	printk("ZX4500 Board ID: 0x%x, Revision #: 0x%x\n",
-		in_8((volatile u_char *)ZX4500_CPLD_BOARD_ID),
-		in_8((volatile u_char *)ZX4500_CPLD_REV));
-
-	return;
-}
-
-static ulong __init
-zx4500_find_end_of_memory(void)
-{
-	return mpc10x_get_mem_size(MPC10X_MEM_MAP_B);
-}
-
-static void __init
-zx4500_map_io(void)
-{
-	io_block_mapping(0xfe000000, 0xfe000000, 0x02000000, _PAGE_IO);
-}
-
-/*
- * Enable interrupts routed thru CPLD to reach the 8240's EPIC.
- * Need to enable all 4 PMC intrs, BCM INTA, and 21554 SINTA to 8240.
- * UART intrs routed directly to 8240 (not thru CPLD).
- */
-static void __init
-zx4500_enable_cpld_intrs(void)
-{
-	u_char	sysctl;
-
-	sysctl = in_8((volatile u_char *)ZX4500_CPLD_SYSCTL);
-	sysctl |= (ZX4500_CPLD_SYSCTL_PMC |
-		   ZX4500_CPLD_SYSCTL_BCM |
-		   ZX4500_CPLD_SYSCTL_SINTA);
-	out_8((volatile u_char *)ZX4500_CPLD_SYSCTL, sysctl);
-
-	return;
-}
-
-static void __init
-zx4500_init_IRQ(void)
-{
-	OpenPIC_InitSenses = zx4500_openpic_initsenses;
-	OpenPIC_NumInitSenses = sizeof(zx4500_openpic_initsenses);
-
-	openpic_init(1, 0, NULL, -1);
-
-	zx4500_enable_cpld_intrs(); /* Allow CPLD to route intrs to 8240 */
-
-	return;
-}
-
-static void
-zx4500_restart(char *cmd)
-{
-	local_irq_disable();
-
-	out_8((volatile u_char *)ZX4500_CPLD_RESET, ZX4500_CPLD_RESET_XBUS);
-	for (;;);
-
-	panic("Restart failed.\n");
-	/* NOTREACHED */
-}
-
-static void
-zx4500_power_off(void)
-{
-	local_irq_disable();
-	for(;;);  /* No way to shut power off with software */
-	/* NOTREACHED */
-}
-
-static void
-zx4500_halt(void)
-{
-	zx4500_power_off();
-	/* NOTREACHED */
-}
-
-static int
-zx4500_get_bus_speed(void)
-{
-	int bus_speed;
-
-	bus_speed = 100000000;
-
-	return bus_speed;
-}
-
-static int
-zx4500_show_cpuinfo(struct seq_file *m)
-{
-	uint pvid;
-
-	seq_printf(m, "vendor\t\t: Znyx\n");
-	seq_printf(m, "machine\t\t: ZX4500\n");
-	seq_printf(m, "processor\t: PVID: 0x%x, vendor: %s\n",
-			pvid, (pvid & (1<<15) ? "IBM" : "Motorola"));
-	seq_printf(m, "bus speed\t: %dMhz\n",
-			zx4500_get_bus_speed()/1000000);
-
-	return 0;
-}
-
-static void __init
-zx4500_calibrate_decr(void)
-{
-	ulong freq;
-
-	freq = zx4500_get_bus_speed() / 4;
-
-	printk("time_init: decrementer frequency = %lu.%.6lu MHz\n",
-	       freq/1000000, freq%1000000);
-
-	tb_ticks_per_jiffy = freq / HZ;
-	tb_to_us = mulhwu_scale_factor(freq, 1000000);
-
-	return;
-}
-
-/*
- * Set BAT 3 to map 0xf0000000 to end of physical memory space 1-1.
- */
-static __inline__ void
-zx4500_set_bat(void)
-{
-	unsigned long   bat3u, bat3l;
-	static int	mapping_set = 0;
-
-	if (!mapping_set) {
-
-		__asm__ __volatile__(
-		" lis %0,0xf800\n \
-		  ori %1,%0,0x002a\n \
-		  ori %0,%0,0x0ffe\n \
-		  mtspr 0x21e,%0\n \
-		  mtspr 0x21f,%1\n \
-		  isync\n \
-		  sync "
-		  : "=r" (bat3u), "=r" (bat3l));
-
-		mapping_set = 1;
-	}
-
-	return;
-}
-
-#ifdef	CONFIG_SERIAL_TEXT_DEBUG
-#include <linux/serialP.h>
-#include <linux/serial_reg.h>
-#include <asm/serial.h>
-
-static struct serial_state rs_table[RS_TABLE_SIZE] = {
-	SERIAL_PORT_DFNS	/* Defined in <asm/serial.h> */
-};
-
-void
-zx4500_progress(char *s, unsigned short hex)
-{
-	volatile char c;
-	volatile unsigned long com_port;
-	u16 shift;
-
-	com_port = rs_table[0].port;
-	shift = rs_table[0].iomem_reg_shift;
-
-	while ((c = *s++) != 0) {
-		while ((*((volatile unsigned char *)com_port +
-				(UART_LSR << shift)) & UART_LSR_THRE) == 0)
-		                ;
-	        *(volatile unsigned char *)com_port = c;
-
-		if (c == '\n') {
-			while ((*((volatile unsigned char *)com_port +
-				(UART_LSR << shift)) & UART_LSR_THRE) == 0)
-					;
-	        	*(volatile unsigned char *)com_port = '\r';
-		}
-	}
-}
-#endif	/* CONFIG_SERIAL_TEXT_DEBUG */
-
-void __init
-platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
-	      unsigned long r6, unsigned long r7)
-{
-	parse_bootinfo(find_bootinfo());
-
-	/* Map in board registers, etc. */
-	zx4500_set_bat();
-
-	isa_io_base = MPC10X_MAPB_ISA_IO_BASE;
-	isa_mem_base = MPC10X_MAPB_ISA_MEM_BASE;
-	pci_dram_offset = MPC10X_MAPB_DRAM_OFFSET;
-
-	ppc_md.setup_arch = zx4500_setup_arch;
-	ppc_md.show_cpuinfo = zx4500_show_cpuinfo;
-	ppc_md.irq_canonicalize = NULL;
-	ppc_md.init_IRQ = zx4500_init_IRQ;
-	ppc_md.get_irq = openpic_get_irq;
-	ppc_md.init = NULL;
-
-	ppc_md.restart = zx4500_restart;
-	ppc_md.power_off = zx4500_power_off;
-	ppc_md.halt = zx4500_halt;
-
-	ppc_md.find_end_of_memory = zx4500_find_end_of_memory;
-	ppc_md.setup_io_mappings = zx4500_map_io;
-
-	ppc_md.calibrate_decr = zx4500_calibrate_decr;
-
-	ppc_md.heartbeat = NULL;
-	ppc_md.heartbeat_reset = 0;
-	ppc_md.heartbeat_count = 0;
-
-#ifdef	CONFIG_SERIAL_TEXT_DEBUG
-	ppc_md.progress = zx4500_progress;
-#else	/* !CONFIG_SERIAL_TEXT_DEBUG */
-	ppc_md.progress = NULL;
-#endif	/* CONFIG_SERIAL_TEXT_DEBUG */
-
-	return;
-}
diff -Nru a/arch/ppc/syslib/Makefile b/arch/ppc/syslib/Makefile
--- a/arch/ppc/syslib/Makefile	Wed Jun  4 20:07:13 2003
+++ b/arch/ppc/syslib/Makefile	Wed Jul  2 17:44:14 2003
@@ -61,8 +61,9 @@
 					pci_auto.o indirect_pci.o todc_time.o
 obj-$(CONFIG_SPRUCE)		+= cpc700_pic.o indirect_pci.o pci_auto.o \
 				   todc_time.o
-obj-$(CONFIG_ZX4500)		+= indirect_pci.o pci_auto.o mpc10x_common.o \
-					i8259.o open_pic.o
 obj-$(CONFIG_8260)		+= m8260_setup.o ppc8260_pic.o
+ifeq ($(CONFIG_SERIAL_8250)$(CONFIG_PPC_GEN550),yy)
+obj-$(CONFIG_KGDB)		+= gen550_kgdb.o gen550_dbg.o
+obj-$(CONFIG_SERIAL_TEXT_DEBUG)	+= gen550_dbg.o
+endif
 obj-$(CONFIG_BOOTX_TEXT)	+= btext.o
-
diff -Nru a/arch/ppc/syslib/gen550_dbg.c b/arch/ppc/syslib/gen550_dbg.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/arch/ppc/syslib/gen550_dbg.c	Tue Jul  1 08:34:08 2003
@@ -0,0 +1,174 @@
+/*
+ * arch/ppc/syslib/gen550_dbg.c
+ *
+ * A library of polled 16550 serial routines.  These are intended to
+ * be used to support progress messages, xmon, kgdb, etc. on a
+ * variety of platforms.
+ *
+ * Adapted from lots of code ripped from the arch/ppc/boot/ polled
+ * 16550 support.
+ *
+ * Author: Matt Porter <mporter@mvista.com>
+ *
+ * 2002-2003 (c) MontaVista Software, Inc.  This file is licensed under
+ * the terms of the GNU General Public License version 2.  This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#include <linux/config.h>
+#include <linux/tty.h>		/* For linux/serial_core.h */
+#include <linux/serial_core.h>
+#include <linux/serialP.h>
+#include <linux/serial_reg.h>
+#include <asm/machdep.h>
+#include <asm/serial.h>
+#include <asm/io.h>
+
+#define SERIAL_BAUD	9600
+
+static struct serial_state rs_table[RS_TABLE_SIZE] = {
+	SERIAL_PORT_DFNS	/* defined in <asm/serial.h> */
+};
+
+static void (*serial_outb)(unsigned long, unsigned char);
+static unsigned long (*serial_inb)(unsigned long);
+
+static int shift;
+
+unsigned long direct_inb(unsigned long addr)
+{
+	return readb(addr);
+}
+
+void direct_outb(unsigned long addr, unsigned char val)
+{
+	writeb(val, addr);
+}
+
+unsigned long io_inb(unsigned long port)
+{
+	return inb(port);
+}
+
+void io_outb(unsigned long port, unsigned char val)
+{
+	outb(val, port);
+}
+
+unsigned long serial_init(int chan, void *ignored)
+{
+	unsigned long com_port;
+	unsigned char lcr, dlm;
+
+	/* We need to find out which type io we're expecting.  If it's
+	 * 'SERIAL_IO_PORT', we get an offset from the isa_io_base.
+	 * If it's 'SERIAL_IO_MEM', we can the exact location.  -- Tom */
+	switch (rs_table[chan].io_type) {
+		case SERIAL_IO_PORT:
+			com_port = rs_table[chan].port;
+			serial_outb = io_outb;
+			serial_inb = io_inb;
+			break;
+		case SERIAL_IO_MEM:
+			com_port = (unsigned long)rs_table[chan].iomem_base;
+			serial_outb = direct_outb;
+			serial_inb = direct_inb;
+			break;
+		default:
+			/* We can't deal with it. */
+			return -1;
+	}
+
+	/* How far apart the registers are. */
+	shift = rs_table[chan].iomem_reg_shift;
+
+	/* save the LCR */
+	lcr = serial_inb(com_port + (UART_LCR << shift));
+	
+	/* Access baud rate */
+	serial_outb(com_port + (UART_LCR << shift), UART_LCR_DLAB);
+	dlm = serial_inb(com_port + (UART_DLM << shift));
+
+	/*
+	 * Test if serial port is unconfigured
+	 * We assume that no-one uses less than 110 baud or
+	 * less than 7 bits per character these days.
+	 *  -- paulus.
+	 */
+	if ((dlm <= 4) && (lcr & 2)) {
+		/* port is configured, put the old LCR back */
+		serial_outb(com_port + (UART_LCR << shift), lcr);
+	}
+	else {
+		/* Input clock. */
+		serial_outb(com_port + (UART_DLL << shift),
+			(rs_table[chan].baud_base / SERIAL_BAUD) & 0xFF);
+		serial_outb(com_port + (UART_DLM << shift),
+				(rs_table[chan].baud_base / SERIAL_BAUD) >> 8);
+		/* 8 data, 1 stop, no parity */
+		serial_outb(com_port + (UART_LCR << shift), 0x03);
+		/* RTS/DTR */
+		serial_outb(com_port + (UART_MCR << shift), 0x03);
+
+		/* Clear & enable FIFOs */
+		serial_outb(com_port + (UART_FCR << shift), 0x07);
+	}
+
+	return (com_port);
+}
+
+void
+serial_putc(unsigned long com_port, unsigned char c)
+{
+	while ((serial_inb(com_port + (UART_LSR << shift)) & UART_LSR_THRE) == 0)
+		;
+	serial_outb(com_port, c);
+}
+
+unsigned char
+serial_getc(unsigned long com_port)
+{
+	while ((serial_inb(com_port + (UART_LSR << shift)) & UART_LSR_DR) == 0)
+		;
+	return serial_inb(com_port);
+}
+
+int
+serial_tstc(unsigned long com_port)
+{
+	return ((serial_inb(com_port + (UART_LSR << shift)) & UART_LSR_DR) != 0);
+}
+
+void
+serial_close(unsigned long com_port)
+{
+}
+
+void
+gen550_init(int i, struct uart_port *serial_req)
+{
+	rs_table[i].io_type = serial_req->iotype;
+	rs_table[i].port = serial_req->line;
+	rs_table[i].iomem_base = serial_req->membase;
+	rs_table[i].iomem_reg_shift = serial_req->regshift;
+}
+
+#ifdef CONFIG_SERIAL_TEXT_DEBUG
+void
+gen550_progress(char *s, unsigned short hex)
+{
+	volatile unsigned int progress_debugport;
+	volatile char c;
+
+	progress_debugport = serial_init(0, NULL);
+
+	serial_putc(progress_debugport, '\r');
+
+	while ((c = *s++) != 0)
+		serial_putc(progress_debugport, c);
+
+	serial_putc(progress_debugport, '\n');
+	serial_putc(progress_debugport, '\r');
+}
+#endif /* CONFIG_SERIAL_TEXT_DEBUG */
diff -Nru a/arch/ppc/syslib/gen550_kgdb.c b/arch/ppc/syslib/gen550_kgdb.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/arch/ppc/syslib/gen550_kgdb.c	Tue Jul  1 08:34:08 2003
@@ -0,0 +1,84 @@
+/*
+ * arch/ppc/syslib/gen550_kgdb.c
+ *
+ * Generic 16550 kgdb support intended to be useful on a variety
+ * of platforms.  To enable this support, it is necessary to set
+ * the CONFIG_GEN550 option.  Any virtual mapping of the serial
+ * port(s) to be used can be accomplished by setting
+ * ppc_md.early_serial_map to a platform-specific mapping function.
+ *
+ * Adapted from ppc4xx_kgdb.c. 
+ *
+ * Author: Matt Porter <mporter@mvista.com>
+ *
+ * 2002-2003 (c) MontaVista Software, Inc.  This file is licensed under
+ * the terms of the GNU General Public License version 2.  This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+
+#include <asm/machdep.h>
+
+extern unsigned long serial_init(int, void *);
+extern unsigned long serial_getc(unsigned long);
+extern unsigned long serial_putc(unsigned long, unsigned char);
+
+#if defined(CONFIG_KGDB_TTYS0)
+#define KGDB_PORT 0
+#elif defined(CONFIG_KGDB_TTYS1)
+#define KGDB_PORT 1
+#elif defined(CONFIG_KGDB_TTYS2)
+#define KGDB_PORT 2
+#elif defined(CONFIG_KGDB_TTYS3)
+#define KGDB_PORT 3
+#else
+#error "invalid kgdb_tty port"
+#endif
+
+static volatile unsigned int kgdb_debugport;
+
+void putDebugChar(unsigned char c)
+{
+	if (kgdb_debugport == 0)
+		kgdb_debugport = serial_init(KGDB_PORT, NULL);
+
+	serial_putc(kgdb_debugport, c);
+}
+
+int getDebugChar(void)
+{
+	if (kgdb_debugport == 0)
+		kgdb_debugport = serial_init(KGDB_PORT, NULL);
+
+	return(serial_getc(kgdb_debugport));
+}
+
+void kgdb_interruptible(int enable)
+{
+	return;
+}
+
+void putDebugString(char* str)
+{
+	while (*str != '\0') {
+		putDebugChar(*str);
+		str++;
+	}
+	putDebugChar('\r');
+	return;
+}
+
+/*
+ * Note: gen550_init() must be called already on the port we are going
+ * to use.
+ */
+void
+kgdb_map_scc(void)
+{
+	printk(KERN_DEBUG "kgdb init\n");
+	kgdb_debugport = serial_init(KGDB_PORT, NULL);
+}
diff -Nru a/arch/ppc/syslib/open_pic.c b/arch/ppc/syslib/open_pic.c
--- a/arch/ppc/syslib/open_pic.c	Tue May 20 22:24:05 2003
+++ b/arch/ppc/syslib/open_pic.c	Tue Jun 10 10:47:59 2003
@@ -33,6 +33,7 @@
 
 void* OpenPIC_Addr;
 static volatile struct OpenPIC *OpenPIC = NULL;
+
 /*
  * We define OpenPIC_InitSenses table thusly:
  * bit 0x1: sense, 0 for edge and 1 for level.
@@ -261,32 +262,32 @@
 }
 #endif /* CONFIG_SMP */
 
-#if defined(CONFIG_EPIC_SERIAL_MODE) || defined(CONFIG_PMAC_PBOOK)
-static void openpic_reset(void)
+#ifdef CONFIG_EPIC_SERIAL_MODE
+static void __init openpic_eicr_set_clk(u_int clkval)
 {
-	openpic_setfield(&OpenPIC->Global.Global_Configuration0,
-			 OPENPIC_CONFIG_RESET);
-	while (openpic_readfield(&OpenPIC->Global.Global_Configuration0,
-				 OPENPIC_CONFIG_RESET))
-		mb();
+	openpic_writefield(&OpenPIC->Global.Global_Configuration1,
+			OPENPIC_EICR_S_CLK_MASK, (clkval << 28));
 }
-#endif
 
-#ifdef CONFIG_EPIC_SERIAL_MODE
-static void openpic_enable_sie(void)
+static void __init openpic_enable_sie(void)
 {
 	openpic_setfield(&OpenPIC->Global.Global_Configuration1,
-			 OPENPIC_EICR_SIE);
+			OPENPIC_EICR_SIE);
 }
+#endif
 
-static void openpic_eicr_set_clk(u_int clkval)
+#if defined(CONFIG_EPIC_SERIAL_MODE) || defined(CONFIG_PMAC_PBOOK)
+static void openpic_reset(void)
 {
-	openpic_writefield(&OpenPIC->Global.Global_Configuration1,
-			 OPENPIC_EICR_S_CLK_MASK, (clkval << 28));
+	openpic_setfield(&OpenPIC->Global.Global_Configuration0,
+			 OPENPIC_CONFIG_RESET);
+	while (openpic_readfield(&OpenPIC->Global.Global_Configuration0,
+				 OPENPIC_CONFIG_RESET))
+		mb();
 }
 #endif
 
-void openpic_set_sources(int first_irq, int num_irqs, void *first_ISR)
+void __init openpic_set_sources(int first_irq, int num_irqs, void *first_ISR)
 {
 	volatile OpenPIC_Source *src = first_ISR;
 	int i, last_irq;
@@ -300,7 +301,14 @@
 		ISR[i] = src;
 }
 
-void __init openpic_init(int linux_irq_offset)
+/*
+ * The `offset' parameter defines where the interrupts handled by the
+ * OpenPIC start in the space of interrupt numbers that the kernel knows
+ * about.  In other words, the OpenPIC's IRQ0 is numbered `offset' in the
+ * kernel's interrupt numbering scheme.
+ * We assume there is only one OpenPIC.
+ */
+void __init openpic_init(int offset)
 {
 	u_int t, i;
 	u_int timerfreq;
@@ -349,13 +357,13 @@
 		printk("OpenPIC timer frequency is %d.%06d MHz\n",
 		       timerfreq / 1000000, timerfreq % 1000000);
 
-	open_pic_irq_offset = linux_irq_offset;
+	open_pic_irq_offset = offset;
 
 	/* Initialize timer interrupts */
 	if ( ppc_md.progress ) ppc_md.progress("openpic: timer",0x3ba);
 	for (i = 0; i < OPENPIC_NUM_TIMERS; i++) {
 		/* Disabled, Priority 0 */
-		openpic_inittimer(i, 0, OPENPIC_VEC_TIMER+i+linux_irq_offset);
+		openpic_inittimer(i, 0, OPENPIC_VEC_TIMER+i+offset);
 		/* No processor */
 		openpic_maptimer(i, 0);
 	}
@@ -365,12 +373,10 @@
 	if ( ppc_md.progress ) ppc_md.progress("openpic: ipi",0x3bb);
 	for (i = 0; i < OPENPIC_NUM_IPI; i++) {
 		/* Disabled, Priority 10..13 */
-		openpic_initipi(i, 10+i, OPENPIC_VEC_IPI+i+linux_irq_offset);
+		openpic_initipi(i, 10+i, OPENPIC_VEC_IPI+i+offset);
 		/* IPIs are per-CPU */
-		irq_desc[OPENPIC_VEC_IPI+i+linux_irq_offset].status |=
-			IRQ_PER_CPU;
-		irq_desc[OPENPIC_VEC_IPI+i+linux_irq_offset].handler =
-			&open_pic_ipi;
+		irq_desc[OPENPIC_VEC_IPI+i+offset].status |= IRQ_PER_CPU;
+		irq_desc[OPENPIC_VEC_IPI+i+offset].handler = &open_pic_ipi;
 	}
 #endif
 
@@ -387,40 +393,36 @@
 			continue;
 
 		/* the bootloader may have left it enabled (bad !) */
-		openpic_disable_irq(i+linux_irq_offset);
+		openpic_disable_irq(i+offset);
 
-		/*
-		 * We find the value from either the InitSenses table
-		 * or assume a negative polarity level interrupt.
-		 */
-		sense = (i < OpenPIC_NumInitSenses)? OpenPIC_InitSenses[i]: 1;
+		sense = (i < OpenPIC_NumInitSenses)? OpenPIC_InitSenses[i]: \
+				(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE);
 
-		if ((sense & IRQ_SENSE_MASK) == 1)
-			irq_desc[i+linux_irq_offset].status = IRQ_LEVEL;
+		if (sense & IRQ_SENSE_MASK)
+			irq_desc[i+offset].status = IRQ_LEVEL;
 
 		/* Enabled, Priority 8 */
-		openpic_initirq(i, 8, i + linux_irq_offset,
-				(sense & IRQ_POLARITY_MASK),
+		openpic_initirq(i, 8, i+offset, (sense & IRQ_POLARITY_MASK),
 				(sense & IRQ_SENSE_MASK));
 		/* Processor 0 */
 		openpic_mapirq(i, 1<<0, 0);
 	}
 
 	/* Init descriptors */
-	for (i = linux_irq_offset; i < NumSources + linux_irq_offset; i++)
+	for (i = offset; i < NumSources + offset; i++)
 		irq_desc[i].handler = &open_pic;
 
 	/* Initialize the spurious interrupt */
 	if (ppc_md.progress) ppc_md.progress("openpic: spurious",0x3bd);
-	openpic_set_spurious(OPENPIC_VEC_SPURIOUS+linux_irq_offset);
+	openpic_set_spurious(OPENPIC_VEC_SPURIOUS+offset);
 
 	/* Initialize the cascade */
-	if (linux_irq_offset) {
-		if (request_irq(linux_irq_offset, no_action, SA_INTERRUPT,
+	if (offset) {
+		if (request_irq(offset, no_action, SA_INTERRUPT,
 				"82c59 cascade", NULL))
 			printk("Unable to get OpenPIC IRQ 0 for cascade\n");
 	}
- 	openpic_disable_8259_pass_through();
+	openpic_disable_8259_pass_through();
 #ifdef CONFIG_EPIC_SERIAL_MODE
 	openpic_eicr_set_clk(7);	/* Slowest value until we know better */
 	openpic_enable_sie();
@@ -479,7 +481,7 @@
 }
 #endif /* notused */
 
-static void openpic_set_priority(u_int pri)
+static void __init openpic_set_priority(u_int pri)
 {
 	DECL_THIS_CPU;
 
@@ -656,29 +658,18 @@
 }
 
 /*
- * Initalize the interrupt source which will generate an NMI (and disable it).
+ * Initalize the interrupt source which will generate an NMI.
+ * This raises the interrupt's priority from 8 to 9.
  *
  * irq: The logical IRQ which generates an NMI.
  */
 void __init
 openpic_init_nmi_irq(u_int irq)
 {
-	int sense;
-
-	/* If this wasn't given, assume a level, negative polarity interrupt. */
-	sense = (irq < OpenPIC_NumInitSenses) ? OpenPIC_InitSenses[irq] :
-		(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE);
-
-	openpic_safe_writefield(&ISR[irq]->Vector_Priority,
-				OPENPIC_PRIORITY_MASK | OPENPIC_VECTOR_MASK |
-				OPENPIC_SENSE_MASK | OPENPIC_POLARITY_MASK,
-				(9 << OPENPIC_PRIORITY_SHIFT) |
-				(irq + open_pic_irq_offset) |
-				((sense & IRQ_POLARITY_MASK) ?
-				 OPENPIC_POLARITY_POSITIVE :
-				 OPENPIC_POLARITY_NEGATIVE) |
-				((sense & IRQ_SENSE_MASK) ? OPENPIC_SENSE_LEVEL
-				 : OPENPIC_SENSE_EDGE));
+	check_arg_irq(irq);
+	openpic_safe_writefield(&ISR[irq - open_pic_irq_offset]->Vector_Priority,
+				OPENPIC_PRIORITY_MASK,
+				9 << OPENPIC_PRIORITY_SHIFT);
 }
 
 /*
@@ -752,7 +743,8 @@
  *  pol: polarity (1 for positive, 0 for negative)
  *  sense: 1 for level, 0 for edge
  */
-static void openpic_initirq(u_int irq, u_int pri, u_int vec, int pol, int sense)
+static void __init
+openpic_initirq(u_int irq, u_int pri, u_int vec, int pol, int sense)
 {
 	openpic_safe_writefield(&ISR[irq]->Vector_Priority,
 				OPENPIC_PRIORITY_MASK | OPENPIC_VECTOR_MASK |
diff -Nru a/arch/ppc64/mm/init.c b/arch/ppc64/mm/init.c
--- a/arch/ppc64/mm/init.c	Fri Jun  6 18:19:27 2003
+++ b/arch/ppc64/mm/init.c	Wed Jul  2 21:20:53 2003
@@ -109,7 +109,7 @@
 	show_free_areas();
 	printk("Free swap:       %6dkB\n",nr_swap_pages<<(PAGE_SHIFT-10));
 	for_each_pgdat(pgdat) {
-		for (i = 0; i < pgdat->node_size; i++) {
+		for (i = 0; i < pgdat->node_spanned_pages; i++) {
 			page = pgdat->node_mem_map + i;
 			total++;
 			if (PageReserved(page))
@@ -564,7 +564,7 @@
 	int nid;
 
         for (nid = 0; nid < numnodes; nid++) {
-		if (node_data[nid].node_size != 0) {
+		if (node_data[nid].node_spanned_pages != 0) {
 			printk("freeing bootmem node %x\n", nid);
 			totalram_pages +=
 				free_all_bootmem_node(NODE_DATA(nid));
diff -Nru a/arch/ppc64/mm/numa.c b/arch/ppc64/mm/numa.c
--- a/arch/ppc64/mm/numa.c	Sat Jun  7 13:07:24 2003
+++ b/arch/ppc64/mm/numa.c	Wed Jul  2 21:20:53 2003
@@ -160,21 +160,21 @@
 		 * this simple case and complain if there is a gap in
 		 * memory
 		 */
-		if (node_data[numa_domain].node_size) {
+		if (node_data[numa_domain].node_spanned_pages) {
 			unsigned long shouldstart =
 				node_data[numa_domain].node_start_pfn + 
-				node_data[numa_domain].node_size;
+				node_data[numa_domain].node_spanned_pages;
 			if (shouldstart != (start / PAGE_SIZE)) {
 				printk(KERN_ERR "Hole in node, disabling "
 						"region start %lx length %lx\n",
 						start, size);
 				continue;
 			}
-			node_data[numa_domain].node_size += size / PAGE_SIZE;
+			node_data[numa_domain].node_spanned_pages += size / PAGE_SIZE;
 		} else {
 			node_data[numa_domain].node_start_pfn =
 				start / PAGE_SIZE;
-			node_data[numa_domain].node_size = size / PAGE_SIZE;
+			node_data[numa_domain].node_spanned_pages = size / PAGE_SIZE;
 		}
 
 		for (i = start ; i < (start+size); i += MEMORY_INCREMENT)
@@ -202,7 +202,7 @@
 		map_cpu_to_node(i, 0);
 
 	node_data[0].node_start_pfn = 0;
-	node_data[0].node_size = lmb_end_of_DRAM() / PAGE_SIZE;
+	node_data[0].node_spanned_pages = lmb_end_of_DRAM() / PAGE_SIZE;
 
 	for (i = 0 ; i < lmb_end_of_DRAM(); i += MEMORY_INCREMENT)
 		numa_memory_lookup_table[i >> MEMORY_INCREMENT_SHIFT] = 0;
@@ -224,12 +224,12 @@
 		unsigned long bootmem_paddr;
 		unsigned long bootmap_pages;
 
-		if (node_data[nid].node_size == 0)
+		if (node_data[nid].node_spanned_pages == 0)
 			continue;
 
 		start_paddr = node_data[nid].node_start_pfn * PAGE_SIZE;
 		end_paddr = start_paddr + 
-				(node_data[nid].node_size * PAGE_SIZE);
+				(node_data[nid].node_spanned_pages * PAGE_SIZE);
 
 		dbg("node %d\n", nid);
 		dbg("start_paddr = %lx\n", start_paddr);
@@ -311,7 +311,7 @@
 		unsigned long start_pfn;
 		unsigned long end_pfn;
 
-		if (node_data[nid].node_size == 0)
+		if (node_data[nid].node_spanned_pages == 0)
 			continue;
 
 		start_pfn = plat_node_bdata[nid].node_boot_start >> PAGE_SHIFT;
diff -Nru a/arch/s390/kernel/compat_exec.c b/arch/s390/kernel/compat_exec.c
--- a/arch/s390/kernel/compat_exec.c	Wed May 14 23:43:46 2003
+++ b/arch/s390/kernel/compat_exec.c	Wed Jul  2 21:22:38 2003
@@ -23,6 +23,7 @@
 #include <linux/spinlock.h>
 #include <linux/binfmts.h>
 #include <linux/module.h>
+#include <linux/security.h>
 
 #include <asm/uaccess.h>
 #include <asm/pgalloc.h>
@@ -55,7 +56,7 @@
 	if (!mpnt) 
 		return -ENOMEM; 
 	
-	if (!vm_enough_memory((STACK_TOP - (PAGE_MASK & (unsigned long) bprm->p))>>PAGE_SHIFT)) {
+	if (security_vm_enough_memory((STACK_TOP - (PAGE_MASK & (unsigned long) bprm->p))>>PAGE_SHIFT)) {
 		kmem_cache_free(vm_area_cachep, mpnt);
 		return -ENOMEM;
 	}
diff -Nru a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c
--- a/arch/s390/kernel/setup.c	Sun Apr 20 09:14:41 2003
+++ b/arch/s390/kernel/setup.c	Sun Jul  6 18:51:59 2003
@@ -107,7 +107,7 @@
         current->active_mm = &init_mm;
         if (current->mm)
                 BUG();
-        enter_lazy_tlb(&init_mm, current, nr);
+        enter_lazy_tlb(&init_mm, current);
 }
 
 /*
diff -Nru a/arch/sh/kernel/cpu/sh4/pci-sh7751.c b/arch/sh/kernel/cpu/sh4/pci-sh7751.c
--- a/arch/sh/kernel/cpu/sh4/pci-sh7751.c	Tue May  6 15:06:40 2003
+++ b/arch/sh/kernel/cpu/sh4/pci-sh7751.c	Thu Jul  3 08:08:45 2003
@@ -200,7 +200,7 @@
 		return;
 	PCIDBG(2,"PCI: Peer bridge fixup\n");
 	for (n=0; n <= pcibios_last_bus; n++) {
-		if (pci_bus_exists(&pci_root_buses, n))
+		if (pci_find_bus(0, n))
 			continue;
 		bus.number = n;
 		bus.ops = pci_root_ops;
diff -Nru a/arch/um/kernel/process_kern.c b/arch/um/kernel/process_kern.c
--- a/arch/um/kernel/process_kern.c	Wed Feb  5 20:16:02 2003
+++ b/arch/um/kernel/process_kern.c	Sun Jul  6 18:51:59 2003
@@ -113,8 +113,9 @@
 }
 
 void switch_mm(struct mm_struct *prev, struct mm_struct *next, 
-	       struct task_struct *tsk, unsigned cpu)
+	       struct task_struct *tsk)
 {
+	unsigned cpu = smp_processor_id();
 	if (prev != next) 
 		clear_bit(cpu, &prev->cpu_vm_mask);
 	set_bit(cpu, &next->cpu_vm_mask);
diff -Nru a/arch/x86_64/ia32/ia32_binfmt.c b/arch/x86_64/ia32/ia32_binfmt.c
--- a/arch/x86_64/ia32/ia32_binfmt.c	Thu Jun 26 02:32:32 2003
+++ b/arch/x86_64/ia32/ia32_binfmt.c	Wed Jul  2 21:22:38 2003
@@ -14,6 +14,8 @@
 #include <linux/string.h>
 #include <linux/binfmts.h>
 #include <linux/mm.h>
+#include <linux/security.h>
+
 #include <asm/segment.h> 
 #include <asm/ptrace.h>
 #include <asm/processor.h>
@@ -339,7 +341,7 @@
 	if (!mpnt) 
 		return -ENOMEM; 
 	
-	if (!vm_enough_memory((IA32_STACK_TOP - (PAGE_MASK & (unsigned long) bprm->p))>>PAGE_SHIFT)) {
+	if (security_vm_enough_memory((IA32_STACK_TOP - (PAGE_MASK & (unsigned long) bprm->p))>>PAGE_SHIFT)) {
 		kmem_cache_free(vm_area_cachep, mpnt);
 		return -ENOMEM;
 	}
diff -Nru a/arch/x86_64/kernel/setup64.c b/arch/x86_64/kernel/setup64.c
--- a/arch/x86_64/kernel/setup64.c	Fri May 23 03:22:07 2003
+++ b/arch/x86_64/kernel/setup64.c	Sun Jul  6 18:51:59 2003
@@ -288,7 +288,7 @@
 	me->active_mm = &init_mm;
 	if (me->mm)
 		BUG();
-	enter_lazy_tlb(&init_mm, me, cpu);
+	enter_lazy_tlb(&init_mm, me);
 
 	set_tss_desc(cpu, t);
 	load_TR_desc();
diff -Nru a/arch/x86_64/mm/init.c b/arch/x86_64/mm/init.c
--- a/arch/x86_64/mm/init.c	Sun Jun 15 07:12:07 2003
+++ b/arch/x86_64/mm/init.c	Wed Jul  2 21:20:53 2003
@@ -64,7 +64,7 @@
 	printk("Free swap:       %6dkB\n",nr_swap_pages<<(PAGE_SHIFT-10));
 
 	for_each_pgdat(pgdat) {
-               for (i = 0; i < pgdat->node_size; ++i) {
+               for (i = 0; i < pgdat->node_spanned_pages; ++i) {
                        page = pgdat->node_mem_map + i;
 		total++;
                        if (PageReserved(page))
diff -Nru a/arch/x86_64/mm/numa.c b/arch/x86_64/mm/numa.c
--- a/arch/x86_64/mm/numa.c	Fri May 23 03:22:07 2003
+++ b/arch/x86_64/mm/numa.c	Wed Jul  2 21:20:53 2003
@@ -86,7 +86,7 @@
 	memset(NODE_DATA(nodeid), 0, sizeof(pg_data_t));
 	NODE_DATA(nodeid)->bdata = &plat_node_bdata[nodeid];
 	NODE_DATA(nodeid)->node_start_pfn = start_pfn;
-	NODE_DATA(nodeid)->node_size = end_pfn - start_pfn;
+	NODE_DATA(nodeid)->node_spanned_pages = end_pfn - start_pfn;
 
 	/* Find a place for the bootmem map */
 	bootmap_pages = bootmem_bootmap_pages(end_pfn - start_pfn); 
diff -Nru a/drivers/base/class.c b/drivers/base/class.c
--- a/drivers/base/class.c	Wed Jun 11 15:40:05 2003
+++ b/drivers/base/class.c	Thu Jul  3 17:51:00 2003
@@ -3,6 +3,8 @@
  *
  * Copyright (c) 2002-3 Patrick Mochel
  * Copyright (c) 2002-3 Open Source Development Labs
+ * Copyright (c) 2003 Greg Kroah-Hartman
+ * Copyright (c) 2003 IBM Corp.
  * 
  * This file is released under the GPLv2
  *
@@ -337,6 +339,24 @@
 		 class_dev->class_id);
 	class_device_del(class_dev);
 	class_device_put(class_dev);
+}
+
+int class_device_rename(struct class_device *class_dev, char *new_name)
+{
+	class_dev = class_device_get(class_dev);
+	if (!class_dev)
+		return -EINVAL;
+
+	pr_debug("CLASS: renaming '%s' to '%s'\n", class_dev->class_id,
+		 new_name);
+
+	strlcpy(class_dev->class_id, new_name, KOBJ_NAME_LEN);
+
+	kobject_rename(&class_dev->kobj, new_name);
+
+	class_device_put(class_dev);
+
+	return 0;
 }
 
 struct class_device * class_device_get(struct class_device *class_dev)
diff -Nru a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c
--- a/drivers/base/firmware_class.c	Tue Jun 17 02:10:01 2003
+++ b/drivers/base/firmware_class.c	Thu Jul  3 14:02:41 2003
@@ -149,7 +149,7 @@
 	if (offset + count > fw->size)
 		count = fw->size - offset;
 
-	memcpy(buffer, fw->data + offset, count);
+	memcpy(buffer + offset, fw->data + offset, count);
 	return count;
 }
 static int
@@ -198,7 +198,7 @@
 	if (retval)
 		return retval;
 
-	memcpy(fw->data + offset, buffer, count);
+	memcpy(fw->data + offset, buffer + offset, count);
 
 	fw->size = max_t(size_t, offset + count, fw->size);
 
diff -Nru a/drivers/block/Makefile b/drivers/block/Makefile
--- a/drivers/block/Makefile	Sun Apr 20 16:21:17 2003
+++ b/drivers/block/Makefile	Fri Jul  4 23:52:37 2003
@@ -8,7 +8,13 @@
 # In the future, some of these should be built conditionally.
 #
 
-obj-y	:= elevator.o ll_rw_blk.o ioctl.o genhd.o scsi_ioctl.o deadline-iosched.o
+#
+# NOTE that ll_rw_blk.c must come early in linkage order - it starts the
+# kblockd threads
+#
+
+obj-y	:= elevator.o ll_rw_blk.o ioctl.o genhd.o scsi_ioctl.o \
+	deadline-iosched.o as-iosched.o
 
 obj-$(CONFIG_MAC_FLOPPY)	+= swim3.o
 obj-$(CONFIG_BLK_DEV_FD)	+= floppy.o
diff -Nru a/drivers/block/as-iosched.c b/drivers/block/as-iosched.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/block/as-iosched.c	Fri Jul  4 23:52:51 2003
@@ -0,0 +1,1837 @@
+/*
+ *  linux/drivers/block/as-iosched.c
+ *
+ *  Anticipatory & deadline i/o scheduler.
+ *
+ *  Copyright (C) 2002 Jens Axboe <axboe@suse.de>
+ *                     Nick Piggin <piggin@cyberone.com.au>
+ *
+ */
+#include <linux/kernel.h>
+#include <linux/fs.h>
+#include <linux/blkdev.h>
+#include <linux/elevator.h>
+#include <linux/bio.h>
+#include <linux/blk.h>
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/compiler.h>
+#include <linux/hash.h>
+#include <linux/rbtree.h>
+#include <linux/interrupt.h>
+
+#define REQ_SYNC	1
+#define REQ_ASYNC	0
+
+/*
+ * See Documentation/as-iosched.txt
+ */
+
+/*
+ * max time before a read is submitted.
+ */
+#define default_read_expire (HZ / 20)
+
+/*
+ * ditto for writes, these limits are not hard, even
+ * if the disk is capable of satisfying them.
+ */
+#define default_write_expire (HZ / 5)
+
+/*
+ * read_batch_expire describes how long we will allow a stream of reads to
+ * persist before looking to see whether it is time to switch over to writes.
+ */
+#define default_read_batch_expire (HZ / 5)
+
+/*
+ * write_batch_expire describes how long we want a stream of writes to run for.
+ * This is not a hard limit, but a target we set for the auto-tuning thingy.
+ * See, the problem is: we can send a lot of writes to disk cache / TCQ in
+ * a short amount of time...
+ */
+#define default_write_batch_expire (HZ / 20)
+
+/*
+ * max time we may wait to anticipate a read (default around 6ms)
+ */
+#define default_antic_expire ((HZ / 150) ? HZ / 150 : 1)
+
+/*
+ * Keep track of up to 20ms thinktimes. We can go as big as we like here,
+ * however huge values tend to interfere and not decay fast enough. A program
+ * might be in a non-io phase of operation. Waiting on user input for example,
+ * or doing a lengthy computation. A small penalty can be justified there, and
+ * will still catch out those processes that constantly have large thinktimes.
+ */
+#define MAX_THINKTIME (HZ/50UL)
+
+/* Bits in as_io_context.state */
+enum as_io_states {
+	AS_TASK_RUNNING=0,	/* Process has not exitted */
+	AS_TASK_IORUNNING,	/* Process has completed some IO */
+};
+
+enum anticipation_status {
+	ANTIC_OFF=0,		/* Not anticipating (normal operation)	*/
+	ANTIC_WAIT_REQ,		/* The last read has not yet completed  */
+	ANTIC_WAIT_NEXT,	/* Currently anticipating a request vs
+				   last read (which has completed) */
+	ANTIC_FINISHED,		/* Anticipating but have found a candidate
+				 * or timed out */
+};
+
+struct as_data {
+	/*
+	 * run time data
+	 */
+
+	struct request_queue *q;	/* the "owner" queue */
+
+	/*
+	 * requests (as_rq s) are present on both sort_list and fifo_list
+	 */
+	struct rb_root sort_list[2];
+	struct list_head fifo_list[2];
+
+	struct as_rq *next_arq[2];	/* next in sort order */
+	sector_t last_sector[2];	/* last REQ_SYNC & REQ_ASYNC sectors */
+	struct list_head *dispatch;	/* driver dispatch queue */
+	struct list_head *hash;		/* request hash */
+	unsigned long hash_valid_count;	/* barrier hash count */
+	unsigned long current_batch_expires;
+	unsigned long last_check_fifo[2];
+	int changed_batch;
+	int batch_data_dir;		/* current batch REQ_SYNC / REQ_ASYNC */
+	int write_batch_count;		/* max # of reqs in a write batch */
+	int current_write_count;	/* how many requests left this batch */
+	int write_batch_idled;		/* has the write batch gone idle? */
+	mempool_t *arq_pool;
+
+	enum anticipation_status antic_status;
+	unsigned long antic_start;	/* jiffies: when it started */
+	struct timer_list antic_timer;	/* anticipatory scheduling timer */
+	struct work_struct antic_work;	/* Deferred unplugging */
+	struct io_context *io_context;	/* Identify the expected process */
+	int ioc_finished; /* IO associated with io_context is finished */
+	int nr_dispatched;
+
+	/*
+	 * settings that change how the i/o scheduler behaves
+	 */
+	unsigned long fifo_expire[2];
+	unsigned long batch_expire[2];
+	unsigned long antic_expire;
+};
+
+#define list_entry_fifo(ptr)	list_entry((ptr), struct as_rq, fifo)
+
+/*
+ * per-request data.
+ */
+enum arq_state {
+	AS_RQ_NEW=0,		/* New - not referenced and not on any lists */
+	AS_RQ_QUEUED,		/* In the request queue. It belongs to the
+				   scheduler */
+	AS_RQ_DISPATCHED,	/* On the dispatch list. It belongs to the
+				   driver now */
+};
+
+struct as_rq {
+	/*
+	 * rbtree index, key is the starting offset
+	 */
+	struct rb_node rb_node;
+	sector_t rb_key;
+
+	struct request *request;
+
+	struct io_context *io_context;	/* The submitting task */
+
+	/*
+	 * request hash, key is the ending offset (for back merge lookup)
+	 */
+	struct list_head hash;
+	unsigned long hash_valid_count;
+
+	/*
+	 * expire fifo
+	 */
+	struct list_head fifo;
+	unsigned long expires;
+
+	int is_sync;
+	enum arq_state state; /* debug only */
+};
+
+#define RQ_DATA(rq)	((struct as_rq *) (rq)->elevator_private)
+
+static kmem_cache_t *arq_pool;
+
+/*
+ * IO Context helper functions
+ */
+/* Debug */
+static atomic_t nr_as_io_requests = ATOMIC_INIT(0);
+
+/* Called to deallocate the as_io_context */
+static void free_as_io_context(struct as_io_context *aic)
+{
+	atomic_dec(&nr_as_io_requests);
+	kfree(aic);
+}
+
+/* Called when the task exits */
+static void exit_as_io_context(struct as_io_context *aic)
+{
+	clear_bit(AS_TASK_RUNNING, &aic->state);
+}
+
+static struct as_io_context *alloc_as_io_context(void)
+{
+	struct as_io_context *ret;
+
+	ret = kmalloc(sizeof(*ret), GFP_ATOMIC);
+	if (ret) {
+		atomic_inc(&nr_as_io_requests);
+		ret->dtor = free_as_io_context;
+		ret->exit = exit_as_io_context;
+		ret->state = 1 << AS_TASK_RUNNING;
+		atomic_set(&ret->nr_queued, 0);
+		atomic_set(&ret->nr_dispatched, 0);
+		spin_lock_init(&ret->lock);
+		ret->ttime_total = 0;
+		ret->ttime_samples = 0;
+		ret->ttime_mean = 0;
+		ret->seek_total = 0;
+		ret->seek_samples = 0;
+		ret->seek_mean = 0;
+	}
+
+	return ret;
+}
+
+/*
+ * If the current task has no AS IO context then create one and initialise it.
+ * Then take a ref on the task's io context and return it.
+ */
+static struct io_context *as_get_io_context(void)
+{
+	struct io_context *ioc = get_io_context(GFP_ATOMIC);
+	if (ioc && !ioc->aic) {
+		ioc->aic = alloc_as_io_context();
+		if (!ioc->aic) {
+			put_io_context(ioc);
+			ioc = NULL;
+		}
+	}
+	return ioc;
+}
+
+/*
+ * the back merge hash support functions
+ */
+static const int as_hash_shift = 6;
+#define AS_HASH_BLOCK(sec)	((sec) >> 3)
+#define AS_HASH_FN(sec)		(hash_long(AS_HASH_BLOCK((sec)), as_hash_shift))
+#define AS_HASH_ENTRIES		(1 << as_hash_shift)
+#define rq_hash_key(rq)		((rq)->sector + (rq)->nr_sectors)
+#define list_entry_hash(ptr)	list_entry((ptr), struct as_rq, hash)
+#define ON_HASH(arq)		(arq)->hash_valid_count
+
+#define AS_INVALIDATE_HASH(ad)				\
+	do {						\
+		if (!++(ad)->hash_valid_count)		\
+			(ad)->hash_valid_count = 1;	\
+	} while (0)
+
+static inline void __as_del_arq_hash(struct as_rq *arq)
+{
+	arq->hash_valid_count = 0;
+	list_del_init(&arq->hash);
+}
+
+static inline void as_del_arq_hash(struct as_rq *arq)
+{
+	if (ON_HASH(arq))
+		__as_del_arq_hash(arq);
+}
+
+static void as_remove_merge_hints(request_queue_t *q, struct as_rq *arq)
+{
+	as_del_arq_hash(arq);
+
+	if (q->last_merge == &arq->request->queuelist)
+		q->last_merge = NULL;
+}
+
+static void as_add_arq_hash(struct as_data *ad, struct as_rq *arq)
+{
+	struct request *rq = arq->request;
+
+	BUG_ON(ON_HASH(arq));
+
+	arq->hash_valid_count = ad->hash_valid_count;
+	list_add(&arq->hash, &ad->hash[AS_HASH_FN(rq_hash_key(rq))]);
+}
+
+/*
+ * move hot entry to front of chain
+ */
+static inline void as_hot_arq_hash(struct as_data *ad, struct as_rq *arq)
+{
+	struct request *rq = arq->request;
+	struct list_head *head = &ad->hash[AS_HASH_FN(rq_hash_key(rq))];
+
+	if (!ON_HASH(arq)) {
+		WARN_ON(1);
+		return;
+	}
+
+	if (arq->hash.prev != head) {
+		list_del(&arq->hash);
+		list_add(&arq->hash, head);
+	}
+}
+
+static struct request *as_find_arq_hash(struct as_data *ad, sector_t offset)
+{
+	struct list_head *hash_list = &ad->hash[AS_HASH_FN(offset)];
+	struct list_head *entry, *next = hash_list->next;
+
+	while ((entry = next) != hash_list) {
+		struct as_rq *arq = list_entry_hash(entry);
+		struct request *__rq = arq->request;
+
+		next = entry->next;
+
+		BUG_ON(!ON_HASH(arq));
+
+		if (!rq_mergeable(__rq)
+		    || arq->hash_valid_count != ad->hash_valid_count) {
+			__as_del_arq_hash(arq);
+			continue;
+		}
+
+		if (rq_hash_key(__rq) == offset)
+			return __rq;
+	}
+
+	return NULL;
+}
+
+/*
+ * rb tree support functions
+ */
+#define RB_NONE		(2)
+#define RB_EMPTY(root)	((root)->rb_node == NULL)
+#define ON_RB(node)	((node)->rb_color != RB_NONE)
+#define RB_CLEAR(node)	((node)->rb_color = RB_NONE)
+#define rb_entry_arq(node)	rb_entry((node), struct as_rq, rb_node)
+#define ARQ_RB_ROOT(ad, arq)	(&(ad)->sort_list[(arq)->is_sync])
+#define rq_rb_key(rq)		(rq)->sector
+
+/*
+ * as_find_first_arq finds the first (lowest sector numbered) request
+ * for the specified data_dir. Used to sweep back to the start of the disk
+ * (1-way elevator) after we process the last (highest sector) request.
+ */
+static struct as_rq *as_find_first_arq(struct as_data *ad, int data_dir)
+{
+	struct rb_node *n = ad->sort_list[data_dir].rb_node;
+
+	if (n == NULL)
+		return NULL;
+
+	for (;;) {
+		if (n->rb_left == NULL)
+			return rb_entry_arq(n);
+
+		n = n->rb_left;
+	}
+}
+
+static struct as_rq *__as_add_arq_rb(struct as_data *ad, struct as_rq *arq)
+{
+	struct rb_node **p = &ARQ_RB_ROOT(ad, arq)->rb_node;
+	struct rb_node *parent = NULL;
+	struct as_rq *__arq;
+
+	while (*p) {
+		parent = *p;
+		__arq = rb_entry_arq(parent);
+
+		if (arq->rb_key < __arq->rb_key)
+			p = &(*p)->rb_left;
+		else if (arq->rb_key > __arq->rb_key)
+			p = &(*p)->rb_right;
+		else
+			return __arq;
+	}
+
+	rb_link_node(&arq->rb_node, parent, p);
+	return 0;
+}
+
+static void as_move_to_dispatch(struct as_data *ad, struct as_rq *arq);
+/*
+ * Add the request to the rb tree if it is unique.  If there is an alias (an
+ * existing request against the same sector), which can happen when using
+ * direct IO, then move the alias to the dispatch list and then add the
+ * request.
+ */
+static void as_add_arq_rb(struct as_data *ad, struct as_rq *arq)
+{
+	struct as_rq *alias;
+	struct request *rq = arq->request;
+
+	arq->rb_key = rq_rb_key(rq);
+
+	/* This can be caused by direct IO */
+	while ((alias = __as_add_arq_rb(ad, arq)))
+		as_move_to_dispatch(ad, alias);
+
+	rb_insert_color(&arq->rb_node, ARQ_RB_ROOT(ad, arq));
+}
+
+static inline void as_del_arq_rb(struct as_data *ad, struct as_rq *arq)
+{
+	if (!ON_RB(&arq->rb_node)) {
+		WARN_ON(1);
+		return;
+	}
+
+	rb_erase(&arq->rb_node, ARQ_RB_ROOT(ad, arq));
+	RB_CLEAR(&arq->rb_node);
+}
+
+static struct request *
+as_find_arq_rb(struct as_data *ad, sector_t sector, int data_dir)
+{
+	struct rb_node *n = ad->sort_list[data_dir].rb_node;
+	struct as_rq *arq;
+
+	while (n) {
+		arq = rb_entry_arq(n);
+
+		if (sector < arq->rb_key)
+			n = n->rb_left;
+		else if (sector > arq->rb_key)
+			n = n->rb_right;
+		else
+			return arq->request;
+	}
+
+	return NULL;
+}
+
+/*
+ * IO Scheduler proper
+ */
+
+#define MAXBACK (1024 * 1024)	/*
+				 * Maximum distance the disk will go backward
+				 * for a request.
+				 */
+
+/*
+ * as_choose_req selects the preferred one of two requests of the same data_dir
+ * ignoring time - eg. timeouts, which is the job of as_dispatch_request
+ */
+static struct as_rq *
+as_choose_req(struct as_data *ad, struct as_rq *arq1, struct as_rq *arq2)
+{
+	int data_dir;
+	sector_t last, s1, s2, d1, d2;
+	int r1_wrap=0, r2_wrap=0;	/* requests are behind the disk head */
+	const sector_t maxback = MAXBACK;
+
+	if (arq1 == NULL || arq1 == arq2)
+		return arq2;
+	if (arq2 == NULL)
+		return arq1;
+
+	data_dir = arq1->is_sync;
+
+	last = ad->last_sector[data_dir];
+	s1 = arq1->request->sector;
+	s2 = arq2->request->sector;
+
+	BUG_ON(data_dir != arq2->is_sync);
+
+	/*
+	 * Strict one way elevator _except_ in the case where we allow
+	 * short backward seeks which are biased as twice the cost of a
+	 * similar forward seek.
+	 */
+	if (s1 >= last)
+		d1 = s1 - last;
+	else if (s1+maxback >= last)
+		d1 = (last - s1)*2;
+	else {
+		r1_wrap = 1;
+		d1 = 0; /* shut up, gcc */
+	}
+
+	if (s2 >= last)
+		d2 = s2 - last;
+	else if (s2+maxback >= last)
+		d2 = (last - s2)*2;
+	else {
+		r2_wrap = 1;
+		d2 = 0;
+	}
+
+	/* Found required data */
+	if (!r1_wrap && r2_wrap)
+		return arq1;
+	else if (!r2_wrap && r1_wrap)
+		return arq2;
+	else if (r1_wrap && r2_wrap) {
+		/* both behind the head */
+		if (s1 <= s2)
+			return arq1;
+		else
+			return arq2;
+	}
+
+	/* Both requests in front of the head */
+	if (d1 < d2)
+		return arq1;
+	else if (d2 < d1)
+		return arq2;
+	else {
+		if (s1 >= s2)
+			return arq1;
+		else
+			return arq2;
+	}
+}
+
+/*
+ * as_find_next_arq finds the next request after @prev in elevator order.
+ * this with as_choose_req form the basis for how the scheduler chooses
+ * what request to process next. Anticipation works on top of this.
+ */
+static struct as_rq *as_find_next_arq(struct as_data *ad, struct as_rq *last)
+{
+	const int data_dir = last->is_sync;
+	struct as_rq *ret;
+	struct rb_node *rbnext = rb_next(&last->rb_node);
+	struct rb_node *rbprev = rb_prev(&last->rb_node);
+	struct as_rq *arq_next, *arq_prev;
+
+	BUG_ON(!ON_RB(&last->rb_node));
+
+	if (rbprev)
+		arq_prev = rb_entry_arq(rbprev);
+	else
+		arq_prev = NULL;
+
+	if (rbnext)
+		arq_next = rb_entry_arq(rbnext);
+	else {
+		arq_next = as_find_first_arq(ad, data_dir);
+		if (arq_next == last)
+			arq_next = NULL;
+	}
+
+	ret = as_choose_req(ad,	arq_next, arq_prev);
+
+	return ret;
+}
+
+/*
+ * anticipatory scheduling functions follow
+ */
+
+/*
+ * as_antic_expired tells us when we have anticipated too long.
+ * The funny "absolute difference" math on the elapsed time is to handle
+ * jiffy wraps, and disks which have been idle for 0x80000000 jiffies.
+ */
+static int as_antic_expired(struct as_data *ad)
+{
+	long delta_jif;
+
+	delta_jif = jiffies - ad->antic_start;
+	if (unlikely(delta_jif < 0))
+		delta_jif = -delta_jif;
+	if (delta_jif < ad->antic_expire)
+		return 0;
+
+	return 1;
+}
+
+/*
+ * as_antic_waitnext starts anticipating that a nice request will soon be
+ * submitted. See also as_antic_waitreq
+ */
+static void as_antic_waitnext(struct as_data *ad)
+{
+	unsigned long timeout;
+
+	BUG_ON(ad->antic_status != ANTIC_OFF
+			&& ad->antic_status != ANTIC_WAIT_REQ);
+
+	timeout = ad->antic_start + ad->antic_expire;
+
+	mod_timer(&ad->antic_timer, timeout);
+
+	ad->antic_status = ANTIC_WAIT_NEXT;
+}
+
+/*
+ * as_antic_waitreq starts anticipating. We don't start timing the anticipation
+ * until the request that we're anticipating on has finished. This means we
+ * are timing from when the candidate process wakes up hopefully.
+ */
+static void as_antic_waitreq(struct as_data *ad)
+{
+	BUG_ON(ad->antic_status == ANTIC_FINISHED);
+	if (ad->antic_status == ANTIC_OFF) {
+		if (!ad->io_context || ad->ioc_finished)
+			as_antic_waitnext(ad);
+		else
+			ad->antic_status = ANTIC_WAIT_REQ;
+	}
+}
+
+/*
+ * This is called directly by the functions in this file to stop anticipation.
+ * We kill the timer and schedule a call to the request_fn asap.
+ */
+static void as_antic_stop(struct as_data *ad)
+{
+	int status = ad->antic_status;
+
+	if (status == ANTIC_WAIT_REQ || status == ANTIC_WAIT_NEXT) {
+		if (status == ANTIC_WAIT_NEXT)
+			del_timer(&ad->antic_timer);
+		ad->antic_status = ANTIC_FINISHED;
+		/* see as_work_handler */
+		kblockd_schedule_work(&ad->antic_work);
+	}
+}
+
+/*
+ * as_antic_timeout is the timer function set by as_antic_waitnext.
+ */
+static void as_antic_timeout(unsigned long data)
+{
+	struct request_queue *q = (struct request_queue *)data;
+	struct as_data *ad = q->elevator.elevator_data;
+	unsigned long flags;
+
+	spin_lock_irqsave(q->queue_lock, flags);
+	if (ad->antic_status == ANTIC_WAIT_REQ
+			|| ad->antic_status == ANTIC_WAIT_NEXT) {
+		ad->antic_status = ANTIC_FINISHED;
+		kblockd_schedule_work(&ad->antic_work);
+	}
+	spin_unlock_irqrestore(q->queue_lock, flags);
+}
+
+/*
+ * as_close_req decides if one request is considered "close" to the
+ * previous one issued.
+ */
+static int as_close_req(struct as_data *ad, struct as_rq *arq)
+{
+	unsigned long delay;	/* milliseconds */
+	sector_t last = ad->last_sector[ad->batch_data_dir];
+	sector_t next = arq->request->sector;
+	sector_t delta;	/* acceptable close offset (in sectors) */
+
+	if (ad->antic_status == ANTIC_OFF || !ad->ioc_finished)
+		delay = 0;
+	else
+		delay = ((jiffies - ad->antic_start) * 1000) / HZ;
+
+	if (delay <= 1)
+		delta = 64;
+	else if (delay <= 20 && delay <= ad->antic_expire)
+		delta = 64 << (delay-1);
+	else
+		return 1;
+
+	return (last - (delta>>1) <= next) && (next <= last + delta);
+}
+
+/*
+ * as_can_break_anticipation returns true if we have been anticipating this
+ * request.
+ *
+ * It also returns true if the process against which we are anticipating
+ * submits a write - that's presumably an fsync, O_SYNC write, etc. We want to
+ * dispatch it ASAP, because we know that application will not be submitting
+ * any new reads.
+ *
+ * If the task which has submitted the request has exitted, break anticipation.
+ *
+ * If this task has queued some other IO, do not enter enticipation.
+ */
+static int as_can_break_anticipation(struct as_data *ad, struct as_rq *arq)
+{
+	struct io_context *ioc;
+	struct as_io_context *aic;
+
+	if (arq && arq->is_sync == REQ_SYNC && as_close_req(ad, arq)) {
+		/* close request */
+		return 1;
+	}
+
+	if (ad->ioc_finished && as_antic_expired(ad)) {
+		/*
+		 * In this situation status should really be FINISHED,
+		 * however the timer hasn't had the chance to run yet.
+		 */
+		return 1;
+	}
+
+	ioc = ad->io_context;
+	BUG_ON(!ioc);
+
+	if (arq && ioc == arq->io_context) {
+		/* request from same process */
+		return 1;
+	}
+
+	aic = ioc->aic;
+	if (!aic)
+		return 0;
+
+	if (!test_bit(AS_TASK_RUNNING, &aic->state)) {
+		/* process anticipated on has exitted */
+		return 1;
+	}
+
+	if (atomic_read(&aic->nr_queued) > 0) {
+		/* process has more requests queued */
+		return 1;
+	}
+
+	if (atomic_read(&aic->nr_dispatched) > 0) {
+		/* process has more requests dispatched */
+		return 1;
+	}
+
+	if (aic->ttime_mean > ad->antic_expire) {
+		/* the process thinks too much between requests */
+		return 1;
+	}
+
+	if (arq && aic->seek_samples) {
+		sector_t s;
+		if (ad->last_sector[REQ_SYNC] < arq->request->sector)
+			s = arq->request->sector - ad->last_sector[REQ_SYNC];
+		else
+			s = ad->last_sector[REQ_SYNC] - arq->request->sector;
+
+		if (aic->seek_mean > (s>>1)) {
+			/* this request is better than what we're expecting */
+			return 1;
+		}
+	}
+
+	return 0;
+}
+
+/*
+ * as_can_anticipate indicates weather we should either run arq
+ * or keep anticipating a better request.
+ */
+static int as_can_anticipate(struct as_data *ad, struct as_rq *arq)
+{
+	if (!ad->io_context)
+		/*
+		 * Last request submitted was a write
+		 */
+		return 0;
+
+	if (ad->antic_status == ANTIC_FINISHED)
+		/*
+		 * Don't restart if we have just finished. Run the next request
+		 */
+		return 0;
+
+	if (as_can_break_anticipation(ad, arq))
+		/*
+		 * This request is a good candidate. Don't keep anticipating,
+		 * run it.
+		 */
+		return 0;
+
+	/*
+	 * OK from here, we haven't finished, and don't have a decent request!
+	 * Status is either ANTIC_OFF so start waiting,
+	 * ANTIC_WAIT_REQ so continue waiting for request to finish
+	 * or ANTIC_WAIT_NEXT so continue waiting for an acceptable request.
+	 *
+	 */
+
+	return 1;
+}
+
+/*
+ * as_update_iohist keeps a decaying histogram of IO thinktimes, and
+ * updates @aic->ttime_mean based on that. It is called when a new
+ * request is queued.
+ */
+static void as_update_iohist(struct as_io_context *aic, struct request *rq)
+{
+	struct as_rq *arq = RQ_DATA(rq);
+	int data_dir = arq->is_sync;
+	unsigned long thinktime;
+	sector_t seek_dist;
+
+	if (aic == NULL)
+		return;
+
+	if (data_dir == REQ_SYNC) {
+		spin_lock(&aic->lock);
+
+		if (test_bit(AS_TASK_IORUNNING, &aic->state)
+				&& !atomic_read(&aic->nr_queued)
+				&& !atomic_read(&aic->nr_dispatched)) {
+			/* Calculate read -> read thinktime */
+			thinktime = jiffies - aic->last_end_request;
+			thinktime = min(thinktime, MAX_THINKTIME-1);
+			/* fixed point: 1.0 == 1<<8 */
+			aic->ttime_samples += 256;
+			aic->ttime_total += 256*thinktime;
+			if (aic->ttime_samples)
+				/* fixed point factor is cancelled here */
+				aic->ttime_mean = (aic->ttime_total + 128)
+							/ aic->ttime_samples;
+			aic->ttime_samples = (aic->ttime_samples>>1)
+						+ (aic->ttime_samples>>2);
+			aic->ttime_total = (aic->ttime_total>>1)
+						+ (aic->ttime_total>>2);
+		}
+
+		/* Calculate read -> read seek distance */
+		if (!aic->seek_samples)
+			seek_dist = 0;
+		else if (aic->last_request_pos < rq->sector)
+			seek_dist = rq->sector - aic->last_request_pos;
+		else
+			seek_dist = aic->last_request_pos - rq->sector;
+
+		aic->last_request_pos = rq->sector + rq->nr_sectors;
+
+		/*
+		 * Don't allow the seek distance to get too large from the
+		 * odd fragment, pagein, etc
+		 */
+		if (aic->seek_samples < 400) /* second&third seek */
+			seek_dist = min(seek_dist, (aic->seek_mean * 4)
+							+ 2*1024*1024);
+		else
+			seek_dist = min(seek_dist, (aic->seek_mean * 4)
+							+ 2*1024*64);
+
+		aic->seek_samples += 256;
+		aic->seek_total += 256*seek_dist;
+		if (aic->seek_samples) {
+			aic->seek_mean = aic->seek_total + 128;
+			do_div(aic->seek_mean, aic->seek_samples);
+		}
+		aic->seek_samples = (aic->seek_samples>>1)
+					+ (aic->seek_samples>>2);
+		aic->seek_total = (aic->seek_total>>1)
+					+ (aic->seek_total>>2);
+
+		spin_unlock(&aic->lock);
+	}
+}
+
+/*
+ * as_update_arq must be called whenever a request (arq) is added to
+ * the sort_list. This function keeps caches up to date, and checks if the
+ * request might be one we are "anticipating"
+ */
+static void as_update_arq(struct as_data *ad, struct as_rq *arq)
+{
+	const int data_dir = arq->is_sync;
+
+	/* keep the next_arq cache up to date */
+	ad->next_arq[data_dir] = as_choose_req(ad, arq, ad->next_arq[data_dir]);
+
+	/*
+	 * have we been anticipating this request?
+	 * or does it come from the same process as the one we are anticipating
+	 * for?
+	 */
+	if (ad->antic_status == ANTIC_WAIT_REQ
+			|| ad->antic_status == ANTIC_WAIT_NEXT) {
+		if (as_can_break_anticipation(ad, arq))
+			as_antic_stop(ad);
+	}
+}
+
+/*
+ * Gathers timings and resizes the write batch automatically
+ */
+void update_write_batch(struct as_data *ad)
+{
+	unsigned long batch = ad->batch_expire[REQ_ASYNC];
+	long write_time;
+
+	write_time = (jiffies - ad->current_batch_expires) + batch;
+	if (write_time < 0)
+		write_time = 0;
+
+	if (write_time > batch && !ad->write_batch_idled) {
+		if (write_time > batch * 3)
+			ad->write_batch_count /= 2;
+		else
+			ad->write_batch_count--;
+	} else if (write_time < batch && ad->current_write_count == 0) {
+		if (batch > write_time * 3)
+			ad->write_batch_count *= 2;
+		else
+			ad->write_batch_count++;
+	}
+
+	if (ad->write_batch_count < 1)
+		ad->write_batch_count = 1;
+}
+
+/*
+ * as_completed_request is to be called when a request has completed and
+ * returned something to the requesting process, be it an error or data.
+ */
+static void as_completed_request(request_queue_t *q, struct request *rq)
+{
+	struct as_data *ad = q->elevator.elevator_data;
+	struct as_rq *arq = RQ_DATA(rq);
+	struct as_io_context *aic;
+
+	if (unlikely(!blk_fs_request(rq)))
+		return;
+
+	WARN_ON(blk_fs_request(rq) && arq->state == AS_RQ_NEW);
+
+	if (arq->state != AS_RQ_DISPATCHED)
+		return;
+
+	if (ad->changed_batch && ad->nr_dispatched == 1) {
+		kblockd_schedule_work(&ad->antic_work);
+		ad->changed_batch = 2;
+	}
+	ad->nr_dispatched--;
+
+	/*
+	 * Start counting the batch from when a request of that direction is
+	 * actually serviced. This should help devices with big TCQ windows
+	 * and writeback caches
+	 */
+	if (ad->batch_data_dir == REQ_SYNC && ad->changed_batch
+			&& ad->batch_data_dir == arq->is_sync) {
+		update_write_batch(ad);
+		ad->current_batch_expires = jiffies +
+				ad->batch_expire[REQ_SYNC];
+		ad->changed_batch = 0;
+	}
+
+	if (!arq->io_context)
+		return;
+
+	if (ad->io_context == arq->io_context) {
+		ad->antic_start = jiffies;
+		ad->ioc_finished = 1;
+		if (ad->antic_status == ANTIC_WAIT_REQ) {
+			/*
+			 * We were waiting on this request, now anticipate
+			 * the next one
+			 */
+			as_antic_waitnext(ad);
+		}
+	}
+
+	aic = arq->io_context->aic;
+	if (!aic)
+		return;
+
+	spin_lock(&aic->lock);
+	if (arq->is_sync == REQ_SYNC) {
+		set_bit(AS_TASK_IORUNNING, &aic->state);
+		aic->last_end_request = jiffies;
+	}
+	spin_unlock(&aic->lock);
+
+	put_io_context(arq->io_context);
+}
+
+/*
+ * as_remove_queued_request removes a request from the pre dispatch queue
+ * without updating refcounts. It is expected the caller will drop the
+ * reference unless it replaces the request at somepart of the elevator
+ * (ie. the dispatch queue)
+ */
+static void as_remove_queued_request(request_queue_t *q, struct request *rq)
+{
+	struct as_rq *arq = RQ_DATA(rq);
+	const int data_dir = arq->is_sync;
+	struct as_data *ad = q->elevator.elevator_data;
+
+	WARN_ON(arq->state != AS_RQ_QUEUED);
+
+	if (arq->io_context && arq->io_context->aic) {
+		BUG_ON(!atomic_read(&arq->io_context->aic->nr_queued));
+		atomic_dec(&arq->io_context->aic->nr_queued);
+	}
+
+	/*
+	 * Update the "next_arq" cache if we are about to remove its
+	 * entry
+	 */
+	if (ad->next_arq[data_dir] == arq)
+		ad->next_arq[data_dir] = as_find_next_arq(ad, arq);
+
+	list_del_init(&arq->fifo);
+	as_remove_merge_hints(q, arq);
+	as_del_arq_rb(ad, arq);
+}
+
+/*
+ * as_remove_dispatched_request is called to remove a request which has gone
+ * to the dispatch list.
+ */
+static void as_remove_dispatched_request(request_queue_t *q, struct request *rq)
+{
+	struct as_rq *arq = RQ_DATA(rq);
+	struct as_io_context *aic;
+
+	if (!arq) {
+		WARN_ON(1);
+		return;
+	}
+
+	WARN_ON(arq->state != AS_RQ_DISPATCHED);
+	WARN_ON(ON_RB(&arq->rb_node));
+	if (arq->io_context && arq->io_context->aic) {
+		aic = arq->io_context->aic;
+		if (aic) {
+			WARN_ON(!atomic_read(&aic->nr_dispatched));
+			atomic_dec(&aic->nr_dispatched);
+		}
+	}
+}
+/*
+ * as_remove_request is called when a driver has finished with a request.
+ * This should be only called for dispatched requests, but for some reason
+ * a POWER4 box running hwscan it does not.
+ */
+static void as_remove_request(request_queue_t *q, struct request *rq)
+{
+	struct as_rq *arq = RQ_DATA(rq);
+
+	if (unlikely(!blk_fs_request(rq)))
+		return;
+
+	if (!arq) {
+		WARN_ON(1);
+		return;
+	}
+
+	if (ON_RB(&arq->rb_node))
+		as_remove_queued_request(q, rq);
+	else
+		as_remove_dispatched_request(q, rq);
+}
+
+/*
+ * as_fifo_expired returns 0 if there are no expired reads on the fifo,
+ * 1 otherwise.  It is ratelimited so that we only perform the check once per
+ * `fifo_expire' interval.  Otherwise a large number of expired requests
+ * would create a hopeless seekstorm.
+ *
+ * See as_antic_expired comment.
+ */
+static int as_fifo_expired(struct as_data *ad, int adir)
+{
+	struct as_rq *arq;
+	long delta_jif;
+
+	delta_jif = jiffies - ad->last_check_fifo[adir];
+	if (unlikely(delta_jif < 0))
+		delta_jif = -delta_jif;
+	if (delta_jif < ad->fifo_expire[adir])
+		return 0;
+
+	ad->last_check_fifo[adir] = jiffies;
+
+	if (list_empty(&ad->fifo_list[adir]))
+		return 0;
+
+	arq = list_entry_fifo(ad->fifo_list[adir].next);
+
+	return time_after(jiffies, arq->expires);
+}
+
+/*
+ * as_batch_expired returns true if the current batch has expired. A batch
+ * is a set of reads or a set of writes.
+ */
+static inline int as_batch_expired(struct as_data *ad)
+{
+	if (ad->changed_batch)
+		return 0;
+
+	if (ad->batch_data_dir == REQ_SYNC)
+		/* TODO! add a check so a complete fifo gets written? */
+		return time_after(jiffies, ad->current_batch_expires);
+
+	return time_after(jiffies, ad->current_batch_expires)
+		|| ad->current_write_count == 0;
+}
+
+/*
+ * move an entry to dispatch queue
+ */
+static void as_move_to_dispatch(struct as_data *ad, struct as_rq *arq)
+{
+	const int data_dir = arq->is_sync;
+
+	BUG_ON(!ON_RB(&arq->rb_node));
+
+	as_antic_stop(ad);
+	ad->antic_status = ANTIC_OFF;
+
+	/*
+	 * This has to be set in order to be correctly updated by
+	 * as_find_next_arq
+	 */
+	ad->last_sector[data_dir] = arq->request->sector
+					+ arq->request->nr_sectors;
+
+	ad->nr_dispatched++;
+
+	if (data_dir == REQ_SYNC) {
+		/* In case we have to anticipate after this */
+		copy_io_context(&ad->io_context, &arq->io_context);
+	} else {
+		if (ad->io_context) {
+			put_io_context(ad->io_context);
+			ad->io_context = NULL;
+		}
+
+		if (ad->current_write_count != 0)
+			ad->current_write_count--;
+	}
+	ad->ioc_finished = 0;
+
+	ad->next_arq[data_dir] = as_find_next_arq(ad, arq);
+
+	/*
+	 * take it off the sort and fifo list, add to dispatch queue
+	 */
+	as_remove_queued_request(ad->q, arq->request);
+	list_add_tail(&arq->request->queuelist, ad->dispatch);
+	if (arq->io_context && arq->io_context->aic)
+		atomic_inc(&arq->io_context->aic->nr_dispatched);
+
+	WARN_ON(arq->state != AS_RQ_QUEUED);
+	arq->state = AS_RQ_DISPATCHED;
+}
+
+/*
+ * as_dispatch_request selects the best request according to
+ * read/write expire, batch expire, etc, and moves it to the dispatch
+ * queue. Returns 1 if a request was found, 0 otherwise.
+ */
+static int as_dispatch_request(struct as_data *ad)
+{
+	struct as_rq *arq;
+	const int reads = !list_empty(&ad->fifo_list[REQ_SYNC]);
+	const int writes = !list_empty(&ad->fifo_list[REQ_ASYNC]);
+
+	/* Signal that the write batch was uncontended, so we can't time it */
+	if (ad->batch_data_dir == REQ_ASYNC && !reads) {
+		if (ad->current_write_count == 0 || !writes)
+			ad->write_batch_idled = 1;
+	}
+
+	if (!(reads || writes)
+		|| ad->antic_status == ANTIC_WAIT_REQ
+		|| ad->antic_status == ANTIC_WAIT_NEXT
+		|| ad->changed_batch == 1)
+		return 0;
+
+	if (!(reads && writes && as_batch_expired(ad)) ) {
+		/*
+		 * batch is still running or no reads or no writes
+		 */
+		arq = ad->next_arq[ad->batch_data_dir];
+
+		if (ad->batch_data_dir == REQ_SYNC && ad->antic_expire) {
+			if (as_fifo_expired(ad, REQ_SYNC))
+				goto fifo_expired;
+
+			if (as_can_anticipate(ad, arq)) {
+				as_antic_waitreq(ad);
+				return 0;
+			}
+		}
+
+		if (arq) {
+			/* we have a "next request" */
+			if (reads && !writes)
+				ad->current_batch_expires =
+					jiffies + ad->batch_expire[REQ_SYNC];
+			goto dispatch_request;
+		}
+	}
+
+	/*
+	 * at this point we are not running a batch. select the appropriate
+	 * data direction (read / write)
+	 */
+
+	if (reads) {
+		BUG_ON(RB_EMPTY(&ad->sort_list[REQ_SYNC]));
+
+		if (writes && ad->batch_data_dir == REQ_SYNC)
+			/*
+			 * Last batch was a read, switch to writes
+			 */
+			goto dispatch_writes;
+
+ 		if (ad->batch_data_dir == REQ_ASYNC)
+ 			ad->changed_batch = 1;
+		ad->batch_data_dir = REQ_SYNC;
+		arq = list_entry_fifo(ad->fifo_list[ad->batch_data_dir].next);
+		ad->last_check_fifo[ad->batch_data_dir] = jiffies;
+		goto dispatch_request;
+	}
+
+	/*
+	 * the last batch was a read
+	 */
+
+	if (writes) {
+dispatch_writes:
+		BUG_ON(RB_EMPTY(&ad->sort_list[REQ_ASYNC]));
+
+ 		if (ad->batch_data_dir == REQ_SYNC)
+ 			ad->changed_batch = 1;
+		ad->batch_data_dir = REQ_ASYNC;
+		ad->current_write_count = ad->write_batch_count;
+		ad->write_batch_idled = 0;
+		arq = ad->next_arq[ad->batch_data_dir];
+		goto dispatch_request;
+	}
+
+	BUG();
+	return 0;
+
+dispatch_request:
+	/*
+	 * If a request has expired, service it.
+	 */
+
+	if (as_fifo_expired(ad, ad->batch_data_dir)) {
+fifo_expired:
+		arq = list_entry_fifo(ad->fifo_list[ad->batch_data_dir].next);
+		BUG_ON(arq == NULL);
+	}
+
+	if (ad->changed_batch) {
+		if (ad->changed_batch == 1 && ad->nr_dispatched)
+			return 0;
+		if (ad->batch_data_dir == REQ_ASYNC) {
+			ad->current_batch_expires = jiffies +
+					ad->batch_expire[REQ_ASYNC];
+			ad->changed_batch = 0;
+		} else
+			ad->changed_batch = 2;
+		arq->request->flags |= REQ_HARDBARRIER;
+	}
+
+	/*
+	 * arq is the selected appropriate request.
+	 */
+	as_move_to_dispatch(ad, arq);
+
+	return 1;
+}
+
+static struct request *as_next_request(request_queue_t *q)
+{
+	struct as_data *ad = q->elevator.elevator_data;
+	struct request *rq = NULL;
+
+	/*
+	 * if there are still requests on the dispatch queue, grab the first
+	 */
+	if (!list_empty(ad->dispatch) || as_dispatch_request(ad))
+		rq = list_entry_rq(ad->dispatch->next);
+
+	return rq;
+}
+
+/*
+ * add arq to rbtree and fifo
+ */
+static void as_add_request(struct as_data *ad, struct as_rq *arq)
+{
+	int data_dir;
+
+	if (rq_data_dir(arq->request) == READ
+			|| current->flags&PF_SYNCWRITE)
+		arq->is_sync = 1;
+	else
+		arq->is_sync = 0;
+	data_dir = arq->is_sync;
+
+	arq->io_context = as_get_io_context();
+
+	if (arq->io_context) {
+		atomic_inc(&arq->io_context->aic->nr_queued);
+		as_update_iohist(arq->io_context->aic, arq->request);
+	}
+
+	as_add_arq_rb(ad, arq);
+
+	/*
+	 * set expire time (only used for reads) and add to fifo list
+	 */
+	arq->expires = jiffies + ad->fifo_expire[data_dir];
+	list_add_tail(&arq->fifo, &ad->fifo_list[data_dir]);
+	arq->state = AS_RQ_QUEUED;
+	as_update_arq(ad, arq); /* keep state machine up to date */
+}
+
+static void
+as_insert_request(request_queue_t *q, struct request *rq,
+			struct list_head *insert_here)
+{
+	struct as_data *ad = q->elevator.elevator_data;
+	struct as_rq *arq = RQ_DATA(rq);
+
+	if (unlikely(rq->flags & REQ_HARDBARRIER)) {
+		AS_INVALIDATE_HASH(ad);
+		q->last_merge = NULL;
+
+		while (ad->next_arq[REQ_SYNC])
+			as_move_to_dispatch(ad, ad->next_arq[REQ_SYNC]);
+
+		while (ad->next_arq[REQ_ASYNC])
+			as_move_to_dispatch(ad, ad->next_arq[REQ_ASYNC]);
+	}
+
+	if (unlikely(!blk_fs_request(rq))) {
+		if (!insert_here)
+			insert_here = ad->dispatch->prev;
+
+		list_add(&rq->queuelist, insert_here);
+
+		/* Stop anticipating - let this request get through */
+		if (!list_empty(ad->dispatch)
+			&& (ad->antic_status == ANTIC_WAIT_REQ
+				|| ad->antic_status == ANTIC_WAIT_NEXT))
+			as_antic_stop(ad);
+
+		return;
+	}
+
+	if (rq_mergeable(rq)) {
+		as_add_arq_hash(ad, arq);
+
+		if (!q->last_merge)
+			q->last_merge = &rq->queuelist;
+	}
+
+	as_add_request(ad, arq);
+}
+
+/*
+ * as_queue_empty tells us if there are requests left in the device. It may
+ * not be the case that a driver can get the next request even if the queue
+ * is not empty - it is used in the block layer to check for plugging and
+ * merging opportunities
+ */
+static int as_queue_empty(request_queue_t *q)
+{
+	struct as_data *ad = q->elevator.elevator_data;
+
+	if (!list_empty(&ad->fifo_list[REQ_ASYNC])
+		|| !list_empty(&ad->fifo_list[REQ_SYNC])
+		|| !list_empty(ad->dispatch))
+			return 0;
+
+	return 1;
+}
+
+static struct request *
+as_former_request(request_queue_t *q, struct request *rq)
+{
+	struct as_rq *arq = RQ_DATA(rq);
+	struct rb_node *rbprev = rb_prev(&arq->rb_node);
+	struct request *ret = NULL;
+
+	if (rbprev)
+		ret = rb_entry_arq(rbprev)->request;
+
+	return ret;
+}
+
+static struct request *
+as_latter_request(request_queue_t *q, struct request *rq)
+{
+	struct as_rq *arq = RQ_DATA(rq);
+	struct rb_node *rbnext = rb_next(&arq->rb_node);
+	struct request *ret = NULL;
+
+	if (rbnext)
+		ret = rb_entry_arq(rbnext)->request;
+
+	return ret;
+}
+
+static int
+as_merge(request_queue_t *q, struct list_head **insert, struct bio *bio)
+{
+	struct as_data *ad = q->elevator.elevator_data;
+	sector_t rb_key = bio->bi_sector + bio_sectors(bio);
+	struct request *__rq;
+	int ret;
+
+	/*
+	 * try last_merge to avoid going to hash
+	 */
+	ret = elv_try_last_merge(q, bio);
+	if (ret != ELEVATOR_NO_MERGE) {
+		__rq = list_entry_rq(q->last_merge);
+		goto out_insert;
+	}
+
+	/*
+	 * see if the merge hash can satisfy a back merge
+	 */
+	__rq = as_find_arq_hash(ad, bio->bi_sector);
+	if (__rq) {
+		BUG_ON(__rq->sector + __rq->nr_sectors != bio->bi_sector);
+
+		if (elv_rq_merge_ok(__rq, bio)) {
+			ret = ELEVATOR_BACK_MERGE;
+			goto out;
+		}
+	}
+
+	/*
+	 * check for front merge
+	 */
+	__rq = as_find_arq_rb(ad, rb_key, bio_data_dir(bio));
+	if (__rq) {
+		BUG_ON(rb_key != rq_rb_key(__rq));
+
+		if (elv_rq_merge_ok(__rq, bio)) {
+			ret = ELEVATOR_FRONT_MERGE;
+			goto out;
+		}
+	}
+
+	return ELEVATOR_NO_MERGE;
+out:
+	q->last_merge = &__rq->queuelist;
+out_insert:
+	if (ret)
+		as_hot_arq_hash(ad, RQ_DATA(__rq));
+	*insert = &__rq->queuelist;
+	return ret;
+}
+
+static void as_merged_request(request_queue_t *q, struct request *req)
+{
+	struct as_data *ad = q->elevator.elevator_data;
+	struct as_rq *arq = RQ_DATA(req);
+
+	/*
+	 * hash always needs to be repositioned, key is end sector
+	 */
+	as_del_arq_hash(arq);
+	as_add_arq_hash(ad, arq);
+
+	/*
+	 * if the merge was a front merge, we need to reposition request
+	 */
+	if (rq_rb_key(req) != arq->rb_key) {
+		as_del_arq_rb(ad, arq);
+		as_add_arq_rb(ad, arq);
+		/*
+		 * Note! At this stage of this and the next function, our next
+		 * request may not be optimal - eg the request may have "grown"
+		 * behind the disk head. We currently don't bother adjusting.
+		 */
+	}
+
+	q->last_merge = &req->queuelist;
+}
+
+static void
+as_merged_requests(request_queue_t *q, struct request *req,
+			 struct request *next)
+{
+	struct as_data *ad = q->elevator.elevator_data;
+	struct as_rq *arq = RQ_DATA(req);
+	struct as_rq *anext = RQ_DATA(next);
+
+	BUG_ON(!arq);
+	BUG_ON(!anext);
+
+	/*
+	 * reposition arq (this is the merged request) in hash, and in rbtree
+	 * in case of a front merge
+	 */
+	as_del_arq_hash(arq);
+	as_add_arq_hash(ad, arq);
+
+	if (rq_rb_key(req) != arq->rb_key) {
+		as_del_arq_rb(ad, arq);
+		as_add_arq_rb(ad, arq);
+	}
+
+	/*
+	 * if anext expires before arq, assign its expire time to arq
+	 * and move into anext position (anext will be deleted) in fifo
+	 */
+	if (!list_empty(&arq->fifo) && !list_empty(&anext->fifo)) {
+		if (time_before(anext->expires, arq->expires)) {
+			list_move(&arq->fifo, &anext->fifo);
+			arq->expires = anext->expires;
+			/*
+			 * Don't copy here but swap, because when anext is
+			 * removed below, it must contain the unused context
+			 */
+			swap_io_context(&arq->io_context, &anext->io_context);
+		}
+	}
+
+	/*
+	 * kill knowledge of next, this one is a goner
+	 */
+	as_remove_queued_request(q, next);
+	put_io_context(anext->io_context);
+}
+
+/*
+ * This is executed in a "deferred" process context, by kblockd. It calls the
+ * driver's request_fn so the driver can submit that request.
+ *
+ * IMPORTANT! This guy will reenter the elevator, so set up all queue global
+ * state before calling, and don't rely on any state over calls.
+ *
+ * FIXME! dispatch queue is not a queue at all!
+ */
+static void as_work_handler(void *data)
+{
+	struct request_queue *q = data;
+	unsigned long flags;
+
+	spin_lock_irqsave(q->queue_lock, flags);
+	if (as_next_request(q))
+		q->request_fn(q);
+	spin_unlock_irqrestore(q->queue_lock, flags);
+}
+
+static void as_put_request(request_queue_t *q, struct request *rq)
+{
+	struct as_data *ad = q->elevator.elevator_data;
+	struct as_rq *arq = RQ_DATA(rq);
+
+	if (!arq) {
+		WARN_ON(1);
+		return;
+	}
+
+	mempool_free(arq, ad->arq_pool);
+	rq->elevator_private = NULL;
+}
+
+static int as_set_request(request_queue_t *q, struct request *rq, int gfp_mask)
+{
+	struct as_data *ad = q->elevator.elevator_data;
+	struct as_rq *arq = mempool_alloc(ad->arq_pool, gfp_mask);
+
+	if (arq) {
+		RB_CLEAR(&arq->rb_node);
+		arq->request = rq;
+		arq->state = AS_RQ_NEW;
+		arq->io_context = NULL;
+		INIT_LIST_HEAD(&arq->hash);
+		arq->hash_valid_count = 0;
+		INIT_LIST_HEAD(&arq->fifo);
+		rq->elevator_private = arq;
+		return 0;
+	}
+
+	return 1;
+}
+
+static int as_may_queue(request_queue_t *q, int rw)
+{
+	int ret = 0;
+	struct as_data *ad = q->elevator.elevator_data;
+	struct io_context *ioc;
+	if (ad->antic_status == ANTIC_WAIT_REQ ||
+			ad->antic_status == ANTIC_WAIT_NEXT) {
+		ioc = as_get_io_context();
+		if (ad->io_context == ioc)
+			ret = 1;
+		put_io_context(ioc);
+	}
+
+	return ret;
+}
+
+static void as_exit(request_queue_t *q, elevator_t *e)
+{
+	struct as_data *ad = e->elevator_data;
+
+	del_timer_sync(&ad->antic_timer);
+	kblockd_flush();
+
+	BUG_ON(!list_empty(&ad->fifo_list[REQ_SYNC]));
+	BUG_ON(!list_empty(&ad->fifo_list[REQ_ASYNC]));
+
+	mempool_destroy(ad->arq_pool);
+	put_io_context(ad->io_context);
+	kfree(ad->hash);
+	kfree(ad);
+}
+
+/*
+ * initialize elevator private data (as_data), and alloc a arq for
+ * each request on the free lists
+ */
+static int as_init(request_queue_t *q, elevator_t *e)
+{
+	struct as_data *ad;
+	int i;
+
+	if (!arq_pool)
+		return -ENOMEM;
+
+	ad = kmalloc(sizeof(*ad), GFP_KERNEL);
+	if (!ad)
+		return -ENOMEM;
+	memset(ad, 0, sizeof(*ad));
+
+	ad->q = q; /* Identify what queue the data belongs to */
+
+	ad->hash = kmalloc(sizeof(struct list_head)*AS_HASH_ENTRIES,GFP_KERNEL);
+	if (!ad->hash) {
+		kfree(ad);
+		return -ENOMEM;
+	}
+
+	ad->arq_pool = mempool_create(BLKDEV_MIN_RQ, mempool_alloc_slab, mempool_free_slab, arq_pool);
+	if (!ad->arq_pool) {
+		kfree(ad->hash);
+		kfree(ad);
+		return -ENOMEM;
+	}
+
+	/* anticipatory scheduling helpers */
+	ad->antic_timer.function = as_antic_timeout;
+	ad->antic_timer.data = (unsigned long)q;
+	init_timer(&ad->antic_timer);
+	INIT_WORK(&ad->antic_work, as_work_handler, q);
+
+	for (i = 0; i < AS_HASH_ENTRIES; i++)
+		INIT_LIST_HEAD(&ad->hash[i]);
+
+	INIT_LIST_HEAD(&ad->fifo_list[REQ_SYNC]);
+	INIT_LIST_HEAD(&ad->fifo_list[REQ_ASYNC]);
+	ad->sort_list[REQ_SYNC] = RB_ROOT;
+	ad->sort_list[REQ_ASYNC] = RB_ROOT;
+	ad->dispatch = &q->queue_head;
+	ad->fifo_expire[REQ_SYNC] = default_read_expire;
+	ad->fifo_expire[REQ_ASYNC] = default_write_expire;
+	ad->hash_valid_count = 1;
+	ad->antic_expire = default_antic_expire;
+	ad->batch_expire[REQ_SYNC] = default_read_batch_expire;
+	ad->batch_expire[REQ_ASYNC] = default_write_batch_expire;
+	e->elevator_data = ad;
+
+	ad->current_batch_expires = jiffies + ad->batch_expire[REQ_SYNC];
+	ad->write_batch_count = ad->batch_expire[REQ_ASYNC] / 10;
+	if (ad->write_batch_count < 2)
+		ad->write_batch_count = 2;
+	return 0;
+}
+
+/*
+ * sysfs parts below
+ */
+struct as_fs_entry {
+	struct attribute attr;
+	ssize_t (*show)(struct as_data *, char *);
+	ssize_t (*store)(struct as_data *, const char *, size_t);
+};
+
+static ssize_t
+as_var_show(unsigned int var, char *page)
+{
+	var = (var * 1000) / HZ;
+	return sprintf(page, "%d\n", var);
+}
+
+static ssize_t
+as_var_store(unsigned long *var, const char *page, size_t count)
+{
+	unsigned long tmp;
+	char *p = (char *) page;
+
+	tmp = simple_strtoul(p, &p, 10);
+	if (tmp != 0) {
+		tmp = (tmp * HZ) / 1000;
+		if (tmp == 0)
+			tmp = 1;
+	}
+	*var = tmp;
+	return count;
+}
+
+#define SHOW_FUNCTION(__FUNC, __VAR)					\
+static ssize_t __FUNC(struct as_data *ad, char *page)		\
+{									\
+	return as_var_show(__VAR, (page));			\
+}
+SHOW_FUNCTION(as_readexpire_show, ad->fifo_expire[REQ_SYNC]);
+SHOW_FUNCTION(as_writeexpire_show, ad->fifo_expire[REQ_ASYNC]);
+SHOW_FUNCTION(as_anticexpire_show, ad->antic_expire);
+SHOW_FUNCTION(as_read_batchexpire_show, ad->batch_expire[REQ_SYNC]);
+SHOW_FUNCTION(as_write_batchexpire_show, ad->batch_expire[REQ_ASYNC]);
+#undef SHOW_FUNCTION
+
+#define STORE_FUNCTION(__FUNC, __PTR, MIN, MAX)				\
+static ssize_t __FUNC(struct as_data *ad, const char *page, size_t count)	\
+{									\
+	int ret = as_var_store(__PTR, (page), count);		\
+	if (*(__PTR) < (MIN))						\
+		*(__PTR) = (MIN);					\
+	else if (*(__PTR) > (MAX))					\
+		*(__PTR) = (MAX);					\
+	return ret;							\
+}
+STORE_FUNCTION(as_readexpire_store, &ad->fifo_expire[REQ_SYNC], 0, INT_MAX);
+STORE_FUNCTION(as_writeexpire_store, &ad->fifo_expire[REQ_ASYNC], 0, INT_MAX);
+STORE_FUNCTION(as_anticexpire_store, &ad->antic_expire, 0, INT_MAX);
+STORE_FUNCTION(as_read_batchexpire_store,
+			&ad->batch_expire[REQ_SYNC], 0, INT_MAX);
+STORE_FUNCTION(as_write_batchexpire_store,
+			&ad->batch_expire[REQ_ASYNC], 0, INT_MAX);
+#undef STORE_FUNCTION
+
+static struct as_fs_entry as_readexpire_entry = {
+	.attr = {.name = "read_expire", .mode = S_IRUGO | S_IWUSR },
+	.show = as_readexpire_show,
+	.store = as_readexpire_store,
+};
+static struct as_fs_entry as_writeexpire_entry = {
+	.attr = {.name = "write_expire", .mode = S_IRUGO | S_IWUSR },
+	.show = as_writeexpire_show,
+	.store = as_writeexpire_store,
+};
+static struct as_fs_entry as_anticexpire_entry = {
+	.attr = {.name = "antic_expire", .mode = S_IRUGO | S_IWUSR },
+	.show = as_anticexpire_show,
+	.store = as_anticexpire_store,
+};
+static struct as_fs_entry as_read_batchexpire_entry = {
+	.attr = {.name = "read_batch_expire", .mode = S_IRUGO | S_IWUSR },
+	.show = as_read_batchexpire_show,
+	.store = as_read_batchexpire_store,
+};
+static struct as_fs_entry as_write_batchexpire_entry = {
+	.attr = {.name = "write_batch_expire", .mode = S_IRUGO | S_IWUSR },
+	.show = as_write_batchexpire_show,
+	.store = as_write_batchexpire_store,
+};
+
+static struct attribute *default_attrs[] = {
+	&as_readexpire_entry.attr,
+	&as_writeexpire_entry.attr,
+	&as_anticexpire_entry.attr,
+	&as_read_batchexpire_entry.attr,
+	&as_write_batchexpire_entry.attr,
+	NULL,
+};
+
+#define to_as(atr) container_of((atr), struct as_fs_entry, attr)
+
+static ssize_t
+as_attr_show(struct kobject *kobj, struct attribute *attr, char *page)
+{
+	elevator_t *e = container_of(kobj, elevator_t, kobj);
+	struct as_fs_entry *entry = to_as(attr);
+
+	if (!entry->show)
+		return 0;
+
+	return entry->show(e->elevator_data, page);
+}
+
+static ssize_t
+as_attr_store(struct kobject *kobj, struct attribute *attr,
+		    const char *page, size_t length)
+{
+	elevator_t *e = container_of(kobj, elevator_t, kobj);
+	struct as_fs_entry *entry = to_as(attr);
+
+	if (!entry->store)
+		return -EINVAL;
+
+	return entry->store(e->elevator_data, page, length);
+}
+
+static struct sysfs_ops as_sysfs_ops = {
+	.show	= as_attr_show,
+	.store	= as_attr_store,
+};
+
+struct kobj_type as_ktype = {
+	.sysfs_ops	= &as_sysfs_ops,
+	.default_attrs	= default_attrs,
+};
+
+static int __init as_slab_setup(void)
+{
+	arq_pool = kmem_cache_create("as_arq", sizeof(struct as_rq),
+				     0, 0, NULL, NULL);
+
+	if (!arq_pool)
+		panic("as: can't init slab pool\n");
+
+	return 0;
+}
+
+subsys_initcall(as_slab_setup);
+
+elevator_t iosched_as = {
+	.elevator_merge_fn = 		as_merge,
+	.elevator_merged_fn =		as_merged_request,
+	.elevator_merge_req_fn =	as_merged_requests,
+	.elevator_next_req_fn =		as_next_request,
+	.elevator_add_req_fn =		as_insert_request,
+	.elevator_remove_req_fn =	as_remove_request,
+	.elevator_queue_empty_fn =	as_queue_empty,
+	.elevator_completed_req_fn =	as_completed_request,
+	.elevator_former_req_fn =	as_former_request,
+	.elevator_latter_req_fn =	as_latter_request,
+	.elevator_set_req_fn =		as_set_request,
+	.elevator_put_req_fn =		as_put_request,
+	.elevator_may_queue_fn =	as_may_queue,
+	.elevator_init_fn =		as_init,
+	.elevator_exit_fn =		as_exit,
+
+	.elevator_ktype =		&as_ktype,
+};
+
+EXPORT_SYMBOL(iosched_as);
diff -Nru a/drivers/block/cciss.c b/drivers/block/cciss.c
--- a/drivers/block/cciss.c	Thu Jun  5 06:17:28 2003
+++ b/drivers/block/cciss.c	Wed Jul  2 21:23:13 2003
@@ -1887,7 +1887,7 @@
                 BUG();
 
 	if (( c = cmd_alloc(h, 1)) == NULL)
-		goto startio;
+		goto full;
 
 	blkdev_dequeue_request(creq);
 
@@ -1960,8 +1960,9 @@
 		h->maxQsinceinit = h->Qdepth; 
 
 	goto queue;
-startio:
+full:
 	blk_stop_queue(q);
+startio:
 	start_io(h);
 }
 
diff -Nru a/drivers/block/elevator.c b/drivers/block/elevator.c
--- a/drivers/block/elevator.c	Thu May 22 08:23:58 2003
+++ b/drivers/block/elevator.c	Fri Jul  4 23:52:45 2003
@@ -361,17 +361,31 @@
 		e->elevator_put_req_fn(q, rq);
 }
 
-int elv_register_queue(struct gendisk *disk)
+int elv_may_queue(request_queue_t *q, int rw)
 {
-	request_queue_t *q = disk->queue;
-	elevator_t *e;
+	elevator_t *e = &q->elevator;
+
+	if (e->elevator_may_queue_fn)
+		return e->elevator_may_queue_fn(q, rw);
+
+	return 0;
+}
 
-	if (!q)
-		return -ENXIO;
+void elv_completed_request(request_queue_t *q, struct request *rq)
+{
+	elevator_t *e = &q->elevator;
+
+	if (e->elevator_completed_req_fn)
+		e->elevator_completed_req_fn(q, rq);
+}
+
+int elv_register_queue(struct request_queue *q)
+{
+	elevator_t *e;
 
 	e = &q->elevator;
 
-	e->kobj.parent = kobject_get(&disk->kobj);
+	e->kobj.parent = kobject_get(&q->kobj);
 	if (!e->kobj.parent)
 		return -EBUSY;
 
@@ -381,14 +395,12 @@
 	return kobject_register(&e->kobj);
 }
 
-void elv_unregister_queue(struct gendisk *disk)
+void elv_unregister_queue(struct request_queue *q)
 {
-	request_queue_t *q = disk->queue;
-
 	if (q) {
 		elevator_t * e = &q->elevator;
 		kobject_unregister(&e->kobj);
-		kobject_put(&disk->kobj);
+		kobject_put(&q->kobj);
 	}
 }
 
@@ -408,5 +420,6 @@
 EXPORT_SYMBOL(elv_next_request);
 EXPORT_SYMBOL(elv_remove_request);
 EXPORT_SYMBOL(elv_queue_empty);
+EXPORT_SYMBOL(elv_completed_request);
 EXPORT_SYMBOL(elevator_exit);
 EXPORT_SYMBOL(elevator_init);
diff -Nru a/drivers/block/floppy.c b/drivers/block/floppy.c
--- a/drivers/block/floppy.c	Sun May 25 02:45:06 2003
+++ b/drivers/block/floppy.c	Sun Jun 29 23:49:25 2003
@@ -3767,7 +3767,7 @@
 	 * Needed so that programs such as fdrawcmd still can work on write
 	 * protected disks */
 	if ((filp->f_mode & 2) || 
-	    (inode->i_sb && (permission(inode,2) == 0)))
+	    (inode->i_sb && (permission(inode,2, NULL) == 0)))
 	    filp->private_data = (void*) 8;
 
 	if (UFDCS->rawcmd == 1)
diff -Nru a/drivers/block/genhd.c b/drivers/block/genhd.c
--- a/drivers/block/genhd.c	Sun Jun  1 12:55:40 2003
+++ b/drivers/block/genhd.c	Fri Jul  4 23:52:40 2003
@@ -191,7 +191,7 @@
 	blk_register_region(MKDEV(disk->major, disk->first_minor),
 			    disk->minors, NULL, exact_match, exact_lock, disk);
 	register_disk(disk);
-	elv_register_queue(disk);
+	blk_register_queue(disk);
 }
 
 EXPORT_SYMBOL(add_disk);
@@ -199,7 +199,7 @@
 
 void unlink_gendisk(struct gendisk *disk)
 {
-	elv_unregister_queue(disk);
+	blk_unregister_queue(disk);
 	blk_unregister_region(MKDEV(disk->major, disk->first_minor),
 			      disk->minors);
 }
diff -Nru a/drivers/block/ll_rw_blk.c b/drivers/block/ll_rw_blk.c
--- a/drivers/block/ll_rw_blk.c	Mon Jun  2 18:32:46 2003
+++ b/drivers/block/ll_rw_blk.c	Fri Jul  4 23:52:53 2003
@@ -42,40 +42,50 @@
 static LIST_HEAD(blk_plug_list);
 static spinlock_t blk_plug_lock __cacheline_aligned_in_smp = SPIN_LOCK_UNLOCKED;
 
+static wait_queue_head_t congestion_wqh[2];
+
 /*
- * Number of requests per queue.  This many for reads and for writes (twice
- * this number, total).
+ * Controlling structure to kblockd
  */
-static int queue_nr_requests;
+static struct workqueue_struct *kblockd_workqueue; 
 
 unsigned long blk_max_low_pfn, blk_max_pfn;
-static wait_queue_head_t congestion_wqh[2];
+
+/* Amount of time in which a process may batch requests */
+#define BLK_BATCH_TIME	(HZ/50UL)
+
+/* Number of requests a "batching" process may submit */
+#define BLK_BATCH_REQ	32
 
 /*
- * Return the threshold (number of free requests) at which the queue is
+ * Return the threshold (number of used requests) at which the queue is
  * considered to be congested.  It include a little hysteresis to keep the
  * context switch rate down.
  */
-static inline int queue_congestion_on_threshold(void)
+static inline int queue_congestion_on_threshold(struct request_queue *q)
 {
 	int ret;
 
-	ret = queue_nr_requests / 8 - 1;
-	if (ret < 0)
-		ret = 1;
+	ret = q->nr_requests - (q->nr_requests / 8) + 1;
+
+	if (ret > q->nr_requests)
+		ret = q->nr_requests;
+
 	return ret;
 }
 
 /*
  * The threshold at which a queue is considered to be uncongested
  */
-static inline int queue_congestion_off_threshold(void)
+static inline int queue_congestion_off_threshold(struct request_queue *q)
 {
 	int ret;
 
-	ret = queue_nr_requests / 8 + 1;
-	if (ret > queue_nr_requests)
-		ret = queue_nr_requests;
+	ret = q->nr_requests - (q->nr_requests / 8) - 1;
+
+	if (ret < 1)
+		ret = 1;
+
 	return ret;
 }
 
@@ -188,6 +198,7 @@
 	/*
 	 * set defaults
 	 */
+	q->nr_requests = BLKDEV_MAX_RQ;
 	q->max_phys_segments = MAX_PHYS_SEGMENTS;
 	q->max_hw_segments = MAX_HW_SEGMENTS;
 	q->make_request_fn = mfn;
@@ -441,13 +452,15 @@
 	q->queue_flags &= ~(1 << QUEUE_FLAG_QUEUED);
 }
 
-static int init_tag_map(struct blk_queue_tag *tags, int depth)
+static int
+init_tag_map(request_queue_t *q, struct blk_queue_tag *tags, int depth)
 {
 	int bits, i;
 
-	if (depth > (queue_nr_requests*2)) {
-		depth = (queue_nr_requests*2);
-		printk(KERN_ERR "%s: adjusted depth to %d\n", __FUNCTION__, depth);
+	if (depth > q->nr_requests * 2) {
+		depth = q->nr_requests * 2;
+		printk(KERN_ERR "%s: adjusted depth to %d\n",
+				__FUNCTION__, depth);
 	}
 
 	tags->tag_index = kmalloc(depth * sizeof(struct request *), GFP_ATOMIC);
@@ -476,7 +489,6 @@
 	return -ENOMEM;
 }
 
-
 /**
  * blk_queue_init_tags - initialize the queue tag info
  * @q:  the request queue for the device
@@ -490,7 +502,7 @@
 	if (!tags)
 		goto fail;
 
-	if (init_tag_map(tags, depth))
+	if (init_tag_map(q, tags, depth))
 		goto fail;
 
 	INIT_LIST_HEAD(&tags->busy_list);
@@ -540,7 +552,7 @@
 	tag_map = bqt->tag_map;
 	max_depth = bqt->real_max_depth;
 
-	if (init_tag_map(bqt, new_depth))
+	if (init_tag_map(q, bqt, new_depth))
 		return -ENOMEM;
 
 	memcpy(bqt->tag_index, tag_index, max_depth * sizeof(struct request *));
@@ -1022,7 +1034,7 @@
 	/*
 	 * was plugged, fire request_fn if queue has stuff to do
 	 */
-	if (!elv_queue_empty(q))
+	if (elv_next_request(q))
 		q->request_fn(q);
 }
 
@@ -1057,7 +1069,7 @@
 {
 	request_queue_t *q = (request_queue_t *)data;
 
-	schedule_work(&q->unplug_work);
+	kblockd_schedule_work(&q->unplug_work);
 }
 
 /**
@@ -1072,8 +1084,8 @@
  **/
 void blk_start_queue(request_queue_t *q)
 {
-	if (test_and_clear_bit(QUEUE_FLAG_STOPPED, &q->queue_flags))
-		schedule_work(&q->unplug_work);
+	clear_bit(QUEUE_FLAG_STOPPED, &q->queue_flags);
+	schedule_work(&q->unplug_work);
 }
 
 /**
@@ -1165,7 +1177,7 @@
 	elevator_exit(q);
 
 	del_timer_sync(&q->unplug_timer);
-	flush_scheduled_work();
+	kblockd_flush();
 
 	mempool_destroy(rl->rq_pool);
 
@@ -1180,6 +1192,8 @@
 	struct request_list *rl = &q->rq;
 
 	rl->count[READ] = rl->count[WRITE] = 0;
+	init_waitqueue_head(&rl->wait[READ]);
+	init_waitqueue_head(&rl->wait[WRITE]);
 
 	rl->rq_pool = mempool_create(BLKDEV_MIN_RQ, mempool_alloc_slab, mempool_free_slab, request_cachep);
 
@@ -1191,6 +1205,18 @@
 
 static int __make_request(request_queue_t *, struct bio *);
 
+static elevator_t *chosen_elevator = &iosched_as;
+
+static int __init elevator_setup(char *str)
+{
+	if (!strcmp(str, "deadline"))
+		chosen_elevator = &iosched_deadline;
+	if (!strcmp(str, "as"))
+		chosen_elevator = &iosched_as;
+	return 1;
+}
+__setup("elevator=", elevator_setup);
+
 /**
  * blk_init_queue  - prepare a request queue for use with a block device
  * @q:    The &request_queue_t to be initialised
@@ -1222,11 +1248,20 @@
 int blk_init_queue(request_queue_t *q, request_fn_proc *rfn, spinlock_t *lock)
 {
 	int ret;
+	static int printed;
 
 	if (blk_init_free_list(q))
 		return -ENOMEM;
 
-	if ((ret = elevator_init(q, &iosched_deadline))) {
+	if (!printed) {
+		printed = 1;
+		if (chosen_elevator == &iosched_deadline)
+			printk("deadline elevator\n");
+		else if (chosen_elevator == &iosched_as)
+			printk("anticipatory scheduling elevator\n");
+	}
+
+	if ((ret = elevator_init(q, chosen_elevator))) {
 		blk_cleanup_queue(q);
 		return ret;
 	}
@@ -1271,6 +1306,60 @@
 	return NULL;
 }
 
+/*
+ * ioc_batching returns true if the ioc is a valid batching request and
+ * should be given priority access to a request.
+ */
+static inline int ioc_batching(struct io_context *ioc)
+{
+	if (!ioc)
+		return 0;
+
+	/*
+	 * Make sure the process is able to allocate at least 1 request
+	 * even if the batch times out, otherwise we could theoretically
+	 * lose wakeups.
+	 */
+	return ioc->nr_batch_requests == BLK_BATCH_REQ ||
+		(ioc->nr_batch_requests > 0
+		&& time_before(jiffies, ioc->last_waited + BLK_BATCH_TIME));
+}
+
+/*
+ * ioc_set_batching sets ioc to be a new "batcher" if it is not one. This
+ * will cause the process to be a "batcher" on all queues in the system. This
+ * is the behaviour we want though - once it gets a wakeup it should be given
+ * a nice run.
+ */
+void ioc_set_batching(struct io_context *ioc)
+{
+	if (!ioc || ioc_batching(ioc))
+		return;
+
+	ioc->nr_batch_requests = BLK_BATCH_REQ;
+	ioc->last_waited = jiffies;
+}
+
+/*
+ * A request has just been released.  Account for it, update the full and
+ * congestion status, wake up any waiters.   Called under q->queue_lock.
+ */
+static void freed_request(request_queue_t *q, int rw)
+{
+	struct request_list *rl = &q->rq;
+
+	rl->count[rw]--;
+	if (rl->count[rw] < queue_congestion_off_threshold(q))
+		clear_queue_congested(q, rw);
+	if (rl->count[rw]+1 <= q->nr_requests) {
+		smp_mb();
+		if (waitqueue_active(&rl->wait[rw]))
+			wake_up(&rl->wait[rw]);
+		if (!waitqueue_active(&rl->wait[rw]))
+			blk_clear_queue_full(q, rw);
+	}
+}
+
 #define blkdev_free_rq(list) list_entry((list)->next, struct request, queuelist)
 /*
  * Get a free request, queue_lock must not be held
@@ -1279,26 +1368,54 @@
 {
 	struct request *rq = NULL;
 	struct request_list *rl = &q->rq;
+	struct io_context *ioc = get_io_context(gfp_mask);
 
 	spin_lock_irq(q->queue_lock);
-	if (rl->count[rw] == BLKDEV_MAX_RQ) {
+	if (rl->count[rw]+1 >= q->nr_requests) {
+		/*
+		 * The queue will fill after this allocation, so set it as
+		 * full, and mark this process as "batching". This process
+		 * will be allowed to complete a batch of requests, others
+		 * will be blocked.
+		 */
+		if (!blk_queue_full(q, rw)) {
+			ioc_set_batching(ioc);
+			blk_set_queue_full(q, rw);
+		}
+	}
+
+	if (blk_queue_full(q, rw)
+			&& !ioc_batching(ioc) && !elv_may_queue(q, rw)) {
+		/*
+		 * The queue is full and the allocating process is not a
+		 * "batcher", and not exempted by the IO scheduler
+		 */
 		spin_unlock_irq(q->queue_lock);
 		goto out;
 	}
+
 	rl->count[rw]++;
-	if ((BLKDEV_MAX_RQ - rl->count[rw]) < queue_congestion_on_threshold())
+	if (rl->count[rw] >= queue_congestion_on_threshold(q))
 		set_queue_congested(q, rw);
 	spin_unlock_irq(q->queue_lock);
 
 	rq = blk_alloc_request(q, gfp_mask);
 	if (!rq) {
+		/*
+		 * Allocation failed presumably due to memory. Undo anything
+		 * we might have messed up.
+		 *
+		 * Allocating task should really be put onto the front of the
+		 * wait queue, but this is pretty rare.
+		 */
 		spin_lock_irq(q->queue_lock);
-		rl->count[rw]--;
-		if ((BLKDEV_MAX_RQ - rl->count[rw]) >= queue_congestion_off_threshold())
-                        clear_queue_congested(q, rw);
+		freed_request(q, rw);
 		spin_unlock_irq(q->queue_lock);
 		goto out;
 	}
+
+	if (ioc_batching(ioc))
+		ioc->nr_batch_requests--;
 	
 	INIT_LIST_HEAD(&rq->queuelist);
 
@@ -1321,22 +1438,44 @@
 	rq->sense = NULL;
 
 out:
+	put_io_context(ioc);
 	return rq;
 }
 
 /*
- * No available requests for this queue, unplug the device.
+ * No available requests for this queue, unplug the device and wait for some
+ * requests to become available.
  */
 static struct request *get_request_wait(request_queue_t *q, int rw)
 {
+	DEFINE_WAIT(wait);
 	struct request *rq;
 
 	generic_unplug_device(q);
 	do {
+		struct request_list *rl = &q->rq;
+
+		prepare_to_wait_exclusive(&rl->wait[rw], &wait,
+				TASK_UNINTERRUPTIBLE);
+
 		rq = get_request(q, rw, GFP_NOIO);
 
-		if (!rq)
-			blk_congestion_wait(rw, HZ / 50);
+		if (!rq) {
+			struct io_context *ioc;
+
+			io_schedule();
+
+			/*
+			 * After sleeping, we become a "batching" process and
+			 * will be able to allocate at least one request, and
+			 * up to a big batch of them for a small period time.
+			 * See ioc_batching, ioc_set_batching
+			 */
+			ioc = get_io_context(GFP_NOIO);
+			ioc_set_batching(ioc);
+			put_io_context(ioc);
+		}
+		finish_wait(&rl->wait[rw], &wait);
 	} while (!rq);
 
 	return rq;
@@ -1348,10 +1487,10 @@
 
 	BUG_ON(rw != READ && rw != WRITE);
 
-	rq = get_request(q, rw, gfp_mask);
-
-	if (!rq && (gfp_mask & __GFP_WAIT))
+	if (gfp_mask & __GFP_WAIT)
 		rq = get_request_wait(q, rw);
+	else
+		rq = get_request(q, rw, gfp_mask);
 
 	return rq;
 }
@@ -1482,6 +1621,8 @@
 	if (unlikely(--req->ref_count))
 		return;
 
+	elv_completed_request(req->q, req);
+
 	req->rq_status = RQ_INACTIVE;
 	req->q = NULL;
 	req->rl = NULL;
@@ -1496,10 +1637,7 @@
 		BUG_ON(!list_empty(&req->queuelist));
 
 		blk_free_request(q, req);
-
-		rl->count[rw]--;
-		if ((BLKDEV_MAX_RQ - rl->count[rw]) >= queue_congestion_off_threshold())
-			clear_queue_congested(q, rw);
+		freed_request(q, rw);
 	}
 }
 
@@ -1786,13 +1924,12 @@
 		__blk_put_request(q, freereq);
 
 	if (blk_queue_plugged(q)) {
-		int nr_queued = q->rq.count[0] + q->rq.count[1];
+		int nr_queued = q->rq.count[READ] + q->rq.count[WRITE];
 
 		if (nr_queued == q->unplug_thresh)
 			__generic_unplug_device(q);
 	}
 	spin_unlock_irq(q->queue_lock);
-
 	return 0;
 
 end_io:
@@ -1800,7 +1937,6 @@
 	return 0;
 }
 
-
 /*
  * If bio->bi_dev is a partition, remap the location
  */
@@ -1850,8 +1986,7 @@
  * bio happens to be merged with someone else, and may change bi_dev and
  * bi_sector for remaps as it sees fit.  So the values of these fields
  * should NOT be depended on after the call to generic_make_request.
- *
- * */
+ */
 void generic_make_request(struct bio *bio)
 {
 	request_queue_t *q;
@@ -2282,30 +2417,286 @@
 	rq->current_nr_sectors = rq->hard_cur_sectors;
 }
 
+int kblockd_schedule_work(struct work_struct *work)
+{
+	return queue_work(kblockd_workqueue, work);
+}
+
+void kblockd_flush(void)
+{
+	flush_workqueue(kblockd_workqueue);
+}
+
 int __init blk_dev_init(void)
 {
 	int i;
 
+	kblockd_workqueue = create_workqueue("kblockd");
+	if (!kblockd_workqueue)
+		panic("Failed to create kblockd\n");
+
 	request_cachep = kmem_cache_create("blkdev_requests",
 			sizeof(struct request), 0, 0, NULL, NULL);
 	if (!request_cachep)
 		panic("Can't create request pool slab cache\n");
 
-	queue_nr_requests = BLKDEV_MAX_RQ;
-
-	printk("block request queues:\n");
-	printk(" %d/%d requests per read queue\n", BLKDEV_MIN_RQ, queue_nr_requests);
-	printk(" %d/%d requests per write queue\n", BLKDEV_MIN_RQ, queue_nr_requests);
-	printk(" enter congestion at %d\n", queue_congestion_on_threshold());
-	printk(" exit congestion at %d\n", queue_congestion_off_threshold());
-
 	blk_max_low_pfn = max_low_pfn;
 	blk_max_pfn = max_pfn;
 
 	for (i = 0; i < ARRAY_SIZE(congestion_wqh); i++)
 		init_waitqueue_head(&congestion_wqh[i]);
 	return 0;
+}
+
+static atomic_t nr_io_contexts = ATOMIC_INIT(0);
+
+/*
+ * IO Context helper functions
+ */
+void put_io_context(struct io_context *ioc)
+{
+	if (ioc == NULL)
+		return;
+
+	BUG_ON(atomic_read(&ioc->refcount) == 0);
+
+	if (atomic_dec_and_test(&ioc->refcount)) {
+		if (ioc->aic && ioc->aic->dtor)
+			ioc->aic->dtor(ioc->aic);
+		kfree(ioc);
+		atomic_dec(&nr_io_contexts);
+	}
+}
+
+/* Called by the exitting task */
+void exit_io_context(void)
+{
+	unsigned long flags;
+	struct io_context *ioc;
+
+	local_irq_save(flags);
+	ioc = current->io_context;
+	if (ioc) {
+		if (ioc->aic && ioc->aic->exit)
+			ioc->aic->exit(ioc->aic);
+		put_io_context(ioc);
+		current->io_context = NULL;
+	} else
+		WARN_ON(1);
+	local_irq_restore(flags);
+}
+
+/*
+ * If the current task has no IO context then create one and initialise it.
+ * If it does have a context, take a ref on it.
+ *
+ * This is always called in the context of the task which submitted the I/O.
+ * But weird things happen, so we disable local interrupts to ensure exclusive
+ * access to *current.
+ */
+struct io_context *get_io_context(int gfp_flags)
+{
+	struct task_struct *tsk = current;
+	unsigned long flags;
+	struct io_context *ret;
+
+	local_irq_save(flags);
+	ret = tsk->io_context;
+	if (ret == NULL) {
+		ret = kmalloc(sizeof(*ret), GFP_ATOMIC);
+		if (ret) {
+			atomic_inc(&nr_io_contexts);
+			atomic_set(&ret->refcount, 1);
+			ret->pid = tsk->pid;
+			ret->last_waited = jiffies; /* doesn't matter... */
+			ret->nr_batch_requests = 0; /* because this is 0 */
+			ret->aic = NULL;
+			tsk->io_context = ret;
+		}
+	}
+	if (ret)
+		atomic_inc(&ret->refcount);
+	local_irq_restore(flags);
+	return ret;
+}
+
+void copy_io_context(struct io_context **pdst, struct io_context **psrc)
+{
+	struct io_context *src = *psrc;
+	struct io_context *dst = *pdst;
+
+	if (src) {
+		BUG_ON(atomic_read(&src->refcount) == 0);
+		atomic_inc(&src->refcount);
+		put_io_context(dst);
+		*pdst = src;
+	}
+}
+
+void swap_io_context(struct io_context **ioc1, struct io_context **ioc2)
+{
+	struct io_context *temp;
+	temp = *ioc1;
+	*ioc1 = *ioc2;
+	*ioc2 = temp;
+}
+
+
+/*
+ * sysfs parts below
+ */
+struct queue_sysfs_entry {
+	struct attribute attr;
+	ssize_t (*show)(struct request_queue *, char *);
+	ssize_t (*store)(struct request_queue *, const char *, size_t);
+};
+
+static ssize_t
+queue_var_show(unsigned int var, char *page)
+{
+	return sprintf(page, "%d\n", var);
+}
+
+static ssize_t
+queue_var_store(unsigned long *var, const char *page, size_t count)
+{
+	char *p = (char *) page;
+
+	*var = simple_strtoul(p, &p, 10);
+	return count;
+}
+
+static ssize_t queue_requests_show(struct request_queue *q, char *page)
+{
+	return queue_var_show(q->nr_requests, (page));
+}
+
+static ssize_t
+queue_requests_store(struct request_queue *q, const char *page, size_t count)
+{
+	struct request_list *rl = &q->rq;
+
+	int ret = queue_var_store(&q->nr_requests, page, count);
+	if (q->nr_requests < BLKDEV_MIN_RQ)
+		q->nr_requests = BLKDEV_MIN_RQ;
+
+	if (rl->count[READ] >= queue_congestion_on_threshold(q))
+		set_queue_congested(q, READ);
+	else if (rl->count[READ] < queue_congestion_off_threshold(q))
+		clear_queue_congested(q, READ);
+
+	if (rl->count[WRITE] >= queue_congestion_on_threshold(q))
+		set_queue_congested(q, WRITE);
+	else if (rl->count[WRITE] < queue_congestion_off_threshold(q))
+		clear_queue_congested(q, WRITE);
+
+	if (rl->count[READ] >= q->nr_requests) {
+		blk_set_queue_full(q, READ);
+	} else if (rl->count[READ]+1 <= q->nr_requests) {
+		blk_clear_queue_full(q, READ);
+		wake_up(&rl->wait[READ]);
+	}
+
+	if (rl->count[WRITE] >= q->nr_requests) {
+		blk_set_queue_full(q, WRITE);
+	} else if (rl->count[WRITE]+1 <= q->nr_requests) {
+		blk_clear_queue_full(q, WRITE);
+		wake_up(&rl->wait[WRITE]);
+	}
+	return ret;
+}
+
+static struct queue_sysfs_entry queue_requests_entry = {
+	.attr = {.name = "nr_requests", .mode = S_IRUGO | S_IWUSR },
+	.show = queue_requests_show,
+	.store = queue_requests_store,
 };
+
+static struct attribute *default_attrs[] = {
+	&queue_requests_entry.attr,
+	NULL,
+};
+
+#define to_queue(atr) container_of((atr), struct queue_sysfs_entry, attr)
+
+static ssize_t
+queue_attr_show(struct kobject *kobj, struct attribute *attr, char *page)
+{
+	struct queue_sysfs_entry *entry = to_queue(attr);
+	struct request_queue *q;
+
+	q = container_of(kobj, struct request_queue, kobj);
+	if (!entry->show)
+		return 0;
+
+	return entry->show(q, page);
+}
+
+static ssize_t
+queue_attr_store(struct kobject *kobj, struct attribute *attr,
+		    const char *page, size_t length)
+{
+	struct queue_sysfs_entry *entry = to_queue(attr);
+	struct request_queue *q;
+
+	q = container_of(kobj, struct request_queue, kobj);
+	if (!entry->store)
+		return -EINVAL;
+
+	return entry->store(q, page, length);
+}
+
+static struct sysfs_ops queue_sysfs_ops = {
+	.show	= queue_attr_show,
+	.store	= queue_attr_store,
+};
+
+struct kobj_type queue_ktype = {
+	.sysfs_ops	= &queue_sysfs_ops,
+	.default_attrs	= default_attrs,
+};
+
+int blk_register_queue(struct gendisk *disk)
+{
+	int ret;
+
+	request_queue_t *q = disk->queue;
+
+	if (!q)
+		return -ENXIO;
+
+	q->kobj.parent = kobject_get(&disk->kobj);
+	if (!q->kobj.parent)
+		return -EBUSY;
+
+	snprintf(q->kobj.name, KOBJ_NAME_LEN, "%s", "queue");
+	q->kobj.ktype = &queue_ktype;
+
+	ret = kobject_register(&q->kobj);
+	if (ret < 0)
+		return ret;
+
+	ret = elv_register_queue(q);
+	if (ret) {
+		kobject_unregister(&q->kobj);
+		return ret;
+	}
+
+	return 0;
+}
+
+void blk_unregister_queue(struct gendisk *disk)
+{
+	request_queue_t *q = disk->queue;
+
+	if (q) {
+		elv_unregister_queue(q);
+
+		kobject_unregister(&q->kobj);
+		kobject_put(&disk->kobj);
+	}
+}
+
 
 EXPORT_SYMBOL(process_that_request_first);
 EXPORT_SYMBOL(end_that_request_first);
diff -Nru a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c
--- a/drivers/char/pcmcia/synclink_cs.c	Wed Jun 11 12:32:41 2003
+++ b/drivers/char/pcmcia/synclink_cs.c	Wed Jun 18 08:31:08 2003
@@ -1,7 +1,7 @@
 /*
  * linux/drivers/char/pcmcia/synclink_cs.c
  *
- * $Id: synclink_cs.c,v 4.10 2003/05/13 16:06:03 paulkf Exp $
+ * $Id: synclink_cs.c,v 4.13 2003/06/18 15:29:32 paulkf Exp $
  *
  * Device driver for Microgate SyncLink PC Card
  * multiprotocol serial adapter.
@@ -467,7 +467,6 @@
  * assigned major number. May be forced as module parameter.
  */
 static int ttymajor=0;
-static int cuamajor=0;
 
 static int debug_level = 0;
 static int maxframe[MAX_DEVICE_COUNT] = {0,};
@@ -485,7 +484,6 @@
 
 MODULE_PARM(break_on_load,"i");
 MODULE_PARM(ttymajor,"i");
-MODULE_PARM(cuamajor,"i");
 MODULE_PARM(debug_level,"i");
 MODULE_PARM(maxframe,"1-" __MODULE_STRING(MAX_DEVICE_COUNT) "i");
 MODULE_PARM(dosyncppp,"1-" __MODULE_STRING(MAX_DEVICE_COUNT) "i");
@@ -493,7 +491,7 @@
 MODULE_LICENSE("GPL");
 
 static char *driver_name = "SyncLink PC Card driver";
-static char *driver_version = "$Revision: 4.10 $";
+static char *driver_version = "$Revision: 4.13 $";
 
 static struct tty_driver *serial_driver;
 
@@ -1290,7 +1288,7 @@
 			       (info->serial_signals & SerialSignal_DCD) ? "on" : "off");
 		if (info->serial_signals & SerialSignal_DCD)
 			wake_up_interruptible(&info->open_wait);
-		else if (!(info->flags & ASYNC_CALLOUT_NOHUP)) {
+		else {
 			if (debug_level >= DEBUG_LEVEL_ISR)
 				printk("doing serial hangup...");
 			if (info->tty)
@@ -2538,14 +2536,17 @@
 {
 	MGSLPC_INFO * info = (MGSLPC_INFO *)tty->driver_data;
 
-	if (!info || mgslpc_paranoia_check(info, tty->name, "mgslpc_close"))
+	if (mgslpc_paranoia_check(info, tty->name, "mgslpc_close"))
 		return;
 	
 	if (debug_level >= DEBUG_LEVEL_INFO)
 		printk("%s(%d):mgslpc_close(%s) entry, count=%d\n",
 			 __FILE__,__LINE__, info->device_name, info->count);
 			 
-	if (!info->count || tty_hung_up_p(filp))
+	if (!info->count)
+		return;
+
+	if (tty_hung_up_p(filp))
 		goto cleanup;
 			
 	if ((tty->count == 1) && (info->count != 1)) {
@@ -2822,16 +2823,11 @@
 	info = mgslpc_device_list;
 	while(info && info->line != line)
 		info = info->next_device;
-	if ( !info ){
-		printk("%s(%d):Can't find specified device on open (line=%d)\n",
-			__FILE__,__LINE__,line);
+	if (mgslpc_paranoia_check(info, tty->name, "mgslpc_open"))
 		return -ENODEV;
-	}
 	
 	tty->driver_data = info;
 	info->tty = tty;
-	if (mgslpc_paranoia_check(info, tty->name, "mgslpc_open"))
-		return -ENODEV;
 		
 	if (debug_level >= DEBUG_LEVEL_INFO)
 		printk("%s(%d):mgslpc_open(%s), old ref count = %d\n",
@@ -2879,6 +2875,8 @@
 	
 cleanup:			
 	if (retval) {
+		if (tty->count == 1)
+			info->tty = 0; /* tty layer will release tty struct */
 		if(info->count)
 			info->count--;
 	}
diff -Nru a/drivers/char/synclink.c b/drivers/char/synclink.c
--- a/drivers/char/synclink.c	Wed Jun 11 12:32:41 2003
+++ b/drivers/char/synclink.c	Wed Jun 18 08:31:00 2003
@@ -1,7 +1,7 @@
 /*
  * linux/drivers/char/synclink.c
  *
- * $Id: synclink.c,v 4.9 2003/05/06 21:18:51 paulkf Exp $
+ * $Id: synclink.c,v 4.12 2003/06/18 15:29:32 paulkf Exp $
  *
  * Device driver for Microgate SyncLink ISA and PCI
  * high speed multiprotocol serial adapters.
@@ -910,7 +910,7 @@
 MODULE_PARM(txholdbufs,"1-" __MODULE_STRING(MAX_TOTAL_DEVICES) "i");
 
 static char *driver_name = "SyncLink serial driver";
-static char *driver_version = "$Revision: 4.9 $";
+static char *driver_version = "$Revision: 4.12 $";
 
 static int synclink_init_one (struct pci_dev *dev,
 				     const struct pci_device_id *ent);
@@ -3170,14 +3170,17 @@
 {
 	struct mgsl_struct * info = (struct mgsl_struct *)tty->driver_data;
 
-	if (!info || mgsl_paranoia_check(info, tty->name, "mgsl_close"))
+	if (mgsl_paranoia_check(info, tty->name, "mgsl_close"))
 		return;
 	
 	if (debug_level >= DEBUG_LEVEL_INFO)
 		printk("%s(%d):mgsl_close(%s) entry, count=%d\n",
 			 __FILE__,__LINE__, info->device_name, info->count);
 			 
-	if (!info->count || tty_hung_up_p(filp))
+	if (!info->count)
+		return;
+
+	if (tty_hung_up_p(filp))
 		goto cleanup;
 			
 	if ((tty->count == 1) && (info->count != 1)) {
@@ -3493,16 +3496,11 @@
 	info = mgsl_device_list;
 	while(info && info->line != line)
 		info = info->next_device;
-	if ( !info ){
-		printk("%s(%d):Can't find specified device on open (line=%d)\n",
-			__FILE__,__LINE__,line);
+	if (mgsl_paranoia_check(info, tty->name, "mgsl_open"))
 		return -ENODEV;
-	}
 	
 	tty->driver_data = info;
 	info->tty = tty;
-	if (mgsl_paranoia_check(info, tty->name, "mgsl_open"))
-		return -ENODEV;
 		
 	if (debug_level >= DEBUG_LEVEL_INFO)
 		printk("%s(%d):mgsl_open(%s), old ref count = %d\n",
@@ -3562,6 +3560,8 @@
 	
 cleanup:			
 	if (retval) {
+		if (tty->count == 1)
+			info->tty = 0; /* tty layer will release tty struct */
 		if(info->count)
 			info->count--;
 	}
@@ -4461,7 +4461,6 @@
 int mgsl_init_tty(void);
 int mgsl_init_tty()
 {
-	struct mgsl_struct *info;
 	serial_driver = alloc_tty_driver(mgsl_device_count);
 	if (!serial_driver)
 		return -ENOMEM;
diff -Nru a/drivers/char/synclinkmp.c b/drivers/char/synclinkmp.c
--- a/drivers/char/synclinkmp.c	Wed Jun 11 12:32:41 2003
+++ b/drivers/char/synclinkmp.c	Wed Jun 18 08:31:01 2003
@@ -1,5 +1,5 @@
 /*
- * $Id: synclinkmp.c,v 4.8 2003/04/21 17:46:55 paulkf Exp $
+ * $Id: synclinkmp.c,v 4.12 2003/06/18 15:29:33 paulkf Exp $
  *
  * Device driver for Microgate SyncLink Multiport
  * high speed multiprotocol serial adapter.
@@ -481,7 +481,6 @@
  * assigned major number. May be forced as module parameter.
  */
 static int ttymajor=0;
-static int cuamajor=0;
 
 /*
  * Array of user specified options for ISA adapters.
@@ -492,13 +491,12 @@
 
 MODULE_PARM(break_on_load,"i");
 MODULE_PARM(ttymajor,"i");
-MODULE_PARM(cuamajor,"i");
 MODULE_PARM(debug_level,"i");
 MODULE_PARM(maxframe,"1-" __MODULE_STRING(MAX_DEVICES) "i");
 MODULE_PARM(dosyncppp,"1-" __MODULE_STRING(MAX_DEVICES) "i");
 
 static char *driver_name = "SyncLink MultiPort driver";
-static char *driver_version = "$Revision: 4.8 $";
+static char *driver_version = "$Revision: 4.12 $";
 
 static int synclinkmp_init_one(struct pci_dev *dev,const struct pci_device_id *ent);
 static void synclinkmp_remove_one(struct pci_dev *dev);
@@ -739,12 +737,8 @@
 	info = synclinkmp_device_list;
 	while(info && info->line != line)
 		info = info->next_device;
-	if ( !info ){
-		printk("%s(%d):%s Can't find specified device on open (line=%d)\n",
-			__FILE__,__LINE__,info->device_name,line);
+	if (sanity_check(info, tty->name, "open"))
 		return -ENODEV;
-	}
-
 	if ( info->init_error ) {
 		printk("%s(%d):%s device is not allocated, init error=%d\n",
 			__FILE__,__LINE__,info->device_name,info->init_error);
@@ -753,8 +747,6 @@
 
 	tty->driver_data = info;
 	info->tty = tty;
-	if (sanity_check(info, tty->name, "open"))
-		return -ENODEV;
 
 	if (debug_level >= DEBUG_LEVEL_INFO)
 		printk("%s(%d):%s open(), old ref count = %d\n",
@@ -802,6 +794,8 @@
 
 cleanup:
 	if (retval) {
+		if (tty->count == 1)
+			info->tty = 0; /* tty layer will release tty struct */
 		if(info->count)
 			info->count--;
 	}
@@ -816,14 +810,17 @@
 {
 	SLMP_INFO * info = (SLMP_INFO *)tty->driver_data;
 
-	if (!info || sanity_check(info, tty->name, "close"))
+	if (sanity_check(info, tty->name, "close"))
 		return;
 
 	if (debug_level >= DEBUG_LEVEL_INFO)
 		printk("%s(%d):%s close() entry, count=%d\n",
 			 __FILE__,__LINE__, info->device_name, info->count);
 
-	if (!info->count || tty_hung_up_p(filp))
+	if (!info->count)
+		return;
+
+	if (tty_hung_up_p(filp))
 		goto cleanup;
 
 	if ((tty->count == 1) && (info->count != 1)) {
@@ -3775,8 +3772,6 @@
 
 static int __init synclinkmp_init(void)
 {
-	SLMP_INFO *info;
-
 	if (break_on_load) {
 	 	synclinkmp_get_text_ptr();
   		BREAKPOINT();
diff -Nru a/drivers/eisa/eisa-bus.c b/drivers/eisa/eisa-bus.c
--- a/drivers/eisa/eisa-bus.c	Sun May 25 17:00:00 2003
+++ b/drivers/eisa/eisa-bus.c	Fri Jul  4 00:41:28 2003
@@ -1,7 +1,7 @@
 /*
  * EISA bus support functions for sysfs.
  *
- * (C) 2002 Marc Zyngier <maz@wild-wind.fr.eu.org>
+ * (C) 2002, 2003 Marc Zyngier <maz@wild-wind.fr.eu.org>
  *
  * This code is released under the GPL version 2.
  */
@@ -10,6 +10,7 @@
 #include <linux/device.h>
 #include <linux/eisa.h>
 #include <linux/module.h>
+#include <linux/moduleparam.h>
 #include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/ioport.h>
@@ -24,7 +25,7 @@
 	char name[DEVICE_NAME_SIZE];
 };
 
-struct eisa_device_info __initdata eisa_table[] = {
+static struct eisa_device_info __initdata eisa_table[] = {
 #ifdef CONFIG_EISA_NAMES
 #include "devlist.h"
 #endif
@@ -32,6 +33,30 @@
 
 #define EISA_INFOS (sizeof (eisa_table) / (sizeof (struct eisa_device_info)))
 
+#define EISA_MAX_FORCED_DEV 16
+#define EISA_FORCED_OFFSET  2
+
+static int enable_dev[EISA_MAX_FORCED_DEV + EISA_FORCED_OFFSET]  = { 1, EISA_MAX_FORCED_DEV, };
+static int disable_dev[EISA_MAX_FORCED_DEV + EISA_FORCED_OFFSET] = { 1, EISA_MAX_FORCED_DEV, };
+
+static int is_forced_dev (int *forced_tab,
+			  struct eisa_root_device *root,
+			  struct eisa_device *edev)
+{
+	int i, x;
+
+	for (i = 0; i < EISA_MAX_FORCED_DEV; i++) {
+		if (!forced_tab[EISA_FORCED_OFFSET + i])
+			return 0;
+
+		x = (root->bus_nr << 8) | edev->slot;
+		if (forced_tab[EISA_FORCED_OFFSET + i] == x)
+			return 1;
+	}
+
+	return 0;
+}
+
 static void __init eisa_name_device (struct eisa_device *edev)
 {
 	int i;
@@ -92,7 +117,8 @@
 		return 0;
 
 	while (strlen (eids->sig)) {
-		if (!strcmp (eids->sig, edev->id.sig)) {
+		if (!strcmp (eids->sig, edev->id.sig) &&
+		    edev->state & EISA_CONFIG_ENABLED) {
 			edev->id.driver_data = eids->driver_data;
 			return 1;
 		}
@@ -132,41 +158,160 @@
 
 static DEVICE_ATTR(signature, S_IRUGO, eisa_show_sig, NULL);
 
-static int __init eisa_register_device (struct eisa_root_device *root,
-					struct eisa_device *edev,
-					char *sig, int slot)
+static ssize_t eisa_show_state (struct device *dev, char *buf)
+{
+        struct eisa_device *edev = to_eisa_device (dev);
+        return sprintf (buf,"%d\n", edev->state & EISA_CONFIG_ENABLED);
+}
+
+static DEVICE_ATTR(enabled, S_IRUGO, eisa_show_state, NULL);
+
+static int __init eisa_init_device (struct eisa_root_device *root,
+				    struct eisa_device *edev,
+				    int slot)
 {
+	char *sig;
+        unsigned long sig_addr;
+	int i;
+
+	sig_addr = SLOT_ADDRESS (root, slot) + EISA_VENDOR_ID_OFFSET;
+
+	if (!(sig = decode_eisa_sig (sig_addr)))
+		return -1;	/* No EISA device here */
+	
 	memcpy (edev->id.sig, sig, EISA_SIG_LEN);
 	edev->slot = slot;
+	edev->state = inb (SLOT_ADDRESS (root, slot) + EISA_CONFIG_OFFSET) & EISA_CONFIG_ENABLED;
 	edev->base_addr = SLOT_ADDRESS (root, slot);
-	edev->dma_mask = 0xffffffff; /* Default DMA mask */
+	edev->dma_mask = root->dma_mask; /* Default DMA mask */
 	eisa_name_device (edev);
 	edev->dev.parent = root->dev;
 	edev->dev.bus = &eisa_bus_type;
 	edev->dev.dma_mask = &edev->dma_mask;
 	sprintf (edev->dev.bus_id, "%02X:%02X", root->bus_nr, slot);
 
-	edev->res.name  = edev->dev.name;
+	for (i = 0; i < EISA_MAX_RESOURCES; i++)
+		edev->res[i].name  = edev->dev.name;
+
+	if (is_forced_dev (enable_dev, root, edev))
+		edev->state = EISA_CONFIG_ENABLED | EISA_CONFIG_FORCED;
+	
+	if (is_forced_dev (disable_dev, root, edev))
+		edev->state = EISA_CONFIG_FORCED;
+
+	return 0;
+}
 
+static int __init eisa_register_device (struct eisa_device *edev)
+{
 	if (device_register (&edev->dev))
 		return -1;
 
 	device_create_file (&edev->dev, &dev_attr_signature);
+	device_create_file (&edev->dev, &dev_attr_enabled);
+
+	return 0;
+}
+
+static int __init eisa_request_resources (struct eisa_root_device *root,
+					  struct eisa_device *edev,
+					  int slot)
+{
+	int i;
+
+	for (i = 0; i < EISA_MAX_RESOURCES; i++) {
+		/* Don't register resource for slot 0, since this is
+		 * very likely to fail... :-( Instead, grab the EISA
+		 * id, now we can display something in /proc/ioports.
+		 */
+
+		/* Only one region for mainboard */
+		if (!slot && i > 0) {
+			edev->res[i].start = edev->res[i].end = 0;
+			continue;
+		}
+		
+		if (slot) {
+			edev->res[i].name  = NULL;
+			edev->res[i].start = SLOT_ADDRESS (root, slot) + (i * 0x400);
+			edev->res[i].end   = edev->res[i].start + 0xff;
+			edev->res[i].flags = IORESOURCE_IO;
+		} else {
+			edev->res[i].name  = NULL;
+			edev->res[i].start = SLOT_ADDRESS (root, slot) + EISA_VENDOR_ID_OFFSET;
+			edev->res[i].end   = edev->res[i].start + 3;
+			edev->res[i].flags = IORESOURCE_BUSY;
+		}
+
+		if (request_resource (root->res, &edev->res[i]))
+			goto failed;
+	}
 
 	return 0;
+	
+ failed:
+	while (--i >= 0)
+		release_resource (&edev->res[i]);
+
+	return -1;
+}
+
+static void __init eisa_release_resources (struct eisa_device *edev)
+{
+	int i;
+
+	for (i = 0; i < EISA_MAX_RESOURCES; i++)
+		if (edev->res[i].start || edev->res[i].end)
+			release_resource (&edev->res[i]);
 }
 
 static int __init eisa_probe (struct eisa_root_device *root)
 {
         int i, c;
-        char *str;
-        unsigned long sig_addr;
 	struct eisa_device *edev;
 
         printk (KERN_INFO "EISA: Probing bus %d at %s\n",
 		root->bus_nr, root->dev->name);
+
+	/* First try to get hold of slot 0. If there is no device
+	 * here, simply fail, unless root->force_probe is set. */
+	
+	if (!(edev = kmalloc (sizeof (*edev), GFP_KERNEL))) {
+		printk (KERN_ERR "EISA: Couldn't allocate mainboard slot\n");
+		return -ENOMEM;
+	}
+		
+	memset (edev, 0, sizeof (*edev));
+
+	if (eisa_request_resources (root, edev, 0)) {
+		printk (KERN_WARNING \
+			"EISA: Cannot allocate resource for mainboard\n");
+		kfree (edev);
+		if (!root->force_probe)
+			return -EBUSY;
+		goto force_probe;
+	}
+
+	if (eisa_init_device (root, edev, 0)) {
+		eisa_release_resources (edev);
+		kfree (edev);
+		if (!root->force_probe)
+			return -ENODEV;
+		goto force_probe;
+	}
+
+	printk (KERN_INFO "EISA: Mainboard %s detected.\n", edev->id.sig);
+
+	if (eisa_register_device (edev)) {
+		printk (KERN_ERR "EISA: Failed to register %s\n",
+			edev->id.sig);
+		eisa_release_resources (edev);
+		kfree (edev);
+	}
 	
-        for (c = 0, i = 0; i <= root->slots; i++) {
+ force_probe:
+	
+        for (c = 0, i = 1; i <= root->slots; i++) {
 		if (!(edev = kmalloc (sizeof (*edev), GFP_KERNEL))) {
 			printk (KERN_ERR "EISA: Out of memory for slot %d\n",
 				i);
@@ -175,24 +320,7 @@
 		
 		memset (edev, 0, sizeof (*edev));
 
-		/* Don't register resource for slot 0, since this is
-		 * very likely to fail... :-( Instead, grab the EISA
-		 * id, now we can display something in /proc/ioports.
-		 */
-
-		if (i) {
-			edev->res.name  = NULL;
-			edev->res.start = SLOT_ADDRESS (root, i);
-			edev->res.end   = edev->res.start + 0xfff;
-			edev->res.flags = IORESOURCE_IO;
-		} else {
-			edev->res.name  = NULL;
-			edev->res.start = SLOT_ADDRESS (root, i) + EISA_VENDOR_ID_OFFSET;
-			edev->res.end   = edev->res.start + 3;
-			edev->res.flags = IORESOURCE_BUSY;
-		}
-	
-		if (request_resource (root->res, &edev->res)) {
+		if (eisa_request_resources (root, edev, i)) {
 			printk (KERN_WARNING \
 				"Cannot allocate resource for EISA slot %d\n",
 				i);
@@ -200,30 +328,41 @@
 			continue;
 		}
 
-		sig_addr = SLOT_ADDRESS (root, i) + EISA_VENDOR_ID_OFFSET;
-
-                if (!(str = decode_eisa_sig (sig_addr))) {
-			release_resource (&edev->res);
+                if (eisa_init_device (root, edev, i)) {
+			eisa_release_resources (edev);
 			kfree (edev);
 			continue;
 		}
 		
-		if (!i)
-			printk (KERN_INFO "EISA: Motherboard %s detected\n",
-				str);
-		else {
-			printk (KERN_INFO "EISA: slot %d : %s detected.\n",
-				i, str);
-
-			c++;
+		printk (KERN_INFO "EISA: slot %d : %s detected",
+			i, edev->id.sig);
+			
+		switch (edev->state) {
+		case EISA_CONFIG_ENABLED | EISA_CONFIG_FORCED:
+			printk (" (forced enabled)");
+			break;
+
+		case EISA_CONFIG_FORCED:
+			printk (" (forced disabled)");
+			break;
+
+		case 0:
+			printk (" (disabled)");
+			break;
 		}
+			
+		printk (".\n");
+
+		c++;
 
-		if (eisa_register_device (root, edev, str, i)) {
-			printk (KERN_ERR "EISA: Failed to register %s\n", str);
-			release_resource (&edev->res);
+		if (eisa_register_device (edev)) {
+			printk (KERN_ERR "EISA: Failed to register %s\n",
+				edev->id.sig);
+			eisa_release_resources (edev);
 			kfree (edev);
 		}
         }
+
         printk (KERN_INFO "EISA: Detected %d card%s.\n", c, c == 1 ? "" : "s");
 
 	return 0;
@@ -273,6 +412,13 @@
 	printk (KERN_INFO "EISA bus registered\n");
 	return 0;
 }
+
+/* Couldn't use intarray with checking on... :-( */
+#undef  param_check_intarray
+#define param_check_intarray(name, p)
+
+module_param(enable_dev,  intarray, 0444);
+module_param(disable_dev, intarray, 0444);
 
 postcore_initcall (eisa_init);
 
diff -Nru a/drivers/eisa/eisa.ids b/drivers/eisa/eisa.ids
--- a/drivers/eisa/eisa.ids	Mon Apr 21 09:19:07 2003
+++ b/drivers/eisa/eisa.ids	Fri Jul  4 00:39:32 2003
@@ -504,6 +504,7 @@
 DTK0003 "DTK PLM-3331P EISACACHE486 33/25/50 MHZ"
 ECS0580 "DI-580A EISA SCSI Host Adapter"
 ECS0590 "DI-590 EISA SCSI Cache Host Adapter"
+EGL0101 "Eagle Technology EP3210 EtherXpert EISA Adapter"
 ELS8041 "ELSA  WINNER 1000  Enhanced VGA"
 ETI1001 "NE3300 Ethernet Rev. C & D"
 EVX0002 "PN-3000 System Board"
@@ -515,6 +516,9 @@
 FSI2001 "ESA-200 ATM"
 FSI2002 "ESA-200A ATM"
 FSI2003 "ESA-200E ATM"
+GCI0101 "Gateway G/Ethernet 32EB -- 32-Bit EISA Bus Master Ethernet Adpater"
+GCI0102 "Gateway G/Ethernet 32EB -- 32-Bit EISA Bus Master Ethernet Adapter"
+GCI0103 "Gateway G/Ethernet 32EB -- 32-Bit EISA Bus Master Ethernet Adapter"
 GDT2001 "GDT2000/GDT2020 Fast-SCSI Cache Controller - Rev. 1.0"
 GDT3001 "GDT3000/GDT3020 Dual Channel SCSI Controller - Rev. 1.0"
 GDT3002 "GDT30x0A Cache Controller"
@@ -1138,12 +1142,14 @@
 NON0601 "c't Universal 8-Bit Adapter"
 NSS0011 "Newport Systems Solutions WNIC Adapter"
 NVL0701 "Novell NE3200 Bus Master Ethernet"
+NVL0702 "Novell NE3200T Bus Master Ethernet"
 NVL0901 "Novell NE2100 Ethernet/Cheapernet Adapter"
 NVL1001 "Novell NMSL (Netware Mirrored Server Link)"
 NVL1201 "Novell NE32HUB 32-bit Base EISA Adapter"
 NVL1301 "Novell NE32HUB 32-bit TPE EISA Adapter"
 NVL1401 "Novell NE32HUB PME ISA Adapter"
 NVL1501 "Novell NE2000PLUS Ethernet Adapter"
+NVL1801 "Eagle Technology NE3210 EISA Ethernet LAN Adapter"
 OLC0701 "Olicom ISA 16/4 Token-Ring Network Adapter"
 OLC0702 "Olicom OC-3117, ISA 16/4 Adapter (NIC)"
 OLC0801 "OC-3118 Olicom ISA 16/4 Token-Ring Network Adapter"
diff -Nru a/drivers/eisa/pci_eisa.c b/drivers/eisa/pci_eisa.c
--- a/drivers/eisa/pci_eisa.c	Sat Feb 15 04:56:07 2003
+++ b/drivers/eisa/pci_eisa.c	Fri Jul  4 00:40:43 2003
@@ -20,7 +20,7 @@
 static struct eisa_root_device pci_eisa_root;
 
 static int __devinit pci_eisa_init (struct pci_dev *pdev,
-				  const struct pci_device_id *ent)
+				    const struct pci_device_id *ent)
 {
 	int rc;
 
@@ -35,6 +35,7 @@
 	pci_eisa_root.res	       = pdev->bus->resource[0];
 	pci_eisa_root.bus_base_addr    = pdev->bus->resource[0]->start;
 	pci_eisa_root.slots	       = EISA_MAX_SLOTS;
+	pci_eisa_root.dma_mask         = pdev->dma_mask;
 
 	if (eisa_root_register (&pci_eisa_root)) {
 		printk (KERN_ERR "pci_eisa : Could not register EISA root\n");
diff -Nru a/drivers/eisa/virtual_root.c b/drivers/eisa/virtual_root.c
--- a/drivers/eisa/virtual_root.c	Wed Mar  5 07:11:17 2003
+++ b/drivers/eisa/virtual_root.c	Fri Jul  4 00:45:31 2003
@@ -7,12 +7,22 @@
  * This code is released under the GPL version 2.
  */
 
+#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/device.h>
 #include <linux/eisa.h>
 #include <linux/module.h>
+#include <linux/moduleparam.h>
 #include <linux/init.h>
 
+#if defined(CONFIG_ALPHA_JENSEN) || defined(CONFIG_EISA_VLB_PRIMING)
+#define EISA_FORCE_PROBE_DEFAULT 1
+#else
+#define EISA_FORCE_PROBE_DEFAULT 0
+#endif
+
+static int force_probe = EISA_FORCE_PROBE_DEFAULT;
+
 /* The default EISA device parent (virtual root device).
  * Now use a platform device, since that's the obvious choice. */
 
@@ -29,6 +39,7 @@
 	.bus_base_addr = 0,
 	.res	       = &ioport_resource,
 	.slots	       = EISA_MAX_SLOTS,
+	.dma_mask      = 0xffffffff,
 };
 
 static int virtual_eisa_root_init (void)
@@ -39,6 +50,8 @@
                 return r;
         }
 
+	eisa_bus_root.force_probe = force_probe;
+	
 	eisa_root_dev.dev.driver_data = &eisa_bus_root;
 
 	if (eisa_root_register (&eisa_bus_root)) {
@@ -50,5 +63,7 @@
 
 	return 0;
 }
+
+module_param (force_probe, int, 0444);
 
 device_initcall (virtual_eisa_root_init);
diff -Nru a/drivers/ide/ppc/pmac.c b/drivers/ide/ppc/pmac.c
--- a/drivers/ide/ppc/pmac.c	Sat May 17 08:31:07 2003
+++ b/drivers/ide/ppc/pmac.c	Thu Jul  3 17:00:00 2003
@@ -1514,6 +1514,8 @@
 	ide_hwifs[ix].ide_dma_timeout = &__ide_dma_timeout;
 	ide_hwifs[ix].ide_dma_retune = &__ide_dma_retune;
 	ide_hwifs[ix].ide_dma_lostirq = &pmac_ide_dma_lostirq;
+	ide_hwifs[ix].ide_dma_queued_on = &__ide_dma_queued_on;
+	ide_hwifs[ix].ide_dma_queued_off = &__ide_dma_queued_off;
 
 #ifdef CONFIG_BLK_DEV_IDEDMA_PMAC_AUTO
 	if (!noautodma)
diff -Nru a/drivers/ieee1394/sbp2.c b/drivers/ieee1394/sbp2.c
--- a/drivers/ieee1394/sbp2.c	Tue Jun 24 20:47:32 2003
+++ b/drivers/ieee1394/sbp2.c	Thu Jul  3 00:39:27 2003
@@ -56,6 +56,8 @@
 #include <linux/smp_lock.h>
 #include <linux/init.h>
 #include <linux/version.h>
+#include <linux/pci.h>
+
 #include <asm/current.h>
 #include <asm/uaccess.h>
 #include <asm/io.h>
diff -Nru a/drivers/macintosh/macserial.c b/drivers/macintosh/macserial.c
--- a/drivers/macintosh/macserial.c	Wed Jun 11 12:32:36 2003
+++ b/drivers/macintosh/macserial.c	Tue Jun 17 04:57:19 2003
@@ -76,6 +76,8 @@
    in the order we want. */
 #define RECOVERY_DELAY	eieio()
 
+static struct tty_driver *serial_driver;
+
 struct mac_zschannel zs_channels[NUM_CHANNELS];
 
 struct mac_serial zs_soft[NUM_CHANNELS];
@@ -2093,12 +2095,7 @@
 	 */
 	if (info->flags & ZILOG_CLOSING) {
 		interruptible_sleep_on(&info->close_wait);
-#ifdef SERIAL_DO_RESTART
-		return ((info->flags & ZILOG_HUP_NOTIFY) ?
-			-EAGAIN : -ERESTARTSYS);
-#else
 		return -EAGAIN;
-#endif
 	}
 
 	/*
@@ -2139,14 +2136,7 @@
 		set_current_state(TASK_INTERRUPTIBLE);
 		if (tty_hung_up_p(filp) ||
 		    !(info->flags & ZILOG_INITIALIZED)) {
-#ifdef SERIAL_DO_RESTART
-			if (info->flags & ZILOG_HUP_NOTIFY)
-				retval = -EAGAIN;
-			else
-				retval = -ERESTARTSYS;
-#else
 			retval = -EAGAIN;
-#endif
 			break;
 		}
 		if (!(info->flags & ZILOG_CLOSING) &&
@@ -2222,12 +2212,7 @@
 	    (info->flags & ZILOG_CLOSING)) {
 		if (info->flags & ZILOG_CLOSING)
 			interruptible_sleep_on(&info->close_wait);
-#ifdef SERIAL_DO_RESTART
-		return ((info->flags & ZILOG_HUP_NOTIFY) ?
-			-EAGAIN : -ERESTARTSYS);
-#else
 		return -EAGAIN;
-#endif
 	}
 
 	/*
diff -Nru a/drivers/message/i2o/i2o_scsi.c b/drivers/message/i2o/i2o_scsi.c
--- a/drivers/message/i2o/i2o_scsi.c	Sun Jun  8 12:18:41 2003
+++ b/drivers/message/i2o/i2o_scsi.c	Fri Jul  4 23:52:59 2003
@@ -49,6 +49,7 @@
 #include <linux/delay.h>
 #include <linux/proc_fs.h>
 #include <linux/prefetch.h>
+#include <linux/pci.h>
 #include <asm/dma.h>
 #include <asm/system.h>
 #include <asm/io.h>
diff -Nru a/drivers/mtd/mtd_blkdevs.c b/drivers/mtd/mtd_blkdevs.c
--- a/drivers/mtd/mtd_blkdevs.c	Mon Jun 23 06:35:33 2003
+++ b/drivers/mtd/mtd_blkdevs.c	Fri Jul  4 23:52:57 2003
@@ -211,9 +211,10 @@
 	case HDIO_GETGEO:
 		if (tr->getgeo) {
 			struct hd_geometry g;
+			int ret;
 
 			memset(&g, 0, sizeof(g));
-			int ret = tr->getgeo(dev, &g);
+			ret = tr->getgeo(dev, &g);
 			if (ret)
 				return ret;
 
diff -Nru a/drivers/net/Kconfig b/drivers/net/Kconfig
--- a/drivers/net/Kconfig	Wed Jun 25 14:16:04 2003
+++ b/drivers/net/Kconfig	Wed Jul  2 21:21:29 2003
@@ -1397,7 +1397,7 @@
 
 config TC35815
 	tristate "TOSHIBA TC35815 Ethernet support"
-	depends on NET_PCI && PCI
+	depends on NET_PCI && PCI && TOSHIBA_JMR3927
 
 config DGRS
 	tristate "Digi Intl. RightSwitch SE-X support"
diff -Nru a/drivers/net/e100/e100_main.c b/drivers/net/e100/e100_main.c
--- a/drivers/net/e100/e100_main.c	Sun Jun  1 15:50:09 2003
+++ b/drivers/net/e100/e100_main.c	Thu Jun 26 17:35:25 2003
@@ -1085,9 +1085,9 @@
 		goto exit1;
 	}
 
-	e100_prepare_xmit_buff(bdp, skb);
-
 	bdp->drv_stats.net_stats.tx_bytes += skb->len;
+
+	e100_prepare_xmit_buff(bdp, skb);
 
 	dev->trans_start = jiffies;
 
diff -Nru a/drivers/net/irda/irtty-sir.c b/drivers/net/irda/irtty-sir.c
--- a/drivers/net/irda/irtty-sir.c	Mon May 12 10:53:09 2003
+++ b/drivers/net/irda/irtty-sir.c	Tue May 27 01:52:33 2003
@@ -212,13 +212,6 @@
 /* called from sir_dev when there is more data to send
  * context is either netdev->hard_xmit or some transmit-completion bh
  * i.e. we are under spinlock here and must not sleep.
- *
- * Note: as of 2.5.44 the usb-serial driver calls down() on a semaphore
- * hence we are hitting the might_sleep bugcatcher. IMHO the whole tty-api
- * would be pretty pointless if write_room/write would be allowed to sleep.
- * Furthermore other tty ldiscs (like ppp) do also require the driver not
- * to sleep there. Hence this is considered a current limitation of
- * usb-serial.
  */
 
 static int irtty_do_write(struct sir_dev *dev, const unsigned char *ptr, size_t len)
@@ -269,16 +262,15 @@
 	struct sirtty_cb *priv = tty->disc_data;
 	int	i;
 
-	if (unlikely(!priv || priv->magic!=IRTTY_MAGIC))
-		return;
-	/* Please use ASSERT - Fix ASSERT as needed - Jean II */
+	ASSERT(priv != NULL, return;);
+	ASSERT(priv->magic == IRTTY_MAGIC, return;);
 
 	if (unlikely(count==0))		/* yes, this happens */
 		return;
 
 	dev = priv->dev;
 	if (!dev) {
-		printk(KERN_ERR "%s(), not ready yet!\n", __FUNCTION__);
+		WARNING("%s(), not ready yet!\n", __FUNCTION__);
 		return;
 	}
 
@@ -306,8 +298,8 @@
 {
 	struct sirtty_cb *priv = tty->disc_data;
 
-	if (unlikely(!priv || priv->magic!=IRTTY_MAGIC))
-		return 0;
+	ASSERT(priv != NULL, return 0;);
+	ASSERT(priv->magic == IRTTY_MAGIC, return 0;);
 
 	return 65536;  /* We can handle an infinite amount of data. :-) */
 }
@@ -323,8 +315,8 @@
 {
 	struct sirtty_cb *priv = tty->disc_data;
 
-	if (unlikely(!priv || priv->magic!=IRTTY_MAGIC))
-		return;
+	ASSERT(priv != NULL, return;);
+	ASSERT(priv->magic == IRTTY_MAGIC, return;);
 
 	tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP);
 
@@ -559,7 +551,7 @@
 
 	up(&irtty_sem);
 
-	printk(KERN_INFO "%s - done\n", __FUNCTION__);
+	IRDA_DEBUG(0, "%s - %s: irda line discipline opened\n", __FUNCTION__, tty->name);
 
 	return 0;
 
@@ -580,8 +572,8 @@
 {
 	struct sirtty_cb *priv = tty->disc_data;
 
-	if (!priv  ||  priv->magic != IRTTY_MAGIC)
-		return;
+	ASSERT(priv != NULL, return;);
+	ASSERT(priv->magic == IRTTY_MAGIC, return;);
 
 	/* Hm, with a dongle attached the dongle driver wants
 	 * to close the dongle - which requires the use of
@@ -610,6 +602,8 @@
 		tty->driver->stop(tty);
 
 	kfree(priv);
+
+	IRDA_DEBUG(0, "%s - %s: irda line discipline closed\n", __FUNCTION__, tty->name);
 }
 
 /* ------------------------------------------------------- */
diff -Nru a/drivers/net/irda/sir_dev.c b/drivers/net/irda/sir_dev.c
--- a/drivers/net/irda/sir_dev.c	Thu Feb 20 03:11:44 2003
+++ b/drivers/net/irda/sir_dev.c	Tue May 27 01:52:33 2003
@@ -201,14 +201,12 @@
 int sirdev_receive(struct sir_dev *dev, const unsigned char *cp, size_t count) 
 {
 	if (!dev || !dev->netdev) {
-		IRDA_DEBUG(0, "%s(), not ready yet!\n", __FUNCTION__);
-		/* Use WARNING instead of IRDA_DEBUG */
+		WARNING("%s(), not ready yet!\n", __FUNCTION__);
 		return -1;
 	}
 
 	if (!dev->irlap) {
-		IRDA_DEBUG(0, "%s - too early: %p / %d!\n", __FUNCTION__, cp, count);
-		/* Use WARNING instead of IRDA_DEBUG */
+		WARNING("%s - too early: %p / %d!\n", __FUNCTION__, cp, count);
 		return -1;
 	}
 
@@ -218,7 +216,7 @@
 		 */
 		irda_device_set_media_busy(dev->netdev, TRUE);
 		dev->stats.rx_dropped++;
-		printk(KERN_INFO "%s; rx-drop: %d\n", __FUNCTION__, count);
+		IRDA_DEBUG(0, "%s; rx-drop: %d\n", __FUNCTION__, count);
 		return 0;
 	}
 
@@ -431,7 +429,6 @@
 		return -ENOMEM;
 	skb_reserve(dev->rx_buff.skb, 1);
 	dev->rx_buff.head = dev->rx_buff.skb->data;
-	/* No need to memset the buffer, unless you are really pedantic */
 
 	dev->tx_buff.head = kmalloc(dev->tx_buff.truesize, GFP_KERNEL);
 	if (dev->tx_buff.head == NULL) {
@@ -439,8 +436,6 @@
 		dev->rx_buff.skb = NULL;
 		dev->rx_buff.head = NULL;
 		return -ENOMEM;
-		/* Hu ??? This should not be here, Martin ? */
-		memset(dev->tx_buff.head, 0, dev->tx_buff.truesize);
 	}
 
 	dev->tx_buff.data = dev->tx_buff.head;
@@ -492,7 +487,7 @@
 
 	netif_wake_queue(ndev);
 
-	printk(KERN_INFO "%s - done, speed = %d\n", __FUNCTION__, dev->speed);
+	IRDA_DEBUG(2, "%s - done, speed = %d\n", __FUNCTION__, dev->speed);
 
 	return 0;
 
@@ -512,7 +507,7 @@
 	struct sir_dev *dev = ndev->priv;
 	const struct sir_driver *drv;
 
-	printk(KERN_INFO "%s\n", __FUNCTION__);
+//	IRDA_DEBUG(0, "%s\n", __FUNCTION__);
 
 	netif_stop_queue(ndev);
 
@@ -570,7 +565,7 @@
 	struct net_device *ndev;
 	struct sir_dev *dev;
 
-	printk(KERN_INFO "%s - %s\n", __FUNCTION__, name);
+	IRDA_DEBUG(0, "%s - %s\n", __FUNCTION__, name);
 
 	/* instead of adding tests to protect against drv->do_write==NULL
 	 * at several places we refuse to create a sir_dev instance for
@@ -584,8 +579,7 @@
 	 */
 	dev = kmalloc(sizeof(*dev), GFP_KERNEL);
 	if (dev == NULL) {
-		printk(KERN_ERR "IrDA: Can't allocate memory for "
-		       "IrDA control block!\n");
+		ERROR("%s - Can't allocate memory for IrDA control block!\n", __FUNCTION__);
 		goto out;
 	}
 	memset(dev, 0, sizeof(*dev));
@@ -638,7 +632,7 @@
 {
 	int err = 0;
 
-	printk(KERN_INFO "%s\n", __FUNCTION__);
+	IRDA_DEBUG(0, "%s\n", __FUNCTION__);
 
 	atomic_set(&dev->enable_rx, 0);
 
diff -Nru a/drivers/net/irda/sir_kthread.c b/drivers/net/irda/sir_kthread.c
--- a/drivers/net/irda/sir_kthread.c	Mon May 12 10:55:49 2003
+++ b/drivers/net/irda/sir_kthread.c	Mon Jun 30 13:46:34 2003
@@ -19,6 +19,7 @@
 #include <linux/smp_lock.h>
 #include <linux/completion.h>
 #include <linux/delay.h>
+#include <linux/suspend.h>
 
 #include <net/irda/irda.h>
 
@@ -107,44 +108,12 @@
 	spin_unlock_irqrestore(&irda_rq_queue.lock, flags);
 }		
 
-static int irda_rt_prio = 0;		/* MODULE_PARM? */
-
 static int irda_thread(void *startup)
 {
 	DECLARE_WAITQUEUE(wait, current);
 
 	daemonize("kIrDAd");
 
-	set_fs(KERNEL_DS);
-
-	if (irda_rt_prio > 0) {
-#if 0		/* works but requires EXPORT_SYMBOL(setscheduler) */
-		struct sched_param param;
-
-		param.sched_priority = irda_rt_prio;
-		setscheduler(0, SCHED_FIFO, &param);
-#endif
-
-#if 0		/* doesn't work - has some tendency to trigger instant reboot!
-		 * looks like we would have to deactivate current on the
-		 * runqueue - which is only possible inside of kernel/sched.h
-		 */
-
-		/* runqueues are per-cpu and we are current on this cpu. Hence
-		 * The tasklist_lock with irq-off protects our runqueue too
-		 * and we don't have to lock it (which would be impossible,
-		 * because it is private in kernel/sched.c)
-		 */
-
-		read_lock_irq(&tasklist_lock);
-		current->rt_priority = (irda_rt_prio<MAX_RT_PRIO)
-					? irda_rt_prio : MAX_RT_PRIO-1;
-		current->policy = SCHED_FIFO;
-		current->prio = MAX_USER_RT_PRIO-1 - irda_rt_prio;
-		read_unlock_irq(&tasklist_lock);
-#endif
-	}
-
 	irda_rq_queue.thread = current;
 
 	complete((struct completion *)startup);
@@ -166,6 +135,10 @@
 			set_task_state(current, TASK_RUNNING);
 		remove_wait_queue(&irda_rq_queue.kick, &wait);
 
+		/* make swsusp happy with our thread */
+		if (current->flags & PF_FREEZE)
+			refrigerator(PF_IOTHREAD);
+
 		run_irda_queue();
 	}
 
@@ -442,7 +415,6 @@
 		case SIRDEV_STATE_COMPLETE:
 			/* config change finished, so we are not busy any longer */
 			sirdev_enable_rx(dev);
-			printk(KERN_INFO "%s - up\n", __FUNCTION__);
 			up(&fsm->sem);
 			return;
 		}
@@ -462,9 +434,7 @@
 	struct sir_fsm *fsm = &dev->fsm;
 	int xmit_was_down;
 
-//	IRDA_DEBUG(2, "%s - state=0x%04x / param=%u\n", __FUNCTION__, initial_state, param);
-
-	printk(KERN_INFO "%s - state=0x%04x / param=%u\n", __FUNCTION__, initial_state, param);
+	IRDA_DEBUG(2, "%s - state=0x%04x / param=%u\n", __FUNCTION__, initial_state, param);
 
 	if (in_interrupt()) {
 		if (down_trylock(&fsm->sem)) {
@@ -474,12 +444,10 @@
 	}
 	else
 		down(&fsm->sem);
-	printk(KERN_INFO "%s - down\n", __FUNCTION__);
 
 	if (fsm->state == SIRDEV_STATE_DEAD) {
 		/* race with sirdev_close should never happen */
 		ERROR("%s(), instance staled!\n", __FUNCTION__);
-		printk(KERN_INFO "%s - up\n", __FUNCTION__);
 		up(&fsm->sem);
 		return -ESTALE;		/* or better EPIPE? */
 	}
@@ -501,7 +469,6 @@
 		atomic_set(&dev->enable_rx, 1);
 		if (!xmit_was_down)
 			netif_wake_queue(dev->netdev);		
-		printk(KERN_INFO "%s - up\n", __FUNCTION__);
 		up(&fsm->sem);
 		return -EAGAIN;
 	}
diff -Nru a/drivers/net/wan/comx.c b/drivers/net/wan/comx.c
--- a/drivers/net/wan/comx.c	Mon May 19 23:57:38 2003
+++ b/drivers/net/wan/comx.c	Thu Jul  3 06:36:44 2003
@@ -86,7 +86,7 @@
 
 static int comx_mkdir(struct inode *, struct dentry *, int);
 static int comx_rmdir(struct inode *, struct dentry *);
-static struct dentry *comx_lookup(struct inode *, struct dentry *);
+static struct dentry *comx_lookup(struct inode *, struct dentry *, struct nameidata *);
 
 static struct inode_operations comx_root_inode_ops = {
 	.lookup = comx_lookup,
@@ -922,7 +922,7 @@
 	return 0;
 }
 
-static struct dentry *comx_lookup(struct inode *dir, struct dentry *dentry)
+static struct dentry *comx_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
 {
 	struct proc_dir_entry *de;
 	struct inode *inode = NULL;
diff -Nru a/drivers/net/wan/hdlc_generic.c b/drivers/net/wan/hdlc_generic.c
--- a/drivers/net/wan/hdlc_generic.c	Mon May 19 23:22:52 2003
+++ b/drivers/net/wan/hdlc_generic.c	Sat Jul  5 07:01:51 2003
@@ -177,11 +177,8 @@
 
 struct packet_type hdlc_packet_type=
 {
-        __constant_htons(ETH_P_HDLC),
-        NULL,
-        hdlc_rcv,
-        NULL,
-        NULL
+	.type = __constant_htons(ETH_P_HDLC),
+	.func = hdlc_rcv,
 };
 
 
diff -Nru a/drivers/parisc/eisa.c b/drivers/parisc/eisa.c
--- a/drivers/parisc/eisa.c	Sat May 31 19:25:29 2003
+++ b/drivers/parisc/eisa.c	Fri Jul  4 00:39:46 2003
@@ -378,19 +378,21 @@
 		}
 	}
 	eisa_eeprom_init(eisa_dev.eeprom_addr);
-	eisa_enumerator(eisa_dev.eeprom_addr, &eisa_dev.hba.io_space, &eisa_dev.hba.lmmio_space);
+	result = eisa_enumerator(eisa_dev.eeprom_addr, &eisa_dev.hba.io_space, &eisa_dev.hba.lmmio_space);
 	init_eisa_pic();
 
-	/* FIXME : Get the number of slots from the enumerator, not a
-	 * hadcoded value. Also don't enumerate the bus twice. */
-	eisa_dev.root.dev = &dev->dev;
-	dev->dev.driver_data = &eisa_dev.root;
-	eisa_dev.root.bus_base_addr = 0;
-	eisa_dev.root.res = &eisa_dev.hba.io_space;
-	eisa_dev.root.slots = EISA_MAX_SLOTS;
-	if (eisa_root_register (&eisa_dev.root)) {
-		printk(KERN_ERR "EISA: Failed to register EISA root\n");
-		return -1;
+	if (result >= 0) {
+		/* FIXME : Don't enumerate the bus twice. */
+		eisa_dev.root.dev = &dev->dev;
+		dev->dev.driver_data = &eisa_dev.root;
+		eisa_dev.root.bus_base_addr = 0;
+		eisa_dev.root.res = &eisa_dev.hba.io_space;
+		eisa_dev.root.slots = result;
+		eisa_dev.root.dma_mask = 0xffffffff; /* wild guess */
+		if (eisa_root_register (&eisa_dev.root)) {
+			printk(KERN_ERR "EISA: Failed to register EISA root\n");
+			return -1;
+		}
 	}
 	
 	return 0;
diff -Nru a/drivers/parisc/eisa_enumerator.c b/drivers/parisc/eisa_enumerator.c
--- a/drivers/parisc/eisa_enumerator.c	Sun Nov  3 16:21:18 2002
+++ b/drivers/parisc/eisa_enumerator.c	Fri Jul  4 00:40:06 2003
@@ -438,6 +438,10 @@
 		id = le32_to_cpu(inl(SLOT2PORT(slot)+EPI));
 		
 		if (0xffffffff == id) {
+			/* Maybe we didn't expect a card to be here... */
+			if (es->eisa_slot_id == 0xffffffff)
+				return -1;
+			
 			/* this board is not here or it does not 
 			 * support readid 
 			 */
@@ -499,8 +503,7 @@
 			(&eeprom_buf[HPEE_SLOT_INFO(i)]);
 	        
 		if (-1==init_slot(i+1, es)) {
-			return -1;
-			
+			continue;
 		}
 		
 		if (es->config_data_offset < HPEE_MAX_LENGTH) {
@@ -513,6 +516,6 @@
 			return -1;
 		}
 	}
-	return 0;
+	return eh->num_slots;
 }
 
diff -Nru a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c
--- a/drivers/pci/hotplug/acpiphp_glue.c	Tue Jun 17 17:36:42 2003
+++ b/drivers/pci/hotplug/acpiphp_glue.c	Thu Jul  3 04:46:01 2003
@@ -385,7 +385,7 @@
 	bridge->seg = seg;
 	bridge->bus = bus;
 
-	bridge->pci_bus = pci_find_bus(bus);
+	bridge->pci_bus = pci_find_bus(seg, bus);
 
 	bridge->res_lock = SPIN_LOCK_UNLOCKED;
 
diff -Nru a/drivers/pci/hotplug/cpci_hotplug_pci.c b/drivers/pci/hotplug/cpci_hotplug_pci.c
--- a/drivers/pci/hotplug/cpci_hotplug_pci.c	Tue Jun  3 15:44:23 2003
+++ b/drivers/pci/hotplug/cpci_hotplug_pci.c	Thu Jul  3 04:46:06 2003
@@ -395,7 +395,7 @@
 
 	/* Scan behind bridge */
 	n = pci_scan_bridge(bus, dev, max, 2);
-	child = pci_find_bus(max + 1);
+	child = pci_find_bus(0, max + 1);
 	if (!child)
 		return -ENODEV;
 	pci_proc_attach_bus(child);
diff -Nru a/drivers/pci/hotplug/ibmphp_core.c b/drivers/pci/hotplug/ibmphp_core.c
--- a/drivers/pci/hotplug/ibmphp_core.c	Thu Jun 26 08:35:33 2003
+++ b/drivers/pci/hotplug/ibmphp_core.c	Thu Jul  3 04:46:23 2003
@@ -774,7 +774,7 @@
 	struct pci_dev *dev;
 	u16 l;
 
-	if (pci_find_bus(busno) || !(ibmphp_find_same_bus_num (busno)))
+	if (pci_find_bus(0, busno) || !(ibmphp_find_same_bus_num (busno)))
 		return 1;
 
 	bus = kmalloc (sizeof (*bus), GFP_KERNEL);
@@ -819,7 +819,7 @@
 		func->dev = pci_find_slot (func->busno, PCI_DEVFN(func->device, func->function));
 
 	if (func->dev == NULL) {
-		struct pci_bus *bus = pci_find_bus(func->busno);
+		struct pci_bus *bus = pci_find_bus(0, func->busno);
 		if (!bus)
 			return 0;
 
@@ -1335,7 +1335,7 @@
 		goto exit;
 	}
 
-	bus = pci_find_bus(0);
+	bus = pci_find_bus(0, 0);
 	if (!bus) {
 		err ("Can't find the root pci bus, can not continue\n");
 		rc = -ENODEV;
diff -Nru a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c
--- a/drivers/pci/pci-sysfs.c	Wed Jun 11 04:46:21 2003
+++ b/drivers/pci/pci-sysfs.c	Thu Jul  3 13:32:04 2003
@@ -3,6 +3,8 @@
  *
  * (C) Copyright 2002 Greg Kroah-Hartman
  * (C) Copyright 2002 IBM Corp.
+ * (C) Copyright 2003 Matthew Wilcox
+ * (C) Copyright 2003 Hewlett-Packard
  *
  * File attributes for PCI devices
  *
@@ -60,6 +62,108 @@
 
 static DEVICE_ATTR(resource,S_IRUGO,pci_show_resources,NULL);
 
+static ssize_t
+pci_read_config(struct kobject *kobj, char *buf, loff_t off, size_t count)
+{
+	struct pci_dev *dev = to_pci_dev(container_of(kobj,struct device,kobj));
+	unsigned int size = 64;
+
+	/* Several chips lock up trying to read undefined config space */
+	if (capable(CAP_SYS_ADMIN)) {
+		size = 256;
+	} else if (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS) {
+		size = 128;
+	}
+
+	if (off > size)
+		return 0;
+	if (off + count > size) {
+		size -= off;
+		count = size;
+	} else {
+		size = count;
+	}
+
+	while (off & 3) {
+		unsigned char val;
+		pci_read_config_byte(dev, off, &val);
+		buf[off] = val;
+		off++;
+		if (--size == 0)
+			break;
+	}
+
+	while (size > 3) {
+		unsigned int val;
+		pci_read_config_dword(dev, off, &val);
+		buf[off] = val & 0xff;
+		buf[off + 1] = (val >> 8) & 0xff;
+		buf[off + 2] = (val >> 16) & 0xff;
+		buf[off + 3] = (val >> 24) & 0xff;
+		off += 4;
+		size -= 4;
+	}
+
+	while (size > 0) {
+		unsigned char val;
+		pci_read_config_byte(dev, off, &val);
+		buf[off] = val;
+		off++;
+		--size;
+	}
+
+	return count;
+}
+
+static ssize_t
+pci_write_config(struct kobject *kobj, char *buf, loff_t off, size_t count)
+{
+	struct pci_dev *dev = to_pci_dev(container_of(kobj,struct device,kobj));
+	unsigned int size = count;
+
+	if (off > 256)
+		return 0;
+	if (off + count > 256) {
+		size = 256 - off;
+		count = size;
+	}
+
+	while (off & 3) {
+		pci_write_config_byte(dev, off, buf[off]);
+		off++;
+		if (--size == 0)
+			break;
+	}
+
+	while (size > 3) {
+		unsigned int val = buf[off];
+		val |= (unsigned int) buf[off + 1] << 8;
+		val |= (unsigned int) buf[off + 2] << 16;
+		val |= (unsigned int) buf[off + 3] << 24;
+		pci_write_config_dword(dev, off, val);
+		off += 4;
+		size -= 4;
+	}
+
+	while (size > 0) {
+		pci_write_config_byte(dev, off, buf[off]);
+		off++;
+		--size;
+	}
+
+	return count;
+}
+
+static struct bin_attribute pci_config_attr = {
+	.attr =	{
+		.name = "config",
+		.mode = S_IRUGO | S_IWUSR,
+	},
+	.size = 256,
+	.read = pci_read_config,
+	.write = pci_write_config,
+};
+
 void pci_create_sysfs_dev_files (struct pci_dev *pdev)
 {
 	struct device *dev = &pdev->dev;
@@ -72,4 +176,5 @@
 	device_create_file (dev, &dev_attr_class);
 	device_create_file (dev, &dev_attr_irq);
 	device_create_file (dev, &dev_attr_resource);
+	sysfs_create_bin_file(&dev->kobj, &pci_config_attr);
 }
diff -Nru a/drivers/pci/pci.h b/drivers/pci/pci.h
--- a/drivers/pci/pci.h	Thu Jun 19 15:02:58 2003
+++ b/drivers/pci/pci.h	Thu Jul  3 04:43:34 2003
@@ -29,7 +29,6 @@
 extern unsigned char pci_max_busnr(void);
 extern unsigned char pci_bus_max_busnr(struct pci_bus *bus);
 extern int pci_bus_find_capability (struct pci_bus *bus, unsigned int devfn, int cap);
-extern struct pci_bus *pci_find_bus(unsigned char busnr);
 
 struct pci_dev_wrapped {
 	struct pci_dev	*dev;
diff -Nru a/drivers/pci/probe.c b/drivers/pci/probe.c
--- a/drivers/pci/probe.c	Wed Jun 25 19:45:53 2003
+++ b/drivers/pci/probe.c	Fri Jul  4 23:52:26 2003
@@ -633,27 +633,10 @@
 	return max;
 }
 
-int __devinit pci_bus_exists(const struct list_head *list, int nr)
-{
-	const struct pci_bus *b;
-
-	list_for_each_entry(b, list, node) {
-		if (b->number == nr || pci_bus_exists(&b->children, nr))
-			return 1;
-	}
-	return 0;
-}
-
 struct pci_bus * __devinit pci_scan_bus_parented(struct device *parent, int bus, struct pci_ops *ops, void *sysdata)
 {
 	struct pci_bus *b;
 
-	if (pci_bus_exists(&pci_root_buses, bus)) {
-		/* If we already got to this bus through a different bridge, ignore it */
-		DBG("PCI: Bus %02x already known\n", bus);
-		return NULL;
-	}
-
 	b = pci_alloc_bus();
 	if (!b)
 		return NULL;
@@ -666,6 +649,14 @@
 
 	b->sysdata = sysdata;
 	b->ops = ops;
+
+	if (pci_find_bus(pci_domain_nr(b), bus)) {
+		/* If we already got to this bus through a different bridge, ignore it */
+		DBG("PCI: Bus %02x already known\n", bus);
+		kfree(b->dev);
+		kfree(b);
+		return NULL;
+	}
 
 	list_add_tail(&b->node, &pci_root_buses);
 
diff -Nru a/drivers/pci/search.c b/drivers/pci/search.c
--- a/drivers/pci/search.c	Thu Jun 19 09:14:03 2003
+++ b/drivers/pci/search.c	Thu Jul  3 08:09:17 2003
@@ -7,12 +7,14 @@
  *	Copyright 2003 -- Greg Kroah-Hartman <greg@kroah.com>
  */
 
+#include <linux/init.h>
 #include <linux/pci.h>
 #include <linux/module.h>
+#include <linux/interrupt.h>
 
 spinlock_t pci_bus_lock = SPIN_LOCK_UNLOCKED;
 
-static struct pci_bus *
+static struct pci_bus * __devinit
 pci_do_find_bus(struct pci_bus* bus, unsigned char busnr)
 {
 	struct pci_bus* child;
@@ -30,22 +32,24 @@
 }
 
 /**
- * pci_find_bus - locate PCI bus from a given bus number
+ * pci_find_bus - locate PCI bus from a given domain and bus number
+ * @domain: number of PCI domain to search
  * @busnr: number of desired PCI bus
  *
- * Given a PCI bus number, the desired PCI bus is located in system
- * global list of PCI buses.  If the bus is found, a pointer to its
+ * Given a PCI bus number and domain number, the desired PCI bus is located
+ * in the global list of PCI buses.  If the bus is found, a pointer to its
  * data structure is returned.  If no bus is found, %NULL is returned.
  */
-struct pci_bus *
-pci_find_bus(unsigned char busnr)
+struct pci_bus * __devinit pci_find_bus(int domain, int busnr)
 {
-	struct pci_bus* bus = NULL;
-	struct pci_bus* tmp_bus;
+	struct pci_bus *bus = NULL;
+	struct pci_bus *tmp_bus;
 
 	while ((bus = pci_find_next_bus(bus)) != NULL)  {
+		if (pci_domain_nr(bus) != domain)
+			continue;
 		tmp_bus = pci_do_find_bus(bus, busnr);
-		if(tmp_bus)
+		if (tmp_bus)
 			return tmp_bus;
 	}
 	return NULL;
@@ -66,7 +70,7 @@
 	struct list_head *n;
 	struct pci_bus *b = NULL;
 
-	WARN_ON(irqs_disabled());
+	WARN_ON(in_interrupt());
 	spin_lock(&pci_bus_lock);
 	n = from ? from->node.next : pci_root_buses.next;
 	if (n != &pci_root_buses)
@@ -125,7 +129,7 @@
 	struct list_head *n;
 	struct pci_dev *dev;
 
-	WARN_ON(irqs_disabled());
+	WARN_ON(in_interrupt());
 	spin_lock(&pci_bus_lock);
 	n = from ? from->global_list.next : pci_devices.next;
 
@@ -190,7 +194,7 @@
 	struct list_head *n;
 	struct pci_dev *dev;
 
-	WARN_ON(irqs_disabled());
+	WARN_ON(in_interrupt());
 	spin_lock(&pci_bus_lock);
 	n = from ? from->global_list.next : pci_devices.next;
 
@@ -256,7 +260,7 @@
 	struct list_head *n;
 	struct pci_dev *dev;
 
-	WARN_ON(irqs_disabled());
+	WARN_ON(in_interrupt());
 	spin_lock(&pci_bus_lock);
 	n = from ? from->global_list.prev : pci_devices.prev;
 
diff -Nru a/drivers/pnp/interface.c b/drivers/pnp/interface.c
--- a/drivers/pnp/interface.c	Tue Jun 24 13:17:01 2003
+++ b/drivers/pnp/interface.c	Thu Jul  3 08:38:43 2003
@@ -259,7 +259,10 @@
 	for (i = 0; i < PNP_MAX_PORT; i++) {
 		if (pnp_port_valid(dev, i)) {
 			pnp_printf(buffer,"io");
-			pnp_printf(buffer," 0x%lx-0x%lx \n",
+			if (pnp_port_flags(dev, i) & IORESOURCE_DISABLED)
+				pnp_printf(buffer," disabled\n");
+			else
+				pnp_printf(buffer," 0x%lx-0x%lx\n",
 						pnp_port_start(dev, i),
 						pnp_port_end(dev, i));
 		}
@@ -267,7 +270,10 @@
 	for (i = 0; i < PNP_MAX_MEM; i++) {
 		if (pnp_mem_valid(dev, i)) {
 			pnp_printf(buffer,"mem");
-			pnp_printf(buffer," 0x%lx-0x%lx \n",
+			if (pnp_mem_flags(dev, i) & IORESOURCE_DISABLED)
+				pnp_printf(buffer," disabled\n");
+			else
+				pnp_printf(buffer," 0x%lx-0x%lx\n",
 						pnp_mem_start(dev, i),
 						pnp_mem_end(dev, i));
 		}
@@ -275,13 +281,21 @@
 	for (i = 0; i < PNP_MAX_IRQ; i++) {
 		if (pnp_irq_valid(dev, i)) {
 			pnp_printf(buffer,"irq");
-			pnp_printf(buffer," %ld \n", pnp_irq(dev, i));
+			if (pnp_irq_flags(dev, i) & IORESOURCE_DISABLED)
+				pnp_printf(buffer," disabled\n");
+			else
+				pnp_printf(buffer," %ld\n",
+						pnp_irq(dev, i));
 		}
 	}
 	for (i = 0; i < PNP_MAX_DMA; i++) {
 		if (pnp_dma_valid(dev, i)) {
 			pnp_printf(buffer,"dma");
-			pnp_printf(buffer," %ld \n", pnp_dma(dev, i));
+			if (pnp_dma_flags(dev, i) & IORESOURCE_DISABLED)
+				pnp_printf(buffer," disabled\n");
+			else
+				pnp_printf(buffer," %ld\n",
+						pnp_dma(dev, i));
 		}
 	}
 	ret = (buffer->curr - buf);
diff -Nru a/drivers/pnp/manager.c b/drivers/pnp/manager.c
--- a/drivers/pnp/manager.c	Tue Jun 24 13:24:06 2003
+++ b/drivers/pnp/manager.c	Thu Jul  3 08:45:32 2003
@@ -45,9 +45,15 @@
 	flags = &dev->res.port_resource[idx].flags;
 
 	/* set the initial values */
+	*flags = *flags | rule->flags | IORESOURCE_IO;
+
+	if (!rule->size) {
+		*flags |= IORESOURCE_DISABLED;
+		return 1; /* skip disabled resource requests */
+	}
+
 	*start = rule->min;
 	*end = *start + rule->size - 1;
-	*flags = *flags | rule->flags | IORESOURCE_IO;
 
 	/* run through until pnp_check_port is happy */
 	while (!pnp_check_port(dev, idx)) {
@@ -81,8 +87,6 @@
 	flags = &dev->res.mem_resource[idx].flags;
 
 	/* set the initial values */
-	*start = rule->min;
-	*end = *start + rule->size -1;
 	*flags = *flags | rule->flags | IORESOURCE_MEM;
 
 	/* convert pnp flags to standard Linux flags */
@@ -95,6 +99,14 @@
 	if (rule->flags & IORESOURCE_MEM_SHADOWABLE)
 		*flags |= IORESOURCE_SHADOWABLE;
 
+	if (!rule->size) {
+		*flags |= IORESOURCE_DISABLED;
+		return 1; /* skip disabled resource requests */
+	}
+
+	*start = rule->min;
+	*end = *start + rule->size -1;
+
 	/* run through until pnp_check_mem is happy */
 	while (!pnp_check_mem(dev, idx)) {
 		*start += rule->align;
@@ -135,6 +147,11 @@
 	/* set the initial values */
 	*flags = *flags | rule->flags | IORESOURCE_IRQ;
 
+	if (!rule->map) {
+		*flags |= IORESOURCE_DISABLED;
+		return 1; /* skip disabled resource requests */
+	}
+
 	for (i = 0; i < 16; i++) {
 		if(rule->map & (1<<xtab[i])) {
 			*start = *end = xtab[i];
@@ -175,6 +192,11 @@
 	/* set the initial values */
 	*flags = *flags | rule->flags | IORESOURCE_DMA;
 
+	if (!rule->map) {
+		*flags |= IORESOURCE_DISABLED;
+		return 1; /* skip disabled resource requests */
+	}
+
 	for (i = 0; i < 8; i++) {
 		if(rule->map & (1<<xtab[i])) {
 			*start = *end = xtab[i];
@@ -378,25 +400,24 @@
 	dev->res = *res;
 	if (!(mode & PNP_CONFIG_FORCE)) {
 		for (i = 0; i < PNP_MAX_PORT; i++) {
-			if(pnp_check_port(dev,i))
+			if(!pnp_check_port(dev,i))
 				goto fail;
 		}
 		for (i = 0; i < PNP_MAX_MEM; i++) {
-			if(pnp_check_mem(dev,i))
+			if(!pnp_check_mem(dev,i))
 				goto fail;
 		}
 		for (i = 0; i < PNP_MAX_IRQ; i++) {
-			if(pnp_check_irq(dev,i))
+			if(!pnp_check_irq(dev,i))
 				goto fail;
 		}
 		for (i = 0; i < PNP_MAX_DMA; i++) {
-			if(pnp_check_dma(dev,i))
+			if(!pnp_check_dma(dev,i))
 				goto fail;
 		}
 	}
 	up(&pnp_res_mutex);
 
-	pnp_auto_config_dev(dev);
 	kfree(bak);
 	return 0;
 
diff -Nru a/drivers/pnp/resource.c b/drivers/pnp/resource.c
--- a/drivers/pnp/resource.c	Wed Jun 25 16:30:51 2003
+++ b/drivers/pnp/resource.c	Thu Jul  3 08:38:43 2003
@@ -286,6 +286,8 @@
 			continue;
 		for (tmp = 0; tmp < PNP_MAX_PORT; tmp++) {
 			if (tdev->res.port_resource[tmp].flags & IORESOURCE_IO) {
+				if (pnp_port_flags(dev, tmp) & IORESOURCE_DISABLED)
+					continue;
 				tport = &tdev->res.port_resource[tmp].start;
 				tend = &tdev->res.port_resource[tmp].end;
 				if (ranged_conflict(port,end,tport,tend))
@@ -340,6 +342,8 @@
 			continue;
 		for (tmp = 0; tmp < PNP_MAX_MEM; tmp++) {
 			if (tdev->res.mem_resource[tmp].flags & IORESOURCE_MEM) {
+				if (pnp_mem_flags(dev, tmp) & IORESOURCE_DISABLED)
+					continue;
 				taddr = &tdev->res.mem_resource[tmp].start;
 				tend = &tdev->res.mem_resource[tmp].end;
 				if (ranged_conflict(addr,end,taddr,tend))
@@ -409,6 +413,8 @@
 			continue;
 		for (tmp = 0; tmp < PNP_MAX_IRQ; tmp++) {
 			if (tdev->res.irq_resource[tmp].flags & IORESOURCE_IRQ) {
+				if (pnp_irq_flags(dev, tmp) & IORESOURCE_DISABLED)
+					continue;
 				if ((tdev->res.irq_resource[tmp].start == *irq))
 					return 0;
 			}
@@ -462,6 +468,8 @@
 			continue;
 		for (tmp = 0; tmp < PNP_MAX_DMA; tmp++) {
 			if (tdev->res.dma_resource[tmp].flags & IORESOURCE_DMA) {
+				if (pnp_dma_flags(dev, tmp) & IORESOURCE_DISABLED)
+					continue;
 				if ((tdev->res.dma_resource[tmp].start == *dma))
 					return 0;
 			}
diff -Nru a/drivers/pnp/support.c b/drivers/pnp/support.c
--- a/drivers/pnp/support.c	Tue Jun 24 13:17:01 2003
+++ b/drivers/pnp/support.c	Thu Jul  3 08:38:43 2003
@@ -68,9 +68,13 @@
 	int i = 0;
 	while ((res->irq_resource[i].flags & IORESOURCE_IRQ) && i < PNP_MAX_IRQ) i++;
 	if (i < PNP_MAX_IRQ) {
+		res->irq_resource[i].flags = IORESOURCE_IRQ;  // Also clears _UNSET flag
+		if (irq == -1) {
+			res->irq_resource[i].flags |= IORESOURCE_DISABLED;
+			return;
+		}
 		res->irq_resource[i].start =
 		res->irq_resource[i].end = (unsigned long) irq;
-		res->irq_resource[i].flags = IORESOURCE_IRQ;  // Also clears _UNSET flag
 	}
 }
 
@@ -79,9 +83,13 @@
 	int i = 0;
 	while ((res->dma_resource[i].flags & IORESOURCE_DMA) && i < PNP_MAX_DMA) i++;
 	if (i < PNP_MAX_DMA) {
+		res->dma_resource[i].flags = IORESOURCE_DMA;  // Also clears _UNSET flag
+		if (dma == -1) {
+			res->dma_resource[i].flags |= IORESOURCE_DISABLED;
+			return;
+		}
 		res->dma_resource[i].start =
 		res->dma_resource[i].end = (unsigned long) dma;
-		res->dma_resource[i].flags = IORESOURCE_DMA;  // Also clears _UNSET flag
 	}
 }
 
@@ -90,9 +98,13 @@
 	int i = 0;
 	while ((res->port_resource[i].flags & IORESOURCE_IO) && i < PNP_MAX_PORT) i++;
 	if (i < PNP_MAX_PORT) {
+		res->port_resource[i].flags = IORESOURCE_IO;  // Also clears _UNSET flag
+		if (len <= 0 || (io + len -1) >= 0x10003) {
+			res->port_resource[i].flags |= IORESOURCE_DISABLED;
+			return;
+		}
 		res->port_resource[i].start = (unsigned long) io;
 		res->port_resource[i].end = (unsigned long)(io + len - 1);
-		res->port_resource[i].flags = IORESOURCE_IO;  // Also clears _UNSET flag
 	}
 }
 
@@ -101,9 +113,13 @@
 	int i = 0;
 	while ((res->mem_resource[i].flags & IORESOURCE_MEM) && i < PNP_MAX_MEM) i++;
 	if (i < PNP_MAX_MEM) {
+		res->mem_resource[i].flags = IORESOURCE_MEM;  // Also clears _UNSET flag
+		if (len <= 0) {
+			res->mem_resource[i].flags |= IORESOURCE_DISABLED;
+			return;
+		}
 		res->mem_resource[i].start = (unsigned long) mem;
 		res->mem_resource[i].end = (unsigned long)(mem + len - 1);
-		res->mem_resource[i].flags = IORESOURCE_MEM;  // Also clears _UNSET flag
 	}
 }
 
diff -Nru a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c
--- a/drivers/scsi/scsi.c	Wed Jun 25 04:47:15 2003
+++ b/drivers/scsi/scsi.c	Wed Jul  2 00:19:28 2003
@@ -582,7 +582,7 @@
 	local_irq_save(flags);
 	cpu = smp_processor_id();
 	list_add_tail(&cmd->eh_entry, &done_q[cpu]);
-	cpu_raise_softirq(cpu, SCSI_SOFTIRQ);
+	raise_softirq_irqoff(SCSI_SOFTIRQ);
 	local_irq_restore(flags);
 }
 
diff -Nru a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
--- a/drivers/scsi/scsi_scan.c	Wed Jun 25 04:47:15 2003
+++ b/drivers/scsi/scsi_scan.c	Fri Jul  4 17:24:28 2003
@@ -646,7 +646,7 @@
 	sdev->max_device_blocked = SCSI_DEFAULT_DEVICE_BLOCKED;
 
 	sdev->use_10_for_rw = 1;
-	sdev->use_10_for_ms = 1;
+	sdev->use_10_for_ms = 0;
 
 	if(sdev->host->hostt->slave_configure)
 		sdev->host->hostt->slave_configure(sdev);
diff -Nru a/drivers/serial/68328serial.c b/drivers/serial/68328serial.c
--- a/drivers/serial/68328serial.c	Wed Jun 11 12:32:34 2003
+++ b/drivers/serial/68328serial.c	Wed Jul  2 18:18:07 2003
@@ -1533,7 +1533,6 @@
 }
 	
 module_init(rs68328_init);
-/* DAVIDM module_exit(rs68328_fini); */
 
 
 
diff -Nru a/drivers/serial/8250_cs.c b/drivers/serial/8250_cs.c
--- a/drivers/serial/8250_cs.c	Wed Jun 25 16:31:00 2003
+++ b/drivers/serial/8250_cs.c	Sun Jul  6 11:54:22 2003
@@ -133,7 +133,7 @@
 static void serial_remove(dev_link_t *link)
 {
 	struct serial_info *info = link->priv;
-	int i, ret;
+	int i;
 
 	link->state &= ~DEV_PRESENT;
 
diff -Nru a/drivers/serial/mcfserial.c b/drivers/serial/mcfserial.c
--- a/drivers/serial/mcfserial.c	Sun Jun 15 19:45:52 2003
+++ b/drivers/serial/mcfserial.c	Wed Jul  2 18:18:07 2003
@@ -1643,7 +1643,6 @@
 }
 
 module_init(mcfrs_init);
-/* DAVIDM module_exit(mcfrs_fini); */
 
 /****************************************************************************/
 /*                          Serial Console                                  */
diff -Nru a/fs/adfs/adfs.h b/fs/adfs/adfs.h
--- a/fs/adfs/adfs.h	Wed May  1 11:54:55 2002
+++ b/fs/adfs/adfs.h	Thu Jul  3 06:36:44 2003
@@ -88,7 +88,7 @@
 #define adfs_error(sb, fmt...) __adfs_error(sb, __FUNCTION__, fmt)
 
 /* namei.c */
-extern struct dentry *adfs_lookup(struct inode *dir, struct dentry *dentry);
+extern struct dentry *adfs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *);
 
 /* super.c */
 
diff -Nru a/fs/adfs/dir.c b/fs/adfs/dir.c
--- a/fs/adfs/dir.c	Sat Aug  3 03:12:00 2002
+++ b/fs/adfs/dir.c	Thu Jul  3 06:36:44 2003
@@ -269,7 +269,7 @@
 	.d_compare	= adfs_compare,
 };
 
-struct dentry *adfs_lookup(struct inode *dir, struct dentry *dentry)
+struct dentry *adfs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
 {
 	struct inode *inode = NULL;
 	struct object_info obj;
diff -Nru a/fs/affs/namei.c b/fs/affs/namei.c
--- a/fs/affs/namei.c	Sun Mar 16 22:33:20 2003
+++ b/fs/affs/namei.c	Sun Jun 29 23:49:04 2003
@@ -210,7 +210,7 @@
 }
 
 struct dentry *
-affs_lookup(struct inode *dir, struct dentry *dentry)
+affs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
 {
 	struct super_block *sb = dir->i_sb;
 	struct buffer_head *bh;
@@ -256,7 +256,7 @@
 }
 
 int
-affs_create(struct inode *dir, struct dentry *dentry, int mode)
+affs_create(struct inode *dir, struct dentry *dentry, int mode, struct nameidata *nd)
 {
 	struct super_block *sb = dir->i_sb;
 	struct inode	*inode;
diff -Nru a/fs/afs/dir.c b/fs/afs/dir.c
--- a/fs/afs/dir.c	Wed Apr  2 22:51:32 2003
+++ b/fs/afs/dir.c	Thu Jul  3 06:36:44 2003
@@ -23,10 +23,10 @@
 #include "super.h"
 #include "internal.h"
 
-static struct dentry *afs_dir_lookup(struct inode *dir, struct dentry *dentry);
+static struct dentry *afs_dir_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *);
 static int afs_dir_open(struct inode *inode, struct file *file);
 static int afs_dir_readdir(struct file *file, void *dirent, filldir_t filldir);
-static int afs_d_revalidate(struct dentry *dentry, int flags);
+static int afs_d_revalidate(struct dentry *dentry, struct nameidata *);
 static int afs_d_delete(struct dentry *dentry);
 static int afs_dir_lookup_filldir(void *_cookie, const char *name, int nlen, loff_t fpos,
 				     ino_t ino, unsigned dtype);
@@ -414,7 +414,7 @@
 /*
  * look up an entry in a directory
  */
-static struct dentry *afs_dir_lookup(struct inode *dir, struct dentry *dentry)
+static struct dentry *afs_dir_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
 {
 	struct afs_dir_lookup_cookie cookie;
 	struct afs_super_info *as;
@@ -487,7 +487,7 @@
  * - NOTE! the hit can be a negative hit too, so we can't assume we have an inode
  * (derived from nfs_lookup_revalidate)
  */
-static int afs_d_revalidate(struct dentry *dentry, int flags)
+static int afs_d_revalidate(struct dentry *dentry, struct nameidata *nd)
 {
 	struct afs_dir_lookup_cookie cookie;
 	struct dentry *parent;
@@ -495,7 +495,7 @@
 	unsigned fpos;
 	int ret;
 
-	_enter("%s,%x",dentry->d_name.name,flags);
+	_enter("%s,%p",dentry->d_name.name,nd);
 
 	parent = dget_parent(dentry);
 	dir = parent->d_inode;
diff -Nru a/fs/afs/mntpt.c b/fs/afs/mntpt.c
--- a/fs/afs/mntpt.c	Wed Oct 16 05:34:58 2002
+++ b/fs/afs/mntpt.c	Thu Jul  3 06:36:44 2003
@@ -21,7 +21,7 @@
 #include "internal.h"
 
 
-static struct dentry *afs_mntpt_lookup(struct inode *dir, struct dentry *dentry);
+static struct dentry *afs_mntpt_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *);
 static int afs_mntpt_open(struct inode *inode, struct file *file);
 
 struct file_operations afs_mntpt_file_operations = {
@@ -93,7 +93,7 @@
 /*
  * no valid lookup procedure on this sort of dir
  */
-static struct dentry *afs_mntpt_lookup(struct inode *dir, struct dentry *dentry)
+static struct dentry *afs_mntpt_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
 {
 	return ERR_PTR(-EREMOTE);
 } /* end afs_mntpt_lookup() */
diff -Nru a/fs/aio.c b/fs/aio.c
--- a/fs/aio.c	Wed Jun  4 00:50:19 2003
+++ b/fs/aio.c	Sun Jul  6 18:51:59 2003
@@ -552,7 +552,7 @@
 {
 	current->mm = NULL;
 	/* active_mm is still 'mm' */
-	enter_lazy_tlb(mm, current, smp_processor_id());
+	enter_lazy_tlb(mm, current);
 }
 
 /* Run on kevent's context.  FIXME: needs to be per-cpu and warn if an
diff -Nru a/fs/attr.c b/fs/attr.c
--- a/fs/attr.c	Thu May 29 22:42:39 2003
+++ b/fs/attr.c	Wed Jul  2 21:21:22 2003
@@ -22,8 +22,6 @@
 	int retval = -EPERM;
 	unsigned int ia_valid = attr->ia_valid;
 
-	lock_kernel();
-
 	/* If force is set do it anyway. */
 	if (ia_valid & ATTR_FORCE)
 		goto fine;
@@ -58,7 +56,6 @@
 fine:
 	retval = 0;
 error:
-	unlock_kernel();
 	return retval;
 }
 
diff -Nru a/fs/autofs/root.c b/fs/autofs/root.c
--- a/fs/autofs/root.c	Sun Nov 17 12:30:45 2002
+++ b/fs/autofs/root.c	Thu Jul  3 06:36:44 2003
@@ -18,7 +18,7 @@
 #include "autofs_i.h"
 
 static int autofs_root_readdir(struct file *,void *,filldir_t);
-static struct dentry *autofs_root_lookup(struct inode *,struct dentry *);
+static struct dentry *autofs_root_lookup(struct inode *,struct dentry *, struct nameidata *);
 static int autofs_root_symlink(struct inode *,struct dentry *,const char *);
 static int autofs_root_unlink(struct inode *,struct dentry *);
 static int autofs_root_rmdir(struct inode *,struct dentry *);
@@ -144,7 +144,7 @@
  * yet completely filled in, and revalidate has to delay such
  * lookups..
  */
-static int autofs_revalidate(struct dentry * dentry, int flags)
+static int autofs_revalidate(struct dentry * dentry, struct nameidata *nd)
 {
 	struct inode * dir;
 	struct autofs_sb_info *sbi;
@@ -195,7 +195,7 @@
 	.d_revalidate	= autofs_revalidate,
 };
 
-static struct dentry *autofs_root_lookup(struct inode *dir, struct dentry *dentry)
+static struct dentry *autofs_root_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
 {
 	struct autofs_sb_info *sbi;
 	int oz_mode;
@@ -230,7 +230,7 @@
 	d_add(dentry, NULL);
 
 	up(&dir->i_sem);
-	autofs_revalidate(dentry, 0);
+	autofs_revalidate(dentry, nd);
 	down(&dir->i_sem);
 
 	/*
diff -Nru a/fs/autofs4/root.c b/fs/autofs4/root.c
--- a/fs/autofs4/root.c	Sun May 25 23:19:27 2003
+++ b/fs/autofs4/root.c	Thu Jul  3 06:36:44 2003
@@ -18,13 +18,13 @@
 #include <linux/smp_lock.h>
 #include "autofs_i.h"
 
-static struct dentry *autofs4_dir_lookup(struct inode *,struct dentry *);
+static struct dentry *autofs4_dir_lookup(struct inode *,struct dentry *, struct nameidata *);
 static int autofs4_dir_symlink(struct inode *,struct dentry *,const char *);
 static int autofs4_dir_unlink(struct inode *,struct dentry *);
 static int autofs4_dir_rmdir(struct inode *,struct dentry *);
 static int autofs4_dir_mkdir(struct inode *,struct dentry *,int);
 static int autofs4_root_ioctl(struct inode *, struct file *,unsigned int,unsigned long);
-static struct dentry *autofs4_root_lookup(struct inode *,struct dentry *);
+static struct dentry *autofs4_root_lookup(struct inode *,struct dentry *, struct nameidata *);
 
 struct file_operations autofs4_root_operations = {
 	.open		= dcache_dir_open,
@@ -143,7 +143,7 @@
  * yet completely filled in, and revalidate has to delay such
  * lookups..
  */
-static int autofs4_root_revalidate(struct dentry * dentry, int flags)
+static int autofs4_root_revalidate(struct dentry * dentry, struct nameidata *nd)
 {
 	struct inode * dir = dentry->d_parent->d_inode;
 	struct autofs_sb_info *sbi = autofs4_sbi(dir->i_sb);
@@ -183,7 +183,7 @@
 	return 1;
 }
 
-static int autofs4_revalidate(struct dentry *dentry, int flags)
+static int autofs4_revalidate(struct dentry *dentry, struct nameidata *nd)
 {
 	struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb);
 
@@ -225,7 +225,7 @@
 /* Lookups in non-root dirs never find anything - if it's there, it's
    already in the dcache */
 /* SMP-safe */
-static struct dentry *autofs4_dir_lookup(struct inode *dir, struct dentry *dentry)
+static struct dentry *autofs4_dir_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
 {
 #if 0
 	DPRINTK(("autofs_dir_lookup: ignoring lookup of %.*s/%.*s\n",
@@ -239,7 +239,7 @@
 }
 
 /* Lookups in the root directory */
-static struct dentry *autofs4_root_lookup(struct inode *dir, struct dentry *dentry)
+static struct dentry *autofs4_root_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
 {
 	struct autofs_sb_info *sbi;
 	int oz_mode;
@@ -276,7 +276,7 @@
 
 	if (dentry->d_op && dentry->d_op->d_revalidate) {
 		up(&dir->i_sem);
-		(dentry->d_op->d_revalidate)(dentry, 0);
+		(dentry->d_op->d_revalidate)(dentry, nd);
 		down(&dir->i_sem);
 	}
 
diff -Nru a/fs/befs/linuxvfs.c b/fs/befs/linuxvfs.c
--- a/fs/befs/linuxvfs.c	Fri Jun 20 13:16:06 2003
+++ b/fs/befs/linuxvfs.c	Thu Jul  3 06:36:44 2003
@@ -33,7 +33,7 @@
 static int befs_get_block(struct inode *, sector_t, struct buffer_head *, int);
 static int befs_readpage(struct file *file, struct page *page);
 static sector_t befs_bmap(struct address_space *mapping, sector_t block);
-static struct dentry *befs_lookup(struct inode *, struct dentry *);
+static struct dentry *befs_lookup(struct inode *, struct dentry *, struct nameidata *);
 static void befs_read_inode(struct inode *ino);
 static struct inode *befs_alloc_inode(struct super_block *sb);
 static void befs_destroy_inode(struct inode *inode);
@@ -163,7 +163,7 @@
 }
 
 static struct dentry *
-befs_lookup(struct inode *dir, struct dentry *dentry)
+befs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
 {
 	struct inode *inode = NULL;
 	struct super_block *sb = dir->i_sb;
diff -Nru a/fs/bfs/dir.c b/fs/bfs/dir.c
--- a/fs/bfs/dir.c	Sun May  4 22:49:54 2003
+++ b/fs/bfs/dir.c	Sun Jun 29 23:49:04 2003
@@ -78,7 +78,8 @@
 
 extern void dump_imap(const char *, struct super_block *);
 
-static int bfs_create(struct inode * dir, struct dentry * dentry, int mode)
+static int bfs_create(struct inode * dir, struct dentry * dentry, int mode,
+		struct nameidata *nd)
 {
 	int err;
 	struct inode * inode;
@@ -127,7 +128,7 @@
 	return 0;
 }
 
-static struct dentry * bfs_lookup(struct inode * dir, struct dentry * dentry)
+static struct dentry * bfs_lookup(struct inode * dir, struct dentry * dentry, struct nameidata *nd)
 {
 	struct inode * inode = NULL;
 	struct buffer_head * bh;
diff -Nru a/fs/binfmt_flat.c b/fs/binfmt_flat.c
--- a/fs/binfmt_flat.c	Wed Feb 19 12:23:50 2003
+++ b/fs/binfmt_flat.c	Wed Jul  2 18:18:14 2003
@@ -1,15 +1,17 @@
+/****************************************************************************/
 /*
  *  linux/fs/binfmt_flat.c
  *
- *	Copyright (C) 2000, 2001 Lineo, by David McCullough <davidm@uclinux.org>
+ *	Copyright (C) 2000-2003 David McCullough <davidm@snapgear.com>
  *	Copyright (C) 2002 Greg Ungerer <gerg@snapgear.com>
- *
+ *	Copyright (C) 2002 SnapGear, by Paul Dale <pauli@snapgear.com>
+ *	Copyright (C) 2000, 2001 Lineo, by David McCullough <davidm@lineo.com>
  *  based heavily on:
  *
  *  linux/fs/binfmt_aout.c:
  *      Copyright (C) 1991, 1992, 1996  Linus Torvalds
  *  linux/fs/binfmt_flat.c for 2.0 kernel
- *	Copyright (C) 1998  Kenneth Albanowski <kjahds@kjahds.com>
+ *	    Copyright (C) 1998  Kenneth Albanowski <kjahds@kjahds.com>
  *	JAN/99 -- coded full program relocation (gerg@snapgear.com)
  */
 
@@ -42,27 +44,69 @@
 #include <asm/unaligned.h>
 #include <asm/cacheflush.h>
 
-#undef DEBUG
+/****************************************************************************/
+
+#if 0
+#define DEBUG 1
+#endif
+
 #ifdef DEBUG
-#define	DBG_FLT(a...)	printk(##a)
+#define	DBG_FLT(a...)	printk(a)
 #else
 #define	DBG_FLT(a...)
 #endif
 
+#define RELOC_FAILED 0xff00ff01		/* Relocation incorrect somewhere */
+#define UNLOADED_LIB 0x7ff000ff		/* Placeholder for unused library */
+
+struct lib_info {
+	struct {
+		unsigned long start_code;		/* Start of text segment */
+		unsigned long start_data;		/* Start of data segment */
+		unsigned long start_brk;		/* End of data segment */
+		unsigned long text_len;			/* Length of text segment */
+		unsigned long entry;			/* Start address for this module */
+		unsigned long build_date;		/* When this one was compiled */
+		short loaded;				/* Has this library been loaded? */
+	} lib_list[MAX_SHARED_LIBS];
+};
+
+#ifdef CONFIG_BINFMT_SHARED_FLAT
+static int load_flat_shared_library(int id, struct lib_info *p);
+#endif
+
 static int load_flat_binary(struct linux_binprm *, struct pt_regs * regs);
-static int load_flat_library(struct file*);
+static int flat_core_dump(long signr, struct pt_regs * regs, struct file *file);
+
 extern void dump_thread(struct pt_regs *, struct user *);
 
 static struct linux_binfmt flat_format = {
-	NULL, THIS_MODULE, load_flat_binary, load_flat_library, NULL, PAGE_SIZE
+	.module		= THIS_MODULE,
+	.load_binary	= load_flat_binary,
+	.core_dump	= flat_core_dump,
+	.min_coredump	= PAGE_SIZE
 };
 
+/****************************************************************************/
+/*
+ * Routine writes a core dump image in the current directory.
+ * Currently only a stub-function.
+ */
+
+static int flat_core_dump(long signr, struct pt_regs * regs, struct file *file)
+{
+	printk("Process %s:%d received signr %d and should have core dumped\n",
+			current->comm, current->pid, (int) signr);
+	return(1);
+}
 
+/****************************************************************************/
 /*
  * create_flat_tables() parses the env- and arg-strings in new user
  * memory and creates the pointer tables from them, and puts their
  * addresses on the "stack", returning the new stack pointer value.
  */
+
 static unsigned long create_flat_tables(
 	unsigned long pp,
 	struct linux_binprm * bprm)
@@ -80,10 +124,13 @@
 	envp = sp;
 	sp -= argc+1;
 	argv = sp;
+
+	flat_stack_align(sp);
 	if (flat_argvp_envp_on_stack()) {
-		put_user((unsigned long) envp, --sp);
-		put_user((unsigned long) argv, --sp);
+		--sp; put_user((unsigned long) envp, sp);
+		--sp; put_user((unsigned long) argv, sp);
 	}
+
 	put_user(argc,--sp);
 	current->mm->arg_start = (unsigned long) p;
 	while (argc-->0) {
@@ -105,6 +152,7 @@
 	return (unsigned long)sp;
 }
 
+/****************************************************************************/
 
 #ifdef CONFIG_BINFMT_ZFLAT
 
@@ -183,7 +231,7 @@
 	if (buf[3] & EXTRA_FIELD) {
 		ret += 2 + buf[10] + (buf[11] << 8);
 		if (unlikely(LBUFSIZE == ret)) {
-			DBG_FLAT("binfmt_flat: buffer overflow (EXTRA)?\n");
+			DBG_FLT("binfmt_flat: buffer overflow (EXTRA)?\n");
 			return -ENOEXEC;
 		}
 	}
@@ -191,7 +239,7 @@
 		for (; ret < LBUFSIZE && (buf[ret] != 0); ret++)
 			;
 		if (unlikely(LBUFSIZE == ret)) {
-			DBG_FLAT("binfmt_flat: buffer overflow (ORIG_NAME)?\n");
+			DBG_FLT("binfmt_flat: buffer overflow (ORIG_NAME)?\n");
 			return -ENOEXEC;
 		}
 	}
@@ -199,7 +247,7 @@
 		for (;  ret < LBUFSIZE && (buf[ret] != 0); ret++)
 			;
 		if (unlikely(LBUFSIZE == ret)) {
-			DBG_FLAT("binfmt_flat: buffer overflow (COMMENT)?\n");
+			DBG_FLT("binfmt_flat: buffer overflow (COMMENT)?\n");
 			return -ENOEXEC;
 		}
 	}
@@ -243,48 +291,78 @@
 
 #endif /* CONFIG_BINFMT_ZFLAT */
 
+/****************************************************************************/
 
 static unsigned long
-calc_reloc(unsigned long r, unsigned long text_len)
+calc_reloc(unsigned long r, struct lib_info *p, int curid, int internalp)
 {
 	unsigned long addr;
-
-	if (r > current->mm->start_brk - current->mm->start_data + text_len) {
-		printk("BINFMT_FLAT: reloc outside program 0x%x (0 - 0x%x), killing!\n",
-				(int) r,(int)(current->mm->start_brk-current->mm->start_code));
-		send_sig(SIGSEGV, current, 0);
-		return(current->mm->start_brk); /* return something safe to write to */
+	int id;
+	unsigned long start_brk;
+	unsigned long start_data;
+	unsigned long text_len;
+	unsigned long start_code;
+
+#ifdef CONFIG_BINFMT_SHARED_FLAT
+	if (r == 0)
+		id = curid;	/* Relocs of 0 are always self referring */
+	else {
+		id = (r >> 24) & 0xff;	/* Find ID for this reloc */
+		r &= 0x00ffffff;	/* Trim ID off here */
+	}
+	if (id >= MAX_SHARED_LIBS) {
+		printk("BINFMT_FLAT: reference 0x%x to shared library %d",
+				(unsigned) r, id);
+		goto failed;
+	}
+	if (curid != id) {
+		if (internalp) {
+			printk("BINFMT_FLAT: reloc address 0x%x not in same module "
+					"(%d != %d)", (unsigned) r, curid, id);
+			goto failed;
+		} else if ( ! p->lib_list[id].loaded &&
+				load_flat_shared_library(id, p) > (unsigned long) -4096) {
+			printk("BINFMT_FLAT: failed to load library %d", id);
+			goto failed;
+		}
+		/* Check versioning information (i.e. time stamps) */
+		if (p->lib_list[id].build_date && p->lib_list[curid].build_date &&
+				p->lib_list[curid].build_date < p->lib_list[id].build_date) {
+			printk("BINFMT_FLAT: library %d is younger than %d", id, curid);
+			goto failed;
+		}
 	}
+#else
+	id = 0;
+#endif
 
-	if (r < text_len) {
-		/* In text segment */
-		return r + current->mm->start_code;
-	}
+	start_brk = p->lib_list[id].start_brk;
+	start_data = p->lib_list[id].start_data;
+	start_code = p->lib_list[id].start_code;
+	text_len = p->lib_list[id].text_len;
+
+	if (!flat_reloc_valid(r, start_brk - start_data + text_len)) {
+		printk("BINFMT_FLAT: reloc outside program 0x%x (0 - 0x%x/0x%x)",
+		       (int) r,(int)(start_brk-start_code),(int)text_len);
+		goto failed;
+	}
+
+	if (r < text_len)			/* In text segment */
+		addr = r + start_code;
+	else					/* In data segment */
+		addr = r - text_len + start_data;
 
-	/*
-	 * we allow inclusive ranges here so that programs may do things
-	 * like reference the end of data (_end) without failing these tests
-	 */
-	addr =  r - text_len + current->mm->start_data;
-	if (addr >= current->mm->start_code &&
-			addr <= current->mm->start_code + text_len)
-		return(addr);
-
-	if (addr >= current->mm->start_data &&
-			addr <= current->mm->start_brk)
-		return(addr);
-
-	printk("BINFMT_FLAT: reloc addr outside text/data 0x%x "
-			"code(0x%x - 0x%x) data(0x%x - 0x%x) killing\n", (int) addr,
-			(int) current->mm->start_code,
-			(int) (current->mm->start_code + text_len),
-			(int) current->mm->start_data,
-			(int) current->mm->start_brk);
+	/* Range checked already above so doing the range tests is redundant...*/
+	return(addr);
+
+failed:
+	printk(", killing %s!\n", current->comm);
 	send_sig(SIGSEGV, current, 0);
 
-	return(current->mm->start_brk); /* return something safe to write to */
+	return RELOC_FAILED;
 }
 
+/****************************************************************************/
 
 void old_reloc(unsigned long rl)
 {
@@ -327,26 +405,22 @@
 #endif
 }		
 
+/****************************************************************************/
 
-/*
- * These are the functions used to load flat style executables and shared
- * libraries.  There is no binary dependent code anywhere else.
- */
-
-static int load_flat_binary(struct linux_binprm * bprm, struct pt_regs * regs)
+static int load_flat_file(struct linux_binprm * bprm,
+		struct lib_info *libinfo, int id, unsigned long *extra_stack)
 {
 	struct flat_hdr * hdr;
 	unsigned long textpos = 0, datapos = 0, result;
+	unsigned long realdatastart = 0;
 	unsigned long text_len, data_len, bss_len, stack_len, flags;
-	unsigned long memp = 0, memkasked = 0; /* for finding the brk area */
+	unsigned long memp = 0; /* for finding the brk area */
 	unsigned long extra, rlim;
-	unsigned long p = bprm->p;
 	unsigned long *reloc = 0, *rp;
 	struct inode *inode;
 	int i, rev, relocs = 0;
 	loff_t fpos;
-
-	DBG_FLT("BINFMT_FLAT: Loading file: %x\n", bprm->file);
+	unsigned long start_code, end_code;
 
 	hdr = ((struct flat_hdr *) bprm->buf);		/* exec-header */
 	inode = bprm->file->f_dentry->d_inode;
@@ -355,41 +429,42 @@
 	data_len  = ntohl(hdr->data_end) - ntohl(hdr->data_start);
 	bss_len   = ntohl(hdr->bss_end) - ntohl(hdr->data_end);
 	stack_len = ntohl(hdr->stack_size);
+	if (extra_stack) {
+		stack_len += *extra_stack;
+		*extra_stack = stack_len;
+	}
 	relocs    = ntohl(hdr->reloc_count);
 	flags     = ntohl(hdr->flags);
 	rev       = ntohl(hdr->rev);
 
-	/*
-	 * We have to add the size of our arguments to our stack size
-	 * otherwise it's too easy for users to create stack overflows
-	 * by passing in a huge argument list.  And yes,  we have to be
-	 * pedantic and include space for the argv/envp array as it may have
-	 * a lot of entries.
-	 */
-	#define TOP_OF_ARGS (PAGE_SIZE*MAX_ARG_PAGES-sizeof(void *))
-	stack_len += TOP_OF_ARGS - bprm->p;             /* the strings */
-	stack_len += (bprm->argc + 1) * sizeof(char *); /* the argv array */
-	stack_len += (bprm->envc + 1) * sizeof(char *); /* the envp array */
+	if (flags & FLAT_FLAG_KTRACE)
+		printk("BINFMT_FLAT: Loading file: %s\n", bprm->filename);
 
 	if (strncmp(hdr->magic, "bFLT", 4) ||
 			(rev != FLAT_VERSION && rev != OLD_FLAT_VERSION)) {
 		/*
 		 * because a lot of people do not manage to produce good
 		 * flat binaries,  we leave this printk to help them realise
-		 * the problem.  We only print the error if it's 
-		 * not a script file.
+		 * the problem.  We only print the error if its not a script file
 		 */
 		if (strncmp(hdr->magic, "#!", 2))
 			printk("BINFMT_FLAT: bad magic/rev (0x%x, need 0x%x)\n",
 					rev, (int) FLAT_VERSION);
 		return -ENOEXEC;
 	}
+	
+	/* Don't allow old format executables to use shared libraries */
+	if (rev == OLD_FLAT_VERSION && id != 0) {
+		printk("BINFMT_FLAT: shared libraries are not available before rev 0x%x\n",
+				(int) FLAT_VERSION);
+		return -ENOEXEC;
+	}
 
 	/*
 	 * fix up the flags for the older format,  there were all kinds
 	 * of endian hacks,  this only works for the simple cases
 	 */
-	if (rev == OLD_FLAT_VERSION && flags)
+	if (rev == OLD_FLAT_VERSION && flat_old_ram_flag(flags))
 		flags = FLAT_FLAG_RAM;
 
 #ifndef CONFIG_BINFMT_ZFLAT
@@ -411,15 +486,22 @@
 		return -ENOMEM;
 
 	/* Flush all traces of the currently running executable */
-	result = flush_old_exec(bprm);
-	if (result)
-		return result;
+	if (id == 0) {
+		result = flush_old_exec(bprm);
+		if (result)
+			return result;
+
+		/* OK, This is the point of no return */
+		set_personality(PER_LINUX);
+	}
 
-	/* OK, This is the point of no return */
-	set_personality(PER_LINUX);
+	/*
+	 * calculate the extra space we need to map in
+	 */
+	extra = max(bss_len + stack_len, relocs * sizeof(unsigned long));
 
 	/*
-	 * there are a couple of cases here,  the separate code/data
+	 * there are a couple of cases here,  the seperate code/data
 	 * case,  and then the fully copied to RAM case which lumps
 	 * it all together.
 	 */
@@ -437,26 +519,27 @@
 			if (!textpos)
 				textpos = (unsigned long) -ENOMEM;
 			printk("Unable to mmap process text, errno %d\n", (int)-textpos);
+			return(textpos);
 		}
 
-		extra = max(bss_len + stack_len, relocs * sizeof(unsigned long)),
-
 		down_write(&current->mm->mmap_sem);
-		datapos = do_mmap(0, 0, data_len + extra,
+		realdatastart = do_mmap(0, 0, data_len + extra +
+				MAX_SHARED_LIBS * sizeof(unsigned long),
 				PROT_READ|PROT_WRITE|PROT_EXEC, 0, 0);
 		up_write(&current->mm->mmap_sem);
 
-		if (datapos == 0 || datapos >= (unsigned long)-4096) {
-			if (!datapos)
-				datapos = (unsigned long) -ENOMEM;
+		if (realdatastart == 0 || realdatastart >= (unsigned long)-4096) {
+			if (!realdatastart)
+				realdatastart = (unsigned long) -ENOMEM;
 			printk("Unable to allocate RAM for process data, errno %d\n",
 					(int)-datapos);
 			do_munmap(current->mm, textpos, text_len);
-			return datapos;
+			return realdatastart;
 		}
+		datapos = realdatastart + MAX_SHARED_LIBS * sizeof(unsigned long);
 
 		DBG_FLT("BINFMT_FLAT: Allocated data+bss+stack (%d bytes): %x\n",
-				data_len + bss_len + stack_len, datapos);
+				(int)(data_len + bss_len + stack_len), (int)datapos);
 
 		fpos = ntohl(hdr->data_start);
 #ifdef CONFIG_BINFMT_ZFLAT
@@ -466,30 +549,24 @@
 		} else
 #endif
 		{
-			result = bprm->file->f_op->read(bprm->file,
-					(char *) datapos, data_len + extra, &fpos);
+			result = bprm->file->f_op->read(bprm->file, (char *) datapos,
+					data_len + (relocs * sizeof(unsigned long)), &fpos);
 		}
 		if (result >= (unsigned long)-4096) {
 			printk("Unable to read data+bss, errno %d\n", (int)-result);
 			do_munmap(current->mm, textpos, text_len);
-			do_munmap(current->mm, datapos, data_len + extra);
+			do_munmap(current->mm, realdatastart, data_len + extra);
 			return result;
 		}
 
 		reloc = (unsigned long *) (datapos+(ntohl(hdr->reloc_start)-text_len));
-		memp = datapos;
-		memkasked = data_len + extra;
+		memp = realdatastart;
 
 	} else {
 
-		/*
-		 * calculate the extra space we need to map in
-		 */
-
-		extra = max(bss_len + stack_len, relocs * sizeof(unsigned long)),
-
 		down_write(&current->mm->mmap_sem);
-		textpos = do_mmap(0, 0, text_len + data_len + extra,
+		textpos = do_mmap(0, 0, text_len + data_len + extra +
+					MAX_SHARED_LIBS * sizeof(unsigned long),
 				PROT_READ | PROT_EXEC | PROT_WRITE, 0, 0);
 		up_write(&current->mm->mmap_sem);
 		if (!textpos  || textpos >= (unsigned long) -4096) {
@@ -497,12 +574,14 @@
 				textpos = (unsigned long) -ENOMEM;
 			printk("Unable to allocate RAM for process text/data, errno %d\n",
 					(int)-textpos);
+			return(textpos);
 		}
 
-		datapos = textpos + ntohl (hdr->data_start);
-		reloc = (unsigned long *) (textpos + ntohl(hdr->reloc_start));
+		realdatastart = textpos + ntohl(hdr->data_start);
+		datapos = realdatastart + MAX_SHARED_LIBS * sizeof(unsigned long);
+		reloc = (unsigned long *) (textpos + ntohl(hdr->reloc_start) +
+				MAX_SHARED_LIBS * sizeof(unsigned long));
 		memp = textpos;
-		memkasked = text_len + data_len + extra;
 
 #ifdef CONFIG_BINFMT_ZFLAT
 		/*
@@ -514,6 +593,8 @@
 					 (text_len + data_len + (relocs * sizeof(unsigned long))
 						  - sizeof (struct flat_hdr)),
 					 0);
+			memmove((void *) datapos, (void *) realdatastart,
+					data_len + (relocs * sizeof(unsigned long)));
 		} else if (flags & FLAT_FLAG_GZDATA) {
 			fpos = 0;
 			result = bprm->file->f_op->read(bprm->file,
@@ -527,40 +608,64 @@
 		{
 			fpos = 0;
 			result = bprm->file->f_op->read(bprm->file,
-					(char *) textpos, text_len + data_len + extra, &fpos);
+					(char *) textpos, text_len, &fpos);
+			if (result < (unsigned long) -4096) {
+				fpos = ntohl(hdr->data_start);
+				result = bprm->file->f_op->read(bprm->file, (char *) datapos,
+					data_len + (relocs * sizeof(unsigned long)), &fpos);
+			}
 		}
 		if (result >= (unsigned long)-4096) {
 			printk("Unable to read code+data+bss, errno %d\n",(int)-result);
-			do_munmap(current->mm, textpos, text_len + data_len + extra);
+			do_munmap(current->mm, textpos, text_len + data_len + extra +
+				MAX_SHARED_LIBS * sizeof(unsigned long));
 			return result;
 		}
 	}
 
-	DBG_FLT("Mapping is %x, Entry point is %x, data_start is %x\n",
-			textpos, ntohl(hdr->entry), ntohl(hdr->data_start));
+	if (flags & FLAT_FLAG_KTRACE)
+		printk("Mapping is %x, Entry point is %x, data_start is %x\n",
+			(int)textpos, 0x00ffffff&ntohl(hdr->entry), ntohl(hdr->data_start));
+
+	/* The main program needs a little extra setup in the task structure */
+	start_code = textpos + sizeof (struct flat_hdr);
+	end_code = textpos + text_len;
+	if (id == 0) {
+		current->mm->start_code = start_code;
+		current->mm->end_code = end_code;
+		current->mm->start_data = datapos;
+		current->mm->end_data = datapos + data_len;
+		/*
+		 * set up the brk stuff, uses any slack left in data/bss/stack
+		 * allocation.  We put the brk after the bss (between the bss
+		 * and stack) like other platforms.
+		 */
+		current->mm->start_brk = datapos + data_len + bss_len;
+		current->mm->brk = (current->mm->start_brk + 3) & ~3;
+		current->mm->context.end_brk = memp + ksize((void *) memp) - stack_len;
+		current->mm->rss = 0;
+	}
 
-	current->mm->start_code = textpos + sizeof (struct flat_hdr);
-	current->mm->end_code = textpos + text_len;
-	current->mm->start_data = datapos;
-	current->mm->end_data = datapos + data_len;
-	/*
-	 *	set up the brk stuff (uses any slack left in data/bss/stack allocation
-	 *	We put the brk after the bss (between the bss and stack) like other
-	 *	platforms.
-	 */
-	current->mm->start_brk = datapos + data_len + bss_len;
-	current->mm->brk = (current->mm->start_brk + 3) & ~3;
-	current->mm->context.end_brk = memp + ksize((void *) memp) - stack_len;
-	current->mm->rss = 0;
-
-	DBG_FLT("Load %s: TEXT=%x-%x DATA=%x-%x BSS=%x-%x\n",
-		bprm->filename,
-		(int) current->mm->start_code, (int) current->mm->end_code,
-		(int) current->mm->start_data, (int) current->mm->end_data,
-		(int) current->mm->end_data, (int) current->mm->brk);
+	if (flags & FLAT_FLAG_KTRACE)
+		printk("%s %s: TEXT=%x-%x DATA=%x-%x BSS=%x-%x\n",
+			id ? "Lib" : "Load", bprm->filename,
+			(int) start_code, (int) end_code,
+			(int) datapos,
+			(int) (datapos + data_len),
+			(int) (datapos + data_len),
+			(int) (((datapos + data_len + bss_len) + 3) & ~3));
 
 	text_len -= sizeof(struct flat_hdr); /* the real code len */
 
+	/* Store the current module values into the global library structure */
+	libinfo->lib_list[id].start_code = start_code;
+	libinfo->lib_list[id].start_data = datapos;
+	libinfo->lib_list[id].start_brk = datapos + data_len + bss_len;
+	libinfo->lib_list[id].text_len = text_len;
+	libinfo->lib_list[id].loaded = 1;
+	libinfo->lib_list[id].entry = (0x00ffffff & ntohl(hdr->entry)) + textpos;
+	libinfo->lib_list[id].build_date = ntohl(hdr->build_date);
+	
 	/*
 	 * We just load the allocations into some temporary memory to
 	 * help simplify all this mumbo jumbo
@@ -573,10 +678,16 @@
 	 * really an offset into the image which contains an offset into the
 	 * image.
 	 */
-	
 	if (flags & FLAT_FLAG_GOTPIC) {
-		for (rp = (unsigned long *)datapos; *rp != 0xffffffff; rp++)
-			*rp = calc_reloc(*rp, text_len);
+		for (rp = (unsigned long *)datapos; *rp != 0xffffffff; rp++) {
+			unsigned long addr;
+			if (*rp) {
+				addr = calc_reloc(*rp, libinfo, id, 0);
+				if (addr == RELOC_FAILED)
+					return -ENOEXEC;
+				*rp = addr;
+			}
+		}
 	}
 
 	/*
@@ -590,63 +701,172 @@
 	 * reference to be statically initialised to _stext (I've moved
 	 * __start to address 4 so that is okay).
 	 */
-
 	if (rev > OLD_FLAT_VERSION) {
 		for (i=0; i < relocs; i++) {
-			unsigned long addr;
+			unsigned long addr, relval;
 
 			/* Get the address of the pointer to be
 			   relocated (of course, the address has to be
 			   relocated first).  */
-			rp = (unsigned long *) calc_reloc(ntohl(reloc[i]), text_len);
+			relval = ntohl(reloc[i]);
+			addr = flat_get_relocate_addr(relval);
+			rp = (unsigned long *) calc_reloc(addr, libinfo, id, 1);
+			if (rp == (unsigned long *)RELOC_FAILED)
+				return -ENOEXEC;
 
 			/* Get the pointer's value.  */
-			addr = get_unaligned (rp);
-
+			addr = flat_get_addr_from_rp(rp, relval);
 			if (addr != 0) {
 				/*
 				 * Do the relocation.  PIC relocs in the data section are
 				 * already in target order
 				 */
-				addr = calc_reloc(
-						(flags & FLAT_FLAG_GOTPIC) ? addr : ntohl(addr),
-						text_len);
+				if ((flags & FLAT_FLAG_GOTPIC) == 0)
+					addr = ntohl(addr);
+				addr = calc_reloc(addr, libinfo, id, 0);
+				if (addr == RELOC_FAILED)
+					return -ENOEXEC;
+
 				/* Write back the relocated pointer.  */
-				put_unaligned (addr, rp);
+				flat_put_addr_at_rp(rp, addr, relval);
 			}
 		}
 	} else {
 		for (i=0; i < relocs; i++)
 			old_reloc(ntohl(reloc[i]));
 	}
+	
+	flush_icache_range(start_code, end_code);
 
 	/* zero the BSS,  BRK and stack areas */
 	memset((void*)(datapos + data_len), 0, bss_len + 
-			(current->mm->context.end_brk - current->mm->start_brk) +
+			(memp + ksize((void *) memp) - stack_len -	/* end brk */
+			libinfo->lib_list[id].start_brk) +		/* start brk */
 			stack_len);
 
+	return 0;
+}
+
+
+/****************************************************************************/
+#ifdef CONFIG_BINFMT_SHARED_FLAT
+
+/*
+ * Load a shared library into memory.  The library gets its own data
+ * segment (including bss) but not argv/argc/environ.
+ */
+
+static int load_flat_shared_library(int id, struct lib_info *libs)
+{
+	struct linux_binprm bprm;
+	int res;
+	char buf[16];
+
+	/* Create the file name */
+	sprintf(buf, "/lib/lib%d.so", id);
+
+	/* Open the file up */
+	bprm.filename = buf;
+	bprm.file = open_exec(bprm.filename);
+	res = PTR_ERR(bprm.file);
+	if (IS_ERR(bprm.file))
+		return res;
+
+	res = prepare_binprm(&bprm);
+
+	if (res <= (unsigned long)-4096)
+		res = load_flat_file(&bprm, libs, id, NULL);
+	if (bprm.file) {
+		allow_write_access(bprm.file);
+		fput(bprm.file);
+		bprm.file = NULL;
+	}
+	return(res);
+}
+
+#endif /* CONFIG_BINFMT_SHARED_FLAT */
+/****************************************************************************/
+
+/*
+ * These are the functions used to load flat style executables and shared
+ * libraries.  There is no binary dependent code anywhere else.
+ */
+
+static int load_flat_binary(struct linux_binprm * bprm, struct pt_regs * regs)
+{
+	struct lib_info libinfo;
+	unsigned long p = bprm->p;
+	unsigned long stack_len;
+	unsigned long start_addr;
+	unsigned long *sp;
+	int res;
+	int i, j;
+
+	memset(&libinfo, 0, sizeof(libinfo));
+	/*
+	 * We have to add the size of our arguments to our stack size
+	 * otherwise it's too easy for users to create stack overflows
+	 * by passing in a huge argument list.  And yes,  we have to be
+	 * pedantic and include space for the argv/envp array as it may have
+	 * a lot of entries.
+	 */
+#define TOP_OF_ARGS (PAGE_SIZE * MAX_ARG_PAGES - sizeof(void *))
+	stack_len = TOP_OF_ARGS - bprm->p;             /* the strings */
+	stack_len += (bprm->argc + 1) * sizeof(char *); /* the argv array */
+	stack_len += (bprm->envc + 1) * sizeof(char *); /* the envp array */
+
+	
+	res = load_flat_file(bprm, &libinfo, 0, &stack_len);
+	if (res > (unsigned long)-4096)
+		return res;
+	
+	/* Update data segment pointers for all libraries */
+	for (i=0; i<MAX_SHARED_LIBS; i++)
+		if (libinfo.lib_list[i].loaded)
+			for (j=0; j<MAX_SHARED_LIBS; j++)
+				(-(j+1))[(unsigned long *)(libinfo.lib_list[i].start_data)] =
+					(libinfo.lib_list[j].loaded)?
+						libinfo.lib_list[j].start_data:UNLOADED_LIB;
+
 	compute_creds(bprm);
  	current->flags &= ~PF_FORKNOEXEC;
 
-	flush_icache_range(current->mm->start_code, current->mm->end_code);
-
 	set_binfmt(&flat_format);
 
 	p = ((current->mm->context.end_brk + stack_len + 3) & ~3) - 4;
-	DBG_FLT("p=%x\n", p);
+	DBG_FLT("p=%x\n", (int)p);
 
 	/* copy the arg pages onto the stack, this could be more efficient :-) */
 	for (i = TOP_OF_ARGS - 1; i >= bprm->p; i--)
 		* (char *) --p =
 			((char *) page_address(bprm->page[i/PAGE_SIZE]))[i % PAGE_SIZE];
 
-	current->mm->start_stack = (unsigned long) create_flat_tables(p, bprm);
+	sp = (unsigned long *) create_flat_tables(p, bprm);
+	
+	/* Fake some return addresses to ensure the call chain will
+	 * initialise library in order for us.  We are required to call
+	 * lib 1 first, then 2, ... and finally the main program (id 0).
+	 */
+	start_addr = libinfo.lib_list[0].entry;
 
+#ifdef CONFIG_BINFMT_SHARED_FLAT
+	for (i = MAX_SHARED_LIBS-1; i>0; i--) {
+		if (libinfo.lib_list[i].loaded) {
+			/* Push previos first to call address */
+			--sp;	put_user(start_addr, sp);
+			start_addr = libinfo.lib_list[i].entry;
+		}
+	}
+#endif
+	
+	/* Stash our initial stack pointer into the mm structure */
+	current->mm->start_stack = (unsigned long )sp;
+
+	
 	DBG_FLT("start_thread(regs=0x%x, entry=0x%x, start_stack=0x%x)\n",
-		regs, textpos + ntohl(hdr->entry), current->mm->start_stack);
-	start_thread(regs,
-		     textpos + ntohl(hdr->entry),
-		     current->mm->start_stack);
+		(int)regs, (int)start_addr, (int)current->mm->start_stack);
+	
+	start_thread(regs, start_addr, current->mm->start_stack);
 
 	if (current->ptrace & PT_PTRACED)
 		send_sig(SIGTRAP, current, 0);
@@ -654,10 +874,7 @@
 	return 0;
 }
 
-static int load_flat_library(struct file *file)
-{
-	return(-ENOEXEC);
-}
+/****************************************************************************/
 
 static int __init init_flat_binfmt(void)
 {
@@ -669,5 +886,9 @@
 	unregister_binfmt(&flat_format);
 }
 
+/****************************************************************************/
+
 module_init(init_flat_binfmt);
 module_exit(exit_flat_binfmt);
+
+/****************************************************************************/
diff -Nru a/fs/block_dev.c b/fs/block_dev.c
--- a/fs/block_dev.c	Sun May 25 18:29:01 2003
+++ b/fs/block_dev.c	Wed Jul  2 21:21:28 2003
@@ -155,11 +155,13 @@
  */
 static loff_t block_llseek(struct file *file, loff_t offset, int origin)
 {
-	/* ewww */
-	loff_t size = file->f_dentry->d_inode->i_bdev->bd_inode->i_size;
+	struct inode *bd_inode;
+	loff_t size;
 	loff_t retval;
 
-	lock_kernel();
+	bd_inode = file->f_dentry->d_inode->i_bdev->bd_inode;
+	down(&bd_inode->i_sem);
+	size = bd_inode->i_size;
 
 	switch (origin) {
 		case 2:
@@ -175,7 +177,7 @@
 		}
 		retval = offset;
 	}
-	unlock_kernel();
+	up(&bd_inode->i_sem);
 	return retval;
 }
 	
diff -Nru a/fs/buffer.c b/fs/buffer.c
--- a/fs/buffer.c	Fri Jun 27 01:46:43 2003
+++ b/fs/buffer.c	Sun Jul  6 18:06:47 2003
@@ -319,6 +319,7 @@
 
 	/* We need to protect against concurrent writers.. */
 	down(&inode->i_sem);
+	current->flags |= PF_SYNCWRITE;
 	ret = filemap_fdatawrite(inode->i_mapping);
 	err = file->f_op->fsync(file, dentry, 0);
 	if (!ret)
@@ -326,6 +327,7 @@
 	err = filemap_fdatawait(inode->i_mapping);
 	if (!ret)
 		ret = err;
+	current->flags &= ~PF_SYNCWRITE;
 	up(&inode->i_sem);
 
 out_putf:
@@ -354,6 +356,7 @@
 		goto out_putf;
 
 	down(&inode->i_sem);
+	current->flags |= PF_SYNCWRITE;
 	ret = filemap_fdatawrite(inode->i_mapping);
 	err = file->f_op->fsync(file, dentry, 1);
 	if (!ret)
@@ -361,6 +364,7 @@
 	err = filemap_fdatawait(inode->i_mapping);
 	if (!ret)
 		ret = err;
+	current->flags &= ~PF_SYNCWRITE;
 	up(&inode->i_sem);
 
 out_putf:
@@ -1446,6 +1450,17 @@
 	return bh;
 }
 EXPORT_SYMBOL(__getblk);
+
+/*
+ * Do async read-ahead on a buffer..
+ */
+void __breadahead(struct block_device *bdev, sector_t block, int size)
+{
+	struct buffer_head *bh = __getblk(bdev, block, size);
+	ll_rw_block(READA, 1, &bh);
+	brelse(bh);
+}
+EXPORT_SYMBOL(__breadahead);
 
 /**
  *  __bread() - reads a specified block and returns the bh
diff -Nru a/fs/cifs/CHANGES b/fs/cifs/CHANGES
--- a/fs/cifs/CHANGES	Wed Jun 18 00:03:00 2003
+++ b/fs/cifs/CHANGES	Sun Jul  6 22:36:33 2003
@@ -1,3 +1,13 @@
+Version 0.81
+------------
+Finish up CIFS packet digital signing for the default
+NTLM security case. This should help Windows 2003
+network interoperability since it is common for
+packet signing to be required now. Fix statfs (stat -f)
+which recently started returning errors due to 
+invalid value (-1 instead of 0) being set in the
+struct kstatfs f_ffiles field.
+
 Version 0.80
 -----------
 Fix oops on stopping oplock thread when removing cifs when
diff -Nru a/fs/cifs/Makefile b/fs/cifs/Makefile
--- a/fs/cifs/Makefile	Sat Dec 14 04:38:56 2002
+++ b/fs/cifs/Makefile	Fri Jul  4 15:07:25 2003
@@ -3,4 +3,4 @@
 #
 obj-$(CONFIG_CIFS) += cifs.o
 
-cifs-objs := cifsfs.o cifssmb.o cifs_debug.o connect.o dir.o file.o inode.o link.o misc.o netmisc.o smbdes.o smbencrypt.o transport.o asn1.o md4.o md5.o cifs_unicode.o nterr.o
+cifs-objs := cifsfs.o cifssmb.o cifs_debug.o connect.o dir.o file.o inode.o link.o misc.o netmisc.o smbdes.o smbencrypt.o transport.o asn1.o md4.o md5.o cifs_unicode.o nterr.o xattr.o cifsencrypt.o
diff -Nru a/fs/cifs/README b/fs/cifs/README
--- a/fs/cifs/README	Thu Nov 21 14:58:06 2002
+++ b/fs/cifs/README	Fri Jul  4 16:31:08 2003
@@ -1,5 +1,5 @@
-This is the CIFS VFS support for Linux.  It supports many advanced network filesystem
-features such as heirarchical dfs like filesystem, hardlinks, locking and more.
+The CIFS VFS support for Linux supports many advanced network filesystem
+features such as heirarchical dfs like namespace, hardlinks, locking and more.
 It was designed to comply with the SNIA CIFS Technical Reference (which supersedes
 the 1992 X/Open SMB Standard) as well as to perform best practice practical
 interoperability with Windows 2000, Windows XP, Samba and equivalent 
@@ -9,43 +9,65 @@
 
 Build instructions:
 ==================
-Get the kernel source e.g. http://linux.bkbits.net/linux-2.5 or http://www.kernel.org 
-http://cifs.bkbits.net/linux-2.4  
-make menuconfig (or make xconfig)
-select cifs from within the network filesystem choices
-save and exit
-make dep
-make modules  (or "make" if you did not select CIFS VFS to be built as a module)
+For Linux 2.4:
+1a) Get the linux kernel source with cifs vfs already in it
+from bitkeeper via bk://cifs.bkbits.net/linux-2.4
+or
+1b) Get the kernel source (e.g.from http://www.kernel.org)
+and download the cifs vfs source (see the project page
+at http://us1.samba.org/samba/Linux_CIFS_client.html)
+and change directory into the top of the kernel directory
+then patch the kernel (e.g. "patch -p1 < cifs_24.patch") 
+to add the cifs vfs to your kernel configure options if
+it has not already been added (e.g. current SuSE and UL
+users do not need to do not need that patch since the cifs vfs is
+already in the kernel configure menu) and then
+mkdir linux/fs/cifs and then copy the current cifs vfs files from
+the cifs download to your kernel build directory e.g.
+	cp <cifs_download_dir>/fs/cifs/* to <kernel_download_dir>/fs/cifs
+2) make menuconfig (or make xconfig)
+3) select cifs from within the network filesystem choices
+4) save and exit
+5) make dep
+6) make modules (or "make" if CIFS VFS not to be built as a module)
+
+For Linux 2.5:
+1) Download the kernel (e.g. from http://www.kernel.org or from bitkeeper
+at bk://linux.bkbits.net/linux-2.5) and change directory into the top
+of the kernel directory tree (e.g. /usr/src/linux-2.5.73)
+2) make menuconfig (or make xconfig)
+3) select cifs from within the network filesystem choices
+4) save and exit
+5) make
+
 
 Installation instructions:
 =========================
-If you have built the CIFS vfs as module (successfully)you
-simply type "make modules_install" (or if you prefer manually copy the file to
+If you have built the CIFS vfs as module (successfully) simply
+type "make modules_install" (or if you prefer, manually copy the file to
 the modules directory e.g. /lib/modules/2.4.10-4GB/kernel/fs/cifs/cifs.o).
 
 If you have built the CIFS vfs into the kernel itself, follow the instructions
 for your distribution on how to install a new kernel (usually you
 would simply type "make install").
 
-If you do not have the utility mount.cifs (in the Samba 3.0 source tree and on the
-CIFS VFS web site) copy it to the directory /sbin (or the same directory in which 
-mount.smbfs resides).  Although no helper software is required, the installation
-of mount.cifs is recommended.  Eventually the Samba 3.0 utility program "net" 
+If you do not have the utility mount.cifs (in the Samba 3.0 source tree and on 
+the CIFS VFS web site) copy it to the same directory in which mount.smbfs and 
+similar files reside (usually /sbin).  Although the helper software is required, 
+mount.cifs is recommended.  Eventually the Samba 3.0 utility program "net" 
 may also be helpful since it may someday provide easier mount syntax for users used 
 to Windows e.g.
 	 net use <mount point> <UNC name or cifs URL> 	 
-and there will likely be other helper programs available ala smbmount to provide
-additional optional function in the future.  Note that running Winbind on all
-of your Linux clients is useful in mapping Uids and Gids consistently to the
-proper network user.	
+Note that running Winbind on all of your Linux clients is useful in 
+in mapping Uids and Gids consistently to the proper network user.
 
 Samba Considerations
 ====================
 To get the maximum benefit from the CIFS VFS, we recommend using a server that
-supports the SNIA CIFS Unix Extensions standard (e.g. Samba 2.2.5 or Samba 3.0)
-but the CIFS vfs works fine with a wide variety of CIFS servers.  Note that the
-uid, gid and file permissions will display default values if you do not have
-a server that supports the Unix extensions for CIFS (such as Samba 2.2.3 or
+supports the SNIA CIFS Unix Extensions standard (e.g. Samba 2.2.5 or later or 
+Samba 3.0) but the CIFS vfs works fine with a wide variety of CIFS servers. 
+Note that uid, gid and file permissions will display default values if you do
+not have a server that supports the Unix extensions for CIFS (such as Samba 2.2.3 or
 later).   To enable the Unix CIFS Extensions in the Samba server, add the line:
 	unix extensions = yes
 to your smb.conf file on the server.  Note that the following smb.conf settings are
@@ -81,15 +103,79 @@
 "Netbios-Over-TCP/IP."  Neither of these is likely to be a problem as most servers
 support this.  IPv6 support is planned for the future.  
 
+CIFS VFS Mount Options
+======================
+A partial list of the supported mount options follows:
+  user		The user name to use when trying to establish
+		the CIFS session.
+  password	The user password.  If the mount helper is
+		installed, the user will be prompted for password
+		if it is not supplied.
+  ip		The ip address of the target server
+  unc		The target server Universal Network Name (export) to 
+		mount.	
+  domain	Set the SMB/CIFS workgroup name prepended to the
+		username during CIFS session establishment
+  uid           If CIFS Unix extensions are not supported by the server
+                this overrides the default uid for inodes.
+  gid		If CIFS Unix extensions are not supported by the server
+		this overrides the default gid for inodes.
+  file_mode     If CIFS Unix extensions are not supported by the server
+		this overrides the default mode for file inodes.
+  dir_mode      If CIFS Unix extensions are not supported by the server 
+		this overrides the default mode for directory inodes.
+  port		attempt to contact the server on this tcp port, before
+		trying the usual ports (port 445, then 139).
+  rsize		default read size
+  wsize		default write size
+  rw		mount the network share read-write (note that the
+		server may still consider the share read-only)
+  ro		mount network share read-only
+  version	used to distinguish different versions of the
+		mount helper utility (not typically needed)
+
 Misc /proc/fs/cifs Flags and Debug Info
 =======================================
-Various experimental features and tracing can be enabled by changing flags in /proc/fs/cifs (after
-the cifs module has been installed or built into the kernel, e.g. insmod cifs).  To enable
-a feature you can set it to 1 e.g. to enable tracing to the kernel message log you can do
-"echo 1 > /proc/fs/cifs/cifsFYI" and "echo 1 > /proc/fs/cifs/traceSMB"
-Also note that "cat /proc/fs/cifs/DebugData" will display some information about the currently
-active sessions and the shares that are mounted. Currently the ntlmv2 enablement and packet
-signing will not work since they the implementation is not quite complete, so do not enable
+Informational pseudo-files:
+  DebugData		Displays information about active CIFS sessions
+  SimultaneousOps       Counter which holds maximum number of
+			simultaneous outstanding SMB/CIFS requests.
+  Stats			Lists summary resource usage information
+
+Configuration pseudo-files:
+  MultiuserMount	If set to one, more than one CIFS session to 
+			the same server ip address can be established
+			if more than one uid accesses the same mount
+			point and if the uids user/password mapping
+			information is available. (default is 0)
+  PacketSigningEnabled  If set to one, cifs packet signing is enabled
+			(default 0)
+  cifsFYI		If set to one, additional debug information is
+			logged to the system error log. (default 0)
+  ExtendedSecurity	If set to one, SPNEGO session establishment
+			is allowed which enables more advanced 
+			secure CIFS session establishment (default 0)
+  NTLMV2Enabled		If set to one, more secure password hashes
+			are used when the server supports them and
+			when kerberos is not negotiated (default 0)
+  traceSMB		If set to one, debug information is logged to the
+			system error log with the start of smb requests
+			and responses (default 0)
+  LookupCacheEnable     If set to one, inode information is kept cached
+			for one second improving performance of lookups
+			(default 1)
+  OplockEnabled		If set to one, safe distributed caching enabled.
+
+These experimental features and tracing can be enabled by changing flags in /proc/fs/cifs
+(after the cifs module has been installed or built into the kernel, e.g. insmod cifs). 
+To enable a feature set it to 1 e.g. to enable tracing to the kernel message log
+type:
+	echo 1 > /proc/fs/cifs/cifsFYI
+and for more extensive tracing including the start of smb requests and responses
+	echo 1 > /proc/fs/cifs/traceSMB
+Also note that "cat /proc/fs/cifs/DebugData" will display some information about the
+active sessions and the shares that are mounted. NTLMv2 enablement and packet
+signing will not work since they the implementation is not quite complete. Do not enable
 these flags unless you are doing specific testing.  Enabling extended security works to
 Windows 2000 Workstations and XP but not to Windows 2000 server or Samba since it does not
 usually send "raw NTLMSSP" (instead it sends NTLMSSP encapsulated in SPNEGO/GSSAPI, which
diff -Nru a/fs/cifs/TODO b/fs/cifs/TODO
--- a/fs/cifs/TODO	Fri May 16 09:07:44 2003
+++ b/fs/cifs/TODO	Fri Jul  4 16:31:08 2003
@@ -1,4 +1,4 @@
-version 0.6.5 February 15, 2003
+version 0.8.1 July 4th, 2003
 
 A Partial List of Known Problems and Missing Features
 =====================================================
@@ -19,10 +19,9 @@
 
 e) NTLMv2 authentication and MD5-HMAC signing SMB PDUs - (mostly implemented)
 	signing necessary for some Windows 2003 servers in domain 
-	controller mode.
+	mode.
 
-f) oplock support (ie safe CIFS distributed file caching) is not quite complete.
-In addition Directory entry caching relies on a 1 second timer, rather than 
+f) Directory entry caching relies on a 1 second timer, rather than 
 using FindNotify or equivalent.  - (started)
 
 g) There may be a few additional changes that could be done to take advantage
@@ -47,15 +46,16 @@
 n) send oplock break response when sent (oplock currently disabled in
 /proc/fs/cifs)
 
-o) remove calls to set end of file by name when we already have file open
-(use the existing handle since some servers only support that and it
-reduces the oplock breaks coming from windows).  Piggyback identical
+o) reduces the oplock breaks coming from windows).  Piggyback identical
 file opens on top of each other by incrementing reference count rather
 than resending (helps reduce server resource utilization and avoid
 spurious oplock breaks).
 
+p) Improve performance of readpages by sending more than one read
+at a time when 8 pages or more are requested.
 
-KNOWN BUGS (updated May 16, 2003)
+
+KNOWN BUGS (updated July 4th, 2003)
 ====================================
 1) existing symbolic links (Windows reparse points) are recognized but
 can not be created remotely. They are implemented for Samba and those that
@@ -74,8 +74,8 @@
 1) check out max path names and max path name components against various server
 types.
 
-2) Run dbench
+2) Run dbench. Modify file portion of ltp so it can run against a mounted network
+share and run it against cifs vfs.
 
-3) Finish high stress fsx testing on SMP clients
+3) Additional performance testing and optimization using iozone and similar tools.
 
-4) Additional performance testing and optimization
diff -Nru a/fs/cifs/cifs_unicode.c b/fs/cifs/cifs_unicode.c
--- a/fs/cifs/cifs_unicode.c	Sat Feb 15 14:10:23 2003
+++ b/fs/cifs/cifs_unicode.c	Fri Jun 27 00:52:19 2003
@@ -34,7 +34,7 @@
 void
 toUpper(const struct nls_table *n, char *mixed_string)
 {
-	int i;
+	unsigned int i;
 	char temp;
 
 	for (i = 0; i < strlen(mixed_string); i++) {
diff -Nru a/fs/cifs/cifsencrypt.c b/fs/cifs/cifsencrypt.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/fs/cifs/cifsencrypt.c	Sun Jul  6 18:24:42 2003
@@ -0,0 +1,140 @@
+/*
+ *   fs/cifs/cifsencrypt.c
+ *
+ *   Copyright (c) International Business Machines  Corp., 2003
+ *   Author(s): Steve French (sfrench@us.ibm.com)
+ *
+ *   This library is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU Lesser General Public License as published
+ *   by the Free Software Foundation; either version 2.1 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This library is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
+ *   the GNU Lesser General Public License for more details.
+ *
+ *   You should have received a copy of the GNU Lesser General Public License
+ *   along with this library; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/fs.h>
+#include "cifspdu.h"
+#include "cifsglob.h" 
+#include "cifs_debug.h"
+#include "md5.h"
+
+/* Calculate and return the CIFS signature based on the mac key and the smb pdu */
+/* the 16 byte signature must be allocated by the caller  */
+/* Note we only use the 1st eight bytes */
+/* Note that the smb header signature field on input contains the  
+	sequence number before this function is called */
+
+extern void mdfour(unsigned char *out, unsigned char *in, int n);
+extern void E_md4hash(const unsigned char *passwd, unsigned char *p16);
+	
+static int cifs_calculate_signature(const struct smb_hdr * cifs_pdu, const char * key, char * signature)
+{
+	struct	MD5Context context;
+
+	if((cifs_pdu == NULL) || (signature == NULL))
+		return -EINVAL;
+
+	MD5Init(&context);
+	MD5Update(&context,key,CIFS_SESSION_KEY_SIZE+16);
+	MD5Update(&context,cifs_pdu->Protocol,cifs_pdu->smb_buf_length);
+	MD5Final(signature,&context);
+	return 0;
+}
+
+int cifs_sign_smb(struct smb_hdr * cifs_pdu, struct cifsSesInfo * ses,
+	__u32 * pexpected_response_sequence_number)
+{
+	int rc = 0;
+	char smb_signature[20];
+
+	/* BB remember to initialize sequence number elsewhere and initialize mac_signing key elsewhere BB */
+	/* BB remember to add code to save expected sequence number in midQ entry BB */
+
+	if((cifs_pdu == NULL) || (ses == NULL))
+		return -EINVAL;
+
+	if((le32_to_cpu(cifs_pdu->Flags2) & SMBFLG2_SECURITY_SIGNATURE) == 0) 
+		return rc;
+
+	write_lock(&GlobalMid_Lock);
+	cifs_pdu->Signature.Sequence.SequenceNumber = cpu_to_le32(ses->sequence_number);
+	cifs_pdu->Signature.Sequence.Reserved = 0;
+	
+	*pexpected_response_sequence_number = ses->sequence_number++;
+	ses->sequence_number++;
+	write_unlock(&GlobalMid_Lock);
+
+	rc = cifs_calculate_signature(cifs_pdu, ses->mac_signing_key,smb_signature);
+	if(rc)
+                memset(cifs_pdu->Signature.SecuritySignature, 0, 8);
+	else
+		memcpy(cifs_pdu->Signature.SecuritySignature, smb_signature, 8);
+
+	return rc;
+}
+
+int cifs_verify_signature(struct smb_hdr * cifs_pdu, const char * mac_key,
+	__u32 expected_sequence_number)
+{
+	unsigned int rc;
+	char server_response_sig[8];
+	char what_we_think_sig_should_be[20];
+
+        if((cifs_pdu == NULL) || (mac_key == NULL))
+                return -EINVAL;
+
+	if (cifs_pdu->Command == SMB_COM_NEGOTIATE)
+		return 0;
+
+	/* BB what if signatures are supposed to be on for session but server does not
+		send one? BB */
+	/* BB also do not verify oplock breaks for signature */
+	
+	/* Do not need to verify session setups with signature "BSRSPYL "  */
+	if(memcmp(cifs_pdu->Signature.SecuritySignature,"BSRSPYL ",8)==0)
+		cFYI(1,("dummy signature received for smb command 0x%x",cifs_pdu->Command));
+
+	expected_sequence_number = cpu_to_le32(expected_sequence_number);
+
+	/* save off the origiginal signature so we can modify the smb and check
+		its signature against what the server sent */
+	memcpy(server_response_sig,cifs_pdu->Signature.SecuritySignature,8);
+
+        cifs_pdu->Signature.Sequence.SequenceNumber = expected_sequence_number;
+        cifs_pdu->Signature.Sequence.Reserved = 0;
+
+        rc = cifs_calculate_signature(cifs_pdu, mac_key,
+		what_we_think_sig_should_be);
+
+	if(rc)
+		return rc;
+
+	
+/*	cifs_dump_mem("what we think it should be: ",what_we_think_sig_should_be,16); */
+
+	if(memcmp(server_response_sig, what_we_think_sig_should_be, 8))
+		return -EACCES;
+	else
+		return 0;
+
+}
+
+/* We fill in key by putting in 40 byte array which was allocated by caller */
+int cifs_calculate_mac_key(char * key, const char * rn, const char * password)
+{
+	char temp_key[16];
+	if ((key == NULL) || (rn == NULL) || (password == NULL))
+		return -EINVAL;
+
+	E_md4hash(password, temp_key);  /* BB may have to do another md4 of it */
+	mdfour(key,temp_key,16);
+	memcpy(key+16,rn, CIFS_SESSION_KEY_SIZE);
+	return 0;
+} 
diff -Nru a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
--- a/fs/cifs/cifsfs.c	Fri Jun 20 13:16:06 2003
+++ b/fs/cifs/cifsfs.c	Sun Jul  6 22:36:36 2003
@@ -165,7 +165,7 @@
 					   able to support more than this, but best to be safe
 					   since Win2k and others can not handle very long filenames */
 	buf->f_files = 0;	/* undefined */
-	buf->f_ffree = -1;	/* unlimited */
+	buf->f_ffree = 0;	/* unlimited */
 
 	rc = CIFSSMBQFSInfo(xid, pTcon, buf, cifs_sb->local_nls);
 
@@ -178,7 +178,7 @@
 	return 0;		/* always return success? what if volume is no longer available? */
 }
 
-static int cifs_permission(struct inode * inode, int mask)
+static int cifs_permission(struct inode * inode, int mask, struct nameidata *nd)
 {
 	/* the server does permission checks, we do not need to do it here */
 	return 0;
diff -Nru a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h
--- a/fs/cifs/cifsfs.h	Sat Feb 15 14:10:23 2003
+++ b/fs/cifs/cifsfs.h	Fri Jul  4 16:05:49 2003
@@ -46,8 +46,8 @@
 
 /* Functions related to inodes */
 extern struct inode_operations cifs_dir_inode_ops;
-extern int cifs_create(struct inode *, struct dentry *, int);
-extern struct dentry *cifs_lookup(struct inode *, struct dentry *);
+extern int cifs_create(struct inode *, struct dentry *, int, struct nameidata *);
+extern struct dentry *cifs_lookup(struct inode *, struct dentry *, struct nameidata *);
 extern int cifs_unlink(struct inode *, struct dentry *);
 extern int cifs_hardlink(struct dentry *, struct inode *, struct dentry *);
 extern int cifs_mkdir(struct inode *, struct dentry *, int);
@@ -88,5 +88,9 @@
 extern int cifs_readlink(struct dentry *direntry, char *buffer, int buflen);
 extern int cifs_symlink(struct inode *inode, struct dentry *direntry,
 			const char *symname);
-
+extern int	cifs_removexattr(struct dentry *, const char *);
+extern int 	cifs_setxattr(struct dentry *, const char *, const void *,
+			 size_t, int);
+extern ssize_t	cifs_getxattr(struct dentry *, const char *, void *, size_t);
+extern ssize_t	cifs_listxattr(struct dentry *, char *, size_t);
 #endif				/* _CIFSSMB_H */
diff -Nru a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
--- a/fs/cifs/cifsglob.h	Fri May 16 09:07:44 2003
+++ b/fs/cifs/cifsglob.h	Sun Jul  6 18:24:42 2003
@@ -149,7 +149,9 @@
 	struct TCP_Server_Info *server;	/* pointer to server info */
 	atomic_t inUse;		/* # of CURRENT users of this ses */
 	enum statusEnum status;
+	__u32 sequence_number;  /* needed for CIFS PDU signature */
 	__u16 ipc_tid;		/* special tid for connection to IPC share */
+	char mac_signing_key[CIFS_SESSION_KEY_SIZE + 16];	
 	char *serverOS;		/* name of operating system underlying the server */
 	char *serverNOS;	/* name of network operating system that the server is running */
 	char *serverDomain;	/* security realm of server */
@@ -249,6 +251,7 @@
 	struct list_head qhead;	/* mids waiting on reply from this server */
 	__u16 mid;		/* multiplex id */
 	__u16 pid;		/* process id */
+	__u32 sequence_number;  /* for CIFS signing */
 	__u16 command;		/* smb command code */
 	struct timeval when_sent;	/* time when smb sent */
 	struct cifsSesInfo *ses;	/* smb was sent to this server */
diff -Nru a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h
--- a/fs/cifs/cifspdu.h	Tue May 13 11:00:10 2003
+++ b/fs/cifs/cifspdu.h	Fri Jul  4 15:07:26 2003
@@ -307,7 +307,13 @@
 	__u8 Flags;
 	__u16 Flags2;		/* note: le */
 	__u16 PidHigh;		/* note: le */
-	__u8 SecuritySignature[8];	/* note le */
+	union {
+		struct {
+			__u32 SequenceNumber;  /* le */
+			__u32 Reserved; /* zero */
+		} Sequence;
+		__u8 SecuritySignature[8];	/* le */
+	} Signature;
 	__u8 pad[2];
 	__u16 Tid;
 	__u16 Pid;		/* note: le */
diff -Nru a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
--- a/fs/cifs/cifsproto.h	Sun Jun 22 02:38:54 2003
+++ b/fs/cifs/cifsproto.h	Sun Jul  6 18:24:42 2003
@@ -79,8 +79,7 @@
 			struct nls_table * nls_info);
 extern int CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses);
 extern int CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
-			char *session_key, char *ntlm_session_key,
-			const struct nls_table *);
+			char *ntlm_session_key, const struct nls_table *);
 extern int CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses,
 			char *SecurityBlob,int SecurityBlobLength,
 			const struct nls_table *);
@@ -225,6 +224,11 @@
 
 extern int cifs_demultiplex_thread(struct TCP_Server_Info *);
 extern int cifs_reconnect(struct TCP_Server_Info *server);
+
+extern int cifs_sign_smb(struct smb_hdr *, struct cifsSesInfo *,__u32 *);
+extern int cifs_verify_signature(const struct smb_hdr *, const char * mac_key,
+	__u32 expected_sequence_number);
+extern int cifs_calculate_mac_key(char * key,const char * rn,const char * pass);
 
 /* BB routines below not implemented yet BB */
 
diff -Nru a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
--- a/fs/cifs/cifssmb.c	Sun Jun 22 02:44:57 2003
+++ b/fs/cifs/cifssmb.c	Fri Jul  4 15:07:26 2003
@@ -106,9 +106,6 @@
 	pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
 	if (extended_security)
 		pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
-	if (sign_CIFS_PDUs) {
-		pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
-	}
 
 	pSMB->ByteCount = strlen(protocols[0].name) + 1;
 	strncpy(pSMB->DialectsArray, protocols[0].name, 30);	
@@ -260,10 +257,13 @@
 		up(&ses->sesSem);
 		return -EBUSY;
 	}
-	if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
-		pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
+
 	rc = smb_init(SMB_COM_LOGOFF_ANDX, 2, 0 /* no tcon anymore */,
 		 (void **) &pSMB, (void **) &smb_buffer_response);
+
+        if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
+                pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
+
 	if (rc) {
 		up(&ses->sesSem);
 		return rc;
@@ -1657,8 +1657,6 @@
 	if (ses->capabilities & CAP_DFS) {
 		pSMB->hdr.Flags2 |= SMBFLG2_DFS;
 	}
-	if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
-		pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
 
 	if (ses->capabilities & CAP_UNICODE) {
 		pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
diff -Nru a/fs/cifs/connect.c b/fs/cifs/connect.c
--- a/fs/cifs/connect.c	Tue Jun 10 05:52:17 2003
+++ b/fs/cifs/connect.c	Sun Jul  6 18:24:42 2003
@@ -200,7 +200,7 @@
 			continue;
 		}
 		pdu_length = 4 + ntohl(smb_buffer->smb_buf_length);
-		cFYI(1, ("Peek length rcvd: %d with smb length: %d", length, pdu_length));	/* BB */
+		cFYI(1, ("Peek length rcvd: %d with smb length: %d", length, pdu_length));
 
 		temp = (char *) smb_buffer;
 		if (length > 3) {
@@ -332,8 +332,9 @@
 		kfree(server);
 	} else	/* BB need to more gracefully handle the rare negative session 
 			   response case because response will be still outstanding */
-		cERROR(1, ("There are still active MIDs in queue and we are exiting but we can not delete mid_q_entries or TCP_Server_Info structure due to pending requests MEMORY LEAK!!"));	/* BB wake up waitors, and/or wait and/or free stale mids and try again? BB */
-/* BB Need to fix bug in error path above - perhaps wait until smb requests
+		cERROR(1, ("Active MIDs in queue while exiting - can not delete mid_q_entries or TCP_Server_Info structure due to pending requests MEMORY LEAK!!"));
+	/* BB wake up waitors, and/or wait and/or free stale mids and try again? BB */
+	/* BB Need to fix bug in error path above - perhaps wait until smb requests
    time out and then free the tcp per server struct BB */
 	read_unlock(&GlobalSMBSeslock);
 
@@ -641,6 +642,7 @@
 	if(pSesInfo->server->maxBuf == 0) /* no need to send on reconnect */
 		rc = CIFSSMBNegotiate(xid, pSesInfo);
 	pSesInfo->capabilities = pSesInfo->server->capabilities;
+	pSesInfo->sequence_number = 0;
 	if (!rc) {
 		cFYI(1,("Security Mode: 0x%x Capabilities: 0x%x Time Zone: %d",
 			pSesInfo->server->secMode,
@@ -671,6 +673,8 @@
 					SMBNTencrypt(pSesInfo->password_with_pad,
 						pSesInfo->server->cryptKey,ntlm_session_key);
 
+				/* BB add call to save MAC key here BB */
+
 				/* for better security the weaker lanman hash not sent 
 				   in AuthSessSetup so why bother calculating it */
 				/* toUpper(nls_info,
@@ -689,10 +693,10 @@
 			SMBNTencrypt(pSesInfo->password_with_pad,
 				pSesInfo->server->cryptKey,
 				ntlm_session_key);
+
+			cifs_calculate_mac_key(pSesInfo->mac_signing_key, ntlm_session_key, pSesInfo->password_with_pad);
 			rc = CIFSSessSetup(xid, pSesInfo,
-				session_key,
-				ntlm_session_key,
-				nls_info);
+				ntlm_session_key, nls_info);
 		}
 		if (rc) {
 			cERROR(1,("Send error in SessSetup = %d",rc));
@@ -1024,7 +1028,6 @@
 int
 CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
 	      char session_key[CIFS_SESSION_KEY_SIZE],
-	      char session_key2[CIFS_SESSION_KEY_SIZE],
 	      const struct nls_table *nls_codepage)
 {
 	struct smb_hdr *smb_buffer;
@@ -1081,9 +1084,9 @@
 	pSMB->req_no_secext.CaseSensitivePasswordLength =
 	    cpu_to_le16(CIFS_SESSION_KEY_SIZE);
 	bcc_ptr = pByteArea(smb_buffer);
-	/* memcpy(bcc_ptr, (char *) session_key, CIFS_SESSION_KEY_SIZE);
+	/* memcpy(bcc_ptr, (char *) lm_session_key, CIFS_SESSION_KEY_SIZE);
 	   bcc_ptr += CIFS_SESSION_KEY_SIZE; */
-	memcpy(bcc_ptr, (char *) session_key2, CIFS_SESSION_KEY_SIZE);
+	memcpy(bcc_ptr, (char *) session_key, CIFS_SESSION_KEY_SIZE);
 	bcc_ptr += CIFS_SESSION_KEY_SIZE;
 
 	if (ses->capabilities & CAP_UNICODE) {
@@ -1094,7 +1097,7 @@
 		if(user == NULL)
 			bytes_returned = 0; /* skill null user */
         else
-		    bytes_returned =
+		bytes_returned =
 		        cifs_strtoUCS((wchar_t *) bcc_ptr, user, 100, nls_codepage);
 		bcc_ptr += 2 * bytes_returned;	/* convert num 16 bit words to bytes */
 		bcc_ptr += 2;	/* trailing null */
diff -Nru a/fs/cifs/dir.c b/fs/cifs/dir.c
--- a/fs/cifs/dir.c	Sat Feb 15 14:10:23 2003
+++ b/fs/cifs/dir.c	Sun Jun 29 23:49:04 2003
@@ -119,7 +119,8 @@
 /* Inode operations in similar order to how they appear in the Linux file fs.h */
 
 int
-cifs_create(struct inode *inode, struct dentry *direntry, int mode)
+cifs_create(struct inode *inode, struct dentry *direntry, int mode,
+		struct nameidata *nd)
 {
 	int rc = -ENOENT;
 	int xid;
@@ -178,7 +179,7 @@
 }
 
 struct dentry *
-cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry)
+cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, struct nameidata *nd)
 {
 	int rc, xid;
 	struct cifs_sb_info *cifs_sb;
@@ -262,7 +263,7 @@
 }
 
 static int
-cifs_d_revalidate(struct dentry *direntry, int flags)
+cifs_d_revalidate(struct dentry *direntry, struct nameidata *nd)
 {
 	int isValid = 1;
 
diff -Nru a/fs/cifs/inode.c b/fs/cifs/inode.c
--- a/fs/cifs/inode.c	Tue Jun 10 17:29:01 2003
+++ b/fs/cifs/inode.c	Thu Jun 26 17:47:04 2003
@@ -635,9 +635,9 @@
 	struct cifsFileInfo *open_file = NULL;
 	FILE_BASIC_INFO time_buf;
 	int set_time = FALSE;
-	__u64 mode = 0xFFFFFFFFFFFFFFFF;
-	__u64 uid = 0xFFFFFFFFFFFFFFFF;
-	__u64 gid = 0xFFFFFFFFFFFFFFFF;
+	__u64 mode = 0xFFFFFFFFFFFFFFFFULL;
+	__u64 uid = 0xFFFFFFFFFFFFFFFFULL;
+	__u64 gid = 0xFFFFFFFFFFFFFFFFULL;
 	struct cifsInodeInfo *cifsInode;
 
 	xid = GetXid();
diff -Nru a/fs/cifs/smbdes.c b/fs/cifs/smbdes.c
--- a/fs/cifs/smbdes.c	Thu Oct 10 12:16:14 2002
+++ b/fs/cifs/smbdes.c	Fri Jun 27 00:52:20 2003
@@ -399,7 +399,7 @@
 		s_box[ind] = s_box[j];
 		s_box[j] = tc;
 	}
-	for (ind = 0; ind < (val ? 516 : 16); ind++) {
+	for (ind = 0; ind < val; ind++) {
 		unsigned char tc;
 		unsigned char t;
 
diff -Nru a/fs/cifs/smbencrypt.c b/fs/cifs/smbencrypt.c
--- a/fs/cifs/smbencrypt.c	Sat Feb 15 14:10:24 2003
+++ b/fs/cifs/smbencrypt.c	Fri Jul  4 15:07:26 2003
@@ -5,7 +5,8 @@
    Copyright (C) Andrew Tridgell 1992-2000
    Copyright (C) Luke Kenneth Casson Leighton 1996-2000
    Modified by Jeremy Allison 1995.
-   Modified by Steve French (sfrench@us.ibm.com) 2002
+   Copyright (C) Andrew Bartlett <abartlet@samba.org> 2002-2003
+   Modified by Steve French (sfrench@us.ibm.com) 2002-2003
    
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -97,13 +98,15 @@
 	E_P16(p14, p21);
 
 	SMBOWFencrypt(p21, c8, p24);
-
+	
 #ifdef DEBUG_PASSWORD
 	DEBUG(100, ("SMBencrypt: lm#, challenge, response\n"));
 	dump_data(100, (char *) p21, 16);
 	dump_data(100, (char *) c8, 8);
 	dump_data(100, (char *) p24, 24);
 #endif
+	memset(p14,0,15);
+	memset(p21,0,21);
 }
 
 /* Routines for Windows NT MD4 Hash functions. */
@@ -161,6 +164,7 @@
 	len = _my_wcslen(wpwd) * sizeof (__u16);
 
 	mdfour(p16, (unsigned char *) wpwd, len);
+	memset(wpwd,0,129 * 2);
 }
 
 /* Does both the NT and LM owfs of a user's password */
@@ -222,7 +226,7 @@
 	/* push_ucs2(NULL, user_u, user_n, (user_l+1)*2, STR_UNICODE|STR_NOALIGN|STR_TERMINATE|STR_UPPER);
 	   push_ucs2(NULL, dom_u, domain_n, (domain_l+1)*2, STR_UNICODE|STR_NOALIGN|STR_TERMINATE|STR_UPPER); */
 
-	/* do not think it is supposed to be uppercased */
+	/* BB user and domain may need to be uppercased */
 	user_l = cifs_strtoUCS(user_u, user_n, 511, nls_codepage);
 	domain_l = cifs_strtoUCS(dom_u, domain_n, 511, nls_codepage);
 
@@ -297,8 +301,52 @@
 #endif
 }
 
-int
-make_oem_passwd_hash(char data[516], const char *passwd,
+/* Does the md5 encryption from the NT hash for NTLMv2. */
+void
+SMBOWFencrypt_ntv2(const unsigned char kr[16],
+                   const struct data_blob * srv_chal,
+                   const struct data_blob * cli_chal, unsigned char resp_buf[16])
+{
+        struct HMACMD5Context ctx;
+
+        hmac_md5_init_limK_to_64(kr, 16, &ctx);
+        hmac_md5_update(srv_chal->data, srv_chal->length, &ctx);
+        hmac_md5_update(cli_chal->data, cli_chal->length, &ctx);
+        hmac_md5_final(resp_buf, &ctx);
+
+#ifdef DEBUG_PASSWORD
+        DEBUG(100, ("SMBOWFencrypt_ntv2: srv_chal, cli_chal, resp_buf\n"));
+        dump_data(100, srv_chal->data, srv_chal->length);
+        dump_data(100, cli_chal->data, cli_chal->length);
+        dump_data(100, resp_buf, 16);
+#endif
+}
+
+static struct data_blob LMv2_generate_response(const unsigned char ntlm_v2_hash[16],
+                                        const struct data_blob * server_chal)
+{
+        unsigned char lmv2_response[16];
+	struct data_blob lmv2_client_data/* = data_blob(NULL, 8)*/; /* BB Fix BB */
+        struct data_blob final_response /* = data_blob(NULL, 24)*/; /* BB Fix BB */
+
+        /* LMv2 */
+        /* client-supplied random data */
+        get_random_bytes(lmv2_client_data.data, lmv2_client_data.length);
+        /* Given that data, and the challenge from the server, generate a response */
+        SMBOWFencrypt_ntv2(ntlm_v2_hash, server_chal, &lmv2_client_data, lmv2_response);
+        memcpy(final_response.data, lmv2_response, sizeof(lmv2_response));
+
+        /* after the first 16 bytes is the random data we generated above,
+           so the server can verify us with it */
+        memcpy(final_response.data+sizeof(lmv2_response),
+               lmv2_client_data.data, lmv2_client_data.length);
+
+/*        data_blob_free(&lmv2_client_data); */ /* BB fix BB */
+
+        return final_response;
+}
+
+int make_oem_passwd_hash(char data[516], const char *passwd,
 		     unsigned char old_pw_hash[16], int unicode)
 {
 	int new_pw_len = strlen(passwd) * (unicode ? 2 : 1);
@@ -333,32 +381,11 @@
 	DEBUG(100, ("make_oem_passwd_hash\n"));
 	dump_data(100, data, 516);
 #endif
-	SamOEMhash((unsigned char *) data, (unsigned char *) old_pw_hash, TRUE);
+	SamOEMhash((unsigned char *) data, (unsigned char *) old_pw_hash, 516);
 
 	return TRUE;
 }
 
-/* Does the md5 encryption from the NT hash for NTLMv2. */
-void
-SMBOWFencrypt_ntv2(const unsigned char kr[16],
-		   const struct data_blob srv_chal,
-		   const struct data_blob cli_chal, unsigned char resp_buf[16])
-{
-	struct HMACMD5Context ctx;
-
-	hmac_md5_init_limK_to_64(kr, 16, &ctx);
-	hmac_md5_update(srv_chal.data, srv_chal.length, &ctx);
-	hmac_md5_update(cli_chal.data, cli_chal.length, &ctx);
-	hmac_md5_final(resp_buf, &ctx);
-
-#ifdef DEBUG_PASSWORD
-	DEBUG(100, ("SMBOWFencrypt_ntv2: srv_chal, cli_chal, resp_buf\n"));
-	dump_data(100, srv_chal.data, srv_chal.length);
-	dump_data(100, cli_chal.data, cli_chal.length);
-	dump_data(100, resp_buf, 16);
-#endif
-}
-
 void
 SMBsesskeygen_ntv2(const unsigned char kr[16],
 		   const unsigned char *nt_resp, __u8 sess_key[16])
@@ -407,6 +434,44 @@
 	return TRUE;
 }
 
+int SMBNTLMv2encrypt(const char *user, const char *domain, const char *password,
+                      const struct data_blob *server_chal,
+                      const struct data_blob *names_blob,
+                      struct data_blob *lm_response, struct data_blob *nt_response,
+                      struct data_blob *nt_session_key,struct nls_table * nls_codepage)
+{
+        unsigned char nt_hash[16];
+        unsigned char ntlm_v2_hash[16];
+        E_md4hash(password, nt_hash);
+
+        /* We don't use the NT# directly.  Instead we use it mashed up with
+           the username and domain.
+           This prevents username swapping during the auth exchange
+        */
+        ntv2_owf_gen(nt_hash, user, domain, ntlm_v2_hash,nls_codepage);
+
+        if (nt_response) {
+/*                *nt_response = NTLMv2_generate_response(ntlm_v2_hash, server_chal,
+                                                        names_blob); */ /* BB fix BB */
+                if (nt_session_key) {
+/*                        *nt_session_key = data_blob(NULL, 16); */ /* BB fix BB */
+
+                        /* The NTLMv2 calculations also provide a session key, for signing etc later */
+                        /* use only the first 16 bytes of nt_response for session key */
+                        SMBsesskeygen_ntv2(ntlm_v2_hash, nt_response->data, nt_session_key->data);
+                }
+        }
+
+        /* LMv2 */
+
+        if (lm_response) {
+                *lm_response = LMv2_generate_response(ntlm_v2_hash, server_chal);
+        }
+
+        return TRUE;
+}
+
+
 /***********************************************************
  SMB signing - setup the MAC key.
 ************************************************************/
@@ -455,7 +520,7 @@
 		  be32_to_cpu(outbuf->smb_buf_length));
 	MD5Final(calc_md5_mac, &md5_ctx);
 
-	memcpy(outbuf->SecuritySignature, calc_md5_mac, 8);
+	memcpy(outbuf->Signature.SecuritySignature, calc_md5_mac, 8);
 	(*send_seq_num)++;
 	*reply_seq_num = *send_seq_num;
 	(*send_seq_num)++;
diff -Nru a/fs/cifs/transport.c b/fs/cifs/transport.c
--- a/fs/cifs/transport.c	Tue May 27 17:41:17 2003
+++ b/fs/cifs/transport.c	Sun Jul  6 18:24:42 2003
@@ -154,12 +154,8 @@
 
 	/* smb header is converted in header_assemble. bcc and rest of SMB word
 	   area, and byte area if necessary, is converted to littleendian in 
-	   cifssmb.c and RFC1001 len is converted to bigendian in smb_send */
-	if (smb_buf_length > 12)
-		smb_buffer->Flags2 = cpu_to_le16(smb_buffer->Flags2);
-
-	/* if(smb_buffer->Flags2 & SMBFLG2_SECURITY_SIGNATURE)
-		sign_smb(smb_buffer); */ /* BB enable when signing tested more */
+	   cifssmb.c and RFC1001 len is converted to bigendian in smb_send 
+	   Flags2 is converted in SendReceive */
 
 	smb_buffer->smb_buf_length = cpu_to_be32(smb_buffer->smb_buf_length);
 	cFYI(1, ("Sending smb of length %d ", smb_buf_length));
@@ -200,6 +196,12 @@
 		DeleteMidQEntry(midQ);
 		return -EIO;
 	}
+
+        if (in_buf->smb_buf_length > 12)
+                in_buf->Flags2 = cpu_to_le16(in_buf->Flags2);
+
+        rc = cifs_sign_smb(in_buf, ses, &midQ->sequence_number);
+
 	midQ->midState = MID_REQUEST_SUBMITTED;
 	rc = smb_send(ses->server->ssocket, in_buf, in_buf->smb_buf_length,
 		      (struct sockaddr *) &(ses->server->sockAddr));
@@ -247,11 +249,18 @@
 			memcpy(out_buf, midQ->resp_buf,
 			       receive_len +
 			       4 /* include 4 byte RFC1001 header */ );
-			/* convert the length back to a form that we can use */
 
 			dump_smb(out_buf, 92);
+			/* convert the length into a more usable form */
 			out_buf->smb_buf_length =
 			    be32_to_cpu(out_buf->smb_buf_length);
+			if((out_buf->smb_buf_length > 24) &&
+			   (ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))) {
+				rc = cifs_verify_signature(out_buf, ses->mac_signing_key,midQ->sequence_number); /* BB fix BB */
+				if(rc)
+					cFYI(1,("Unexpected signature received from server"));
+			}
+
 			if (out_buf->smb_buf_length > 12)
 				out_buf->Flags2 = le16_to_cpu(out_buf->Flags2);
 			if (out_buf->smb_buf_length > 28)
diff -Nru a/fs/cifs/xattr.c b/fs/cifs/xattr.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/fs/cifs/xattr.c	Sun Jun 29 18:24:03 2003
@@ -0,0 +1,56 @@
+/*
+ *   fs/cifs/xattr.c
+ *
+ *   Copyright (c) International Business Machines  Corp., 2003
+ *   Author(s): Steve French (sfrench@us.ibm.com)
+ *
+ *   This library is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU Lesser General Public License as published
+ *   by the Free Software Foundation; either version 2.1 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This library is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
+ *   the GNU Lesser General Public License for more details.
+ *
+ *   You should have received a copy of the GNU Lesser General Public License
+ *   along with this library; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/fs.h>
+
+int cifs_removexattr(struct dentry * direntry, const char * name)
+{
+        int rc = -EOPNOTSUPP;
+        return rc;
+}
+
+int cifs_setxattr(struct dentry * direntry, const char * name,
+        const void * value, size_t size, int flags)
+{
+        int rc = -EOPNOTSUPP;
+        return rc;
+}
+
+ssize_t cifs_getxattr(struct dentry * direntry, const char * name,
+         void * value, size_t size)
+{
+        ssize_t rc = -EOPNOTSUPP;
+        return rc;
+}
+
+ssize_t cifs_listxattr(struct dentry * direntry, char * ea_data, size_t ea_size)
+{
+        ssize_t rc = -EOPNOTSUPP;
+
+	/* return dosattributes as pseudo xattr */
+	/* return alt name if available as pseudo attr */
+
+	/* if proc/fs/cifs/streamstoxattr is set then
+		search server for EAs or streams to 
+		returns as xattrs */
+
+        return rc;
+}
diff -Nru a/fs/coda/dir.c b/fs/coda/dir.c
--- a/fs/coda/dir.c	Wed Nov 20 03:19:02 2002
+++ b/fs/coda/dir.c	Sun Jun 29 23:49:25 2003
@@ -28,9 +28,9 @@
 #include <linux/coda_proc.h>
 
 /* dir inode-ops */
-static int coda_create(struct inode *dir, struct dentry *new, int mode);
+static int coda_create(struct inode *dir, struct dentry *new, int mode, struct nameidata *nd);
 static int coda_mknod(struct inode *dir, struct dentry *new, int mode, dev_t rdev);
-static struct dentry *coda_lookup(struct inode *dir, struct dentry *target);
+static struct dentry *coda_lookup(struct inode *dir, struct dentry *target, struct nameidata *nd);
 static int coda_link(struct dentry *old_dentry, struct inode *dir_inode, 
 		     struct dentry *entry);
 static int coda_unlink(struct inode *dir_inode, struct dentry *entry);
@@ -45,7 +45,7 @@
 static int coda_readdir(struct file *file, void *dirent, filldir_t filldir);
 
 /* dentry ops */
-static int coda_dentry_revalidate(struct dentry *de, int);
+static int coda_dentry_revalidate(struct dentry *de, struct nameidata *nd);
 static int coda_dentry_delete(struct dentry *);
 
 /* support routines */
@@ -90,7 +90,7 @@
 
 /* inode operations for directories */
 /* access routines: lookup, readlink, permission */
-static struct dentry *coda_lookup(struct inode *dir, struct dentry *entry)
+static struct dentry *coda_lookup(struct inode *dir, struct dentry *entry, struct nameidata *nd)
 {
 	struct inode *res_inode = NULL;
 	struct ViceFid resfid = {0,0,0};
@@ -147,7 +147,7 @@
 }
 
 
-int coda_permission(struct inode *inode, int mask)
+int coda_permission(struct inode *inode, int mask, struct nameidata *nd)
 {
         int error = 0;
  
@@ -190,7 +190,7 @@
 }
 
 /* creation routines: create, mknod, mkdir, link, symlink */
-static int coda_create(struct inode *dir, struct dentry *de, int mode)
+static int coda_create(struct inode *dir, struct dentry *de, int mode, struct nameidata *nd)
 {
         int error=0;
 	const char *name=de->d_name.name;
@@ -627,7 +627,7 @@
 }
 
 /* called when a cache lookup succeeds */
-static int coda_dentry_revalidate(struct dentry *de, int flags)
+static int coda_dentry_revalidate(struct dentry *de, struct nameidata *nd)
 {
 	struct inode *inode = de->d_inode;
 	struct coda_inode_info *cii;
diff -Nru a/fs/coda/file.c b/fs/coda/file.c
--- a/fs/coda/file.c	Sat Oct  5 15:33:50 2002
+++ b/fs/coda/file.c	Wed Jul  2 21:46:34 2003
@@ -153,19 +153,22 @@
 	struct inode *coda_inode;
 	int err = 0, fcnt;
 
+	lock_kernel();
+
 	coda_vfs_stat.flush++;
 
 	/* last close semantics */
 	fcnt = file_count(coda_file);
-	if (fcnt > 1) return 0;
+	if (fcnt > 1)
+		goto out;
 
 	/* No need to make an upcall when we have not made any modifications
 	 * to the file */
 	if ((coda_file->f_flags & O_ACCMODE) == O_RDONLY)
-		return 0;
+		goto out;
 
 	if (use_coda_close)
-		return 0;
+		goto out;
 
 	cfi = CODA_FTOC(coda_file);
 	BUG_ON(!cfi || cfi->cfi_magic != CODA_MAGIC);
@@ -180,6 +183,8 @@
 		err = 0;
 	}
 
+out:
+	unlock_kernel();
 	return err;
 }
 
diff -Nru a/fs/coda/pioctl.c b/fs/coda/pioctl.c
--- a/fs/coda/pioctl.c	Sat Oct  5 15:36:27 2002
+++ b/fs/coda/pioctl.c	Sun Jun 29 23:49:25 2003
@@ -24,7 +24,8 @@
 #include <linux/coda_psdev.h>
 
 /* pioctl ops */
-static int coda_ioctl_permission(struct inode *inode, int mask);
+static int coda_ioctl_permission(struct inode *inode, int mask,
+				 struct nameidata *nd);
 static int coda_pioctl(struct inode * inode, struct file * filp, 
                        unsigned int cmd, unsigned long user_data);
 
@@ -41,7 +42,8 @@
 };
 
 /* the coda pioctl inode ops */
-static int coda_ioctl_permission(struct inode *inode, int mask)
+static int coda_ioctl_permission(struct inode *inode, int mask,
+				 struct nameidata *nd)
 {
         return 0;
 }
diff -Nru a/fs/cramfs/inode.c b/fs/cramfs/inode.c
--- a/fs/cramfs/inode.c	Fri Jun 20 13:16:06 2003
+++ b/fs/cramfs/inode.c	Thu Jul  3 06:36:44 2003
@@ -342,7 +342,7 @@
 /*
  * Lookup and fill in the inode data..
  */
-static struct dentry * cramfs_lookup(struct inode *dir, struct dentry *dentry)
+static struct dentry * cramfs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
 {
 	unsigned int offset = 0;
 	int sorted;
diff -Nru a/fs/devfs/base.c b/fs/devfs/base.c
--- a/fs/devfs/base.c	Tue Jun 10 23:33:24 2003
+++ b/fs/devfs/base.c	Thu Jul  3 06:36:44 2003
@@ -2175,7 +2175,7 @@
     .d_iput       = devfs_d_iput,
 };
 
-static int devfs_d_revalidate_wait (struct dentry *dentry, int flags);
+static int devfs_d_revalidate_wait (struct dentry *dentry, struct nameidata *);
 
 static struct dentry_operations devfs_wait_dops =
 {
@@ -2212,7 +2212,7 @@
 
 /* XXX: this doesn't handle the case where we got a negative dentry
         but a devfs entry has been registered in the meanwhile */
-static int devfs_d_revalidate_wait (struct dentry *dentry, int flags)
+static int devfs_d_revalidate_wait (struct dentry *dentry, struct nameidata *nd)
 {
     struct inode *dir = dentry->d_parent->d_inode;
     struct fs_info *fs_info = dir->i_sb->s_fs_info;
@@ -2265,7 +2265,7 @@
 
 /*  Inode operations for device entries follow  */
 
-static struct dentry *devfs_lookup (struct inode *dir, struct dentry *dentry)
+static struct dentry *devfs_lookup (struct inode *dir, struct dentry *dentry, struct nameidata *nd)
 {
     struct devfs_entry tmp;  /*  Must stay in scope until devfsd idle again  */
     struct devfs_lookup_struct lookup_info;
diff -Nru a/fs/dquot.c b/fs/dquot.c
--- a/fs/dquot.c	Mon May 26 08:56:05 2003
+++ b/fs/dquot.c	Fri Jul  4 19:29:30 2003
@@ -74,6 +74,7 @@
 #include <linux/module.h>
 #include <linux/proc_fs.h>
 #include <linux/security.h>
+#include <linux/kmod.h>
 
 #include <asm/uaccess.h>
 
@@ -96,6 +97,7 @@
 
 static char *quotatypes[] = INITQFNAMES;
 static struct quota_format_type *quota_formats;	/* List of registered formats */
+static struct quota_module_name module_names[] = INIT_QUOTA_MODULE_NAMES;
 
 int register_quota_format(struct quota_format_type *fmt)
 {
@@ -123,8 +125,19 @@
 
 	spin_lock(&dq_list_lock);
 	for (actqf = quota_formats; actqf && actqf->qf_fmt_id != id; actqf = actqf->qf_next);
-	if (actqf && !try_module_get(actqf->qf_owner))
-		actqf = NULL;
+	if (!actqf || !try_module_get(actqf->qf_owner)) {
+		int qm;
+
+		for (qm = 0; module_names[qm].qm_fmt_id && module_names[qm].qm_fmt_id != id; qm++);
+		if (!module_names[qm].qm_fmt_id || request_module(module_names[qm].qm_mod_name)) {
+			actqf = NULL;
+			goto out;
+		}
+		for (actqf = quota_formats; actqf && actqf->qf_fmt_id != id; actqf = actqf->qf_next);
+		if (actqf && !try_module_get(actqf->qf_owner))
+			actqf = NULL;
+	}
+out:
 	spin_unlock(&dq_list_lock);
 	return actqf;
 }
diff -Nru a/fs/efs/namei.c b/fs/efs/namei.c
--- a/fs/efs/namei.c	Thu May 23 06:18:43 2002
+++ b/fs/efs/namei.c	Thu Jul  3 06:36:44 2003
@@ -57,7 +57,7 @@
 	return(0);
 }
 
-struct dentry *efs_lookup(struct inode *dir, struct dentry *dentry) {
+struct dentry *efs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd) {
 	efs_ino_t inodenum;
 	struct inode * inode = NULL;
 
diff -Nru a/fs/eventpoll.c b/fs/eventpoll.c
--- a/fs/eventpoll.c	Sat Jun  7 15:17:55 2003
+++ b/fs/eventpoll.c	Fri Jul  4 23:52:56 2003
@@ -443,29 +443,17 @@
 
 
 /*
- * This is called from inside fs/file_table.c:__fput() to unlink files
- * from the eventpoll interface. We need to have this facility to cleanup
- * correctly files that are closed without being removed from the eventpoll
- * interface.
+ * This is called from eventpoll_release() to unlink files from the eventpoll
+ * interface. We need to have this facility to cleanup correctly files that are
+ * closed without being removed from the eventpoll interface.
  */
-void eventpoll_release(struct file *file)
+void eventpoll_release_file(struct file *file)
 {
 	struct list_head *lsthead = &file->f_ep_links;
 	struct eventpoll *ep;
 	struct epitem *epi;
 
 	/*
-	 * Fast check to avoid the get/release of the semaphore. Since
-	 * we're doing this outside the semaphore lock, it might return
-	 * false negatives, but we don't care. It'll help in 99.99% of cases
-	 * to avoid the semaphore lock. False positives simply cannot happen
-	 * because the file in on the way to be removed and nobody ( but
-	 * eventpoll ) has still a reference to this file.
-	 */
-	if (list_empty(lsthead))
-		return;
-
-	/*
 	 * We don't want to get "file->f_ep_lock" because it is not
 	 * necessary. It is not necessary because we're in the "struct file"
 	 * cleanup path, and this means that noone is using this file anymore.
@@ -541,7 +529,7 @@
 /*
  * The following function implement the controller interface for the eventpoll
  * file that enable the insertion/removal/change of file descriptors inside
- * the interest set. It rapresents the kernel part of the user spcae epoll_ctl(2).
+ * the interest set. It rapresents the kernel part of the user space epoll_ctl(2).
  */
 asmlinkage long sys_epoll_ctl(int epfd, int op, int fd, struct epoll_event *event)
 {
@@ -551,8 +539,8 @@
 	struct epitem *epi;
 	struct epoll_event epds;
 
-	DNPRINTK(3, (KERN_INFO "[%p] eventpoll: sys_epoll_ctl(%d, %d, %d, %u)\n",
-		     current, epfd, op, fd, event->events));
+	DNPRINTK(3, (KERN_INFO "[%p] eventpoll: sys_epoll_ctl(%d, %d, %d, %p)\n",
+		     current, epfd, op, fd, event));
 
 	error = -EFAULT;
 	if (copy_from_user(&epds, event, sizeof(struct epoll_event)))
@@ -633,8 +621,8 @@
 eexit_2:
 	fput(file);
 eexit_1:
-	DNPRINTK(3, (KERN_INFO "[%p] eventpoll: sys_epoll_ctl(%d, %d, %d, %u) = %d\n",
-		     current, epfd, op, fd, event->events, error));
+	DNPRINTK(3, (KERN_INFO "[%p] eventpoll: sys_epoll_ctl(%d, %d, %d, %p) = %d\n",
+		     current, epfd, op, fd, event, error));
 
 	return error;
 }
diff -Nru a/fs/exec.c b/fs/exec.c
--- a/fs/exec.c	Thu Jun  5 23:36:53 2003
+++ b/fs/exec.c	Fri Jul  4 23:52:54 2003
@@ -117,7 +117,8 @@
 	struct nameidata nd;
 	int error;
 
-	error = user_path_walk(library, &nd);
+	nd.intent.open.flags = O_RDONLY;
+	error = __user_walk(library, LOOKUP_FOLLOW|LOOKUP_OPEN, &nd);
 	if (error)
 		goto out;
 
@@ -125,7 +126,7 @@
 	if (!S_ISREG(nd.dentry->d_inode->i_mode))
 		goto exit;
 
-	error = permission(nd.dentry->d_inode, MAY_READ | MAY_EXEC);
+	error = permission(nd.dentry->d_inode, MAY_READ | MAY_EXEC, &nd);
 	if (error)
 		goto exit;
 
@@ -392,7 +393,7 @@
 	if (!mpnt)
 		return -ENOMEM;
 
-	if (!vm_enough_memory((STACK_TOP - (PAGE_MASK & (unsigned long) bprm->p))>>PAGE_SHIFT)) {
+	if (security_vm_enough_memory((STACK_TOP - (PAGE_MASK & (unsigned long) bprm->p))>>PAGE_SHIFT)) {
 		kmem_cache_free(vm_area_cachep, mpnt);
 		return -ENOMEM;
 	}
@@ -441,9 +442,9 @@
 {
 	int i;
 
-	for (i = 0 ; i < MAX_ARG_PAGES ; i++) {
+	for (i = 0; i < MAX_ARG_PAGES; i++) {
 		if (bprm->page[i])
-		__free_page(bprm->page[i]);
+			__free_page(bprm->page[i]);
 		bprm->page[i] = NULL;
 	}
 }
@@ -461,7 +462,7 @@
 		file = ERR_PTR(-EACCES);
 		if (!(nd.mnt->mnt_flags & MNT_NOEXEC) &&
 		    S_ISREG(inode->i_mode)) {
-			int err = permission(inode, MAY_EXEC);
+			int err = permission(inode, MAY_EXEC, &nd);
 			if (!err && !(inode->i_mode & 0111))
 				err = -EACCES;
 			file = ERR_PTR(err);
@@ -758,12 +759,6 @@
 	char * name;
 	int i, ch, retval;
 
-	/* 
-	 * Release all of the old mmap stuff
-	 */
-	retval = exec_mmap(bprm->mm);
-	if (retval)
-		goto out;
 	/*
 	 * Make sure we have a private signal table and that
 	 * we are unassociated from the previous thread group.
@@ -772,6 +767,15 @@
 	if (retval)
 		goto out;
 
+	/*
+	 * Release all of the old mmap stuff
+	 */
+	retval = exec_mmap(bprm->mm);
+	if (retval)
+		goto out;
+
+	bprm->mm = NULL;		/* We're using it now */
+
 	/* This is the point of no return */
 
 	current->sas_ss_sp = current->sas_ss_size = 0;
@@ -791,7 +795,7 @@
 	flush_thread();
 
 	if (bprm->e_uid != current->euid || bprm->e_gid != current->egid || 
-	    permission(bprm->file->f_dentry->d_inode,MAY_READ))
+	    permission(bprm->file->f_dentry->d_inode,MAY_READ, NULL))
 		current->mm->dumpable = 0;
 
 	/* An exec changes our domain. We are no longer part of the thread
@@ -999,7 +1003,7 @@
 			}
 			read_lock(&binfmt_lock);
 			put_binfmt(fmt);
-			if (retval != -ENOEXEC)
+			if (retval != -ENOEXEC || bprm->mm == NULL)
 				break;
 			if (!bprm->file) {
 				read_unlock(&binfmt_lock);
@@ -1007,7 +1011,7 @@
 			}
 		}
 		read_unlock(&binfmt_lock);
-		if (retval != -ENOEXEC) {
+		if (retval != -ENOEXEC || bprm->mm == NULL) {
 			break;
 #ifdef CONFIG_KMOD
 		}else{
@@ -1035,7 +1039,6 @@
 	struct linux_binprm bprm;
 	struct file *file;
 	int retval;
-	int i;
 
 	sched_balance_exec();
 
@@ -1103,17 +1106,14 @@
 
 out:
 	/* Something went wrong, return the inode and free the argument pages*/
-	for (i = 0 ; i < MAX_ARG_PAGES ; i++) {
-		struct page * page = bprm.page[i];
-		if (page)
-			__free_page(page);
-	}
+	free_arg_pages(&bprm);
 
 	if (bprm.security)
 		security_bprm_free(&bprm);
 
 out_mm:
-	mmdrop(bprm.mm);
+	if (bprm.mm)
+		mmdrop(bprm.mm);
 
 out_file:
 	if (bprm.file) {
diff -Nru a/fs/ext2/acl.c b/fs/ext2/acl.c
--- a/fs/ext2/acl.c	Tue Feb 25 08:21:08 2003
+++ b/fs/ext2/acl.c	Fri Jul  4 22:31:39 2003
@@ -1,7 +1,7 @@
 /*
  * linux/fs/ext2/acl.c
  *
- * Copyright (C) 2001 by Andreas Gruenbacher, <a.gruenbacher@computer.org>
+ * Copyright (C) 2001-2003 Andreas Gruenbacher, <agruen@suse.de>
  */
 
 #include <linux/init.h>
@@ -19,7 +19,7 @@
 ext2_acl_from_disk(const void *value, size_t size)
 {
 	const char *end = (char *)value + size;
-	int n, count;
+	size_t n, count;
 	struct posix_acl *acl;
 
 	if (!value)
@@ -85,7 +85,7 @@
 {
 	ext2_acl_header *ext_acl;
 	char *e;
-	int n;
+	size_t n;
 
 	*size = ext2_acl_size(acl->a_count);
 	ext_acl = (ext2_acl_header *)kmalloc(sizeof(ext2_acl_header) +
@@ -124,16 +124,41 @@
 	return ERR_PTR(-EINVAL);
 }
 
+static inline struct posix_acl *
+ext2_iget_acl(struct inode *inode, struct posix_acl **i_acl)
+{
+	struct posix_acl *acl = EXT2_ACL_NOT_CACHED;
+
+	spin_lock(&inode->i_lock);
+	if (*i_acl != EXT2_ACL_NOT_CACHED)
+		acl = posix_acl_dup(*i_acl);
+	spin_unlock(&inode->i_lock);
+
+	return acl;
+}
+
+static inline void
+ext2_iset_acl(struct inode *inode, struct posix_acl **i_acl,
+		   struct posix_acl *acl)
+{
+	spin_lock(&inode->i_lock);
+	if (*i_acl != EXT2_ACL_NOT_CACHED)
+		posix_acl_release(*i_acl);
+	*i_acl = posix_acl_dup(acl);
+	spin_unlock(&inode->i_lock);
+}
+
 /*
- * inode->i_sem: down
+ * inode->i_sem: don't care
  */
 static struct posix_acl *
 ext2_get_acl(struct inode *inode, int type)
 {
+	const size_t max_size = ext2_acl_size(EXT2_ACL_MAX_ENTRIES);
+	struct ext2_inode_info *ei = EXT2_I(inode);
 	int name_index;
 	char *value;
-	struct posix_acl *acl, **p_acl;
-	const size_t size = ext2_acl_size(EXT2_ACL_MAX_ENTRIES);
+	struct posix_acl *acl;
 	int retval;
 
 	if (!test_opt(inode->i_sb, POSIX_ACL))
@@ -141,36 +166,45 @@
 
 	switch(type) {
 		case ACL_TYPE_ACCESS:
-			p_acl = &EXT2_I(inode)->i_acl;
+			acl = ext2_iget_acl(inode, &ei->i_acl);
+			if (acl != EXT2_ACL_NOT_CACHED)
+				return acl;
 			name_index = EXT2_XATTR_INDEX_POSIX_ACL_ACCESS;
 			break;
 
 		case ACL_TYPE_DEFAULT:
-			p_acl = &EXT2_I(inode)->i_default_acl;
+			acl = ext2_iget_acl(inode, &ei->i_default_acl);
+			if (acl != EXT2_ACL_NOT_CACHED)
+				return acl;
 			name_index = EXT2_XATTR_INDEX_POSIX_ACL_DEFAULT;
 			break;
 
 		default:
 			return ERR_PTR(-EINVAL);
 	}
-	if (*p_acl != EXT2_ACL_NOT_CACHED)
-		return posix_acl_dup(*p_acl);
-	value = kmalloc(size, GFP_KERNEL);
+	value = kmalloc(max_size, GFP_KERNEL);
 	if (!value)
 		return ERR_PTR(-ENOMEM);
 
-	retval = ext2_xattr_get(inode, name_index, "", value, size);
-
-	if (retval == -ENODATA || retval == -ENOSYS)
-		*p_acl = acl = NULL;
-	else if (retval < 0)
-		acl = ERR_PTR(retval);
-	else {
+	retval = ext2_xattr_get(inode, name_index, "", value, max_size);
+	acl = ERR_PTR(retval);
+	if (retval >= 0)
 		acl = ext2_acl_from_disk(value, retval);
-		if (!IS_ERR(acl))
-			*p_acl = posix_acl_dup(acl);
-	}
+	else if (retval == -ENODATA || retval == -ENOSYS)
+		acl = NULL;
 	kfree(value);
+
+	if (!IS_ERR(acl)) {
+		switch(type) {
+			case ACL_TYPE_ACCESS:
+				ext2_iset_acl(inode, &ei->i_acl, acl);
+				break;
+
+			case ACL_TYPE_DEFAULT:
+				ext2_iset_acl(inode, &ei->i_default_acl, acl);
+				break;
+		}
+	}
 	return acl;
 }
 
@@ -180,9 +214,9 @@
 static int
 ext2_set_acl(struct inode *inode, int type, struct posix_acl *acl)
 {
+	struct ext2_inode_info *ei = EXT2_I(inode);
 	int name_index;
 	void *value = NULL;
-	struct posix_acl **p_acl;
 	size_t size;
 	int error;
 
@@ -194,7 +228,6 @@
 	switch(type) {
 		case ACL_TYPE_ACCESS:
 			name_index = EXT2_XATTR_INDEX_POSIX_ACL_ACCESS;
-			p_acl = &EXT2_I(inode)->i_acl;
 			if (acl) {
 				mode_t mode = inode->i_mode;
 				error = posix_acl_equiv_mode(acl, &mode);
@@ -211,7 +244,6 @@
 
 		case ACL_TYPE_DEFAULT:
 			name_index = EXT2_XATTR_INDEX_POSIX_ACL_DEFAULT;
-			p_acl = &EXT2_I(inode)->i_default_acl;
 			if (!S_ISDIR(inode->i_mode))
 				return acl ? -EACCES : 0;
 			break;
@@ -232,15 +264,26 @@
 	if (value)
 		kfree(value);
 	if (!error) {
-		if (*p_acl && *p_acl != EXT2_ACL_NOT_CACHED)
-			posix_acl_release(*p_acl);
-		*p_acl = posix_acl_dup(acl);
+		switch(type) {
+			case ACL_TYPE_ACCESS:
+				ext2_iset_acl(inode, &ei->i_acl, acl);
+				break;
+
+			case ACL_TYPE_DEFAULT:
+				ext2_iset_acl(inode, &ei->i_default_acl, acl);
+				break;
+		}
 	}
 	return error;
 }
 
-static int
-__ext2_permission(struct inode *inode, int mask, int lock)
+/*
+ * Inode operation permission().
+ *
+ * inode->i_sem: don't care
+ */
+int
+ext2_permission(struct inode *inode, int mask, struct nameidata *nd)
 {
 	int mode = inode->i_mode;
 
@@ -254,29 +297,16 @@
 	if (current->fsuid == inode->i_uid) {
 		mode >>= 6;
 	} else if (test_opt(inode->i_sb, POSIX_ACL)) {
-		/* ACL can't contain additional permissions if
-		   the ACL_MASK entry is 0 */
-		if (!(mode & S_IRWXG))
-			goto check_groups;
-		if (EXT2_I(inode)->i_acl == EXT2_ACL_NOT_CACHED) {
-			struct posix_acl *acl;
-
-			if (lock) {
-				down(&inode->i_sem);
-				acl = ext2_get_acl(inode, ACL_TYPE_ACCESS);
-				up(&inode->i_sem);
-			} else
-				acl = ext2_get_acl(inode, ACL_TYPE_ACCESS);
+		struct posix_acl *acl;
 
-			if (IS_ERR(acl))
-				return PTR_ERR(acl);
+		/* The access ACL cannot grant access if the group class
+		   permission bits don't contain all requested permissions. */
+		if (((mode >> 3) & mask & S_IRWXO) != mask)
+			goto check_groups;
+		acl = ext2_get_acl(inode, ACL_TYPE_ACCESS);
+		if (acl) {
+			int error = posix_acl_permission(inode, acl, mask);
 			posix_acl_release(acl);
-			if (EXT2_I(inode)->i_acl == EXT2_ACL_NOT_CACHED)
-				return -EIO;
-		}
-		if (EXT2_I(inode)->i_acl) {
-			int error = posix_acl_permission(inode,
-				EXT2_I(inode)->i_acl, mask);
 			if (error == -EACCES)
 				goto check_capabilities;
 			return error;
@@ -303,32 +333,10 @@
 }
 
 /*
- * Inode operation permission().
- *
- * inode->i_sem: up
- * BKL held [before 2.5.x]
- */
-int
-ext2_permission(struct inode *inode, int mask)
-{
-	return __ext2_permission(inode, mask, 1);
-}
-
-/*
- * Used internally if i_sem is already down.
- */
-int
-ext2_permission_locked(struct inode *inode, int mask)
-{
-	return __ext2_permission(inode, mask, 0);
-}
-
-/*
  * Initialize the ACLs of a new inode. Called from ext2_new_inode.
  *
  * dir->i_sem: down
  * inode->i_sem: up (access to inode is still exclusive)
- * BKL held [before 2.5.x] 
  */
 int
 ext2_init_acl(struct inode *inode, struct inode *dir)
@@ -388,7 +396,6 @@
  * file mode.
  *
  * inode->i_sem: down
- * BKL held [before 2.5.x]
  */
 int
 ext2_acl_chmod(struct inode *inode)
diff -Nru a/fs/ext2/acl.h b/fs/ext2/acl.h
--- a/fs/ext2/acl.h	Wed Oct 30 23:34:13 2002
+++ b/fs/ext2/acl.h	Fri Jul  4 22:31:27 2003
@@ -59,8 +59,7 @@
 #define EXT2_ACL_NOT_CACHED ((void *)-1)
 
 /* acl.c */
-extern int ext2_permission (struct inode *, int);
-extern int ext2_permission_locked (struct inode *, int);
+extern int ext2_permission (struct inode *, int, struct nameidata *);
 extern int ext2_acl_chmod (struct inode *);
 extern int ext2_init_acl (struct inode *, struct inode *);
 
diff -Nru a/fs/ext2/ext2.h b/fs/ext2/ext2.h
--- a/fs/ext2/ext2.h	Sun Mar 16 22:33:16 2003
+++ b/fs/ext2/ext2.h	Fri Jul  4 22:31:27 2003
@@ -41,6 +41,16 @@
 	__u32	i_prealloc_block;
 	__u32	i_prealloc_count;
 	__u32	i_dir_start_lookup;
+#ifdef CONFIG_EXT2_FS_XATTR
+	/*
+	 * Extended attributes can be read independently of the main file
+	 * data. Taking i_sem even when reading would cause contention
+	 * between readers of EAs and writers of regular file data, so
+	 * instead we synchronize on xattr_sem when reading or changing
+	 * EAs.
+	 */
+	struct rw_semaphore xattr_sem;
+#endif
 #ifdef CONFIG_EXT2_FS_POSIX_ACL
 	struct posix_acl	*i_acl;
 	struct posix_acl	*i_default_acl;
diff -Nru a/fs/ext2/ialloc.c b/fs/ext2/ialloc.c
--- a/fs/ext2/ialloc.c	Thu Apr 17 12:14:09 2003
+++ b/fs/ext2/ialloc.c	Wed Jul  2 21:22:40 2003
@@ -489,17 +489,18 @@
 	return group;
 }
 
-struct inode * ext2_new_inode(struct inode * dir, int mode)
+struct inode *ext2_new_inode(struct inode *dir, int mode)
 {
 	struct super_block *sb;
 	struct buffer_head *bitmap_bh = NULL;
 	struct buffer_head *bh2;
 	int group, i;
-	ino_t ino;
+	ino_t ino = 0;
 	struct inode * inode;
-	struct ext2_group_desc * desc;
-	struct ext2_super_block * es;
+	struct ext2_group_desc *gdp;
+	struct ext2_super_block *es;
 	struct ext2_inode_info *ei;
+	struct ext2_sb_info *sbi;
 	int err;
 
 	sb = dir->i_sb;
@@ -508,36 +509,62 @@
 		return ERR_PTR(-ENOMEM);
 
 	ei = EXT2_I(inode);
-	es = EXT2_SB(sb)->s_es;
+	sbi = EXT2_SB(sb);
+	es = sbi->s_es;
 repeat:
 	if (S_ISDIR(mode)) {
-		if (test_opt (sb, OLDALLOC))
+		if (test_opt(sb, OLDALLOC))
 			group = find_group_dir(sb, dir);
 		else
 			group = find_group_orlov(sb, dir);
 	} else 
 		group = find_group_other(sb, dir);
 
-	err = -ENOSPC;
-	if (group == -1)
+	if (group == -1) {
+		err = -ENOSPC;
 		goto fail;
+	}
 
-	err = -EIO;
-	bitmap_bh = read_inode_bitmap(sb, group);
-	if (!bitmap_bh)
-		goto fail2;
-
-	i = ext2_find_first_zero_bit((unsigned long *)bitmap_bh->b_data,
-				      EXT2_INODES_PER_GROUP(sb));
-	if (i >= EXT2_INODES_PER_GROUP(sb))
-		goto bad_count;
-	if (ext2_set_bit_atomic(sb_bgl_lock(EXT2_SB(sb), group),
-			i, (void *) bitmap_bh->b_data)) {
+	for (i = 0; i < sbi->s_groups_count; i++) {
+		gdp = ext2_get_group_desc(sb, group, &bh2);
 		brelse(bitmap_bh);
-		ext2_release_inode(sb, group, S_ISDIR(mode));
-		goto repeat;
+		bitmap_bh = read_inode_bitmap(sb, group);
+		if (!bitmap_bh) {
+			err = -EIO;
+			goto fail2;
+		}
+
+		i = ext2_find_first_zero_bit((unsigned long *)bitmap_bh->b_data,
+					      EXT2_INODES_PER_GROUP(sb));
+		if (i >= EXT2_INODES_PER_GROUP(sb)) {
+			/*
+			 * Rare race: find_group_xx() decided that there were
+			 * free inodes in this group, but by the time we tried
+			 * to allocate one, they're all gone.  This can also
+			 * occur because the counters which find_group_orlov()
+			 * uses are approximate.  So just go and search the
+			 * next block group.
+			 */
+			if (++group == sbi->s_groups_count)
+				group = 0;
+			continue;
+		}
+		if (ext2_set_bit_atomic(sb_bgl_lock(EXT2_SB(sb), group),
+						i, bitmap_bh->b_data)) {
+			brelse(bitmap_bh);
+			bitmap_bh = NULL;
+			ext2_release_inode(sb, group, S_ISDIR(mode));
+			goto repeat;
+		}
+		goto got;
 	}
 
+	/*
+	 * Scanned all blockgroups.
+	 */
+	err = -ENOSPC;
+	goto fail2;
+got:
 	mark_buffer_dirty(bitmap_bh);
 	if (sb->s_flags & MS_SYNCHRONOUS)
 		sync_dirty_buffer(bitmap_bh);
@@ -605,8 +632,9 @@
 	inode->i_generation = EXT2_SB(sb)->s_next_generation++;
 	insert_inode_hash(inode);
 
-	if(DQUOT_ALLOC_INODE(inode)) {
+	if (DQUOT_ALLOC_INODE(inode)) {
 		DQUOT_DROP(inode);
+		err = -ENOSPC;
 		goto fail3;
 	}
 	err = ext2_init_acl(inode, dir);
@@ -631,21 +659,6 @@
 	make_bad_inode(inode);
 	iput(inode);
 	return ERR_PTR(err);
-
-bad_count:
-	brelse(bitmap_bh);
-	ext2_error (sb, "ext2_new_inode",
-		    "Free inodes count corrupted in group %d",
-		    group);
-	/* Is it really ENOSPC? */
-	err = -ENOSPC;
-	if (sb->s_flags & MS_RDONLY)
-		goto fail;
-
-	desc = ext2_get_group_desc (sb, group, &bh2);
-	desc->bg_free_inodes_count = 0;
-	mark_buffer_dirty(bh2);
-	goto repeat;
 }
 
 unsigned long ext2_count_free_inodes (struct super_block * sb)
diff -Nru a/fs/ext2/namei.c b/fs/ext2/namei.c
--- a/fs/ext2/namei.c	Thu Nov 21 13:10:50 2002
+++ b/fs/ext2/namei.c	Sun Jun 29 23:49:04 2003
@@ -66,7 +66,7 @@
  * Methods themselves.
  */
 
-static struct dentry *ext2_lookup(struct inode * dir, struct dentry *dentry)
+static struct dentry *ext2_lookup(struct inode * dir, struct dentry *dentry, struct nameidata *nd)
 {
 	struct inode * inode;
 	ino_t ino;
@@ -120,7 +120,7 @@
  * If the create succeeds, we fill in the inode information
  * with d_instantiate(). 
  */
-static int ext2_create (struct inode * dir, struct dentry * dentry, int mode)
+static int ext2_create (struct inode * dir, struct dentry * dentry, int mode, struct nameidata *nd)
 {
 	struct inode * inode = ext2_new_inode (dir, mode);
 	int err = PTR_ERR(inode);
diff -Nru a/fs/ext2/super.c b/fs/ext2/super.c
--- a/fs/ext2/super.c	Fri Jun 20 13:16:06 2003
+++ b/fs/ext2/super.c	Fri Jul  4 22:31:27 2003
@@ -177,6 +177,9 @@
 	if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) ==
 	    SLAB_CTOR_CONSTRUCTOR) {
 		rwlock_init(&ei->i_meta_lock);
+#ifdef CONFIG_EXT2_FS_XATTR
+		init_rwsem(&ei->xattr_sem);
+#endif
 		inode_init_once(&ei->vfs_inode);
 	}
 }
diff -Nru a/fs/ext2/xattr.c b/fs/ext2/xattr.c
--- a/fs/ext2/xattr.c	Mon May  5 06:19:21 2003
+++ b/fs/ext2/xattr.c	Fri Jul  4 22:31:27 2003
@@ -1,7 +1,7 @@
 /*
  * linux/fs/ext2/xattr.c
  *
- * Copyright (C) 2001 by Andreas Gruenbacher, <a.gruenbacher@computer.org>
+ * Copyright (C) 2001-2003 Andreas Gruenbacher <agruen@suse.de>
  *
  * Fix by Harrison Xing <harrison@mountainviewdata.com>.
  * Extended attributes for symlinks and special files added per
@@ -42,13 +42,12 @@
  *
  * Locking strategy
  * ----------------
- * The VFS already holds the BKL and the inode->i_sem semaphore when any of
- * the xattr inode operations are called, so we are guaranteed that only one
- * processes accesses extended attributes of an inode at any time.
- *
- * For writing we also grab the ext2_xattr_sem semaphore. This ensures that
- * only a single process is modifying an extended attribute block, even
- * if the block is shared among inodes.
+ * EXT2_I(inode)->i_file_acl is protected by EXT2_I(inode)->xattr_sem.
+ * EA blocks are only changed if they are exclusive to an inode, so
+ * holding xattr_sem also means that nothing but the EA block's reference
+ * count will change. Multiple writers to an EA block are synchronized
+ * by the bh lock. No more than a single bh lock is held at any time
+ * to avoid deadlocks.
  */
 
 #include <linux/buffer_head.h>
@@ -57,7 +56,7 @@
 #include <linux/slab.h>
 #include <linux/mbcache.h>
 #include <linux/quotaops.h>
-#include <asm/semaphore.h>
+#include <linux/rwsem.h>
 #include "ext2.h"
 #include "xattr.h"
 #include "acl.h"
@@ -83,8 +82,9 @@
 	} while (0)
 # define ea_bdebug(bh, f...) do { \
 		char b[BDEVNAME_SIZE]; \
-		printk(KERN_DEBUG "block %s:%ld: ", \
-			bdevname(bh->b_bdev, b), bh->b_blocknr); \
+		printk(KERN_DEBUG "block %s:%lu: ", \
+			bdevname(bh->b_bdev, b), \
+			(unsigned long) bh->b_blocknr); \
 		printk(f); \
 		printk("\n"); \
 	} while (0)
@@ -104,15 +104,6 @@
 			      struct ext2_xattr_entry *);
 
 static struct mb_cache *ext2_xattr_cache;
-
-/*
- * If a file system does not share extended attributes among inodes,
- * we should not need the ext2_xattr_sem semaphore. However, the
- * filesystem may still contain shared blocks, so we always take
- * the lock.
- */
-
-static DECLARE_MUTEX(ext2_xattr_sem);
 static struct ext2_xattr_handler *ext2_xattr_handlers[EXT2_XATTR_INDEX_MAX];
 static rwlock_t ext2_handler_lock = RW_LOCK_UNLOCKED;
 
@@ -195,8 +186,7 @@
 /*
  * Inode operation getxattr()
  *
- * dentry->d_inode->i_sem down
- * BKL held [before 2.5.x]
+ * dentry->d_inode->i_sem: don't care
  */
 ssize_t
 ext2_getxattr(struct dentry *dentry, const char *name,
@@ -214,8 +204,7 @@
 /*
  * Inode operation listxattr()
  *
- * dentry->d_inode->i_sem down
- * BKL held [before 2.5.x]
+ * dentry->d_inode->i_sem: don't care
  */
 ssize_t
 ext2_listxattr(struct dentry *dentry, char *buffer, size_t size)
@@ -226,8 +215,7 @@
 /*
  * Inode operation setxattr()
  *
- * dentry->d_inode->i_sem down
- * BKL held [before 2.5.x]
+ * dentry->d_inode->i_sem: down
  */
 int
 ext2_setxattr(struct dentry *dentry, const char *name,
@@ -247,8 +235,7 @@
 /*
  * Inode operation removexattr()
  *
- * dentry->d_inode->i_sem down
- * BKL held [before 2.5.x]
+ * dentry->d_inode->i_sem: down
  */
 int
 ext2_removexattr(struct dentry *dentry, const char *name)
@@ -278,21 +265,24 @@
 {
 	struct buffer_head *bh = NULL;
 	struct ext2_xattr_entry *entry;
-	unsigned int size;
+	size_t name_len, size;
 	char *end;
-	int name_len, error;
+	int error;
 
 	ea_idebug(inode, "name=%d.%s, buffer=%p, buffer_size=%ld",
 		  name_index, name, buffer, (long)buffer_size);
 
 	if (name == NULL)
 		return -EINVAL;
+	down_read(&EXT2_I(inode)->xattr_sem);
+	error = -ENODATA;
 	if (!EXT2_I(inode)->i_file_acl)
-		return -ENODATA;
+		goto cleanup;
 	ea_idebug(inode, "reading block %d", EXT2_I(inode)->i_file_acl);
 	bh = sb_bread(inode->i_sb, EXT2_I(inode)->i_file_acl);
+	error = -EIO;
 	if (!bh)
-		return -EIO;
+		goto cleanup;
 	ea_bdebug(bh, "b_count=%d, refcount=%d",
 		atomic_read(&(bh->b_count)), le32_to_cpu(HDR(bh)->h_refcount));
 	end = bh->b_data + bh->b_size;
@@ -357,6 +347,7 @@
 
 cleanup:
 	brelse(bh);
+	up_read(&EXT2_I(inode)->xattr_sem);
 
 	return error;
 }
@@ -376,19 +367,22 @@
 {
 	struct buffer_head *bh = NULL;
 	struct ext2_xattr_entry *entry;
-	unsigned int size = 0;
+	size_t size = 0;
 	char *buf, *end;
 	int error;
 
 	ea_idebug(inode, "buffer=%p, buffer_size=%ld",
 		  buffer, (long)buffer_size);
 
+	down_read(&EXT2_I(inode)->xattr_sem);
+	error = 0;
 	if (!EXT2_I(inode)->i_file_acl)
-		return 0;
+		goto cleanup;
 	ea_idebug(inode, "reading block %d", EXT2_I(inode)->i_file_acl);
 	bh = sb_bread(inode->i_sb, EXT2_I(inode)->i_file_acl);
+	error = -EIO;
 	if (!bh)
-		return -EIO;
+		goto cleanup;
 	ea_bdebug(bh, "b_count=%d, refcount=%d",
 		atomic_read(&(bh->b_count)), le32_to_cpu(HDR(bh)->h_refcount));
 	end = bh->b_data + bh->b_size;
@@ -441,6 +435,7 @@
 
 cleanup:
 	brelse(bh);
+	up_read(&EXT2_I(inode)->xattr_sem);
 
 	return error;
 }
@@ -482,8 +477,8 @@
 	struct buffer_head *bh = NULL;
 	struct ext2_xattr_header *header = NULL;
 	struct ext2_xattr_entry *here, *last;
-	unsigned int name_len;
-	int min_offs = sb->s_blocksize, not_found = 1, free, error;
+	size_t name_len, free, min_offs = sb->s_blocksize;
+	int not_found = 1, error;
 	char *end;
 	
 	/*
@@ -512,8 +507,7 @@
 	name_len = strlen(name);
 	if (name_len > 255 || value_len > sb->s_blocksize)
 		return -ERANGE;
-	down(&ext2_xattr_sem);
-
+	down_write(&EXT2_I(inode)->xattr_sem);
 	if (EXT2_I(inode)->i_file_acl) {
 		/* The inode already has an extended attribute block. */
 		bh = sb_bread(sb, EXT2_I(inode)->i_file_acl);
@@ -540,7 +534,7 @@
 			if ((char *)next >= end)
 				goto bad_block;
 			if (!here->e_value_block && here->e_value_size) {
-				int offs = le16_to_cpu(here->e_value_offs);
+				size_t offs = le16_to_cpu(here->e_value_offs);
 				if (offs < min_offs)
 					min_offs = offs;
 			}
@@ -560,7 +554,7 @@
 			if ((char *)next >= end)
 				goto bad_block;
 			if (!last->e_value_block && last->e_value_size) {
-				int offs = le16_to_cpu(last->e_value_offs);
+				size_t offs = le16_to_cpu(last->e_value_offs);
 				if (offs < min_offs)
 					min_offs = offs;
 			}
@@ -584,36 +578,38 @@
 		error = 0;
 		if (value == NULL)
 			goto cleanup;
-		else
-			free -= EXT2_XATTR_LEN(name_len);
 	} else {
 		/* Request to create an existing attribute? */
 		error = -EEXIST;
 		if (flags & XATTR_CREATE)
 			goto cleanup;
 		if (!here->e_value_block && here->e_value_size) {
-			unsigned int size = le32_to_cpu(here->e_value_size);
+			size_t size = le32_to_cpu(here->e_value_size);
 
 			if (le16_to_cpu(here->e_value_offs) + size > 
 			    sb->s_blocksize || size > sb->s_blocksize)
 				goto bad_block;
 			free += EXT2_XATTR_SIZE(size);
 		}
+		free += EXT2_XATTR_LEN(name_len);
 	}
-	free -= EXT2_XATTR_SIZE(value_len);
 	error = -ENOSPC;
-	if (free < 0)
+	if (free < EXT2_XATTR_LEN(name_len) + EXT2_XATTR_SIZE(value_len))
 		goto cleanup;
 
 	/* Here we know that we can set the new attribute. */
 
 	if (header) {
+		/* assert(header == HDR(bh)); */
+		lock_buffer(bh);
 		if (header->h_refcount == cpu_to_le32(1)) {
 			ea_bdebug(bh, "modifying in-place");
 			ext2_xattr_cache_remove(bh);
+			/* keep the buffer locked while modifying it. */
 		} else {
 			int offset;
 
+			unlock_buffer(bh);
 			ea_bdebug(bh, "cloning");
 			header = kmalloc(bh->b_size, GFP_KERNEL);
 			error = -ENOMEM;
@@ -638,23 +634,36 @@
 		last = here = ENTRY(header+1);
 	}
 
+	/* Iff we are modifying the block in-place, bh is locked here. */
+
 	if (not_found) {
 		/* Insert the new name. */
-		int size = EXT2_XATTR_LEN(name_len);
-		int rest = (char *)last - (char *)here;
+		size_t size = EXT2_XATTR_LEN(name_len);
+		size_t rest = (char *)last - (char *)here;
 		memmove((char *)here + size, here, rest);
 		memset(here, 0, size);
 		here->e_name_index = name_index;
 		here->e_name_len = name_len;
 		memcpy(here->e_name, name, name_len);
 	} else {
-		/* Remove the old value. */
 		if (!here->e_value_block && here->e_value_size) {
 			char *first_val = (char *)header + min_offs;
-			int offs = le16_to_cpu(here->e_value_offs);
+			size_t offs = le16_to_cpu(here->e_value_offs);
 			char *val = (char *)header + offs;
 			size_t size = EXT2_XATTR_SIZE(
 				le32_to_cpu(here->e_value_size));
+
+			if (size == EXT2_XATTR_SIZE(value_len)) {
+				/* The old and the new value have the same
+				   size. Just replace. */
+				here->e_value_size = cpu_to_le32(value_len);
+				memset(val + size - EXT2_XATTR_PAD, 0,
+				       EXT2_XATTR_PAD); /* Clear pad bytes. */
+				memcpy(val, value, value_len);
+				goto skip_replace;
+			}
+
+			/* Remove the old value. */
 			memmove(first_val + size, first_val, val - first_val);
 			memset(first_val, 0, size);
 			here->e_value_offs = 0;
@@ -663,7 +672,7 @@
 			/* Adjust all value offsets. */
 			last = ENTRY(header+1);
 			while (!IS_LAST_ENTRY(last)) {
-				int o = le16_to_cpu(last->e_value_offs);
+				size_t o = le16_to_cpu(last->e_value_offs);
 				if (!last->e_value_block && o < offs)
 					last->e_value_offs =
 						cpu_to_le16(o + size);
@@ -671,19 +680,12 @@
 			}
 		}
 		if (value == NULL) {
-			/* Remove this attribute. */
-			if (EXT2_XATTR_NEXT(ENTRY(header+1)) == last) {
-				/* This block is now empty. */
-				error = ext2_xattr_set2(inode, bh, NULL);
-				goto cleanup;
-			} else {
-				/* Remove the old name. */
-				int size = EXT2_XATTR_LEN(name_len);
-				last = ENTRY((char *)last - size);
-				memmove(here, (char*)here + size,
-					(char*)last - (char*)here);
-				memset(last, 0, size);
-			}
+			/* Remove the old name. */
+			size_t size = EXT2_XATTR_LEN(name_len);
+			last = ENTRY((char *)last - size);
+			memmove(here, (char*)here + size,
+				(char*)last - (char*)here);
+			memset(last, 0, size);
 		}
 	}
 
@@ -700,15 +702,25 @@
 			memcpy(val, value, value_len);
 		}
 	}
-	ext2_xattr_rehash(header, here);
 
-	error = ext2_xattr_set2(inode, bh, header);
+skip_replace:
+	if (IS_LAST_ENTRY(ENTRY(header+1))) {
+		/* This block is now empty. */
+		if (bh && header == HDR(bh))
+			unlock_buffer(bh);  /* we were modifying in-place. */
+		error = ext2_xattr_set2(inode, bh, NULL);
+	} else {
+		ext2_xattr_rehash(header, here);
+		if (bh && header == HDR(bh))
+			unlock_buffer(bh);  /* we were modifying in-place. */
+		error = ext2_xattr_set2(inode, bh, header);
+	}
 
 cleanup:
 	brelse(bh);
 	if (!(bh && header == HDR(bh)))
 		kfree(header);
-	up(&ext2_xattr_sem);
+	up_write(&EXT2_I(inode)->xattr_sem);
 
 	return error;
 }
@@ -728,31 +740,37 @@
 		new_bh = ext2_xattr_cache_find(inode, header);
 		if (new_bh) {
 			/*
-			 * We found an identical block in the cache.
-			 * The old block will be released after updating
-			 * the inode.
+			 * We found an identical block in the cache. The
+			 * block returned is locked. The old block will
+			 * be released after updating the inode.
 			 */
-			ea_bdebug(new_bh, "%s block %ld",
+			ea_bdebug(new_bh, "%s block %lu",
 				(old_bh == new_bh) ? "keeping" : "reusing",
-				new_bh->b_blocknr);
+				(unsigned long) new_bh->b_blocknr);
 			
 			error = -EDQUOT;
-			if (DQUOT_ALLOC_BLOCK(inode, 1))
+			if (DQUOT_ALLOC_BLOCK(inode, 1)) {
+				unlock_buffer(new_bh);
 				goto cleanup;
+			}
 			
 			HDR(new_bh)->h_refcount = cpu_to_le32(
 				le32_to_cpu(HDR(new_bh)->h_refcount) + 1);
 			ea_bdebug(new_bh, "refcount now=%d",
 				le32_to_cpu(HDR(new_bh)->h_refcount));
+			unlock_buffer(new_bh);
 		} else if (old_bh && header == HDR(old_bh)) {
-			/* Keep this block. */
+			/* Keep this block. No need to lock the block as we
+			   don't need to change the reference count. */
 			new_bh = old_bh;
 			get_bh(new_bh);
 			ext2_xattr_cache_insert(new_bh);
 		} else {
 			/* We need to allocate a new block */
-			int goal = le32_to_cpu(EXT2_SB(sb)->s_es->s_first_data_block) +
-				EXT2_I(inode)->i_block_group * EXT2_BLOCKS_PER_GROUP(sb);
+			int goal = le32_to_cpu(EXT2_SB(sb)->s_es->
+						           s_first_data_block) +
+				   EXT2_I(inode)->i_block_group *
+				   EXT2_BLOCKS_PER_GROUP(sb);
 			int block = ext2_new_block(inode, goal, 0, 0, &error);
 			if (error)
 				goto cleanup;
@@ -794,12 +812,11 @@
 	error = 0;
 	if (old_bh && old_bh != new_bh) {
 		/*
-		 * If there was an old block, and we are not still using it,
-		 * we now release the old block.
-		*/
-		unsigned int refcount = le32_to_cpu(HDR(old_bh)->h_refcount);
-
-		if (refcount == 1) {
+		 * If there was an old block and we are no longer using it,
+		 * release the old block.
+		 */
+		lock_buffer(old_bh);
+		if (HDR(old_bh)->h_refcount == cpu_to_le32(1)) {
 			/* Free the old block. */
 			ea_bdebug(old_bh, "freeing");
 			ext2_free_blocks(inode, old_bh->b_blocknr, 1);
@@ -809,12 +826,14 @@
 			bforget(old_bh);
 		} else {
 			/* Decrement the refcount only. */
-			refcount--;
-			HDR(old_bh)->h_refcount = cpu_to_le32(refcount);
+			HDR(old_bh)->h_refcount = cpu_to_le32(
+				le32_to_cpu(HDR(old_bh)->h_refcount) - 1);
 			DQUOT_FREE_BLOCK(inode, 1);
 			mark_buffer_dirty(old_bh);
-			ea_bdebug(old_bh, "refcount now=%d", refcount);
+			ea_bdebug(old_bh, "refcount now=%d",
+				le32_to_cpu(HDR(old_bh)->h_refcount));
 		}
+		unlock_buffer(old_bh);
 	}
 
 cleanup:
@@ -832,12 +851,11 @@
 void
 ext2_xattr_delete_inode(struct inode *inode)
 {
-	struct buffer_head *bh;
+	struct buffer_head *bh = NULL;
 
+	down_write(&EXT2_I(inode)->xattr_sem);
 	if (!EXT2_I(inode)->i_file_acl)
-		return;
-	down(&ext2_xattr_sem);
-
+		goto cleanup;
 	bh = sb_bread(inode->i_sb, EXT2_I(inode)->i_file_acl);
 	if (!bh) {
 		ext2_error(inode->i_sb, "ext2_xattr_delete_inode",
@@ -853,12 +871,12 @@
 			EXT2_I(inode)->i_file_acl);
 		goto cleanup;
 	}
-	ea_bdebug(bh, "refcount now=%d", le32_to_cpu(HDR(bh)->h_refcount) - 1);
+	lock_buffer(bh);
 	if (HDR(bh)->h_refcount == cpu_to_le32(1)) {
 		ext2_xattr_cache_remove(bh);
 		ext2_free_blocks(inode, EXT2_I(inode)->i_file_acl, 1);
+		get_bh(bh);
 		bforget(bh);
-		bh = NULL;
 	} else {
 		HDR(bh)->h_refcount = cpu_to_le32(
 			le32_to_cpu(HDR(bh)->h_refcount) - 1);
@@ -867,11 +885,13 @@
 			sync_dirty_buffer(bh);
 		DQUOT_FREE_BLOCK(inode, 1);
 	}
+	ea_bdebug(bh, "refcount now=%d", le32_to_cpu(HDR(bh)->h_refcount) - 1);
+	unlock_buffer(bh);
 	EXT2_I(inode)->i_file_acl = 0;
 
 cleanup:
 	brelse(bh);
-	up(&ext2_xattr_sem);
+	up_write(&EXT2_I(inode)->xattr_sem);
 }
 
 /*
@@ -964,8 +984,8 @@
  *
  * Find an identical extended attribute block.
  *
- * Returns a pointer to the block found, or NULL if such a block was
- * not found or an error occurred.
+ * Returns a locked buffer head to the block found, or NULL if such
+ * a block was not found or an error occurred.
  */
 static struct buffer_head *
 ext2_xattr_cache_find(struct inode *inode, struct ext2_xattr_header *header)
@@ -976,7 +996,8 @@
 	if (!header->h_hash)
 		return NULL;  /* never share */
 	ea_idebug(inode, "looking for cached blocks [%x]", (int)hash);
-	ce = mb_cache_entry_find_first(ext2_xattr_cache, 0, inode->i_bdev, hash);
+	ce = mb_cache_entry_find_first(ext2_xattr_cache, 0,
+				       inode->i_sb->s_bdev, hash);
 	while (ce) {
 		struct buffer_head *bh = sb_bread(inode->i_sb, ce->e_block);
 
@@ -984,19 +1005,24 @@
 			ext2_error(inode->i_sb, "ext2_xattr_cache_find",
 				"inode %ld: block %ld read error",
 				inode->i_ino, (unsigned long) ce->e_block);
-		} else if (le32_to_cpu(HDR(bh)->h_refcount) >
-			   EXT2_XATTR_REFCOUNT_MAX) {
-			ea_idebug(inode, "block %ld refcount %d>%d",
-				  (unsigned long) ce->e_block,
-				  le32_to_cpu(HDR(bh)->h_refcount),
-				  EXT2_XATTR_REFCOUNT_MAX);
-		} else if (!ext2_xattr_cmp(header, HDR(bh))) {
-			ea_bdebug(bh, "b_count=%d",atomic_read(&(bh->b_count)));
-			mb_cache_entry_release(ce);
-			return bh;
+		} else {
+			lock_buffer(bh);
+			if (le32_to_cpu(HDR(bh)->h_refcount) >
+				   EXT2_XATTR_REFCOUNT_MAX) {
+				ea_idebug(inode, "block %ld refcount %d>%d",
+					  (unsigned long) ce->e_block,
+					  le32_to_cpu(HDR(bh)->h_refcount),
+					  EXT2_XATTR_REFCOUNT_MAX);
+			} else if (!ext2_xattr_cmp(header, HDR(bh))) {
+				ea_bdebug(bh, "b_count=%d",
+					  atomic_read(&(bh->b_count)));
+				mb_cache_entry_release(ce);
+				return bh;
+			}
+			unlock_buffer(bh);
+			brelse(bh);
 		}
-		brelse(bh);
-		ce = mb_cache_entry_find_next(ce, 0, inode->i_bdev, hash);
+		ce = mb_cache_entry_find_next(ce, 0, inode->i_sb->s_bdev, hash);
 	}
 	return NULL;
 }
diff -Nru a/fs/ext2/xattr_user.c b/fs/ext2/xattr_user.c
--- a/fs/ext2/xattr_user.c	Tue Feb 25 08:21:08 2003
+++ b/fs/ext2/xattr_user.c	Fri Jul  4 22:31:27 2003
@@ -11,10 +11,6 @@
 #include "ext2.h"
 #include "xattr.h"
 
-#ifdef CONFIG_EXT2_FS_POSIX_ACL
-# include "acl.h"
-#endif
-
 #define XATTR_USER_PREFIX "user."
 
 static size_t
@@ -44,11 +40,7 @@
 		return -EINVAL;
 	if (!test_opt(inode->i_sb, XATTR_USER))
 		return -EOPNOTSUPP;
-#ifdef CONFIG_EXT2_FS_POSIX_ACL
-	error = ext2_permission_locked(inode, MAY_READ);
-#else
-	error = permission(inode, MAY_READ);
-#endif
+	error = permission(inode, MAY_READ, NULL);
 	if (error)
 		return error;
 
@@ -68,11 +60,7 @@
 	if ( !S_ISREG(inode->i_mode) &&
 	    (!S_ISDIR(inode->i_mode) || inode->i_mode & S_ISVTX))
 		return -EPERM;
-#ifdef CONFIG_EXT2_FS_POSIX_ACL
-	error = ext2_permission_locked(inode, MAY_WRITE);
-#else
-	error = permission(inode, MAY_WRITE);
-#endif
+	error = permission(inode, MAY_WRITE, NULL);
 	if (error)
 		return error;
 
diff -Nru a/fs/ext3/acl.c b/fs/ext3/acl.c
--- a/fs/ext3/acl.c	Fri Jun 20 13:16:31 2003
+++ b/fs/ext3/acl.c	Fri Jul  4 22:31:27 2003
@@ -1,7 +1,7 @@
 /*
  * linux/fs/ext3/acl.c
  *
- * Copyright (C) 2001 by Andreas Gruenbacher, <a.gruenbacher@computer.org>
+ * Copyright (C) 2001-2003 Andreas Gruenbacher, <agruen@suse.de>
  */
 
 #include <linux/init.h>
@@ -20,7 +20,7 @@
 ext3_acl_from_disk(const void *value, size_t size)
 {
 	const char *end = (char *)value + size;
-	int n, count;
+	size_t n, count;
 	struct posix_acl *acl;
 
 	if (!value)
@@ -86,7 +86,7 @@
 {
 	ext3_acl_header *ext_acl;
 	char *e;
-	int n;
+	size_t n;
 
 	*size = ext3_acl_size(acl->a_count);
 	ext_acl = (ext3_acl_header *)kmalloc(sizeof(ext3_acl_header) +
@@ -125,18 +125,43 @@
 	return ERR_PTR(-EINVAL);
 }
 
+static inline struct posix_acl *
+ext3_iget_acl(struct inode *inode, struct posix_acl **i_acl)
+{
+	struct posix_acl *acl = EXT3_ACL_NOT_CACHED;
+
+	spin_lock(&inode->i_lock);
+	if (*i_acl != EXT3_ACL_NOT_CACHED)
+		acl = posix_acl_dup(*i_acl);
+	spin_unlock(&inode->i_lock);
+
+	return acl;
+}
+
+static inline void
+ext3_iset_acl(struct inode *inode, struct posix_acl **i_acl,
+                  struct posix_acl *acl)
+{
+	spin_lock(&inode->i_lock);
+	if (*i_acl != EXT3_ACL_NOT_CACHED)
+		posix_acl_release(*i_acl);
+	*i_acl = posix_acl_dup(acl);
+	spin_unlock(&inode->i_lock);
+}
+
 /*
  * Inode operation get_posix_acl().
  *
- * inode->i_sem: down
+ * inode->i_sem: don't care
  */
 static struct posix_acl *
 ext3_get_acl(struct inode *inode, int type)
 {
+	const size_t max_size = ext3_acl_size(EXT3_ACL_MAX_ENTRIES);
+	struct ext3_inode_info *ei = EXT3_I(inode);
 	int name_index;
 	char *value;
-	struct posix_acl *acl, **p_acl;
-	const size_t size = ext3_acl_size(EXT3_ACL_MAX_ENTRIES);
+	struct posix_acl *acl;
 	int retval;
 
 	if (!test_opt(inode->i_sb, POSIX_ACL))
@@ -144,36 +169,45 @@
 
 	switch(type) {
 		case ACL_TYPE_ACCESS:
-			p_acl = &EXT3_I(inode)->i_acl;
+			acl = ext3_iget_acl(inode, &ei->i_acl);
+			if (acl != EXT3_ACL_NOT_CACHED)
+				return acl;
 			name_index = EXT3_XATTR_INDEX_POSIX_ACL_ACCESS;
 			break;
 
 		case ACL_TYPE_DEFAULT:
-			p_acl = &EXT3_I(inode)->i_default_acl;
+			acl = ext3_iget_acl(inode, &ei->i_default_acl);
+			if (acl != EXT3_ACL_NOT_CACHED)
+				return acl;
 			name_index = EXT3_XATTR_INDEX_POSIX_ACL_DEFAULT;
 			break;
 
 		default:
 			return ERR_PTR(-EINVAL);
 	}
-	if (*p_acl != EXT3_ACL_NOT_CACHED)
-		return posix_acl_dup(*p_acl);
-	value = kmalloc(size, GFP_KERNEL);
+	value = kmalloc(max_size, GFP_KERNEL);
 	if (!value)
 		return ERR_PTR(-ENOMEM);
 
-	retval = ext3_xattr_get(inode, name_index, "", value, size);
-
-	if (retval == -ENODATA || retval == -ENOSYS)
-		*p_acl = acl = NULL;
-	else if (retval < 0)
-		acl = ERR_PTR(retval);
-	else {
+	retval = ext3_xattr_get(inode, name_index, "", value, max_size);
+	acl = ERR_PTR(retval);
+	if (retval > 0)
 		acl = ext3_acl_from_disk(value, retval);
-		if (!IS_ERR(acl))
-			*p_acl = posix_acl_dup(acl);
-	}
+	else if (retval == -ENODATA || retval == -ENOSYS)
+		acl = NULL;
 	kfree(value);
+
+	if (!IS_ERR(acl)) {
+		switch(type) {
+			case ACL_TYPE_ACCESS:
+				ext3_iset_acl(inode, &ei->i_acl, acl);
+				break;
+
+			case ACL_TYPE_DEFAULT:
+				ext3_iset_acl(inode, &ei->i_default_acl, acl);
+				break;
+		}
+	}
 	return acl;
 }
 
@@ -186,9 +220,9 @@
 ext3_set_acl(handle_t *handle, struct inode *inode, int type,
 	     struct posix_acl *acl)
 {
+	struct ext3_inode_info *ei = EXT3_I(inode);
 	int name_index;
 	void *value = NULL;
-	struct posix_acl **p_acl;
 	size_t size;
 	int error;
 
@@ -198,7 +232,6 @@
 	switch(type) {
 		case ACL_TYPE_ACCESS:
 			name_index = EXT3_XATTR_INDEX_POSIX_ACL_ACCESS;
-			p_acl = &EXT3_I(inode)->i_acl;
 			if (acl) {
 				mode_t mode = inode->i_mode;
 				error = posix_acl_equiv_mode(acl, &mode);
@@ -215,7 +248,6 @@
 
 		case ACL_TYPE_DEFAULT:
 			name_index = EXT3_XATTR_INDEX_POSIX_ACL_DEFAULT;
-			p_acl = &EXT3_I(inode)->i_default_acl;
 			if (!S_ISDIR(inode->i_mode))
 				return acl ? -EACCES : 0;
 			break;
@@ -231,20 +263,32 @@
 			return (int)PTR_ERR(value);
 	}
 
-	error = ext3_xattr_set_handle(handle, inode, name_index, "", value, size, 0);
+	error = ext3_xattr_set_handle(handle, inode, name_index, "",
+				      value, size, 0);
 
 	if (value)
 		kfree(value);
 	if (!error) {
-		if (*p_acl && *p_acl != EXT3_ACL_NOT_CACHED)
-			posix_acl_release(*p_acl);
-		*p_acl = posix_acl_dup(acl);
+		switch(type) {
+			case ACL_TYPE_ACCESS:
+				ext3_iset_acl(inode, &ei->i_acl, acl);
+				break;
+
+			case ACL_TYPE_DEFAULT:
+				ext3_iset_acl(inode, &ei->i_default_acl, acl);
+				break;
+		}
 	}
 	return error;
 }
 
-static int
-__ext3_permission(struct inode *inode, int mask, int lock)
+/*
+ * Inode operation permission().
+ *
+ * inode->i_sem: don't care
+ */
+int
+ext3_permission(struct inode *inode, int mask, struct nameidata *nd)
 {
 	int mode = inode->i_mode;
 
@@ -258,29 +302,16 @@
 	if (current->fsuid == inode->i_uid) {
 		mode >>= 6;
 	} else if (test_opt(inode->i_sb, POSIX_ACL)) {
-		/* ACL can't contain additional permissions if
-		   the ACL_MASK entry is 0 */
-		if (!(mode & S_IRWXG))
-			goto check_groups;
-		if (EXT3_I(inode)->i_acl == EXT3_ACL_NOT_CACHED) {
-			struct posix_acl *acl;
+		struct posix_acl *acl;
 
-			if (lock) {
-				down(&inode->i_sem);
-				acl = ext3_get_acl(inode, ACL_TYPE_ACCESS);
-				up(&inode->i_sem);
-			} else
-				acl = ext3_get_acl(inode, ACL_TYPE_ACCESS);
-
-			if (IS_ERR(acl))
-				return PTR_ERR(acl);
+		/* The access ACL cannot grant access if the group class
+		   permission bits don't contain all requested permissions. */
+		if (((mode >> 3) & mask & S_IRWXO) != mask)
+			goto check_groups;
+		acl = ext3_get_acl(inode, ACL_TYPE_ACCESS);
+		if (acl) {
+			int error = posix_acl_permission(inode, acl, mask);
 			posix_acl_release(acl);
-			if (EXT3_I(inode)->i_acl == EXT3_ACL_NOT_CACHED)
-				return -EIO;
-		}
-		if (EXT3_I(inode)->i_acl) {
-			int error = posix_acl_permission(inode,
-				EXT3_I(inode)->i_acl, mask);
 			if (error == -EACCES)
 				goto check_capabilities;
 			return error;
@@ -304,26 +335,6 @@
 	    (S_ISDIR(inode->i_mode) && !(mask & MAY_WRITE))))
 		return 0;
 	return -EACCES;
-}
-
-/*
- * Inode operation permission().
- *
- * inode->i_sem: up
- */
-int
-ext3_permission(struct inode *inode, int mask)
-{
-	return __ext3_permission(inode, mask, 1);
-}
-
-/*
- * Used internally if i_sem is already down.
- */
-int
-ext3_permission_locked(struct inode *inode, int mask)
-{
-	return __ext3_permission(inode, mask, 0);
 }
 
 /*
diff -Nru a/fs/ext3/acl.h b/fs/ext3/acl.h
--- a/fs/ext3/acl.h	Wed Oct 30 23:32:57 2002
+++ b/fs/ext3/acl.h	Fri Jul  4 22:31:27 2003
@@ -59,8 +59,7 @@
 #define EXT3_ACL_NOT_CACHED ((void *)-1)
 
 /* acl.c */
-extern int ext3_permission (struct inode *, int);
-extern int ext3_permission_locked (struct inode *, int);
+extern int ext3_permission (struct inode *, int, struct nameidata *);
 extern int ext3_acl_chmod (struct inode *);
 extern int ext3_init_acl (handle_t *, struct inode *, struct inode *);
 
diff -Nru a/fs/ext3/inode.c b/fs/ext3/inode.c
--- a/fs/ext3/inode.c	Wed Jun 25 16:30:56 2003
+++ b/fs/ext3/inode.c	Thu Jul  3 19:20:48 2003
@@ -2290,68 +2290,72 @@
 	ext3_journal_stop(handle);
 }
 
-/* 
- * ext3_get_inode_loc returns with an extra refcount against the
- * inode's underlying buffer_head on success. 
- */
-
-int ext3_get_inode_loc (struct inode *inode, struct ext3_iloc *iloc)
+static unsigned long ext3_get_inode_block(struct super_block *sb,
+		unsigned long ino, struct ext3_iloc *iloc)
 {
-	struct buffer_head *bh = 0;
-	unsigned long block;
-	unsigned long block_group;
-	unsigned long group_desc;
-	unsigned long desc;
-	unsigned long offset;
+	unsigned long desc, group_desc, block_group;
+	unsigned long offset, block;
+	struct buffer_head *bh;
 	struct ext3_group_desc * gdp;
 
-	if ((inode->i_ino != EXT3_ROOT_INO &&
-		inode->i_ino != EXT3_JOURNAL_INO &&
-		inode->i_ino < EXT3_FIRST_INO(inode->i_sb)) ||
-		inode->i_ino > le32_to_cpu(
-			EXT3_SB(inode->i_sb)->s_es->s_inodes_count)) {
-		ext3_error (inode->i_sb, "ext3_get_inode_loc",
-			    "bad inode number: %lu", inode->i_ino);
-		goto bad_inode;
-	}
-	block_group = (inode->i_ino - 1) / EXT3_INODES_PER_GROUP(inode->i_sb);
-	if (block_group >= EXT3_SB(inode->i_sb)->s_groups_count) {
-		ext3_error (inode->i_sb, "ext3_get_inode_loc",
+	if ((ino != EXT3_ROOT_INO &&
+		ino != EXT3_JOURNAL_INO &&
+		ino < EXT3_FIRST_INO(sb)) ||
+		ino > le32_to_cpu(
+			EXT3_SB(sb)->s_es->s_inodes_count)) {
+		ext3_error (sb, "ext3_get_inode_block",
+			    "bad inode number: %lu", ino);
+		return 0;
+	}
+	block_group = (ino - 1) / EXT3_INODES_PER_GROUP(sb);
+	if (block_group >= EXT3_SB(sb)->s_groups_count) {
+		ext3_error (sb, "ext3_get_inode_block",
 			    "group >= groups count");
-		goto bad_inode;
+		return 0;
 	}
-	group_desc = block_group >> EXT3_DESC_PER_BLOCK_BITS(inode->i_sb);
-	desc = block_group & (EXT3_DESC_PER_BLOCK(inode->i_sb) - 1);
-	bh = EXT3_SB(inode->i_sb)->s_group_desc[group_desc];
+	group_desc = block_group >> EXT3_DESC_PER_BLOCK_BITS(sb);
+	desc = block_group & (EXT3_DESC_PER_BLOCK(sb) - 1);
+	bh = EXT3_SB(sb)->s_group_desc[group_desc];
 	if (!bh) {
-		ext3_error (inode->i_sb, "ext3_get_inode_loc",
+		ext3_error (sb, "ext3_get_inode_block",
 			    "Descriptor not loaded");
-		goto bad_inode;
+		return 0;
 	}
 
 	gdp = (struct ext3_group_desc *) bh->b_data;
 	/*
 	 * Figure out the offset within the block group inode table
 	 */
-	offset = ((inode->i_ino - 1) % EXT3_INODES_PER_GROUP(inode->i_sb)) *
-		EXT3_INODE_SIZE(inode->i_sb);
+	offset = ((ino - 1) % EXT3_INODES_PER_GROUP(sb)) *
+		EXT3_INODE_SIZE(sb);
 	block = le32_to_cpu(gdp[desc].bg_inode_table) +
-		(offset >> EXT3_BLOCK_SIZE_BITS(inode->i_sb));
-	if (!(bh = sb_bread(inode->i_sb, block))) {
-		ext3_error (inode->i_sb, "ext3_get_inode_loc",
-			    "unable to read inode block - "
-			    "inode=%lu, block=%lu", inode->i_ino, block);
-		goto bad_inode;
-	}
-	offset &= (EXT3_BLOCK_SIZE(inode->i_sb) - 1);
+		(offset >> EXT3_BLOCK_SIZE_BITS(sb));
 
-	iloc->bh = bh;
-	iloc->raw_inode = (struct ext3_inode *) (bh->b_data + offset);
 	iloc->block_group = block_group;
+	iloc->offset = offset & (EXT3_BLOCK_SIZE(sb) - 1);
+	return block;
+}
 
-	return 0;
+/* 
+ * ext3_get_inode_loc returns with an extra refcount against the
+ * inode's underlying buffer_head on success. 
+ */
+
+int ext3_get_inode_loc (struct inode *inode, struct ext3_iloc *iloc)
+{
+	unsigned long block;
 
- bad_inode:
+	block = ext3_get_inode_block(inode->i_sb, inode->i_ino, iloc);
+	if (block) {
+		struct buffer_head *bh = sb_bread(inode->i_sb, block);
+		if (bh) {
+			iloc->bh = bh;
+			return 0;
+		}
+		ext3_error (inode->i_sb, "ext3_get_inode_loc",
+			    "unable to read inode block - "
+			    "inode=%lu, block=%lu", inode->i_ino, block);
+	}
 	return -EIO;
 }
 
@@ -2388,7 +2392,7 @@
 	if (ext3_get_inode_loc(inode, &iloc))
 		goto bad_inode;
 	bh = iloc.bh;
-	raw_inode = iloc.raw_inode;
+	raw_inode = ext3_raw_inode(&iloc);
 	inode->i_mode = le16_to_cpu(raw_inode->i_mode);
 	inode->i_uid = (uid_t)le16_to_cpu(raw_inode->i_uid_low);
 	inode->i_gid = (gid_t)le16_to_cpu(raw_inode->i_gid_low);
@@ -2454,11 +2458,9 @@
 	 * even on big-endian machines: we do NOT byteswap the block numbers!
 	 */
 	for (block = 0; block < EXT3_N_BLOCKS; block++)
-		ei->i_data[block] = iloc.raw_inode->i_block[block];
+		ei->i_data[block] = raw_inode->i_block[block];
 	INIT_LIST_HEAD(&ei->i_orphan);
 
-	brelse (iloc.bh);
-
 	if (S_ISREG(inode->i_mode)) {
 		inode->i_op = &ext3_file_inode_operations;
 		inode->i_fop = &ext3_file_operations;
@@ -2476,8 +2478,9 @@
 	} else {
 		inode->i_op = &ext3_special_inode_operations;
 		init_special_inode(inode, inode->i_mode,
-				   le32_to_cpu(iloc.raw_inode->i_block[0]));
+				   le32_to_cpu(raw_inode->i_block[0]));
 	}
+	brelse (iloc.bh);
 	ext3_set_inode_flags(inode);
 	return;
 
@@ -2497,7 +2500,7 @@
 				struct inode *inode, 
 				struct ext3_iloc *iloc)
 {
-	struct ext3_inode *raw_inode = iloc->raw_inode;
+	struct ext3_inode *raw_inode = ext3_raw_inode(iloc);
 	struct ext3_inode_info *ei = EXT3_I(inode);
 	struct buffer_head *bh = iloc->bh;
 	int err = 0, rc, block;
diff -Nru a/fs/ext3/namei.c b/fs/ext3/namei.c
--- a/fs/ext3/namei.c	Wed Jun 25 16:30:59 2003
+++ b/fs/ext3/namei.c	Sun Jun 29 23:49:04 2003
@@ -970,7 +970,7 @@
 }
 #endif
 
-static struct dentry *ext3_lookup(struct inode * dir, struct dentry *dentry)
+static struct dentry *ext3_lookup(struct inode * dir, struct dentry *dentry, struct nameidata *nd)
 {
 	struct inode * inode;
 	struct ext3_dir_entry_2 * de;
@@ -1623,7 +1623,8 @@
  * If the create succeeds, we fill in the inode information
  * with d_instantiate(). 
  */
-static int ext3_create (struct inode * dir, struct dentry * dentry, int mode)
+static int ext3_create (struct inode * dir, struct dentry * dentry, int mode,
+		struct nameidata *nd)
 {
 	handle_t *handle; 
 	struct inode * inode;
diff -Nru a/fs/ext3/super.c b/fs/ext3/super.c
--- a/fs/ext3/super.c	Fri Jun 27 23:20:44 2003
+++ b/fs/ext3/super.c	Fri Jul  4 22:31:27 2003
@@ -519,6 +519,9 @@
 	if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) ==
 	    SLAB_CTOR_CONSTRUCTOR) {
 		INIT_LIST_HEAD(&ei->i_orphan);
+#ifdef CONFIG_EXT3_FS_XATTR
+		init_rwsem(&ei->xattr_sem);
+#endif
 		init_rwsem(&ei->truncate_sem);
 		inode_init_once(&ei->vfs_inode);
 	}
diff -Nru a/fs/ext3/xattr.c b/fs/ext3/xattr.c
--- a/fs/ext3/xattr.c	Fri Jun 20 13:16:31 2003
+++ b/fs/ext3/xattr.c	Fri Jul  4 22:31:27 2003
@@ -1,7 +1,7 @@
 /*
  * linux/fs/ext3/xattr.c
  *
- * Copyright (C) 2001 by Andreas Gruenbacher, <a.gruenbacher@computer.org>
+ * Copyright (C) 2001-2003 Andreas Gruenbacher, <agruen@suse.de>
  *
  * Fix by Harrison Xing <harrison@mountainviewdata.com>.
  * Ext3 code with a lot of help from Eric Jarman <ejarman@acm.org>.
@@ -43,13 +43,12 @@
  *
  * Locking strategy
  * ----------------
- * The VFS holdsinode->i_sem semaphore when any of the xattr inode
- * operations are called, so we are guaranteed that only one
- * processes accesses extended attributes of an inode at any time.
- *
- * For writing we also grab the ext3_xattr_sem semaphore. This ensures that
- * only a single process is modifying an extended attribute block, even
- * if the block is shared among inodes.
+ * EXT3_I(inode)->i_file_acl is protected by EXT3_I(inode)->xattr_sem.
+ * EA blocks are only changed if they are exclusive to an inode, so
+ * holding xattr_sem also means that nothing but the EA block's reference
+ * count will change. Multiple writers to an EA block are synchronized
+ * by the bh lock. No more than a single bh lock is held at any time
+ * to avoid deadlocks.
  */
 
 #include <linux/init.h>
@@ -59,12 +58,10 @@
 #include <linux/ext3_fs.h>
 #include <linux/mbcache.h>
 #include <linux/quotaops.h>
-#include <asm/semaphore.h>
+#include <linux/rwsem.h>
 #include "xattr.h"
 #include "acl.h"
 
-#define EXT3_EA_USER "user."
-
 #define HDR(bh) ((struct ext3_xattr_header *)((bh)->b_data))
 #define ENTRY(ptr) ((struct ext3_xattr_entry *)(ptr))
 #define FIRST_ENTRY(bh) ENTRY(HDR(bh)+1)
@@ -79,8 +76,9 @@
 	} while (0)
 # define ea_bdebug(bh, f...) do { \
 		char b[BDEVNAME_SIZE]; \
-		printk(KERN_DEBUG "block %s:%ld: ", \
-			bdevname(bh->b_bdev, b), bh->b_blocknr); \
+		printk(KERN_DEBUG "block %s:%lu: ", \
+			bdevname(bh->b_bdev, b), \
+			(unsigned long) bh->b_blocknr); \
 		printk(f); \
 		printk("\n"); \
 	} while (0)
@@ -94,22 +92,14 @@
 				  struct ext3_xattr_header *);
 
 static int ext3_xattr_cache_insert(struct buffer_head *);
-static struct buffer_head *ext3_xattr_cache_find(struct inode *,
-						 struct ext3_xattr_header *);
+static struct buffer_head *ext3_xattr_cache_find(handle_t *, struct inode *,
+						 struct ext3_xattr_header *,
+						 int *);
 static void ext3_xattr_cache_remove(struct buffer_head *);
 static void ext3_xattr_rehash(struct ext3_xattr_header *,
 			      struct ext3_xattr_entry *);
 
 static struct mb_cache *ext3_xattr_cache;
-
-/*
- * If a file system does not share extended attributes among inodes,
- * we should not need the ext3_xattr_sem semaphore. However, the
- * filesystem may still contain shared blocks, so we always take
- * the lock.
- */
-
-static DECLARE_MUTEX(ext3_xattr_sem);
 static struct ext3_xattr_handler *ext3_xattr_handlers[EXT3_XATTR_INDEX_MAX];
 static rwlock_t ext3_handler_lock = RW_LOCK_UNLOCKED;
 
@@ -192,7 +182,7 @@
 /*
  * Inode operation getxattr()
  *
- * dentry->d_inode->i_sem down
+ * dentry->d_inode->i_sem: don't care
  */
 ssize_t
 ext3_getxattr(struct dentry *dentry, const char *name,
@@ -210,7 +200,7 @@
 /*
  * Inode operation listxattr()
  *
- * dentry->d_inode->i_sem down
+ * dentry->d_inode->i_sem: don't care
  */
 ssize_t
 ext3_listxattr(struct dentry *dentry, char *buffer, size_t size)
@@ -221,7 +211,7 @@
 /*
  * Inode operation setxattr()
  *
- * dentry->d_inode->i_sem down
+ * dentry->d_inode->i_sem: down
  */
 int
 ext3_setxattr(struct dentry *dentry, const char *name,
@@ -241,7 +231,7 @@
 /*
  * Inode operation removexattr()
  *
- * dentry->d_inode->i_sem down
+ * dentry->d_inode->i_sem: down
  */
 int
 ext3_removexattr(struct dentry *dentry, const char *name)
@@ -271,21 +261,24 @@
 {
 	struct buffer_head *bh = NULL;
 	struct ext3_xattr_entry *entry;
-	unsigned int size;
+	size_t name_len, size;
 	char *end;
-	int name_len, error;
+	int error;
 
 	ea_idebug(inode, "name=%d.%s, buffer=%p, buffer_size=%ld",
 		  name_index, name, buffer, (long)buffer_size);
 
 	if (name == NULL)
 		return -EINVAL;
+	down_read(&EXT3_I(inode)->xattr_sem);
+	error = -ENODATA;
 	if (!EXT3_I(inode)->i_file_acl)
-		return -ENODATA;
+		goto cleanup;
 	ea_idebug(inode, "reading block %d", EXT3_I(inode)->i_file_acl);
 	bh = sb_bread(inode->i_sb, EXT3_I(inode)->i_file_acl);
+	error = -EIO;
 	if (!bh)
-		return -EIO;
+		goto cleanup;
 	ea_bdebug(bh, "b_count=%d, refcount=%d",
 		atomic_read(&(bh->b_count)), le32_to_cpu(HDR(bh)->h_refcount));
 	end = bh->b_data + bh->b_size;
@@ -350,6 +343,7 @@
 
 cleanup:
 	brelse(bh);
+	up_read(&EXT3_I(inode)->xattr_sem);
 
 	return error;
 }
@@ -369,19 +363,22 @@
 {
 	struct buffer_head *bh = NULL;
 	struct ext3_xattr_entry *entry;
-	unsigned int size = 0;
+	size_t size = 0;
 	char *buf, *end;
 	int error;
 
 	ea_idebug(inode, "buffer=%p, buffer_size=%ld",
 		  buffer, (long)buffer_size);
 
+	down_read(&EXT3_I(inode)->xattr_sem);
+	error = 0;
 	if (!EXT3_I(inode)->i_file_acl)
-		return 0;
+		goto cleanup;
 	ea_idebug(inode, "reading block %d", EXT3_I(inode)->i_file_acl);
 	bh = sb_bread(inode->i_sb, EXT3_I(inode)->i_file_acl);
+	error = -EIO;
 	if (!bh)
-		return -EIO;
+		goto cleanup;
 	ea_bdebug(bh, "b_count=%d, refcount=%d",
 		atomic_read(&(bh->b_count)), le32_to_cpu(HDR(bh)->h_refcount));
 	end = bh->b_data + bh->b_size;
@@ -434,6 +431,7 @@
 
 cleanup:
 	brelse(bh);
+	up_read(&EXT3_I(inode)->xattr_sem);
 
 	return error;
 }
@@ -449,11 +447,12 @@
 		return;
 
 	lock_super(sb);
-	ext3_journal_get_write_access(handle, EXT3_SB(sb)->s_sbh);
-	EXT3_SB(sb)->s_es->s_feature_compat |=
-		cpu_to_le32(EXT3_FEATURE_COMPAT_EXT_ATTR);
-	sb->s_dirt = 1;
-	ext3_journal_dirty_metadata(handle, EXT3_SB(sb)->s_sbh);
+	if (ext3_journal_get_write_access(handle, EXT3_SB(sb)->s_sbh) == 0) {
+		EXT3_SB(sb)->s_es->s_feature_compat |=
+			cpu_to_le32(EXT3_FEATURE_COMPAT_EXT_ATTR);
+		sb->s_dirt = 1;
+		ext3_journal_dirty_metadata(handle, EXT3_SB(sb)->s_sbh);
+	}
 	unlock_super(sb);
 }
 
@@ -478,8 +477,8 @@
 	struct buffer_head *bh = NULL;
 	struct ext3_xattr_header *header = NULL;
 	struct ext3_xattr_entry *here, *last;
-	unsigned int name_len;
-	int min_offs = sb->s_blocksize, not_found = 1, free, error;
+	size_t name_len, free, min_offs = sb->s_blocksize;
+	int not_found = 1, error;
 	char *end;
 
 	/*
@@ -508,8 +507,7 @@
 	name_len = strlen(name);
 	if (name_len > 255 || value_len > sb->s_blocksize)
 		return -ERANGE;
-	down(&ext3_xattr_sem);
-
+	down_write(&EXT3_I(inode)->xattr_sem);
 	if (EXT3_I(inode)->i_file_acl) {
 		/* The inode already has an extended attribute block. */
 		bh = sb_bread(sb, EXT3_I(inode)->i_file_acl);
@@ -536,7 +534,7 @@
 			if ((char *)next >= end)
 				goto bad_block;
 			if (!here->e_value_block && here->e_value_size) {
-				int offs = le16_to_cpu(here->e_value_offs);
+				size_t offs = le16_to_cpu(here->e_value_offs);
 				if (offs < min_offs)
 					min_offs = offs;
 			}
@@ -556,7 +554,7 @@
 			if ((char *)next >= end)
 				goto bad_block;
 			if (!last->e_value_block && last->e_value_size) {
-				int offs = le16_to_cpu(last->e_value_offs);
+				size_t offs = le16_to_cpu(last->e_value_offs);
 				if (offs < min_offs)
 					min_offs = offs;
 			}
@@ -580,39 +578,50 @@
 		error = 0;
 		if (value == NULL)
 			goto cleanup;
-		else
-			free -= EXT3_XATTR_LEN(name_len);
 	} else {
 		/* Request to create an existing attribute? */
 		error = -EEXIST;
 		if (flags & XATTR_CREATE)
 			goto cleanup;
 		if (!here->e_value_block && here->e_value_size) {
-			unsigned int size = le32_to_cpu(here->e_value_size);
+			size_t size = le32_to_cpu(here->e_value_size);
 
 			if (le16_to_cpu(here->e_value_offs) + size > 
 			    sb->s_blocksize || size > sb->s_blocksize)
 				goto bad_block;
 			free += EXT3_XATTR_SIZE(size);
 		}
+		free += EXT3_XATTR_LEN(name_len);
 	}
-	free -= EXT3_XATTR_SIZE(value_len);
 	error = -ENOSPC;
-	if (free < 0)
+	if (free < EXT3_XATTR_LEN(name_len) + EXT3_XATTR_SIZE(value_len))
 		goto cleanup;
 
 	/* Here we know that we can set the new attribute. */
 
 	if (header) {
+		int credits = 0;
+
+		/* assert(header == HDR(bh)); */
+		if (header->h_refcount != cpu_to_le32(1))
+			goto skip_get_write_access;
+		/* ext3_journal_get_write_access() requires an unlocked bh,
+		   which complicates things here. */
+		error = ext3_journal_get_write_access_credits(handle, bh,
+							      &credits);
+		if (error)
+			goto cleanup;
+		lock_buffer(bh);
 		if (header->h_refcount == cpu_to_le32(1)) {
 			ea_bdebug(bh, "modifying in-place");
 			ext3_xattr_cache_remove(bh);
-			error = ext3_journal_get_write_access(handle, bh);
-			if (error)
-				goto cleanup;
+			/* keep the buffer locked while modifying it. */
 		} else {
 			int offset;
 
+			unlock_buffer(bh);
+			journal_release_buffer(handle, bh, credits);
+		skip_get_write_access:
 			ea_bdebug(bh, "cloning");
 			header = kmalloc(bh->b_size, GFP_KERNEL);
 			error = -ENOMEM;
@@ -637,23 +646,36 @@
 		last = here = ENTRY(header+1);
 	}
 
+	/* Iff we are modifying the block in-place, bh is locked here. */
+
 	if (not_found) {
 		/* Insert the new name. */
-		int size = EXT3_XATTR_LEN(name_len);
-		int rest = (char *)last - (char *)here;
+		size_t size = EXT3_XATTR_LEN(name_len);
+		size_t rest = (char *)last - (char *)here;
 		memmove((char *)here + size, here, rest);
 		memset(here, 0, size);
 		here->e_name_index = name_index;
 		here->e_name_len = name_len;
 		memcpy(here->e_name, name, name_len);
 	} else {
-		/* Remove the old value. */
 		if (!here->e_value_block && here->e_value_size) {
 			char *first_val = (char *)header + min_offs;
-			int offs = le16_to_cpu(here->e_value_offs);
+			size_t offs = le16_to_cpu(here->e_value_offs);
 			char *val = (char *)header + offs;
 			size_t size = EXT3_XATTR_SIZE(
 				le32_to_cpu(here->e_value_size));
+
+			if (size == EXT3_XATTR_SIZE(value_len)) {
+				/* The old and the new value have the same
+				   size. Just replace. */
+				here->e_value_size = cpu_to_le32(value_len);
+				memset(val + size - EXT3_XATTR_PAD, 0,
+				       EXT3_XATTR_PAD); /* Clear pad bytes. */
+				memcpy(val, value, value_len);
+				goto skip_replace;
+			}
+
+			/* Remove the old value. */
 			memmove(first_val + size, first_val, val - first_val);
 			memset(first_val, 0, size);
 			here->e_value_offs = 0;
@@ -662,7 +684,7 @@
 			/* Adjust all value offsets. */
 			last = ENTRY(header+1);
 			while (!IS_LAST_ENTRY(last)) {
-				int o = le16_to_cpu(last->e_value_offs);
+				size_t o = le16_to_cpu(last->e_value_offs);
 				if (!last->e_value_block && o < offs)
 					last->e_value_offs =
 						cpu_to_le16(o + size);
@@ -670,20 +692,12 @@
 			}
 		}
 		if (value == NULL) {
-			/* Remove this attribute. */
-			if (EXT3_XATTR_NEXT(ENTRY(header+1)) == last) {
-				/* This block is now empty. */
-				error = ext3_xattr_set_handle2(handle, inode,
-							       bh, NULL);
-				goto cleanup;
-			} else {
-				/* Remove the old name. */
-				int size = EXT3_XATTR_LEN(name_len);
-				last = ENTRY((char *)last - size);
-				memmove(here, (char*)here + size,
-					(char*)last - (char*)here);
-				memset(last, 0, size);
-			}
+			/* Remove the old name. */
+			size_t size = EXT3_XATTR_LEN(name_len);
+			last = ENTRY((char *)last - size);
+			memmove(here, (char*)here + size,
+				(char*)last - (char*)here);
+			memset(last, 0, size);
 		}
 	}
 
@@ -700,15 +714,25 @@
 			memcpy(val, value, value_len);
 		}
 	}
-	ext3_xattr_rehash(header, here);
 
-	error = ext3_xattr_set_handle2(handle, inode, bh, header);
+skip_replace:
+	if (IS_LAST_ENTRY(ENTRY(header+1))) {
+		/* This block is now empty. */
+		if (bh && header == HDR(bh))
+			unlock_buffer(bh);  /* we were modifying in-place. */
+		error = ext3_xattr_set_handle2(handle, inode, bh, NULL);
+	} else {
+		ext3_xattr_rehash(header, here);
+		if (bh && header == HDR(bh))
+			unlock_buffer(bh);  /* we were modifying in-place. */
+		error = ext3_xattr_set_handle2(handle, inode, bh, header);
+	}
 
 cleanup:
 	brelse(bh);
 	if (!(bh && header == HDR(bh)))
 		kfree(header);
-	up(&ext3_xattr_sem);
+	up_write(&EXT3_I(inode)->xattr_sem);
 
 	return error;
 }
@@ -723,33 +747,34 @@
 {
 	struct super_block *sb = inode->i_sb;
 	struct buffer_head *new_bh = NULL;
-	int error;
+	int credits = 0, error;
 
 	if (header) {
-		new_bh = ext3_xattr_cache_find(inode, header);
+		new_bh = ext3_xattr_cache_find(handle, inode, header, &credits);
 		if (new_bh) {
 			/*
-			 * We found an identical block in the cache.
-			 * The old block will be released after updating
-			 * the inode.
+			 * We found an identical block in the cache. The
+			 * block returned is locked. The old block will
+			 * be released after updating the inode.
 			 */
-			ea_bdebug(new_bh, "%s block %ld",
+			ea_bdebug(new_bh, "%s block %lu",
 				(old_bh == new_bh) ? "keeping" : "reusing",
-				new_bh->b_blocknr);
+				(unsigned long) new_bh->b_blocknr);
 
 			error = -EDQUOT;
-			if (DQUOT_ALLOC_BLOCK(inode, 1))
-				goto cleanup;
-
-			error = ext3_journal_get_write_access(handle, new_bh);
-			if (error)
+			if (DQUOT_ALLOC_BLOCK(inode, 1)) {
+				unlock_buffer(new_bh);
+				journal_release_buffer(handle, new_bh, credits);
 				goto cleanup;
+			}
 			HDR(new_bh)->h_refcount = cpu_to_le32(
 				le32_to_cpu(HDR(new_bh)->h_refcount) + 1);
 			ea_bdebug(new_bh, "refcount now=%d",
 				le32_to_cpu(HDR(new_bh)->h_refcount));
+			unlock_buffer(new_bh);
 		} else if (old_bh && header == HDR(old_bh)) {
-			/* Keep this block. */
+			/* Keep this block. No need to lock the block as we
+			 * don't need to change the reference count. */
 			new_bh = old_bh;
 			get_bh(new_bh);
 			ext3_xattr_cache_insert(new_bh);
@@ -759,7 +784,7 @@
 					EXT3_SB(sb)->s_es->s_first_data_block) +
 				EXT3_I(inode)->i_block_group *
 				EXT3_BLOCKS_PER_GROUP(sb);
-			int block  = ext3_new_block(handle,
+			int block = ext3_new_block(handle,
 				inode, goal, 0, 0, &error);
 			if (error)
 				goto cleanup;
@@ -800,15 +825,14 @@
 	error = 0;
 	if (old_bh && old_bh != new_bh) {
 		/*
-		 * If there was an old block, and we are not still using it,
-		 * we now release the old block.
+		 * If there was an old block, and we are no longer using it,
+		 * release the old block.
 		*/
-		unsigned int refcount = le32_to_cpu(HDR(old_bh)->h_refcount);
-
 		error = ext3_journal_get_write_access(handle, old_bh);
 		if (error)
 			goto cleanup;
-		if (refcount == 1) {
+		lock_buffer(old_bh);
+		if (HDR(old_bh)->h_refcount == cpu_to_le32(1)) {
 			/* Free the old block. */
 			ea_bdebug(old_bh, "freeing");
 			ext3_free_blocks(handle, inode, old_bh->b_blocknr, 1);
@@ -820,12 +844,14 @@
 			ext3_forget(handle, 1, inode, old_bh,old_bh->b_blocknr);
 		} else {
 			/* Decrement the refcount only. */
-			refcount--;
-			HDR(old_bh)->h_refcount = cpu_to_le32(refcount);
+			HDR(old_bh)->h_refcount = cpu_to_le32(
+				le32_to_cpu(HDR(old_bh)->h_refcount) - 1);
 			DQUOT_FREE_BLOCK(inode, 1);
 			ext3_journal_dirty_metadata(handle, old_bh);
-			ea_bdebug(old_bh, "refcount now=%d", refcount);
+			ea_bdebug(old_bh, "refcount now=%d",
+				le32_to_cpu(HDR(old_bh)->h_refcount));
 		}
+		unlock_buffer(old_bh);
 	}
 
 cleanup:
@@ -869,12 +895,11 @@
 void
 ext3_xattr_delete_inode(handle_t *handle, struct inode *inode)
 {
-	struct buffer_head *bh;
+	struct buffer_head *bh = NULL;
 
+	down_write(&EXT3_I(inode)->xattr_sem);
 	if (!EXT3_I(inode)->i_file_acl)
-		return;
-	down(&ext3_xattr_sem);
-
+		goto cleanup;
 	bh = sb_bread(inode->i_sb, EXT3_I(inode)->i_file_acl);
 	if (!bh) {
 		ext3_error(inode->i_sb, "ext3_xattr_delete_inode",
@@ -882,7 +907,6 @@
 			EXT3_I(inode)->i_file_acl);
 		goto cleanup;
 	}
-	ea_bdebug(bh, "b_count=%d", atomic_read(&(bh->b_count)));
 	if (HDR(bh)->h_magic != cpu_to_le32(EXT3_XATTR_MAGIC) ||
 	    HDR(bh)->h_blocks != cpu_to_le32(1)) {
 		ext3_error(inode->i_sb, "ext3_xattr_delete_inode",
@@ -890,13 +914,14 @@
 			EXT3_I(inode)->i_file_acl);
 		goto cleanup;
 	}
-	ext3_journal_get_write_access(handle, bh);
-	ea_bdebug(bh, "refcount now=%d", le32_to_cpu(HDR(bh)->h_refcount) - 1);
+	if (ext3_journal_get_write_access(handle, bh) != 0)
+		goto cleanup;
+	lock_buffer(bh);
 	if (HDR(bh)->h_refcount == cpu_to_le32(1)) {
 		ext3_xattr_cache_remove(bh);
 		ext3_free_blocks(handle, inode, EXT3_I(inode)->i_file_acl, 1);
+		get_bh(bh);
 		ext3_forget(handle, 1, inode, bh, EXT3_I(inode)->i_file_acl);
-		bh = NULL;
 	} else {
 		HDR(bh)->h_refcount = cpu_to_le32(
 			le32_to_cpu(HDR(bh)->h_refcount) - 1);
@@ -905,11 +930,13 @@
 			handle->h_sync = 1;
 		DQUOT_FREE_BLOCK(inode, 1);
 	}
+	ea_bdebug(bh, "refcount now=%d", le32_to_cpu(HDR(bh)->h_refcount) - 1);
+	unlock_buffer(bh);
 	EXT3_I(inode)->i_file_acl = 0;
 
 cleanup:
 	brelse(bh);
-	up(&ext3_xattr_sem);
+	up_write(&EXT3_I(inode)->xattr_sem);
 }
 
 /*
@@ -1005,7 +1032,8 @@
  * not found or an error occurred.
  */
 static struct buffer_head *
-ext3_xattr_cache_find(struct inode *inode, struct ext3_xattr_header *header)
+ext3_xattr_cache_find(handle_t *handle, struct inode *inode,
+		      struct ext3_xattr_header *header, int *credits)
 {
 	__u32 hash = le32_to_cpu(header->h_hash);
 	struct mb_cache_entry *ce;
@@ -1013,7 +1041,8 @@
 	if (!header->h_hash)
 		return NULL;  /* never share */
 	ea_idebug(inode, "looking for cached blocks [%x]", (int)hash);
-	ce = mb_cache_entry_find_first(ext3_xattr_cache, 0, inode->i_bdev, hash);
+	ce = mb_cache_entry_find_first(ext3_xattr_cache, 0,
+				       inode->i_sb->s_bdev, hash);
 	while (ce) {
 		struct buffer_head *bh = sb_bread(inode->i_sb, ce->e_block);
 
@@ -1021,19 +1050,29 @@
 			ext3_error(inode->i_sb, "ext3_xattr_cache_find",
 				"inode %ld: block %ld read error",
 				inode->i_ino, (unsigned long) ce->e_block);
-		} else if (le32_to_cpu(HDR(bh)->h_refcount) >
-			   EXT3_XATTR_REFCOUNT_MAX) {
-			ea_idebug(inode, "block %ld refcount %d>%d",
-				  (unsigned long) ce->e_block,
-				  le32_to_cpu(HDR(bh)->h_refcount),
-				  EXT3_XATTR_REFCOUNT_MAX);
-		} else if (!ext3_xattr_cmp(header, HDR(bh))) {
-			ea_bdebug(bh, "b_count=%d",atomic_read(&(bh->b_count)));
-			mb_cache_entry_release(ce);
-			return bh;
+		} else {
+			/* ext3_journal_get_write_access() requires an unlocked
+			 * bh, which complicates things here. */
+			if (ext3_journal_get_write_access_credits(handle, bh,
+								  credits) != 0)
+				return NULL;
+			lock_buffer(bh);
+			if (le32_to_cpu(HDR(bh)->h_refcount) >
+				   EXT3_XATTR_REFCOUNT_MAX) {
+				ea_idebug(inode, "block %ld refcount %d>%d",
+					  (unsigned long) ce->e_block,
+					  le32_to_cpu(HDR(bh)->h_refcount),
+					  EXT3_XATTR_REFCOUNT_MAX);
+			} else if (!ext3_xattr_cmp(header, HDR(bh))) {
+				mb_cache_entry_release(ce);
+				/* buffer will be unlocked by caller */
+				return bh;
+			}
+			unlock_buffer(bh);
+			journal_release_buffer(handle, bh, *credits);
+			brelse(bh);
 		}
-		brelse(bh);
-		ce = mb_cache_entry_find_next(ce, 0, inode->i_bdev, hash);
+		ce = mb_cache_entry_find_next(ce, 0, inode->i_sb->s_bdev, hash);
 	}
 	return NULL;
 }
diff -Nru a/fs/ext3/xattr_user.c b/fs/ext3/xattr_user.c
--- a/fs/ext3/xattr_user.c	Tue Feb 25 08:21:08 2003
+++ b/fs/ext3/xattr_user.c	Fri Jul  4 22:31:27 2003
@@ -13,10 +13,6 @@
 #include <linux/ext3_fs.h>
 #include "xattr.h"
 
-#ifdef CONFIG_EXT3_FS_POSIX_ACL
-# include "acl.h"
-#endif
-
 #define XATTR_USER_PREFIX "user."
 
 static size_t
@@ -46,11 +42,7 @@
 		return -EINVAL;
 	if (!test_opt(inode->i_sb, XATTR_USER))
 		return -EOPNOTSUPP;
-#ifdef CONFIG_EXT3_FS_POSIX_ACL
-	error = ext3_permission_locked(inode, MAY_READ);
-#else
-	error = permission(inode, MAY_READ);
-#endif
+	error = permission(inode, MAY_READ, NULL);
 	if (error)
 		return error;
 
@@ -70,11 +62,7 @@
 	if ( !S_ISREG(inode->i_mode) &&
 	    (!S_ISDIR(inode->i_mode) || inode->i_mode & S_ISVTX))
 		return -EPERM;
-#ifdef CONFIG_EXT3_FS_POSIX_ACL
-	error = ext3_permission_locked(inode, MAY_WRITE);
-#else
-	error = permission(inode, MAY_WRITE);
-#endif
+	error = permission(inode, MAY_WRITE, NULL);
 	if (error)
 		return error;
 
diff -Nru a/fs/freevxfs/vxfs_lookup.c b/fs/freevxfs/vxfs_lookup.c
--- a/fs/freevxfs/vxfs_lookup.c	Wed Apr 24 09:20:09 2002
+++ b/fs/freevxfs/vxfs_lookup.c	Thu Jul  3 06:36:44 2003
@@ -51,7 +51,7 @@
 #define VXFS_BLOCK_PER_PAGE(sbp)  ((PAGE_CACHE_SIZE / (sbp)->s_blocksize))
 
 
-static struct dentry *	vxfs_lookup(struct inode *, struct dentry *);
+static struct dentry *	vxfs_lookup(struct inode *, struct dentry *, struct nameidata *);
 static int		vxfs_readdir(struct file *, void *, filldir_t);
 
 struct inode_operations vxfs_dir_inode_ops = {
@@ -193,6 +193,7 @@
  * vxfs_lookup - lookup pathname component
  * @dip:	dir in which we lookup
  * @dp:		dentry we lookup
+ * @nd:		lookup nameidata
  *
  * Description:
  *   vxfs_lookup tries to lookup the pathname component described
@@ -203,7 +204,7 @@
  *   in the return pointer.
  */
 static struct dentry *
-vxfs_lookup(struct inode *dip, struct dentry *dp)
+vxfs_lookup(struct inode *dip, struct dentry *dp, struct nameidata *nd)
 {
 	struct inode		*ip = NULL;
 	ino_t			ino;
diff -Nru a/fs/fs-writeback.c b/fs/fs-writeback.c
--- a/fs/fs-writeback.c	Fri Jun 20 13:16:22 2003
+++ b/fs/fs-writeback.c	Fri Jul  4 23:52:37 2003
@@ -516,6 +516,7 @@
 	int need_write_inode_now = 0;
 	int err2;
 
+	current->flags |= PF_SYNCWRITE;
 	if (what & OSYNC_DATA)
 		err = filemap_fdatawrite(inode->i_mapping);
 	if (what & (OSYNC_METADATA|OSYNC_DATA)) {
@@ -528,6 +529,7 @@
 		if (!err)
 			err = err2;
 	}
+	current->flags &= ~PF_SYNCWRITE;
 
 	spin_lock(&inode_lock);
 	if ((inode->i_state & I_DIRTY) &&
diff -Nru a/fs/hfs/dir.c b/fs/hfs/dir.c
--- a/fs/hfs/dir.c	Thu Feb 14 16:54:38 2002
+++ b/fs/hfs/dir.c	Sun Jun 29 23:49:04 2003
@@ -163,7 +163,7 @@
  * a directory and return a corresponding inode, given the inode for
  * the directory and the name (and its length) of the new file.
  */
-int hfs_create(struct inode * dir, struct dentry *dentry, int mode)
+int hfs_create(struct inode * dir, struct dentry *dentry, int mode, struct nameidata *nd)
 {
 	struct hfs_cat_entry *entry = HFS_I(dir)->entry;
 	struct hfs_cat_entry *new;
diff -Nru a/fs/hfs/dir_cap.c b/fs/hfs/dir_cap.c
--- a/fs/hfs/dir_cap.c	Mon Oct  7 13:51:35 2002
+++ b/fs/hfs/dir_cap.c	Thu Jul  3 06:36:44 2003
@@ -28,7 +28,7 @@
 
 /*================ Forward declarations ================*/
 
-static struct dentry *cap_lookup(struct inode *, struct dentry *);
+static struct dentry *cap_lookup(struct inode *, struct dentry *, struct nameidata *);
 static int cap_readdir(struct file *, void *, filldir_t);
 
 /*================ Global variables ================*/
@@ -95,7 +95,7 @@
  * inode corresponding to an entry in a directory, given the inode for
  * the directory and the name (and its length) of the entry.
  */
-static struct dentry *cap_lookup(struct inode * dir, struct dentry *dentry)
+static struct dentry *cap_lookup(struct inode * dir, struct dentry *dentry, struct nameidata *nd)
 {
 	ino_t dtype;
 	struct hfs_name cname;
diff -Nru a/fs/hfs/dir_dbl.c b/fs/hfs/dir_dbl.c
--- a/fs/hfs/dir_dbl.c	Mon Oct  7 13:51:35 2002
+++ b/fs/hfs/dir_dbl.c	Sun Jun 29 23:49:04 2003
@@ -24,9 +24,9 @@
 
 /*================ Forward declarations ================*/
 
-static struct dentry *dbl_lookup(struct inode *, struct dentry *);
+static struct dentry *dbl_lookup(struct inode *, struct dentry *, struct nameidata *);
 static int dbl_readdir(struct file *, void *, filldir_t);
-static int dbl_create(struct inode *, struct dentry *, int);
+static int dbl_create(struct inode *, struct dentry *, int, struct nameidata *);
 static int dbl_mkdir(struct inode *, struct dentry *, int);
 static int dbl_unlink(struct inode *, struct dentry *);
 static int dbl_rmdir(struct inode *, struct dentry *);
@@ -108,7 +108,7 @@
  * the inode for the directory and the name (and its length) of the
  * entry.
  */
-static struct dentry *dbl_lookup(struct inode * dir, struct dentry *dentry)
+static struct dentry *dbl_lookup(struct inode * dir, struct dentry *dentry, struct nameidata *nd)
 {
 	struct hfs_name cname;
 	struct hfs_cat_entry *entry;
@@ -272,7 +272,7 @@
  * the directory and the name (and its length) of the new file.
  */
 static int dbl_create(struct inode * dir, struct dentry *dentry,
-		      int mode)
+		      int mode, struct nameidata *nd)
 {
 	int error;
 
@@ -280,7 +280,7 @@
 	if (is_hdr(dir, dentry->d_name.name, dentry->d_name.len)) {
 		error = -EEXIST;
 	} else {
-		error = hfs_create(dir, dentry, mode);
+		error = hfs_create(dir, dentry, mode, nd);
 	}
 	unlock_kernel();
 	return error;
diff -Nru a/fs/hfs/dir_nat.c b/fs/hfs/dir_nat.c
--- a/fs/hfs/dir_nat.c	Mon Oct  7 13:51:36 2002
+++ b/fs/hfs/dir_nat.c	Thu Jul  3 06:36:44 2003
@@ -30,7 +30,7 @@
 
 /*================ Forward declarations ================*/
 
-static struct dentry *nat_lookup(struct inode *, struct dentry *);
+static struct dentry *nat_lookup(struct inode *, struct dentry *, struct nameidata *);
 static int nat_readdir(struct file *, void *, filldir_t);
 static int nat_rmdir(struct inode *, struct dentry *);
 static int nat_hdr_unlink(struct inode *, struct dentry *);
@@ -97,7 +97,7 @@
  * the inode corresponding to an entry in a directory, given the inode
  * for the directory and the name (and its length) of the entry.
  */
-static struct dentry *nat_lookup(struct inode * dir, struct dentry *dentry)
+static struct dentry *nat_lookup(struct inode * dir, struct dentry *dentry, struct nameidata *nd)
 {
 	ino_t dtype;
 	struct hfs_name cname;
diff -Nru a/fs/hfs/sysdep.c b/fs/hfs/sysdep.c
--- a/fs/hfs/sysdep.c	Sun Nov 17 11:53:57 2002
+++ b/fs/hfs/sysdep.c	Thu Jul  3 06:36:44 2003
@@ -19,7 +19,7 @@
 #include <linux/hfs_fs.h>
 #include <linux/smp_lock.h>
 
-static int hfs_revalidate_dentry(struct dentry *, int);
+static int hfs_revalidate_dentry(struct dentry *, struct nameidata *);
 static int hfs_hash_dentry(struct dentry *, struct qstr *);
 static int hfs_compare_dentry(struct dentry *, struct qstr *, struct qstr *);
 static void hfs_dentry_iput(struct dentry *, struct inode *);
@@ -90,7 +90,7 @@
 	iput(inode);
 }
 
-static int hfs_revalidate_dentry(struct dentry *dentry, int flags)
+static int hfs_revalidate_dentry(struct dentry *dentry, struct nameidata *nd)
 {
 	struct inode *inode = dentry->d_inode;
 	int diff;
diff -Nru a/fs/hpfs/dir.c b/fs/hpfs/dir.c
--- a/fs/hpfs/dir.c	Sun Nov 17 11:53:57 2002
+++ b/fs/hpfs/dir.c	Thu Jul  3 06:36:44 2003
@@ -198,7 +198,7 @@
  *	      to tell read_inode to read fnode or not.
  */
 
-struct dentry *hpfs_lookup(struct inode *dir, struct dentry *dentry)
+struct dentry *hpfs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
 {
 	const char *name = dentry->d_name.name;
 	unsigned len = dentry->d_name.len;
diff -Nru a/fs/hpfs/hpfs_fn.h b/fs/hpfs/hpfs_fn.h
--- a/fs/hpfs/hpfs_fn.h	Fri Jun 20 13:16:06 2003
+++ b/fs/hpfs/hpfs_fn.h	Sun Jun 29 23:49:04 2003
@@ -216,7 +216,7 @@
 int hpfs_dir_release(struct inode *, struct file *);
 loff_t hpfs_dir_lseek(struct file *, loff_t, int);
 int hpfs_readdir(struct file *, void *, filldir_t);
-struct dentry *hpfs_lookup(struct inode *, struct dentry *);
+struct dentry *hpfs_lookup(struct inode *, struct dentry *, struct nameidata *);
 
 /* dnode.c */
 
@@ -285,7 +285,7 @@
 /* namei.c */
 
 int hpfs_mkdir(struct inode *, struct dentry *, int);
-int hpfs_create(struct inode *, struct dentry *, int);
+int hpfs_create(struct inode *, struct dentry *, int, struct nameidata *);
 int hpfs_mknod(struct inode *, struct dentry *, int, dev_t);
 int hpfs_symlink(struct inode *, struct dentry *, const char *);
 int hpfs_unlink(struct inode *, struct dentry *);
diff -Nru a/fs/hpfs/namei.c b/fs/hpfs/namei.c
--- a/fs/hpfs/namei.c	Wed Jun 25 16:30:54 2003
+++ b/fs/hpfs/namei.c	Sun Jun 29 23:49:25 2003
@@ -106,7 +106,7 @@
 	return -ENOSPC;
 }
 
-int hpfs_create(struct inode *dir, struct dentry *dentry, int mode)
+int hpfs_create(struct inode *dir, struct dentry *dentry, int mode, struct nameidata *nd)
 {
 	const char *name = dentry->d_name.name;
 	unsigned len = dentry->d_name.len;
@@ -374,7 +374,7 @@
 		d_drop(dentry);
 		spin_lock(&dentry->d_lock);
 		if (atomic_read(&dentry->d_count) > 1 ||
-		    permission(inode, MAY_WRITE) ||
+		    permission(inode, MAY_WRITE, NULL) ||
 		    get_write_access(inode)) {
 			spin_unlock(&dentry->d_lock);
 			d_rehash(dentry);
diff -Nru a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c
--- a/fs/hugetlbfs/inode.c	Fri Jun 20 13:16:19 2003
+++ b/fs/hugetlbfs/inode.c	Sun Jun 29 23:49:04 2003
@@ -462,7 +462,7 @@
 	return retval;
 }
 
-static int hugetlbfs_create(struct inode *dir, struct dentry *dentry, int mode)
+static int hugetlbfs_create(struct inode *dir, struct dentry *dentry, int mode, struct nameidata *nd)
 {
 	return hugetlbfs_mknod(dir, dentry, mode | S_IFREG, 0);
 }
diff -Nru a/fs/intermezzo/dcache.c b/fs/intermezzo/dcache.c
--- a/fs/intermezzo/dcache.c	Thu Mar 13 16:52:26 2003
+++ b/fs/intermezzo/dcache.c	Thu Jul  3 06:36:44 2003
@@ -50,7 +50,7 @@
 kmem_cache_t * presto_dentry_slab;
 
 /* called when a cache lookup succeeds */
-static int presto_d_revalidate(struct dentry *de, int flag)
+static int presto_d_revalidate(struct dentry *de, struct nameidata *nd)
 {
         struct inode *inode = de->d_inode;
         struct presto_file_set * root_fset;
diff -Nru a/fs/intermezzo/dir.c b/fs/intermezzo/dir.c
--- a/fs/intermezzo/dir.c	Tue Mar 18 09:08:01 2003
+++ b/fs/intermezzo/dir.c	Sun Jun 29 23:49:25 2003
@@ -81,7 +81,7 @@
 /*
  * these are initialized in super.c
  */
-extern int presto_permission(struct inode *inode, int mask);
+extern int presto_permission(struct inode *inode, int mask, struct nameidata *nd);
 static int izo_authorized_uid = 0;
 
 int izo_dentry_is_ilookup(struct dentry *dentry, ino_t *id,
@@ -239,7 +239,7 @@
         return de;
 }
 
-struct dentry *presto_lookup(struct inode * dir, struct dentry *dentry)
+struct dentry *presto_lookup(struct inode * dir, struct dentry *dentry, struct nameidata *nd)
 {
         int rc = 0;
         struct dentry *de;
@@ -286,7 +286,7 @@
                                 (dir, dentry, ino, generation);
                         is_ilookup = 1;
                 } else
-                        de = iops->lookup(dir, dentry);
+                        de = iops->lookup(dir, dentry, nd);
 #if 0
         }
 #endif
@@ -412,7 +412,8 @@
         return 0;
 }
 
-static int presto_create(struct inode * dir, struct dentry * dentry, int mode)
+static int presto_create(struct inode * dir, struct dentry * dentry, int mode,
+                struct nameidata *nd)
 {
         int error;
         struct presto_cache *cache;
@@ -829,7 +830,7 @@
  * appropriate permission function. Thus we do not worry here about ACLs
  * or EAs. -SHP
  */
-int presto_permission(struct inode *inode, int mask)
+int presto_permission(struct inode *inode, int mask, struct nameidata *nd)
 {
         unsigned short mode = inode->i_mode;
         struct presto_cache *cache;
@@ -851,11 +852,11 @@
 
                 if ( S_ISREG(mode) && fiops && fiops->permission ) {
                         EXIT;
-                        return fiops->permission(inode, mask);
+                        return fiops->permission(inode, mask, nd);
                 }
                 if ( S_ISDIR(mode) && diops && diops->permission ) {
                         EXIT;
-                        return diops->permission(inode, mask);
+                        return diops->permission(inode, mask, nd);
                 }
         }
 
@@ -866,7 +867,7 @@
          * the VFS permission function.
          */
         inode->i_op->permission = NULL;
-        rc = permission(inode, mask);
+        rc = permission(inode, mask, nd);
         inode->i_op->permission = &presto_permission;
 
         EXIT;
diff -Nru a/fs/intermezzo/file.c b/fs/intermezzo/file.c
--- a/fs/intermezzo/file.c	Tue Mar 18 09:08:01 2003
+++ b/fs/intermezzo/file.c	Sun Jun 29 23:49:25 2003
@@ -53,7 +53,7 @@
 /*
  * these are initialized in super.c
  */
-extern int presto_permission(struct inode *inode, int mask);
+extern int presto_permission(struct inode *inode, int mask, struct nameidata *nd);
 
 
 static int presto_open_upcall(int minor, struct dentry *de)
diff -Nru a/fs/intermezzo/intermezzo_fs.h b/fs/intermezzo/intermezzo_fs.h
--- a/fs/intermezzo/intermezzo_fs.h	Fri Jun 20 13:16:06 2003
+++ b/fs/intermezzo/intermezzo_fs.h	Thu Jul  3 06:36:44 2003
@@ -370,7 +370,7 @@
 # define PRESTO_ILOOKUP_MAGIC "...ino:"
 # define PRESTO_ILOOKUP_SEP ':'
 int izo_dentry_is_ilookup(struct dentry *, ino_t *id, unsigned int *generation);
-struct dentry *presto_lookup(struct inode * dir, struct dentry *dentry);
+struct dentry *presto_lookup(struct inode * dir, struct dentry *dentry, struct nameidata *nd);
 
 struct presto_dentry_data {
         int dd_count; /* how mnay dentries are using this dentry */
diff -Nru a/fs/intermezzo/vfs.c b/fs/intermezzo/vfs.c
--- a/fs/intermezzo/vfs.c	Wed Jun 11 20:00:51 2003
+++ b/fs/intermezzo/vfs.c	Sun Jun 29 23:49:25 2003
@@ -134,7 +134,7 @@
         int error;
         if (!victim->d_inode || victim->d_parent->d_inode != dir)
                 return -ENOENT;
-        error = permission(dir,MAY_WRITE | MAY_EXEC);
+        error = permission(dir,MAY_WRITE | MAY_EXEC, NULL);
         if (error)
                 return error;
         if (IS_APPEND(dir))
@@ -158,7 +158,7 @@
                 return -EEXIST;
         if (IS_DEADDIR(dir))
                 return -ENOENT;
-        return permission(dir,MAY_WRITE | MAY_EXEC);
+        return permission(dir,MAY_WRITE | MAY_EXEC, NULL);
 }
 
 #ifdef PRESTO_DEBUG
@@ -598,7 +598,7 @@
         }
         DQUOT_INIT(dir->d_inode);
         lock_kernel();
-        error = iops->create(dir->d_inode, dentry, mode);
+        error = iops->create(dir->d_inode, dentry, mode, NULL);
         if (error) {
                 EXIT;
                 goto exit_lock;
@@ -1840,7 +1840,7 @@
          * we'll need to flip '..'.
          */
         if (new_dir != old_dir) {
-                error = permission(old_dentry->d_inode, MAY_WRITE);
+                error = permission(old_dentry->d_inode, MAY_WRITE, NULL);
         }
         if (error)
                 return error;
diff -Nru a/fs/isofs/namei.c b/fs/isofs/namei.c
--- a/fs/isofs/namei.c	Thu May 23 06:18:50 2002
+++ b/fs/isofs/namei.c	Thu Jul  3 06:36:44 2003
@@ -158,7 +158,7 @@
 	return 0;
 }
 
-struct dentry *isofs_lookup(struct inode * dir, struct dentry * dentry)
+struct dentry *isofs_lookup(struct inode * dir, struct dentry * dentry, struct nameidata *nd)
 {
 	unsigned long ino;
 	struct inode *inode;
diff -Nru a/fs/jbd/commit.c b/fs/jbd/commit.c
--- a/fs/jbd/commit.c	Wed Jun 25 16:30:56 2003
+++ b/fs/jbd/commit.c	Wed Jul  2 21:23:09 2003
@@ -169,10 +169,23 @@
 	 * that multiple journal_get_write_access() calls to the same
 	 * buffer are perfectly permissable.
 	 */
-	while (commit_transaction->t_reserved_list) {
-		jh = commit_transaction->t_reserved_list;
-		JBUFFER_TRACE(jh, "reserved, unused: refile");
-		journal_refile_buffer(journal, jh);
+	{
+		int nr = 0;
+		while (commit_transaction->t_reserved_list) {
+			jh = commit_transaction->t_reserved_list;
+			JBUFFER_TRACE(jh, "reserved, unused: refile");
+			journal_refile_buffer(journal, jh);
+			nr++;
+		}
+		if (nr) {
+			static int noisy;
+
+			if (noisy < 10) {
+				noisy++;
+				printk("%s: freed %d reserved buffers\n",
+					__FUNCTION__, nr);
+			}
+		}
 	}
 
 	/*
diff -Nru a/fs/jbd/transaction.c b/fs/jbd/transaction.c
--- a/fs/jbd/transaction.c	Fri Jun 20 13:16:32 2003
+++ b/fs/jbd/transaction.c	Wed Jul  2 21:23:09 2003
@@ -1168,37 +1168,24 @@
  * journal_release_buffer: undo a get_write_access without any buffer
  * updates, if the update decided in the end that it didn't need access.
  *
- * journal_get_write_access() can block, so it is quite possible for a
- * journaling component to decide after the write access is returned
- * that global state has changed and the update is no longer required.
- *
  * The caller passes in the number of credits which should be put back for
  * this buffer (zero or one).
+ *
+ * We leave the buffer attached to t_reserved_list because even though this
+ * handle doesn't want it, some other concurrent handle may want to journal
+ * this buffer.  If that handle is curently in between get_write_access() and
+ * journal_dirty_metadata() then it expects the buffer to be reserved.  If
+ * we were to rip it off t_reserved_list here, the other handle will explode
+ * when journal_dirty_metadata is presented with a non-reserved buffer.
+ *
+ * If nobody really wants to journal this buffer then it will be thrown
+ * away at the start of commit.
  */
 void
 journal_release_buffer(handle_t *handle, struct buffer_head *bh, int credits)
 {
-	transaction_t *transaction = handle->h_transaction;
-	journal_t *journal = transaction->t_journal;
-	struct journal_head *jh = bh2jh(bh);
-
-	JBUFFER_TRACE(jh, "entry");
-
-	/* If the buffer is reserved but not modified by this
-	 * transaction, then it is safe to release it.  In all other
-	 * cases, just leave the buffer as it is. */
-
-	jbd_lock_bh_state(bh);
-	spin_lock(&journal->j_list_lock);
-	if (jh->b_jlist == BJ_Reserved && jh->b_transaction == transaction &&
-	    !buffer_jbddirty(jh2bh(jh))) {
-		JBUFFER_TRACE(jh, "unused: refiling it");
-		__journal_refile_buffer(jh);
-	}
-	spin_unlock(&journal->j_list_lock);
-	jbd_unlock_bh_state(bh);
+	BUFFER_TRACE(bh, "entry");
 	handle->h_buffer_credits += credits;
-	JBUFFER_TRACE(jh, "exit");
 }
 
 /** 
diff -Nru a/fs/jffs/inode-v23.c b/fs/jffs/inode-v23.c
--- a/fs/jffs/inode-v23.c	Sun May 25 20:01:37 2003
+++ b/fs/jffs/inode-v23.c	Sun Jun 29 23:49:04 2003
@@ -642,7 +642,7 @@
 /* Find a file in a directory. If the file exists, return its
    corresponding dentry.  */
 static struct dentry *
-jffs_lookup(struct inode *dir, struct dentry *dentry)
+jffs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
 {
 	struct jffs_file *d;
 	struct jffs_file *f;
@@ -1273,7 +1273,8 @@
  * with d_instantiate().
  */
 static int
-jffs_create(struct inode *dir, struct dentry *dentry, int mode)
+jffs_create(struct inode *dir, struct dentry *dentry, int mode,
+		struct nameidata *nd)
 {
 	struct jffs_raw_inode raw_inode;
 	struct jffs_control *c;
diff -Nru a/fs/jffs2/dir.c b/fs/jffs2/dir.c
--- a/fs/jffs2/dir.c	Mon Jun 23 05:42:27 2003
+++ b/fs/jffs2/dir.c	Sun Jun 29 23:49:04 2003
@@ -32,8 +32,8 @@
 
 static int jffs2_readdir (struct file *, void *, filldir_t);
 
-static int jffs2_create (struct inode *,struct dentry *,int);
-static struct dentry *jffs2_lookup (struct inode *,struct dentry *);
+static int jffs2_create (struct inode *,struct dentry *,int, struct nameidata *);
+static struct dentry *jffs2_lookup (struct inode *,struct dentry *, struct nameidata *);
 static int jffs2_link (struct dentry *,struct inode *,struct dentry *);
 static int jffs2_unlink (struct inode *,struct dentry *);
 static int jffs2_symlink (struct inode *,struct dentry *,const char *);
@@ -73,7 +73,7 @@
    and we use the same hash function as the dentries. Makes this 
    nice and simple
 */
-static struct dentry *jffs2_lookup(struct inode *dir_i, struct dentry *target)
+static struct dentry *jffs2_lookup(struct inode *dir_i, struct dentry *target, struct nameidata *nd)
 {
 	struct jffs2_inode_info *dir_f;
 	struct jffs2_sb_info *c;
@@ -175,7 +175,8 @@
 /***********************************************************************/
 
 
-static int jffs2_create(struct inode *dir_i, struct dentry *dentry, int mode)
+static int jffs2_create(struct inode *dir_i, struct dentry *dentry, int mode,
+		struct nameidata *nd)
 {
 	struct jffs2_raw_inode *ri;
 	struct jffs2_inode_info *f, *dir_f;
diff -Nru a/fs/jfs/acl.c b/fs/jfs/acl.c
--- a/fs/jfs/acl.c	Mon Nov 11 06:27:31 2002
+++ b/fs/jfs/acl.c	Sun Jun 29 23:49:25 2003
@@ -208,7 +208,7 @@
 
 	return -EACCES;
 }
-int jfs_permission(struct inode * inode, int mask)
+int jfs_permission(struct inode * inode, int mask, struct nameidata *nd)
 {
 	return __jfs_permission(inode, mask, 0);
 }
diff -Nru a/fs/jfs/jfs_acl.h b/fs/jfs/jfs_acl.h
--- a/fs/jfs/jfs_acl.h	Sat Nov  9 12:41:48 2002
+++ b/fs/jfs/jfs_acl.h	Sun Jun 29 23:49:25 2003
@@ -25,7 +25,7 @@
 struct posix_acl *jfs_get_acl(struct inode *, int);
 int jfs_set_acl(struct inode *, int, struct posix_acl *);
 int jfs_permission_have_sem(struct inode *, int);
-int jfs_permission(struct inode *, int);
+int jfs_permission(struct inode *, int, struct nameidata *);
 int jfs_init_acl(struct inode *, struct inode *);
 int jfs_setattr(struct dentry *, struct iattr *);
 
diff -Nru a/fs/jfs/namei.c b/fs/jfs/namei.c
--- a/fs/jfs/namei.c	Wed Jun 11 10:26:32 2003
+++ b/fs/jfs/namei.c	Sun Jun 29 23:49:04 2003
@@ -54,11 +54,13 @@
  * PARAMETER:	dip 	- parent directory vnode
  *		dentry	- dentry of new file
  *		mode	- create mode (rwxrwxrwx).
+ *		nd- nd struct
  *
  * RETURN:	Errors from subroutines
  *
  */
-int jfs_create(struct inode *dip, struct dentry *dentry, int mode)
+int jfs_create(struct inode *dip, struct dentry *dentry, int mode,
+		struct nameidata *nd)
 {
 	int rc = 0;
 	tid_t tid;		/* transaction id */
@@ -1373,7 +1375,7 @@
 	return -rc;
 }
 
-static struct dentry *jfs_lookup(struct inode *dip, struct dentry *dentry)
+static struct dentry *jfs_lookup(struct inode *dip, struct dentry *dentry, struct nameidata *nd)
 {
 	struct btstack btstack;
 	ino_t inum;
diff -Nru a/fs/jfs/xattr.c b/fs/jfs/xattr.c
--- a/fs/jfs/xattr.c	Tue Feb 25 08:21:08 2003
+++ b/fs/jfs/xattr.c	Fri Jul  4 22:16:53 2003
@@ -731,7 +731,7 @@
 #ifdef CONFIG_JFS_POSIX_ACL
 	return jfs_permission_have_sem(inode, MAY_WRITE);
 #else
-	return permission(inode, MAY_WRITE);
+	return permission(inode, MAY_WRITE, NULL);
 #endif
 }
 
@@ -893,7 +893,7 @@
 	else
 		return jfs_permission_have_sem(inode, MAY_READ);
 #else
-	return permission(inode, MAY_READ);
+	return permission(inode, MAY_READ, NULL);
 #endif
 }
 
@@ -964,10 +964,17 @@
 ssize_t jfs_getxattr(struct dentry *dentry, const char *name, void *data,
 		     size_t buf_size)
 {
-	return __jfs_getxattr(dentry->d_inode, name, data, buf_size);
+	int err;
+
+	down(&dentry->d_inode->i_sem);
+	err = __jfs_getxattr(dentry->d_inode, name, data, buf_size);
+	up(&dentry->d_inode->i_sem);
+
+	return err;
 }
 
-ssize_t jfs_listxattr(struct dentry * dentry, char *data, size_t buf_size)
+static ssize_t __jfs_listxattr(struct dentry * dentry, char *data,
+			       size_t buf_size)
 {
 	struct inode *inode = dentry->d_inode;
 	char *buffer;
@@ -1011,6 +1018,17 @@
 	ea_release(inode, &ea_buf);
       out:
 	return size;
+}
+
+ssize_t jfs_listxattr(struct dentry * dentry, char *data, size_t buf_size)
+{
+	int err;
+
+	down(&dentry->d_inode->i_sem);
+	err = __jfs_listxattr(dentry, data, buf_size);
+	up(&dentry->d_inode->i_sem);
+
+	return err;
 }
 
 int jfs_removexattr(struct dentry *dentry, const char *name)
diff -Nru a/fs/libfs.c b/fs/libfs.c
--- a/fs/libfs.c	Fri Jun 20 13:16:06 2003
+++ b/fs/libfs.c	Thu Jul  3 06:36:44 2003
@@ -29,7 +29,7 @@
  * exist, we know it is negative.
  */
 
-struct dentry *simple_lookup(struct inode *dir, struct dentry *dentry)
+struct dentry *simple_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
 {
 	d_add(dentry, NULL);
 	return NULL;
diff -Nru a/fs/minix/namei.c b/fs/minix/namei.c
--- a/fs/minix/namei.c	Wed Nov 20 03:19:02 2002
+++ b/fs/minix/namei.c	Sun Jun 29 23:49:04 2003
@@ -54,7 +54,7 @@
 	.d_hash		= minix_hash,
 };
 
-static struct dentry *minix_lookup(struct inode * dir, struct dentry *dentry)
+static struct dentry *minix_lookup(struct inode * dir, struct dentry *dentry, struct nameidata *nd)
 {
 	struct inode * inode = NULL;
 	ino_t ino;
@@ -89,7 +89,8 @@
 	return error;
 }
 
-static int minix_create(struct inode * dir, struct dentry *dentry, int mode)
+static int minix_create(struct inode * dir, struct dentry *dentry, int mode,
+		struct nameidata *nd)
 {
 	return minix_mknod(dir, dentry, mode, 0);
 }
diff -Nru a/fs/msdos/namei.c b/fs/msdos/namei.c
--- a/fs/msdos/namei.c	Tue May 27 07:32:40 2003
+++ b/fs/msdos/namei.c	Sun Jun 29 23:49:04 2003
@@ -193,7 +193,7 @@
  */
 
 /***** Get inode using directory and name */
-struct dentry *msdos_lookup(struct inode *dir,struct dentry *dentry)
+struct dentry *msdos_lookup(struct inode *dir,struct dentry *dentry, struct nameidata *nd)
 {
 	struct super_block *sb = dir->i_sb;
 	struct inode *inode = NULL;
@@ -261,7 +261,8 @@
  */
 
 /***** Create a file */
-int msdos_create(struct inode *dir,struct dentry *dentry,int mode)
+int msdos_create(struct inode *dir,struct dentry *dentry,int mode,
+		struct nameidata *nd)
 {
 	struct super_block *sb = dir->i_sb;
 	struct buffer_head *bh;
diff -Nru a/fs/namei.c b/fs/namei.c
--- a/fs/namei.c	Mon Jun 16 22:09:04 2003
+++ b/fs/namei.c	Mon Jul  7 12:25:00 2003
@@ -203,7 +203,7 @@
 	return -EACCES;
 }
 
-int permission(struct inode * inode,int mask)
+int permission(struct inode * inode,int mask, struct nameidata *nd)
 {
 	int retval;
 	int submask;
@@ -212,7 +212,7 @@
 	submask = mask & ~MAY_APPEND;
 
 	if (inode->i_op && inode->i_op->permission)
-		retval = inode->i_op->permission(inode, submask);
+		retval = inode->i_op->permission(inode, submask, nd);
 	else
 		retval = vfs_permission(inode, submask);
 	if (retval)
@@ -273,7 +273,7 @@
  * Internal lookup() using the new generic dcache.
  * SMP-safe
  */
-static struct dentry * cached_lookup(struct dentry * parent, struct qstr * name, int flags)
+static struct dentry * cached_lookup(struct dentry * parent, struct qstr * name, struct nameidata *nd)
 {
 	struct dentry * dentry = __d_lookup(parent, name);
 
@@ -284,7 +284,7 @@
 		dentry = d_lookup(parent, name);
 
 	if (dentry && dentry->d_op && dentry->d_op->d_revalidate) {
-		if (!dentry->d_op->d_revalidate(dentry, flags) && !d_invalidate(dentry)) {
+		if (!dentry->d_op->d_revalidate(dentry, nd) && !d_invalidate(dentry)) {
 			dput(dentry);
 			dentry = NULL;
 		}
@@ -336,7 +336,7 @@
  * make sure that nobody added the entry to the dcache in the meantime..
  * SMP-safe
  */
-static struct dentry * real_lookup(struct dentry * parent, struct qstr * name, int flags)
+static struct dentry * real_lookup(struct dentry * parent, struct qstr * name, struct nameidata *nd)
 {
 	struct dentry * result;
 	struct inode *dir = parent->d_inode;
@@ -361,7 +361,7 @@
 		struct dentry * dentry = d_alloc(parent, name);
 		result = ERR_PTR(-ENOMEM);
 		if (dentry) {
-			result = dir->i_op->lookup(dir, dentry);
+			result = dir->i_op->lookup(dir, dentry, nd);
 			if (result)
 				dput(dentry);
 			else
@@ -377,7 +377,7 @@
 	 */
 	up(&dir->i_sem);
 	if (result->d_op && result->d_op->d_revalidate) {
-		if (!result->d_op->d_revalidate(result, flags) && !d_invalidate(result)) {
+		if (!result->d_op->d_revalidate(result, nd) && !d_invalidate(result)) {
 			dput(result);
 			result = ERR_PTR(-ENOENT);
 		}
@@ -524,7 +524,7 @@
  *  It _is_ time-critical.
  */
 static int do_lookup(struct nameidata *nd, struct qstr *name,
-		     struct path *path, int flags)
+		     struct path *path)
 {
 	struct vfsmount *mnt = nd->mnt;
 	struct dentry *dentry = __d_lookup(nd->dentry, name);
@@ -539,13 +539,13 @@
 	return 0;
 
 need_lookup:
-	dentry = real_lookup(nd->dentry, name, LOOKUP_CONTINUE);
+	dentry = real_lookup(nd->dentry, name, nd);
 	if (IS_ERR(dentry))
 		goto fail;
 	goto done;
 
 need_revalidate:
-	if (dentry->d_op->d_revalidate(dentry, flags))
+	if (dentry->d_op->d_revalidate(dentry, nd))
 		goto done;
 	if (d_invalidate(dentry))
 		goto done;
@@ -588,7 +588,7 @@
 
 		err = exec_permission_lite(inode);
 		if (err == -EAGAIN) { 
-			err = permission(inode, MAY_EXEC);
+			err = permission(inode, MAY_EXEC, nd);
 		}
  		if (err)
 			break;
@@ -638,8 +638,9 @@
 			if (err < 0)
 				break;
 		}
+		nd->flags |= LOOKUP_CONTINUE;
 		/* This does the actual lookups.. */
-		err = do_lookup(nd, &this, &next, LOOKUP_CONTINUE);
+		err = do_lookup(nd, &this, &next);
 		if (err)
 			break;
 		/* Check mountpoints.. */
@@ -681,6 +682,7 @@
 last_with_slashes:
 		lookup_flags |= LOOKUP_FOLLOW | LOOKUP_DIRECTORY;
 last_component:
+		nd->flags &= ~LOOKUP_CONTINUE;
 		if (lookup_flags & LOOKUP_PARENT)
 			goto lookup_parent;
 		if (this.name[0] == '.') switch (this.len) {
@@ -700,7 +702,7 @@
 			if (err < 0)
 				break;
 		}
-		err = do_lookup(nd, &this, &next, 0);
+		err = do_lookup(nd, &this, &next);
 		if (err)
 			break;
 		follow_mount(&next.mnt, &next.dentry);
@@ -769,6 +771,7 @@
 		 */
 		nd_root.last_type = LAST_ROOT;
 		nd_root.flags = nd->flags;
+		memcpy(&nd_root.intent, &nd->intent, sizeof(nd_root.intent));
 		read_lock(&current->fs->lock);
 		nd_root.mnt = mntget(current->fs->rootmnt);
 		nd_root.dentry = dget(current->fs->root);
@@ -866,14 +869,14 @@
  * needs parent already locked. Doesn't follow mounts.
  * SMP-safe.
  */
-struct dentry * lookup_hash(struct qstr *name, struct dentry * base)
+static struct dentry * __lookup_hash(struct qstr *name, struct dentry * base, struct nameidata *nd)
 {
 	struct dentry * dentry;
 	struct inode *inode;
 	int err;
 
 	inode = base->d_inode;
-	err = permission(inode, MAY_EXEC);
+	err = permission(inode, MAY_EXEC, nd);
 	dentry = ERR_PTR(err);
 	if (err)
 		goto out;
@@ -889,13 +892,13 @@
 			goto out;
 	}
 
-	dentry = cached_lookup(base, name, 0);
+	dentry = cached_lookup(base, name, nd);
 	if (!dentry) {
 		struct dentry *new = d_alloc(base, name);
 		dentry = ERR_PTR(-ENOMEM);
 		if (!new)
 			goto out;
-		dentry = inode->i_op->lookup(inode, new);
+		dentry = inode->i_op->lookup(inode, new, nd);
 		if (!dentry)
 			dentry = new;
 		else
@@ -905,6 +908,11 @@
 	return dentry;
 }
 
+struct dentry * lookup_hash(struct qstr *name, struct dentry * base)
+{
+	return __lookup_hash(name, base, NULL);
+}
+
 /* SMP-safe */
 struct dentry * lookup_one_len(const char * name, struct dentry * base, int len)
 {
@@ -988,12 +996,12 @@
  * 10. We don't allow removal of NFS sillyrenamed files; it's handled by
  *     nfs_async_unlink().
  */
-static inline int may_delete(struct inode *dir,struct dentry *victim, int isdir)
+static inline int may_delete(struct inode *dir,struct dentry *victim,int isdir)
 {
 	int error;
 	if (!victim->d_inode || victim->d_parent->d_inode != dir)
 		return -ENOENT;
-	error = permission(dir,MAY_WRITE | MAY_EXEC);
+	error = permission(dir,MAY_WRITE | MAY_EXEC, NULL);
 	if (error)
 		return error;
 	if (IS_APPEND(dir))
@@ -1023,12 +1031,14 @@
  *  3. We should have write and exec permissions on dir
  *  4. We can't do it if dir is immutable (done in permission())
  */
-static inline int may_create(struct inode *dir, struct dentry *child) {
+static inline int may_create(struct inode *dir, struct dentry *child,
+			     struct nameidata *nd)
+{
 	if (child->d_inode)
 		return -EEXIST;
 	if (IS_DEADDIR(dir))
 		return -ENOENT;
-	return permission(dir,MAY_WRITE | MAY_EXEC);
+	return permission(dir,MAY_WRITE | MAY_EXEC, nd);
 }
 
 /* 
@@ -1097,9 +1107,10 @@
 	}
 }
 
-int vfs_create(struct inode *dir, struct dentry *dentry, int mode)
+int vfs_create(struct inode *dir, struct dentry *dentry, int mode,
+		struct nameidata *nd)
 {
-	int error = may_create(dir, dentry);
+	int error = may_create(dir, dentry, nd);
 
 	if (error)
 		return error;
@@ -1112,7 +1123,7 @@
 	if (error)
 		return error;
 	DQUOT_INIT(dir);
-	error = dir->i_op->create(dir, dentry, mode);
+	error = dir->i_op->create(dir, dentry, mode, nd);
 	if (!error) {
 		inode_dir_notify(dir, DN_CREATE);
 		security_inode_post_create(dir, dentry, mode);
@@ -1135,7 +1146,7 @@
 	if (S_ISDIR(inode->i_mode) && (flag & FMODE_WRITE))
 		return -EISDIR;
 
-	error = permission(inode, acc_mode);
+	error = permission(inode, acc_mode, nd);
 	if (error)
 		return error;
 
@@ -1222,11 +1233,15 @@
 	if (flag & O_APPEND)
 		acc_mode |= MAY_APPEND;
 
+	/* Fill in the open() intent data */
+	nd->intent.open.flags = flag;
+	nd->intent.open.create_mode = mode;
+
 	/*
 	 * The simplest case - just a plain lookup.
 	 */
 	if (!(flag & O_CREAT)) {
-		error = path_lookup(pathname, lookup_flags(flag), nd);
+		error = path_lookup(pathname, lookup_flags(flag)|LOOKUP_OPEN, nd);
 		if (error)
 			return error;
 		dentry = nd->dentry;
@@ -1236,7 +1251,7 @@
 	/*
 	 * Create - we need to know the parent.
 	 */
-	error = path_lookup(pathname, LOOKUP_PARENT, nd);
+	error = path_lookup(pathname, LOOKUP_PARENT|LOOKUP_OPEN|LOOKUP_CREATE, nd);
 	if (error)
 		return error;
 
@@ -1250,8 +1265,9 @@
 		goto exit;
 
 	dir = nd->dentry;
+	nd->flags &= ~LOOKUP_PARENT;
 	down(&dir->d_inode->i_sem);
-	dentry = lookup_hash(&nd->last, nd->dentry);
+	dentry = __lookup_hash(&nd->last, nd->dentry, nd);
 
 do_last:
 	error = PTR_ERR(dentry);
@@ -1264,7 +1280,7 @@
 	if (!dentry->d_inode) {
 		if (!IS_POSIXACL(dir->d_inode))
 			mode &= ~current->fs->umask;
-		error = vfs_create(dir->d_inode, dentry, mode);
+		error = vfs_create(dir->d_inode, dentry, mode, nd);
 		up(&dir->d_inode->i_sem);
 		dput(nd->dentry);
 		nd->dentry = dentry;
@@ -1328,6 +1344,7 @@
 	 * stored in nd->last.name and we will have to putname() it when we
 	 * are done. Procfs-like symlinks just set LAST_BIND.
 	 */
+	nd->flags |= LOOKUP_PARENT;
 	error = security_inode_follow_link(dentry, nd);
 	if (error)
 		goto exit_dput;
@@ -1336,6 +1353,7 @@
 	dput(dentry);
 	if (error)
 		return error;
+	nd->flags &= ~LOOKUP_PARENT;
 	if (nd->last_type == LAST_BIND) {
 		dentry = nd->dentry;
 		goto ok;
@@ -1354,7 +1372,7 @@
 	}
 	dir = nd->dentry;
 	down(&dir->d_inode->i_sem);
-	dentry = lookup_hash(&nd->last, nd->dentry);
+	dentry = __lookup_hash(&nd->last, nd->dentry, nd);
 	putname(nd->last.name);
 	goto do_last;
 }
@@ -1368,6 +1386,7 @@
 	dentry = ERR_PTR(-EEXIST);
 	if (nd->last_type != LAST_NORM)
 		goto fail;
+	nd->flags &= ~LOOKUP_PARENT;
 	dentry = lookup_hash(&nd->last, nd->dentry);
 	if (IS_ERR(dentry))
 		goto fail;
@@ -1383,7 +1402,7 @@
 
 int vfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
 {
-	int error = may_create(dir, dentry);
+	int error = may_create(dir, dentry, NULL);
 
 	if (error)
 		return error;
@@ -1431,7 +1450,7 @@
 	if (!IS_ERR(dentry)) {
 		switch (mode & S_IFMT) {
 		case 0: case S_IFREG:
-			error = vfs_create(nd.dentry->d_inode,dentry,mode);
+			error = vfs_create(nd.dentry->d_inode,dentry,mode,&nd);
 			break;
 		case S_IFCHR: case S_IFBLK: case S_IFIFO: case S_IFSOCK:
 			error = vfs_mknod(nd.dentry->d_inode,dentry,mode,dev);
@@ -1454,7 +1473,7 @@
 
 int vfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
 {
-	int error = may_create(dir, dentry);
+	int error = may_create(dir, dentry, NULL);
 
 	if (error)
 		return error;
@@ -1700,7 +1719,7 @@
 
 int vfs_symlink(struct inode *dir, struct dentry *dentry, const char *oldname)
 {
-	int error = may_create(dir, dentry);
+	int error = may_create(dir, dentry, NULL);
 
 	if (error)
 		return error;
@@ -1762,7 +1781,7 @@
 	if (!inode)
 		return -ENOENT;
 
-	error = may_create(dir, new_dentry);
+	error = may_create(dir, new_dentry, NULL);
 	if (error)
 		return error;
 
@@ -1883,7 +1902,7 @@
 	 * we'll need to flip '..'.
 	 */
 	if (new_dir != old_dir) {
-		error = permission(old_dentry->d_inode, MAY_WRITE);
+		error = permission(old_dentry->d_inode, MAY_WRITE, NULL);
 		if (error)
 			return error;
 	}
@@ -1961,7 +1980,7 @@
 		return error;
 
 	if (!new_dentry->d_inode)
-		error = may_create(new_dir, new_dentry);
+		error = may_create(new_dir, new_dentry, NULL);
 	else
 		error = may_delete(new_dir, new_dentry, is_dir);
 	if (error)
diff -Nru a/fs/namespace.c b/fs/namespace.c
--- a/fs/namespace.c	Thu Jun  5 08:55:12 2003
+++ b/fs/namespace.c	Sun Jun 29 23:49:25 2003
@@ -403,7 +403,7 @@
 		if (current->uid != nd->dentry->d_inode->i_uid)
 			return -EPERM;
 	}
-	if (permission(nd->dentry->d_inode, MAY_WRITE))
+	if (permission(nd->dentry->d_inode, MAY_WRITE, nd))
 		return -EPERM;
 	return 0;
 #endif
diff -Nru a/fs/ncpfs/dir.c b/fs/ncpfs/dir.c
--- a/fs/ncpfs/dir.c	Wed Apr  2 22:51:32 2003
+++ b/fs/ncpfs/dir.c	Sun Jun 29 23:49:04 2003
@@ -34,8 +34,8 @@
 
 static int ncp_readdir(struct file *, void *, filldir_t);
 
-static int ncp_create(struct inode *, struct dentry *, int);
-static struct dentry *ncp_lookup(struct inode *, struct dentry *);
+static int ncp_create(struct inode *, struct dentry *, int, struct nameidata *);
+static struct dentry *ncp_lookup(struct inode *, struct dentry *, struct nameidata *);
 static int ncp_unlink(struct inode *, struct dentry *);
 static int ncp_mkdir(struct inode *, struct dentry *, int);
 static int ncp_rmdir(struct inode *, struct dentry *);
@@ -72,7 +72,7 @@
 /*
  * Dentry operations routines
  */
-static int ncp_lookup_validate(struct dentry *, int);
+static int ncp_lookup_validate(struct dentry *, struct nameidata *);
 static int ncp_hash_dentry(struct dentry *, struct qstr *);
 static int ncp_compare_dentry (struct dentry *, struct qstr *, struct qstr *);
 static int ncp_delete_dentry(struct dentry *);
@@ -264,7 +264,7 @@
 
 
 static int
-__ncp_lookup_validate(struct dentry * dentry, int flags)
+__ncp_lookup_validate(struct dentry * dentry, struct nameidata *nd)
 {
 	struct ncp_server *server;
 	struct dentry *parent;
@@ -333,11 +333,11 @@
 }
 
 static int
-ncp_lookup_validate(struct dentry * dentry, int flags)
+ncp_lookup_validate(struct dentry * dentry, struct nameidata *nd)
 {
 	int res;
 	lock_kernel();
-	res = __ncp_lookup_validate(dentry, flags);
+	res = __ncp_lookup_validate(dentry, nd);
 	unlock_kernel();
 	return res;
 }
@@ -797,7 +797,7 @@
 	return result;
 }
 
-static struct dentry *ncp_lookup(struct inode *dir, struct dentry *dentry)
+static struct dentry *ncp_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
 {
 	struct ncp_server *server = NCP_SERVER(dir);
 	struct inode *inode = NULL;
@@ -942,7 +942,8 @@
 	return error;
 }
 
-static int ncp_create(struct inode *dir, struct dentry *dentry, int mode)
+static int ncp_create(struct inode *dir, struct dentry *dentry, int mode,
+		struct nameidata *nd)
 {
 	return ncp_create_new(dir, dentry, mode, 0, 0);
 }
diff -Nru a/fs/ncpfs/ioctl.c b/fs/ncpfs/ioctl.c
--- a/fs/ncpfs/ioctl.c	Mon Mar 10 22:34:29 2003
+++ b/fs/ncpfs/ioctl.c	Sun Jun 29 23:49:25 2003
@@ -40,7 +40,7 @@
 	switch (cmd) {
 	case NCP_IOC_NCPREQUEST:
 
-		if ((permission(inode, MAY_WRITE) != 0)
+		if ((permission(inode, MAY_WRITE, NULL) != 0)
 		    && (current->uid != server->m.mounted_uid)) {
 			return -EACCES;
 		}
@@ -99,7 +99,7 @@
 		{
 			struct ncp_fs_info info;
 
-			if ((permission(inode, MAY_WRITE) != 0)
+			if ((permission(inode, MAY_WRITE, NULL) != 0)
 			    && (current->uid != server->m.mounted_uid)) {
 				return -EACCES;
 			}
@@ -127,7 +127,7 @@
 		{
 			struct ncp_fs_info_v2 info2;
 
-			if ((permission(inode, MAY_WRITE) != 0)
+			if ((permission(inode, MAY_WRITE, NULL) != 0)
 			    && (current->uid != server->m.mounted_uid)) {
 				return -EACCES;
 			}
@@ -155,7 +155,7 @@
 		{
 			unsigned long tmp = server->m.mounted_uid;
 
-			if (   (permission(inode, MAY_READ) != 0)
+			if (   (permission(inode, MAY_READ, NULL) != 0)
 			    && (current->uid != server->m.mounted_uid))
 			{
 				return -EACCES;
@@ -169,7 +169,7 @@
 		{
 			struct ncp_setroot_ioctl sr;
 
-			if (   (permission(inode, MAY_READ) != 0)
+			if (   (permission(inode, MAY_READ, NULL) != 0)
 			    && (current->uid != server->m.mounted_uid))
 			{
 				return -EACCES;
@@ -249,7 +249,7 @@
 
 #ifdef CONFIG_NCPFS_PACKET_SIGNING	
 	case NCP_IOC_SIGN_INIT:
-		if ((permission(inode, MAY_WRITE) != 0)
+		if ((permission(inode, MAY_WRITE, NULL) != 0)
 		    && (current->uid != server->m.mounted_uid))
 		{
 			return -EACCES;
@@ -272,7 +272,7 @@
 		return 0;		
 		
         case NCP_IOC_SIGN_WANTED:
-		if (   (permission(inode, MAY_READ) != 0)
+		if (   (permission(inode, MAY_READ, NULL) != 0)
 		    && (current->uid != server->m.mounted_uid))
 		{
 			return -EACCES;
@@ -285,7 +285,7 @@
 		{
 			int newstate;
 
-			if (   (permission(inode, MAY_WRITE) != 0)
+			if (   (permission(inode, MAY_WRITE, NULL) != 0)
 			    && (current->uid != server->m.mounted_uid))
 			{
 				return -EACCES;
@@ -306,7 +306,7 @@
 
 #ifdef CONFIG_NCPFS_IOCTL_LOCKING
 	case NCP_IOC_LOCKUNLOCK:
-		if (   (permission(inode, MAY_WRITE) != 0)
+		if (   (permission(inode, MAY_WRITE, NULL) != 0)
 		    && (current->uid != server->m.mounted_uid))
 		{
 			return -EACCES;
@@ -608,7 +608,7 @@
 		}
 #endif /* CONFIG_NCPFS_NLS */
 	case NCP_IOC_SETDENTRYTTL:
-		if ((permission(inode, MAY_WRITE) != 0) &&
+		if ((permission(inode, MAY_WRITE, NULL) != 0) &&
 				 (current->uid != server->m.mounted_uid))
 			return -EACCES;
 		{
@@ -637,7 +637,7 @@
 	/* NCP_IOC_GETMOUNTUID may be same as NCP_IOC_GETMOUNTUID2,
            so we have this out of switch */
 	if (cmd == NCP_IOC_GETMOUNTUID) {
-		if ((permission(inode, MAY_READ) != 0)
+		if ((permission(inode, MAY_READ, NULL) != 0)
 		    && (current->uid != server->m.mounted_uid)) {
 			return -EACCES;
 		}
diff -Nru a/fs/nfs/dir.c b/fs/nfs/dir.c
--- a/fs/nfs/dir.c	Wed Jun 25 16:30:54 2003
+++ b/fs/nfs/dir.c	Mon Jun 30 07:19:26 2003
@@ -37,10 +37,10 @@
 
 static int nfs_opendir(struct inode *, struct file *);
 static int nfs_readdir(struct file *, void *, filldir_t);
-static struct dentry *nfs_lookup(struct inode *, struct dentry *);
+static struct dentry *nfs_lookup(struct inode *, struct dentry *, struct nameidata *);
 static int nfs_cached_lookup(struct inode *, struct dentry *,
 				struct nfs_fh *, struct nfs_fattr *);
-static int nfs_create(struct inode *, struct dentry *, int);
+static int nfs_create(struct inode *, struct dentry *, int, struct nameidata *);
 static int nfs_mkdir(struct inode *, struct dentry *, int);
 static int nfs_rmdir(struct inode *, struct dentry *);
 static int nfs_unlink(struct inode *, struct dentry *);
@@ -78,13 +78,9 @@
 static int
 nfs_opendir(struct inode *inode, struct file *filp)
 {
-	struct nfs_server *server = NFS_SERVER(inode);
 	int res = 0;
 
 	lock_kernel();
-	/* Do cto revalidation */
-	if (!(server->flags & NFS_MOUNT_NOCTO))
-		res = __nfs_revalidate_inode(server, inode);
 	/* Call generic open code in order to cache credentials */
 	if (!res)
 		res = nfs_open(inode, filp);
@@ -485,9 +481,13 @@
 }
 
 static inline
-int nfs_lookup_verify_inode(struct inode *inode)
+int nfs_lookup_verify_inode(struct inode *inode, int isopen)
 {
-	return nfs_revalidate_inode(NFS_SERVER(inode), inode);
+	struct nfs_server *server = NFS_SERVER(inode);
+
+	if (isopen && !(server->flags & NFS_MOUNT_NOCTO))
+		return __nfs_revalidate_inode(server, inode);
+	return nfs_revalidate_inode(server, inode);
 }
 
 /*
@@ -497,8 +497,17 @@
  * If parent mtime has changed, we revalidate, else we wait for a
  * period corresponding to the parent's attribute cache timeout value.
  */
-static inline int nfs_neg_need_reval(struct inode *dir, struct dentry *dentry)
+static inline
+int nfs_neg_need_reval(struct inode *dir, struct dentry *dentry,
+		       struct nameidata *nd)
 {
+	int ndflags = 0;
+
+	if (nd)
+		ndflags = nd->flags;
+	/* Don't revalidate a negative dentry if we're creating a new file */
+	if ((ndflags & LOOKUP_CREATE) && !(ndflags & LOOKUP_CONTINUE))
+		return 0;
 	if (!nfs_check_verifier(dir, dentry))
 		return 1;
 	return time_after(jiffies, dentry->d_time + NFS_ATTRTIMEO(dir));
@@ -515,7 +524,7 @@
  * If the parent directory is seen to have changed, we throw out the
  * cached dentry and do a new lookup.
  */
-static int nfs_lookup_revalidate(struct dentry * dentry, int flags)
+static int nfs_lookup_revalidate(struct dentry * dentry, struct nameidata *nd)
 {
 	struct inode *dir;
 	struct inode *inode;
@@ -523,14 +532,18 @@
 	int error;
 	struct nfs_fh fhandle;
 	struct nfs_fattr fattr;
+	int isopen = 0;
 
 	parent = dget_parent(dentry);
 	lock_kernel();
 	dir = parent->d_inode;
 	inode = dentry->d_inode;
 
+	if (nd && !(nd->flags & LOOKUP_CONTINUE) && (nd->flags & LOOKUP_OPEN))
+		isopen = 1;
+
 	if (!inode) {
-		if (nfs_neg_need_reval(dir, dentry))
+		if (nfs_neg_need_reval(dir, dentry, nd))
 			goto out_bad;
 		goto out_valid;
 	}
@@ -543,7 +556,7 @@
 
 	/* Force a full look up iff the parent directory has changed */
 	if (nfs_check_verifier(dir, dentry)) {
-		if (nfs_lookup_verify_inode(inode))
+		if (nfs_lookup_verify_inode(inode, isopen))
 			goto out_bad;
 		goto out_valid;
 	}
@@ -552,7 +565,7 @@
 	if (!error) {
 		if (memcmp(NFS_FH(inode), &fhandle, sizeof(struct nfs_fh))!= 0)
 			goto out_bad;
-		if (nfs_lookup_verify_inode(inode))
+		if (nfs_lookup_verify_inode(inode, isopen))
 			goto out_bad;
 		goto out_valid_renew;
 	}
@@ -630,7 +643,17 @@
 	.d_iput		= nfs_dentry_iput,
 };
 
-static struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry)
+static inline
+int nfs_is_exclusive_create(struct inode *dir, struct nameidata *nd)
+{
+	if (NFS_PROTO(dir)->version == 2)
+		return 0;
+	if (!nd || (nd->flags & LOOKUP_CONTINUE) || !(nd->flags & LOOKUP_CREATE))
+		return 0;
+	return (nd->intent.open.flags & O_EXCL) != 0;
+}
+
+static struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, struct nameidata *nd)
 {
 	struct inode *inode = NULL;
 	int error;
@@ -647,6 +670,10 @@
 	error = -ENOMEM;
 	dentry->d_op = &nfs_dentry_operations;
 
+	/* If we're doing an exclusive create, optimize away the lookup */
+	if (nfs_is_exclusive_create(dir, nd))
+		return NULL;
+
 	lock_kernel();
 	error = nfs_cached_lookup(dir, dentry, &fhandle, &fattr);
 	if (!error) {
@@ -787,12 +814,14 @@
  * that the operation succeeded on the server, but an error in the
  * reply path made it appear to have failed.
  */
-static int nfs_create(struct inode *dir, struct dentry *dentry, int mode)
+static int nfs_create(struct inode *dir, struct dentry *dentry, int mode,
+		struct nameidata *nd)
 {
 	struct iattr attr;
 	struct nfs_fattr fattr;
 	struct nfs_fh fhandle;
 	int error;
+	int open_flags = 0;
 
 	dfprintk(VFS, "NFS: create(%s/%ld, %s\n", dir->i_sb->s_id, 
 		dir->i_ino, dentry->d_name.name);
@@ -800,6 +829,9 @@
 	attr.ia_mode = mode;
 	attr.ia_valid = ATTR_MODE;
 
+	if (nd && (nd->flags & LOOKUP_CREATE))
+		open_flags = nd->intent.open.flags;
+
 	/*
 	 * The 0 argument passed into the create function should one day
 	 * contain the O_EXCL flag if requested. This allows NFSv3 to
@@ -809,7 +841,7 @@
 	lock_kernel();
 	nfs_zap_caches(dir);
 	error = NFS_PROTO(dir)->create(dir, &dentry->d_name,
-					 &attr, 0, &fhandle, &fattr);
+					 &attr, open_flags, &fhandle, &fattr);
 	if (!error)
 		error = nfs_instantiate(dentry, &fhandle, &fattr);
 	else
@@ -1239,12 +1271,19 @@
 }
 
 int
-nfs_permission(struct inode *inode, int mask)
+nfs_permission(struct inode *inode, int mask, struct nameidata *nd)
 {
 	struct nfs_access_cache *cache = &NFS_I(inode)->cache_access;
 	struct rpc_cred *cred;
 	int mode = inode->i_mode;
 	int res;
+
+	/* Are we checking permissions on anything other than lookup? */
+	if (!(mask & MAY_EXEC)) {
+		/* We only need to check permissions on file open() and access() */
+		if (!nd || !(nd->flags & (LOOKUP_OPEN|LOOKUP_ACCESS)))
+			return 0;
+	}
 
 	if (mask & MAY_WRITE) {
 		/*
diff -Nru a/fs/nfs/file.c b/fs/nfs/file.c
--- a/fs/nfs/file.c	Wed May  7 03:34:41 2003
+++ b/fs/nfs/file.c	Sun Jun 29 23:49:50 2003
@@ -82,9 +82,6 @@
 	/* Do NFSv4 open() call */
 	if ((open = server->rpc_ops->file_open) != NULL)
 		res = open(inode, filp);
-	/* Do cto revalidation */
-	else if (!(server->flags & NFS_MOUNT_NOCTO))
-		res = __nfs_revalidate_inode(server, inode);
 	/* Call generic open code in order to cache credentials */
 	if (!res)
 		res = nfs_open(inode, filp);
@@ -104,11 +101,13 @@
 
 	dfprintk(VFS, "nfs: flush(%s/%ld)\n", inode->i_sb->s_id, inode->i_ino);
 
+	lock_kernel();
 	status = nfs_wb_file(inode, file);
 	if (!status) {
 		status = file->f_error;
 		file->f_error = 0;
 	}
+	unlock_kernel();
 	return status;
 }
 
diff -Nru a/fs/nfsd/nfsfh.c b/fs/nfsd/nfsfh.c
--- a/fs/nfsd/nfsfh.c	Tue Jun 17 16:31:29 2003
+++ b/fs/nfsd/nfsfh.c	Sun Jun 29 23:49:26 2003
@@ -56,7 +56,7 @@
 		/* make sure parents give x permission to user */
 		int err;
 		parent = dget_parent(tdentry);
-		err = permission(parent->d_inode, S_IXOTH);
+		err = permission(parent->d_inode, S_IXOTH, NULL);
 		if (err < 0) {
 			dput(parent);
 			break;
diff -Nru a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
--- a/fs/nfsd/vfs.c	Fri Jun 20 13:16:06 2003
+++ b/fs/nfsd/vfs.c	Sun Jun 29 23:49:26 2003
@@ -924,7 +924,7 @@
 	err = nfserr_perm;
 	switch (type) {
 	case S_IFREG:
-		err = vfs_create(dirp, dchild, iap->ia_mode);
+		err = vfs_create(dirp, dchild, iap->ia_mode, NULL);
 		break;
 	case S_IFDIR:
 		err = vfs_mkdir(dirp, dchild, iap->ia_mode);
@@ -1067,7 +1067,7 @@
 		goto out;
 	}
 
-	err = vfs_create(dirp, dchild, iap->ia_mode);
+	err = vfs_create(dirp, dchild, iap->ia_mode, NULL);
 	if (err < 0)
 		goto out_nfserr;
 
@@ -1584,12 +1584,12 @@
 	    inode->i_uid == current->fsuid)
 		return 0;
 
-	err = permission(inode, acc & (MAY_READ|MAY_WRITE|MAY_EXEC));
+	err = permission(inode, acc & (MAY_READ|MAY_WRITE|MAY_EXEC), NULL);
 
 	/* Allow read access to binaries even when mode 111 */
 	if (err == -EACCES && S_ISREG(inode->i_mode) &&
 	    acc == (MAY_READ | MAY_OWNER_OVERRIDE))
-		err = permission(inode, MAY_EXEC);
+		err = permission(inode, MAY_EXEC, NULL);
 
 	return err? nfserrno(err) : 0;
 }
diff -Nru a/fs/ntfs/namei.c b/fs/ntfs/namei.c
--- a/fs/ntfs/namei.c	Wed Apr 30 05:51:58 2003
+++ b/fs/ntfs/namei.c	Thu Jul  3 06:36:44 2003
@@ -29,6 +29,7 @@
  * ntfs_lookup - find the inode represented by a dentry in a directory inode
  * @dir_ino:	directory inode in which to look for the inode
  * @dent:	dentry representing the inode to look for
+ * @nd:		lookup nameidata
  *
  * In short, ntfs_lookup() looks for the inode represented by the dentry @dent
  * in the directory inode @dir_ino and if found attaches the inode to the
@@ -87,7 +88,7 @@
  *    name. We then convert the name to the current NLS code page, and proceed
  *    searching for a dentry with this name, etc, as in case 2), above.
  */
-static struct dentry *ntfs_lookup(struct inode *dir_ino, struct dentry *dent)
+static struct dentry *ntfs_lookup(struct inode *dir_ino, struct dentry *dent, struct nameidata *nd)
 {
 	ntfs_volume *vol = NTFS_SB(dir_ino->i_sb);
 	struct inode *dent_inode;
diff -Nru a/fs/open.c b/fs/open.c
--- a/fs/open.c	Fri Jun 20 13:16:06 2003
+++ b/fs/open.c	Sun Jun 29 23:49:26 2003
@@ -219,7 +219,7 @@
 	if (!S_ISREG(inode->i_mode))
 		goto dput_and_out;
 
-	error = permission(inode,MAY_WRITE);
+	error = permission(inode,MAY_WRITE,&nd);
 	if (error)
 		goto dput_and_out;
 
@@ -365,7 +365,7 @@
 		newattrs.ia_valid |= ATTR_ATIME_SET | ATTR_MTIME_SET;
 	} else {
 		if (current->fsuid != inode->i_uid &&
-		    (error = permission(inode,MAY_WRITE)) != 0)
+		    (error = permission(inode,MAY_WRITE,&nd)) != 0)
 			goto dput_and_out;
 	}
 	down(&inode->i_sem);
@@ -410,7 +410,7 @@
 		newattrs.ia_valid |= ATTR_ATIME_SET | ATTR_MTIME_SET;
 	} else {
 		if (current->fsuid != inode->i_uid &&
-		    (error = permission(inode,MAY_WRITE)) != 0)
+		    (error = permission(inode,MAY_WRITE,&nd)) != 0)
 			goto dput_and_out;
 	}
 	down(&inode->i_sem);
@@ -467,9 +467,9 @@
 	else
 		current->cap_effective = current->cap_permitted;
 
-	res = user_path_walk(filename, &nd);
+	res = __user_walk(filename, LOOKUP_FOLLOW|LOOKUP_ACCESS, &nd);
 	if (!res) {
-		res = permission(nd.dentry->d_inode, mode);
+		res = permission(nd.dentry->d_inode, mode, &nd);
 		/* SuS v2 requires we report a read only fs too */
 		if(!res && (mode & S_IWOTH) && IS_RDONLY(nd.dentry->d_inode)
 		   && !special_file(nd.dentry->d_inode->i_mode))
@@ -493,7 +493,7 @@
 	if (error)
 		goto out;
 
-	error = permission(nd.dentry->d_inode,MAY_EXEC);
+	error = permission(nd.dentry->d_inode,MAY_EXEC,&nd);
 	if (error)
 		goto dput_and_out;
 
@@ -526,7 +526,7 @@
 	if (!S_ISDIR(inode->i_mode))
 		goto out_putf;
 
-	error = permission(inode, MAY_EXEC);
+	error = permission(inode, MAY_EXEC, NULL);
 	if (!error)
 		set_fs_pwd(current->fs, mnt, dentry);
 out_putf:
@@ -544,7 +544,7 @@
 	if (error)
 		goto out;
 
-	error = permission(nd.dentry->d_inode,MAY_EXEC);
+	error = permission(nd.dentry->d_inode,MAY_EXEC,&nd);
 	if (error)
 		goto dput_and_out;
 
@@ -952,11 +952,8 @@
 		return 0;
 	}
 	retval = 0;
-	if (filp->f_op && filp->f_op->flush) {
-		lock_kernel();
+	if (filp->f_op && filp->f_op->flush)
 		retval = filp->f_op->flush(filp);
-		unlock_kernel();
-	}
 	dnotify_flush(filp, id);
 	locks_remove_posix(filp, id);
 	fput(filp);
diff -Nru a/fs/openpromfs/inode.c b/fs/openpromfs/inode.c
--- a/fs/openpromfs/inode.c	Sun May 25 20:01:15 2003
+++ b/fs/openpromfs/inode.c	Sun Jun 29 23:49:04 2003
@@ -59,9 +59,9 @@
 #define NODE2INO(node) (node + OPENPROM_FIRST_INO)
 #define NODEP2INO(no) (no + OPENPROM_FIRST_INO + last_node)
 
-static int openpromfs_create (struct inode *, struct dentry *, int);
+static int openpromfs_create (struct inode *, struct dentry *, int, struct nameidata *);
 static int openpromfs_readdir(struct file *, void *, filldir_t);
-static struct dentry *openpromfs_lookup(struct inode *, struct dentry *dentry);
+static struct dentry *openpromfs_lookup(struct inode *, struct dentry *dentry, struct nameidata *nd);
 static int openpromfs_unlink (struct inode *, struct dentry *dentry);
 
 static ssize_t nodenum_read(struct file *file, char *buf,
@@ -639,7 +639,7 @@
 	return 0;
 }
 
-static struct dentry *openpromfs_lookup(struct inode * dir, struct dentry *dentry)
+static struct dentry *openpromfs_lookup(struct inode * dir, struct dentry *dentry, struct nameidata *nd)
 {
 	int ino = 0;
 #define OPFSL_DIR	0
@@ -854,7 +854,8 @@
 	return 0;
 }
 
-static int openpromfs_create (struct inode *dir, struct dentry *dentry, int mode)
+static int openpromfs_create (struct inode *dir, struct dentry *dentry, int mode,
+		struct nameidata *nd)
 {
 	char *p;
 	struct inode *inode;
diff -Nru a/fs/proc/base.c b/fs/proc/base.c
--- a/fs/proc/base.c	Fri Jun 20 13:16:23 2003
+++ b/fs/proc/base.c	Sun Jul  6 18:06:49 2003
@@ -334,7 +334,7 @@
 	goto exit;
 }
 
-static int proc_permission(struct inode *inode, int mask)
+static int proc_permission(struct inode *inode, int mask, struct nameidata *nd)
 {
 	if (vfs_permission(inode, mask) != 0)
 		return -EACCES;
@@ -864,7 +864,7 @@
  * directory. In this case, however, we can do it - no aliasing problems
  * due to the way we treat inodes.
  */
-static int pid_revalidate(struct dentry * dentry, int flags)
+static int pid_revalidate(struct dentry * dentry, struct nameidata *nd)
 {
 	if (pid_alive(proc_task(dentry->d_inode)))
 		return 1;
@@ -872,7 +872,7 @@
 	return 0;
 }
 
-static int pid_fd_revalidate(struct dentry * dentry, int flags)
+static int pid_fd_revalidate(struct dentry * dentry, struct nameidata *nd)
 {
 	struct task_struct *task = proc_task(dentry->d_inode);
 	int fd = proc_type(dentry->d_inode) - PROC_PID_FD_DIR;
@@ -961,7 +961,7 @@
 }
 
 /* SMP-safe */
-static struct dentry *proc_lookupfd(struct inode * dir, struct dentry * dentry)
+static struct dentry *proc_lookupfd(struct inode * dir, struct dentry * dentry, struct nameidata *nd)
 {
 	struct task_struct *task = proc_task(dir);
 	unsigned fd = name_to_int(dentry);
@@ -1219,7 +1219,7 @@
 	return ERR_PTR(error);
 }
 
-static struct dentry *proc_base_lookup(struct inode *dir, struct dentry *dentry){
+static struct dentry *proc_base_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd){
 	return proc_pident_lookup(dir, dentry, base_stuff);
 }
 
@@ -1245,7 +1245,9 @@
 	.readdir	= proc_attr_readdir,
 };
 
-static struct dentry *proc_attr_lookup(struct inode *dir, struct dentry *dentry){
+static struct dentry *proc_attr_lookup(struct inode *dir,
+				struct dentry *dentry, struct nameidata *nd)
+{
 	return proc_pident_lookup(dir, dentry, attr_stuff);
 }
 
@@ -1326,7 +1328,7 @@
 }
 
 /* SMP-safe */
-struct dentry *proc_pid_lookup(struct inode *dir, struct dentry * dentry)
+struct dentry *proc_pid_lookup(struct inode *dir, struct dentry * dentry, struct nameidata *nd)
 {
 	struct task_struct *task;
 	struct inode *inode;
diff -Nru a/fs/proc/generic.c b/fs/proc/generic.c
--- a/fs/proc/generic.c	Fri Apr 25 08:46:19 2003
+++ b/fs/proc/generic.c	Thu Jul  3 06:36:44 2003
@@ -336,7 +336,7 @@
  * Don't create negative dentries here, return -ENOENT by hand
  * instead.
  */
-struct dentry *proc_lookup(struct inode * dir, struct dentry *dentry)
+struct dentry *proc_lookup(struct inode * dir, struct dentry *dentry, struct nameidata *nd)
 {
 	struct inode *inode = NULL;
 	struct proc_dir_entry * de;
diff -Nru a/fs/proc/proc_misc.c b/fs/proc/proc_misc.c
--- a/fs/proc/proc_misc.c	Tue Jun 24 08:42:14 2003
+++ b/fs/proc/proc_misc.c	Wed Jul  2 21:21:25 2003
@@ -497,11 +497,10 @@
 static int locks_read_proc(char *page, char **start, off_t off,
 				 int count, int *eof, void *data)
 {
-	int len;
-	lock_kernel();
-	len = get_locks_status(page, start, off, count);
-	unlock_kernel();
-	if (len < count) *eof = 1;
+	int len = get_locks_status(page, start, off, count);
+
+	if (len < count)
+		*eof = 1;
 	return len;
 }
 
diff -Nru a/fs/proc/root.c b/fs/proc/root.c
--- a/fs/proc/root.c	Sun May 25 18:48:57 2003
+++ b/fs/proc/root.c	Thu Jul  3 06:36:44 2003
@@ -79,19 +79,21 @@
 	proc_bus = proc_mkdir("bus", 0);
 }
 
-static struct dentry *proc_root_lookup(struct inode * dir, struct dentry * dentry)
+static struct dentry *proc_root_lookup(struct inode * dir, struct dentry * dentry, struct nameidata *nd)
 {
-	if (dir->i_ino == PROC_ROOT_INO) { /* check for safety... */
-		lock_kernel();
+	/*
+	 * nr_threads is actually protected by the tasklist_lock;
+	 * however, it's conventional to do reads, especially for
+	 * reporting, without any locking whatsoever.
+	 */
+	if (dir->i_ino == PROC_ROOT_INO) /* check for safety... */
 		dir->i_nlink = proc_root.nlink + nr_threads;
-		unlock_kernel();
-	}
 
-	if (!proc_lookup(dir, dentry)) {
+	if (!proc_lookup(dir, dentry, nd)) {
 		return NULL;
 	}
 	
-	return proc_pid_lookup(dir, dentry);
+	return proc_pid_lookup(dir, dentry, nd);
 }
 
 static int proc_root_readdir(struct file * filp,
diff -Nru a/fs/qnx4/namei.c b/fs/qnx4/namei.c
--- a/fs/qnx4/namei.c	Thu May 23 06:18:54 2002
+++ b/fs/qnx4/namei.c	Sun Jun 29 23:49:04 2003
@@ -107,7 +107,7 @@
 	return NULL;
 }
 
-struct dentry * qnx4_lookup(struct inode *dir, struct dentry *dentry)
+struct dentry * qnx4_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
 {
 	int ino;
 	struct qnx4_inode_entry *de;
@@ -142,7 +142,8 @@
 }
 
 #ifdef CONFIG_QNX4FS_RW
-int qnx4_create(struct inode *dir, struct dentry *dentry, int mode)
+int qnx4_create(struct inode *dir, struct dentry *dentry, int mode,
+		struct nameidata *nd)
 {
 	QNX4DEBUG(("qnx4: qnx4_create\n"));
 	if (dir == NULL) {
diff -Nru a/fs/ramfs/inode.c b/fs/ramfs/inode.c
--- a/fs/ramfs/inode.c	Sun May 25 19:19:54 2003
+++ b/fs/ramfs/inode.c	Sun Jun 29 23:49:04 2003
@@ -111,7 +111,7 @@
 	return retval;
 }
 
-static int ramfs_create(struct inode *dir, struct dentry *dentry, int mode)
+static int ramfs_create(struct inode *dir, struct dentry *dentry, int mode, struct nameidata *nd)
 {
 	return ramfs_mknod(dir, dentry, mode | S_IFREG, 0);
 }
@@ -146,6 +146,7 @@
 	.mmap		= generic_file_mmap,
 	.fsync		= simple_sync_file,
 	.sendfile	= generic_file_sendfile,
+	.llseek		= generic_file_llseek,
 };
 
 static struct inode_operations ramfs_file_inode_operations = {
diff -Nru a/fs/reiserfs/namei.c b/fs/reiserfs/namei.c
--- a/fs/reiserfs/namei.c	Sat Dec  7 02:19:52 2002
+++ b/fs/reiserfs/namei.c	Sun Jun 29 23:49:04 2003
@@ -316,7 +316,7 @@
 }
 
 
-static struct dentry * reiserfs_lookup (struct inode * dir, struct dentry * dentry)
+static struct dentry * reiserfs_lookup (struct inode * dir, struct dentry * dentry, struct nameidata *nd)
 {
     int retval;
     struct inode * inode = NULL;
@@ -558,7 +558,8 @@
     return 0 ;
 }
 
-static int reiserfs_create (struct inode * dir, struct dentry *dentry, int mode)
+static int reiserfs_create (struct inode * dir, struct dentry *dentry, int mode,
+		struct nameidata *nd)
 {
     int retval;
     struct inode * inode;
diff -Nru a/fs/romfs/inode.c b/fs/romfs/inode.c
--- a/fs/romfs/inode.c	Fri Jun 20 13:16:06 2003
+++ b/fs/romfs/inode.c	Thu Jul  3 06:36:44 2003
@@ -329,7 +329,7 @@
 }
 
 static struct dentry *
-romfs_lookup(struct inode *dir, struct dentry *dentry)
+romfs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
 {
 	unsigned long offset, maxoff;
 	int fslen, res;
diff -Nru a/fs/smbfs/dir.c b/fs/smbfs/dir.c
--- a/fs/smbfs/dir.c	Wed Apr  2 22:51:32 2003
+++ b/fs/smbfs/dir.c	Sun Jun 29 23:49:04 2003
@@ -24,8 +24,8 @@
 static int smb_readdir(struct file *, void *, filldir_t);
 static int smb_dir_open(struct inode *, struct file *);
 
-static struct dentry *smb_lookup(struct inode *, struct dentry *);
-static int smb_create(struct inode *, struct dentry *, int);
+static struct dentry *smb_lookup(struct inode *, struct dentry *, struct nameidata *);
+static int smb_create(struct inode *, struct dentry *, int, struct nameidata *);
 static int smb_mkdir(struct inode *, struct dentry *, int);
 static int smb_rmdir(struct inode *, struct dentry *);
 static int smb_unlink(struct inode *, struct dentry *);
@@ -268,7 +268,7 @@
 /*
  * Dentry operations routines
  */
-static int smb_lookup_validate(struct dentry *, int);
+static int smb_lookup_validate(struct dentry *, struct nameidata *);
 static int smb_hash_dentry(struct dentry *, struct qstr *);
 static int smb_compare_dentry(struct dentry *, struct qstr *, struct qstr *);
 static int smb_delete_dentry(struct dentry *);
@@ -292,7 +292,7 @@
  * This is the callback when the dcache has a lookup hit.
  */
 static int
-smb_lookup_validate(struct dentry * dentry, int flags)
+smb_lookup_validate(struct dentry * dentry, struct nameidata *nd)
 {
 	struct smb_sb_info *server = server_from_dentry(dentry);
 	struct inode * inode = dentry->d_inode;
@@ -420,7 +420,7 @@
 }
 
 static struct dentry *
-smb_lookup(struct inode *dir, struct dentry *dentry)
+smb_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
 {
 	struct smb_fattr finfo;
 	struct inode *inode;
@@ -510,7 +510,8 @@
 
 /* N.B. How should the mode argument be used? */
 static int
-smb_create(struct inode *dir, struct dentry *dentry, int mode)
+smb_create(struct inode *dir, struct dentry *dentry, int mode,
+		struct nameidata *nd)
 {
 	struct smb_sb_info *server = server_from_dentry(dentry);
 	__u16 fileid;
diff -Nru a/fs/smbfs/file.c b/fs/smbfs/file.c
--- a/fs/smbfs/file.c	Sat Dec 14 09:42:09 2002
+++ b/fs/smbfs/file.c	Sun Jun 29 23:49:26 2003
@@ -367,7 +367,7 @@
  * privileges, so we need our own check for this.
  */
 static int
-smb_file_permission(struct inode *inode, int mask)
+smb_file_permission(struct inode *inode, int mask, struct nameidata *nd)
 {
 	int mode = inode->i_mode;
 	int error = 0;
diff -Nru a/fs/sysfs/bin.c b/fs/sysfs/bin.c
--- a/fs/sysfs/bin.c	Wed Jun 11 14:48:45 2003
+++ b/fs/sysfs/bin.c	Thu Jul  3 09:05:47 2003
@@ -2,6 +2,8 @@
  * bin.c - binary file operations for sysfs.
  */
 
+#undef DEBUG
+
 #include <linux/errno.h>
 #include <linux/fs.h>
 #include <linux/kobject.h>
@@ -42,18 +44,17 @@
 
 	ret = fill_read(dentry, buffer, offs, count);
 	if (ret < 0) 
-		goto Done;
+		return ret;
 	count = ret;
 
-	ret = -EFAULT;
-	if (copy_to_user(userbuf, buffer, count) != 0)
-		goto Done;
+	if (copy_to_user(userbuf, buffer + offs, count) != 0)
+		return -EINVAL;
+
+	pr_debug("offs = %lld, *off = %lld, count = %zd\n", offs, *off, count);
 
 	*off = offs + count;
-	ret = count;
 
- Done:
-	return ret;
+	return count;
 }
 
 static int
@@ -72,7 +73,6 @@
 	struct dentry *dentry = file->f_dentry;
 	int size = dentry->d_inode->i_size;
 	loff_t offs = *off;
-	int ret;
 
 	if (count > PAGE_SIZE)
 		count = PAGE_SIZE;
@@ -83,16 +83,13 @@
 			count = size - offs;
 	}
 
-	ret = -EFAULT;
-	if (copy_from_user(buffer, userbuf, count))
-		goto Done;
+	if (copy_from_user(buffer + offs, userbuf, count))
+		return -EFAULT;
 
 	count = flush_write(dentry, buffer, offs, count);
 	if (count > 0)
 		*off = offs + count;
-	ret = count;
- Done:
-	return ret;
+	return count;
 }
 
 static int open(struct inode * inode, struct file * file)
diff -Nru a/fs/sysfs/dir.c b/fs/sysfs/dir.c
--- a/fs/sysfs/dir.c	Tue Mar 11 13:30:18 2003
+++ b/fs/sysfs/dir.c	Thu Jul  3 10:41:51 2003
@@ -121,7 +121,29 @@
 	dput(parent);
 }
 
+void sysfs_rename_dir(struct kobject * kobj, char *new_name)
+{
+	struct dentry * new_dentry, * parent;
+
+	if (!strcmp(kobj->name, new_name))
+		return;
+
+	if (!kobj->parent)
+		return;
+
+	parent = kobj->parent->dentry;
+
+	down(&parent->d_inode->i_sem);
+
+	new_dentry = sysfs_get_dentry(parent, new_name);
+	d_move(kobj->dentry, new_dentry);
+
+	strlcpy(kobj->name, new_name, KOBJ_NAME_LEN);
+
+	up(&parent->d_inode->i_sem);	
+}
 
 EXPORT_SYMBOL(sysfs_create_dir);
 EXPORT_SYMBOL(sysfs_remove_dir);
+EXPORT_SYMBOL(sysfs_rename_dir);
 
diff -Nru a/fs/sysfs/file.c b/fs/sysfs/file.c
--- a/fs/sysfs/file.c	Wed Jun 11 14:48:45 2003
+++ b/fs/sysfs/file.c	Thu Jul  3 09:27:08 2003
@@ -247,6 +247,12 @@
 	if (!kobj || !attr)
 		goto Einval;
 
+	/* Grab the module reference for this attribute if we have one */
+	if (!try_module_get(attr->owner)) {
+		error = -ENODEV;
+		goto Done;
+	}
+
 	/* if the kobject has no ktype, then we assume that it is a subsystem
 	 * itself, and use ops for it.
 	 */
@@ -300,6 +306,7 @@
 	goto Done;
  Eaccess:
 	error = -EACCES;
+	module_put(attr->owner);
  Done:
 	if (error && kobj)
 		kobject_put(kobj);
@@ -314,10 +321,12 @@
 static int sysfs_release(struct inode * inode, struct file * filp)
 {
 	struct kobject * kobj = filp->f_dentry->d_parent->d_fsdata;
+	struct attribute * attr = filp->f_dentry->d_fsdata;
 	struct sysfs_buffer * buffer = filp->private_data;
 
 	if (kobj) 
 		kobject_put(kobj);
+	module_put(attr->owner);
 
 	if (buffer) {
 		if (buffer->page)
diff -Nru a/fs/sysv/namei.c b/fs/sysv/namei.c
--- a/fs/sysv/namei.c	Wed Nov 20 03:19:02 2002
+++ b/fs/sysv/namei.c	Sun Jun 29 23:49:04 2003
@@ -64,7 +64,7 @@
 	.d_hash		= sysv_hash,
 };
 
-static struct dentry *sysv_lookup(struct inode * dir, struct dentry * dentry)
+static struct dentry *sysv_lookup(struct inode * dir, struct dentry * dentry, struct nameidata *nd)
 {
 	struct inode * inode = NULL;
 	ino_t ino;
@@ -96,7 +96,7 @@
 	return err;
 }
 
-static int sysv_create(struct inode * dir, struct dentry * dentry, int mode)
+static int sysv_create(struct inode * dir, struct dentry * dentry, int mode, struct nameidata *nd)
 {
 	return sysv_mknod(dir, dentry, mode, 0);
 }
diff -Nru a/fs/udf/file.c b/fs/udf/file.c
--- a/fs/udf/file.c	Sat Dec 14 09:42:09 2002
+++ b/fs/udf/file.c	Sun Jun 29 23:49:26 2003
@@ -188,7 +188,7 @@
 {
 	int result = -EINVAL;
 
-	if ( permission(inode, MAY_READ) != 0 )
+	if ( permission(inode, MAY_READ, NULL) != 0 )
 	{
 		udf_debug("no permission to access inode %lu\n",
 						inode->i_ino);
diff -Nru a/fs/udf/namei.c b/fs/udf/namei.c
--- a/fs/udf/namei.c	Wed Nov 20 03:19:02 2002
+++ b/fs/udf/namei.c	Sun Jun 29 23:49:04 2003
@@ -289,6 +289,7 @@
  * PRE-CONDITIONS
  *	dir			Pointer to inode of parent directory.
  *	dentry			Pointer to dentry to complete.
+ *	nd			Pointer to lookup nameidata
  *
  * POST-CONDITIONS
  *	<return>		Zero on success.
@@ -299,7 +300,7 @@
  */
 
 static struct dentry *
-udf_lookup(struct inode *dir, struct dentry *dentry)
+udf_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
 {
 	struct inode *inode = NULL;
 	struct fileIdentDesc cfi, *fi;
@@ -620,7 +621,7 @@
 	return udf_write_fi(inode, cfi, fi, fibh, NULL, NULL);
 }
 
-static int udf_create(struct inode *dir, struct dentry *dentry, int mode)
+static int udf_create(struct inode *dir, struct dentry *dentry, int mode, struct nameidata *nd)
 {
 	struct udf_fileident_bh fibh;
 	struct inode *inode;
diff -Nru a/fs/ufs/namei.c b/fs/ufs/namei.c
--- a/fs/ufs/namei.c	Wed Nov 20 03:19:02 2002
+++ b/fs/ufs/namei.c	Sun Jun 29 23:49:04 2003
@@ -62,7 +62,7 @@
 	return err;
 }
 
-static struct dentry *ufs_lookup(struct inode * dir, struct dentry *dentry)
+static struct dentry *ufs_lookup(struct inode * dir, struct dentry *dentry, struct nameidata *nd)
 {
 	struct inode * inode = NULL;
 	ino_t ino;
@@ -92,7 +92,8 @@
  * If the create succeeds, we fill in the inode information
  * with d_instantiate(). 
  */
-static int ufs_create (struct inode * dir, struct dentry * dentry, int mode)
+static int ufs_create (struct inode * dir, struct dentry * dentry, int mode,
+		struct nameidata *nd)
 {
 	struct inode * inode = ufs_new_inode(dir, mode);
 	int err = PTR_ERR(inode);
diff -Nru a/fs/umsdos/dir.c b/fs/umsdos/dir.c
--- a/fs/umsdos/dir.c	Tue Nov  5 07:35:59 2002
+++ b/fs/umsdos/dir.c	Thu Jul  3 06:36:44 2003
@@ -30,7 +30,7 @@
  */
 
 /* nothing for now ... */
-static int umsdos_dentry_validate(struct dentry *dentry, int flags)
+static int umsdos_dentry_validate(struct dentry *dentry, struct nameidata *nd)
 {
 	return 1;
 }
@@ -564,7 +564,7 @@
  * Called by VFS; should fill dentry->d_inode via d_add.
  */
 
-struct dentry *UMSDOS_lookup (struct inode *dir, struct dentry *dentry)
+struct dentry *UMSDOS_lookup (struct inode *dir, struct dentry *dentry, struct nameidata *nd)
 {
 	struct dentry *ret;
 
diff -Nru a/fs/umsdos/emd.c b/fs/umsdos/emd.c
--- a/fs/umsdos/emd.c	Mon Apr 29 15:18:54 2002
+++ b/fs/umsdos/emd.c	Sun Jun 29 23:49:04 2003
@@ -105,7 +105,7 @@
 Printk(("umsdos_make_emd: creating EMD %s/%s\n",
 parent->d_name.name, demd->d_name.name));
 
-	err = msdos_create(parent->d_inode, demd, S_IFREG | 0777);
+	err = msdos_create(parent->d_inode, demd, S_IFREG | 0777, NULL);
 	if (err) {
 		printk (KERN_WARNING
 			"umsdos_make_emd: create %s/%s failed, err=%d\n",
diff -Nru a/fs/umsdos/namei.c b/fs/umsdos/namei.c
--- a/fs/umsdos/namei.c	Wed Nov 20 03:19:02 2002
+++ b/fs/umsdos/namei.c	Sun Jun 29 23:49:04 2003
@@ -274,7 +274,7 @@
 	if (fake->d_inode)
 		goto out_remove_dput;
 
-	ret = msdos_create (dir, fake, S_IFREG | 0777);
+	ret = msdos_create (dir, fake, S_IFREG | 0777, NULL);
 	if (ret)
 		goto out_remove_dput;
 
@@ -311,7 +311,7 @@
  * 
  * Return the status of the operation. 0 mean success.
  */
-int UMSDOS_create (struct inode *dir, struct dentry *dentry, int mode)
+int UMSDOS_create (struct inode *dir, struct dentry *dentry, int mode, struct nameidata *nd)
 {
 	return umsdos_create_any (dir, dentry, mode, 0, 0);
 }
diff -Nru a/fs/umsdos/rdir.c b/fs/umsdos/rdir.c
--- a/fs/umsdos/rdir.c	Tue Nov  5 07:35:59 2002
+++ b/fs/umsdos/rdir.c	Thu Jul  3 06:36:44 2003
@@ -101,7 +101,7 @@
 		goto out;
 	}
 
-	ret = msdos_lookup (dir, dentry);
+	ret = msdos_lookup (dir, dentry, NULL);
 	if (ret) {
 		printk(KERN_WARNING
 			"umsdos_rlookup_x: %s/%s failed, ret=%ld\n",
@@ -129,7 +129,7 @@
 }
 
 
-struct dentry *UMSDOS_rlookup ( struct inode *dir, struct dentry *dentry)
+struct dentry *UMSDOS_rlookup ( struct inode *dir, struct dentry *dentry, struct nameidata *nd)
 {
 	return umsdos_rlookup_x (dir, dentry, 0);
 }
diff -Nru a/fs/vfat/namei.c b/fs/vfat/namei.c
--- a/fs/vfat/namei.c	Tue May 27 07:32:40 2003
+++ b/fs/vfat/namei.c	Sun Jun 29 23:49:04 2003
@@ -45,7 +45,7 @@
 static int vfat_hash(struct dentry *parent, struct qstr *qstr);
 static int vfat_cmpi(struct dentry *dentry, struct qstr *a, struct qstr *b);
 static int vfat_cmp(struct dentry *dentry, struct qstr *a, struct qstr *b);
-static int vfat_revalidate(struct dentry *dentry, int);
+static int vfat_revalidate(struct dentry *dentry, struct nameidata *nd);
 
 static struct dentry_operations vfat_dentry_ops[4] = {
 	{
@@ -68,7 +68,7 @@
 	}
 };
 
-static int vfat_revalidate(struct dentry *dentry, int flags)
+static int vfat_revalidate(struct dentry *dentry, struct nameidata *nd)
 {
 	PRINTK1(("vfat_revalidate: %s\n", dentry->d_name.name));
 	spin_lock(&dcache_lock);
@@ -860,7 +860,7 @@
 	return res ? res : -ENOENT;
 }
 
-struct dentry *vfat_lookup(struct inode *dir,struct dentry *dentry)
+struct dentry *vfat_lookup(struct inode *dir,struct dentry *dentry, struct nameidata *nd)
 {
 	int res;
 	struct vfat_slot_info sinfo;
@@ -912,7 +912,8 @@
 	return dentry;
 }
 
-int vfat_create(struct inode *dir,struct dentry* dentry,int mode)
+int vfat_create(struct inode *dir,struct dentry* dentry,int mode,
+		struct nameidata *nd)
 {
 	struct super_block *sb = dir->i_sb;
 	struct inode *inode = NULL;
diff -Nru a/fs/xattr.c b/fs/xattr.c
--- a/fs/xattr.c	Tue May  6 07:02:55 2003
+++ b/fs/xattr.c	Fri Jul  4 22:16:53 2003
@@ -160,9 +160,7 @@
 		error = security_inode_getxattr(d, kname);
 		if (error)
 			goto out;
-		down(&d->d_inode->i_sem);
 		error = d->d_inode->i_op->getxattr(d, kname, kvalue, size);
-		up(&d->d_inode->i_sem);
 	}
 
 	if (kvalue && error > 0)
@@ -233,9 +231,7 @@
 		error = security_inode_listxattr(d);
 		if (error)
 			goto out;
-		down(&d->d_inode->i_sem);
 		error = d->d_inode->i_op->listxattr(d, klist, size);
-		up(&d->d_inode->i_sem);
 	}
 
 	if (klist && error > 0)
diff -Nru a/fs/xfs/linux/xfs_iops.c b/fs/xfs/linux/xfs_iops.c
--- a/fs/xfs/linux/xfs_iops.c	Thu Jun 19 11:39:57 2003
+++ b/fs/xfs/linux/xfs_iops.c	Fri Jul  4 22:16:53 2003
@@ -175,7 +175,8 @@
 linvfs_create(
 	struct inode	*dir,
 	struct dentry	*dentry,
-	int		mode)
+	int		mode,
+	struct nameidata *nd)
 {
 	return linvfs_mknod(dir, dentry, mode, 0);
 }
@@ -192,7 +193,8 @@
 STATIC struct dentry *
 linvfs_lookup(
 	struct inode	*dir,
-	struct dentry	*dentry)
+	struct dentry	*dentry,
+	struct nameidata *nd)
 {
 	struct inode	*ip = NULL;
 	vnode_t		*vp, *cvp = NULL;
@@ -429,7 +431,8 @@
 STATIC int
 linvfs_permission(
 	struct inode	*inode,
-	int		mode)
+	int		mode,
+	struct nameidata *nd)
 {
 	vnode_t		*vp = LINVFS_GET_VP(inode);
 	int		error;
@@ -639,7 +642,7 @@
 }
 
 STATIC ssize_t
-linvfs_getxattr(
+__linvfs_getxattr(
 	struct dentry	*dentry,
 	const char	*name,
 	void		*data,
@@ -694,9 +697,24 @@
 	return -EOPNOTSUPP;
 }
 
+STATIC ssize_t
+linvfs_getxattr(
+	struct dentry	*dentry,
+	const char	*name,
+	void		*data,
+	size_t		size)
+{
+	int error;
+
+	down(&dentry->d_inode->i_sem);
+	error = __linvfs_getxattr(dentry, name, data, size);
+	up(&dentry->d_inode->i_sem);
+
+	return error;
+}
 
 STATIC ssize_t
-linvfs_listxattr(
+__linvfs_listxattr(
 	struct dentry		*dentry,
 	char			*data,
 	size_t			size)
@@ -736,6 +754,21 @@
 		}
 	}
 	return result;
+}
+
+STATIC ssize_t
+linvfs_listxattr(
+	struct dentry		*dentry,
+	char			*data,
+	size_t			size)
+{
+	int error;
+
+	down(&dentry->d_inode->i_sem);
+	error = __linvfs_listxattr(dentry, data, size);
+	up(&dentry->d_inode->i_sem);
+
+	return error;
 }
 
 STATIC int
diff -Nru a/fs/xfs/linux/xfs_super.c b/fs/xfs/linux/xfs_super.c
--- a/fs/xfs/linux/xfs_super.c	Mon Jun 23 12:01:45 2003
+++ b/fs/xfs/linux/xfs_super.c	Sun Jul  6 11:13:41 2003
@@ -265,8 +265,8 @@
 
 	if (set_blocksize(btp->pbr_bdev, sectorsize)) {
 		printk(KERN_WARNING
-			"XFS: Cannot set_blocksize to %u on device 0x%x\n",
-			sectorsize, btp->pbr_dev);
+			"XFS: Cannot set_blocksize to %u on device 0x%lx\n",
+			sectorsize, (unsigned long)btp->pbr_dev);
 	}
 }
 
diff -Nru a/include/asm-alpha/div64.h b/include/asm-alpha/div64.h
--- a/include/asm-alpha/div64.h	Tue Feb  5 09:39:46 2002
+++ b/include/asm-alpha/div64.h	Thu Jul  3 00:37:22 2003
@@ -1,14 +1 @@
-#ifndef __ALPHA_DIV64
-#define __ALPHA_DIV64
-
-/*
- * Hey, we're already 64-bit, no
- * need to play games..
- */
-#define do_div(n,base) ({ \
-	int __res; \
-	__res = ((unsigned long) (n)) % (unsigned) (base); \
-	(n) = ((unsigned long) (n)) / (unsigned) (base); \
-	__res; })
-
-#endif
+#include <asm-generic/div64.h>
diff -Nru a/include/asm-alpha/machvec.h b/include/asm-alpha/machvec.h
--- a/include/asm-alpha/machvec.h	Wed Feb 19 11:26:51 2003
+++ b/include/asm-alpha/machvec.h	Sun Jul  6 18:51:59 2003
@@ -68,7 +68,7 @@
 	int (*mv_is_ioaddr)(unsigned long);
 
 	void (*mv_switch_mm)(struct mm_struct *, struct mm_struct *,
-			     struct task_struct *, long);
+			     struct task_struct *);
 	void (*mv_activate_mm)(struct mm_struct *, struct mm_struct *);
 
 	void (*mv_flush_tlb_current)(struct mm_struct *);
diff -Nru a/include/asm-alpha/mmu_context.h b/include/asm-alpha/mmu_context.h
--- a/include/asm-alpha/mmu_context.h	Mon Apr 14 16:35:04 2003
+++ b/include/asm-alpha/mmu_context.h	Sun Jul  6 18:51:59 2003
@@ -130,11 +130,12 @@
 
 __EXTERN_INLINE void
 ev5_switch_mm(struct mm_struct *prev_mm, struct mm_struct *next_mm,
-	      struct task_struct *next, long cpu)
+	      struct task_struct *next)
 {
 	/* Check if our ASN is of an older version, and thus invalid. */
 	unsigned long asn;
 	unsigned long mmc;
+	long cpu = smp_processor_id();
 
 #ifdef CONFIG_SMP
 	cpu_data[cpu].asn_lock = 1;
@@ -159,7 +160,7 @@
 
 __EXTERN_INLINE void
 ev4_switch_mm(struct mm_struct *prev_mm, struct mm_struct *next_mm,
-	      struct task_struct *next, long cpu)
+	      struct task_struct *next)
 {
 	/* As described, ASN's are broken for TLB usage.  But we can
 	   optimize for switching between threads -- if the mm is
@@ -174,7 +175,7 @@
 
 	/* Do continue to allocate ASNs, because we can still use them
 	   to avoid flushing the icache.  */
-	ev5_switch_mm(prev_mm, next_mm, next, cpu);
+	ev5_switch_mm(prev_mm, next_mm, next);
 }
 
 extern void __load_new_mm_context(struct mm_struct *);
@@ -212,14 +213,14 @@
 #define deactivate_mm(tsk,mm)	do { } while (0)
 
 #ifdef CONFIG_ALPHA_GENERIC
-# define switch_mm(a,b,c,d)	alpha_mv.mv_switch_mm((a),(b),(c),(d))
+# define switch_mm(a,b,c)	alpha_mv.mv_switch_mm((a),(b),(c))
 # define activate_mm(x,y)	alpha_mv.mv_activate_mm((x),(y))
 #else
 # ifdef CONFIG_ALPHA_EV4
-#  define switch_mm(a,b,c,d)	ev4_switch_mm((a),(b),(c),(d))
+#  define switch_mm(a,b,c)	ev4_switch_mm((a),(b),(c))
 #  define activate_mm(x,y)	ev4_activate_mm((x),(y))
 # else
-#  define switch_mm(a,b,c,d)	ev5_switch_mm((a),(b),(c),(d))
+#  define switch_mm(a,b,c)	ev5_switch_mm((a),(b),(c))
 #  define activate_mm(x,y)	ev5_activate_mm((x),(y))
 # endif
 #endif
@@ -245,7 +246,7 @@
 }
 
 static inline void
-enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk, unsigned cpu)
+enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
 {
 	tsk->thread_info->pcb.ptbr
 	  = ((unsigned long)mm->pgd - IDENT_ADDR) >> PAGE_SHIFT;
diff -Nru a/include/asm-alpha/mmzone.h b/include/asm-alpha/mmzone.h
--- a/include/asm-alpha/mmzone.h	Thu Apr  3 14:49:57 2003
+++ b/include/asm-alpha/mmzone.h	Wed Jul  2 21:20:53 2003
@@ -31,7 +31,6 @@
 
 #define pa_to_nid(pa)		alpha_pa_to_nid(pa)
 #define NODE_DATA(nid)		(&node_data[(nid)])
-#define node_size(nid)		(NODE_DATA(nid)->node_size)
 
 #define node_localnr(pfn, nid)	((pfn) - NODE_DATA(nid)->node_start_pfn)
 
@@ -124,7 +123,7 @@
 #define pfn_to_nid(pfn)		pa_to_nid(((u64)pfn << PAGE_SHIFT))
 #define pfn_valid(pfn)							\
 	(((pfn) - node_start_pfn(pfn_to_nid(pfn))) <			\
-	 node_size(pfn_to_nid(pfn)))					\
+	 node_spanned_pages(pfn_to_nid(pfn)))					\
 
 #define virt_addr_valid(kaddr)	pfn_valid((__pa(kaddr) >> PAGE_SHIFT))
 
diff -Nru a/include/asm-arm/mmu_context.h b/include/asm-arm/mmu_context.h
--- a/include/asm-arm/mmu_context.h	Thu Jan  9 23:21:00 2003
+++ b/include/asm-arm/mmu_context.h	Sun Jul  6 18:51:59 2003
@@ -28,7 +28,7 @@
  * tsk->mm will be NULL
  */
 static inline void
-enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk, unsigned cpu)
+enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
 {
 }
 
@@ -40,7 +40,7 @@
  */
 static inline void
 switch_mm(struct mm_struct *prev, struct mm_struct *next,
-	  struct task_struct *tsk, unsigned int cpu)
+	  struct task_struct *tsk)
 {
 	if (prev != next) {
 		cpu_switch_mm(next->pgd, next);
diff -Nru a/include/asm-arm26/arch.h b/include/asm-arm26/arch.h
--- a/include/asm-arm26/arch.h	Wed Jun  4 04:14:10 2003
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,62 +0,0 @@
-/*
- *  linux/include/asm-arm/mach/arch.h
- *
- *  Copyright (C) 2000 Russell King
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-/*
- * The size of struct machine_desc
- *   (for assembler code)
- * FIXME - I count 45... or is this padding?
- */
-#define SIZEOF_MACHINE_DESC	48
-
-#ifndef __ASSEMBLY__
-
-struct tag;
-
-struct machine_desc {
-	int			nr; /* arch no FIXME - get rid */
-	const char		*name;		/* architecture name	*/
-	unsigned int		param_offset;	/* parameter page	*/
-
-	unsigned int		video_start;	/* start of video RAM	*/
-	unsigned int		video_end;	/* end of video RAM	*/
-
-	unsigned int		reserve_lp0 :1;	/* never has lp0	*/
-	unsigned int		reserve_lp1 :1;	/* never has lp1	*/
-	unsigned int		reserve_lp2 :1;	/* never has lp2	*/
-	unsigned int		soft_reboot :1;	/* soft reboot		*/
-	void			(*fixup)(struct machine_desc *,
-					 struct tag *, char **,
-					 struct meminfo *);
-	void			(*map_io)(void);/* IO mapping function	*/
-	void			(*init_irq)(void);
-};
-
-/*
- * Set of macros to define architecture features.  This is built into
- * a table by the linker.
- */
-#define MACHINE_START(_type,_name)		\
-const struct machine_desc __mach_desc_##_type	\
- __attribute__((__section__(".arch.info"))) = {	\
-	nr:		MACH_TYPE_##_type,	\
-	name:		_name,
-
-#define MAINTAINER(n)
-
-#define BOOT_PARAMS(_params)			\
-	param_offset:	_params,
-
-#define INITIRQ(_func)				\
-	init_irq:	_func,
-
-#define MACHINE_END				\
-};
-
-#endif
diff -Nru a/include/asm-arm26/bug.h b/include/asm-arm26/bug.h
--- a/include/asm-arm26/bug.h	Wed Jun  4 04:14:10 2003
+++ b/include/asm-arm26/bug.h	Sun Jul  6 16:40:01 2003
@@ -4,7 +4,7 @@
 #include <linux/config.h>
 
 #ifdef CONFIG_DEBUG_BUGVERBOSE
-extern void __bug(const char *file, int line, void *data);
+extern volatile void __bug(const char *file, int line, void *data);
 
 /* give file/line information */
 #define BUG()		__bug(__FILE__, __LINE__, NULL)
@@ -17,5 +17,14 @@
 #define PAGE_BUG(page)	(*(int *)0 = 0)
 
 #endif
+
+#define BUG_ON(condition) do { if (unlikely((condition)!=0)) BUG(); } while(0)
+
+#define WARN_ON(condition) do { \
+	if (unlikely((condition)!=0)) { \
+		printk("Badness in %s at %s:%d\n", __FUNCTION__, __FILE__, __LINE__); \
+		dump_stack(); \
+	} \
+} while (0)
 
 #endif
diff -Nru a/include/asm-arm26/bugs.h b/include/asm-arm26/bugs.h
--- a/include/asm-arm26/bugs.h	Wed Jun  4 04:14:10 2003
+++ b/include/asm-arm26/bugs.h	Sun Jul  6 16:40:01 2003
@@ -1,5 +1,5 @@
 /*
- *  linux/include/asm-arm/bugs.h
+ *  linux/include/asm-arm26/bugs.h
  *
  *  Copyright (C) 1995  Russell King
  *
diff -Nru a/include/asm-arm26/div64.h b/include/asm-arm26/div64.h
--- a/include/asm-arm26/div64.h	Wed Jun  4 04:14:10 2003
+++ b/include/asm-arm26/div64.h	Thu Jul  3 00:37:22 2003
@@ -1,14 +1 @@
-#ifndef __ASM_ARM_DIV64
-#define __ASM_ARM_DIV64
-
-/* We're not 64-bit, but... */
-#define do_div(n,base)						\
-({								\
-	int __res;						\
-	__res = ((unsigned long)n) % (unsigned int)base;	\
-	n = ((unsigned long)n) / (unsigned int)base;		\
-	__res;							\
-})
-
-#endif
-
+#include <asm-generic/div64.h>
diff -Nru a/include/asm-arm26/ecard.h b/include/asm-arm26/ecard.h
--- a/include/asm-arm26/ecard.h	Wed Jun  4 04:14:10 2003
+++ b/include/asm-arm26/ecard.h	Sun Jul  6 16:40:01 2003
@@ -26,6 +26,9 @@
 #define PROD_ACORN_ETHER1		0x0003
 #define PROD_ACORN_MFM			0x000b
 
+#define MANU_CCONCEPTS		0x0009
+#define PROD_CCONCEPTS_COLOURCARD	0x0050
+
 #define MANU_ANT2		0x0011
 #define PROD_ANT_ETHER3			0x00a4
 
diff -Nru a/include/asm-arm26/mach-types.h b/include/asm-arm26/mach-types.h
--- a/include/asm-arm26/mach-types.h	Wed Jun  4 04:14:10 2003
+++ b/include/asm-arm26/mach-types.h	Sun Jul  6 16:40:02 2003
@@ -1,5 +1,6 @@
 /*
  * Unlike ARM32 this is NOT automatically generated. DONT delete it
+ * Instead, consider FIXME-ing it so its auto-detected.
  */
 
 #ifndef __ASM_ARM_MACH_TYPE_H
diff -Nru a/include/asm-arm26/mmu_context.h b/include/asm-arm26/mmu_context.h
--- a/include/asm-arm26/mmu_context.h	Wed Jun  4 04:14:10 2003
+++ b/include/asm-arm26/mmu_context.h	Sun Jul  6 18:51:59 2003
@@ -26,7 +26,7 @@
  * tsk->mm will be NULL
  */
 static inline void
-enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk, unsigned cpu)
+enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
 {
 }
 
@@ -36,7 +36,7 @@
  */
 static inline void
 switch_mm(struct mm_struct *prev, struct mm_struct *next,
-	  struct task_struct *tsk, unsigned int cpu)
+	  struct task_struct *tsk)
 {
 	cpu_switch_mm(next->pgd, next);
 }
diff -Nru a/include/asm-arm26/pgalloc.h b/include/asm-arm26/pgalloc.h
--- a/include/asm-arm26/pgalloc.h	Sat Jun  7 07:24:16 2003
+++ b/include/asm-arm26/pgalloc.h	Sun Jul  6 16:40:02 2003
@@ -55,9 +55,9 @@
  * is thrown away. It just cant be zero. -IM
  */
 
-#define pmd_alloc_one(mm,addr)		((pmd_t *)2); BUG()
+#define pmd_alloc_one(mm,addr)		({ BUG(); ((pmd_t *)2); })
 #define pmd_free(pmd)			do { } while (0)
-#define pgd_populate(mm,pmd,pte)	(0)
+#define pgd_populate(mm,pmd,pte)	BUG()
 
 extern pgd_t *get_pgd_slow(struct mm_struct *mm);
 extern void free_pgd_slow(pgd_t *pgd);
diff -Nru a/include/asm-arm26/pgtable.h b/include/asm-arm26/pgtable.h
--- a/include/asm-arm26/pgtable.h	Sat Jun  7 07:21:42 2003
+++ b/include/asm-arm26/pgtable.h	Sun Jul  6 16:40:02 2003
@@ -179,7 +179,7 @@
 /* Is pmd_page supposed to return a pointer to a page in some arches? ours seems to
  * return a pointer to memory (no special alignment)
  */
-#define pmd_page(pmd)  ((unsigned long)(pmd_val((pmd)) & ~_PMD_PRESENT))
+#define pmd_page(pmd)  ((struct page *)(pmd_val((pmd)) & ~_PMD_PRESENT))
 #define pmd_page_kernel(pmd) ((pte_t *)(pmd_val((pmd)) & ~_PMD_PRESENT))
 
 #define pte_offset_kernel(dir,addr)     (pmd_page_kernel(*(dir)) + __pte_index(addr))
diff -Nru a/include/asm-arm26/statfs.h b/include/asm-arm26/statfs.h
--- a/include/asm-arm26/statfs.h	Wed Jun  4 04:14:10 2003
+++ b/include/asm-arm26/statfs.h	Sun Jul  6 16:40:02 2003
@@ -1,25 +1,8 @@
 #ifndef _ASMARM_STATFS_H
 #define _ASMARM_STATFS_H
 
-#ifndef __KERNEL_STRICT_NAMES
+//FIXME - this may not be appropriate for arm26. check it out.
 
-#include <linux/types.h>
-
-typedef __kernel_fsid_t	fsid_t;
-
-#endif
-
-struct statfs {
-	long f_type;
-	long f_bsize;
-	long f_blocks;
-	long f_bfree;
-	long f_bavail;
-	long f_files;
-	long f_ffree;
-	__kernel_fsid_t f_fsid;
-	long f_namelen;
-	long f_spare[6];
-};
+#include <asm-generic/statfs.h>
 
 #endif
diff -Nru a/include/asm-arm26/thread_info.h b/include/asm-arm26/thread_info.h
--- a/include/asm-arm26/thread_info.h	Wed Jun  4 04:14:11 2003
+++ b/include/asm-arm26/thread_info.h	Sun Jul  6 16:40:02 2003
@@ -85,7 +85,7 @@
 //#define INIT_THREAD_SIZE        (65536)
 #define __get_user_regs(x) (((struct pt_regs *)((unsigned long)(x) + THREAD_SIZE - 8)) - 1)
 
-extern struct thread_info *alloc_thread_info(void);
+extern struct thread_info *alloc_thread_info(struct task_struct *task);
 extern void free_thread_info(struct thread_info *);
 
 #define get_thread_info(ti)	get_task_struct((ti)->task)
diff -Nru a/include/asm-cris/div64.h b/include/asm-cris/div64.h
--- a/include/asm-cris/div64.h	Tue Feb  5 09:56:43 2002
+++ b/include/asm-cris/div64.h	Thu Jul  3 00:37:22 2003
@@ -1,16 +1 @@
-#ifndef __ASM_CRIS_DIV64
-#define __ASM_CRIS_DIV64
-
-/* copy from asm-arm */
-
-/* We're not 64-bit, but... */
-#define do_div(n,base)						\
-({								\
-	int __res;						\
-	__res = ((unsigned long)n) % (unsigned int)base;	\
-	n = ((unsigned long)n) / (unsigned int)base;		\
-	__res;							\
-})
-
-#endif
-
+#include <asm-generic/div64.h>
diff -Nru a/include/asm-cris/mmu_context.h b/include/asm-cris/mmu_context.h
--- a/include/asm-cris/mmu_context.h	Thu Jan  9 23:21:00 2003
+++ b/include/asm-cris/mmu_context.h	Sun Jul  6 18:51:59 2003
@@ -5,11 +5,11 @@
 extern void get_mmu_context(struct mm_struct *mm);
 extern void destroy_context(struct mm_struct *mm);
 extern void switch_mm(struct mm_struct *prev, struct mm_struct *next,
-		      struct task_struct *tsk, int cpu);
+		      struct task_struct *tsk);
 
 #define deactivate_mm(tsk,mm)	do { } while (0)
 
-#define activate_mm(prev,next) switch_mm((prev),(next),NULL,smp_processor_id())
+#define activate_mm(prev,next) switch_mm((prev),(next),NULL)
 
 /* current active pgd - this is similar to other processors pgd 
  * registers like cr3 on the i386
@@ -17,7 +17,7 @@
 
 extern volatile pgd_t *current_pgd;   /* defined in arch/cris/mm/fault.c */
 
-static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk, unsigned cpu)
+static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
 {
 }
 
diff -Nru a/include/asm-generic/div64.h b/include/asm-generic/div64.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/include/asm-generic/div64.h	Thu Jul  3 00:55:04 2003
@@ -0,0 +1,53 @@
+#ifndef _ASM_GENERIC_DIV64_H
+#define _ASM_GENERIC_DIV64_H
+/*
+ * Copyright (C) 2003 Bernardo Innocenti <bernie@develer.com>
+ * Based on former asm-ppc/div64.h and asm-m68knommu/div64.h
+ *
+ * The semantics of do_div() are:
+ *
+ * uint32_t do_div(uint64_t *n, uint32_t base)
+ * {
+ * 	uint32_t remainder = *n % base;
+ * 	*n = *n / base;
+ * 	return remainder;
+ * }
+ *
+ * NOTE: macro parameter n is evaluated multiple times,
+ *       beware of side effects!
+ */
+
+#include <linux/types.h>
+
+#if BITS_PER_LONG == 64
+
+# define do_div(n,base) ({					\
+	uint32_t __base = (base);				\
+	uint32_t __rem;						\
+	__rem = ((uint64_t)(n)) % __base;			\
+	(n) = ((uint64_t)(n)) / __base;				\
+	__rem;							\
+ })
+
+#elif BITS_PER_LONG == 32
+
+extern uint32_t __div64_32(uint64_t *dividend, uint32_t divisor);
+
+# define do_div(n,base) ({				\
+	uint32_t __base = (base);			\
+	uint32_t __rem;					\
+	if (((n) >> 32) == 0) {				\
+		__rem = (uint32_t)(n) % __base;		\
+		(n) = (uint32_t)(n) / __base;		\
+	} else 						\
+		__rem = __div64_32(&(n), __base);	\
+	__rem;						\
+ })
+
+#else /* BITS_PER_LONG == ?? */
+
+# error do_div() does not yet support the C64
+
+#endif /* BITS_PER_LONG */
+
+#endif /* _ASM_GENERIC_DIV64_H */
diff -Nru a/include/asm-h8300/div64.h b/include/asm-h8300/div64.h
--- a/include/asm-h8300/div64.h	Sun Feb 16 16:01:58 2003
+++ b/include/asm-h8300/div64.h	Thu Jul  3 00:37:22 2003
@@ -1,13 +1 @@
-#ifndef H8300_DIV64_H
-#define H8300_DIV64_H
-
-/* n = n / base; return rem; */
-
-#define do_div(n,base) ({					\
-	int __res;						\
-	__res = ((unsigned long) n) % (unsigned) base;		\
-	n = ((unsigned long) n) / (unsigned) base;		\
-	__res;							\
-})
-
-#endif /* _H8300_DIV64_H */
+#include <asm-generic/div64.h>
diff -Nru a/include/asm-h8300/flat.h b/include/asm-h8300/flat.h
--- a/include/asm-h8300/flat.h	Thu Apr 17 12:31:21 2003
+++ b/include/asm-h8300/flat.h	Wed Jul  2 18:18:29 2003
@@ -5,6 +5,21 @@
 #ifndef __H8300_FLAT_H__
 #define __H8300_FLAT_H__
 
-#define flat_argvp_envp_on_stack()	1
+#define	flat_stack_align(sp)			/* nothing needed */
+#define	flat_argvp_envp_on_stack()		1
+#define	flat_old_ram_flag(flags)		1
+#define	flat_reloc_valid(reloc, size)		((reloc) <= (size))
+
+/*
+ * on the H8 a couple of the relocations have an instruction in the
+ * top byte.  As there can only be 24bits of address space,  we just
+ * always preserve that 8bits at the top,  when it isn't an instruction
+ * is is 0 (davidm@snapgear.com)
+ */
+
+#define	flat_get_relocate_addr(rel)		(rel)
+#define flat_get_addr_from_rp(rp, relval)       (get_unaligned(rp) & 0x0ffffff)
+#define flat_put_addr_at_rp(rp, addr, rel) \
+	put_unaligned (((*(char *)(rp)) << 24) | ((addr) & 0x00ffffff), rp)
 
 #endif /* __H8300_FLAT_H__ */
diff -Nru a/include/asm-h8300/mmu_context.h b/include/asm-h8300/mmu_context.h
--- a/include/asm-h8300/mmu_context.h	Thu Apr 17 12:31:21 2003
+++ b/include/asm-h8300/mmu_context.h	Sun Jul  6 18:51:59 2003
@@ -6,7 +6,7 @@
 #include <asm/page.h>
 #include <asm/pgalloc.h>
 
-static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk, unsigned cpu)
+static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
 {
 }
 
@@ -20,7 +20,7 @@
 #define destroy_context(mm)		do { } while(0)
 #define deactivate_mm(tsk,mm)           do { } while(0)
 
-static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, struct task_struct *tsk, unsigned cpu)
+static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, struct task_struct *tsk)
 {
 }
 
diff -Nru a/include/asm-i386/cacheflush.h b/include/asm-i386/cacheflush.h
--- a/include/asm-i386/cacheflush.h	Sat Apr 12 16:21:01 2003
+++ b/include/asm-i386/cacheflush.h	Wed Jul  2 21:19:42 2003
@@ -17,4 +17,9 @@
 void global_flush_tlb(void); 
 int change_page_attr(struct page *page, int numpages, pgprot_t prot);
 
+#ifdef CONFIG_DEBUG_PAGEALLOC
+/* internal debugging function */
+void kernel_map_pages(struct page *page, int numpages, int enable);
+#endif
+
 #endif /* _I386_CACHEFLUSH_H */
diff -Nru a/include/asm-i386/hardirq.h b/include/asm-i386/hardirq.h
--- a/include/asm-i386/hardirq.h	Mon Mar 31 14:29:49 2003
+++ b/include/asm-i386/hardirq.h	Mon Jun 30 22:26:58 2003
@@ -7,8 +7,6 @@
 
 typedef struct {
 	unsigned int __softirq_pending;
-	unsigned int __syscall_count;
-	struct task_struct * __ksoftirqd_task; /* waitqueue is too large */
 	unsigned long idle_timestamp;
 	unsigned int __nmi_count;	/* arch dependent */
 	unsigned int apic_timer_irqs;	/* arch dependent */
diff -Nru a/include/asm-i386/mmu_context.h b/include/asm-i386/mmu_context.h
--- a/include/asm-i386/mmu_context.h	Sat May 17 14:09:52 2003
+++ b/include/asm-i386/mmu_context.h	Sun Jul  6 18:51:59 2003
@@ -14,16 +14,21 @@
 void destroy_context(struct mm_struct *mm);
 
 
-static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk, unsigned cpu)
+static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
 {
 #ifdef CONFIG_SMP
+	unsigned cpu = smp_processor_id();
 	if (cpu_tlbstate[cpu].state == TLBSTATE_OK)
 		cpu_tlbstate[cpu].state = TLBSTATE_LAZY;	
 #endif
 }
 
-static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, struct task_struct *tsk, unsigned cpu)
+static inline void switch_mm(struct mm_struct *prev,
+			     struct mm_struct *next,
+			     struct task_struct *tsk)
 {
+	int cpu = smp_processor_id();
+
 	if (likely(prev != next)) {
 		/* stop flush ipis for the previous mm */
 		clear_bit(cpu, &prev->cpu_vm_mask);
@@ -62,6 +67,6 @@
 	asm("movl %0,%%fs ; movl %0,%%gs": :"r" (0))
 
 #define activate_mm(prev, next) \
-	switch_mm((prev),(next),NULL,smp_processor_id())
+	switch_mm((prev),(next),NULL)
 
 #endif
diff -Nru a/include/asm-i386/mmzone.h b/include/asm-i386/mmzone.h
--- a/include/asm-i386/mmzone.h	Sun May  4 23:38:34 2003
+++ b/include/asm-i386/mmzone.h	Wed Jul  2 21:20:53 2003
@@ -32,8 +32,7 @@
 #define alloc_bootmem_low_pages_node(ignore, x) \
 	__alloc_bootmem_node(NODE_DATA(0), (x), PAGE_SIZE, 0)
 
-#define node_size(nid)		(node_data[nid]->node_size)
-#define node_localnr(pfn, nid)	((pfn) - node_data[nid]->node_start_pfn)
+#define node_localnr(pfn, nid)		((pfn) - node_data[nid]->node_start_pfn)
 
 /*
  * Following are macros that each numa implmentation must define.
@@ -54,7 +53,7 @@
 #define node_end_pfn(nid)						\
 ({									\
 	pg_data_t *__pgdat = NODE_DATA(nid);				\
-	__pgdat->node_start_pfn + __pgdat->node_size;			\
+	__pgdat->node_start_pfn + __pgdat->node_spanned_pages;		\
 })
 
 #define local_mapnr(kvaddr)						\
diff -Nru a/include/asm-i386/timer.h b/include/asm-i386/timer.h
--- a/include/asm-i386/timer.h	Mon Mar 31 08:03:54 2003
+++ b/include/asm-i386/timer.h	Wed Jul  2 21:21:34 2003
@@ -21,8 +21,21 @@
 #define TICK_SIZE (tick_nsec / 1000)
 
 extern struct timer_opts* select_timer(void);
+extern void clock_fallback(void);
 
 /* Modifiers for buggy PIT handling */
 
 extern int pit_latch_buggy;
+
+extern struct timer_opts *cur_timer;
+extern int timer_ack;
+
+/* list of externed timers */
+extern struct timer_opts timer_none;
+extern struct timer_opts timer_pit;
+extern struct timer_opts timer_tsc;
+#ifdef CONFIG_X86_CYCLONE_TIMER
+extern struct timer_opts timer_cyclone;
+#endif
+
 #endif
diff -Nru a/include/asm-i386/unistd.h b/include/asm-i386/unistd.h
--- a/include/asm-i386/unistd.h	Fri Jun 20 13:16:06 2003
+++ b/include/asm-i386/unistd.h	Mon Jul  7 12:32:37 2003
@@ -275,8 +275,9 @@
 #define __NR_clock_nanosleep	(__NR_timer_create+8)
 #define __NR_statfs64		268
 #define __NR_fstatfs64		269
+#define __NR_tgkill		270
 
-#define NR_syscalls 270
+#define NR_syscalls 271
 
 /* user-visible error numbers are in the range -1 - -124: see <asm-i386/errno.h> */
 
diff -Nru a/include/asm-ia64/div64.h b/include/asm-ia64/div64.h
--- a/include/asm-ia64/div64.h	Tue Feb  5 09:39:54 2002
+++ b/include/asm-ia64/div64.h	Thu Jul  3 00:37:22 2003
@@ -1,20 +1 @@
-#ifndef _ASM_IA64_DIV64_H
-#define _ASM_IA64_DIV64_H
-
-/*
- * Copyright (C) 1999 Hewlett-Packard Co
- * Copyright (C) 1999 David Mosberger-Tang <davidm@hpl.hp.com>
- *
- * vsprintf uses this to divide a 64-bit integer N by a small integer BASE.
- * This is incredibly hard on IA-64...
- */
-
-#define do_div(n,base)						\
-({								\
-	int _res;						\
-	_res = ((unsigned long) (n)) % (unsigned) (base);	\
-	(n) = ((unsigned long) (n)) / (unsigned) (base);	\
-	_res;							\
-})
-
-#endif /* _ASM_IA64_DIV64_H */
+#include <asm-generic/div64.h>
diff -Nru a/include/asm-ia64/mmu_context.h b/include/asm-ia64/mmu_context.h
--- a/include/asm-ia64/mmu_context.h	Fri Jan 24 11:56:49 2003
+++ b/include/asm-ia64/mmu_context.h	Sun Jul  6 18:51:59 2003
@@ -71,7 +71,7 @@
 extern void wrap_mmu_context (struct mm_struct *mm);
 
 static inline void
-enter_lazy_tlb (struct mm_struct *mm, struct task_struct *tsk, unsigned cpu)
+enter_lazy_tlb (struct mm_struct *mm, struct task_struct *tsk)
 {
 }
 
@@ -198,7 +198,7 @@
 	activate_context(next);
 }
 
-#define switch_mm(prev_mm,next_mm,next_task,cpu)	activate_mm(prev_mm, next_mm)
+#define switch_mm(prev_mm,next_mm,next_task)	activate_mm(prev_mm, next_mm)
 
 # endif /* ! __ASSEMBLY__ */
 #endif /* _ASM_IA64_MMU_CONTEXT_H */
diff -Nru a/include/asm-m68k/div64.h b/include/asm-m68k/div64.h
--- a/include/asm-m68k/div64.h	Tue Feb  5 09:39:47 2002
+++ b/include/asm-m68k/div64.h	Thu Jul  3 00:37:22 2003
@@ -3,7 +3,6 @@
 
 /* n = n / base; return rem; */
 
-#if 1
 #define do_div(n, base) ({					\
 	union {							\
 		unsigned long n32[2];				\
@@ -23,13 +22,5 @@
 	(n) = __n.n64;						\
 	__rem;							\
 })
-#else
-#define do_div(n,base) ({					\
-	int __res;						\
-	__res = ((unsigned long) n) % (unsigned) base;		\
-	n = ((unsigned long) n) / (unsigned) base;		\
-	__res;							\
-})
-#endif
 
 #endif /* _M68K_DIV64_H */
diff -Nru a/include/asm-m68k/mmu_context.h b/include/asm-m68k/mmu_context.h
--- a/include/asm-m68k/mmu_context.h	Sat Jan 11 09:17:55 2003
+++ b/include/asm-m68k/mmu_context.h	Sun Jul  6 18:52:00 2003
@@ -3,7 +3,7 @@
 
 #include <linux/config.h>
 
-static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk, unsigned cpu)
+static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
 {
 }
 
@@ -79,7 +79,7 @@
 	asm volatile (".chip 68k");
 }
 
-static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, struct task_struct *tsk, unsigned cpu)
+static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, struct task_struct *tsk)
 {
 	if (prev != next) {
 		if (CPU_IS_020_OR_030)
@@ -137,7 +137,7 @@
 	sun3_put_context(mm->context);
 }
 
-static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, struct task_struct *tsk, unsigned cpu)
+static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, struct task_struct *tsk)
 {
 	activate_context(tsk->mm);
 }
diff -Nru a/include/asm-m68knommu/div64.h b/include/asm-m68knommu/div64.h
--- a/include/asm-m68knommu/div64.h	Fri Nov  1 08:37:46 2002
+++ b/include/asm-m68knommu/div64.h	Thu Jul  3 00:37:22 2003
@@ -1,13 +1 @@
-#ifndef _M68KNOMMU_DIV64_H
-#define _M68KNOMMU_DIV64_H
-
-/* n = n / base; return rem; */
-
-#define do_div(n,base) ({					\
-	int __res;						\
-	__res = ((unsigned long) n) % (unsigned) base;		\
-	n = ((unsigned long) n) / (unsigned) base;		\
-	__res;							\
-})
-
-#endif /* _M68K_DIV64_H */
+#include <asm-generic/div64.h>
diff -Nru a/include/asm-m68knommu/flat.h b/include/asm-m68knommu/flat.h
--- a/include/asm-m68knommu/flat.h	Tue Feb 18 02:28:54 2003
+++ b/include/asm-m68knommu/flat.h	Wed Jul  2 18:18:30 2003
@@ -5,6 +5,12 @@
 #ifndef __M68KNOMMU_FLAT_H__
 #define __M68KNOMMU_FLAT_H__
 
-#define flat_argvp_envp_on_stack()	1
+#define	flat_stack_align(sp)			/* nothing needed */
+#define	flat_argvp_envp_on_stack()		1
+#define	flat_old_ram_flag(flags)		(flags)
+#define	flat_reloc_valid(reloc, size)		((reloc) <= (size))
+#define	flat_get_addr_from_rp(rp, relval)	get_unaligned(rp)
+#define	flat_put_addr_at_rp(rp, val, relval)	put_unaligned(val,rp)
+#define	flat_get_relocate_addr(rel)		(rel)
 
 #endif /* __M68KNOMMU_FLAT_H__ */
diff -Nru a/include/asm-m68knommu/io.h b/include/asm-m68knommu/io.h
--- a/include/asm-m68knommu/io.h	Fri Nov  1 08:37:46 2002
+++ b/include/asm-m68knommu/io.h	Wed Jul  2 18:18:30 2003
@@ -43,6 +43,13 @@
 #define writew(b,addr) (void)((*(volatile unsigned short *) (addr)) = (b))
 #define writel(b,addr) (void)((*(volatile unsigned int *) (addr)) = (b))
 
+#define __raw_readb readb
+#define __raw_readw readw
+#define __raw_readl readl
+#define __raw_writeb writeb
+#define __raw_writew writew
+#define __raw_writel writel
+
 static inline void io_outsb(unsigned int addr, void *buf, int len)
 {
 	volatile unsigned char *ap = (volatile unsigned char *) addr;
@@ -100,7 +107,7 @@
 #define memcpy_fromio(a,b,c)	memcpy((a),(void *)(b),(c))
 #define memcpy_toio(a,b,c)	memcpy((void *)(a),(b),(c))
 
-#define inb(addr)      readb(addr)
+#define inb(addr)    readb(addr)
 #define inw(addr)    readw(addr)
 #define inl(addr)    readl(addr)
 #define outb(x,addr) ((void) writeb(x,addr))
diff -Nru a/include/asm-m68knommu/mmu_context.h b/include/asm-m68knommu/mmu_context.h
--- a/include/asm-m68knommu/mmu_context.h	Thu Jan  9 23:21:00 2003
+++ b/include/asm-m68knommu/mmu_context.h	Sun Jul  6 18:52:00 2003
@@ -6,7 +6,7 @@
 #include <asm/page.h>
 #include <asm/pgalloc.h>
 
-static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk, unsigned cpu)
+static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
 {
 }
 
@@ -19,7 +19,7 @@
 
 #define destroy_context(mm)		do { } while(0)
 
-static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, struct task_struct *tsk, unsigned cpu)
+static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, struct task_struct *tsk)
 {
 }
 
diff -Nru a/include/asm-m68knommu/page.h b/include/asm-m68knommu/page.h
--- a/include/asm-m68knommu/page.h	Wed Jan 15 03:04:34 2003
+++ b/include/asm-m68knommu/page.h	Wed Jul  2 18:18:30 2003
@@ -6,7 +6,7 @@
 /* PAGE_SHIFT determines the page size */
 
 #define PAGE_SHIFT	(12)
-#define PAGE_SIZE	(4096)
+#define PAGE_SIZE	(1UL << PAGE_SHIFT)
 #define PAGE_MASK	(~(PAGE_SIZE-1))
 
 #ifdef __KERNEL__
diff -Nru a/include/asm-m68knommu/semaphore.h b/include/asm-m68knommu/semaphore.h
--- a/include/asm-m68knommu/semaphore.h	Fri Nov  1 08:37:46 2002
+++ b/include/asm-m68knommu/semaphore.h	Wed Jul  2 18:18:30 2003
@@ -145,7 +145,7 @@
 		".previous"
 		: "=d" (result)
 		: "a" (sem1)
-		: "%d0", "memory");
+		: "memory");
 	return result;
 }
 
diff -Nru a/include/asm-m68knommu/uaccess.h b/include/asm-m68knommu/uaccess.h
--- a/include/asm-m68knommu/uaccess.h	Fri Jun 20 13:12:59 2003
+++ b/include/asm-m68knommu/uaccess.h	Wed Jul  2 18:18:30 2003
@@ -13,21 +13,14 @@
 #define VERIFY_READ	0
 #define VERIFY_WRITE	1
 
-/* We let the MMU do all checking */
-extern inline int access_ok(int type, const void * addr, unsigned long size)
+#define access_ok(type,addr,size)	_access_ok((unsigned long)(addr),(size))
+
+static inline int _access_ok(unsigned long addr, unsigned long size)
 {
-#define	RANGE_CHECK_OK(addr, size, lower, upper) \
-	(((addr) >= (lower)) && (((addr) + (size)) < (upper)))
+	extern unsigned long memory_start, memory_end;
 
-#ifdef CONFIG_COLDFIRE
-	extern unsigned long _ramend;
-	return(RANGE_CHECK_OK((unsigned long) addr, size, 0L, _ramend) ||
-			(is_in_rom((unsigned long) addr) &&
-					is_in_rom((unsigned long) addr + size)));
-#else
-	/* DAVIDM - this could be restricted a lot more */
-	return(RANGE_CHECK_OK((unsigned long)addr, size, 0, 0x10f00000));
-#endif
+	return (((addr >= memory_start) && (addr+size < memory_end)) ||
+		(is_in_rom(addr) && is_in_rom(addr+size)));
 }
 
 extern inline int verify_area(int type, const void * addr, unsigned long size)
diff -Nru a/include/asm-mips/mmu_context.h b/include/asm-mips/mmu_context.h
--- a/include/asm-mips/mmu_context.h	Sun Jun 15 16:56:21 2003
+++ b/include/asm-mips/mmu_context.h	Sun Jul  6 18:52:00 2003
@@ -49,7 +49,7 @@
 #define cpu_asid(cpu, mm)	(cpu_context((cpu), (mm)) & ASID_MASK)
 #define asid_cache(cpu)		(cpu_data[cpu].asid_cache)
 
-static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk, unsigned cpu)
+static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
 {
 }
 
@@ -92,9 +92,10 @@
 }
 
 static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
-                             struct task_struct *tsk, unsigned cpu)
+                             struct task_struct *tsk)
 {
 	unsigned long flags;
+	unsigned cpu = smp_processor_id();
 
 	local_irq_save(flags);
 
diff -Nru a/include/asm-mips64/div64.h b/include/asm-mips64/div64.h
--- a/include/asm-mips64/div64.h	Mon Apr 14 20:10:07 2003
+++ b/include/asm-mips64/div64.h	Thu Jul  3 00:39:28 2003
@@ -27,23 +27,6 @@
 	(res) = __quot; \
 	__mod; })
 
-/*
- * Hey, we're already 64-bit, no
- * need to play games..
- */
-#define do_div(n, base) ({ \
-	unsigned long __quot; \
-	unsigned int __mod; \
-	unsigned long __div; \
-	unsigned int __base; \
-	\
-	__div = (n); \
-	__base = (base); \
-	\
-	__mod = __div % __base; \
-	__quot = __div / __base; \
-	\
-	(n) = __quot; \
-	__mod; })
+#include <asm-generic.h>
 
 #endif /* _ASM_DIV64_H */
diff -Nru a/include/asm-mips64/mmu_context.h b/include/asm-mips64/mmu_context.h
--- a/include/asm-mips64/mmu_context.h	Sun Jun 15 16:56:22 2003
+++ b/include/asm-mips64/mmu_context.h	Sun Jul  6 18:52:00 2003
@@ -40,7 +40,7 @@
 #define cpu_asid(cpu, mm)	(cpu_context((cpu), (mm)) & ASID_MASK)
 #define asid_cache(cpu)		(cpu_data[cpu].asid_cache)
 
-static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk, unsigned cpu)
+static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
 {
 }
 
diff -Nru a/include/asm-mips64/mmzone.h b/include/asm-mips64/mmzone.h
--- a/include/asm-mips64/mmzone.h	Sun Jun 15 16:56:22 2003
+++ b/include/asm-mips64/mmzone.h	Wed Jul  2 21:20:53 2003
@@ -24,7 +24,7 @@
 
 #define PHYSADDR_TO_NID(pa)		NASID_TO_COMPACT_NODEID(NASID_GET(pa))
 #define PLAT_NODE_DATA(n)		(plat_node_data[n])
-#define PLAT_NODE_DATA_SIZE(n)	     (PLAT_NODE_DATA(n)->gendata.node_size)
+#define PLAT_NODE_DATA_SIZE(n)	     (PLAT_NODE_DATA(n)->gendata.node_spanned_pages)
 #define PLAT_NODE_DATA_LOCALNR(p, n) \
 		(((p) >> PAGE_SHIFT) - PLAT_NODE_DATA(n)->gendata.node_start_pfn)
 
diff -Nru a/include/asm-parisc/div64.h b/include/asm-parisc/div64.h
--- a/include/asm-parisc/div64.h	Tue Feb  5 09:39:57 2002
+++ b/include/asm-parisc/div64.h	Thu Jul  3 00:37:22 2003
@@ -1,54 +1 @@
-#ifndef __ASM_PARISC_DIV64
-#define __ASM_PARISC_DIV64
-
-#ifdef __LP64__
-
-/*
- * Copyright (C) 1999 Hewlett-Packard Co
- * Copyright (C) 1999 David Mosberger-Tang <davidm@hpl.hp.com>
- *
- * vsprintf uses this to divide a 64-bit integer N by a small integer BASE.
- * This is incredibly hard on IA-64 and HPPA
- */
-
-#define do_div(n,base)						\
-({								\
-	int _res;						\
-	_res = ((unsigned long) (n)) % (unsigned) (base);	\
-	(n) = ((unsigned long) (n)) / (unsigned) (base);	\
-	_res;							\
-})
-
-#else
-/*
- * unsigned long long division.  Yuck Yuck!  What is Linux coming to?
- * This is 100% disgusting
- */
-#define do_div(n,base)							\
-({									\
-	unsigned long __low, __low2, __high, __rem;			\
-	__low  = (n) & 0xffffffff;					\
-	__high = (n) >> 32;						\
-	if (__high) {							\
-		__rem   = __high % (unsigned long)base;			\
-		__high  = __high / (unsigned long)base;			\
-		__low2  = __low >> 16;					\
-		__low2 += __rem << 16;					\
-		__rem   = __low2 % (unsigned long)base;			\
-		__low2  = __low2 / (unsigned long)base;			\
-		__low   = __low & 0xffff;				\
-		__low  += __rem << 16;					\
-		__rem   = __low  % (unsigned long)base;			\
-		__low   = __low  / (unsigned long)base;			\
-		n = __low  + ((long long)__low2 << 16) +		\
-			((long long) __high << 32);			\
-	} else {							\
-		__rem = __low % (unsigned long)base;			\
-		n = (__low / (unsigned long)base);			\
-	}								\
-	__rem;								\
-})
-#endif
-
-#endif
-
+#include <asm-generic/div64.h>
diff -Nru a/include/asm-parisc/mmu_context.h b/include/asm-parisc/mmu_context.h
--- a/include/asm-parisc/mmu_context.h	Thu Jan  9 23:21:00 2003
+++ b/include/asm-parisc/mmu_context.h	Sun Jul  6 18:52:00 2003
@@ -6,7 +6,7 @@
 #include <asm/pgalloc.h>
 #include <asm/pgtable.h>
 
-static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk, unsigned cpu)
+static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
 {
 }
 
@@ -43,7 +43,7 @@
 #endif
 }
 
-static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, struct task_struct *tsk, unsigned cpu)
+static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, struct task_struct *tsk)
 {
 
 	if (prev != next) {
@@ -69,6 +69,6 @@
 	if (next->context == 0)
 	    next->context = alloc_sid();
 
-	switch_mm(prev,next,current,0);
+	switch_mm(prev,next,current);
 }
 #endif
diff -Nru a/include/asm-ppc/div64.h b/include/asm-ppc/div64.h
--- a/include/asm-ppc/div64.h	Fri Oct 18 05:50:50 2002
+++ b/include/asm-ppc/div64.h	Thu Jul  3 00:37:22 2003
@@ -1,23 +1 @@
-#ifndef __PPC_DIV64
-#define __PPC_DIV64
-
-#include <linux/types.h>
-
-extern u32 __div64_32(u64 *dividend, u32 div);
-
-#define do_div(n, div)	({			\
-	u64 __n = (n);				\
-	u32 __d = (div);			\
-	u32 __q, __r;				\
-	if ((__n >> 32) == 0) {			\
-		__q = (u32)__n / __d;		\
-		__r = (u32)__n - __q * __d;	\
-		(n) = __q;			\
-	} else {				\
-		__r = __div64_32(&__n, __d);	\
-		(n) = __n;			\
-	}					\
-	__r;					\
-})
-
-#endif
+#include <asm-generic/div64.h>
diff -Nru a/include/asm-ppc/mmu_context.h b/include/asm-ppc/mmu_context.h
--- a/include/asm-ppc/mmu_context.h	Sat Jun  7 02:18:02 2003
+++ b/include/asm-ppc/mmu_context.h	Sun Jul  6 18:52:00 2003
@@ -48,7 +48,7 @@
    	-- Dan
  */
 
-static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk, unsigned cpu)
+static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
 {
 }
 
@@ -153,7 +153,7 @@
 }
 
 static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
-			     struct task_struct *tsk, int cpu)
+			     struct task_struct *tsk)
 {
 	tsk->thread.pgdir = next->pgd;
 	get_mmu_context(next);
diff -Nru a/include/asm-ppc/serial.h b/include/asm-ppc/serial.h
--- a/include/asm-ppc/serial.h	Sun Sep 15 21:52:06 2002
+++ b/include/asm-ppc/serial.h	Wed Jul  2 17:44:15 2003
@@ -25,11 +25,9 @@
 #elif defined(CONFIG_PRPMC800)
 #include <platforms/prpmc800_serial.h>
 #elif defined(CONFIG_SANDPOINT)
-#include <platforms/sandpoint_serial.h>
+#include <platforms/sandpoint.h>
 #elif defined(CONFIG_SPRUCE)
 #include <platforms/spruce_serial.h>
-#elif defined(CONFIG_ZX4500)
-#include <platforms/zx4500_serial.h>
 #elif defined(CONFIG_40x)
 #include <asm/ibm4xx.h>
 #else
diff -Nru a/include/asm-ppc64/div64.h b/include/asm-ppc64/div64.h
--- a/include/asm-ppc64/div64.h	Thu Feb 14 04:14:36 2002
+++ b/include/asm-ppc64/div64.h	Thu Jul  3 00:37:22 2003
@@ -1,18 +1 @@
-#ifndef __PPC_DIV64
-#define __PPC_DIV64
-
-/* Copyright 2001 PPC64 Team, IBM Corp
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- */
-
-#define do_div(n,base) ({ \
-	int __res; \
-	__res = ((unsigned long) (n)) % (unsigned) (base); \
-	(n) = ((unsigned long) (n)) / (unsigned) (base); \
-	__res; })
-
-#endif
+#include <asm-generic/div64.h>
diff -Nru a/include/asm-ppc64/mmu_context.h b/include/asm-ppc64/mmu_context.h
--- a/include/asm-ppc64/mmu_context.h	Thu Jan  9 23:21:00 2003
+++ b/include/asm-ppc64/mmu_context.h	Sun Jul  6 18:52:00 2003
@@ -56,7 +56,7 @@
 extern struct mmu_context_queue_t mmu_context_queue;
 
 static inline void
-enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk, unsigned cpu)
+enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
 {
 }
 
@@ -140,10 +140,10 @@
  */
 static inline void
 switch_mm(struct mm_struct *prev, struct mm_struct *next,
-	  struct task_struct *tsk, int cpu)
+	  struct task_struct *tsk)
 {
 	flush_stab(tsk, next);
-	set_bit(cpu, &next->cpu_vm_mask);
+	set_bit(smp_processor_id(), &next->cpu_vm_mask);
 }
 
 #define deactivate_mm(tsk,mm)	do { } while (0)
@@ -153,7 +153,7 @@
  * the context for the new mm so we see the new mappings.
  */
 #define activate_mm(active_mm, mm) \
-	switch_mm(active_mm, mm, current, smp_processor_id());
+	switch_mm(active_mm, mm, current);
 
 #define VSID_RANDOMIZER 42470972311
 #define VSID_MASK	0xfffffffff
diff -Nru a/include/asm-ppc64/mmzone.h b/include/asm-ppc64/mmzone.h
--- a/include/asm-ppc64/mmzone.h	Thu Jun  5 23:37:10 2003
+++ b/include/asm-ppc64/mmzone.h	Wed Jul  2 21:20:53 2003
@@ -54,7 +54,6 @@
  */
 #define NODE_DATA(nid)		(&node_data[nid])
 
-#define node_size(nid)		(NODE_DATA(nid)->node_size)
 #define node_localnr(pfn, nid)	((pfn) - NODE_DATA(nid)->node_start_pfn)
 
 /*
diff -Nru a/include/asm-s390/div64.h b/include/asm-s390/div64.h
--- a/include/asm-s390/div64.h	Mon Apr 14 12:11:58 2003
+++ b/include/asm-s390/div64.h	Thu Jul  3 00:37:22 2003
@@ -43,13 +43,7 @@
 })
 
 #else /* __s390x__ */
-
-#define do_div(n,base) ({ \
-int __res; \
-__res = ((unsigned long) n) % (unsigned) base; \
-n = ((unsigned long) n) / (unsigned) base; \
-__res; })
-
+#include <asm-generic/div64.h>
 #endif /* __s390x__ */
 
 #endif
diff -Nru a/include/asm-s390/mmu_context.h b/include/asm-s390/mmu_context.h
--- a/include/asm-s390/mmu_context.h	Mon Apr 14 12:11:58 2003
+++ b/include/asm-s390/mmu_context.h	Sun Jul  6 18:52:00 2003
@@ -17,12 +17,12 @@
 #define destroy_context(mm)             flush_tlb_mm(mm)
 
 static inline void enter_lazy_tlb(struct mm_struct *mm,
-                                  struct task_struct *tsk, unsigned cpu)
+                                  struct task_struct *tsk)
 {
 }
 
 static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
-                             struct task_struct *tsk, unsigned cpu)
+                             struct task_struct *tsk)
 {
         unsigned long pgd;
 
@@ -42,7 +42,7 @@
                              : : "m" (pgd) );
 #endif /* __s390x__ */
         }
-	set_bit(cpu, &next->cpu_vm_mask);
+	set_bit(smp_processor_id(), &next->cpu_vm_mask);
 }
 
 #define deactivate_mm(tsk,mm)	do { } while (0)
@@ -50,7 +50,7 @@
 extern inline void activate_mm(struct mm_struct *prev,
                                struct mm_struct *next)
 {
-        switch_mm(prev, next, current, smp_processor_id());
+        switch_mm(prev, next, current);
 }
 
 #endif
diff -Nru a/include/asm-sh/div64.h b/include/asm-sh/div64.h
--- a/include/asm-sh/div64.h	Tue May  6 12:33:19 2003
+++ b/include/asm-sh/div64.h	Thu Jul  3 00:38:59 2003
@@ -1,20 +1 @@
-#ifndef __ASM_SH_DIV64
-#define __ASM_SH_DIV64
-
-extern u64 __div64_32(u64 n, u32 d);
-
-#define do_div(n,base) ({ \
-u64 __n = (n), __q; \
-u32 __base = (base); \
-u32 __res; \
-if ((__n >> 32) == 0) { \
-	__res = ((unsigned long) __n) % (unsigned) __base; \
-	(n) = ((unsigned long) __n) / (unsigned) __base; \
-} else { \
-	__q = __div64_32(__n, __base); \
-	__res = __n - __q * __base; \
-	(n) = __q; \
-} \
-__res; })
-
-#endif /* __ASM_SH_DIV64 */
+#include <asm-generic/div64.h>
diff -Nru a/include/asm-sh/mmu_context.h b/include/asm-sh/mmu_context.h
--- a/include/asm-sh/mmu_context.h	Sun May  4 08:30:01 2003
+++ b/include/asm-sh/mmu_context.h	Sun Jul  6 18:52:00 2003
@@ -129,7 +129,7 @@
    (Currently not used) */
 static __inline__ void switch_mm(struct mm_struct *prev,
 				 struct mm_struct *next,
-				 struct task_struct *tsk, unsigned int cpu)
+				 struct task_struct *tsk)
 {
 	if (likely(prev != next)) {
 		unsigned long __pgdir = (unsigned long)next->pgd;
@@ -144,10 +144,10 @@
 #define deactivate_mm(tsk,mm)	do { } while (0)
 
 #define activate_mm(prev, next) \
-	switch_mm((prev),(next),NULL,smp_processor_id())
+	switch_mm((prev),(next),NULL)
 
 static __inline__ void
-enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk, unsigned cpu)
+enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
 {
 }
 #else /* !CONFIG_MMU */
@@ -157,10 +157,10 @@
 #define set_asid(asid)			do { } while (0)
 #define get_asid()			(0)
 #define activate_context(mm)		do { } while (0)
-#define switch_mm(prev,next,tsk,cpu)	do { } while (0)
+#define switch_mm(prev,next,tsk)	do { } while (0)
 #define deactivate_mm(tsk,mm)		do { } while (0)
 #define activate_mm(prev,next)		do { } while (0)
-#define enter_lazy_tlb(mm,tsk,cpu)	do { } while (0)
+#define enter_lazy_tlb(mm,tsk)		do { } while (0)
 #endif /* CONFIG_MMU */
 
 #if defined(CONFIG_CPU_SH3) || defined(CONFIG_CPU_SH4)
diff -Nru a/include/asm-sparc/div64.h b/include/asm-sparc/div64.h
--- a/include/asm-sparc/div64.h	Tue Feb  5 09:39:48 2002
+++ b/include/asm-sparc/div64.h	Thu Jul  3 00:37:22 2003
@@ -1,11 +1 @@
-#ifndef __SPARC_DIV64
-#define __SPARC_DIV64
-
-/* We're not 64-bit, but... */
-#define do_div(n,base) ({ \
-	int __res; \
-	__res = ((unsigned long) n) % (unsigned) base; \
-	n = ((unsigned long) n) / (unsigned) base; \
-	__res; })
-
-#endif /* __SPARC_DIV64 */
+#include <asm-generic/div64.h>
diff -Nru a/include/asm-sparc/mmu_context.h b/include/asm-sparc/mmu_context.h
--- a/include/asm-sparc/mmu_context.h	Thu Jan  9 23:21:00 2003
+++ b/include/asm-sparc/mmu_context.h	Sun Jul  6 18:52:00 2003
@@ -5,7 +5,7 @@
 
 #ifndef __ASSEMBLY__
 
-static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk, unsigned cpu)
+static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
 {
 }
 
@@ -26,14 +26,14 @@
 #define destroy_context(mm) BTFIXUP_CALL(destroy_context)(mm)
 
 /* Switch the current MM context. */
-BTFIXUPDEF_CALL(void, switch_mm, struct mm_struct *, struct mm_struct *, struct task_struct *, int)
+BTFIXUPDEF_CALL(void, switch_mm, struct mm_struct *, struct mm_struct *, struct task_struct *)
 
-#define switch_mm(old_mm, mm, tsk, cpu) BTFIXUP_CALL(switch_mm)(old_mm, mm, tsk, cpu)
+#define switch_mm(old_mm, mm, tsk) BTFIXUP_CALL(switch_mm)(old_mm, mm, tsk)
 
 #define deactivate_mm(tsk,mm)	do { } while (0)
 
 /* Activate a new MM instance for the current task. */
-#define activate_mm(active_mm, mm) switch_mm((active_mm), (mm), NULL, smp_processor_id())
+#define activate_mm(active_mm, mm) switch_mm((active_mm), (mm), NULL)
 
 #endif /* !(__ASSEMBLY__) */
 
diff -Nru a/include/asm-sparc64/div64.h b/include/asm-sparc64/div64.h
--- a/include/asm-sparc64/div64.h	Tue Feb  5 09:39:51 2002
+++ b/include/asm-sparc64/div64.h	Thu Jul  3 00:37:22 2003
@@ -1,14 +1 @@
-#ifndef __SPARC64_DIV64
-#define __SPARC64_DIV64
-
-/*
- * Hey, we're already 64-bit, no
- * need to play games..
- */
-#define do_div(n,base) ({ \
-	int __res; \
-	__res = ((unsigned long) n) % (unsigned) base; \
-	n = ((unsigned long) n) / (unsigned) base; \
-	__res; })
-
-#endif /* __SPARC64_DIV64 */
+#include <asm-generic/div64.h>
diff -Nru a/include/asm-sparc64/mmu_context.h b/include/asm-sparc64/mmu_context.h
--- a/include/asm-sparc64/mmu_context.h	Thu Jan  9 23:21:00 2003
+++ b/include/asm-sparc64/mmu_context.h	Sun Jul  6 18:52:00 2003
@@ -27,7 +27,7 @@
 #include <asm/system.h>
 #include <asm/spitfire.h>
 
-static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk, unsigned cpu)
+static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
 {
 }
 
@@ -106,7 +106,7 @@
 extern void __flush_tlb_mm(unsigned long, unsigned long);
 
 /* Switch the current MM context. */
-static inline void switch_mm(struct mm_struct *old_mm, struct mm_struct *mm, struct task_struct *tsk, int cpu)
+static inline void switch_mm(struct mm_struct *old_mm, struct mm_struct *mm, struct task_struct *tsk)
 {
 	unsigned long ctx_valid;
 
@@ -125,7 +125,7 @@
 	}
 
 	{
-		unsigned long vm_mask = (1UL << cpu);
+		unsigned long vm_mask = (1UL << smp_processor_id());
 
 		/* Even if (mm == old_mm) we _must_ check
 		 * the cpu_vm_mask.  If we do not we could
diff -Nru a/include/asm-um/mmu_context.h b/include/asm-um/mmu_context.h
--- a/include/asm-um/mmu_context.h	Thu Jan  9 23:21:00 2003
+++ b/include/asm-um/mmu_context.h	Sun Jul  6 18:52:00 2003
@@ -21,8 +21,10 @@
 extern void switch_mm_skas(int mm_fd);
 
 static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, 
-			     struct task_struct *tsk, unsigned cpu)
+			     struct task_struct *tsk)
 {
+	unsigned cpu = smp_processor_id();
+
 	if(prev != next){
 		clear_bit(cpu, &prev->cpu_vm_mask);
 		set_bit(cpu, &next->cpu_vm_mask);
@@ -33,7 +35,7 @@
 }
 
 static inline void enter_lazy_tlb(struct mm_struct *mm, 
-				  struct task_struct *tsk, unsigned cpu)
+				  struct task_struct *tsk)
 {
 }
 
diff -Nru a/include/asm-v850/div64.h b/include/asm-v850/div64.h
--- a/include/asm-v850/div64.h	Fri Nov  1 08:38:12 2002
+++ b/include/asm-v850/div64.h	Thu Jul  3 00:37:22 2003
@@ -1,11 +1 @@
-#ifndef __V850_DIV64_H__
-#define __V850_DIV64_H__
-
-/* We're not 64-bit, but... */
-#define do_div(n,base) ({ \
-	int __res; \
-	__res = ((unsigned long) n) % (unsigned) base; \
-	n = ((unsigned long) n) / (unsigned) base; \
-	__res; })
-
-#endif /* __V850_DIV64_H__ */
+#include <asm-generic/div64.h>
diff -Nru a/include/asm-v850/flat.h b/include/asm-v850/flat.h
--- a/include/asm-v850/flat.h	Tue Feb 18 02:28:57 2003
+++ b/include/asm-v850/flat.h	Wed Jul  2 18:18:38 2003
@@ -1,8 +1,8 @@
 /*
  * include/asm-v850/flat.h -- uClinux flat-format executables
  *
- *  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,117 @@
 #ifndef __V850_FLAT_H__
 #define __V850_FLAT_H__
 
-#define flat_argvp_envp_on_stack()	0
+/* The amount by which a relocation can exceed the program image limits
+   without being regarded as an error.  On the v850, the relocations of
+   some base-pointers can be offset by 0x8000 (to allow better usage of the
+   space offered by 16-bit signed offsets -- in most cases the offsets used
+   with such a base-pointer will be negative).  */
+
+#define	flat_reloc_valid(reloc, size)	((reloc) <= (size + 0x8000))
+
+#define	flat_stack_align(sp)		/* nothing needed */
+#define	flat_argvp_envp_on_stack()	0
+#define	flat_old_ram_flag(flags)	(flags)
+
+/* We store the type of relocation in the top 4 bits of the `relval.' */
+
+/* Convert a relocation entry into an address.  */
+static inline unsigned long
+flat_get_relocate_addr (unsigned long relval)
+{
+	return relval & 0x0fffffff; /* Mask out top 4-bits */
+}
+
+#define flat_v850_get_reloc_type(relval) ((relval) >> 28)
+
+#define FLAT_V850_R_32		0 /* Normal 32-bit reloc */
+#define FLAT_V850_R_HI16S_LO15	1 /* High 16-bits + signed 15-bit low field */
+#define FLAT_V850_R_HI16S_LO16	2 /* High 16-bits + signed 16-bit low field */
+
+/* Extract the address to be relocated from the symbol reference at RP;
+   RELVAL is the raw relocation-table entry from which RP is derived.
+   For the v850, RP should always be half-word aligned.  */
+static inline unsigned long flat_get_addr_from_rp (unsigned long *rp,
+						   unsigned long relval)
+{
+	short *srp = (short *)rp;
+
+	switch (flat_v850_get_reloc_type (relval))
+	{
+	case FLAT_V850_R_32:
+		/* Simple 32-bit address.  */
+		return srp[0] | (srp[1] << 16);
+
+	case FLAT_V850_R_HI16S_LO16:
+		/* The high and low halves of the address are in the 16
+		   bits at RP, and the 2nd word of the 32-bit instruction
+		   following that, respectively.  The low half is _signed_
+		   so we have to sign-extend it and add it to the upper
+		   half instead of simply or-ing them together.
+
+		   Unlike most relocated address, this one is stored in
+		   native (little-endian) byte-order to avoid problems with
+		   trashing the low-order bit, so we have to convert to
+		   network-byte-order before returning, as that's what the
+		   caller expects.  */
+		return htonl ((srp[0] << 16) + srp[2]);
+
+	case FLAT_V850_R_HI16S_LO15:
+		/* The high and low halves of the address are in the 16
+		   bits at RP, and the upper 15 bits of the 2nd word of the
+		   32-bit instruction following that, respectively.  The
+		   low half is _signed_ so we have to sign-extend it and
+		   add it to the upper half instead of simply or-ing them
+		   together.  The lowest bit is always zero.
+
+		   Unlike most relocated address, this one is stored in
+		   native (little-endian) byte-order to avoid problems with
+		   trashing the low-order bit, so we have to convert to
+		   network-byte-order before returning, as that's what the
+		   caller expects.  */
+		return htonl ((srp[0] << 16) + (srp[2] & ~0x1));
+
+	default:
+		return ~0;	/* bogus value */
+	}
+}
+
+/* Insert the address ADDR into the symbol reference at RP;
+   RELVAL is the raw relocation-table entry from which RP is derived.
+   For the v850, RP should always be half-word aligned.  */
+static inline void flat_put_addr_at_rp (unsigned long *rp, unsigned long addr,
+					unsigned long relval)
+{
+	short *srp = (short *)rp;
+
+	switch (flat_v850_get_reloc_type (relval)) {
+	case FLAT_V850_R_32:
+		/* Simple 32-bit address.  */
+		srp[0] = addr & 0xFFFF;
+		srp[1] = (addr >> 16);
+		break;
+
+	case FLAT_V850_R_HI16S_LO16:
+		/* The high and low halves of the address are in the 16
+		   bits at RP, and the 2nd word of the 32-bit instruction
+		   following that, respectively.  The low half is _signed_
+		   so we must carry its sign bit to the upper half before
+		   writing the upper half.  */
+		srp[0] = (addr >> 16) + ((addr >> 15) & 0x1);
+		srp[2] = addr & 0xFFFF;
+		break;
+
+	case FLAT_V850_R_HI16S_LO15:
+		/* The high and low halves of the address are in the 16
+		   bits at RP, and the upper 15 bits of the 2nd word of the
+		   32-bit instruction following that, respectively.  The
+		   low half is _signed_ so we must carry its sign bit to
+		   the upper half before writing the upper half.  The
+		   lowest bit we preserve from the existing instruction.  */
+		srp[0] = (addr >> 16) + ((addr >> 15) & 0x1);
+		srp[2] = (addr & 0xFFFE) | (srp[2] & 0x1);
+		break;
+	}
+}
 
 #endif /* __V850_FLAT_H__ */
diff -Nru a/include/asm-v850/mmu_context.h b/include/asm-v850/mmu_context.h
--- a/include/asm-v850/mmu_context.h	Thu Jan  9 23:21:00 2003
+++ b/include/asm-v850/mmu_context.h	Sun Jul  6 18:52:00 2003
@@ -3,9 +3,9 @@
 
 #define destroy_context(mm)		((void)0)
 #define init_new_context(tsk,mm)	0
-#define switch_mm(prev,next,tsk,cpu)	((void)0)
+#define switch_mm(prev,next,tsk)	((void)0)
 #define deactivate_mm(tsk,mm)		do { } while (0)
 #define activate_mm(prev,next)		((void)0)
-#define enter_lazy_tlb(mm,tsk,cpu)	((void)0)
+#define enter_lazy_tlb(mm,tsk)		((void)0)
 
 #endif /* __V850_MMU_CONTEXT_H__ */
diff -Nru a/include/asm-x86_64/div64.h b/include/asm-x86_64/div64.h
--- a/include/asm-x86_64/div64.h	Thu Feb  7 02:55:27 2002
+++ b/include/asm-x86_64/div64.h	Thu Jul  3 00:37:22 2003
@@ -1,14 +1 @@
-#ifndef __X86_64_DIV64
-#define __X86_64_DIV64
-
-/*
- * Hey, we're already 64-bit, no
- * need to play games..
- */
-#define do_div(n,base) ({ \
-	int __res; \
-	__res = ((unsigned long) (n)) % (unsigned) (base); \
-	(n) = ((unsigned long) (n)) / (unsigned) (base); \
-	__res; })
-
-#endif
+#include <asm-generic/div64.h>
diff -Nru a/include/asm-x86_64/mmu_context.h b/include/asm-x86_64/mmu_context.h
--- a/include/asm-x86_64/mmu_context.h	Mon Jan 13 14:57:28 2003
+++ b/include/asm-x86_64/mmu_context.h	Sun Jul  6 18:52:00 2003
@@ -17,20 +17,21 @@
 
 #ifdef CONFIG_SMP
 
-static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk, unsigned cpu)
+static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
 {
 	if (read_pda(mmu_state) == TLBSTATE_OK) 
 		write_pda(mmu_state, TLBSTATE_LAZY);
 }
 #else
-static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk, unsigned cpu)
+static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
 {
 }
 #endif
 
 static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, 
-			     struct task_struct *tsk, unsigned cpu)
+			     struct task_struct *tsk)
 {
+	unsigned cpu = smp_processor_id();
 	if (likely(prev != next)) {
 		/* stop flush ipis for the previous mm */
 		clear_bit(cpu, &prev->cpu_vm_mask);
@@ -68,7 +69,7 @@
 } while(0)
 
 #define activate_mm(prev, next) \
-	switch_mm((prev),(next),NULL,smp_processor_id())
+	switch_mm((prev),(next),NULL)
 
 
 #endif
diff -Nru a/include/asm-x86_64/mmzone.h b/include/asm-x86_64/mmzone.h
--- a/include/asm-x86_64/mmzone.h	Sun Jun 15 02:06:56 2003
+++ b/include/asm-x86_64/mmzone.h	Wed Jul  2 21:20:53 2003
@@ -40,8 +40,7 @@
 #define node_mem_map(nid)	(NODE_DATA(nid)->node_mem_map)
 #define node_start_pfn(nid)	(NODE_DATA(nid)->node_start_pfn)
 #define node_end_pfn(nid)       (NODE_DATA(nid)->node_start_pfn + \
-				 NODE_DATA(nid)->node_size)
-#define node_size(nid)		(NODE_DATA(nid)->node_size)
+				 NODE_DATA(nid)->node_spanned_pages)
 
 #define local_mapnr(kvaddr) \
 	( (__pa(kvaddr) >> PAGE_SHIFT) - node_start_pfn(kvaddr_to_nid(kvaddr)) )
diff -Nru a/include/linux/acct.h b/include/linux/acct.h
--- a/include/linux/acct.h	Sun Dec  1 22:19:28 2002
+++ b/include/linux/acct.h	Sat Jul  5 01:48:36 2003
@@ -78,7 +78,7 @@
 #ifdef CONFIG_BSD_PROCESS_ACCT
 struct super_block;
 extern void acct_auto_close(struct super_block *sb);
-extern int acct_process(long exitcode);
+extern void acct_process(long exitcode);
 #else
 #define acct_auto_close(x)	do { } while (0)
 #define acct_process(x)		do { } while (0)
diff -Nru a/include/linux/affs_fs.h b/include/linux/affs_fs.h
--- a/include/linux/affs_fs.h	Sun Mar 17 11:38:14 2002
+++ b/include/linux/affs_fs.h	Sun Jun 29 23:49:04 2003
@@ -41,9 +41,9 @@
 /* namei.c */
 
 extern int	affs_hash_name(struct super_block *sb, const u8 *name, unsigned int len);
-extern struct dentry *affs_lookup(struct inode *dir, struct dentry *dentry);
+extern struct dentry *affs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *);
 extern int	affs_unlink(struct inode *dir, struct dentry *dentry);
-extern int	affs_create(struct inode *dir, struct dentry *dentry, int mode);
+extern int	affs_create(struct inode *dir, struct dentry *dentry, int mode, struct nameidata *);
 extern int	affs_mkdir(struct inode *dir, struct dentry *dentry, int mode);
 extern int	affs_rmdir(struct inode *dir, struct dentry *dentry);
 extern int	affs_link(struct dentry *olddentry, struct inode *dir,
diff -Nru a/include/linux/blkdev.h b/include/linux/blkdev.h
--- a/include/linux/blkdev.h	Wed Jun 11 18:17:55 2003
+++ b/include/linux/blkdev.h	Fri Jul  4 23:52:51 2003
@@ -22,11 +22,62 @@
 struct request_pm_state;
 
 #define BLKDEV_MIN_RQ	4
-#define BLKDEV_MAX_RQ	128
+#define BLKDEV_MAX_RQ	128	/* Default maximum */
+
+/*
+ * This is the per-process anticipatory I/O scheduler state.
+ */
+struct as_io_context {
+	spinlock_t lock;
+
+	void (*dtor)(struct as_io_context *aic); /* destructor */
+	void (*exit)(struct as_io_context *aic); /* called on task exit */
+
+	unsigned long state;
+	atomic_t nr_queued; /* queued reads & sync writes */
+	atomic_t nr_dispatched; /* number of requests gone to the drivers */
+
+	/* IO History tracking */
+	/* Thinktime */
+	unsigned long last_end_request;
+	unsigned long ttime_total;
+	unsigned long ttime_samples;
+	unsigned long ttime_mean;
+	/* Layout pattern */
+	long seek_samples;
+	sector_t last_request_pos;
+	sector_t seek_total;
+	sector_t seek_mean;
+};
+
+/*
+ * This is the per-process I/O subsystem state.  It is refcounted and
+ * kmalloc'ed. Currently all fields are modified in process io context
+ * (apart from the atomic refcount), so require no locking.
+ */
+struct io_context {
+	atomic_t refcount;
+	pid_t pid;
+
+	/*
+	 * For request batching
+	 */
+	unsigned long last_waited; /* Time last woken after wait for request */
+	int nr_batch_requests;     /* Number of requests left in the batch */
+
+	struct as_io_context *aic;
+};
+
+void put_io_context(struct io_context *ioc);
+void exit_io_context(void);
+struct io_context *get_io_context(int gfp_flags);
+void copy_io_context(struct io_context **pdst, struct io_context **psrc);
+void swap_io_context(struct io_context **ioc1, struct io_context **ioc2);
 
 struct request_list {
 	int count[2];
 	mempool_t *rq_pool;
+	wait_queue_head_t wait[2];
 };
 
 /*
@@ -268,8 +319,15 @@
 	spinlock_t		*queue_lock;
 
 	/*
+	 * queue kobject
+	 */
+	struct kobject kobj;
+
+	/*
 	 * queue settings
 	 */
+	unsigned long		nr_requests;	/* Max # of requests */
+
 	unsigned short		max_sectors;
 	unsigned short		max_phys_segments;
 	unsigned short		max_hw_segments;
@@ -299,6 +357,8 @@
 #define QUEUE_FLAG_CLUSTER	0	/* cluster several segments into 1 */
 #define QUEUE_FLAG_QUEUED	1	/* uses generic tag queueing */
 #define QUEUE_FLAG_STOPPED	2	/* queue is stopped */
+#define	QUEUE_FLAG_READFULL	3	/* write queue has been filled */
+#define QUEUE_FLAG_WRITEFULL	4	/* read queue has been filled */
 
 #define blk_queue_plugged(q)	!list_empty(&(q)->plug_list)
 #define blk_queue_tagged(q)	test_bit(QUEUE_FLAG_QUEUED, &(q)->queue_flags)
@@ -314,6 +374,30 @@
 
 #define rq_data_dir(rq)		((rq)->flags & 1)
 
+static inline int blk_queue_full(struct request_queue *q, int rw)
+{
+	if (rw == READ)
+		return test_bit(QUEUE_FLAG_READFULL, &q->queue_flags);
+	return test_bit(QUEUE_FLAG_WRITEFULL, &q->queue_flags);
+}
+
+static inline void blk_set_queue_full(struct request_queue *q, int rw)
+{
+	if (rw == READ)
+		set_bit(QUEUE_FLAG_READFULL, &q->queue_flags);
+	else
+		set_bit(QUEUE_FLAG_WRITEFULL, &q->queue_flags);
+}
+
+static inline void blk_clear_queue_full(struct request_queue *q, int rw)
+{
+	if (rw == READ)
+		clear_bit(QUEUE_FLAG_READFULL, &q->queue_flags);
+	else
+		clear_bit(QUEUE_FLAG_WRITEFULL, &q->queue_flags);
+}
+
+
 /*
  * mergeable request must not have _NOMERGE or _BARRIER bit set, nor may
  * it already be started by driver.
@@ -397,6 +481,8 @@
 	unsigned block_size_bits;
 };
 
+extern int blk_register_queue(struct gendisk *disk);
+extern void blk_unregister_queue(struct gendisk *disk);
 extern void register_disk(struct gendisk *dev);
 extern void generic_make_request(struct bio *bio);
 extern void blk_put_request(struct request *);
@@ -559,6 +645,10 @@
 {
 	page_cache_release(p.v);
 }
+
+struct work_struct;
+int kblockd_schedule_work(struct work_struct *work);
+void kblockd_flush(void);
 
 #ifdef CONFIG_LBD
 # include <asm/div64.h>
diff -Nru a/include/linux/buffer_head.h b/include/linux/buffer_head.h
--- a/include/linux/buffer_head.h	Thu Apr 24 03:30:41 2003
+++ b/include/linux/buffer_head.h	Thu Jul  3 18:54:38 2003
@@ -167,6 +167,7 @@
 struct buffer_head * __getblk(struct block_device *, sector_t, int);
 void __brelse(struct buffer_head *);
 void __bforget(struct buffer_head *);
+void __breadahead(struct block_device *, sector_t block, int size);
 struct buffer_head *__bread(struct block_device *, sector_t block, int size);
 struct buffer_head *alloc_buffer_head(int gfp_flags);
 void free_buffer_head(struct buffer_head * bh);
@@ -239,6 +240,12 @@
 sb_bread(struct super_block *sb, sector_t block)
 {
 	return __bread(sb->s_bdev, block, sb->s_blocksize);
+}
+
+static inline void
+sb_breadahead(struct super_block *sb, sector_t block)
+{
+	__breadahead(sb->s_bdev, block, sb->s_blocksize);
 }
 
 static inline struct buffer_head *
diff -Nru a/include/linux/coda_linux.h b/include/linux/coda_linux.h
--- a/include/linux/coda_linux.h	Sat Nov 16 19:49:10 2002
+++ b/include/linux/coda_linux.h	Sun Jun 29 23:49:26 2003
@@ -38,7 +38,7 @@
 int coda_open(struct inode *i, struct file *f);
 int coda_flush(struct file *f);
 int coda_release(struct inode *i, struct file *f);
-int coda_permission(struct inode *inode, int mask);
+int coda_permission(struct inode *inode, int mask, struct nameidata *nd);
 int coda_revalidate_inode(struct dentry *);
 int coda_getattr(struct vfsmount *, struct dentry *, struct kstat *);
 int coda_setattr(struct dentry *, struct iattr *);
diff -Nru a/include/linux/compat_ioctl.h b/include/linux/compat_ioctl.h
--- a/include/linux/compat_ioctl.h	Sat Jun 14 16:15:54 2003
+++ b/include/linux/compat_ioctl.h	Sun Jul  6 20:27:48 2003
@@ -117,7 +117,7 @@
 COMPATIBLE_IOCTL(STOP_ARRAY)
 COMPATIBLE_IOCTL(STOP_ARRAY_RO)
 COMPATIBLE_IOCTL(RESTART_ARRAY_RW)
-#ifdef CONFIG_DM
+#ifdef CONFIG_BLK_DEV_DM
 /* DM */
 COMPATIBLE_IOCTL(DM_VERSION)
 COMPATIBLE_IOCTL(DM_REMOVE_ALL)
diff -Nru a/include/linux/dcache.h b/include/linux/dcache.h
--- a/include/linux/dcache.h	Thu Jun 12 09:31:21 2003
+++ b/include/linux/dcache.h	Thu Jul  3 06:36:44 2003
@@ -10,6 +10,7 @@
 #include <linux/rcupdate.h>
 #include <asm/bug.h>
 
+struct nameidata;
 struct vfsmount;
 
 /*
@@ -106,7 +107,7 @@
 #define DNAME_INLINE_LEN	(sizeof(struct dentry)-offsetof(struct dentry,d_iname))
  
 struct dentry_operations {
-	int (*d_revalidate)(struct dentry *, int);
+	int (*d_revalidate)(struct dentry *, struct nameidata *);
 	int (*d_hash) (struct dentry *, struct qstr *);
 	int (*d_compare) (struct dentry *, struct qstr *, struct qstr *);
 	int (*d_delete)(struct dentry *);
diff -Nru a/include/linux/device.h b/include/linux/device.h
--- a/include/linux/device.h	Tue Jun 10 12:01:32 2003
+++ b/include/linux/device.h	Thu Jul  3 10:42:01 2003
@@ -18,6 +18,7 @@
 #include <linux/spinlock.h>
 #include <linux/types.h>
 #include <linux/ioport.h>
+#include <linux/module.h>
 #include <asm/semaphore.h>
 #include <asm/atomic.h>
 
@@ -95,7 +96,7 @@
 
 #define BUS_ATTR(_name,_mode,_show,_store)	\
 struct bus_attribute bus_attr_##_name = { 		\
-	.attr = {.name = __stringify(_name), .mode = _mode },	\
+	.attr = {.name = __stringify(_name), .mode = _mode, .owner = THIS_MODULE },	\
 	.show	= _show,				\
 	.store	= _store,				\
 };
@@ -136,7 +137,7 @@
 
 #define DRIVER_ATTR(_name,_mode,_show,_store)	\
 struct driver_attribute driver_attr_##_name = { 		\
-	.attr = {.name = __stringify(_name), .mode = _mode },	\
+	.attr = {.name = __stringify(_name), .mode = _mode, .owner = THIS_MODULE },	\
 	.show	= _show,				\
 	.store	= _store,				\
 };
@@ -176,7 +177,7 @@
 
 #define CLASS_ATTR(_name,_mode,_show,_store)			\
 struct class_attribute class_attr_##_name = { 			\
-	.attr = {.name = __stringify(_name), .mode = _mode },	\
+	.attr = {.name = __stringify(_name), .mode = _mode, .owner = THIS_MODULE },	\
 	.show	= _show,					\
 	.store	= _store,					\
 };
@@ -215,6 +216,8 @@
 extern int class_device_add(struct class_device *);
 extern void class_device_del(struct class_device *);
 
+extern int class_device_rename(struct class_device *, char *);
+
 extern struct class_device * class_device_get(struct class_device *);
 extern void class_device_put(struct class_device *);
 
@@ -226,7 +229,7 @@
 
 #define CLASS_DEVICE_ATTR(_name,_mode,_show,_store)		\
 struct class_device_attribute class_device_attr_##_name = { 	\
-	.attr = {.name = __stringify(_name), .mode = _mode },	\
+	.attr = {.name = __stringify(_name), .mode = _mode, .owner = THIS_MODULE },	\
 	.show	= _show,					\
 	.store	= _store,					\
 };
@@ -324,7 +327,7 @@
 
 #define DEVICE_ATTR(_name,_mode,_show,_store) \
 struct device_attribute dev_attr_##_name = { 		\
-	.attr = {.name = __stringify(_name), .mode = _mode },	\
+	.attr = {.name = __stringify(_name), .mode = _mode, .owner = THIS_MODULE },	\
 	.show	= _show,				\
 	.store	= _store,				\
 };
diff -Nru a/include/linux/efs_fs.h b/include/linux/efs_fs.h
--- a/include/linux/efs_fs.h	Fri Jun 20 13:16:06 2003
+++ b/include/linux/efs_fs.h	Thu Jul  3 06:36:44 2003
@@ -46,7 +46,7 @@
 extern void efs_read_inode(struct inode *);
 extern efs_block_t efs_map_block(struct inode *, efs_block_t);
 
-extern struct dentry *efs_lookup(struct inode *, struct dentry *);
+extern struct dentry *efs_lookup(struct inode *, struct dentry *, struct nameidata *);
 extern int efs_bmap(struct inode *, int);
 
 #endif /* __EFS_FS_H__ */
diff -Nru a/include/linux/eisa.h b/include/linux/eisa.h
--- a/include/linux/eisa.h	Mon Apr 21 09:22:28 2003
+++ b/include/linux/eisa.h	Fri Jul  4 00:46:02 2003
@@ -4,6 +4,8 @@
 #define EISA_SIG_LEN   8
 #define EISA_MAX_SLOTS 8
 
+#define EISA_MAX_RESOURCES 4
+
 /* A few EISA constants/offsets... */
 
 #define EISA_DMA1_STATUS            8
@@ -17,6 +19,10 @@
 #define EISA_INT1_EDGE_LEVEL    0x4D0
 #define EISA_INT2_EDGE_LEVEL    0x4D1
 #define EISA_VENDOR_ID_OFFSET   0xC80
+#define EISA_CONFIG_OFFSET      0xC84
+
+#define EISA_CONFIG_ENABLED         1
+#define EISA_CONFIG_FORCED          2
 
 /* The EISA signature, in ASCII form, null terminated */
 struct eisa_device_id {
@@ -26,19 +32,28 @@
 
 /* There is not much we can say about an EISA device, apart from
  * signature, slot number, and base address. dma_mask is set by
- * default to 32 bits.*/
+ * default to parent device mask..*/
 
 struct eisa_device {
 	struct eisa_device_id id;
 	int                   slot;
+	int                   state;
 	unsigned long         base_addr;
-	struct resource       res;
+	struct resource       res[EISA_MAX_RESOURCES];
 	u64                   dma_mask;
 	struct device         dev; /* generic device */
 };
 
 #define to_eisa_device(n) container_of(n, struct eisa_device, dev)
 
+static inline int eisa_get_region_index (void *addr)
+{
+	unsigned long x = (unsigned long) addr;
+
+	x &= 0xc00;
+	return (x >> 12);
+}
+
 struct eisa_driver {
 	const struct eisa_device_id *id_table;
 	struct device_driver         driver;
@@ -69,6 +84,8 @@
 	struct resource *res;
 	unsigned long    bus_base_addr;
 	int		 slots;  /* Max slot number */
+	int		 force_probe; /* Probe even when no slot 0 */
+	u64		 dma_mask; /* from bridge device */
 	int              bus_nr; /* Set by eisa_root_register */
 	struct resource  eisa_root_res;	/* ditto */
 };
diff -Nru a/include/linux/elevator.h b/include/linux/elevator.h
--- a/include/linux/elevator.h	Thu May 22 08:23:58 2003
+++ b/include/linux/elevator.h	Fri Jul  4 23:52:40 2003
@@ -15,6 +15,9 @@
 typedef void (elevator_remove_req_fn) (request_queue_t *, struct request *);
 typedef struct request *(elevator_request_list_fn) (request_queue_t *, struct request *);
 typedef struct list_head *(elevator_get_sort_head_fn) (request_queue_t *, struct request *);
+typedef void (elevator_completed_req_fn) (request_queue_t *, struct request *);
+typedef int (elevator_may_queue_fn) (request_queue_t *, int);
+
 typedef int (elevator_set_req_fn) (request_queue_t *, struct request *, int);
 typedef void (elevator_put_req_fn) (request_queue_t *, struct request *);
 
@@ -32,6 +35,7 @@
 	elevator_remove_req_fn *elevator_remove_req_fn;
 
 	elevator_queue_empty_fn *elevator_queue_empty_fn;
+	elevator_completed_req_fn *elevator_completed_req_fn;
 
 	elevator_request_list_fn *elevator_former_req_fn;
 	elevator_request_list_fn *elevator_latter_req_fn;
@@ -39,6 +43,8 @@
 	elevator_set_req_fn *elevator_set_req_fn;
 	elevator_put_req_fn *elevator_put_req_fn;
 
+	elevator_may_queue_fn *elevator_may_queue_fn;
+
 	elevator_init_fn *elevator_init_fn;
 	elevator_exit_fn *elevator_exit_fn;
 
@@ -62,8 +68,10 @@
 extern struct request *elv_next_request(struct request_queue *q);
 extern struct request *elv_former_request(request_queue_t *, struct request *);
 extern struct request *elv_latter_request(request_queue_t *, struct request *);
-extern int elv_register_queue(struct gendisk *);
-extern void elv_unregister_queue(struct gendisk *);
+extern int elv_register_queue(request_queue_t *q);
+extern void elv_unregister_queue(request_queue_t *q);
+extern int elv_may_queue(request_queue_t *, int);
+extern void elv_completed_request(request_queue_t *, struct request *);
 extern int elv_set_request(request_queue_t *, struct request *, int);
 extern void elv_put_request(request_queue_t *, struct request *);
 
@@ -80,6 +88,11 @@
  * starvation
  */
 extern elevator_t iosched_deadline;
+
+/*
+ * anticipatory I/O scheduler
+ */
+extern elevator_t iosched_as;
 
 extern int elevator_init(request_queue_t *, elevator_t *);
 extern void elevator_exit(request_queue_t *);
diff -Nru a/include/linux/eventpoll.h b/include/linux/eventpoll.h
--- a/include/linux/eventpoll.h	Tue Jun 24 04:44:30 2003
+++ b/include/linux/eventpoll.h	Fri Jul  4 23:52:56 2003
@@ -14,6 +14,8 @@
 #ifndef _LINUX_EVENTPOLL_H
 #define _LINUX_EVENTPOLL_H
 
+#include <linux/types.h>
+
 
 /* Valid opcodes to issue to sys_epoll_ctl() */
 #define EPOLL_CTL_ADD 1
@@ -55,8 +57,37 @@
 /* Used to initialize the epoll bits inside the "struct file" */
 void eventpoll_init_file(struct file *file);
 
-/* Used in fs/file_table.c:__fput() to unlink files from the eventpoll interface */
-void eventpoll_release(struct file *file);
+/* Used to release the epoll bits inside the "struct file" */
+void eventpoll_release_file(struct file *file);
+
+/*
+ * This is called from inside fs/file_table.c:__fput() to unlink files
+ * from the eventpoll interface. We need to have this facility to cleanup
+ * correctly files that are closed without being removed from the eventpoll
+ * interface.
+ */
+static inline void eventpoll_release(struct file *file)
+{
+
+	/*
+	 * Fast check to avoid the get/release of the semaphore. Since
+	 * we're doing this outside the semaphore lock, it might return
+	 * false negatives, but we don't care. It'll help in 99.99% of cases
+	 * to avoid the semaphore lock. False positives simply cannot happen
+	 * because the file in on the way to be removed and nobody ( but
+	 * eventpoll ) has still a reference to this file.
+	 */
+	if (likely(list_empty(&file->f_ep_links)))
+		return;
+
+	/*
+	 * The file is being closed while it is still linked to an epoll
+	 * descriptor. We need to handle this by correctly unlinking it
+	 * from its containers.
+	 */
+	eventpoll_release_file(file);
+}
+
 
 #else
 
diff -Nru a/include/linux/ext3_fs.h b/include/linux/ext3_fs.h
--- a/include/linux/ext3_fs.h	Fri Jun 27 23:20:44 2003
+++ b/include/linux/ext3_fs.h	Thu Jul  3 19:20:48 2003
@@ -636,10 +636,14 @@
 struct ext3_iloc
 {
 	struct buffer_head *bh;
-	struct ext3_inode *raw_inode;
+	unsigned long offset;
 	unsigned long block_group;
 };
 
+static inline struct ext3_inode *ext3_raw_inode(struct ext3_iloc *iloc)
+{
+	return (struct ext3_inode *) (iloc->bh->b_data + iloc->offset);
+}
 
 /*
  * This structure is stuffed into the struct file's private_data field
diff -Nru a/include/linux/ext3_fs_i.h b/include/linux/ext3_fs_i.h
--- a/include/linux/ext3_fs_i.h	Fri Jun 20 13:16:32 2003
+++ b/include/linux/ext3_fs_i.h	Fri Jul  4 22:31:27 2003
@@ -62,6 +62,16 @@
 	__u32	i_prealloc_count;
 #endif
 	__u32	i_dir_start_lookup;
+#ifdef CONFIG_EXT3_FS_XATTR
+	/*
+	 * Extended attributes can be read independently of the main file
+	 * data. Taking i_sem even when reading would cause contention
+	 * between readers of EAs and writers of regular file data, so
+	 * instead we synchronize on xattr_sem when reading or changing
+	 * EAs.
+	 */
+	struct rw_semaphore xattr_sem;
+#endif
 #ifdef CONFIG_EXT3_FS_POSIX_ACL
 	struct posix_acl	*i_acl;
 	struct posix_acl	*i_default_acl;
diff -Nru a/include/linux/flat.h b/include/linux/flat.h
--- a/include/linux/flat.h	Tue Feb 18 02:29:00 2003
+++ b/include/linux/flat.h	Wed Jul  2 18:18:38 2003
@@ -1,7 +1,7 @@
-
-/* Copyright (C) 1998  Kenneth Albanowski <kjahds@kjahds.com>
- *                     The Silver Hammer Group, Ltd.
- * Copyright (C) 2002  David McCullough <davidm@snapgear.com>
+/*
+ * Copyright (C) 2002-2003  David McCullough <davidm@snapgear.com>
+ * Copyright (C) 1998       Kenneth Albanowski <kjahds@kjahds.com>
+ *                          The Silver Hammer Group, Ltd.
  *
  * This file provides the definitions and structures needed to
  * support uClinux flat-format executables.
@@ -10,10 +10,18 @@
 #ifndef _LINUX_FLAT_H
 #define _LINUX_FLAT_H
 
+#ifdef __KERNEL__
 #include <asm/flat.h>
+#endif
 
 #define	FLAT_VERSION			0x00000004L
 
+#ifdef CONFIG_BINFMT_SHARED_FLAT
+#define	MAX_SHARED_LIBS			(4)
+#else
+#define	MAX_SHARED_LIBS			(1)
+#endif
+
 /*
  * To make everything easier to port and manage cross platform
  * development,  all fields are in network byte order.
@@ -46,8 +54,10 @@
 #define FLAT_FLAG_GOTPIC 0x0002 /* program is PIC with GOT */
 #define FLAT_FLAG_GZIP   0x0004 /* all but the header is compressed */
 #define FLAT_FLAG_GZDATA 0x0008 /* only data/relocs are compressed (for XIP) */
+#define FLAT_FLAG_KTRACE 0x0010 /* output useful kernel trace for debugging */
 
 
+#ifdef __KERNEL__ /* so systems without linux headers can compile the apps */
 /*
  * While it would be nice to keep this header clean,  users of older
  * tools still need this support in the kernel.  So this section is
@@ -84,5 +94,7 @@
 # endif
 	} reloc;
 } flat_v2_reloc_t;
+
+#endif /* __KERNEL__ */
 
 #endif /* _LINUX_FLAT_H */
diff -Nru a/include/linux/fs.h b/include/linux/fs.h
--- a/include/linux/fs.h	Fri Jun 20 13:16:06 2003
+++ b/include/linux/fs.h	Sun Jul  6 13:23:51 2003
@@ -420,6 +420,8 @@
 	unsigned long ahead_start;	/* Ahead window */
 	unsigned long ahead_size;
 	unsigned long ra_pages;		/* Maximum readahead window */
+	unsigned long mmap_hit;		/* Cache hit stat for mmap accesses */
+	unsigned long mmap_miss;	/* Cache miss stat for mmap accesses */
 };
 
 struct file {
@@ -639,7 +641,7 @@
 /*
  * VFS helper functions..
  */
-extern int vfs_create(struct inode *, struct dentry *, int);
+extern int vfs_create(struct inode *, struct dentry *, int, struct nameidata *);
 extern int vfs_mkdir(struct inode *, struct dentry *, int);
 extern int vfs_mknod(struct inode *, struct dentry *, int, dev_t);
 extern int vfs_symlink(struct inode *, struct dentry *, const char *);
@@ -730,8 +732,8 @@
 };
 
 struct inode_operations {
-	int (*create) (struct inode *,struct dentry *,int);
-	struct dentry * (*lookup) (struct inode *,struct dentry *);
+	int (*create) (struct inode *,struct dentry *,int, struct nameidata *);
+	struct dentry * (*lookup) (struct inode *,struct dentry *, struct nameidata *);
 	int (*link) (struct dentry *,struct inode *,struct dentry *);
 	int (*unlink) (struct inode *,struct dentry *);
 	int (*symlink) (struct inode *,struct dentry *,const char *);
@@ -743,7 +745,7 @@
 	int (*readlink) (struct dentry *, char __user *,int);
 	int (*follow_link) (struct dentry *, struct nameidata *);
 	void (*truncate) (struct inode *);
-	int (*permission) (struct inode *, int);
+	int (*permission) (struct inode *, int, struct nameidata *);
 	int (*setattr) (struct dentry *, struct iattr *);
 	int (*getattr) (struct vfsmount *mnt, struct dentry *, struct kstat *);
 	int (*setxattr) (struct dentry *, const char *,const void *,size_t,int);
@@ -1121,7 +1123,7 @@
 extern sector_t bmap(struct inode *, sector_t);
 extern int setattr_mask(unsigned int);
 extern int notify_change(struct dentry *, struct iattr *);
-extern int permission(struct inode *, int);
+extern int permission(struct inode *, int, struct nameidata *);
 extern int vfs_permission(struct inode *, int);
 extern int get_write_access(struct inode *);
 extern int deny_write_access(struct file *);
@@ -1291,7 +1293,7 @@
 extern int simple_commit_write(struct file *file, struct page *page,
 				unsigned offset, unsigned to);
 
-extern struct dentry *simple_lookup(struct inode *, struct dentry *);
+extern struct dentry *simple_lookup(struct inode *, struct dentry *, struct nameidata *);
 extern ssize_t generic_read_dir(struct file *, char __user *, size_t, loff_t *);
 extern struct file_operations simple_dir_operations;
 extern struct inode_operations simple_dir_inode_operations;
diff -Nru a/include/linux/hfs_fs.h b/include/linux/hfs_fs.h
--- a/include/linux/hfs_fs.h	Mon Oct  7 10:27:58 2002
+++ b/include/linux/hfs_fs.h	Sun Jun 29 23:49:04 2003
@@ -234,7 +234,7 @@
 					 const struct hfs_cat_key *);
 
 /* dir.c */
-extern int hfs_create(struct inode *, struct dentry *, int);
+extern int hfs_create(struct inode *, struct dentry *, int, struct nameidata *);
 extern int hfs_mkdir(struct inode *, struct dentry *, int);
 extern int hfs_unlink(struct inode *, struct dentry *);
 extern int hfs_rmdir(struct inode *, struct dentry *);
diff -Nru a/include/linux/interrupt.h b/include/linux/interrupt.h
--- a/include/linux/interrupt.h	Thu May 22 23:53:24 2003
+++ b/include/linux/interrupt.h	Wed Jul  2 00:17:58 2003
@@ -94,8 +94,8 @@
 asmlinkage void do_softirq(void);
 extern void open_softirq(int nr, void (*action)(struct softirq_action*), void *data);
 extern void softirq_init(void);
-#define __cpu_raise_softirq(cpu, nr) do { softirq_pending(cpu) |= 1UL << (nr); } while (0)
-extern void FASTCALL(cpu_raise_softirq(unsigned int cpu, unsigned int nr));
+#define __raise_softirq_irqoff(nr) do { local_softirq_pending() |= 1UL << (nr); } while (0)
+extern void FASTCALL(raise_softirq_irqoff(unsigned int nr));
 extern void FASTCALL(raise_softirq(unsigned int nr));
 
 #ifndef invoke_softirq
diff -Nru a/include/linux/ioport.h b/include/linux/ioport.h
--- a/include/linux/ioport.h	Thu Jun 12 03:02:55 2003
+++ b/include/linux/ioport.h	Thu Jul  3 08:38:43 2003
@@ -43,6 +43,7 @@
 #define IORESOURCE_SHADOWABLE	0x00010000
 #define IORESOURCE_BUS_HAS_VGA	0x00080000
 
+#define IORESOURCE_DISABLED	0x10000000
 #define IORESOURCE_UNSET	0x20000000
 #define IORESOURCE_AUTO		0x40000000
 #define IORESOURCE_BUSY		0x80000000	/* Driver has marked this resource busy */
diff -Nru a/include/linux/irq_cpustat.h b/include/linux/irq_cpustat.h
--- a/include/linux/irq_cpustat.h	Wed Jun 11 19:53:38 2003
+++ b/include/linux/irq_cpustat.h	Mon Jun 30 22:26:58 2003
@@ -29,10 +29,6 @@
   /* arch independent irq_stat fields */
 #define softirq_pending(cpu)	__IRQ_STAT((cpu), __softirq_pending)
 #define local_softirq_pending()	softirq_pending(smp_processor_id())
-#define syscall_count(cpu)	__IRQ_STAT((cpu), __syscall_count)
-#define local_syscall_count()	syscall_count(smp_processor_id())
-#define ksoftirqd_task(cpu)	__IRQ_STAT((cpu), __ksoftirqd_task)
-#define local_ksoftirqd_task()	ksoftirqd_task(smp_processor_id())
 
   /* arch dependent irq_stat fields */
 #define nmi_count(cpu)		__IRQ_STAT((cpu), __nmi_count)	/* i386 */
diff -Nru a/include/linux/iso_fs.h b/include/linux/iso_fs.h
--- a/include/linux/iso_fs.h	Fri Apr 25 12:35:37 2003
+++ b/include/linux/iso_fs.h	Thu Jul  3 06:36:44 2003
@@ -227,7 +227,7 @@
 int get_joliet_filename(struct iso_directory_record *, unsigned char *, struct inode *);
 int get_acorn_filename(struct iso_directory_record *, char *, struct inode *);
 
-extern struct dentry *isofs_lookup(struct inode *, struct dentry *);
+extern struct dentry *isofs_lookup(struct inode *, struct dentry *, struct nameidata *);
 extern struct buffer_head *isofs_bread(struct inode *, sector_t);
 extern int isofs_get_blocks(struct inode *, sector_t, struct buffer_head **, unsigned long);
 
diff -Nru a/include/linux/kernel_stat.h b/include/linux/kernel_stat.h
--- a/include/linux/kernel_stat.h	Mon Nov 25 14:41:41 2002
+++ b/include/linux/kernel_stat.h	Sun Jul  6 21:03:14 2003
@@ -31,7 +31,8 @@
 DECLARE_PER_CPU(struct kernel_stat, kstat);
 
 #define kstat_cpu(cpu)	per_cpu(kstat, cpu)
-#define kstat_this_cpu	kstat_cpu(smp_processor_id())
+/* Must have preemption disabled for this to be meaningful. */
+#define kstat_this_cpu	__get_cpu_var(kstat)
 
 extern unsigned long nr_context_switches(void);
 
diff -Nru a/include/linux/kobject.h b/include/linux/kobject.h
--- a/include/linux/kobject.h	Mon Jun  9 16:41:19 2003
+++ b/include/linux/kobject.h	Thu Jul  3 10:41:56 2003
@@ -39,6 +39,8 @@
 extern int kobject_add(struct kobject *);
 extern void kobject_del(struct kobject *);
 
+extern void kobject_rename(struct kobject *, char *new_name);
+
 extern int kobject_register(struct kobject *);
 extern void kobject_unregister(struct kobject *);
 
diff -Nru a/include/linux/mm.h b/include/linux/mm.h
--- a/include/linux/mm.h	Sat May 17 14:09:59 2003
+++ b/include/linux/mm.h	Sun Jul  6 13:23:51 2003
@@ -339,9 +339,14 @@
 	page->flags |= zone_num << ZONE_SHIFT;
 }
 
-static inline void * lowmem_page_address(struct page *page)
+#ifndef CONFIG_DISCONTIGMEM
+/* The array of struct pages - for discontigmem use pgdat->lmem_map */
+extern struct page *mem_map;
+#endif
+
+static inline void *lowmem_page_address(struct page *page)
 {
-	return __va( ( (page - page_zone(page)->zone_mem_map)	+ page_zone(page)->zone_start_pfn) << PAGE_SHIFT);
+	return __va(page_to_pfn(page) << PAGE_SHIFT);
 }
 
 #if defined(CONFIG_HIGHMEM) && !defined(WANT_PAGE_VIRTUAL)
@@ -395,11 +400,6 @@
 #define VM_FAULT_MINOR	1
 #define VM_FAULT_MAJOR	2
 
-#ifndef CONFIG_DISCONTIGMEM
-/* The array of struct pages - for discontigmem use pgdat->lmem_map */
-extern struct page *mem_map;
-#endif 
-
 extern void show_free_areas(void);
 
 struct page *shmem_nopage(struct vm_area_struct * vma,
@@ -571,10 +571,6 @@
 			  struct file_ra_state *ra,
 			  struct file *filp,
 			  unsigned long offset);
-void page_cache_readaround(struct address_space *mapping, 
-			   struct file_ra_state *ra,
-			   struct file *filp,
-			   unsigned long offset);
 void handle_ra_miss(struct address_space *mapping, 
 		    struct file_ra_state *ra, pgoff_t offset);
 unsigned long max_sane_readahead(unsigned long nr);
@@ -609,5 +605,13 @@
 		int write);
 extern int remap_page_range(struct vm_area_struct *vma, unsigned long from,
 		unsigned long to, unsigned long size, pgprot_t prot);
+
+#ifndef CONFIG_DEBUG_PAGEALLOC
+static inline void
+kernel_map_pages(struct page *page, int numpages, int enable)
+{
+}
+#endif
+
 #endif /* __KERNEL__ */
 #endif /* _LINUX_MM_H */
diff -Nru a/include/linux/mman.h b/include/linux/mman.h
--- a/include/linux/mman.h	Tue Mar 18 01:44:12 2003
+++ b/include/linux/mman.h	Wed Jul  2 21:22:38 2003
@@ -9,7 +9,8 @@
 #define MREMAP_MAYMOVE	1
 #define MREMAP_FIXED	2
 
-extern int vm_enough_memory(long pages);
+extern int sysctl_overcommit_memory;
+extern int sysctl_overcommit_ratio;
 extern atomic_t vm_committed_space;
 
 #ifdef CONFIG_SMP
diff -Nru a/include/linux/mmzone.h b/include/linux/mmzone.h
--- a/include/linux/mmzone.h	Thu Jun  5 23:37:53 2003
+++ b/include/linux/mmzone.h	Wed Jul  2 21:20:53 2003
@@ -184,11 +184,16 @@
 	unsigned long *valid_addr_bitmap;
 	struct bootmem_data *bdata;
 	unsigned long node_start_pfn;
-	unsigned long node_size;
+	unsigned long node_present_pages; /* total number of physical pages */
+	unsigned long node_spanned_pages; /* total size of physical page
+					     range, including holes */
 	int node_id;
 	struct pglist_data *pgdat_next;
 	wait_queue_head_t       kswapd_wait;
 } pg_data_t;
+
+#define node_present_pages(nid)	(NODE_DATA(nid)->node_present_pages)
+#define node_spanned_pages(nid)	(NODE_DATA(nid)->node_spanned_pages)
 
 extern int numnodes;
 extern struct pglist_data *pgdat_list;
diff -Nru a/include/linux/msdos_fs.h b/include/linux/msdos_fs.h
--- a/include/linux/msdos_fs.h	Fri Jun 20 13:16:06 2003
+++ b/include/linux/msdos_fs.h	Sun Jun 29 23:49:04 2003
@@ -307,8 +307,8 @@
 		    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 *);
-extern int msdos_create(struct inode *dir, struct dentry *dentry, int mode);
+extern struct dentry *msdos_lookup(struct inode *dir, struct dentry *, struct nameidata *);
+extern int msdos_create(struct inode *dir, struct dentry *dentry, int mode, struct nameidata *);
 extern int msdos_rmdir(struct inode *dir, struct dentry *dentry);
 extern int msdos_mkdir(struct inode *dir, struct dentry *dentry, int mode);
 extern int msdos_unlink(struct inode *dir, struct dentry *dentry);
@@ -317,8 +317,8 @@
 extern int msdos_fill_super(struct super_block *sb, void *data, int silent);
 
 /* vfat/namei.c - these are for dmsdos */
-extern struct dentry *vfat_lookup(struct inode *dir, struct dentry *);
-extern int vfat_create(struct inode *dir, struct dentry *dentry, int mode);
+extern struct dentry *vfat_lookup(struct inode *dir, struct dentry *, struct nameidata *);
+extern int vfat_create(struct inode *dir, struct dentry *dentry, int mode, struct nameidata *);
 extern int vfat_rmdir(struct inode *dir, struct dentry *dentry);
 extern int vfat_unlink(struct inode *dir, struct dentry *dentry);
 extern int vfat_mkdir(struct inode *dir, struct dentry *dentry, int mode);
diff -Nru a/include/linux/namei.h b/include/linux/namei.h
--- a/include/linux/namei.h	Wed Apr  9 11:44:15 2003
+++ b/include/linux/namei.h	Sun Jun 29 23:49:26 2003
@@ -5,12 +5,22 @@
 
 struct vfsmount;
 
+struct open_intent {
+	int	flags;
+	int	create_mode;
+};
+
 struct nameidata {
 	struct dentry	*dentry;
 	struct vfsmount *mnt;
 	struct qstr	last;
 	unsigned int	flags;
 	int		last_type;
+
+	/* Intent data */
+	union {
+		struct open_intent open;
+	} intent;
 };
 
 /*
@@ -31,7 +41,12 @@
 #define LOOKUP_CONTINUE		 4
 #define LOOKUP_PARENT		16
 #define LOOKUP_NOALT		32
-
+/*
+ * Intent data
+ */
+#define LOOKUP_OPEN		(0x0100)
+#define LOOKUP_CREATE		(0x0200)
+#define LOOKUP_ACCESS		(0x0400)
 
 extern int FASTCALL(__user_walk(const char __user *, unsigned, struct nameidata *));
 #define user_path_walk(name,nd) \
diff -Nru a/include/linux/netdevice.h b/include/linux/netdevice.h
--- a/include/linux/netdevice.h	Wed Jun 25 21:48:56 2003
+++ b/include/linux/netdevice.h	Wed Jul  2 00:20:08 2003
@@ -561,7 +561,7 @@
 		cpu = smp_processor_id();
 		dev->next_sched = softnet_data[cpu].output_queue;
 		softnet_data[cpu].output_queue = dev;
-		cpu_raise_softirq(cpu, NET_TX_SOFTIRQ);
+		raise_softirq_irqoff(NET_TX_SOFTIRQ);
 		local_irq_restore(flags);
 	}
 }
@@ -612,7 +612,7 @@
 		cpu = smp_processor_id();
 		skb->next = softnet_data[cpu].completion_queue;
 		softnet_data[cpu].completion_queue = skb;
-		cpu_raise_softirq(cpu, NET_TX_SOFTIRQ);
+		raise_softirq_irqoff(NET_TX_SOFTIRQ);
 		local_irq_restore(flags);
 	}
 }
@@ -779,7 +779,7 @@
 		dev->quota += dev->weight;
 	else
 		dev->quota = dev->weight;
-	__cpu_raise_softirq(cpu, NET_RX_SOFTIRQ);
+	__raise_softirq_irqoff(NET_RX_SOFTIRQ);
 	local_irq_restore(flags);
 }
 
@@ -805,7 +805,7 @@
 		local_irq_save(flags);
 		cpu = smp_processor_id();
 		list_add_tail(&dev->poll_list, &softnet_data[cpu].poll_list);
-		__cpu_raise_softirq(cpu, NET_RX_SOFTIRQ);
+		__raise_softirq_irqoff(NET_RX_SOFTIRQ);
 		local_irq_restore(flags);
 		return 1;
 	}
diff -Nru a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h
--- a/include/linux/nfs_fs.h	Mon Apr  7 15:27:32 2003
+++ b/include/linux/nfs_fs.h	Sun Jun 29 23:49:26 2003
@@ -240,7 +240,7 @@
 				struct nfs_fattr *);
 extern int __nfs_refresh_inode(struct inode *, struct nfs_fattr *);
 extern int nfs_getattr(struct vfsmount *, struct dentry *, struct kstat *);
-extern int nfs_permission(struct inode *, int);
+extern int nfs_permission(struct inode *, int, struct nameidata *);
 extern int nfs_open(struct inode *, struct file *);
 extern int nfs_release(struct inode *, struct file *);
 extern int __nfs_revalidate_inode(struct nfs_server *, struct inode *);
diff -Nru a/include/linux/pci.h b/include/linux/pci.h
--- a/include/linux/pci.h	Wed Jun 25 19:45:54 2003
+++ b/include/linux/pci.h	Thu Jul  3 08:08:44 2003
@@ -543,7 +543,7 @@
 
 /* Generic PCI functions used internally */
 
-int pci_bus_exists(const struct list_head *list, int nr);
+extern struct pci_bus *pci_find_bus(int domain, int busnr);
 struct pci_bus *pci_scan_bus_parented(struct device *parent, int bus, struct pci_ops *ops, void *sysdata);
 static inline struct pci_bus *pci_scan_bus(int bus, struct pci_ops *ops, void *sysdata)
 {
diff -Nru a/include/linux/proc_fs.h b/include/linux/proc_fs.h
--- a/include/linux/proc_fs.h	Sat Jun  7 15:17:50 2003
+++ b/include/linux/proc_fs.h	Thu Jul  3 06:36:45 2003
@@ -92,7 +92,7 @@
 extern void proc_root_init(void);
 extern void proc_misc_init(void);
 
-struct dentry *proc_pid_lookup(struct inode *dir, struct dentry * dentry);
+struct dentry *proc_pid_lookup(struct inode *dir, struct dentry * dentry, struct nameidata *);
 struct dentry *proc_pid_unhash(struct task_struct *p);
 void proc_pid_flush(struct dentry *proc_dentry);
 int proc_pid_readdir(struct file * filp, void * dirent, filldir_t filldir);
@@ -115,7 +115,7 @@
  * of the /proc/<pid> subdirectories.
  */
 extern int proc_readdir(struct file *, void *, filldir_t);
-extern struct dentry *proc_lookup(struct inode *, struct dentry *);
+extern struct dentry *proc_lookup(struct inode *, struct dentry *, struct nameidata *);
 
 extern struct file_operations proc_kcore_operations;
 extern struct file_operations proc_kmsg_operations;
diff -Nru a/include/linux/qnx4_fs.h b/include/linux/qnx4_fs.h
--- a/include/linux/qnx4_fs.h	Mon Oct  7 10:27:58 2002
+++ b/include/linux/qnx4_fs.h	Sun Jun 29 23:49:04 2003
@@ -110,21 +110,20 @@
 	struct inode vfs_inode;
 };
 
-extern struct dentry *qnx4_lookup(struct inode *dir, struct dentry *dentry);
+extern struct dentry *qnx4_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd);
 extern unsigned long qnx4_count_free_blocks(struct super_block *sb);
 extern unsigned long qnx4_block_map(struct inode *inode, long iblock);
 
 extern struct buffer_head *qnx4_getblk(struct inode *, int, int);
 extern struct buffer_head *qnx4_bread(struct inode *, int, int);
 
-extern int qnx4_create(struct inode *dir, struct dentry *dentry, int mode);
 extern struct inode_operations qnx4_file_inode_operations;
 extern struct inode_operations qnx4_dir_inode_operations;
 extern struct file_operations qnx4_file_operations;
 extern struct file_operations qnx4_dir_operations;
 extern int qnx4_is_free(struct super_block *sb, long block);
 extern int qnx4_set_bitmap(struct super_block *sb, long block, int busy);
-extern int qnx4_create(struct inode *inode, struct dentry *dentry, int mode);
+extern int qnx4_create(struct inode *inode, struct dentry *dentry, int mode, struct nameidata *nd);
 extern void qnx4_truncate(struct inode *inode);
 extern void qnx4_free_inode(struct inode *inode);
 extern int qnx4_unlink(struct inode *dir, struct dentry *dentry);
diff -Nru a/include/linux/quota.h b/include/linux/quota.h
--- a/include/linux/quota.h	Sat Apr 12 00:30:08 2003
+++ b/include/linux/quota.h	Fri Jul  4 19:29:30 2003
@@ -306,6 +306,16 @@
 void unregister_quota_format(struct quota_format_type *fmt);
 void init_dquot_operations(struct dquot_operations *fsdqops);
 
+struct quota_module_name {
+	int qm_fmt_id;
+	char *qm_mod_name;
+};
+
+#define INIT_QUOTA_MODULE_NAMES {\
+	{QFMT_VFS_OLD, "quota_v1"},\
+	{QFMT_VFS_V0, "quota_v2"},\
+	{0, NULL}}
+
 #else
 
 # /* nodep */ include <sys/cdefs.h>
diff -Nru a/include/linux/sched.h b/include/linux/sched.h
--- a/include/linux/sched.h	Thu Jun 19 22:04:35 2003
+++ b/include/linux/sched.h	Fri Jul  4 23:52:49 2003
@@ -321,6 +321,8 @@
 };
 
 
+struct io_context;			/* See blkdev.h */
+void exit_io_context(void);
 
 struct task_struct {
 	volatile long state;	/* -1 unrunnable, 0 runnable, >0 stopped */
@@ -450,6 +452,8 @@
 	struct dentry *proc_dentry;
 	struct backing_dev_info *backing_dev_info;
 
+	struct io_context *io_context;
+
 	unsigned long ptrace_message;
 	siginfo_t *last_siginfo; /* For ptrace use.  */
 };
@@ -481,6 +485,7 @@
 #define PF_KSWAPD	0x00040000	/* I am kswapd */
 #define PF_SWAPOFF	0x00080000	/* I am in swapoff */
 #define PF_LESS_THROTTLE 0x01000000	/* Throttle me less: I clena memory */
+#define PF_SYNCWRITE	0x00200000	/* I am doing a sync write */
 
 #ifdef CONFIG_SMP
 extern int set_cpus_allowed(task_t *p, unsigned long new_mask);
diff -Nru a/include/linux/security.h b/include/linux/security.h
--- a/include/linux/security.h	Wed Jun 25 16:30:52 2003
+++ b/include/linux/security.h	Wed Jul  2 21:22:38 2003
@@ -49,6 +49,7 @@
 extern int cap_task_post_setuid (uid_t old_ruid, uid_t old_euid, uid_t old_suid, int flags);
 extern void cap_task_reparent_to_init (struct task_struct *p);
 extern int cap_syslog (int type);
+extern int cap_vm_enough_memory (long pages);
 
 static inline int cap_netlink_send (struct sk_buff *skb)
 {
@@ -958,6 +959,10 @@
  *	See the syslog(2) manual page for an explanation of the @type values.  
  *	@type contains the type of action.
  *	Return 0 if permission is granted.
+ * @vm_enough_memory:
+ *	Check permissions for allocating a new virtual mapping.
+ *      @pages contains the number of pages.
+ *	Return 0 if permission is granted.
  *
  * @register_security:
  * 	allow module stacking.
@@ -989,6 +994,7 @@
 	int (*quotactl) (int cmds, int type, int id, struct super_block * sb);
 	int (*quota_on) (struct file * f);
 	int (*syslog) (int type);
+	int (*vm_enough_memory) (long pages);
 
 	int (*bprm_alloc_security) (struct linux_binprm * bprm);
 	void (*bprm_free_security) (struct linux_binprm * bprm);
@@ -1238,6 +1244,11 @@
 	return security_ops->syslog(type);
 }
 
+static inline int security_vm_enough_memory(long pages)
+{
+	return security_ops->vm_enough_memory(pages);
+}
+
 static inline int security_bprm_alloc (struct linux_binprm *bprm)
 {
 	return security_ops->bprm_alloc_security (bprm);
@@ -1896,6 +1907,11 @@
 static inline int security_syslog(int type)
 {
 	return cap_syslog(type);
+}
+
+static inline int security_vm_enough_memory(long pages)
+{
+	return cap_vm_enough_memory(pages);
 }
 
 static inline int security_bprm_alloc (struct linux_binprm *bprm)
diff -Nru a/include/linux/sem.h b/include/linux/sem.h
--- a/include/linux/sem.h	Fri Jun 20 13:16:16 2003
+++ b/include/linux/sem.h	Fri Jul  4 23:52:29 2003
@@ -109,7 +109,6 @@
 	int			id;	 /* internal sem id */
 	struct sembuf *		sops;	 /* array of pending operations */
 	int			nsops;	 /* number of operations */
-	int			alter;	 /* operation will alter semaphore */
 };
 
 /* Each task has a list of undo requests. They are executed automatically
diff -Nru a/include/linux/slab.h b/include/linux/slab.h
--- a/include/linux/slab.h	Sat Jun 14 20:55:10 2003
+++ b/include/linux/slab.h	Wed Jul  2 21:22:38 2003
@@ -114,6 +114,10 @@
 extern kmem_cache_t	*sighand_cachep;
 extern kmem_cache_t	*bio_cachep;
 
+void ptrinfo(unsigned long addr);
+
+extern atomic_t slab_reclaim_pages;
+
 #endif	/* __KERNEL__ */
 
 #endif	/* _LINUX_SLAB_H */
diff -Nru a/include/linux/sysfs.h b/include/linux/sysfs.h
--- a/include/linux/sysfs.h	Thu May 22 16:35:57 2003
+++ b/include/linux/sysfs.h	Thu Jul  3 10:41:51 2003
@@ -10,9 +10,11 @@
 #define _SYSFS_H_
 
 struct kobject;
+struct module;
 
 struct attribute {
 	char			* name;
+	struct module 		* owner;
 	mode_t			mode;
 };
 
@@ -36,6 +38,9 @@
 
 extern void
 sysfs_remove_dir(struct kobject *);
+
+extern void
+sysfs_rename_dir(struct kobject *, char *new_name);
 
 extern int
 sysfs_create_file(struct kobject *, struct attribute *);
diff -Nru a/include/linux/umsdos_fs.p b/include/linux/umsdos_fs.p
--- a/include/linux/umsdos_fs.p	Wed Nov 20 03:19:02 2002
+++ b/include/linux/umsdos_fs.p	Thu Jul  3 06:36:45 2003
@@ -10,7 +10,7 @@
 void umsdos_lookup_patch_new(struct dentry *, struct umsdos_info *);
 int umsdos_is_pseudodos (struct inode *dir, struct dentry *dentry);
 struct dentry *umsdos_lookup_x ( struct inode *dir, struct dentry *dentry, int nopseudo);
-struct dentry *UMSDOS_lookup(struct inode *, struct dentry *);
+struct dentry *UMSDOS_lookup(struct inode *, struct dentry *, struct nameidata *);
 struct dentry *umsdos_lookup_dentry(struct dentry *, char *, int, int);
 struct dentry *umsdos_covered(struct dentry *, char *, int);
 
@@ -92,7 +92,7 @@
 
 /* rdir.c 22/03/95 03.31.42 */
 struct dentry *umsdos_rlookup_x (struct inode *dir, struct dentry *dentry, int nopseudo);
-struct dentry *UMSDOS_rlookup (struct inode *dir, struct dentry *dentry);
+struct dentry *UMSDOS_rlookup (struct inode *dir, struct dentry *dentry, struct nameidata *nd);
 
 static inline struct umsdos_inode_info *UMSDOS_I(struct inode *inode)
 {
diff -Nru a/init/Kconfig b/init/Kconfig
--- a/init/Kconfig	Sun May 25 14:08:02 2003
+++ b/init/Kconfig	Wed Jul  2 21:23:11 2003
@@ -93,7 +93,8 @@
 	  limited in memory.
 
 config LOG_BUF_SHIFT
-	int "Kernel log buffer size" if DEBUG_KERNEL
+	int "Kernel log buffer size (16 => 64KB, 17 => 128KB)" if DEBUG_KERNEL
+	range 12 20
 	default 17 if ARCH_S390
 	default 16 if X86_NUMAQ || IA64
 	default 15 if SMP
diff -Nru a/ipc/sem.c b/ipc/sem.c
--- a/ipc/sem.c	Fri Jun 20 13:16:16 2003
+++ b/ipc/sem.c	Fri Jul  4 23:52:29 2003
@@ -49,6 +49,10 @@
  *      increase. If there are decrement operations in the operations
  *      array we do the same as before.
  *
+ * With the incarnation of O(1) scheduler, it becomes unnecessary to perform
+ * check/retry algorithm for waking up blocked processes as the new scheduler
+ * is better at handling thread switch than the old one.
+ *
  * /proc/sysvipc/sem support (c) 1999 Dragos Acostachioaie <dragos@iname.com>
  *
  * SMP-threaded, sysctl's added
@@ -258,8 +262,7 @@
  */
 
 static int try_atomic_semop (struct sem_array * sma, struct sembuf * sops,
-			     int nsops, struct sem_undo *un, int pid,
-			     int do_undo)
+			     int nsops, struct sem_undo *un, int pid)
 {
 	int result, sem_op;
 	struct sembuf *sop;
@@ -289,10 +292,6 @@
 		curr->semval = result;
 	}
 
-	if (do_undo) {
-		result = 0;
-		goto undo;
-	}
 	sop--;
 	while (sop >= sops) {
 		sma->sem_base[sop->sem_num].sempid = pid;
@@ -334,23 +333,14 @@
 
 	for (q = sma->sem_pending; q; q = q->next) {
 			
-		if (q->status == 1)
-			continue;	/* this one was woken up before */
-
 		error = try_atomic_semop(sma, q->sops, q->nsops,
-					 q->undo, q->pid, q->alter);
+					 q->undo, q->pid);
 
 		/* Does q->sleeper still need to sleep? */
 		if (error <= 0) {
-				/* Found one, wake it up */
-			wake_up_process(q->sleeper);
-			if (error == 0 && q->alter) {
-				/* if q-> alter let it self try */
-				q->status = 1;
-				return;
-			}
 			q->status = error;
 			remove_from_queue(sma,q);
+			wake_up_process(q->sleeper);
 		}
 	}
 }
@@ -1062,7 +1052,7 @@
 	if (error)
 		goto out_unlock_free;
 
-	error = try_atomic_semop (sma, sops, nsops, un, current->pid, 0);
+	error = try_atomic_semop (sma, sops, nsops, un, current->pid);
 	if (error <= 0)
 		goto update;
 
@@ -1075,55 +1065,46 @@
 	queue.nsops = nsops;
 	queue.undo = un;
 	queue.pid = current->pid;
-	queue.alter = decrease;
 	queue.id = semid;
 	if (alter)
 		append_to_queue(sma ,&queue);
 	else
 		prepend_to_queue(sma ,&queue);
 
-	for (;;) {
-		queue.status = -EINTR;
-		queue.sleeper = current;
-		current->state = TASK_INTERRUPTIBLE;
-		sem_unlock(sma);
+	queue.status = -EINTR;
+	queue.sleeper = current;
+	current->state = TASK_INTERRUPTIBLE;
+	sem_unlock(sma);
 
-		if (timeout)
-			jiffies_left = schedule_timeout(jiffies_left);
-		else
-			schedule();
+	if (timeout)
+		jiffies_left = schedule_timeout(jiffies_left);
+	else
+		schedule();
 
-		sma = sem_lock(semid);
-		if(sma==NULL) {
-			if(queue.prev != NULL)
-				BUG();
-			error = -EIDRM;
-			goto out_free;
-		}
-		/*
-		 * If queue.status == 1 we where woken up and
-		 * have to retry else we simply return.
-		 * If an interrupt occurred we have to clean up the
-		 * queue
-		 *
-		 */
-		if (queue.status == 1)
-		{
-			error = try_atomic_semop (sma, sops, nsops, un,
-						  current->pid,0);
-			if (error <= 0) 
-				break;
-		} else {
-			error = queue.status;
-			if (error == -EINTR && timeout && jiffies_left == 0)
-				error = -EAGAIN;
-			if (queue.prev) /* got Interrupt */
-				break;
-			/* Everything done by update_queue */
-			goto out_unlock_free;
-		}
+	sma = sem_lock(semid);
+	if(sma==NULL) {
+		if(queue.prev != NULL)
+			BUG();
+		error = -EIDRM;
+		goto out_free;
+	}
+
+	/*
+	 * If queue.status != -EINTR we are woken up by another process
+	 */
+	error = queue.status;
+	if (queue.status != -EINTR) {
+		goto out_unlock_free;
 	}
+
+	/*
+	 * If an interrupt occurred we have to clean up the queue
+	 */
+	if (timeout && jiffies_left == 0)
+		error = -EAGAIN;
 	remove_from_queue(sma,&queue);
+	goto out_unlock_free;
+
 update:
 	if (alter)
 		update_queue (sma);
diff -Nru a/kernel/acct.c b/kernel/acct.c
--- a/kernel/acct.c	Fri Jun 20 13:16:06 2003
+++ b/kernel/acct.c	Sun Jul  6 23:50:45 2003
@@ -394,17 +394,25 @@
 /*
  * acct_process - now just a wrapper around do_acct_process
  */
-int acct_process(long exitcode)
+void acct_process(long exitcode)
 {
 	struct file *file = NULL;
+
+	/*
+	 * accelerate the common fastpath:
+	 */
+	if (!acct_globals.file)
+		return;
+
 	spin_lock(&acct_globals.lock);
-	if (acct_globals.file) {
-		file = acct_globals.file;
-		get_file(file);
+	file = acct_globals.file;
+	if (unlikely(!file)) {
 		spin_unlock(&acct_globals.lock);
-		do_acct_process(exitcode, file);
-		fput(file);
-	} else
-		spin_unlock(&acct_globals.lock);
-	return 0;
+		return;
+	}
+	get_file(file);
+	spin_unlock(&acct_globals.lock);
+
+	do_acct_process(exitcode, file);
+	fput(file);
 }
diff -Nru a/kernel/exit.c b/kernel/exit.c
--- a/kernel/exit.c	Fri Jun 27 09:43:50 2003
+++ b/kernel/exit.c	Mon Jul  7 13:01:46 2003
@@ -230,6 +230,7 @@
 	/* signals? */
 	security_task_reparent_to_init(current);
 	memcpy(current->rlim, init_task.rlim, sizeof(*(current->rlim)));
+	atomic_inc(&(INIT_USER->__count));
 	switch_uid(INIT_USER);
 
 	write_unlock_irq(&tasklist_lock);
@@ -442,7 +443,7 @@
 	/* more a memory barrier than a real lock */
 	task_lock(tsk);
 	tsk->mm = NULL;
-	enter_lazy_tlb(mm, current, smp_processor_id());
+	enter_lazy_tlb(mm, current);
 	task_unlock(tsk);
 	mmput(mm);
 }
@@ -651,6 +652,8 @@
 	if (tsk->exit_signal != -1) {
 		int signal = tsk->parent == tsk->real_parent ? tsk->exit_signal : SIGCHLD;
 		do_notify_parent(tsk, signal);
+	} else if (tsk->ptrace) {
+		do_notify_parent(tsk, SIGCHLD);
 	}
 
 	tsk->state = TASK_ZOMBIE;
@@ -680,6 +683,8 @@
 		panic("Attempted to kill the idle task!");
 	if (unlikely(tsk->pid == 1))
 		panic("Attempted to kill init!");
+	if (tsk->io_context)
+		exit_io_context();
 	tsk->flags |= PF_EXITING;
 	del_timer_sync(&tsk->real_timer);
 
@@ -715,7 +720,7 @@
 	tsk->exit_code = code;
 	exit_notify(tsk);
 
-	if (tsk->exit_signal == -1)
+	if (tsk->exit_signal == -1 && tsk->ptrace == 0)
 		release_task(tsk);
 
 	schedule();
@@ -859,7 +864,7 @@
 		BUG_ON(state != TASK_DEAD);
 		return 0;
 	}
-	if (unlikely(p->exit_signal == -1))
+	if (unlikely(p->exit_signal == -1 && p->ptrace == 0))
 		/*
 		 * This can only happen in a race with a ptraced thread
 		 * dying on another processor.
@@ -889,8 +894,12 @@
 		/* Double-check with lock held.  */
 		if (p->real_parent != p->parent) {
 			__ptrace_unlink(p);
-			do_notify_parent(p, p->exit_signal);
 			p->state = TASK_ZOMBIE;
+			/* If this is a detached thread, this is where it goes away.  */
+			if (p->exit_signal == -1)
+				release_task (p);
+			else
+				do_notify_parent(p, p->exit_signal);
 			p = NULL;
 		}
 		write_unlock_irq(&tasklist_lock);
diff -Nru a/kernel/fork.c b/kernel/fork.c
--- a/kernel/fork.c	Fri Jun 27 09:43:50 2003
+++ b/kernel/fork.c	Fri Jul  4 23:52:49 2003
@@ -286,7 +286,7 @@
 			continue;
 		if (mpnt->vm_flags & VM_ACCOUNT) {
 			unsigned int len = (mpnt->vm_end - mpnt->vm_start) >> PAGE_SHIFT;
-			if (!vm_enough_memory(len))
+			if (security_vm_enough_memory(len))
 				goto fail_nomem;
 			charge += len;
 		}
@@ -864,6 +864,7 @@
 	p->lock_depth = -1;		/* -1 = no lock */
 	p->start_time = get_jiffies_64();
 	p->security = NULL;
+	p->io_context = NULL;
 
 	retval = -ENOMEM;
 	if ((retval = security_task_alloc(p)))
diff -Nru a/kernel/ksyms.c b/kernel/ksyms.c
--- a/kernel/ksyms.c	Tue Jun 24 14:26:24 2003
+++ b/kernel/ksyms.c	Thu Jul  3 00:32:44 2003
@@ -462,6 +462,7 @@
 #endif
 EXPORT_SYMBOL(schedule_timeout);
 EXPORT_SYMBOL(yield);
+EXPORT_SYMBOL(io_schedule);
 EXPORT_SYMBOL(__cond_resched);
 EXPORT_SYMBOL(set_user_nice);
 EXPORT_SYMBOL(task_nice);
@@ -586,7 +587,7 @@
 EXPORT_SYMBOL(do_softirq);
 EXPORT_SYMBOL(raise_softirq);
 EXPORT_SYMBOL(open_softirq);
-EXPORT_SYMBOL(cpu_raise_softirq);
+EXPORT_SYMBOL(raise_softirq_irqoff);
 EXPORT_SYMBOL(__tasklet_schedule);
 EXPORT_SYMBOL(__tasklet_hi_schedule);
 
diff -Nru a/kernel/sched.c b/kernel/sched.c
--- a/kernel/sched.c	Tue Jul  1 09:35:15 2003
+++ b/kernel/sched.c	Mon Jul  7 13:01:46 2003
@@ -508,8 +508,8 @@
 		}
 #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);
+			if (unlikely(kick) && task_running(rq, p) && (task_cpu(p) != smp_processor_id()))
+				smp_send_reschedule(task_cpu(p));
 #endif
 		p->state = TASK_RUNNING;
 	}
@@ -646,9 +646,9 @@
 	if (unlikely(!mm)) {
 		next->active_mm = oldmm;
 		atomic_inc(&oldmm->mm_count);
-		enter_lazy_tlb(oldmm, next, smp_processor_id());
+		enter_lazy_tlb(oldmm, next);
 	} else
-		switch_mm(oldmm, mm, next, smp_processor_id());
+		switch_mm(oldmm, mm, next);
 
 	if (unlikely(!prev->mm)) {
 		prev->active_mm = NULL;
@@ -1175,6 +1175,7 @@
 void scheduler_tick(int user_ticks, int sys_ticks)
 {
 	int cpu = smp_processor_id();
+	struct cpu_usage_stat *cpustat = &kstat_this_cpu.cpustat;
 	runqueue_t *rq = this_rq();
 	task_t *p = current;
 
@@ -1184,19 +1185,19 @@
 	if (p == rq->idle) {
 		/* note: this timer irq context must be accounted for as well */
 		if (irq_count() - HARDIRQ_OFFSET >= SOFTIRQ_OFFSET)
-			kstat_cpu(cpu).cpustat.system += sys_ticks;
+			cpustat->system += sys_ticks;
 		else if (atomic_read(&rq->nr_iowait) > 0)
-			kstat_cpu(cpu).cpustat.iowait += sys_ticks;
+			cpustat->iowait += sys_ticks;
 		else
-			kstat_cpu(cpu).cpustat.idle += sys_ticks;
+			cpustat->idle += sys_ticks;
 		rebalance_tick(rq, 1);
 		return;
 	}
 	if (TASK_NICE(p) > 0)
-		kstat_cpu(cpu).cpustat.nice += user_ticks;
+		cpustat->nice += user_ticks;
 	else
-		kstat_cpu(cpu).cpustat.user += user_ticks;
-	kstat_cpu(cpu).cpustat.system += sys_ticks;
+		cpustat->user += user_ticks;
+	cpustat->system += sys_ticks;
 
 	/* Task might have expired already, but not scheduled off yet */
 	if (p->array != rq->active) {
@@ -1332,7 +1333,7 @@
 switch_tasks:
 	prefetch(next);
 	clear_tsk_need_resched(prev);
-	RCU_qsctr(prev->thread_info->cpu)++;
+	RCU_qsctr(task_cpu(prev))++;
 
 	if (likely(prev != next)) {
 		rq->nr_switches++;
@@ -2527,7 +2528,7 @@
 	 * The boot idle thread does lazy MMU switching as well:
 	 */
 	atomic_inc(&init_mm.mm_count);
-	enter_lazy_tlb(&init_mm, current, smp_processor_id());
+	enter_lazy_tlb(&init_mm, current);
 }
 
 #ifdef CONFIG_DEBUG_SPINLOCK_SLEEP
diff -Nru a/kernel/signal.c b/kernel/signal.c
--- a/kernel/signal.c	Mon Jun  2 13:37:11 2003
+++ b/kernel/signal.c	Mon Jul  7 12:39:36 2003
@@ -579,8 +579,8 @@
 /*
  * Bad permissions for sending the signal
  */
-static inline int check_kill_permission(int sig, struct siginfo *info,
-					struct task_struct *t)
+static int check_kill_permission(int sig, struct siginfo *info,
+				 struct task_struct *t)
 {
 	int error = -EINVAL;
 	if (sig < 0 || sig > _NSIG)
@@ -797,10 +797,11 @@
 	int ret;
 
 	spin_lock_irqsave(&t->sighand->siglock, flags);
-	if (t->sighand->action[sig-1].sa.sa_handler == SIG_IGN)
+	if (sigismember(&t->blocked, sig) || t->sighand->action[sig-1].sa.sa_handler == SIG_IGN) {
 		t->sighand->action[sig-1].sa.sa_handler = SIG_DFL;
-	sigdelset(&t->blocked, sig);
-	recalc_sigpending_tsk(t);
+		sigdelset(&t->blocked, sig);
+		recalc_sigpending_tsk(t);
+	}
 	ret = specific_send_sig_info(sig, info, t);
 	spin_unlock_irqrestore(&t->sighand->siglock, flags);
 
@@ -2081,12 +2082,58 @@
 	info.si_signo = sig;
 	info.si_errno = 0;
 	info.si_code = SI_USER;
-	info.si_pid = current->pid;
+	info.si_pid = current->tgid;
 	info.si_uid = current->uid;
 
 	return kill_something_info(sig, &info, pid);
 }
 
+/**
+ *  sys_tkill - send signal to one specific thread
+ *  @tgid: the thread group ID of the thread
+ *  @pid: the PID of the thread
+ *  @sig: signal to be sent
+ *
+ *  This syscall also checks the tgid and returns -ESRCH even if the PID
+ *  exists but it's not belonging to the target process anymore. This
+ *  method solves the problem of threads exiting and PIDs getting reused.
+ */
+asmlinkage long sys_tgkill(int tgid, int pid, int sig)
+{
+	struct siginfo info;
+	int error;
+	struct task_struct *p;
+
+	/* This is only valid for single tasks */
+	if (pid <= 0 || tgid <= 0)
+		return -EINVAL;
+
+	info.si_signo = sig;
+	info.si_errno = 0;
+	info.si_code = SI_TKILL;
+	info.si_pid = current->tgid;
+	info.si_uid = current->uid;
+
+	read_lock(&tasklist_lock);
+	p = find_task_by_pid(pid);
+	error = -ESRCH;
+	if (p && (p->tgid == tgid)) {
+		error = check_kill_permission(sig, &info, p);
+		/*
+		 * The null signal is a permissions and process existence
+		 * probe.  No signal is actually delivered.
+		 */
+		if (!error && sig && p->sighand) {
+			spin_lock_irq(&p->sighand->siglock);
+			handle_stop_signal(sig, p);
+			error = specific_send_sig_info(sig, &info, p);
+			spin_unlock_irq(&p->sighand->siglock);
+		}
+	}
+	read_unlock(&tasklist_lock);
+	return error;
+}
+
 /*
  *  Send a signal to only one task, even if it's a CLONE_THREAD task.
  */
@@ -2104,7 +2151,7 @@
 	info.si_signo = sig;
 	info.si_errno = 0;
 	info.si_code = SI_TKILL;
-	info.si_pid = current->pid;
+	info.si_pid = current->tgid;
 	info.si_uid = current->uid;
 
 	read_lock(&tasklist_lock);
diff -Nru a/kernel/softirq.c b/kernel/softirq.c
--- a/kernel/softirq.c	Wed Jun 11 19:53:38 2003
+++ b/kernel/softirq.c	Mon Jun 30 22:26:58 2003
@@ -14,6 +14,7 @@
 #include <linux/init.h>
 #include <linux/mm.h>
 #include <linux/notifier.h>
+#include <linux/percpu.h>
 #include <linux/cpu.h>
 
 /*
@@ -41,15 +42,18 @@
 
 static struct softirq_action softirq_vec[32] __cacheline_aligned_in_smp;
 
+static DEFINE_PER_CPU(struct task_struct *, ksoftirqd);
+
 /*
  * we cannot loop indefinitely here to avoid userspace starvation,
  * but we also don't want to introduce a worst case 1/HZ latency
  * to the pending events, so lets the scheduler to balance
  * the softirq load for us.
  */
-static inline void wakeup_softirqd(unsigned cpu)
+static inline void wakeup_softirqd(void)
 {
-	struct task_struct * tsk = ksoftirqd_task(cpu);
+	/* Interrupts are disabled: no need to stop preemption */
+	struct task_struct *tsk = __get_cpu_var(ksoftirqd);
 
 	if (tsk && tsk->state != TASK_RUNNING)
 		wake_up_process(tsk);
@@ -96,7 +100,7 @@
 			goto restart;
 		}
 		if (pending)
-			wakeup_softirqd(smp_processor_id());
+			wakeup_softirqd();
 		__local_bh_enable();
 	}
 
@@ -117,9 +121,9 @@
 /*
  * This function must run with irqs disabled!
  */
-inline void cpu_raise_softirq(unsigned int cpu, unsigned int nr)
+inline void raise_softirq_irqoff(unsigned int nr)
 {
-	__cpu_raise_softirq(cpu, nr);
+	__raise_softirq_irqoff(nr);
 
 	/*
 	 * If we're in an interrupt or softirq, we're done
@@ -131,7 +135,7 @@
 	 * schedule the softirq soon.
 	 */
 	if (!in_interrupt())
-		wakeup_softirqd(cpu);
+		wakeup_softirqd();
 }
 
 void raise_softirq(unsigned int nr)
@@ -139,7 +143,7 @@
 	unsigned long flags;
 
 	local_irq_save(flags);
-	cpu_raise_softirq(smp_processor_id(), nr);
+	raise_softirq_irqoff(nr);
 	local_irq_restore(flags);
 }
 
@@ -168,7 +172,7 @@
 	local_irq_save(flags);
 	t->next = __get_cpu_var(tasklet_vec).list;
 	__get_cpu_var(tasklet_vec).list = t;
-	cpu_raise_softirq(smp_processor_id(), TASKLET_SOFTIRQ);
+	raise_softirq_irqoff(TASKLET_SOFTIRQ);
 	local_irq_restore(flags);
 }
 
@@ -179,7 +183,7 @@
 	local_irq_save(flags);
 	t->next = __get_cpu_var(tasklet_hi_vec).list;
 	__get_cpu_var(tasklet_hi_vec).list = t;
-	cpu_raise_softirq(smp_processor_id(), HI_SOFTIRQ);
+	raise_softirq_irqoff(HI_SOFTIRQ);
 	local_irq_restore(flags);
 }
 
@@ -211,7 +215,7 @@
 		local_irq_disable();
 		t->next = __get_cpu_var(tasklet_vec).list;
 		__get_cpu_var(tasklet_vec).list = t;
-		__cpu_raise_softirq(smp_processor_id(), TASKLET_SOFTIRQ);
+		__raise_softirq_irqoff(TASKLET_SOFTIRQ);
 		local_irq_enable();
 	}
 }
@@ -244,7 +248,7 @@
 		local_irq_disable();
 		t->next = __get_cpu_var(tasklet_hi_vec).list;
 		__get_cpu_var(tasklet_hi_vec).list = t;
-		__cpu_raise_softirq(smp_processor_id(), HI_SOFTIRQ);
+		__raise_softirq_irqoff(HI_SOFTIRQ);
 		local_irq_enable();
 	}
 }
@@ -325,7 +329,7 @@
 	__set_current_state(TASK_INTERRUPTIBLE);
 	mb();
 
-	local_ksoftirqd_task() = current;
+	__get_cpu_var(ksoftirqd) = current;
 
 	for (;;) {
 		if (!local_softirq_pending())
@@ -354,7 +358,7 @@
 			return NOTIFY_BAD;
 		}
 
-		while (!ksoftirqd_task(hotcpu))
+		while (!per_cpu(ksoftirqd, hotcpu))
 			yield();
  	}
 	return NOTIFY_OK;
diff -Nru a/kernel/suspend.c b/kernel/suspend.c
--- a/kernel/suspend.c	Sun May 25 23:19:07 2003
+++ b/kernel/suspend.c	Mon Jul  7 13:10:40 2003
@@ -1203,12 +1203,12 @@
 
 void software_resume(void)
 {
-#ifdef CONFIG_SMP
-	printk(KERN_WARNING "Software Suspend has a malfunctioning SMP support. Disabled :(\n");
-#else
+	if (num_online_cpus() > 1) {
+		printk(KERN_WARNING "Software Suspend has malfunctioning SMP support. Disabled :(\n");	
+		return;
+	}
 	/* We enable the possibility of machine suspend */
 	software_suspend_enabled = 1;
-#endif
 	if (!resume_status)
 		return;
 
diff -Nru a/kernel/sysctl.c b/kernel/sysctl.c
--- a/kernel/sysctl.c	Sat Jun 14 16:16:11 2003
+++ b/kernel/sysctl.c	Sun Jun 29 23:49:26 2003
@@ -130,7 +130,7 @@
 
 static ssize_t proc_readsys(struct file *, char __user *, size_t, loff_t *);
 static ssize_t proc_writesys(struct file *, const char __user *, size_t, loff_t *);
-static int proc_sys_permission(struct inode *, int);
+static int proc_sys_permission(struct inode *, int, struct nameidata *);
 
 struct file_operations proc_sys_file_operations = {
 	.read		= proc_readsys,
@@ -1177,7 +1177,7 @@
 	return do_rw_proc(1, file, (char __user *) buf, count, ppos);
 }
 
-static int proc_sys_permission(struct inode *inode, int op)
+static int proc_sys_permission(struct inode *inode, int op, struct nameidata *nd)
 {
 	return test_perm(inode->i_mode, op);
 }
diff -Nru a/kernel/timer.c b/kernel/timer.c
--- a/kernel/timer.c	Fri Jun 27 09:43:50 2003
+++ b/kernel/timer.c	Sat Jul  5 17:00:00 2003
@@ -126,13 +126,17 @@
 		 * or you set a timer to go off in the past
 		 */
 		vec = base->tv1.vec + (base->timer_jiffies & TVR_MASK);
-	} else if (idx <= 0xffffffffUL) {
-		int i = (expires >> (TVR_BITS + 3 * TVN_BITS)) & TVN_MASK;
-		vec = base->tv5.vec + i;
 	} else {
-		/* Can only get here on architectures with 64-bit jiffies */
-		INIT_LIST_HEAD(&timer->entry);
-		return;
+		int i;
+		/* If the timeout is larger than 0xffffffff on 64-bit
+		 * architectures then we use the maximum timeout:
+		 */
+		if (idx > 0xffffffffUL) {
+			idx = 0xffffffffUL;
+			expires = idx + base->timer_jiffies;
+		}
+		i = (expires >> (TVR_BITS + 3 * TVN_BITS)) & TVN_MASK;
+		vec = base->tv5.vec + i;
 	}
 	/*
 	 * Timers are FIFO:
diff -Nru a/kernel/user.c b/kernel/user.c
--- a/kernel/user.c	Mon Feb 10 19:20:53 2003
+++ b/kernel/user.c	Fri Jul  4 23:52:56 2003
@@ -126,7 +126,6 @@
 	 * we should be checking for it.  -DaveM
 	 */
 	old_user = current->user;
-	atomic_inc(&new_user->__count);
 	atomic_inc(&new_user->processes);
 	atomic_dec(&old_user->processes);
 	current->user = new_user;
diff -Nru a/lib/Makefile b/lib/Makefile
--- a/lib/Makefile	Tue May 27 04:51:59 2003
+++ b/lib/Makefile	Thu Jul  3 00:37:22 2003
@@ -5,7 +5,7 @@
 
 lib-y := errno.o ctype.o string.o vsprintf.o cmdline.o \
 	 bust_spinlocks.o rbtree.o radix-tree.o dump_stack.o \
-	 kobject.o idr.o
+	 kobject.o idr.o div64.o
 
 lib-$(CONFIG_RWSEM_GENERIC_SPINLOCK) += rwsem-spinlock.o
 lib-$(CONFIG_RWSEM_XCHGADD_ALGORITHM) += rwsem.o
diff -Nru a/lib/div64.c b/lib/div64.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/lib/div64.c	Thu Jul  3 00:37:22 2003
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2003 Bernardo Innocenti <bernie@develer.com>
+ *
+ * Based on former do_div() implementation from asm-parisc/div64.h:
+ *	Copyright (C) 1999 Hewlett-Packard Co
+ *	Copyright (C) 1999 David Mosberger-Tang <davidm@hpl.hp.com>
+ *
+ *
+ * Generic C version of 64bit/32bit division and modulo, with
+ * 64bit result and 32bit remainder.
+ *
+ * The fast case for (n>>32 == 0) is handled inline by do_div(). 
+ *
+ * Code generated for this function might be very inefficient
+ * for some CPUs. div64_32() can be overridden by linking arch-specific
+ * assembly versions such as arch/ppc/lib/div64.S and arch/sh/lib/div64.S.
+ */
+
+#include <linux/types.h>
+#include <asm/div64.h>
+
+uint32_t __div64_32(uint64_t *n, uint32_t base)
+{
+	uint32_t low, low2, high, rem;
+
+	low   = *n   & 0xffffffff;
+	high  = *n  >> 32;
+	rem   = high % (uint32_t)base;
+	high  = high / (uint32_t)base;
+	low2  = low >> 16;
+	low2 += rem << 16;
+	rem   = low2 % (uint32_t)base;
+	low2  = low2 / (uint32_t)base;
+	low   = low  & 0xffff;
+	low  += rem << 16;
+	rem   = low  % (uint32_t)base;
+	low   = low  / (uint32_t)base;
+
+	*n = low +
+		((uint64_t)low2 << 16) +
+		((uint64_t)high << 32);
+
+	return rem;
+}
+
diff -Nru a/lib/kobject.c b/lib/kobject.c
--- a/lib/kobject.c	Mon Jun 16 09:02:18 2003
+++ b/lib/kobject.c	Thu Jul  3 10:41:56 2003
@@ -314,6 +314,21 @@
 }
 
 /**
+ *	kobject_rename - change the name of an object
+ *	@kobj:	object in question.
+ *	@new_name: object's new name
+ */
+
+void kobject_rename(struct kobject * kobj, char *new_name)
+{
+	kobj = kobject_get(kobj);
+	if (!kobj)
+		return;
+	sysfs_rename_dir(kobj, new_name);
+	kobject_put(kobj);
+}
+
+/**
  *	kobject_del - unlink kobject from hierarchy.
  * 	@kobj:	object.
  */
diff -Nru a/mm/bootmem.c b/mm/bootmem.c
--- a/mm/bootmem.c	Sat Jun  7 15:17:54 2003
+++ b/mm/bootmem.c	Fri Jul  4 23:52:55 2003
@@ -84,10 +84,6 @@
 
 	if (!size) BUG();
 
-	if (sidx < 0)
-		BUG();
-	if (eidx < 0)
-		BUG();
 	if (sidx >= eidx)
 		BUG();
 	if ((addr >> PAGE_SHIFT) >= bdata->node_low_pfn)
@@ -202,7 +198,7 @@
 		;
 	}
 
-	if (preferred) {
+	if (preferred > offset) {
 		preferred = offset;
 		goto restart_scan;
 	}
diff -Nru a/mm/filemap.c b/mm/filemap.c
--- a/mm/filemap.c	Wed Jun  4 00:50:31 2003
+++ b/mm/filemap.c	Sun Jul  6 13:23:51 2003
@@ -925,6 +925,9 @@
 	return error == -EEXIST ? 0 : error;
 }
 
+#define MMAP_READAROUND (16UL)
+#define MMAP_LOTSAMISS  (100)
+
 /*
  * filemap_nopage() is invoked via the vma operations vector for a
  * mapped memory region to read in file data during a page fault.
@@ -942,19 +945,19 @@
 	struct inode *inode = mapping->host;
 	struct page *page;
 	unsigned long size, pgoff, endoff;
-	int did_readahead;
+	int did_readaround = 0;
 
 	pgoff = ((address - area->vm_start) >> PAGE_CACHE_SHIFT) + area->vm_pgoff;
 	endoff = ((area->vm_end - area->vm_start) >> PAGE_CACHE_SHIFT) + area->vm_pgoff;
 
 retry_all:
-	/*
-	 * An external ptracer can access pages that normally aren't
-	 * accessible..
-	 */
 	size = (inode->i_size + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
-	if ((pgoff >= size) && (area->vm_mm == current->mm))
-		return NULL;
+	if (pgoff >= size)
+		goto outside_data_content;
+
+	/* If we don't want any read-ahead, don't bother */
+	if (VM_RandomReadHint(area))
+		goto no_cached_page;
 
 	/*
 	 * The "size" of the file, as far as mmap is concerned, isn't bigger
@@ -963,25 +966,14 @@
 	if (size > endoff)
 		size = endoff;
 
-	did_readahead = 0;
-
 	/*
 	 * The readahead code wants to be told about each and every page
 	 * so it can build and shrink its windows appropriately
+	 *
+	 * For sequential accesses, we use the generic readahead logic.
 	 */
-	if (VM_SequentialReadHint(area)) {
-		did_readahead = 1;
+	if (VM_SequentialReadHint(area))
 		page_cache_readahead(mapping, ra, file, pgoff);
-	}
-
-	/*
-	 * If the offset is outside the mapping size we're off the end
-	 * of a privately mapped file, so we need to map a zero page.
-	 */
-	if ((pgoff < size) && !VM_RandomReadHint(area)) {
-		did_readahead = 1;
-		page_cache_readaround(mapping, ra, file, pgoff);
-	}
 
 	/*
 	 * Do we have something in the page cache already?
@@ -989,13 +981,27 @@
 retry_find:
 	page = find_get_page(mapping, pgoff);
 	if (!page) {
-		if (did_readahead) {
+		if (VM_SequentialReadHint(area)) {
 			handle_ra_miss(mapping, ra, pgoff);
-			did_readahead = 0;
+			goto no_cached_page;
 		}
-		goto no_cached_page;
+		ra->mmap_miss++;
+
+		/*
+		 * Do we miss much more than hit in this file? If so,
+		 * stop bothering with read-ahead. It will only hurt.
+		 */
+		if (ra->mmap_miss > ra->mmap_hit + MMAP_LOTSAMISS)
+			goto no_cached_page;
+
+		did_readaround = 1;
+		do_page_cache_readahead(mapping, file, pgoff & ~(MMAP_READAROUND-1), MMAP_READAROUND);
+		goto retry_find;
 	}
 
+	if (!did_readaround)
+		ra->mmap_hit++;
+
 	/*
 	 * Ok, found a page in the page cache, now we need to check
 	 * that it's up-to-date.
@@ -1010,6 +1016,14 @@
 	mark_page_accessed(page);
 	return page;
 
+outside_data_content:
+	/*
+	 * An external ptracer can access pages that normally aren't
+	 * accessible..
+	 */
+	if (area->vm_mm == current->mm)
+		return NULL;
+	/* Fall through to the non-read-ahead case */
 no_cached_page:
 	/*
 	 * We're only likely to ever get here if MADV_RANDOM is in
diff -Nru a/mm/mmap.c b/mm/mmap.c
--- a/mm/mmap.c	Mon Jun 30 03:56:22 2003
+++ b/mm/mmap.c	Wed Jul  2 21:22:38 2003
@@ -18,6 +18,7 @@
 #include <linux/security.h>
 #include <linux/hugetlb.h>
 #include <linux/profile.h>
+#include <linux/module.h>
 
 #include <asm/uaccess.h>
 #include <asm/pgalloc.h>
@@ -53,65 +54,9 @@
 int sysctl_overcommit_ratio = 50;	/* default is 50% */
 atomic_t vm_committed_space = ATOMIC_INIT(0);
 
-/*
- * Check that a process has enough memory to allocate a new virtual
- * mapping. 1 means there is enough memory for the allocation to
- * succeed and 0 implies there is not.
- *
- * We currently support three overcommit policies, which are set via the
- * vm.overcommit_memory sysctl.  See Documentation/vm/overcommit-acounting
- *
- * Strict overcommit modes added 2002 Feb 26 by Alan Cox.
- * Additional code 2002 Jul 20 by Robert Love.
- */
-extern atomic_t slab_reclaim_pages;
-int vm_enough_memory(long pages)
-{
-	unsigned long free, allowed;
-
-	vm_acct_memory(pages);
-
-        /*
-	 * Sometimes we want to use more memory than we have
-	 */
-	if (sysctl_overcommit_memory == 1)
-		return 1;
-
-	if (sysctl_overcommit_memory == 0) {
-		free = get_page_cache_size();
-		free += nr_free_pages();
-		free += nr_swap_pages;
-
-		/*
-		 * Any slabs which are created with the
-		 * SLAB_RECLAIM_ACCOUNT flag claim to have contents
-		 * which are reclaimable, under pressure.  The dentry
-		 * cache and most inode caches should fall into this
-		 */
-		free += atomic_read(&slab_reclaim_pages);
-
-		/*
-		 * Leave the last 3% for root
-		 */
-		if (!capable(CAP_SYS_ADMIN))
-			free -= free / 32;
-		
-		if (free > pages)
-			return 1;
-		vm_unacct_memory(pages);
-		return 0;
-	}
-
-	allowed = totalram_pages * sysctl_overcommit_ratio / 100;
-	allowed += total_swap_pages;
-
-	if (atomic_read(&vm_committed_space) < allowed)
-		return 1;
-
-	vm_unacct_memory(pages);
-
-	return 0;
-}
+EXPORT_SYMBOL(sysctl_overcommit_memory);
+EXPORT_SYMBOL(sysctl_overcommit_ratio);
+EXPORT_SYMBOL(vm_committed_space);
 
 /*
  * Requires inode->i_mapping->i_shared_sem
@@ -646,7 +591,7 @@
 			 * Private writable mapping: check memory availability
 			 */
 			charged = len >> PAGE_SHIFT;
-			if (!vm_enough_memory(charged))
+			if (security_vm_enough_memory(charged))
 				return -ENOMEM;
 			vm_flags |= VM_ACCOUNT;
 		}
@@ -950,7 +895,7 @@
 	grow = (address - vma->vm_end) >> PAGE_SHIFT;
 
 	/* Overcommit.. */
-	if (!vm_enough_memory(grow)) {
+	if (security_vm_enough_memory(grow)) {
 		spin_unlock(&vma->vm_mm->page_table_lock);
 		return -ENOMEM;
 	}
@@ -1004,7 +949,7 @@
 	grow = (vma->vm_start - address) >> PAGE_SHIFT;
 
 	/* Overcommit.. */
-	if (!vm_enough_memory(grow)) {
+	if (security_vm_enough_memory(grow)) {
 		spin_unlock(&vma->vm_mm->page_table_lock);
 		return -ENOMEM;
 	}
@@ -1376,7 +1321,7 @@
 	if (mm->map_count > MAX_MAP_COUNT)
 		return -ENOMEM;
 
-	if (!vm_enough_memory(len >> PAGE_SHIFT))
+	if (security_vm_enough_memory(len >> PAGE_SHIFT))
 		return -ENOMEM;
 
 	flags = VM_DATA_DEFAULT_FLAGS | VM_ACCOUNT | mm->def_flags;
diff -Nru a/mm/mprotect.c b/mm/mprotect.c
--- a/mm/mprotect.c	Wed Nov 27 15:12:41 2002
+++ b/mm/mprotect.c	Wed Jul  2 21:22:38 2003
@@ -175,7 +175,7 @@
 	if (newflags & VM_WRITE) {
 		if (!(vma->vm_flags & (VM_ACCOUNT|VM_WRITE|VM_SHARED))) {
 			charged = (end - start) >> PAGE_SHIFT;
-			if (!vm_enough_memory(charged))
+			if (security_vm_enough_memory(charged))
 				return -ENOMEM;
 			newflags |= VM_ACCOUNT;
 		}
diff -Nru a/mm/mremap.c b/mm/mremap.c
--- a/mm/mremap.c	Thu Feb 20 08:37:02 2003
+++ b/mm/mremap.c	Wed Jul  2 21:22:38 2003
@@ -16,6 +16,7 @@
 #include <linux/fs.h>
 #include <linux/highmem.h>
 #include <linux/rmap-locking.h>
+#include <linux/security.h>
 
 #include <asm/uaccess.h>
 #include <asm/pgalloc.h>
@@ -244,9 +245,7 @@
 	}
 
 	if (!move_page_tables(vma, new_addr, addr, old_len)) {
-		unsigned long must_fault_in;
-		unsigned long fault_in_start;
-		unsigned long fault_in_end;
+		unsigned long vm_locked = vma->vm_flags & VM_LOCKED;
 
 		if (allocated_vma) {
 			*new_vma = *vma;
@@ -272,14 +271,8 @@
 		} else
 			vma = NULL;		/* nothing more to do */
 
-		must_fault_in = new_vma->vm_flags & VM_LOCKED;
-		fault_in_start = new_vma->vm_start;
-		fault_in_end = new_vma->vm_end;
-
 		do_munmap(current->mm, addr, old_len);
 
-		/* new_vma could have been invalidated by do_munmap */
-
 		/* Restore VM_ACCOUNT if one or two pieces of vma left */
 		if (vma) {
 			vma->vm_flags |= VM_ACCOUNT;
@@ -288,9 +281,11 @@
 		}
 
 		current->mm->total_vm += new_len >> PAGE_SHIFT;
-		if (must_fault_in) {
+		if (vm_locked) {
 			current->mm->locked_vm += new_len >> PAGE_SHIFT;
-			make_pages_present(fault_in_start, fault_in_end);
+			if (new_len > old_len)
+				make_pages_present(new_addr + old_len,
+						   new_addr + new_len);
 		}
 		return new_addr;
 	}
@@ -391,7 +386,7 @@
 
 	if (vma->vm_flags & VM_ACCOUNT) {
 		charged = (new_len - old_len) >> PAGE_SHIFT;
-		if (!vm_enough_memory(charged))
+		if (security_vm_enough_memory(charged))
 			goto out_nc;
 	}
 
diff -Nru a/mm/nommu.c b/mm/nommu.c
--- a/mm/nommu.c	Thu May  8 15:49:08 2003
+++ b/mm/nommu.c	Wed Jul  2 18:18:55 2003
@@ -62,11 +62,8 @@
 	inode->i_size = offset;
 
 out_truncate:
-	if (inode->i_op && inode->i_op->truncate) {
-		lock_kernel();
+	if (inode->i_op && inode->i_op->truncate)
 		inode->i_op->truncate(inode);
-		unlock_kernel();
-	}
 	return 0;
 out_sig:
 	send_sig(SIGXFSZ, current, 0);
@@ -253,23 +250,16 @@
 #ifdef DEBUG
 static void show_process_blocks(void)
 {
-	struct mm_tblock_struct * tblock, *tmp;
-	
+	struct mm_tblock_struct *tblock;
+
 	printk("Process blocks %d:", current->pid);
-	
-	tmp = current->mm->context.tblock;
-	while (tmp) {
-		printk(" %p: %p", tmp, tmp->rblock);
-		if (tmp->rblock)
-			printk(" (%d @%p #%d)", kobjsize(tmp->rblock->kblock),
-				tmp->rblock->kblock, tmp->rblock->refcount);
-		if (tmp->next)
-			printk(" ->");
-		else
-			printk(".");
-		tmp = tmp->next;
+
+	for (tblock = &current->mm->context.tblock; tblock; tblock = tblock->next) {
+		printk(" %p: %p", tblock, tblock->rblock);
+		if (tblock->rblock)
+			printk(" (%d @%p #%d)", kobjsize(tblock->rblock->kblock), tblock->rblock->kblock, tblock->rblock->refcount);
+		printk(tblock->next ? " ->" : ".\n");
 	}
-	printk("\n");
 }
 #endif /* DEBUG */
 
@@ -358,7 +348,7 @@
 			error = file->f_op->mmap(file, &vma);
 				   
 #ifdef DEBUG
-			printk("mmap mmap returned %d /%x\n", error, vma.vm_start);
+			printk("f_op->mmap() returned %d/%lx\n", error, vma.vm_start);
 #endif
 			if (!error)
 				return vma.vm_start;
diff -Nru a/mm/page_alloc.c b/mm/page_alloc.c
--- a/mm/page_alloc.c	Tue Jun 10 23:33:21 2003
+++ b/mm/page_alloc.c	Wed Jul  2 21:22:38 2003
@@ -32,6 +32,8 @@
 #include <linux/sysctl.h>
 #include <linux/cpu.h>
 
+#include <asm/tlbflush.h>
+
 DECLARE_BITMAP(node_online_map, MAX_NUMNODES);
 DECLARE_BITMAP(memblk_online_map, MAX_NR_MEMBLKS);
 struct pglist_data *pgdat_list;
@@ -41,6 +43,9 @@
 int numnodes = 1;
 int sysctl_lower_zone_protection = 0;
 
+EXPORT_SYMBOL(totalram_pages);
+EXPORT_SYMBOL(nr_swap_pages);
+
 /*
  * Used by page_zone() to look up the address of the struct zone whose
  * id is encoded in the upper bits of page->flags
@@ -265,6 +270,7 @@
 	mod_page_state(pgfree, 1 << order);
 	free_pages_check(__FUNCTION__, page);
 	list_add(&page->list, &list);
+	kernel_map_pages(page, 1<<order, 0);
 	free_pages_bulk(page_zone(page), 1, &list, order);
 }
 
@@ -440,6 +446,7 @@
 	struct per_cpu_pages *pcp;
 	unsigned long flags;
 
+	kernel_map_pages(page, 1, 0);
 	inc_page_state(pgfree);
 	free_pages_check(__FUNCTION__, page);
 	pcp = &zone->pageset[get_cpu()].pcp[cold];
@@ -556,7 +563,7 @@
 				(!wait && z->free_pages >= z->pages_high)) {
 			page = buffered_rmqueue(z, order, cold);
 			if (page)
-				return page;
+		       		goto got_pg;
 		}
 		min += z->pages_low * sysctl_lower_zone_protection;
 	}
@@ -579,7 +586,7 @@
 				(!wait && z->free_pages >= z->pages_high)) {
 			page = buffered_rmqueue(z, order, cold);
 			if (page)
-				return page;
+				goto got_pg;
 		}
 		min += local_min * sysctl_lower_zone_protection;
 	}
@@ -594,7 +601,7 @@
 
 			page = buffered_rmqueue(z, order, cold);
 			if (page)
-				return page;
+				goto got_pg;
 		}
 		goto nopage;
 	}
@@ -622,7 +629,7 @@
 				(!wait && z->free_pages >= z->pages_high)) {
 			page = buffered_rmqueue(z, order, cold);
 			if (page)
-				return page;
+				goto got_pg;
 		}
 		min += z->pages_low * sysctl_lower_zone_protection;
 	}
@@ -653,6 +660,9 @@
 			current->comm, order, gfp_mask);
 	}
 	return NULL;
+got_pg:
+	kernel_map_pages(page, 1 << order, 1);
+	return page;
 }
 
 /*
@@ -726,6 +736,7 @@
 
 	return sum;
 }
+EXPORT_SYMBOL(nr_free_pages);
 
 unsigned int nr_used_zone_pages(void)
 {
@@ -818,6 +829,7 @@
 EXPORT_PER_CPU_SYMBOL(page_states);
 
 atomic_t nr_pagecache = ATOMIC_INIT(0);
+EXPORT_SYMBOL(nr_pagecache);
 #ifdef CONFIG_SMP
 DEFINE_PER_CPU(long, nr_pagecache_local) = 0;
 #endif
@@ -896,7 +908,7 @@
 {
 	pg_data_t *pgdat = NODE_DATA(nid);
 
-	val->totalram = pgdat->node_size;
+	val->totalram = pgdat->node_present_pages;
 	val->freeram = nr_free_pages_pgdat(pgdat);
 	val->totalhigh = pgdat->node_zones[ZONE_HIGHMEM].present_pages;
 	val->freehigh = pgdat->node_zones[ZONE_HIGHMEM].free_pages;
@@ -1131,12 +1143,13 @@
 
 	for (i = 0; i < MAX_NR_ZONES; i++)
 		totalpages += zones_size[i];
-	pgdat->node_size = totalpages;
+	pgdat->node_spanned_pages = totalpages;
 
 	realtotalpages = totalpages;
 	if (zholes_size)
 		for (i = 0; i < MAX_NR_ZONES; i++)
 			realtotalpages -= zholes_size[i];
+	pgdat->node_present_pages = realtotalpages;
 	printk("On node %d totalpages: %lu\n", pgdat->node_id, realtotalpages);
 }
 
@@ -1342,7 +1355,7 @@
 	pgdat->node_start_pfn = node_start_pfn;
 	calculate_zone_totalpages(pgdat, zones_size, zholes_size);
 	if (!node_mem_map) {
-		size = (pgdat->node_size + 1) * sizeof(struct page); 
+		size = (pgdat->node_spanned_pages + 1) * sizeof(struct page);
 		node_mem_map = alloc_bootmem_node(pgdat, size);
 	}
 	pgdat->node_mem_map = node_mem_map;
diff -Nru a/mm/readahead.c b/mm/readahead.c
--- a/mm/readahead.c	Fri Jun 27 23:20:11 2003
+++ b/mm/readahead.c	Sun Jul  6 13:23:51 2003
@@ -363,9 +363,9 @@
 	} else {
 		/*
 		 * A miss - lseek, pagefault, pread, etc.  Shrink the readahead
-		 * window by 25%.
+		 * window.
 		 */
-		ra->next_size -= ra->next_size / 4 + 2;
+		ra->next_size -= 2;
 	}
 
 	if ((long)ra->next_size > (long)max)
@@ -437,37 +437,6 @@
 	return;
 }
 
-/*
- * For mmap reads (typically executables) the access pattern is fairly random,
- * but somewhat ascending.  So readaround favours pages beyond the target one.
- * We also boost the window size, as it can easily shrink due to misses.
- */
-void
-page_cache_readaround(struct address_space *mapping, struct file_ra_state *ra,
-			struct file *filp, unsigned long offset)
-{
-	if (ra->next_size != -1UL) {
-		const unsigned long min = get_min_readahead(ra) * 2;
-		unsigned long target;
-		unsigned long backward;
-
-		/*
-		 * If next_size is zero then leave it alone, because that's a
-		 * readahead startup state.
-		 */
-		if (ra->next_size && ra->next_size < min)
-			ra->next_size = min;
-
-		target = offset;
-		backward = ra->next_size / 4;
-
-		if (backward > target)
-			target = 0;
-		else
-			target -= backward;
-		page_cache_readahead(mapping, ra, filp, target);
-	}
-}
 
 /*
  * handle_ra_miss() is called when it is known that a page which should have
diff -Nru a/mm/shmem.c b/mm/shmem.c
--- a/mm/shmem.c	Fri Jun 20 13:16:19 2003
+++ b/mm/shmem.c	Sun Jun 29 23:49:04 2003
@@ -36,6 +36,7 @@
 #include <linux/writeback.h>
 #include <linux/vfs.h>
 #include <linux/blkdev.h>
+#include <linux/security.h>
 #include <asm/uaccess.h>
 #include <asm/div64.h>
 
@@ -507,7 +508,7 @@
 	 	 */
 		change = VM_ACCT(attr->ia_size) - VM_ACCT(inode->i_size);
 		if (change > 0) {
-			if (!vm_enough_memory(change))
+			if (security_vm_enough_memory(change))
 				return -ENOMEM;
 		} else if (attr->ia_size < inode->i_size) {
 			vm_unacct_memory(-change);
@@ -1139,7 +1140,7 @@
 	maxpos = inode->i_size;
 	if (maxpos < pos + count) {
 		maxpos = pos + count;
-		if (!vm_enough_memory(VM_ACCT(maxpos) - VM_ACCT(inode->i_size))) {
+		if (security_vm_enough_memory(VM_ACCT(maxpos) - VM_ACCT(inode->i_size))) {
 			err = -ENOMEM;
 			goto out;
 		}
@@ -1397,7 +1398,8 @@
 	return 0;
 }
 
-static int shmem_create(struct inode *dir, struct dentry *dentry, int mode)
+static int shmem_create(struct inode *dir, struct dentry *dentry, int mode,
+		struct nameidata *nd)
 {
 	return shmem_mknod(dir, dentry, mode | S_IFREG, 0);
 }
@@ -1493,7 +1495,7 @@
 		memcpy(info, symname, len);
 		inode->i_op = &shmem_symlink_inline_operations;
 	} else {
-		if (!vm_enough_memory(VM_ACCT(1))) {
+		if (security_vm_enough_memory(VM_ACCT(1))) {
 			iput(inode);
 			return -ENOMEM;
 		}
@@ -1887,7 +1889,7 @@
 	if (size > SHMEM_MAX_BYTES)
 		return ERR_PTR(-EINVAL);
 
-	if ((flags & VM_ACCOUNT) && !vm_enough_memory(VM_ACCT(size)))
+	if ((flags & VM_ACCOUNT) && security_vm_enough_memory(VM_ACCT(size)))
 		return ERR_PTR(-ENOMEM);
 
 	error = -ENOMEM;
diff -Nru a/mm/slab.c b/mm/slab.c
--- a/mm/slab.c	Fri Jun 27 23:20:42 2003
+++ b/mm/slab.c	Wed Jul  2 18:34:36 2003
@@ -89,7 +89,12 @@
 #include	<linux/notifier.h>
 #include	<linux/kallsyms.h>
 #include	<linux/cpu.h>
+#include	<linux/sysctl.h>
+#include	<linux/module.h>
+
 #include	<asm/uaccess.h>
+#include	<asm/cacheflush.h>
+#include	<asm/tlbflush.h>
 
 /*
  * DEBUG	- 1 for kmem_cache_create() to honour; SLAB_DEBUG_INITIAL,
@@ -351,6 +356,34 @@
 #define POISON_AFTER	0x6b	/* for use-after-free poisoning */
 #define	POISON_END	0xa5	/* end-byte of poisoning */
 
+static inline int obj_dbghead(kmem_cache_t *cachep)
+{
+	if (cachep->flags & SLAB_RED_ZONE)
+		return BYTES_PER_WORD;
+	return 0;
+}
+
+static inline int obj_dbglen(kmem_cache_t *cachep)
+{
+	int len = 0;
+
+	if (cachep->flags & SLAB_RED_ZONE) {
+		len += 2*BYTES_PER_WORD;
+	}
+	if (cachep->flags & SLAB_STORE_USER) {
+		len += BYTES_PER_WORD;
+	}
+	return len;
+}
+#else
+static inline int obj_dbghead(kmem_cache_t *cachep)
+{
+	return 0;
+}
+static inline int obj_dbglen(kmem_cache_t *cachep)
+{
+	return 0;
+}
 #endif
 
 /*
@@ -430,6 +463,7 @@
  * SLAB_RECLAIM_ACCOUNT turns this on per-slab
  */
 atomic_t slab_reclaim_pages;
+EXPORT_SYMBOL(slab_reclaim_pages);
 
 /*
  * chicken and egg problem: delay the per-cpu array allocation
@@ -441,7 +475,7 @@
 	FULL
 } g_cpucache_up;
 
-static struct timer_list reap_timers[NR_CPUS];
+static DEFINE_PER_CPU(struct timer_list, reap_timers);
 
 static void reap_timer_fnc(unsigned long data);
 
@@ -491,7 +525,7 @@
  */
 static void start_cpu_timer(int cpu)
 {
-	struct timer_list *rt = &reap_timers[cpu];
+	struct timer_list *rt = &per_cpu(reap_timers, cpu);
 
 	if (rt->function == NULL) {
 		init_timer(rt);
@@ -765,16 +799,45 @@
 }
 
 #if DEBUG
-static void poison_obj(kmem_cache_t *cachep, void *addr, unsigned char val)
+
+#ifdef CONFIG_DEBUG_PAGEALLOC
+static void store_stackinfo(kmem_cache_t *cachep, unsigned long *addr, unsigned long caller)
 {
-	int size = cachep->objsize;
-	if (cachep->flags & SLAB_RED_ZONE) {
-		addr += BYTES_PER_WORD;
-		size -= 2*BYTES_PER_WORD;
-	}
-	if (cachep->flags & SLAB_STORE_USER) {
-		size -= BYTES_PER_WORD;
+	int size = cachep->objsize-obj_dbglen(cachep);
+
+	addr = (unsigned long *)&((char*)addr)[obj_dbghead(cachep)];
+
+	if (size < 5*sizeof(unsigned long))
+		return;
+
+	*addr++=0x12345678;
+	*addr++=caller;
+	*addr++=smp_processor_id();
+	size -= 3*sizeof(unsigned long);
+	{
+		unsigned long *sptr = &caller;
+		unsigned long svalue;
+
+		while (((long) sptr & (THREAD_SIZE-1)) != 0) {
+			svalue = *sptr++;
+			if (kernel_text_address(svalue)) {
+				*addr++=svalue;
+				size -= sizeof(unsigned long);
+				if (size <= sizeof(unsigned long))
+					break;
+			}
+		}
+
 	}
+	*addr++=0x87654321;
+}
+#endif
+
+static void poison_obj(kmem_cache_t *cachep, void *addr, unsigned char val)
+{
+	int size = cachep->objsize-obj_dbglen(cachep);
+	addr = &((char*)addr)[obj_dbghead(cachep)];
+
 	memset(addr, val, size);
 	*(unsigned char *)(addr+size-1) = POISON_END;
 }
@@ -796,15 +859,11 @@
 
 static void check_poison_obj(kmem_cache_t *cachep, void *addr)
 {
-	int size = cachep->objsize;
 	void *end;
-	if (cachep->flags & SLAB_RED_ZONE) {
-		addr += BYTES_PER_WORD;
-		size -= 2*BYTES_PER_WORD;
-	}
-	if (cachep->flags & SLAB_STORE_USER) {
-		size -= BYTES_PER_WORD;
-	}
+	int size = cachep->objsize-obj_dbglen(cachep);
+
+	addr = &((char*)addr)[obj_dbghead(cachep)];
+
 	end = scan_poisoned_obj(addr, size);
 	if (end) {
 		int s;
@@ -858,8 +917,16 @@
 		void *objp = slabp->s_mem + cachep->objsize * i;
 		int objlen = cachep->objsize;
 
-		if (cachep->flags & SLAB_POISON)
+		if (cachep->flags & SLAB_POISON) {
+#ifdef CONFIG_DEBUG_PAGEALLOC
+			if ((cachep->objsize%PAGE_SIZE)==0 && OFF_SLAB(cachep))
+				kernel_map_pages(virt_to_page(objp), cachep->objsize/PAGE_SIZE,1);
+			else
+				check_poison_obj(cachep, objp);
+#else
 			check_poison_obj(cachep, objp);
+#endif
+		}
 		if (cachep->flags & SLAB_STORE_USER)
 			objlen -= BYTES_PER_WORD;
 
@@ -952,6 +1019,10 @@
 	}
 
 #if FORCED_DEBUG
+#ifdef CONFIG_DEBUG_PAGEALLOC
+	if (size < PAGE_SIZE-3*BYTES_PER_WORD && size > 128)
+		size = PAGE_SIZE-3*BYTES_PER_WORD;
+#endif
 	/*
 	 * Enable redzoning and last user accounting, except
 	 * - for caches with forced alignment: redzoning would violate the
@@ -1404,6 +1475,8 @@
 				slab_error(cachep, "constructor overwrote the"
 							" start of an object");
 		}
+		if ((cachep->objsize % PAGE_SIZE) == 0 && OFF_SLAB(cachep) && cachep->flags & SLAB_POISON)
+	       		kernel_map_pages(virt_to_page(objp), cachep->objsize/PAGE_SIZE, 0);
 #else
 		if (cachep->ctor)
 			cachep->ctor(objp, cachep, ctor_flags);
@@ -1584,25 +1657,28 @@
 		 * caller can perform a verify of its state (debugging).
 		 * Called without the cache-lock held.
 		 */
-		if (cachep->flags & SLAB_RED_ZONE) {
-			cachep->ctor(objp+BYTES_PER_WORD,
+		cachep->ctor(objp+obj_dbghead(cachep),
 					cachep, SLAB_CTOR_CONSTRUCTOR|SLAB_CTOR_VERIFY);
-		} else {
-			cachep->ctor(objp, cachep, SLAB_CTOR_CONSTRUCTOR|SLAB_CTOR_VERIFY);
-		}
 	}
 	if (cachep->flags & SLAB_POISON && cachep->dtor) {
 		/* we want to cache poison the object,
 		 * call the destruction callback
 		 */
-		if (cachep->flags & SLAB_RED_ZONE)
-			cachep->dtor(objp+BYTES_PER_WORD, cachep, 0);
-		else
-			cachep->dtor(objp, cachep, 0);
+		cachep->dtor(objp+obj_dbghead(cachep), cachep, 0);
 	}
-	if (cachep->flags & SLAB_POISON)
+	if (cachep->flags & SLAB_POISON) {
+#ifdef CONFIG_DEBUG_PAGEALLOC
+		if ((cachep->objsize % PAGE_SIZE) == 0 && OFF_SLAB(cachep)) {
+			store_stackinfo(cachep, objp, POISON_AFTER);
+	       		kernel_map_pages(virt_to_page(objp), cachep->objsize/PAGE_SIZE, 0);
+		} else {
+			poison_obj(cachep, objp, POISON_AFTER);
+		}
+#else
 		poison_obj(cachep, objp, POISON_AFTER);
 #endif
+	}
+#endif
 	return objp;
 }
 
@@ -1617,6 +1693,7 @@
 	for (i = slabp->free; i != BUFCTL_END; i = slab_bufctl(slabp)[i]) {
 		entries++;
 		BUG_ON(entries > cachep->num);
+		BUG_ON(i < 0 || i >= cachep->num);
 	}
 	BUG_ON(entries != cachep->num - slabp->inuse);
 #endif
@@ -1746,9 +1823,16 @@
 
 	if (!objp)	
 		return objp;
-	if (cachep->flags & SLAB_POISON) {
+ 	if (cachep->flags & SLAB_POISON) {
+#ifdef CONFIG_DEBUG_PAGEALLOC
+		if ((cachep->objsize % PAGE_SIZE) == 0 && OFF_SLAB(cachep))
+			kernel_map_pages(virt_to_page(objp), cachep->objsize/PAGE_SIZE, 1);
+		else
+			check_poison_obj(cachep, objp);
+#else
 		check_poison_obj(cachep, objp);
- 		poison_obj(cachep, objp, POISON_BEFORE);
+#endif
+		poison_obj(cachep, objp, POISON_BEFORE);
 	}
 	if (cachep->flags & SLAB_STORE_USER) {
 		objlen -= BYTES_PER_WORD;
@@ -2085,16 +2169,7 @@
 
 unsigned int kmem_cache_size(kmem_cache_t *cachep)
 {
-	unsigned int objlen = cachep->objsize;
-
-#if DEBUG
-	if (cachep->flags & SLAB_RED_ZONE)
-		objlen -= 2*BYTES_PER_WORD;
-	if (cachep->flags & SLAB_STORE_USER)
-		objlen -= BYTES_PER_WORD;
-#endif
-
-	return objlen;
+	return cachep->objsize-obj_dbglen(cachep);
 }
 
 kmem_cache_t * kmem_find_general_cachep (size_t size, int gfpflags)
@@ -2382,7 +2457,7 @@
 static void reap_timer_fnc(unsigned long data)
 {
 	int cpu = smp_processor_id();
-	struct timer_list *rt = &reap_timers[cpu];
+	struct timer_list *rt = &__get_cpu_var(reap_timers);
 
 	cache_reap();
 	mod_timer(rt, jiffies + REAPTIMEOUT_CPUC + cpu);
@@ -2626,3 +2701,70 @@
 	return size;
 }
 
+void ptrinfo(unsigned long addr)
+{
+	struct page *page;
+
+	printk("Dumping data about address %p.\n", (void*)addr);
+	if (!virt_addr_valid((void*)addr)) {
+		printk("virt addr invalid.\n");
+		return;
+	}
+	do {
+		pgd_t *pgd = pgd_offset_k(addr);
+		pmd_t *pmd;
+		if (pgd_none(*pgd)) {
+			printk("No pgd.\n");
+			break;
+		}
+		pmd = pmd_offset(pgd, addr);
+		if (pmd_none(*pmd)) {
+			printk("No pmd.\n");
+			break;
+		}
+#ifdef CONFIG_X86
+		if (pmd_large(*pmd)) {
+			printk("Large page.\n");
+			break;
+		}
+#endif
+		printk("normal page, pte_val 0x%llx\n",
+		  (unsigned long long)pte_val(*pte_offset_kernel(pmd, addr)));
+	} while(0);
+
+	page = virt_to_page((void*)addr);
+	printk("struct page at %p, flags %lxh.\n", page, page->flags);
+	if (PageSlab(page)) {
+		kmem_cache_t *c;
+		struct slab *s;
+		unsigned long flags;
+		int objnr;
+		void *objp;
+
+		c = GET_PAGE_CACHE(page);
+		printk("belongs to cache %s.\n",c->name);
+
+		spin_lock_irqsave(&c->spinlock, flags);
+		s = GET_PAGE_SLAB(page);
+		printk("slabp %p with %d inuse objects (from %d).\n",
+			s, s->inuse, c->num);
+		check_slabp(c,s);
+
+		objnr = (addr-(unsigned long)s->s_mem)/c->objsize;
+		objp = s->s_mem+c->objsize*objnr;
+		printk("points into object no %d, starting at %p, len %d.\n",
+			objnr, objp, c->objsize);
+		if (objnr >= c->num) {
+			printk("Bad obj number.\n");
+		} else {
+			kernel_map_pages(virt_to_page(objp), c->objsize/PAGE_SIZE, 1);
+
+			printk("redzone: %lxh/%lxh/%lxh.\n",
+				((unsigned long*)objp)[0],
+				((unsigned long*)(objp+c->objsize))[-2],
+				((unsigned long*)(objp+c->objsize))[-1]);
+		}
+		spin_unlock_irqrestore(&c->spinlock, flags);
+
+	}
+}
diff -Nru a/mm/swap.c b/mm/swap.c
--- a/mm/swap.c	Fri Jun 27 01:46:43 2003
+++ b/mm/swap.c	Wed Jul  2 21:22:38 2003
@@ -20,6 +20,7 @@
 #include <linux/pagemap.h>
 #include <linux/pagevec.h>
 #include <linux/init.h>
+#include <linux/module.h>
 #include <linux/mm_inline.h>
 #include <linux/buffer_head.h>	/* for try_to_release_page() */
 #include <linux/percpu.h>
@@ -370,6 +371,7 @@
 	}
 	preempt_enable();
 }
+EXPORT_SYMBOL(vm_acct_memory);
 #endif
 
 
diff -Nru a/mm/swapfile.c b/mm/swapfile.c
--- a/mm/swapfile.c	Mon May 19 09:02:40 2003
+++ b/mm/swapfile.c	Wed Jul  2 21:22:38 2003
@@ -20,7 +20,9 @@
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
 #include <linux/init.h>
+#include <linux/module.h>
 #include <linux/rmap-locking.h>
+#include <linux/security.h>
 
 #include <asm/pgtable.h>
 #include <linux/swapops.h>
@@ -30,6 +32,8 @@
 int total_swap_pages;
 static int swap_overflow;
 
+EXPORT_SYMBOL(total_swap_pages);
+
 static const char Bad_file[] = "Bad swap file entry ";
 static const char Unused_file[] = "Unused swap file entry ";
 static const char Bad_offset[] = "Bad swap offset entry ";
@@ -1042,7 +1046,7 @@
 		swap_list_unlock();
 		goto out_dput;
 	}
-	if (vm_enough_memory(p->pages))
+	if (!security_vm_enough_memory(p->pages))
 		vm_unacct_memory(p->pages);
 	else {
 		err = -ENOMEM;
diff -Nru a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c
--- a/net/bluetooth/hci_sock.c	Mon Jun 16 08:11:36 2003
+++ b/net/bluetooth/hci_sock.c	Fri Jul  4 23:52:58 2003
@@ -632,6 +632,7 @@
 
 struct net_proto_family hci_sock_family_ops = {
 	.family = PF_BLUETOOTH,
+	.owner	= THIS_MODULE,
 	.create = hci_sock_create,
 };
 
diff -Nru a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c
--- a/net/bluetooth/rfcomm/sock.c	Mon Jun 16 08:11:36 2003
+++ b/net/bluetooth/rfcomm/sock.c	Fri Jul  4 23:52:58 2003
@@ -878,6 +878,7 @@
 
 static struct net_proto_family rfcomm_sock_family_ops = {
 	.family		= PF_BLUETOOTH,
+	.owner		= THIS_MODULE,
 	.create		= rfcomm_sock_create
 };
 
diff -Nru a/net/core/dev.c b/net/core/dev.c
--- a/net/core/dev.c	Sat Jun 28 00:10:39 2003
+++ b/net/core/dev.c	Thu Jul  3 00:32:44 2003
@@ -1712,7 +1712,7 @@
 
 softnet_break:
 	netdev_rx_stat[this_cpu].time_squeeze++;
-	__cpu_raise_softirq(this_cpu, NET_RX_SOFTIRQ);
+	__raise_softirq_irqoff(NET_RX_SOFTIRQ);
 	goto out;
 }
 
diff -Nru a/net/ipv4/igmp.c b/net/ipv4/igmp.c
--- a/net/ipv4/igmp.c	Mon Jun 30 23:22:39 2003
+++ b/net/ipv4/igmp.c	Sun Jul  6 19:28:33 2003
@@ -2099,7 +2099,7 @@
 	struct in_device *in_dev;
 };
 
-#define	igmp_mc_seq_private(seq)	((struct igmp_mc_iter_state *)&seq->private)
+#define	igmp_mc_seq_private(seq)	((struct igmp_mc_iter_state *)(seq)->private)
 
 static inline struct ip_mc_list *igmp_mc_get_first(struct seq_file *seq)
 {
@@ -2254,7 +2254,7 @@
 	struct ip_mc_list *im;
 };
 
-#define igmp_mcf_seq_private(seq)	((struct igmp_mcf_iter_state *)&seq->private)
+#define igmp_mcf_seq_private(seq)	((struct igmp_mcf_iter_state *)(seq)->private)
 
 static inline struct ip_sf_list *igmp_mcf_get_first(struct seq_file *seq)
 {
diff -Nru a/net/ipv4/ipconfig.c b/net/ipv4/ipconfig.c
--- a/net/ipv4/ipconfig.c	Sun May 25 19:36:24 2003
+++ b/net/ipv4/ipconfig.c	Fri Jul  4 03:04:24 2003
@@ -1115,6 +1115,8 @@
 				       "nameserver %u.%u.%u.%u\n",
 				       NIPQUAD(ic_nameservers[i]));
 	}
+	len += sprintf(buffer + len, "bootserver %u.%u.%u.%u\n",
+			NIPQUAD(ic_servaddr));
 
 	if (offset > len)
 		offset = len;
diff -Nru a/net/ipv4/raw.c b/net/ipv4/raw.c
--- a/net/ipv4/raw.c	Mon Jun 30 09:01:47 2003
+++ b/net/ipv4/raw.c	Sun Jul  6 19:28:33 2003
@@ -687,7 +687,7 @@
 	int bucket;
 };
 
-#define raw_seq_private(seq) ((struct raw_iter_state *)&seq->private)
+#define raw_seq_private(seq) ((struct raw_iter_state *)(seq)->private)
 
 static struct sock *raw_get_first(struct seq_file *seq)
 {
diff -Nru a/net/ipv6/anycast.c b/net/ipv6/anycast.c
--- a/net/ipv6/anycast.c	Mon Jun 30 23:23:48 2003
+++ b/net/ipv6/anycast.c	Sun Jul  6 19:28:33 2003
@@ -441,7 +441,7 @@
 	struct inet6_dev *idev;
 };
 
-#define ac6_seq_private(seq)	((struct ac6_iter_state *)&seq->private)
+#define ac6_seq_private(seq)	((struct ac6_iter_state *)(seq)->private)
 
 static inline struct ifacaddr6 *ac6_get_first(struct seq_file *seq)
 {
diff -Nru a/net/ipv6/ip6_flowlabel.c b/net/ipv6/ip6_flowlabel.c
--- a/net/ipv6/ip6_flowlabel.c	Mon Jun 30 09:02:51 2003
+++ b/net/ipv6/ip6_flowlabel.c	Sun Jul  6 19:28:33 2003
@@ -559,7 +559,7 @@
 	int bucket;
 };
 
-#define ip6fl_seq_private(seq)	((struct ip6fl_iter_state *)&(seq)->private)
+#define ip6fl_seq_private(seq)	((struct ip6fl_iter_state *)(seq)->private)
 
 static struct ip6_flowlabel *ip6fl_get_first(struct seq_file *seq)
 {
diff -Nru a/net/ipv6/mcast.c b/net/ipv6/mcast.c
--- a/net/ipv6/mcast.c	Mon Jun 30 23:23:14 2003
+++ b/net/ipv6/mcast.c	Sun Jul  6 19:28:33 2003
@@ -2045,7 +2045,7 @@
 	struct inet6_dev *idev;
 };
 
-#define igmp6_mc_seq_private(seq)	((struct igmp6_mc_iter_state *)&seq->private)
+#define igmp6_mc_seq_private(seq)	((struct igmp6_mc_iter_state *)(seq)->private)
 
 static inline struct ifmcaddr6 *igmp6_mc_get_first(struct seq_file *seq)
 {
@@ -2185,7 +2185,7 @@
 	struct ifmcaddr6 *im;
 };
 
-#define igmp6_mcf_seq_private(seq)	((struct igmp6_mcf_iter_state *)&seq->private)
+#define igmp6_mcf_seq_private(seq)	((struct igmp6_mcf_iter_state *)(seq)->private)
 
 static inline struct ip6_sf_list *igmp6_mcf_get_first(struct seq_file *seq)
 {
diff -Nru a/net/ipv6/raw.c b/net/ipv6/raw.c
--- a/net/ipv6/raw.c	Mon Jun 30 09:01:47 2003
+++ b/net/ipv6/raw.c	Sun Jul  6 19:28:33 2003
@@ -913,7 +913,7 @@
 	int bucket;
 };
 
-#define raw6_seq_private(seq) ((struct raw6_iter_state *)&seq->private)
+#define raw6_seq_private(seq) ((struct raw6_iter_state *)(seq)->private)
 
 static struct sock *raw6_get_first(struct seq_file *seq)
 {
diff -Nru a/net/unix/af_unix.c b/net/unix/af_unix.c
--- a/net/unix/af_unix.c	Wed Jun 18 13:59:01 2003
+++ b/net/unix/af_unix.c	Sun Jun 29 23:49:26 2003
@@ -594,7 +594,7 @@
 		err = path_lookup(sunname->sun_path, LOOKUP_FOLLOW, &nd);
 		if (err)
 			goto fail;
-		err = permission(nd.dentry->d_inode,MAY_WRITE);
+		err = permission(nd.dentry->d_inode,MAY_WRITE, &nd);
 		if (err)
 			goto put_fail;
 
diff -Nru a/security/capability.c b/security/capability.c
--- a/security/capability.c	Wed Jun 25 16:30:52 2003
+++ b/security/capability.c	Wed Jul  2 21:22:38 2003
@@ -15,6 +15,9 @@
 #include <linux/security.h>
 #include <linux/file.h>
 #include <linux/mm.h>
+#include <linux/mman.h>
+#include <linux/pagemap.h>
+#include <linux/swap.h>
 #include <linux/smp_lock.h>
 #include <linux/skbuff.h>
 #include <linux/netlink.h>
@@ -275,6 +278,65 @@
 	return 0;
 }
 
+/*
+ * Check that a process has enough memory to allocate a new virtual
+ * mapping. 0 means there is enough memory for the allocation to
+ * succeed and -ENOMEM implies there is not.
+ *
+ * We currently support three overcommit policies, which are set via the
+ * vm.overcommit_memory sysctl.  See Documentation/vm/overcommit-acounting
+ *
+ * Strict overcommit modes added 2002 Feb 26 by Alan Cox.
+ * Additional code 2002 Jul 20 by Robert Love.
+ */
+int cap_vm_enough_memory(long pages)
+{
+	unsigned long free, allowed;
+
+	vm_acct_memory(pages);
+
+        /*
+	 * Sometimes we want to use more memory than we have
+	 */
+	if (sysctl_overcommit_memory == 1)
+		return 0;
+
+	if (sysctl_overcommit_memory == 0) {
+		free = get_page_cache_size();
+		free += nr_free_pages();
+		free += nr_swap_pages;
+
+		/*
+		 * Any slabs which are created with the
+		 * SLAB_RECLAIM_ACCOUNT flag claim to have contents
+		 * which are reclaimable, under pressure.  The dentry
+		 * cache and most inode caches should fall into this
+		 */
+		free += atomic_read(&slab_reclaim_pages);
+
+		/*
+		 * Leave the last 3% for root
+		 */
+		if (!capable(CAP_SYS_ADMIN))
+			free -= free / 32;
+
+		if (free > pages)
+			return 0;
+		vm_unacct_memory(pages);
+		return -ENOMEM;
+	}
+
+	allowed = totalram_pages * sysctl_overcommit_ratio / 100;
+	allowed += total_swap_pages;
+
+	if (atomic_read(&vm_committed_space) < allowed)
+		return 0;
+
+	vm_unacct_memory(pages);
+
+	return -ENOMEM;
+}
+
 EXPORT_SYMBOL(cap_capable);
 EXPORT_SYMBOL(cap_ptrace);
 EXPORT_SYMBOL(cap_capget);
@@ -286,6 +348,7 @@
 EXPORT_SYMBOL(cap_task_post_setuid);
 EXPORT_SYMBOL(cap_task_reparent_to_init);
 EXPORT_SYMBOL(cap_syslog);
+EXPORT_SYMBOL(cap_vm_enough_memory);
 
 #ifdef CONFIG_SECURITY
 
@@ -307,6 +370,8 @@
 	.task_reparent_to_init =	cap_task_reparent_to_init,
 
 	.syslog =                       cap_syslog,
+
+	.vm_enough_memory =             cap_vm_enough_memory,
 };
 
 #if defined(CONFIG_SECURITY_CAPABILITIES_MODULE)
diff -Nru a/security/dummy.c b/security/dummy.c
--- a/security/dummy.c	Wed Jun 25 16:30:52 2003
+++ b/security/dummy.c	Wed Jul  2 21:22:38 2003
@@ -17,6 +17,9 @@
 #include <linux/config.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
+#include <linux/mman.h>
+#include <linux/pagemap.h>
+#include <linux/swap.h>
 #include <linux/security.h>
 #include <linux/skbuff.h>
 #include <linux/netlink.h>
@@ -97,6 +100,54 @@
 	return 0;
 }
 
+static int dummy_vm_enough_memory(long pages)
+{
+	unsigned long free, allowed;
+
+	vm_acct_memory(pages);
+
+        /*
+	 * Sometimes we want to use more memory than we have
+	 */
+	if (sysctl_overcommit_memory == 1)
+		return 0;
+
+	if (sysctl_overcommit_memory == 0) {
+		free = get_page_cache_size();
+		free += nr_free_pages();
+		free += nr_swap_pages;
+
+		/*
+		 * Any slabs which are created with the
+		 * SLAB_RECLAIM_ACCOUNT flag claim to have contents
+		 * which are reclaimable, under pressure.  The dentry
+		 * cache and most inode caches should fall into this
+		 */
+		free += atomic_read(&slab_reclaim_pages);
+
+		/*
+		 * Leave the last 3% for root
+		 */
+		if (current->euid)
+			free -= free / 32;
+
+		if (free > pages)
+			return 0;
+		vm_unacct_memory(pages);
+		return -ENOMEM;
+	}
+
+	allowed = totalram_pages * sysctl_overcommit_ratio / 100;
+	allowed += total_swap_pages;
+
+	if (atomic_read(&vm_committed_space) < allowed)
+		return 0;
+
+	vm_unacct_memory(pages);
+
+	return -ENOMEM;
+}
+
 static int dummy_bprm_alloc_security (struct linux_binprm *bprm)
 {
 	return 0;
@@ -793,6 +844,7 @@
 	set_to_dummy_if_null(ops, quota_on);
 	set_to_dummy_if_null(ops, sysctl);
 	set_to_dummy_if_null(ops, syslog);
+	set_to_dummy_if_null(ops, vm_enough_memory);
 	set_to_dummy_if_null(ops, bprm_alloc_security);
 	set_to_dummy_if_null(ops, bprm_free_security);
 	set_to_dummy_if_null(ops, bprm_compute_creds);
