diff -Nru a/MAINTAINERS b/MAINTAINERS
--- a/MAINTAINERS	Mon Sep  9 10:36:11 2002
+++ b/MAINTAINERS	Mon Sep  9 10:36:11 2002
@@ -1099,20 +1099,17 @@
 L:	linux-scsi@vger.kernel.org
 S:	Maintained
 
-NETFILTER
+NETFILTER/IPTABLES
 P:	Rusty Russell
-M:	rusty@rustcorp.com.au
 P:	Marc Boucher
-M:	marc@mbsi.ca
 P:	James Morris
-M:	jamesm@intercode.com.au
 P:	Harald Welte
-M:	laforge@gnumonks.org
 P:	Jozsef Kadlecsik
-M:	kadlec@blackhole.kfki.hu
+M:	coreteam@netfilter.org
 W:	http://www.netfilter.org/
 W:	http://www.iptables.org/
-L:	netfilter@lists.samba.org
+L:	netfilter@lists.netfilter.org
+L:	netfilter-devel@lists.netfilter.org
 S:	Supported
 
 NETROM NETWORK LAYER
diff -Nru a/Makefile b/Makefile
--- a/Makefile	Mon Sep  9 10:35:56 2002
+++ b/Makefile	Mon Sep  9 10:35:56 2002
@@ -1,6 +1,6 @@
 VERSION = 2
 PATCHLEVEL = 5
-SUBLEVEL = 33
+SUBLEVEL = 34
 EXTRAVERSION =
 
 # *DOCUMENTATION*
@@ -318,7 +318,7 @@
 #	This can be used by arch/$ARCH/Makefile to preprocess
 #	their vmlinux.lds.S file
 
-arch/$ARCH/vmlinux.lds.s: arch/$ARCH/vmlinux.lds.S
+arch/$(ARCH)/vmlinux.lds.s: arch/$(ARCH)/vmlinux.lds.S
 	$(CPP) $(CPPFLAGS) $(CPPFLAGS_$@) -P -C -U$(ARCH) $< -o $@
 
 # Single targets
diff -Nru a/arch/alpha/Makefile b/arch/alpha/Makefile
--- a/arch/alpha/Makefile	Mon Sep  9 10:35:56 2002
+++ b/arch/alpha/Makefile	Mon Sep  9 10:35:56 2002
@@ -128,6 +128,9 @@
 
 vmlinux: arch/alpha/vmlinux.lds.s
 
+arch/$(ARCH)/vmlinux.lds.s: arch/$(ARCH)/vmlinux.lds.S
+	$(CPP) $(CPPFLAGS) $(CPPFLAGS_$@) -D__ASSEMBLY__ -P -C -U$(ARCH) $< -o $@
+
 bootpfile:
 	@$(MAKEBOOT) bootpfile
 
diff -Nru a/arch/alpha/kernel/core_apecs.c b/arch/alpha/kernel/core_apecs.c
--- a/arch/alpha/kernel/core_apecs.c	Mon Sep  9 10:36:01 2002
+++ b/arch/alpha/kernel/core_apecs.c	Mon Sep  9 10:36:01 2002
@@ -90,11 +90,11 @@
  */
 
 static int
-mk_conf_addr(struct pci_bus *bus_dev, unsigned int device_fn, int where,
+mk_conf_addr(struct pci_bus *pbus, unsigned int device_fn, int where,
 	     unsigned long *pci_addr, unsigned char *type1)
 {
 	unsigned long addr;
-	u8 bus = bus_dev->number;
+	u8 bus = pbus->number;
 
 	DBGC(("mk_conf_addr(bus=%d ,device_fn=0x%x, where=0x%x,"
 	      " pci_addr=0x%p, type1=0x%p)\n",
@@ -272,8 +272,8 @@
 }
 
 static int
-apecs_read_config(struct pci_bus *bus, unsigned int devfn, int where, int size,
-		  u8 *value)
+apecs_read_config(struct pci_bus *bus, unsigned int devfn, int where,
+		  int size, u32 *value)
 {
 	unsigned long addr, pci_addr;
 	unsigned char type1;
@@ -283,27 +283,16 @@
 	if (mk_conf_addr(bus, devfn, where, &pci_addr, &type1))
 		return PCIBIOS_DEVICE_NOT_FOUND;
 
-		switch (size) {
-	case 1:
-		mask = 0x00;
-		shift = (where & 3) * 8;
-		break;
-	case 2:
-		mask = 0x08;
-		shift = (where & 3) * 8;
-		break;
-	case 4:
-		mask = 0x18;
-		shift = 0;
-		break;
-	}
+	mask = (size - 1) * 8;
+	shift = (where & 3) * 8;
 	addr = (pci_addr << 5) + mask + APECS_CONF;
 	*value = conf_read(addr, type1) >> (shift);
 	return PCIBIOS_SUCCESSFUL;
 }
 
 static int
-apecs_write_config(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 value)
+apecs_write_config(struct pci_bus *bus, unsigned int devfn, int where,
+		   int size, u32 value)
 {
 	unsigned long addr, pci_addr;
 	unsigned char type1;
@@ -312,17 +301,7 @@
 	if (mk_conf_addr(bus, devfn, where, &pci_addr, &type1))
 		return PCIBIOS_DEVICE_NOT_FOUND;
 
-	switch (size) {
-	case 1:
-		mask = 0x00;
-		break;
-	case 2:
-		mask = 0x08;
-		break;
-	case 4:
-		mask = 0x18;
-		break;
-	}
+	mask = (size - 1) * 8;
 	addr = (pci_addr << 5) + mask + APECS_CONF;
 	conf_write(addr, value << ((where & 3) * 8), type1);
 	return PCIBIOS_SUCCESSFUL;
diff -Nru a/arch/alpha/kernel/core_cia.c b/arch/alpha/kernel/core_cia.c
--- a/arch/alpha/kernel/core_cia.c	Mon Sep  9 10:36:11 2002
+++ b/arch/alpha/kernel/core_cia.c	Mon Sep  9 10:36:11 2002
@@ -219,22 +219,9 @@
 	if (mk_conf_addr(bus, devfn, where, &pci_addr, &type1))
 		return PCIBIOS_DEVICE_NOT_FOUND;
 
-	switch (size) {
-	case 1:
-		mask = 0x00;
-		shift = (where & 3) * 8;
-		break;
-	case 2:
-		mask = 0x08;
-		shift = (where & 3) * 8;
-		break;
-	case 4:
-		mase = 0x18;
-		shift = 0;
-		break;
-	}
-
-	addr = (pci_addr << 5) + 0x18 + CIA_CONF;
+	mask = (size - 1) * 8;
+	shift = (where & 3) * 8;
+	addr = (pci_addr << 5) + mask + CIA_CONF;
 	*value = conf_read(addr, type1) >> (shift);
 	return PCIBIOS_SUCCESSFUL;
 }
@@ -250,18 +237,7 @@
 	if (mk_conf_addr(bus, devfn, where, &pci_addr, &type1))
 		return PCIBIOS_DEVICE_NOT_FOUND;
 
-	switch (size) {
-	case 1:
-		mask = 0x00;
-		break;
-	case 2:
-		mask = 0x08;
-		break;
-	case 4:
-		mase = 0x18;
-		break;
-	}
-
+	mask = (size - 1) * 8;
 	addr = (pci_addr << 5) + mask + CIA_CONF;
 	conf_write(addr, value << ((where & 3) * 8), type1);
 	return PCIBIOS_SUCCESSFUL;
diff -Nru a/arch/alpha/kernel/core_irongate.c b/arch/alpha/kernel/core_irongate.c
--- a/arch/alpha/kernel/core_irongate.c	Mon Sep  9 10:36:01 2002
+++ b/arch/alpha/kernel/core_irongate.c	Mon Sep  9 10:36:01 2002
@@ -83,11 +83,11 @@
  */
 
 static int
-mk_conf_addr(struct pci_bus *bus_dev, unsigned int device_fn, int where,
+mk_conf_addr(struct pci_bus *pbus, unsigned int device_fn, int where,
 	     unsigned long *pci_addr, unsigned char *type1)
 {
 	unsigned long addr;
-	u8 bus = bus_dev->number;
+	u8 bus = pbus->number;
 
 	DBG_CFG(("mk_conf_addr(bus=%d ,device_fn=0x%x, where=0x%x, "
 		 "pci_addr=0x%p, type1=0x%p)\n",
@@ -113,7 +113,18 @@
 	if (mk_conf_addr(bus, devfn, where, &addr, &type1))
 		return PCIBIOS_DEVICE_NOT_FOUND;
 
-	*value = __kernel_ldbu(*(vucp)addr);
+	switch (size) {
+	case 1:
+		*value = __kernel_ldbu(*(vucp)addr);
+		break;
+	case 2:
+		*value = __kernel_ldwu(*(vusp)addr);
+		break;
+	case 4:
+		*value = *(vuip)addr;
+		break;
+	}
+
 	return PCIBIOS_SUCCESSFUL;
 }
 
@@ -127,12 +138,26 @@
 	if (mk_conf_addr(bus, devfn, where, &addr, &type1))
 		return PCIBIOS_DEVICE_NOT_FOUND;
 
-	__kernel_stb(value, *(vucp)addr);
-	mb();
-	__kernel_ldbu(*(vucp)addr);
+	switch (size) {
+	case 1:
+		__kernel_stb(value, *(vucp)addr);
+		mb();
+		__kernel_ldbu(*(vucp)addr);
+		break;
+	case 2:
+		__kernel_stw(value, *(vusp)addr);
+		mb();
+		__kernel_ldwu(*(vusp)addr);
+		break;
+	case 4:
+		*(vuip)addr = value;
+		mb();
+		*(vuip)addr;
+		break;
+	}
+
 	return PCIBIOS_SUCCESSFUL;
 }
-
 
 struct pci_ops irongate_pci_ops =
 {
diff -Nru a/arch/alpha/kernel/core_lca.c b/arch/alpha/kernel/core_lca.c
--- a/arch/alpha/kernel/core_lca.c	Mon Sep  9 10:36:01 2002
+++ b/arch/alpha/kernel/core_lca.c	Mon Sep  9 10:36:01 2002
@@ -99,11 +99,11 @@
  */
 
 static int
-mk_conf_addr(struct pci_bus *bus_dev, unsigned int device_fn, int where,
+mk_conf_addr(struct pci_bus *pbus, unsigned int device_fn, int where,
 	     unsigned long *pci_addr)
 {
 	unsigned long addr;
-	u8 bus = bus_dev->number;
+	u8 bus = pbus->number;
 
 	if (bus == 0) {
 		int device = device_fn >> 3;
@@ -204,32 +204,20 @@
 {
 	unsigned long addr, pci_addr;
 	long mask;
-	int shift
+	int shift;
 
-	if (mk_conf_addr(bus, devfn, dev, where, &pci_addr))
+	if (mk_conf_addr(bus, devfn, where, &pci_addr))
 		return PCIBIOS_DEVICE_NOT_FOUND;
 
-	switch (size) {
-	case 1:
-		shift = (where & 3) * 8;
-		mask = 0x00;
-		break;
-	case 2:
-		shift = (where & 3) * 8;
-		mask = 0x08
-		break;
-	case 4:
-		shift = 0;
-		mask = 0x18
-		break;
-	}
+	shift = (where & 3) * 8;
+	mask = (size - 1) * 8;
 	addr = (pci_addr << 5) + mask + LCA_CONF;
 	*value = conf_read(addr) >> (shift);
 	return PCIBIOS_SUCCESSFUL;
 }
 
 static int 
-lca_write_config(struct pci_bus *dev, unsigned int devfn, int where, int size,
+lca_write_config(struct pci_bus *bus, unsigned int devfn, int where, int size,
 		 u32 value)
 {
 	unsigned long addr, pci_addr;
@@ -238,17 +226,7 @@
 	if (mk_conf_addr(bus, devfn, where, &pci_addr))
 		return PCIBIOS_DEVICE_NOT_FOUND;
 
-		switch (size) {
-	case 1:
-		mask = 0x00;
-		break;
-	case 2:
-		mask = 0x08
-		break;
-	case 4:
-		mask = 0x18
-		break;
-	}
+	mask = (size - 1) * 8;
 	addr = (pci_addr << 5) + mask + LCA_CONF;
 	conf_write(addr, value << ((where & 3) * 8));
 	return PCIBIOS_SUCCESSFUL;
diff -Nru a/arch/alpha/kernel/core_mcpcia.c b/arch/alpha/kernel/core_mcpcia.c
--- a/arch/alpha/kernel/core_mcpcia.c	Mon Sep  9 10:36:12 2002
+++ b/arch/alpha/kernel/core_mcpcia.c	Mon Sep  9 10:36:12 2002
@@ -171,11 +171,11 @@
 }
 
 static int
-mk_conf_addr(struct pci_dev *dev, int where, struct pci_controller *hose,
-	     unsigned long *pci_addr, unsigned char *type1)
+mk_conf_addr(struct pci_bus *pbus, unsigned int devfn, int where,
+	     struct pci_controller *hose, unsigned long *pci_addr,
+	     unsigned char *type1)
 {
-	u8 bus = dev->bus->number;
-	u8 devfn = dev->devfn;
+	u8 bus = pbus->number;
 	unsigned long addr;
 
 	DBG_CFG(("mk_conf_addr(bus=%d,devfn=0x%x,hose=%d,where=0x%x,"
@@ -185,7 +185,7 @@
 	/* Type 1 configuration cycle for *ALL* busses.  */
 	*type1 = 1;
 
-	if (dev->bus->number == hose->first_busno)
+	if (bus == hose->first_busno)
 		bus = 0;
 	addr = (bus << 16) | (devfn << 8) | (where);
 	addr <<= 5; /* swizzle for SPARSE */
@@ -197,94 +197,53 @@
 }
 
 static int
-mcpcia_read_config_byte(struct pci_dev *dev, int where, u8 *value)
+mcpcia_read_config(struct pci_bus *bus, unsigned int devfn, int where,
+		   int size, u32 *value)
 {
-	struct pci_controller *hose = dev->sysdata;
+	struct pci_controller *hose = bus->sysdata;
 	unsigned long addr, w;
 	unsigned char type1;
 
-	if (mk_conf_addr(dev, where, hose, &addr, &type1))
+	if (mk_conf_addr(bus, devfn, where, hose, &addr, &type1))
 		return PCIBIOS_DEVICE_NOT_FOUND;
 
-	addr |= 0x00;
+	addr |= (size - 1) * 8;
 	w = conf_read(addr, type1, hose);
-	*value = __kernel_extbl(w, where & 3);
+	switch (size) {
+	case 1:
+		*value = __kernel_extbl(w, where & 3);
+		break;
+	case 2:
+		*value = __kernel_extwl(w, where & 3);
+		break;
+	case 4:
+		*value = w;
+		break;
+	}
 	return PCIBIOS_SUCCESSFUL;
 }
 
 static int
-mcpcia_read_config_word(struct pci_dev *dev, int where, u16 *value)
+mcpcia_write_config(struct pci_bus *bus, unsigned int devfn, int where,
+		    int size, u32 value)
 {
-	struct pci_controller *hose = dev->sysdata;
-	unsigned long addr, w;
-	unsigned char type1;
-
-	if (mk_conf_addr(dev, where, hose, &addr, &type1))
-		return PCIBIOS_DEVICE_NOT_FOUND;
-
-	addr |= 0x08;
-	w = conf_read(addr, type1, hose);
-	*value = __kernel_extwl(w, where & 3);
-	return PCIBIOS_SUCCESSFUL;
-}
-
-static int
-mcpcia_read_config_dword(struct pci_dev *dev, int where, u32 *value)
-{
-	struct pci_controller *hose = dev->sysdata;
+	struct pci_controller *hose = bus->sysdata;
 	unsigned long addr;
 	unsigned char type1;
 
-	if (mk_conf_addr(dev, where, hose, &addr, &type1))
+	if (mk_conf_addr(bus, devfn, where, hose, &addr, &type1))
 		return PCIBIOS_DEVICE_NOT_FOUND;
 
-	addr |= 0x18;
-	*value = conf_read(addr, type1, hose);
-	return PCIBIOS_SUCCESSFUL;
-}
-
-static int
-mcpcia_write_config(struct pci_dev *dev, int where, u32 value, long mask)
-{
-	struct pci_controller *hose = dev->sysdata;
-	unsigned long addr;
-	unsigned char type1;
-
-	if (mk_conf_addr(dev, where, hose, &addr, &type1))
-		return PCIBIOS_DEVICE_NOT_FOUND;
-
-	addr |= mask;
+	addr |= (size - 1) * 8;
 	value = __kernel_insql(value, where & 3);
 	conf_write(addr, value, type1, hose);
 	return PCIBIOS_SUCCESSFUL;
 }
 
-static int
-mcpcia_write_config_byte(struct pci_dev *dev, int where, u8 value)
-{
-	return mcpcia_write_config(dev, where, value, 0x00);
-}
-
-static int
-mcpcia_write_config_word(struct pci_dev *dev, int where, u16 value)
-{
-	return mcpcia_write_config(dev, where, value, 0x08);
-}
-
-static int
-mcpcia_write_config_dword(struct pci_dev *dev, int where, u32 value)
-{
-	return mcpcia_write_config(dev, where, value, 0x18);
-}
-
 struct pci_ops mcpcia_pci_ops = 
 {
-	read_byte:	mcpcia_read_config_byte,
-	read_word:	mcpcia_read_config_word,
-	read_dword:	mcpcia_read_config_dword,
-	write_byte:	mcpcia_write_config_byte,
-	write_word:	mcpcia_write_config_word,
-	write_dword:	mcpcia_write_config_dword
+	.read =		mcpcia_read_config,
+	.write =	mcpcia_write_config,
 };
 
 void
diff -Nru a/arch/alpha/kernel/core_polaris.c b/arch/alpha/kernel/core_polaris.c
--- a/arch/alpha/kernel/core_polaris.c	Mon Sep  9 10:36:01 2002
+++ b/arch/alpha/kernel/core_polaris.c	Mon Sep  9 10:36:01 2002
@@ -65,10 +65,10 @@
  */
 
 static int
-mk_conf_addr(struct pci_bus *bus_dev, unsigned int device_fn, int where,
+mk_conf_addr(struct pci_bus *pbus, unsigned int device_fn, int where,
 	     unsigned long *pci_addr, u8 *type1)
 {
-	u8 bus = bus_dev->number;
+	u8 bus = pbus->number;
 
 	*type1 = (bus == 0) ? 0 : 1;
 	*pci_addr = (bus << 16) | (device_fn << 8) | (where) |
@@ -85,13 +85,24 @@
 polaris_read_config(struct pci_bus *bus, unsigned int devfn, int where,
 		    int size, u32 *value)
 {
-	unsigned long pci_addr;
+	unsigned long addr;
 	unsigned char type1;
 
-	if (mk_conf_addr(bus, devfn, where, &pci_addr, &type1))
+	if (mk_conf_addr(bus, devfn, where, &addr, &type1))
                 return PCIBIOS_DEVICE_NOT_FOUND;
 
-	*value = __kernel_ldbu(*(vucp)pci_addr);
+	switch (size) {
+	case 1:
+		*value = __kernel_ldbu(*(vucp)addr);
+		break;
+	case 2:
+		*value = __kernel_ldwu(*(vusp)addr);
+		break;
+	case 4:
+		*value = *(vuip)addr;
+		break;
+	}
+
 	return PCIBIOS_SUCCESSFUL;
 }
 
@@ -100,15 +111,30 @@
 polaris_write_config(struct pci_bus *bus, unsigned int devfn, int where,
 		     int size, u32 value)
 {
-	unsigned long pci_addr;
+	unsigned long addr;
 	unsigned char type1;
 
-	if (mk_conf_addr(bus, devfn, where, &pci_addr, &type1))
+	if (mk_conf_addr(bus, devfn, where, &addr, &type1))
                 return PCIBIOS_DEVICE_NOT_FOUND;
 
-        __kernel_stb(value, *(vucp)pci_addr);
-	mb();
-	__kernel_ldbu(*(vucp)pci_addr);
+	switch (size) {
+	case 1:
+		__kernel_stb(value, *(vucp)addr);
+		mb();
+		__kernel_ldbu(*(vucp)addr);
+		break;
+	case 2:
+		__kernel_stw(value, *(vusp)addr);
+		mb();
+		__kernel_ldwu(*(vusp)addr);
+		break;
+	case 4:
+		*(vuip)addr = value;
+		mb();
+		*(vuip)addr;
+		break;
+	}
+
 	return PCIBIOS_SUCCESSFUL;
 }
 
diff -Nru a/arch/alpha/kernel/core_t2.c b/arch/alpha/kernel/core_t2.c
--- a/arch/alpha/kernel/core_t2.c	Mon Sep  9 10:35:55 2002
+++ b/arch/alpha/kernel/core_t2.c	Mon Sep  9 10:35:55 2002
@@ -26,6 +26,18 @@
 #include "proto.h"
 #include "pci_impl.h"
 
+/*
+ * By default, we direct-map starting at 2GB, in order to allow the
+ * maximum size direct-map window (2GB) to match the maximum amount of
+ * memory (2GB) that can be present on SABLEs. But that limits the
+ * floppy to DMA only via the scatter/gather window set up for 8MB
+ * ISA DMA, since the maximum ISA DMA address is 2GB-1.
+ *
+ * For now, this seems a reasonable trade-off: even though most SABLEs
+ * have far less than even 1GB of memory, floppy usage/performance will
+ * not really be affected by forcing it to go via scatter/gather...
+ */
+#define T2_DIRECTMAP_2G 1
 
 /*
  * NOTE: Herein lie back-to-back mb instructions.  They are magic. 
@@ -89,11 +101,11 @@
  */
 
 static int
-mk_conf_addr(struct pci_bus *bus_dev, unsigned int device_fn, int where,
+mk_conf_addr(struct pci_bus *pbus, unsigned int device_fn, int where,
 	     unsigned long *pci_addr, unsigned char *type1)
 {
 	unsigned long addr;
-	u8 bus = bus_dev->number;
+	u8 bus = pbus->number;
 
 	DBG(("mk_conf_addr(bus=%d, dfn=0x%x, where=0x%x,"
 	     " addr=0x%lx, type1=0x%x)\n",
@@ -248,20 +260,8 @@
 	if (mk_conf_addr(bus, devfn, where, &pci_addr, &type1))
 		return PCIBIOS_DEVICE_NOT_FOUND;
 
-	switch (size) {
-	case 1:
-		mask = 0x00;
-		shift = (where & 3) * 8;
-		break;
-	case 2:
-		mask = 0x08;
-		shift = (where & 3) * 8;
-		break;
-	case 4:
-		mask = 0x18;
-		shift = 0;
-		break;
-	}
+	mask = (size - 1) * 8;
+	shift = (where & 3) * 8;
 	addr = (pci_addr << 5) + mask + T2_CONF;
 	*value = conf_read(addr, type1) >> (shift);
 	return PCIBIOS_SUCCESSFUL;
@@ -275,20 +275,10 @@
 	unsigned char type1;
 	long mask;
 
-	if (mk_conf_addr(dev, where, &pci_addr, &type1))
+	if (mk_conf_addr(bus, devfn, where, &pci_addr, &type1))
 		return PCIBIOS_DEVICE_NOT_FOUND;
 
-	switch (size) {
-	case 1:
-		mask = 0x00;
-		break;
-	case 2:
-		mask = 0x08;
-		break;
-	case 4:
-		mask = 0x18;
-		break;
-	}
+	mask = (size - 1) * 8;
 	addr = (pci_addr << 5) + mask + T2_CONF;
 	conf_write(addr, value << ((where & 3) * 8), type1);
 	return PCIBIOS_SUCCESSFUL;
@@ -304,6 +294,7 @@
 t2_init_arch(void)
 {
 	struct pci_controller *hose;
+	unsigned long t2_iocsr;
 	unsigned int i;
 
 	for (i = 0; i < NR_CPUS; i++) {
@@ -312,43 +303,80 @@
 	}
 
 #if 0
-	{
-	  /* Set up error reporting.  */
-	  unsigned long t2_err;
+	/* Set up error reporting.  */
+	t2_iocsr = *(vulp)T2_IOCSR;
+	*(vulp)T2_IOCSR = t2_iocsr | (0x1UL << 7); /* TLB error check */
+	mb();
+	*(vulp)T2_IOCSR; /* read it back to make sure */
+#endif
 
-	  t2_err = *(vulp)T2_IOCSR;
-	  t2_err |= (0x1 << 7);   /* master abort */
-	  *(vulp)T2_IOCSR = t2_err;
-	  mb();
+	/* Enable scatter/gather TLB use.  */
+	t2_iocsr = *(vulp)T2_IOCSR;
+	if (!(t2_iocsr & (0x1UL << 26))) {
+		printk("t2_init_arch: enabling SG TLB, IOCSR was 0x%lx\n",
+		       t2_iocsr);
+		*(vulp)T2_IOCSR = t2_iocsr | (0x1UL << 26);
+		mb();	
+		*(vulp)T2_IOCSR; /* read it back to make sure */
 	}
-#endif
 
-	printk("t2_init: HBASE was 0x%lx\n", *(vulp)T2_HBASE);
 #if 0
-	printk("t2_init: WBASE1=0x%lx WMASK1=0x%lx TBASE1=0x%lx\n",
-	       *(vulp)T2_WBASE1,
-	       *(vulp)T2_WMASK1,
-	       *(vulp)T2_TBASE1);
-	printk("t2_init: WBASE2=0x%lx WMASK2=0x%lx TBASE2=0x%lx\n",
-	       *(vulp)T2_WBASE2,
-	       *(vulp)T2_WMASK2,
-	       *(vulp)T2_TBASE2);
+	printk("t2_init_arch: HBASE was 0x%lx\n", *(vulp)T2_HBASE);
+	printk("t2_init_arch: WBASE1=0x%lx WMASK1=0x%lx TBASE1=0x%lx\n",
+	       *(vulp)T2_WBASE1, *(vulp)T2_WMASK1, *(vulp)T2_TBASE1);
+	printk("t2_init_arch: WBASE2=0x%lx WMASK2=0x%lx TBASE2=0x%lx\n",
+	       *(vulp)T2_WBASE2, *(vulp)T2_WMASK2, *(vulp)T2_TBASE2);
 #endif
 
 	/*
+	 * Create our single hose.
+	 */
+
+	pci_isa_hose = hose = alloc_pci_controller();
+	hose->io_space = &ioport_resource;
+	hose->mem_space = &iomem_resource;
+	hose->index = 0;
+
+	hose->sparse_mem_base = T2_SPARSE_MEM - IDENT_ADDR;
+	hose->dense_mem_base = T2_DENSE_MEM - IDENT_ADDR;
+	hose->sparse_io_base = T2_IO - IDENT_ADDR;
+	hose->dense_io_base = 0;
+
+	/* Note we can only do 1 SG window, as the other is for direct, so
+	   do an ISA SG area, especially for the floppy. */
+        hose->sg_isa = iommu_arena_new(hose, 0x00800000, 0x00800000, 0);
+	hose->sg_pci = NULL;
+
+	/*
 	 * Set up the PCI->physical memory translation windows.
-	 * For now, window 2 is  disabled.  In the future, we may
-	 * want to use it to do scatter/gather DMA. 
 	 *
-	 * Window 1 goes at 1 GB and is 1 GB large.
+	 * Window 1 goes at ? GB and is ?GB large, direct mapped.
+	 * Window 2 goes at 8 MB and is 8MB large, scatter/gather (for ISA).
 	 */
 
-	/* WARNING!! must correspond to the DMA_WIN params!!! */
+#if T2_DIRECTMAP_2G
+	__direct_map_base = 0x80000000UL;
+	__direct_map_size = 0x80000000UL;
+
+	/* WARNING!! must correspond to the direct map window params!!! */
+	*(vulp)T2_WBASE1 = 0x80080fffU;
+	*(vulp)T2_WMASK1 = 0x7ff00000U;
+	*(vulp)T2_TBASE1 = 0;
+#else /* T2_DIRECTMAP_2G */
+	__direct_map_base = 0x40000000UL;
+	__direct_map_size = 0x40000000UL;
+
+	/* WARNING!! must correspond to the direct map window params!!! */
 	*(vulp)T2_WBASE1 = 0x400807ffU;
 	*(vulp)T2_WMASK1 = 0x3ff00000U;
 	*(vulp)T2_TBASE1 = 0;
+#endif /* T2_DIRECTMAP_2G */
+
+	/* WARNING!! must correspond to the SG arena/window params!!! */
+	*(vulp)T2_WBASE2 = 0x008c000fU;
+	*(vulp)T2_WMASK2 = 0x00700000U;
+	*(vulp)T2_TBASE2 = virt_to_phys(hose->sg_isa->ptes) >> 1;
 
-	*(vulp)T2_WBASE2 = 0x0;
 	*(vulp)T2_HBASE = 0x0;
 
 	/* Zero HAE.  */
@@ -356,26 +384,28 @@
 	*(vulp)T2_HAE_2 = 0; mb();
 	*(vulp)T2_HAE_3 = 0; mb();
 #if 0
-	*(vulp)T2_HAE_4 = 0; mb(); /* do not touch this */
+	*(vulp)T2_HAE_4 = 0; mb(); /* DO NOT TOUCH THIS!!! */
 #endif
 
-	/*
-	 * Create our single hose.
-	 */
+	t2_pci_tbi(hose, 0, -1); /* flush TLB all */
+}
 
-	pci_isa_hose = hose = alloc_pci_controller();
-	hose->io_space = &ioport_resource;
-	hose->mem_space = &iomem_resource;
-	hose->index = 0;
+void
+t2_pci_tbi(struct pci_controller *hose, dma_addr_t start, dma_addr_t end)
+{
+	unsigned long t2_iocsr;
 
-	hose->sparse_mem_base = T2_SPARSE_MEM - IDENT_ADDR;
-	hose->dense_mem_base = T2_DENSE_MEM - IDENT_ADDR;
-	hose->sparse_io_base = T2_IO - IDENT_ADDR;
-	hose->dense_io_base = 0;
+	t2_iocsr = *(vulp)T2_IOCSR;
 
-	hose->sg_isa = hose->sg_pci = NULL;
-	__direct_map_base = 0x40000000;
-	__direct_map_size = 0x40000000;
+	/* set the TLB Clear bit */
+	*(vulp)T2_IOCSR = t2_iocsr | (0x1UL << 28);
+	mb();
+	*(vulp)T2_IOCSR; /* read it back to make sure */
+
+	/* clear the TLB Clear bit */
+	*(vulp)T2_IOCSR = t2_iocsr & ~(0x1UL << 28);
+	mb();
+	*(vulp)T2_IOCSR; /* read it back to make sure */
 }
 
 #define SIC_SEIC (1UL << 33)    /* System Event Clear */
diff -Nru a/arch/alpha/kernel/core_titan.c b/arch/alpha/kernel/core_titan.c
--- a/arch/alpha/kernel/core_titan.c	Mon Sep  9 10:36:01 2002
+++ b/arch/alpha/kernel/core_titan.c	Mon Sep  9 10:36:01 2002
@@ -82,19 +82,18 @@
  */
 
 static int
-mk_conf_addr(struct pci_dev *dev, int where, unsigned long *pci_addr,
-	     unsigned char *type1)
+mk_conf_addr(struct pci_bus *pbus, unsigned int device_fn, int where,
+	     unsigned long *pci_addr, unsigned char *type1)
 {
-	struct pci_controller *hose = dev->sysdata;
+	struct pci_controller *hose = pbus->sysdata;
 	unsigned long addr;
-	u8 bus = dev->bus->number;
-	u8 device_fn = dev->devfn;
+	u8 bus = pbus->number;
 
 	DBG_CFG(("mk_conf_addr(bus=%d ,device_fn=0x%x, where=0x%x, "
 		 "pci_addr=0x%p, type1=0x%p)\n",
 		 bus, device_fn, where, pci_addr, type1));
 
-        if (hose->first_busno == dev->bus->number)
+        if (hose->first_busno == bus)
 		bus = 0;
         *type1 = (bus != 0);
 
@@ -106,98 +105,66 @@
 	return 0;
 }
 
-static int 
-titan_read_config_byte(struct pci_dev *dev, int where, u8 *value)
-{
-	unsigned long addr;
-	unsigned char type1;
-
-	if (mk_conf_addr(dev, where, &addr, &type1))
-		return PCIBIOS_DEVICE_NOT_FOUND;
-
-	*value = __kernel_ldbu(*(vucp)addr);
-	return PCIBIOS_SUCCESSFUL;
-}
-
-static int
-titan_read_config_word(struct pci_dev *dev, int where, u16 *value)
-{
-	unsigned long addr;
-	unsigned char type1;
-
-	if (mk_conf_addr(dev, where, &addr, &type1))
-		return PCIBIOS_DEVICE_NOT_FOUND;
-
-	*value = __kernel_ldwu(*(vusp)addr);
-	return PCIBIOS_SUCCESSFUL;
-}
-
 static int
-titan_read_config_dword(struct pci_dev *dev, int where, u32 *value)
+titan_read_config(struct pci_bus *bus, unsigned int devfn, int where,
+		  int size, u32 *value)
 {
 	unsigned long addr;
 	unsigned char type1;
 
-	if (mk_conf_addr(dev, where, &addr, &type1))
+	if (mk_conf_addr(bus, devfn, where, &addr, &type1))
 		return PCIBIOS_DEVICE_NOT_FOUND;
 
-	*value = *(vuip)addr;
-	return PCIBIOS_SUCCESSFUL;
-}
-
-static int 
-titan_write_config_byte(struct pci_dev *dev, int where, u8 value)
-{
-	unsigned long addr;
-	unsigned char type1;
-
-	if (mk_conf_addr(dev, where, &addr, &type1))
-		return PCIBIOS_DEVICE_NOT_FOUND;
+	switch (size) {
+	case 1:
+		*value = __kernel_ldbu(*(vucp)addr);
+		break;
+	case 2:
+		*value = __kernel_ldwu(*(vusp)addr);
+		break;
+	case 4:
+		*value = *(vuip)addr;
+		break;
+	}
 
-	__kernel_stb(value, *(vucp)addr);
-	mb();
-	__kernel_ldbu(*(vucp)addr);
 	return PCIBIOS_SUCCESSFUL;
 }
 
 static int 
-titan_write_config_word(struct pci_dev *dev, int where, u16 value)
+titan_write_config(struct pci_bus *bus, unsigned int devfn, int where,
+		   int size, u32 value)
 {
 	unsigned long addr;
 	unsigned char type1;
 
-	if (mk_conf_addr(dev, where, &addr, &type1))
+	if (mk_conf_addr(bus, devfn, where, &addr, &type1))
 		return PCIBIOS_DEVICE_NOT_FOUND;
 
-	__kernel_stw(value, *(vusp)addr);
-	mb();
-	__kernel_ldwu(*(vusp)addr);
-	return PCIBIOS_SUCCESSFUL;
-}
-
-static int
-titan_write_config_dword(struct pci_dev *dev, int where, u32 value)
-{
-	unsigned long addr;
-	unsigned char type1;
-
-	if (mk_conf_addr(dev, where, &addr, &type1))
-		return PCIBIOS_DEVICE_NOT_FOUND;
+	switch (size) {
+	case 1:
+		__kernel_stb(value, *(vucp)addr);
+		mb();
+		__kernel_ldbu(*(vucp)addr);
+		break;
+	case 2:
+		__kernel_stw(value, *(vusp)addr);
+		mb();
+		__kernel_ldwu(*(vusp)addr);
+		break;
+	case 4:
+		*(vuip)addr = value;
+		mb();
+		*(vuip)addr;
+		break;
+	}
 
-	*(vuip)addr = value;
-	mb();
-	*(vuip)addr;
 	return PCIBIOS_SUCCESSFUL;
 }
 
 struct pci_ops titan_pci_ops = 
 {
-	read_byte:	titan_read_config_byte,
-	read_word:	titan_read_config_word,
-	read_dword:	titan_read_config_dword,
-	write_byte:	titan_write_config_byte,
-	write_word:	titan_write_config_word,
-	write_dword:	titan_write_config_dword
+	.read =		titan_read_config,
+	.write =	titan_write_config,
 };
 
 
diff -Nru a/arch/alpha/kernel/core_tsunami.c b/arch/alpha/kernel/core_tsunami.c
--- a/arch/alpha/kernel/core_tsunami.c	Mon Sep  9 10:36:11 2002
+++ b/arch/alpha/kernel/core_tsunami.c	Mon Sep  9 10:36:11 2002
@@ -89,19 +89,18 @@
  */
 
 static int
-mk_conf_addr(struct pci_dev *dev, int where, unsigned long *pci_addr,
-	     unsigned char *type1)
+mk_conf_addr(struct pci_bus *pbus, unsigned int device_fn, int where,
+	     unsigned long *pci_addr, unsigned char *type1)
 {
-	struct pci_controller *hose = dev->sysdata;
+	struct pci_controller *hose = pbus->sysdata;
 	unsigned long addr;
-	u8 bus = dev->bus->number;
-	u8 device_fn = dev->devfn;
+	u8 bus = pbus->number;
 
 	DBG_CFG(("mk_conf_addr(bus=%d ,device_fn=0x%x, where=0x%x, "
 		 "pci_addr=0x%p, type1=0x%p)\n",
 		 bus, device_fn, where, pci_addr, type1));
 
-	if (hose->first_busno == dev->bus->number)
+	if (hose->first_busno == bus)
 		bus = 0;
 	*type1 = (bus != 0);
 
@@ -114,97 +113,65 @@
 }
 
 static int 
-tsunami_read_config_byte(struct pci_dev *dev, int where, u8 *value)
+tsunami_read_config(struct pci_bus *bus, unsigned int devfn, int where,
+		    int size, u32 *value)
 {
 	unsigned long addr;
 	unsigned char type1;
 
-	if (mk_conf_addr(dev, where, &addr, &type1))
+	if (mk_conf_addr(bus, devfn, where, &addr, &type1))
 		return PCIBIOS_DEVICE_NOT_FOUND;
 
-	*value = __kernel_ldbu(*(vucp)addr);
-	return PCIBIOS_SUCCESSFUL;
-}
-
-static int
-tsunami_read_config_word(struct pci_dev *dev, int where, u16 *value)
-{
-	unsigned long addr;
-	unsigned char type1;
-
-	if (mk_conf_addr(dev, where, &addr, &type1))
-		return PCIBIOS_DEVICE_NOT_FOUND;
-
-	*value = __kernel_ldwu(*(vusp)addr);
-	return PCIBIOS_SUCCESSFUL;
-}
-
-static int
-tsunami_read_config_dword(struct pci_dev *dev, int where, u32 *value)
-{
-	unsigned long addr;
-	unsigned char type1;
-
-	if (mk_conf_addr(dev, where, &addr, &type1))
-		return PCIBIOS_DEVICE_NOT_FOUND;
-
-	*value = *(vuip)addr;
-	return PCIBIOS_SUCCESSFUL;
-}
-
-static int 
-tsunami_write_config_byte(struct pci_dev *dev, int where, u8 value)
-{
-	unsigned long addr;
-	unsigned char type1;
-
-	if (mk_conf_addr(dev, where, &addr, &type1))
-		return PCIBIOS_DEVICE_NOT_FOUND;
+	switch (size) {
+	case 1:
+		*value = __kernel_ldbu(*(vucp)addr);
+		break;
+	case 2:
+		*value = __kernel_ldwu(*(vusp)addr);
+		break;
+	case 4:
+		*value = *(vuip)addr;
+		break;
+	}
 
-	__kernel_stb(value, *(vucp)addr);
-	mb();
-	__kernel_ldbu(*(vucp)addr);
 	return PCIBIOS_SUCCESSFUL;
 }
 
 static int 
-tsunami_write_config_word(struct pci_dev *dev, int where, u16 value)
+tsunami_write_config(struct pci_bus *bus, unsigned int devfn, int where,
+		     int size, u32 value)
 {
 	unsigned long addr;
 	unsigned char type1;
 
-	if (mk_conf_addr(dev, where, &addr, &type1))
+	if (mk_conf_addr(bus, devfn, where, &addr, &type1))
 		return PCIBIOS_DEVICE_NOT_FOUND;
 
-	__kernel_stw(value, *(vusp)addr);
-	mb();
-	__kernel_ldwu(*(vusp)addr);
-	return PCIBIOS_SUCCESSFUL;
-}
-
-static int
-tsunami_write_config_dword(struct pci_dev *dev, int where, u32 value)
-{
-	unsigned long addr;
-	unsigned char type1;
-
-	if (mk_conf_addr(dev, where, &addr, &type1))
-		return PCIBIOS_DEVICE_NOT_FOUND;
+	switch (size) {
+	case 1:
+		__kernel_stb(value, *(vucp)addr);
+		mb();
+		__kernel_ldbu(*(vucp)addr);
+		break;
+	case 2:
+		__kernel_stw(value, *(vusp)addr);
+		mb();
+		__kernel_ldwu(*(vusp)addr);
+		break;
+	case 4:
+		*(vuip)addr = value;
+		mb();
+		*(vuip)addr;
+		break;
+	}
 
-	*(vuip)addr = value;
-	mb();
-	*(vuip)addr;
 	return PCIBIOS_SUCCESSFUL;
 }
 
 struct pci_ops tsunami_pci_ops = 
 {
-	read_byte:	tsunami_read_config_byte,
-	read_word:	tsunami_read_config_word,
-	read_dword:	tsunami_read_config_dword,
-	write_byte:	tsunami_write_config_byte,
-	write_word:	tsunami_write_config_word,
-	write_dword:	tsunami_write_config_dword
+	.read =		tsunami_read_config,
+	.write = 	tsunami_write_config,
 };
 
 void
@@ -350,10 +317,17 @@
 	 * Window 0 is scatter-gather 8MB at 8MB (for isa)
 	 * Window 1 is scatter-gather (up to) 1GB at 1GB
 	 * Window 2 is direct access 2GB at 2GB
+	 *
+	 * NOTE: we need the align_entry settings for Acer devices on ES40,
+	 * specifically floppy and IDE when memory is larger than 2GB.
 	 */
 	hose->sg_isa = iommu_arena_new(hose, 0x00800000, 0x00800000, 0);
+	/* Initially set for 4 PTEs, but will be overridden to 64K for ISA. */
+        hose->sg_isa->align_entry = 4;
+
 	hose->sg_pci = iommu_arena_new(hose, 0x40000000,
 				       size_for_memory(0x40000000), 0);
+        hose->sg_pci->align_entry = 4; /* Tsunami caches 4 PTEs at a time */
 
 	__direct_map_base = 0x80000000;
 	__direct_map_size = 0x80000000;
diff -Nru a/arch/alpha/kernel/core_wildfire.c b/arch/alpha/kernel/core_wildfire.c
--- a/arch/alpha/kernel/core_wildfire.c	Mon Sep  9 10:35:45 2002
+++ b/arch/alpha/kernel/core_wildfire.c	Mon Sep  9 10:35:45 2002
@@ -357,19 +357,18 @@
 }
 
 static int
-mk_conf_addr(struct pci_dev *dev, int where, unsigned long *pci_addr,
-	     unsigned char *type1)
+mk_conf_addr(struct pci_bus *pbus, unsigned int device_fn, int where,
+	     unsigned long *pci_addr, unsigned char *type1)
 {
-	struct pci_controller *hose = dev->sysdata;
+	struct pci_controller *hose = pbus->sysdata;
 	unsigned long addr;
-	u8 bus = dev->bus->number;
-	u8 device_fn = dev->devfn;
+	u8 bus = pbus->number;
 
 	DBG_CFG(("mk_conf_addr(bus=%d ,device_fn=0x%x, where=0x%x, "
 		 "pci_addr=0x%p, type1=0x%p)\n",
 		 bus, device_fn, where, pci_addr, type1));
 
-	if (hose->first_busno == dev->bus->number)
+	if (hose->first_busno == bus)
 		bus = 0;
 	*type1 = (bus != 0);
 
@@ -382,97 +381,65 @@
 }
 
 static int 
-wildfire_read_config_byte(struct pci_dev *dev, int where, u8 *value)
+wildfire_read_config(struct pci_bus *bus, unsigned int devfn, int where,
+		     int size, u32 *value)
 {
 	unsigned long addr;
 	unsigned char type1;
 
-	if (mk_conf_addr(dev, where, &addr, &type1))
+	if (mk_conf_addr(bus, devfn, where, &addr, &type1))
 		return PCIBIOS_DEVICE_NOT_FOUND;
 
-	*value = __kernel_ldbu(*(vucp)addr);
-	return PCIBIOS_SUCCESSFUL;
-}
-
-static int
-wildfire_read_config_word(struct pci_dev *dev, int where, u16 *value)
-{
-	unsigned long addr;
-	unsigned char type1;
-
-	if (mk_conf_addr(dev, where, &addr, &type1))
-		return PCIBIOS_DEVICE_NOT_FOUND;
-
-	*value = __kernel_ldwu(*(vusp)addr);
-	return PCIBIOS_SUCCESSFUL;
-}
+	switch (size) {
+	case 1:
+		*value = __kernel_ldbu(*(vucp)addr);
+		break;
+	case 2:
+		*value = __kernel_ldwu(*(vusp)addr);
+		break;
+	case 4:
+		*value = *(vuip)addr;
+		break;
+	}
 
-static int
-wildfire_read_config_dword(struct pci_dev *dev, int where, u32 *value)
-{
-	unsigned long addr;
-	unsigned char type1;
-
-	if (mk_conf_addr(dev, where, &addr, &type1))
-		return PCIBIOS_DEVICE_NOT_FOUND;
-
-	*value = *(vuip)addr;
 	return PCIBIOS_SUCCESSFUL;
 }
 
 static int 
-wildfire_write_config_byte(struct pci_dev *dev, int where, u8 value)
+wildfire_write_config(struct pci_bus *bus, unsigned int devfn, int where,
+		      int size, u32 value)
 {
 	unsigned long addr;
 	unsigned char type1;
 
-	if (mk_conf_addr(dev, where, &addr, &type1))
+	if (mk_conf_addr(bus, devfn, where, &addr, &type1))
 		return PCIBIOS_DEVICE_NOT_FOUND;
 
-	__kernel_stb(value, *(vucp)addr);
-	mb();
-	__kernel_ldbu(*(vucp)addr);
-	return PCIBIOS_SUCCESSFUL;
-}
-
-static int 
-wildfire_write_config_word(struct pci_dev *dev, int where, u16 value)
-{
-	unsigned long addr;
-	unsigned char type1;
-
-	if (mk_conf_addr(dev, where, &addr, &type1))
-		return PCIBIOS_DEVICE_NOT_FOUND;
-
-	__kernel_stw(value, *(vusp)addr);
-	mb();
-	__kernel_ldwu(*(vusp)addr);
-	return PCIBIOS_SUCCESSFUL;
-}
-
-static int
-wildfire_write_config_dword(struct pci_dev *dev, int where, u32 value)
-{
-	unsigned long addr;
-	unsigned char type1;
-
-	if (mk_conf_addr(dev, where, &addr, &type1))
-		return PCIBIOS_DEVICE_NOT_FOUND;
+	switch (size) {
+	case 1:
+		__kernel_stb(value, *(vucp)addr);
+		mb();
+		__kernel_ldbu(*(vucp)addr);
+		break;
+	case 2:
+		__kernel_stw(value, *(vusp)addr);
+		mb();
+		__kernel_ldwu(*(vusp)addr);
+		break;
+	case 4:
+		*(vuip)addr = value;
+		mb();
+		*(vuip)addr;
+		break;
+	}
 
-	*(vuip)addr = value;
-	mb();
-	*(vuip)addr;
 	return PCIBIOS_SUCCESSFUL;
 }
 
 struct pci_ops wildfire_pci_ops = 
 {
-	read_byte:	wildfire_read_config_byte,
-	read_word:	wildfire_read_config_word,
-	read_dword:	wildfire_read_config_dword,
-	write_byte:	wildfire_write_config_byte,
-	write_word:	wildfire_write_config_word,
-	write_dword:	wildfire_write_config_dword
+	.read =		wildfire_read_config,
+	.write =	wildfire_write_config,
 };
 
 #if DEBUG_DUMP_REGS
diff -Nru a/arch/alpha/kernel/irq.c b/arch/alpha/kernel/irq.c
--- a/arch/alpha/kernel/irq.c	Mon Sep  9 10:36:13 2002
+++ b/arch/alpha/kernel/irq.c	Mon Sep  9 10:36:13 2002
@@ -12,11 +12,11 @@
 
 #include <linux/config.h>
 #include <linux/kernel.h>
-#include <linux/ptrace.h>
 #include <linux/errno.h>
 #include <linux/kernel_stat.h>
 #include <linux/signal.h>
 #include <linux/sched.h>
+#include <linux/ptrace.h>
 #include <linux/interrupt.h>
 #include <linux/slab.h>
 #include <linux/random.h>
diff -Nru a/arch/alpha/kernel/pci.c b/arch/alpha/kernel/pci.c
--- a/arch/alpha/kernel/pci.c	Mon Sep  9 10:35:56 2002
+++ b/arch/alpha/kernel/pci.c	Mon Sep  9 10:35:56 2002
@@ -97,15 +97,22 @@
 	   way to turn this off.  The bridge also supports several extended
 	   BIOS ranges (disabled after power-up), and some consoles do turn
 	   them on.  So if we use a large direct-map window, or a large SG
-	   window, we must avoid entire 0xfff00000-0xffffffff region.  */
+	   window, we must avoid the entire 0xfff00000-0xffffffff region.  */
 	else if (dev->class >> 8 == PCI_CLASS_BRIDGE_ISA) {
-		if (__direct_map_base + __direct_map_size >= 0xfff00000)
-			__direct_map_size = 0xfff00000 - __direct_map_base;
-		else {
+#define DMAPSZ (max_low_pfn << PAGE_SHIFT) /* memory size, not window size */
+		if ((__direct_map_base + DMAPSZ - 1) >= 0xfff00000UL) {
+			__direct_map_size = 0xfff00000UL - __direct_map_base;
+			printk("%s: adjusting direct map size to 0x%x\n",
+			       __FUNCTION__, __direct_map_size);
+		} else {
 			struct pci_controller *hose = dev->sysdata;
 			struct pci_iommu_arena *pci = hose->sg_pci;
-			if (pci && pci->dma_base + pci->size >= 0xfff00000)
-				pci->size = 0xfff00000 - pci->dma_base;
+			if (pci &&
+			    (pci->dma_base + pci->size - 1) >= 0xfff00000UL) {
+				pci->size = 0xfff00000UL - pci->dma_base;
+ 				printk("%s: adjusting PCI S/G size to 0x%x\n",
+				       __FUNCTION__, pci->size);
+			}
 		}
 	}
 }
diff -Nru a/arch/alpha/kernel/pci_impl.h b/arch/alpha/kernel/pci_impl.h
--- a/arch/alpha/kernel/pci_impl.h	Mon Sep  9 10:36:13 2002
+++ b/arch/alpha/kernel/pci_impl.h	Mon Sep  9 10:36:13 2002
@@ -52,15 +52,16 @@
 #define APECS_AND_LCA_DEFAULT_MEM_BASE ((16+2)*1024*1024)
 
 /*
- * Because the MCPCIA core logic supports more bits for physical addresses,
- * it should allow an expanded range of SPARSE memory addresses.
- * However, we do not use them all, in order to avoid the HAE manipulation
- * that would be needed.
+ * Because MCPCIA and T2 core logic support more bits for
+ * physical addresses, they should allow an expanded range of SPARSE
+ * memory addresses.  However, we do not use them all, in order to
+ * avoid the HAE manipulation that would be needed.
  */
 #define MCPCIA_DEFAULT_MEM_BASE ((32+2)*1024*1024)
+#define T2_DEFAULT_MEM_BASE ((16+1)*1024*1024)
 
 /*
- * Because CIA and PYXIS and T2 have more bits for physical addresses,
+ * Because CIA and PYXIS have more bits for physical addresses,
  * they support an expanded range of SPARSE memory addresses.
  */
 #define DEFAULT_MEM_BASE ((128+16)*1024*1024)
@@ -157,8 +158,6 @@
 extern struct pci_iommu_arena *iommu_arena_new(struct pci_controller *,
 					       dma_addr_t, unsigned long,
 					       unsigned long);
-extern long iommu_arena_alloc(struct pci_iommu_arena *arena, long n);
-
 extern const char *const pci_io_names[];
 extern const char *const pci_mem_names[];
 extern const char pci_hae0_name[];
diff -Nru a/arch/alpha/kernel/pci_iommu.c b/arch/alpha/kernel/pci_iommu.c
--- a/arch/alpha/kernel/pci_iommu.c	Mon Sep  9 10:36:17 2002
+++ b/arch/alpha/kernel/pci_iommu.c	Mon Sep  9 10:36:17 2002
@@ -30,6 +30,9 @@
 #define DEBUG_NODIRECT 0
 #define DEBUG_FORCEDAC 0
 
+/* Most Alphas support 32-bit ISA DMA. Exceptions are XL, Ruffian,
+   Nautilus, Sable, and Alcor (see asm-alpha/dma.h for details). */
+#define ISA_DMA_MASK	(MAX_DMA_ADDRESS - IDENT_ADDR - 1)
 
 static inline unsigned long
 mk_iommu_pte(unsigned long paddr)
@@ -129,8 +132,8 @@
 	return p;
 }
 
-long
-iommu_arena_alloc(struct pci_iommu_arena *arena, long n)
+static long
+iommu_arena_alloc(struct pci_iommu_arena *arena, long n, unsigned int align)
 {
 	unsigned long flags;
 	unsigned long *ptes;
@@ -140,7 +143,7 @@
 
 	/* Search for N empty ptes */
 	ptes = arena->ptes;
-	mask = arena->align_entry - 1;
+	mask = max(align, arena->align_entry) - 1;
 	p = iommu_arena_find_pages(arena, n, mask);
 	if (p < 0) {
 		spin_unlock_irqrestore(&arena->lock, flags);
@@ -181,7 +184,7 @@
 		 int dac_allowed)
 {
 	struct pci_controller *hose = pdev ? pdev->sysdata : pci_isa_hose;
-	dma_addr_t max_dma = pdev ? pdev->dma_mask : 0x00ffffff;
+	dma_addr_t max_dma = pdev ? pdev->dma_mask : ISA_DMA_MASK;
 	struct pci_iommu_arena *arena;
 	long npages, dma_ofs, i;
 	unsigned long paddr;
@@ -232,7 +235,8 @@
 		arena = hose->sg_isa;
 
 	npages = calc_npages((paddr & ~PAGE_MASK) + size);
-	dma_ofs = iommu_arena_alloc(arena, npages);
+	/* Force allocation to 64KB boundary for all ISA devices. */
+	dma_ofs = iommu_arena_alloc(arena, npages, pdev ? 8 : 0);
 	if (dma_ofs < 0) {
 		printk(KERN_WARNING "pci_map_single failed: "
 		       "could not allocate dma page tables\n");
@@ -499,7 +503,7 @@
 
 	paddr &= ~PAGE_MASK;
 	npages = calc_npages(paddr + size);
-	dma_ofs = iommu_arena_alloc(arena, npages);
+	dma_ofs = iommu_arena_alloc(arena, npages, 0);
 	if (dma_ofs < 0) {
 		/* If we attempted a direct map above but failed, die.  */
 		if (leader->dma_address == 0)
@@ -588,7 +592,7 @@
 	/* Second, figure out where we're going to map things.  */
 	if (alpha_mv.mv_pci_tbi) {
 		hose = pdev ? pdev->sysdata : pci_isa_hose;
-		max_dma = pdev ? pdev->dma_mask : 0x00ffffff;
+		max_dma = pdev ? pdev->dma_mask : ISA_DMA_MASK;
 		arena = hose->sg_pci;
 		if (!arena || arena->dma_base + arena->size - 1 > max_dma)
 			arena = hose->sg_isa;
@@ -651,7 +655,7 @@
 		return;
 
 	hose = pdev ? pdev->sysdata : pci_isa_hose;
-	max_dma = pdev ? pdev->dma_mask : 0x00ffffff;
+	max_dma = pdev ? pdev->dma_mask : ISA_DMA_MASK;
 	arena = hose->sg_pci;
 	if (!arena || arena->dma_base + arena->size - 1 > max_dma)
 		arena = hose->sg_isa;
diff -Nru a/arch/alpha/kernel/process.c b/arch/alpha/kernel/process.c
--- a/arch/alpha/kernel/process.c	Mon Sep  9 10:36:01 2002
+++ b/arch/alpha/kernel/process.c	Mon Sep  9 10:36:01 2002
@@ -261,11 +261,13 @@
 	    struct switch_stack * swstack)
 {
 	struct task_struct *p;
+	struct pt_regs *u_regs = (struct pt_regs *) (swstack+1);
+	int *user_tid = (int *)u_regs->r19;
+
 	if (!usp)
 		usp = rdusp();
 
-	p = do_fork(clone_flags & ~CLONE_IDLETASK,
-		    usp, (struct pt_regs *) (swstack+1), 0);
+	p = do_fork(clone_flags & ~CLONE_IDLETASK, usp, u_regs, 0, user_tid);
 	return IS_ERR(p) ? PTR_ERR(p) : p->pid;
 }
 
@@ -274,7 +276,7 @@
 {
 	struct task_struct *p;
 	p = do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, rdusp(),
-		    (struct pt_regs *) (swstack+1), 0);
+		    (struct pt_regs *) (swstack+1), 0, NULL);
 	return IS_ERR(p) ? PTR_ERR(p) : p->pid;
 }
 
diff -Nru a/arch/alpha/kernel/proto.h b/arch/alpha/kernel/proto.h
--- a/arch/alpha/kernel/proto.h	Mon Sep  9 10:36:01 2002
+++ b/arch/alpha/kernel/proto.h	Mon Sep  9 10:36:01 2002
@@ -59,7 +59,7 @@
 extern struct pci_ops t2_pci_ops;
 extern void t2_init_arch(void);
 extern void t2_machine_check(u64, u64, struct pt_regs *);
-#define t2_pci_tbi ((void *)0)
+extern void t2_pci_tbi(struct pci_controller *, dma_addr_t, dma_addr_t);
 
 /* core_titan.c */
 extern struct pci_ops titan_pci_ops;
diff -Nru a/arch/alpha/kernel/smp.c b/arch/alpha/kernel/smp.c
--- a/arch/alpha/kernel/smp.c	Mon Sep  9 10:36:01 2002
+++ b/arch/alpha/kernel/smp.c	Mon Sep  9 10:36:01 2002
@@ -432,7 +432,7 @@
 	/* Don't care about the contents of regs since we'll never
 	   reschedule the forked task. */
 	struct pt_regs regs;
-	return do_fork(CLONE_VM|CLONE_IDLETASK, 0, &regs, 0);
+	return do_fork(CLONE_VM|CLONE_IDLETASK, 0, &regs, 0, NULL);
 }
 
 /*
diff -Nru a/arch/alpha/kernel/sys_alcor.c b/arch/alpha/kernel/sys_alcor.c
--- a/arch/alpha/kernel/sys_alcor.c	Mon Sep  9 10:36:11 2002
+++ b/arch/alpha/kernel/sys_alcor.c	Mon Sep  9 10:36:11 2002
@@ -251,7 +251,7 @@
 	DO_CIA_IO,
 	DO_CIA_BUS,
 	machine_check:		cia_machine_check,
-	max_dma_address:	ALPHA_MAX_DMA_ADDRESS,
+	max_dma_address:	ALPHA_ALCOR_MAX_DMA_ADDRESS,
 	min_io_address:		EISA_DEFAULT_IO_BASE,
 	min_mem_address:	CIA_DEFAULT_MEM_BASE,
 
diff -Nru a/arch/alpha/kernel/sys_rx164.c b/arch/alpha/kernel/sys_rx164.c
--- a/arch/alpha/kernel/sys_rx164.c	Mon Sep  9 10:35:51 2002
+++ b/arch/alpha/kernel/sys_rx164.c	Mon Sep  9 10:35:51 2002
@@ -35,16 +35,15 @@
 /* Note mask bit is true for ENABLED irqs.  */
 static unsigned long cached_irq_mask;
 
-/* Bus 0, Device 0.  Nothing else matters, since we invoke the
-   POLARIS routines directly.  */
-static struct pci_dev rx164_system;
-
 static inline void
 rx164_update_irq_hw(unsigned long mask)
 {
-	unsigned int temp;
-	polaris_write_config_dword(&rx164_system, 0x74, mask);
-	polaris_read_config_dword(&rx164_system, 0x74, &temp);
+	volatile unsigned int *irq_mask;
+
+	irq_mask = (void *)(POLARIS_DENSE_CONFIG_BASE + 0x74);
+	*irq_mask = mask;
+	mb();
+	*irq_mask;
 }
 
 static inline void
@@ -86,14 +85,14 @@
 static void 
 rx164_device_interrupt(unsigned long vector, struct pt_regs *regs)
 {
-	unsigned int temp;
 	unsigned long pld;
+	volatile unsigned int *dirr;
 	long i;
 
 	/* Read the interrupt summary register.  On Polaris, this is
 	   the DIRR register in PCI config space (offset 0x84).  */
-	polaris_read_config_dword(&rx164_system, 0x84, &temp);
-	pld = temp;
+	dirr = (void *)(POLARIS_DENSE_CONFIG_BASE + 0x84);
+	pld = *dirr;
 
 	/*
 	 * Now for every possible bit set, work through them and call
diff -Nru a/arch/alpha/kernel/sys_sable.c b/arch/alpha/kernel/sys_sable.c
--- a/arch/alpha/kernel/sys_sable.c	Mon Sep  9 10:35:56 2002
+++ b/arch/alpha/kernel/sys_sable.c	Mon Sep  9 10:35:56 2002
@@ -290,9 +290,9 @@
 	DO_T2_IO,
 	DO_T2_BUS,
 	machine_check:		t2_machine_check,
-	max_dma_address:	ALPHA_MAX_DMA_ADDRESS,
+	max_dma_address:	ALPHA_SABLE_MAX_DMA_ADDRESS,
 	min_io_address:		EISA_DEFAULT_IO_BASE,
-	min_mem_address:	DEFAULT_MEM_BASE,
+	min_mem_address:	T2_DEFAULT_MEM_BASE,
 
 	nr_irqs:		40,
 	device_interrupt:	sable_srm_device_interrupt,
@@ -322,9 +322,9 @@
 	DO_T2_IO,
 	DO_T2_BUS,
 	machine_check:		t2_machine_check,
-	max_dma_address:	ALPHA_MAX_DMA_ADDRESS,
+	max_dma_address:	ALPHA_SABLE_MAX_DMA_ADDRESS,
 	min_io_address:		EISA_DEFAULT_IO_BASE,
-	min_mem_address:	DEFAULT_MEM_BASE,
+	min_mem_address:	T2_DEFAULT_MEM_BASE,
 
 	nr_irqs:		40,
 	device_interrupt:	sable_srm_device_interrupt,
diff -Nru a/arch/alpha/kernel/time.c b/arch/alpha/kernel/time.c
--- a/arch/alpha/kernel/time.c	Mon Sep  9 10:36:11 2002
+++ b/arch/alpha/kernel/time.c	Mon Sep  9 10:36:11 2002
@@ -185,8 +185,8 @@
 		unsigned int min, max;
 	} cpu_hz[] __initdata = {
 		[EV3_CPU]    = {   50000000,  200000000 },	/* guess */
-		[EV4_CPU]    = {  150000000,  300000000 },
-		[LCA4_CPU]   = {  150000000,  300000000 },	/* guess */
+		[EV4_CPU]    = {  100000000,  300000000 },
+		[LCA4_CPU]   = {  100000000,  300000000 },	/* guess */
 		[EV45_CPU]   = {  200000000,  300000000 },
 		[EV5_CPU]    = {  250000000,  433000000 },
 		[EV56_CPU]   = {  333000000,  667000000 },
@@ -257,12 +257,12 @@
 
 	cc = rpcc();
 	do {
-		count++;
+	  count+=100; /* by 1 takes too long to timeout from 0 */
 	} while ((inb(0x61) & 0x20) == 0 && count > 0);
 	cc = rpcc() - cc;
 
 	/* Error: ECTCNEVERSET or ECPUTOOFAST.  */
-	if (count <= 1)
+	if (count <= 100)
 		return 0;
 
 	/* Error: ECPUTOOSLOW.  */
diff -Nru a/arch/alpha/kernel/traps.c b/arch/alpha/kernel/traps.c
--- a/arch/alpha/kernel/traps.c	Mon Sep  9 10:36:01 2002
+++ b/arch/alpha/kernel/traps.c	Mon Sep  9 10:36:01 2002
@@ -29,6 +29,7 @@
 */
 static int opDEC_testing = 0;
 static int opDEC_fix = 0;
+static int opDEC_checked = 0;
 static unsigned long opDEC_test_pc = 0;
 
 static void
@@ -36,6 +37,8 @@
 {
 	unsigned long test_pc;
 
+	if (opDEC_checked) return;
+
 	lock_kernel();
 	opDEC_testing = 1;
 
@@ -48,6 +51,7 @@
 		: );
 
 	opDEC_testing = 0;
+	opDEC_checked = 1;
 	unlock_kernel();
 }
 
diff -Nru a/arch/alpha/mm/numa.c b/arch/alpha/mm/numa.c
--- a/arch/alpha/mm/numa.c	Mon Sep  9 10:35:56 2002
+++ b/arch/alpha/mm/numa.c	Mon Sep  9 10:35:56 2002
@@ -294,7 +294,7 @@
 			zones_size[ZONE_DMA] = dma_local_pfn;
 			zones_size[ZONE_NORMAL] = (end_pfn - start_pfn) - dma_local_pfn;
 		}
-		free_area_init_node(nid, NODE_DATA(nid), NULL, zones_size, start_pfn<<PAGE_SHIFT, NULL);
+		free_area_init_node(nid, NODE_DATA(nid), NULL, zones_size, start_pfn, NULL);
 		lmax_mapnr = PLAT_NODE_DATA_STARTNR(nid) + PLAT_NODE_DATA_SIZE(nid);
 		if (lmax_mapnr > max_mapnr) {
 			max_mapnr = lmax_mapnr;
@@ -371,7 +371,7 @@
 		totalram_pages += free_all_bootmem_node(NODE_DATA(nid));
 
 		lmem_map = NODE_MEM_MAP(nid);
-		pfn = NODE_DATA(nid)->node_start_paddr >> PAGE_SHIFT;
+		pfn = NODE_DATA(nid)->node_start_pfn;
 		for (i = 0; i < PLAT_NODE_DATA_SIZE(nid); i++, pfn++)
 			if (page_is_ram(pfn) && PageReserved(lmem_map+i))
 				reservedpages++;
diff -Nru a/arch/arm/mm/init.c b/arch/arm/mm/init.c
--- a/arch/arm/mm/init.c	Mon Sep  9 10:35:56 2002
+++ b/arch/arm/mm/init.c	Mon Sep  9 10:35:56 2002
@@ -512,7 +512,7 @@
 		arch_adjust_zones(node, zone_size, zhole_size);
 
 		free_area_init_node(node, pgdat, 0, zone_size,
-				bdata->node_boot_start, zhole_size);
+				bdata->node_boot_start >> PAGE_SHIFT, zhole_size);
 	}
 
 	/*
diff -Nru a/arch/cris/mm/init.c b/arch/cris/mm/init.c
--- a/arch/cris/mm/init.c	Mon Sep  9 10:36:11 2002
+++ b/arch/cris/mm/init.c	Mon Sep  9 10:36:11 2002
@@ -345,7 +345,7 @@
 	 * mem_map page array.
 	 */
 
-	free_area_init_node(0, 0, 0, zones_size, PAGE_OFFSET, 0);
+	free_area_init_node(0, 0, 0, zones_size, PAGE_OFFSET >> PAGE_SHIFT, 0);
 
 }
 
diff -Nru a/arch/i386/Config.help b/arch/i386/Config.help
--- a/arch/i386/Config.help	Mon Sep  9 10:35:56 2002
+++ b/arch/i386/Config.help	Mon Sep  9 10:35:56 2002
@@ -41,7 +41,7 @@
   486, 586, Pentiums, and various instruction-set-compatible chips by
   AMD, Cyrix, and others.
 
-CONFIG_MULTIQUAD
+CONFIG_X86_NUMAQ
   This option is used for getting Linux to run on a (IBM/Sequent) NUMA 
   multiquad box. This changes the way that processors are bootstrapped,
   and uses Clustered Logical APIC addressing mode instead of Flat Logical.
diff -Nru a/arch/i386/Makefile b/arch/i386/Makefile
--- a/arch/i386/Makefile	Mon Sep  9 10:36:05 2002
+++ b/arch/i386/Makefile	Mon Sep  9 10:36:05 2002
@@ -18,7 +18,7 @@
 
 LDFLAGS		:= -m elf_i386
 OBJCOPYFLAGS	:= -O binary -R .note -R .comment -S
-LDFLAGS_vmlinux := -T arch/i386/vmlinux.lds -e stext
+LDFLAGS_vmlinux := -T arch/i386/vmlinux.lds.s -e stext
 
 CFLAGS += -pipe
 
@@ -104,7 +104,7 @@
 
 MAKEBOOT = +$(MAKE) -C arch/$(ARCH)/boot
 
-vmlinux: arch/i386/vmlinux.lds
+vmlinux: arch/i386/vmlinux.lds.s
 
 .PHONY: zImage bzImage compressed zlilo bzlilo zdisk bzdisk install \
 		clean archclean archmrproper
diff -Nru a/arch/i386/config.in b/arch/i386/config.in
--- a/arch/i386/config.in	Mon Sep  9 10:36:01 2002
+++ b/arch/i386/config.in	Mon Sep  9 10:36:01 2002
@@ -166,7 +166,22 @@
       define_bool CONFIG_X86_IO_APIC y
    fi
 else
-   bool 'Multiquad NUMA system' CONFIG_MULTIQUAD
+  bool 'Multi-node NUMA system support' CONFIG_X86_NUMA
+  if [ "$CONFIG_X86_NUMA" = "y" ]; then
+     #Platform Choices
+     bool 'Multiquad (IBM/Sequent) NUMAQ support' CONFIG_X86_NUMAQ
+     if [ "$CONFIG_X86_NUMAQ" = "y" ]; then
+        define_bool CONFIG_MULTIQUAD y
+     fi
+     # Common NUMA Features
+     if [ "$CONFIG_X86_NUMAQ" = "y" ]; then
+        bool 'Numa Memory Allocation Support' CONFIG_NUMA
+        if [ "$CONFIG_NUMA" = "y" ]; then
+           define_bool CONFIG_DISCONTIGMEM y
+           define_bool CONFIG_HAVE_ARCH_BOOTMEM_NODE y
+        fi
+     fi
+  fi
 fi
 
 bool 'Machine Check Exception' CONFIG_X86_MCE
diff -Nru a/arch/i386/kernel/Makefile b/arch/i386/kernel/Makefile
--- a/arch/i386/kernel/Makefile	Mon Sep  9 10:36:01 2002
+++ b/arch/i386/kernel/Makefile	Mon Sep  9 10:36:01 2002
@@ -6,7 +6,7 @@
 
 O_TARGET := kernel.o
 
-export-objs     := mca.o msr.o i386_ksyms.o time.o
+export-objs     := mca.o i386_ksyms.o time.o
 
 obj-y	:= process.o semaphore.o signal.o entry.o traps.o irq.o vm86.o \
 		ptrace.o i8259.o ioport.o ldt.o setup.o time.o sys_i386.o \
@@ -25,6 +25,7 @@
 obj-$(CONFIG_X86_LOCAL_APIC)	+= mpparse.o apic.o nmi.o
 obj-$(CONFIG_X86_IO_APIC)	+= io_apic.o
 obj-$(CONFIG_SOFTWARE_SUSPEND)	+= suspend.o
+obj-$(CONFIG_X86_NUMAQ)		+= numaq.o
 ifdef CONFIG_VISWS
 obj-y += setup-visws.o
 obj-$(CONFIG_X86_VISWS_APIC)	+= visws_apic.o
diff -Nru a/arch/i386/kernel/dmi_scan.c b/arch/i386/kernel/dmi_scan.c
--- a/arch/i386/kernel/dmi_scan.c	Mon Sep  9 10:36:11 2002
+++ b/arch/i386/kernel/dmi_scan.c	Mon Sep  9 10:36:11 2002
@@ -12,6 +12,7 @@
 
 unsigned long dmi_broken;
 int is_sony_vaio_laptop;
+int is_unsafe_smbus;
 
 struct dmi_header
 {
@@ -459,6 +460,19 @@
 	return 0;
 }
 
+/* 
+ * Don't access SMBus on IBM systems which get corrupted eeproms 
+ */
+
+static __init int disable_smbus(struct dmi_blacklist *d)
+{
+	if (is_unsafe_smbus == 0) {
+		is_unsafe_smbus = 1;
+		printk(KERN_INFO "%s machine detected. Disabling SMBus accesses.\n", d->ident);
+	}
+	return 0;
+}
+
 /*
  *	Simple "print if true" callback
  */
@@ -728,6 +742,15 @@
 	 */
 	 
 	{ set_apm_ints, "IBM", {	/* Allow interrupts during suspend on IBM laptops */
+			MATCH(DMI_SYS_VENDOR, "IBM"),
+			NO_MATCH, NO_MATCH, NO_MATCH
+			} },
+
+	/*
+	 *	SMBus / sensors settings
+	 */
+	 
+	{ disable_smbus, "IBM", {
 			MATCH(DMI_SYS_VENDOR, "IBM"),
 			NO_MATCH, NO_MATCH, NO_MATCH
 			} },
diff -Nru a/arch/i386/kernel/init_task.c b/arch/i386/kernel/init_task.c
--- a/arch/i386/kernel/init_task.c	Mon Sep  9 10:36:17 2002
+++ b/arch/i386/kernel/init_task.c	Mon Sep  9 10:36:17 2002
@@ -10,7 +10,7 @@
 
 static struct fs_struct init_fs = INIT_FS;
 static struct files_struct init_files = INIT_FILES;
-static struct signal_struct init_signals = INIT_SIGNALS;
+static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
 struct mm_struct init_mm = INIT_MM(init_mm);
 
 /*
diff -Nru a/arch/i386/kernel/irq.c b/arch/i386/kernel/irq.c
--- a/arch/i386/kernel/irq.c	Mon Sep  9 10:35:56 2002
+++ b/arch/i386/kernel/irq.c	Mon Sep  9 10:35:56 2002
@@ -380,8 +380,9 @@
 			break;
 		desc->status &= ~IRQ_PENDING;
 	}
-out:
 	desc->status &= ~IRQ_INPROGRESS;
+
+out:
 	/*
 	 * The ->end() handler has to deal with interrupts which got
 	 * disabled while the handler was running.
@@ -768,7 +769,7 @@
 
 	if (!shared) {
 		desc->depth = 0;
-		desc->status &= ~(IRQ_DISABLED | IRQ_AUTODETECT | IRQ_WAITING);
+		desc->status &= ~(IRQ_DISABLED | IRQ_AUTODETECT | IRQ_WAITING | IRQ_INPROGRESS);
 		desc->handler->startup(irq);
 	}
 	spin_unlock_irqrestore(&desc->lock,flags);
diff -Nru a/arch/i386/kernel/numaq.c b/arch/i386/kernel/numaq.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/arch/i386/kernel/numaq.c	Mon Sep  9 10:36:18 2002
@@ -0,0 +1,143 @@
+/*
+ * Written by: Patricia Gaughen, IBM Corporation
+ *
+ * Copyright (C) 2002, IBM Corp.
+ *
+ * All rights reserved.          
+ *
+ * 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.
+ *
+ * This program 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, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Send feedback to <gone@us.ibm.com>
+ */
+
+#include <linux/config.h>
+#include <linux/mm.h>
+#include <linux/bootmem.h>
+#include <linux/mmzone.h>
+#include <asm/numaq.h>
+
+u64 nodes_mem_start[MAX_NUMNODES];
+u64 nodes_mem_size[MAX_NUMNODES];
+
+/*
+ * Function: smp_dump_qct()
+ *
+ * Description: gets memory layout from the quad config table.  This
+ * function also increments numnodes with the number of nodes (quads)
+ * present.
+ */
+static void __init smp_dump_qct(void)
+{
+	int node;
+	struct eachquadmem *eq;
+	struct sys_cfg_data *scd =
+		(struct sys_cfg_data *)__va(SYS_CFG_DATA_PRIV_ADDR);
+
+#define	MB_TO_B(addr) ((addr) << 20)
+	numnodes = 0;
+	for(node = 0; node < MAX_NUMNODES; node++) {
+		if(scd->quads_present31_0 & (1 << node)) {
+			numnodes++;
+			eq = &scd->eq[node];
+			/* Convert to bytes */
+			nodes_mem_start[node] = MB_TO_B((u64)eq->hi_shrd_mem_start -
+							(u64)eq->priv_mem_size);
+			nodes_mem_size[node] = MB_TO_B((u64)eq->hi_shrd_mem_size +
+						       (u64)eq->priv_mem_size);
+		}
+	}
+}
+
+/*
+ * -----------------------------------------
+ *
+ * functions related to physnode_map
+ *
+ * -----------------------------------------
+ */
+/*
+ * physnode_map keeps track of the physical memory layout of the
+ * numaq nodes on a 256Mb break (each element of the array will
+ * represent 256Mb of memory and will be marked by the node id.  so,
+ * if the first gig is on node 0, and the second gig is on node 1
+ * physnode_map will contain:
+ * physnode_map[0-3] = 0;
+ * physnode_map[4-7] = 1;
+ * physnode_map[8- ] = -1;
+ */
+int physnode_map[MAX_ELEMENTS] = { [0 ... (MAX_ELEMENTS - 1)] = -1};
+
+#define MB_TO_ELEMENT(x) (x >> ELEMENT_REPRESENTS)
+#define PA_TO_MB(pa) (pa >> 20) 	/* assumption: a physical address is in bytes */
+
+int numaqpa_to_nid(u64 pa)
+{
+	int nid;
+	
+	nid = physnode_map[MB_TO_ELEMENT(PA_TO_MB(pa))];
+
+	/* the physical address passed in is not in the map for the system */
+	if (nid == -1)
+		BUG();
+
+	return nid;
+}
+
+int numaqpfn_to_nid(unsigned long pfn)
+{
+	return numaqpa_to_nid(((u64)pfn) << PAGE_SHIFT);
+}
+
+/*
+ * for each node mark the regions
+ *        TOPOFMEM = hi_shrd_mem_start + hi_shrd_mem_size
+ *
+ * need to be very careful to not mark 1024+ as belonging
+ * to node 0. will want 1027 to show as belonging to node 1
+ * example:
+ *  TOPOFMEM = 1024
+ * 1024 >> 8 = 4 (subtract 1 for starting at 0]
+ * tmpvar = TOPOFMEM - 256 = 768
+ * 1024 >> 8 = 4 (subtract 1 for starting at 0]
+ * 
+ */
+static void __init initialize_physnode_map(void)
+{
+	int nid;
+	unsigned int topofmem, cur;
+	struct eachquadmem *eq;
+ 	struct sys_cfg_data *scd =
+		(struct sys_cfg_data *)__va(SYS_CFG_DATA_PRIV_ADDR);
+
+	
+	for(nid = 0; nid < numnodes; nid++) {
+		if(scd->quads_present31_0 & (1 << nid)) {
+			eq = &scd->eq[nid];
+			cur = eq->hi_shrd_mem_start;
+			topofmem = eq->hi_shrd_mem_start + eq->hi_shrd_mem_size;
+			while (cur < topofmem) {
+				physnode_map[cur >> 8] = nid;
+				cur += (ELEMENT_REPRESENTS - 1);
+			}
+		}
+	}
+}
+
+void __init get_memcfg_numaq(void)
+{
+	smp_dump_qct();
+	initialize_physnode_map();
+}
diff -Nru a/arch/i386/kernel/setup.c b/arch/i386/kernel/setup.c
--- a/arch/i386/kernel/setup.c	Mon Sep  9 10:36:11 2002
+++ b/arch/i386/kernel/setup.c	Mon Sep  9 10:36:11 2002
@@ -36,6 +36,7 @@
 #include <linux/highmem.h>
 #include <asm/e820.h>
 #include <asm/mpspec.h>
+#include <asm/setup.h>
 
 /*
  * Machine setup..
@@ -85,35 +86,10 @@
 
 unsigned long saved_videomode;
 
-/*
- * This is set up by the setup-routine at boot-time
- */
-#define PARAM	((unsigned char *)empty_zero_page)
-#define SCREEN_INFO (*(struct screen_info *) (PARAM+0))
-#define EXT_MEM_K (*(unsigned short *) (PARAM+2))
-#define ALT_MEM_K (*(unsigned long *) (PARAM+0x1e0))
-#define E820_MAP_NR (*(char*) (PARAM+E820NR))
-#define E820_MAP    ((struct e820entry *) (PARAM+E820MAP))
-#define APM_BIOS_INFO (*(struct apm_bios_info *) (PARAM+0x40))
-#define DRIVE_INFO (*(struct drive_info_struct *) (PARAM+0x80))
-#define SYS_DESC_TABLE (*(struct sys_desc_table_struct*)(PARAM+0xa0))
-#define MOUNT_ROOT_RDONLY (*(unsigned short *) (PARAM+0x1F2))
-#define RAMDISK_FLAGS (*(unsigned short *) (PARAM+0x1F8))
-#define VIDEO_MODE (*(unsigned short *) (PARAM+0x1FA))
-#define ORIG_ROOT_DEV (*(unsigned short *) (PARAM+0x1FC))
-#define AUX_DEVICE_INFO (*(unsigned char *) (PARAM+0x1FF))
-#define LOADER_TYPE (*(unsigned char *) (PARAM+0x210))
-#define KERNEL_START (*(unsigned long *) (PARAM+0x214))
-#define INITRD_START (*(unsigned long *) (PARAM+0x218))
-#define INITRD_SIZE (*(unsigned long *) (PARAM+0x21c))
-#define COMMAND_LINE ((char *) (PARAM+2048))
-#define COMMAND_LINE_SIZE 256
-
 #define RAMDISK_IMAGE_START_MASK  	0x07FF
 #define RAMDISK_PROMPT_FLAG		0x8000
 #define RAMDISK_LOAD_FLAG		0x4000	
 
-
 static char command_line[COMMAND_LINE_SIZE];
        char saved_command_line[COMMAND_LINE_SIZE];
 
@@ -599,72 +575,13 @@
 	}
 }
 
-void __init setup_arch(char **cmdline_p)
-{
-	unsigned long bootmap_size, low_mem_size;
-	unsigned long start_pfn, max_low_pfn;
-	int i;
-
-	early_cpu_init();
-
-#ifdef CONFIG_VISWS
-	visws_get_board_type_and_rev();
-#endif
-
- 	ROOT_DEV = ORIG_ROOT_DEV;
- 	drive_info = DRIVE_INFO;
- 	screen_info = SCREEN_INFO;
-	apm_info.bios = APM_BIOS_INFO;
-	saved_videomode = VIDEO_MODE;
-	printk("Video mode to be used for restore is %lx\n", saved_videomode);
-	if( SYS_DESC_TABLE.length != 0 ) {
-		MCA_bus = SYS_DESC_TABLE.table[3] &0x2;
-		machine_id = SYS_DESC_TABLE.table[0];
-		machine_submodel_id = SYS_DESC_TABLE.table[1];
-		BIOS_revision = SYS_DESC_TABLE.table[2];
-	}
-	aux_device_present = AUX_DEVICE_INFO;
-
-#ifdef CONFIG_BLK_DEV_RAM
-	rd_image_start = RAMDISK_FLAGS & RAMDISK_IMAGE_START_MASK;
-	rd_prompt = ((RAMDISK_FLAGS & RAMDISK_PROMPT_FLAG) != 0);
-	rd_doload = ((RAMDISK_FLAGS & RAMDISK_LOAD_FLAG) != 0);
-#endif
-	setup_memory_region();
-
-	if (!MOUNT_ROOT_RDONLY)
-		root_mountflags &= ~MS_RDONLY;
-	init_mm.start_code = (unsigned long) &_text;
-	init_mm.end_code = (unsigned long) &_etext;
-	init_mm.end_data = (unsigned long) &_edata;
-	init_mm.brk = (unsigned long) &_end;
-
-	code_resource.start = virt_to_phys(&_text);
-	code_resource.end = virt_to_phys(&_etext)-1;
-	data_resource.start = virt_to_phys(&_etext);
-	data_resource.end = virt_to_phys(&_edata)-1;
-
-	parse_cmdline_early(cmdline_p);
-
-#define PFN_UP(x)	(((x) + PAGE_SIZE-1) >> PAGE_SHIFT)
-#define PFN_DOWN(x)	((x) >> PAGE_SHIFT)
-#define PFN_PHYS(x)	((x) << PAGE_SHIFT)
-
 /*
- * Reserved space for vmalloc and iomap - defined in asm/page.h
+ * Find the highest page frame number we have available
  */
-#define MAXMEM_PFN	PFN_DOWN(MAXMEM)
-#define MAX_NONPAE_PFN	(1 << 20)
-
-	/*
-	 * partially used pages are not usable - thus
-	 * we are rounding upwards:
-	 */
-	start_pfn = PFN_UP(__pa(&_end));
+void __init find_max_pfn(void)
+{
+	int i;
 
-	/*
-	 * Find the highest page frame number we have available
-	 */
 	max_pfn = 0;
 	for (i = 0; i < e820.nr_map; i++) {
 		unsigned long start, end;
@@ -678,10 +595,15 @@
 		if (end > max_pfn)
 			max_pfn = end;
 	}
+}
+
+/*
+ * Determine low and high memory ranges:
+ */
+unsigned long __init find_max_low_pfn(void)
+{
+	unsigned long max_low_pfn;
 
-	/*
-	 * Determine low and high memory ranges:
-	 */
 	max_low_pfn = max_pfn;
 	if (max_low_pfn > MAXMEM_PFN) {
 		if (highmem_pages == -1)
@@ -731,28 +653,20 @@
 			printk(KERN_ERR "ignoring highmem size on non-highmem kernel!\n");
 #endif
 	}
+	return max_low_pfn;
+}
 
-#ifdef CONFIG_HIGHMEM
-	highstart_pfn = highend_pfn = max_pfn;
-	if (max_pfn > max_low_pfn) {
-		highstart_pfn = max_low_pfn;
-	}
-	printk(KERN_NOTICE "%ldMB HIGHMEM available.\n",
-		pages_to_mb(highend_pfn - highstart_pfn));
-#endif
-	printk(KERN_NOTICE "%ldMB LOWMEM available.\n",
-			pages_to_mb(max_low_pfn));
-	/*
-	 * Initialize the boot-time allocator (with low memory only):
-	 */
-	bootmap_size = init_bootmem(start_pfn, max_low_pfn);
+#ifndef CONFIG_DISCONTIGMEM
+/*
+ * Register fully available low RAM pages with the bootmem allocator.
+ */
+static void __init register_bootmem_low_pages(unsigned long max_low_pfn)
+{
+	int i;
 
-	/*
-	 * Register fully available low RAM pages with the bootmem allocator.
-	 */
 	for (i = 0; i < e820.nr_map; i++) {
 		unsigned long curr_pfn, last_pfn, size;
- 		/*
+		/*
 		 * Reserve usable low memory
 		 */
 		if (e820.map[i].type != E820_RAM)
@@ -781,6 +695,39 @@
 		size = last_pfn - curr_pfn;
 		free_bootmem(PFN_PHYS(curr_pfn), PFN_PHYS(size));
 	}
+}
+
+static unsigned long __init setup_memory(void)
+{
+	unsigned long bootmap_size, start_pfn, max_low_pfn;
+
+	/*
+	 * partially used pages are not usable - thus
+	 * we are rounding upwards:
+	 */
+	start_pfn = PFN_UP(__pa(&_end));
+
+	find_max_pfn();
+
+	max_low_pfn = find_max_low_pfn();
+
+#ifdef CONFIG_HIGHMEM
+	highstart_pfn = highend_pfn = max_pfn;
+	if (max_pfn > max_low_pfn) {
+		highstart_pfn = max_low_pfn;
+	}
+	printk(KERN_NOTICE "%ldMB HIGHMEM available.\n",
+		pages_to_mb(highend_pfn - highstart_pfn));
+#endif
+	printk(KERN_NOTICE "%ldMB LOWMEM available.\n",
+			pages_to_mb(max_low_pfn));
+	/*
+	 * Initialize the boot-time allocator (with low memory only):
+	 */
+	bootmap_size = init_bootmem(start_pfn, max_low_pfn);
+
+	register_bootmem_low_pages(max_low_pfn);
+
 	/*
 	 * Reserve the bootmem bitmap itself as well. We do this in two
 	 * steps (first step was init_bootmem()) because this catches
@@ -816,6 +763,7 @@
 	 */
 	find_smp_config();
 #endif
+
 #ifdef CONFIG_BLK_DEV_INITRD
 	if (LOADER_TYPE && INITRD_START) {
 		if (INITRD_START + INITRD_SIZE <= (max_low_pfn << PAGE_SHIFT)) {
@@ -833,33 +781,21 @@
 		}
 	}
 #endif
+	return max_low_pfn;
+}
+#else
+extern unsigned long setup_memory(void);
+#endif /* !CONFIG_DISCONTIGMEM */
 
-	/*
-	 * NOTE: before this point _nobody_ is allowed to allocate
-	 * any memory using the bootmem allocator.
-	 */
-
-#ifdef CONFIG_SMP
-	smp_alloc_memory(); /* AP processor realmode stacks in low memory*/
-#endif
-	paging_init();
-#ifdef CONFIG_ACPI_BOOT
-	/*
-	 * Parse the ACPI tables for possible boot-time SMP configuration.
-	 */
-	if (!acpi_disabled)
-		acpi_boot_init(*cmdline_p);
-#endif
-#ifdef CONFIG_X86_LOCAL_APIC
-	if (smp_found_config)
-		get_smp_config();
-#endif
-
+/*
+ * Request address space for all standard RAM and ROM resources
+ * and also for regions reported as reserved by the e820.
+ */
+static void __init register_memory(unsigned long max_low_pfn)
+{
+	unsigned long low_mem_size;
+	int i;
 
-	/*
-	 * Request address space for all standard RAM and ROM resources
-	 * and also for regions reported as reserved by the e820.
-	 */
 	probe_roms();
 	for (i = 0; i < e820.nr_map; i++) {
 		struct resource *res;
@@ -896,6 +832,77 @@
 	low_mem_size = ((max_low_pfn << PAGE_SHIFT) + 0xfffff) & ~0xfffff;
 	if (low_mem_size > pci_mem_start)
 		pci_mem_start = low_mem_size;
+}
+
+void __init setup_arch(char **cmdline_p)
+{
+	unsigned long max_low_pfn;
+
+	early_cpu_init();
+
+#ifdef CONFIG_VISWS
+	visws_get_board_type_and_rev();
+#endif
+
+ 	ROOT_DEV = ORIG_ROOT_DEV;
+ 	drive_info = DRIVE_INFO;
+ 	screen_info = SCREEN_INFO;
+	apm_info.bios = APM_BIOS_INFO;
+	saved_videomode = VIDEO_MODE;
+	printk("Video mode to be used for restore is %lx\n", saved_videomode);
+	if( SYS_DESC_TABLE.length != 0 ) {
+		MCA_bus = SYS_DESC_TABLE.table[3] &0x2;
+		machine_id = SYS_DESC_TABLE.table[0];
+		machine_submodel_id = SYS_DESC_TABLE.table[1];
+		BIOS_revision = SYS_DESC_TABLE.table[2];
+	}
+	aux_device_present = AUX_DEVICE_INFO;
+
+#ifdef CONFIG_BLK_DEV_RAM
+	rd_image_start = RAMDISK_FLAGS & RAMDISK_IMAGE_START_MASK;
+	rd_prompt = ((RAMDISK_FLAGS & RAMDISK_PROMPT_FLAG) != 0);
+	rd_doload = ((RAMDISK_FLAGS & RAMDISK_LOAD_FLAG) != 0);
+#endif
+	setup_memory_region();
+
+	if (!MOUNT_ROOT_RDONLY)
+		root_mountflags &= ~MS_RDONLY;
+	init_mm.start_code = (unsigned long) &_text;
+	init_mm.end_code = (unsigned long) &_etext;
+	init_mm.end_data = (unsigned long) &_edata;
+	init_mm.brk = (unsigned long) &_end;
+
+	code_resource.start = virt_to_phys(&_text);
+	code_resource.end = virt_to_phys(&_etext)-1;
+	data_resource.start = virt_to_phys(&_etext);
+	data_resource.end = virt_to_phys(&_edata)-1;
+
+	parse_cmdline_early(cmdline_p);
+
+	max_low_pfn = setup_memory();
+
+	/*
+	 * NOTE: before this point _nobody_ is allowed to allocate
+	 * any memory using the bootmem allocator.
+	 */
+
+#ifdef CONFIG_SMP
+	smp_alloc_memory(); /* AP processor realmode stacks in low memory*/
+#endif
+	paging_init();
+#ifdef CONFIG_ACPI_BOOT
+	/*
+	 * Parse the ACPI tables for possible boot-time SMP configuration.
+	 */
+	if (!acpi_disabled)
+		acpi_boot_init(*cmdline_p);
+#endif
+#ifdef CONFIG_X86_LOCAL_APIC
+	if (smp_found_config)
+		get_smp_config();
+#endif
+
+	register_memory(max_low_pfn);
 
 #ifdef CONFIG_VT
 #if defined(CONFIG_VGA_CONSOLE)
diff -Nru a/arch/i386/mm/Makefile b/arch/i386/mm/Makefile
--- a/arch/i386/mm/Makefile	Mon Sep  9 10:36:01 2002
+++ b/arch/i386/mm/Makefile	Mon Sep  9 10:36:01 2002
@@ -10,6 +10,7 @@
 O_TARGET := mm.o
 
 obj-y	 := init.o pgtable.o fault.o ioremap.o extable.o pageattr.o 
+obj-$(CONFIG_DISCONTIGMEM)	+= discontig.o
 export-objs := pageattr.o
 
 include $(TOPDIR)/Rules.make
diff -Nru a/arch/i386/mm/discontig.c b/arch/i386/mm/discontig.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/arch/i386/mm/discontig.c	Mon Sep  9 10:36:18 2002
@@ -0,0 +1,301 @@
+/*
+ * Written by: Patricia Gaughen, IBM Corporation
+ *
+ * Copyright (C) 2002, IBM Corp.
+ *
+ * All rights reserved.          
+ *
+ * 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.
+ *
+ * This program 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, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Send feedback to <gone@us.ibm.com>
+ */
+
+#include <linux/config.h>
+#include <linux/mm.h>
+#include <linux/bootmem.h>
+#include <linux/mmzone.h>
+#include <linux/highmem.h>
+#ifdef CONFIG_BLK_DEV_RAM
+#include <linux/blk.h>
+#endif
+#include <asm/e820.h>
+#include <asm/setup.h>
+
+struct pfns {
+	unsigned long start_pfn;
+	unsigned long max_pfn;
+};
+
+struct plat_pglist_data *plat_node_data[MAX_NUMNODES];
+bootmem_data_t plat_node_bdata;
+struct pfns plat_node_bootpfns[MAX_NUMNODES];
+
+extern unsigned long find_max_low_pfn(void);
+extern void find_max_pfn(void);
+extern void one_highpage_init(struct page *, int, int);
+
+extern u64 nodes_mem_start[], nodes_mem_size[];
+extern struct e820map e820;
+extern char _end;
+extern unsigned long highend_pfn, highstart_pfn;
+extern unsigned long max_low_pfn;
+extern unsigned long totalram_pages;
+extern unsigned long totalhigh_pages;
+
+/*
+ * Find the highest page frame number we have available for the node
+ */
+static void __init find_max_pfn_node(int nid)
+{
+	unsigned long node_datasz;
+	unsigned long start, end;
+
+	start = plat_node_bootpfns[nid].start_pfn = PFN_UP(nodes_mem_start[nid]);
+	end = PFN_DOWN(nodes_mem_start[nid]) + PFN_DOWN(nodes_mem_size[nid]);
+
+	if (start >= end) {
+		BUG();
+	}
+	if (end > max_pfn) {
+		end = max_pfn;
+	}
+	plat_node_bootpfns[nid].max_pfn = end;
+
+	node_datasz = PFN_UP(sizeof(struct plat_pglist_data));
+	PLAT_NODE_DATA(nid) = (struct plat_pglist_data *)(__va(min_low_pfn << PAGE_SHIFT));
+	min_low_pfn += node_datasz;
+}
+
+/*
+ * Register fully available low RAM pages with the bootmem allocator.
+ */
+static void __init register_bootmem_low_pages(unsigned long system_max_low_pfn)
+{
+	int i;
+
+	for (i = 0; i < e820.nr_map; i++) {
+		unsigned long curr_pfn, last_pfn, size;
+		/*
+		 * Reserve usable low memory
+		 */
+		if (e820.map[i].type != E820_RAM)
+			continue;
+		/*
+		 * We are rounding up the start address of usable memory:
+		 */
+		curr_pfn = PFN_UP(e820.map[i].addr);
+		if (curr_pfn >= system_max_low_pfn)
+			continue;
+		/*
+		 * ... and at the end of the usable range downwards:
+		 */
+		last_pfn = PFN_DOWN(e820.map[i].addr + e820.map[i].size);
+
+		if (last_pfn > system_max_low_pfn)
+			last_pfn = system_max_low_pfn;
+
+		/*
+		 * .. finally, did all the rounding and playing
+		 * around just make the area go away?
+		 */
+		if (last_pfn <= curr_pfn)
+			continue;
+
+		size = last_pfn - curr_pfn;
+		free_bootmem_node(NODE_DATA(0), PFN_PHYS(curr_pfn), PFN_PHYS(size));
+	}
+}
+
+unsigned long __init setup_memory(void)
+{
+	int nid;
+	unsigned long bootmap_size, system_start_pfn, system_max_low_pfn;
+
+	get_memcfg_numa();
+
+	/*
+	 * partially used pages are not usable - thus
+	 * we are rounding upwards:
+	 */
+	system_start_pfn = min_low_pfn = PFN_UP(__pa(&_end));
+
+	find_max_pfn();
+	system_max_low_pfn = max_low_pfn = find_max_low_pfn();
+
+#ifdef CONFIG_HIGHMEM
+		highstart_pfn = highend_pfn = max_pfn;
+		if (max_pfn > system_max_low_pfn) {
+			highstart_pfn = system_max_low_pfn;
+		}
+		printk(KERN_NOTICE "%ldMB HIGHMEM available.\n",
+		       pages_to_mb(highend_pfn - highstart_pfn));
+#endif
+	printk(KERN_NOTICE "%ldMB LOWMEM available.\n",
+			pages_to_mb(system_max_low_pfn));
+	
+	for (nid = 0; nid < numnodes; nid++)
+	{	
+		find_max_pfn_node(nid);
+
+	}
+
+	NODE_DATA(0)->bdata = &plat_node_bdata;
+
+	/*
+	 * Initialize the boot-time allocator (with low memory only):
+	 */
+	bootmap_size = init_bootmem_node(NODE_DATA(0), min_low_pfn, 0, system_max_low_pfn);
+
+	register_bootmem_low_pages(system_max_low_pfn);
+
+	/*
+	 * Reserve the bootmem bitmap itself as well. We do this in two
+	 * steps (first step was init_bootmem()) because this catches
+	 * the (very unlikely) case of us accidentally initializing the
+	 * bootmem allocator with an invalid RAM area.
+	 */
+	reserve_bootmem_node(NODE_DATA(0), HIGH_MEMORY, (PFN_PHYS(min_low_pfn) +
+		 bootmap_size + PAGE_SIZE-1) - (HIGH_MEMORY));
+
+	/*
+	 * reserve physical page 0 - it's a special BIOS page on many boxes,
+	 * enabling clean reboots, SMP operation, laptop functions.
+	 */
+	reserve_bootmem_node(NODE_DATA(0), 0, PAGE_SIZE);
+
+	/*
+	 * But first pinch a few for the stack/trampoline stuff
+	 * FIXME: Don't need the extra page at 4K, but need to fix
+	 * trampoline before removing it. (see the GDT stuff)
+	 */
+	reserve_bootmem_node(NODE_DATA(0), PAGE_SIZE, PAGE_SIZE);
+
+#ifdef CONFIG_ACPI_SLEEP
+	/*
+	 * Reserve low memory region for sleep support.
+	 */
+	acpi_reserve_bootmem();
+#endif
+
+	/*
+	 * Find and reserve possible boot-time SMP configuration:
+	 */
+	find_smp_config();
+
+	/*insert other nodes into pgdat_list*/
+	for (nid = 1; nid < numnodes; nid++){       
+		NODE_DATA(nid)->pgdat_next = pgdat_list;
+		pgdat_list = NODE_DATA(nid);
+	}
+       
+
+#ifdef CONFIG_BLK_DEV_INITRD
+	if (LOADER_TYPE && INITRD_START) {
+		if (INITRD_START + INITRD_SIZE <= (system_max_low_pfn << PAGE_SHIFT)) {
+			reserve_bootmem_node(NODE_DATA(0), INITRD_START, INITRD_SIZE);
+			initrd_start =
+				INITRD_START ? INITRD_START + PAGE_OFFSET : 0;
+			initrd_end = initrd_start+INITRD_SIZE;
+		}
+		else {
+			printk(KERN_ERR "initrd extends beyond end of memory "
+			    "(0x%08lx > 0x%08lx)\ndisabling initrd\n",
+			    INITRD_START + INITRD_SIZE,
+			    system_max_low_pfn << PAGE_SHIFT);
+			initrd_start = 0;
+		}
+	}
+#endif
+	return system_max_low_pfn;
+}
+
+void __init zone_sizes_init(void)
+{
+	int nid;
+
+	for (nid = 0; nid < numnodes; nid++) {
+		unsigned long zones_size[MAX_NR_ZONES] = {0, 0, 0};
+		unsigned int max_dma;
+
+		unsigned long low = max_low_pfn;
+		unsigned long high = plat_node_bootpfns[nid].max_pfn;
+		unsigned long start = plat_node_bootpfns[nid].start_pfn;
+		
+		max_dma = virt_to_phys((char *)MAX_DMA_ADDRESS) >> PAGE_SHIFT;
+
+		if (start > low) {
+#ifdef CONFIG_HIGHMEM
+		  zones_size[ZONE_HIGHMEM] = high - start;
+#endif
+		} else {
+			if (low < max_dma)
+				zones_size[ZONE_DMA] = low;
+			else {
+				zones_size[ZONE_DMA] = max_dma;
+				zones_size[ZONE_NORMAL] = low - max_dma;
+#ifdef CONFIG_HIGHMEM
+				zones_size[ZONE_HIGHMEM] = high - low;
+#endif
+			}
+		}
+		free_area_init_node(nid, NODE_DATA(nid), 0, zones_size, start, 0);
+	}
+	return;
+}
+
+void __init set_highmem_pages_init(int bad_ppro) 
+{
+#ifdef CONFIG_HIGHMEM
+	int nid;
+
+	for (nid = 0; nid < numnodes; nid++) {
+		unsigned long node_pfn, node_high_size, zone_start_pfn;
+		struct page * zone_mem_map;
+		
+		node_high_size = NODE_DATA(nid)->node_zones[ZONE_HIGHMEM].size;
+		zone_mem_map = NODE_DATA(nid)->node_zones[ZONE_HIGHMEM].zone_mem_map;
+		zone_start_pfn = NODE_DATA(nid)->node_zones[ZONE_HIGHMEM].zone_start_pfn;
+
+		printk("Initializing highpages for node %d\n", nid);
+		for (node_pfn = 0; node_pfn < node_high_size; node_pfn++) {
+			one_highpage_init((struct page *)(zone_mem_map + node_pfn),
+					  zone_start_pfn + node_pfn, bad_ppro);
+		}
+	}
+	totalram_pages += totalhigh_pages;
+#endif
+}
+
+void __init set_max_mapnr_init(void)
+{
+#ifdef CONFIG_HIGHMEM
+	unsigned long lmax_mapnr;
+	int nid;
+	
+	highmem_start_page = mem_map + NODE_DATA(0)->node_zones[ZONE_HIGHMEM].zone_start_mapnr;
+	num_physpages = highend_pfn;
+
+	for (nid = 0; nid < numnodes; nid++) {
+		lmax_mapnr = PLAT_NODE_DATA_STARTNR(nid) + PLAT_NODE_DATA_SIZE(nid);
+		if (lmax_mapnr > max_mapnr) {
+			max_mapnr = lmax_mapnr;
+		}
+	}
+	
+#else
+	max_mapnr = num_physpages = max_low_pfn;
+#endif
+}
diff -Nru a/arch/i386/mm/init.c b/arch/i386/mm/init.c
--- a/arch/i386/mm/init.c	Mon Sep  9 10:36:01 2002
+++ b/arch/i386/mm/init.c	Mon Sep  9 10:36:01 2002
@@ -213,29 +213,34 @@
 	pkmap_page_table = pte;	
 }
 
+void __init one_highpage_init(struct page *page, int pfn, int bad_ppro)
+{
+	if (!page_is_ram(pfn)) {
+		SetPageReserved(page);
+		return;
+	}
+	if (bad_ppro && page_kills_ppro(pfn)) {
+		SetPageReserved(page);
+		return;
+	}
+	ClearPageReserved(page);
+	set_bit(PG_highmem, &page->flags);
+	atomic_set(&page->count, 1);
+	__free_page(page);
+	totalhigh_pages++;
+}
+
+#ifndef CONFIG_DISCONTIGMEM
 void __init set_highmem_pages_init(int bad_ppro) 
 {
 	int pfn;
-	for (pfn = highstart_pfn; pfn < highend_pfn; pfn++) {
-		struct page *page = mem_map + pfn;
-
-		if (!page_is_ram(pfn)) {
-			SetPageReserved(page);
-			continue;
-		}
-		if (bad_ppro && page_kills_ppro(pfn))
-		{
-			SetPageReserved(page);
-			continue;
-		}
-		ClearPageReserved(page);
-		set_bit(PG_highmem, &page->flags);
-		atomic_set(&page->count, 1);
-		__free_page(page);
-		totalhigh_pages++;
-	}
+	for (pfn = highstart_pfn; pfn < highend_pfn; pfn++)
+		one_highpage_init(pfn_to_page(pfn), pfn, bad_ppro);
 	totalram_pages += totalhigh_pages;
 }
+#else
+extern void set_highmem_pages_init(int);
+#endif /* !CONFIG_DISCONTIGMEM */
 
 #else
 #define kmap_init() do { } while (0)
@@ -309,6 +314,7 @@
 	flush_tlb_all();
 }
 
+#ifndef CONFIG_DISCONTIGMEM
 void __init zone_sizes_init(void)
 {
 	unsigned long zones_size[MAX_NR_ZONES] = {0, 0, 0};
@@ -329,6 +335,9 @@
 	}
 	free_area_init(zones_size);	
 }
+#else
+extern void zone_sizes_init(void);
+#endif /* !CONFIG_DISCONTIGMEM */
 
 /*
  * paging_init() sets up the page tables - note that the first 8MB are
@@ -405,7 +414,23 @@
 		printk("Ok.\n");
 	}
 }
-	
+
+#ifndef CONFIG_DISCONTIGMEM
+static void __init set_max_mapnr_init(void)
+{
+#ifdef CONFIG_HIGHMEM
+	highmem_start_page = pfn_to_page(highstart_pfn);
+	max_mapnr = num_physpages = highend_pfn;
+#else
+	max_mapnr = num_physpages = max_low_pfn;
+#endif
+}
+#define __free_all_bootmem() free_all_bootmem()
+#else
+#define __free_all_bootmem() free_all_bootmem_node(NODE_DATA(0))
+extern void set_max_mapnr_init(void);
+#endif /* !CONFIG_DISCONTIGMEM */
+
 void __init mem_init(void)
 {
 	extern int ppro_with_ram_bug(void);
@@ -418,26 +443,22 @@
 	
 	bad_ppro = ppro_with_ram_bug();
 
-#ifdef CONFIG_HIGHMEM
-	highmem_start_page = mem_map + highstart_pfn;
-	max_mapnr = num_physpages = highend_pfn;
-#else
-	max_mapnr = num_physpages = max_low_pfn;
-#endif
+	set_max_mapnr_init();
+
 	high_memory = (void *) __va(max_low_pfn * PAGE_SIZE);
 
 	/* clear the zero-page */
 	memset(empty_zero_page, 0, PAGE_SIZE);
 
 	/* this will put all low memory onto the freelists */
-	totalram_pages += free_all_bootmem();
+	totalram_pages += __free_all_bootmem();
 
 	reservedpages = 0;
 	for (tmp = 0; tmp < max_low_pfn; tmp++)
 		/*
 		 * Only count reserved RAM pages
 		 */
-		if (page_is_ram(tmp) && PageReserved(mem_map+tmp))
+		if (page_is_ram(tmp) && PageReserved(pfn_to_page(tmp)))
 			reservedpages++;
 
 	set_highmem_pages_init(bad_ppro);
diff -Nru a/arch/i386/mm/pgtable.c b/arch/i386/mm/pgtable.c
--- a/arch/i386/mm/pgtable.c	Mon Sep  9 10:36:18 2002
+++ b/arch/i386/mm/pgtable.c	Mon Sep  9 10:36:18 2002
@@ -22,24 +22,26 @@
 
 void show_mem(void)
 {
-	int i, total = 0, reserved = 0;
+	int pfn, total = 0, reserved = 0;
 	int shared = 0, cached = 0;
 	int highmem = 0;
+	struct page *page;
 
 	printk("Mem-info:\n");
 	show_free_areas();
 	printk("Free swap:       %6dkB\n",nr_swap_pages<<(PAGE_SHIFT-10));
-	i = max_mapnr;
-	while (i-- > 0) {
+	pfn = max_mapnr;
+	while (pfn-- > 0) {
+		page = pfn_to_page(pfn);
 		total++;
-		if (PageHighMem(mem_map+i))
+		if (PageHighMem(page))
 			highmem++;
-		if (PageReserved(mem_map+i))
+		if (PageReserved(page))
 			reserved++;
-		else if (PageSwapCache(mem_map+i))
+		else if (PageSwapCache(page))
 			cached++;
-		else if (page_count(mem_map+i))
-			shared += page_count(mem_map+i) - 1;
+		else if (page_count(page))
+			shared += page_count(page) - 1;
 	}
 	printk("%d pages of RAM\n", total);
 	printk("%d pages of HIGHMEM\n",highmem);
diff -Nru a/arch/i386/pci/fixup.c b/arch/i386/pci/fixup.c
--- a/arch/i386/pci/fixup.c	Mon Sep  9 10:35:59 2002
+++ b/arch/i386/pci/fixup.c	Mon Sep  9 10:36:01 2002
@@ -166,6 +166,22 @@
 	}
 }
 
+/*
+ * For some reasons Intel decided that certain parts of their
+ * 815, 845 and some other chipsets must look like PCI-to-PCI bridges
+ * while they are obviously not. The 82801 family (AA, AB, BAM/CAM,
+ * BA/CA/DB and E) PCI bridges are actually HUB-to-PCI ones, according
+ * to Intel terminology. These devices do forward all addresses from
+ * system to PCI bus no matter what are their window settings, so they are
+ * "transparent" (or subtractive decoding) from programmers point of view.
+ */
+static void __init pci_fixup_transparent_bridge(struct pci_dev *dev)
+{
+	if ((dev->class >> 8) == PCI_CLASS_BRIDGE_PCI &&
+	    (dev->device & 0xff00) == 0x2400)
+		dev->transparent = 1;
+}
+
 struct pci_fixup pcibios_fixups[] = {
 	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82451NX,	pci_fixup_i450nx },
 	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82454GX,	pci_fixup_i450gx },
@@ -183,5 +199,6 @@
 	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_8361,	        pci_fixup_via_northbridge_bug },
 	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_8367_0,	pci_fixup_via_northbridge_bug },
 	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_NCR,	PCI_DEVICE_ID_NCR_53C810,	pci_fixup_ncr53c810 },
+	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_INTEL,	PCI_ANY_ID,			pci_fixup_transparent_bridge },
 	{ 0 }
 };
diff -Nru a/arch/i386/vmlinux.lds b/arch/i386/vmlinux.lds
--- a/arch/i386/vmlinux.lds	Mon Sep  9 10:36:01 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,101 +0,0 @@
-/* ld script to make i386 Linux kernel
- * Written by Martin Mares <mj@atrey.karlin.mff.cuni.cz>;
- */
-OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
-OUTPUT_ARCH(i386)
-ENTRY(_start)
-jiffies = jiffies_64;
-SECTIONS
-{
-  . = 0xC0000000 + 0x100000;
-  _text = .;			/* Text and read-only data */
-  .text : {
-	*(.text)
-	*(.fixup)
-	*(.gnu.warning)
-	} = 0x9090
-
-  _etext = .;			/* End of text section */
-
-  .rodata : { *(.rodata) *(.rodata.*) }
-  .kstrtab : { *(.kstrtab) }
-
-  . = ALIGN(16);		/* Exception table */
-  __start___ex_table = .;
-  __ex_table : { *(__ex_table) }
-  __stop___ex_table = .;
-
-  __start___ksymtab = .;	/* Kernel symbol table */
-  __ksymtab : { *(__ksymtab) }
-  __stop___ksymtab = .;
-
-  .data : {			/* Data */
-	*(.data)
-	CONSTRUCTORS
-	}
-
-  _edata = .;			/* End of data section */
-
-  . = ALIGN(8192);		/* init_task */
-  .data.init_task : { *(.data.init_task) }
-
-  . = ALIGN(4096);		/* Init code and data */
-  __init_begin = .;
-  .text.init : { *(.text.init) }
-  .data.init : { *(.data.init) }
-  . = ALIGN(16);
-  __setup_start = .;
-  .setup.init : { *(.setup.init) }
-  __setup_end = .;
-  __initcall_start = .;
-  .initcall.init : {
-	*(.initcall1.init) 
-	*(.initcall2.init) 
-	*(.initcall3.init) 
-	*(.initcall4.init) 
-	*(.initcall5.init) 
-	*(.initcall6.init) 
-	*(.initcall7.init)
-  }
-  __initcall_end = .;
-  . = ALIGN(32);
-  __per_cpu_start = .;
-  .data.percpu  : { *(.data.percpu) }
-  __per_cpu_end = .;
-  . = ALIGN(4096);
-  __init_end = .;
-
-  . = ALIGN(4096);
-  __nosave_begin = .;
-  .data_nosave : { *(.data.nosave) }
-  . = ALIGN(4096);
-  __nosave_end = .;
-
-  . = ALIGN(4096);
-  .data.page_aligned : { *(.data.idt) }
-
-  . = ALIGN(32);
-  .data.cacheline_aligned : { *(.data.cacheline_aligned) }
-
-  __bss_start = .;		/* BSS */
-  .bss : {
-	*(.bss)
-	}
-  _end = . ;
-
-  /* Sections to be discarded */
-  /DISCARD/ : {
-	*(.text.exit)
-	*(.data.exit)
-	*(.exitcall.exit)
-	}
-
-  /* Stabs debugging sections.  */
-  .stab 0 : { *(.stab) }
-  .stabstr 0 : { *(.stabstr) }
-  .stab.excl 0 : { *(.stab.excl) }
-  .stab.exclstr 0 : { *(.stab.exclstr) }
-  .stab.index 0 : { *(.stab.index) }
-  .stab.indexstr 0 : { *(.stab.indexstr) }
-  .comment 0 : { *(.comment) }
-}
diff -Nru a/arch/i386/vmlinux.lds.S b/arch/i386/vmlinux.lds.S
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/arch/i386/vmlinux.lds.S	Mon Sep  9 10:36:01 2002
@@ -0,0 +1,101 @@
+/* ld script to make i386 Linux kernel
+ * Written by Martin Mares <mj@atrey.karlin.mff.cuni.cz>;
+ */
+OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
+OUTPUT_ARCH(i386)
+ENTRY(_start)
+jiffies = jiffies_64;
+SECTIONS
+{
+  . = 0xC0000000 + 0x100000;
+  _text = .;			/* Text and read-only data */
+  .text : {
+	*(.text)
+	*(.fixup)
+	*(.gnu.warning)
+	} = 0x9090
+
+  _etext = .;			/* End of text section */
+
+  .rodata : { *(.rodata) *(.rodata.*) }
+  .kstrtab : { *(.kstrtab) }
+
+  . = ALIGN(16);		/* Exception table */
+  __start___ex_table = .;
+  __ex_table : { *(__ex_table) }
+  __stop___ex_table = .;
+
+  __start___ksymtab = .;	/* Kernel symbol table */
+  __ksymtab : { *(__ksymtab) }
+  __stop___ksymtab = .;
+
+  .data : {			/* Data */
+	*(.data)
+	CONSTRUCTORS
+	}
+
+  _edata = .;			/* End of data section */
+
+  . = ALIGN(8192);		/* init_task */
+  .data.init_task : { *(.data.init_task) }
+
+  . = ALIGN(4096);		/* Init code and data */
+  __init_begin = .;
+  .text.init : { *(.text.init) }
+  .data.init : { *(.data.init) }
+  . = ALIGN(16);
+  __setup_start = .;
+  .setup.init : { *(.setup.init) }
+  __setup_end = .;
+  __initcall_start = .;
+  .initcall.init : {
+	*(.initcall1.init) 
+	*(.initcall2.init) 
+	*(.initcall3.init) 
+	*(.initcall4.init) 
+	*(.initcall5.init) 
+	*(.initcall6.init) 
+	*(.initcall7.init)
+  }
+  __initcall_end = .;
+  . = ALIGN(32);
+  __per_cpu_start = .;
+  .data.percpu  : { *(.data.percpu) }
+  __per_cpu_end = .;
+  . = ALIGN(4096);
+  __init_end = .;
+
+  . = ALIGN(4096);
+  __nosave_begin = .;
+  .data_nosave : { *(.data.nosave) }
+  . = ALIGN(4096);
+  __nosave_end = .;
+
+  . = ALIGN(4096);
+  .data.page_aligned : { *(.data.idt) }
+
+  . = ALIGN(32);
+  .data.cacheline_aligned : { *(.data.cacheline_aligned) }
+
+  __bss_start = .;		/* BSS */
+  .bss : {
+	*(.bss)
+	}
+  _end = . ;
+
+  /* Sections to be discarded */
+  /DISCARD/ : {
+	*(.text.exit)
+	*(.data.exit)
+	*(.exitcall.exit)
+	}
+
+  /* Stabs debugging sections.  */
+  .stab 0 : { *(.stab) }
+  .stabstr 0 : { *(.stabstr) }
+  .stab.excl 0 : { *(.stab.excl) }
+  .stab.exclstr 0 : { *(.stab.exclstr) }
+  .stab.index 0 : { *(.stab.index) }
+  .stab.indexstr 0 : { *(.stab.indexstr) }
+  .comment 0 : { *(.comment) }
+}
diff -Nru a/arch/ia64/config.in b/arch/ia64/config.in
--- a/arch/ia64/config.in	Mon Sep  9 10:36:18 2002
+++ b/arch/ia64/config.in	Mon Sep  9 10:36:18 2002
@@ -76,10 +76,6 @@
 	bool '  Enable SGI Medusa Simulator Support' CONFIG_IA64_SGI_SN_SIM
 	bool '  Enable autotest (llsc). Option to run cache test instead of booting' \
 			CONFIG_IA64_SGI_AUTOTEST
-	define_bool CONFIG_DEVFS_FS y
-	if [ "$CONFIG_DEVFS_FS" = "y" ]; then
-	  bool '    Enable DEVFS Debug Code' CONFIG_DEVFS_DEBUG
-	fi
 	bool '  Enable protocol mode for the L1 console' CONFIG_SERIAL_SGI_L1_PROTOCOL
 	define_bool CONFIG_DISCONTIGMEM y
 	define_bool CONFIG_IA64_MCA y
diff -Nru a/arch/m68k/hp300/Makefile b/arch/m68k/hp300/Makefile
--- a/arch/m68k/hp300/Makefile	Mon Sep  9 10:35:56 2002
+++ b/arch/m68k/hp300/Makefile	Mon Sep  9 10:35:56 2002
@@ -9,8 +9,6 @@
 
 O_TARGET := hp300.o
 
-export-objs	:= ksyms.o
-
 obj-y		:= ksyms.o config.o ints.o time.o reboot.o
 
 obj-$(CONFIG_VT)	+= hil.o
diff -Nru a/arch/m68k/sun3x/Makefile b/arch/m68k/sun3x/Makefile
--- a/arch/m68k/sun3x/Makefile	Mon Sep  9 10:36:11 2002
+++ b/arch/m68k/sun3x/Makefile	Mon Sep  9 10:36:11 2002
@@ -9,6 +9,8 @@
 
 O_TARGET := sun3x.o
 
+export-objs	:= sun3x_ksyms.o
+
 obj-y		:= config.o time.o dvma.o prom.o
 
 include $(TOPDIR)/Rules.make
diff -Nru a/arch/mips/au1000/common/Makefile b/arch/mips/au1000/common/Makefile
--- a/arch/mips/au1000/common/Makefile	Mon Sep  9 10:36:17 2002
+++ b/arch/mips/au1000/common/Makefile	Mon Sep  9 10:36:17 2002
@@ -8,6 +8,8 @@
 
 O_TARGET := au1000.o
 
+export-objs := serial.o
+
 obj-y := prom.o dbg_io.o int-handler.o irq.o puts.o time.o reset.o
 
 obj-$(CONFIG_AU1000_UART) += serial.o             
diff -Nru a/arch/mips64/sgi-ip27/ip27-memory.c b/arch/mips64/sgi-ip27/ip27-memory.c
--- a/arch/mips64/sgi-ip27/ip27-memory.c	Mon Sep  9 10:36:01 2002
+++ b/arch/mips64/sgi-ip27/ip27-memory.c	Mon Sep  9 10:36:01 2002
@@ -253,7 +253,7 @@
 
 		zones_size[ZONE_DMA] = end_pfn + 1 - start_pfn;
 		free_area_init_node(node, NODE_DATA(node), 0, zones_size, 
-						start_pfn << PAGE_SHIFT, 0);
+						start_pfn, 0);
 		if ((PLAT_NODE_DATA_STARTNR(node) + 
 					PLAT_NODE_DATA_SIZE(node)) > pagenr)
 			pagenr = PLAT_NODE_DATA_STARTNR(node) +
diff -Nru a/arch/ppc/4xx_io/serial_sicc.c b/arch/ppc/4xx_io/serial_sicc.c
--- a/arch/ppc/4xx_io/serial_sicc.c	Mon Sep  9 10:35:51 2002
+++ b/arch/ppc/4xx_io/serial_sicc.c	Mon Sep  9 10:35:51 2002
@@ -343,13 +343,13 @@
 
 static struct SICC_port sicc_ports[SERIAL_SICC_NR] = {
     {
-        uart_base:  0,
-        uart_base_phys:  SICC0_IO_BASE,
-        irqrx:      SICC0_INTRX,
-        irqtx:      SICC0_INTTX,
-//      uartclk:    0,
-        fifosize:   1,
-        set_mctrl:  sicc_set_mctrl_null,
+        .uart_base = 0,
+        .uart_base_phys = SICC0_IO_BASE,
+        .irqrx =    SICC0_INTRX,
+        .irqtx =    SICC0_INTTX,
+//      .uartclk =    0,
+        .fifosize = 1,
+        .set_mctrl = sicc_set_mctrl_null,
     }
 };
 
@@ -2113,16 +2113,16 @@
 
 static struct console siccuart_cons =
 {
-    name:       SERIAL_SICC_NAME,
-    write:      siccuart_console_write,
+    .name =     SERIAL_SICC_NAME,
+    .write =    siccuart_console_write,
 #ifdef used_and_not_const_char_pointer
-    read:       siccuart_console_read,
+    .read =     siccuart_console_read,
 #endif
-    device:     siccuart_console_device,
-    wait_key:   siccuart_console_wait_key,
-    setup:      siccuart_console_setup,
-    flags:      CON_PRINTBUFFER,
-    index:      -1,
+    .device =   siccuart_console_device,
+    .wait_key = siccuart_console_wait_key,
+    .setup =    siccuart_console_setup,
+    .flags =    CON_PRINTBUFFER,
+    .index =    -1,
 };
 
 void __init sicc_console_init(void)
diff -Nru a/arch/ppc/8260_io/uart.c b/arch/ppc/8260_io/uart.c
--- a/arch/ppc/8260_io/uart.c	Mon Sep  9 10:35:56 2002
+++ b/arch/ppc/8260_io/uart.c	Mon Sep  9 10:35:56 2002
@@ -2463,12 +2463,12 @@
 
 
 static struct console sercons = {
-	name:		"ttyS",
-	write:		serial_console_write,
-	device:		serial_console_device,
-	setup:		serial_console_setup,
-	flags:		CON_PRINTBUFFER,
-	index:		CONFIG_SERIAL_CONSOLE_PORT,
+	.name =		"ttyS",
+	.write =	serial_console_write,
+	.device =	serial_console_device,
+	.setup =	serial_console_setup,
+	.flags =	CON_PRINTBUFFER,
+	.index =	CONFIG_SERIAL_CONSOLE_PORT,
 };
 
 /*
diff -Nru a/arch/ppc/8xx_io/cs4218_tdm.c b/arch/ppc/8xx_io/cs4218_tdm.c
--- a/arch/ppc/8xx_io/cs4218_tdm.c	Mon Sep  9 10:35:56 2002
+++ b/arch/ppc/8xx_io/cs4218_tdm.c	Mon Sep  9 10:35:56 2002
@@ -1376,7 +1376,7 @@
 }
 
 static struct timer_list beep_timer = {
-	function: cs_nosound
+	.function = cs_nosound
 };
 
 static void cs_mksound(unsigned int hz, unsigned int ticks)
@@ -1468,21 +1468,21 @@
 }
 
 static MACHINE mach_cs4218 = {
-	name:		"HIOX CS4218",
-	name2:		"Built-in Sound",
-	open:		CS_open,
-	release:	CS_release,
-	dma_alloc:	CS_Alloc,
-	dma_free:	CS_Free,
-	irqinit:	CS_IrqInit,
+	.name =		"HIOX CS4218",
+	.name2 =	"Built-in Sound",
+	.open =		CS_open,
+	.release =	CS_release,
+	.dma_alloc =	CS_Alloc,
+	.dma_free =	CS_Free,
+	.irqinit =	CS_IrqInit,
 #ifdef MODULE
-	irqcleanup:	CS_IrqCleanup,
+	.irqcleanup =	CS_IrqCleanup,
 #endif /* MODULE */
-	init:		CS_Init,
-	silence:	CS_Silence,
-	setFormat:	CS_SetFormat,
-	setVolume:	CS_SetVolume,
-	play:		CS_Play
+	.init =		CS_Init,
+	.silence =	CS_Silence,
+	.setFormat =	CS_SetFormat,
+	.setVolume =	CS_SetVolume,
+	.play =		CS_Play
 };
 
 
@@ -1724,11 +1724,11 @@
 
 static struct file_operations mixer_fops =
 {
-	owner:		THIS_MODULE,
-	llseek:		sound_lseek,
-	ioctl:		mixer_ioctl,
-	open:		mixer_open,
-	release:	mixer_release,
+	.owner =	THIS_MODULE,
+	.llseek =	sound_lseek,
+	.ioctl =	mixer_ioctl,
+	.open =		mixer_open,
+	.release =	mixer_release,
 };
 
 
@@ -2314,13 +2314,13 @@
 
 static struct file_operations sq_fops =
 {
-	owner:		THIS_MODULE,
-	llseek:		sound_lseek,
-	read:		sq_read,			/* sq_read */
-	write:		sq_write,
-	ioctl:		sq_ioctl,
-	open:		sq_open,
-	release:	sq_release,
+	.owner =	THIS_MODULE,
+	.llseek =	sound_lseek,
+	.read =		sq_read,			/* sq_read */
+	.write =	sq_write,
+	.ioctl =	sq_ioctl,
+	.open =		sq_open,
+	.release =	sq_release,
 };
 
 
@@ -2451,11 +2451,11 @@
 
 static struct file_operations state_fops =
 {
-	owner:		THIS_MODULE,
-	llseek:		sound_lseek,
-	read:		state_read,
-	open:		state_open,
-	release:	state_release,
+	.owner =	THIS_MODULE,
+	.llseek =	sound_lseek,
+	.read =		state_read,
+	.open =		state_open,
+	.release =	state_release,
 };
 
 
diff -Nru a/arch/ppc/8xx_io/uart.c b/arch/ppc/8xx_io/uart.c
--- a/arch/ppc/8xx_io/uart.c	Mon Sep  9 10:36:13 2002
+++ b/arch/ppc/8xx_io/uart.c	Mon Sep  9 10:36:13 2002
@@ -224,12 +224,12 @@
 } ser_info_t;
 
 static struct console sercons = {
-	name:		"ttyS",
-	write:		serial_console_write,
-	device:		serial_console_device,
-	setup:		serial_console_setup,
-	flags:		CON_PRINTBUFFER,
-	index:		CONFIG_SERIAL_CONSOLE_PORT,
+	.name =		"ttyS",
+	.write =	serial_console_write,
+	.device =	serial_console_device,
+	.setup =	serial_console_setup,
+	.flags =	CON_PRINTBUFFER,
+	.index =	CONFIG_SERIAL_CONSOLE_PORT,
 };
 
 static void change_speed(ser_info_t *info);
diff -Nru a/arch/ppc/amiga/Makefile b/arch/ppc/amiga/Makefile
--- a/arch/ppc/amiga/Makefile	Mon Sep  9 10:36:11 2002
+++ b/arch/ppc/amiga/Makefile	Mon Sep  9 10:36:11 2002
@@ -1,4 +1,4 @@
-# BK Id: SCCS/s.Makefile 1.5 05/21/01 00:48:24 cort
+# BK Id: %F% %I% %G% %U% %#%
 #
 #
 # Makefile for Linux arch/m68k/amiga source directory
diff -Nru a/arch/ppc/amiga/config.c b/arch/ppc/amiga/config.c
--- a/arch/ppc/amiga/config.c	Mon Sep  9 10:36:01 2002
+++ b/arch/ppc/amiga/config.c	Mon Sep  9 10:36:01 2002
@@ -109,9 +109,9 @@
 #endif
 
 static struct console amiga_console_driver = {
-	name:		"debug",
-	flags:		CON_PRINTBUFFER,
-	index:		-1,
+	.name =		"debug",
+	.flags =	CON_PRINTBUFFER,
+	.index =	-1,
 };
 
 
@@ -123,10 +123,10 @@
     struct resource _ciab, _ciaa, _custom, _kickstart;
 } mb_resources = {
 //    { "Ranger Memory", 0x00c00000, 0x00c7ffff },
-    _ciab:	{ "CIA B", 0x00bfd000, 0x00bfdfff },
-    _ciaa:	{ "CIA A", 0x00bfe000, 0x00bfefff },
-    _custom:	{ "Custom I/O", 0x00dff000, 0x00dfffff },
-    _kickstart:	{ "Kickstart ROM", 0x00f80000, 0x00ffffff }
+    ._ciab =	  { "CIA B", 0x00bfd000, 0x00bfdfff },
+    ._ciaa =	  { "CIA A", 0x00bfe000, 0x00bfefff },
+    ._custom =	  { "Custom I/O", 0x00dff000, 0x00dfffff },
+    ._kickstart = { "Kickstart ROM", 0x00f80000, 0x00ffffff }
 };
 
 static struct resource rtc_resource = {
diff -Nru a/arch/ppc/iSeries/LparData.c b/arch/ppc/iSeries/LparData.c
--- a/arch/ppc/iSeries/LparData.c	Mon Sep  9 10:36:11 2002
+++ b/arch/ppc/iSeries/LparData.c	Mon Sep  9 10:36:11 2002
@@ -59,21 +59,21 @@
 // 8192 indicates to map 8192 pages (32 MB) of the load area.
 
 struct LparMap xLparMap = { 	
-		xNumberEsids:	4,		// Number ESID/VSID pairs
-		xNumberRanges:	1,		// Number of memory ranges
-		xSegmentTableOffs:  0,		// Segment Table Page (unused)
-		xKernelEsidC:	0xC,		// ESID to map
-		xKernelVsidC:	0xCCC,		// VSID to map
-		xKernelEsidD:	0xD,		// ESID to map
-		xKernelVsidD:	0xDDD,		// VSID to map
-		xKernelEsidE:	0xE,		// ESID to map
-		xKernelVsidE:	0xEEE,		// VSID to map
-		xKernelEsidF:	0xF,		// ESID to map
-		xKernelVsidF:	0xFFF,		// VSID to map
-
-		xPages:		HvPagesToMap,	// # of pages to map (8192)
-		xOffset:	0,		// Offset into load area
-		xVPN:		0xCCC0000	// VPN of first mapped page
+		.xNumberEsids =4,		// Number ESID/VSID pairs
+		.xNumberRanges =1,		// Number of memory ranges
+		.xSegmentTableOffs =0,		// Segment Table Page (unused)
+		.xKernelEsidC =0xC,		// ESID to map
+		.xKernelVsidC =0xCCC,		// VSID to map
+		.xKernelEsidD =0xD,		// ESID to map
+		.xKernelVsidD =0xDDD,		// VSID to map
+		.xKernelEsidE =0xE,		// ESID to map
+		.xKernelVsidE =0xEEE,		// VSID to map
+		.xKernelEsidF =0xF,		// ESID to map
+		.xKernelVsidF =0xFFF,		// VSID to map
+
+		.xPages =		HvPagesToMap,	// # of pages to map (8192)
+		.xOffset =	0,		// Offset into load area
+		.xVPN =	0xCCC0000	// VPN of first mapped page
 };					
 
 // The Naca has a pointer to the ItVpdAreas.  The hypervisor finds
@@ -119,11 +119,11 @@
 	  (lpq),		\
 	  0, 0, {0},		\
 	  { /* LpPaca */		\
-		xDesc: 0xd397d781, /* "LpPa" */	\
-		xSize: sizeof(struct ItLpPaca),	\
-		xFPRegsInUse:	1,		\
-		xDynProcStatus: 2,		\
-		xEndOfQuantum:	0xffffffffffffffff	\
+		.xDesc = 0xd397d781, /* "LpPa" */	\
+		.xSize = sizeof(struct ItLpPaca),	\
+		.xFPRegsInUse =1,		\
+		.xDynProcStatus = 2,		\
+		.xEndOfQuantum =0xffffffffffffffff	\
 	  },			\
 	  { /* LpRegSave */	\
 		0xd397d9e2,	/* "LpRS" */	\
@@ -245,7 +245,7 @@
 
 struct IoHriProcessorVpd xIoHriProcessorVpd[maxProcessors] = {
 	{ 
-	xTimeBaseFreq: 50000000
+	.xTimeBaseFreq = 50000000
 	}
 };
 	
diff -Nru a/arch/ppc/iSeries/rtc.c b/arch/ppc/iSeries/rtc.c
--- a/arch/ppc/iSeries/rtc.c	Mon Sep  9 10:36:11 2002
+++ b/arch/ppc/iSeries/rtc.c	Mon Sep  9 10:36:11 2002
@@ -175,12 +175,12 @@
  */
 
 static struct file_operations rtc_fops = {
-	owner:		THIS_MODULE,
-	llseek:		rtc_llseek,
-	read:		rtc_read,
-	ioctl:		rtc_ioctl,
-	open:		rtc_open,
-	release:	rtc_release,
+	.owner =	THIS_MODULE,
+	.llseek =	rtc_llseek,
+	.read =		rtc_read,
+	.ioctl =	rtc_ioctl,
+	.open =		rtc_open,
+	.release =	rtc_release,
 };
 
 static struct miscdevice rtc_dev=
diff -Nru a/arch/ppc/kernel/Makefile b/arch/ppc/kernel/Makefile
--- a/arch/ppc/kernel/Makefile	Mon Sep  9 10:36:01 2002
+++ b/arch/ppc/kernel/Makefile	Mon Sep  9 10:36:01 2002
@@ -60,7 +60,7 @@
 					todc_time.o
 obj-$(CONFIG_EV64260)		+= gt64260_common.o gt64260_pic.o \
 					indirect_pci.o todc_time.o pci_auto.o
-obj-$(CONFIG_GEMINI)		+= open_pic.o i8259.o
+obj-$(CONFIG_GEMINI)		+= open_pic.o i8259.o indirect_pci.o
 obj-$(CONFIG_K2)		+= i8259.o indirect_pci.o todc_time.o \
 					pci_auto.o
 obj-$(CONFIG_LOPEC)		+= mpc10x_common.o indirect_pci.o pci_auto.o \
diff -Nru a/arch/ppc/kernel/galaxy_pci.c b/arch/ppc/kernel/galaxy_pci.c
--- a/arch/ppc/kernel/galaxy_pci.c	Mon Sep  9 10:36:11 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,121 +0,0 @@
-/*
- * BK Id: %F% %I% %G% %U% %#%
- */
-/*
- *
- *    Copyright (c) 2000 Grant Erickson <grant@borg.umn.edu>
- *    All rights reserved.
- *
- *    Module name: galaxy_pci.c
- *
- *    Description:
- *      PCI interface code for the IBM PowerPC 405GP on-chip PCI bus
- *      interface.
- *
- *      Why is this file called "galaxy_pci"? Because on the original
- *      IBM "Walnut" evaluation board schematic I have, the 405GP is
- *      is labeled "GALAXY".
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/pci.h>
-#include <linux/string.h>
-#include <linux/init.h>
-
-#include <asm/processor.h>
-#include <asm/system.h>
-#include <asm/io.h>
-#include <asm/machdep.h>
-#include <asm/pci-bridge.h>
-
-
-/* Preprocessor Defines */
-
-#define	PCICFGADDR	(volatile unsigned int *)(0xEEC00000)
-#define	PCICFGDATA	(volatile unsigned int *)(0xEEC00004)
-
-
-/* Function Prototypes */
-
-void __init
-galaxy_pcibios_fixup(void)
-{
-
-}
-
-static int
-galaxy_pcibios_read_config_byte(struct pci_controller* hose,
-				  u8 bus, u8 dev, u8 offset, u8 *val)
-{
-
-	return (PCIBIOS_SUCCESSFUL);
-}
-
-static int
-galaxy_pcibios_read_config_word(struct pci_controller* hose,
-				  u8 bus, u8 dev, u8 offset, u16 *val)
-{
-
-	return (PCIBIOS_SUCCESSFUL);
-}
-
-static int
-galaxy_pcibios_read_config_dword(struct pci_controller* hose,
-				  u8 bus, u8 dev, u8 offset, u32 *val)
-{
-
-	return (PCIBIOS_SUCCESSFUL);
-}
-
-static int
-galaxy_pcibios_write_config_byte(struct pci_controller* hose,
-				  u8 bus, u8 dev, u8 offset, u8 val)
-{
-
-	return (PCIBIOS_SUCCESSFUL);
-}
-
-static int
-galaxy_pcibios_write_config_word(struct pci_controller* hose,
-				  u8 bus, u8 dev, u8 offset, u16 val)
-{
-
-	return (PCIBIOS_SUCCESSFUL);
-}
-
-static int
-galaxy_pcibios_write_config_dword(struct pci_controller* hose,
-				  u8 bus, u8 dev, u8 offset, u32 val)
-{
-
-	return (PCIBIOS_SUCCESSFUL);
-}
-
-static struct pci_controller_ops galaxy_pci_ops =
-{
-	galaxy_pcibios_read_config_byte,
-	galaxy_pcibios_read_config_word,
-	galaxy_pcibios_read_config_dword,
-	galaxy_pcibios_write_config_byte,
-	galaxy_pcibios_write_config_word,
-	galaxy_pcibios_write_config_dword
-};
-
-void __init
-galaxy_find_bridges(void)
-{
-	struct pci_controller* hose;
-
-	set_config_access_method(galaxy);
-
-	ppc_md.pcibios_fixup = galaxy_pcibios_fixup;
-	hose = pcibios_alloc_controller();
-	if (!hose)
-		return;
-	hose->ops = &galaxy_pci_ops;
-	/* Todo ...
-	hose->cfg_data = ioremap(PCICFGDATA, ...);
-	hose->cfg_addr = ioremap(PCICFGADDR, ...);
-	*/
-}
diff -Nru a/arch/ppc/kernel/indirect_pci.c b/arch/ppc/kernel/indirect_pci.c
--- a/arch/ppc/kernel/indirect_pci.c	Mon Sep  9 10:35:56 2002
+++ b/arch/ppc/kernel/indirect_pci.c	Mon Sep  9 10:35:56 2002
@@ -24,48 +24,88 @@
 #include <asm/pci-bridge.h>
 #include <asm/machdep.h>
 
-#define cfg_read(val, addr, type, op)	*val = op((type)(addr))
-#define cfg_write(val, addr, type, op)	op((type *)(addr), (val))
+static int
+indirect_read_config(struct pci_bus *bus, unsigned int devfn, int offset,
+		     int len, u32 *val)
+{
+	struct pci_controller *hose = bus->sysdata;
+	volatile unsigned char *cfg_data;
+
+	if (ppc_md.pci_exclude_device)
+		if (ppc_md.pci_exclude_device(bus->number, devfn))
+			return PCIBIOS_DEVICE_NOT_FOUND;
 
-#define INDIRECT_PCI_OP(rw, size, type, op, mask)			 \
-static int								 \
-indirect_##rw##_config_##size(struct pci_dev *dev, int offset, type val) \
-{									 \
-	struct pci_controller *hose = dev->sysdata;			 \
-									 \
-	if (ppc_md.pci_exclude_device)					 \
-		if (ppc_md.pci_exclude_device(dev->bus->number, dev->devfn)) \
-			return PCIBIOS_DEVICE_NOT_FOUND;		 \
-									 \
-	out_be32(hose->cfg_addr, 					 \
-		 ((offset & 0xfc) << 24) | (dev->devfn << 16)		 \
-		 | ((dev->bus->number - hose->bus_offset) << 8) | 0x80); \
-	cfg_##rw(val, hose->cfg_data + (offset & mask), type, op);	 \
-	return PCIBIOS_SUCCESSFUL;    					 \
+	out_be32(hose->cfg_addr,
+		 ((offset & 0xfc) << 24) | (devfn << 16)
+		 | ((bus->number - hose->bus_offset) << 8) | 0x80);
+	/*
+	 * Note: the caller has already checked that offset is
+	 * suitably aligned and that len is 1, 2 or 4.
+	 */
+	cfg_data = hose->cfg_data + (offset & 3);
+	switch (len) {
+	case 1:
+		*val = in_8((u8 *)cfg_data);
+		break;
+	case 2:
+		*val = in_le16((u16 *)cfg_data);
+		break;
+	default:
+		*val = in_le32((u32 *)cfg_data);
+		break;
+	}
+	return PCIBIOS_SUCCESSFUL;
 }
 
-INDIRECT_PCI_OP(read, byte, u8 *, in_8, 3)
-INDIRECT_PCI_OP(read, word, u16 *, in_le16, 2)
-INDIRECT_PCI_OP(read, dword, u32 *, in_le32, 0)
-INDIRECT_PCI_OP(write, byte, u8, out_8, 3)
-INDIRECT_PCI_OP(write, word, u16, out_le16, 2)
-INDIRECT_PCI_OP(write, dword, u32, out_le32, 0)
+static int
+indirect_write_config(struct pci_bus *bus, unsigned int devfn, int offset,
+		      int len, u32 val)
+{
+	struct pci_controller *hose = bus->sysdata;
+	volatile unsigned char *cfg_data;
+
+	if (ppc_md.pci_exclude_device)
+		if (ppc_md.pci_exclude_device(bus->number, devfn))
+			return PCIBIOS_DEVICE_NOT_FOUND;
+
+	out_be32(hose->cfg_addr,
+		 ((offset & 0xfc) << 24) | (devfn << 16)
+		 | ((bus->number - hose->bus_offset) << 8) | 0x80);
+	/*
+	 * Note: the caller has already checked that offset is
+	 * suitably aligned and that len is 1, 2 or 4.
+	 */
+	cfg_data = hose->cfg_data + (offset & 3);
+	switch (len) {
+	case 1:
+		out_8((u8 *)cfg_data, val);
+		break;
+	case 2:
+		out_le16((u16 *)cfg_data, val);
+		break;
+	default:
+		out_le32((u32 *)cfg_data, val);
+		break;
+	}
+	return PCIBIOS_SUCCESSFUL;
+}
 
 static struct pci_ops indirect_pci_ops =
 {
-	indirect_read_config_byte,
-	indirect_read_config_word,
-	indirect_read_config_dword,
-	indirect_write_config_byte,
-	indirect_write_config_word,
-	indirect_write_config_dword
+	indirect_read_config,
+	indirect_write_config
 };
 
 void __init
 setup_indirect_pci(struct pci_controller* hose, u32 cfg_addr, u32 cfg_data)
 {
+	unsigned long base = cfg_addr & PAGE_MASK;
+	char *mbase;
+
+	mbase = ioremap(base, PAGE_SIZE);
+	hose->cfg_addr = (unsigned int *)(mbase + (cfg_addr & ~PAGE_MASK));
+	if ((cfg_data & PAGE_MASK) != base)
+		mbase = ioremap(cfg_data & PAGE_MASK, PAGE_SIZE);
+	hose->cfg_data = (unsigned char *)(mbase + (cfg_data & ~PAGE_MASK));
 	hose->ops = &indirect_pci_ops;
-	hose->cfg_addr = (unsigned int *) ioremap(cfg_addr, 4);
-	hose->cfg_data = (unsigned char *) ioremap(cfg_data, 4);
 }
-
diff -Nru a/arch/ppc/kernel/pci.c b/arch/ppc/kernel/pci.c
--- a/arch/ppc/kernel/pci.c	Mon Sep  9 10:36:11 2002
+++ b/arch/ppc/kernel/pci.c	Mon Sep  9 10:36:11 2002
@@ -816,19 +816,19 @@
 /* 
  * Scans the OF tree for a device node matching a PCI device
  */
-struct device_node*
-pci_device_to_OF_node(struct pci_dev *dev)
+struct device_node *
+pci_busdev_to_OF_node(struct pci_bus *bus, int devfn)
 {
 	struct pci_controller *hose;
 	struct device_node *node;
-	int bus;
+	int busnr;
 	
 	if (!have_of)
 		return NULL;
 		
 	/* Lookup the hose */
-	bus = dev->bus->number;
-	hose = pci_bus_to_hose(bus);
+	busnr = bus->number;
+	hose = pci_bus_to_hose(busnr);
 	if (!hose)
 		return NULL;
 
@@ -839,12 +839,18 @@
 
 	/* Fixup bus number according to what OF think it is. */
 	if (pci_to_OF_bus_map)
-		bus = pci_to_OF_bus_map[bus];
-	if (bus == 0xff)
+		busnr = pci_to_OF_bus_map[busnr];
+	if (busnr == 0xff)
 		return NULL;
 		
 	/* Now, lookup childs of the hose */
-	return scan_OF_childs_for_device(node->child, bus, dev->devfn);
+	return scan_OF_childs_for_device(node->child, busnr, devfn);
+}
+
+struct device_node*
+pci_device_to_OF_node(struct pci_dev *dev)
+{
+	return pci_busdev_to_OF_node(dev->bus, dev->devfn);
 }
 
 /* This routine is meant to be used early during boot, when the
@@ -1512,31 +1518,33 @@
 	return PCIBIOS_DEVICE_NOT_FOUND;    				\
 }
 
-NULL_PCI_OP(read, byte, u8 *)
-NULL_PCI_OP(read, word, u16 *)
-NULL_PCI_OP(read, dword, u32 *)
-NULL_PCI_OP(write, byte, u8)
-NULL_PCI_OP(write, word, u16)
-NULL_PCI_OP(write, dword, u32)
+static int
+null_read_config(struct pci_bus *bus, unsigned int devfn, int offset,
+		 int len, u32 *val)
+{
+	return PCIBIOS_DEVICE_NOT_FOUND;
+}
+
+static int
+null_write_config(struct pci_bus *bus, unsigned int devfn, int offset,
+		  int len, u32 val)
+{
+	return PCIBIOS_DEVICE_NOT_FOUND;
+}
 
 static struct pci_ops null_pci_ops =
 {
-	null_read_config_byte,
-	null_read_config_word,
-	null_read_config_dword,
-	null_write_config_byte,
-	null_write_config_word,
-	null_write_config_dword
+	null_read_config,
+	null_write_config
 };
 
 /*
  * These functions are used early on before PCI scanning is done
  * and all of the pci_dev and pci_bus structures have been created.
  */
-static struct pci_dev *
-fake_pci_dev(struct pci_controller *hose, int busnr, int devfn)
+static struct pci_bus *
+fake_pci_bus(struct pci_controller *hose, int busnr)
 {
-	static struct pci_dev dev;
 	static struct pci_bus bus;
 
 	if (hose == 0) {
@@ -1544,20 +1552,17 @@
 		if (hose == 0)
 			printk(KERN_ERR "Can't find hose for PCI bus %d!\n", busnr);
 	}
-	dev.bus = &bus;
-	dev.sysdata = hose;
-	dev.devfn = devfn;
 	bus.number = busnr;
 	bus.ops = hose? hose->ops: &null_pci_ops;
-	return &dev;
+	return &bus;
 }
 
 #define EARLY_PCI_OP(rw, size, type)					\
 int early_##rw##_config_##size(struct pci_controller *hose, int bus,	\
 			       int devfn, int offset, type value)	\
 {									\
-	return pci_##rw##_config_##size(fake_pci_dev(hose, bus, devfn),	\
-					offset, value);			\
+	return pci_bus_##rw##_config_##size(fake_pci_bus(hose, bus),	\
+					    devfn, offset, value);	\
 }
 
 EARLY_PCI_OP(read, byte, u8 *)
diff -Nru a/arch/ppc/kernel/ppc4xx_serial.c b/arch/ppc/kernel/ppc4xx_serial.c
--- a/arch/ppc/kernel/ppc4xx_serial.c	Mon Sep  9 10:35:44 2002
+++ b/arch/ppc/kernel/ppc4xx_serial.c	Mon Sep  9 10:35:44 2002
@@ -166,11 +166,11 @@
 }
 
 static struct console ppc405_sercons = {
-	name:		"dbg_cons",
-	write:		ppc405_console_write,
-	setup:		ppc405_console_setup,
-	flags:		CON_PRINTBUFFER,
-	index:		-1,
+	.name =		"dbg_cons",
+	.write =	ppc405_console_write,
+	.setup =	ppc405_console_setup,
+	.flags =	CON_PRINTBUFFER,
+	.index =	-1,
 };
 
 void
diff -Nru a/arch/ppc/kernel/ppc_htab.c b/arch/ppc/kernel/ppc_htab.c
--- a/arch/ppc/kernel/ppc_htab.c	Mon Sep  9 10:35:56 2002
+++ b/arch/ppc/kernel/ppc_htab.c	Mon Sep  9 10:35:56 2002
@@ -66,9 +66,9 @@
 #define PMC2 954
 
 struct file_operations ppc_htab_operations = {
-        llseek:         ppc_htab_lseek,
-        read:           ppc_htab_read,
-        write:          ppc_htab_write,
+        .llseek =       ppc_htab_lseek,
+        .read =         ppc_htab_read,
+        .write =        ppc_htab_write,
 };
 
 static char *pmc1_lookup(unsigned long mmcr0)
diff -Nru a/arch/ppc/kernel/ppc_ksyms.c b/arch/ppc/kernel/ppc_ksyms.c
--- a/arch/ppc/kernel/ppc_ksyms.c	Mon Sep  9 10:36:13 2002
+++ b/arch/ppc/kernel/ppc_ksyms.c	Mon Sep  9 10:36:13 2002
@@ -42,10 +42,6 @@
 #include <asm/nvram.h>
 #include <asm/mmu_context.h>
 #include <asm/backlight.h>
-#ifdef CONFIG_SMP
-#include <asm/smplock.h>
-#include <asm/smp.h>
-#endif /* CONFIG_SMP */
 #include <asm/time.h>
 #include <asm/cputable.h>
 #include <asm/btext.h>
@@ -250,6 +246,7 @@
 EXPORT_SYMBOL(get_property);
 EXPORT_SYMBOL(request_OF_resource);
 EXPORT_SYMBOL(release_OF_resource);
+EXPORT_SYMBOL(pci_busdev_to_OF_node);
 EXPORT_SYMBOL(pci_device_to_OF_node);
 EXPORT_SYMBOL(pci_device_from_OF_node);
 EXPORT_SYMBOL(pmac_newworld);
diff -Nru a/arch/ppc/kernel/process.c b/arch/ppc/kernel/process.c
--- a/arch/ppc/kernel/process.c	Mon Sep  9 10:36:11 2002
+++ b/arch/ppc/kernel/process.c	Mon Sep  9 10:36:11 2002
@@ -445,7 +445,7 @@
 {
  	struct task_struct *p;
 	CHECK_FULL_REGS(regs);
- 	p = do_fork(p1 & ~CLONE_IDLETASK, regs->gpr[1], regs, 0);
+ 	p = do_fork(p1 & ~CLONE_IDLETASK, p2, regs, 0, (int *)p3);
  	return IS_ERR(p) ? PTR_ERR(p) : p->pid;
 }
 
@@ -454,7 +454,7 @@
 {
 	struct task_struct *p;
 	CHECK_FULL_REGS(regs);
-	p = do_fork(SIGCHLD, regs->gpr[1], regs, 0);
+	p = do_fork(SIGCHLD, regs->gpr[1], regs, 0, NULL);
 	return IS_ERR(p) ? PTR_ERR(p) : p->pid;
 }
 
@@ -463,7 +463,7 @@
 {
 	struct task_struct *p;
 	CHECK_FULL_REGS(regs);
-	p = do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->gpr[1], regs, 0);
+	p = do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->gpr[1], regs, 0, NULL);
 	return IS_ERR(p) ? PTR_ERR(p) : p->pid;
 }
 
diff -Nru a/arch/ppc/kernel/setup.c b/arch/ppc/kernel/setup.c
--- a/arch/ppc/kernel/setup.c	Mon Sep  9 10:36:17 2002
+++ b/arch/ppc/kernel/setup.c	Mon Sep  9 10:36:17 2002
@@ -250,10 +250,10 @@
 }
 
 struct seq_operations cpuinfo_op = {
-	start:	c_start,
-	next:	c_next,
-	stop:	c_stop,
-	show:	show_cpuinfo,
+	.start =c_start,
+	.next =	c_next,
+	.stop =	c_stop,
+	.show =	show_cpuinfo,
 };
 
 /*
diff -Nru a/arch/ppc/kernel/smp.c b/arch/ppc/kernel/smp.c
--- a/arch/ppc/kernel/smp.c	Mon Sep  9 10:36:17 2002
+++ b/arch/ppc/kernel/smp.c	Mon Sep  9 10:36:17 2002
@@ -392,7 +392,7 @@
 	/* create a process for the processor */
 	/* only regs.msr is actually used, and 0 is OK for it */
 	memset(&regs, 0, sizeof(struct pt_regs));
-	p = do_fork(CLONE_VM|CLONE_IDLETASK, 0, &regs, 0);
+	p = do_fork(CLONE_VM|CLONE_IDLETASK, 0, &regs, 0, NULL);
 	if (IS_ERR(p))
 		panic("failed fork for CPU %u: %li", cpu, PTR_ERR(p));
 
diff -Nru a/arch/ppc/mm/fault.c b/arch/ppc/mm/fault.c
--- a/arch/ppc/mm/fault.c	Mon Sep  9 10:36:01 2002
+++ b/arch/ppc/mm/fault.c	Mon Sep  9 10:36:01 2002
@@ -102,7 +102,7 @@
 #endif /* !CONFIG_4xx */
 #endif /* CONFIG_XMON || CONFIG_KGDB */
 
-	if (in_interrupt() || mm == NULL) {
+	if (in_atomic() || mm == NULL) {
 		bad_page_fault(regs, address, SIGSEGV);
 		return;
 	}
diff -Nru a/arch/ppc/platforms/apus_pci.c b/arch/ppc/platforms/apus_pci.c
--- a/arch/ppc/platforms/apus_pci.c	Mon Sep  9 10:36:13 2002
+++ b/arch/ppc/platforms/apus_pci.c	Mon Sep  9 10:36:13 2002
@@ -61,49 +61,72 @@
 }
 
 
-#define cfg_read(val, addr, type, op)	*val = op((type)(addr))
-#define cfg_write(val, addr, type, op)	op((val), (type *)(addr)); DEFW()
-#define cfg_read_bad	*val = ~0;
-#define cfg_write_bad	;
-#define cfg_read_val(val)	*val
-#define cfg_write_val(val)	val
-
-#define APUS_PCI_OP(rw, size, type, op, mask)					\
-int									\
-apus_pcibios_##rw##_config_##size(struct pci_dev *dev, int offset, type val)	\
-{										\
-	int fnno = FNNO(dev->devfn);						\
-	int devno = DEVNO(dev->devfn);						\
-										\
-	if (dev->bus->number > 0 || devno != 1) {				\
-		cfg_##rw##_bad;							\
-		return PCIBIOS_DEVICE_NOT_FOUND;				\
-	}									\
-	/* base address + function offset + offset ^ endianness conversion */	\
-	cfg_##rw(val, apus_hose->cfg_data + (fnno<<5) + (offset ^ mask),	\
-		 type, op);							\
-										\
-	DPRINTK(#op " b: 0x%x, d: 0x%x, f: 0x%x, o: 0x%x, v: 0x%x\n",		\
-		dev->bus->number, dev->devfn>>3, dev->devfn&7,			\
-		offset, cfg_##rw##_val(val));					\
-	return PCIBIOS_SUCCESSFUL;						\
+int
+apus_pcibios_read_config(struct pci_bus *bus, int devfn, int offset,
+			 int len, u32 *val)
+{
+	int fnno = FNNO(devfn);
+	int devno = DEVNO(devfn);
+	volatile unsigned char *cfg_data;
+
+	if (bus->number > 0 || devno != 1) {
+		*val = ~0;
+		return PCIBIOS_DEVICE_NOT_FOUND;
+	}
+	/* base address + function offset + offset ^ endianness conversion */
+	/* XXX the fnno<<5 bit seems wacky  -- paulus */
+	cfg_data = apus_hose->cfg_data + (fnno<<5) + (offset ^ (len - 1));
+	switch (len) {
+	case 1:
+		*val = readb(cfg_data);
+		break;
+	case 2:
+		*val = readw(cfg_data);
+		break;
+	default:
+		*val = readl(cfg_data);
+		break;
+	}
+
+	DPRINTK("read b: 0x%x, d: 0x%x, f: 0x%x, o: 0x%x, l: %d, v: 0x%x\n",
+		bus->number, devfn>>3, devfn&7, offset, len, *val);
+	return PCIBIOS_SUCCESSFUL;
 }
 
-APUS_PCI_OP(read, byte, u8 *, readb, 3)
-APUS_PCI_OP(read, word, u16 *, readw, 2)
-APUS_PCI_OP(read, dword, u32 *, readl, 0)
-APUS_PCI_OP(write, byte, u8, writeb, 3)
-APUS_PCI_OP(write, word, u16, writew, 2)
-APUS_PCI_OP(write, dword, u32, writel, 0)
+int
+apus_pcibios_write_config(struct pci_bus *bus, int devfn, int offset,
+			  int len, u32 *val)
+{
+	int fnno = FNNO(devfn);
+	int devno = DEVNO(devfn);
+	volatile unsigned char *cfg_data;
 
+	if (bus->number > 0 || devno != 1) {
+		return PCIBIOS_DEVICE_NOT_FOUND;
+	}
+	/* base address + function offset + offset ^ endianness conversion */
+	/* XXX the fnno<<5 bit seems wacky  -- paulus */
+	cfg_data = apus_hose->cfg_data + (fnno<<5) + (offset ^ (len - 1));
+	switch (len) {
+	case 1:
+		writeb(val, cfg_data); DEFW();
+		break;
+	case 2:
+		writew(val, cfg_data); DEFW();
+		break;
+	default:
+		writel(val, cfg_data); DEFW();
+		break;
+	}
+
+	DPRINTK("write b: 0x%x, d: 0x%x, f: 0x%x, o: 0x%x, l: %d, v: 0x%x\n",
+		bus->number, devfn>>3, devfn&7, offset, len, val);
+	return PCIBIOS_SUCCESSFUL;
+}
 
 static struct pci_ops apus_pci_ops = {
-	apus_pcibios_read_config_byte,
-	apus_pcibios_read_config_word,
-	apus_pcibios_read_config_dword,
-	apus_pcibios_write_config_byte,
-	apus_pcibios_write_config_word,
-	apus_pcibios_write_config_dword
+	apus_pcibios_read_config,
+	apus_pcibios_write_config
 };
 
 static struct resource pci_mem = { "B/CVisionPPC PCI mem", CVPPC_FB_APERTURE_ONE, CVPPC_PCI_CONFIG, IORESOURCE_MEM };
diff -Nru a/arch/ppc/platforms/apus_setup.c b/arch/ppc/platforms/apus_setup.c
--- a/arch/ppc/platforms/apus_setup.c	Mon Sep  9 10:36:11 2002
+++ b/arch/ppc/platforms/apus_setup.c	Mon Sep  9 10:36:11 2002
@@ -667,14 +667,14 @@
 extern void amiga_disable_irq(unsigned int irq);
 
 struct hw_interrupt_type amiga_sys_irqctrl = {
-	typename: "Amiga IPL",
-	end: apus_end_irq,
+	.typename = "Amiga IPL",
+	.end = apus_end_irq,
 };
 
 struct hw_interrupt_type amiga_irqctrl = {
-	typename: "Amiga    ",
-	enable: amiga_enable_irq,
-	disable: amiga_disable_irq,
+	.typename = "Amiga    ",
+	.enable = amiga_enable_irq,
+	.disable = amiga_disable_irq,
 };
 
 #define HARDWARE_MAPPED_SIZE (512*1024)
diff -Nru a/arch/ppc/platforms/chrp_pci.c b/arch/ppc/platforms/chrp_pci.c
--- a/arch/ppc/platforms/chrp_pci.c	Mon Sep  9 10:36:18 2002
+++ b/arch/ppc/platforms/chrp_pci.c	Mon Sep  9 10:36:18 2002
@@ -28,136 +28,108 @@
 /* LongTrail */
 unsigned long gg2_pci_config_base;
 
-#define pci_config_addr(dev, offset) \
-(gg2_pci_config_base | ((dev->bus->number)<<16) | ((dev->devfn)<<8) | (offset))
-
-volatile struct Hydra *Hydra = NULL;
-
 /*
  * The VLSI Golden Gate II has only 512K of PCI configuration space, so we
  * limit the bus number to 3 bits
  */
 
-#define cfg_read(val, addr, type, op)	*val = op((type)(addr))
-#define cfg_write(val, addr, type, op)	op((type *)(addr), (val))
-
-#define cfg_read_bad(val, size)		*val = bad_##size;
-#define cfg_write_bad(val, size)
+int __chrp gg2_read_config(struct pci_bus *bus, unsigned int devfn, int off,
+			   int len, u32 *val)
+{
+	volatile unsigned char *cfg_data;
+	struct pci_controller *hose = bus->sysdata;
 
-#define bad_byte	0xff
-#define bad_word	0xffff
-#define bad_dword	0xffffffffU
-
-#define GG2_PCI_OP(rw, size, type, op)					    \
-int __chrp gg2_##rw##_config_##size(struct pci_dev *dev, int off, type val) \
-{									    \
-	if (dev->bus->number > 7) {					    \
-		cfg_##rw##_bad(val, size)				    \
-		return PCIBIOS_DEVICE_NOT_FOUND;			    \
-	}								    \
-	cfg_##rw(val, pci_config_addr(dev, off), type, op);		    \
-	return PCIBIOS_SUCCESSFUL;					    \
+	if (bus->number > 7)
+		return PCIBIOS_DEVICE_NOT_FOUND;
+	/*
+	 * Note: the caller has already checked that off is
+	 * suitably aligned and that len is 1, 2 or 4.
+	 */
+	cfg_data = hose->cfg_data + ((bus->number<<16) | (devfn<<8) | off);
+	switch (len) {
+	case 1:
+		*val =  in_8((u8 *)cfg_data);
+		break;
+	case 2:
+		*val = in_le16((u16 *)cfg_data);
+		break;
+	default:
+		*val = in_le32((u32 *)cfg_data);
+		break;
+	}
+	return PCIBIOS_SUCCESSFUL;
 }
 
-GG2_PCI_OP(read, byte, u8 *, in_8)
-GG2_PCI_OP(read, word, u16 *, in_le16)
-GG2_PCI_OP(read, dword, u32 *, in_le32)
-GG2_PCI_OP(write, byte, u8, out_8)
-GG2_PCI_OP(write, word, u16, out_le16)
-GG2_PCI_OP(write, dword, u32, out_le32)
-
-static struct pci_ops gg2_pci_ops =
+int __chrp gg2_write_config(struct pci_bus *bus, unsigned int devfn, int off,
+			    int len, u32 val)
 {
-	gg2_read_config_byte,
-	gg2_read_config_word,
-	gg2_read_config_dword,
-	gg2_write_config_byte,
-	gg2_write_config_word,
-	gg2_write_config_dword
-};
+	volatile unsigned char *cfg_data;
+	struct pci_controller *hose = bus->sysdata;
 
-/*
- * Access functions for PCI config space on IBM "python" host bridges.
- */
-#define PYTHON_CFA(b, d, o)	(0x80 | ((b) << 8) | ((d) << 16) \
-				 | (((o) & ~3) << 24))
-
-#define PYTHON_PCI_OP(rw, size, type, op, mask)			    	     \
-int __chrp								     \
-python_##rw##_config_##size(struct pci_dev *dev, int offset, type val) 	     \
-{									     \
-	struct pci_controller *hose = dev->sysdata;			     \
-									     \
-	out_be32(hose->cfg_addr,					     \
-		 PYTHON_CFA(dev->bus->number, dev->devfn, offset));	     \
-	cfg_##rw(val, hose->cfg_data + (offset & mask), type, op);   	     \
-	return PCIBIOS_SUCCESSFUL;					     \
+	if (bus->number > 7)
+		return PCIBIOS_DEVICE_NOT_FOUND;
+	/*
+	 * Note: the caller has already checked that off is
+	 * suitably aligned and that len is 1, 2 or 4.
+	 */
+	cfg_data = hose->cfg_data + ((bus->number<<16) | (devfn<<8) | off);
+	switch (len) {
+	case 1:
+		out_8((u8 *)cfg_data, val);
+		break;
+	case 2:
+		out_le16((u16 *)cfg_data, val);
+		break;
+	default:
+		out_le32((u32 *)cfg_data, val);
+		break;
+	}
+	return PCIBIOS_SUCCESSFUL;
 }
 
-PYTHON_PCI_OP(read, byte, u8 *, in_8, 3)
-PYTHON_PCI_OP(read, word, u16 *, in_le16, 2)
-PYTHON_PCI_OP(read, dword, u32 *, in_le32, 0)
-PYTHON_PCI_OP(write, byte, u8, out_8, 3)
-PYTHON_PCI_OP(write, word, u16, out_le16, 2)
-PYTHON_PCI_OP(write, dword, u32, out_le32, 0)
-
-static struct pci_ops python_pci_ops =
+static struct pci_ops gg2_pci_ops =
 {
-	python_read_config_byte,
-	python_read_config_word,
-	python_read_config_dword,
-	python_write_config_byte,
-	python_write_config_word,
-	python_write_config_dword
+	gg2_read_config,
+	gg2_write_config
 };
 
 /*
  * Access functions for PCI config space using RTAS calls.
  */
-#define RTAS_PCI_READ_OP(size, type, nbytes)			    	  \
-int __chrp								  \
-rtas_read_config_##size(struct pci_dev *dev, int offset, type val) 	  \
-{									  \
-	unsigned long addr = (offset & 0xff) | ((dev->devfn & 0xff) << 8) \
-		| ((dev->bus->number & 0xff) << 16);			  \
-	unsigned long ret = ~0UL;					  \
-	int rval;							  \
-									  \
-	rval = call_rtas("read-pci-config", 2, 2, &ret, addr, nbytes);	  \
-	*val = ret;							  \
-	return rval? PCIBIOS_DEVICE_NOT_FOUND: PCIBIOS_SUCCESSFUL;    	  \
-}
+int __chrp
+rtas_read_config(struct pci_bus *bus, unsigned int devfn, int offset,
+		 int len, u32 *val)
+{
+	unsigned long addr = (offset & 0xff) | ((devfn & 0xff) << 8)
+		| ((bus->number & 0xff) << 16);
+        unsigned long ret = ~0UL;
+	int rval;
+
+	rval = call_rtas("read-pci-config", 2, 2, &ret, addr, len);
+	*val = ret;
+	return rval? PCIBIOS_DEVICE_NOT_FOUND: PCIBIOS_SUCCESSFUL;
+}
+
+int __chrp
+rtas_write_config(struct pci_bus *bus, unsigned int devfn, int offset,
+		  int len, u32 val)
+{
+	unsigned long addr = (offset & 0xff) | ((devfn & 0xff) << 8)
+		| ((bus->number & 0xff) << 16);
+	int rval;
 
-#define RTAS_PCI_WRITE_OP(size, type, nbytes)				  \
-int __chrp								  \
-rtas_write_config_##size(struct pci_dev *dev, int offset, type val)	  \
-{									  \
-	unsigned long addr = (offset & 0xff) | ((dev->devfn & 0xff) << 8) \
-		| ((dev->bus->number & 0xff) << 16);			  \
-	int rval;							  \
-									  \
-	rval = call_rtas("write-pci-config", 3, 1, NULL,		  \
-			 addr, nbytes, (ulong)val);			  \
-	return rval? PCIBIOS_DEVICE_NOT_FOUND: PCIBIOS_SUCCESSFUL;	  \
+	rval = call_rtas("write-pci-config", 3, 1, NULL, addr, len, val);
+	return rval? PCIBIOS_DEVICE_NOT_FOUND: PCIBIOS_SUCCESSFUL;
 }
 
-RTAS_PCI_READ_OP(byte, u8 *, 1)
-RTAS_PCI_READ_OP(word, u16 *, 2)
-RTAS_PCI_READ_OP(dword, u32 *, 4)
-RTAS_PCI_WRITE_OP(byte, u8, 1)
-RTAS_PCI_WRITE_OP(word, u16, 2)
-RTAS_PCI_WRITE_OP(dword, u32, 4)
-
 static struct pci_ops rtas_pci_ops =
 {
-	rtas_read_config_byte,
-	rtas_read_config_word,
-	rtas_read_config_dword,
-	rtas_write_config_byte,
-	rtas_write_config_word,
-	rtas_write_config_dword
+	rtas_read_config,
+	rtas_write_config
 };
 
+volatile struct Hydra *Hydra = NULL;
+
 int __init
 hydra_init(void)
 {
@@ -203,12 +175,9 @@
 setup_python(struct pci_controller *hose, struct device_node *dev)
 {
 	u32 *reg, val;
-	volatile unsigned char *cfg;
+	unsigned long addr = dev->addrs[0].address;
 
-	hose->ops = &python_pci_ops;
-	cfg = ioremap(dev->addrs[0].address + 0xf8000, 0x20);
-	hose->cfg_addr = (volatile unsigned int *) cfg;
-	hose->cfg_data = cfg + 0x10;
+	setup_indirect_pci(hose, addr + 0xf8000, addr + 0xf8010);
 
 	/* Clear the magic go-slow bit */
 	reg = (u32 *) ioremap(dev->addrs[0].address + 0xf6000, 0x40);
@@ -288,8 +257,9 @@
 			setup_grackle(hose);
 		} else if (is_longtrail) {
 			hose->ops = &gg2_pci_ops;
-			gg2_pci_config_base = (unsigned long)
+			hose->cfg_data = (unsigned char *)
 				ioremap(GG2_PCI_CONFIG_BASE, 0x80000);
+			gg2_pci_config_base = (unsigned long) hose->cfg_data;
 		} else {
 			printk("No methods for %s (model %s), using RTAS\n",
 			       dev->full_name, model);
diff -Nru a/arch/ppc/platforms/gemini_pci.c b/arch/ppc/platforms/gemini_pci.c
--- a/arch/ppc/platforms/gemini_pci.c	Mon Sep  9 10:36:01 2002
+++ b/arch/ppc/platforms/gemini_pci.c	Mon Sep  9 10:36:01 2002
@@ -13,84 +13,6 @@
 #include <asm/uaccess.h>
 #include <asm/pci-bridge.h>
 
-#define pci_config_addr(bus,dev,offset) \
-        (0x80000000 | (bus<<16) | (dev<<8) | offset)
-
-
-int
-gemini_pcibios_read_config_byte(struct pci_dev *dev, int offset, u8 *val)
-{
-	unsigned long reg;
-	reg = grackle_read(pci_config_addr(dev->bus->number, dev->devfn,
-					   (offset & ~(0x3))));
-	*val = ((reg >> ((offset & 0x3) << 3)) & 0xff);
-	return PCIBIOS_SUCCESSFUL;
-}
-
-int
-gemini_pcibios_read_config_word(struct pci_dev *dev, int offset, u16 *val)
-{
-	unsigned long reg;
-	reg = grackle_read(pci_config_addr(dev->bus->number, dev->devfn,
-					   (offset & ~(0x3))));
-	*val = ((reg >> ((offset & 0x3) << 3)) & 0xffff);
-	return PCIBIOS_SUCCESSFUL;
-}
-
-int
-gemini_pcibios_read_config_dword(struct pci_dev *dev, int offset, u32 *val)
-{
-	*val = grackle_read(pci_config_addr(dev->bus->number, dev->devfn,
-					    (offset & ~(0x3))));
-	return PCIBIOS_SUCCESSFUL;
-}
-
-int
-gemini_pcibios_write_config_byte(struct pci_dev *dev, int offset, u8 val)
-{
-	unsigned long reg;
-	int shifts = offset & 0x3;
-	unsigned int addr = pci_config_addr(dev->bus->number, dev->devfn,
-					    (offset & ~(0x3)));
-
-	reg = grackle_read(addr);
-	reg = (reg & ~(0xff << (shifts << 3))) | (val << (shifts << 3));
-	grackle_write(addr, reg );
-	return PCIBIOS_SUCCESSFUL;
-}
-
-int
-gemini_pcibios_write_config_word(struct pci_dev *dev, int offset, u16 val)
-{
-	unsigned long reg;
-	int shifts = offset & 0x3;
-	unsigned int addr = pci_config_addr(dev->bus->number, dev->devfn,
-					    (offset & ~(0x3)));
-
-	reg = grackle_read(addr);
-	reg = (reg & ~(0xffff << (shifts << 3))) | (val << (shifts << 3));
-	grackle_write(addr, reg );
-	return PCIBIOS_SUCCESSFUL;
-}
-
-int
-gemini_pcibios_write_config_dword(struct pci_dev *dev, int offset, u32 val)
-{
-	grackle_write(pci_config_addr(dev->bus->number, dev->devfn,
-				      (offset & ~(0x3))), val);
-	return PCIBIOS_SUCCESSFUL;
-}
-
-static struct pci_ops gemini_pci_ops =
-{
-	gemini_pcibios_read_config_byte,
-	gemini_pcibios_read_config_word,
-	gemini_pcibios_read_config_dword,
-	gemini_pcibios_write_config_byte,
-	gemini_pcibios_write_config_word,
-	gemini_pcibios_write_config_dword
-};
-
 void __init gemini_pcibios_fixup(void)
 {
 	int i;
@@ -118,5 +40,5 @@
 	hose = pcibios_alloc_controller();
 	if (!hose)
 		return;
-	hose->ops = &gemini_pci_ops;
+	setup_indirect_pci(hose, 0xfec00000, 0xfee00000);
 }
diff -Nru a/arch/ppc/platforms/pmac_pci.c b/arch/ppc/platforms/pmac_pci.c
--- a/arch/ppc/platforms/pmac_pci.c	Mon Sep  9 10:36:11 2002
+++ b/arch/ppc/platforms/pmac_pci.c	Mon Sep  9 10:36:11 2002
@@ -137,101 +137,118 @@
 	/* Uninorth will return garbage if we don't read back the value ! */
 	do {
 		out_le32(hose->cfg_addr, caddr);
-	} while(in_le32(hose->cfg_addr) != caddr);
+	} while (in_le32(hose->cfg_addr) != caddr);
 
 	offset &= has_uninorth ? 0x07 : 0x03;
 	return (unsigned int)(hose->cfg_data) + (unsigned int)offset;
 }
 
-#define cfg_read(val, addr, type, op, op2)	\
-	*val = op((type)(addr))
-#define cfg_write(val, addr, type, op, op2)	\
-	op((type *)(addr), (val)); (void) op2((type *)(addr))
-
-#define cfg_read_bad(val, size)		*val = bad_##size;
-#define cfg_write_bad(val, size)
-
-#define bad_byte	0xff
-#define bad_word	0xffff
-#define bad_dword	0xffffffffU
-
-#define MACRISC_PCI_OP(rw, size, type, op, op2)				    \
-static int __pmac							    \
-macrisc_##rw##_config_##size(struct pci_dev *dev, int off, type val)	    \
-{									    \
-	struct pci_controller *hose = dev->sysdata;			    \
-	unsigned int addr;						    \
-									    \
-	addr = macrisc_cfg_access(hose, dev->bus->number, dev->devfn, off); \
-	if (!addr) {							    \
-		cfg_##rw##_bad(val, size)				    \
-		return PCIBIOS_DEVICE_NOT_FOUND;			    \
-	}								    \
-	cfg_##rw(val, addr, type, op, op2);				    \
-	return PCIBIOS_SUCCESSFUL;					    \
-}
-
-MACRISC_PCI_OP(read, byte, u8 *, in_8, x)
-MACRISC_PCI_OP(read, word, u16 *, in_le16, x)
-MACRISC_PCI_OP(read, dword, u32 *, in_le32, x)
-MACRISC_PCI_OP(write, byte, u8, out_8, in_8)
-MACRISC_PCI_OP(write, word, u16, out_le16, in_le16)
-MACRISC_PCI_OP(write, dword, u32, out_le32, in_le32)
+static int __pmac
+macrisc_read_config(struct pci_bus *bus, unsigned int devfn, int offset,
+		    int len, u32 *val)
+{
+	struct pci_controller *hose = bus->sysdata;
+	unsigned int addr;
+
+	addr = macrisc_cfg_access(hose, bus->number, devfn, offset);
+	if (!addr)
+		return PCIBIOS_DEVICE_NOT_FOUND;
+	/*
+	 * Note: the caller has already checked that offset is
+	 * suitably aligned and that len is 1, 2 or 4.
+	 */
+	switch (len) {
+	case 1:
+		*val = in_8((u8 *)addr);
+		break;
+	case 2:
+		*val = in_le16((u16 *)addr);
+		break;
+	default:
+		*val = in_le32((u32 *)addr);
+		break;
+	}
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static int __pmac
+macrisc_write_config(struct pci_bus *bus, unsigned int devfn, int offset,
+		     int len, u32 val)
+{
+	struct pci_controller *hose = bus->sysdata;
+	unsigned int addr;
+
+	addr = macrisc_cfg_access(hose, bus->number, devfn, offset);
+	if (!addr)
+		return PCIBIOS_DEVICE_NOT_FOUND;
+	/*
+	 * Note: the caller has already checked that offset is
+	 * suitably aligned and that len is 1, 2 or 4.
+	 */
+	switch (len) {
+	case 1:
+		out_8((u8 *)addr, val);
+		(void) in_8((u8 *)addr);
+		break;
+	case 2:
+		out_le16((u16 *)addr, val);
+		(void) in_le16((u16 *)addr);
+		break;
+	default:
+		out_le32((u32 *)addr, val);
+		(void) in_le32((u32 *)addr);
+		break;
+	}
+	return PCIBIOS_SUCCESSFUL;
+}
 
 static struct pci_ops macrisc_pci_ops =
 {
-	macrisc_read_config_byte,
-	macrisc_read_config_word,
-	macrisc_read_config_dword,
-	macrisc_write_config_byte,
-	macrisc_write_config_word,
-	macrisc_write_config_dword
+	macrisc_read_config,
+	macrisc_write_config
 };
 
 /*
  * Verifiy that a specific (bus, dev_fn) exists on chaos
  */
 static int __pmac
-chaos_validate_dev(struct pci_dev *dev, int offset)
+chaos_validate_dev(struct pci_bus *bus, int devfn, int offset)
 {
-	if(pci_device_to_OF_node(dev) == 0)
+	if (pci_busdev_to_OF_node(bus, devfn) == 0)
 		return PCIBIOS_DEVICE_NOT_FOUND;
-	if((dev->vendor == 0x106b) && (dev->device == 3) && (offset >= 0x10) &&
-	    (offset != 0x14) && (offset != 0x18) && (offset <= 0x24)) {
+	if (/*(dev->vendor == 0x106b) && (dev->device == 3) &&*/ (offset >= 0x10)
+	    && (offset != 0x14) && (offset != 0x18) && (offset <= 0x24)) {
 		return PCIBIOS_BAD_REGISTER_NUMBER;
 	}
 	return PCIBIOS_SUCCESSFUL;
 }
 
-#define CHAOS_PCI_OP(rw, size, type)					\
-static int __pmac							\
-chaos_##rw##_config_##size(struct pci_dev *dev, int off, type val)	\
-{									\
-	int result = chaos_validate_dev(dev, off);			\
-	if(result == PCIBIOS_BAD_REGISTER_NUMBER) {			\
-		cfg_##rw##_bad(val, size)				\
-		return PCIBIOS_BAD_REGISTER_NUMBER;			\
-	}								\
-	if(result == PCIBIOS_SUCCESSFUL)				\
-		return macrisc_##rw##_config_##size(dev, off, val);	\
-	return result;							\
-}
-
-CHAOS_PCI_OP(read, byte, u8 *)
-CHAOS_PCI_OP(read, word, u16 *)
-CHAOS_PCI_OP(read, dword, u32 *)
-CHAOS_PCI_OP(write, byte, u8)
-CHAOS_PCI_OP(write, word, u16)
-CHAOS_PCI_OP(write, dword, u32) 
+static int __pmac
+chaos_read_config(struct pci_bus *bus, unsigned int devfn, int offset,
+		  int len, u32 *val)
+{
+	int result = chaos_validate_dev(bus, devfn, offset);
+	if (result == PCIBIOS_BAD_REGISTER_NUMBER)
+		*val = ~0U;
+	if (result != PCIBIOS_SUCCESSFUL)
+		return result;
+	return macrisc_read_config(bus, devfn, offset, len, val);
+}
+
+static int __pmac
+chaos_write_config(struct pci_bus *bus, unsigned int devfn, int offset,
+		   int len, u32 val)
+{
+	int result = chaos_validate_dev(bus, devfn, offset);
+	if (result != PCIBIOS_SUCCESSFUL)
+		return result;
+	return macrisc_write_config(bus, devfn, offset, len, val);
+}
 
 static struct pci_ops chaos_pci_ops =
 {
-	chaos_read_config_byte,
-	chaos_read_config_word,
-	chaos_read_config_dword,
-	chaos_write_config_byte,
-	chaos_write_config_word,
-	chaos_write_config_dword
+	chaos_read_config,
+	chaos_write_config
 };
 
 
@@ -489,7 +506,8 @@
 	 * obtained from the OF device-tree
 	 */
 	pci_for_each_dev(dev) {
-		struct device_node* node = pci_device_to_OF_node(dev);
+		struct device_node *node;
+		node = pci_device_to_OF_node(dev);
 		/* this is the node, see if it has interrupts */
 		if (node && node->n_intrs > 0)
 			dev->irq = node->intrs[0].line;
diff -Nru a/arch/ppc/platforms/proc_rtas.c b/arch/ppc/platforms/proc_rtas.c
--- a/arch/ppc/platforms/proc_rtas.c	Mon Sep  9 10:36:18 2002
+++ b/arch/ppc/platforms/proc_rtas.c	Mon Sep  9 10:36:18 2002
@@ -164,26 +164,26 @@
 		size_t count, loff_t *ppos);
 
 struct file_operations ppc_rtas_poweron_operations = {
-	read:		ppc_rtas_poweron_read,
-	write:		ppc_rtas_poweron_write
+	.read =		ppc_rtas_poweron_read,
+	.write =	ppc_rtas_poweron_write
 };
 struct file_operations ppc_rtas_progress_operations = {
-	read:		ppc_rtas_progress_read,
-	write:		ppc_rtas_progress_write
+	.read =		ppc_rtas_progress_read,
+	.write =	ppc_rtas_progress_write
 };
 
 struct file_operations ppc_rtas_clock_operations = {
-	read:		ppc_rtas_clock_read,
-	write:		ppc_rtas_clock_write
+	.read =		ppc_rtas_clock_read,
+	.write =	ppc_rtas_clock_write
 };
 
 struct file_operations ppc_rtas_tone_freq_operations = {
-	read:		ppc_rtas_tone_freq_read,
-	write:		ppc_rtas_tone_freq_write
+	.read =		ppc_rtas_tone_freq_read,
+	.write =	ppc_rtas_tone_freq_write
 };
 struct file_operations ppc_rtas_tone_volume_operations = {
-	read:		ppc_rtas_tone_volume_read,
-	write:		ppc_rtas_tone_volume_write
+	.read =		ppc_rtas_tone_volume_read,
+	.write =	ppc_rtas_tone_volume_write
 };
 
 int ppc_rtas_find_all_sensors (void);
diff -Nru a/arch/ppc/xmon/start.c b/arch/ppc/xmon/start.c
--- a/arch/ppc/xmon/start.c	Mon Sep  9 10:35:52 2002
+++ b/arch/ppc/xmon/start.c	Mon Sep  9 10:35:52 2002
@@ -105,9 +105,9 @@
 
 static struct sysrq_key_op sysrq_xmon_op = 
 {
-	handler:	sysrq_handle_xmon,
-	help_msg:	"Xmon",
-	action_msg:	"Entering xmon\n",
+	.handler =	sysrq_handle_xmon,
+	.help_msg =	"Xmon",
+	.action_msg =	"Entering xmon\n",
 };
 #endif
 
diff -Nru a/arch/sh/mm/init.c b/arch/sh/mm/init.c
--- a/arch/sh/mm/init.c	Mon Sep  9 10:36:13 2002
+++ b/arch/sh/mm/init.c	Mon Sep  9 10:36:13 2002
@@ -123,11 +123,11 @@
 			zones_size[ZONE_DMA] = max_dma - start_pfn;
 			zones_size[ZONE_NORMAL] = low - max_dma;
 		}
-		free_area_init_node(0, NODE_DATA(0), 0, zones_size, __MEMORY_START, 0);
+		free_area_init_node(0, NODE_DATA(0), 0, zones_size, __MEMORY_START >> PAGE_SHIFT, 0);
 #ifdef CONFIG_DISCONTIGMEM
 		zones_size[ZONE_DMA] = __MEMORY_SIZE_2ND >> PAGE_SHIFT;
 		zones_size[ZONE_NORMAL] = 0;
-		free_area_init_node(1, NODE_DATA(1), 0, zones_size, __MEMORY_START_2ND, 0);
+		free_area_init_node(1, NODE_DATA(1), 0, zones_size, __MEMORY_START_2ND >> PAGE_SHIFT, 0);
 #endif
  	}
 }
diff -Nru a/arch/sparc/kernel/pcic.c b/arch/sparc/kernel/pcic.c
--- a/arch/sparc/kernel/pcic.c	Mon Sep  9 10:35:49 2002
+++ b/arch/sparc/kernel/pcic.c	Mon Sep  9 10:35:49 2002
@@ -193,39 +193,34 @@
 
 #define CONFIG_CMD(bus, device_fn, where) (0x80000000 | (((unsigned int)bus) << 16) | (((unsigned int)device_fn) << 8) | (where & ~3))
 
-static int pcic_read_config_dword(struct pci_dev *dev, int where, u32 *value);
-static int pcic_write_config_dword(struct pci_dev *dev, int where, u32 value);
-
-static int pcic_read_config_byte(struct pci_dev *dev, int where, u8 *value)
-{
-	unsigned int v;
-
-	pcic_read_config_dword(dev, where&~3, &v);
-	*value = 0xff & (v >> (8*(where & 3)));
-	return PCIBIOS_SUCCESSFUL;
-}
-
-static int pcic_read_config_word(struct pci_dev *dev, int where, u16 *value)
+static int pcic_read_config(struct pci_bus *bus, unsigned int devfn,
+			    int where, int size, u32 *value)
 {
 	unsigned int v;
-	if (where&1) return PCIBIOS_BAD_REGISTER_NUMBER;
+	unsigned char busnum = bus->number;
+	struct linux_pcic *pcic;
+	unsigned long flags;
+	/* unsigned char where; */
 
-	pcic_read_config_dword(dev, where&~3, &v);
-	*value = 0xffff & (v >> (8*(where & 3)));
-	return PCIBIOS_SUCCESSFUL;
-}
+	switch (size) {
+	case 1:
+		pcic_read_config(bus, devfn, where&~3, 4, &v);
+		*value = 0xff & (v >> (8*(where & 3)));
+		return PCIBIOS_SUCCESSFUL;
+		break;
 
-static int pcic_read_config_dword(struct pci_dev *dev, int where, u32 *value)
-{
-	unsigned char bus = dev->bus->number;
-	unsigned char device_fn = dev->devfn;
-	/* unsigned char where; */
+	case 2:
+		if (where&1) return PCIBIOS_BAD_REGISTER_NUMBER;
 
-	struct linux_pcic *pcic;
-	unsigned long flags;
+		pcic_read_config(bus, devfn, where&~3, 4, &v);
+		*value = 0xffff & (v >> (8*(where & 3)));
+		return PCIBIOS_SUCCESSFUL;
+		break;
+	}
 
+	/* size == 4, i.e. dword */
 	if (where&3) return PCIBIOS_BAD_REGISTER_NUMBER;
-	if (bus != 0) return PCIBIOS_DEVICE_NOT_FOUND;
+	if (busnum != 0) return PCIBIOS_DEVICE_NOT_FOUND;
 	pcic = &pcic0;
 
 	save_and_cli(flags);
@@ -233,7 +228,7 @@
 	pcic_speculative = 1;
 	pcic_trapped = 0;
 #endif
-	writel(CONFIG_CMD(bus,device_fn,where), pcic->pcic_config_space_addr);
+	writel(CONFIG_CMD(busnum,devfn,where), pcic->pcic_config_space_addr);
 #if 0 /* does not fail here */
 	nop();
 	if (pcic_trapped) {
@@ -257,52 +252,46 @@
 	return PCIBIOS_SUCCESSFUL;
 }
 
-static int pcic_write_config_byte(struct pci_dev *dev, int where, u8 value)
+static int pcic_write_config(struct pci_bus *bus, unsigned int devfn,
+			     int where, int size, u32 value)
 {
 	unsigned int v;
-
-	pcic_read_config_dword(dev, where&~3, &v);
-        v = (v & ~(0xff << (8*(where&3)))) |
-            ((0xff&(unsigned)value) << (8*(where&3)));
-	return pcic_write_config_dword(dev, where&~3, v);
-}
-
-static int pcic_write_config_word(struct pci_dev *dev, int where, u16 value)
-{
-	unsigned int v;
-
-	if (where&1) return PCIBIOS_BAD_REGISTER_NUMBER;
-	pcic_read_config_dword(dev, where&~3, &v);
-	v = (v & ~(0xffff << (8*(where&3)))) |
-	    ((0xffff&(unsigned)value) << (8*(where&3)));
-	return pcic_write_config_dword(dev, where&~3, v);
-}
-
-static int pcic_write_config_dword(struct pci_dev *dev, int where, u32 value)
-{
-	unsigned char bus = dev->bus->number;
-	unsigned char devfn = dev->devfn;
+	unsigned char busnum = bus->number;
 	struct linux_pcic *pcic;
 	unsigned long flags;
 
+	switch (size) {
+	case 1:
+		pcic_read_config(bus, devfn, where&~3, 4, &v);
+	        v = (v & ~(0xff << (8*(where&3)))) |
+	            ((0xff&(unsigned)value) << (8*(where&3)));
+		return pcic_write_config(bus, devfn, where&~3, 4, v);
+		break;
+
+	case 2:
+		if (where&1) return PCIBIOS_BAD_REGISTER_NUMBER;
+		pcic_read_config(bus, devfn, where&~3, 4, &v);
+		v = (v & ~(0xffff << (8*(where&3)))) |
+		    ((0xffff&(unsigned)value) << (8*(where&3)));
+		return pcic_write_config(bus, devfn, where&~3, 4, v);
+		break;
+	}
+
+	/* size == 4, i.e. dword */
 	if (where&3) return PCIBIOS_BAD_REGISTER_NUMBER;
-	if (bus != 0) return PCIBIOS_DEVICE_NOT_FOUND;
+	if (busnum != 0) return PCIBIOS_DEVICE_NOT_FOUND;
 	pcic = &pcic0;
 
 	save_and_cli(flags);
-	writel(CONFIG_CMD(bus,devfn,where), pcic->pcic_config_space_addr);
+	writel(CONFIG_CMD(busnum,devfn,where), pcic->pcic_config_space_addr);
 	writel(value, pcic->pcic_config_space_data + (where&4));
 	restore_flags(flags);
 	return PCIBIOS_SUCCESSFUL;
 }
 
 static struct pci_ops pcic_ops = {
-	pcic_read_config_byte,
-	pcic_read_config_word,
-	pcic_read_config_dword,
-	pcic_write_config_byte,
-	pcic_write_config_word,
-	pcic_write_config_dword,
+	.read =		pcic_read_config,
+	.write =	pcic_write_config,
 };
 
 /*
diff -Nru a/arch/sparc/kernel/process.c b/arch/sparc/kernel/process.c
--- a/arch/sparc/kernel/process.c	Mon Sep  9 10:35:59 2002
+++ b/arch/sparc/kernel/process.c	Mon Sep  9 10:35:59 2002
@@ -459,15 +459,16 @@
                              struct pt_regs *regs,
                              unsigned long stack_size)
 {
+	unsigned long tid_ptr = 0;
 	struct task_struct *p;
 
-	/* XXX This was spelled in DaveM's will and testament. Why? */
-	if (clone_flags & CLONE_IDLETASK) {
-		printk(KERN_DEBUG "Userland clone with CLONE_IDLETASK\n");
-		clone_flags &= ~CLONE_IDLETASK;
-	}
+	clone_flags &= ~CLONE_IDLETASK;
 
-	p = do_fork(clone_flags, stack_start, regs, stack_size);
+	if (clone_flags & (CLONE_SETTID | CLONE_CLEARTID))
+		tid_ptr = regs->u_regs[UREG_G2];
+
+	p = do_fork(clone_flags, stack_start,
+		    regs, stack_size, (int *) tid_ptr);
 	return IS_ERR(p) ? PTR_ERR(p) : p->pid;
 }
 
diff -Nru a/arch/sparc/mm/fault.c b/arch/sparc/mm/fault.c
--- a/arch/sparc/mm/fault.c	Mon Sep  9 10:36:01 2002
+++ b/arch/sparc/mm/fault.c	Mon Sep  9 10:36:01 2002
@@ -233,7 +233,7 @@
 	 * If we're in an interrupt or have no user
 	 * context, we must not take the fault..
 	 */
-        if (in_interrupt() || !mm)
+        if (in_atomic() || !mm)
                 goto no_context;
 
 	down_read(&mm->mmap_sem);
diff -Nru a/arch/sparc/mm/srmmu.c b/arch/sparc/mm/srmmu.c
--- a/arch/sparc/mm/srmmu.c	Mon Sep  9 10:36:11 2002
+++ b/arch/sparc/mm/srmmu.c	Mon Sep  9 10:36:11 2002
@@ -1311,7 +1311,7 @@
 		zholes_size[ZONE_HIGHMEM] = npages - calc_highpages();
 
 		free_area_init_node(0, NULL, NULL, zones_size,
-				    phys_base, zholes_size);
+				    phys_base >> PAGE_SHIFT, zholes_size);
 	}
 
 /* P3: easy to fix, todo. Current code is utterly broken, though. */
diff -Nru a/arch/sparc/mm/sun4c.c b/arch/sparc/mm/sun4c.c
--- a/arch/sparc/mm/sun4c.c	Mon Sep  9 10:36:01 2002
+++ b/arch/sparc/mm/sun4c.c	Mon Sep  9 10:36:01 2002
@@ -2074,7 +2074,7 @@
 		zholes_size[ZONE_HIGHMEM] = npages - calc_highpages();
 
 		free_area_init_node(0, NULL, NULL, zones_size,
-				    phys_base, zholes_size);
+				    phys_base >> PAGE_SHIFT, zholes_size);
 	}
 
 	cnt = 0;
diff -Nru a/arch/sparc64/defconfig b/arch/sparc64/defconfig
--- a/arch/sparc64/defconfig	Mon Sep  9 10:36:01 2002
+++ b/arch/sparc64/defconfig	Mon Sep  9 10:36:01 2002
@@ -388,6 +388,15 @@
 CONFIG_INET_ECN=y
 # CONFIG_SYN_COOKIES is not set
 CONFIG_IPV6=m
+
+#
+#    SCTP Configuration (EXPERIMENTAL)
+#
+CONFIG_IPV6_SCTP__=m
+CONFIG_IP_SCTP=m
+# CONFIG_SCTP_ADLER32 is not set
+# CONFIG_SCTP_DBG_MSG is not set
+# CONFIG_SCTP_DBG_OBJCNT is not set
 # CONFIG_ATM is not set
 CONFIG_VLAN_8021Q=m
 CONFIG_LLC=m
@@ -613,9 +622,6 @@
 # CONFIG_GAMEPORT_CS461x is not set
 CONFIG_SERIO=y
 CONFIG_SERIO_I8042=y
-CONFIG_I8042_REG_BASE=60
-CONFIG_I8042_KBD_IRQ=1
-CONFIG_I8042_AUX_IRQ=12
 # CONFIG_SERIO_SERPORT is not set
 # CONFIG_SERIO_CT82C710 is not set
 # CONFIG_SERIO_PARKBD is not set
diff -Nru a/arch/sparc64/kernel/ioctl32.c b/arch/sparc64/kernel/ioctl32.c
--- a/arch/sparc64/kernel/ioctl32.c	Mon Sep  9 10:36:01 2002
+++ b/arch/sparc64/kernel/ioctl32.c	Mon Sep  9 10:36:05 2002
@@ -99,6 +99,7 @@
 #include <linux/usbdevice_fs.h>
 #include <linux/nbd.h>
 #include <linux/random.h>
+#include <linux/filter.h>
 
 /* Use this to get at 32-bit user passed pointers. 
    See sys_sparc32.c for description about these. */
@@ -482,7 +483,7 @@
 }
 #endif
 
-static inline int dev_ifconf(unsigned int fd, unsigned int cmd, unsigned long arg)
+static int dev_ifconf(unsigned int fd, unsigned int cmd, unsigned long arg)
 {
 	struct ifconf32 ifc32;
 	struct ifconf ifc;
@@ -667,7 +668,44 @@
 	return err;
 }
 
-static inline int dev_ifsioc(unsigned int fd, unsigned int cmd, unsigned long arg)
+static __inline__ void *alloc_user_space(long len)
+{
+	struct pt_regs *regs = current_thread_info()->kregs;
+	unsigned long usp = regs->u_regs[UREG_I6];
+
+	if (!(test_thread_flag(TIF_32BIT)))
+		usp += STACK_BIAS;
+
+	return (void *) (usp - len);
+}
+
+static int siocdevprivate_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+	struct ifreq *u_ifreq64;
+	struct ifreq32 *u_ifreq32 = (struct ifreq32 *) arg;
+	char tmp_buf[IFNAMSIZ];
+	void *data64;
+	u32 data32;
+
+	if (copy_from_user(&tmp_buf[0], &(u_ifreq32->ifr_ifrn.ifrn_name[0]),
+			   IFNAMSIZ))
+		return -EFAULT;
+	if (__get_user(data32, &u_ifreq32->ifr_ifru.ifru_data))
+		return -EFAULT;
+	data64 = (void *) A(data32);
+
+	u_ifreq64 = alloc_user_space(sizeof(*u_ifreq64));
+
+	/* Don't check these user accesses, just let that get trapped
+	 * in the ioctl handler instead.
+	 */
+	copy_to_user(&u_ifreq64->ifr_ifrn.ifrn_name[0], &tmp_buf[0], IFNAMSIZ);
+	__put_user(data64, &u_ifreq64->ifr_ifru.ifru_data);
+
+	return sys_ioctl(fd, cmd, (unsigned long) u_ifreq64);
+}
+
+static int dev_ifsioc(unsigned int fd, unsigned int cmd, unsigned long arg)
 {
 	struct ifreq ifr;
 	mm_segment_t old_fs;
@@ -685,15 +723,6 @@
 		if (err)
 			return -EFAULT;
 		break;
-	case SIOCGPPPSTATS:
-	case SIOCGPPPCSTATS:
-	case SIOCGPPPVER:
-		if (copy_from_user(&ifr, (struct ifreq32 *)arg, sizeof(struct ifreq32)))
-			return -EFAULT;
-		ifr.ifr_data = (__kernel_caddr_t)get_free_page(GFP_KERNEL);
-		if (!ifr.ifr_data)
-			return -EAGAIN;
-		break;
 	default:
 		if (copy_from_user(&ifr, (struct ifreq32 *)arg, sizeof(struct ifreq32)))
 			return -EFAULT;
@@ -719,27 +748,6 @@
 			if (copy_to_user((struct ifreq32 *)arg, &ifr, sizeof(struct ifreq32)))
 				return -EFAULT;
 			break;
-		case SIOCGPPPSTATS:
-		case SIOCGPPPCSTATS:
-		case SIOCGPPPVER:
-		{
-			u32 data;
-			int len;
-
-			__get_user(data, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_data));
-			if(cmd == SIOCGPPPVER)
-				len = strlen((char *)ifr.ifr_data) + 1;
-			else if(cmd == SIOCGPPPCSTATS)
-				len = sizeof(struct ppp_comp_stats);
-			else
-				len = sizeof(struct ppp_stats);
-
-			len = copy_to_user((char *)A(data), ifr.ifr_data, len);
-			free_page((unsigned long)ifr.ifr_data);
-			if(len)
-				return -EFAULT;
-			break;
-		}
 		case SIOCGIFMAP:
 			err = copy_to_user((struct ifreq32 *)arg, &ifr, sizeof(ifr.ifr_name));
 			err |= __put_user(ifr.ifr_map.mem_start, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_map.mem_start));
@@ -752,14 +760,6 @@
 				err = -EFAULT;
 			break;
 		}
-	} else {
-		switch (cmd) {
-		case SIOCGPPPSTATS:
-		case SIOCGPPPCSTATS:
-		case SIOCGPPPVER:
-			free_page((unsigned long)ifr.ifr_data);
-			break;
-		}
 	}
 	return err;
 }
@@ -798,7 +798,7 @@
 
 extern struct socket *sockfd_lookup(int fd, int *err);
 
-static inline int routing_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
+static int routing_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
 {
 	int ret;
 	void *r = NULL;
@@ -856,7 +856,7 @@
 	u32 start;
 };
                         
-static inline int hdio_getgeo(unsigned int fd, unsigned int cmd, unsigned long arg)
+static int hdio_getgeo(unsigned int fd, unsigned int cmd, unsigned long arg)
 {
 	mm_segment_t old_fs = get_fs();
 	struct hd_geometry geo;
@@ -883,7 +883,7 @@
 #define FBIOPUTCMAP32	_IOW('F', 3, struct fbcmap32)
 #define FBIOGETCMAP32	_IOW('F', 4, struct fbcmap32)
 
-static inline int fbiogetputcmap(unsigned int fd, unsigned int cmd, unsigned long arg)
+static int fbiogetputcmap(unsigned int fd, unsigned int cmd, unsigned long arg)
 {
 	struct fbcmap f;
 	int ret;
@@ -934,7 +934,7 @@
 #define FBIOSCURSOR32	_IOW('F', 24, struct fbcursor32)
 #define FBIOGCURSOR32	_IOW('F', 25, struct fbcursor32)
 
-static inline int fbiogscursor(unsigned int fd, unsigned int cmd, unsigned long arg)
+static int fbiogscursor(unsigned int fd, unsigned int cmd, unsigned long arg)
 {
 	struct fbcursor f;
 	int ret;
@@ -1669,6 +1669,40 @@
 	return err;
 }
 
+struct sock_fprog32 {
+	__u16	len;
+	__u32	filter;
+};
+
+#define PPPIOCSPASS32	_IOW('t', 71, struct sock_fprog32)
+#define PPPIOCSACTIVE32	_IOW('t', 70, struct sock_fprog32)
+
+static int ppp_sock_fprog_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+	struct sock_fprog32 *u_fprog32 = (struct sock_fprog32 *) arg;
+	struct sock_fprog *u_fprog64 = alloc_user_space(sizeof(struct sock_fprog));
+	void *fptr64;
+	u32 fptr32;
+	u16 flen;
+
+	if (get_user(flen, &u_fprog32->len) ||
+	    get_user(fptr32, &u_fprog32->filter))
+		return -EFAULT;
+
+	fptr64 = (void *) A(fptr32);
+
+	if (put_user(flen, &u_fprog64->len) ||
+	    put_user(fptr64, &u_fprog64->filter))
+		return -EFAULT;
+
+	if (cmd == PPPIOCSPASS32)
+		cmd = PPPIOCSPASS;
+	else
+		cmd = PPPIOCSACTIVE;
+
+	return sys_ioctl(fd, cmd, (unsigned long) u_fprog64);
+}
+
 struct ppp_option_data32 {
 	__kernel_caddr_t32	ptr;
 	__u32			length;
@@ -3834,8 +3868,7 @@
 #define MEMWRITEOOB32 	_IOWR('M',3,struct mtd_oob_buf32)
 #define MEMREADOOB32 	_IOWR('M',4,struct mtd_oob_buf32)
 
-static inline int 
-mtd_rw_oob(unsigned int fd, unsigned int cmd, unsigned long arg)
+static int mtd_rw_oob(unsigned int fd, unsigned int cmd, unsigned long arg)
 {
 	mm_segment_t 			old_fs 	= get_fs();
 	struct mtd_oob_buf32	*uarg 	= (struct mtd_oob_buf32 *)arg;
@@ -4239,13 +4272,16 @@
 COMPATIBLE_IOCTL(PPPIOCSMRU)
 COMPATIBLE_IOCTL(PPPIOCSMAXCID)
 COMPATIBLE_IOCTL(PPPIOCGXASYNCMAP)
-COMPATIBLE_IOCTL(LPGETSTATUS)
 COMPATIBLE_IOCTL(PPPIOCSXASYNCMAP)
 COMPATIBLE_IOCTL(PPPIOCXFERUNIT)
+/* PPPIOCSCOMPRESS is translated */
 COMPATIBLE_IOCTL(PPPIOCGNPMODE)
 COMPATIBLE_IOCTL(PPPIOCSNPMODE)
+/* PPPIOCSPASS is translated */
+/* PPPIOCSACTIVE is translated */
 COMPATIBLE_IOCTL(PPPIOCGDEBUG)
 COMPATIBLE_IOCTL(PPPIOCSDEBUG)
+/* PPPIOCGIDLE is translated */
 COMPATIBLE_IOCTL(PPPIOCNEWUNIT)
 COMPATIBLE_IOCTL(PPPIOCATTACH)
 COMPATIBLE_IOCTL(PPPIOCDETACH)
@@ -4254,6 +4290,8 @@
 COMPATIBLE_IOCTL(PPPIOCDISCONN)
 COMPATIBLE_IOCTL(PPPIOCATTCHAN)
 COMPATIBLE_IOCTL(PPPIOCGCHAN)
+/* LP */
+COMPATIBLE_IOCTL(LPGETSTATUS)
 /* PPPOX */
 COMPATIBLE_IOCTL(PPPOEIOCSFWD)
 COMPATIBLE_IOCTL(PPPOEIOCDFWD)
@@ -4636,9 +4674,6 @@
 HANDLE_IOCTL(SIOCSIFNETMASK, dev_ifsioc)
 HANDLE_IOCTL(SIOCSIFPFLAGS, dev_ifsioc)
 HANDLE_IOCTL(SIOCGIFPFLAGS, dev_ifsioc)
-HANDLE_IOCTL(SIOCGPPPSTATS, dev_ifsioc)
-HANDLE_IOCTL(SIOCGPPPCSTATS, dev_ifsioc)
-HANDLE_IOCTL(SIOCGPPPVER, dev_ifsioc)
 HANDLE_IOCTL(SIOCGIFTXQLEN, dev_ifsioc)
 HANDLE_IOCTL(SIOCSIFTXQLEN, dev_ifsioc)
 HANDLE_IOCTL(SIOCETHTOOL, ethtool_ioctl)
@@ -4682,6 +4717,8 @@
 HANDLE_IOCTL(SG_IO,sg_ioctl_trans)
 HANDLE_IOCTL(PPPIOCGIDLE32, ppp_ioctl_trans)
 HANDLE_IOCTL(PPPIOCSCOMPRESS32, ppp_ioctl_trans)
+HANDLE_IOCTL(PPPIOCSPASS32, ppp_sock_fprog_ioctl_trans)
+HANDLE_IOCTL(PPPIOCSACTIVE32, ppp_sock_fprog_ioctl_trans)
 HANDLE_IOCTL(MTIOCGET32, mt_ioctl_trans)
 HANDLE_IOCTL(MTIOCPOS32, mt_ioctl_trans)
 HANDLE_IOCTL(MTIOCGETCONFIG32, mt_ioctl_trans)
@@ -4896,6 +4933,9 @@
 	if (t) {
 		handler = (void *)(long)t->handler;
 		error = handler(fd, cmd, arg, filp);
+	} else if (cmd >= SIOCDEVPRIVATE &&
+		   cmd <= (SIOCDEVPRIVATE + 15)) {
+		error = siocdevprivate_ioctl(fd, cmd, arg);
 	} else {
 		static int count;
 		if (++count <= 20)
diff -Nru a/arch/sparc64/kernel/pci_psycho.c b/arch/sparc64/kernel/pci_psycho.c
--- a/arch/sparc64/kernel/pci_psycho.c	Mon Sep  9 10:36:11 2002
+++ b/arch/sparc64/kernel/pci_psycho.c	Mon Sep  9 10:36:11 2002
@@ -107,119 +107,66 @@
 
 /* PSYCHO PCI configuration space accessors. */
 
-static int psycho_read_byte(struct pci_dev *dev, int where, u8 *value)
+static int psycho_read_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn,
+			       int where, int size, u32 *value)
 {
-	struct pci_pbm_info *pbm = pci_bus2pbm[dev->bus->number];
-	unsigned char bus = dev->bus->number;
-	unsigned int devfn = dev->devfn;
-	u8 *addr;
-
-	*value = 0xff;
-	addr = psycho_pci_config_mkaddr(pbm, bus, devfn, where);
-	if (!addr)
-		return PCIBIOS_SUCCESSFUL;
-
-	if (psycho_out_of_range(pbm, bus, devfn))
-		return PCIBIOS_SUCCESSFUL;
-	pci_config_read8(addr, value);
-	return PCIBIOS_SUCCESSFUL;
-}
-
-static int psycho_read_word(struct pci_dev *dev, int where, u16 *value)
-{
-	struct pci_pbm_info *pbm = pci_bus2pbm[dev->bus->number];
-	unsigned char bus = dev->bus->number;
-	unsigned int devfn = dev->devfn;
-	u16 *addr;
-
-	*value = 0xffff;
-	addr = psycho_pci_config_mkaddr(pbm, bus, devfn, where);
-	if (!addr)
-		return PCIBIOS_SUCCESSFUL;
-
-	if (psycho_out_of_range(pbm, bus, devfn))
-		return PCIBIOS_SUCCESSFUL;
-
-	if (where & 0x01) {
-		printk("pcibios_read_config_word: misaligned reg [%x]\n",
-		       where);
-		return PCIBIOS_SUCCESSFUL;
-	}
-	pci_config_read16(addr, value);
-	return PCIBIOS_SUCCESSFUL;
-}
-
-static int psycho_read_dword(struct pci_dev *dev, int where, u32 *value)
-{
-	struct pci_pbm_info *pbm = pci_bus2pbm[dev->bus->number];
-	unsigned char bus = dev->bus->number;
-	unsigned int devfn = dev->devfn;
+	struct pci_pbm_info *pbm = pci_bus2pbm[bus_dev->number];
+	unsigned char bus = bus_dev->number;
 	u32 *addr;
+	u16 tmp16;
+	u8 tmp8;
 
-	*value = 0xffffffff;
-	addr = psycho_pci_config_mkaddr(pbm, bus, devfn, where);
-	if (!addr)
-		return PCIBIOS_SUCCESSFUL;
-
-	if (psycho_out_of_range(pbm, bus, devfn))
-		return PCIBIOS_SUCCESSFUL;
-
-	if (where & 0x03) {
-		printk("pcibios_read_config_dword: misaligned reg [%x]\n",
-		       where);
-		return PCIBIOS_SUCCESSFUL;
+	switch (size) {
+	case 1:
+		*value = 0xff;
+		break;
+	case 2:
+		*value = 0xffff;
+		break;
+	case 4:
+		*value = 0xffffffff;
+		break;
 	}
 
-	pci_config_read32(addr, value);
-	return PCIBIOS_SUCCESSFUL;
-}
-
-static int psycho_write_byte(struct pci_dev *dev, int where, u8 value)
-{
-	struct pci_pbm_info *pbm = pci_bus2pbm[dev->bus->number];
-	unsigned char bus = dev->bus->number;
-	unsigned int devfn = dev->devfn;
-	u8 *addr;
-
-	addr = psycho_pci_config_mkaddr(pbm, bus, devfn, where);
-	if (!addr)
-		return PCIBIOS_SUCCESSFUL;
-
-	if (psycho_out_of_range(pbm, bus, devfn))
-		return PCIBIOS_SUCCESSFUL;
-
-	pci_config_write8(addr, value);
-	return PCIBIOS_SUCCESSFUL;
-}
-
-static int psycho_write_word(struct pci_dev *dev, int where, u16 value)
-{
-	struct pci_pbm_info *pbm = pci_bus2pbm[dev->bus->number];
-	unsigned char bus = dev->bus->number;
-	unsigned int devfn = dev->devfn;
-	u16 *addr;
-
 	addr = psycho_pci_config_mkaddr(pbm, bus, devfn, where);
 	if (!addr)
 		return PCIBIOS_SUCCESSFUL;
 
 	if (psycho_out_of_range(pbm, bus, devfn))
 		return PCIBIOS_SUCCESSFUL;
-
-	if (where & 0x01) {
-		printk("pcibios_write_config_word: misaligned reg [%x]\n",
-		       where);
-		return PCIBIOS_SUCCESSFUL;
+	switch (size) {
+	case 1:
+		pci_config_read8((u8 *)addr, &tmp8);
+		*value = (u32) tmp8;
+		break;
+
+	case 2:
+		if (where & 0x01) {
+			printk("pci_read_config_word: misaligned reg [%x]\n",
+			       where);
+			return PCIBIOS_SUCCESSFUL;
+		}
+		pci_config_read16((u16 *)addr, &tmp16);
+		*value = (u32) tmp16;
+		break;
+
+	case 4:
+		if (where & 0x03) {
+			printk("pci_read_config_dword: misaligned reg [%x]\n",
+			       where);
+			return PCIBIOS_SUCCESSFUL;
+		}
+		pci_config_read32(addr, value);
+		break;
 	}
-	pci_config_write16(addr, value);
 	return PCIBIOS_SUCCESSFUL;
 }
 
-static int psycho_write_dword(struct pci_dev *dev, int where, u32 value)
+static int psycho_write_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn,
+				int where, int size, u32 value)
 {
-	struct pci_pbm_info *pbm = pci_bus2pbm[dev->bus->number];
-	unsigned char bus = dev->bus->number;
-	unsigned int devfn = dev->devfn;
+	struct pci_pbm_info *pbm = pci_bus2pbm[bus_dev->number];
+	unsigned char bus = bus_dev->number;
 	u32 *addr;
 
 	addr = psycho_pci_config_mkaddr(pbm, bus, devfn, where);
@@ -229,22 +176,34 @@
 	if (psycho_out_of_range(pbm, bus, devfn))
 		return PCIBIOS_SUCCESSFUL;
 
-	if (where & 0x03) {
-		printk("pcibios_write_config_dword: misaligned reg [%x]\n",
-		       where);
-		return PCIBIOS_SUCCESSFUL;
+	switch (size) {
+	case 1:
+		pci_config_write8((u8 *)addr, value);
+		break;
+
+	case 2:
+		if (where & 0x01) {
+			printk("pci_write_config_word: misaligned reg [%x]\n",
+			       where);
+			return PCIBIOS_SUCCESSFUL;
+		}
+		pci_config_write16((u16 *)addr, value);
+		break;
+
+	case 4:
+		if (where & 0x03) {
+			printk("pci_write_config_dword: misaligned reg [%x]\n",
+			       where);
+			return PCIBIOS_SUCCESSFUL;
+		}
+		pci_config_write32(addr, value);
 	}
-	pci_config_write32(addr, value);
 	return PCIBIOS_SUCCESSFUL;
 }
 
 static struct pci_ops psycho_ops = {
-	psycho_read_byte,
-	psycho_read_word,
-	psycho_read_dword,
-	psycho_write_byte,
-	psycho_write_word,
-	psycho_write_dword
+	.read =		psycho_read_pci_cfg,
+	.write =	psycho_write_pci_cfg,
 };
 
 /* PSYCHO interrupt mapping support. */
diff -Nru a/arch/sparc64/kernel/pci_sabre.c b/arch/sparc64/kernel/pci_sabre.c
--- a/arch/sparc64/kernel/pci_sabre.c	Mon Sep  9 10:36:11 2002
+++ b/arch/sparc64/kernel/pci_sabre.c	Mon Sep  9 10:36:11 2002
@@ -258,56 +258,27 @@
 		 PCI_SLOT(devfn) > 8));
 }
 
-static int __sabre_read_byte(struct pci_dev *dev, int where, u8 *value)
+static int __sabre_read_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn,
+				int where, int size, u32 *value)
 {
-	struct pci_pbm_info *pbm = pci_bus2pbm[dev->bus->number];
-	unsigned char bus = dev->bus->number;
-	unsigned int devfn = dev->devfn;
-	u8 *addr;
-
-	*value = 0xff;
-	addr = sabre_pci_config_mkaddr(pbm, bus, devfn, where);
-	if (!addr)
-		return PCIBIOS_SUCCESSFUL;
-
-	if (__sabre_out_of_range(pbm, bus, devfn))
-		return PCIBIOS_SUCCESSFUL;
-	pci_config_read8(addr, value);
-	return PCIBIOS_SUCCESSFUL;
-}
-
-static int __sabre_read_word(struct pci_dev *dev, int where, u16 *value)
-{
-	struct pci_pbm_info *pbm = pci_bus2pbm[dev->bus->number];
-	unsigned char bus = dev->bus->number;
-	unsigned int devfn = dev->devfn;
-	u16 *addr;
-
-	*value = 0xffff;
-	addr = sabre_pci_config_mkaddr(pbm, bus, devfn, where);
-	if (!addr)
-		return PCIBIOS_SUCCESSFUL;
-
-	if (__sabre_out_of_range(pbm, bus, devfn))
-		return PCIBIOS_SUCCESSFUL;
+	struct pci_pbm_info *pbm = pci_bus2pbm[bus_dev->number];
+	unsigned char bus = bus_dev->number;
+	u32 *addr;
+	u16 tmp16;
+	u8 tmp8;
 
-	if (where & 0x01) {
-		printk("pcibios_read_config_word: misaligned reg [%x]\n",
-		       where);
-		return PCIBIOS_SUCCESSFUL;
+	switch (size) {
+	case 1:
+		*value = 0xff;
+		break;
+	case 2:
+		*value = 0xffff;
+		break;
+	case 4:
+		*value = 0xffffffff;
+		break;
 	}
-	pci_config_read16(addr, value);
-	return PCIBIOS_SUCCESSFUL;
-}
 
-static int __sabre_read_dword(struct pci_dev *dev, int where, u32 *value)
-{
-	struct pci_pbm_info *pbm = pci_bus2pbm[dev->bus->number];
-	unsigned char bus = dev->bus->number;
-	unsigned int devfn = dev->devfn;
-	u32 *addr;
-
-	*value = 0xffffffff;
 	addr = sabre_pci_config_mkaddr(pbm, bus, devfn, where);
 	if (!addr)
 		return PCIBIOS_SUCCESSFUL;
@@ -315,86 +286,110 @@
 	if (__sabre_out_of_range(pbm, bus, devfn))
 		return PCIBIOS_SUCCESSFUL;
 
-	if (where & 0x03) {
-		printk("pcibios_read_config_dword: misaligned reg [%x]\n",
-		       where);
-		return PCIBIOS_SUCCESSFUL;
-	}
-	pci_config_read32(addr, value);
-	return PCIBIOS_SUCCESSFUL;
-}
-
-static int sabre_read_byte(struct pci_dev *dev, int where, u8 *value)
-{
-	if (dev->bus->number)
-		return __sabre_read_byte(dev, where, value);
-
-	if (sabre_out_of_range(dev->devfn)) {
-		*value = 0xff;
-		return PCIBIOS_SUCCESSFUL;
+	switch (size) {
+	case 1:
+		pci_config_read8((u8 *) addr, &tmp8);
+		*value = tmp8;
+		break;
+
+	case 2:
+		if (where & 0x01) {
+			printk("pci_read_config_word: misaligned reg [%x]\n",
+			       where);
+			return PCIBIOS_SUCCESSFUL;
+		}
+		pci_config_read16((u16 *) addr, &tmp16);
+		*value = tmp16;
+		break;
+
+	case 4:
+		if (where & 0x03) {
+			printk("pci_read_config_dword: misaligned reg [%x]\n",
+			       where);
+			return PCIBIOS_SUCCESSFUL;
+		}
+		pci_config_read32(addr, value);
+		break;
 	}
 
-	if (where < 8) {
-		u16 tmp;
-
-		__sabre_read_word(dev, where & ~1, &tmp);
-		if (where & 1)
-			*value = tmp >> 8;
-		else
-			*value = tmp & 0xff;
-		return PCIBIOS_SUCCESSFUL;
-	} else
-		return __sabre_read_byte(dev, where, value);
+	return PCIBIOS_SUCCESSFUL;
 }
 
-static int sabre_read_word(struct pci_dev *dev, int where, u16 *value)
+static int sabre_read_pci_cfg(struct pci_bus *bus, unsigned int devfn,
+			      int where, int size, u32 *value)
 {
-	if (dev->bus->number)
-		return __sabre_read_word(dev, where, value);
+	if (bus->number)
+		return __sabre_read_pci_cfg(bus, devfn, where, size, value);
 
-	if (sabre_out_of_range(dev->devfn)) {
-		*value = 0xffff;
+	if (sabre_out_of_range(devfn)) {
+		switch (size) {
+		case 1:
+			*value = 0xff;
+			break;
+		case 2:
+			*value = 0xffff;
+			break;
+		case 4:
+			*value = 0xffffffff;
+			break;
+		}
 		return PCIBIOS_SUCCESSFUL;
 	}
 
-	if (where < 8)
-		return __sabre_read_word(dev, where, value);
-	else {
-		u8 tmp;
+	switch (size) {
+	case 1:
+		if (where < 8) {
+			u32 tmp32;
+			u16 tmp16;
+
+			__sabre_read_pci_cfg(bus, devfn, where & ~1, 2, &tmp32);
+			tmp16 = (u16) tmp32;
+			if (where & 1)
+				*value = tmp16 >> 8;
+			else
+				*value = tmp16 & 0xff;
+		} else
+			return __sabre_read_pci_cfg(bus, devfn, where, 1, value);
+		break;
+
+	case 2:
+		if (where < 8)
+			return __sabre_read_pci_cfg(bus, devfn, where, 2, value);
+		else {
+			u32 tmp32;
+			u8 tmp8;
+
+			__sabre_read_pci_cfg(bus, devfn, where, 1, &tmp32);
+			tmp8 = (u8) tmp32;
+			*value = tmp8;
+			__sabre_read_pci_cfg(bus, devfn, where + 1, 1, &tmp32);
+			tmp8 = (u8) tmp32;
+			*value |= tmp8 << 8;
+		}
+		break;
 
-		__sabre_read_byte(dev, where, &tmp);
-		*value = tmp;
-		__sabre_read_byte(dev, where + 1, &tmp);
-		*value |= tmp << 8;
-		return PCIBIOS_SUCCESSFUL;
+	case 4: {
+		u32 tmp32;
+		u16 tmp16;
+
+		sabre_read_pci_cfg(bus, devfn, where, 2, &tmp32);
+		tmp16 = (u16) tmp32;
+		*value = tmp16;
+		sabre_read_pci_cfg(bus, devfn, where + 2, 2, &tmp32);
+		tmp16 = (u16) tmp32;
+		*value |= tmp16 << 16;
+		break;
 	}
-}
-
-static int sabre_read_dword(struct pci_dev *dev, int where, u32 *value)
-{
-	u16 tmp;
-
-	if (dev->bus->number)
-		return __sabre_read_dword(dev, where, value);
-
-	if (sabre_out_of_range(dev->devfn)) {
-		*value = 0xffffffff;
-		return PCIBIOS_SUCCESSFUL;
 	}
-
-	sabre_read_word(dev, where, &tmp);
-	*value = tmp;
-	sabre_read_word(dev, where + 2, &tmp);
-	*value |= tmp << 16;
 	return PCIBIOS_SUCCESSFUL;
 }
 
-static int __sabre_write_byte(struct pci_dev *dev, int where, u8 value)
+static int __sabre_write_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn,
+				 int where, int size, u32 value)
 {
-	struct pci_pbm_info *pbm = pci_bus2pbm[dev->bus->number];
-	unsigned char bus = dev->bus->number;
-	unsigned int devfn = dev->devfn;
-	u8 *addr;
+	struct pci_pbm_info *pbm = pci_bus2pbm[bus_dev->number];
+	unsigned char bus = bus_dev->number;
+	u32 *addr;
 
 	addr = sabre_pci_config_mkaddr(pbm, bus, devfn, where);
 	if (!addr)
@@ -402,117 +397,82 @@
 
 	if (__sabre_out_of_range(pbm, bus, devfn))
 		return PCIBIOS_SUCCESSFUL;
-	pci_config_write8(addr, value);
-	return PCIBIOS_SUCCESSFUL;
-}
-
-static int __sabre_write_word(struct pci_dev *dev, int where, u16 value)
-{
-	struct pci_pbm_info *pbm = pci_bus2pbm[dev->bus->number];
-	unsigned char bus = dev->bus->number;
-	unsigned int devfn = dev->devfn;
-	u16 *addr;
-
-	addr = sabre_pci_config_mkaddr(pbm, bus, devfn, where);
-	if (!addr)
-		return PCIBIOS_SUCCESSFUL;
 
-	if (__sabre_out_of_range(pbm, bus, devfn))
-		return PCIBIOS_SUCCESSFUL;
+	switch (size) {
+	case 1:
+		pci_config_write8((u8 *) addr, value);
+		break;
+
+	case 2:
+		if (where & 0x01) {
+			printk("pci_write_config_word: misaligned reg [%x]\n",
+			       where);
+			return PCIBIOS_SUCCESSFUL;
+		}
+		pci_config_write16((u16 *) addr, value);
+		break;
 
-	if (where & 0x01) {
-		printk("pcibios_write_config_word: misaligned reg [%x]\n",
-		       where);
-		return PCIBIOS_SUCCESSFUL;
+	case 4:
+		if (where & 0x03) {
+			printk("pci_write_config_dword: misaligned reg [%x]\n",
+			       where);
+			return PCIBIOS_SUCCESSFUL;
+		}
+		pci_config_write32(addr, value);
+		break;
 	}
-	pci_config_write16(addr, value);
-	return PCIBIOS_SUCCESSFUL;
-}
 
-static int __sabre_write_dword(struct pci_dev *dev, int where, u32 value)
-{
-	struct pci_pbm_info *pbm = pci_bus2pbm[dev->bus->number];
-	unsigned char bus = dev->bus->number;
-	unsigned int devfn = dev->devfn;
-	u32 *addr;
-
-	addr = sabre_pci_config_mkaddr(pbm, bus, devfn, where);
-	if (!addr)
-		return PCIBIOS_SUCCESSFUL;
-
-	if (__sabre_out_of_range(pbm, bus, devfn))
-		return PCIBIOS_SUCCESSFUL;
-
-	if (where & 0x03) {
-		printk("pcibios_write_config_dword: misaligned reg [%x]\n",
-		       where);
-		return PCIBIOS_SUCCESSFUL;
-	}
-	pci_config_write32(addr, value);
 	return PCIBIOS_SUCCESSFUL;
 }
 
-static int sabre_write_byte(struct pci_dev *dev, int where, u8 value)
+static int sabre_write_pci_cfg(struct pci_bus *bus, unsigned int devfn,
+			       int where, int size, u32 value)
 {
-	if (dev->bus->number)
-		return __sabre_write_byte(dev, where, value);
+	if (bus->number)
+		return __sabre_write_pci_cfg(bus, devfn, where, size, value);
 
-	if (sabre_out_of_range(dev->devfn))
+	if (sabre_out_of_range(devfn))
 		return PCIBIOS_SUCCESSFUL;
 
-	if (where < 8) {
-		u16 tmp;
-
-		__sabre_read_word(dev, where & ~1, &tmp);
-		if (where & 1) {
-			value &= 0x00ff;
-			value |= tmp << 8;
-		} else {
-			value &= 0xff00;
-			value |= tmp;
+	switch (size) {
+	case 1:
+		if (where < 8) {
+			u32 tmp32;
+			u16 tmp16;
+
+			__sabre_read_pci_cfg(bus, devfn, where & ~1, 2, &tmp32);
+			tmp16 = (u16) tmp32;
+			if (where & 1) {
+				value &= 0x00ff;
+				value |= tmp16 << 8;
+			} else {
+				value &= 0xff00;
+				value |= tmp16;
+			}
+			tmp32 = (u32) tmp16;
+			return __sabre_write_pci_cfg(bus, devfn, where & ~1, 2, tmp32);
+		} else
+			return __sabre_write_pci_cfg(bus, devfn, where, 1, value);
+		break;
+	case 2:
+		if (where < 8)
+			return __sabre_write_pci_cfg(bus, devfn, where, 2, value);
+		else {
+			__sabre_write_pci_cfg(bus, devfn, where, 1, value & 0xff);
+			__sabre_write_pci_cfg(bus, devfn, where + 1, 1, value >> 8);
 		}
-		return __sabre_write_word(dev, where & ~1, tmp);
-	} else
-		return __sabre_write_byte(dev, where, value);
-}
-
-static int sabre_write_word(struct pci_dev *dev, int where, u16 value)
-{
-	if (dev->bus->number)
-		return __sabre_write_word(dev, where, value);
-
-	if (sabre_out_of_range(dev->devfn))
-		return PCIBIOS_SUCCESSFUL;
-
-	if (where < 8)
-		return __sabre_write_word(dev, where, value);
-	else {
-		__sabre_write_byte(dev, where, value & 0xff);
-		__sabre_write_byte(dev, where + 1, value >> 8);
-		return PCIBIOS_SUCCESSFUL;
+		break;
+	case 4:
+		sabre_write_pci_cfg(bus, devfn, where, 2, value & 0xffff);
+		sabre_write_pci_cfg(bus, devfn, where + 2, 2, value >> 16);
+		break;
 	}
-}
-
-static int sabre_write_dword(struct pci_dev *dev, int where, u32 value)
-{
-	if (dev->bus->number)
-		return __sabre_write_dword(dev, where, value);
-
-	if (sabre_out_of_range(dev->devfn))
-		return PCIBIOS_SUCCESSFUL;
-
-	sabre_write_word(dev, where, value & 0xffff);
-	sabre_write_word(dev, where + 2, value >> 16);
 	return PCIBIOS_SUCCESSFUL;
 }
 
 static struct pci_ops sabre_ops = {
-	sabre_read_byte,
-	sabre_read_word,
-	sabre_read_dword,
-	sabre_write_byte,
-	sabre_write_word,
-	sabre_write_dword
+	.read =		sabre_read_pci_cfg,
+	.write =	sabre_write_pci_cfg,
 };
 
 static unsigned long sabre_pcislot_imap_offset(unsigned long ino)
@@ -1112,31 +1072,41 @@
 
 		if (pdev->vendor == PCI_VENDOR_ID_SUN &&
 		    pdev->device == PCI_DEVICE_ID_SUN_SIMBA) {
-			u16 word;
+			u32 word32;
+			u16 word16;
 
-			sabre_read_word(pdev, PCI_COMMAND, &word);
-			word |= PCI_COMMAND_SERR | PCI_COMMAND_PARITY |
+			sabre_read_pci_cfg(pdev->bus, pdev->devfn,
+					   PCI_COMMAND, 2, &word32);
+			word16 = (u16) word32;
+			word16 |= PCI_COMMAND_SERR | PCI_COMMAND_PARITY |
 				PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY |
 				PCI_COMMAND_IO;
-			sabre_write_word(pdev, PCI_COMMAND, word);
+			word32 = (u32) word16;
+			sabre_write_pci_cfg(pdev->bus, pdev->devfn,
+					    PCI_COMMAND, 2, word32);
 
 			/* Status register bits are "write 1 to clear". */
-			sabre_write_word(pdev, PCI_STATUS, 0xffff);
-			sabre_write_word(pdev, PCI_SEC_STATUS, 0xffff);
+			sabre_write_pci_cfg(pdev->bus, pdev->devfn,
+					    PCI_STATUS, 2, 0xffff);
+			sabre_write_pci_cfg(pdev->bus, pdev->devfn,
+					    PCI_SEC_STATUS, 2, 0xffff);
 
 			/* Use a primary/seconday latency timer value
 			 * of 64.
 			 */
-			sabre_write_byte(pdev, PCI_LATENCY_TIMER, 64);
-			sabre_write_byte(pdev, PCI_SEC_LATENCY_TIMER, 64);
+			sabre_write_pci_cfg(pdev->bus, pdev->devfn,
+					    PCI_LATENCY_TIMER, 1, 64);
+			sabre_write_pci_cfg(pdev->bus, pdev->devfn,
+					    PCI_SEC_LATENCY_TIMER, 1, 64);
 
 			/* Enable reporting/forwarding of master aborts,
 			 * parity, and SERR.
 			 */
-			sabre_write_byte(pdev, PCI_BRIDGE_CONTROL,
-					 (PCI_BRIDGE_CTL_PARITY |
-					  PCI_BRIDGE_CTL_SERR |
-					  PCI_BRIDGE_CTL_MASTER_ABORT));
+			sabre_write_pci_cfg(pdev->bus, pdev->devfn,
+					    PCI_BRIDGE_CONTROL, 1,
+					    (PCI_BRIDGE_CTL_PARITY |
+					     PCI_BRIDGE_CTL_SERR |
+					     PCI_BRIDGE_CTL_MASTER_ABORT));
 		}
 	}
 }
diff -Nru a/arch/sparc64/kernel/pci_schizo.c b/arch/sparc64/kernel/pci_schizo.c
--- a/arch/sparc64/kernel/pci_schizo.c	Mon Sep  9 10:36:13 2002
+++ b/arch/sparc64/kernel/pci_schizo.c	Mon Sep  9 10:36:13 2002
@@ -124,119 +124,66 @@
 
 /* SCHIZO PCI configuration space accessors. */
 
-static int schizo_read_byte(struct pci_dev *dev, int where, u8 *value)
+static int schizo_read_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn,
+			       int where, int size, u32 *value)
 {
-	struct pci_pbm_info *pbm = pci_bus2pbm[dev->bus->number];
-	unsigned char bus = dev->bus->number;
-	unsigned int devfn = dev->devfn;
-	u8 *addr;
-
-	*value = 0xff;
-	addr = schizo_pci_config_mkaddr(pbm, bus, devfn, where);
-	if (!addr)
-		return PCIBIOS_SUCCESSFUL;
-
-	if (schizo_out_of_range(pbm, bus, devfn))
-		return PCIBIOS_SUCCESSFUL;
-	pci_config_read8(addr, value);
-	return PCIBIOS_SUCCESSFUL;
-}
-
-static int schizo_read_word(struct pci_dev *dev, int where, u16 *value)
-{
-	struct pci_pbm_info *pbm = pci_bus2pbm[dev->bus->number];
-	unsigned char bus = dev->bus->number;
-	unsigned int devfn = dev->devfn;
-	u16 *addr;
-
-	*value = 0xffff;
-	addr = schizo_pci_config_mkaddr(pbm, bus, devfn, where);
-	if (!addr)
-		return PCIBIOS_SUCCESSFUL;
-
-	if (schizo_out_of_range(pbm, bus, devfn))
-		return PCIBIOS_SUCCESSFUL;
-
-	if (where & 0x01) {
-		printk("pcibios_read_config_word: misaligned reg [%x]\n",
-		       where);
-		return PCIBIOS_SUCCESSFUL;
-	}
-	pci_config_read16(addr, value);
-	return PCIBIOS_SUCCESSFUL;
-}
-
-static int schizo_read_dword(struct pci_dev *dev, int where, u32 *value)
-{
-	struct pci_pbm_info *pbm = pci_bus2pbm[dev->bus->number];
-	unsigned char bus = dev->bus->number;
-	unsigned int devfn = dev->devfn;
+	struct pci_pbm_info *pbm = pci_bus2pbm[bus_dev->number];
+	unsigned char bus = bus_dev->number;
 	u32 *addr;
+	u16 tmp16;
+	u8 tmp8;
 
-	*value = 0xffffffff;
-	addr = schizo_pci_config_mkaddr(pbm, bus, devfn, where);
-	if (!addr)
-		return PCIBIOS_SUCCESSFUL;
-
-	if (schizo_out_of_range(pbm, bus, devfn))
-		return PCIBIOS_SUCCESSFUL;
-
-	if (where & 0x03) {
-		printk("pcibios_read_config_dword: misaligned reg [%x]\n",
-		       where);
-		return PCIBIOS_SUCCESSFUL;
+	switch (size) {
+	case 1:
+		*value = 0xff;
+		break;
+	case 2:
+		*value = 0xffff;
+		break;
+	case 4:
+		*value = 0xffffffff;
+		break;
 	}
 
-	pci_config_read32(addr, value);
-	return PCIBIOS_SUCCESSFUL;
-}
-
-static int schizo_write_byte(struct pci_dev *dev, int where, u8 value)
-{
-	struct pci_pbm_info *pbm = pci_bus2pbm[dev->bus->number];
-	unsigned char bus = dev->bus->number;
-	unsigned int devfn = dev->devfn;
-	u8 *addr;
-
-	addr = schizo_pci_config_mkaddr(pbm, bus, devfn, where);
-	if (!addr)
-		return PCIBIOS_SUCCESSFUL;
-
-	if (schizo_out_of_range(pbm, bus, devfn))
-		return PCIBIOS_SUCCESSFUL;
-
-	pci_config_write8(addr, value);
-	return PCIBIOS_SUCCESSFUL;
-}
-
-static int schizo_write_word(struct pci_dev *dev, int where, u16 value)
-{
-	struct pci_pbm_info *pbm = pci_bus2pbm[dev->bus->number];
-	unsigned char bus = dev->bus->number;
-	unsigned int devfn = dev->devfn;
-	u16 *addr;
-
 	addr = schizo_pci_config_mkaddr(pbm, bus, devfn, where);
 	if (!addr)
 		return PCIBIOS_SUCCESSFUL;
 
 	if (schizo_out_of_range(pbm, bus, devfn))
 		return PCIBIOS_SUCCESSFUL;
-
-	if (where & 0x01) {
-		printk("pcibios_write_config_word: misaligned reg [%x]\n",
-		       where);
-		return PCIBIOS_SUCCESSFUL;
+	switch (size) {
+	case 1:
+		pci_config_read8((u8 *)addr, &tmp8);
+		*value = tmp8;
+		break;
+
+	case 2:
+		if (where & 0x01) {
+			printk("pci_read_config_word: misaligned reg [%x]\n",
+			       where);
+			return PCIBIOS_SUCCESSFUL;
+		}
+		pci_config_read16((u16 *)addr, &tmp16);
+		*value = tmp16;
+		break;
+
+	case 4:
+		if (where & 0x03) {
+			printk("pci_read_config_dword: misaligned reg [%x]\n",
+			       where);
+			return PCIBIOS_SUCCESSFUL;
+		}
+		pci_config_read32(addr, value);
+		break;
 	}
-	pci_config_write16(addr, value);
 	return PCIBIOS_SUCCESSFUL;
 }
 
-static int schizo_write_dword(struct pci_dev *dev, int where, u32 value)
+static int schizo_write_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn,
+				int where, int size, u32 value)
 {
-	struct pci_pbm_info *pbm = pci_bus2pbm[dev->bus->number];
-	unsigned char bus = dev->bus->number;
-	unsigned int devfn = dev->devfn;
+	struct pci_pbm_info *pbm = pci_bus2pbm[bus_dev->number];
+	unsigned char bus = bus_dev->number;
 	u32 *addr;
 
 	addr = schizo_pci_config_mkaddr(pbm, bus, devfn, where);
@@ -246,22 +193,34 @@
 	if (schizo_out_of_range(pbm, bus, devfn))
 		return PCIBIOS_SUCCESSFUL;
 
-	if (where & 0x03) {
-		printk("pcibios_write_config_dword: misaligned reg [%x]\n",
-		       where);
-		return PCIBIOS_SUCCESSFUL;
+	switch (size) {
+	case 1:
+		pci_config_write8((u8 *)addr, value);
+		break;
+
+	case 2:
+		if (where & 0x01) {
+			printk("pci_write_config_word: misaligned reg [%x]\n",
+			       where);
+			return PCIBIOS_SUCCESSFUL;
+		}
+		pci_config_write16((u16 *)addr, value);
+		break;
+
+	case 4:
+		if (where & 0x03) {
+			printk("pci_write_config_dword: misaligned reg [%x]\n",
+			       where);
+			return PCIBIOS_SUCCESSFUL;
+		}
+		pci_config_write32(addr, value);
 	}
-	pci_config_write32(addr, value);
 	return PCIBIOS_SUCCESSFUL;
 }
 
 static struct pci_ops schizo_ops = {
-	schizo_read_byte,
-	schizo_read_word,
-	schizo_read_dword,
-	schizo_write_byte,
-	schizo_write_word,
-	schizo_write_dword
+	.read =		schizo_read_pci_cfg,
+	.write =	schizo_write_pci_cfg,
 };
 
 /* SCHIZO interrupt mapping support.  Unlike Psycho, for this controller the
diff -Nru a/arch/sparc64/kernel/process.c b/arch/sparc64/kernel/process.c
--- a/arch/sparc64/kernel/process.c	Mon Sep  9 10:36:11 2002
+++ b/arch/sparc64/kernel/process.c	Mon Sep  9 10:36:11 2002
@@ -568,8 +568,19 @@
 			     struct pt_regs *regs,
 			     unsigned long stack_size)
 {
-	struct task_struct *p = do_fork(clone_flags, stack_start,
-					regs, stack_size);
+	struct task_struct *p;
+	unsigned long tid_ptr = 0;
+
+	clone_flags &= ~CLONE_IDLETASK;
+
+	if (clone_flags & (CLONE_SETTID | CLONE_CLEARTID)) {
+		tid_ptr = regs->u_regs[UREG_G2];
+		if (test_thread_flag(TIF_32BIT))
+			tid_ptr &= 0xffffffff;
+	}
+
+	p = do_fork(clone_flags, stack_start,
+		    regs, stack_size, (int *) tid_ptr);
 
 	return IS_ERR(p) ? PTR_ERR(p) : p->pid;
 }
@@ -648,19 +659,6 @@
 
 	/* Set the second return value for the parent. */
 	regs->u_regs[UREG_I1] = 0;
-
-	if (!(clone_flags & (CLONE_SETTID | CLONE_CLEARTID)))
-		return 0;
-
-	if (t->flags & _TIF_32BIT)
-		t->kregs->u_regs[UREG_G2] &= 0xffffffff;
-
-	if (clone_flags & CLONE_SETTID)
-		if (put_user(p->pid, (int *)t->kregs->u_regs[UREG_G2]))
-			return -EFAULT;
-
-	if (clone_flags & CLONE_CLEARTID)
-		p->user_tid = (int *) t->kregs->u_regs[UREG_G2];
 
 	return 0;
 }
diff -Nru a/arch/sparc64/lib/VIScsum.S b/arch/sparc64/lib/VIScsum.S
--- a/arch/sparc64/lib/VIScsum.S	Mon Sep  9 10:36:17 2002
+++ b/arch/sparc64/lib/VIScsum.S	Mon Sep  9 10:36:17 2002
@@ -212,6 +212,8 @@
 	mov		1, %g5			/*  IEU0	Group		*/
 	cmp		%o1, 6			/*  IEU1			*/
 	bl,pn		%icc, 21f		/*  CTI				*/
+	 andcc		%o0, 1, %g0		/*  IEU1	Group		*/
+	bne,pn		%icc, csump_really_slow /*  CTI				*/
 	 andcc		%o0, 2, %g0		/*  IEU1	Group		*/
 	be,pt		%icc, 1f		/*  CTI				*/
 	 and		%o0, 4, %g7		/*  IEU0			*/
@@ -449,3 +451,96 @@
 	 add		%o2, 1, %o2		/*  IEU0			*/
 1:	ba,pt		%xcc, 25b		/*  CTI		Group		*/
 	 sllx		%o2, 32, %g1		/*  IEU0			*/
+
+	/* When buff is byte aligned and len is large, we backoff to
+	 * this really slow handling.  The issue is that we cannot do
+	 * the VIS stuff when buff is byte aligned as unaligned.c will
+	 * not fix it up.
+	 */
+csump_really_slow:
+	mov	%o0, %o3
+	mov	%o1, %o4
+	cmp	%o1, 0
+	ble,pn	%icc, 9f
+	 mov	0, %o0
+	andcc	%o3, 1, %o5
+	be,pt	%icc, 1f
+	 sra	%o4, 1, %g3
+	add	%o1, -1, %o4
+	ldub	[%o3], %o0
+	add	%o3, 1, %o3
+	sra	%o4, 1, %g3
+1:
+	cmp	%g3, 0
+	be,pt	%icc, 3f
+	 and	%o4, 1, %g2
+	and	%o3, 2, %g2
+	brz,a,pt %g2, 1f
+	 sra	%g3, 1, %g3
+	add	%g3, -1, %g3
+	add	%o4, -2, %o4
+	lduh	[%o3], %g2
+	add	%o3, 2, %o3
+	add	%o0, %g2, %o0
+	sra	%g3, 1, %g3
+1:
+	cmp	%g3, 0
+	be,pt	%icc, 2f
+	 and	%o4, 2, %g2
+1:
+	ld	[%o3], %g2
+	addcc	%o0, %g2, %o0
+	addx	%o0, %g0, %o0
+	addcc	%g3, -1, %g3
+	bne,pt	%icc, 1b
+	 add	%o3, 4, %o3
+	srl	%o0, 16, %o1
+	sethi	%hi(64512), %g2
+	or	%g2, 1023, %g2
+	and	%o0, %g2, %g3
+	add	%g3, %o1, %g3
+	srl	%g3, 16, %o0
+	and	%g3, %g2, %g2
+	add	%g2, %o0, %g3
+	sll	%g3, 16, %g3
+	srl	%g3, 16, %o0
+	and	%o4, 2, %g2
+2:
+	cmp	%g2, 0
+	be,pt	%icc, 3f
+	 and	%o4, 1, %g2
+	lduh	[%o3], %g2
+	add	%o3, 2, %o3
+	add	%o0, %g2, %o0
+	and	%o4, 1, %g2
+3:
+	cmp	%g2, 0
+	be,pt	%icc, 1f
+	 srl	%o0, 16, %o1
+	ldub	[%o3], %g2
+	sll	%g2, 8, %g2
+	add	%o0, %g2, %o0
+	srl	%o0, 16, %o1
+1:
+	sethi	%hi(64512), %g2
+	or	%g2, 1023, %g2
+	cmp	%o5, 0
+	and	%o0, %g2, %g3
+	add	%g3, %o1, %g3
+	srl	%g3, 16, %o0
+	and	%g3, %g2, %g2
+	add	%g2, %o0, %g3
+	sll	%g3, 16, %g3
+	srl	%g3, 16, %o0
+	srl	%g3, 24, %g3
+	and	%o0, 255, %g2
+	sll	%g2, 8, %g2
+	bne,pt	%icc, 1f
+	 or	%g3, %g2, %g2
+9:
+	mov	%o0, %g2
+1:
+	addcc	%g2, %o2, %g2
+	addx	%g2, %g0, %g2
+	retl
+	 srl	%g2, 0, %o0
diff -Nru a/arch/sparc64/mm/init.c b/arch/sparc64/mm/init.c
--- a/arch/sparc64/mm/init.c	Mon Sep  9 10:36:07 2002
+++ b/arch/sparc64/mm/init.c	Mon Sep  9 10:36:11 2002
@@ -1559,7 +1559,7 @@
 		zholes_size[ZONE_DMA] = npages - pages_avail;
 
 		free_area_init_node(0, NULL, NULL, zones_size,
-				    phys_base, zholes_size);
+				    phys_base >> PAGE_SHIFT, zholes_size);
 	}
 
 	device_scan();
diff -Nru a/drivers/acorn/block/mfmhd.c b/drivers/acorn/block/mfmhd.c
--- a/drivers/acorn/block/mfmhd.c	Mon Sep  9 10:36:01 2002
+++ b/drivers/acorn/block/mfmhd.c	Mon Sep  9 10:36:01 2002
@@ -193,8 +193,6 @@
 
 #define MFM_DRV_INFO mfm_info[raw_cmd.dev]
 
-static struct hd_struct mfm[MFM_MAXDRIVES << 6];
-
 /* Stuff from the assembly routines */
 extern unsigned int hdc63463_baseaddress;	/* Controller base address */
 extern unsigned int hdc63463_irqpolladdress;	/* Address to read to test for int */
@@ -882,6 +880,20 @@
 	mfm_request();
 }
 
+static struct gendisk mfm_gendisk[2] = {
+{
+	.major		= MAJOR_NR,
+	.first_minor	= 0,
+	.major_name	= "mfma",
+	.minor_shift	= 6,
+},
+{
+	.major		= MAJOR_NR,
+	.first_minor	= 64,
+	.major_name	= "mfmb",
+	.minor_shift	= 6,
+};
+
 static void mfm_request(void)
 {
 	DBG("mfm_request CURRENT=%p Busy=%d\n", CURRENT, Busy);
@@ -895,7 +907,7 @@
 	Busy = 1;
 
 	while (1) {
-		unsigned int dev, block, nsect;
+		unsigned int dev, block, nsect, unit;
 
 		DBG("mfm_request: loop start\n");
 		sti();
@@ -912,26 +924,26 @@
 		DBG("mfm_request:                 before arg extraction\n");
 
 		dev = minor(CURRENT->rq_dev);
+		unit = dev>>6;
 		block = CURRENT->sector;
 		nsect = CURRENT->nr_sectors;
 #ifdef DEBUG
-		/*if ((dev>>6)==1) */ console_printf("mfm_request:                                raw vals: dev=%d (block=512 bytes) block=%d nblocks=%d\n", dev, block, nsect);
+		/*if (unit==1) */ console_printf("mfm_request:                                raw vals: dev=%d (block=512 bytes) block=%d nblocks=%d\n", dev, block, nsect);
 #endif
-		if (dev >= (mfm_drives << 6) ||
-		    block >= mfm[dev].nr_sects || ((block+nsect) > mfm[dev].nr_sects)) {
-			if (dev >= (mfm_drives << 6))
+		if (unit >= mfm_drives ||
+		    block >= get_capacity(mfm_gendisk + unit) ||
+		    ((block+nsect) > get_capacity(mfm_gendisk + unit))) {
+			if (unit >= mfm_drives)
 				printk("mfm: bad minor number: device=%s\n", kdevname(CURRENT->rq_dev));
 			else
-				printk("mfm%c: bad access: block=%d, count=%d, nr_sects=%ld\n", (dev >> 6)+'a',
-				       block, nsect, mfm[dev].nr_sects);
+				printk("mfm%c: bad access: block=%d, count=%d, nr_sects=%ld\n", unit+'a',
+				       block, nsect, get_capacity(mfm_gendisk+unit));
 			printk("mfm: continue 1\n");
 			end_request(CURRENT, 0);
 			Busy = 0;
 			continue;
 		}
 
-		block += mfm[dev].start_sect;
-
 		/* DAG: Linux doesn't cope with this - even though it has an array telling
 		   it the hardware block size - silly */
 		block <<= 1;	/* Now in 256 byte sectors */
@@ -1163,18 +1175,9 @@
 static int mfm_ioctl(struct inode *inode, struct file *file, u_int cmd, u_long arg)
 {
 	struct hd_geometry *geo = (struct hd_geometry *) arg;
-	kdev_t dev;
-	int device, minor, err;
-
-	if (!inode || !(dev = inode->i_rdev))
-		return -EINVAL;
-
-	minor = minor(dev);
-
-	device = DEVICE_NR(minor(inode->i_rdev)), err;
+	int device = DEVICE_NR(minor(inode->i_rdev));
 	if (device >= mfm_drives)
 		return -EINVAL;
-
 	if (cmd != HDIO_GETGEO)
 		return -EINVAL;
 	if (!arg)
@@ -1185,7 +1188,8 @@
 		return -EFAULT;
 	if (put_user (mfm_info[device].cylinders, &geo->cylinders))
 		return -EFAULT;
-	if (put_user (mfm[minor].start_sect, &geo->start))
+	start = get_start_sect(inode->i_bdev);
+	if (put_user (get_start_sect(inode->i_bdev), &geo->start))
 		return -EFAULT;
 	return 0;
 }
@@ -1237,27 +1241,10 @@
 		if (raw_cmd.dev == drive)
 			mfm_specify ();
 		mfm_geometry (drive);
-		mfm[drive << 6].start_sect = 0;
-		mfm[drive << 6].nr_sects = mfm_info[drive].cylinders * mfm_info[drive].heads * mfm_info[drive].sectors / 2;
+		set_capacity(&mfm_gendisk[drive], mfm_info[drive].cylinders * mfm_info[drive].heads * mfm_info[drive].sectors / 2);
 	}
 }
 
-static struct gendisk mfm_gendisk[2] = {
-{
-	.major		= MAJOR_NR,
-	.first_minor	= 0,
-	.major_name	= "mfma",
-	.minor_shift	= 6,
-	.part		= mfm,
-},
-{
-	.major		= MAJOR_NR,
-	.first_minor	= 64,
-	.major_name	= "mfmb",
-	.minor_shift	= 6,
-	.part		= mfm + 64,
-};
-
 static struct block_device_operations mfm_fops =
 {
 	.owner		= THIS_MODULE,
@@ -1280,7 +1267,6 @@
 		outw(0x80, mfm_irqenable);	/* Required to enable IRQs from MFM podule */
 
 	for (i = 0; i < mfm_drives; i++) {
-		mfm_gendisk[i].nr_real = 1;
 		add_gendisk(mfm_gendisk + i);
 		mfm_geometry (i);
 		register_disk(mfm_gendisk + i, mk_kdev(MAJOR_NR,i<<6), 1<<6,
diff -Nru a/drivers/acpi/Config.in b/drivers/acpi/Config.in
--- a/drivers/acpi/Config.in	Mon Sep  9 10:36:13 2002
+++ b/drivers/acpi/Config.in	Mon Sep  9 10:36:13 2002
@@ -32,7 +32,7 @@
       tristate     '  Processor'	CONFIG_ACPI_PROCESSOR
       dep_tristate '  Thermal Zone' 	CONFIG_ACPI_THERMAL $CONFIG_ACPI_PROCESSOR
       if [ "$CONFIG_NUMA" = "y" ]; then
-        bool       '  NUMA support'     CONFIG_ACPI_NUMA $CONFIG_NUMA
+         dep_bool       '  NUMA support'     CONFIG_ACPI_NUMA $CONFIG_NUMA
       fi
       tristate     '  Toshiba Laptop Extras'	CONFIG_ACPI_TOSHIBA
       bool         '  Debug Statements'	CONFIG_ACPI_DEBUG
@@ -83,7 +83,7 @@
     tristate     '  Processor'		CONFIG_ACPI_PROCESSOR
     dep_tristate '  Thermal Zone'       CONFIG_ACPI_THERMAL $CONFIG_ACPI_PROCESSOR
     if [ "$CONFIG_NUMA" = "y" ]; then
-      bool       '  NUMA support'       CONFIG_ACPI_NUMA $CONFIG_NUMA
+       dep_bool       '  NUMA support'       CONFIG_ACPI_NUMA $CONFIG_NUMA
     fi
     bool         '  Debug Statements' 	CONFIG_ACPI_DEBUG
     endmenu
diff -Nru a/drivers/base/fs/Makefile b/drivers/base/fs/Makefile
--- a/drivers/base/fs/Makefile	Mon Sep  9 10:36:11 2002
+++ b/drivers/base/fs/Makefile	Mon Sep  9 10:36:11 2002
@@ -1,5 +1,5 @@
 obj-y		:= device.o bus.o driver.o class.o intf.o
 
-export-objs	:= device.o bus.o driver.o class.o intf.o
+export-objs	:= device.o bus.o driver.o class.o
 
 include $(TOPDIR)/Rules.make
diff -Nru a/drivers/block/DAC960.c b/drivers/block/DAC960.c
--- a/drivers/block/DAC960.c	Mon Sep  9 10:36:13 2002
+++ b/drivers/block/DAC960.c	Mon Sep  9 10:36:13 2002
@@ -1968,12 +1968,10 @@
 	struct gendisk *disk = &Controller->disks[n];
 	memset(disk, 0, sizeof(struct gendisk));
 	sprintf(names + 9 * n, "rd/c%dd%d", Controller->ControllerNumber, n);
-	disk->part = Controller->DiskPartitions + (n<<DAC960_MaxPartitionsBits);
 	disk->major = MajorNumber;
 	disk->first_minor = n << DAC960_MaxPartitionsBits;
 	disk->major_name = names + 9 * n;
 	disk->minor_shift = DAC960_MaxPartitionsBits;
-	disk->nr_real = 1;
 	disk->fops = &DAC960_BlockDeviceOperations;
 	add_gendisk(disk);
    }
@@ -2034,10 +2032,9 @@
 
 static void DAC960_ComputeGenericDiskInfo(DAC960_Controller_T *Controller)
 {
-	struct gendisk *disks = Controller->disks;
 	int disk;
 	for (disk = 0; disk < DAC960_MaxLogicalDrives; disk++)
-		disks->part[0].nr_sects = disk_size(Controller, disk);
+		set_capacity(Controller->disks + disk, disk_size(Controller, disk));
 }
 
 static int DAC960_revalidate(kdev_t dev)
@@ -2045,7 +2042,7 @@
 	int ctlr = DAC960_ControllerNumber(dev);
 	int disk = DAC960_LogicalDriveNumber(dev);
 	DAC960_Controller_T *p = DAC960_Controllers[ctlr];
-	p->disks[disk].part[0].nr_sects = disk_size(p, disk);
+	set_capacity(&p->disks[disk], disk_size(p, disk));
 	return 0;
 }
 
@@ -5277,7 +5274,7 @@
 	    DAC960_KernelDevice(Controller->ControllerNumber, LogicalDriveNumber, 0),
 	    DAC960_MaxPartitions, &DAC960_BlockDeviceOperations, size);
     }
-  if (Controller->disks[LogicalDriveNumber].part[0].nr_sects == 0)
+  if (!get_capacity(&Controller->disks[LogicalDriveNumber]))
     return -ENXIO;
   /*
     Increment Controller and Logical Drive Usage Counts.
diff -Nru a/drivers/block/DAC960.h b/drivers/block/DAC960.h
--- a/drivers/block/DAC960.h	Mon Sep  9 10:36:13 2002
+++ b/drivers/block/DAC960.h	Mon Sep  9 10:36:13 2002
@@ -2196,7 +2196,6 @@
 typedef struct block_device_operations BlockDeviceOperations_T;
 typedef struct completion Completion_T;
 typedef struct hd_geometry DiskGeometry_T;
-typedef struct hd_struct DiskPartition_T;
 typedef struct inode Inode_T;
 typedef struct inode_operations InodeOperations_T;
 typedef kdev_t KernelDevice_T;
@@ -2472,7 +2471,6 @@
       boolean LogicalDriveFoundDuringScan[DAC960_MaxLogicalDrives];
     } V2;
   } FW;
-  DiskPartition_T DiskPartitions[DAC960_MinorCount];
   unsigned char ProgressBuffer[DAC960_ProgressBufferSize];
   unsigned char UserStatusBuffer[DAC960_UserMessageSize];
 }
diff -Nru a/drivers/block/Makefile b/drivers/block/Makefile
--- a/drivers/block/Makefile	Mon Sep  9 10:36:13 2002
+++ b/drivers/block/Makefile	Mon Sep  9 10:36:13 2002
@@ -8,8 +8,8 @@
 # In the future, some of these should be built conditionally.
 #
 
-export-objs	:= elevator.o ll_rw_blk.o blkpg.o loop.o genhd.o \
-		   block_ioctl.o acsi.o
+export-objs	:= elevator.o ll_rw_blk.o loop.o genhd.o acsi.o \
+		   block_ioctl.o
 
 obj-y	:= elevator.o ll_rw_blk.o blkpg.o genhd.o block_ioctl.o
 
diff -Nru a/drivers/block/acsi.c b/drivers/block/acsi.c
--- a/drivers/block/acsi.c	Mon Sep  9 10:36:11 2002
+++ b/drivers/block/acsi.c	Mon Sep  9 10:36:11 2002
@@ -245,7 +245,6 @@
 unsigned long 	phys_acsi_buffer;
 
 static int NDevices;
-static struct hd_struct	acsi_part[MAX_DEV<<4];
 static char acsi_names[MAX_DEV*4];
 static int access_count[MAX_DEV];
 
@@ -783,7 +782,7 @@
 	
 	status = acsi_getstatus();
 	if (status != 0) {
-		int dev = minor(CURRENT->rq_dev);
+		int dev = DEVICE_NR(CURRENT->rq_dev);
 		printk( KERN_ERR "ad%c: ", dev+'a' );
 		if (!acsi_reqsense( acsi_buffer, acsi_info[dev].target, 
 					acsi_info[dev].lun))
@@ -814,7 +813,7 @@
 
 	status = acsi_getstatus();
 	if (status != 0) {
-		int	dev = minor(CURRENT->rq_dev);
+		int	dev = DEVICE_NR(CURRENT->rq_dev);
 		printk( KERN_ERR "ad%c: ", dev+'a' );
 		if (!acsi_reqsense( acsi_buffer, acsi_info[dev].target,
 					acsi_info[dev].lun))
@@ -973,15 +972,15 @@
 			panic(DEVICE_NAME ": block not locked");
 	}
 
-	dev = minor(CURRENT->rq_dev);
+	dev = DEVICE_NR(CURRENT->rq_dev);
 	block = CURRENT->sector;
 	if (dev >= NDevices ||
-		block+CURRENT->nr_sectors >= acsi_part[dev].nr_sects) {
+		block+CURRENT->nr_sectors >= get_capacity(acsi_gendisk + dev)) {
 #ifdef DEBUG
 		printk( "ad%c: attempted access for blocks %d...%ld past end of device at block %ld.\n",
 		       dev+'a',
 		       block, block + CURRENT->nr_sectors - 1,
-		       acsi_part[dev].nr_sects);
+		       get_capacity(acsi_gendisk + dev));
 #endif
 		end_request(CURRENT, 0);
 		goto repeat;
@@ -1088,11 +1087,7 @@
 static int acsi_ioctl( struct inode *inode, struct file *file,
 					   unsigned int cmd, unsigned long arg )
 {
-	dev_t dev;
-
-	if (!inode)
-		return -EINVAL;
-	dev = minor(inode->i_rdev);
+	int dev = DEVICE_NR(inode->i_rdev);
 	if (dev >= NDevices)
 		return -EINVAL;
 	switch (cmd) {
@@ -1140,7 +1135,7 @@
 	int  device;
 	struct acsi_info_struct *aip;
 
-	device = minor(inode->i_rdev);
+	device = DEVICE_NR(inode->i_rdev);
 	if (device >= NDevices)
 		return -ENXIO;
 	aip = &acsi_info[device];
@@ -1176,7 +1171,7 @@
 
 static int acsi_release( struct inode * inode, struct file * file )
 {
-	int device = minor(inode->i_rdev);
+	int device = DEVICE_NR(inode->i_rdev);
 	if (--access_count[device] == 0 && acsi_info[device].removable)
 		acsi_prevent_removal(device, 0);
 	return( 0 );
@@ -1204,7 +1199,7 @@
 
 static int acsi_media_change (kdev_t dev)
 {
-	int device = minor(dev);
+	int device = DEVICE_NR(dev);
 	struct acsi_info_struct *aip;
 
 	aip = &acsi_info[device];
@@ -1702,9 +1697,7 @@
 		disk->first_minor = i << 4;
 		disk->major_name = acsi_names + 4*i;
 		disk->minor_shift = (acsi_info[i].type==HARDDISK)?4:0;
-		disk->part = acsi_part + (i<<4);
 		disk->fops = &acsi_fops;
-		disk->nr_real = 1;
 		add_gendisk(disk);
 		register_disk(disk, mk_kdev(disk->major, disk->first_minor),
 				1<<disk->minor_shift,
@@ -1808,7 +1801,7 @@
 
 static int acsi_revalidate(kdev_t dev)
 {
-	int unit = DEVICE_NR(minor(dev));
+	int unit = DEVICE_NR(dev);
 	struct acsi_info_struct *aip = &acsi_info[unit];
 	stdma_lock( NULL, NULL );
 	if (acsi_devinit(aip) != DEV_SUPPORTED) {
@@ -1822,6 +1815,6 @@
 
 	ENABLE_IRQ();
 	stdma_release();
-	acsi_part[minor(dev)].nr_sects = aip->size;
+	set_capacity(acsi_gendisk + unit, aip->size);
 	return 0;
 }
diff -Nru a/drivers/block/blkpg.c b/drivers/block/blkpg.c
--- a/drivers/block/blkpg.c	Mon Sep  9 10:35:56 2002
+++ b/drivers/block/blkpg.c	Mon Sep  9 10:35:56 2002
@@ -71,7 +71,6 @@
 	long pstart, plength;
 	int i;
 	kdev_t dev = to_kdev_t(bdev->bd_dev);
-	struct hd_struct *part;
 
 	/* convert bytes to sectors, check for fit in a hd_struct */
 	ppstart = (p->start >> 9);
@@ -86,7 +85,6 @@
 	g = get_gendisk(dev);
 	if (!g)
 		return -ENXIO;
-	part = g->part + minor(dev) - g->first_minor;
 
 	/* existing drive? */
 
@@ -97,19 +95,19 @@
 		return -EINVAL;
 
 	/* partition number in use? */
-	if (part[p->pno].nr_sects != 0)
+	if (g->part[p->pno - 1].nr_sects != 0)
 		return -EBUSY;
 
 	/* overlap? */
-	for (i = 1; i < (1<<g->minor_shift); i++)
-		if (!(pstart+plength <= part[i].start_sect ||
-		      pstart >= part[i].start_sect + part[i].nr_sects))
+	for (i = 0; i < (1<<g->minor_shift) - 1; i++)
+		if (!(pstart+plength <= g->part[i].start_sect ||
+		      pstart >= g->part[i].start_sect + g->part[i].nr_sects))
 			return -EBUSY;
 
 	/* all seems OK */
-	part[p->pno].start_sect = pstart;
-	part[p->pno].nr_sects = plength;
-	devfs_register_partitions (g, minor(dev), 0);
+	g->part[p->pno - 1].start_sect = pstart;
+	g->part[p->pno - 1].nr_sects = plength;
+	update_partition(g, p->pno);
 	return 0;
 }
 
@@ -128,22 +126,19 @@
 	kdev_t dev = to_kdev_t(bdev->bd_dev);
 	struct gendisk *g;
 	struct block_device *bdevp;
-	struct hd_struct *part;
 	int holder;
 
 	/* find the drive major */
 	g = get_gendisk(dev);
 	if (!g)
 		return -ENXIO;
-	part = g->part + minor(dev) - g->first_minor;
-
 	if (bdev != bdev->bd_contains)
 		return -EINVAL;
 	if (p->pno <= 0 || p->pno >= (1 << g->minor_shift))
   		return -EINVAL;
 
 	/* existing drive and partition? */
-	if (part[p->pno].nr_sects == 0)
+	if (g->part[p->pno - 1].nr_sects == 0)
 		return -ENXIO;
 
 	/* partition in use? Incomplete check for now. */
@@ -159,9 +154,9 @@
 	fsync_bdev(bdevp);
 	invalidate_bdev(bdevp, 0);
 
-	part[p->pno].start_sect = 0;
-	part[p->pno].nr_sects = 0;
-	devfs_register_partitions (g, minor(dev), 0);
+	g->part[p->pno - 1].start_sect = 0;
+	g->part[p->pno - 1].nr_sects = 0;
+	update_partition(g, p->pno);
 	bd_release(bdevp);
 	bdput(bdevp);
 
diff -Nru a/drivers/block/cciss.c b/drivers/block/cciss.c
--- a/drivers/block/cciss.c	Mon Sep  9 10:36:17 2002
+++ b/drivers/block/cciss.c	Mon Sep  9 10:36:17 2002
@@ -407,8 +407,7 @@
                         driver_geo.sectors = 0x3f;
                         driver_geo.cylinders = hba[ctlr]->drv[dsk].nr_blocks / (0xff*0x3f);
                 }
-                driver_geo.start=
-                        hba[ctlr]->hd[minor(inode->i_rdev)].start_sect;
+                driver_geo.start= get_start_sect(inode->i_bdev);
                 if (copy_to_user((void *) arg, &driver_geo,
                                 sizeof( struct hd_geometry)))
                         return  -EFAULT;
@@ -705,7 +704,7 @@
         int ctlr = major(dev) - MAJOR_NR;
 	int target = minor(dev) >> NWD_SHIFT;
         struct gendisk *disk = &hba[ctlr]->gendisk[target];
-	disk->part[0].nr_sects = hba[ctlr]->drv[target].nr_blocks;
+	set_capacity(disk, hba[ctlr]->drv[target].nr_blocks);
 	return 0;
 }
 
@@ -742,7 +741,6 @@
 	for(i=0; i< NWD; i++) {
 		struct gendisk *disk = &hba[ctlr]->gendisk[i];
 		if (disk->major_name) {
-			wipe_partitions(mk_kdev(disk->major, disk->first_minor));
 			del_gendisk(disk);
 			disk->major_name = NULL;
 		}
@@ -752,7 +750,6 @@
          * Set the partition and block size structures for all volumes
          * on this controller to zero.  We will reread all of this data
          */
-	memset(hba[ctlr]->hd,         0, sizeof(struct hd_struct) * 256);
         memset(hba[ctlr]->drv,        0, sizeof(drive_info_struct)
 						* CISS_MAX_LUN);
         /*
@@ -802,7 +799,6 @@
 
 	/* invalidate the devices and deregister the disk */ 
 	if (disk->major_name) {
-		wipe_partitions(mk_kdev(disk->major, disk->first_minor));
 		del_gendisk(disk);
 		disk->major_name = NULL;
 	}
@@ -2448,8 +2444,6 @@
 		disk->first_minor = j << NWD_SHIFT;
 		disk->major_name = NULL;
 		disk->minor_shift = NWD_SHIFT;
-		disk->part = hba[i]->hd + (j << NWD_SHIFT);
-		disk->nr_real = 1;
 		if( !(drv->nr_blocks))
 			continue;
 		(BLK_DEFAULT_QUEUE(MAJOR_NR + i))->hardsect_size = drv->block_size;
diff -Nru a/drivers/block/cciss.h b/drivers/block/cciss.h
--- a/drivers/block/cciss.h	Mon Sep  9 10:35:49 2002
+++ b/drivers/block/cciss.h	Mon Sep  9 10:35:49 2002
@@ -83,9 +83,6 @@
 	// Disk structures we need to pass back
 	struct gendisk   gendisk[NWD];
 	char names[12 * NWD];
-	   // indexed by minor numbers
-	struct hd_struct hd[256];
-	int		 sizes[256];
 #ifdef CONFIG_CISS_SCSI_TAPE
 	void *scsi_ctlr; /* ptr to structure containing scsi related stuff */
 #endif
diff -Nru a/drivers/block/cpqarray.c b/drivers/block/cpqarray.c
--- a/drivers/block/cpqarray.c	Mon Sep  9 10:35:59 2002
+++ b/drivers/block/cpqarray.c	Mon Sep  9 10:35:59 2002
@@ -75,7 +75,6 @@
 
 static int nr_ctlr;
 static ctlr_info_t *hba[MAX_CTLR];
-static devfs_handle_t de_arr[MAX_CTLR][NWD];
 
 static int eisa[8];
 
@@ -103,7 +102,6 @@
 	{ 0x40580E11, "Smart Array 431",	&smart4_access },
 };
 
-static struct hd_struct * ida;
 static char *ida_names;
 static struct gendisk ida_gendisk[MAX_CTLR * NWD];
 
@@ -321,7 +319,6 @@
 	}
 	devfs_find_and_unregister(NULL, "ida", 0, 0, 0, 0);
 	remove_proc_entry("cpqarray", proc_root_driver);
-	kfree(ida);
 	kfree(ida_names);
 }
 #endif /* MODULE */
@@ -347,15 +344,12 @@
 	printk("Found %d controller(s)\n", nr_ctlr);
 
 	/* allocate space for disk structs */
-	ida = kmalloc(sizeof(struct hd_struct)*nr_ctlr*NWD*16, GFP_KERNEL);
 	ida_names = kmalloc(nr_ctlr*NWD*10, GFP_KERNEL);
-	if (!ida || !ida_names) {
+	if (!ida_names) {
 		printk( KERN_ERR "cpqarray: out of memory");
-		kfree(ida);
 		kfree(ida_names);
 		return(num_cntlrs_reg);
 	}
-	memset(ida, 0, sizeof(struct hd_struct)*nr_ctlr*NWD*16);
 	/* 
 	 * register block devices
 	 * Find disks and fill in structs
@@ -408,7 +402,6 @@
 	
 			if (num_cntlrs_reg == 0) 
 			{
-				kfree(ida);
 				kfree(ida_names);
 			}
                 	return(num_cntlrs_reg);
@@ -450,9 +443,7 @@
 			disk->major = MAJOR_NR + i;
 			disk->first_minor = j<<NWD_SHIFT;
 			disk->minor_shift = NWD_SHIFT;
-			disk->part = ida + i*256 + (j<<NWD_SHIFT);
-			disk->nr_real = 1; 
-			disk->de_arr = &de_arr[i][j]; 
+			disk->flags = GENHD_FL_DEVFS;
 			disk->fops = &ida_fops; 
 			if (!drv->nr_blks)
 				continue;
@@ -1461,11 +1452,9 @@
 		struct gendisk *disk = ida_gendisk + ctlr*NWD + i;
 		if (!disk->major_name)
 			continue;
-		wipe_partitions(mk_kdev(disk->major, disk->first_minor));
 		del_gendisk(disk);
 		disk->major_name = NULL;
 	}
-	memset(ida+(ctlr*256),            0, sizeof(struct hd_struct)*NWD*16);
 	memset(hba[ctlr]->drv,            0, sizeof(drv_info_t)*NWD);
 
 	/*
@@ -1500,7 +1489,7 @@
         int ctlr = major(dev) - MAJOR_NR;
 	int target = DEVICE_NR(dev);
         struct gendisk *gdev = &ida_gendisk[ctlr*NWD+target];
-	gdev->part[minor(dev)].nr_sects = hba[ctlr]->drv[target].nr_blks;
+	set_capacity(gdev, hba[ctlr]->drv[target].nr_blks);
 	return 0;
 }
 
@@ -1667,6 +1656,7 @@
 	     (log_index < id_ctlr_buf->nr_drvs)
 	     && (log_unit < NWD);
 	     log_unit++) {
+		struct gendisk *disk = ida_gendisk + ctlr * NWD + log_unit;
 
 		size = sizeof(sense_log_drv_stat_t);
 
@@ -1731,13 +1721,10 @@
                 			return;
 
 				}
-				if (!de_arr[ctlr][log_unit]) {
+				if (!disk->de) {
 					char txt[16];
-
-					sprintf(txt, "ida/c%dd%d", ctlr,
-						log_unit);
-					de_arr[ctlr][log_unit] =
-						devfs_mk_dir(NULL, txt, NULL);
+					sprintf(txt,"ida/c%dd%d",ctlr,log_unit);
+					disk->de = devfs_mk_dir(NULL,txt,NULL);
 				}
 				info_p->phys_drives =
 				    sense_config_buf->ctlr_phys_drv;
diff -Nru a/drivers/block/floppy.c b/drivers/block/floppy.c
--- a/drivers/block/floppy.c	Mon Sep  9 10:36:01 2002
+++ b/drivers/block/floppy.c	Mon Sep  9 10:36:01 2002
@@ -2295,17 +2295,15 @@
 {
 	kdev_t dev = req->rq_dev;
 
-	if (end_that_request_first(req, uptodate, req->hard_cur_sectors))
+	if (end_that_request_first(req, uptodate, current_count_sectors))
 		return;
 	add_blkdev_randomness(major(dev));
 	floppy_off(DEVICE_NR(dev));
+	blkdev_dequeue_request(req);
 	end_that_request_last(req);
 
-	/* Get the next request */
-	req = elv_next_request(QUEUE);
-	if (req)
-		blkdev_dequeue_request(req);
-	CURRENT = req;
+	/* We're done with the request */
+	CURRENT = NULL;
 }
 
 
@@ -2336,27 +2334,8 @@
 
 		/* unlock chained buffers */
 		spin_lock_irqsave(q->queue_lock, flags);
-		while (current_count_sectors && CURRENT &&
-		       current_count_sectors >= req->current_nr_sectors){
-			current_count_sectors -= req->current_nr_sectors;
-			req->nr_sectors -= req->current_nr_sectors;
-			req->sector += req->current_nr_sectors;
-			end_request(req, 1);
-		}
+		end_request(req, 1);
 		spin_unlock_irqrestore(q->queue_lock, flags);
-
-		if (current_count_sectors && CURRENT) {
-			/* "unlock" last subsector */
-			req->buffer += current_count_sectors <<9;
-			req->current_nr_sectors -= current_count_sectors;
-			req->nr_sectors -= current_count_sectors;
-			req->sector += current_count_sectors;
-			return;
-		}
-
-		if (current_count_sectors && !CURRENT)
-			DPRINT("request list destroyed in floppy request done\n");
-
 	} else {
 		if (rq_data_dir(req) == WRITE) {
 			/* record write error information */
@@ -2939,7 +2918,6 @@
 				unlock_fdc();
 				return;
 			}
-			blkdev_dequeue_request(req);
 			CURRENT = req;
 		}
 		if (major(CURRENT->rq_dev) != MAJOR_NR)
diff -Nru a/drivers/block/genhd.c b/drivers/block/genhd.c
--- a/drivers/block/genhd.c	Mon Sep  9 10:36:11 2002
+++ b/drivers/block/genhd.c	Mon Sep  9 10:36:11 2002
@@ -23,6 +23,7 @@
 #include <linux/init.h>
 #include <linux/spinlock.h>
 #include <linux/seq_file.h>
+#include <linux/slab.h>
 
 
 static rwlock_t gendisk_lock;
@@ -43,6 +44,19 @@
 add_gendisk(struct gendisk *gp)
 {
 	struct gendisk *sgp;
+	struct hd_struct *p = NULL;
+
+	if (gp->minor_shift) {
+		size_t size = sizeof(struct hd_struct)*((1<<gp->minor_shift)-1);
+		p = kmalloc(size, GFP_KERNEL);
+		if (!p) {
+			printk(KERN_ERR "out of memory; no partitions for %s\n",
+				gp->major_name);
+			gp->minor_shift = 0;
+		} else
+			memset(p, 0, size);
+	}
+	gp->part = p;
 
 	write_lock(&gendisk_lock);
 
@@ -67,32 +81,20 @@
 }
 
 EXPORT_SYMBOL(add_gendisk);
+EXPORT_SYMBOL(del_gendisk);
 
-
-/**
- * del_gendisk - remove partitioning information from kernel list
- * @gp: per-device partitioning information
- *
- * This function unregisters the partitioning information in @gp
- * with the kernel.
- */
-void
-del_gendisk(struct gendisk *gp)
+void unlink_gendisk(struct gendisk *disk)
 {
-	struct gendisk **gpp;
-
+	struct gendisk **p;
 	write_lock(&gendisk_lock);
-	for (gpp = &gendisk_head; *gpp; gpp = &((*gpp)->next))
-		if (*gpp == gp)
+	for (p = &gendisk_head; *p; p = &((*p)->next))
+		if (*p == disk)
 			break;
-	if (*gpp)
-		*gpp = (*gpp)->next;
+	if (*p)
+		*p = (*p)->next;
 	write_unlock(&gendisk_lock);
 }
 
-EXPORT_SYMBOL(del_gendisk);
-
-
 /**
  * get_gendisk - get partitioning information for a given device
  * @dev: device to get partitioning information for
@@ -160,14 +162,17 @@
 		seq_puts(part, "major minor  #blocks  name\n\n");
 
 	/* show the full disk and all non-0 size partitions of it */
-	for (n = 0; n < (sgp->nr_real << sgp->minor_shift); n++) {
-		int minormask = (1<<sgp->minor_shift) - 1;
-		if ((n & minormask) && sgp->part[n].nr_sects == 0)
+	seq_printf(part, "%4d  %4d %10ld %s\n",
+		sgp->major, sgp->first_minor,
+		get_capacity(sgp) >> 1,
+		disk_name(sgp, 0, buf));
+	for (n = 0; n < (1<<sgp->minor_shift) - 1; n++) {
+		if (sgp->part[n].nr_sects == 0)
 			continue;
 		seq_printf(part, "%4d  %4d %10ld %s\n",
-			sgp->major, n + sgp->first_minor,
+			sgp->major, n + 1 + sgp->first_minor,
 			sgp->part[n].nr_sects >> 1 ,
-			disk_name(sgp, n + sgp->first_minor, buf));
+			disk_name(sgp, n + 1, buf));
 	}
 
 	return 0;
diff -Nru a/drivers/block/ll_rw_blk.c b/drivers/block/ll_rw_blk.c
--- a/drivers/block/ll_rw_blk.c	Mon Sep  9 10:35:56 2002
+++ b/drivers/block/ll_rw_blk.c	Mon Sep  9 10:35:56 2002
@@ -1992,11 +1992,11 @@
 		 * not a complete bvec done
 		 */
 		if (unlikely(nsect > nr_sectors)) {
-			int residual = (nsect - nr_sectors) << 9;
+			int partial = nr_sectors << 9;
 
-			bio->bi_size -= residual;
-			bio_iovec(bio)->bv_offset += residual;
-			bio_iovec(bio)->bv_len -= residual;
+			bio->bi_size -= partial;
+			bio_iovec(bio)->bv_offset += partial;
+			bio_iovec(bio)->bv_len -= partial;
 			blk_recalc_rq_sectors(req, nr_sectors);
 			blk_recalc_rq_segments(req);
 			return 1;
diff -Nru a/drivers/block/loop.c b/drivers/block/loop.c
--- a/drivers/block/loop.c	Mon Sep  9 10:36:11 2002
+++ b/drivers/block/loop.c	Mon Sep  9 10:36:11 2002
@@ -210,8 +210,7 @@
 			goto fail;
 		if (aops->prepare_write(file, page, offset, offset+size))
 			goto unlock;
-		kaddr = page_address(page);
-		flush_dcache_page(page);
+		kaddr = kmap(page);
 		transfer_result = lo_do_transfer(lo, WRITE, kaddr + offset, data, size, IV);
 		if (transfer_result) {
 			/*
@@ -221,6 +220,8 @@
 			printk(KERN_ERR "loop: transfer error block %ld\n", index);
 			memset(kaddr + offset, 0, size);
 		}
+		flush_dcache_page(page);
+		kunmap(page);
 		if (aops->commit_write(file, page, offset, offset+size))
 			goto unlock;
 		if (transfer_result)
diff -Nru a/drivers/block/paride/pcd.c b/drivers/block/paride/pcd.c
--- a/drivers/block/paride/pcd.c	Mon Sep  9 10:36:11 2002
+++ b/drivers/block/paride/pcd.c	Mon Sep  9 10:36:11 2002
@@ -111,28 +111,21 @@
 
 */
 
-static int      verbose = 0;
-static int      major = PCD_MAJOR;
-static char     *name = PCD_NAME;
-static int      nice = 0;
-static int      disable = 0;
-
-static int drive0[6] = {0,0,0,-1,-1,-1};
-static int drive1[6] = {0,0,0,-1,-1,-1};
-static int drive2[6] = {0,0,0,-1,-1,-1};
-static int drive3[6] = {0,0,0,-1,-1,-1};
+static int verbose = 0;
+static int major = PCD_MAJOR;
+static char *name = PCD_NAME;
+static int nice = 0;
+static int disable = 0;
+
+static int drive0[6] = { 0, 0, 0, -1, -1, -1 };
+static int drive1[6] = { 0, 0, 0, -1, -1, -1 };
+static int drive2[6] = { 0, 0, 0, -1, -1, -1 };
+static int drive3[6] = { 0, 0, 0, -1, -1, -1 };
 
-static int (*drives[4])[6] = {&drive0,&drive1,&drive2,&drive3};
+static int (*drives[4])[6] = {&drive0, &drive1, &drive2, &drive3};
 static int pcd_drive_count;
 
-#define D_PRT   0
-#define D_PRO   1
-#define D_UNI   2
-#define D_MOD   3
-#define D_SLV   4
-#define D_DLY   5
-
-#define DU              (*drives[unit])
+enum {D_PRT, D_PRO, D_UNI, D_MOD, D_SLV, D_DLY};
 
 /* end of parameters */
 
@@ -153,28 +146,30 @@
 
 #include "setup.h"
 
-static STT pcd_stt[6] = {{"drive0",6,drive0},
-                         {"drive1",6,drive1},
-                         {"drive2",6,drive2},
-                         {"drive3",6,drive3},
-			 {"disable",1,&disable},
-                         {"nice",1,&nice}};
-
-void pcd_setup( char *str, int *ints)
+static STT pcd_stt[6] = {
+	{"drive0", 6, drive0},
+	{"drive1", 6, drive1},
+	{"drive2", 6, drive2},
+	{"drive3", 6, drive3},
+	{"disable", 1, &disable},
+	{"nice", 1, &nice}
+};
 
-{       generic_setup(pcd_stt,6,str);
+void pcd_setup(char *str, int *ints)
+{
+	generic_setup(pcd_stt, 6, str);
 }
 
 #endif
 
-MODULE_PARM(verbose,"i");
-MODULE_PARM(major,"i");
-MODULE_PARM(name,"s");
-MODULE_PARM(nice,"i");
-MODULE_PARM(drive0,"1-6i");
-MODULE_PARM(drive1,"1-6i");
-MODULE_PARM(drive2,"1-6i");
-MODULE_PARM(drive3,"1-6i");
+MODULE_PARM(verbose, "i");
+MODULE_PARM(major, "i");
+MODULE_PARM(name, "s");
+MODULE_PARM(nice, "i");
+MODULE_PARM(drive0, "1-6i");
+MODULE_PARM(drive1, "1-6i");
+MODULE_PARM(drive2, "1-6i");
+MODULE_PARM(drive3, "1-6i");
 
 #include "paride.h"
 
@@ -189,10 +184,10 @@
 #include "pseudo.h"
 
 #define PCD_RETRIES	     5
-#define PCD_TMO		   800		/* timeout in jiffies */
-#define PCD_DELAY           50          /* spin delay in uS */
-#define PCD_READY_TMO	    20		/* in seconds */
-#define PCD_RESET_TMO	   100		/* in tenths of a second */
+#define PCD_TMO		   800	/* timeout in jiffies */
+#define PCD_DELAY           50	/* spin delay in uS */
+#define PCD_READY_TMO	    20	/* in seconds */
+#define PCD_RESET_TMO	   100	/* in tenths of a second */
 
 #define PCD_SPIN	(1000000*PCD_TMO)/(HZ*PCD_DELAY)
 
@@ -208,127 +203,108 @@
 static int pcd_tray_move(struct cdrom_device_info *cdi, int position);
 static int pcd_lock_door(struct cdrom_device_info *cdi, int lock);
 static int pcd_drive_reset(struct cdrom_device_info *cdi);
-static int pcd_get_mcn (struct cdrom_device_info *cdi, struct cdrom_mcn *mcn);
+static int pcd_get_mcn(struct cdrom_device_info *cdi, struct cdrom_mcn *mcn);
 static int pcd_audio_ioctl(struct cdrom_device_info *cdi,
-				unsigned int cmd, void *arg);
+			   unsigned int cmd, void *arg);
 static int pcd_packet(struct cdrom_device_info *cdi,
-				struct cdrom_generic_command *cgc);
+		      struct cdrom_generic_command *cgc);
 
-static int 	pcd_detect(void);
-static void 	pcd_probe_capabilities(void);
-static void     do_pcd_read_drq(void);
-static void 	do_pcd_request(request_queue_t * q);
-static void 	do_pcd_read(void);
+static int pcd_detect(void);
+static void pcd_probe_capabilities(void);
+static void do_pcd_read_drq(void);
+static void do_pcd_request(request_queue_t * q);
+static void do_pcd_read(void);
 
 struct pcd_unit {
-	struct pi_adapter pia;		/* interface to paride layer */
+	struct pi_adapter pia;	/* interface to paride layer */
 	struct pi_adapter *pi;
-	int drive;			/* master/slave */
-	int last_sense;			/* result of last request sense */
-	int changed;			/* media change seen */
-	int present;			/* does this unit exist ? */
-	char *name;			/* pcd0, pcd1, etc */
+	int drive;		/* master/slave */
+	int last_sense;		/* result of last request sense */
+	int changed;		/* media change seen */
+	int present;		/* does this unit exist ? */
+	char *name;		/* pcd0, pcd1, etc */
 	struct cdrom_device_info info;	/* uniform cdrom interface */
-	};
+};
 
 struct pcd_unit pcd[PCD_UNITS];
 
-/*  'unit' must be defined in all functions - either as a local or a param */
-
-#define PCD pcd[unit]
-#define PI PCD.pi
-
 static char pcd_scratch[64];
-static char pcd_buffer[2048];           /* raw block buffer */
-static int pcd_bufblk = -1;             /* block in buffer, in CD units,
-                                           -1 for nothing there. See also
-					   pd_unit.
-					 */
+static char pcd_buffer[2048];	/* raw block buffer */
+static int pcd_bufblk = -1;	/* block in buffer, in CD units,
+				   -1 for nothing there. See also
+				   pd_unit.
+				 */
 
 /* the variables below are used mainly in the I/O request engine, which
    processes only one request at a time.
 */
 
-static int pcd_unit = -1;		/* unit of current request & bufblk */
-static int pcd_retries;			/* retries on current request */
-static int pcd_busy = 0;		/* request being processed ? */
-static int pcd_sector;			/* address of next requested sector */
-static int pcd_count;			/* number of blocks still to do */
-static char * pcd_buf;			/* buffer for request in progress */
+static struct pcd_unit *pcd_current; /* current request's drive */
+static int pcd_retries;		/* retries on current request */
+static int pcd_busy;		/* request being processed ? */
+static int pcd_sector;		/* address of next requested sector */
+static int pcd_count;		/* number of blocks still to do */
+static char *pcd_buf;		/* buffer for request in progress */
 
-static int pcd_warned = 0;		/* Have we logged a phase warning ? */
+static int pcd_warned;		/* Have we logged a phase warning ? */
 
 /* kernel glue structures */
 
 static struct block_device_operations pcd_bdops = {
-	owner:			THIS_MODULE,
-	open:			cdrom_open,
-	release:		cdrom_release,
-	ioctl:			cdrom_ioctl,
-	check_media_change:	cdrom_media_changed,
+	.owner			= THIS_MODULE,
+	.open			= cdrom_open,
+	.release		= cdrom_release,
+	.ioctl			= cdrom_ioctl,
+	.check_media_change	= cdrom_media_changed,
 };
 
 static struct cdrom_device_ops pcd_dops = {
-	pcd_open,
-	pcd_release,
-	pcd_drive_status,
-	pcd_media_changed,
-	pcd_tray_move,
-	pcd_lock_door,
-	0,			/* select speed */
-	0,			/* select disk  */
-	0, 			/* get last session */
-	pcd_get_mcn,
-	pcd_drive_reset,
-	pcd_audio_ioctl,
-	0,			/* dev_ioctl */
-	CDC_CLOSE_TRAY	   |
-	CDC_OPEN_TRAY	   |
-	CDC_LOCK	   |
-	CDC_MCN		   |
-	CDC_MEDIA_CHANGED  |
-	CDC_RESET	   |
-	CDC_PLAY_AUDIO	   |
-	CDC_GENERIC_PACKET |
-	CDC_CD_R	   |
-	CDC_CD_RW,
-	0,
-	pcd_packet,
+	.open		= pcd_open,
+	.release	= pcd_release,
+	.drive_status	= pcd_drive_status,
+	.media_changed	= pcd_media_changed,
+	.tray_move	= pcd_tray_move,
+	.lock_door	= pcd_lock_door,
+	.get_mcn	= pcd_get_mcn,
+	.reset		= pcd_drive_reset,
+	.audio_ioctl	= pcd_audio_ioctl,
+	.generic_packet	= pcd_packet,
+	.capability	= CDC_CLOSE_TRAY | CDC_OPEN_TRAY | CDC_LOCK |
+			  CDC_MCN | CDC_MEDIA_CHANGED | CDC_RESET |
+			  CDC_PLAY_AUDIO | CDC_GENERIC_PACKET | CDC_CD_R |
+			  CDC_CD_RW,
 };
 
-static void pcd_init_units( void )
-
-{       int     unit, j;
+static void pcd_init_units(void)
+{
+	struct pcd_unit *cd;
+	int unit;
 
-        pcd_drive_count = 0;
-        for (unit=0;unit<PCD_UNITS;unit++) {
-                PCD.pi = & PCD.pia;
-                PCD.present = 0;
-		PCD.last_sense = 0;
-		PCD.changed = 1;
-                PCD.drive = DU[D_SLV];
-                if (DU[D_PRT]) pcd_drive_count++;
- 
-                j = 0;
-                while ((j < (sizeof(PCD.info.name)-2)) && 
-		       (PCD.info.name[j]=name[j])) j++;
-                PCD.info.name[j++] = '0' + unit;
-                PCD.info.name[j] = 0;
-		PCD.name = &PCD.info.name[0];
-
-		PCD.info.ops = &pcd_dops;
-		PCD.info.handle = NULL;
-		PCD.info.dev = mk_kdev(major,unit);
-		PCD.info.speed = 0;
-		PCD.info.capacity = 1;
-		PCD.info.mask = 0;
-        }
+	pcd_drive_count = 0;
+	for (unit = 0, cd = pcd; unit < PCD_UNITS; unit++, cd++) {
+		cd->pi = &cd->pia;
+		cd->present = 0;
+		cd->last_sense = 0;
+		cd->changed = 1;
+		cd->drive = (*drives[unit])[D_SLV];
+		if ((*drives[unit])[D_PRT])
+			pcd_drive_count++;
+
+		cd->name = &cd->info.name[0];
+		snprintf(cd->name, sizeof(cd->info.name), "%s%d", name, unit);
+		cd->info.ops = &pcd_dops;
+		cd->info.handle = cd;
+		cd->info.dev = mk_kdev(major, unit);
+		cd->info.speed = 0;
+		cd->info.capacity = 1;
+		cd->info.mask = 0;
+	}
 }
 
 static int pcd_open(struct cdrom_device_info *cdi, int purpose)
 {
-	int unit = DEVICE_NR(cdi->dev);
-	if  ((unit >= PCD_UNITS) || (!PCD.present))
+	struct pcd_unit *cd = cdi->handle;
+	if (!cd->present)
 		return -ENODEV;
 	return 0;
 }
@@ -337,554 +313,598 @@
 {
 }
 
-#define WR(c,r,v)       pi_write_regr(PI,c,r,v)
-#define RR(c,r)         (pi_read_regr(PI,c,r))
+static inline int status_reg(struct pcd_unit *cd)
+{
+	return pi_read_regr(cd->pi, 1, 6);
+}
 
-static int pcd_wait( int unit, int go, int stop, char * fun, char * msg )
+static inline int read_reg(struct pcd_unit *cd, int reg)
+{
+	return pi_read_regr(cd->pi, 0, reg);
+}
 
-{	int j, r, e, s, p;
+static inline void write_reg(struct pcd_unit *cd, int reg, int val)
+{
+	pi_write_regr(cd->pi, 0, reg, val);
+}
+
+static int pcd_wait(struct pcd_unit *cd, int go, int stop, char *fun, char *msg)
+{
+	int j, r, e, s, p;
 
 	j = 0;
-	while ((((r=RR(1,6))&go)||(stop&&(!(r&stop))))&&(j++<PCD_SPIN))
+	while ((((r = status_reg(cd)) & go) || (stop && (!(r & stop))))
+	       && (j++ < PCD_SPIN))
 		udelay(PCD_DELAY);
 
-	if ((r&(IDE_ERR&stop))||(j>=PCD_SPIN)) {
-	   s = RR(0,7);
-	   e = RR(0,1);
-	   p = RR(0,2);
-       	   if (j >= PCD_SPIN) e |= 0x100;
-           if (fun) printk("%s: %s %s: alt=0x%x stat=0x%x err=0x%x"
-			   " loop=%d phase=%d\n",
-			    PCD.name,fun,msg,r,s,e,j,p);
-	   return (s<<8)+r;
+	if ((r & (IDE_ERR & stop)) || (j >= PCD_SPIN)) {
+		s = read_reg(cd, 7);
+		e = read_reg(cd, 1);
+		p = read_reg(cd, 2);
+		if (j >= PCD_SPIN)
+			e |= 0x100;
+		if (fun)
+			printk("%s: %s %s: alt=0x%x stat=0x%x err=0x%x"
+			       " loop=%d phase=%d\n",
+			       cd->name, fun, msg, r, s, e, j, p);
+		return (s << 8) + r;
 	}
 	return 0;
 }
 
-static int pcd_command( int unit, char * cmd, int dlen, char * fun )
-
-{	pi_connect(PI);
+static int pcd_command(struct pcd_unit *cd, char *cmd, int dlen, char *fun)
+{
+	pi_connect(cd->pi);
 
-        WR(0,6,0xa0 + 0x10*PCD.drive);
+	write_reg(cd, 6, 0xa0 + 0x10 * cd->drive);
 
-	if (pcd_wait(unit,IDE_BUSY|IDE_DRQ,0,fun,"before command")) {
-		pi_disconnect(PI);
+	if (pcd_wait(cd, IDE_BUSY | IDE_DRQ, 0, fun, "before command")) {
+		pi_disconnect(cd->pi);
 		return -1;
 	}
 
-        WR(0,4,dlen % 256);
-        WR(0,5,dlen / 256);
-        WR(0,7,0xa0);          /* ATAPI packet command */
+	write_reg(cd, 4, dlen % 256);
+	write_reg(cd, 5, dlen / 256);
+	write_reg(cd, 7, 0xa0);	/* ATAPI packet command */
 
-        if (pcd_wait(unit,IDE_BUSY,IDE_DRQ,fun,"command DRQ")) {
-		pi_disconnect(PI);
+	if (pcd_wait(cd, IDE_BUSY, IDE_DRQ, fun, "command DRQ")) {
+		pi_disconnect(cd->pi);
 		return -1;
 	}
 
-        if (RR(0,2) != 1) {
-           printk("%s: %s: command phase error\n",PCD.name,fun);
-	   pi_disconnect(PI);
-           return -1;
-        }
+	if (read_reg(cd, 2) != 1) {
+		printk("%s: %s: command phase error\n", cd->name, fun);
+		pi_disconnect(cd->pi);
+		return -1;
+	}
 
-	pi_write_block(PI,cmd,12);
+	pi_write_block(cd->pi, cmd, 12);
 
 	return 0;
 }
 
-static int pcd_completion( int unit, char * buf,  char * fun )
-
-{	int r, d, p, n, k, j;
+static int pcd_completion(struct pcd_unit *cd, char *buf, char *fun)
+{
+	int r, d, p, n, k, j;
 
-	r = -1; k = 0; j = 0;
+	r = -1;
+	k = 0;
+	j = 0;
 
-	if (!pcd_wait(unit,IDE_BUSY,IDE_DRQ|IDE_READY|IDE_ERR,
-						fun,"completion")) {
-	    r = 0;
-	    while (RR(0,7)&IDE_DRQ) {
-	        d = (RR(0,4)+256*RR(0,5));
-	        n = ((d+3)&0xfffc);
-	        p = RR(0,2)&3;
-
-	        if ((p == 2) && (n > 0) && (j == 0)) {
-		    pi_read_block(PI,buf,n);
-	            if (verbose > 1) 
-			printk("%s: %s: Read %d bytes\n",PCD.name,fun,n);
-		    r = 0; j++;
-	        } else {
-		    if (verbose > 1) 
-		        printk("%s: %s: Unexpected phase %d, d=%d, k=%d\n",
-					PCD.name,fun,p,d,k);
-		    if ((verbose < 2) && !pcd_warned) {
-	               	pcd_warned = 1;
-			printk("%s: WARNING: ATAPI phase errors\n",PCD.name);
+	if (!pcd_wait(cd, IDE_BUSY, IDE_DRQ | IDE_READY | IDE_ERR,
+		      fun, "completion")) {
+		r = 0;
+		while (read_reg(cd, 7) & IDE_DRQ) {
+			d = read_reg(cd, 4) + 256 * read_reg(cd, 5);
+			n = (d + 3) & 0xfffc;
+			p = read_reg(cd, 2) & 3;
+
+			if ((p == 2) && (n > 0) && (j == 0)) {
+				pi_read_block(cd->pi, buf, n);
+				if (verbose > 1)
+					printk("%s: %s: Read %d bytes\n",
+					       cd->name, fun, n);
+				r = 0;
+				j++;
+			} else {
+				if (verbose > 1)
+					printk
+					    ("%s: %s: Unexpected phase %d, d=%d, k=%d\n",
+					     cd->name, fun, p, d, k);
+				if ((verbose < 2) && !pcd_warned) {
+					pcd_warned = 1;
+					printk
+					    ("%s: WARNING: ATAPI phase errors\n",
+					     cd->name);
+				}
+				mdelay(1);
+			}
+			if (k++ > PCD_TMO) {
+				printk("%s: Stuck DRQ\n", cd->name);
+				break;
+			}
+			if (pcd_wait
+			    (cd, IDE_BUSY, IDE_DRQ | IDE_READY | IDE_ERR, fun,
+			     "completion")) {
+				r = -1;
+				break;
 			}
-		    mdelay(1);
-	        } 
-		if (k++ > PCD_TMO) {
-			printk("%s: Stuck DRQ\n",PCD.name);
-			break;
-		}
-	        if (pcd_wait(unit,IDE_BUSY,IDE_DRQ|IDE_READY|IDE_ERR,
-				fun,"completion")) { 
-			r = -1;
-			break;
 		}
-	    }
 	}
-	
-	pi_disconnect(PI); 
+
+	pi_disconnect(cd->pi);
 
 	return r;
 }
 
-static void pcd_req_sense( int unit, char *fun )
-
-{	char	rs_cmd[12] = { 0x03,0,0,0,16,0,0,0,0,0,0,0 };
-	char	buf[16];
-	int 	r, c;
+static void pcd_req_sense(struct pcd_unit *cd, char *fun)
+{
+	char rs_cmd[12] = { 0x03, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0 };
+	char buf[16];
+	int r, c;
 
-	r = pcd_command(unit,rs_cmd,16,"Request sense");
+	r = pcd_command(cd, rs_cmd, 16, "Request sense");
 	mdelay(1);
-	if (!r) pcd_completion(unit,buf,"Request sense");
+	if (!r)
+		pcd_completion(cd, buf, "Request sense");
 
-	PCD.last_sense = -1;  c = 2;
+	cd->last_sense = -1;
+	c = 2;
 	if (!r) {
-            if (fun) printk("%s: %s: Sense key: %x, ASC: %x, ASQ: %x\n",
-	                       PCD.name,fun,buf[2]&0xf,buf[12],buf[13]);
-	    c = buf[2]&0xf;
-	    PCD.last_sense = c | ((buf[12]&0xff)<<8) | ((buf[13]&0xff)<<16);
-        } 
-	if ((c == 2) || (c == 6)) PCD.changed = 1;
+		if (fun)
+			printk("%s: %s: Sense key: %x, ASC: %x, ASQ: %x\n",
+			       cd->name, fun, buf[2] & 0xf, buf[12], buf[13]);
+		c = buf[2] & 0xf;
+		cd->last_sense =
+		    c | ((buf[12] & 0xff) << 8) | ((buf[13] & 0xff) << 16);
+	}
+	if ((c == 2) || (c == 6))
+		cd->changed = 1;
 }
 
-static int pcd_atapi( int unit, char * cmd, int dlen, char * buf, char * fun )
-
-{	int r;
+static int pcd_atapi(struct pcd_unit *cd, char *cmd, int dlen, char *buf, char *fun)
+{
+	int r;
 
-	r = pcd_command(unit,cmd,dlen,fun);
+	r = pcd_command(cd, cmd, dlen, fun);
 	mdelay(1);
-	if (!r) r = pcd_completion(unit,buf,fun);
-	if (r) pcd_req_sense(unit,fun);
-	
+	if (!r)
+		r = pcd_completion(cd, buf, fun);
+	if (r)
+		pcd_req_sense(cd, fun);
+
 	return r;
 }
 
-static int pcd_packet(struct cdrom_device_info *cdi,
-				struct cdrom_generic_command *cgc)
+static int pcd_packet(struct cdrom_device_info *cdi, struct cdrom_generic_command *cgc)
 {
-	char	*un_cmd;
-	int	unit = DEVICE_NR(cdi->dev);
-
-	un_cmd = cgc->cmd;
-	return pcd_atapi(unit,un_cmd,cgc->buflen,cgc->buffer, "generic packet");
+	return pcd_atapi(cdi->handle, cgc->cmd, cgc->buflen, cgc->buffer,
+			 "generic packet");
 }
 
 #define DBMSG(msg)	((verbose>1)?(msg):NULL)
 
 static int pcd_media_changed(struct cdrom_device_info *cdi, int slot_nr)
-
-{	int 	r;
-	int	unit = DEVICE_NR(cdi->dev);
-
-	r = PCD.changed;
-	PCD.changed = 0;
-
-	return r;    
+{
+	struct pcd_unit *cd = cdi->handle;
+	int res = cd->changed;
+	if (res)
+		cd->changed = 0;
+	return res;
 }
 
 static int pcd_lock_door(struct cdrom_device_info *cdi, int lock)
+{
+	char un_cmd[12] = { 0x1e, 0, 0, 0, lock, 0, 0, 0, 0, 0, 0, 0 };
 
-{	char	un_cmd[12] = { 0x1e,0,0,0,lock,0,0,0,0,0,0,0 };
-        int     unit = DEVICE_NR(cdi->dev);
-
-	return pcd_atapi(unit,un_cmd,0,pcd_scratch,
-				lock?"lock door":"unlock door");
+	return pcd_atapi(cdi->handle, un_cmd, 0, pcd_scratch,
+			 lock ? "lock door" : "unlock door");
 }
 
 static int pcd_tray_move(struct cdrom_device_info *cdi, int position)
+{
+	char ej_cmd[12] = { 0x1b, 0, 0, 0, 3 - position, 0, 0, 0, 0, 0, 0, 0 };
 
-{	char	ej_cmd[12] = { 0x1b,0,0,0,3-position,0,0,0,0,0,0,0 };
-	int	unit = DEVICE_NR(cdi->dev);
-
-	return pcd_atapi(unit,ej_cmd,0,pcd_scratch,
-				position?"eject":"close tray");
+	return pcd_atapi(cdi->handle, ej_cmd, 0, pcd_scratch,
+			 position ? "eject" : "close tray");
 }
 
-static void pcd_sleep( int cs )
-
-{       current->state = TASK_INTERRUPTIBLE;
-        schedule_timeout(cs);
+static void pcd_sleep(int cs)
+{
+	current->state = TASK_INTERRUPTIBLE;
+	schedule_timeout(cs);
 }
 
-static int pcd_reset( int unit )
-
-{	int	i, k, flg;
-	int	expect[5] = {1,1,1,0x14,0xeb};
+static int pcd_reset(struct pcd_unit *cd)
+{
+	int i, k, flg;
+	int expect[5] = { 1, 1, 1, 0x14, 0xeb };
 
-	pi_connect(PI);
-	WR(0,6,0xa0 + 0x10*PCD.drive);
-	WR(0,7,8);
+	pi_connect(cd->pi);
+	write_reg(cd, 6, 0xa0 + 0x10 * cd->drive);
+	write_reg(cd, 7, 8);
 
-	pcd_sleep(20*HZ/1000);  		/* delay a bit */
+	pcd_sleep(20 * HZ / 1000);	/* delay a bit */
 
 	k = 0;
-	while ((k++ < PCD_RESET_TMO) && (RR(1,6)&IDE_BUSY))
-		pcd_sleep(HZ/10);
+	while ((k++ < PCD_RESET_TMO) && (status_reg(cd) & IDE_BUSY))
+		pcd_sleep(HZ / 10);
 
 	flg = 1;
-	for(i=0;i<5;i++) flg &= (RR(0,i+1) == expect[i]);
+	for (i = 0; i < 5; i++)
+		flg &= (read_reg(cd, i + 1) == expect[i]);
 
 	if (verbose) {
-		printk("%s: Reset (%d) signature = ",PCD.name,k);
-		for (i=0;i<5;i++) printk("%3x",RR(0,i+1));
-		if (!flg) printk(" (incorrect)");
+		printk("%s: Reset (%d) signature = ", cd->name, k);
+		for (i = 0; i < 5; i++)
+			printk("%3x", read_reg(cd, i + 1));
+		if (!flg)
+			printk(" (incorrect)");
 		printk("\n");
 	}
-	
-	pi_disconnect(PI);
-	return flg-1;	
+
+	pi_disconnect(cd->pi);
+	return flg - 1;
 }
 
 static int pcd_drive_reset(struct cdrom_device_info *cdi)
-
-{	return pcd_reset(DEVICE_NR(cdi->dev));
+{
+	return pcd_reset(cdi->handle);
 }
 
-static int pcd_ready_wait( int unit, int tmo )
-
-{       char    tr_cmd[12] = {0,0,0,0,0,0,0,0,0,0,0,0};
-        int     k, p;
+static int pcd_ready_wait(struct pcd_unit *cd, int tmo)
+{
+	char tr_cmd[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+	int k, p;
 
-        k = 0;
-        while (k < tmo) {
-          PCD.last_sense = 0;
-          pcd_atapi(unit,tr_cmd,0,NULL,DBMSG("test unit ready"));
-          p = PCD.last_sense;
-          if (!p) return 0;
-	  if (!(((p & 0xffff) == 0x0402)||((p & 0xff) == 6))) return p;
-          k++;
-          pcd_sleep(HZ);
-        }
-        return 0x000020;        /* timeout */
+	k = 0;
+	while (k < tmo) {
+		cd->last_sense = 0;
+		pcd_atapi(cd, tr_cmd, 0, NULL, DBMSG("test unit ready"));
+		p = cd->last_sense;
+		if (!p)
+			return 0;
+		if (!(((p & 0xffff) == 0x0402) || ((p & 0xff) == 6)))
+			return p;
+		k++;
+		pcd_sleep(HZ);
+	}
+	return 0x000020;	/* timeout */
 }
 
 static int pcd_drive_status(struct cdrom_device_info *cdi, int slot_nr)
+{
+	char rc_cmd[12] = { 0x25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+	struct pcd_unit *cd = cdi->handle;
 
-{	char    rc_cmd[12] = { 0x25,0,0,0,0,0,0,0,0,0,0,0};
-	int	unit = DEVICE_NR(cdi->dev);
-
-	if (pcd_ready_wait(unit,PCD_READY_TMO)) 
+	if (pcd_ready_wait(cd, PCD_READY_TMO))
 		return CDS_DRIVE_NOT_READY;
-	if (pcd_atapi(unit,rc_cmd,8,pcd_scratch,DBMSG("check media")))
+	if (pcd_atapi(cd, rc_cmd, 8, pcd_scratch, DBMSG("check media")))
 		return CDS_NO_DISC;
 	return CDS_DISC_OK;
 }
 
-static int pcd_identify( int unit, char * id )
-
-{	int k, s;
-	char   id_cmd[12] = {0x12,0,0,0,36,0,0,0,0,0,0,0};
+static int pcd_identify(struct pcd_unit *cd, char *id)
+{
+	int k, s;
+	char id_cmd[12] = { 0x12, 0, 0, 0, 36, 0, 0, 0, 0, 0, 0, 0 };
 
 	pcd_bufblk = -1;
 
-        s = pcd_atapi(unit,id_cmd,36,pcd_buffer,"identify");
+	s = pcd_atapi(cd, id_cmd, 36, pcd_buffer, "identify");
 
-	if (s) return -1;
+	if (s)
+		return -1;
 	if ((pcd_buffer[0] & 0x1f) != 5) {
-	  if (verbose) printk("%s: %s is not a CD-ROM\n",
-			PCD.name,PCD.drive?"Slave":"Master");
-	  return -1;
+		if (verbose)
+			printk("%s: %s is not a CD-ROM\n",
+			       cd->name, cd->drive ? "Slave" : "Master");
+		return -1;
+	}
+	memcpy(id, pcd_buffer + 16, 16);
+	id[16] = 0;
+	k = 16;
+	while ((k >= 0) && (id[k] <= 0x20)) {
+		id[k] = 0;
+		k--;
 	}
-	for (k=0;k<16;k++) id[k] = pcd_buffer[16+k]; id[16] = 0;
-	k = 16; while ((k >= 0) && (id[k] <= 0x20)) { id[k] = 0; k--; }
 
-	printk("%s: %s: %s\n",PCD.name,PCD.drive?"Slave":"Master",id);
+	printk("%s: %s: %s\n", cd->name, cd->drive ? "Slave" : "Master", id);
 
 	return 0;
 }
 
-static int pcd_probe( int unit, int ms, char * id )
-
-/*	returns  0, with id set if drive is detected
-	        -1, if drive detection failed
-*/
-
-{	if (ms == -1) {
-            for (PCD.drive=0;PCD.drive<=1;PCD.drive++)
-	       if (!pcd_reset(unit) && !pcd_identify(unit,id)) 
-		  return 0;
+/*
+ * returns  0, with id set if drive is detected
+ *	    -1, if drive detection failed
+ */
+static int pcd_probe(struct pcd_unit *cd, int ms, char *id)
+{
+	if (ms == -1) {
+		for (cd->drive = 0; cd->drive <= 1; cd->drive++)
+			if (!pcd_reset(cd) && !pcd_identify(cd, id))
+				return 0;
 	} else {
-	    PCD.drive = ms;
-            if (!pcd_reset(unit) && !pcd_identify(unit,id)) 
-		return 0;
+		cd->drive = ms;
+		if (!pcd_reset(cd) && !pcd_identify(cd, id))
+			return 0;
 	}
 	return -1;
 }
 
-static void pcd_probe_capabilities( void )
-
-{	int	unit, r;
-	char	buffer[32];
-	char 	cmd[12]={0x5a,1<<3,0x2a,0,0,0,0,18,0,0,0,0};
-
-	for (unit=0;unit<PCD_UNITS;unit++) {
-		if (!PCD.present) continue;
-		r = pcd_atapi(unit,cmd,18, buffer,"mode sense capabilities");
-		if (r) continue;
+static void pcd_probe_capabilities(void)
+{
+	int unit, r;
+	char buffer[32];
+	char cmd[12] = { 0x5a, 1 << 3, 0x2a, 0, 0, 0, 0, 18, 0, 0, 0, 0 };
+	struct pcd_unit *cd;
+
+	for (unit = 0, cd = pcd; unit < PCD_UNITS; unit++, cd++) {
+		if (!cd->present)
+			continue;
+		r = pcd_atapi(cd, cmd, 18, buffer, "mode sense capabilities");
+		if (r)
+			continue;
 		/* we should now have the cap page */
 		if ((buffer[11] & 1) == 0)
-			PCD.info.mask |= CDC_CD_R;
+			cd->info.mask |= CDC_CD_R;
 		if ((buffer[11] & 2) == 0)
-			PCD.info.mask |= CDC_CD_RW;
+			cd->info.mask |= CDC_CD_RW;
 		if ((buffer[12] & 1) == 0)
-			PCD.info.mask |= CDC_PLAY_AUDIO;
+			cd->info.mask |= CDC_PLAY_AUDIO;
 		if ((buffer[14] & 1) == 0)
-			PCD.info.mask |= CDC_LOCK;
+			cd->info.mask |= CDC_LOCK;
 		if ((buffer[14] & 8) == 0)
-			PCD.info.mask |= CDC_OPEN_TRAY;
+			cd->info.mask |= CDC_OPEN_TRAY;
 		if ((buffer[14] >> 6) == 0)
-			PCD.info.mask |= CDC_CLOSE_TRAY;
+			cd->info.mask |= CDC_CLOSE_TRAY;
 	}
 }
 
-static int pcd_detect( void )
-
-{	char    id[18];
-	int	k, unit;
+static int pcd_detect(void)
+{
+	char id[18];
+	int k, unit;
+	struct pcd_unit *cd;
 
 	printk("%s: %s version %s, major %d, nice %d\n",
-		name,name,PCD_VERSION,major,nice);
+	       name, name, PCD_VERSION, major, nice);
 
 	k = 0;
-	if (pcd_drive_count == 0) {  /* nothing spec'd - so autoprobe for 1 */
-	    unit = 0;
-	    if (pi_init(PI,1,-1,-1,-1,-1,-1,pcd_buffer,
-                     PI_PCD,verbose,PCD.name)) {
-		if (!pcd_probe(unit,-1,id)) {
-			PCD.present = 1;
-			k++;
-		} else pi_release(PI);
-	    }
-
-	} else for (unit=0;unit<PCD_UNITS;unit++) if (DU[D_PRT])
-	    if (pi_init(PI,0,DU[D_PRT],DU[D_MOD],DU[D_UNI],
-                        DU[D_PRO],DU[D_DLY],pcd_buffer,PI_PCD,verbose,
-                        PCD.name)) {
-		if (!pcd_probe(unit,DU[D_SLV],id)) {
-                        PCD.present = 1;
-                        k++;
-                } else pi_release(PI);
-            }
-
-	if (k) return 0;
-	
-	printk("%s: No CD-ROM drive found\n",name);
+	if (pcd_drive_count == 0) { /* nothing spec'd - so autoprobe for 1 */
+		cd = pcd;
+		if (pi_init(cd->pi, 1, -1, -1, -1, -1, -1, pcd_buffer,
+			    PI_PCD, verbose, cd->name)) {
+			if (!pcd_probe(cd, -1, id)) {
+				cd->present = 1;
+				k++;
+			} else
+				pi_release(cd->pi);
+		}
+	} else {
+		for (unit = 0, cd = pcd; unit < PCD_UNITS; unit++, cd++) {
+			int *conf = *drives[unit];
+			if (!conf[D_PRT])
+				continue;
+			if (!pi_init(cd->pi, 0, conf[D_PRT], conf[D_MOD],
+				     conf[D_UNI], conf[D_PRO], conf[D_DLY],
+				     pcd_buffer, PI_PCD, verbose, cd->name)) 
+				continue;
+			if (!pcd_probe(cd, conf[D_SLV], id)) {
+				cd->present = 1;
+				k++;
+			} else
+				pi_release(cd->pi);
+		}
+	}
+	if (k)
+		return 0;
+
+	printk("%s: No CD-ROM drive found\n", name);
 	return -1;
 }
 
 /* I/O request processing */
 
-static void do_pcd_request (request_queue_t * q)
-
-{       int unit;
-
-	if (pcd_busy) return;
-        while (1) {
-	    if (blk_queue_empty(QUEUE))
-		    return;
-
-	    if (rq_data_dir(CURRENT) == READ) {
-		unit = minor(CURRENT->rq_dev);
-		if (unit != pcd_unit) {
-			pcd_bufblk = -1;
-			pcd_unit = unit;
-		}
-	        pcd_sector = CURRENT->sector;
-	        pcd_count = CURRENT->current_nr_sectors;
-	        pcd_buf = CURRENT->buffer;
-		pcd_busy = 1;
-	        ps_set_intr(do_pcd_read,0,0,nice); 
+static void do_pcd_request(request_queue_t * q)
+{
+	if (pcd_busy)
 		return;
-	    } 
-	    else end_request(CURRENT, 0);
+	while (1) {
+		struct request *req;
+		if (blk_queue_empty(QUEUE))
+			return;
+		req = CURRENT;
+		if (rq_data_dir(req) == READ) {
+			struct pcd_unit *cd = pcd + minor(req->rq_dev);
+			if (cd != pcd_current)
+				pcd_bufblk = -1;
+			pcd_current = cd;
+			pcd_sector = req->sector;
+			pcd_count = req->current_nr_sectors;
+			pcd_buf = req->buffer;
+			pcd_busy = 1;
+			ps_set_intr(do_pcd_read, 0, 0, nice);
+			return;
+		} else
+			end_request(req, 0);
 	}
 }
 
-static int pcd_ready( void )
-
-{	int	unit = pcd_unit;
-
-	return (((RR(1,6)&(IDE_BUSY|IDE_DRQ))==IDE_DRQ)) ;
+static int pcd_ready(void)
+{
+	return (((status_reg(pcd_current) & (IDE_BUSY | IDE_DRQ)) == IDE_DRQ));
 }
 
-static void pcd_transfer( void )
-
-{	int	k, o;
+static void pcd_transfer(void)
+{
 
-	while (pcd_count && (pcd_sector/4 == pcd_bufblk)) {
-		o = (pcd_sector % 4) * 512;
-		for(k=0;k<512;k++) pcd_buf[k] = pcd_buffer[o+k];
+	while (pcd_count && (pcd_sector / 4 == pcd_bufblk)) {
+		int o = (pcd_sector % 4) * 512;
+		memcpy(pcd_buf, pcd_buffer + o, 512);
 		pcd_count--;
 		pcd_buf += 512;
 		pcd_sector++;
 	}
 }
 
-static void pcd_start( void )
-
-{	int	unit = pcd_unit;
-	int	b, i;
-	char	rd_cmd[12] = {0xa8,0,0,0,0,0,0,0,0,1,0,0};
-	long    saved_flags;
+static void pcd_start(void)
+{
+	int b, i;
+	char rd_cmd[12] = { 0xa8, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 };
+	long saved_flags;
 
 	pcd_bufblk = pcd_sector / 4;
-        b = pcd_bufblk;
-	for(i=0;i<4;i++) { 
-	   rd_cmd[5-i] = b & 0xff;
-	   b = b >> 8;
+	b = pcd_bufblk;
+	for (i = 0; i < 4; i++) {
+		rd_cmd[5 - i] = b & 0xff;
+		b = b >> 8;
 	}
 
-	if (pcd_command(unit,rd_cmd,2048,"read block")) {
-		pcd_bufblk = -1; 
-		spin_lock_irqsave(&pcd_lock,saved_flags);
+	if (pcd_command(pcd_current, rd_cmd, 2048, "read block")) {
+		pcd_bufblk = -1;
+		spin_lock_irqsave(&pcd_lock, saved_flags);
 		pcd_busy = 0;
 		end_request(CURRENT, 0);
 		do_pcd_request(NULL);
-		spin_unlock_irqrestore(&pcd_lock,saved_flags);
+		spin_unlock_irqrestore(&pcd_lock, saved_flags);
 		return;
 	}
 
 	mdelay(1);
 
-	ps_set_intr(do_pcd_read_drq,pcd_ready,PCD_TMO,nice);
-
+	ps_set_intr(do_pcd_read_drq, pcd_ready, PCD_TMO, nice);
 }
 
-static void do_pcd_read( void )
-
-
-{	int	unit = pcd_unit;
-	long    saved_flags;
-
+static void do_pcd_read(void)
+{
 	pcd_busy = 1;
 	pcd_retries = 0;
 	pcd_transfer();
 	if (!pcd_count) {
-		spin_lock_irqsave(&pcd_lock,saved_flags);
+		long saved_flags;
+		spin_lock_irqsave(&pcd_lock, saved_flags);
 		end_request(CURRENT, 1);
 		pcd_busy = 0;
 		do_pcd_request(NULL);
-		spin_unlock_irqrestore(&pcd_lock,saved_flags);
+		spin_unlock_irqrestore(&pcd_lock, saved_flags);
 		return;
 	}
 
-	pi_do_claimed(PI,pcd_start);
+	pi_do_claimed(pcd_current->pi, pcd_start);
 }
 
-static void do_pcd_read_drq( void )
-
-{	int	unit = pcd_unit;
-	long    saved_flags;
+static void do_pcd_read_drq(void)
+{
+	long saved_flags;
 
-	if (pcd_completion(unit,pcd_buffer,"read block")) {
-                if (pcd_retries < PCD_RETRIES) {
-                        mdelay(1); 
-                        pcd_retries++;
-			pi_do_claimed(PI,pcd_start);
-                        return;
-                        }
-		spin_lock_irqsave(&pcd_lock,saved_flags);
+	if (pcd_completion(pcd_current, pcd_buffer, "read block")) {
+		if (pcd_retries < PCD_RETRIES) {
+			mdelay(1);
+			pcd_retries++;
+			pi_do_claimed(pcd_current->pi, pcd_start);
+			return;
+		}
+		spin_lock_irqsave(&pcd_lock, saved_flags);
 		pcd_busy = 0;
 		pcd_bufblk = -1;
 		end_request(CURRENT, 0);
 		do_pcd_request(NULL);
-		spin_unlock_irqrestore(&pcd_lock,saved_flags);
+		spin_unlock_irqrestore(&pcd_lock, saved_flags);
 		return;
 	}
 
 	do_pcd_read();
-	spin_lock_irqsave(&pcd_lock,saved_flags);
+	spin_lock_irqsave(&pcd_lock, saved_flags);
 	do_pcd_request(NULL);
-	spin_unlock_irqrestore(&pcd_lock,saved_flags); 
+	spin_unlock_irqrestore(&pcd_lock, saved_flags);
 }
 
 /* the audio_ioctl stuff is adapted from sr_ioctl.c */
 
-static int pcd_audio_ioctl(struct cdrom_device_info *cdi,
-                                unsigned int cmd, void *arg)
+static int pcd_audio_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, void *arg)
+{
+	struct pcd_unit *cd = cdi->handle;
+
+	switch (cmd) {
+
+	case CDROMREADTOCHDR:
+
+		{
+			char cmd[12] =
+			    { GPCMD_READ_TOC_PMA_ATIP, 0, 0, 0, 0, 0, 0, 0, 12,
+			 0, 0, 0 };
+			struct cdrom_tochdr *tochdr =
+			    (struct cdrom_tochdr *) arg;
+			char buffer[32];
+			int r;
+
+			r = pcd_atapi(cd, cmd, 12, buffer, "read toc header");
+
+			tochdr->cdth_trk0 = buffer[2];
+			tochdr->cdth_trk1 = buffer[3];
 
-{	int	unit = DEVICE_NR(cdi->dev);
- 
-    	switch (cmd) { 
-    
-    	case CDROMREADTOCHDR:
-    
-	{	char cmd[12]={GPCMD_READ_TOC_PMA_ATIP,0,0,0,0,0,0,0,12,0,0,0};
-		struct cdrom_tochdr* tochdr = (struct cdrom_tochdr*)arg;
-		char buffer[32];
-		int r;
-	
-		r = pcd_atapi(unit,cmd,12,buffer,"read toc header");
-
-		tochdr->cdth_trk0 = buffer[2];
-		tochdr->cdth_trk1 = buffer[3];
-	
-		return r * EIO;
-    	}
-	
-    	case CDROMREADTOCENTRY:
-
-    	{	char cmd[12]={GPCMD_READ_TOC_PMA_ATIP,0,0,0,0,0,0,0,12,0,0,0};
-
-		struct cdrom_tocentry* tocentry = (struct cdrom_tocentry*)arg;
-		unsigned char buffer[32];
-		int	r;
-	
-		cmd[1] = (tocentry->cdte_format == CDROM_MSF ? 0x02 : 0);
-		cmd[6] = tocentry->cdte_track;
-	
-		r = pcd_atapi(unit,cmd,12,buffer,"read toc entry");
-
-        	tocentry->cdte_ctrl = buffer[5] & 0xf;	
-        	tocentry->cdte_adr = buffer[5] >> 4;
-        	tocentry->cdte_datamode = (tocentry->cdte_ctrl & 0x04)?1:0;
-		if (tocentry->cdte_format == CDROM_MSF) {
-		    tocentry->cdte_addr.msf.minute = buffer[9];
-	    	    tocentry->cdte_addr.msf.second = buffer[10];
-	            tocentry->cdte_addr.msf.frame = buffer[11];
-	        } else
-	            tocentry->cdte_addr.lba = 
-				(((((buffer[8] << 8) + buffer[9]) << 8)
-                                       + buffer[10]) << 8) + buffer[11];
-	
-                return r * EIO;
-        }
-
-    	default:
-
-        	return -ENOSYS;
-    	}
-}
-	
-static int pcd_get_mcn (struct cdrom_device_info *cdi, struct cdrom_mcn *mcn)
-
-{	char 	cmd[12]={GPCMD_READ_SUBCHANNEL,0,0x40,2,0,0,0,0,24,0,0,0};
-        char 	buffer[32];
-	int	k;
-	int	unit = DEVICE_NR(cdi->dev);
+			return r ? -EIO : 0;
+		}
+
+	case CDROMREADTOCENTRY:
+
+		{
+			char cmd[12] =
+			    { GPCMD_READ_TOC_PMA_ATIP, 0, 0, 0, 0, 0, 0, 0, 12,
+			 0, 0, 0 };
+
+			struct cdrom_tocentry *tocentry =
+			    (struct cdrom_tocentry *) arg;
+			unsigned char buffer[32];
+			int r;
+
+			cmd[1] =
+			    (tocentry->cdte_format == CDROM_MSF ? 0x02 : 0);
+			cmd[6] = tocentry->cdte_track;
+
+			r = pcd_atapi(cd, cmd, 12, buffer, "read toc entry");
+
+			tocentry->cdte_ctrl = buffer[5] & 0xf;
+			tocentry->cdte_adr = buffer[5] >> 4;
+			tocentry->cdte_datamode =
+			    (tocentry->cdte_ctrl & 0x04) ? 1 : 0;
+			if (tocentry->cdte_format == CDROM_MSF) {
+				tocentry->cdte_addr.msf.minute = buffer[9];
+				tocentry->cdte_addr.msf.second = buffer[10];
+				tocentry->cdte_addr.msf.frame = buffer[11];
+			} else
+				tocentry->cdte_addr.lba =
+				    (((((buffer[8] << 8) + buffer[9]) << 8)
+				      + buffer[10]) << 8) + buffer[11];
+
+			return r ? -EIO : 0;
+		}
+
+	default:
 
-        if (pcd_atapi(unit,cmd,24,buffer,"get mcn")) return -EIO;
+		return -ENOSYS;
+	}
+}
 
-	for (k=0;k<13;k++) mcn->medium_catalog_number[k] = buffer[k+9];
+static int pcd_get_mcn(struct cdrom_device_info *cdi, struct cdrom_mcn *mcn)
+{
+	char cmd[12] =
+	    { GPCMD_READ_SUBCHANNEL, 0, 0x40, 2, 0, 0, 0, 0, 24, 0, 0, 0 };
+	char buffer[32];
+
+	if (pcd_atapi(cdi->handle, cmd, 24, buffer, "get mcn"))
+		return -EIO;
+
+	memcpy(mcn->medium_catalog_number, buffer + 9, 13);
 	mcn->medium_catalog_number[13] = 0;
-	
+
 	return 0;
 }
 
-
 static int __init pcd_init(void)
 {
+	struct pcd_unit *cd;
 	int unit;
 
 	if (disable)
@@ -898,15 +918,15 @@
 	/* get the atapi capabilities page */
 	pcd_probe_capabilities();
 
-	if (register_blkdev(MAJOR_NR,name,&pcd_bdops)) {
-		printk("pcd: unable to get major number %d\n",MAJOR_NR);
+	if (register_blkdev(MAJOR_NR, name, &pcd_bdops)) {
+		printk("pcd: unable to get major number %d\n", MAJOR_NR);
 		return -1;
 	}
 
-	for (unit=0;unit<PCD_UNITS;unit++) {
-		if (PCD.present) {
-			register_cdrom(&PCD.info);
-			devfs_plain_cdrom(&PCD.info, &pcd_bdops);
+	for (unit = 0, cd = pcd; unit < PCD_UNITS; unit++, cd++) {
+		if (cd->present) {
+			register_cdrom(&cd->info);
+			devfs_plain_cdrom(&cd->info, &pcd_bdops);
 		}
 	}
 
@@ -917,13 +937,16 @@
 
 static void __exit pcd_exit(void)
 {
+	struct pcd_unit *cd;
 	int unit;
-	for (unit=0;unit<PCD_UNITS;unit++) 
-		if (PCD.present) {
-			pi_release(PI);
-			unregister_cdrom(&PCD.info);
+
+	for (unit = 0, cd = pcd; unit < PCD_UNITS; unit++, cd++) {
+		if (cd->present) {
+			pi_release(cd->pi);
+			unregister_cdrom(&cd->info);
 		}
-	unregister_blkdev(MAJOR_NR,name);
+	}
+	unregister_blkdev(MAJOR_NR, name);
 }
 
 MODULE_LICENSE("GPL");
diff -Nru a/drivers/block/paride/pd.c b/drivers/block/paride/pd.c
--- a/drivers/block/paride/pd.c	Mon Sep  9 10:36:13 2002
+++ b/drivers/block/paride/pd.c	Mon Sep  9 10:36:13 2002
@@ -271,8 +271,6 @@
 static int pd_check_media(kdev_t dev);
 static void pd_eject( int unit);
 
-static struct hd_struct pd_hd[PD_DEVS];
-
 #define PD_NAMELEN	8
 
 struct pd_unit {
@@ -438,9 +436,9 @@
 	if ((unit >= PD_UNITS) || !PD.present)
 		return -ENODEV;
 	if (pd_identify(unit))
-		pd_hd[minor(dev)].nr_sects = PD.capacity;
+		set_capacity(&PD.gd, PD.capacity);
 	else
-		pd_hd[minor(dev)].nr_sects = 0;
+		set_capacity(&PD.gd, 0);
         return 0;
 }
 
@@ -687,10 +685,8 @@
 			PD.gd.major_name = PD.name;
 			PD.gd.minor_shift = PD_BITS;
 			PD.gd.fops = &pd_fops;
-			PD.gd.nr_real = 1;
 			PD.gd.major = major;
 			PD.gd.first_minor = unit << PD_BITS;
-			PD.gd.part = pd_hd + (unit << PD_BITS);
 			add_gendisk(&PD.gd);
 			register_disk(&PD.gd,mk_kdev(MAJOR_NR,unit<<PD_BITS),
 					PD_PARTNS,&pd_fops,
@@ -728,7 +724,7 @@
         pd_count = CURRENT->current_nr_sectors;
 
         if ((pd_dev >= PD_DEVS) || 
-	    ((pd_block+pd_count) > pd_hd[pd_dev].nr_sects)) {
+	    ((pd_block+pd_count) > get_capacity(&pd[unit].gd))) {
                 end_request(CURRENT, 0);
                 goto repeat;
         }
diff -Nru a/drivers/block/ps2esdi.c b/drivers/block/ps2esdi.c
--- a/drivers/block/ps2esdi.c	Mon Sep  9 10:35:43 2002
+++ b/drivers/block/ps2esdi.c	Mon Sep  9 10:35:44 2002
@@ -109,7 +109,6 @@
 
 static int no_int_yet;
 static int ps2esdi_drives;
-static struct hd_struct ps2esdi[MAX_HD << 6];
 static u_short io_base;
 static struct timer_list esdi_timer = { function: ps2esdi_reset_timer };
 static int reset_status;
@@ -152,17 +151,13 @@
 	major_name:	"eda",
 	first_minor:	0,
 	minor_shift:	6,
-	part:		ps2esdi,
 	fops:		&ps2esdi_fops,
-	nr_real:	1
 },{
 	major:		MAJOR_NR,
 	first_minor:	64,
 	major_name:	"edb",
 	minor_shift:	6,
-	part:		ps2esdi+64,
 	fops:		&ps2esdi_fops,
-	nr_real:	1
 }
 };
 
@@ -489,6 +484,7 @@
 static void do_ps2esdi_request(request_queue_t * q)
 {
 	u_int block, count;
+	int unit;
 	/* since, this routine is called with interrupts cleared - they 
 	   must be before it finishes  */
 
@@ -505,18 +501,19 @@
 	if (blk_queue_empty(QUEUE))
 		return;
 
+	unit = DEVICE_NR(CURRENT->rq_dev);
 	if (isa_virt_to_bus(CURRENT->buffer + CURRENT->current_nr_sectors * 512) > 16 * MB) {
 		printk("%s: DMA above 16MB not supported\n", DEVICE_NAME);
 		end_request(CURRENT, FAIL);
 	}			/* check for above 16Mb dmas */
-	else if ((DEVICE_NR(CURRENT->rq_dev) < ps2esdi_drives) &&
+	else if ((unit < ps2esdi_drives) &&
 	    (CURRENT->sector + CURRENT->current_nr_sectors <=
-	     ps2esdi[minor(CURRENT->rq_dev)].nr_sects) &&
+	     get_capacity(&ps2esdi_gendisk[unit])) &&
 	    	CURRENT->flags & REQ_CMD) {
 #if 0
 		printk("%s:got request. device : %d minor : %d command : %d  sector : %ld count : %ld\n",
 		       DEVICE_NAME,
-		       DEVICE_NR(CURRENT->rq_dev), minor(CURRENT->rq_dev),
+		       unit, minor(CURRENT->rq_dev),
 		       CURRENT->cmd, CURRENT->sector,
 		       CURRENT->current_nr_sectors);
 #endif
@@ -526,10 +523,10 @@
 
 		switch (rq_data_dir(CURRENT)) {
 		case READ:
-			ps2esdi_readwrite(READ, DEVICE_NR(CURRENT->rq_dev), block, count);
+			ps2esdi_readwrite(READ, unit, block, count);
 			break;
 		case WRITE:
-			ps2esdi_readwrite(WRITE, DEVICE_NR(CURRENT->rq_dev), block, count);
+			ps2esdi_readwrite(WRITE, unit, block, count);
 			break;
 		default:
 			printk("%s: Unknown command\n", DEVICE_NAME);
@@ -540,7 +537,7 @@
 	/* is request is valid */ 
 	else {
 		printk("Grrr. error. ps2esdi_drives: %d, %lu %lu\n", ps2esdi_drives,
-		       CURRENT->sector, ps2esdi[minor(CURRENT->rq_dev)].nr_sects);
+		       CURRENT->sector, get_capacity(&ps2esdi_gendisk[unit]));
 		end_request(CURRENT, FAIL);
 	}
 
diff -Nru a/drivers/block/rd.c b/drivers/block/rd.c
--- a/drivers/block/rd.c	Mon Sep  9 10:36:12 2002
+++ b/drivers/block/rd.c	Mon Sep  9 10:36:12 2002
@@ -109,9 +109,11 @@
 static int ramdisk_readpage(struct file *file, struct page * page)
 {
 	if (!PageUptodate(page)) {
-		memset(kmap(page), 0, PAGE_CACHE_SIZE);
-		kunmap(page);
+		void *kaddr = kmap_atomic(page, KM_USER0);
+
+		memset(kaddr, 0, PAGE_CACHE_SIZE);
 		flush_dcache_page(page);
+		kunmap_atomic(kaddr, KM_USER0);
 		SetPageUptodate(page);
 	}
 	unlock_page(page);
@@ -121,9 +123,11 @@
 static int ramdisk_prepare_write(struct file *file, struct page *page, unsigned offset, unsigned to)
 {
 	if (!PageUptodate(page)) {
-		void *addr = page_address(page);
-		memset(addr, 0, PAGE_CACHE_SIZE);
+		void *kaddr = kmap_atomic(page, KM_USER0);
+
+		memset(kaddr, 0, PAGE_CACHE_SIZE);
 		flush_dcache_page(page);
+		kunmap_atomic(kaddr, KM_USER0);
 		SetPageUptodate(page);
 	}
 	SetPageDirty(page);
@@ -178,8 +182,11 @@
 			err = 0;
 
 			if (!PageUptodate(page)) {
-				memset(kmap(page), 0, PAGE_CACHE_SIZE);
-				kunmap(page);
+				void *kaddr = kmap_atomic(page, KM_USER0);
+
+				memset(kaddr, 0, PAGE_CACHE_SIZE);
+				flush_dcache_page(page);
+				kunmap_atomic(kaddr, KM_USER0);
 				SetPageUptodate(page);
 			}
 
diff -Nru a/drivers/block/umem.c b/drivers/block/umem.c
--- a/drivers/block/umem.c	Mon Sep  9 10:36:18 2002
+++ b/drivers/block/umem.c	Mon Sep  9 10:36:18 2002
@@ -159,9 +159,6 @@
 static struct block_device_operations mm_fops;
 static struct timer_list battery_timer;
 
-
-static struct hd_struct mm_partitions[MM_MAXCARDS << MM_SHIFT];
-
 static int num_cards = 0;
 
 static struct gendisk mm_gendisk[MM_MAXCARDS];
@@ -812,7 +809,7 @@
 static int mm_revalidate(kdev_t i_rdev)
 {
 	int card_number = DEVICE_NR(i_rdev);
-	mm_partitions[minor(i_rdev)].nr_sects = cards[card_number].mm_size << 1;
+	set_capacity(mm_gendisk + card_number, cards[card_number].mm_size << 1);
 	return 0;
 }
 /*
@@ -1192,8 +1189,6 @@
 		struct gendisk *disk = mm_gendisk + i;
 		sprintf(mm_names + i*6, "umem%c", 'a'+i);
 		spin_lock_init(&cards[i].lock);
-		disk->part  = mm_partitions + (i << MM_SHIFT);
-		disk->nr_real = 1;
 		disk->major = major_nr;
 		disk->first_minor  = i << MM_SHIFT;
 		disk->major_name = mm_names + i*6;
@@ -1222,10 +1217,8 @@
 
 	del_battery_timer();
 
-	for (i=0; i < num_cards ; i++) {
-		devfs_register_partitions(mm_gendisk + i, i<<MM_SHIFT, 1);
+	for (i=0; i < num_cards ; i++)
 		del_gendisk(mm_gendisk + i);
-	}
 	if (devfs_handle)
 		devfs_unregister(devfs_handle);
 	devfs_handle = NULL;
diff -Nru a/drivers/block/xd.c b/drivers/block/xd.c
--- a/drivers/block/xd.c	Mon Sep  9 10:36:01 2002
+++ b/drivers/block/xd.c	Mon Sep  9 10:36:01 2002
@@ -121,8 +121,6 @@
 	0xE0000
 };
 
-static struct hd_struct xd_struct[XD_MAXDRIVES << 6];
-
 static spinlock_t xd_lock = SPIN_LOCK_UNLOCKED;
 
 extern struct block_device_operations xd_fops;
@@ -133,17 +131,13 @@
 	.first_minor =	0,
 	.major_name =	"xda",
 	.minor_shift =	6,
-	.part =		xd_struct,
 	.fops =		&xd_fops,
-	.nr_real =	1
 },{
 	.major =	MAJOR_NR,
 	.first_minor =	64,
 	.major_name =	"xdb",
 	.minor_shift =	6,
-	.part =		xd_struct + 64,
 	.fops =		&xd_fops,
-	.nr_real =	1
 }
 };
 
@@ -281,15 +275,17 @@
 		return;
 
 	while (1) {
+		int unit;
 		code = 0;
 		/* do some checking on the request structure */
 		if (blk_queue_empty(QUEUE))
 			return;
 
-		if (DEVICE_NR(CURRENT->rq_dev) < xd_drives
+		unit = DEVICE_NR(CURRENT->rq_dev);
+		if (unit < xd_drives
 		    && (CURRENT->flags & REQ_CMD)
 		    && CURRENT->sector + CURRENT->nr_sectors
-		         <= xd_struct[minor(CURRENT->rq_dev)].nr_sects) {
+		         <= get_capacity(xd_gendisk + unit)) {
 			block = CURRENT->sector;
 			count = CURRENT->nr_sectors;
 
@@ -297,7 +293,7 @@
 				case READ:
 				case WRITE:
 					for (retry = 0; (retry < XD_RETRIES) && !code; retry++)
-						code = xd_readwrite(rq_data_dir(CURRENT),DEVICE_NR(CURRENT->rq_dev),
+						code = xd_readwrite(rq_data_dir(CURRENT),unit,
 							CURRENT->buffer,block,count);
 					break;
 				default:
diff -Nru a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c
--- a/drivers/cdrom/cdrom.c	Mon Sep  9 10:36:01 2002
+++ b/drivers/cdrom/cdrom.c	Mon Sep  9 10:36:01 2002
@@ -254,6 +254,7 @@
 #include <linux/config.h>
 #include <linux/module.h>
 #include <linux/fs.h>
+#include <linux/buffer_head.h>
 #include <linux/major.h>
 #include <linux/types.h>
 #include <linux/errno.h>
@@ -1608,6 +1609,7 @@
 		cdinfo(CD_DO_IOCTL, "entering CDROM_RESET\n");
 		if (!CDROM_CAN(CDC_RESET))
 			return -ENOSYS;
+		invalidate_buffers(dev);
 		return cdo->reset(cdi);
 		}
 
diff -Nru a/drivers/cdrom/cdu31a.c b/drivers/cdrom/cdu31a.c
--- a/drivers/cdrom/cdu31a.c	Mon Sep  9 10:35:59 2002
+++ b/drivers/cdrom/cdu31a.c	Mon Sep  9 10:35:59 2002
@@ -331,12 +331,11 @@
    from the abort read. */
 static int abort_read_started = 0;
 
-
 /*
- * This routine returns 1 if the disk has been changed since the last
- * check or 0 if it hasn't.
+ * Uniform cdrom interface function
+ * report back, if disc has changed from time of last request.
  */
-static int scd_disk_change(kdev_t full_dev)
+static int scd_media_changed(struct cdrom_device_info *cdi, int disc_nr)
 {
 	int retval;
 
@@ -344,15 +343,6 @@
 	disk_changed = 0;
 
 	return retval;
-}
-
-/*
- * Uniform cdrom interface function
- * report back, if disc has changed from time of last request.
- */
-static int scd_media_changed(struct cdrom_device_info *cdi, int disc_nr)
-{
-	return scd_disk_change(cdi->dev);
 }
 
 /*
diff -Nru a/drivers/cdrom/mcdx.c b/drivers/cdrom/mcdx.c
--- a/drivers/cdrom/mcdx.c	Mon Sep  9 10:36:11 2002
+++ b/drivers/cdrom/mcdx.c	Mon Sep  9 10:36:11 2002
@@ -73,7 +73,6 @@
 
 #include <linux/major.h>
 #define MAJOR_NR MITSUMI_X_CDROM_MAJOR
-#define DEVICE_NR(device) (minor(device))
 #include <linux/blk.h>
 #include <linux/devfs_fs_kernel.h>
 
@@ -197,7 +196,6 @@
 	void *rreg_status;	/* r status */
 
 	int irq;		/* irq used by this drive */
-	int minor;		/* minor number of this drive */
 	int present;		/* drive present and its capabilities */
 	unsigned char readcmd;	/* read cmd depends on single/double speed */
 	unsigned char playcmd;	/* play should always be single speed */
@@ -207,6 +205,7 @@
 	int lastsector;		/* last block accessible */
 	int status;		/* last operation's error / status */
 	int readerrs;		/* # of blocks read w/o error */
+	struct cdrom_device_info info;
 };
 
 
@@ -305,21 +304,13 @@
 	    CDC_PLAY_AUDIO | CDC_DRIVE_STATUS,
 };
 
-static struct cdrom_device_info mcdx_info = {
-	ops:&mcdx_dops,
-	speed:2,
-	capacity:1,
-	name:"mcdx",
-};
-
-
 /* KERNEL INTERFACE FUNCTIONS **************************************/
 
 
 static int mcdx_audio_ioctl(struct cdrom_device_info *cdi,
 			    unsigned int cmd, void *arg)
 {
-	struct s_drive_stuff *stuffp = mcdx_stuffp[minor(cdi->dev)];
+	struct s_drive_stuff *stuffp = cdi->handle;
 
 	if (!stuffp->present)
 		return -ENXIO;
@@ -627,7 +618,7 @@
 {
 	struct s_drive_stuff *stuffp;
 	xtrace(OPENCLOSE, "open()\n");
-	stuffp = mcdx_stuffp[minor(cdi->dev)];
+	stuffp = cdi->handle;
 	if (!stuffp->present)
 		return -ENXIO;
 
@@ -776,7 +767,7 @@
 
 	xtrace(OPENCLOSE, "close()\n");
 
-	stuffp = mcdx_stuffp[minor(cdi->dev)];
+	stuffp = cdi->handle;
 
 	--stuffp->users;
 }
@@ -787,10 +778,9 @@
 {
 	struct s_drive_stuff *stuffp;
 
-	xinfo("mcdx_media_changed called for device %s\n",
-	      kdevname(cdi->dev));
+	xinfo("mcdx_media_changed called for device %s\n", cdi->name);
 
-	stuffp = mcdx_stuffp[minor(cdi->dev)];
+	stuffp = cdi->handle;
 	mcdx_getstatus(stuffp, 1);
 
 	if (stuffp->yyy == 0)
@@ -1027,14 +1017,13 @@
 	xinfo("cleanup_module called\n");
 
 	for (i = 0; i < MCDX_NDRIVES; i++) {
-		struct s_drive_stuff *stuffp;
-		if (unregister_cdrom(&mcdx_info)) {
+		struct s_drive_stuff *stuffp = mcdx_stuffp[i];
+		if (!stuffp)
+			continue;
+		if (unregister_cdrom(&stuffp->info)) {
 			printk(KERN_WARNING "Can't unregister cdrom mcdx\n");
 			return;
 		}
-		stuffp = mcdx_stuffp[i];
-		if (!stuffp)
-			continue;
 		release_region((unsigned long) stuffp->wreg_data,
 			       MCDX_IO_SIZE);
 		free_irq(stuffp->irq, NULL);
@@ -1208,15 +1197,19 @@
 	xtrace(INIT, "init() set non dma but irq mode\n");
 	mcdx_config(stuffp, 1);
 
-	stuffp->minor = drive;
+	stuffp->info.ops = &mcdx_dops;
+	stuffp->info.speed = 2;
+	stuffp->info.capacity = 1;
+	stuffp->info.handle = stuffp;
+	sprintf(stuffp->info.name, "mcdx%d", drive);
+	stuffp->info.dev = mk_kdev(MAJOR_NR, drive);
 
 	sprintf(msg, " mcdx: Mitsumi CD-ROM installed at 0x%3p, irq %d."
 		" (Firmware version %c %x)\n",
 		stuffp->wreg_data, stuffp->irq, version.code, version.ver);
 	mcdx_stuffp[drive] = stuffp;
 	xtrace(INIT, "init() mcdx_stuffp[%d] = %p\n", drive, stuffp);
-	mcdx_info.dev = mk_kdev(MAJOR_NR, 0);
-	if (register_cdrom(&mcdx_info) != 0) {
+	if (register_cdrom(&stuffp->info) != 0) {
 		printk("Cannot register Mitsumi CD-ROM!\n");
 		release_region((unsigned long) stuffp->wreg_data,
 			       MCDX_IO_SIZE);
@@ -1227,7 +1220,7 @@
 		blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
 		return 2;
 	}
-	devfs_plain_cdrom(&mcdx_info, &mcdx_bdops);
+	devfs_plain_cdrom(&stuffp->info, &mcdx_bdops);
 	printk(msg);
 	return 0;
 }
@@ -1685,7 +1678,7 @@
 
 static int mcdx_tray_move(struct cdrom_device_info *cdi, int position)
 {
-	struct s_drive_stuff *stuffp = mcdx_stuffp[minor(cdi->dev)];
+	struct s_drive_stuff *stuffp = cdi->handle;
 
 	if (!stuffp->present)
 		return -ENXIO;
@@ -1875,7 +1868,7 @@
 
 static int mcdx_lockdoor(struct cdrom_device_info *cdi, int lock)
 {
-	struct s_drive_stuff *stuffp = mcdx_stuffp[minor(cdi->dev)];
+	struct s_drive_stuff *stuffp = cdi->handle;
 	char cmd[2] = { 0xfe };
 
 	if (!(stuffp->present & DOOR))
diff -Nru a/drivers/cdrom/sbpcd.c b/drivers/cdrom/sbpcd.c
--- a/drivers/cdrom/sbpcd.c	Mon Sep  9 10:36:01 2002
+++ b/drivers/cdrom/sbpcd.c	Mon Sep  9 10:36:01 2002
@@ -480,7 +480,6 @@
 static int sbp_data(struct request *req);
 static int cmd_out(void);
 static int DiskInfo(void);
-static int sbpcd_chk_disk_change(kdev_t);
 
 /*==========================================================================*/
 
@@ -623,9 +622,7 @@
 /*
  * drive space begins here (needed separate for each unit) 
  */
-static int d; /* DriveStruct index: drive number */
-
-static struct {
+static struct sbpcd_drive {
 	char drv_id;           /* "jumpered" drive ID or -1 */
 	char drv_sel;          /* drive select lines bits */
 	
@@ -728,6 +725,8 @@
 
 } D_S[NR_SBPCD];
 
+static struct sbpcd_drive *current_drive = D_S;
+
 /*
  * drive space ends here (needed separate for each unit)
  */
@@ -760,7 +759,7 @@
 	
 	msgnum++;
 	if (msgnum>99) msgnum=0;
-	sprintf(buf, MSG_LEVEL "%s-%d [%02d]:  ", major_name, d, msgnum);
+	sprintf(buf, MSG_LEVEL "%s-%d [%02d]:  ", major_name, current_drive - D_S, msgnum);
 	va_start(args, fmt);
 	vsprintf(&buf[18], fmt, args);
 	va_end(args);
@@ -1103,51 +1102,51 @@
 /*==========================================================================*/
 static void EvaluateStatus(int st)
 {
-	D_S[d].status_bits=0;
-	if (fam1_drive) D_S[d].status_bits=st|p_success;
+	current_drive->status_bits=0;
+	if (fam1_drive) current_drive->status_bits=st|p_success;
 	else if (fam0_drive)
 	{
-		if (st&p_caddin_old) D_S[d].status_bits |= p_door_closed|p_caddy_in;
-		if (st&p_spinning) D_S[d].status_bits |= p_spinning;
-		if (st&p_check) D_S[d].status_bits |= p_check;
- 		if (st&p_success_old) D_S[d].status_bits |= p_success;
- 		if (st&p_busy_old) D_S[d].status_bits |= p_busy_new;
-		if (st&p_disk_ok) D_S[d].status_bits |= p_disk_ok;
+		if (st&p_caddin_old) current_drive->status_bits |= p_door_closed|p_caddy_in;
+		if (st&p_spinning) current_drive->status_bits |= p_spinning;
+		if (st&p_check) current_drive->status_bits |= p_check;
+ 		if (st&p_success_old) current_drive->status_bits |= p_success;
+ 		if (st&p_busy_old) current_drive->status_bits |= p_busy_new;
+		if (st&p_disk_ok) current_drive->status_bits |= p_disk_ok;
 	}
 	else if (famLV_drive)
 	{
- 		D_S[d].status_bits |= p_success;
-		if (st&p_caddin_old) D_S[d].status_bits |= p_disk_ok|p_caddy_in;
-		if (st&p_spinning) D_S[d].status_bits |= p_spinning;
-		if (st&p_check) D_S[d].status_bits |= p_check;
-		if (st&p_busy_old) D_S[d].status_bits |= p_busy_new;
-		if (st&p_lcs_door_closed) D_S[d].status_bits |= p_door_closed;
-		if (st&p_lcs_door_locked) D_S[d].status_bits |= p_door_locked;
+ 		current_drive->status_bits |= p_success;
+		if (st&p_caddin_old) current_drive->status_bits |= p_disk_ok|p_caddy_in;
+		if (st&p_spinning) current_drive->status_bits |= p_spinning;
+		if (st&p_check) current_drive->status_bits |= p_check;
+		if (st&p_busy_old) current_drive->status_bits |= p_busy_new;
+		if (st&p_lcs_door_closed) current_drive->status_bits |= p_door_closed;
+		if (st&p_lcs_door_locked) current_drive->status_bits |= p_door_locked;
 	}
 	else if (fam2_drive)
 	{
- 		D_S[d].status_bits |= p_success;
-		if (st&p2_check) D_S[d].status_bits |= p1_check;
-		if (st&p2_door_closed) D_S[d].status_bits |= p1_door_closed;
-		if (st&p2_disk_in) D_S[d].status_bits |= p1_disk_in;
-		if (st&p2_busy1) D_S[d].status_bits |= p1_busy;
-		if (st&p2_busy2) D_S[d].status_bits |= p1_busy;
-		if (st&p2_spinning) D_S[d].status_bits |= p1_spinning;
-		if (st&p2_door_locked) D_S[d].status_bits |= p1_door_locked;
-		if (st&p2_disk_ok) D_S[d].status_bits |= p1_disk_ok;
+ 		current_drive->status_bits |= p_success;
+		if (st&p2_check) current_drive->status_bits |= p1_check;
+		if (st&p2_door_closed) current_drive->status_bits |= p1_door_closed;
+		if (st&p2_disk_in) current_drive->status_bits |= p1_disk_in;
+		if (st&p2_busy1) current_drive->status_bits |= p1_busy;
+		if (st&p2_busy2) current_drive->status_bits |= p1_busy;
+		if (st&p2_spinning) current_drive->status_bits |= p1_spinning;
+		if (st&p2_door_locked) current_drive->status_bits |= p1_door_locked;
+		if (st&p2_disk_ok) current_drive->status_bits |= p1_disk_ok;
 	}
 	else if (famT_drive)
 	{
 		return; /* still needs to get coded */
- 		D_S[d].status_bits |= p_success;
-		if (st&p2_check) D_S[d].status_bits |= p1_check;
-		if (st&p2_door_closed) D_S[d].status_bits |= p1_door_closed;
-		if (st&p2_disk_in) D_S[d].status_bits |= p1_disk_in;
-		if (st&p2_busy1) D_S[d].status_bits |= p1_busy;
-		if (st&p2_busy2) D_S[d].status_bits |= p1_busy;
-		if (st&p2_spinning) D_S[d].status_bits |= p1_spinning;
-		if (st&p2_door_locked) D_S[d].status_bits |= p1_door_locked;
-		if (st&p2_disk_ok) D_S[d].status_bits |= p1_disk_ok;
+ 		current_drive->status_bits |= p_success;
+		if (st&p2_check) current_drive->status_bits |= p1_check;
+		if (st&p2_door_closed) current_drive->status_bits |= p1_door_closed;
+		if (st&p2_disk_in) current_drive->status_bits |= p1_disk_in;
+		if (st&p2_busy1) current_drive->status_bits |= p1_busy;
+		if (st&p2_busy2) current_drive->status_bits |= p1_busy;
+		if (st&p2_spinning) current_drive->status_bits |= p1_spinning;
+		if (st&p2_door_locked) current_drive->status_bits |= p1_door_locked;
+		if (st&p2_disk_ok) current_drive->status_bits |= p1_disk_ok;
 	}
 	return;
 }
@@ -1159,7 +1158,7 @@
 	static int cmd_out_T(void);
 
 	clr_cmdbuf();
-	D_S[d].n_bytes=1;
+	current_drive->n_bytes=1;
 	drvcmd[0]=CMDT_STATUS;
 	i=cmd_out_T();
 	if (i>=0) i=infobuf[0];
@@ -1170,33 +1169,33 @@
 	}
 	if (i>=0)
 		/* 2: closed, disk in */
-		D_S[d].status_bits=p1_door_closed|p1_disk_in|p1_spinning|p1_disk_ok;
-	else if (D_S[d].error_state==6)
+		current_drive->status_bits=p1_door_closed|p1_disk_in|p1_spinning|p1_disk_ok;
+	else if (current_drive->error_state==6)
 	{
 		/* 3: closed, disk in, changed ("06 xx xx") */
-		D_S[d].status_bits=p1_door_closed|p1_disk_in;
-		D_S[d].CD_changed=0xFF;
-		D_S[d].diskstate_flags &= ~toc_bit;
+		current_drive->status_bits=p1_door_closed|p1_disk_in;
+		current_drive->CD_changed=0xFF;
+		current_drive->diskstate_flags &= ~toc_bit;
 	}
-	else if ((D_S[d].error_state!=2)||(D_S[d].b3!=0x3A)||(D_S[d].b4==0x00))
+	else if ((current_drive->error_state!=2)||(current_drive->b3!=0x3A)||(current_drive->b4==0x00))
 	{
 		/* 1: closed, no disk ("xx yy zz"or "02 3A 00") */
-		D_S[d].status_bits=p1_door_closed;
-		D_S[d].open_count=0;
+		current_drive->status_bits=p1_door_closed;
+		current_drive->open_count=0;
 	}
-	else if (D_S[d].b4==0x01)
+	else if (current_drive->b4==0x01)
 	{
 		/* 0: open ("02 3A 01") */
-		D_S[d].status_bits=0;
-		D_S[d].open_count=0;
+		current_drive->status_bits=0;
+		current_drive->open_count=0;
 	}
 	else
 	{
 		/* 1: closed, no disk ("02 3A xx") */
-		D_S[d].status_bits=p1_door_closed;
-		D_S[d].open_count=0;
+		current_drive->status_bits=p1_door_closed;
+		current_drive->open_count=0;
 	}
-	return (D_S[d].status_bits);
+	return (current_drive->status_bits);
 }
 /*==========================================================================*/
 static int ResponseStatus(void)
@@ -1226,14 +1225,14 @@
 	{
 		if ((flags_cmd_out & f_respo3) == 0)
 			msg(DBG_STA,"ResponseStatus: timeout.\n");
-		D_S[d].status_bits=0;
+		current_drive->status_bits=0;
 		return (-401);
 	}
 	i=inb(CDi_info);
 	msg(DBG_STA,"ResponseStatus: response %02X.\n", i);
 	EvaluateStatus(i);
-	msg(DBG_STA,"status_bits=%02X, i=%02X\n",D_S[d].status_bits,i);
-	return (D_S[d].status_bits);
+	msg(DBG_STA,"status_bits=%02X, i=%02X\n",current_drive->status_bits,i);
+	return (current_drive->status_bits);
 }
 /*==========================================================================*/
 static void cc_ReadStatus(void)
@@ -1283,18 +1282,18 @@
 		drvcmd[0]=CMDT_READ_ERR;
 	}
 	i=cmd_out();
-	D_S[d].error_byte=0;
+	current_drive->error_byte=0;
 	msg(DBG_ERR,"cc_ReadError: cmd_out(CMDx_READ_ERR) returns %d (%02X)\n",i,i);
 	if (i<0) return (i);
 	if (fam0V_drive) i=1;
 	else i=2;
-	D_S[d].error_byte=infobuf[i];
-	msg(DBG_ERR,"cc_ReadError: infobuf[%d] is %d (%02X)\n",i,D_S[d].error_byte,D_S[d].error_byte);
+	current_drive->error_byte=infobuf[i];
+	msg(DBG_ERR,"cc_ReadError: infobuf[%d] is %d (%02X)\n",i,current_drive->error_byte,current_drive->error_byte);
 	i=sta2err(infobuf[i]);
         if (i==-ERR_DISKCHANGE)
         {
-                D_S[d].CD_changed=0xFF;
-                D_S[d].diskstate_flags &= ~toc_bit;
+                current_drive->CD_changed=0xFF;
+                current_drive->diskstate_flags &= ~toc_bit;
         }
 	return (i);
 }
@@ -1307,18 +1306,18 @@
 	
 	static int cc_DriveReset(void);
 	int i, j, l=0, m, ntries;
-	long flags;
+	unsigned long flags;
 
-	D_S[d].error_state=0;
-	D_S[d].b3=0;
-	D_S[d].b4=0;
-	D_S[d].f_drv_error=0;
+	current_drive->error_state=0;
+	current_drive->b3=0;
+	current_drive->b4=0;
+	current_drive->f_drv_error=0;
 	for (i=0;i<10;i++) sprintf(&msgbuf[i*3]," %02X",drvcmd[i]);
 	msgbuf[i*3]=0;
 	msg(DBG_CMD,"cmd_out_T:%s\n",msgbuf);
 
 	OUT(CDo_sel_i_d,0);
-	OUT(CDo_enable,D_S[d].drv_sel);
+	OUT(CDo_enable,current_drive->drv_sel);
 	i=inb(CDi_status);
 	do_16bit=0;
 	if ((f_16bit)&&(!(i&0x80)))
@@ -1435,16 +1434,16 @@
 				sbp_sleep(1);
 			}
 			while (j<0);
-			D_S[d].error_state=infobuf[2];
-			D_S[d].b3=infobuf[3];
-			D_S[d].b4=infobuf[4];
-			if (D_S[d].f_drv_error)
+			current_drive->error_state=infobuf[2];
+			current_drive->b3=infobuf[3];
+			current_drive->b4=infobuf[4];
+			if (current_drive->f_drv_error)
 			{
-				D_S[d].f_drv_error=0;
+				current_drive->f_drv_error=0;
 				cc_DriveReset();
-				D_S[d].error_state=2;
+				current_drive->error_state=2;
 			}
-			return (-D_S[d].error_state-400);
+			return (-current_drive->error_state-400);
 		}
 		if (drvcmd[0]==CMDT_READ) return (0); /* handled elsewhere */
 		if ((teac==0)||(ntries<(CMDT_TRIES-5))) sbp_sleep(HZ/10);
@@ -1452,9 +1451,9 @@
 		if (ntries>(CMDT_TRIES-50)) continue;
 		msg(DBG_TEA,"cmd_out_T: next CMDT_TRIES (%02X): %d.\n", drvcmd[0], ntries-1);
 	}
-	D_S[d].f_drv_error=1;
+	current_drive->f_drv_error=1;
 	cc_DriveReset();
-	D_S[d].error_state=2;
+	current_drive->error_state=2;
 	return (-99);
 }
 /*==========================================================================*/
@@ -1487,7 +1486,7 @@
 		else i=ResponseInfo();
 		if (i<0) return (i);
 	}
-	if (D_S[d].in_SpinUp) msg(DBG_SPI,"in_SpinUp: to CDi_stat_loop.\n");
+	if (current_drive->in_SpinUp) msg(DBG_SPI,"in_SpinUp: to CDi_stat_loop.\n");
 	if (flags_cmd_out&f_lopsta)
 	{
 		i=CDi_stat_loop();
@@ -1496,13 +1495,13 @@
 	if (!(flags_cmd_out&f_getsta)) goto LOC_229;
 	
  LOC_228:
-	if (D_S[d].in_SpinUp) msg(DBG_SPI,"in_SpinUp: to cc_ReadStatus.\n");
+	if (current_drive->in_SpinUp) msg(DBG_SPI,"in_SpinUp: to cc_ReadStatus.\n");
 	cc_ReadStatus();
 	
  LOC_229:
 	if (flags_cmd_out&f_ResponseStatus) 
 	{
-		if (D_S[d].in_SpinUp) msg(DBG_SPI,"in_SpinUp: to ResponseStatus.\n");
+		if (current_drive->in_SpinUp) msg(DBG_SPI,"in_SpinUp: to ResponseStatus.\n");
 		i=ResponseStatus();
 		/* builds status_bits, returns orig. status or p_busy_new */
 		if (i<0) return (i);
@@ -1518,9 +1517,9 @@
  LOC_232:
 	if (!(flags_cmd_out&f_obey_p_check)) return (0);
 	if (!st_check) return (0);
-	if (D_S[d].in_SpinUp) msg(DBG_SPI,"in_SpinUp: to cc_ReadError.\n");
+	if (current_drive->in_SpinUp) msg(DBG_SPI,"in_SpinUp: to cc_ReadError.\n");
 	i=cc_ReadError();
-	if (D_S[d].in_SpinUp) msg(DBG_SPI,"in_SpinUp: to cmd_out OK.\n");
+	if (current_drive->in_SpinUp) msg(DBG_SPI,"in_SpinUp: to cmd_out OK.\n");
 	msg(DBG_000,"cmd_out: cc_ReadError=%d\n", i);
 	return (i);
 }
@@ -1574,7 +1573,7 @@
 		drvcmd[3]=(pos>>16)&0x00FF;
 		drvcmd[4]=(pos>>8)&0x00FF;
 		drvcmd[5]=pos&0x00FF;
-		D_S[d].n_bytes=1;
+		current_drive->n_bytes=1;
 	}
 	response_count=0;
 	i=cmd_out();
@@ -1586,7 +1585,7 @@
 	int i;
 	
 	msg(DBG_SPI,"SpinUp.\n");
-	D_S[d].in_SpinUp = 1;
+	current_drive->in_SpinUp = 1;
 	clr_cmdbuf();
 	if (fam0LV_drive)
 	{
@@ -1615,7 +1614,7 @@
 	}
 	response_count=0;
 	i=cmd_out();
-	D_S[d].in_SpinUp = 0;
+	current_drive->in_SpinUp = 0;
 	return (i);
 }
 /*==========================================================================*/
@@ -1676,15 +1675,15 @@
 	clr_cmdbuf();
 	response_count=1;
 	drvcmd[0]=CMDT_SETMODE;
-	drvcmd[1]=D_S[d].speed_byte;
-	drvcmd[2]=D_S[d].frmsiz>>8;
-	drvcmd[3]=D_S[d].frmsiz&0x0FF;
-	drvcmd[4]=D_S[d].f_XA; /* 1: XA */
-	drvcmd[5]=D_S[d].type_byte; /* 0, 1, 3 */
-	drvcmd[6]=D_S[d].mode_xb_6;
-	drvcmd[7]=D_S[d].mode_yb_7|D_S[d].volume_control;
-	drvcmd[8]=D_S[d].mode_xb_8;
-	drvcmd[9]=D_S[d].delay;
+	drvcmd[1]=current_drive->speed_byte;
+	drvcmd[2]=current_drive->frmsiz>>8;
+	drvcmd[3]=current_drive->frmsiz&0x0FF;
+	drvcmd[4]=current_drive->f_XA; /* 1: XA */
+	drvcmd[5]=current_drive->type_byte; /* 0, 1, 3 */
+	drvcmd[6]=current_drive->mode_xb_6;
+	drvcmd[7]=current_drive->mode_yb_7|current_drive->volume_control;
+	drvcmd[8]=current_drive->mode_xb_8;
+	drvcmd[9]=current_drive->delay;
 	i=cmd_out_T();
 	return (i);
 }
@@ -1699,15 +1698,15 @@
 		sprintf(&msgbuf[i*3], " %02X", infobuf[i]);
 	msgbuf[i*3]=0;
 	msg(DBG_TEA,"CMDT_GETMODE:%s\n", msgbuf);
-	D_S[d].speed_byte=0x02; /* 0x02: auto quad, 0x82: quad, 0x81: double, 0x80: single */
-	D_S[d].frmsiz=make16(infobuf[2],infobuf[3]);
-	D_S[d].f_XA=infobuf[4];
-	if (D_S[d].f_XA==0) D_S[d].type_byte=0;
-	else D_S[d].type_byte=1;
-	D_S[d].mode_xb_6=infobuf[6];
-	D_S[d].mode_yb_7=1;
-	D_S[d].mode_xb_8=infobuf[8];
-	D_S[d].delay=0; /* 0, 1, 2, 3 */
+	current_drive->speed_byte=0x02; /* 0x02: auto quad, 0x82: quad, 0x81: double, 0x80: single */
+	current_drive->frmsiz=make16(infobuf[2],infobuf[3]);
+	current_drive->f_XA=infobuf[4];
+	if (current_drive->f_XA==0) current_drive->type_byte=0;
+	else current_drive->type_byte=1;
+	current_drive->mode_xb_6=infobuf[6];
+	current_drive->mode_yb_7=1;
+	current_drive->mode_xb_8=infobuf[8];
+	current_drive->delay=0; /* 0, 1, 2, 3 */
 	j=cc_set_mode_T();
 	i=cc_get_mode_T();
 	for (i=0;i<10;i++)
@@ -1762,17 +1761,17 @@
 	u_char channel0,channel1,volume0,volume1;
 	u_char control0,value0,control1,value1;
 	
-	D_S[d].diskstate_flags &= ~volume_bit;
+	current_drive->diskstate_flags &= ~volume_bit;
 	clr_cmdbuf();
-	channel0=D_S[d].vol_chan0;
-	volume0=D_S[d].vol_ctrl0;
-	channel1=control1=D_S[d].vol_chan1;
-	volume1=value1=D_S[d].vol_ctrl1;
+	channel0=current_drive->vol_chan0;
+	volume0=current_drive->vol_ctrl0;
+	channel1=control1=current_drive->vol_chan1;
+	volume1=value1=current_drive->vol_ctrl1;
 	control0=value0=0;
 	
 	if (famV_drive) return (0);
 
-	if (((D_S[d].drv_options&audio_mono)!=0)&&(D_S[d].drv_type>=drv_211))
+	if (((current_drive->drv_options&audio_mono)!=0)&&(current_drive->drv_type>=drv_211))
 	{
 		if ((volume0!=0)&&(volume1==0))
 		{
@@ -1841,7 +1840,7 @@
 	}
 	else if (fam0_drive) /* different firmware levels */
 	{
-		if (D_S[d].drv_type>=drv_300)
+		if (current_drive->drv_type>=drv_300)
 		{
 			control0=volume0&0xFC;
 			value0=volume1&0xFC;
@@ -1853,7 +1852,7 @@
 		else
 		{
 			value0=(volume0>volume1)?volume0:volume1;
-			if (D_S[d].drv_type<drv_211)
+			if (current_drive->drv_type<drv_211)
 			{
 				if (channel0!=0)
 				{
@@ -1886,14 +1885,14 @@
 				if (volume0==0xFF) volume1=0xFF;
 				else if (volume1==0xFF) volume0=0xFF;
 			}
-			else if (D_S[d].drv_type<drv_201) volume0=volume1=value0;
+			else if (current_drive->drv_type<drv_201) volume0=volume1=value0;
 			
-			if (D_S[d].drv_type>=drv_201)
+			if (current_drive->drv_type>=drv_201)
 			{
 				if (volume0==0) control0 |= 0x80;
 				if (volume1==0) control0 |= 0x40;
 			}
-			if (D_S[d].drv_type>=drv_211)
+			if (current_drive->drv_type>=drv_211)
 			{
 				if (channel0!=0) control0 |= 0x20;
 				if (channel1!=1) control0 |= 0x10;
@@ -1907,9 +1906,9 @@
 	}
 	else if (famT_drive)
 	{
-		D_S[d].volume_control=0;
-		if (!volume0) D_S[d].volume_control|=0x10;
-		if (!volume1) D_S[d].volume_control|=0x20;
+		current_drive->volume_control=0;
+		if (!volume0) current_drive->volume_control|=0x10;
+		if (!volume1) current_drive->volume_control|=0x20;
 		i=cc_prep_mode_T();
 		if (i<0) return (i);
 	}
@@ -1919,7 +1918,7 @@
 		i=cmd_out();
 		if (i<0) return (i);
 	}
-	D_S[d].diskstate_flags |= volume_bit;
+	current_drive->diskstate_flags |= volume_bit;
 	return (0);
 }
 /*==========================================================================*/
@@ -1959,7 +1958,7 @@
 	else if (famT_drive)
 	{
 		OUT(CDo_sel_i_d,0);
-		OUT(CDo_enable,D_S[d].drv_sel);
+		OUT(CDo_enable,current_drive->drv_sel);
 		OUT(CDo_command,CMDT_RESET);
 		for (i=1;i<10;i++) OUT(CDo_command,0);
 	}
@@ -1976,7 +1975,7 @@
 	i=GetStatus();
 	if (i<0) return i;
 	if (!famT_drive)
-		if (D_S[d].error_byte!=aud_12) return -501;
+		if (current_drive->error_byte!=aud_12) return -501;
 	return (0);
 }
 
@@ -1985,27 +1984,26 @@
 {
 	int i, speed;
 	
-	if (!(D_S[d].drv_options&(speed_auto|speed_300|speed_150))) return (0);
+	if (!(current_drive->drv_options&(speed_auto|speed_300|speed_150))) return (0);
 	speed=speed_auto;
-	if (!(D_S[d].drv_options&speed_auto))
+	if (!(current_drive->drv_options&speed_auto))
 	{
 		speed |= speed_300;
-		if (!(D_S[d].drv_options&speed_300)) speed=0;
+		if (!(current_drive->drv_options&speed_300)) speed=0;
 	}
 	i=cc_SetSpeed(speed,0,0);
 	return (i);
 }
 
-static void switch_drive(int i);
+static void switch_drive(struct sbpcd_drive *);
 
 static int sbpcd_select_speed(struct cdrom_device_info *cdi, int speed)
 {
-  int i = minor(cdi->dev);
+	struct sbpcd_drive *p = cdi->handle;
+	if (p != current_drive)
+		switch_drive(p);
 
-  if (i != d)
-    switch_drive(i);
-
-  return cc_SetSpeed(speed == 2 ? speed_300 : speed_150, 0, 0);
+	return cc_SetSpeed(speed == 2 ? speed_300 : speed_150, 0, 0);
 }
 
 /*==========================================================================*/
@@ -2026,7 +2024,7 @@
 	}
 	while (!st_diskok);
 #if 000
-	D_S[d].CD_changed=1;
+	current_drive->CD_changed=1;
 #endif
 	if ((st_door_closed) && (st_caddy_in))
 	{
@@ -2038,12 +2036,10 @@
 
 static int sbpcd_reset(struct cdrom_device_info *cdi)
 {
-  int i = minor(cdi->dev);
-
-  if (i != d)
-    switch_drive(i);
-
-  return DriveReset();
+	struct sbpcd_drive *p = cdi->handle;
+	if (p != current_drive)
+		switch_drive(p);
+	return DriveReset();
 }
 
 /*==========================================================================*/
@@ -2051,7 +2047,7 @@
 {
 	int i, j, n;
 	
-	if (D_S[d].audio_state==audio_playing) return (-EINVAL);
+	if (current_drive->audio_state==audio_playing) return (-EINVAL);
 	clr_cmdbuf();
 	response_count=0;
 	if (famLV_drive)
@@ -2141,7 +2137,7 @@
 	}
 	else if (famT_drive)
 	{
-		if (pau_res==3)	return (cc_PlayAudio(D_S[d].pos_audio_start,D_S[d].pos_audio_end));
+		if (pau_res==3)	return (cc_PlayAudio(current_drive->pos_audio_start,current_drive->pos_audio_end));
 		else if (pau_res==1) drvcmd[0]=CMDT_PAUSE;
 		else return (-56);
 	}
@@ -2154,7 +2150,7 @@
 	int i;
 	
 	if (fam0_drive) return (0);
-	msg(DBG_LCK,"cc_LockDoor: %d (drive %d)\n", lock, d);
+	msg(DBG_LCK,"cc_LockDoor: %d (drive %d)\n", lock, current_drive - D_S);
 	msg(DBG_LCS,"p_door_locked bit %d before\n", st_door_locked);
 	clr_cmdbuf();
 	response_count=0;
@@ -2248,7 +2244,7 @@
 	int i;
 	
 	if (fam0_drive) return (0);
-	msg(DBG_LCK,"cc_CloseTray (drive %d)\n", d);
+	msg(DBG_LCK,"cc_CloseTray (drive %d)\n", current_drive - D_S);
 	msg(DBG_LCS,"p_door_closed bit %d before\n", st_door_closed);
 	
 	clr_cmdbuf();
@@ -2317,14 +2313,12 @@
 
 static int sbpcd_tray_move(struct cdrom_device_info *cdi, int position)
 {
-	int i;
 	int retval=0;
-	i = minor(cdi->dev);
-	switch_drive(i);
+	switch_drive(cdi->handle);
 	/* DUH! --AJK */
-	if(D_S[d].CD_changed != 0xFF) {
-		D_S[d].CD_changed=0xFF;
-		D_S[d].diskstate_flags &= ~cd_size_bit;
+	if(current_drive->CD_changed != 0xFF) {
+		current_drive->CD_changed=0xFF;
+		current_drive->diskstate_flags &= ~cd_size_bit;
 	}
 	if (position == 1) {
 		cc_SpinDown();
@@ -2339,7 +2333,7 @@
 {
 	int i,j;
 
-	D_S[d].diskstate_flags &= ~subq_bit;
+	current_drive->diskstate_flags &= ~subq_bit;
 	for (j=255;j>0;j--)
 	{
 		clr_cmdbuf();
@@ -2388,26 +2382,26 @@
 		if (infobuf[0]!=0) break;
 		if ((!st_spinning) || (j==1))
 		{
-			D_S[d].SubQ_ctl_adr=D_S[d].SubQ_trk=D_S[d].SubQ_pnt_idx=D_S[d].SubQ_whatisthis=0;
-			D_S[d].SubQ_run_tot=D_S[d].SubQ_run_trk=0;
+			current_drive->SubQ_ctl_adr=current_drive->SubQ_trk=current_drive->SubQ_pnt_idx=current_drive->SubQ_whatisthis=0;
+			current_drive->SubQ_run_tot=current_drive->SubQ_run_trk=0;
 			return (0);
 		}
 	}
-	if (famT_drive) D_S[d].SubQ_ctl_adr=infobuf[1];
-	else D_S[d].SubQ_ctl_adr=swap_nibbles(infobuf[1]);
-	D_S[d].SubQ_trk=byt2bcd(infobuf[2]);
-	D_S[d].SubQ_pnt_idx=byt2bcd(infobuf[3]);
+	if (famT_drive) current_drive->SubQ_ctl_adr=infobuf[1];
+	else current_drive->SubQ_ctl_adr=swap_nibbles(infobuf[1]);
+	current_drive->SubQ_trk=byt2bcd(infobuf[2]);
+	current_drive->SubQ_pnt_idx=byt2bcd(infobuf[3]);
 	if (fam0LV_drive) i=5;
 	else if (fam12_drive) i=4;
 	else if (famT_drive) i=8;
-	D_S[d].SubQ_run_tot=make32(make16(0,infobuf[i]),make16(infobuf[i+1],infobuf[i+2])); /* msf-bin */
+	current_drive->SubQ_run_tot=make32(make16(0,infobuf[i]),make16(infobuf[i+1],infobuf[i+2])); /* msf-bin */
 	i=7;
 	if (fam0LV_drive) i=9;
 	else if (fam12_drive) i=7;
 	else if (famT_drive) i=4;
-	D_S[d].SubQ_run_trk=make32(make16(0,infobuf[i]),make16(infobuf[i+1],infobuf[i+2])); /* msf-bin */
-	D_S[d].SubQ_whatisthis=infobuf[i+3];
-	D_S[d].diskstate_flags |= subq_bit;
+	current_drive->SubQ_run_trk=make32(make16(0,infobuf[i]),make16(infobuf[i+1],infobuf[i+2])); /* msf-bin */
+	current_drive->SubQ_whatisthis=infobuf[i+3];
+	current_drive->diskstate_flags |= subq_bit;
 	return (0);
 }
 /*==========================================================================*/
@@ -2417,7 +2411,7 @@
 	
 	if (fam2_drive) return (0);
 	if (famV_drive) return (0);
-	D_S[d].diskstate_flags &= ~frame_size_bit;
+	current_drive->diskstate_flags &= ~frame_size_bit;
 	clr_cmdbuf();
 	if (fam1_drive)
 	{
@@ -2441,21 +2435,21 @@
 	i=cmd_out();
 	if (i<0) return (i);
 	i=0;
-	D_S[d].sense_byte=0;
-	if (fam1_drive) D_S[d].sense_byte=infobuf[i++];
+	current_drive->sense_byte=0;
+	if (fam1_drive) current_drive->sense_byte=infobuf[i++];
 	else if (famT_drive)
 	{
-		if (infobuf[4]==0x01) D_S[d].xa_byte=0x20;
-		else D_S[d].xa_byte=0;
+		if (infobuf[4]==0x01) current_drive->xa_byte=0x20;
+		else current_drive->xa_byte=0;
 		i=2;
 	}
-	D_S[d].frame_size=make16(infobuf[i],infobuf[i+1]);
+	current_drive->frame_size=make16(infobuf[i],infobuf[i+1]);
 	for (i=0;i<response_count;i++)
 		sprintf(&msgbuf[i*3], " %02X", infobuf[i]);
 	msgbuf[i*3]=0;
 	msg(DBG_XA1,"cc_ModeSense:%s\n", msgbuf);
 	
-	D_S[d].diskstate_flags |= frame_size_bit;
+	current_drive->diskstate_flags |= frame_size_bit;
 	return (0);
 }
 /*==========================================================================*/
@@ -2466,30 +2460,30 @@
 	
 	if (fam2_drive) return (0);
 	if (famV_drive) return (0);
-	D_S[d].diskstate_flags &= ~frame_size_bit;
+	current_drive->diskstate_flags &= ~frame_size_bit;
 	clr_cmdbuf();
-	D_S[d].frame_size=framesize;
-	if (framesize==CD_FRAMESIZE_RAW) D_S[d].sense_byte=0x82;
-	else D_S[d].sense_byte=0x00;
+	current_drive->frame_size=framesize;
+	if (framesize==CD_FRAMESIZE_RAW) current_drive->sense_byte=0x82;
+	else current_drive->sense_byte=0x00;
 	
 	msg(DBG_XA1,"cc_ModeSelect: %02X %04X\n",
-	    D_S[d].sense_byte, D_S[d].frame_size);
+	    current_drive->sense_byte, current_drive->frame_size);
 	
 	if (fam1_drive)
 	{
 		drvcmd[0]=CMD1_SETMODE;
 		drvcmd[1]=0x00;
-		drvcmd[2]=D_S[d].sense_byte;
-		drvcmd[3]=(D_S[d].frame_size>>8)&0xFF;
-		drvcmd[4]=D_S[d].frame_size&0xFF;
+		drvcmd[2]=current_drive->sense_byte;
+		drvcmd[3]=(current_drive->frame_size>>8)&0xFF;
+		drvcmd[4]=current_drive->frame_size&0xFF;
 		flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check;
 	}
 	else if (fam0L_drive)
 	{
 		drvcmd[0]=CMD0_SETMODE;
 		drvcmd[1]=0x00;
-		drvcmd[2]=(D_S[d].frame_size>>8)&0xFF;
-		drvcmd[3]=D_S[d].frame_size&0xFF;
+		drvcmd[2]=(current_drive->frame_size>>8)&0xFF;
+		drvcmd[3]=current_drive->frame_size&0xFF;
 		drvcmd[4]=0x00;
 		if(famL_drive)
 			flags_cmd_out=f_putcmd|f_lopsta|f_getsta|f_ResponseStatus|f_obey_p_check;
@@ -2503,7 +2497,7 @@
 	response_count=0;
 	i=cmd_out();
 	if (i<0) return (i);
-	D_S[d].diskstate_flags |= frame_size_bit;
+	current_drive->diskstate_flags |= frame_size_bit;
 	return (0);
 }
 /*==========================================================================*/
@@ -2517,7 +2511,7 @@
 	u_char vol1=0;
 	
 	if (famV_drive) return (0);
-	D_S[d].diskstate_flags &= ~volume_bit;
+	current_drive->diskstate_flags &= ~volume_bit;
 	clr_cmdbuf();
 	if (fam1_drive)
 	{
@@ -2593,14 +2587,14 @@
 		chan0=0;
 		chan1=1;
 		vol0=vol1=infobuf[1];
-		if (D_S[d].drv_type>=drv_201)
+		if (current_drive->drv_type>=drv_201)
 		{
-			if (D_S[d].drv_type<drv_300)
+			if (current_drive->drv_type<drv_300)
 			{
 				switches=infobuf[0];
 				if ((switches&0x80)!=0) vol0=0;
 				if ((switches&0x40)!=0) vol1=0;
-				if (D_S[d].drv_type>=drv_211)
+				if (current_drive->drv_type>=drv_211)
 				{
 					if ((switches&0x20)!=0) chan0=1;
 					if ((switches&0x10)!=0) chan1=0;
@@ -2620,25 +2614,25 @@
 	}
 	else if (famT_drive)
 	{
-		D_S[d].volume_control=infobuf[7];
+		current_drive->volume_control=infobuf[7];
 		chan0=0;
 		chan1=1;
-		if (D_S[d].volume_control&0x10) vol0=0;
+		if (current_drive->volume_control&0x10) vol0=0;
 		else vol0=0xff;
-		if (D_S[d].volume_control&0x20) vol1=0;
+		if (current_drive->volume_control&0x20) vol1=0;
 		else vol1=0xff;
 	}
-	D_S[d].vol_chan0=chan0;
-	D_S[d].vol_ctrl0=vol0;
-	D_S[d].vol_chan1=chan1;
-	D_S[d].vol_ctrl1=vol1;
+	current_drive->vol_chan0=chan0;
+	current_drive->vol_ctrl0=vol0;
+	current_drive->vol_chan1=chan1;
+	current_drive->vol_ctrl1=vol1;
 #if 000
-	D_S[d].vol_chan2=2;
-	D_S[d].vol_ctrl2=0xFF;
-	D_S[d].vol_chan3=3;
-	D_S[d].vol_ctrl3=0xFF;
+	current_drive->vol_chan2=2;
+	current_drive->vol_ctrl2=0xFF;
+	current_drive->vol_chan3=3;
+	current_drive->vol_ctrl3=0xFF;
 #endif /*  000 */
-	D_S[d].diskstate_flags |= volume_bit;
+	current_drive->diskstate_flags |= volume_bit;
 	return (0);
 }
 /*==========================================================================*/
@@ -2649,7 +2643,7 @@
 	if (fam2_drive) return (0); /* some firmware lacks this command */
 	if (famLV_drive) return (0); /* some firmware lacks this command */
 	if (famT_drive) return (0); /* done with cc_ReadTocDescr() */
-	D_S[d].diskstate_flags &= ~cd_size_bit;
+	current_drive->diskstate_flags &= ~cd_size_bit;
 	for (j=3;j>0;j--)
 	{
 		clr_cmdbuf();
@@ -2679,13 +2673,13 @@
 		cc_ReadError();
 	}
 	if (j==0) return (i);
-	if (fam1_drive) D_S[d].CDsize_frm=msf2blk(make32(make16(0,infobuf[0]),make16(infobuf[1],infobuf[2])))+CD_MSF_OFFSET;
-	else if (fam0_drive) D_S[d].CDsize_frm=make32(make16(0,infobuf[0]),make16(infobuf[1],infobuf[2]));
+	if (fam1_drive) current_drive->CDsize_frm=msf2blk(make32(make16(0,infobuf[0]),make16(infobuf[1],infobuf[2])))+CD_MSF_OFFSET;
+	else if (fam0_drive) current_drive->CDsize_frm=make32(make16(0,infobuf[0]),make16(infobuf[1],infobuf[2]));
 #if 00
-	else if (fam2_drive) D_S[d].CDsize_frm=make32(make16(infobuf[0],infobuf[1]),make16(infobuf[2],infobuf[3]));
+	else if (fam2_drive) current_drive->CDsize_frm=make32(make16(infobuf[0],infobuf[1]),make16(infobuf[2],infobuf[3]));
 #endif
-	D_S[d].diskstate_flags |= cd_size_bit;
-	msg(DBG_000,"cc_ReadCapacity: %d frames.\n", D_S[d].CDsize_frm);
+	current_drive->diskstate_flags |= cd_size_bit;
+	msg(DBG_000,"cc_ReadCapacity: %d frames.\n", current_drive->CDsize_frm);
 	return (0);
 }
 /*==========================================================================*/
@@ -2693,7 +2687,7 @@
 {
 	int i;
 	
-	D_S[d].diskstate_flags &= ~toc_bit;
+	current_drive->diskstate_flags &= ~toc_bit;
 	clr_cmdbuf();
 	if (fam1_drive)
 	{
@@ -2713,7 +2707,7 @@
 	else if (fam2_drive)
 	{
 		/* possibly longer timeout periods necessary */
-		D_S[d].f_multisession=0;
+		current_drive->f_multisession=0;
 		drvcmd[0]=CMD2_DISKINFO;
 		drvcmd[1]=0x02;
 		drvcmd[2]=0xAB;
@@ -2723,7 +2717,7 @@
 	}
 	else if (famT_drive)
 	{
-		D_S[d].f_multisession=0;
+		current_drive->f_multisession=0;
 		response_count=12;
 		drvcmd[0]=CMDT_DISKINFO;
 		drvcmd[1]=0x02;
@@ -2735,25 +2729,25 @@
 	if (i<0) return (i);
 	if ((famT_drive)&&(i<response_count)) return (-100-i);
 	if ((fam1_drive)||(fam2_drive)||(fam0LV_drive))
-		D_S[d].xa_byte=infobuf[0];
+		current_drive->xa_byte=infobuf[0];
 	if (fam2_drive)
 	{
-		D_S[d].first_session=infobuf[1];
-		D_S[d].last_session=infobuf[2];
-		D_S[d].n_first_track=infobuf[3];
-		D_S[d].n_last_track=infobuf[4];
-		if (D_S[d].first_session!=D_S[d].last_session)
+		current_drive->first_session=infobuf[1];
+		current_drive->last_session=infobuf[2];
+		current_drive->n_first_track=infobuf[3];
+		current_drive->n_last_track=infobuf[4];
+		if (current_drive->first_session!=current_drive->last_session)
 		{
-			D_S[d].f_multisession=1;
-			D_S[d].lba_multi=msf2blk(make32(make16(0,infobuf[5]),make16(infobuf[6],infobuf[7])));
+			current_drive->f_multisession=1;
+			current_drive->lba_multi=msf2blk(make32(make16(0,infobuf[5]),make16(infobuf[6],infobuf[7])));
 		}
 #if 0
-		if (D_S[d].first_session!=D_S[d].last_session)
+		if (current_drive->first_session!=current_drive->last_session)
 		{
-			if (D_S[d].last_session<=20)
-				zwanzig=D_S[d].last_session+1;
+			if (current_drive->last_session<=20)
+				zwanzig=current_drive->last_session+1;
 			else zwanzig=20;
-			for (count=D_S[d].first_session;count<zwanzig;count++)
+			for (count=current_drive->first_session;count<zwanzig;count++)
 			{
 				drvcmd[0]=CMD2_DISKINFO;
 				drvcmd[1]=0x02;
@@ -2763,9 +2757,9 @@
 				flags_cmd_out=f_putcmd;
 				i=cmd_out();
 				if (i<0) return (i);
-				D_S[d].msf_multi_n[count]=make32(make16(0,infobuf[5]),make16(infobuf[6],infobuf[7]));
+				current_drive->msf_multi_n[count]=make32(make16(0,infobuf[5]),make16(infobuf[6],infobuf[7]));
 			}
-			D_S[d].diskstate_flags |= multisession_bit;
+			current_drive->diskstate_flags |= multisession_bit;
 		}
 #endif
 		drvcmd[0]=CMD2_DISKINFO;
@@ -2776,34 +2770,34 @@
 		flags_cmd_out=f_putcmd;
 		i=cmd_out();
 		if (i<0) return (i);
-		D_S[d].size_msf=make32(make16(0,infobuf[2]),make16(infobuf[3],infobuf[4]));
-		D_S[d].size_blk=msf2blk(D_S[d].size_msf);
-		D_S[d].CDsize_frm=D_S[d].size_blk+1;
+		current_drive->size_msf=make32(make16(0,infobuf[2]),make16(infobuf[3],infobuf[4]));
+		current_drive->size_blk=msf2blk(current_drive->size_msf);
+		current_drive->CDsize_frm=current_drive->size_blk+1;
 	}
 	else if (famT_drive)
 	{
-		D_S[d].size_msf=make32(make16(infobuf[8],infobuf[9]),make16(infobuf[10],infobuf[11]));
-		D_S[d].size_blk=msf2blk(D_S[d].size_msf);
-		D_S[d].CDsize_frm=D_S[d].size_blk+1;
-		D_S[d].n_first_track=infobuf[2];
-		D_S[d].n_last_track=infobuf[3];
+		current_drive->size_msf=make32(make16(infobuf[8],infobuf[9]),make16(infobuf[10],infobuf[11]));
+		current_drive->size_blk=msf2blk(current_drive->size_msf);
+		current_drive->CDsize_frm=current_drive->size_blk+1;
+		current_drive->n_first_track=infobuf[2];
+		current_drive->n_last_track=infobuf[3];
 	}
 	else
 	{
-		D_S[d].n_first_track=infobuf[1];
-		D_S[d].n_last_track=infobuf[2];
-		D_S[d].size_msf=make32(make16(0,infobuf[3]),make16(infobuf[4],infobuf[5]));
-		D_S[d].size_blk=msf2blk(D_S[d].size_msf);
-		if (famLV_drive) D_S[d].CDsize_frm=D_S[d].size_blk+1;
+		current_drive->n_first_track=infobuf[1];
+		current_drive->n_last_track=infobuf[2];
+		current_drive->size_msf=make32(make16(0,infobuf[3]),make16(infobuf[4],infobuf[5]));
+		current_drive->size_blk=msf2blk(current_drive->size_msf);
+		if (famLV_drive) current_drive->CDsize_frm=current_drive->size_blk+1;
 	}
-	D_S[d].diskstate_flags |= toc_bit;
+	current_drive->diskstate_flags |= toc_bit;
 	msg(DBG_TOC,"TocDesc: xa %02X firstt %02X lastt %02X size %08X firstses %02X lastsess %02X\n",
-	    D_S[d].xa_byte,
-	    D_S[d].n_first_track,
-	    D_S[d].n_last_track,
-	    D_S[d].size_msf,
-	    D_S[d].first_session,
-	    D_S[d].last_session);
+	    current_drive->xa_byte,
+	    current_drive->n_first_track,
+	    current_drive->n_last_track,
+	    current_drive->size_msf,
+	    current_drive->first_session,
+	    current_drive->last_session);
 	return (0);
 }
 /*==========================================================================*/
@@ -2853,36 +2847,36 @@
 	if ((famT_drive)&&(i<response_count)) return (-100-i);
 	if ((fam1_drive)||(fam0LV_drive))
 	{
-		D_S[d].TocEnt_nixbyte=infobuf[0];
+		current_drive->TocEnt_nixbyte=infobuf[0];
 		i=1;
 	}
 	else if (fam2_drive) i=0;
 	else if (famT_drive) i=5;
-	D_S[d].TocEnt_ctl_adr=swap_nibbles(infobuf[i++]);
+	current_drive->TocEnt_ctl_adr=swap_nibbles(infobuf[i++]);
 	if ((fam1_drive)||(fam0L_drive))
 	{
-		D_S[d].TocEnt_number=infobuf[i++];
-		D_S[d].TocEnt_format=infobuf[i];
+		current_drive->TocEnt_number=infobuf[i++];
+		current_drive->TocEnt_format=infobuf[i];
 	}
 	else
 	  {
-	    D_S[d].TocEnt_number=num;
-	    D_S[d].TocEnt_format=0;
+	    current_drive->TocEnt_number=num;
+	    current_drive->TocEnt_format=0;
 	  }
 	if (fam1_drive) i=4;
 	else if (fam0LV_drive) i=5;
 	else if (fam2_drive) i=2;
 	else if (famT_drive) i=9;
-	D_S[d].TocEnt_address=make32(make16(0,infobuf[i]),
+	current_drive->TocEnt_address=make32(make16(0,infobuf[i]),
 				     make16(infobuf[i+1],infobuf[i+2]));
 	for (i=0;i<response_count;i++)
 		sprintf(&msgbuf[i*3], " %02X", infobuf[i]);
 	msgbuf[i*3]=0;
 	msg(DBG_ECS,"TocEntry:%s\n", msgbuf);
 	msg(DBG_TOC,"TocEntry: %02X %02X %02X %02X %08X\n",
-	    D_S[d].TocEnt_nixbyte, D_S[d].TocEnt_ctl_adr,
-	    D_S[d].TocEnt_number, D_S[d].TocEnt_format,
-	    D_S[d].TocEnt_address);
+	    current_drive->TocEnt_nixbyte, current_drive->TocEnt_ctl_adr,
+	    current_drive->TocEnt_number, current_drive->TocEnt_format,
+	    current_drive->TocEnt_address);
 	return (0);
 }
 /*==========================================================================*/
@@ -2913,11 +2907,11 @@
 	if (fam0L_drive) p[13]=0;
 	for (i=0;i<7;i++)
 	{
-		if (fam1_drive) D_S[d].UPC_buf[i]=swap_nibbles(*p++);
+		if (fam1_drive) current_drive->UPC_buf[i]=swap_nibbles(*p++);
 		else if (fam0L_drive)
 		{
-			D_S[d].UPC_buf[i]=((*p++)<<4)&0xFF;
-			D_S[d].UPC_buf[i] |= *p++;
+			current_drive->UPC_buf[i]=((*p++)<<4)&0xFF;
+			current_drive->UPC_buf[i] |= *p++;
 		}
 		else if (famT_drive)
 		{
@@ -2928,7 +2922,7 @@
 			return (-1);
 		}
 	}
-	D_S[d].UPC_buf[6] &= 0xF0;
+	current_drive->UPC_buf[6] &= 0xF0;
 	return (0);
 }
 /*==========================================================================*/
@@ -2946,7 +2940,7 @@
 	if (fam0_drive) return (0); /* but it should work */
 #endif
 	
-	D_S[d].diskstate_flags &= ~upc_bit;
+	current_drive->diskstate_flags &= ~upc_bit;
 #if TEST_UPC
 	for (block=CD_MSF_OFFSET+1;block<CD_MSF_OFFSET+200;block++)
 	{
@@ -3015,20 +3009,20 @@
 		if ((checksum&0x7F)!=0) break;
 	}
 #endif /* TEST_UPC */ 
-	D_S[d].UPC_ctl_adr=0;
+	current_drive->UPC_ctl_adr=0;
 	if (fam1_drive) i=0;
 	else i=2;
 	if ((infobuf[i]&0x80)!=0)
 	{
 		convert_UPC(&infobuf[i]);
-		D_S[d].UPC_ctl_adr = (D_S[d].TocEnt_ctl_adr & 0xF0) | 0x02;
+		current_drive->UPC_ctl_adr = (current_drive->TocEnt_ctl_adr & 0xF0) | 0x02;
 	}
 	for (i=0;i<7;i++)
-		sprintf(&msgbuf[i*3], " %02X", D_S[d].UPC_buf[i]);
-	sprintf(&msgbuf[i*3], " (%02X)", D_S[d].UPC_ctl_adr);
+		sprintf(&msgbuf[i*3], " %02X", current_drive->UPC_buf[i]);
+	sprintf(&msgbuf[i*3], " (%02X)", current_drive->UPC_ctl_adr);
 	msgbuf[i*3+5]=0;
 	msg(DBG_UPC,"UPC code:%s\n", msgbuf);
-	D_S[d].diskstate_flags |= upc_bit;
+	current_drive->diskstate_flags |= upc_bit;
 	return (0);
 }
 
@@ -3038,7 +3032,7 @@
 	unsigned char *mcnp = mcn->medium_catalog_number;
 	unsigned char *resp;
 
-	D_S[d].diskstate_flags &= ~upc_bit;
+	current_drive->diskstate_flags &= ~upc_bit;
 	clr_cmdbuf();
 	if (fam1_drive)
 	{
@@ -3077,7 +3071,7 @@
 			return (i);
 		}
 	}
-	D_S[d].UPC_ctl_adr=0;
+	current_drive->UPC_ctl_adr=0;
 	if (fam1_drive) i=0;
 	else i=2;
 
@@ -3100,7 +3094,7 @@
 	}
 	*mcnp = '\0';
 
-	D_S[d].diskstate_flags |= upc_bit;
+	current_drive->diskstate_flags |= upc_bit;
 	return (0);
 }
 
@@ -3110,8 +3104,8 @@
 	int i;
 	
 	if (fam2_drive) return (0);
-	D_S[d].f_multisession=0;
-	D_S[d].lba_multi=0;
+	current_drive->f_multisession=0;
+	current_drive->lba_multi=0;
 	if (fam0_drive) return (0);
 	clr_cmdbuf();
 	if (fam1_drive)
@@ -3123,8 +3117,8 @@
 		if (i<0) return (i);
 		if ((infobuf[0]&0x80)!=0)
 		{
-			D_S[d].f_multisession=1;
-			D_S[d].lba_multi=msf2blk(make32(make16(0,infobuf[1]),
+			current_drive->f_multisession=1;
+			current_drive->lba_multi=msf2blk(make32(make16(0,infobuf[1]),
 							make16(infobuf[2],infobuf[3])));
 		}
 	}
@@ -3137,7 +3131,7 @@
 		flags_cmd_out=f_putcmd;
 		i=cmd_out();
 		if (i<0) return (i);
-		D_S[d].lba_multi=msf2blk(make32(make16(0,infobuf[5]),
+		current_drive->lba_multi=msf2blk(make32(make16(0,infobuf[5]),
 						make16(infobuf[6],infobuf[7])));
 	}
 	else if (famT_drive)
@@ -3151,23 +3145,23 @@
 		i=cmd_out();
 		if (i<0) return (i);
 		if (i<response_count) return (-100-i);
-		D_S[d].first_session=infobuf[2];
-		D_S[d].last_session=infobuf[3];
-		D_S[d].track_of_last_session=infobuf[6];
-		if (D_S[d].first_session!=D_S[d].last_session)
+		current_drive->first_session=infobuf[2];
+		current_drive->last_session=infobuf[3];
+		current_drive->track_of_last_session=infobuf[6];
+		if (current_drive->first_session!=current_drive->last_session)
 		{
-			D_S[d].f_multisession=1;
-			D_S[d].lba_multi=msf2blk(make32(make16(0,infobuf[9]),make16(infobuf[10],infobuf[11])));
+			current_drive->f_multisession=1;
+			current_drive->lba_multi=msf2blk(make32(make16(0,infobuf[9]),make16(infobuf[10],infobuf[11])));
 		}
 	}
 	for (i=0;i<response_count;i++)
 		sprintf(&msgbuf[i*3], " %02X", infobuf[i]);
 	msgbuf[i*3]=0;
-	msg(DBG_MUL,"MultiSession Info:%s (%d)\n", msgbuf, D_S[d].lba_multi);
-	if (D_S[d].lba_multi>200)
+	msg(DBG_MUL,"MultiSession Info:%s (%d)\n", msgbuf, current_drive->lba_multi);
+	if (current_drive->lba_multi>200)
 	{
-		D_S[d].f_multisession=1;
-		msg(DBG_MUL,"MultiSession base: %06X\n", D_S[d].lba_multi);
+		current_drive->f_multisession=1;
+		msg(DBG_MUL,"MultiSession base: %06X\n", current_drive->lba_multi);
 	}
 	return (0);
 }
@@ -3184,7 +3178,7 @@
 		return (-1);
 	}
 #if 0
-	if (D_S[d].audio_state!=audio_playing) return (-ENODATA);
+	if (current_drive->audio_state!=audio_playing) return (-ENODATA);
 #endif
 	clr_cmdbuf();
 	drvcmd[0]=CMD1_SUBCHANINF;
@@ -3195,7 +3189,7 @@
 	drvcmd[6]=count&0xFF;
 	flags_cmd_out=f_putcmd|f_respo2|f_ResponseStatus|f_obey_p_check;
 	cmd_type=READ_SC;
-	D_S[d].frame_size=CD_FRAMESIZE_SUB;
+	current_drive->frame_size=CD_FRAMESIZE_SUB;
 	i=cmd_out(); /* which buffer to use? */
 	return (i);
 }
@@ -3279,7 +3273,7 @@
 	msg(DBG_INF, "(don't mail if you are not using the actual kernel):\n");
 	msg(DBG_INF, "%s\n", VERSION);
 	msg(DBG_INF, "address %03X, type %s, drive %s (ID %d)\n",
-	    CDo_command, type, D_S[d].drive_model, D_S[d].drv_id);
+	    CDo_command, type, current_drive->drive_model, current_drive->drv_id);
 	for (i=0;i<12;i++)
 		sprintf(&msgbuf[i*3], " %02X", infobuf[i]);
 	msgbuf[i*3]=0;
@@ -3295,8 +3289,8 @@
 	int i, j, l;
 	int teac_possible=0;
 	
-	msg(DBG_INI,"check_version: id=%d, d=%d.\n", D_S[d].drv_id, d);
-	D_S[d].drv_type=0;
+	msg(DBG_INI,"check_version: id=%d, d=%d.\n", current_drive->drv_id, current_drive - D_S);
+	current_drive->drv_type=0;
 
 	/* check for CR-52x, CR-56x, LCS-7260 and ECS-AT */
 	/* clear any pending error state */
@@ -3331,54 +3325,54 @@
 	for (i=0;i<4;i++) if (infobuf[i]!=family1[i]) break;
 	if (i==4)
 	{
-		D_S[d].drive_model[0]='C';
-		D_S[d].drive_model[1]='R';
-		D_S[d].drive_model[2]='-';
-		D_S[d].drive_model[3]='5';
-		D_S[d].drive_model[4]=infobuf[i++];
-		D_S[d].drive_model[5]=infobuf[i++];
-		D_S[d].drive_model[6]=0;
-		D_S[d].drv_type=drv_fam1;
+		current_drive->drive_model[0]='C';
+		current_drive->drive_model[1]='R';
+		current_drive->drive_model[2]='-';
+		current_drive->drive_model[3]='5';
+		current_drive->drive_model[4]=infobuf[i++];
+		current_drive->drive_model[5]=infobuf[i++];
+		current_drive->drive_model[6]=0;
+		current_drive->drv_type=drv_fam1;
 	}
-	if (!D_S[d].drv_type)
+	if (!current_drive->drv_type)
 	{
 		for (i=0;i<8;i++) if (infobuf[i]!=family0[i]) break;
 		if (i==8)
 		{
-			D_S[d].drive_model[0]='C';
-			D_S[d].drive_model[1]='R';
-			D_S[d].drive_model[2]='-';
-			D_S[d].drive_model[3]='5';
-			D_S[d].drive_model[4]='2';
-			D_S[d].drive_model[5]='x';
-			D_S[d].drive_model[6]=0;
-			D_S[d].drv_type=drv_fam0;
+			current_drive->drive_model[0]='C';
+			current_drive->drive_model[1]='R';
+			current_drive->drive_model[2]='-';
+			current_drive->drive_model[3]='5';
+			current_drive->drive_model[4]='2';
+			current_drive->drive_model[5]='x';
+			current_drive->drive_model[6]=0;
+			current_drive->drv_type=drv_fam0;
 		}
 	}
-	if (!D_S[d].drv_type)
+	if (!current_drive->drv_type)
 	{
 		for (i=0;i<8;i++) if (infobuf[i]!=familyL[i]) break;
 		if (i==8)
 		{
 			for (j=0;j<8;j++)
-				D_S[d].drive_model[j]=infobuf[j];
-			D_S[d].drive_model[8]=0;
-			D_S[d].drv_type=drv_famL;
+				current_drive->drive_model[j]=infobuf[j];
+			current_drive->drive_model[8]=0;
+			current_drive->drv_type=drv_famL;
 		}
 	}
-	if (!D_S[d].drv_type)
+	if (!current_drive->drv_type)
 	{
 		for (i=0;i<6;i++) if (infobuf[i]!=familyV[i]) break;
 		if (i==6)
 		{
 			for (j=0;j<6;j++)
-				D_S[d].drive_model[j]=infobuf[j];
-			D_S[d].drive_model[6]=0;
-			D_S[d].drv_type=drv_famV;
+				current_drive->drive_model[j]=infobuf[j];
+			current_drive->drive_model[6]=0;
+			current_drive->drv_type=drv_famV;
 			i+=2; /* 2 blanks before version */
 		}
 	}
-	if (!D_S[d].drv_type)
+	if (!current_drive->drv_type)
 	{
 		/* check for CD200 */
 		clr_cmdbuf();
@@ -3395,7 +3389,7 @@
 #if 0
 		OUT(CDo_reset,0);
 		sbp_sleep(6*HZ);
-		OUT(CDo_enable,D_S[d].drv_sel);
+		OUT(CDo_enable,current_drive->drv_sel);
 #endif
 		drvcmd[0]=CMD2_READ_VER;
 		response_count=12;
@@ -3421,37 +3415,37 @@
 			for (i=0;i<5;i++) if (infobuf[i]!=family2[i]) break;
 			if (i==5)
 			{
-				D_S[d].drive_model[0]='C';
-				D_S[d].drive_model[1]='D';
-				D_S[d].drive_model[2]='2';
-				D_S[d].drive_model[3]='0';
-				D_S[d].drive_model[4]='0';
-				D_S[d].drive_model[5]=infobuf[i++];
-				D_S[d].drive_model[6]=infobuf[i++];
-				D_S[d].drive_model[7]=0;
-				D_S[d].drv_type=drv_fam2;
+				current_drive->drive_model[0]='C';
+				current_drive->drive_model[1]='D';
+				current_drive->drive_model[2]='2';
+				current_drive->drive_model[3]='0';
+				current_drive->drive_model[4]='0';
+				current_drive->drive_model[5]=infobuf[i++];
+				current_drive->drive_model[6]=infobuf[i++];
+				current_drive->drive_model[7]=0;
+				current_drive->drv_type=drv_fam2;
 			}
 		}
 	}
-	if (!D_S[d].drv_type)
+	if (!current_drive->drv_type)
 	{
 		/* check for TEAC CD-55A */
 		msg(DBG_TEA,"teac_possible: %d\n",teac_possible);
-		for (j=1;j<=((D_S[d].drv_id==0)?3:1);j++)
+		for (j=1;j<=((current_drive->drv_id==0)?3:1);j++)
 		{
-			for (l=1;l<=((D_S[d].drv_id==0)?10:1);l++)
+			for (l=1;l<=((current_drive->drv_id==0)?10:1);l++)
 			{
 				msg(DBG_TEA,"TEAC reset #%d-%d.\n", j, l);
 				if (sbpro_type==1) OUT(CDo_reset,0);
 				else
 				{
-					OUT(CDo_enable,D_S[d].drv_sel);
+					OUT(CDo_enable,current_drive->drv_sel);
 					OUT(CDo_sel_i_d,0);
 					OUT(CDo_command,CMDT_RESET);
 					for (i=0;i<9;i++) OUT(CDo_command,0);
 				}
 				sbp_sleep(5*HZ/10);
-				OUT(CDo_enable,D_S[d].drv_sel);
+				OUT(CDo_enable,current_drive->drv_sel);
 				OUT(CDo_sel_i_d,0);
 				i=inb(CDi_status);
 				msg(DBG_TEA,"TEAC CDi_status: %02X.\n",i);
@@ -3478,82 +3472,82 @@
 			for (i=1;i<6;i++) if (infobuf[i]!=familyT[i-1]) break;
 			if (i==6)
 			{
-				D_S[d].drive_model[0]='C';
-				D_S[d].drive_model[1]='D';
-				D_S[d].drive_model[2]='-';
-				D_S[d].drive_model[3]='5';
-				D_S[d].drive_model[4]='5';
-				D_S[d].drive_model[5]=0;
-				D_S[d].drv_type=drv_famT;
+				current_drive->drive_model[0]='C';
+				current_drive->drive_model[1]='D';
+				current_drive->drive_model[2]='-';
+				current_drive->drive_model[3]='5';
+				current_drive->drive_model[4]='5';
+				current_drive->drive_model[5]=0;
+				current_drive->drv_type=drv_famT;
 			}
 		}
 	}
-	if (!D_S[d].drv_type)
+	if (!current_drive->drv_type)
 	{
-		msg(DBG_TEA,"no drive found at address %03X under ID %d.\n",CDo_command,D_S[d].drv_id);
+		msg(DBG_TEA,"no drive found at address %03X under ID %d.\n",CDo_command,current_drive->drv_id);
 		return (-522);
 	}
-	for (j=0;j<4;j++) D_S[d].firmware_version[j]=infobuf[i+j];
+	for (j=0;j<4;j++) current_drive->firmware_version[j]=infobuf[i+j];
 	if (famL_drive)
 	{
 	  u_char lcs_firm_e1[]="A E1";
 	  u_char lcs_firm_f4[]="A4F4";
 		
 	  for (j=0;j<4;j++)
-	    if (D_S[d].firmware_version[j]!=lcs_firm_e1[j]) break;
-	  if (j==4) D_S[d].drv_type=drv_e1;
+	    if (current_drive->firmware_version[j]!=lcs_firm_e1[j]) break;
+	  if (j==4) current_drive->drv_type=drv_e1;
 	  
 	  for (j=0;j<4;j++)
-	    if (D_S[d].firmware_version[j]!=lcs_firm_f4[j]) break;
-	  if (j==4) D_S[d].drv_type=drv_f4;
+	    if (current_drive->firmware_version[j]!=lcs_firm_f4[j]) break;
+	  if (j==4) current_drive->drv_type=drv_f4;
 
-	  if (D_S[d].drv_type==drv_famL) ask_mail();
+	  if (current_drive->drv_type==drv_famL) ask_mail();
 	}
 	else if (famT_drive)
 	{
 		j=infobuf[4]; /* one-byte version??? - here: 0x15 */
 		if (j=='5')
 		{
-			D_S[d].firmware_version[0]=infobuf[7];
-			D_S[d].firmware_version[1]=infobuf[8];
-			D_S[d].firmware_version[2]=infobuf[10];
-			D_S[d].firmware_version[3]=infobuf[11];
+			current_drive->firmware_version[0]=infobuf[7];
+			current_drive->firmware_version[1]=infobuf[8];
+			current_drive->firmware_version[2]=infobuf[10];
+			current_drive->firmware_version[3]=infobuf[11];
 		}
 		else
 		{
 			if (j!=0x15) ask_mail();
-			D_S[d].firmware_version[0]='0';
-			D_S[d].firmware_version[1]='.';
-			D_S[d].firmware_version[2]='0'+(j>>4);
-			D_S[d].firmware_version[3]='0'+(j&0x0f);
+			current_drive->firmware_version[0]='0';
+			current_drive->firmware_version[1]='.';
+			current_drive->firmware_version[2]='0'+(j>>4);
+			current_drive->firmware_version[3]='0'+(j&0x0f);
 		}
 	}
 	else /* CR-52x, CR-56x, CD200, ECS-AT */
 	{
-		j = (D_S[d].firmware_version[0] & 0x0F) * 100 +
-			(D_S[d].firmware_version[2] & 0x0F) *10 +
-				(D_S[d].firmware_version[3] & 0x0F);
+		j = (current_drive->firmware_version[0] & 0x0F) * 100 +
+			(current_drive->firmware_version[2] & 0x0F) *10 +
+				(current_drive->firmware_version[3] & 0x0F);
 		if (fam0_drive)
 		{
-			if (j<200) D_S[d].drv_type=drv_199;
-			else if (j<201) D_S[d].drv_type=drv_200;
-			else if (j<210) D_S[d].drv_type=drv_201;
-			else if (j<211) D_S[d].drv_type=drv_210;
-			else if (j<300) D_S[d].drv_type=drv_211;
-			else if (j>=300) D_S[d].drv_type=drv_300;
+			if (j<200) current_drive->drv_type=drv_199;
+			else if (j<201) current_drive->drv_type=drv_200;
+			else if (j<210) current_drive->drv_type=drv_201;
+			else if (j<211) current_drive->drv_type=drv_210;
+			else if (j<300) current_drive->drv_type=drv_211;
+			else if (j>=300) current_drive->drv_type=drv_300;
 		}
 		else if (fam1_drive)
 		{
-			if (j<100) D_S[d].drv_type=drv_099;
+			if (j<100) current_drive->drv_type=drv_099;
 			else
 			{
-				D_S[d].drv_type=drv_100;
+				current_drive->drv_type=drv_100;
 				if ((j!=500)&&(j!=102)) ask_mail();
 			}
 		}
 		else if (fam2_drive)
 		{
-			if (D_S[d].drive_model[5]=='F')
+			if (current_drive->drive_model[5]=='F')
 			{
 				if ((j!=1)&&(j!=35)&&(j!=200)&&(j!=210))
 				  ask_mail(); /* unknown version at time */
@@ -3567,20 +3561,21 @@
 		}
 		else if (famV_drive)
 		  {
-		    if ((j==100)||(j==150)) D_S[d].drv_type=drv_at;
+		    if ((j==100)||(j==150)) current_drive->drv_type=drv_at;
 		    ask_mail(); /* hopefully we get some feedback by this */
 		  }
 	}
-	msg(DBG_LCS,"drive type %02X\n",D_S[d].drv_type);
+	msg(DBG_LCS,"drive type %02X\n",current_drive->drv_type);
 	msg(DBG_INI,"check_version done.\n");
 	return (0);
 }
 /*==========================================================================*/
-static void switch_drive(int i)
+static void switch_drive(struct sbpcd_drive *p)
 {
-	d=i;
-	OUT(CDo_enable,D_S[d].drv_sel);
-	msg(DBG_DID,"drive %d (ID=%d) activated.\n", i, D_S[d].drv_id);
+	current_drive = p;
+	OUT(CDo_enable,current_drive->drv_sel);
+	msg(DBG_DID,"drive %d (ID=%d) activated.\n",
+		current_drive - D_S, current_drive->drv_id);
 	return;
 }
 /*==========================================================================*/
@@ -3700,23 +3695,24 @@
 	ndrives=0;
 	for (j=0;j<max_drives;j++)
 	{
-		D_S[ndrives].drv_id=j;
-		if (sbpro_type==1) D_S[ndrives].drv_sel=(j&0x01)<<1|(j&0x02)>>1;
-		else D_S[ndrives].drv_sel=j;
-		switch_drive(ndrives);
+		struct sbpcd_drive *p = D_S + ndrives;
+		p->drv_id=j;
+		if (sbpro_type==1) p->drv_sel=(j&0x01)<<1|(j&0x02)>>1;
+		else p->drv_sel=j;
+		switch_drive(p);
 		msg(DBG_INI,"check_drives: drive %d (ID=%d) activated.\n",ndrives,j);
 		msg(DBG_000,"check_drives: drive %d (ID=%d) activated.\n",ndrives,j);
 		i=check_version();
 		if (i<0) msg(DBG_INI,"check_version returns %d.\n",i);
 		else
 		{
-			D_S[d].drv_options=drv_pattern[j];
-			if (fam0L_drive) D_S[d].drv_options&=~(speed_auto|speed_300|speed_150);
+			current_drive->drv_options=drv_pattern[j];
+			if (fam0L_drive) current_drive->drv_options&=~(speed_auto|speed_300|speed_150);
 			msg(DBG_INF, "Drive %d (ID=%d): %.9s (%.4s) at 0x%03X (type %d)\n",
-			    d,
-			    D_S[d].drv_id,
-			    D_S[d].drive_model,
-			    D_S[d].firmware_version,
+			    current_drive - D_S,
+			    current_drive->drv_id,
+			    current_drive->drive_model,
+			    current_drive->firmware_version,
 			    CDo_command,
 			    sbpro_type);
 			ndrives++;
@@ -3852,7 +3848,7 @@
 {
 	int i;
 
-	i=msf2blk(D_S[d].pos_audio_end)-1;
+	i=msf2blk(current_drive->pos_audio_end)-1;
 	if (i<0) return (-1);
 	i=cc_Seek(i,0);
 	return (i);
@@ -3862,24 +3858,24 @@
 static int ReadToC(void)
 {
 	int i, j;
-	D_S[d].diskstate_flags &= ~toc_bit;
-	D_S[d].ored_ctl_adr=0;
+	current_drive->diskstate_flags &= ~toc_bit;
+	current_drive->ored_ctl_adr=0;
 	/* special handling of CD-I HE */
-	if ((D_S[d].n_first_track == 2 && D_S[d].n_last_track == 2) ||
-             D_S[d].xa_byte == 0x10)
+	if ((current_drive->n_first_track == 2 && current_drive->n_last_track == 2) ||
+             current_drive->xa_byte == 0x10)
         {
-		D_S[d].TocBuffer[1].nixbyte=0;
-		D_S[d].TocBuffer[1].ctl_adr=0x40;
-		D_S[d].TocBuffer[1].number=1;
-		D_S[d].TocBuffer[1].format=0;
-		D_S[d].TocBuffer[1].address=blk2msf(0);
-		D_S[d].ored_ctl_adr |= 0x40;
-		D_S[d].n_first_track = 1;
-		D_S[d].n_last_track = 1;
-		D_S[d].xa_byte = 0x10;
+		current_drive->TocBuffer[1].nixbyte=0;
+		current_drive->TocBuffer[1].ctl_adr=0x40;
+		current_drive->TocBuffer[1].number=1;
+		current_drive->TocBuffer[1].format=0;
+		current_drive->TocBuffer[1].address=blk2msf(0);
+		current_drive->ored_ctl_adr |= 0x40;
+		current_drive->n_first_track = 1;
+		current_drive->n_last_track = 1;
+		current_drive->xa_byte = 0x10;
                 j = 2;
         } else
-	for (j=D_S[d].n_first_track;j<=D_S[d].n_last_track;j++)
+	for (j=current_drive->n_first_track;j<=current_drive->n_last_track;j++)
 	{
 		i=cc_ReadTocEntry(j);
 		if (i<0)
@@ -3887,21 +3883,21 @@
 			msg(DBG_INF,"cc_ReadTocEntry(%d) returns %d.\n",j,i);
 			return (i);
 		}
-		D_S[d].TocBuffer[j].nixbyte=D_S[d].TocEnt_nixbyte;
-		D_S[d].TocBuffer[j].ctl_adr=D_S[d].TocEnt_ctl_adr;
-		D_S[d].TocBuffer[j].number=D_S[d].TocEnt_number;
-		D_S[d].TocBuffer[j].format=D_S[d].TocEnt_format;
-		D_S[d].TocBuffer[j].address=D_S[d].TocEnt_address;
-		D_S[d].ored_ctl_adr |= D_S[d].TocEnt_ctl_adr;
+		current_drive->TocBuffer[j].nixbyte=current_drive->TocEnt_nixbyte;
+		current_drive->TocBuffer[j].ctl_adr=current_drive->TocEnt_ctl_adr;
+		current_drive->TocBuffer[j].number=current_drive->TocEnt_number;
+		current_drive->TocBuffer[j].format=current_drive->TocEnt_format;
+		current_drive->TocBuffer[j].address=current_drive->TocEnt_address;
+		current_drive->ored_ctl_adr |= current_drive->TocEnt_ctl_adr;
 	}
 	/* fake entry for LeadOut Track */
-	D_S[d].TocBuffer[j].nixbyte=0;
-	D_S[d].TocBuffer[j].ctl_adr=0;
-	D_S[d].TocBuffer[j].number=CDROM_LEADOUT;
-	D_S[d].TocBuffer[j].format=0;
-	D_S[d].TocBuffer[j].address=D_S[d].size_msf;
+	current_drive->TocBuffer[j].nixbyte=0;
+	current_drive->TocBuffer[j].ctl_adr=0;
+	current_drive->TocBuffer[j].number=CDROM_LEADOUT;
+	current_drive->TocBuffer[j].format=0;
+	current_drive->TocBuffer[j].address=current_drive->size_msf;
 	
-	D_S[d].diskstate_flags |= toc_bit;
+	current_drive->diskstate_flags |= toc_bit;
 	return (0);
 }
 /*==========================================================================*/
@@ -3909,7 +3905,7 @@
 {
 	int i, j;
 	
-	D_S[d].mode=READ_M1;
+	current_drive->mode=READ_M1;
 	
 #undef LOOP_COUNT
 #define LOOP_COUNT 10 /* needed for some "old" drives */
@@ -3959,9 +3955,9 @@
 		msg(DBG_INF,"DiskInfo: cc_CheckMultiSession returns %d\n", i);
 		return (i);
 	}
-	if (D_S[d].f_multisession) D_S[d].sbp_bufsiz=1;  /* possibly a weird PhotoCD */
-	else D_S[d].sbp_bufsiz=buffers;
-	i=cc_ReadTocEntry(D_S[d].n_first_track);
+	if (current_drive->f_multisession) current_drive->sbp_bufsiz=1;  /* possibly a weird PhotoCD */
+	else current_drive->sbp_bufsiz=buffers;
+	i=cc_ReadTocEntry(current_drive->n_first_track);
 	if (i<0)
 	{
 		msg(DBG_INF,"DiskInfo: cc_ReadTocEntry(1) returns %d\n", i);
@@ -3969,7 +3965,7 @@
 	}
 	i=cc_ReadUPC();
 	if (i<0) msg(DBG_INF,"DiskInfo: cc_ReadUPC returns %d\n", i);
-	if ((fam0L_drive) && (D_S[d].xa_byte==0x20 || D_S[d].xa_byte == 0x10))
+	if ((fam0L_drive) && (current_drive->xa_byte==0x20 || current_drive->xa_byte == 0x10))
 	{
 		/* XA disk with old drive */
 		cc_ModeSelect(CD_FRAMESIZE_RAW1);
@@ -3982,6 +3978,7 @@
 
 static int sbpcd_drive_status(struct cdrom_device_info *cdi, int slot_nr)
 {
+	struct sbpcd_drive *p = cdi->handle;
 	int st;
 
 	if (CDSL_CURRENT != slot_nr) {
@@ -4004,13 +4001,13 @@
 	msg(DBG_000,"Drive Status: busy =%d.\n", st_busy);
 
 #if 0
-  if (!(D_S[minor(cdi->dev)].status_bits & p_door_closed)) return CDS_TRAY_OPEN;
-  if (D_S[minor(cdi->dev)].status_bits & p_disk_ok) return CDS_DISC_OK;
-  if (D_S[minor(cdi->dev)].status_bits & p_disk_in) return CDS_DRIVE_NOT_READY;
+  if (!(p->status_bits & p_door_closed)) return CDS_TRAY_OPEN;
+  if (p->status_bits & p_disk_ok) return CDS_DISC_OK;
+  if (p->status_bits & p_disk_in) return CDS_DRIVE_NOT_READY;
 
   return CDS_NO_DISC;
 #else
-  if (D_S[minor(cdi->dev)].status_bits & p_spinning) return CDS_DISC_OK;
+  if (p->status_bits & p_spinning) return CDS_DISC_OK;
 /*  return CDS_TRAY_OPEN; */
   return CDS_NO_DISC;
   
@@ -4037,10 +4034,10 @@
 	else if (fam1_drive) GetStatus();
 	else if (fam2_drive) GetStatus();
 	else if (famT_drive) GetStatus();
-	if (D_S[d].CD_changed==0xFF)
+	if (current_drive->CD_changed==0xFF)
 	{
-		D_S[d].diskstate_flags=0;
-		D_S[d].audio_state=0;
+		current_drive->diskstate_flags=0;
+		current_drive->audio_state=0;
 		if (!st_diskok)
 		{
 			i=check_allowed1(func,subfunc);
@@ -4051,7 +4048,7 @@
 			i=check_allowed3(func,subfunc);
 			if (i<0)
 			{
-				D_S[d].CD_changed=1;
+				current_drive->CD_changed=1;
 				return (-15);
 			}
 		}
@@ -4060,8 +4057,8 @@
 	{
 		if (!st_diskok)
 		{
-			D_S[d].diskstate_flags=0;
-			D_S[d].audio_state=0;
+			current_drive->diskstate_flags=0;
+			current_drive->audio_state=0;
 			i=check_allowed1(func,subfunc);
 			if (i<0) return (-2);
 		}
@@ -4069,7 +4066,7 @@
 		{ 
 			if (st_busy)
 			{
-				if (D_S[d].audio_state!=audio_pausing)
+				if (current_drive->audio_state!=audio_pausing)
 				{
 					i=check_allowed2(func,subfunc);
 					if (i<0) return (-2);
@@ -4077,16 +4074,16 @@
 			}
 			else
 			{
-				if (D_S[d].audio_state==audio_playing) seek_pos_audio_end();
-				D_S[d].audio_state=0;
+				if (current_drive->audio_state==audio_playing) seek_pos_audio_end();
+				current_drive->audio_state=0;
 			}
 			if (!frame_size_valid)
 			{
 				i=DiskInfo();
 				if (i<0)
 				{
-					D_S[d].diskstate_flags=0;
-					D_S[d].audio_state=0;
+					current_drive->diskstate_flags=0;
+					current_drive->audio_state=0;
 					i=check_allowed1(func,subfunc);
 					if (i<0) return (-2);
 				}
@@ -4145,9 +4142,10 @@
 		
 static int sbpcd_get_last_session(struct cdrom_device_info *cdi, struct cdrom_multisession *ms_infp)
 {
+	struct sbpcd_drive *p = cdi->handle;
 	ms_infp->addr_format = CDROM_LBA;
-	ms_infp->addr.lba    = D_S[minor(cdi->dev)].lba_multi;
-	if (D_S[minor(cdi->dev)].f_multisession)
+	ms_infp->addr.lba    = p->lba_multi;
+	if (p->f_multisession)
 		ms_infp->xa_flag=1; /* valid redirection address */
 	else
 		ms_infp->xa_flag=0; /* invalid redirection address */
@@ -4163,20 +4161,19 @@
 static int sbpcd_dev_ioctl(struct cdrom_device_info *cdi, u_int cmd,
 		      u_long arg)
 {
+	struct sbpcd_drive *p = cdi->handle;
 	int i;
 	
-	msg(DBG_IO2,"ioctl(%d, 0x%08lX, 0x%08lX)\n",
-	    minor(cdi->dev), cmd, arg);
-	i=minor(cdi->dev);
-	if ((i<0) || (i>=NR_SBPCD) || (D_S[i].drv_id==-1))
-	{
-		msg(DBG_INF, "ioctl: bad device: %04X\n", cdi->dev);
+	msg(DBG_IO2,"ioctl(%s, 0x%08lX, 0x%08lX)\n", cdi->name, cmd, arg);
+	if (p->drv_id==-1) {
+		msg(DBG_INF, "ioctl: bad device: %s\n", cdi->name);
 		return (-ENXIO);             /* no such drive */
 	}
 	down(&ioctl_read_sem);
-	if (d!=i) switch_drive(i);
+	if (p != current_drive)
+		switch_drive(p);
 	
-	msg(DBG_IO2,"ioctl: device %d, request %04X\n",i,cmd);
+	msg(DBG_IO2,"ioctl: device %s, request %04X\n",cdi->name,cmd);
 	switch (cmd) 		/* Sun-compatible */
 	{
 	case DDIOCSDBG:		/* DDI Debug */
@@ -4186,52 +4183,52 @@
 	case CDROMRESET:      /* hard reset the drive */
 		msg(DBG_IOC,"ioctl: CDROMRESET entered.\n");
 		i=DriveReset();
-		D_S[d].audio_state=0;
+		current_drive->audio_state=0;
 		RETURN_UP(i);
 		
 	case CDROMREADMODE1:
 		msg(DBG_IOC,"ioctl: CDROMREADMODE1 requested.\n");
 #if SAFE_MIXED
-		if (D_S[d].has_data>1) RETURN_UP(-EBUSY);
+		if (current_drive->has_data>1) RETURN_UP(-EBUSY);
 #endif /* SAFE_MIXED */
 		cc_ModeSelect(CD_FRAMESIZE);
 		cc_ModeSense();
-		D_S[d].mode=READ_M1;
+		current_drive->mode=READ_M1;
 		RETURN_UP(0);
 		
 	case CDROMREADMODE2: /* not usable at the moment */
 		msg(DBG_IOC,"ioctl: CDROMREADMODE2 requested.\n");
 #if SAFE_MIXED
-		if (D_S[d].has_data>1) RETURN_UP(-EBUSY);
+		if (current_drive->has_data>1) RETURN_UP(-EBUSY);
 #endif /* SAFE_MIXED */
 		cc_ModeSelect(CD_FRAMESIZE_RAW1);
 		cc_ModeSense();
-		D_S[d].mode=READ_M2;
+		current_drive->mode=READ_M2;
 		RETURN_UP(0);
 		
 	case CDROMAUDIOBUFSIZ: /* configure the audio buffer size */
 		msg(DBG_IOC,"ioctl: CDROMAUDIOBUFSIZ entered.\n");
-		if (D_S[d].sbp_audsiz>0) vfree(D_S[d].aud_buf);
-		D_S[d].aud_buf=NULL;
-		D_S[d].sbp_audsiz=arg;
+		if (current_drive->sbp_audsiz>0) vfree(current_drive->aud_buf);
+		current_drive->aud_buf=NULL;
+		current_drive->sbp_audsiz=arg;
 		
-		if (D_S[d].sbp_audsiz>16)
+		if (current_drive->sbp_audsiz>16)
 		{
-			D_S[d].sbp_audsiz = 0;
-			RETURN_UP(D_S[d].sbp_audsiz);
+			current_drive->sbp_audsiz = 0;
+			RETURN_UP(current_drive->sbp_audsiz);
 		}
 	
-		if (D_S[d].sbp_audsiz>0)
+		if (current_drive->sbp_audsiz>0)
 		{
-			D_S[d].aud_buf=(u_char *) vmalloc(D_S[d].sbp_audsiz*CD_FRAMESIZE_RAW);
-			if (D_S[d].aud_buf==NULL)
+			current_drive->aud_buf=(u_char *) vmalloc(current_drive->sbp_audsiz*CD_FRAMESIZE_RAW);
+			if (current_drive->aud_buf==NULL)
 			{
-				msg(DBG_INF,"audio buffer (%d frames) not available.\n",D_S[d].sbp_audsiz);
-				D_S[d].sbp_audsiz=0;
+				msg(DBG_INF,"audio buffer (%d frames) not available.\n",current_drive->sbp_audsiz);
+				current_drive->sbp_audsiz=0;
 			}
-			else msg(DBG_INF,"audio buffer size: %d frames.\n",D_S[d].sbp_audsiz);
+			else msg(DBG_INF,"audio buffer size: %d frames.\n",current_drive->sbp_audsiz);
 		}
-		RETURN_UP(D_S[d].sbp_audsiz);
+		RETURN_UP(current_drive->sbp_audsiz);
 
 	case CDROMREADAUDIO:
 	{ /* start of CDROMREADAUDIO */
@@ -4251,13 +4248,13 @@
 		if (famV_drive) RETURN_UP(-EINVAL);
 		if (famT_drive) RETURN_UP(-EINVAL);
 #if SAFE_MIXED
-		if (D_S[d].has_data>1) RETURN_UP(-EBUSY);
+		if (current_drive->has_data>1) RETURN_UP(-EBUSY);
 #endif /* SAFE_MIXED */ 
-		if (D_S[d].aud_buf==NULL) RETURN_UP(-EINVAL);
+		if (current_drive->aud_buf==NULL) RETURN_UP(-EINVAL);
 		if (copy_from_user(&read_audio, (void *)arg,
 				   sizeof(struct cdrom_read_audio)))
 			RETURN_UP(-EFAULT);
-		if (read_audio.nframes < 0 || read_audio.nframes>D_S[d].sbp_audsiz) RETURN_UP(-EINVAL);
+		if (read_audio.nframes < 0 || read_audio.nframes>current_drive->sbp_audsiz) RETURN_UP(-EINVAL);
 		i=verify_area(VERIFY_WRITE, read_audio.buf,
 			      read_audio.nframes*CD_FRAMESIZE_RAW);
 		if (i) RETURN_UP(i);
@@ -4282,7 +4279,7 @@
 		for (data_tries=5; data_tries>0; data_tries--)
 		{
 			msg(DBG_AUD,"data_tries=%d ...\n", data_tries);
-			D_S[d].mode=READ_AU;
+			current_drive->mode=READ_AU;
 			cc_ModeSelect(CD_FRAMESIZE_RAW);
 			cc_ModeSense();
 			for (status_tries=3; status_tries > 0; status_tries--)
@@ -4372,13 +4369,13 @@
 				}
 				msg(DBG_AUD,"read_audio: before reading data.\n");
 				error_flag=0;
-				p = D_S[d].aud_buf;
+				p = current_drive->aud_buf;
 				if (sbpro_type==1) OUT(CDo_sel_i_d,1);
 				if (do_16bit)
 				{
 					u_short *p2 = (u_short *) p;
 
-					for (; (u_char *) p2 < D_S[d].aud_buf + read_audio.nframes*CD_FRAMESIZE_RAW;)
+					for (; (u_char *) p2 < current_drive->aud_buf + read_audio.nframes*CD_FRAMESIZE_RAW;)
 				  	{
 						if ((inb_p(CDi_status)&s_not_data_ready)) continue;
 
@@ -4387,7 +4384,7 @@
 						*p2++ = inw_p(CDi_data);
 					}
 				} else {
-					for (; p < D_S[d].aud_buf + read_audio.nframes*CD_FRAMESIZE_RAW;)
+					for (; p < current_drive->aud_buf + read_audio.nframes*CD_FRAMESIZE_RAW;)
 				  	{
 						if ((inb_p(CDi_status)&s_not_data_ready)) continue;
 
@@ -4442,7 +4439,7 @@
 				i=ResponseStatus();  /* builds status_bits, returns orig. status (old) or faked p_success (new) */
 				if (i<0) { msg(DBG_AUD,
 					       "read_audio: cc_ReadStatus error after read: %02X\n",
-					       D_S[d].status_bits);
+					       current_drive->status_bits);
 					   continue; /* FIXME */
 				   }
 			}
@@ -4454,7 +4451,7 @@
 				continue;
 			}
 			if (copy_to_user((u_char *)read_audio.buf,
-					 (u_char *) D_S[d].aud_buf,
+					 (u_char *) current_drive->aud_buf,
 					 read_audio.nframes * CD_FRAMESIZE_RAW))
 				RETURN_UP(-EFAULT);
 			msg(DBG_AUD,"read_audio: copy_to_user done.\n");
@@ -4462,7 +4459,7 @@
 		}
 		cc_ModeSelect(CD_FRAMESIZE);
 		cc_ModeSense();
-		D_S[d].mode=READ_M1;
+		current_drive->mode=READ_M1;
 #if OLD_BUSY
 		busy_audio=0;
 #endif /* OLD_BUSY */ 
@@ -4484,20 +4481,19 @@
 static int sbpcd_audio_ioctl(struct cdrom_device_info *cdi, u_int cmd,
 		       void * arg)
 {
+	struct sbpcd_drive *p = cdi->handle;
 	int i, st, j;
 	
-	msg(DBG_IO2,"ioctl(%d, 0x%08lX, 0x%08p)\n",
-	    minor(cdi->dev), cmd, arg);
-	i=minor(cdi->dev);
-	if ((i<0) || (i>=NR_SBPCD) || (D_S[i].drv_id==-1))
-	{
-		msg(DBG_INF, "ioctl: bad device: %04X\n", cdi->dev);
+	msg(DBG_IO2,"ioctl(%s, 0x%08lX, 0x%08p)\n", cdi->name, cmd, arg);
+	if (p->drv_id==-1) {
+		msg(DBG_INF, "ioctl: bad device: %s\n", cdi->name);
 		return (-ENXIO);             /* no such drive */
 	}
 	down(&ioctl_read_sem);
-	if (d!=i) switch_drive(i);
+	if (p != current_drive)
+		switch_drive(p);
 	
-	msg(DBG_IO2,"ioctl: device %d, request %04X\n",i,cmd);
+	msg(DBG_IO2,"ioctl: device %s, request %04X\n",cdi->name,cmd);
 	switch (cmd) 		/* Sun-compatible */
 	{
 		
@@ -4507,7 +4503,7 @@
 		/* or reset the starting and ending locations when in PAUSED mode. */
 		/* If applicable, at the next stopping point it reaches            */
 		/* the drive will discontinue playing.                             */
-		switch (D_S[d].audio_state)
+		switch (current_drive->audio_state)
 		{
 		case audio_playing:
 			if (famL_drive) i=cc_ReadSubQ();
@@ -4516,11 +4512,11 @@
 			if (famL_drive) i=cc_Pause_Resume(1);
 			else i=cc_ReadSubQ();
 			if (i<0) RETURN_UP(-EIO);
-			D_S[d].pos_audio_start=D_S[d].SubQ_run_tot;
-			D_S[d].audio_state=audio_pausing;
+			current_drive->pos_audio_start=current_drive->SubQ_run_tot;
+			current_drive->audio_state=audio_pausing;
 			RETURN_UP(0);
 		case audio_pausing:
-			i=cc_Seek(D_S[d].pos_audio_start,1);
+			i=cc_Seek(current_drive->pos_audio_start,1);
 			if (i<0) RETURN_UP(-EIO);
 			RETURN_UP(0);
 		default:
@@ -4532,56 +4528,56 @@
 		/* resume playing audio tracks when a previous PLAY AUDIO call has  */
 		/* been paused with a PAUSE command.                                */
 		/* It will resume playing from the location saved in SubQ_run_tot.  */
-		if (D_S[d].audio_state!=audio_pausing) RETURN_UP(-EINVAL);
+		if (current_drive->audio_state!=audio_pausing) RETURN_UP(-EINVAL);
 		if (famL_drive)
-			i=cc_PlayAudio(D_S[d].pos_audio_start,
-				       D_S[d].pos_audio_end);
+			i=cc_PlayAudio(current_drive->pos_audio_start,
+				       current_drive->pos_audio_end);
 		else i=cc_Pause_Resume(3);
 		if (i<0) RETURN_UP(-EIO);
-		D_S[d].audio_state=audio_playing;
+		current_drive->audio_state=audio_playing;
 		RETURN_UP(0);
 		
 	case CDROMPLAYMSF:
 		msg(DBG_IOC,"ioctl: CDROMPLAYMSF entered.\n");
 #if SAFE_MIXED
-		if (D_S[d].has_data>1) RETURN_UP(-EBUSY);
+		if (current_drive->has_data>1) RETURN_UP(-EBUSY);
 #endif /* SAFE_MIXED */ 
-		if (D_S[d].audio_state==audio_playing)
+		if (current_drive->audio_state==audio_playing)
 		{
 			i=cc_Pause_Resume(1);
 			if (i<0) RETURN_UP(-EIO);
 			i=cc_ReadSubQ();
 			if (i<0) RETURN_UP(-EIO);
-			D_S[d].pos_audio_start=D_S[d].SubQ_run_tot;
-			i=cc_Seek(D_S[d].pos_audio_start,1);
+			current_drive->pos_audio_start=current_drive->SubQ_run_tot;
+			i=cc_Seek(current_drive->pos_audio_start,1);
 		}
 		memcpy(&msf, (void *) arg, sizeof(struct cdrom_msf));
 		/* values come as msf-bin */
-		D_S[d].pos_audio_start = (msf.cdmsf_min0<<16) |
+		current_drive->pos_audio_start = (msf.cdmsf_min0<<16) |
                         (msf.cdmsf_sec0<<8) |
 				msf.cdmsf_frame0;
-		D_S[d].pos_audio_end = (msf.cdmsf_min1<<16) |
+		current_drive->pos_audio_end = (msf.cdmsf_min1<<16) |
 			(msf.cdmsf_sec1<<8) |
 				msf.cdmsf_frame1;
 		msg(DBG_IOX,"ioctl: CDROMPLAYMSF %08X %08X\n",
-		    D_S[d].pos_audio_start,D_S[d].pos_audio_end);
-		i=cc_PlayAudio(D_S[d].pos_audio_start,D_S[d].pos_audio_end);
+		    current_drive->pos_audio_start,current_drive->pos_audio_end);
+		i=cc_PlayAudio(current_drive->pos_audio_start,current_drive->pos_audio_end);
 		if (i<0)
 		{
 			msg(DBG_INF,"ioctl: cc_PlayAudio returns %d\n",i);
 			DriveReset();
-			D_S[d].audio_state=0;
+			current_drive->audio_state=0;
 			RETURN_UP(-EIO);
 		}
-		D_S[d].audio_state=audio_playing;
+		current_drive->audio_state=audio_playing;
 		RETURN_UP(0);
 		
 	case CDROMPLAYTRKIND: /* Play a track.  This currently ignores index. */
 		msg(DBG_IOC,"ioctl: CDROMPLAYTRKIND entered.\n");
 #if SAFE_MIXED
-		if (D_S[d].has_data>1) RETURN_UP(-EBUSY);
+		if (current_drive->has_data>1) RETURN_UP(-EBUSY);
 #endif /* SAFE_MIXED */ 
-		if (D_S[d].audio_state==audio_playing)
+		if (current_drive->audio_state==audio_playing)
 		{
 			msg(DBG_IOX,"CDROMPLAYTRKIND: already audio_playing.\n");
 #if 1
@@ -4593,27 +4589,27 @@
 		memcpy(&ti,(void *) arg,sizeof(struct cdrom_ti));
 		msg(DBG_IOX,"ioctl: trk0: %d, ind0: %d, trk1:%d, ind1:%d\n",
 		    ti.cdti_trk0,ti.cdti_ind0,ti.cdti_trk1,ti.cdti_ind1);
-		if (ti.cdti_trk0<D_S[d].n_first_track) RETURN_UP(-EINVAL);
-		if (ti.cdti_trk0>D_S[d].n_last_track) RETURN_UP(-EINVAL);
+		if (ti.cdti_trk0<current_drive->n_first_track) RETURN_UP(-EINVAL);
+		if (ti.cdti_trk0>current_drive->n_last_track) RETURN_UP(-EINVAL);
 		if (ti.cdti_trk1<ti.cdti_trk0) ti.cdti_trk1=ti.cdti_trk0;
-		if (ti.cdti_trk1>D_S[d].n_last_track) ti.cdti_trk1=D_S[d].n_last_track;
-		D_S[d].pos_audio_start=D_S[d].TocBuffer[ti.cdti_trk0].address;
-		D_S[d].pos_audio_end=D_S[d].TocBuffer[ti.cdti_trk1+1].address;
-		i=cc_PlayAudio(D_S[d].pos_audio_start,D_S[d].pos_audio_end);
+		if (ti.cdti_trk1>current_drive->n_last_track) ti.cdti_trk1=current_drive->n_last_track;
+		current_drive->pos_audio_start=current_drive->TocBuffer[ti.cdti_trk0].address;
+		current_drive->pos_audio_end=current_drive->TocBuffer[ti.cdti_trk1+1].address;
+		i=cc_PlayAudio(current_drive->pos_audio_start,current_drive->pos_audio_end);
 		if (i<0)
 		{
 			msg(DBG_INF,"ioctl: cc_PlayAudio returns %d\n",i);
 			DriveReset();
-			D_S[d].audio_state=0;
+			current_drive->audio_state=0;
 			RETURN_UP(-EIO);
 		}
-		D_S[d].audio_state=audio_playing;
+		current_drive->audio_state=audio_playing;
 		RETURN_UP(0);
 		
 	case CDROMREADTOCHDR:        /* Read the table of contents header */
 		msg(DBG_IOC,"ioctl: CDROMREADTOCHDR entered.\n");
-		tochdr.cdth_trk0=D_S[d].n_first_track;
-		tochdr.cdth_trk1=D_S[d].n_last_track;
+		tochdr.cdth_trk0=current_drive->n_first_track;
+		tochdr.cdth_trk1=current_drive->n_last_track;
 		memcpy((void *) arg, &tochdr, sizeof(struct cdrom_tochdr));
 		RETURN_UP(0);
 		
@@ -4621,20 +4617,20 @@
 		msg(DBG_IOC,"ioctl: CDROMREADTOCENTRY entered.\n");
 		memcpy(&tocentry, (void *) arg, sizeof(struct cdrom_tocentry));
 		i=tocentry.cdte_track;
-		if (i==CDROM_LEADOUT) i=D_S[d].n_last_track+1;
-		else if (i<D_S[d].n_first_track||i>D_S[d].n_last_track)
+		if (i==CDROM_LEADOUT) i=current_drive->n_last_track+1;
+		else if (i<current_drive->n_first_track||i>current_drive->n_last_track)
                   RETURN_UP(-EINVAL);
-		tocentry.cdte_adr=D_S[d].TocBuffer[i].ctl_adr&0x0F;
-		tocentry.cdte_ctrl=(D_S[d].TocBuffer[i].ctl_adr>>4)&0x0F;
-		tocentry.cdte_datamode=D_S[d].TocBuffer[i].format;
+		tocentry.cdte_adr=current_drive->TocBuffer[i].ctl_adr&0x0F;
+		tocentry.cdte_ctrl=(current_drive->TocBuffer[i].ctl_adr>>4)&0x0F;
+		tocentry.cdte_datamode=current_drive->TocBuffer[i].format;
 		if (tocentry.cdte_format==CDROM_MSF) /* MSF-bin required */
 		{
-			tocentry.cdte_addr.msf.minute=(D_S[d].TocBuffer[i].address>>16)&0x00FF;
-			tocentry.cdte_addr.msf.second=(D_S[d].TocBuffer[i].address>>8)&0x00FF;
-			tocentry.cdte_addr.msf.frame=D_S[d].TocBuffer[i].address&0x00FF;
+			tocentry.cdte_addr.msf.minute=(current_drive->TocBuffer[i].address>>16)&0x00FF;
+			tocentry.cdte_addr.msf.second=(current_drive->TocBuffer[i].address>>8)&0x00FF;
+			tocentry.cdte_addr.msf.frame=current_drive->TocBuffer[i].address&0x00FF;
 		}
 		else if (tocentry.cdte_format==CDROM_LBA) /* blk required */
-			tocentry.cdte_addr.lba=msf2blk(D_S[d].TocBuffer[i].address);
+			tocentry.cdte_addr.lba=msf2blk(current_drive->TocBuffer[i].address);
 		else RETURN_UP(-EINVAL);
 		memcpy((void *) arg, &tocentry, sizeof(struct cdrom_tocentry));
 		RETURN_UP(0);
@@ -4642,10 +4638,10 @@
 	case CDROMSTOP:      /* Spin down the drive */
 		msg(DBG_IOC,"ioctl: CDROMSTOP entered.\n");
 #if SAFE_MIXED
-		if (D_S[d].has_data>1) RETURN_UP(-EBUSY);
+		if (current_drive->has_data>1) RETURN_UP(-EBUSY);
 #endif /* SAFE_MIXED */ 
 		i=cc_Pause_Resume(1);
-		D_S[d].audio_state=0;
+		current_drive->audio_state=0;
 #if 0
 		cc_DriveReset();
 #endif
@@ -4654,16 +4650,16 @@
 	case CDROMSTART:  /* Spin up the drive */
 		msg(DBG_IOC,"ioctl: CDROMSTART entered.\n");
 		cc_SpinUp();
-		D_S[d].audio_state=0;
+		current_drive->audio_state=0;
 		RETURN_UP(0);
 		
 	case CDROMVOLCTRL:   /* Volume control */
 		msg(DBG_IOC,"ioctl: CDROMVOLCTRL entered.\n");
 		memcpy(&volctrl,(char *) arg,sizeof(volctrl));
-		D_S[d].vol_chan0=0;
-		D_S[d].vol_ctrl0=volctrl.channel0;
-		D_S[d].vol_chan1=1;
-		D_S[d].vol_ctrl1=volctrl.channel1;
+		current_drive->vol_chan0=0;
+		current_drive->vol_ctrl0=volctrl.channel0;
+		current_drive->vol_chan1=1;
+		current_drive->vol_ctrl1=volctrl.channel1;
 		i=cc_SetVolume();
 		RETURN_UP(0);
 		
@@ -4671,8 +4667,8 @@
 		msg(DBG_IOC,"ioctl: CDROMVOLREAD entered.\n");
 		st=cc_GetVolume();
 		if (st<0) RETURN_UP(st);
-		volctrl.channel0=D_S[d].vol_ctrl0;
-		volctrl.channel1=D_S[d].vol_ctrl1;
+		volctrl.channel0=current_drive->vol_ctrl0;
+		volctrl.channel1=current_drive->vol_ctrl1;
 		volctrl.channel2=0;
 		volctrl.channel2=0;
 		memcpy((void *)arg,&volctrl,sizeof(volctrl));
@@ -4689,22 +4685,22 @@
 		i=cc_ReadSubQ();
 		if (i<0) {
 			j=cc_ReadError(); /* clear out error status from drive */
-			D_S[d].audio_state=CDROM_AUDIO_NO_STATUS;
+			current_drive->audio_state=CDROM_AUDIO_NO_STATUS;
 			/* get and set the disk state here, 
 			probably not the right place, but who cares!
 			It makes it work properly! --AJK */
-			if (D_S[d].CD_changed==0xFF) {
+			if (current_drive->CD_changed==0xFF) {
 				msg(DBG_000,"Disk changed detect\n");
-				D_S[d].diskstate_flags &= ~cd_size_bit;
+				current_drive->diskstate_flags &= ~cd_size_bit;
 			}
 			RETURN_UP(-EIO);
 		}
-		if (D_S[d].CD_changed==0xFF) {
+		if (current_drive->CD_changed==0xFF) {
 			/* reread the TOC because the disk has changed! --AJK */
 			msg(DBG_000,"Disk changed STILL detected, rereading TOC!\n");
 			i=DiskInfo();
 			if(i==0) {
-				D_S[d].CD_changed=0x00; /* cd has changed, procede, */
+				current_drive->CD_changed=0x00; /* cd has changed, procede, */
 				RETURN_UP(-EIO); /* and get TOC, etc on next try! --AJK */
 			} else {
 				RETURN_UP(-EIO); /* we weren't ready yet! --AJK */
@@ -4725,12 +4721,12 @@
 		msg(DBG_000,"Drive Status: spinning =%d.\n", st_spinning);
 		msg(DBG_000,"Drive Status: busy =%d.\n", st_busy);
 		/* st_busy indicates if it's _ACTUALLY_ playing audio */
-		switch (D_S[d].audio_state)
+		switch (current_drive->audio_state)
 		{
 		case audio_playing:
 			if(st_busy==0) {
 				/* CD has stopped playing audio --AJK */
-				D_S[d].audio_state=audio_completed;
+				current_drive->audio_state=audio_completed;
 				SC.cdsc_audiostatus=CDROM_AUDIO_COMPLETED;
 			} else {
 				SC.cdsc_audiostatus=CDROM_AUDIO_PLAY;
@@ -4746,23 +4742,23 @@
 			SC.cdsc_audiostatus=CDROM_AUDIO_NO_STATUS;
 			break;
 		}
-		SC.cdsc_adr=D_S[d].SubQ_ctl_adr;
-		SC.cdsc_ctrl=D_S[d].SubQ_ctl_adr>>4;
-		SC.cdsc_trk=bcd2bin(D_S[d].SubQ_trk);
-		SC.cdsc_ind=bcd2bin(D_S[d].SubQ_pnt_idx);
+		SC.cdsc_adr=current_drive->SubQ_ctl_adr;
+		SC.cdsc_ctrl=current_drive->SubQ_ctl_adr>>4;
+		SC.cdsc_trk=bcd2bin(current_drive->SubQ_trk);
+		SC.cdsc_ind=bcd2bin(current_drive->SubQ_pnt_idx);
 		if (SC.cdsc_format==CDROM_LBA)
 		{
-			SC.cdsc_absaddr.lba=msf2blk(D_S[d].SubQ_run_tot);
-			SC.cdsc_reladdr.lba=msf2blk(D_S[d].SubQ_run_trk);
+			SC.cdsc_absaddr.lba=msf2blk(current_drive->SubQ_run_tot);
+			SC.cdsc_reladdr.lba=msf2blk(current_drive->SubQ_run_trk);
 		}
 		else /* not only if (SC.cdsc_format==CDROM_MSF) */
 		{
-			SC.cdsc_absaddr.msf.minute=(D_S[d].SubQ_run_tot>>16)&0x00FF;
-			SC.cdsc_absaddr.msf.second=(D_S[d].SubQ_run_tot>>8)&0x00FF;
-			SC.cdsc_absaddr.msf.frame=D_S[d].SubQ_run_tot&0x00FF;
-			SC.cdsc_reladdr.msf.minute=(D_S[d].SubQ_run_trk>>16)&0x00FF;
-			SC.cdsc_reladdr.msf.second=(D_S[d].SubQ_run_trk>>8)&0x00FF;
-			SC.cdsc_reladdr.msf.frame=D_S[d].SubQ_run_trk&0x00FF;
+			SC.cdsc_absaddr.msf.minute=(current_drive->SubQ_run_tot>>16)&0x00FF;
+			SC.cdsc_absaddr.msf.second=(current_drive->SubQ_run_tot>>8)&0x00FF;
+			SC.cdsc_absaddr.msf.frame=current_drive->SubQ_run_tot&0x00FF;
+			SC.cdsc_reladdr.msf.minute=(current_drive->SubQ_run_trk>>16)&0x00FF;
+			SC.cdsc_reladdr.msf.second=(current_drive->SubQ_run_trk>>8)&0x00FF;
+			SC.cdsc_reladdr.msf.frame=current_drive->SubQ_run_trk&0x00FF;
 		}
 		memcpy((void *) arg, &SC, sizeof(struct cdrom_subchnl));
 		msg(DBG_IOS,"CDROMSUBCHNL: %1X %02X %08X %08X %02X %02X %06X %06X\n",
@@ -4786,11 +4782,11 @@
 	long offs;
 	
 	while ( (req->nr_sectors > 0) &&
-	       (req->sector/4 >= D_S[d].sbp_first_frame) &&
-	       (req->sector/4 <= D_S[d].sbp_last_frame) )
+	       (req->sector/4 >= current_drive->sbp_first_frame) &&
+	       (req->sector/4 <= current_drive->sbp_last_frame) )
 	{
-		offs = (req->sector - D_S[d].sbp_first_frame * 4) * 512;
-		memcpy(req->buffer, D_S[d].sbp_buf + offs, 512);
+		offs = (req->sector - current_drive->sbp_first_frame * 4) * 512;
+		memcpy(req->buffer, current_drive->sbp_buf + offs, 512);
 		req->nr_sectors--;
 		req->sector++;
 		req->buffer += 512;
@@ -4833,8 +4829,9 @@
 {
 	u_int block;
 	u_int nsect;
-	int i, status_tries, data_tries;
+	int status_tries, data_tries;
 	struct request *req;
+	struct sbpcd_drive *p;
 #ifdef DEBUG_GTL
 	static int xx_nr=0;
 	int xnr;
@@ -4873,9 +4870,8 @@
 		msg(DBG_INF, "bad cmd %d\n", req->cmd);
 		goto err_done;
 	}
-	i = minor(req->rq_dev);
-	if ( (i<0) || (i>=NR_SBPCD) || (D_S[i].drv_id==-1))
-	{
+	p = D_S + minor(req->rq_dev);
+	if (p->drv_id==-1) {
 		msg(DBG_INF, "do_request: bad device: %s\n",
 			kdevname(req->rq_dev));
 		goto err_done;
@@ -4885,9 +4881,10 @@
 	busy_data=1;
 #endif /* OLD_BUSY */
 	
-	if (D_S[i].audio_state==audio_playing) goto err_done;
-	if (d!=i) switch_drive(i);
-	
+	if (p->audio_state==audio_playing) goto err_done;
+	if (p != current_drive)
+		switch_drive(p);
+
 	block = req->sector; /* always numbered as 512-byte-pieces */
 	nsect = req->nr_sectors; /* always counted as 512-byte-pieces */
 	
@@ -4939,7 +4936,7 @@
 		if (sbp_data(req) != 0)
 		{
 #if SAFE_MIXED
-			D_S[d].has_data=2; /* is really a data disk */
+			current_drive->has_data=2; /* is really a data disk */
 #endif /* SAFE_MIXED */ 
 #ifdef DEBUG_GTL
 			printk(" do_sbpcd_request[%do](%p:%ld+%ld) end 3, Time:%li\n",
@@ -4977,20 +4974,20 @@
 	int i;
 	int block;
 	
-	D_S[d].sbp_first_frame=D_S[d].sbp_last_frame=-1;      /* purge buffer */
-	D_S[d].sbp_current = 0;
+	current_drive->sbp_first_frame=current_drive->sbp_last_frame=-1;      /* purge buffer */
+	current_drive->sbp_current = 0;
 	block=req->sector/4;
-	if (block+D_S[d].sbp_bufsiz <= D_S[d].CDsize_frm)
-		D_S[d].sbp_read_frames = D_S[d].sbp_bufsiz;
+	if (block+current_drive->sbp_bufsiz <= current_drive->CDsize_frm)
+		current_drive->sbp_read_frames = current_drive->sbp_bufsiz;
 	else
 	{
-		D_S[d].sbp_read_frames=D_S[d].CDsize_frm-block;
+		current_drive->sbp_read_frames=current_drive->CDsize_frm-block;
 		/* avoid reading past end of data */
-		if (D_S[d].sbp_read_frames < 1)
+		if (current_drive->sbp_read_frames < 1)
 		{
 			msg(DBG_INF,"requested frame %d, CD size %d ???\n",
-			    block, D_S[d].CDsize_frm);
-			D_S[d].sbp_read_frames=1;
+			    block, current_drive->CDsize_frm);
+			current_drive->sbp_read_frames=1;
 		}
 	}
 	
@@ -5003,27 +5000,27 @@
 	    bin2bcdx(&drvcmd[1]);
 	    bin2bcdx(&drvcmd[2]);
 	    bin2bcdx(&drvcmd[3]);
-	    drvcmd[4]=D_S[d].sbp_read_frames>>8;
-	    drvcmd[5]=D_S[d].sbp_read_frames&0xff;
+	    drvcmd[4]=current_drive->sbp_read_frames>>8;
+	    drvcmd[5]=current_drive->sbp_read_frames&0xff;
 	    drvcmd[6]=0x02; /* flag "msf-bcd" */
 	}
 	else if (fam0L_drive)
 	{
 		flags_cmd_out |= f_lopsta | f_getsta | f_bit1;
-		if (D_S[d].xa_byte==0x20)
+		if (current_drive->xa_byte==0x20)
 		{
 			cmd_type=READ_M2;
 			drvcmd[0]=CMD0_READ_XA; /* "read XA frames", old drives */
 			drvcmd[1]=(block>>16)&0x0ff;
 			drvcmd[2]=(block>>8)&0x0ff;
 			drvcmd[3]=block&0x0ff;
-			drvcmd[4]=(D_S[d].sbp_read_frames>>8)&0x0ff;
-			drvcmd[5]=D_S[d].sbp_read_frames&0x0ff;
+			drvcmd[4]=(current_drive->sbp_read_frames>>8)&0x0ff;
+			drvcmd[5]=current_drive->sbp_read_frames&0x0ff;
 		}
 		else
 		{
 			drvcmd[0]=CMD0_READ; /* "read frames", old drives */
-			if (D_S[d].drv_type>=drv_201)
+			if (current_drive->drv_type>=drv_201)
 			{
 				lba2msf(block,&drvcmd[1]); /* msf-bcd format required */
 				bin2bcdx(&drvcmd[1]);
@@ -5036,24 +5033,24 @@
 				drvcmd[2]=(block>>8)&0x0ff;
 				drvcmd[3]=block&0x0ff;
 			}
-			drvcmd[4]=(D_S[d].sbp_read_frames>>8)&0x0ff;
-			drvcmd[5]=D_S[d].sbp_read_frames&0x0ff;
-			drvcmd[6]=(D_S[d].drv_type<drv_201)?0:2; /* flag "lba or msf-bcd format" */
+			drvcmd[4]=(current_drive->sbp_read_frames>>8)&0x0ff;
+			drvcmd[5]=current_drive->sbp_read_frames&0x0ff;
+			drvcmd[6]=(current_drive->drv_type<drv_201)?0:2; /* flag "lba or msf-bcd format" */
 		}
 	}
 	else if (fam1_drive)
 	{
 		drvcmd[0]=CMD1_READ;
 		lba2msf(block,&drvcmd[1]); /* msf-bin format required */
-		drvcmd[5]=(D_S[d].sbp_read_frames>>8)&0x0ff;
-		drvcmd[6]=D_S[d].sbp_read_frames&0x0ff;
+		drvcmd[5]=(current_drive->sbp_read_frames>>8)&0x0ff;
+		drvcmd[6]=current_drive->sbp_read_frames&0x0ff;
 	}
 	else if (fam2_drive)
 	{
 		drvcmd[0]=CMD2_READ;
 		lba2msf(block,&drvcmd[1]); /* msf-bin format required */
-		drvcmd[4]=(D_S[d].sbp_read_frames>>8)&0x0ff;
-		drvcmd[5]=D_S[d].sbp_read_frames&0x0ff;
+		drvcmd[4]=(current_drive->sbp_read_frames>>8)&0x0ff;
+		drvcmd[5]=current_drive->sbp_read_frames&0x0ff;
 		drvcmd[6]=0x02;
 	}
 	else if (famT_drive)
@@ -5063,8 +5060,8 @@
 		drvcmd[3]=(block>>16)&0x0ff;
 		drvcmd[4]=(block>>8)&0x0ff;
 		drvcmd[5]=block&0x0ff;
-		drvcmd[7]=(D_S[d].sbp_read_frames>>8)&0x0ff;
-		drvcmd[8]=D_S[d].sbp_read_frames&0x0ff;
+		drvcmd[7]=(current_drive->sbp_read_frames>>8)&0x0ff;
+		drvcmd[8]=current_drive->sbp_read_frames&0x0ff;
 	}
 	flags_cmd_out=f_putcmd;
 	response_count=0;
@@ -5075,7 +5072,7 @@
 /*==========================================================================*/
 /*
  *  Check the completion of the read-data command.  On success, read
- *  the D_S[d].sbp_bufsiz * 2048 bytes of data from the disk into buffer.
+ *  the current_drive->sbp_bufsiz * 2048 bytes of data from the disk into buffer.
  */
 static int sbp_data(struct request *req)
 {
@@ -5098,11 +5095,11 @@
 #if LONG_TIMING
 	max_latency=9*HZ;
 #else
-	if (D_S[d].f_multisession) max_latency=15*HZ;
+	if (current_drive->f_multisession) max_latency=15*HZ;
 	else max_latency=5*HZ;
 #endif
 	duration=jiffies;
-	for (frame=0;frame<D_S[d].sbp_read_frames&&!error_flag; frame++)
+	for (frame=0;frame<current_drive->sbp_read_frames&&!error_flag; frame++)
 	{
 		SBPCD_CLI;
 		
@@ -5112,7 +5109,7 @@
 		add_timer(&data_timer);
 		while (!timed_out_data) 
 		{
-			if (D_S[d].f_multisession) try=maxtim_data*4;
+			if (current_drive->f_multisession) try=maxtim_data*4;
 			else try=maxtim_data;
 			msg(DBG_000,"sbp_data: CDi_status loop: try=%d.\n",try);
 			for ( ; try!=0;try--)
@@ -5155,7 +5152,7 @@
 		}
 		if (j&s_not_data_ready)
 		{
-			if ((D_S[d].ored_ctl_adr&0x40)==0)
+			if ((current_drive->ored_ctl_adr&0x40)==0)
 				msg(DBG_INF, "CD contains no data tracks.\n");
 			else msg(DBG_INF, "sbp_data: DATA_READY timeout (%02X).\n", j);
 			error_flag++;
@@ -5164,7 +5161,7 @@
 		if (error_flag) break;
 
 		msg(DBG_000, "sbp_data: beginning to read.\n");
-		p = D_S[d].sbp_buf + frame *  CD_FRAMESIZE;
+		p = current_drive->sbp_buf + frame *  CD_FRAMESIZE;
 		if (sbpro_type==1) OUT(CDo_sel_i_d,1);
 		if (cmd_type==READ_M2) {
                         if (do_16bit) insw(CDi_data, xa_head_buf, CD_XA_HEAD>>1);
@@ -5176,7 +5173,7 @@
                         if (do_16bit) insw(CDi_data, xa_tail_buf, CD_XA_TAIL>>1);
                         else insb(CDi_data, xa_tail_buf, CD_XA_TAIL);
 		}
-		D_S[d].sbp_current++;
+		current_drive->sbp_current++;
 		if (sbpro_type==1) OUT(CDo_sel_i_d,0);
 		if (cmd_type==READ_M2)
 		{
@@ -5255,9 +5252,9 @@
 						sbp_sleep(1);
 					}
 					while (j<0);
-					D_S[d].error_state=infobuf[2];
-					D_S[d].b3=infobuf[3];
-					D_S[d].b4=infobuf[4];
+					current_drive->error_state=infobuf[2];
+					current_drive->b3=infobuf[3];
+					current_drive->b4=infobuf[4];
 				}
 				break;
 			}
@@ -5327,7 +5324,7 @@
 #endif
 			if (i<0)
 			{
-				msg(DBG_INF,"bad cc_ReadStatus after read: %02X\n", D_S[d].status_bits);
+				msg(DBG_INF,"bad cc_ReadStatus after read: %02X\n", current_drive->status_bits);
 				return (0);
 			}
 		}
@@ -5341,14 +5338,14 @@
 	if (fatal_err)
 	{
 		fatal_err=0;
-		D_S[d].sbp_first_frame=D_S[d].sbp_last_frame=-1;      /* purge buffer */
-		D_S[d].sbp_current = 0;
+		current_drive->sbp_first_frame=current_drive->sbp_last_frame=-1;      /* purge buffer */
+		current_drive->sbp_current = 0;
 		msg(DBG_INF,"sbp_data: fatal_err - retrying.\n");
 		return (0);
 	}
 	
-	D_S[d].sbp_first_frame = req -> sector / 4;
-	D_S[d].sbp_last_frame = D_S[d].sbp_first_frame + D_S[d].sbp_read_frames - 1;
+	current_drive->sbp_first_frame = req -> sector / 4;
+	current_drive->sbp_last_frame = current_drive->sbp_first_frame + current_drive->sbp_read_frames - 1;
 	sbp_transfer(req);
 	return (1);
 }
@@ -5368,34 +5365,33 @@
  */
 static int sbpcd_open(struct cdrom_device_info *cdi, int purpose)
 {
-	int i;
-
-	i = minor(cdi->dev);
+	struct sbpcd_drive *p = cdi->handle;
 
 	down(&ioctl_read_sem);
-	switch_drive(i);
+	switch_drive(p);
 
 	/*
 	 * try to keep an "open" counter here and lock the door if 0->1.
 	 */
 	msg(DBG_LCK,"open_count: %d -> %d\n",
-	    D_S[d].open_count,D_S[d].open_count+1);
-	if (++D_S[d].open_count<=1)
+	    current_drive->open_count,current_drive->open_count+1);
+	if (++current_drive->open_count<=1)
 	{
+		int i;
 		i=LockDoor();
-		D_S[d].open_count=1;
+		current_drive->open_count=1;
 		if (famT_drive)	msg(DBG_TEA,"sbpcd_open: before i=DiskInfo();.\n");
 		i=DiskInfo();
 		if (famT_drive)	msg(DBG_TEA,"sbpcd_open: after i=DiskInfo();.\n");
-		if ((D_S[d].ored_ctl_adr&0x40)==0)
+		if ((current_drive->ored_ctl_adr&0x40)==0)
 		{		
 			msg(DBG_INF,"CD contains no data tracks.\n");
 #if SAFE_MIXED
-			D_S[d].has_data=0;
+			current_drive->has_data=0;
 #endif /* SAFE_MIXED */
 		}
 #if SAFE_MIXED
-		else if (D_S[d].has_data<1) D_S[d].has_data=1;
+		else if (current_drive->has_data<1) current_drive->has_data=1;
 #endif /* SAFE_MIXED */ 
 	}
 	if (!st_spinning) cc_SpinUp();
@@ -5407,32 +5403,30 @@
  */
 static void sbpcd_release(struct cdrom_device_info * cdi)
 {
-	int i;
+	struct sbpcd_drive *p = cdi->handle;
 
-	i = minor(cdi->dev);
-	if ((i<0) || (i>=NR_SBPCD) || (D_S[i].drv_id==-1))
-	{
-		msg(DBG_INF, "release: bad device: %04X\n", cdi->dev);
-		return ;
+	if (p->drv_id==-1) {
+		msg(DBG_INF, "release: bad device: %s\n", cdi->name);
+		return;
 	}
 	down(&ioctl_read_sem);
-	switch_drive(i);
+	switch_drive(p);
 	/*
 	 * try to keep an "open" counter here and unlock the door if 1->0.
 	 */
 	msg(DBG_LCK,"open_count: %d -> %d\n",
-	    D_S[d].open_count,D_S[d].open_count-1);
-	if (D_S[d].open_count>-2) /* CDROMEJECT may have been done */
+	    p->open_count,p->open_count-1);
+	if (p->open_count>-2) /* CDROMEJECT may have been done */
 	{
-		if (--D_S[d].open_count<=0) 
+		if (--p->open_count<=0) 
 		{
-			D_S[d].sbp_first_frame=D_S[d].sbp_last_frame=-1;
-			if (D_S[d].audio_state!=audio_playing)
-				if (D_S[d].f_eject) cc_SpinDown();
-			D_S[d].diskstate_flags &= ~cd_size_bit;
-			D_S[d].open_count=0; 
+			p->sbp_first_frame=p->sbp_last_frame=-1;
+			if (p->audio_state!=audio_playing)
+				if (p->f_eject) cc_SpinDown();
+			p->diskstate_flags &= ~cd_size_bit;
+			p->open_count=0; 
 #if SAFE_MIXED
-			D_S[d].has_data=0;
+			p->has_data=0;
 #endif /* SAFE_MIXED */ 
 		}
 	}
@@ -5463,13 +5457,6 @@
 	n_minors:		1,
 };
 
-static struct cdrom_device_info sbpcd_info = {
-	ops:			&sbpcd_dops,
-	speed:			2,
-	capacity:		1,
-	name:			"sbpcd",
-};
-
 /*==========================================================================*/
 /*
  * accept "kernel command line" parameters 
@@ -5708,21 +5695,23 @@
 	
 	for (j=0;j<NR_SBPCD;j++)
 	{
-		if (D_S[j].drv_id==-1) continue;
-		switch_drive(j);
+		struct sbpcd_drive *p = D_S + j;
+		if (p->drv_id==-1)
+			continue;
+		switch_drive(p);
 #if 1
 		if (!famL_drive) cc_DriveReset();
 #endif
 		if (!st_spinning) cc_SpinUp();
-		D_S[j].sbp_first_frame = -1;  /* First frame in buffer */
-		D_S[j].sbp_last_frame = -1;   /* Last frame in buffer  */
-		D_S[j].sbp_read_frames = 0;   /* Number of frames being read to buffer */
-		D_S[j].sbp_current = 0;       /* Frame being currently read */
-		D_S[j].CD_changed=1;
-		D_S[j].frame_size=CD_FRAMESIZE;
-		D_S[j].f_eject=0;
+		p->sbp_first_frame = -1;  /* First frame in buffer */
+		p->sbp_last_frame = -1;   /* Last frame in buffer  */
+		p->sbp_read_frames = 0;   /* Number of frames being read to buffer */
+		p->sbp_current = 0;       /* Frame being currently read */
+		p->CD_changed=1;
+		p->frame_size=CD_FRAMESIZE;
+		p->f_eject=0;
 #if EJECT
-		if (!fam0_drive) D_S[j].f_eject=1;
+		if (!fam0_drive) p->f_eject=1;
 #endif /* EJECT */ 
 		cc_ReadStatus();
 		i=ResponseStatus();  /* returns orig. status or p_busy_new */
@@ -5742,8 +5731,8 @@
 		}
 		msg(DBG_INI,"init: first GetStatus: %d\n",i);
 		msg(DBG_LCS,"init: first GetStatus: error_byte=%d\n",
-		    D_S[j].error_byte);
-		if (D_S[j].error_byte==aud_12)
+		    p->error_byte);
+		if (p->error_byte==aud_12)
 		{
 			timeout=jiffies+2*HZ;
 			do
@@ -5752,14 +5741,14 @@
 				msg(DBG_INI,"init: second GetStatus: %02X\n",i);
 				msg(DBG_LCS,
 				    "init: second GetStatus: error_byte=%d\n",
-				    D_S[j].error_byte);
+				    p->error_byte);
 				if (i<0) break;
 				if (!st_caddy_in) break;
 				}
 			while ((!st_diskok)||time_after(jiffies, timeout));
 		}
 		i=SetSpeed();
-		if (i>=0) D_S[j].CD_changed=1;
+		if (i>=0) p->CD_changed=1;
 	}
 
 	/*
@@ -5788,24 +5777,26 @@
 	for (j=0;j<NR_SBPCD;j++)
 	{
 		struct cdrom_device_info * sbpcd_infop;
+		struct sbpcd_drive *p = D_S + j;
 
-		if (D_S[j].drv_id==-1) continue;
-		switch_drive(j);
+		if (p->drv_id==-1) continue;
+		switch_drive(p);
 #if SAFE_MIXED
-		D_S[j].has_data=0;
+		p->has_data=0;
 #endif /* SAFE_MIXED */ 
 		/*
 		 * allocate memory for the frame buffers
 		 */
-		D_S[j].aud_buf=NULL;
-		D_S[j].sbp_audsiz=0;
-		D_S[j].sbp_bufsiz=buffers;
-		if (D_S[j].drv_type&drv_fam1)
-			if (READ_AUDIO>0) D_S[j].sbp_audsiz=READ_AUDIO;
-		D_S[j].sbp_buf=(u_char *) vmalloc(D_S[j].sbp_bufsiz*CD_FRAMESIZE);
-		if (D_S[j].sbp_buf==NULL)
-		{
-			msg(DBG_INF,"data buffer (%d frames) not available.\n",D_S[j].sbp_bufsiz);
+		p->aud_buf=NULL;
+		p->sbp_audsiz=0;
+		p->sbp_bufsiz=buffers;
+		if (p->drv_type&drv_fam1)
+			if (READ_AUDIO>0)
+				p->sbp_audsiz = READ_AUDIO;
+		p->sbp_buf=(u_char *) vmalloc(buffers*CD_FRAMESIZE);
+		if (!p->sbp_buf) {
+			msg(DBG_INF,"data buffer (%d frames) not available.\n",
+				buffers);
 			if ((unregister_blkdev(MAJOR_NR, major_name) == -EINVAL))
 			{
 				printk("Can't unregister %s\n", major_name);
@@ -5817,11 +5808,11 @@
 #ifdef MODULE
 		msg(DBG_INF,"data buffer size: %d frames.\n",buffers);
 #endif /* MODULE */
-		if (D_S[j].sbp_audsiz>0)
+		if (p->sbp_audsiz>0)
 		{
-			D_S[j].aud_buf=(u_char *) vmalloc(D_S[j].sbp_audsiz*CD_FRAMESIZE_RAW);
-			if (D_S[j].aud_buf==NULL) msg(DBG_INF,"audio buffer (%d frames) not available.\n",D_S[j].sbp_audsiz);
-			else msg(DBG_INF,"audio buffer size: %d frames.\n",D_S[j].sbp_audsiz);
+			p->aud_buf=(u_char *) vmalloc(p->sbp_audsiz*CD_FRAMESIZE_RAW);
+			if (p->aud_buf==NULL) msg(DBG_INF,"audio buffer (%d frames) not available.\n",p->sbp_audsiz);
+			else msg(DBG_INF,"audio buffer size: %d frames.\n",p->sbp_audsiz);
 		}
                 sbpcd_infop = vmalloc(sizeof (struct cdrom_device_info));
 		if (sbpcd_infop == NULL)
@@ -5830,12 +5821,15 @@
 			blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
                         return -ENOMEM;
 		}
-		D_S[j].sbpcd_infop = sbpcd_infop;
-		memcpy (sbpcd_infop, &sbpcd_info, sizeof(struct cdrom_device_info));
+		memset(sbpcd_infop, 0, sizeof(struct cdrom_device_info));
+		sbpcd_infop->ops = &sbpcd_dops;
+		sbpcd_infop->speed = 2;
+		sbpcd_infop->capacity = 1;
+		sprintf(sbpcd_infop->name, "sbpcd%d", j);
 		sbpcd_infop->dev = mk_kdev(MAJOR_NR, j);
-		strncpy(sbpcd_infop->name,major_name, sizeof(sbpcd_infop->name)); 
-
-		sprintf (nbuff, "c0t%d/cd", D_S[j].drv_id);
+		sbpcd_infop->handle = p;
+		p->sbpcd_infop = sbpcd_infop;
+		sprintf(nbuff, "c0t%d/cd", p->drv_id);
 		sbpcd_infop->de =
 		    devfs_register (devfs_handle, nbuff, DEVFS_FL_DEFAULT,
 				    MAJOR_NR, j, S_IFBLK | S_IRUGO | S_IWUGO,
@@ -5886,39 +5880,27 @@
 
 
 #endif /* MODULE */
-/*==========================================================================*/
-/*
- * Check if the media has changed in the CD-ROM drive.
- * used externally (isofs/inode.c, fs/buffer.c)
- */
-static int sbpcd_chk_disk_change(kdev_t full_dev)
+static int sbpcd_media_changed(struct cdrom_device_info *cdi, int disc_nr)
 {
-	int i;
-	
-	i=minor(full_dev);
-	msg(DBG_CHK,"media_check (%d) called\n", i);
+	struct sbpcd_drive *p = cdi->handle;
+	msg(DBG_CHK,"media_check (%s) called\n", cdi->name);
 	
-	if (D_S[i].CD_changed==0xFF)
+	if (p->CD_changed==0xFF)
         {
-                D_S[i].CD_changed=0;
-                msg(DBG_CHK,"medium changed (drive %d)\n", i);
+                p->CD_changed=0;
+                msg(DBG_CHK,"medium changed (drive %s)\n", cdi->name);
 		/* BUG! Should invalidate buffers! --AJK */
 		/* Why should it do the above at all?! --mdcki */
-		D_S[d].diskstate_flags &= ~toc_bit;
-		D_S[d].diskstate_flags &= ~cd_size_bit;
+		current_drive->diskstate_flags &= ~toc_bit;
+		current_drive->diskstate_flags &= ~cd_size_bit;
 #if SAFE_MIXED
-		D_S[d].has_data=0;
+		current_drive->has_data=0;
 #endif /* SAFE_MIXED */ 
 
                 return (1);
         }
         else
                 return (0);
-}
-
-static int sbpcd_media_changed( struct cdrom_device_info *cdi, int disc_nr)
-{
-   return sbpcd_chk_disk_change(cdi->dev);
 }
 
 MODULE_LICENSE("GPL");
diff -Nru a/drivers/cdrom/sbpcd.h b/drivers/cdrom/sbpcd.h
--- a/drivers/cdrom/sbpcd.h	Mon Sep  9 10:35:59 2002
+++ b/drivers/cdrom/sbpcd.h	Mon Sep  9 10:35:59 2002
@@ -242,12 +242,12 @@
 /*
  * disk states (bits of diskstate_flags):
  */
-#define upc_valid		(D_S[d].diskstate_flags&upc_bit)
-#define volume_valid		(D_S[d].diskstate_flags&volume_bit)
-#define toc_valid		(D_S[d].diskstate_flags&toc_bit)
-#define cd_size_valid		(D_S[d].diskstate_flags&cd_size_bit)
-#define subq_valid		(D_S[d].diskstate_flags&subq_bit)
-#define frame_size_valid	(D_S[d].diskstate_flags&frame_size_bit)
+#define upc_valid		(current_drive->diskstate_flags&upc_bit)
+#define volume_valid		(current_drive->diskstate_flags&volume_bit)
+#define toc_valid		(current_drive->diskstate_flags&toc_bit)
+#define cd_size_valid		(current_drive->diskstate_flags&cd_size_bit)
+#define subq_valid		(current_drive->diskstate_flags&subq_bit)
+#define frame_size_valid	(current_drive->diskstate_flags&frame_size_bit)
 
 /*
  * the status_bits variable
@@ -324,13 +324,13 @@
 /*
  * used drive states:
  */
-#define st_door_closed	(D_S[d].status_bits&p_door_closed)
-#define st_caddy_in	(D_S[d].status_bits&p_caddy_in)
-#define st_spinning	(D_S[d].status_bits&p_spinning)
-#define st_check	(D_S[d].status_bits&p_check)
-#define st_busy		(D_S[d].status_bits&p_busy_new)
-#define st_door_locked	(D_S[d].status_bits&p_door_locked)
-#define st_diskok	(D_S[d].status_bits&p_disk_ok)
+#define st_door_closed	(current_drive->status_bits&p_door_closed)
+#define st_caddy_in	(current_drive->status_bits&p_caddy_in)
+#define st_spinning	(current_drive->status_bits&p_spinning)
+#define st_check	(current_drive->status_bits&p_check)
+#define st_busy		(current_drive->status_bits&p_busy_new)
+#define st_door_locked	(current_drive->status_bits&p_door_locked)
+#define st_diskok	(current_drive->status_bits&p_disk_ok)
 
 /*
  * bits of the CDi_status register:
@@ -372,22 +372,22 @@
 #define drv_famV	0x2000		/* ECS-AT (vertos-100) family */
 #define drv_at		(drv_famV+0x01)	/* ECS-AT, firmware "1.00" */
 
-#define fam0_drive	(D_S[d].drv_type&drv_fam0)
-#define famL_drive	(D_S[d].drv_type&drv_famL)
-#define famV_drive	(D_S[d].drv_type&drv_famV)
-#define fam1_drive	(D_S[d].drv_type&drv_fam1)
-#define fam2_drive	(D_S[d].drv_type&drv_fam2)
-#define famT_drive	(D_S[d].drv_type&drv_famT)
-#define fam0L_drive	(D_S[d].drv_type&(drv_fam0|drv_famL))
-#define fam0V_drive	(D_S[d].drv_type&(drv_fam0|drv_famV))
-#define famLV_drive	(D_S[d].drv_type&(drv_famL|drv_famV))
-#define fam0LV_drive	(D_S[d].drv_type&(drv_fam0|drv_famL|drv_famV))
-#define fam1L_drive	(D_S[d].drv_type&(drv_fam1|drv_famL))
-#define fam1V_drive	(D_S[d].drv_type&(drv_fam1|drv_famV))
-#define fam1LV_drive	(D_S[d].drv_type&(drv_fam1|drv_famL|drv_famV))
-#define fam01_drive	(D_S[d].drv_type&(drv_fam0|drv_fam1))
-#define fam12_drive	(D_S[d].drv_type&(drv_fam1|drv_fam2))
-#define fam2T_drive	(D_S[d].drv_type&(drv_fam2|drv_famT))
+#define fam0_drive	(current_drive->drv_type&drv_fam0)
+#define famL_drive	(current_drive->drv_type&drv_famL)
+#define famV_drive	(current_drive->drv_type&drv_famV)
+#define fam1_drive	(current_drive->drv_type&drv_fam1)
+#define fam2_drive	(current_drive->drv_type&drv_fam2)
+#define famT_drive	(current_drive->drv_type&drv_famT)
+#define fam0L_drive	(current_drive->drv_type&(drv_fam0|drv_famL))
+#define fam0V_drive	(current_drive->drv_type&(drv_fam0|drv_famV))
+#define famLV_drive	(current_drive->drv_type&(drv_famL|drv_famV))
+#define fam0LV_drive	(current_drive->drv_type&(drv_fam0|drv_famL|drv_famV))
+#define fam1L_drive	(current_drive->drv_type&(drv_fam1|drv_famL))
+#define fam1V_drive	(current_drive->drv_type&(drv_fam1|drv_famV))
+#define fam1LV_drive	(current_drive->drv_type&(drv_fam1|drv_famL|drv_famV))
+#define fam01_drive	(current_drive->drv_type&(drv_fam0|drv_fam1))
+#define fam12_drive	(current_drive->drv_type&(drv_fam1|drv_fam2))
+#define fam2T_drive	(current_drive->drv_type&(drv_fam2|drv_famT))
 
 /*
  * audio states:
diff -Nru a/drivers/char/Makefile b/drivers/char/Makefile
--- a/drivers/char/Makefile	Mon Sep  9 10:36:17 2002
+++ b/drivers/char/Makefile	Mon Sep  9 10:36:17 2002
@@ -12,10 +12,9 @@
 # All of the (potential) objects that export symbols.
 # This list comes from 'grep -l EXPORT_SYMBOL *.[hc]'.
 
-export-objs     :=	busmouse.o console.o keyboard.o sysrq.o \
-			misc.o pty.o random.o selection.o \
-			sonypi.o tty_io.o tty_ioctl.o generic_serial.o rtc.o \
-			ip2main.o nvram.o
+export-objs     :=	busmouse.o console.o generic_serial.o ip2main.o \
+			ite_gpio.o misc.o nvram.o pty.o random.o rtc.o \
+			selection.o sonypi.o sysrq.o tty_io.o tty_ioctl.o
 
 obj-$(CONFIG_VT) += vt.o vc_screen.o consolemap.o consolemap_deftbl.o selection.o keyboard.o
 obj-$(CONFIG_HW_CONSOLE) += console.o defkeymap.o
diff -Nru a/drivers/char/agp/agp.c b/drivers/char/agp/agp.c
--- a/drivers/char/agp/agp.c	Mon Sep  9 10:36:01 2002
+++ b/drivers/char/agp/agp.c	Mon Sep  9 10:36:01 2002
@@ -751,7 +751,7 @@
 
 #ifdef CONFIG_AGP_ALI
 	{
-		.device_id	= PCI_DEVICE_ID_AL_M1541_0,
+		.device_id	= PCI_DEVICE_ID_AL_M1541,
 		.vendor_id	= PCI_VENDOR_ID_AL,
 		.chipset	= ALI_M1541,
 		.vendor_name	= "Ali",
@@ -759,7 +759,7 @@
 		.chipset_setup	= ali_generic_setup,
 	},
 	{
-		.device_id	= PCI_DEVICE_ID_AL_M1621_0,
+		.device_id	= PCI_DEVICE_ID_AL_M1621,
 		.vendor_id	= PCI_VENDOR_ID_AL,
 		.chipset	= ALI_M1621,
 		.vendor_name	= "Ali",
@@ -767,7 +767,7 @@
 		.chipset_setup	= ali_generic_setup,
 	},
 	{
-		.device_id	= PCI_DEVICE_ID_AL_M1631_0,
+		.device_id	= PCI_DEVICE_ID_AL_M1631,
 		.vendor_id	= PCI_VENDOR_ID_AL,
 		.chipset	= ALI_M1631,
 		.vendor_name	= "Ali",
@@ -775,7 +775,7 @@
 		.chipset_setup	= ali_generic_setup,
 	},
 	{
-		.device_id	= PCI_DEVICE_ID_AL_M1632_0,
+		.device_id	= PCI_DEVICE_ID_AL_M1632,
 		.vendor_id	= PCI_VENDOR_ID_AL,
 		.chipset	= ALI_M1632,
 		.vendor_name	= "Ali",
@@ -783,7 +783,7 @@
 		.chipset_setup	= ali_generic_setup,
 	},
 	{
-		.device_id	= PCI_DEVICE_ID_AL_M1641_0,
+		.device_id	= PCI_DEVICE_ID_AL_M1641,
 		.vendor_id	= PCI_VENDOR_ID_AL,
 		.chipset	= ALI_M1641,
 		.vendor_name	= "Ali",
@@ -791,7 +791,7 @@
 		.chipset_setup	= ali_generic_setup,
 	},
 	{
-		.device_id	= PCI_DEVICE_ID_AL_M1644_0,
+		.device_id	= PCI_DEVICE_ID_AL_M1644,
 		.vendor_id	= PCI_VENDOR_ID_AL,
 		.chipset	= ALI_M1644,
 		.vendor_name	= "Ali",
@@ -799,7 +799,7 @@
 		.chipset_setup	= ali_generic_setup,
 	},
 	{
-		.device_id	= PCI_DEVICE_ID_AL_M1647_0,
+		.device_id	= PCI_DEVICE_ID_AL_M1647,
 		.vendor_id	= PCI_VENDOR_ID_AL,
 		.chipset	= ALI_M1647,
 		.vendor_name	= "Ali",
@@ -807,7 +807,7 @@
 		.chipset_setup	= ali_generic_setup,
 	},
 	{
-		.device_id	= PCI_DEVICE_ID_AL_M1651_0,
+		.device_id	= PCI_DEVICE_ID_AL_M1651,
 		.vendor_id	= PCI_VENDOR_ID_AL,
 		.chipset	= ALI_M1651,
 		.vendor_name	= "Ali",
@@ -826,7 +826,7 @@
 
 #ifdef CONFIG_AGP_AMD
 	{
-		.device_id	= PCI_DEVICE_ID_AMD_IRONGATE_0,
+		.device_id	= PCI_DEVICE_ID_AMD_FE_GATE_7006,
 		.vendor_id	= PCI_VENDOR_ID_AMD,
 		.chipset	= AMD_IRONGATE,
 		.vendor_name	= "AMD",
@@ -834,7 +834,7 @@
 		.chipset_setup	= amd_irongate_setup,
 	},
 	{
-		.device_id	= PCI_DEVICE_ID_AMD_761_0,
+		.device_id	= PCI_DEVICE_ID_AMD_FE_GATE_700E,
 		.vendor_id	= PCI_VENDOR_ID_AMD,
 		.chipset	= AMD_761,
 		.vendor_name	= "AMD",
@@ -842,7 +842,7 @@
 		.chipset_setup	= amd_irongate_setup,
 	},
 	{
-		.device_id	= PCI_DEVICE_ID_AMD_762_0,
+		.device_id	= PCI_DEVICE_ID_AMD_FE_GATE_700C,
 		.vendor_id	= PCI_VENDOR_ID_AMD,
 		.chipset	= AMD_762,
 		.vendor_name	= "AMD",
@@ -885,7 +885,7 @@
 		.chipset_setup	= intel_generic_setup
 	},
 	{
-		.device_id	= PCI_DEVICE_ID_INTEL_815_0,
+		.device_id	= PCI_DEVICE_ID_INTEL_82815_MC,
 		.vendor_id	= PCI_VENDOR_ID_INTEL,
 		.chipset	= INTEL_I815,
 		.vendor_name	= "Intel",
@@ -893,7 +893,7 @@
 		.chipset_setup	= intel_815_setup
 	},
 	{
-		.device_id	= PCI_DEVICE_ID_INTEL_820_0,
+		.device_id	= PCI_DEVICE_ID_INTEL_82820_HB,
 		.vendor_id	= PCI_VENDOR_ID_INTEL,
 		.chipset	= INTEL_I820,
 		.vendor_name	= "Intel",
@@ -901,7 +901,7 @@
 		.chipset_setup	= intel_820_setup
 	},
 	{
-		.device_id	= PCI_DEVICE_ID_INTEL_820_UP_0,
+		.device_id	= PCI_DEVICE_ID_INTEL_82820_UP_HB,
 		.vendor_id	= PCI_VENDOR_ID_INTEL,
 		.chipset	= INTEL_I820,
 		.vendor_name	= "Intel",
@@ -909,7 +909,7 @@
 		.chipset_setup	= intel_820_setup
 	},
 	{
-		.device_id	= PCI_DEVICE_ID_INTEL_830_M_0,
+		.device_id	= PCI_DEVICE_ID_INTEL_82830_HB,
 		.vendor_id	= PCI_VENDOR_ID_INTEL,
 		.chipset	= INTEL_I830_M,
 		.vendor_name	= "Intel",
@@ -917,7 +917,7 @@
 		.chipset_setup	= intel_830mp_setup
 	},
 	{
-		.device_id	= PCI_DEVICE_ID_INTEL_845_G_0,
+		.device_id	= PCI_DEVICE_ID_INTEL_82845G_HB,
 		.vendor_id	= PCI_VENDOR_ID_INTEL,
 		.chipset	= INTEL_I845_G,
 		.vendor_name	= "Intel",
@@ -925,7 +925,7 @@
 		.chipset_setup	= intel_830mp_setup
 	},
 	{
-		.device_id	= PCI_DEVICE_ID_INTEL_840_0,
+		.device_id	= PCI_DEVICE_ID_INTEL_82840_HB,
 		.vendor_id	= PCI_VENDOR_ID_INTEL,
 		.chipset	= INTEL_I840,
 		.vendor_name	= "Intel",
@@ -933,7 +933,7 @@
 		.chipset_setup	= intel_840_setup
 	},
 	{
-		.device_id	= PCI_DEVICE_ID_INTEL_845_0,
+		.device_id	= PCI_DEVICE_ID_INTEL_82845_HB,
 		.vendor_id	= PCI_VENDOR_ID_INTEL,
 		.chipset	= INTEL_I845,
 		.vendor_name	= "Intel",
@@ -941,7 +941,7 @@
 		.chipset_setup	= intel_845_setup
 	},
 	{
-		.device_id	= PCI_DEVICE_ID_INTEL_850_0,
+		.device_id	= PCI_DEVICE_ID_INTEL_82850_HB,
 		.vendor_id	= PCI_VENDOR_ID_INTEL,
 		.chipset	= INTEL_I850,
 		.vendor_name	= "Intel",
@@ -949,7 +949,7 @@
 		.chipset_setup	= intel_850_setup
 	},
 	{
-		.device_id	= PCI_DEVICE_ID_INTEL_860_0,
+		.device_id	= PCI_DEVICE_ID_INTEL_82860_HB,
 		.vendor_id	= PCI_VENDOR_ID_INTEL,
 		.chipset	= INTEL_I860,
 		.vendor_name	= "Intel",
@@ -1092,7 +1092,7 @@
 		.chipset_setup	= via_generic_setup
 	},
 	{
-		.device_id	= PCI_DEVICE_ID_VIA_82C691_0,
+		.device_id	= PCI_DEVICE_ID_VIA_82C691,
 		.vendor_id	= PCI_VENDOR_ID_VIA,
 		.chipset	= VIA_APOLLO_PRO,
 		.vendor_name	= "Via",
@@ -1166,7 +1166,7 @@
 	       (agp_bridge_info[i].vendor_id == pdev->vendor)) {
 		if (pdev->device == agp_bridge_info[i].device_id) {
 #ifdef CONFIG_AGP_ALI
-			if (pdev->device == PCI_DEVICE_ID_AL_M1621_0) {
+			if (pdev->device == PCI_DEVICE_ID_AL_M1621) {
 				u8 hidden_1621_id;
 
 				pci_read_config_byte(pdev, 0xFB, &hidden_1621_id);
@@ -1237,9 +1237,9 @@
 		struct pci_dev *i810_dev;
 
 		switch (dev->device) {
-		case PCI_DEVICE_ID_INTEL_810_0:
+		case PCI_DEVICE_ID_INTEL_82810_MC1:
 			i810_dev = pci_find_device(PCI_VENDOR_ID_INTEL,
-					       PCI_DEVICE_ID_INTEL_810_1,
+					       PCI_DEVICE_ID_INTEL_82810_IG1,
 						   NULL);
 			if (i810_dev == NULL) {
 				printk(KERN_ERR PFX "Detected an Intel i810,"
@@ -1252,9 +1252,9 @@
 			agp_bridge.type = INTEL_I810;
 			return intel_i810_setup (i810_dev);
 
-		case PCI_DEVICE_ID_INTEL_810_DC100_0:
+		case PCI_DEVICE_ID_INTEL_82810_MC3:
 			i810_dev = pci_find_device(PCI_VENDOR_ID_INTEL,
-					 PCI_DEVICE_ID_INTEL_810_DC100_1,
+					 PCI_DEVICE_ID_INTEL_82810_IG3,
 						   NULL);
 			if (i810_dev == NULL) {
 				printk(KERN_ERR PFX "Detected an Intel i810 "
@@ -1267,9 +1267,9 @@
 			agp_bridge.type = INTEL_I810;
 			return intel_i810_setup(i810_dev);
 
-		case PCI_DEVICE_ID_INTEL_810_E_0:
+		case PCI_DEVICE_ID_INTEL_82810E_MC:
 			i810_dev = pci_find_device(PCI_VENDOR_ID_INTEL,
-					     PCI_DEVICE_ID_INTEL_810_E_1,
+					     PCI_DEVICE_ID_INTEL_82810E_IG,
 						   NULL);
 			if (i810_dev == NULL) {
 				printk(KERN_ERR PFX "Detected an Intel i810 E"
@@ -1282,14 +1282,14 @@
 			agp_bridge.type = INTEL_I810;
 			return intel_i810_setup(i810_dev);
 
-		 case PCI_DEVICE_ID_INTEL_815_0:
+		 case PCI_DEVICE_ID_INTEL_82815_MC:
 		   /* The i815 can operate either as an i810 style
 		    * integrated device, or as an AGP4X motherboard.
 		    *
 		    * This only addresses the first mode:
 		    */
 			i810_dev = pci_find_device(PCI_VENDOR_ID_INTEL,
-						   PCI_DEVICE_ID_INTEL_815_1,
+						PCI_DEVICE_ID_INTEL_82815_CGC,
 						   NULL);
 			if (i810_dev == NULL) {
 				printk(KERN_ERR PFX "agpgart: Detected an "
@@ -1303,12 +1303,12 @@
 			agp_bridge.type = INTEL_I810;
 			return intel_i810_setup(i810_dev);
 
-		case PCI_DEVICE_ID_INTEL_845_G_0:
+		case PCI_DEVICE_ID_INTEL_82845G_HB:
 			i810_dev = pci_find_device(PCI_VENDOR_ID_INTEL,
-					PCI_DEVICE_ID_INTEL_845_G_1, NULL);
+					PCI_DEVICE_ID_INTEL_82845G_IG, NULL);
 			if(i810_dev && PCI_FUNC(i810_dev->devfn) != 0) {
 				i810_dev = pci_find_device(PCI_VENDOR_ID_INTEL,
-					PCI_DEVICE_ID_INTEL_845_G_1, i810_dev);
+					PCI_DEVICE_ID_INTEL_82845G_IG, i810_dev);
 			}
 
 			if (i810_dev == NULL) {
@@ -1325,13 +1325,13 @@
 			agp_bridge.type = INTEL_I810;
 			return intel_i830_setup(i810_dev);
 		   
-		case PCI_DEVICE_ID_INTEL_830_M_0:
+		case PCI_DEVICE_ID_INTEL_82830_HB:
 			i810_dev = pci_find_device(PCI_VENDOR_ID_INTEL,
-						   PCI_DEVICE_ID_INTEL_830_M_1,
+						   PCI_DEVICE_ID_INTEL_82830_CGC,
 						   NULL);
 			if(i810_dev && PCI_FUNC(i810_dev->devfn) != 0) {
 				i810_dev = pci_find_device(PCI_VENDOR_ID_INTEL,
-							   PCI_DEVICE_ID_INTEL_830_M_1,
+							   PCI_DEVICE_ID_INTEL_82830_CGC,
 							   i810_dev);
 			}
 
diff -Nru a/drivers/char/agp/agp.h b/drivers/char/agp/agp.h
--- a/drivers/char/agp/agp.h	Mon Sep  9 10:36:11 2002
+++ b/drivers/char/agp/agp.h	Mon Sep  9 10:36:11 2002
@@ -215,118 +215,6 @@
 
 #define PGE_EMPTY(p)	(!(p) || (p) == (unsigned long) agp_bridge.scratch_page)
 
-#ifndef PCI_DEVICE_ID_VIA_82C691_0
-#define PCI_DEVICE_ID_VIA_82C691_0	0x0691
-#endif
-#ifndef PCI_DEVICE_ID_VIA_8371_0
-#define PCI_DEVICE_ID_VIA_8371_0	0x0391
-#endif
-#ifndef PCI_DEVICE_ID_VIA_8363_0
-#define PCI_DEVICE_ID_VIA_8363_0	0x0305
-#endif
-#ifndef PCI_DEVICE_ID_VIA_82C694X_0
-#define PCI_DEVICE_ID_VIA_82C694X_0	0x0605
-#endif
-#ifndef PCI_DEVICE_ID_INTEL_810_0
-#define PCI_DEVICE_ID_INTEL_810_0	0x7120
-#endif
-#ifndef PCI_DEVICE_ID_INTEL_845_G_0
-#define PCI_DEVICE_ID_INTEL_845_G_0	0x2560
-#endif
-#ifndef PCI_DEVICE_ID_INTEL_845_G_1
-#define PCI_DEVICE_ID_INTEL_845_G_1	0x2562
-#endif
-#ifndef PCI_DEVICE_ID_INTEL_830_M_0
-#define PCI_DEVICE_ID_INTEL_830_M_0	0x3575
-#endif
-#ifndef PCI_DEVICE_ID_INTEL_830_M_1
-#define PCI_DEVICE_ID_INTEL_830_M_1	0x3577
-#endif
-#ifndef PCI_DEVICE_ID_INTEL_820_0
-#define PCI_DEVICE_ID_INTEL_820_0	0x2500
-#endif
-#ifndef PCI_DEVICE_ID_INTEL_820_UP_0
-#define PCI_DEVICE_ID_INTEL_820_UP_0	0x2501
-#endif
-#ifndef PCI_DEVICE_ID_INTEL_840_0
-#define PCI_DEVICE_ID_INTEL_840_0	0x1a21
-#endif
-#ifndef PCI_DEVICE_ID_INTEL_845_0
-#define PCI_DEVICE_ID_INTEL_845_0	0x1a30
-#endif
-#ifndef PCI_DEVICE_ID_INTEL_850_0
-#define PCI_DEVICE_ID_INTEL_850_0	0x2530
-#endif
-#ifndef PCI_DEVICE_ID_INTEL_860_0
-#define PCI_DEVICE_ID_INTEL_860_0	0x2531
-#endif
-#ifndef PCI_DEVICE_ID_INTEL_810_DC100_0
-#define PCI_DEVICE_ID_INTEL_810_DC100_0	0x7122
-#endif
-#ifndef PCI_DEVICE_ID_INTEL_810_E_0
-#define PCI_DEVICE_ID_INTEL_810_E_0	0x7124
-#endif
-#ifndef PCI_DEVICE_ID_INTEL_82443GX_0
-#define PCI_DEVICE_ID_INTEL_82443GX_0	0x71a0
-#endif
-#ifndef PCI_DEVICE_ID_INTEL_810_1
-#define PCI_DEVICE_ID_INTEL_810_1	0x7121
-#endif
-#ifndef PCI_DEVICE_ID_INTEL_810_DC100_1
-#define PCI_DEVICE_ID_INTEL_810_DC100_1	0x7123
-#endif
-#ifndef PCI_DEVICE_ID_INTEL_810_E_1
-#define PCI_DEVICE_ID_INTEL_810_E_1	0x7125
-#endif
-#ifndef PCI_DEVICE_ID_INTEL_815_0
-#define PCI_DEVICE_ID_INTEL_815_0	0x1130
-#endif
-#ifndef PCI_DEVICE_ID_INTEL_815_1
-#define PCI_DEVICE_ID_INTEL_815_1	0x1132
-#endif
-#ifndef PCI_DEVICE_ID_INTEL_82443GX_1
-#define PCI_DEVICE_ID_INTEL_82443GX_1	0x71a1
-#endif
-#ifndef PCI_DEVICE_ID_INTEL_460GX
-#define PCI_DEVICE_ID_INTEL_460GX	0x84ea
-#endif
-#ifndef PCI_DEVICE_ID_AMD_IRONGATE_0
-#define PCI_DEVICE_ID_AMD_IRONGATE_0	0x7006
-#endif
-#ifndef PCI_DEVICE_ID_AMD_761_0
-#define PCI_DEVICE_ID_AMD_761_0		0x700e
-#endif
-#ifndef PCI_DEVICE_ID_AMD_762_0
-#define PCI_DEVICE_ID_AMD_762_0		0x700C
-#endif
-#ifndef PCI_VENDOR_ID_AL
-#define PCI_VENDOR_ID_AL		0x10b9
-#endif
-#ifndef PCI_DEVICE_ID_AL_M1541_0
-#define PCI_DEVICE_ID_AL_M1541_0	0x1541
-#endif
-#ifndef PCI_DEVICE_ID_AL_M1621_0
-#define PCI_DEVICE_ID_AL_M1621_0	0x1621
-#endif
-#ifndef PCI_DEVICE_ID_AL_M1631_0
-#define PCI_DEVICE_ID_AL_M1631_0	0x1631
-#endif
-#ifndef PCI_DEVICE_ID_AL_M1632_0
-#define PCI_DEVICE_ID_AL_M1632_0	0x1632
-#endif
-#ifndef PCI_DEVICE_ID_AL_M1641_0
-#define PCI_DEVICE_ID_AL_M1641_0	0x1641
-#endif
-#ifndef PCI_DEVICE_ID_AL_M1644_0
-#define PCI_DEVICE_ID_AL_M1644_0	0x1644
-#endif
-#ifndef PCI_DEVICE_ID_AL_M1647_0
-#define PCI_DEVICE_ID_AL_M1647_0	0x1647
-#endif
-#ifndef PCI_DEVICE_ID_AL_M1651_0
-#define PCI_DEVICE_ID_AL_M1651_0	0x1651
-#endif
-
 /* intel register */
 #define INTEL_APBASE	0x10
 #define INTEL_APSIZE	0xb4
diff -Nru a/drivers/char/ftape/lowlevel/Makefile b/drivers/char/ftape/lowlevel/Makefile
--- a/drivers/char/ftape/lowlevel/Makefile	Mon Sep  9 10:36:01 2002
+++ b/drivers/char/ftape/lowlevel/Makefile	Mon Sep  9 10:36:01 2002
@@ -23,8 +23,6 @@
 #      driver for Linux.
 #
 
-export-objs := ftape_syms.o
-
 obj-$(CONFIG_FTAPE) += ftape.o
 
 ftape-objs := ftape-init.o fdc-io.o fdc-isr.o \
diff -Nru a/drivers/char/hvc_console.c b/drivers/char/hvc_console.c
--- a/drivers/char/hvc_console.c	Mon Sep  9 10:36:13 2002
+++ b/drivers/char/hvc_console.c	Mon Sep  9 10:36:13 2002
@@ -232,7 +232,6 @@
 	int i;
 
 	daemonize();
-	reparent_to_init();
 	strcpy(current->comm, "khvcd");
 	sigfillset(&current->blocked);
 
diff -Nru a/drivers/char/sonypi.h b/drivers/char/sonypi.h
--- a/drivers/char/sonypi.h	Mon Sep  9 10:35:55 2002
+++ b/drivers/char/sonypi.h	Mon Sep  9 10:35:56 2002
@@ -258,7 +258,7 @@
 	while (--n && (command)) \
 		udelay(1); \
 	if (!n && (verbose || !quiet)) \
-		printk(KERN_WARNING "sonypi command failed at " __FILE__ " : " __FUNCTION__ "(line %d)\n", __LINE__); \
+		printk(KERN_WARNING "sonypi command failed at %s : %s(line %d)\n", __FILE__, __FUNCTION__, __LINE__); \
 }
 
 #endif /* __KERNEL__ */
diff -Nru a/drivers/char/tty_io.c b/drivers/char/tty_io.c
--- a/drivers/char/tty_io.c	Mon Sep  9 10:36:11 2002
+++ b/drivers/char/tty_io.c	Mon Sep  9 10:36:11 2002
@@ -1458,15 +1458,9 @@
 	if (on) {
 		if (!waitqueue_active(&tty->read_wait))
 			tty->minimum_to_wake = 1;
-		if (filp->f_owner.pid == 0) {
-			retval = security_ops->file_set_fowner(filp);
-			if (retval)
-				return retval;
-
-			filp->f_owner.pid = (-tty->pgrp) ? : current->pid;
-			filp->f_owner.uid = current->uid;
-			filp->f_owner.euid = current->euid;
-		}
+		retval = f_setown(filp, (-tty->pgrp) ? : current->pid, 0);
+		if (retval)
+			return retval;
 	} else {
 		if (!tty->fasync && !waitqueue_active(&tty->read_wait))
 			tty->minimum_to_wake = N_TTY_BUF_SIZE;
diff -Nru a/drivers/hotplug/ibmphp_hpc.c b/drivers/hotplug/ibmphp_hpc.c
--- a/drivers/hotplug/ibmphp_hpc.c	Mon Sep  9 10:36:01 2002
+++ b/drivers/hotplug/ibmphp_hpc.c	Mon Sep  9 10:36:01 2002
@@ -1025,7 +1025,6 @@
 	debug ("%s - Entry\n", __FUNCTION__);
 	lock_kernel ();
 	daemonize ();
-	reparent_to_init ();
 
 	//  New name
 	strcpy (current->comm, "hpc_poll");
diff -Nru a/drivers/i2c/Makefile b/drivers/i2c/Makefile
--- a/drivers/i2c/Makefile	Mon Sep  9 10:35:52 2002
+++ b/drivers/i2c/Makefile	Mon Sep  9 10:35:52 2002
@@ -3,7 +3,7 @@
 #
 
 export-objs	:= i2c-core.o i2c-algo-bit.o i2c-algo-pcf.o \
-		   i2c-algo-ite.o i2c-proc.o
+		   i2c-algo-ite.o i2c-proc.o i2c-algo-ibm_ocp.o
 
 obj-$(CONFIG_I2C)		+= i2c-core.o
 obj-$(CONFIG_I2C_CHARDEV)	+= i2c-dev.o
diff -Nru a/drivers/i2c/i2c-proc.c b/drivers/i2c/i2c-proc.c
--- a/drivers/i2c/i2c-proc.c	Mon Sep  9 10:36:11 2002
+++ b/drivers/i2c/i2c-proc.c	Mon Sep  9 10:36:11 2002
@@ -60,7 +60,6 @@
 static struct ctl_table_header *i2c_entries[SENSORS_ENTRY_MAX];
 
 static struct i2c_client *i2c_clients[SENSORS_ENTRY_MAX];
-static unsigned short i2c_inodes[SENSORS_ENTRY_MAX];
 
 static ctl_table sysctl_table[] = {
 	{CTL_DEV, "dev", NULL, 0, 0555},
@@ -189,8 +188,6 @@
 		return id;
 	}
 #endif				/* DEBUG */
-	i2c_inodes[id - 256] =
-	    new_header->ctl_table->child->child->de->low_ino;
 	new_header->ctl_table->child->child->de->owner = controlling_mod;
 
 	return id;
@@ -211,49 +208,6 @@
 		i2c_entries[id] = NULL;
 		i2c_clients[id] = NULL;
 	}
-}
-
-/* Monitor access for /proc/sys/dev/sensors; make unloading i2c-proc.o 
-   impossible if some process still uses it or some file in it */
-void i2c_fill_inode(struct inode *inode, int fill)
-{
-	if (fill)
-		MOD_INC_USE_COUNT;
-	else
-		MOD_DEC_USE_COUNT;
-}
-
-/* Monitor access for /proc/sys/dev/sensors/ directories; make unloading
-   the corresponding module impossible if some process still uses it or
-   some file in it */
-void i2c_dir_fill_inode(struct inode *inode, int fill)
-{
-	int i;
-	struct i2c_client *client;
-
-#ifdef DEBUG
-	if (!inode) {
-		printk(KERN_ERR "i2c-proc.o: Warning: inode NULL in fill_inode()\n");
-		return;
-	}
-#endif				/* def DEBUG */
-
-	for (i = 0; i < SENSORS_ENTRY_MAX; i++)
-		if (i2c_clients[i]
-		    && (i2c_inodes[i] == inode->i_ino)) break;
-#ifdef DEBUG
-	if (i == SENSORS_ENTRY_MAX) {
-		printk
-		    (KERN_ERR "i2c-proc.o: Warning: inode (%ld) not found in fill_inode()\n",
-		     inode->i_ino);
-		return;
-	}
-#endif				/* def DEBUG */
-	client = i2c_clients[i];
-	if (fill)
-		client->driver->inc_use(client);
-	else
-		client->driver->dec_use(client);
 }
 
 int i2c_proc_chips(ctl_table * ctl, int write, struct file *filp,
diff -Nru a/drivers/ide/Makefile b/drivers/ide/Makefile
--- a/drivers/ide/Makefile	Mon Sep  9 10:36:11 2002
+++ b/drivers/ide/Makefile	Mon Sep  9 10:36:11 2002
@@ -7,7 +7,7 @@
 # Note : at this point, these files are compiled on all systems.
 # In the future, some of these should be built conditionally.
 #
-export-objs		:= ide-taskfile.o ide.o ide-probe.o ataraid.o
+export-objs		:= ide-taskfile.o ide.o ide-probe.o
 
 obj-$(CONFIG_BLK_DEV_IDE)       += ide-mod.o ide-probe-mod.o
 obj-$(CONFIG_BLK_DEV_IDECS)     += ide-cs.o
diff -Nru a/drivers/ide/hd.c b/drivers/ide/hd.c
--- a/drivers/ide/hd.c	Mon Sep  9 10:35:49 2002
+++ b/drivers/ide/hd.c	Mon Sep  9 10:35:49 2002
@@ -145,8 +145,6 @@
 static int NR_HD;
 #endif
 
-static struct hd_struct hd[MAX_HD<<6];
-
 static struct timer_list device_timer;
 
 #define TIMEOUT_VALUE (6*HZ)
@@ -596,22 +594,21 @@
 		reset_hd();
 		return;
 	}
-	dev = minor(CURRENT->rq_dev);
+	dev = DEVICE_NR(CURRENT->rq_dev);
 	block = CURRENT->sector;
 	nsect = CURRENT->nr_sectors;
-	if (dev >= (NR_HD<<6) || (dev & 0x3f) ||
-	    block >= hd[dev].nr_sects || ((block+nsect) > hd[dev].nr_sects)) {
-		if (dev >= (NR_HD<<6) || (dev & 0x3f))
+	if (dev >= NR_HD || block >= get_capacity(hd_gendisk+dev) ||
+	    ((block+nsect) > get_capacity(hd_gendisk+unit))) {
+		if (dev >= NR_HD)
 			printk("hd: bad minor number: device=%s\n",
 			       kdevname(CURRENT->rq_dev));
 		else
 			printk("hd%c: bad access: block=%d, count=%d\n",
-				(minor(CURRENT->rq_dev)>>6)+'a', block, nsect);
+				dev+'a', block, nsect);
 		end_request(CURRENT, 0);
 		goto repeat;
 	}
 
-	dev >>= 6;
 	if (special_op[dev]) {
 		if (do_special_op(dev))
 			goto repeat;
@@ -707,14 +704,12 @@
 	.first_minor =	0,
 	.major_name =	"hda",
 	.minor_shift =	6,
-	.part =		hd,
 	.fops =		&hd_fops,
 },{
 	.major =	MAJOR_NR,
 	.first_minor =	64,
 	.major_name =	"hdb",
 	.minor_shift =	6,
-	.part =		hd + 64,
 	.fops =		&hd_fops,
 }
 };
@@ -819,10 +814,11 @@
 #endif
 
 	for (drive=0 ; drive < NR_HD ; drive++) {
-		hd[drive<<6].nr_sects = hd_info[drive].head *
+		sector_t size = hd_info[drive].head *
 			hd_info[drive].sect * hd_info[drive].cyl;
-		printk ("hd%c: %ldMB, CHS=%d/%d/%d\n", drive+'a',
-			hd[drive<<6].nr_sects / 2048, hd_info[drive].cyl,
+		set_capacity(hd_gendisk + drive, size);
+		printk ("%s: %ldMB, CHS=%d/%d/%d\n", hd_gendisk[drive].major_name,
+			size / 2048, hd_info[drive].cyl,
 			hd_info[drive].head, hd_info[drive].sect);
 	}
 	if (!NR_HD)
@@ -849,7 +845,6 @@
 	}
 
 	for(drive=0; drive < NR_HD; drive++) {
-		hd_gendisk[drive].nr_real = 1;
 		add_gendisk(hd_gendisk + drive);
 		register_disk(hd_gendisk + drive,
 			mk_kdev(MAJOR_NR,drive<<6), 1<<6,
diff -Nru a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c
--- a/drivers/ide/ide-cd.c	Mon Sep  9 10:36:11 2002
+++ b/drivers/ide/ide-cd.c	Mon Sep  9 10:36:11 2002
@@ -2138,7 +2138,7 @@
 	if (stat)
 		toc->capacity = 0x1fffff;
 
-	drive->part[0].nr_sects = toc->capacity * SECTORS_PER_FRAME;
+	set_capacity(drive->disk, toc->capacity * SECTORS_PER_FRAME);
 
 	/* Remember that we've read this stuff. */
 	CDROM_STATE_FLAGS (drive)->toc_valid = 1;
@@ -2593,9 +2593,8 @@
 {
 	struct cdrom_info *info = drive->driver_data;
 	struct cdrom_device_info *devinfo = &info->devinfo;
-	int minor = (drive->select.b.unit) << PARTN_BITS;
 
-	devinfo->dev = mk_kdev(HWIF(drive)->major, minor);
+	devinfo->dev = mk_kdev(drive->disk->major, drive->disk->first_minor);
 	devinfo->ops = &ide_cdrom_dops;
 	devinfo->mask = 0;
 	*(int *)&devinfo->speed = CDROM_STATE_FLAGS (drive)->current_speed;
@@ -2622,7 +2621,8 @@
 		devinfo->mask |= CDC_CLOSE_TRAY;
 
 	devinfo->de = devfs_register(drive->de, "cd", DEVFS_FL_DEFAULT,
-				     HWIF(drive)->major, minor,
+				     drive->disk->major,
+				     drive->disk->first_minor,
 				     S_IFBLK | S_IRUGO | S_IWUGO,
 				     ide_fops, NULL);
 
@@ -2823,13 +2823,12 @@
 {
 	struct cdrom_info *info = drive->driver_data;
 	struct cdrom_device_info *cdi = &info->devinfo;
-	int minor = drive->select.b.unit << PARTN_BITS;
 	int nslots;
 
 	/*
 	 * default to read-only always and fix latter at the bottom
 	 */
-	set_device_ro(mk_kdev(HWIF(drive)->major, minor), 1);
+	set_device_ro(mk_kdev(drive->disk->major, drive->disk->first_minor), 1);
 	blk_queue_hardsect_size(&drive->queue, CD_FRAMESIZE);
 
 	blk_queue_prep_rq(&drive->queue, ll_10byte_cmd_build);
@@ -2951,7 +2950,7 @@
 	nslots = ide_cdrom_probe_capabilities (drive);
 
 	if (CDROM_CONFIG_FLAGS(drive)->dvd_ram)
-		set_device_ro(mk_kdev(HWIF(drive)->major, minor), 0);
+		set_device_ro(mk_kdev(drive->disk->major, drive->disk->first_minor), 0);
 
 	if (ide_cdrom_register (drive, nslots)) {
 		printk ("%s: ide_cdrom_setup failed to register device with the cdrom driver.\n", drive->name);
@@ -2998,8 +2997,8 @@
 static
 int ide_cdrom_check_media_change (ide_drive_t *drive)
 {
-	return cdrom_media_changed(mk_kdev(HWIF (drive)->major,
-			(drive->select.b.unit) << PARTN_BITS));
+	return cdrom_media_changed(mk_kdev(drive->disk->major,
+			drive->disk->first_minor));
 }
 
 static
@@ -3025,9 +3024,7 @@
 {
 	struct cdrom_info *info = drive->driver_data;
 	struct cdrom_device_info *devinfo = &info->devinfo;
-	ide_hwif_t *hwif = HWIF(drive);
-	int unit = drive - hwif->drives;
-	struct gendisk *g = hwif->gd[unit];
+	struct gendisk *g = drive->disk;
 
 	if (ide_unregister_subdriver (drive))
 		return 1;
@@ -3092,9 +3089,7 @@
 static int ide_cdrom_reinit (ide_drive_t *drive)
 {
 	struct cdrom_info *info;
-	ide_hwif_t *hwif = HWIF(drive);
-	int unit = drive - hwif->drives;
-	struct gendisk *g = hwif->gd[unit];
+	struct gendisk *g = drive->disk;
 	struct request_sense sense;
 
 	if (!strstr("ide-cdrom", drive->driver_req))
@@ -3147,10 +3142,13 @@
 
 	cdrom_read_toc(drive, &sense);
 	g->minor_shift = 0;
+	/* probably bogus, but that's the old behaviour */
+	g->de = NULL;
+	g->flags = GENHD_FL_DEVFS;
 	add_gendisk(g);
 	register_disk(g, mk_kdev(g->major,g->first_minor),
 		      1<<g->minor_shift, ide_fops,
-		      g->part[0].nr_sects);
+		      get_capacity(g));
 	return 0;
 failed:
 	return 1;
diff -Nru a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c
--- a/drivers/ide/ide-disk.c	Mon Sep  9 10:36:11 2002
+++ b/drivers/ide/ide-disk.c	Mon Sep  9 10:36:11 2002
@@ -1516,8 +1516,6 @@
 
 static void idedisk_setup (ide_drive_t *drive)
 {
-	int i;
-	
 	struct hd_driveid *id = drive->id;
 	unsigned long capacity;
 	
@@ -1538,15 +1536,6 @@
 			drive->doorlocking = 1;
 		}
 	}
-	for (i = 0; i < MAX_DRIVES; ++i) {
-		ide_hwif_t *hwif = HWIF(drive);
-
-		if (drive != &hwif->drives[i]) continue;
-		hwif->gd[i]->de_arr[i] = drive->de;
-		if (drive->removable)
-			hwif->gd[i]->flags[i] |= GENHD_FL_REMOVABLE;
-		break;
-	}
 
 #if 1
 	(void) probe_lba_addressing(drive, 1);
@@ -1629,9 +1618,7 @@
 
 static int idedisk_cleanup (ide_drive_t *drive)
 {
-	ide_hwif_t *hwif = HWIF(drive);
-	int unit = drive - hwif->drives;
-	struct gendisk *g = hwif->gd[unit];
+	struct gendisk *g = drive->disk;
 	if ((drive->id->cfs_enable_2 & 0x3000) && drive->wcache)
 		if (do_idedisk_flushcache(drive))
 			printk (KERN_INFO "%s: Write Cache FAILED Flushing!\n",
@@ -1683,9 +1670,7 @@
 
 static int idedisk_reinit(ide_drive_t *drive)
 {
-	ide_hwif_t *hwif = HWIF(drive);
-	int unit = drive - hwif->drives;
-	struct gendisk *g = hwif->gd[unit];
+	struct gendisk *g = drive->disk;
 
 	/* strstr("foo", "") is non-NULL */
 	if (!strstr("ide-disk", drive->driver_req))
@@ -1714,6 +1699,9 @@
 	}
 	DRIVER(drive)->busy--;
 	g->minor_shift = PARTN_BITS;
+	g->de = drive->de;
+	g->flags = drive->removable ? GENHD_FL_REMOVABLE : 0;
+	g->flags |= GENHD_FL_DEVFS;
 	add_gendisk(g);
 	register_disk(g, mk_kdev(g->major,g->first_minor),
 		      1<<g->minor_shift, ide_fops,
diff -Nru a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c
--- a/drivers/ide/ide-floppy.c	Mon Sep  9 10:36:11 2002
+++ b/drivers/ide/ide-floppy.c	Mon Sep  9 10:36:11 2002
@@ -1500,7 +1500,7 @@
 	drive->bios_cyl = 0;
 	drive->bios_head = drive->bios_sect = 0;
 	floppy->blocks = floppy->bs_factor = 0;
-	drive->part[0].nr_sects = 0;
+	set_capacity(drive->disk, 0);
 
 	idefloppy_create_read_capacity_cmd (&pc);
 	if (idefloppy_queue_pc_tail (drive, &pc)) {
@@ -1555,7 +1555,7 @@
 		(void) idefloppy_get_flexible_disk_page (drive);
 	}
 
-	drive->part[0].nr_sects = floppy->blocks * floppy->bs_factor;
+	set_capacity(drive->disk, floppy->blocks * floppy->bs_factor);
 	return rc;
 }
 
@@ -1817,7 +1817,7 @@
 		return (idefloppy_get_format_progress(drive, inode, file,
 						      (int *)arg));
 	}
- 	return -EIO;
+ 	return -EINVAL;
 }
 
 /*
@@ -2065,7 +2065,6 @@
 static void idefloppy_setup (ide_drive_t *drive, idefloppy_floppy_t *floppy)
 {
 	struct idefloppy_id_gcw gcw;
-	int i;
 
 	*((unsigned short *) &gcw) = drive->id->config;
 	drive->driver_data = floppy;
@@ -2108,23 +2107,12 @@
 
 	(void) idefloppy_get_capacity (drive);
 	idefloppy_add_settings(drive);
-	for (i = 0; i < MAX_DRIVES; ++i) {
-		ide_hwif_t *hwif = HWIF(drive);
-
-		if (drive != &hwif->drives[i]) continue;
-		hwif->gd[i]->de_arr[i] = drive->de;
-		if (drive->removable)
-			hwif->gd[i]->flags[i] |= GENHD_FL_REMOVABLE;
-		break;
-	}
 }
 
 static int idefloppy_cleanup (ide_drive_t *drive)
 {
 	idefloppy_floppy_t *floppy = drive->driver_data;
-	ide_hwif_t *hwif = HWIF(drive);
-	int unit = drive - hwif->drives;
-	struct gendisk *g = hwif->gd[unit];
+	struct gendisk *g = drive->disk;
 
 	if (ide_unregister_subdriver (drive))
 		return 1;
@@ -2191,9 +2179,7 @@
 static int idefloppy_reinit (ide_drive_t *drive)
 {
 	idefloppy_floppy_t *floppy;
-	ide_hwif_t *hwif = HWIF(drive);
-	int unit = drive - hwif->drives;
-	struct gendisk *g = hwif->gd[unit];
+	struct gendisk *g = drive->disk;
 	if (!strstr("ide-floppy", drive->driver_req))
 		goto failed;
 	if (!drive->present)
@@ -2221,10 +2207,13 @@
 	idefloppy_setup (drive, floppy);
 	DRIVER(drive)->busy--;
 	g->minor_shift = PARTN_BITS;
+	g->de = drive->de;
+	g->flags = drive->removable ? GENHD_FL_REMOVABLE : 0;
+	g->flags |= GENHD_FL_DEVFS;
 	add_gendisk(g);
 	register_disk(g, mk_kdev(g->major,g->first_minor),
 		      1<<g->minor_shift, ide_fops,
-		      g->part[0].nr_sects);
+		      get_capacity(g));
 	return 0;
 failed:
 	return 1;
diff -Nru a/drivers/ide/ide-geometry.c b/drivers/ide/ide-geometry.c
--- a/drivers/ide/ide-geometry.c	Mon Sep  9 10:36:01 2002
+++ b/drivers/ide/ide-geometry.c	Mon Sep  9 10:36:01 2002
@@ -214,7 +214,7 @@
 		ret = 1;
 	}
 
-	drive->part[0].nr_sects = current_capacity(drive);
+	set_capacity(drive->disk, current_capacity(drive));
 
 	if (ret)
 		printk("%s%s [%d/%d/%d]", msg, msg1,
diff -Nru a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c
--- a/drivers/ide/ide-probe.c	Mon Sep  9 10:36:11 2002
+++ b/drivers/ide/ide-probe.c	Mon Sep  9 10:36:11 2002
@@ -807,9 +807,6 @@
 static void init_gendisk (ide_hwif_t *hwif)
 {
 	struct gendisk *gd;
-	struct hd_struct *part;
-	devfs_handle_t *de_arr;
-	char *flags;
 	unsigned int unit, units, minors;
 	extern devfs_handle_t ide_devfs_handle;
 	char *names;
@@ -830,40 +827,19 @@
 		goto err_kmalloc_gd;
 	memset(gd, 0, MAX_DRIVES * sizeof(struct gendisk));
 
-	part  = kmalloc(minors * sizeof(struct hd_struct), GFP_KERNEL);
-	if (!part)
-		goto err_kmalloc_gd_part;
-
-	memset(part, 0, minors * sizeof(struct hd_struct));
-
-	de_arr = kmalloc(sizeof(devfs_handle_t) * MAX_DRIVES, GFP_KERNEL);
-	if (!de_arr)
-		goto err_kmalloc_gd_de_arr;
-	memset(de_arr, 0, sizeof(devfs_handle_t) * MAX_DRIVES);
-
-	flags = kmalloc(sizeof(char) * MAX_DRIVES, GFP_KERNEL);
-	if (!flags)
-		goto err_kmalloc_gd_flags;
-	memset(flags, 0, sizeof(char) * MAX_DRIVES);
-
 	names = kmalloc (4 * MAX_DRIVES, GFP_KERNEL);
 	if (!names)
 		goto err_kmalloc_gd_names;
 	memset(names, 0, 4 * MAX_DRIVES);
 
 	for (unit = 0; unit < units; ++unit) {
-		gd[unit].part = part + (unit << PARTN_BITS);
-		gd[unit].de_arr = de_arr + unit;
-		gd[unit].flags = flags + unit;
-		hwif->drives[unit].part = gd[unit].part;
 		gd[unit].major  = hwif->major;
 		gd[unit].first_minor = unit << PARTN_BITS;
 		sprintf(names + 4*unit, "hd%c",'a'+hwif->index*MAX_DRIVES+unit);
 		gd[unit].major_name = names + 4*unit;
 		gd[unit].minor_shift = PARTN_BITS; 
-		gd[unit].nr_real = 1;
 		gd[unit].fops = ide_fops;
-		hwif->gd[unit] = gd + unit;
+		hwif->drives[unit].disk = gd + unit;
 	}
 
 	for (unit = 0; unit < units; ++unit) {
@@ -892,12 +868,6 @@
 	return;
 
 err_kmalloc_gd_names:
-	kfree(names);
-err_kmalloc_gd_flags:
-	kfree(de_arr);
-err_kmalloc_gd_de_arr:
-	kfree(part);
-err_kmalloc_gd_part:
 	kfree(gd);
 err_kmalloc_gd:
 	printk(KERN_WARNING "(ide::init_gendisk) Out of memory\n");
diff -Nru a/drivers/ide/ide.c b/drivers/ide/ide.c
--- a/drivers/ide/ide.c	Mon Sep  9 10:36:01 2002
+++ b/drivers/ide/ide.c	Mon Sep  9 10:36:01 2002
@@ -275,7 +275,6 @@
 		drive->name[1]			= 'd';
 		drive->name[2]			= 'a' + (index * MAX_DRIVES) + unit;
 		drive->max_failures		= IDE_DEFAULT_MAX_FAILURES;
-		init_waitqueue_head(&drive->wqueue);
 		INIT_LIST_HEAD(&drive->list);
 	}
 }
@@ -1661,7 +1660,7 @@
 			if (unit < MAX_DRIVES) {
 				ide_drive_t *drive = &hwif->drives[unit];
 #if 0
-				if ((drive->present) && (drive->part[minor].nr_sects))
+				if (drive->present && get_capacity(drive->disk))
 #else
 				if (drive->present)
 #endif
@@ -1748,10 +1747,7 @@
 
 void ide_revalidate_drive (ide_drive_t *drive)
 {
-	ide_hwif_t *hwif = HWIF(drive);
-	int unit = drive - hwif->drives;
-	struct gendisk *g = hwif->gd[unit];
-	g->part[0].nr_sects = current_capacity(drive);
+	set_capacity(drive->disk, current_capacity(drive));
 }
 
 /*
@@ -1805,8 +1801,6 @@
 #endif /* defined(CONFIG_BLK_DEV_IDESCSI) && defined(CONFIG_SCSI) */
 	}
 #endif /* CONFIG_KMOD */
-	while (drive->busy)
-		sleep_on(&drive->wqueue);
 	drive->usage++;
 	if (drive->driver != NULL)
 		return DRIVER(drive)->open(inode, filp, drive);
@@ -1877,7 +1871,7 @@
  */
 int ide_replace_subdriver (ide_drive_t *drive, const char *driver)
 {
-	if (!drive->present || drive->busy || drive->usage)
+	if (!drive->present || drive->usage)
 		goto abort;
 	if (drive->driver != NULL && DRIVER(drive)->cleanup(drive))
 		goto abort;
@@ -1961,7 +1955,7 @@
 		drive = &hwif->drives[unit];
 		if (!drive->present)
 			continue;
-		if (drive->busy || drive->usage)
+		if (drive->usage)
 			goto abort;
 		if (drive->driver != NULL && DRIVER(drive)->cleanup(drive))
 			goto abort;
@@ -1978,7 +1972,7 @@
 			continue;
 		minor = drive->select.b.unit << PARTN_BITS;
 		for (p = 0; p < (1<<PARTN_BITS); ++p) {
-			if (drive->part[p].nr_sects > 0) {
+			if (get_capacity(drive->disk)) {
 				kdev_t devp = mk_kdev(hwif->major, minor+p);
 				invalidate_device(devp, 0);
 			}
@@ -2058,17 +2052,12 @@
 	blk_dev[hwif->major].data = NULL;
 	blk_dev[hwif->major].queue = NULL;
 	blk_clear(hwif->major);
-	gd = hwif->gd[0];
+	gd = hwif->drives[0].disk;
 	if (gd) {
 		int i;
-		kfree(gd->part);
-		if (gd->de_arr)
-			kfree (gd->de_arr);
-		if (gd->flags)
-			kfree (gd->flags);
-		kfree(gd);
 		for (i = 0; i < MAX_DRIVES; i++)
-			hwif->gd[i] = NULL;
+			hwif->drives[i].disk = NULL;
+		kfree(gd);
 	}
 	old_hwif		= *hwif;
 	init_hwif_data (index);	/* restore hwif data to pristine status */
@@ -2530,7 +2519,7 @@
 			if (put_user(drive->bios_head, (byte *) &loc->heads)) return -EFAULT;
 			if (put_user(drive->bios_sect, (byte *) &loc->sectors)) return -EFAULT;
 			if (put_user(bios_cyl, (unsigned short *) &loc->cylinders)) return -EFAULT;
-			if (put_user((unsigned)drive->part[minor(inode->i_rdev)&PARTN_MASK].start_sect,
+			if (put_user((unsigned)get_start_sect(inode->i_bdev),
 				(unsigned long *) &loc->start)) return -EFAULT;
 			return 0;
 		}
@@ -2542,7 +2531,7 @@
 			if (put_user(drive->head, (byte *) &loc->heads)) return -EFAULT;
 			if (put_user(drive->sect, (byte *) &loc->sectors)) return -EFAULT;
 			if (put_user(drive->cyl, (unsigned int *) &loc->cylinders)) return -EFAULT;
-			if (put_user((unsigned)drive->part[minor(inode->i_rdev)&PARTN_MASK].start_sect,
+			if (put_user((unsigned)get_start_sect(inode->i_bdev),
 				(unsigned long *) &loc->start)) return -EFAULT;
 			return 0;
 		}
@@ -2653,18 +2642,6 @@
 			}
 			return 0;
 		}
-		case BLKGETSIZE:
-		case BLKGETSIZE64:
-		case BLKROSET:
-		case BLKROGET:
-		case BLKFLSBUF:
-		case BLKSSZGET:
-		case BLKPG:
-		case BLKELVGET:
-		case BLKELVSET:
-		case BLKBSZGET:
-		case BLKBSZSET:
-			return blk_ioctl(inode->i_bdev, cmd, arg);
 
 		case CDROMEJECT:
 		case CDROMCLOSETRAY:
@@ -3362,7 +3339,7 @@
 static int default_ioctl (ide_drive_t *drive, struct inode *inode, struct file *file,
 			  unsigned int cmd, unsigned long arg)
 {
-	return -EIO;
+	return -EINVAL;
 }
 
 static int default_open (struct inode *inode, struct file *filp, ide_drive_t *drive)
@@ -3434,7 +3411,7 @@
 	
 	spin_lock_irqsave(&ide_lock, flags);
 	if (version != IDE_SUBDRIVER_VERSION || !drive->present ||
-	    drive->driver != NULL || drive->busy || drive->usage) {
+	    drive->driver != NULL || drive->usage) {
 		spin_unlock_irqrestore(&ide_lock, flags);
 		return 1;
 	}
@@ -3463,8 +3440,7 @@
 	unsigned long flags;
 	
 	spin_lock_irqsave(&ide_lock, flags);
-	if (drive->usage || drive->busy ||
-	    drive->driver == NULL || DRIVER(drive)->busy) {
+	if (drive->usage || drive->driver == NULL || DRIVER(drive)->busy) {
 		spin_unlock_irqrestore(&ide_lock, flags);
 		return 1;
 	}
diff -Nru a/drivers/isdn/act2000/act2000_isa.c b/drivers/isdn/act2000/act2000_isa.c
--- a/drivers/isdn/act2000/act2000_isa.c	Mon Sep  9 10:36:11 2002
+++ b/drivers/isdn/act2000/act2000_isa.c	Mon Sep  9 10:36:11 2002
@@ -12,7 +12,6 @@
  *
  */
 
-#define __NO_VERSION__
 #include "act2000.h"
 #include "act2000_isa.h"
 #include "capi.h"
diff -Nru a/drivers/isdn/act2000/capi.c b/drivers/isdn/act2000/capi.c
--- a/drivers/isdn/act2000/capi.c	Mon Sep  9 10:36:17 2002
+++ b/drivers/isdn/act2000/capi.c	Mon Sep  9 10:36:17 2002
@@ -13,7 +13,6 @@
  *
  */
 
-#define __NO_VERSION__
 #include "act2000.h"
 #include "capi.h"
 
diff -Nru a/drivers/isdn/divert/divert_procfs.c b/drivers/isdn/divert/divert_procfs.c
--- a/drivers/isdn/divert/divert_procfs.c	Mon Sep  9 10:36:17 2002
+++ b/drivers/isdn/divert/divert_procfs.c	Mon Sep  9 10:36:17 2002
@@ -10,7 +10,6 @@
  */
 
 #include <linux/config.h>
-#define __NO_VERSION__
 #include <linux/module.h>
 #include <linux/version.h>
 #include <linux/poll.h>
diff -Nru a/drivers/isdn/eicon/eicon_idi.c b/drivers/isdn/eicon/eicon_idi.c
--- a/drivers/isdn/eicon/eicon_idi.c	Mon Sep  9 10:35:43 2002
+++ b/drivers/isdn/eicon/eicon_idi.c	Mon Sep  9 10:35:43 2002
@@ -17,7 +17,6 @@
  */
 
 #include <linux/config.h>
-#define __NO_VERSION__
 #include "eicon.h"
 #include "eicon_idi.h"
 #include "eicon_dsp.h"
diff -Nru a/drivers/isdn/eicon/linchr.c b/drivers/isdn/eicon/linchr.c
--- a/drivers/isdn/eicon/linchr.c	Mon Sep  9 10:35:56 2002
+++ b/drivers/isdn/eicon/linchr.c	Mon Sep  9 10:35:56 2002
@@ -8,7 +8,6 @@
  *
  */
 
-#define __NO_VERSION__
 #include <linux/module.h>
 
 #include <linux/kernel.h>
diff -Nru a/drivers/isdn/hisax/amd7930.c b/drivers/isdn/hisax/amd7930.c
--- a/drivers/isdn/hisax/amd7930.c	Mon Sep  9 10:36:11 2002
+++ b/drivers/isdn/hisax/amd7930.c	Mon Sep  9 10:36:11 2002
@@ -90,7 +90,6 @@
  * 
  */
 
-#define __NO_VERSION__
 #include "hisax.h"
 #include "../../sbus/audio/amd7930.h"
 #include "isac.h"
diff -Nru a/drivers/isdn/hisax/amd7930_fn.c b/drivers/isdn/hisax/amd7930_fn.c
--- a/drivers/isdn/hisax/amd7930_fn.c	Mon Sep  9 10:36:12 2002
+++ b/drivers/isdn/hisax/amd7930_fn.c	Mon Sep  9 10:36:12 2002
@@ -53,7 +53,6 @@
  */
 
 
-#define __NO_VERSION__
 #include "hisax.h"
 #include "isdnl1.h"
 #include "isac.h"
diff -Nru a/drivers/isdn/hisax/arcofi.c b/drivers/isdn/hisax/arcofi.c
--- a/drivers/isdn/hisax/arcofi.c	Mon Sep  9 10:36:11 2002
+++ b/drivers/isdn/hisax/arcofi.c	Mon Sep  9 10:36:11 2002
@@ -10,7 +10,6 @@
  *
  */
  
-#define __NO_VERSION__
 #include "hisax.h"
 #include "isdnl1.h"
 #include "isac.h"
diff -Nru a/drivers/isdn/hisax/asuscom.c b/drivers/isdn/hisax/asuscom.c
--- a/drivers/isdn/hisax/asuscom.c	Mon Sep  9 10:36:11 2002
+++ b/drivers/isdn/hisax/asuscom.c	Mon Sep  9 10:36:11 2002
@@ -12,7 +12,6 @@
  *
  */
 
-#define __NO_VERSION__
 #include <linux/init.h>
 #include <linux/isapnp.h>
 #include "hisax.h"
diff -Nru a/drivers/isdn/hisax/avm_a1.c b/drivers/isdn/hisax/avm_a1.c
--- a/drivers/isdn/hisax/avm_a1.c	Mon Sep  9 10:35:56 2002
+++ b/drivers/isdn/hisax/avm_a1.c	Mon Sep  9 10:35:56 2002
@@ -10,7 +10,6 @@
  *
  */
 
-#define __NO_VERSION__
 #include <linux/init.h>
 #include "hisax.h"
 #include "isac.h"
diff -Nru a/drivers/isdn/hisax/avm_a1p.c b/drivers/isdn/hisax/avm_a1p.c
--- a/drivers/isdn/hisax/avm_a1p.c	Mon Sep  9 10:36:11 2002
+++ b/drivers/isdn/hisax/avm_a1p.c	Mon Sep  9 10:36:11 2002
@@ -13,7 +13,6 @@
  *
  */
 
-#define __NO_VERSION__
 #include <linux/init.h>
 #include "hisax.h"
 #include "isac.h"
diff -Nru a/drivers/isdn/hisax/avm_pci.c b/drivers/isdn/hisax/avm_pci.c
--- a/drivers/isdn/hisax/avm_pci.c	Mon Sep  9 10:36:05 2002
+++ b/drivers/isdn/hisax/avm_pci.c	Mon Sep  9 10:36:05 2002
@@ -12,7 +12,6 @@
  *
  */
 
-#define __NO_VERSION__
 #include <linux/config.h>
 #include <linux/init.h>
 #include "hisax.h"
diff -Nru a/drivers/isdn/hisax/bkm_a4t.c b/drivers/isdn/hisax/bkm_a4t.c
--- a/drivers/isdn/hisax/bkm_a4t.c	Mon Sep  9 10:36:11 2002
+++ b/drivers/isdn/hisax/bkm_a4t.c	Mon Sep  9 10:36:11 2002
@@ -10,8 +10,6 @@
  *
  */
 
-#define __NO_VERSION__
-
 #include <linux/config.h>
 #include <linux/init.h>
 #include "hisax.h"
diff -Nru a/drivers/isdn/hisax/bkm_a8.c b/drivers/isdn/hisax/bkm_a8.c
--- a/drivers/isdn/hisax/bkm_a8.c	Mon Sep  9 10:36:13 2002
+++ b/drivers/isdn/hisax/bkm_a8.c	Mon Sep  9 10:36:13 2002
@@ -10,8 +10,6 @@
  *
  */
 
-#define __NO_VERSION__
-
 #include <linux/config.h>
 #include <linux/init.h>
 #include "hisax.h"
diff -Nru a/drivers/isdn/hisax/callc.c b/drivers/isdn/hisax/callc.c
--- a/drivers/isdn/hisax/callc.c	Mon Sep  9 10:36:11 2002
+++ b/drivers/isdn/hisax/callc.c	Mon Sep  9 10:36:11 2002
@@ -16,7 +16,6 @@
  *
  */
 
-#define __NO_VERSION__
 #include <linux/module.h>
 #include <linux/init.h>
 #include "hisax.h"
diff -Nru a/drivers/isdn/hisax/diva.c b/drivers/isdn/hisax/diva.c
--- a/drivers/isdn/hisax/diva.c	Mon Sep  9 10:36:17 2002
+++ b/drivers/isdn/hisax/diva.c	Mon Sep  9 10:36:17 2002
@@ -15,7 +15,6 @@
  *
  */
 
-#define __NO_VERSION__
 #include <linux/init.h>
 #include <linux/config.h>
 #include "hisax.h"
diff -Nru a/drivers/isdn/hisax/elsa.c b/drivers/isdn/hisax/elsa.c
--- a/drivers/isdn/hisax/elsa.c	Mon Sep  9 10:36:01 2002
+++ b/drivers/isdn/hisax/elsa.c	Mon Sep  9 10:36:01 2002
@@ -18,7 +18,6 @@
  *
  */
 
-#define __NO_VERSION__
 #include <linux/init.h>
 #include <linux/config.h>
 #include "hisax.h"
diff -Nru a/drivers/isdn/hisax/enternow_pci.c b/drivers/isdn/hisax/enternow_pci.c
--- a/drivers/isdn/hisax/enternow_pci.c	Mon Sep  9 10:36:13 2002
+++ b/drivers/isdn/hisax/enternow_pci.c	Mon Sep  9 10:36:13 2002
@@ -60,7 +60,6 @@
  */
 
 
-#define __NO_VERSION__
 #include <linux/config.h>
 #include "hisax.h"
 #include "isac.h"
diff -Nru a/drivers/isdn/hisax/fsm.c b/drivers/isdn/hisax/fsm.c
--- a/drivers/isdn/hisax/fsm.c	Mon Sep  9 10:36:01 2002
+++ b/drivers/isdn/hisax/fsm.c	Mon Sep  9 10:36:01 2002
@@ -14,7 +14,6 @@
  *
  */
 
-#define __NO_VERSION__
 #include <linux/module.h>
 #include <linux/init.h>
 #include "hisax.h"
diff -Nru a/drivers/isdn/hisax/gazel.c b/drivers/isdn/hisax/gazel.c
--- a/drivers/isdn/hisax/gazel.c	Mon Sep  9 10:35:49 2002
+++ b/drivers/isdn/hisax/gazel.c	Mon Sep  9 10:35:51 2002
@@ -13,7 +13,6 @@
 
 #include <linux/config.h>
 #include <linux/init.h>
-#define __NO_VERSION__
 #include "hisax.h"
 #include "isac.h"
 #include "hscx.h"
diff -Nru a/drivers/isdn/hisax/hfc_2bds0.c b/drivers/isdn/hisax/hfc_2bds0.c
--- a/drivers/isdn/hisax/hfc_2bds0.c	Mon Sep  9 10:35:56 2002
+++ b/drivers/isdn/hisax/hfc_2bds0.c	Mon Sep  9 10:35:56 2002
@@ -10,7 +10,6 @@
  *
  */
 
-#define __NO_VERSION__
 #include <linux/init.h>
 #include "hisax.h"
 #include "hfc_2bds0.h"
diff -Nru a/drivers/isdn/hisax/hfc_2bs0.c b/drivers/isdn/hisax/hfc_2bs0.c
--- a/drivers/isdn/hisax/hfc_2bs0.c	Mon Sep  9 10:35:56 2002
+++ b/drivers/isdn/hisax/hfc_2bs0.c	Mon Sep  9 10:35:56 2002
@@ -10,7 +10,6 @@
  *
  */
 
-#define __NO_VERSION__
 #include <linux/init.h>
 #include "hisax.h"
 #include "hfc_2bs0.h"
diff -Nru a/drivers/isdn/hisax/hfc_pci.c b/drivers/isdn/hisax/hfc_pci.c
--- a/drivers/isdn/hisax/hfc_pci.c	Mon Sep  9 10:36:11 2002
+++ b/drivers/isdn/hisax/hfc_pci.c	Mon Sep  9 10:36:11 2002
@@ -17,7 +17,6 @@
 
 #include <linux/init.h>
 #include <linux/config.h>
-#define __NO_VERSION__
 #include "hisax.h"
 #include "hfc_pci.h"
 #include "isdnl1.h"
diff -Nru a/drivers/isdn/hisax/hfc_sx.c b/drivers/isdn/hisax/hfc_sx.c
--- a/drivers/isdn/hisax/hfc_sx.c	Mon Sep  9 10:35:56 2002
+++ b/drivers/isdn/hisax/hfc_sx.c	Mon Sep  9 10:35:56 2002
@@ -11,7 +11,6 @@
  *
  */
 
-#define __NO_VERSION__
 #include <linux/init.h>
 #include "hisax.h"
 #include "hfc_sx.h"
diff -Nru a/drivers/isdn/hisax/hfcscard.c b/drivers/isdn/hisax/hfcscard.c
--- a/drivers/isdn/hisax/hfcscard.c	Mon Sep  9 10:36:17 2002
+++ b/drivers/isdn/hisax/hfcscard.c	Mon Sep  9 10:36:17 2002
@@ -10,7 +10,6 @@
  *
  */
 
-#define __NO_VERSION__
 #include <linux/init.h>
 #include <linux/isapnp.h>
 #include "hisax.h"
diff -Nru a/drivers/isdn/hisax/hisax_hfcpci.c b/drivers/isdn/hisax/hisax_hfcpci.c
--- a/drivers/isdn/hisax/hisax_hfcpci.c	Mon Sep  9 10:36:01 2002
+++ b/drivers/isdn/hisax/hisax_hfcpci.c	Mon Sep  9 10:36:01 2002
@@ -46,7 +46,7 @@
 	  .subdevice   = PCI_ANY_ID,             \
 	  .class       = 0,                      \
           .class_mask  = 0,                      \
-	  driver_data: (unsigned long) name }
+	  .driver_data = (unsigned long) name }
 
 static struct pci_device_id hfcpci_ids[] __devinitdata = {
 	ID(CCD,     CCD_2BD0,         "CCD/Billion/Asuscom 2BD0"),
diff -Nru a/drivers/isdn/hisax/hscx.c b/drivers/isdn/hisax/hscx.c
--- a/drivers/isdn/hisax/hscx.c	Mon Sep  9 10:35:55 2002
+++ b/drivers/isdn/hisax/hscx.c	Mon Sep  9 10:35:55 2002
@@ -10,7 +10,6 @@
  *
  */
 
-#define __NO_VERSION__
 #include <linux/init.h>
 #include "hisax.h"
 #include "hscx.h"
diff -Nru a/drivers/isdn/hisax/icc.c b/drivers/isdn/hisax/icc.c
--- a/drivers/isdn/hisax/icc.c	Mon Sep  9 10:35:56 2002
+++ b/drivers/isdn/hisax/icc.c	Mon Sep  9 10:35:56 2002
@@ -14,7 +14,6 @@
  *
  */
 
-#define __NO_VERSION__
 #include <linux/init.h>
 #include "hisax.h"
 #include "icc.h"
diff -Nru a/drivers/isdn/hisax/ipacx.c b/drivers/isdn/hisax/ipacx.c
--- a/drivers/isdn/hisax/ipacx.c	Mon Sep  9 10:36:11 2002
+++ b/drivers/isdn/hisax/ipacx.c	Mon Sep  9 10:36:11 2002
@@ -9,7 +9,6 @@
  * of the GNU General Public License, incorporated herein by reference.
  *
  */
-#define __NO_VERSION__
 #include <linux/kernel.h>
 #include <linux/config.h>
 #include <linux/init.h>
diff -Nru a/drivers/isdn/hisax/isac.c b/drivers/isdn/hisax/isac.c
--- a/drivers/isdn/hisax/isac.c	Mon Sep  9 10:36:01 2002
+++ b/drivers/isdn/hisax/isac.c	Mon Sep  9 10:36:01 2002
@@ -13,7 +13,6 @@
  *
  */
 
-#define __NO_VERSION__
 #include "hisax.h"
 #include "isac.h"
 #include "arcofi.h"
diff -Nru a/drivers/isdn/hisax/isar.c b/drivers/isdn/hisax/isar.c
--- a/drivers/isdn/hisax/isar.c	Mon Sep  9 10:36:11 2002
+++ b/drivers/isdn/hisax/isar.c	Mon Sep  9 10:36:11 2002
@@ -8,7 +8,6 @@
  *
  */
 
-#define __NO_VERSION__
 #include <linux/init.h>
 #include "hisax.h"
 #include "isar.h"
diff -Nru a/drivers/isdn/hisax/isdnl1.c b/drivers/isdn/hisax/isdnl1.c
--- a/drivers/isdn/hisax/isdnl1.c	Mon Sep  9 10:36:01 2002
+++ b/drivers/isdn/hisax/isdnl1.c	Mon Sep  9 10:36:01 2002
@@ -20,7 +20,6 @@
 
 const char *l1_revision = "$Revision: 2.41.6.5 $";
 
-#define __NO_VERSION__
 #include <linux/init.h>
 #include "hisax.h"
 #include "isdnl1.h"
diff -Nru a/drivers/isdn/hisax/isdnl2.c b/drivers/isdn/hisax/isdnl2.c
--- a/drivers/isdn/hisax/isdnl2.c	Mon Sep  9 10:36:01 2002
+++ b/drivers/isdn/hisax/isdnl2.c	Mon Sep  9 10:36:01 2002
@@ -15,7 +15,6 @@
  *
  */
 
-#define __NO_VERSION__
 #include <linux/init.h>
 #include "hisax.h"
 #include "isdnl2.h"
diff -Nru a/drivers/isdn/hisax/isdnl3.c b/drivers/isdn/hisax/isdnl3.c
--- a/drivers/isdn/hisax/isdnl3.c	Mon Sep  9 10:36:11 2002
+++ b/drivers/isdn/hisax/isdnl3.c	Mon Sep  9 10:36:11 2002
@@ -15,7 +15,6 @@
  *
  */
 
-#define __NO_VERSION__
 #include <linux/init.h>
 #include "hisax.h"
 #include "isdnl3.h"
diff -Nru a/drivers/isdn/hisax/isurf.c b/drivers/isdn/hisax/isurf.c
--- a/drivers/isdn/hisax/isurf.c	Mon Sep  9 10:35:51 2002
+++ b/drivers/isdn/hisax/isurf.c	Mon Sep  9 10:35:51 2002
@@ -10,7 +10,6 @@
  *
  */
 
-#define __NO_VERSION__
 #include <linux/init.h>
 #include "hisax.h"
 #include "isac.h"
diff -Nru a/drivers/isdn/hisax/ix1_micro.c b/drivers/isdn/hisax/ix1_micro.c
--- a/drivers/isdn/hisax/ix1_micro.c	Mon Sep  9 10:36:17 2002
+++ b/drivers/isdn/hisax/ix1_micro.c	Mon Sep  9 10:36:17 2002
@@ -17,7 +17,6 @@
  * Germany
  */
 
-#define __NO_VERSION__
 #include <linux/init.h>
 #include <linux/isapnp.h>
 #include "hisax.h"
diff -Nru a/drivers/isdn/hisax/jade.c b/drivers/isdn/hisax/jade.c
--- a/drivers/isdn/hisax/jade.c	Mon Sep  9 10:36:01 2002
+++ b/drivers/isdn/hisax/jade.c	Mon Sep  9 10:36:01 2002
@@ -11,7 +11,6 @@
  */
 
 
-#define __NO_VERSION__
 #include <linux/init.h>
 #include "hisax.h"
 #include "hscx.h"
diff -Nru a/drivers/isdn/hisax/l3_1tr6.c b/drivers/isdn/hisax/l3_1tr6.c
--- a/drivers/isdn/hisax/l3_1tr6.c	Mon Sep  9 10:36:12 2002
+++ b/drivers/isdn/hisax/l3_1tr6.c	Mon Sep  9 10:36:12 2002
@@ -13,7 +13,6 @@
  *
  */
 
-#define __NO_VERSION__
 #include "hisax.h"
 #include "l3_1tr6.h"
 #include "isdnl3.h"
diff -Nru a/drivers/isdn/hisax/l3dss1.c b/drivers/isdn/hisax/l3dss1.c
--- a/drivers/isdn/hisax/l3dss1.c	Mon Sep  9 10:36:11 2002
+++ b/drivers/isdn/hisax/l3dss1.c	Mon Sep  9 10:36:11 2002
@@ -19,7 +19,6 @@
  *
  */
 
-#define __NO_VERSION__
 #include "hisax.h"
 #include "isdnl3.h"
 #include "l3dss1.h"
diff -Nru a/drivers/isdn/hisax/l3ni1.c b/drivers/isdn/hisax/l3ni1.c
--- a/drivers/isdn/hisax/l3ni1.c	Mon Sep  9 10:36:01 2002
+++ b/drivers/isdn/hisax/l3ni1.c	Mon Sep  9 10:36:01 2002
@@ -18,7 +18,6 @@
  *
  */
 
-#define __NO_VERSION__
 #include "hisax.h"
 #include "isdnl3.h"
 #include "l3ni1.h"
diff -Nru a/drivers/isdn/hisax/lmgr.c b/drivers/isdn/hisax/lmgr.c
--- a/drivers/isdn/hisax/lmgr.c	Mon Sep  9 10:36:01 2002
+++ b/drivers/isdn/hisax/lmgr.c	Mon Sep  9 10:36:01 2002
@@ -10,7 +10,6 @@
  *
  */
 
-#define __NO_VERSION__
 #include "hisax.h"
 
 static void
diff -Nru a/drivers/isdn/hisax/mic.c b/drivers/isdn/hisax/mic.c
--- a/drivers/isdn/hisax/mic.c	Mon Sep  9 10:36:13 2002
+++ b/drivers/isdn/hisax/mic.c	Mon Sep  9 10:36:13 2002
@@ -10,7 +10,6 @@
  *
  */
 
-#define __NO_VERSION__
 #include <linux/init.h>
 #include "hisax.h"
 #include "isac.h"
diff -Nru a/drivers/isdn/hisax/netjet.c b/drivers/isdn/hisax/netjet.c
--- a/drivers/isdn/hisax/netjet.c	Mon Sep  9 10:36:01 2002
+++ b/drivers/isdn/hisax/netjet.c	Mon Sep  9 10:36:01 2002
@@ -14,7 +14,6 @@
  *
  */
 
-#define __NO_VERSION__
 #include <linux/init.h>
 #include "hisax.h"
 #include "isac.h"
diff -Nru a/drivers/isdn/hisax/niccy.c b/drivers/isdn/hisax/niccy.c
--- a/drivers/isdn/hisax/niccy.c	Mon Sep  9 10:36:11 2002
+++ b/drivers/isdn/hisax/niccy.c	Mon Sep  9 10:36:11 2002
@@ -14,7 +14,6 @@
  */
 
 
-#define __NO_VERSION__
 #include <linux/config.h>
 #include <linux/init.h>
 #include "hisax.h"
diff -Nru a/drivers/isdn/hisax/nj_s.c b/drivers/isdn/hisax/nj_s.c
--- a/drivers/isdn/hisax/nj_s.c	Mon Sep  9 10:36:01 2002
+++ b/drivers/isdn/hisax/nj_s.c	Mon Sep  9 10:36:01 2002
@@ -5,7 +5,6 @@
  *
  */
 
-#define __NO_VERSION__
 #include <linux/config.h>
 #include <linux/init.h>
 #include "hisax.h"
diff -Nru a/drivers/isdn/hisax/nj_u.c b/drivers/isdn/hisax/nj_u.c
--- a/drivers/isdn/hisax/nj_u.c	Mon Sep  9 10:36:01 2002
+++ b/drivers/isdn/hisax/nj_u.c	Mon Sep  9 10:36:01 2002
@@ -5,7 +5,6 @@
  *
  */
 
-#define __NO_VERSION__
 #include <linux/config.h>
 #include <linux/init.h>
 #include "hisax.h"
diff -Nru a/drivers/isdn/hisax/q931.c b/drivers/isdn/hisax/q931.c
--- a/drivers/isdn/hisax/q931.c	Mon Sep  9 10:36:11 2002
+++ b/drivers/isdn/hisax/q931.c	Mon Sep  9 10:36:11 2002
@@ -17,7 +17,6 @@
  */
 
 
-#define __NO_VERSION__
 #include "hisax.h"
 #include "l3_1tr6.h"
 
diff -Nru a/drivers/isdn/hisax/s0box.c b/drivers/isdn/hisax/s0box.c
--- a/drivers/isdn/hisax/s0box.c	Mon Sep  9 10:35:56 2002
+++ b/drivers/isdn/hisax/s0box.c	Mon Sep  9 10:35:56 2002
@@ -10,7 +10,6 @@
  *
  */
 
-#define __NO_VERSION__
 #include <linux/init.h>
 #include "hisax.h"
 #include "isac.h"
diff -Nru a/drivers/isdn/hisax/saphir.c b/drivers/isdn/hisax/saphir.c
--- a/drivers/isdn/hisax/saphir.c	Mon Sep  9 10:35:51 2002
+++ b/drivers/isdn/hisax/saphir.c	Mon Sep  9 10:35:51 2002
@@ -12,7 +12,6 @@
  *
  */
 
-#define __NO_VERSION__
 #include <linux/init.h>
 #include "hisax.h"
 #include "isac.h"
diff -Nru a/drivers/isdn/hisax/sedlbauer.c b/drivers/isdn/hisax/sedlbauer.c
--- a/drivers/isdn/hisax/sedlbauer.c	Mon Sep  9 10:36:11 2002
+++ b/drivers/isdn/hisax/sedlbauer.c	Mon Sep  9 10:36:11 2002
@@ -38,7 +38,6 @@
  * For example: hisaxctrl <DriverID> 9 ISAR.BIN
 */
 
-#define __NO_VERSION__
 #include <linux/init.h>
 #include <linux/config.h>
 #include "hisax.h"
diff -Nru a/drivers/isdn/hisax/sportster.c b/drivers/isdn/hisax/sportster.c
--- a/drivers/isdn/hisax/sportster.c	Mon Sep  9 10:36:01 2002
+++ b/drivers/isdn/hisax/sportster.c	Mon Sep  9 10:36:01 2002
@@ -12,7 +12,6 @@
  *
  *
  */
-#define __NO_VERSION__
 #include <linux/init.h>
 #include "hisax.h"
 #include "isac.h"
diff -Nru a/drivers/isdn/hisax/tei.c b/drivers/isdn/hisax/tei.c
--- a/drivers/isdn/hisax/tei.c	Mon Sep  9 10:36:13 2002
+++ b/drivers/isdn/hisax/tei.c	Mon Sep  9 10:36:13 2002
@@ -15,7 +15,6 @@
  *
  */
 
-#define __NO_VERSION__
 #include "hisax.h"
 #include "isdnl2.h"
 #include <linux/init.h>
diff -Nru a/drivers/isdn/hisax/teleint.c b/drivers/isdn/hisax/teleint.c
--- a/drivers/isdn/hisax/teleint.c	Mon Sep  9 10:36:18 2002
+++ b/drivers/isdn/hisax/teleint.c	Mon Sep  9 10:36:18 2002
@@ -10,7 +10,6 @@
  *
  */
 
-#define __NO_VERSION__
 #include <linux/init.h>
 #include "hisax.h"
 #include "isac.h"
diff -Nru a/drivers/isdn/hisax/teles0.c b/drivers/isdn/hisax/teles0.c
--- a/drivers/isdn/hisax/teles0.c	Mon Sep  9 10:36:11 2002
+++ b/drivers/isdn/hisax/teles0.c	Mon Sep  9 10:36:11 2002
@@ -15,7 +15,6 @@
  *
  */
 
-#define __NO_VERSION__
 #include <linux/init.h>
 #include "hisax.h"
 #include "isdnl1.h"
diff -Nru a/drivers/isdn/hisax/teles3.c b/drivers/isdn/hisax/teles3.c
--- a/drivers/isdn/hisax/teles3.c	Mon Sep  9 10:36:18 2002
+++ b/drivers/isdn/hisax/teles3.c	Mon Sep  9 10:36:18 2002
@@ -13,7 +13,6 @@
  *              Beat Doebeli
  *
  */
-#define __NO_VERSION__
 #include <linux/init.h>
 #include <linux/isapnp.h>
 #include "hisax.h"
diff -Nru a/drivers/isdn/hisax/telespci.c b/drivers/isdn/hisax/telespci.c
--- a/drivers/isdn/hisax/telespci.c	Mon Sep  9 10:36:13 2002
+++ b/drivers/isdn/hisax/telespci.c	Mon Sep  9 10:36:13 2002
@@ -12,7 +12,6 @@
  *
  */
 
-#define __NO_VERSION__
 #include <linux/init.h>
 #include <linux/config.h>
 #include "hisax.h"
diff -Nru a/drivers/isdn/hisax/w6692.c b/drivers/isdn/hisax/w6692.c
--- a/drivers/isdn/hisax/w6692.c	Mon Sep  9 10:36:13 2002
+++ b/drivers/isdn/hisax/w6692.c	Mon Sep  9 10:36:13 2002
@@ -12,7 +12,6 @@
 
 #include <linux/config.h>
 #include <linux/init.h>
-#define __NO_VERSION__
 #include "hisax.h"
 #include "w6692.h"
 #include "isdnl1.h"
diff -Nru a/drivers/isdn/hysdn/hysdn_net.c b/drivers/isdn/hysdn/hysdn_net.c
--- a/drivers/isdn/hysdn/hysdn_net.c	Mon Sep  9 10:35:56 2002
+++ b/drivers/isdn/hysdn/hysdn_net.c	Mon Sep  9 10:35:56 2002
@@ -13,7 +13,6 @@
  *
  */
 
-#define __NO_VERSION__
 #include <linux/module.h>
 #include <linux/version.h>
 #include <linux/signal.h>
diff -Nru a/drivers/isdn/hysdn/hysdn_procconf.c b/drivers/isdn/hysdn/hysdn_procconf.c
--- a/drivers/isdn/hysdn/hysdn_procconf.c	Mon Sep  9 10:36:01 2002
+++ b/drivers/isdn/hysdn/hysdn_procconf.c	Mon Sep  9 10:36:01 2002
@@ -11,7 +11,6 @@
  *
  */
 
-#define __NO_VERSION__
 #include <linux/module.h>
 #include <linux/version.h>
 #include <linux/poll.h>
diff -Nru a/drivers/isdn/hysdn/hysdn_proclog.c b/drivers/isdn/hysdn/hysdn_proclog.c
--- a/drivers/isdn/hysdn/hysdn_proclog.c	Mon Sep  9 10:36:01 2002
+++ b/drivers/isdn/hysdn/hysdn_proclog.c	Mon Sep  9 10:36:01 2002
@@ -10,7 +10,6 @@
  *
  */
 
-#define __NO_VERSION__
 #include <linux/module.h>
 #include <linux/version.h>
 #include <linux/poll.h>
diff -Nru a/drivers/isdn/i4l/isdn_ppp.c b/drivers/isdn/i4l/isdn_ppp.c
--- a/drivers/isdn/i4l/isdn_ppp.c	Mon Sep  9 10:36:12 2002
+++ b/drivers/isdn/i4l/isdn_ppp.c	Mon Sep  9 10:36:12 2002
@@ -109,8 +109,8 @@
 	struct ippp_struct *is;
 
 	if (lp->ppp_slot < 0 || lp->ppp_slot > ISDN_MAX_CHANNELS) {
-		printk(KERN_ERR __FUNCTION__": ppp_slot(%d) out of range\n",
-			lp->ppp_slot);
+		printk(KERN_ERR "%s: ppp_slot(%d) out of range\n",
+		       __FUNCTION__ , lp->ppp_slot);
 		return 0;
 	}
 
@@ -129,8 +129,8 @@
 	spin_unlock(&lp->netdev->pb->lock);
 #endif /* CONFIG_ISDN_MPP */
 	if (lp->ppp_slot < 0 || lp->ppp_slot > ISDN_MAX_CHANNELS) {
-		printk(KERN_ERR __FUNCTION__": ppp_slot(%d) now invalid\n",
-			lp->ppp_slot);
+		printk(KERN_ERR "%s: ppp_slot(%d) now invalid\n",
+		       __FUNCTION__ , lp->ppp_slot);
 		restore_flags(flags);
 		return 0;
 	}
@@ -231,8 +231,8 @@
 isdn_ppp_wakeup_daemon(isdn_net_local * lp)
 {
 	if (lp->ppp_slot < 0 || lp->ppp_slot >= ISDN_MAX_CHANNELS) {
-		printk(KERN_ERR __FUNCTION__": ppp_slot(%d) out of range\n",
-			lp->ppp_slot);
+		printk(KERN_ERR "%s: ppp_slot(%d) out of range\n",
+		       __FUNCTION__, lp->ppp_slot);
 		return;
 	}
 	ippp_table[lp->ppp_slot]->state = IPPP_OPEN | IPPP_CONNECT | IPPP_NOBLOCK;
@@ -250,8 +250,8 @@
 	struct ippp_struct *is;
 
 	if (slot < 0 || slot >= ISDN_MAX_CHANNELS) {
-		printk(KERN_ERR __FUNCTION__": slot(%d) out of range\n",
-			slot);
+		printk(KERN_ERR "%s: slot(%d) out of range\n",
+		       __FUNCTION__ , slot);
 		return 0;
 	}
 	is = ippp_table[slot];
@@ -351,7 +351,7 @@
 		isdn_net_dev *p = is->lp->netdev;
 
  		if (!p) {
- 			printk(KERN_ERR __FUNCTION__": no lp->netdev\n");
+ 			printk(KERN_ERR "%s: no lp->netdev\n", __FUNCTION__ );
 			unlock_kernel();
  			return 0;
  		}
@@ -706,7 +706,7 @@
  *           reports, that there is data
  */
 
-static int
+static ssize_t
 isdn_ppp_read(struct file *file, char *buf, size_t count, loff_t *off)
 {
 	struct ippp_struct *is;
@@ -765,7 +765,7 @@
  * ipppd wanna write a packet to the card .. non-blocking
  */
 
-static int
+static ssize_t
 isdn_ppp_write(struct file *file, const char *buf, size_t count, loff_t *off)
 {
 	isdn_net_local *lp;
@@ -1079,8 +1079,8 @@
 			if (is->debug & 0x20)
 				printk(KERN_DEBUG "isdn_ppp: VJC_UNCOMP\n");
 			if (net_dev->local.ppp_slot < 0) {
-				printk(KERN_ERR __FUNCTION__": net_dev->local->ppp_slot(%d) out of range\n",
-					net_dev->local.ppp_slot);
+				printk(KERN_ERR "%s: net_dev->local->ppp_slot(%d) out of range\n",
+				       __FUNCTION__ , net_dev->local.ppp_slot);
 				goto drop_packet;
 			}
 			if (slhc_remember(ippp_table[net_dev->local.ppp_slot]->slcomp, skb->data, skb->len) <= 0) {
@@ -1105,8 +1105,8 @@
 				skb_put(skb, skb_old->len + 128);
 				memcpy(skb->data, skb_old->data, skb_old->len);
 				if (net_dev->local.ppp_slot < 0) {
-					printk(KERN_ERR __FUNCTION__": net_dev->local->ppp_slot(%d) out of range\n",
-						net_dev->local.ppp_slot);
+					printk(KERN_ERR "%s: net_dev->local->ppp_slot(%d) out of range\n",
+					       __FUNCTION__ , net_dev->local.ppp_slot);
 					goto drop_packet;
 				}
 				pkt_len = slhc_uncompress(ippp_table[net_dev->local.ppp_slot]->slcomp,
@@ -1442,8 +1442,8 @@
 	struct ippp_struct * is;
 
 	if (lp->ppp_slot < 0) {
-		printk(KERN_ERR __FUNCTION__": lp->ppp_slot(%d) out of range\n",
-			lp->ppp_slot);
+		printk(KERN_ERR "%s: lp->ppp_slot(%d) out of range\n",
+		       __FUNCTION__ , lp->ppp_slot);
 		return(-EINVAL);
 	}
 
@@ -1493,8 +1493,8 @@
         stats = &mp->stats;
 	slot = lp->ppp_slot;
 	if (slot < 0 || slot > ISDN_MAX_CHANNELS) {
-		printk(KERN_ERR __FUNCTION__": lp->ppp_slot(%d)\n",
-			lp->ppp_slot);
+		printk(KERN_ERR "%s: lp->ppp_slot(%d)\n",
+		       __FUNCTION__, lp->ppp_slot);
 		stats->frame_drops++;
 		dev_kfree_skb(skb);
 		spin_unlock_irqrestore(&mp->lock, flags);
@@ -1530,8 +1530,8 @@
 	for (lpq = net_dev->queue;;) {
 		slot = lpq->ppp_slot;
 		if (slot < 0 || slot > ISDN_MAX_CHANNELS) {
-			printk(KERN_ERR __FUNCTION__": lpq->ppp_slot(%d)\n",
-				lpq->ppp_slot);
+			printk(KERN_ERR "%s: lpq->ppp_slot(%d)\n",
+			       __FUNCTION__ , lpq->ppp_slot);
 		} else {
 			u32 lls = ippp_table[slot]->last_link_seqno;
 			if (MP_LT(lls, minseq))
@@ -1764,8 +1764,8 @@
 	unsigned int tot_len;
 
 	if (lp->ppp_slot < 0 || lp->ppp_slot > ISDN_MAX_CHANNELS) {
-		printk(KERN_ERR __FUNCTION__": lp->ppp_slot(%d) out of range\n",
-			lp->ppp_slot);
+		printk(KERN_ERR "%s: lp->ppp_slot(%d) out of range\n",
+		       __FUNCTION__ , lp->ppp_slot);
 		return;
 	}
 	if( MP_FLAGS(from) == (MP_BEGIN_FRAG | MP_END_FRAG) ) {
@@ -2541,8 +2541,8 @@
 	printk(KERN_DEBUG "Received CCP frame from peer slot(%d)\n",
 		lp->ppp_slot);
 	if (lp->ppp_slot < 0 || lp->ppp_slot > ISDN_MAX_CHANNELS) {
-		printk(KERN_ERR __FUNCTION__": lp->ppp_slot(%d) out of range\n",
-			lp->ppp_slot);
+		printk(KERN_ERR "%s: lp->ppp_slot(%d) out of range\n",
+		       __FUNCTION__ , lp->ppp_slot);
 		return;
 	}
 	is = ippp_table[lp->ppp_slot];
@@ -2551,8 +2551,8 @@
 	if(lp->master) {
 		int slot = ((isdn_net_local *) (lp->master->priv))->ppp_slot;
 		if (slot < 0 || slot > ISDN_MAX_CHANNELS) {
-			printk(KERN_ERR __FUNCTION__": slot(%d) out of range\n",
-				slot);
+			printk(KERN_ERR "%s: slot(%d) out of range\n",
+			       __FUNCTION__ , slot);
 			return;
 		}	
 		mis = ippp_table[slot];
@@ -2715,8 +2715,8 @@
 	if(!skb || skb->len < 3)
 		return;
 	if (slot < 0 || slot > ISDN_MAX_CHANNELS) {
-		printk(KERN_ERR __FUNCTION__": lp->ppp_slot(%d) out of range\n",
-			slot);
+		printk(KERN_ERR "%s: lp->ppp_slot(%d) out of range\n",
+		       __FUNCTION__ , slot);
 		return;
 	}	
 	is = ippp_table[slot];
@@ -2738,8 +2738,8 @@
 	if (lp->master) {
 		slot = ((isdn_net_local *) (lp->master->priv))->ppp_slot;
 		if (slot < 0 || slot > ISDN_MAX_CHANNELS) {
-			printk(KERN_ERR __FUNCTION__": slot(%d) out of range\n",
-				slot);
+			printk(KERN_ERR "%s: slot(%d) out of range\n",
+			       __FUNCTION__ , slot);
 			return;
 		}	
 		mis = ippp_table[slot];
diff -Nru a/drivers/isdn/pcbit/drv.c b/drivers/isdn/pcbit/drv.c
--- a/drivers/isdn/pcbit/drv.c	Mon Sep  9 10:36:01 2002
+++ b/drivers/isdn/pcbit/drv.c	Mon Sep  9 10:36:01 2002
@@ -17,8 +17,6 @@
  *		
  */
 
-#define __NO_VERSION__
-
 #include <linux/module.h>
 
 #include <linux/sched.h>
@@ -430,7 +428,7 @@
 	switch(dev->l2_state) {
 	case L2_LWMODE:
 		/* check (size <= rdp_size); write buf into board */
-		if (len > BANK4 + 1)
+		if (len < 0 || len > BANK4 + 1 || len > 1024)
 		{
 			printk("pcbit_writecmd: invalid length %d\n", len);
 			return -EINVAL;
diff -Nru a/drivers/isdn/sc/command.c b/drivers/isdn/sc/command.c
--- a/drivers/isdn/sc/command.c	Mon Sep  9 10:36:01 2002
+++ b/drivers/isdn/sc/command.c	Mon Sep  9 10:36:01 2002
@@ -15,7 +15,6 @@
  *     +1 (416) 297-6433 Facsimile
  */
 
-#define __NO_VERSION__
 #include <linux/module.h>
 #include "includes.h"		/* This must be first */
 #include "hardware.h"
diff -Nru a/drivers/isdn/sc/event.c b/drivers/isdn/sc/event.c
--- a/drivers/isdn/sc/event.c	Mon Sep  9 10:36:12 2002
+++ b/drivers/isdn/sc/event.c	Mon Sep  9 10:36:12 2002
@@ -15,7 +15,6 @@
  *     +1 (416) 297-6433 Facsimile
  */
 
-#define __NO_VERSION__
 #include "includes.h"
 #include "hardware.h"
 #include "message.h"
diff -Nru a/drivers/isdn/sc/interrupt.c b/drivers/isdn/sc/interrupt.c
--- a/drivers/isdn/sc/interrupt.c	Mon Sep  9 10:36:12 2002
+++ b/drivers/isdn/sc/interrupt.c	Mon Sep  9 10:36:12 2002
@@ -15,7 +15,6 @@
  *     +1 (416) 297-6433 Facsimile
  */
 
-#define __NO_VERSION__
 #include "includes.h"
 #include "hardware.h"
 #include "message.h"
diff -Nru a/drivers/isdn/sc/ioctl.c b/drivers/isdn/sc/ioctl.c
--- a/drivers/isdn/sc/ioctl.c	Mon Sep  9 10:36:11 2002
+++ b/drivers/isdn/sc/ioctl.c	Mon Sep  9 10:36:11 2002
@@ -6,7 +6,6 @@
  *
  */
 
-#define __NO_VERSION__
 #include "includes.h"
 #include "hardware.h"
 #include "message.h"
diff -Nru a/drivers/isdn/sc/message.c b/drivers/isdn/sc/message.c
--- a/drivers/isdn/sc/message.c	Mon Sep  9 10:36:13 2002
+++ b/drivers/isdn/sc/message.c	Mon Sep  9 10:36:13 2002
@@ -17,7 +17,6 @@
  *     +1 (416) 297-6433 Facsimile
  */
 
-#define __NO_VERSION__
 #include "includes.h"
 #include "hardware.h"
 #include "message.h"
diff -Nru a/drivers/isdn/sc/packet.c b/drivers/isdn/sc/packet.c
--- a/drivers/isdn/sc/packet.c	Mon Sep  9 10:36:17 2002
+++ b/drivers/isdn/sc/packet.c	Mon Sep  9 10:36:17 2002
@@ -15,7 +15,6 @@
  *     +1 (416) 297-6433 Facsimile
  */
 
-#define __NO_VERSION__
 #include "includes.h"
 #include "hardware.h"
 #include "message.h"
diff -Nru a/drivers/isdn/sc/shmem.c b/drivers/isdn/sc/shmem.c
--- a/drivers/isdn/sc/shmem.c	Mon Sep  9 10:36:01 2002
+++ b/drivers/isdn/sc/shmem.c	Mon Sep  9 10:36:01 2002
@@ -17,7 +17,6 @@
  *     +1 (416) 297-6433 Facsimile
  */
 
-#define __NO_VERSION__
 #include "includes.h"		/* This must be first */
 #include "hardware.h"
 #include "card.h"
diff -Nru a/drivers/isdn/sc/timer.c b/drivers/isdn/sc/timer.c
--- a/drivers/isdn/sc/timer.c	Mon Sep  9 10:36:13 2002
+++ b/drivers/isdn/sc/timer.c	Mon Sep  9 10:36:13 2002
@@ -15,7 +15,6 @@
  *     +1 (416) 297-6433 Facsimile
  */
 
-#define __NO_VERSION__
 #include "includes.h"
 #include "hardware.h"
 #include "message.h"
diff -Nru a/drivers/md/md.c b/drivers/md/md.c
--- a/drivers/md/md.c	Mon Sep  9 10:36:01 2002
+++ b/drivers/md/md.c	Mon Sep  9 10:36:01 2002
@@ -103,11 +103,6 @@
 	{0}
 };
 
-/*
- * these have to be allocated separately because external
- * subsystems want to have a pre-defined structure
- */
-struct hd_struct md_hd_struct[MAX_MD_DEVS];
 static void md_recover_arrays(void);
 static mdk_thread_t *md_recovery_thread;
 
@@ -276,7 +271,7 @@
 	hd = get_gendisk (dev);
 	dname->name = NULL;
 	if (hd)
-		dname->name = disk_name (hd, minor(dev), dname->namebuf);
+		dname->name = disk_name(hd, minor(dev)-hd->first_minor, dname->namebuf);
 	if (!dname->name) {
 		sprintf (dname->namebuf, "[dev %s]", kdevname(dev));
 		dname->name = dname->namebuf;
@@ -618,7 +613,7 @@
 
 	export_array(mddev);
 	md_size[mdidx(mddev)] = 0;
-	md_hd_struct[mdidx(mddev)].nr_sects = 0;
+	set_capacity(disks[mdidx(mddev)], 0);
 }
 
 #undef BAD_CSUM
@@ -1458,8 +1453,6 @@
 	disk->minor_shift = 0;
 	sprintf(major_name, "md%d", mdidx(mddev));
 	disk->major_name = major_name;
-	disk->part = md_hd_struct + mdidx(mddev);
-	disk->nr_real = 1;
 	disk->fops = &md_fops;
 
 	mddev->pers = pers[pnum];
@@ -2344,7 +2337,7 @@
 			err = put_user (4, (char *) &loc->sectors);
 			if (err)
 				goto abort_unlock;
-			err = put_user (md_hd_struct[mdidx(mddev)].nr_sects/8,
+			err = put_user(get_capacity(disks[mdidx(mddev)])/8,
 						(short *) &loc->cylinders);
 			if (err)
 				goto abort_unlock;
@@ -2486,7 +2479,6 @@
 	 */
 
 	daemonize();
-	reparent_to_init();
 
 	sprintf(current->comm, thread->name);
 	current->exit_signal = SIGCHLD;
@@ -3179,11 +3171,10 @@
 		return (-1);
 	}
 	devfs_handle = devfs_mk_dir (NULL, "md", NULL);
-	/* we don't use devfs_register_series because we want to fill md_hd_struct */
 	for (minor=0; minor < MAX_MD_DEVS; ++minor) {
 		char devname[128];
 		sprintf (devname, "%u", minor);
-		md_hd_struct[minor].de = devfs_register (devfs_handle,
+		devfs_register (devfs_handle,
 			devname, DEVFS_FL_DEFAULT, MAJOR_NR, minor,
 			S_IFBLK | S_IRUSR | S_IWUSR, &md_fops, NULL);
 	}
diff -Nru a/drivers/message/i2o/Makefile b/drivers/message/i2o/Makefile
--- a/drivers/message/i2o/Makefile	Mon Sep  9 10:36:01 2002
+++ b/drivers/message/i2o/Makefile	Mon Sep  9 10:36:01 2002
@@ -5,7 +5,7 @@
 # In the future, some of these should be built conditionally.
 #
 
-export-objs	:= i2o_pci.o i2o_core.o i2o_config.o i2o_block.o i2o_lan.o i2o_scsi.o i2o_proc.o
+export-objs	:= i2o_core.o
 
 obj-$(CONFIG_I2O_PCI)	+= i2o_pci.o
 obj-$(CONFIG_I2O)	+= i2o_core.o i2o_config.o
diff -Nru a/drivers/message/i2o/i2o_block.c b/drivers/message/i2o/i2o_block.c
--- a/drivers/message/i2o/i2o_block.c	Mon Sep  9 10:36:13 2002
+++ b/drivers/message/i2o/i2o_block.c	Mon Sep  9 10:36:13 2002
@@ -186,7 +186,6 @@
 
 static struct i2ob_device i2ob_dev[MAX_I2OB<<4];
 static int i2ob_dev_count = 0;
-static struct hd_struct i2ob[MAX_I2OB<<4];
 static struct gendisk i2o_disk[MAX_I2OB];
 static char i2o_names[MAX_I2OB * 8];
 
@@ -248,7 +247,7 @@
  *	Turn a Linux block request into an I2O block read/write.
  */
 
-static int i2ob_send(u32 m, struct i2ob_device *dev, struct i2ob_request *ireq, u32 base, int unit)
+static int i2ob_send(u32 m, struct i2ob_device *dev, struct i2ob_request *ireq, int unit)
 {
 	struct i2o_controller *c = dev->controller;
 	int tid = dev->tid;
@@ -279,7 +278,7 @@
 		
 	/* This can be optimised later - just want to be sure its right for
 	   starters */
-	offset = ((u64)(req->sector+base)) << 9;
+	offset = ((u64)req->sector) << 9;
 	__raw_writel( offset & 0xFFFFFFFF, msg+24);
 	__raw_writel(offset>>32, msg+28);
 	mptr=msg+32;
@@ -724,7 +723,7 @@
 				register_disk(p,
 					      mk_kdev(p->major, p->first_minor),
 					      1<<p->minor_shift, p->fops,
-					      i2ob[unit].nr_sects);
+					      get_capacity(p));
 				break;
 			}
 
@@ -737,7 +736,6 @@
 			case I2O_EVT_IND_BSA_VOLUME_UNLOAD:
 			{
 				struct gendisk *p = &i2o_disk[unit>>4];
-				wipe_partitions(mk_kdev(MAJOR_NR, unit));
 				del_gendisk(p);
 				for(i = unit; i <= unit+15; i++)
 					blk_queue_max_sectors(i2ob_dev[i].req_queue, 0);
@@ -769,7 +767,7 @@
 					i2ob_query_device(&i2ob_dev[unit], 0x0000, 4, &size, 8);
 
 				spin_lock_irqsave(I2O_LOCK(unit), flags);	
-				i2ob[unit].nr_sects = size>>9;
+				set_capacity(&i2o_disk[unit>>4], size>>9);
 				spin_unlock_irqrestore(I2O_LOCK(unit), flags);	
 				break;
 			}
@@ -870,7 +868,7 @@
 			i2ob_backlog_tail[c->unit] = NULL;
 			
 		unit = minor(ireq->req->rq_dev);
-		i2ob_send(m, dev, ireq, i2ob[unit].start_sect, unit);
+		i2ob_send(m, dev, ireq, unit);
 	}
 	if(i2ob_backlog[c->unit])
 		return 1;
@@ -970,7 +968,7 @@
 		i2ob_queues[dev->unit]->i2ob_qhead = ireq->next;
 		ireq->req = req;
 
-		i2ob_send(m, dev, ireq, i2ob[unit].start_sect, (unit&0xF0));
+		i2ob_send(m, dev, ireq, (unit&0xF0));
 	}
 }
 
@@ -1039,7 +1037,7 @@
 		     unsigned int cmd, unsigned long arg)
 {
 	struct hd_geometry g;
-	int u = minor(inode->i_rdev) & 0xF0;
+	int u = minor(inode->i_rdev) >> 4;
 	/* Anyone capable of this syscall can do *real bad* things */
 
 	if (!capable(CAP_SYS_ADMIN))
@@ -1047,7 +1045,7 @@
 
 	if (cmd != HDIO_GETGEO)
 		return -EINVAL;
-	i2o_block_biosparam(i2ob[u].nr_sects, 
+	i2o_block_biosparam(get_capacity(&i2o_disk[u]),
 				&g.cylinders, &g.heads, &g.sectors);
 	g.start = get_start_sect(inode->i_bdev);
 	return copy_to_user((void *)arg, &g, sizeof(g)) ? -EFAULT : 0;
@@ -1223,7 +1221,7 @@
 	
 	i2ob_query_device(dev, 0x0000, 5, &flags, 4);
 	i2ob_query_device(dev, 0x0000, 6, &status, 4);
-	i2ob[unit].nr_sects = size>>9;
+	set_capacity(&i2o_disk[unit>>4], size>>9);
 
 	/* Set limit based on inbound frame size */
 	limit = (d->controller->status_block->inbound_frame_size - 8)/2;
@@ -1327,7 +1325,7 @@
 	i2o_event_register(c, d->lct_data.tid, i2ob_context, unit, 
 		(I2OB_EVENT_MASK & d->lct_data.event_capabilities));
 
-	i2ob[unit].nr_sects = size>>9;
+	set_capacity(i2o_disk[unit>>4], size>>9);
 	return 0;
 }
 
@@ -1472,7 +1470,7 @@
 					register_disk(p,
 						      mk_kdev(p->major, p->first_minor),
 						      1<<p->minor_shift, p->fops,
-						      i2ob[scan_unit].nr_sects);
+						      get_capacity(p));
 					scan_unit+=16;
 					i2ob_dev_count++;
 
@@ -1565,7 +1563,7 @@
 		register_disk(p,
 			      mk_kdev(p->major, p->first_minor),
 			      1<<p->minor_shift, p->fops,
-			      i2ob[unit].nr_sects);
+			      get_capacity(p));
 		i2ob_dev_count++;
 		i2o_device_notify_on(d, &i2o_block_handler);
 	}
@@ -1616,7 +1614,6 @@
 	 * This will force errors when i2ob_get_queue() is called
 	 * by the kenrel.
 	 */
-	wipe_partitions(mk_kdev(MAJOR_NR, unit));
 	del_gendisk(&i2o_disk[unit>>4]);
 	i2ob_dev[unit].req_queue = NULL;
 	for(i = unit; i <= unit+15; i++)
@@ -1773,9 +1770,7 @@
 		disk->major = MAJOR_NR;
 		disk->first_minor = i<<4;
 		disk->minor_shift = 4;
-		disk->part = i2ob + (i<<4);
 		disk->fops = &i2ob_fops;
-		disk->nr_real = 1;
 		disk->major_name = i2o_names + i*8;
 		sprintf(disk->major_name, "i2o/hd%c", 'a' + i);
 	}
diff -Nru a/drivers/mtd/devices/blkmtd.c b/drivers/mtd/devices/blkmtd.c
--- a/drivers/mtd/devices/blkmtd.c	Mon Sep  9 10:35:56 2002
+++ b/drivers/mtd/devices/blkmtd.c	Mon Sep  9 10:35:56 2002
@@ -304,7 +304,6 @@
   DEBUG(1, "blkmtd: writetask: starting (pid = %d)\n", tsk->pid);
   daemonize();
   strcpy(tsk->comm, "blkmtdd");
-  tsk->tty = NULL;
   spin_lock_irq(&tsk->sigmask_lock);
   sigfillset(&tsk->blocked);
   recalc_sigpending();
diff -Nru a/drivers/mtd/ftl.c b/drivers/mtd/ftl.c
--- a/drivers/mtd/ftl.c	Mon Sep  9 10:36:01 2002
+++ b/drivers/mtd/ftl.c	Mon Sep  9 10:36:01 2002
@@ -175,8 +175,6 @@
 #define XFER_PREPARED	0x03
 #define XFER_FAILED	0x04
 
-static struct hd_struct ftl_hd[MINOR_NR(MAX_DEV, 0, 0)];
-
 /*====================================================================*/
 
 static int ftl_ioctl(struct inode *inode, struct file *file,
@@ -846,7 +844,7 @@
     if (partition->state != FTL_FORMATTED)
 	return -ENXIO;
     
-    if (partition->disk->part[0].nr_sects == 0)
+    if (get_capacity(partition->disk) == 0)
 	return -ENXIO;
 
     if (!get_mtd_device(partition->mtd, -1))
@@ -1132,8 +1130,8 @@
 	int unit = minor(dev) >> 4;
 	partition_t *part = myparts[unit];
 	scan_header(part);
-	part->disk->part[0].nr_sects =
-		le32_to_cpu(part->header.FormattedSize)/SECTOR_SIZE);
+	set_capacity(part->disk,
+		le32_to_cpu(part->header.FormattedSize)/SECTOR_SIZE));
 	return 0;
 }
 
@@ -1252,9 +1250,7 @@
 	disk->first_minor = device << 4;
 	disk->major_name = name;
 	disk->minor_shift = PART_BITS;
-	disk->part = ftl_hd + (device << 4);
 	disk->fops = &ftl_blk_fops;
-	disk->nr_real = 1;
 	partition->mtd = mtd;
 	partition->disk = disk;
 
@@ -1298,7 +1294,6 @@
 				ftl_freepart(myparts[i]);
 			
 			myparts[i]->state = 0;
-			wipe_partitions(mk_kdev(MAJOR_NR, i<<4));
 			del_gendisk(myparts[i]->disk);
 			kfree(myparts[i]->disk->name);
 			kfree(myparts[i]->disk);
diff -Nru a/drivers/mtd/nftlcore.c b/drivers/mtd/nftlcore.c
--- a/drivers/mtd/nftlcore.c	Mon Sep  9 10:35:52 2002
+++ b/drivers/mtd/nftlcore.c	Mon Sep  9 10:35:52 2002
@@ -49,16 +49,6 @@
 
 /* Linux-specific block device functions */
 
-/* I _HATE_ the Linux block device setup more than anything else I've ever
- *  encountered, except ...
- */
-
-/* .. for the Linux partition table handling. */
-/* So why didn't you fucking go and clean it up? -- AV */
-struct hd_struct part_table[256];
-
-static struct block_device_operations nftl_fops;
-
 struct NFTLrecord *NFTLs[MAX_NFTLS];
 
 static void NFTL_setup(struct mtd_info *mtd)
@@ -150,9 +140,7 @@
 	gd->major = MAJOR_NR;
 	gd->first_minor = firstfree << NFTL_PARTN_BITS;
 	gd->minor_shift = NFTL_PARTN_BITS;
-	gd->part = part_table + (firstfree << NFTL_PARTN_BITS);
 	gd->major_name = name;
-	gd->nr_real = 1;
 	nftl->disk = gd;
 	add_gendisk(gd);
 	register_disk(gd, mk_kdev(MAJOR_NR,firstfree<<NFTL_PARTN_BITS),
@@ -847,10 +835,10 @@
 		down(&nftl->mutex);
 		DEBUG(MTD_DEBUG_LEVEL3, "Got mutex\n");
 
-		if (block + nsect > part_table[dev].nr_sects) {
+		if (block + nsect > get_capacity(nftl->disk)) {
 			/* access past the end of device */
 			printk("nftl%c%d: bad access: block = %d, count = %d\n",
-			       (minor(req->rq_dev)>>6)+'a', dev & 0xf, block, nsect);
+			       unit+'a', dev & 0xf, block, nsect);
 			up(&nftl->mutex);
 			res = 0; /* fail */
 			goto repeat;
diff -Nru a/drivers/net/8139too.c b/drivers/net/8139too.c
--- a/drivers/net/8139too.c	Mon Sep  9 10:35:43 2002
+++ b/drivers/net/8139too.c	Mon Sep  9 10:35:43 2002
@@ -1582,8 +1582,7 @@
 	struct rtl8139_private *tp = dev->priv;
 	unsigned long timeout;
 
-	daemonize ();
-	reparent_to_init();
+	daemonize();
 	spin_lock_irq(&current->sigmask_lock);
 	sigemptyset(&current->blocked);
 	recalc_sigpending();
diff -Nru a/drivers/net/ns83820.c b/drivers/net/ns83820.c
--- a/drivers/net/ns83820.c	Mon Sep  9 10:36:17 2002
+++ b/drivers/net/ns83820.c	Mon Sep  9 10:36:17 2002
@@ -1081,7 +1081,7 @@
 				   frag->page_offset,
 				   frag->size, PCI_DMA_TODEVICE);
 		dprintk("frag: buf=%08Lx  page=%08lx offset=%08lx\n",
-			(long long)buf, (long)(frag->page - mem_map),
+			(long long)buf, (long) page_to_pfn(frag->page),
 			frag->page_offset);
 		len = frag->size;
 		frag++;
diff -Nru a/drivers/net/ppp_generic.c b/drivers/net/ppp_generic.c
--- a/drivers/net/ppp_generic.c	Mon Sep  9 10:36:17 2002
+++ b/drivers/net/ppp_generic.c	Mon Sep  9 10:36:17 2002
@@ -1401,7 +1401,7 @@
 	if (skb->len > 0)
 		/* note: a 0-length skb is used as an error indication */
 		++ppp->stats.rx_length_errors;
-
+err:
 	kfree_skb(skb);
 	ppp_receive_error(ppp);
 }
diff -Nru a/drivers/net/tun.c b/drivers/net/tun.c
--- a/drivers/net/tun.c	Mon Sep  9 10:36:11 2002
+++ b/drivers/net/tun.c	Mon Sep  9 10:36:11 2002
@@ -513,12 +513,10 @@
 		return ret; 
  
 	if (on) {
+		ret = f_setown(file, current->pid, 0);
+		if (ret)
+			return ret;
 		tun->flags |= TUN_FASYNC;
-		if (!file->f_owner.pid) {
-			file->f_owner.pid  = current->pid;
-			file->f_owner.uid  = current->uid;
-			file->f_owner.euid = current->euid;
-		}
 	} else 
 		tun->flags &= ~TUN_FASYNC;
 
diff -Nru a/drivers/pci/probe.c b/drivers/pci/probe.c
--- a/drivers/pci/probe.c	Mon Sep  9 10:36:01 2002
+++ b/drivers/pci/probe.c	Mon Sep  9 10:36:01 2002
@@ -128,6 +128,13 @@
 	if (!dev)		/* It's a host bus, nothing to read */
 		return;
 
+	if (dev->transparent) {
+		printk("Transparent bridge - %s\n", dev->name);
+		for(i = 0; i < PCI_BUS_NUM_RESOURCES; i++)
+			child->resource[i] = child->parent->resource[i];
+		return;
+	}
+
 	for(i=0; i<3; i++)
 		child->resource[i] = &dev->resource[PCI_BRIDGE_RESOURCES+i];
 
@@ -149,13 +156,6 @@
 		res->flags = (io_base_lo & PCI_IO_RANGE_TYPE_MASK) | IORESOURCE_IO;
 		res->start = base;
 		res->end = limit + 0xfff;
-	} else {
-		/*
-		 * Ugh. We don't know enough about this bridge. Just assume
-		 * that it's entirely transparent.
-		 */
-		printk(KERN_ERR "Unknown bridge resource %d: assuming transparent\n", 0);
-		child->resource[0] = child->parent->resource[0];
 	}
 
 	res = child->resource[1];
@@ -167,10 +167,6 @@
 		res->flags = (mem_base_lo & PCI_MEMORY_RANGE_TYPE_MASK) | IORESOURCE_MEM;
 		res->start = base;
 		res->end = limit + 0xfffff;
-	} else {
-		/* See comment above. Same thing */
-		printk(KERN_ERR "Unknown bridge resource %d: assuming transparent\n", 1);
-		child->resource[1] = child->parent->resource[1];
 	}
 
 	res = child->resource[2];
@@ -197,10 +193,6 @@
 		res->flags = (mem_base_lo & PCI_MEMORY_RANGE_TYPE_MASK) | IORESOURCE_MEM | IORESOURCE_PREFETCH;
 		res->start = base;
 		res->end = limit + 0xfffff;
-	} else {
-		/* See comments above */
-		printk(KERN_ERR "Unknown bridge resource %d: assuming transparent\n", 2);
-		child->resource[2] = child->parent->resource[2];
 	}
 }
 
@@ -389,6 +381,10 @@
 	case PCI_HEADER_TYPE_BRIDGE:		    /* bridge header */
 		if (class != PCI_CLASS_BRIDGE_PCI)
 			goto bad;
+		/* The PCI-to-PCI bridge spec requires that subtractive
+		   decoding (i.e. transparent) bridge must have programming
+		   interface code of 0x01. */ 
+		dev->transparent = ((class & 0xff) == 1);
 		pci_read_bases(dev, 2, PCI_ROM_ADDRESS1);
 		break;
 
diff -Nru a/drivers/pci/quirks.c b/drivers/pci/quirks.c
--- a/drivers/pci/quirks.c	Mon Sep  9 10:35:55 2002
+++ b/drivers/pci/quirks.c	Mon Sep  9 10:35:55 2002
@@ -471,6 +471,11 @@
 	r -> end = 0xffffff;
 }
 
+static void __init quirk_transparent_bridge(struct pci_dev *dev)
+{
+	dev->transparent = 1;
+}
+
 /*
  *  The main table of quirks.
  */
@@ -525,6 +530,13 @@
 
 	{ PCI_FIXUP_FINAL, 	PCI_VENDOR_ID_AMD,	PCI_DEVICE_ID_AMD_VIPER_7410,	quirk_amd_ioapic },
 	{ PCI_FIXUP_FINAL,	PCI_VENDOR_ID_AMD,	PCI_DEVICE_ID_AMD_FE_GATE_700C, quirk_amd_ordering },
+	/*
+	 * i82380FB mobile docking controller: its PCI-to-PCI bridge
+	 * is subtractive decoding (transparent), and does indicate this
+	 * in the ProgIf. Unfortunately, the ProgIf value is wrong - 0x80
+	 * instead of 0x01.
+	 */
+	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82380FB,	quirk_transparent_bridge },
 
 	{ 0 }
 };
diff -Nru a/drivers/pci/setup-res.c b/drivers/pci/setup-res.c
--- a/drivers/pci/setup-res.c	Mon Sep  9 10:36:13 2002
+++ b/drivers/pci/setup-res.c	Mon Sep  9 10:36:13 2002
@@ -73,7 +73,7 @@
 	int i;
 
 	type_mask |= IORESOURCE_IO | IORESOURCE_MEM;
-	for (i = 0 ; i < 4; i++) {
+	for (i = 0 ; i < PCI_BUS_NUM_RESOURCES; i++) {
 		struct resource *r = bus->resource[i];
 		if (!r)
 			continue;
diff -Nru a/drivers/pcmcia/Makefile b/drivers/pcmcia/Makefile
--- a/drivers/pcmcia/Makefile	Mon Sep  9 10:36:01 2002
+++ b/drivers/pcmcia/Makefile	Mon Sep  9 10:36:01 2002
@@ -2,7 +2,7 @@
 # Makefile for the kernel pcmcia subsystem (c/o David Hinds)
 #
 
-export-objs := ds.o cs.o yenta.o sa1100_pcmcia.o
+export-objs := ds.o cs.o yenta.o sa1100_generic.o
 
 obj-$(CONFIG_PCMCIA)			+= pcmcia_core.o ds.o
 ifeq ($(CONFIG_CARDBUS),y)
diff -Nru a/drivers/pnp/pnpbios_core.c b/drivers/pnp/pnpbios_core.c
--- a/drivers/pnp/pnpbios_core.c	Mon Sep  9 10:35:55 2002
+++ b/drivers/pnp/pnpbios_core.c	Mon Sep  9 10:35:55 2002
@@ -126,12 +126,16 @@
 );
 
 #define Q_SET_SEL(cpu, selname, address, size) \
+do { \
 set_base(cpu_gdt_table[cpu][(selname) >> 3], __va((u32)(address))); \
-set_limit(&cpu_gdt_table[cpu][(selname) >> 3], size)
+set_limit(cpu_gdt_table[cpu][(selname) >> 3], size); \
+} while(0)
 
 #define Q2_SET_SEL(cpu, selname, address, size) \
+do { \
 set_base(cpu_gdt_table[cpu][(selname) >> 3], (u32)(address)); \
-set_limit(&cpu_gdt_table[cpu][(selname) >> 3], size)
+set_limit(cpu_gdt_table[cpu][(selname) >> 3], size); \
+} while(0)
 
 /*
  * At some point we want to use this stack frame pointer to unwind
@@ -612,7 +616,6 @@
 	static struct pnp_docking_station_info now;
 	int docked = -1, d = 0;
 	daemonize();
-	reparent_to_init();
 	strcpy(current->comm, "kpnpbiosd");
 	while(!unloading && !signal_pending(current))
 	{
diff -Nru a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c
--- a/drivers/s390/block/dasd.c	Mon Sep  9 10:36:11 2002
+++ b/drivers/s390/block/dasd.c	Mon Sep  9 10:36:11 2002
@@ -302,7 +302,7 @@
 	/* Add a proc directory and the dasd device entry to devfs. */
 	sprintf(buffer, "%04x", device->devinfo.devno);
 	dir = devfs_mk_dir(dasd_devfs_handle, buffer, device);
-	gdp->de_arr[0] = dir;
+	gdp->de = dir;
 	if (devmap->features & DASD_FEATURE_READONLY)
 		devfs_perm = S_IFBLK | S_IRUSR;
 	else
@@ -328,7 +328,7 @@
 		return;
 	/* Remove device entry and devfs directory. */
 	devfs_unregister(device->devfs_entry);
-	devfs_unregister(gdp->de_arr[0]);
+	devfs_unregister(gdp->de);
 
 	/* Forget the discipline information. */
 	device->discipline = NULL;
diff -Nru a/drivers/s390/block/dasd_genhd.c b/drivers/s390/block/dasd_genhd.c
--- a/drivers/s390/block/dasd_genhd.c	Mon Sep  9 10:36:13 2002
+++ b/drivers/s390/block/dasd_genhd.c	Mon Sep  9 10:36:13 2002
@@ -34,10 +34,7 @@
 	struct list_head list;
 	int major;
 	struct gendisk disks[DASD_PER_MAJOR];
-	devfs_handle_t de_arr[DASD_PER_MAJOR];
-	char flags[DASD_PER_MAJOR];
 	char names[DASD_PER_MAJOR * 8];
-	struct hd_struct part[1<<MINORBITS];
 };
 
 /*
@@ -106,11 +103,8 @@
 		disk->major = new_major;
 		disk->first_minor = i << DASD_PARTN_BITS;
 		disk->minor_shift = DASD_PARTN_BITS;
-		disk->nr_real = 1;
 		disk->fops = &dasd_device_operations;
-		disk->de_arr = mi->de_arr + i;
-		disk->flags = mi->flags + i;
-		disk->part = mi->part + (i << DASD_PARTN_BITS);
+		disk->flags = GENHD_FL_DEVFS;
 	}
 
 	/* Setup block device pointers for the new major. */
@@ -284,14 +278,6 @@
 	if (disk == NULL)
 		return;
 
-	wipe_partitions(device->kdev);
-
-	/*
-	 * This is confusing. The funcions is devfs_register_partitions
-	 * but the 1 as third parameter makes it do an unregister...
-	 * FIXME: there must be a better way to get rid of the devfs entries
-	 */
-	devfs_register_partitions(disk, minor(device->kdev), 1);
 	del_gendisk(disk);
 }
 
diff -Nru a/drivers/scsi/qlogicfc.c b/drivers/scsi/qlogicfc.c
--- a/drivers/scsi/qlogicfc.c	Mon Sep  9 10:36:13 2002
+++ b/drivers/scsi/qlogicfc.c	Mon Sep  9 10:36:13 2002
@@ -1342,18 +1342,11 @@
 
 	num_free = QLOGICFC_REQ_QUEUE_LEN - REQ_QUEUE_DEPTH(in_ptr, out_ptr);
 	num_free = (num_free > 2) ? num_free - 2 : 0;
-	host->can_queue = hostdata->queued + num_free;
+       host->can_queue = host->host_busy + num_free;
 	if (host->can_queue > QLOGICFC_REQ_QUEUE_LEN)
 		host->can_queue = QLOGICFC_REQ_QUEUE_LEN;
 	host->sg_tablesize = QLOGICFC_MAX_SG(num_free);
 
-	/* this is really gross */
-	if (host->can_queue <= host->host_busy){
-	        if (host->can_queue+2 < host->host_busy) 
-			DEBUG(printk("qlogicfc%d.c crosses its fingers.\n", hostdata->host_id));
-		host->can_queue = host->host_busy + 1;
-	}
-
 	LEAVE("isp2x00_queuecommand");
 
 	return 0;
@@ -1623,16 +1616,10 @@
 
 	num_free = QLOGICFC_REQ_QUEUE_LEN - REQ_QUEUE_DEPTH(in_ptr, out_ptr);
 	num_free = (num_free > 2) ? num_free - 2 : 0;
-	host->can_queue = hostdata->queued + num_free;
+       host->can_queue = host->host_busy + num_free;
 	if (host->can_queue > QLOGICFC_REQ_QUEUE_LEN)
 		host->can_queue = QLOGICFC_REQ_QUEUE_LEN;
 	host->sg_tablesize = QLOGICFC_MAX_SG(num_free);
-
-	if (host->can_queue <= host->host_busy){
-	        if (host->can_queue+2 < host->host_busy) 
-		        DEBUG(printk("qlogicfc%d : crosses its fingers.\n", hostdata->host_id));
-		host->can_queue = host->host_busy + 1;
-	}
 
 	outw(HCCR_CLEAR_RISC_INTR, host->io_port + HOST_HCCR);
 	LEAVE_INTR("isp2x00_intr_handler");
diff -Nru a/drivers/scsi/qlogicfc.h b/drivers/scsi/qlogicfc.h
--- a/drivers/scsi/qlogicfc.h	Mon Sep  9 10:36:07 2002
+++ b/drivers/scsi/qlogicfc.h	Mon Sep  9 10:36:07 2002
@@ -65,7 +65,7 @@
 #define DATASEGS_PER_COMMAND 2
 #define DATASEGS_PER_CONT 5
 
-#define QLOGICFC_REQ_QUEUE_LEN	127	/* must be power of two - 1 */
+#define QLOGICFC_REQ_QUEUE_LEN 255     /* must be power of two - 1 */
 #define QLOGICFC_MAX_SG(ql)	(DATASEGS_PER_COMMAND + (((ql) > 0) ? DATASEGS_PER_CONT*((ql) - 1) : 0))
 #define QLOGICFC_CMD_PER_LUN    8
 
diff -Nru a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c
--- a/drivers/scsi/scsi_error.c	Mon Sep  9 10:35:51 2002
+++ b/drivers/scsi/scsi_error.c	Mon Sep  9 10:35:51 2002
@@ -1878,7 +1878,6 @@
 	 */
 
 	daemonize();
-	reparent_to_init();
 
 	/*
 	 * Set the name of this process.
diff -Nru a/drivers/scsi/sd.c b/drivers/scsi/sd.c
--- a/drivers/scsi/sd.c	Mon Sep  9 10:36:01 2002
+++ b/drivers/scsi/sd.c	Mon Sep  9 10:36:01 2002
@@ -84,9 +84,6 @@
 
 #define SD_DSK_ARR_LUMP 6 /* amount to over allocate sd_dsk_arr by */
 
-
-struct hd_struct *sd;
-
 static Scsi_Disk ** sd_dsk_arr;
 static rwlock_t sd_dsk_arr_lock = RW_LOCK_UNLOCKED;
 
@@ -126,8 +123,6 @@
 
 static Scsi_Disk * sd_get_sdisk(int index);
 
-extern void driverfs_remove_partitions(struct gendisk *hd, int minor);
-
 #if defined(CONFIG_PPC32)
 /**
  *	sd_find_target - find kdev_t of first scsi disk that matches
@@ -288,6 +283,8 @@
 		return NULL;	/* No such device */
 }
 
+static struct gendisk **sd_disks;
+
 /**
  *	sd_init_command - build a scsi (read or write) command from
  *	information in the request structure.
@@ -323,7 +320,7 @@
 	/* >>>>> this change is not in the lk 2.5 series */
 	if (part_nr >= (sd_template.dev_max << 4) || (part_nr & 0xf) ||
 	    !sdp || !sdp->online ||
- 	    block + SCpnt->request->nr_sectors > sd[part_nr].nr_sects) {
+ 	    block + SCpnt->request->nr_sectors > get_capacity(sd_disks[dsk_nr])) {
 		SCSI_LOG_HLQUEUE(2, printk("Finishing %ld sectors\n", 
 				 SCpnt->request->nr_sectors));
 		SCSI_LOG_HLQUEUE(2, printk("Retry with 0x%p\n", SCpnt));
@@ -590,8 +587,6 @@
 	revalidate:		sd_revalidate
 };
 
-static struct gendisk **sd_disks;
-
 /**
  *	sd_rw_intr - bottom half handler: called when the lower level
  *	driver has completed (successfully or otherwise) a scsi command.
@@ -1007,6 +1002,28 @@
 	sdkp->device->sector_size = sector_size;
 }
 
+static int
+sd_do_mode_sense6(Scsi_Device *sdp, Scsi_Request *SRpnt,
+		  int modepage, unsigned char *buffer, int len) {
+	unsigned char cmd[8];
+
+	memset((void *) &cmd[0], 0, 8);
+	cmd[0] = MODE_SENSE;
+	cmd[1] = (sdp->scsi_level <= SCSI_2) ? ((sdp->lun << 5) & 0xe0) : 0;
+	cmd[2] = modepage;
+	cmd[4] = len;
+
+	SRpnt->sr_cmd_len = 0;
+	SRpnt->sr_sense_buffer[0] = 0;
+	SRpnt->sr_sense_buffer[2] = 0;
+	SRpnt->sr_data_direction = SCSI_DATA_READ;
+
+	scsi_wait_req(SRpnt, (void *) cmd, (void *) buffer,
+		      len, SD_TIMEOUT, MAX_RETRIES);
+
+	return SRpnt->sr_result;
+}
+
 /*
  * read write protect setting, if possible - called only in sd_init_onedisk()
  */
@@ -1014,50 +1031,38 @@
 sd_read_write_protect_flag(Scsi_Disk *sdkp, char *diskname,
 			   Scsi_Request *SRpnt, unsigned char *buffer) {
 	Scsi_Device *sdp = sdkp->device;
-	unsigned char cmd[8];
-	int the_result;
+	int res;
 
 	/*
-	 * For removable scsi disks we have to recognise the
-	 * Write Protect Flag. This flag is kept in the Scsi_Disk
-	 * struct and tested at open !
-	 * Daniel Roche ( dan@lectra.fr )
-	 *
-	 * Changed to get all pages (0x3f) rather than page 1 to
-	 * get around devices which do not have a page 1.  Since
-	 * we're only interested in the header anyway, this should
-	 * be fine.
-	 *   -- Matthew Dharm (mdharm-scsi@one-eyed-alien.net)
-	 *
-	 * As it turns out, some devices return an error for
-	 * every MODE_SENSE request except one for page 0.
-	 * So, we should also try that. --aeb
+	 * First attempt: ask for all pages (0x3F), but only 4 bytes.
+	 * We have to start carefully: some devices hang if we ask
+	 * for more than is available.
 	 */
+	res = sd_do_mode_sense6(sdp, SRpnt, 0x3F, buffer, 4);
 
-	memset((void *) &cmd[0], 0, 8);
-	cmd[0] = MODE_SENSE;
-	cmd[1] = (sdp->scsi_level <= SCSI_2) ?
-		((sdp->lun << 5) & 0xe0) : 0;
-	cmd[2] = 0x3f;	/* Get all pages */
-	cmd[4] = 255;   /* Ask for 255 bytes, even tho we want just the first 8 */
-	SRpnt->sr_cmd_len = 0;
-	SRpnt->sr_sense_buffer[0] = 0;
-	SRpnt->sr_sense_buffer[2] = 0;
-	SRpnt->sr_data_direction = SCSI_DATA_READ;
-
-	scsi_wait_req(SRpnt, (void *) cmd, (void *) buffer,
-		      255, SD_TIMEOUT, MAX_RETRIES);
+	/*
+	 * Second attempt: ask for page 0
+	 * When only page 0 is implemented, a request for page 3F may return
+	 * Sense Key 5: Illegal Request, Sense Code 24: Invalid field in CDB.
+	 */
+	if (res)
+		res = sd_do_mode_sense6(sdp, SRpnt, 0, buffer, 4);
 
-	the_result = SRpnt->sr_result;
+	/*
+	 * Third attempt: ask 255 bytes, as we did earlier.
+	 */
+	if (res)
+		res = sd_do_mode_sense6(sdp, SRpnt, 0x3F, buffer, 255);
 
-	if (the_result) {
-		printk("%s: test WP failed, assume Write Enabled\n",
-		       diskname);
-		/* alternatively, try page 0 */
+	if (res) {
+		printk(KERN_WARNING
+		       "%s: test WP failed, assume Write Enabled\n", diskname);
 	} else {
 		sdkp->write_prot = ((buffer[2] & 0x80) != 0);
 		printk(KERN_NOTICE "%s: Write Protect is %s\n", diskname,
 		       sdkp->write_prot ? "on" : "off");
+		printk(KERN_DEBUG "%s: Mode Sense: %02x %02x %02x %02x\n",
+		       diskname, buffer[0], buffer[1], buffer[2], buffer[3]);
 	}
 }
 
@@ -1197,12 +1202,10 @@
 	init_mem_lth(sd_disks, sd_template.dev_max);
 	if (sd_disks)
 		zero_mem_lth(sd_disks, sd_template.dev_max);
-	init_mem_lth(sd, maxparts);
 
-	if (!sd_dsk_arr || !sd || !sd_disks)
+	if (!sd_dsk_arr || !sd_disks)
 		goto cleanup_mem;
 
-	zero_mem_lth(sd, maxparts);
 	return 0;
 
 #undef init_mem_lth
@@ -1211,8 +1214,6 @@
 cleanup_mem:
 	vfree(sd_disks);
 	sd_disks = NULL;
-	vfree(sd);
-	sd = NULL;
 	if (sd_dsk_arr) {
                 for (k = 0; k < sd_template.dev_max; ++k)
 			vfree(sd_dsk_arr[k]);
@@ -1302,9 +1303,6 @@
 	unsigned long iflags;
 	struct {
 		struct gendisk disk;
-		devfs_handle_t de;
-		struct device *dev;
-		char flags;
 		char name[5];
 	} *p;
 	struct gendisk *gd;
@@ -1317,9 +1315,6 @@
 	if (!p)
 		return 1;
 	gd = &p->disk;
-	gd->de_arr = &p->de;
-	gd->flags = &p->flags;
-	gd->driverfs_dev_arr = &p->dev;
 
 	SCSI_LOG_HLQUEUE(3, printk("sd_attach: scsi device: <%d,%d,%d,%d>\n", 
 			 sdp->host->host_no, sdp->channel, sdp->id, sdp->lun));
@@ -1351,21 +1346,19 @@
 	}
 
 	sd_template.nr_dev++;
-	gd->nr_real = 1;
-        gd->de_arr[0] = sdp->de;
-        gd->driverfs_dev_arr[0] = &sdp->sdev_driverfs_dev;
+        gd->de = sdp->de;
 	gd->major = SD_MAJOR(dsk_nr>>4);
 	gd->first_minor = (dsk_nr & 15)<<4;
 	gd->minor_shift = 4;
-	gd->part = sd + (dsk_nr << 4);
 	gd->fops = &sd_fops;
 	if (dsk_nr > 26)
 		sprintf(p->name, "sd%c%c", 'a'+dsk_nr/26-1, 'a'+dsk_nr%26);
 	else
 		sprintf(p->name, "sd%c", 'a'+dsk_nr%26);
 	gd->major_name = p->name;
-        if (sdp->removable)
-		gd->flags[0] |= GENHD_FL_REMOVABLE;
+        gd->flags = sdp->removable ? GENHD_FL_REMOVABLE : 0;
+        gd->driverfs_dev = &sdp->sdev_driverfs_dev;
+        gd->flags |= GENHD_FL_DRIVERFS | GENHD_FL_DEVFS;
 	sd_disks[dsk_nr] = gd;
 	sd_dskname(dsk_nr, diskname);
 	printk(KERN_NOTICE "Attached scsi %sdisk %s at scsi%d, channel %d, "
@@ -1383,7 +1376,7 @@
 		return -ENODEV;
 
 	sd_init_onedisk(sdkp, dsk_nr);
-	sd_disks[dsk_nr]->part[0].nr_sects = sdkp->capacity;
+	set_capacity(sd_disks[dsk_nr], sdkp->capacity);
 	return 0;
 }
 
@@ -1425,10 +1418,6 @@
 	if (sdkp->has_been_registered) {
 		sdkp->has_been_registered = 0;
 		dev = MKDEV_SD(dsk_nr);
-		driverfs_remove_partitions(sd_disks[dsk_nr], minor(dev));
-		wipe_partitions(dev);
-		devfs_register_partitions (sd_disks[dsk_nr], minor(dev), 1);
-		/* unregister_disk() */
 		del_gendisk(sd_disks[dsk_nr]);
 	}
 	sdp->attached--;
@@ -1478,7 +1467,6 @@
 			vfree(sd_dsk_arr[k]);
 		vfree(sd_dsk_arr);
 	}
-	vfree((char *) sd);
 	for (k = 0; k < N_USED_SD_MAJORS; k++) {
 		blk_dev[SD_MAJOR(k)].queue = NULL;
 		blk_clear(SD_MAJOR(k));
diff -Nru a/drivers/scsi/sd.h b/drivers/scsi/sd.h
--- a/drivers/scsi/sd.h	Mon Sep  9 10:36:11 2002
+++ b/drivers/scsi/sd.h	Mon Sep  9 10:36:11 2002
@@ -20,8 +20,6 @@
 #include <linux/genhd.h>
 #endif
 
-extern struct hd_struct *sd;
-
 typedef struct scsi_disk {
 	unsigned capacity;		/* size in 512-byte sectors */
 	Scsi_Device *device;
diff -Nru a/drivers/scsi/sr.c b/drivers/scsi/sr.c
--- a/drivers/scsi/sr.c	Mon Sep  9 10:36:01 2002
+++ b/drivers/scsi/sr.c	Mon Sep  9 10:36:01 2002
@@ -87,25 +87,24 @@
 	init_command:sr_init_command
 };
 
-Scsi_CD *scsi_CDs;
-static int *sr_sizes;
+static Scsi_CD *scsi_CDs;
 
 static int sr_open(struct cdrom_device_info *, int);
-void get_sectorsize(int);
-void get_capabilities(int);
+static void get_sectorsize(Scsi_CD *);
+static void get_capabilities(Scsi_CD *);
 
 static int sr_media_change(struct cdrom_device_info *, int);
 static int sr_packet(struct cdrom_device_info *, struct cdrom_generic_command *);
 
 static void sr_release(struct cdrom_device_info *cdi)
 {
-	Scsi_CD *SCp = cdi->handle;
+	Scsi_CD *cd = cdi->handle;
 
-	if (SCp->device->sector_size > 2048)
-		sr_set_blocklength(minor(cdi->dev), 2048);
-	SCp->device->access_count--;
-	if (SCp->device->host->hostt->module)
-		__MOD_DEC_USE_COUNT(SCp->device->host->hostt->module);
+	if (cd->device->sector_size > 2048)
+		sr_set_blocklength(cd, 2048);
+	cd->device->access_count--;
+	if (cd->device->host->hostt->module)
+		__MOD_DEC_USE_COUNT(cd->device->host->hostt->module);
 	if (sr_template.module)
 		__MOD_DEC_USE_COUNT(sr_template.module);
 }
@@ -146,7 +145,7 @@
 
 int sr_media_change(struct cdrom_device_info *cdi, int slot)
 {
-	Scsi_CD *SCp = cdi->handle;
+	Scsi_CD *cd = cdi->handle;
 	int retval;
 
 	if (CDSL_CURRENT != slot) {
@@ -154,19 +153,19 @@
 		return -EINVAL;
 	}
 
-	retval = scsi_ioctl(SCp->device, SCSI_IOCTL_TEST_UNIT_READY, 0);
+	retval = scsi_ioctl(cd->device, SCSI_IOCTL_TEST_UNIT_READY, 0);
 	if (retval) {
 		/* Unable to test, unit probably not ready.  This usually
 		 * means there is no disc in the drive.  Mark as changed,
 		 * and we will figure it out later once the drive is
 		 * available again.  */
-		SCp->device->changed = 1;
+		cd->device->changed = 1;
 		return 1;	/* This will force a flush, if called from
 				 * check_disk_change */
 	};
 
-	retval = SCp->device->changed;
-	SCp->device->changed = 0;
+	retval = cd->device->changed;
+	cd->device->changed = 0;
 	/* If the disk changed, the capacity will now be different,
 	 * so we force a re-read of this information */
 	if (retval) {
@@ -180,8 +179,8 @@
 		 * be trying to use something that is too small if the disc
 		 * has changed.
 		 */
-		SCp->needs_sector_size = 1;
-		SCp->device->sector_size = 2048;
+		cd->needs_sector_size = 1;
+		cd->device->sector_size = 2048;
 	}
 	return retval;
 }
@@ -198,7 +197,7 @@
 	int good_sectors = (result == 0 ? this_count : 0);
 	int block_sectors = 0;
 	int device_nr = DEVICE_NR(SCpnt->request->rq_dev);
-	Scsi_CD *SCp = &scsi_CDs[device_nr];
+	Scsi_CD *cd = &scsi_CDs[device_nr];
 
 #ifdef DEBUG
 	printk("sr.c done: %x %p\n", result, SCpnt->request->bh->b_data);
@@ -223,7 +222,7 @@
 			block_sectors = bio_sectors(SCpnt->request->bio);
 		if (block_sectors < 4)
 			block_sectors = 4;
-		if (SCp->device->sector_size == 2048)
+		if (cd->device->sector_size == 2048)
 			error_sector <<= 2;
 		error_sector &= ~(block_sectors - 1);
 		good_sectors = error_sector - SCpnt->request->sector;
@@ -235,9 +234,9 @@
 		 * block.  Therefore, if we hit a medium error within the last
 		 * 75 2K sectors, we decrease the saved size value.
 		 */
-		if ((error_sector >> 1) < sr_sizes[device_nr] &&
-		    SCp->capacity - error_sector < 4 * 75)
-			sr_sizes[device_nr] = error_sector >> 1;
+		if (error_sector < get_capacity(cd->disk) &&
+		    cd->capacity - error_sector < 4 * 75)
+			set_capacity(cd->disk, error_sector);
 	}
 
 	/*
@@ -251,34 +250,34 @@
 
 static request_queue_t *sr_find_queue(kdev_t dev)
 {
-	Scsi_CD *SCp;
+	Scsi_CD *cd;
 
 	if (minor(dev) >= sr_template.dev_max)
 		return NULL;
-	SCp = &scsi_CDs[minor(dev)];
-	if (!SCp->device)
+	cd = &scsi_CDs[minor(dev)];
+	if (!cd->device)
 		return NULL;
-	return &SCp->device->request_queue;
+	return &cd->device->request_queue;
 }
 
 static int sr_init_command(Scsi_Cmnd * SCpnt)
 {
 	int dev, devm, block=0, this_count, s_size;
-	Scsi_CD *SCp;
+	Scsi_CD *cd;
 
 	devm = minor(SCpnt->request->rq_dev);
 	dev = DEVICE_NR(SCpnt->request->rq_dev);
-	SCp = &scsi_CDs[dev];
+	cd = &scsi_CDs[dev];
 
 	SCSI_LOG_HLQUEUE(1, printk("Doing sr request, dev = %d, block = %d\n", devm, block));
 
-	if (dev >= sr_template.nr_dev || !SCp->device || !SCp->device->online) {
+	if (dev >= sr_template.nr_dev || !cd->device || !cd->device->online) {
 		SCSI_LOG_HLQUEUE(2, printk("Finishing %ld sectors\n", SCpnt->request->nr_sectors));
 		SCSI_LOG_HLQUEUE(2, printk("Retry with 0x%p\n", SCpnt));
 		return 0;
 	}
 
-	if (SCp->device->changed) {
+	if (cd->device->changed) {
 		/*
 		 * quietly refuse to do anything to a changed disc until the
 		 * changed bit has been reset
@@ -295,10 +294,10 @@
 	 * we do lazy blocksize switching (when reading XA sectors,
 	 * see CDROMREADMODE2 ioctl) 
 	 */
-	s_size = SCp->device->sector_size;
+	s_size = cd->device->sector_size;
 	if (s_size > 2048) {
 		if (!in_interrupt())
-			sr_set_blocklength(DEVICE_NR(CURRENT->rq_dev), 2048);
+			sr_set_blocklength(cd, 2048);
 		else
 			printk("sr: can't switch blocksize: in interrupt\n");
 	}
@@ -309,7 +308,7 @@
 	}
 
 	if (rq_data_dir(SCpnt->request) == WRITE) {
-		if (!SCp->device->writeable)
+		if (!cd->device->writeable)
 			return 0;
 		SCpnt->cmnd[0] = WRITE_10;
 		SCpnt->sc_data_direction = SCSI_DATA_WRITE;
@@ -332,8 +331,8 @@
 	this_count = (SCpnt->request_bufflen >> 9) / (s_size >> 9);
 
 
-	SCSI_LOG_HLQUEUE(2, printk("sr%d : %s %d/%ld 512 byte blocks.\n",
-                                   devm,
+	SCSI_LOG_HLQUEUE(2, printk("%s : %s %d/%ld 512 byte blocks.\n",
+                                   cd->cdi.name,
 		   (rq_data_dir(SCpnt->request) == WRITE) ? "writing" : "reading",
 				 this_count, SCpnt->request->nr_sectors));
 
@@ -358,7 +357,7 @@
 	 * host adapter, it's safe to assume that we can at least transfer
 	 * this many bytes between each connect / disconnect.
 	 */
-	SCpnt->transfersize = SCp->device->sector_size;
+	SCpnt->transfersize = cd->device->sector_size;
 	SCpnt->underflow = this_count << 9;
 
 	SCpnt->allowed = MAX_RETRIES;
@@ -400,21 +399,20 @@
 
 static int sr_open(struct cdrom_device_info *cdi, int purpose)
 {
-	Scsi_CD *SCp = cdi->handle;
+	Scsi_CD *cd = cdi->handle;
 
-	if (minor(cdi->dev) >= sr_template.dev_max || !SCp->device) {
+	if (!cd->device)
 		return -ENXIO;	/* No such device */
-	}
 	/*
 	 * If the device is in error recovery, wait until it is done.
 	 * If the device is offline, then disallow any access to it.
 	 */
-	if (!scsi_block_when_processing_errors(SCp->device)) {
+	if (!scsi_block_when_processing_errors(cd->device)) {
 		return -ENXIO;
 	}
-	SCp->device->access_count++;
-	if (SCp->device->host->hostt->module)
-		__MOD_INC_USE_COUNT(SCp->device->host->hostt->module);
+	cd->device->access_count++;
+	if (cd->device->host->hostt->module)
+		__MOD_INC_USE_COUNT(cd->device->host->hostt->module);
 	if (sr_template.module)
 		__MOD_INC_USE_COUNT(sr_template.module);
 
@@ -423,8 +421,8 @@
 	 * this is the case, and try again.
 	 */
 
-	if (SCp->needs_sector_size)
-		get_sectorsize(minor(cdi->dev));
+	if (cd->needs_sector_size)
+		get_sectorsize(cd);
 
 	return 0;
 }
@@ -464,35 +462,32 @@
 	if (sr_template.nr_dev > sr_template.dev_max)
 		panic("scsi_devices corrupt (sr)");
 
-	printk("Attached scsi CD-ROM sr%d at scsi%d, channel %d, id %d, lun %d\n",
-	       i, SDp->host->host_no, SDp->channel, SDp->id, SDp->lun);
+	printk("Attached scsi CD-ROM %s at scsi%d, channel %d, id %d, lun %d\n",
+	       scsi_CDs[i].cdi.name, SDp->host->host_no, SDp->channel, SDp->id, SDp->lun);
 	return 0;
 }
 
 
-void get_sectorsize(int i)
+static void get_sectorsize(Scsi_CD *cd)
 {
 	unsigned char cmd[10];
 	unsigned char *buffer;
 	int the_result, retries = 3;
 	int sector_size;
 	Scsi_Request *SRpnt = NULL;
-	Scsi_CD *SCp;
 	request_queue_t *queue;
 
-	SCp = &scsi_CDs[i];
-
 	buffer = kmalloc(512, GFP_DMA);
 	if (!buffer)
 		goto Enomem;
-	SRpnt = scsi_allocate_request(SCp->device);
+	SRpnt = scsi_allocate_request(cd->device);
 	if (!SRpnt)
 		goto Enomem;
 
 	do {
 		cmd[0] = READ_CAPACITY;
-		cmd[1] = (SCp->device->scsi_level <= SCSI_2) ?
-			 ((SCp->device->lun << 5) & 0xe0) : 0;
+		cmd[1] = (cd->device->scsi_level <= SCSI_2) ?
+			 ((cd->device->lun << 5) & 0xe0) : 0;
 		memset((void *) &cmd[2], 0, 8);
 		SRpnt->sr_request->rq_status = RQ_SCSI_BUSY;	/* Mark as really busy */
 		SRpnt->sr_cmd_len = 0;
@@ -515,15 +510,15 @@
 	SRpnt = NULL;
 
 	if (the_result) {
-		SCp->capacity = 0x1fffff;
+		cd->capacity = 0x1fffff;
 		sector_size = 2048;	/* A guess, just in case */
-		SCp->needs_sector_size = 1;
+		cd->needs_sector_size = 1;
 	} else {
 #if 0
-		if (cdrom_get_last_written(&SCp->cdi,
-					   &SCp->capacity))
+		if (cdrom_get_last_written(&cd->cdi,
+					   &cd->capacity))
 #endif
-			SCp->capacity = 1 + ((buffer[0] << 24) |
+			cd->capacity = 1 + ((buffer[0] << 24) |
 						    (buffer[1] << 16) |
 						    (buffer[2] << 8) |
 						    buffer[3]);
@@ -542,45 +537,44 @@
 			sector_size = 2048;
 			/* fall through */
 		case 2048:
-			SCp->capacity *= 4;
+			cd->capacity *= 4;
 			/* fall through */
 		case 512:
 			break;
 		default:
-			printk("sr%d: unsupported sector size %d.\n",
-			       i, sector_size);
-			SCp->capacity = 0;
-			SCp->needs_sector_size = 1;
+			printk("%s: unsupported sector size %d.\n",
+			       cd->cdi.name, sector_size);
+			cd->capacity = 0;
+			cd->needs_sector_size = 1;
 		}
 
-		SCp->device->sector_size = sector_size;
+		cd->device->sector_size = sector_size;
 
 		/*
 		 * Add this so that we have the ability to correctly gauge
 		 * what the device is capable of.
 		 */
-		SCp->needs_sector_size = 0;
-		sr_sizes[i] = SCp->capacity >> (BLOCK_SIZE_BITS - 9);
+		cd->needs_sector_size = 0;
+		set_capacity(cd->disk, cd->capacity);
 	}
 
-	queue = &SCp->device->request_queue;
+	queue = &cd->device->request_queue;
 	blk_queue_hardsect_size(queue, sector_size);
 out:
 	kfree(buffer);
 	return;
 
 Enomem:
-	SCp->capacity = 0x1fffff;
+	cd->capacity = 0x1fffff;
 	sector_size = 2048;	/* A guess, just in case */
-	SCp->needs_sector_size = 1;
+	cd->needs_sector_size = 1;
 	if (SRpnt)
 		scsi_release_request(SRpnt);
 	goto out;
 }
 
-void get_capabilities(int i)
+void get_capabilities(Scsi_CD *cd)
 {
-	Scsi_CD *SCp;
 	unsigned char cmd[6];
 	unsigned char *buffer;
 	int rc, n;
@@ -597,7 +591,6 @@
 		""
 	};
 
-	SCp = &scsi_CDs[i];
 	buffer = kmalloc(512, GFP_DMA);
 	if (!buffer)
 	{
@@ -605,31 +598,31 @@
 		return;
 	}
 	cmd[0] = MODE_SENSE;
-	cmd[1] = (SCp->device->scsi_level <= SCSI_2) ?
-		 ((SCp->device->lun << 5) & 0xe0) : 0;
+	cmd[1] = (cd->device->scsi_level <= SCSI_2) ?
+		 ((cd->device->lun << 5) & 0xe0) : 0;
 	cmd[2] = 0x2a;
 	cmd[4] = 128;
 	cmd[3] = cmd[5] = 0;
-	rc = sr_do_ioctl(i, cmd, buffer, 128, 1, SCSI_DATA_READ, NULL);
+	rc = sr_do_ioctl(cd, cmd, buffer, 128, 1, SCSI_DATA_READ, NULL);
 
 	if (rc) {
 		/* failed, drive doesn't have capabilities mode page */
-		SCp->cdi.speed = 1;
-		SCp->cdi.mask |= (CDC_CD_R | CDC_CD_RW | CDC_DVD_R |
+		cd->cdi.speed = 1;
+		cd->cdi.mask |= (CDC_CD_R | CDC_CD_RW | CDC_DVD_R |
 					 CDC_DVD | CDC_DVD_RAM |
 					 CDC_SELECT_DISC | CDC_SELECT_SPEED);
 		kfree(buffer);
-		printk("sr%i: scsi-1 drive\n", i);
+		printk("%s: scsi-1 drive\n", cd->cdi.name);
 		return;
 	}
 	n = buffer[3] + 4;
-	SCp->cdi.speed = ((buffer[n + 8] << 8) + buffer[n + 9]) / 176;
-	SCp->readcd_known = 1;
-	SCp->readcd_cdda = buffer[n + 5] & 0x01;
+	cd->cdi.speed = ((buffer[n + 8] << 8) + buffer[n + 9]) / 176;
+	cd->readcd_known = 1;
+	cd->readcd_cdda = buffer[n + 5] & 0x01;
 	/* print some capability bits */
-	printk("sr%i: scsi3-mmc drive: %dx/%dx %s%s%s%s%s%s\n", i,
+	printk("%s: scsi3-mmc drive: %dx/%dx %s%s%s%s%s%s\n", cd->cdi.name,
 	       ((buffer[n + 14] << 8) + buffer[n + 15]) / 176,
-	       SCp->cdi.speed,
+	       cd->cdi.speed,
 	       buffer[n + 3] & 0x01 ? "writer " : "",	/* CD Writer */
 	       buffer[n + 3] & 0x20 ? "dvd-ram " : "",
 	       buffer[n + 2] & 0x02 ? "cd/rw " : "",	/* can read rewriteable */
@@ -638,38 +631,38 @@
 	       loadmech[buffer[n + 6] >> 5]);
 	if ((buffer[n + 6] >> 5) == 0)
 		/* caddy drives can't close tray... */
-		SCp->cdi.mask |= CDC_CLOSE_TRAY;
+		cd->cdi.mask |= CDC_CLOSE_TRAY;
 	if ((buffer[n + 2] & 0x8) == 0)
 		/* not a DVD drive */
-		SCp->cdi.mask |= CDC_DVD;
+		cd->cdi.mask |= CDC_DVD;
 	if ((buffer[n + 3] & 0x20) == 0) {
 		/* can't write DVD-RAM media */
-		SCp->cdi.mask |= CDC_DVD_RAM;
+		cd->cdi.mask |= CDC_DVD_RAM;
 	} else {
-		SCp->device->writeable = 1;
+		cd->device->writeable = 1;
 	}
 	if ((buffer[n + 3] & 0x10) == 0)
 		/* can't write DVD-R media */
-		SCp->cdi.mask |= CDC_DVD_R;
+		cd->cdi.mask |= CDC_DVD_R;
 	if ((buffer[n + 3] & 0x2) == 0)
 		/* can't write CD-RW media */
-		SCp->cdi.mask |= CDC_CD_RW;
+		cd->cdi.mask |= CDC_CD_RW;
 	if ((buffer[n + 3] & 0x1) == 0)
 		/* can't write CD-R media */
-		SCp->cdi.mask |= CDC_CD_R;
+		cd->cdi.mask |= CDC_CD_R;
 	if ((buffer[n + 6] & 0x8) == 0)
 		/* can't eject */
-		SCp->cdi.mask |= CDC_OPEN_TRAY;
+		cd->cdi.mask |= CDC_OPEN_TRAY;
 
 	if ((buffer[n + 6] >> 5) == mechtype_individual_changer ||
 	    (buffer[n + 6] >> 5) == mechtype_cartridge_changer)
-		SCp->cdi.capacity =
-		    cdrom_number_of_slots(&SCp->cdi);
-	if (SCp->cdi.capacity <= 1)
+		cd->cdi.capacity =
+		    cdrom_number_of_slots(&cd->cdi);
+	if (cd->cdi.capacity <= 1)
 		/* not a changer */
-		SCp->cdi.mask |= CDC_SELECT_DISC;
+		cd->cdi.mask |= CDC_SELECT_DISC;
 	/*else    I don't think it can close its tray
-		SCp->cdi.mask |= CDC_CLOSE_TRAY; */
+		cd->cdi.mask |= CDC_CLOSE_TRAY; */
 
 	kfree(buffer);
 }
@@ -680,14 +673,14 @@
  */
 static int sr_packet(struct cdrom_device_info *cdi, struct cdrom_generic_command *cgc)
 {
-	Scsi_CD *SCp = cdi->handle;
-	Scsi_Device *device = SCp->device;
+	Scsi_CD *cd = cdi->handle;
+	Scsi_Device *device = cd->device;
 	
 	/* set the LUN */
 	if (device->scsi_level <= SCSI_2)
 		cgc->cmd[1] |= device->lun << 5;
 
-	cgc->stat = sr_do_ioctl(minor(cdi->dev), cgc->cmd, cgc->buffer, cgc->buflen, cgc->quiet, cgc->data_direction, cgc->sense);
+	cgc->stat = sr_do_ioctl(cdi->handle, cgc->cmd, cgc->buffer, cgc->buflen, cgc->quiet, cgc->data_direction, cgc->sense);
 
 	return cgc->stat;
 }
@@ -696,6 +689,7 @@
 
 static int sr_init()
 {
+	int i;
 	if (sr_template.dev_noticed == 0)
 		return 0;
 
@@ -714,15 +708,10 @@
 	if (!scsi_CDs)
 		goto cleanup_dev;
 	memset(scsi_CDs, 0, sr_template.dev_max * sizeof(Scsi_CD));
-
-	sr_sizes = kmalloc(sr_template.dev_max * sizeof(int), GFP_ATOMIC);
-	if (!sr_sizes)
-		goto cleanup_cds;
-	memset(sr_sizes, 0, sr_template.dev_max * sizeof(int));
+	for (i = 0; i < sr_template.dev_max; i++)
+		sprintf(scsi_CDs[i].cdi.name, "sr%d", i);
 	return 0;
 
-cleanup_cds:
-	kfree(scsi_CDs);
 cleanup_dev:
 	unregister_blkdev(MAJOR_NR, "sr");
 	sr_registered--;
@@ -750,67 +739,80 @@
 void sr_finish()
 {
 	int i;
-	char name[6];
 
 	blk_dev[MAJOR_NR].queue = sr_find_queue;
-	blk_size[MAJOR_NR] = sr_sizes;
 
 	for (i = 0; i < sr_template.nr_dev; ++i) {
-		Scsi_CD *SCp = &scsi_CDs[i];
+		struct gendisk *disk;
+		Scsi_CD *cd = &scsi_CDs[i];
 		/* If we have already seen this, then skip it.  Comes up
 		 * with loadable modules. */
-		if (SCp->capacity)
+		if (cd->disk)
+			continue;
+		disk = kmalloc(sizeof(struct gendisk), GFP_KERNEL);
+		if (!disk)
 			continue;
-		SCp->capacity = 0x1fffff;
-		SCp->device->sector_size = 2048;/* A guess, just in case */
-		SCp->needs_sector_size = 1;
-		SCp->device->changed = 1;	/* force recheck CD type */
+		if (cd->disk) {
+			kfree(disk);
+			continue;
+		}
+		memset(disk, 0, sizeof(struct gendisk));
+		disk->major = MAJOR_NR;
+		disk->first_minor = i;
+		disk->minor_shift = 0;
+		disk->major_name = cd->cdi.name;
+		disk->fops = &sr_bdops;
+		cd->disk = disk;
+		cd->capacity = 0x1fffff;
+		cd->device->sector_size = 2048;/* A guess, just in case */
+		cd->needs_sector_size = 1;
+		cd->device->changed = 1;	/* force recheck CD type */
 #if 0
 		/* seems better to leave this for later */
-		get_sectorsize(i);
-		printk("Scd sectorsize = %d bytes.\n", SCp->sector_size);
+		get_sectorsize(cd);
+		printk("Scd sectorsize = %d bytes.\n", cd->sector_size);
 #endif
-		SCp->use = 1;
+		cd->use = 1;
 
-		SCp->device->ten = 1;
-		SCp->device->remap = 1;
-		SCp->readcd_known = 0;
-		SCp->readcd_cdda = 0;
-		sr_sizes[i] = SCp->capacity >> (BLOCK_SIZE_BITS - 9);
-
-		SCp->cdi.ops = &sr_dops;
-		SCp->cdi.handle = SCp;
-		SCp->cdi.dev = mk_kdev(MAJOR_NR, i);
-		SCp->cdi.mask = 0;
-		SCp->cdi.capacity = 1;
+		cd->device->ten = 1;
+		cd->device->remap = 1;
+		cd->readcd_known = 0;
+		cd->readcd_cdda = 0;
+
+		cd->cdi.ops = &sr_dops;
+		cd->cdi.handle = cd;
+		cd->cdi.dev = mk_kdev(MAJOR_NR, i);
+		cd->cdi.mask = 0;
+		cd->cdi.capacity = 1;
 		/*
 		 *	FIXME: someone needs to handle a get_capabilities
 		 *	failure properly ??
 		 */
-		get_capabilities(i);
-		sr_vendor_init(SCp);
+		get_capabilities(cd);
+		sr_vendor_init(cd);
 
-		sprintf(name, "sr%d", i);
-		strcpy(SCp->cdi.name, name);
-		sprintf(SCp->cdi.cdrom_driverfs_dev.bus_id, "%s:cd",
-			SCp->device->sdev_driverfs_dev.bus_id);
-		sprintf(SCp->cdi.cdrom_driverfs_dev.name, "%scdrom",
-			SCp->device->sdev_driverfs_dev.name);
-		SCp->cdi.cdrom_driverfs_dev.parent = 
-			&SCp->device->sdev_driverfs_dev;
-		SCp->cdi.cdrom_driverfs_dev.bus = &scsi_driverfs_bus_type;
-		SCp->cdi.cdrom_driverfs_dev.driver_data = 
+		sprintf(cd->cdi.cdrom_driverfs_dev.bus_id, "%s:cd",
+			cd->device->sdev_driverfs_dev.bus_id);
+		sprintf(cd->cdi.cdrom_driverfs_dev.name, "%scdrom",
+			cd->device->sdev_driverfs_dev.name);
+		cd->cdi.cdrom_driverfs_dev.parent = 
+			&cd->device->sdev_driverfs_dev;
+		cd->cdi.cdrom_driverfs_dev.bus = &scsi_driverfs_bus_type;
+		cd->cdi.cdrom_driverfs_dev.driver_data = 
 			(void *)(long)__mkdev(MAJOR_NR, i);
-		device_register(&SCp->cdi.cdrom_driverfs_dev);
-		device_create_file(&SCp->cdi.cdrom_driverfs_dev,
+		device_register(&cd->cdi.cdrom_driverfs_dev);
+		device_create_file(&cd->cdi.cdrom_driverfs_dev,
 				   &dev_attr_type);
-		device_create_file(&SCp->cdi.cdrom_driverfs_dev,
+		device_create_file(&cd->cdi.cdrom_driverfs_dev,
 				   &dev_attr_kdev);
-                SCp->cdi.de = devfs_register(SCp->device->de, "cd",
+                cd->cdi.de = devfs_register(cd->device->de, "cd",
                                     DEVFS_FL_DEFAULT, MAJOR_NR, i,
                                     S_IFBLK | S_IRUGO | S_IWUGO,
                                     &sr_bdops, NULL);
-		register_cdrom(&SCp->cdi);
+		register_cdrom(&cd->cdi);
+		add_gendisk(disk);
+		register_disk(disk, mk_kdev(disk->major, disk->first_minor),
+				1<<disk->minor_shift, disk->fops, cd->capacity);
 	}
 }
 
@@ -826,7 +828,9 @@
 			 * the device.
 			 * We should be kind to our buffer cache, however.
 			 */
-			invalidate_device(mk_kdev(MAJOR_NR, i), 0);
+			del_gendisk(cpnt->disk);
+			kfree(cpnt->disk);
+			cpnt->disk = NULL;
 
 			/*
 			 * Reset things back to a sane state so that one can
@@ -838,7 +842,6 @@
 			SDp->attached--;
 			sr_template.nr_dev--;
 			sr_template.dev_noticed--;
-			sr_sizes[i] = 0;
 			return;
 		}
 	}
@@ -861,12 +864,8 @@
 	scsi_unregister_device(&sr_template);
 	unregister_blkdev(MAJOR_NR, "sr");
 	sr_registered--;
-	if (scsi_CDs != NULL) {
+	if (scsi_CDs != NULL)
 		kfree(scsi_CDs);
-
-		kfree(sr_sizes);
-		sr_sizes = NULL;
-	}
 	blk_clear(MAJOR_NR);
 
 	sr_template.dev_max = 0;
diff -Nru a/drivers/scsi/sr.h b/drivers/scsi/sr.h
--- a/drivers/scsi/sr.h	Mon Sep  9 10:36:07 2002
+++ b/drivers/scsi/sr.h	Mon Sep  9 10:36:07 2002
@@ -18,6 +18,7 @@
 #define _SR_H
 
 #include "scsi.h"
+#include <linux/genhd.h>
 
 typedef struct {
 	unsigned capacity;	/* size in blocks                       */
@@ -30,11 +31,10 @@
 	unsigned readcd_known:1;	/* drive supports READ_CD (0xbe) */
 	unsigned readcd_cdda:1;	/* reading audio data using READ_CD */
 	struct cdrom_device_info cdi;
+	struct gendisk *disk;
 } Scsi_CD;
 
-extern Scsi_CD *scsi_CDs;
-
-int sr_do_ioctl(int, unsigned char *, void *, unsigned, int, int, struct request_sense *);
+int sr_do_ioctl(Scsi_CD *, unsigned char *, void *, unsigned, int, int, struct request_sense *);
 
 int sr_lock_door(struct cdrom_device_info *, int);
 int sr_tray_move(struct cdrom_device_info *, int);
@@ -47,12 +47,11 @@
 int sr_audio_ioctl(struct cdrom_device_info *, unsigned int, void *);
 int sr_dev_ioctl(struct cdrom_device_info *, unsigned int, unsigned long);
 
-int sr_read_sector(int minor, int lba, int blksize, unsigned char *dest);
-int sr_is_xa(int minor);
+int sr_is_xa(Scsi_CD *);
 
 /* sr_vendor.c */
 void sr_vendor_init(Scsi_CD *);
 int sr_cd_check(struct cdrom_device_info *);
-int sr_set_blocklength(int minor, int blocklength);
+int sr_set_blocklength(Scsi_CD *, int blocklength);
 
 #endif
diff -Nru a/drivers/scsi/sr_ioctl.c b/drivers/scsi/sr_ioctl.c
--- a/drivers/scsi/sr_ioctl.c	Mon Sep  9 10:36:12 2002
+++ b/drivers/scsi/sr_ioctl.c	Mon Sep  9 10:36:12 2002
@@ -24,8 +24,6 @@
  * It is off by default and can be turned on with this module parameter */
 static int xa_test = 0;
 
-extern void get_sectorsize(int);
-
 #define IOCTL_RETRIES 3
 /* The CDROM is fairly slow, so we need a little extra time */
 /* In fact, it is very slow if it has to spin up first */
@@ -69,14 +67,14 @@
 	sr_cmd[6] = trk1_te.cdte_addr.msf.minute;
 	sr_cmd[7] = trk1_te.cdte_addr.msf.second;
 	sr_cmd[8] = trk1_te.cdte_addr.msf.frame;
-	return sr_do_ioctl(minor(cdi->dev), sr_cmd, NULL, 0, 0, SCSI_DATA_NONE, NULL);
+	return sr_do_ioctl(cdi->handle, sr_cmd, NULL, 0, 0, SCSI_DATA_NONE, NULL);
 }
 
 /* We do our own retries because we want to know what the specific
    error code is.  Normally the UNIT_ATTENTION code will automatically
    clear after one error */
 
-int sr_do_ioctl(int target, unsigned char *sr_cmd, void *buffer, unsigned buflength, int quiet, int readwrite, struct request_sense *sense)
+int sr_do_ioctl(Scsi_CD *cd, unsigned char *sr_cmd, void *buffer, unsigned buflength, int quiet, int readwrite, struct request_sense *sense)
 {
 	Scsi_Request *SRpnt;
 	Scsi_Device *SDev;
@@ -84,7 +82,7 @@
 	int result, err = 0, retries = 0;
 	char *bounce_buffer;
 
-	SDev = scsi_CDs[target].device;
+	SDev = cd->device;
 	SRpnt = scsi_allocate_request(SDev);
         if (!SRpnt) {
                 printk("Unable to allocate SCSI request in sr_do_ioctl");
@@ -127,7 +125,7 @@
 		case UNIT_ATTENTION:
 			SDev->changed = 1;
 			if (!quiet)
-				printk(KERN_INFO "sr%d: disc change detected.\n", target);
+				printk(KERN_INFO "%s: disc change detected.\n", cd->cdi.name);
 			if (retries++ < 10)
 				goto retry;
 			err = -ENOMEDIUM;
@@ -137,7 +135,7 @@
 			    SRpnt->sr_sense_buffer[13] == 0x01) {
 				/* sense: Logical unit is in process of becoming ready */
 				if (!quiet)
-					printk(KERN_INFO "sr%d: CDROM not ready yet.\n", target);
+					printk(KERN_INFO "%s: CDROM not ready yet.\n", cd->cdi.name);
 				if (retries++ < 10) {
 					/* sleep 2 sec and try again */
 					scsi_sleep(2 * HZ);
@@ -149,7 +147,7 @@
 				}
 			}
 			if (!quiet)
-				printk(KERN_INFO "sr%d: CDROM not ready.  Make sure there is a disc in the drive.\n", target);
+				printk(KERN_INFO "%s: CDROM not ready.  Make sure there is a disc in the drive.\n", cd->cdi.name);
 #ifdef DEBUG
 			print_req_sense("sr", SRpnt);
 #endif
@@ -157,8 +155,8 @@
 			break;
 		case ILLEGAL_REQUEST:
 			if (!quiet)
-				printk(KERN_ERR "sr%d: CDROM (ioctl) reports ILLEGAL "
-				       "REQUEST.\n", target);
+				printk(KERN_ERR "%s: CDROM (ioctl) reports ILLEGAL "
+				       "REQUEST.\n", cd->cdi.name);
 			if (SRpnt->sr_sense_buffer[12] == 0x20 &&
 			    SRpnt->sr_sense_buffer[13] == 0x00) {
 				/* sense: Invalid command operation code */
@@ -172,7 +170,7 @@
 #endif
 			break;
 		default:
-			printk(KERN_ERR "sr%d: CDROM (ioctl) error, command: ", target);
+			printk(KERN_ERR "%s: CDROM (ioctl) error, command: ", cd->cdi.name);
 			print_command(sr_cmd);
 			print_req_sense("sr", SRpnt);
 			err = -EIO;
@@ -191,38 +189,36 @@
 /* ---------------------------------------------------------------------- */
 /* interface to cdrom.c                                                   */
 
-static int test_unit_ready(int minor)
+static int test_unit_ready(Scsi_CD *cd)
 {
-	Scsi_CD *SCp;
 	u_char sr_cmd[10];
 
-	SCp = &scsi_CDs[minor];
 	sr_cmd[0] = GPCMD_TEST_UNIT_READY;
-	sr_cmd[1] = (SCp->device->scsi_level <= SCSI_2) ?
-	            ((SCp->device->lun) << 5) : 0;
+	sr_cmd[1] = (cd->device->scsi_level <= SCSI_2) ?
+	            ((cd->device->lun) << 5) : 0;
 	sr_cmd[2] = sr_cmd[3] = sr_cmd[4] = sr_cmd[5] = 0;
-	return sr_do_ioctl(minor, sr_cmd, NULL, 0, 1, SCSI_DATA_NONE, NULL);
+	return sr_do_ioctl(cd, sr_cmd, NULL, 0, 1, SCSI_DATA_NONE, NULL);
 }
 
 int sr_tray_move(struct cdrom_device_info *cdi, int pos)
 {
-	Scsi_CD *SCp = cdi->handle;
+	Scsi_CD *cd = cdi->handle;
 	u_char sr_cmd[10];
 
 	sr_cmd[0] = GPCMD_START_STOP_UNIT;
-	sr_cmd[1] = (SCp->device->scsi_level <= SCSI_2) ?
-	            ((SCp->device->lun) << 5) : 0;
+	sr_cmd[1] = (cd->device->scsi_level <= SCSI_2) ?
+	            ((cd->device->lun) << 5) : 0;
 	sr_cmd[2] = sr_cmd[3] = sr_cmd[5] = 0;
 	sr_cmd[4] = (pos == 0) ? 0x03 /* close */ : 0x02 /* eject */ ;
 
-	return sr_do_ioctl(minor(cdi->dev), sr_cmd, NULL, 0, 0, SCSI_DATA_NONE, NULL);
+	return sr_do_ioctl(cd, sr_cmd, NULL, 0, 0, SCSI_DATA_NONE, NULL);
 }
 
 int sr_lock_door(struct cdrom_device_info *cdi, int lock)
 {
-	Scsi_CD *SCp = cdi->handle;
+	Scsi_CD *cd = cdi->handle;
 
-	return scsi_ioctl(SCp->device, lock ? SCSI_IOCTL_DOORLOCK :
+	return scsi_ioctl(cd->device, lock ? SCSI_IOCTL_DOORLOCK :
 			SCSI_IOCTL_DOORUNLOCK, 0);
 }
 
@@ -232,7 +228,7 @@
 		/* we have no changer support */
 		return -EINVAL;
 	}
-	if (0 == test_unit_ready(minor(cdi->dev)))
+	if (0 == test_unit_ready(cdi->handle))
 		return CDS_DISC_OK;
 
 	return CDS_TRAY_OPEN;
@@ -240,7 +236,7 @@
 
 int sr_disk_status(struct cdrom_device_info *cdi)
 {
-	Scsi_CD *SCp = cdi->handle;
+	Scsi_CD *cd = cdi->handle;
 	struct cdrom_tochdr toc_h;
 	struct cdrom_tocentry toc_e;
 	int i, rc, have_datatracks = 0;
@@ -262,7 +258,7 @@
 	if (!have_datatracks)
 		return CDS_AUDIO;
 
-	if (SCp->xa_flag)
+	if (cd->xa_flag)
 		return CDS_XA_2_1;
 	else
 		return CDS_DATA_1;
@@ -271,24 +267,24 @@
 int sr_get_last_session(struct cdrom_device_info *cdi,
 			struct cdrom_multisession *ms_info)
 {
-	Scsi_CD *SCp = cdi->handle;
+	Scsi_CD *cd = cdi->handle;
 
-	ms_info->addr.lba = SCp->ms_offset;
-	ms_info->xa_flag = SCp->xa_flag || SCp->ms_offset > 0;
+	ms_info->addr.lba = cd->ms_offset;
+	ms_info->xa_flag = cd->xa_flag || cd->ms_offset > 0;
 
 	return 0;
 }
 
 int sr_get_mcn(struct cdrom_device_info *cdi, struct cdrom_mcn *mcn)
 {
-	Scsi_CD *SCp = cdi->handle;
+	Scsi_CD *cd = cdi->handle;
 	u_char sr_cmd[10];
 	char buffer[32];
 	int result;
 
 	sr_cmd[0] = GPCMD_READ_SUBCHANNEL;
-	sr_cmd[1] = (SCp->device->scsi_level <= SCSI_2) ?
-	            ((SCp->device->lun) << 5) : 0;
+	sr_cmd[1] = (cd->device->scsi_level <= SCSI_2) ?
+	            ((cd->device->lun) << 5) : 0;
 	sr_cmd[2] = 0x40;	/* I do want the subchannel info */
 	sr_cmd[3] = 0x02;	/* Give me medium catalog number info */
 	sr_cmd[4] = sr_cmd[5] = 0;
@@ -297,7 +293,7 @@
 	sr_cmd[8] = 24;
 	sr_cmd[9] = 0;
 
-	result = sr_do_ioctl(minor(cdi->dev), sr_cmd, buffer, 24, 0, SCSI_DATA_READ, NULL);
+	result = sr_do_ioctl(cd, sr_cmd, buffer, 24, 0, SCSI_DATA_READ, NULL);
 
 	memcpy(mcn->medium_catalog_number, buffer + 9, 13);
 	mcn->medium_catalog_number[13] = 0;
@@ -307,13 +303,12 @@
 
 int sr_reset(struct cdrom_device_info *cdi)
 {
-	invalidate_buffers(cdi->dev);
 	return 0;
 }
 
 int sr_select_speed(struct cdrom_device_info *cdi, int speed)
 {
-	Scsi_CD *SCp = cdi->handle;
+	Scsi_CD *cd = cdi->handle;
 	u_char sr_cmd[MAX_COMMAND_SIZE];
 
 	if (speed == 0)
@@ -323,12 +318,12 @@
 
 	memset(sr_cmd, 0, MAX_COMMAND_SIZE);
 	sr_cmd[0] = GPCMD_SET_SPEED;	/* SET CD SPEED */
-	sr_cmd[1] = (SCp->device->scsi_level <= SCSI_2) ?
-	            ((SCp->device->lun) << 5) : 0;
+	sr_cmd[1] = (cd->device->scsi_level <= SCSI_2) ?
+	            ((cd->device->lun) << 5) : 0;
 	sr_cmd[2] = (speed >> 8) & 0xff;	/* MSB for speed (in kbytes/sec) */
 	sr_cmd[3] = speed & 0xff;	/* LSB */
 
-	if (sr_do_ioctl(minor(cdi->dev), sr_cmd, NULL, 0, 0, SCSI_DATA_NONE, NULL))
+	if (sr_do_ioctl(cd, sr_cmd, NULL, 0, 0, SCSI_DATA_NONE, NULL))
 		return -EIO;
 	return 0;
 }
@@ -341,9 +336,9 @@
 
 int sr_audio_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, void *arg)
 {
-	Scsi_CD *SCp = cdi->handle;
+	Scsi_CD *cd = cdi->handle;
 	u_char sr_cmd[10];
-	int result, target = minor(cdi->dev);
+	int result;
 	unsigned char buffer[32];
 
 	memset(sr_cmd, 0, sizeof(sr_cmd));
@@ -354,12 +349,12 @@
 			struct cdrom_tochdr *tochdr = (struct cdrom_tochdr *) arg;
 
 			sr_cmd[0] = GPCMD_READ_TOC_PMA_ATIP;
-			sr_cmd[1] = (SCp->device->scsi_level <= SCSI_2) ?
-			            ((SCp->device->lun) << 5) : 0;
+			sr_cmd[1] = (cd->device->scsi_level <= SCSI_2) ?
+			            ((cd->device->lun) << 5) : 0;
 			sr_cmd[2] = sr_cmd[3] = sr_cmd[4] = sr_cmd[5] = 0;
 			sr_cmd[8] = 12;		/* LSB of length */
 
-			result = sr_do_ioctl(target, sr_cmd, buffer, 12, 1, SCSI_DATA_READ, NULL);
+			result = sr_do_ioctl(cd, sr_cmd, buffer, 12, 1, SCSI_DATA_READ, NULL);
 
 			tochdr->cdth_trk0 = buffer[2];
 			tochdr->cdth_trk1 = buffer[3];
@@ -372,14 +367,14 @@
 			struct cdrom_tocentry *tocentry = (struct cdrom_tocentry *) arg;
 
 			sr_cmd[0] = GPCMD_READ_TOC_PMA_ATIP;
-			sr_cmd[1] = (SCp->device->scsi_level <= SCSI_2) ?
-			            ((SCp->device->lun) << 5) : 0;
+			sr_cmd[1] = (cd->device->scsi_level <= SCSI_2) ?
+			            ((cd->device->lun) << 5) : 0;
 			sr_cmd[1] |= (tocentry->cdte_format == CDROM_MSF) ? 0x02 : 0;
 			sr_cmd[2] = sr_cmd[3] = sr_cmd[4] = sr_cmd[5] = 0;
 			sr_cmd[6] = tocentry->cdte_track;
 			sr_cmd[8] = 12;		/* LSB of length */
 
-			result = sr_do_ioctl(target, sr_cmd, buffer, 12, 0, SCSI_DATA_READ, NULL);
+			result = sr_do_ioctl(cd, sr_cmd, buffer, 12, 0, SCSI_DATA_READ, NULL);
 
 			tocentry->cdte_ctrl = buffer[5] & 0xf;
 			tocentry->cdte_adr = buffer[5] >> 4;
@@ -399,14 +394,14 @@
 		struct cdrom_ti* ti = (struct cdrom_ti*)arg;
 
 		sr_cmd[0] = GPCMD_PLAYAUDIO_TI;
-		sr_cmd[1] = (SCp->device->scsi_level <= SCSI_2) ?
-		            (SCp->device->lun << 5) : 0;
+		sr_cmd[1] = (cd->device->scsi_level <= SCSI_2) ?
+		            (cd->device->lun << 5) : 0;
 		sr_cmd[4] = ti->cdti_trk0;
 		sr_cmd[5] = ti->cdti_ind0;
 		sr_cmd[7] = ti->cdti_trk1;
 		sr_cmd[8] = ti->cdti_ind1;
 
-		result = sr_do_ioctl(target, sr_cmd, NULL, 0, 0, SCSI_DATA_NONE, NULL);
+		result = sr_do_ioctl(cd, sr_cmd, NULL, 0, 0, SCSI_DATA_NONE, NULL);
 		if (result == -EDRIVE_CANT_DO_THIS)
 			result = sr_fake_playtrkind(cdi, ti);
 
@@ -439,20 +434,19 @@
  * blksize: 2048 | 2336 | 2340 | 2352
  */
 
-int sr_read_cd(int minor, unsigned char *dest, int lba, int format, int blksize)
+static int sr_read_cd(Scsi_CD *cd, unsigned char *dest, int lba, int format, int blksize)
 {
 	unsigned char cmd[MAX_COMMAND_SIZE];
-	Scsi_CD *SCp = &scsi_CDs[minor];
 
 #ifdef DEBUG
-	printk("sr%d: sr_read_cd lba=%d format=%d blksize=%d\n",
-	       minor, lba, format, blksize);
+	printk("%s: sr_read_cd lba=%d format=%d blksize=%d\n",
+	       cd->cdi.name, lba, format, blksize);
 #endif
 
 	memset(cmd, 0, MAX_COMMAND_SIZE);
 	cmd[0] = GPCMD_READ_CD;	/* READ_CD */
-	cmd[1] = (SCp->device->scsi_level <= SCSI_2) ?
-	         (SCp->device->lun << 5) : 0;
+	cmd[1] = (cd->device->scsi_level <= SCSI_2) ?
+	         (cd->device->lun << 5) : 0;
 	cmd[1] |= ((format & 7) << 2);
 	cmd[2] = (unsigned char) (lba >> 24) & 0xff;
 	cmd[3] = (unsigned char) (lba >> 16) & 0xff;
@@ -473,47 +467,46 @@
 		cmd[9] = 0x10;
 		break;
 	}
-	return sr_do_ioctl(minor, cmd, dest, blksize, 0, SCSI_DATA_READ, NULL);
+	return sr_do_ioctl(cd, cmd, dest, blksize, 0, SCSI_DATA_READ, NULL);
 }
 
 /*
  * read sectors with blocksizes other than 2048
  */
 
-int sr_read_sector(int minor, int lba, int blksize, unsigned char *dest)
+static int sr_read_sector(Scsi_CD *cd, int lba, int blksize, unsigned char *dest)
 {
 	unsigned char cmd[MAX_COMMAND_SIZE];	/* the scsi-command */
-	Scsi_CD *SCp = &scsi_CDs[minor];
 	int rc;
 
 	/* we try the READ CD command first... */
-	if (SCp->readcd_known) {
-		rc = sr_read_cd(minor, dest, lba, 0, blksize);
+	if (cd->readcd_known) {
+		rc = sr_read_cd(cd, dest, lba, 0, blksize);
 		if (-EDRIVE_CANT_DO_THIS != rc)
 			return rc;
-		SCp->readcd_known = 0;
+		cd->readcd_known = 0;
 		printk("CDROM does'nt support READ CD (0xbe) command\n");
 		/* fall & retry the other way */
 	}
 	/* ... if this fails, we switch the blocksize using MODE SELECT */
-	if (blksize != SCp->device->sector_size) {
-		if (0 != (rc = sr_set_blocklength(minor, blksize)))
+	if (blksize != cd->device->sector_size) {
+		if (0 != (rc = sr_set_blocklength(cd, blksize)))
 			return rc;
 	}
 #ifdef DEBUG
-	printk("sr%d: sr_read_sector lba=%d blksize=%d\n", minor, lba, blksize);
+	printk("%s: sr_read_sector lba=%d blksize=%d\n", cd->cdi.name, lba, blksize);
 #endif
 
 	memset(cmd, 0, MAX_COMMAND_SIZE);
 	cmd[0] = GPCMD_READ_10;
-	cmd[1] = (SCp->device->scsi_level <= SCSI_2) ?
-	         (SCp->device->lun << 5) : 0;
+	cmd[1] = (cd->device->scsi_level <= SCSI_2) ?
+	         (cd->device->lun << 5) : 0;
 	cmd[2] = (unsigned char) (lba >> 24) & 0xff;
 	cmd[3] = (unsigned char) (lba >> 16) & 0xff;
 	cmd[4] = (unsigned char) (lba >> 8) & 0xff;
 	cmd[5] = (unsigned char) lba & 0xff;
 	cmd[8] = 1;
-	rc = sr_do_ioctl(minor, cmd, dest, blksize, 0, SCSI_DATA_READ, NULL);
+	rc = sr_do_ioctl(cd, cmd, dest, blksize, 0, SCSI_DATA_READ, NULL);
 
 	return rc;
 }
@@ -523,10 +516,9 @@
  * ret: 1 == mode2 (XA), 0 == mode1, <0 == error 
  */
 
-int sr_is_xa(int minor)
+int sr_is_xa(Scsi_CD *cd)
 {
 	unsigned char *raw_sector;
-	Scsi_CD *SCp = &scsi_CDs[minor];
 	int is_xa;
 
 	if (!xa_test)
@@ -535,7 +527,7 @@
 	raw_sector = (unsigned char *) kmalloc(2048, GFP_DMA | GFP_KERNEL);
 	if (!raw_sector)
 		return -ENOMEM;
-	if (0 == sr_read_sector(minor, SCp->ms_offset + 16,
+	if (0 == sr_read_sector(cd, cd->ms_offset + 16,
 				CD_FRAMESIZE_RAW1, raw_sector)) {
 		is_xa = (raw_sector[3] == 0x02) ? 1 : 0;
 	} else {
@@ -544,7 +536,7 @@
 	}
 	kfree(raw_sector);
 #ifdef DEBUG
-	printk("sr%d: sr_is_xa: %d\n", minor, is_xa);
+	printk("%s: sr_is_xa: %d\n", cd->cdi.name, is_xa);
 #endif
 	return is_xa;
 }
@@ -552,16 +544,16 @@
 int sr_dev_ioctl(struct cdrom_device_info *cdi,
 		 unsigned int cmd, unsigned long arg)
 {
-	Scsi_CD *SCp = cdi->handle;
+	Scsi_CD *cd = cdi->handle;
 
 	switch (cmd) {
 	case BLKGETSIZE:
-		return put_user(SCp->capacity, (unsigned long *) arg);
+		return put_user(cd->capacity, (unsigned long *) arg);
 	case BLKGETSIZE64:
-		return put_user((u64)SCp->capacity << 9, (u64 *)arg);
+		return put_user((u64)cd->capacity << 9, (u64 *)arg);
 
 	default:
-		return scsi_ioctl(SCp->device, cmd, (void *)arg);
+		return scsi_ioctl(cd->device, cmd, (void *)arg);
 	}
 }
 
diff -Nru a/drivers/scsi/sr_vendor.c b/drivers/scsi/sr_vendor.c
--- a/drivers/scsi/sr_vendor.c	Mon Sep  9 10:36:11 2002
+++ b/drivers/scsi/sr_vendor.c	Mon Sep  9 10:36:11 2002
@@ -58,25 +58,25 @@
 #define VENDOR_TOSHIBA         3
 #define VENDOR_WRITER          4	/* pre-scsi3 writers */
 
-void sr_vendor_init(Scsi_CD *SCp)
+void sr_vendor_init(Scsi_CD *cd)
 {
 #ifndef CONFIG_BLK_DEV_SR_VENDOR
-	SCp->vendor = VENDOR_SCSI3;
+	cd->vendor = VENDOR_SCSI3;
 #else
-	char *vendor = SCp->device->vendor;
-	char *model = SCp->device->model;
+	char *vendor = cd->device->vendor;
+	char *model = cd->device->model;
 	
 	/* default */
-	SCp->vendor = VENDOR_SCSI3;
-	if (SCp->readcd_known)
+	cd->vendor = VENDOR_SCSI3;
+	if (cd->readcd_known)
 		/* this is true for scsi3/mmc drives - no more checks */
 		return;
 
-	if (SCp->device->type == TYPE_WORM) {
-		SCp->vendor = VENDOR_WRITER;
+	if (cd->device->type == TYPE_WORM) {
+		cd->vendor = VENDOR_WRITER;
 
 	} else if (!strncmp(vendor, "NEC", 3)) {
-		SCp->vendor = VENDOR_NEC;
+		cd->vendor = VENDOR_NEC;
 		if (!strncmp(model, "CD-ROM DRIVE:25", 15) ||
 		    !strncmp(model, "CD-ROM DRIVE:36", 15) ||
 		    !strncmp(model, "CD-ROM DRIVE:83", 15) ||
@@ -88,10 +88,10 @@
 #endif
 		    )
 			/* these can't handle multisession, may hang */
-			SCp->cdi.mask |= CDC_MULTI_SESSION;
+			cd->cdi.mask |= CDC_MULTI_SESSION;
 
 	} else if (!strncmp(vendor, "TOSHIBA", 7)) {
-		SCp->vendor = VENDOR_TOSHIBA;
+		cd->vendor = VENDOR_TOSHIBA;
 
 	}
 #endif
@@ -101,16 +101,15 @@
 /* small handy function for switching block length using MODE SELECT,
  * used by sr_read_sector() */
 
-int sr_set_blocklength(int minor, int blocklength)
+int sr_set_blocklength(Scsi_CD *cd, int blocklength)
 {
 	unsigned char *buffer;	/* the buffer for the ioctl */
 	unsigned char cmd[MAX_COMMAND_SIZE];	/* the scsi-command */
 	struct ccs_modesel_head *modesel;
-	Scsi_CD *SCp = &scsi_CDs[minor];
 	int rc, density = 0;
 
 #ifdef CONFIG_BLK_DEV_SR_VENDOR
-	if (SCp->vendor == VENDOR_TOSHIBA)
+	if (cd->vendor == VENDOR_TOSHIBA)
 		density = (blocklength > 2048) ? 0x81 : 0x83;
 #endif
 
@@ -119,12 +118,12 @@
 		return -ENOMEM;
 
 #ifdef DEBUG
-	printk("sr%d: MODE SELECT 0x%x/%d\n", minor, density, blocklength);
+	printk("%s: MODE SELECT 0x%x/%d\n", cd->cdi.name, density, blocklength);
 #endif
 	memset(cmd, 0, MAX_COMMAND_SIZE);
 	cmd[0] = MODE_SELECT;
-	cmd[1] = (SCp->device->scsi_level <= SCSI_2) ?
-	         (SCp->device->lun << 5) : 0;
+	cmd[1] = (cd->device->scsi_level <= SCSI_2) ?
+	         (cd->device->lun << 5) : 0;
 	cmd[1] |= (1 << 4);
 	cmd[4] = 12;
 	modesel = (struct ccs_modesel_head *) buffer;
@@ -133,13 +132,13 @@
 	modesel->density = density;
 	modesel->block_length_med = (blocklength >> 8) & 0xff;
 	modesel->block_length_lo = blocklength & 0xff;
-	if (0 == (rc = sr_do_ioctl(minor, cmd, buffer, sizeof(*modesel), 0, SCSI_DATA_WRITE, NULL))) {
-		SCp->device->sector_size = blocklength;
+	if (0 == (rc = sr_do_ioctl(cd, cmd, buffer, sizeof(*modesel), 0, SCSI_DATA_WRITE, NULL))) {
+		cd->device->sector_size = blocklength;
 	}
 #ifdef DEBUG
 	else
-		printk("sr%d: switching blocklength to %d bytes failed\n",
-		       minor, blocklength);
+		printk("%s: switching blocklength to %d bytes failed\n",
+		       cd->cdi.name, blocklength);
 #endif
 	kfree(buffer);
 	return rc;
@@ -152,14 +151,13 @@
 
 int sr_cd_check(struct cdrom_device_info *cdi)
 {
-	Scsi_CD *SCp = cdi->handle;
+	Scsi_CD *cd = cdi->handle;
 	unsigned long sector;
 	unsigned char *buffer;	/* the buffer for the ioctl */
 	unsigned char cmd[MAX_COMMAND_SIZE];	/* the scsi-command */
-	int rc, no_multi, minor;
+	int rc, no_multi;
 
-	minor = minor(cdi->dev);
-	if (SCp->cdi.mask & CDC_MULTI_SESSION)
+	if (cd->cdi.mask & CDC_MULTI_SESSION)
 		return 0;
 
 	buffer = (unsigned char *) kmalloc(512, GFP_KERNEL | GFP_DMA);
@@ -170,21 +168,21 @@
 	no_multi = 0;		/* flag: the drive can't handle multisession */
 	rc = 0;
 
-	switch (SCp->vendor) {
+	switch (cd->vendor) {
 
 	case VENDOR_SCSI3:
 		memset(cmd, 0, MAX_COMMAND_SIZE);
 		cmd[0] = READ_TOC;
-		cmd[1] = (SCp->device->scsi_level <= SCSI_2) ?
-		         (SCp->device->lun << 5) : 0;
+		cmd[1] = (cd->device->scsi_level <= SCSI_2) ?
+		         (cd->device->lun << 5) : 0;
 		cmd[8] = 12;
 		cmd[9] = 0x40;
-		rc = sr_do_ioctl(minor, cmd, buffer, 12, 1, SCSI_DATA_READ, NULL);
+		rc = sr_do_ioctl(cd, cmd, buffer, 12, 1, SCSI_DATA_READ, NULL);
 		if (rc != 0)
 			break;
 		if ((buffer[0] << 8) + buffer[1] < 0x0a) {
-			printk(KERN_INFO "sr%d: Hmm, seems the drive "
-			   "doesn't support multisession CD's\n", minor);
+			printk(KERN_INFO "%s: Hmm, seems the drive "
+			   "doesn't support multisession CD's\n", cd->cdi.name);
 			no_multi = 1;
 			break;
 		}
@@ -201,16 +199,17 @@
 			unsigned long min, sec, frame;
 			memset(cmd, 0, MAX_COMMAND_SIZE);
 			cmd[0] = 0xde;
-			cmd[1] = (SCp->device->scsi_level <= SCSI_2) ?
-			         (SCp->device->lun << 5) : 0;
+			cmd[1] = (cd->device->scsi_level <= SCSI_2) ?
+			         (cd->device->lun << 5) : 0;
 			cmd[1] |= 0x03;
 			cmd[2] = 0xb0;
-			rc = sr_do_ioctl(minor, cmd, buffer, 0x16, 1, SCSI_DATA_READ, NULL);
+			rc = sr_do_ioctl(cd, cmd, buffer, 0x16, 1, SCSI_DATA_READ, NULL);
 			if (rc != 0)
 				break;
 			if (buffer[14] != 0 && buffer[14] != 0xb0) {
-				printk(KERN_INFO "sr%d: Hmm, seems the cdrom "
-				       "doesn't support multisession CD's\n", minor);
+				printk(KERN_INFO "%s: Hmm, seems the cdrom "
+				       "doesn't support multisession CD's\n",
+				       cd->cdi.name);
 				no_multi = 1;
 				break;
 			}
@@ -228,13 +227,14 @@
 			 * where starts the last session ?) */
 			memset(cmd, 0, MAX_COMMAND_SIZE);
 			cmd[0] = 0xc7;
-			cmd[1] = (SCp->device->scsi_level <= SCSI_2) ?
-			         (SCp->device->lun << 5) : 0;
+			cmd[1] = (cd->device->scsi_level <= SCSI_2) ?
+			         (cd->device->lun << 5) : 0;
 			cmd[1] |= 0x03;
-			rc = sr_do_ioctl(minor, cmd, buffer, 4, 1, SCSI_DATA_READ, NULL);
+			rc = sr_do_ioctl(cd, cmd, buffer, 4, 1, SCSI_DATA_READ, NULL);
 			if (rc == -EINVAL) {
-				printk(KERN_INFO "sr%d: Hmm, seems the drive "
-				       "doesn't support multisession CD's\n", minor);
+				printk(KERN_INFO "%s: Hmm, seems the drive "
+				       "doesn't support multisession CD's\n",
+				       cd->cdi.name);
 				no_multi = 1;
 				break;
 			}
@@ -246,33 +246,33 @@
 			sector = min * CD_SECS * CD_FRAMES + sec * CD_FRAMES + frame;
 			if (sector)
 				sector -= CD_MSF_OFFSET;
-			sr_set_blocklength(minor, 2048);
+			sr_set_blocklength(cd, 2048);
 			break;
 		}
 
 	case VENDOR_WRITER:
 		memset(cmd, 0, MAX_COMMAND_SIZE);
 		cmd[0] = READ_TOC;
-		cmd[1] = (SCp->device->scsi_level <= SCSI_2) ?
-		         (SCp->device->lun << 5) : 0;
+		cmd[1] = (cd->device->scsi_level <= SCSI_2) ?
+		         (cd->device->lun << 5) : 0;
 		cmd[8] = 0x04;
 		cmd[9] = 0x40;
-		rc = sr_do_ioctl(minor, cmd, buffer, 0x04, 1, SCSI_DATA_READ, NULL);
+		rc = sr_do_ioctl(cd, cmd, buffer, 0x04, 1, SCSI_DATA_READ, NULL);
 		if (rc != 0) {
 			break;
 		}
 		if ((rc = buffer[2]) == 0) {
 			printk(KERN_WARNING
-			       "sr%d: No finished session\n", minor);
+			       "%s: No finished session\n", cd->cdi.name);
 			break;
 		}
 		cmd[0] = READ_TOC;	/* Read TOC */
-		cmd[1] = (SCp->device->scsi_level <= SCSI_2) ?
-		         (SCp->device->lun << 5) : 0;
+		cmd[1] = (cd->device->scsi_level <= SCSI_2) ?
+		         (cd->device->lun << 5) : 0;
 		cmd[6] = rc & 0x7f;	/* number of last session */
 		cmd[8] = 0x0c;
 		cmd[9] = 0x40;
-		rc = sr_do_ioctl(minor, cmd, buffer, 12, 1, SCSI_DATA_READ, NULL);
+		rc = sr_do_ioctl(cd, cmd, buffer, 12, 1, SCSI_DATA_READ, NULL);
 		if (rc != 0) {
 			break;
 		}
@@ -284,27 +284,27 @@
 	default:
 		/* should not happen */
 		printk(KERN_WARNING
-		   "sr%d: unknown vendor code (%i), not initialized ?\n",
-		       minor, SCp->vendor);
+		   "%s: unknown vendor code (%i), not initialized ?\n",
+		       cd->cdi.name, cd->vendor);
 		sector = 0;
 		no_multi = 1;
 		break;
 	}
-	SCp->ms_offset = sector;
-	SCp->xa_flag = 0;
-	if (CDS_AUDIO != sr_disk_status(cdi) && 1 == sr_is_xa(minor))
-		SCp->xa_flag = 1;
+	cd->ms_offset = sector;
+	cd->xa_flag = 0;
+	if (CDS_AUDIO != sr_disk_status(cdi) && 1 == sr_is_xa(cd))
+		cd->xa_flag = 1;
 
-	if (2048 != SCp->device->sector_size) {
-		sr_set_blocklength(minor, 2048);
+	if (2048 != cd->device->sector_size) {
+		sr_set_blocklength(cd, 2048);
 	}
 	if (no_multi)
 		cdi->mask |= CDC_MULTI_SESSION;
 
 #ifdef DEBUG
 	if (sector)
-		printk(KERN_DEBUG "sr%d: multisession offset=%lu\n",
-		       minor, sector);
+		printk(KERN_DEBUG "%s: multisession offset=%lu\n",
+		       cd->cdi.name, sector);
 #endif
 	kfree(buffer);
 	return rc;
diff -Nru a/drivers/scsi/st.c b/drivers/scsi/st.c
--- a/drivers/scsi/st.c	Mon Sep  9 10:36:12 2002
+++ b/drivers/scsi/st.c	Mon Sep  9 10:36:12 2002
@@ -184,7 +184,7 @@
 static int st_compression(Scsi_Tape *, int);
 
 static int find_partition(Scsi_Tape *);
-static int update_partition(Scsi_Tape *);
+static int switch_partition(Scsi_Tape *);
 
 static int st_int_ioctl(Scsi_Tape *, unsigned int, unsigned long);
 
@@ -1028,9 +1028,9 @@
 	}
 
 	if (STp->can_partitions &&
-	    (result2 = update_partition(STp)) < 0) {
+	    (result2 = switch_partition(STp)) < 0) {
                 DEBC(printk(ST_DEB_MSG
-                               "st%d: update_partition at close failed.\n", dev));
+                               "st%d: switch_partition at close failed.\n", dev));
 		if (result == 0)
 			result = result2;
 		goto out;
@@ -1206,7 +1206,7 @@
 	} ) /* end DEB */
 
 	if (STp->can_partitions &&
-	    (retval = update_partition(STp)) < 0)
+	    (retval = switch_partition(STp)) < 0)
 		goto out;
 
 	if (STp->block_size == 0 && STp->max_block > 0 &&
@@ -2904,7 +2904,7 @@
 
 
 /* Change the partition if necessary */
-static int update_partition(Scsi_Tape *STp)
+static int switch_partition(Scsi_Tape *STp)
 {
 	ST_partstat *STps;
 
@@ -3239,7 +3239,7 @@
 		}
 
 		if (STp->can_partitions && STp->ready == ST_READY &&
-		    (i = update_partition(STp)) < 0) {
+		    (i = switch_partition(STp)) < 0) {
 			retval = i;
 			goto out;
 		}
@@ -3260,7 +3260,7 @@
 		goto out;
 	}
 	if (STp->can_partitions &&
-	    (i = update_partition(STp)) < 0) {
+	    (i = switch_partition(STp)) < 0) {
 		retval = i;
 		goto out;
 	}
diff -Nru a/drivers/scsi/sym53c8xx.c b/drivers/scsi/sym53c8xx.c
--- a/drivers/scsi/sym53c8xx.c	Mon Sep  9 10:35:59 2002
+++ b/drivers/scsi/sym53c8xx.c	Mon Sep  9 10:35:59 2002
@@ -14115,7 +14115,7 @@
 	if (len)
 		return -EINVAL;
 	else {
-		long flags;
+		unsigned long flags;
 
 		NCR_LOCK_NCB(np, flags);
 		ncr_usercmd (np);
diff -Nru a/drivers/scsi/sym53c8xx_2/sym_glue.c b/drivers/scsi/sym53c8xx_2/sym_glue.c
--- a/drivers/scsi/sym53c8xx_2/sym_glue.c	Mon Sep  9 10:36:11 2002
+++ b/drivers/scsi/sym53c8xx_2/sym_glue.c	Mon Sep  9 10:36:11 2002
@@ -1686,7 +1686,7 @@
 	if (len)
 		return -EINVAL;
 	else {
-		long flags;
+		unsigned long flags;
 
 		SYM_LOCK_HCB(np, flags);
 		sym_exec_user_command (np, uc);
diff -Nru a/drivers/usb/storage/sddr09.c b/drivers/usb/storage/sddr09.c
--- a/drivers/usb/storage/sddr09.c	Mon Sep  9 10:36:13 2002
+++ b/drivers/usb/storage/sddr09.c	Mon Sep  9 10:36:13 2002
@@ -1443,36 +1443,27 @@
 	}
 
 	if (srb->cmnd[0] == MODE_SENSE) {
+		int modepage = (srb->cmnd[2] & 0x3F);
+		int len;
 
-		// Read-write error recovery page: there needs to
-		// be a check for write-protect here
+		/* They ask for the Read/Write error recovery page,
+		   or for all pages. Give as much as they have room for. */
+		if (modepage == 0x01 || modepage == 0x3F) {
 
-		if ( (srb->cmnd[2] & 0x3F) == 0x01 ) {
-
-			US_DEBUGP(
-				"SDDR09: Dummy up request for mode page 1\n");
+			US_DEBUGP("SDDR09: Dummy up request for "
+				  "mode page 0x%x\n", modepage);
 
-			if (ptr == NULL || 
-			    srb->request_bufflen<sizeof(mode_page_01))
+			if (ptr == NULL)
 				return USB_STOR_TRANSPORT_ERROR;
 
+			len = srb->request_bufflen;
+			if (len > sizeof(mode_page_01))
+				len = sizeof(mode_page_01);
+
 			mode_page_01[0] = sizeof(mode_page_01) - 1;
 			mode_page_01[2] = (info->flags & SDDR09_WP) ? 0x80 : 0;
-			memcpy(ptr, mode_page_01, sizeof(mode_page_01));
+			memcpy(ptr, mode_page_01, len);
 			return USB_STOR_TRANSPORT_GOOD;
-
-		} else if ( (srb->cmnd[2] & 0x3F) == 0x3F ) {
-
-			US_DEBUGP("SDDR09: Dummy up request for "
-				  "all mode pages\n");
-
-			if (ptr == NULL || 
-			    srb->request_bufflen<sizeof(mode_page_01))
-				return USB_STOR_TRANSPORT_ERROR;
-
-			memcpy(ptr, mode_page_01, sizeof(mode_page_01));
-			return USB_STOR_TRANSPORT_GOOD;
-
 		}
 
 		return USB_STOR_TRANSPORT_ERROR;
diff -Nru a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
--- a/drivers/usb/storage/usb.c	Mon Sep  9 10:36:01 2002
+++ b/drivers/usb/storage/usb.c	Mon Sep  9 10:36:01 2002
@@ -309,7 +309,6 @@
 	 * so get rid of all our resources..
 	 */
 	daemonize();
-	reparent_to_init();
 
 	/* avoid getting signals */
 	spin_lock_irq(&current->sigmask_lock);
diff -Nru a/drivers/video/Makefile b/drivers/video/Makefile
--- a/drivers/video/Makefile	Mon Sep  9 10:35:56 2002
+++ b/drivers/video/Makefile	Mon Sep  9 10:35:59 2002
@@ -6,12 +6,11 @@
 # This list comes from 'grep -l EXPORT_SYMBOL *.[hc]'.
 
 export-objs    	:= fbmem.o fbcmap.o fbcon.o fbmon.o modedb.o \
-		   fbcon-afb.o fbcon-ilbm.o fbcon-accel.o \
-		   fbcon-vga.o fbcon-iplan2p2.o fbcon-iplan2p4.o \
+		   fbcon-afb.o fbcon-ilbm.o fbcon-accel.o cyber2000fb.o \
+		   fbcon-iplan2p2.o fbcon-iplan2p4.o fbgen.o \
 		   fbcon-iplan2p8.o fbcon-vga-planes.o fbcon-cfb16.o \
 		   fbcon-cfb2.o fbcon-cfb24.o fbcon-cfb32.o fbcon-cfb4.o \
-		   fbcon-cfb8.o fbcon-mfb.o fbcon-hga.o \
-		   cyber2000fb.o sa1100fb.o fbgen.o
+		   fbcon-cfb8.o fbcon-mfb.o fbcon-hga.o
 
 # Each configuration option enables a list of files.
 
diff -Nru a/fs/Makefile b/fs/Makefile
--- a/fs/Makefile	Mon Sep  9 10:36:11 2002
+++ b/fs/Makefile	Mon Sep  9 10:36:11 2002
@@ -7,7 +7,8 @@
 
 O_TARGET := fs.o
 
-export-objs :=	open.o dcache.o buffer.o bio.o inode.o dquot.o mpage.o aio.o
+export-objs :=	open.o dcache.o buffer.o bio.o inode.o dquot.o mpage.o aio.o \
+                fcntl.o
 
 obj-y :=	open.o read_write.o devices.o file_table.o buffer.o \
 		bio.o super.o block_dev.o char_dev.o stat.o exec.o pipe.o \
diff -Nru a/fs/affs/file.c b/fs/affs/file.c
--- a/fs/affs/file.c	Mon Sep  9 10:36:11 2002
+++ b/fs/affs/file.c	Mon Sep  9 10:36:11 2002
@@ -27,6 +27,7 @@
 #include <linux/fs.h>
 #include <linux/amigaffs.h>
 #include <linux/mm.h>
+#include <linux/highmem.h>
 #include <linux/pagemap.h>
 #include <linux/buffer_head.h>
 
@@ -518,6 +519,7 @@
 	pr_debug("AFFS: read_page(%u, %ld, %d, %d)\n", (u32)inode->i_ino, page->index, from, to);
 	if (from > to || to > PAGE_CACHE_SIZE)
 		BUG();
+	kmap(page);
 	data = page_address(page);
 	bsize = AFFS_SB(sb)->s_data_blksize;
 	tmp = (page->index << PAGE_CACHE_SHIFT) + from;
@@ -537,6 +539,8 @@
 		from += tmp;
 		boff = 0;
 	}
+	flush_dcache_page(page);
+	kunmap(page);
 	return 0;
 }
 
@@ -656,7 +660,11 @@
 			return err;
 	}
 	if (to < PAGE_CACHE_SIZE) {
-		memset(page_address(page) + to, 0, PAGE_CACHE_SIZE - to);
+		char *kaddr = kmap_atomic(page, KM_USER0);
+
+		memset(kaddr + to, 0, PAGE_CACHE_SIZE - to);
+		flush_dcache_page(page);
+		kunmap_atomic(kaddr, KM_USER0);
 		if (size > offset + to) {
 			if (size < offset + PAGE_CACHE_SIZE)
 				tmp = size & ~PAGE_CACHE_MASK;
diff -Nru a/fs/aio.c b/fs/aio.c
--- a/fs/aio.c	Mon Sep  9 10:36:11 2002
+++ b/fs/aio.c	Mon Sep  9 10:36:11 2002
@@ -992,7 +992,7 @@
 			break;
 		}
 
-		if (unlikely(__copy_from_user(&tmp, user_iocb, sizeof(tmp)))) {
+		if (unlikely(copy_from_user(&tmp, user_iocb, sizeof(tmp)))) {
 			ret = -EFAULT;
 			break;
 		}
diff -Nru a/fs/binfmt_elf.c b/fs/binfmt_elf.c
--- a/fs/binfmt_elf.c	Mon Sep  9 10:36:11 2002
+++ b/fs/binfmt_elf.c	Mon Sep  9 10:36:11 2002
@@ -132,7 +132,7 @@
 	elf_addr_t *sp, *u_platform;
 	const char *k_platform = ELF_PLATFORM;
 	int items;
-	elf_addr_t elf_info[30];
+	elf_addr_t elf_info[40];
 	int ei_index = 0;
 
 	/*
diff -Nru a/fs/block_dev.c b/fs/block_dev.c
--- a/fs/block_dev.c	Mon Sep  9 10:36:18 2002
+++ b/fs/block_dev.c	Mon Sep  9 10:36:18 2002
@@ -503,21 +503,16 @@
 	struct block_device_operations * bdops = bdev->bd_op;
 	kdev_t dev = to_kdev_t(bdev->bd_dev);
 	struct gendisk *disk;
-	struct hd_struct *part;
 
 	if (bdops->check_media_change == NULL)
 		return 0;
 	if (!bdops->check_media_change(dev))
 		return 0;
 
-	printk(KERN_DEBUG "VFS: Disk change detected on device %s\n",
-		bdevname(bdev));
-
 	if (invalidate_device(dev, 0))
 		printk("VFS: busy inodes on changed media.\n");
 
 	disk = get_gendisk(dev);
-	part = disk->part + minor(dev) - disk->first_minor;
 	if (bdops->revalidate)
 		bdops->revalidate(dev);
 	if (disk && disk->minor_shift)
@@ -527,17 +522,13 @@
 
 int full_check_disk_change(struct block_device *bdev)
 {
-	int res;
+	int res = 0;
+	if (bdev->bd_contains != bdev)
+		BUG();
 	down(&bdev->bd_sem);
-	res = check_disk_change(bdev);
-	if (bdev->bd_invalidated && !bdev->bd_part_count) {
-		struct gendisk *g = get_gendisk(to_kdev_t(bdev->bd_dev));
-		struct hd_struct *part;
-		part = g->part + MINOR(bdev->bd_dev) - g->first_minor;
-		bdev->bd_invalidated = 0;
-		wipe_partitions(to_kdev_t(bdev->bd_dev));
-		if (part[0].nr_sects)
-			check_partition(g, bdev);
+	if (check_disk_change(bdev)) {
+		rescan_partitions(get_gendisk(to_kdev_t(bdev->bd_dev)), bdev);
+		res = 1;
 	}
 	up(&bdev->bd_sem);
 	return res;
@@ -602,8 +593,7 @@
 		struct gendisk *g = get_gendisk(dev);
 		bdev->bd_contains = bdev;
 		if (g) {
-			int shift = g->minor_shift;
-			unsigned minor0 = (minor >> shift) << shift;
+			unsigned minor0 = g->first_minor;
 			if (minor != minor0) {
 				struct block_device *disk;
 				disk = bdget(MKDEV(major(dev), minor0));
@@ -637,11 +627,9 @@
 			sector_t sect = 0;
 
 			bdev->bd_offset = 0;
-			if (g) {
-				struct hd_struct *p;
-				p = g->part + minor(dev) - g->first_minor;
-				sect = p->nr_sects;
-			} else if (blk_size[major(dev)])
+			if (g)
+				sect = get_capacity(g);
+			else if (blk_size[major(dev)])
 				sect = blk_size[major(dev)][minor(dev)] << 1;
 			bd_set_size(bdev, (loff_t)sect << 9);
 			bdi = blk_get_backing_dev_info(bdev);
@@ -650,21 +638,15 @@
 			inode->i_data.backing_dev_info = bdi;
 			bdev->bd_inode->i_data.backing_dev_info = bdi;
 		}
-		if (bdev->bd_invalidated && !bdev->bd_part_count) {
-			struct hd_struct *part;
-			part = g->part + minor(dev) - g->first_minor;
-			bdev->bd_invalidated = 0;
-			wipe_partitions(dev);
-			if (part[0].nr_sects)
-				check_partition(g, bdev);
-		}
+		if (bdev->bd_invalidated)
+			rescan_partitions(g, bdev);
 	} else {
 		down(&bdev->bd_contains->bd_sem);
 		bdev->bd_contains->bd_part_count++;
 		if (!bdev->bd_openers) {
 			struct gendisk *g = get_gendisk(dev);
 			struct hd_struct *p;
-			p = g->part + minor(dev) - g->first_minor;
+			p = g->part + minor(dev) - g->first_minor - 1;
 			inode->i_data.backing_dev_info =
 			   bdev->bd_inode->i_data.backing_dev_info =
 			   bdev->bd_contains->bd_inode->i_data.backing_dev_info;
@@ -792,27 +774,15 @@
 {
 	kdev_t dev = to_kdev_t(bdev->bd_dev);
 	struct gendisk *disk = get_gendisk(dev);
-	struct hd_struct *part;
-	int res;
+	int res = 0;
 
-	if (!disk || !disk->minor_shift)
+	if (!disk || !disk->minor_shift || bdev != bdev->bd_contains)
 		return -EINVAL;
-	part = disk->part + minor(dev) - disk->first_minor;
 	if (!capable(CAP_SYS_ADMIN))
 		return -EACCES;
 	if (down_trylock(&bdev->bd_sem))
 		return -EBUSY;
-	if (bdev->bd_part_count) {
-		up(&bdev->bd_sem);
-		return -EBUSY;
-	}
-	res = wipe_partitions(dev);
-	if (!res) {
-		if (bdev->bd_op->revalidate)
-			bdev->bd_op->revalidate(dev);
-		if (part[0].nr_sects)
-			check_partition(disk, bdev);
-	}
+	res = rescan_partitions(disk, bdev);
 	up(&bdev->bd_sem);
 	return res;
 }
diff -Nru a/fs/buffer.c b/fs/buffer.c
--- a/fs/buffer.c	Mon Sep  9 10:36:11 2002
+++ b/fs/buffer.c	Mon Sep  9 10:36:11 2002
@@ -1784,6 +1784,7 @@
 	if (err == 0)
 		return ret;
 	return err;
+
 recover:
 	/*
 	 * ENOSPC, or some other error.  We may already have added some
@@ -1795,7 +1796,8 @@
 	bh = head;
 	/* Recovery: lock and submit the mapped buffers */
 	do {
-		if (buffer_mapped(bh)) {
+		get_bh(bh);
+		if (buffer_mapped(bh) && buffer_dirty(bh)) {
 			lock_buffer(bh);
 			mark_buffer_async_write(bh);
 		} else {
@@ -1805,21 +1807,21 @@
 			 */
 			clear_buffer_dirty(bh);
 		}
-		bh = bh->b_this_page;
-	} while (bh != head);
+	} while ((bh = bh->b_this_page) != head);
+	SetPageError(page);
+	BUG_ON(PageWriteback(page));
+	SetPageWriteback(page);
+	unlock_page(page);
 	do {
 		struct buffer_head *next = bh->b_this_page;
 		if (buffer_async_write(bh)) {
-			set_buffer_uptodate(bh);
 			clear_buffer_dirty(bh);
 			submit_bh(WRITE, bh);
 			nr_underway++;
 		}
+		put_bh(bh);
 		bh = next;
 	} while (bh != head);
-	BUG_ON(PageWriteback(page));
-	SetPageWriteback(page);
-	unlock_page(page);
 	goto done;
 }
 
@@ -1831,7 +1833,6 @@
 	int err = 0;
 	unsigned blocksize, bbits;
 	struct buffer_head *bh, *head, *wait[2], **wait_bh=wait;
-	char *kaddr = kmap(page);
 
 	BUG_ON(!PageLocked(page));
 	BUG_ON(from > PAGE_CACHE_SIZE);
@@ -1872,13 +1873,19 @@
 					set_buffer_uptodate(bh);
 					continue;
 				}
-				if (block_end > to)
-					memset(kaddr+to, 0, block_end-to);
-				if (block_start < from)
-					memset(kaddr+block_start,
-						0, from-block_start);
-				if (block_end > to || block_start < from)
+				if (block_end > to || block_start < from) {
+					void *kaddr;
+
+					kaddr = kmap_atomic(page, KM_USER0);
+					if (block_end > to)
+						memset(kaddr+to, 0,
+							block_end-to);
+					if (block_start < from)
+						memset(kaddr+block_start,
+							0, from-block_start);
 					flush_dcache_page(page);
+					kunmap_atomic(kaddr, KM_USER0);
+				}
 				continue;
 			}
 		}
@@ -1917,10 +1924,14 @@
 		if (block_start >= to)
 			break;
 		if (buffer_new(bh)) {
+			void *kaddr;
+
 			clear_buffer_new(bh);
 			if (buffer_uptodate(bh))
 				buffer_error();
+			kaddr = kmap_atomic(page, KM_USER0);
 			memset(kaddr+block_start, 0, bh->b_size);
+			kunmap_atomic(kaddr, KM_USER0);
 			set_buffer_uptodate(bh);
 			mark_buffer_dirty(bh);
 		}
@@ -2006,9 +2017,10 @@
 					SetPageError(page);
 			}
 			if (!buffer_mapped(bh)) {
-				memset(kmap(page) + i*blocksize, 0, blocksize);
+				void *kaddr = kmap_atomic(page, KM_USER0);
+				memset(kaddr + i * blocksize, 0, blocksize);
 				flush_dcache_page(page);
-				kunmap(page);
+				kunmap_atomic(kaddr, KM_USER0);
 				set_buffer_uptodate(bh);
 				continue;
 			}
@@ -2116,7 +2128,7 @@
 	long status;
 	unsigned zerofrom;
 	unsigned blocksize = 1 << inode->i_blkbits;
-	char *kaddr;
+	void *kaddr;
 
 	while(page->index > (pgpos = *bytes>>PAGE_CACHE_SHIFT)) {
 		status = -ENOMEM;
@@ -2138,12 +2150,12 @@
 						PAGE_CACHE_SIZE, get_block);
 		if (status)
 			goto out_unmap;
-		kaddr = page_address(new_page);
+		kaddr = kmap_atomic(new_page, KM_USER0);
 		memset(kaddr+zerofrom, 0, PAGE_CACHE_SIZE-zerofrom);
 		flush_dcache_page(new_page);
+		kunmap_atomic(kaddr, KM_USER0);
 		__block_commit_write(inode, new_page,
 				zerofrom, PAGE_CACHE_SIZE);
-		kunmap(new_page);
 		unlock_page(new_page);
 		page_cache_release(new_page);
 	}
@@ -2168,21 +2180,20 @@
 	status = __block_prepare_write(inode, page, zerofrom, to, get_block);
 	if (status)
 		goto out1;
-	kaddr = page_address(page);
 	if (zerofrom < offset) {
+		kaddr = kmap_atomic(page, KM_USER0);
 		memset(kaddr+zerofrom, 0, offset-zerofrom);
 		flush_dcache_page(page);
+		kunmap_atomic(kaddr, KM_USER0);
 		__block_commit_write(inode, page, zerofrom, offset);
 	}
 	return 0;
 out1:
 	ClearPageUptodate(page);
-	kunmap(page);
 	return status;
 
 out_unmap:
 	ClearPageUptodate(new_page);
-	kunmap(new_page);
 	unlock_page(new_page);
 	page_cache_release(new_page);
 out:
@@ -2194,10 +2205,8 @@
 {
 	struct inode *inode = page->mapping->host;
 	int err = __block_prepare_write(inode, page, from, to, get_block);
-	if (err) {
+	if (err)
 		ClearPageUptodate(page);
-		kunmap(page);
-	}
 	return err;
 }
 
@@ -2205,7 +2214,6 @@
 {
 	struct inode *inode = page->mapping->host;
 	__block_commit_write(inode,page,from,to);
-	kunmap(page);
 	return 0;
 }
 
@@ -2215,7 +2223,6 @@
 	struct inode *inode = page->mapping->host;
 	loff_t pos = ((loff_t)page->index << PAGE_CACHE_SHIFT) + to;
 	__block_commit_write(inode,page,from,to);
-	kunmap(page);
 	if (pos > inode->i_size) {
 		inode->i_size = pos;
 		mark_inode_dirty(inode);
@@ -2232,6 +2239,7 @@
 	struct inode *inode = mapping->host;
 	struct page *page;
 	struct buffer_head *bh;
+	void *kaddr;
 	int err;
 
 	blocksize = 1 << inode->i_blkbits;
@@ -2284,9 +2292,10 @@
 			goto unlock;
 	}
 
-	memset(kmap(page) + offset, 0, length);
+	kaddr = kmap_atomic(page, KM_USER0);
+	memset(kaddr + offset, 0, length);
 	flush_dcache_page(page);
-	kunmap(page);
+	kunmap_atomic(kaddr, KM_USER0);
 
 	mark_buffer_dirty(bh);
 	err = 0;
@@ -2306,7 +2315,7 @@
 	struct inode * const inode = page->mapping->host;
 	const unsigned long end_index = inode->i_size >> PAGE_CACHE_SHIFT;
 	unsigned offset;
-	char *kaddr;
+	void *kaddr;
 
 	/* Is the page fully inside i_size? */
 	if (page->index < end_index)
@@ -2326,10 +2335,10 @@
 	 * the  page size, the remaining memory is zeroed when mapped, and
 	 * writes to that region are not written out to the file."
 	 */
-	kaddr = kmap(page);
+	kaddr = kmap_atomic(page, KM_USER0);
 	memset(kaddr + offset, 0, PAGE_CACHE_SIZE - offset);
 	flush_dcache_page(page);
-	kunmap(page);
+	kunmap_atomic(kaddr, KM_USER0);
 	return __block_write_full_page(inode, page, get_block);
 }
 
diff -Nru a/fs/dnotify.c b/fs/dnotify.c
--- a/fs/dnotify.c	Mon Sep  9 10:36:01 2002
+++ b/fs/dnotify.c	Mon Sep  9 10:36:01 2002
@@ -68,7 +68,7 @@
 	struct dnotify_struct **prev;
 	struct inode *inode;
 	fl_owner_t id = current->files;
-	int error;
+	int error = 0;
 
 	if ((arg & ~DN_MULTISHOT) == 0) {
 		dnotify_flush(filp, id);
@@ -89,21 +89,15 @@
 			odn->dn_fd = fd;
 			odn->dn_mask |= arg;
 			inode->i_dnotify_mask |= arg & ~DN_MULTISHOT;
-			kmem_cache_free(dn_cache, dn);
-			goto out;
+			goto out_free;
 		}
 		prev = &odn->dn_next;
 	}
 
-	error = security_ops->file_set_fowner(filp);
-	if (error) {
-		write_unlock(&dn_lock);
-		return error;
-	}
+	error = f_setown(filp, current->pid, 1);
+	if (error)
+		goto out_free;
 
-	filp->f_owner.pid = current->pid;
-	filp->f_owner.uid = current->uid;
-	filp->f_owner.euid = current->euid;
 	dn->dn_mask = arg;
 	dn->dn_fd = fd;
 	dn->dn_filp = filp;
@@ -113,7 +107,10 @@
 	inode->i_dnotify = dn;
 out:
 	write_unlock(&dn_lock);
-	return 0;
+	return error;
+out_free:
+	kmem_cache_free(dn_cache, dn);
+	goto out;
 }
 
 void __inode_dir_notify(struct inode *inode, unsigned long event)
@@ -131,8 +128,7 @@
 			continue;
 		}
 		fown = &dn->dn_filp->f_owner;
-		if (fown->pid)
-		        send_sigio(fown, dn->dn_fd, POLL_MSG);
+		send_sigio(fown, dn->dn_fd, POLL_MSG);
 		if (dn->dn_mask & DN_MULTISHOT)
 			prev = &dn->dn_next;
 		else {
diff -Nru a/fs/driverfs/inode.c b/fs/driverfs/inode.c
--- a/fs/driverfs/inode.c	Mon Sep  9 10:35:59 2002
+++ b/fs/driverfs/inode.c	Mon Sep  9 10:35:59 2002
@@ -59,9 +59,11 @@
 static int driverfs_readpage(struct file *file, struct page * page)
 {
 	if (!PageUptodate(page)) {
-		memset(kmap(page), 0, PAGE_CACHE_SIZE);
-		kunmap(page);
+		void *kaddr = kmap_atomic(page, KM_USER0);
+
+		memset(kaddr, 0, PAGE_CACHE_SIZE);
 		flush_dcache_page(page);
+		kunmap_atomic(kaddr, KM_USER0);
 		SetPageUptodate(page);
 	}
 	unlock_page(page);
@@ -70,10 +72,12 @@
 
 static int driverfs_prepare_write(struct file *file, struct page *page, unsigned offset, unsigned to)
 {
-	void *addr = kmap(page);
 	if (!PageUptodate(page)) {
-		memset(addr, 0, PAGE_CACHE_SIZE);
+		void *kaddr = kmap_atomic(page, KM_USER0);
+
+		memset(kaddr, 0, PAGE_CACHE_SIZE);
 		flush_dcache_page(page);
+		kunmap_atomic(kaddr, KM_USER0);
 		SetPageUptodate(page);
 	}
 	return 0;
@@ -85,7 +89,6 @@
 	loff_t pos = ((loff_t)page->index << PAGE_CACHE_SHIFT) + to;
 
 	set_page_dirty(page);
-	kunmap(page);
 	if (pos > inode->i_size)
 		inode->i_size = pos;
 	return 0;
diff -Nru a/fs/exec.c b/fs/exec.c
--- a/fs/exec.c	Mon Sep  9 10:36:11 2002
+++ b/fs/exec.c	Mon Sep  9 10:36:11 2002
@@ -504,6 +504,8 @@
 {
 	struct signal_struct * newsig;
 
+	remove_thread_group(current, current->sig);
+
 	if (atomic_read(&current->sig->count) <= 1)
 		return 0;
 	newsig = kmem_cache_alloc(sigact_cachep, GFP_KERNEL);
@@ -512,6 +514,8 @@
 	spin_lock_init(&newsig->siglock);
 	atomic_set(&newsig->count, 1);
 	memcpy(newsig->action, current->sig->action, sizeof(newsig->action));
+	init_sigpending(&newsig->shared_pending);
+
 	spin_lock_irq(&current->sigmask_lock);
 	current->sig = newsig;
 	spin_unlock_irq(&current->sigmask_lock);
@@ -575,42 +579,10 @@
  */
 static void de_thread(struct task_struct *tsk)
 {
-	struct task_struct *sub;
-	struct list_head *head, *ptr;
-	struct siginfo info;
-	int pause;
-
-	write_lock_irq(&tasklist_lock);
-
-	if (tsk->tgid != tsk->pid) {
-		/* subsidiary thread - just escapes the group */
-		list_del_init(&tsk->thread_group);
-		tsk->tgid = tsk->pid;
-		pause = 0;
-	}
-	else {
-		/* master thread - kill all subsidiary threads */
-		info.si_signo = SIGKILL;
-		info.si_errno = 0;
-		info.si_code = SI_DETHREAD;
-		info.si_pid = current->pid;
-		info.si_uid = current->uid;
-
-		head = tsk->thread_group.next;
-		list_del_init(&tsk->thread_group);
-
-		list_for_each(ptr,head) {
-			sub = list_entry(ptr,struct task_struct,thread_group);
-			send_sig_info(SIGKILL,&info,sub);
-		}
-
-		pause = 1;
-	}
-
-	write_unlock_irq(&tasklist_lock);
-
-	/* give the subsidiary threads a chance to clean themselves up */
-	if (pause) yield();
+	if (!list_empty(&tsk->thread_group))
+		BUG();
+	/* An exec() starts a new thread group: */
+	tsk->tgid = tsk->pid;
 }
 
 int flush_old_exec(struct linux_binprm * bprm)
@@ -633,6 +605,8 @@
 	if (retval) goto mmap_failed;
 
 	/* This is the point of no return */
+	de_thread(current);
+
 	release_old_signals(oldsig);
 
 	current->sas_ss_sp = current->sas_ss_size = 0;
@@ -650,9 +624,6 @@
 	current->comm[i] = '\0';
 
 	flush_thread();
-
-	if (!list_empty(&current->thread_group))
-		de_thread(current);
 
 	if (bprm->e_uid != current->euid || bprm->e_gid != current->egid || 
 	    permission(bprm->file->f_dentry->d_inode,MAY_READ))
diff -Nru a/fs/ext2/dir.c b/fs/ext2/dir.c
--- a/fs/ext2/dir.c	Mon Sep  9 10:35:51 2002
+++ b/fs/ext2/dir.c	Mon Sep  9 10:35:51 2002
@@ -571,8 +571,8 @@
 	struct page *page = grab_cache_page(mapping, 0);
 	unsigned chunk_size = ext2_chunk_size(inode);
 	struct ext2_dir_entry_2 * de;
-	char *base;
 	int err;
+	void *kaddr;
 
 	if (!page)
 		return -ENOMEM;
@@ -581,22 +581,21 @@
 		unlock_page(page);
 		goto fail;
 	}
-	base = page_address(page);
-
-	de = (struct ext2_dir_entry_2 *) base;
+	kaddr = kmap_atomic(page, KM_USER0);
+	de = (struct ext2_dir_entry_2 *)kaddr;
 	de->name_len = 1;
 	de->rec_len = cpu_to_le16(EXT2_DIR_REC_LEN(1));
 	memcpy (de->name, ".\0\0", 4);
 	de->inode = cpu_to_le32(inode->i_ino);
 	ext2_set_de_type (de, inode);
 
-	de = (struct ext2_dir_entry_2 *) (base + EXT2_DIR_REC_LEN(1));
+	de = (struct ext2_dir_entry_2 *)(kaddr + EXT2_DIR_REC_LEN(1));
 	de->name_len = 2;
 	de->rec_len = cpu_to_le16(chunk_size - EXT2_DIR_REC_LEN(1));
 	de->inode = cpu_to_le32(parent->i_ino);
 	memcpy (de->name, "..\0", 4);
 	ext2_set_de_type (de, inode);
-
+	kunmap_atomic(kaddr, KM_USER0);
 	err = ext2_commit_chunk(page, 0, chunk_size);
 fail:
 	page_cache_release(page);
diff -Nru a/fs/ext3/inode.c b/fs/ext3/inode.c
--- a/fs/ext3/inode.c	Mon Sep  9 10:36:12 2002
+++ b/fs/ext3/inode.c	Mon Sep  9 10:36:13 2002
@@ -1082,16 +1082,6 @@
 	if (ext3_should_journal_data(inode)) {
 		ret = walk_page_buffers(handle, page_buffers(page),
 				from, to, NULL, do_journal_get_write_access);
-		if (ret) {
-			/*
-			 * We're going to fail this prepare_write(),
-			 * so commit_write() will not be called.
-			 * We need to undo block_prepare_write()'s kmap().
-			 * AKPM: Do we need to clear PageUptodate?  I don't
-			 * think so.
-			 */
-			kunmap(page);
-		}
 	}
 prepare_write_failed:
 	if (ret)
@@ -1151,7 +1141,6 @@
 			from, to, &partial, commit_write_fn);
 		if (!partial)
 			SetPageUptodate(page);
-		kunmap(page);
 		if (pos > inode->i_size)
 			inode->i_size = pos;
 		EXT3_I(inode)->i_state |= EXT3_STATE_JDATA;
@@ -1162,17 +1151,8 @@
 		}
 		/* Be careful here if generic_commit_write becomes a
 		 * required invocation after block_prepare_write. */
-		if (ret == 0) {
+		if (ret == 0)
 			ret = generic_commit_write(file, page, from, to);
-		} else {
-			/*
-			 * block_prepare_write() was called, but we're not
-			 * going to call generic_commit_write().  So we
-			 * need to perform generic_commit_write()'s kunmap
-			 * by hand.
-			 */
-			kunmap(page);
-		}
 	}
 	if (inode->i_size > EXT3_I(inode)->i_disksize) {
 		EXT3_I(inode)->i_disksize = inode->i_size;
@@ -1535,6 +1515,7 @@
 	struct page *page;
 	struct buffer_head *bh;
 	int err;
+	void *kaddr;
 
 	blocksize = inode->i_sb->s_blocksize;
 	length = offset & (blocksize - 1);
@@ -1590,10 +1571,11 @@
 		if (err)
 			goto unlock;
 	}
-	
-	memset(kmap(page) + offset, 0, length);
+
+	kaddr = kmap_atomic(page, KM_USER0);
+	memset(kaddr + offset, 0, length);
 	flush_dcache_page(page);
-	kunmap(page);
+	kunmap_atomic(kaddr, KM_USER0);
 
 	BUFFER_TRACE(bh, "zeroed end of block");
 
diff -Nru a/fs/fat/inode.c b/fs/fat/inode.c
--- a/fs/fat/inode.c	Mon Sep  9 10:36:11 2002
+++ b/fs/fat/inode.c	Mon Sep  9 10:36:11 2002
@@ -982,11 +982,24 @@
 {
 	return block_read_full_page(page,fat_get_block);
 }
-static int fat_prepare_write(struct file *file, struct page *page, unsigned from, unsigned to)
+
+static int
+fat_prepare_write(struct file *file, struct page *page,
+			unsigned from, unsigned to)
 {
+	kmap(page);
 	return cont_prepare_write(page,from,to,fat_get_block,
 		&MSDOS_I(page->mapping->host)->mmu_private);
 }
+
+static int
+fat_commit_write(struct file *file, struct page *page,
+			unsigned from, unsigned to)
+{
+	kunmap(page);
+	return generic_commit_write(file, page, from, to);
+}
+
 static int _fat_bmap(struct address_space *mapping, long block)
 {
 	return generic_block_bmap(mapping,block,fat_get_block);
@@ -996,7 +1009,7 @@
 	writepage: fat_writepage,
 	sync_page: block_sync_page,
 	prepare_write: fat_prepare_write,
-	commit_write: generic_commit_write,
+	commit_write: fat_commit_write,
 	bmap: _fat_bmap
 };
 
diff -Nru a/fs/fcntl.c b/fs/fcntl.c
--- a/fs/fcntl.c	Mon Sep  9 10:35:56 2002
+++ b/fs/fcntl.c	Mon Sep  9 10:35:56 2002
@@ -11,13 +11,13 @@
 #include <linux/smp_lock.h>
 #include <linux/slab.h>
 #include <linux/iobuf.h>
+#include <linux/module.h>
 #include <linux/security.h>
 
 #include <asm/poll.h>
 #include <asm/siginfo.h>
 #include <asm/uaccess.h>
 
-extern int sock_fcntl (struct file *, unsigned int cmd, unsigned long arg);
 extern int fcntl_setlease(unsigned int fd, struct file *filp, long arg);
 extern int fcntl_getlease(struct file *filp);
 
@@ -259,6 +259,35 @@
 	return error;
 }
 
+static void f_modown(struct file *filp, unsigned long pid,
+                     uid_t uid, uid_t euid, int force)
+{
+	write_lock_irq(&filp->f_owner.lock);
+	if (force || !filp->f_owner.pid) {
+		filp->f_owner.pid = pid;
+		filp->f_owner.uid = uid;
+		filp->f_owner.euid = euid;
+	}
+	write_unlock_irq(&filp->f_owner.lock);
+}
+
+int f_setown(struct file *filp, unsigned long arg, int force)
+{
+	int err;
+	
+	err = security_ops->file_set_fowner(filp);
+	if (err)
+		return err;
+
+	f_modown(filp, arg, current->uid, current->euid, force);
+	return 0;
+}
+
+void f_delown(struct file *filp)
+{
+	f_modown(filp, 0, 0, 0, 1);
+}
+
 static long do_fcntl(unsigned int fd, unsigned int cmd,
 		     unsigned long arg, struct file * filp)
 {
@@ -302,21 +331,7 @@
 			err = filp->f_owner.pid;
 			break;
 		case F_SETOWN:
-			lock_kernel();
-
-			err = security_ops->file_set_fowner(filp);
-			if (err) {
-				unlock_kernel();
-				break;
-			}
-
-			filp->f_owner.pid = arg;
-			filp->f_owner.uid = current->uid;
-			filp->f_owner.euid = current->euid;
-			err = 0;
-			if (S_ISSOCK (filp->f_dentry->d_inode->i_mode))
-				err = sock_fcntl (filp, F_SETOWN, arg);
-			unlock_kernel();
+			err = f_setown(filp, arg, 1);
 			break;
 		case F_GETSIG:
 			err = filp->f_owner.signum;
@@ -339,10 +354,6 @@
 			err = fcntl_dirnotify(fd, filp, arg);
 			break;
 		default:
-			/* sockets need a few special fcntls. */
-			err = -EINVAL;
-			if (S_ISSOCK (filp->f_dentry->d_inode->i_mode))
-				err = sock_fcntl (filp, cmd, arg);
 			break;
 	}
 
@@ -418,14 +429,20 @@
 	POLLHUP | POLLERR			/* POLL_HUP */
 };
 
+static inline int sigio_perm(struct task_struct *p,
+                             struct fown_struct *fown)
+{
+	return ((fown->euid == 0) ||
+ 	        (fown->euid == p->suid) || (fown->euid == p->uid) ||
+ 	        (fown->uid == p->suid) || (fown->uid == p->uid));
+}
+
 static void send_sigio_to_task(struct task_struct *p,
 			       struct fown_struct *fown, 
 			       int fd,
 			       int reason)
 {
-	if ((fown->euid != 0) &&
-	    (fown->euid ^ p->suid) && (fown->euid ^ p->uid) &&
-	    (fown->uid ^ p->suid) && (fown->uid ^ p->uid))
+	if (!sigio_perm(p, fown))
 		return;
 
 	if (security_ops->file_send_sigiotask(p, fown, fd, reason))
@@ -464,12 +481,17 @@
 void send_sigio(struct fown_struct *fown, int fd, int band)
 {
 	struct task_struct * p;
-	int   pid	= fown->pid;
+	int pid;
+	
+	read_lock(&fown->lock);
+	pid = fown->pid;
+	if (!pid)
+		goto out_unlock_fown;
 	
 	read_lock(&tasklist_lock);
 	if ( (pid > 0) && (p = find_task_by_pid(pid)) ) {
 		send_sigio_to_task(p, fown, fd, band);
-		goto out;
+		goto out_unlock_task;
 	}
 	for_each_task(p) {
 		int match = p->pid;
@@ -479,8 +501,49 @@
 			continue;
 		send_sigio_to_task(p, fown, fd, band);
 	}
-out:
+out_unlock_task:
 	read_unlock(&tasklist_lock);
+out_unlock_fown:
+	read_unlock(&fown->lock);
+}
+
+static void send_sigurg_to_task(struct task_struct *p,
+                                struct fown_struct *fown)
+{
+	if (sigio_perm(p, fown))
+		send_sig(SIGURG, p, 1);
+}
+
+int send_sigurg(struct fown_struct *fown)
+{
+	struct task_struct *p;
+	int pid, ret = 0;
+	
+	read_lock(&fown->lock);
+	pid = fown->pid;
+	if (!pid)
+		goto out_unlock_fown;
+
+	ret = 1;
+	
+	read_lock(&tasklist_lock);
+	if ((pid > 0) && (p = find_task_by_pid(pid))) {
+		send_sigurg_to_task(p, fown);
+		goto out_unlock_task;
+	}
+	for_each_task(p) {
+		int match = p->pid;
+		if (pid < 0)
+			match = -p->pgrp;
+		if (pid != match)
+			continue;
+		send_sigurg_to_task(p, fown);
+	}
+out_unlock_task:
+	read_unlock(&tasklist_lock);
+out_unlock_fown:
+	read_unlock(&fown->lock);
+	return ret;
 }
 
 static rwlock_t fasync_lock = RW_LOCK_UNLOCKED;
@@ -543,7 +606,7 @@
 		/* Don't send SIGURG to processes which have not set a
 		   queued signum: SIGURG has its own default signalling
 		   mechanism. */
-		if (fown->pid && !(sig == SIGURG && fown->signum == 0))
+		if (!(sig == SIGURG && fown->signum == 0))
 			send_sigio(fown, fa->fa_fd, band);
 		fa = fa->fa_next;
 	}
@@ -566,3 +629,6 @@
 }
 
 module_init(fasync_init)
+
+EXPORT_SYMBOL(f_setown);
+EXPORT_SYMBOL(f_delown);
diff -Nru a/fs/file_table.c b/fs/file_table.c
--- a/fs/file_table.c	Mon Sep  9 10:35:56 2002
+++ b/fs/file_table.c	Mon Sep  9 10:35:56 2002
@@ -54,6 +54,7 @@
 		f->f_version = ++event;
 		f->f_uid = current->fsuid;
 		f->f_gid = current->fsgid;
+		f->f_owner.lock = RW_LOCK_UNLOCKED;
 		list_add(&f->f_list, &anon_list);
 		file_list_unlock();
 		return f;
diff -Nru a/fs/intermezzo/kml_utils.c b/fs/intermezzo/kml_utils.c
--- a/fs/intermezzo/kml_utils.c	Mon Sep  9 10:36:11 2002
+++ b/fs/intermezzo/kml_utils.c	Mon Sep  9 10:36:11 2002
@@ -25,7 +25,7 @@
         va_list args;
         int  i;
         char *path;
-        long flags;
+        unsigned long flags;
 
         spin_lock_irqsave(&kml_lock, flags);
         va_start(args, format);
diff -Nru a/fs/jffs/inode-v23.c b/fs/jffs/inode-v23.c
--- a/fs/jffs/inode-v23.c	Mon Sep  9 10:36:11 2002
+++ b/fs/jffs/inode-v23.c	Mon Sep  9 10:36:12 2002
@@ -47,6 +47,7 @@
 #include <linux/stat.h>
 #include <linux/blkdev.h>
 #include <linux/quotaops.h>
+#include <linux/highmem.h>
 #include <linux/smp_lock.h>
 #include <asm/semaphore.h>
 #include <asm/byteorder.h>
@@ -751,7 +752,6 @@
 
 	get_page(page);
 	/* Don't SetPageLocked(page), should be locked already */
-	buf = page_address(page);
 	ClearPageUptodate(page);
 	ClearPageError(page);
 
@@ -760,8 +760,10 @@
 
 	read_len = 0;
 	result = 0;
-
 	offset = page->index << PAGE_CACHE_SHIFT;
+
+	kmap(page);
+	buf = page_address(page);
 	if (offset < inode->i_size) {
 		read_len = min_t(long, inode->i_size - offset, PAGE_SIZE);
 		r = jffs_read_data(f, buf, offset, read_len);
@@ -779,6 +781,8 @@
 	/* This handles the case of partial or no read in above */
 	if(read_len < PAGE_SIZE)
 	        memset(buf + read_len, 0, PAGE_SIZE - read_len);
+	flush_dcache_page(page);
+	kunmap(page);
 
 	D3(printk (KERN_NOTICE "readpage(): up biglock\n"));
 	up(&c->fmc->biglock);
@@ -788,9 +792,8 @@
 	}else {
 	        SetPageUptodate(page);	        
 	}
-	flush_dcache_page(page);
 
-	put_page(page);
+	page_cache_release(page);
 
 	D3(printk("jffs_readpage(): Leaving...\n"));
 
diff -Nru a/fs/jffs2/background.c b/fs/jffs2/background.c
--- a/fs/jffs2/background.c	Mon Sep  9 10:35:51 2002
+++ b/fs/jffs2/background.c	Mon Sep  9 10:35:51 2002
@@ -83,7 +83,6 @@
 	struct jffs2_sb_info *c = _c;
 
 	daemonize();
-	current->tty = NULL;
 	c->gc_task = current;
 	up(&c->gc_thread_start);
 
diff -Nru a/fs/jffs2/file.c b/fs/jffs2/file.c
--- a/fs/jffs2/file.c	Mon Sep  9 10:36:18 2002
+++ b/fs/jffs2/file.c	Mon Sep  9 10:36:18 2002
@@ -17,6 +17,7 @@
 #include <linux/fs.h>
 #include <linux/time.h>
 #include <linux/pagemap.h>
+#include <linux/highmem.h>
 #include <linux/crc32.h>
 #include <linux/jffs2.h>
 #include "nodelist.h"
@@ -381,9 +382,10 @@
 	ri->isize = (uint32_t)inode->i_size;
 	ri->atime = ri->ctime = ri->mtime = CURRENT_TIME;
 
-	/* We rely on the fact that generic_file_write() currently kmaps the page for us. */
+	kmap(pg);
 	ret = jffs2_write_inode_range(c, f, ri, page_address(pg) + start,
 				      (pg->index << PAGE_CACHE_SHIFT) + start, end - start, &writtenlen);
+	kunmap(pg);
 
 	if (ret) {
 		/* There was an error writing. */
diff -Nru a/fs/jfs/file.c b/fs/jfs/file.c
--- a/fs/jfs/file.c	Mon Sep  9 10:36:01 2002
+++ b/fs/jfs/file.c	Mon Sep  9 10:36:01 2002
@@ -24,9 +24,6 @@
 #include "jfs_debug.h"
 
 
-extern int generic_file_open(struct inode *, struct file *);
-extern loff_t generic_file_llseek(struct file *, loff_t, int origin);
-
 extern int jfs_commit_inode(struct inode *, int);
 
 int jfs_fsync(struct file *file, struct dentry *dentry, int datasync)
@@ -114,11 +111,3 @@
  	.sendfile	= generic_file_sendfile,
 	.fsync		= jfs_fsync,
 };
-
-struct inode_operations jfs_special_inode_operations = {
-	.setxattr	= jfs_setxattr,
-	.getxattr	= jfs_getxattr,
-	.listxattr	= jfs_listxattr,
-	.removexattr	= jfs_removexattr,
-};
-
diff -Nru a/fs/jfs/inode.c b/fs/jfs/inode.c
--- a/fs/jfs/inode.c	Mon Sep  9 10:35:43 2002
+++ b/fs/jfs/inode.c	Mon Sep  9 10:35:43 2002
@@ -31,7 +31,6 @@
 extern struct inode_operations jfs_dir_inode_operations;
 extern struct inode_operations jfs_file_inode_operations;
 extern struct inode_operations jfs_symlink_inode_operations;
-extern struct inode_operations jfs_special_inode_operations;
 extern struct file_operations jfs_dir_operations;
 extern struct file_operations jfs_file_operations;
 struct address_space_operations jfs_aops;
@@ -66,7 +65,7 @@
 		} else
 			inode->i_op = &jfs_symlink_inode_operations;
 	} else {
-		inode->i_op = &jfs_special_inode_operations;
+		inode->i_op = &jfs_file_inode_operations;
 		init_special_inode(inode, inode->i_mode,
 				   kdev_t_to_nr(inode->i_rdev));
 	}
diff -Nru a/fs/jfs/jfs_dtree.c b/fs/jfs/jfs_dtree.c
--- a/fs/jfs/jfs_dtree.c	Mon Sep  9 10:36:01 2002
+++ b/fs/jfs/jfs_dtree.c	Mon Sep  9 10:36:01 2002
@@ -101,7 +101,6 @@
  */
 
 #include <linux/fs.h>
-#include <linux/smp_lock.h>
 #include "jfs_incore.h"
 #include "jfs_superblock.h"
 #include "jfs_filsys.h"
diff -Nru a/fs/jfs/jfs_extendfs.h b/fs/jfs/jfs_extendfs.h
--- a/fs/jfs/jfs_extendfs.h	Mon Sep  9 10:35:55 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,36 +0,0 @@
-/*
- *   Copyright (c) International Business Machines Corp., 2000-2001
- *
- *   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.
- * 
- *   This program 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 General Public License for more details.
- *
- *   You should have received a copy of the GNU General Public License
- *   along with this program;  if not, write to the Free Software 
- *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-#ifndef	_H_JFS_EXTENDFS
-#define _H_JFS_EXTENDFS
-
-/*
- *	extendfs parameter list
- */
-typedef struct {
-	u32 flag;		/* 4: */
-	u8 dev;			/* 1: */
-	u8 pad[3];		/* 3: */
-	s64 LVSize;		/* 8: LV size in LV block */
-	s64 FSSize;		/* 8: FS size in LV block */
-	s32 LogSize;		/* 4: inlinelog size in LV block */
-} extendfs_t;			/* (28) */
-
-/* plist flag */
-#define EXTENDFS_QUERY		0x00000001
-
-#endif				/* _H_JFS_EXTENDFS */
diff -Nru a/fs/jfs/jfs_extent.c b/fs/jfs/jfs_extent.c
--- a/fs/jfs/jfs_extent.c	Mon Sep  9 10:35:49 2002
+++ b/fs/jfs/jfs_extent.c	Mon Sep  9 10:35:49 2002
@@ -26,8 +26,9 @@
  * forward references
  */
 static int extBalloc(struct inode *, s64, s64 *, s64 *);
+#ifdef _NOTYET
 static int extBrealloc(struct inode *, s64, s64, s64 *, s64 *);
-int extRecord(struct inode *, xad_t *);
+#endif
 static s64 extRoundDown(s64 nb);
 
 /*
@@ -191,6 +192,7 @@
 }
 
 
+#ifdef _NOTYET
 /*
  * NAME:        extRealloc()
  *
@@ -335,6 +337,7 @@
 	up(&JFS_IP(ip)->commit_sem);
 	return (rc);
 }
+#endif			/* _NOTYET */
 
 
 /*
@@ -440,6 +443,7 @@
 }
 
 
+#ifdef _NOTYET
 /*
  * NAME:        extFill()
  *
@@ -473,6 +477,7 @@
 
 	return (0);
 }
+#endif			/* _NOTYET */
 
 
 /*
@@ -548,6 +553,7 @@
 }
 
 
+#ifdef _NOTYET
 /*
  * NAME:	extBrealloc()
  *
@@ -601,6 +607,7 @@
 	 */
 	return (extBalloc(ip, blkno, newnblks, newblkno));
 }
+#endif			/* _NOTYET */
 
 
 /*
diff -Nru a/fs/jfs/jfs_imap.c b/fs/jfs/jfs_imap.c
--- a/fs/jfs/jfs_imap.c	Mon Sep  9 10:36:01 2002
+++ b/fs/jfs/jfs_imap.c	Mon Sep  9 10:36:01 2002
@@ -42,6 +42,8 @@
  */
 
 #include <linux/fs.h>
+#include <linux/buffer_head.h>
+
 #include "jfs_incore.h"
 #include "jfs_filsys.h"
 #include "jfs_dinode.h"
@@ -1175,7 +1177,7 @@
 	 * invalidate any page of the inode extent freed from buffer cache;
 	 */
 	freepxd = iagp->inoext[extno];
-	invalidate_pxd_metapages(JFS_SBI(ip->i_sb)->direct_inode, freepxd);
+	invalidate_pxd_metapages(ip->i_sb->s_bdev->bd_inode, freepxd);
 
 	/*
 	 *      update iag list(s) (careful update step 2)
@@ -2963,26 +2965,30 @@
  *
  * note: shadow page with regular inode (rel.2);
  */
-static void
-duplicateIXtree(struct super_block *sb, s64 blkno, int xlen, s64 * xaddr)
+static void duplicateIXtree(struct super_block *sb, s64 blkno,
+			    int xlen, s64 *xaddr)
 {
-	int rc;
-	tid_t tid;
-	struct inode *ip;
-	metapage_t *mpsuper;
 	struct jfs_superblock *j_sb;
+	struct buffer_head *bh;
+	struct inode *ip;
+	tid_t tid;
+	int rc;
 
 	/* if AIT2 ipmap2 is bad, do not try to update it */
 	if (JFS_SBI(sb)->mntflag & JFS_BAD_SAIT)	/* s_flag */
 		return;
 	ip = diReadSpecial(sb, FILESYSTEM_I, 1);
-	if (ip == 0) {
+	if (ip == NULL) {
 		JFS_SBI(sb)->mntflag |= JFS_BAD_SAIT;
-		if ((rc = readSuper(sb, &mpsuper)))
+		if ((rc = readSuper(sb, &bh)))
 			return;
-		j_sb = (struct jfs_superblock *) (mpsuper->data);
+		j_sb = (struct jfs_superblock *)bh->b_data;
 		j_sb->s_flag |= JFS_BAD_SAIT;
-		write_metapage(mpsuper);
+
+		mark_buffer_dirty(bh);
+		ll_rw_block(WRITE, 1, &bh);
+		wait_on_buffer(bh);
+		brelse(bh);
 		return;
 	}
 
diff -Nru a/fs/jfs/jfs_incore.h b/fs/jfs/jfs_incore.h
--- a/fs/jfs/jfs_incore.h	Mon Sep  9 10:35:56 2002
+++ b/fs/jfs/jfs_incore.h	Mon Sep  9 10:35:56 2002
@@ -152,8 +152,6 @@
         /* Formerly in ipbmap */
 	struct bmap	*bmap;		/* 4: incore bmap descriptor	*/
 	struct nls_table *nls_tab;	/* 4: current codepage		*/
-	struct inode	*direct_inode;	/* 4: inode for physical I/O	*/
-	struct address_space *direct_mapping; /* 4: mapping for physical I/O */
 	uint		state;		/* 4: mount/recovery state	*/
 };
 
diff -Nru a/fs/jfs/jfs_logmgr.c b/fs/jfs/jfs_logmgr.c
--- a/fs/jfs/jfs_logmgr.c	Mon Sep  9 10:36:11 2002
+++ b/fs/jfs/jfs_logmgr.c	Mon Sep  9 10:36:11 2002
@@ -960,17 +960,19 @@
 	 * reset syncpt = sync
 	 */
 	if (log->sync != log->syncpt) {
-		struct jfs_sb_info	*sbi = JFS_SBI(log->sb);
+		struct super_block *sb = log->sb;
+		struct jfs_sb_info *sbi = JFS_SBI(sb);
+
 		/*
 		 * We need to make sure all of the "written" metapages
 		 * actually make it to disk
 		 */
 		filemap_fdatawrite(sbi->ipbmap->i_mapping);
 		filemap_fdatawrite(sbi->ipimap->i_mapping);
-		filemap_fdatawrite(sbi->direct_inode->i_mapping);
+		filemap_fdatawrite(sb->s_bdev->bd_inode->i_mapping);
 		filemap_fdatawait(sbi->ipbmap->i_mapping);
 		filemap_fdatawait(sbi->ipimap->i_mapping);
-		filemap_fdatawait(sbi->direct_inode->i_mapping);
+		filemap_fdatawait(sb->s_bdev->bd_inode->i_mapping);
 
 		lrd.logtid = 0;
 		lrd.backchain = 0;
@@ -1985,6 +1987,7 @@
 
 		jERROR(1, ("lbmIODone: I/O error in JFS log\n"));
 	}
+
 	bio_put(bio);
 
 	/*
@@ -2102,7 +2105,6 @@
 
 		LCACHE_UNLOCK(flags);	/* unlock+enable */
 	}
-	return;
 }
 
 int jfsIOWait(void *arg)
@@ -2114,7 +2116,6 @@
 	lock_kernel();
 
 	daemonize();
-	current->tty = NULL;
 	strcpy(current->comm, "jfsIO");
 
 	unlock_kernel();
diff -Nru a/fs/jfs/jfs_metapage.c b/fs/jfs/jfs_metapage.c
--- a/fs/jfs/jfs_metapage.c	Mon Sep  9 10:36:01 2002
+++ b/fs/jfs/jfs_metapage.c	Mon Sep  9 10:36:01 2002
@@ -27,16 +27,13 @@
 #include "jfs_txnmgr.h"
 #include "jfs_debug.h"
 
-extern struct task_struct *jfsCommitTask;
 static spinlock_t meta_lock = SPIN_LOCK_UNLOCKED;
-static wait_queue_head_t meta_wait;
 
 #ifdef CONFIG_JFS_STATISTICS
 struct {
 	uint	pagealloc;	/* # of page allocations */
 	uint	pagefree;	/* # of page frees */
 	uint	lockwait;	/* # of sleeping lock_metapage() calls */
-	uint	allocwait;	/* # of sleeping alloc_metapage() calls */
 } mpStat;
 #endif
 
@@ -135,11 +132,6 @@
 int __init metapage_init(void)
 {
 	/*
-	 * Initialize wait queue
-	 */
-	init_waitqueue_head(&meta_wait);
-
-	/*
 	 * Allocate the metapage structures
 	 */
 	metapage_cache = kmem_cache_create("jfs_mp", sizeof(metapage_t), 0, 0,
@@ -225,51 +217,6 @@
 		mp->hash_next->hash_prev = mp->hash_prev;
 }
 
-/*
- * Direct address space operations
- */
-
-static int direct_get_block(struct inode *ip, sector_t lblock,
-			    struct buffer_head *bh_result, int create)
-{
-	if (create)
-		set_buffer_new(bh_result);
-
-	map_bh(bh_result, ip->i_sb, lblock);
-
-	return 0;
-}
-
-static int direct_writepage(struct page *page)
-{
-	return block_write_full_page(page, direct_get_block);
-}
-
-static int direct_readpage(struct file *fp, struct page *page)
-{
-	return block_read_full_page(page, direct_get_block);
-}
-
-static int direct_prepare_write(struct file *file, struct page *page,
-				unsigned from, unsigned to)
-{
-	return block_prepare_write(page, from, to, direct_get_block);
-}
-
-static int direct_bmap(struct address_space *mapping, long block)
-{
-	return generic_block_bmap(mapping, block, direct_get_block);
-}
-
-struct address_space_operations direct_aops = {
-	.readpage	= direct_readpage,
-	.writepage	= direct_writepage,
-	.sync_page	= block_sync_page,
-	.prepare_write	= direct_prepare_write,
-	.commit_write	= generic_commit_write,
-	.bmap		= direct_bmap,
-};
-
 metapage_t *__get_metapage(struct inode *inode,
 			   unsigned long lblock, unsigned int size,
 			   int absolute, unsigned long new)
@@ -286,14 +233,12 @@
 		 inode, lblock));
 
 	if (absolute)
-		mapping = JFS_SBI(inode->i_sb)->direct_mapping;
+		mapping = inode->i_sb->s_bdev->bd_inode->i_mapping;
 	else
 		mapping = inode->i_mapping;
 
 	spin_lock(&meta_lock);
-
 	hash_ptr = meta_hash(mapping, lblock);
-
 	mp = search_hash(hash_ptr, mapping, lblock);
 	if (mp) {
 	      page_found:
@@ -309,7 +254,7 @@
 		lock_metapage(mp);
 		spin_unlock(&meta_lock);
 	} else {
-		l2bsize = inode->i_sb->s_blocksize_bits;
+		l2bsize = inode->i_blkbits;
 		l2BlocksPerPage = PAGE_CACHE_SHIFT - l2bsize;
 		page_index = lblock >> l2BlocksPerPage;
 		page_offset = (lblock - (page_index << l2BlocksPerPage)) <<
@@ -431,12 +376,11 @@
 
 static void __write_metapage(metapage_t * mp)
 {
-	struct inode *ip = (struct inode *) mp->mapping->host;
+	int l2bsize = mp->mapping->host->i_blkbits;
+	int l2BlocksPerPage = PAGE_CACHE_SHIFT - l2bsize;
 	unsigned long page_index;
 	unsigned long page_offset;
 	int rc;
-	int l2bsize = ip->i_sb->s_blocksize_bits;
-	int l2BlocksPerPage = PAGE_CACHE_SHIFT - l2bsize;
 
 	jFYI(1, ("__write_metapage: mp = 0x%p\n", mp));
 
@@ -459,7 +403,6 @@
 	if (rc) {
 		jERROR(1, ("prepare_write return %d!\n", rc));
 		ClearPageUptodate(mp->page);
-		kunmap(mp->page);
 		unlock_page(mp->page);
 		clear_bit(META_dirty, &mp->flag);
 		return;
@@ -561,7 +504,7 @@
 {
 	metapage_t **hash_ptr;
 	unsigned long lblock;
-	int l2BlocksPerPage = PAGE_CACHE_SHIFT - ip->i_sb->s_blocksize_bits;
+	int l2BlocksPerPage = PAGE_CACHE_SHIFT - ip->i_blkbits;
 	struct address_space *mapping = ip->i_mapping;
 	metapage_t *mp;
 	struct page *page;
@@ -624,12 +567,10 @@
 		       "=======================\n"
 		       "page allocations = %d\n"
 		       "page frees = %d\n"
-		       "lock waits = %d\n"
-		       "allocation waits = %d\n",
+		       "lock waits = %d\n",
 		       mpStat.pagealloc,
 		       mpStat.pagefree,
-		       mpStat.lockwait,
-		       mpStat.allocwait);
+		       mpStat.lockwait);
 
 	begin = offset;
 	*start = buffer + begin;
diff -Nru a/fs/jfs/jfs_metapage.h b/fs/jfs/jfs_metapage.h
--- a/fs/jfs/jfs_metapage.h	Mon Sep  9 10:36:11 2002
+++ b/fs/jfs/jfs_metapage.h	Mon Sep  9 10:36:11 2002
@@ -57,11 +57,6 @@
 	struct jfs_log *log;
 } metapage_t;
 
-/*
- * Direct-access address space operations
- */
-extern struct address_space_operations direct_aops;
-
 /* metapage flag */
 #define META_locked	0
 #define META_absolute	1
diff -Nru a/fs/jfs/jfs_mount.c b/fs/jfs/jfs_mount.c
--- a/fs/jfs/jfs_mount.c	Mon Sep  9 10:36:01 2002
+++ b/fs/jfs/jfs_mount.c	Mon Sep  9 10:36:01 2002
@@ -48,6 +48,8 @@
  */
 
 #include <linux/fs.h>
+#include <linux/buffer_head.h>
+
 #include "jfs_incore.h"
 #include "jfs_filsys.h"
 #include "jfs_superblock.h"
@@ -314,18 +316,18 @@
 static int chkSuper(struct super_block *sb)
 {
 	int rc = 0;
-	metapage_t *mp;
 	struct jfs_sb_info *sbi = JFS_SBI(sb);
 	struct jfs_superblock *j_sb;
+	struct buffer_head *bh;
 	int AIM_bytesize, AIT_bytesize;
 	int expected_AIM_bytesize, expected_AIT_bytesize;
 	s64 AIM_byte_addr, AIT_byte_addr, fsckwsp_addr;
 	s64 byte_addr_diff0, byte_addr_diff1;
 	s32 bsize;
 
-	if ((rc = readSuper(sb, &mp)))
+	if ((rc = readSuper(sb, &bh)))
 		return rc;
-	j_sb = (struct jfs_superblock *) (mp->data);
+	j_sb = (struct jfs_superblock *)bh->b_data;
 
 	/*
 	 * validate superblock
@@ -414,8 +416,7 @@
 	sbi->ait2 = j_sb->s_ait2;
 
       out:
-	release_metapage(mp);
-
+	brelse(bh);
 	return rc;
 }
 
@@ -429,7 +430,7 @@
 {
 	struct jfs_superblock *j_sb;
 	struct jfs_sb_info *sbi = JFS_SBI(sb);
-	metapage_t *mp;
+	struct buffer_head *bh;
 	int rc;
 
 	/*
@@ -438,10 +439,10 @@
 	if (sbi->state == FM_DIRTY)
 		return 0;
 
-	if ((rc = readSuper(sb, &mp)))
+	if ((rc = readSuper(sb, &bh)))
 		return rc;
 
-	j_sb = (struct jfs_superblock *) (mp->data);
+	j_sb = (struct jfs_superblock *)bh->b_data;
 
 	j_sb->s_state = cpu_to_le32(state);
 	sbi->state = state;
@@ -459,7 +460,10 @@
 			j_sb->s_flag |= cpu_to_le32(JFS_DASD_PRIME);
 	}
 
-	flush_metapage(mp);
+	mark_buffer_dirty(bh);
+	ll_rw_block(WRITE, 1, &bh);
+	wait_on_buffer(bh);
+	brelse(bh);
 
 	return 0;
 }
@@ -470,18 +474,19 @@
  *
  * read superblock by raw sector address
  */
-int readSuper(struct super_block *sb, metapage_t ** mpp)
+int readSuper(struct super_block *sb, struct buffer_head **bpp)
 {
 	/* read in primary superblock */
-	*mpp = read_metapage(JFS_SBI(sb)->direct_inode,
-			     SUPER1_OFF >> sb->s_blocksize_bits, PSIZE, 1);
-	if (*mpp == NULL) {
-		/* read in secondary/replicated superblock */
-		*mpp = read_metapage(JFS_SBI(sb)->direct_inode,
-				     SUPER2_OFF >> sb->s_blocksize_bits,
-				     PSIZE, 1);
-	}
-	return *mpp ? 0 : 1;
+	*bpp = sb_bread(sb, SUPER1_OFF >> sb->s_blocksize_bits);
+	if (bpp)
+		return 0;
+
+	/* read in secondary/replicated superblock */
+	*bpp = sb_bread(sb, SUPER2_OFF >> sb->s_blocksize_bits);
+	if (bpp)
+		return 0;
+
+	return -EIO;
 }
 
 
diff -Nru a/fs/jfs/jfs_superblock.h b/fs/jfs/jfs_superblock.h
--- a/fs/jfs/jfs_superblock.h	Mon Sep  9 10:36:01 2002
+++ b/fs/jfs/jfs_superblock.h	Mon Sep  9 10:36:01 2002
@@ -106,7 +106,7 @@
 
 };
 
-extern int readSuper(struct super_block *, struct metapage **);
+extern int readSuper(struct super_block *, struct buffer_head **);
 extern int updateSuper(struct super_block *, uint);
 
 #endif /*_H_JFS_SUPERBLOCK */
diff -Nru a/fs/jfs/jfs_txnmgr.c b/fs/jfs/jfs_txnmgr.c
--- a/fs/jfs/jfs_txnmgr.c	Mon Sep  9 10:36:11 2002
+++ b/fs/jfs/jfs_txnmgr.c	Mon Sep  9 10:36:11 2002
@@ -144,7 +144,6 @@
  */
 extern int lmGroupCommit(log_t * log, tblock_t * tblk);
 extern void lmSync(log_t *);
-extern int readSuper(struct super_block *sb, metapage_t ** bpp);
 extern int jfs_commit_inode(struct inode *, int);
 extern int jfs_stop_threads;
 
@@ -2763,7 +2762,6 @@
 	lock_kernel();
 
 	daemonize();
-	current->tty = NULL;
 	strcpy(current->comm, "jfsCommit");
 
 	unlock_kernel();
@@ -2961,7 +2959,6 @@
 	lock_kernel();
 
 	daemonize();
-	current->tty = NULL;
 	strcpy(current->comm, "jfsSync");
 
 	unlock_kernel();
diff -Nru a/fs/jfs/jfs_umount.c b/fs/jfs/jfs_umount.c
--- a/fs/jfs/jfs_umount.c	Mon Sep  9 10:35:43 2002
+++ b/fs/jfs/jfs_umount.c	Mon Sep  9 10:35:43 2002
@@ -49,13 +49,14 @@
  */
 int jfs_umount(struct super_block *sb)
 {
-	int rc = 0;
-	log_t *log;
+	struct address_space *bdev_mapping = sb->s_bdev->bd_inode->i_mapping;
 	struct jfs_sb_info *sbi = JFS_SBI(sb);
 	struct inode *ipbmap = sbi->ipbmap;
 	struct inode *ipimap = sbi->ipimap;
 	struct inode *ipaimap = sbi->ipaimap;
 	struct inode *ipaimap2 = sbi->ipaimap2;
+	log_t *log;
+	int rc = 0;
 
 	jFYI(1, ("\n	UnMount JFS: sb:0x%p\n", sb));
 
@@ -112,8 +113,8 @@
 	 * Make sure all metadata makes it to disk before we mark
 	 * the superblock as clean
 	 */
-	filemap_fdatawrite(sbi->direct_inode->i_mapping);
-	filemap_fdatawait(sbi->direct_inode->i_mapping);
+	filemap_fdatawrite(bdev_mapping);
+	filemap_fdatawait(bdev_mapping);
 
 	/*
 	 * ensure all file system file pages are propagated to their
@@ -140,6 +141,7 @@
 
 int jfs_umount_rw(struct super_block *sb)
 {
+	struct address_space *bdev_mapping = sb->s_bdev->bd_inode->i_mapping;
 	struct jfs_sb_info *sbi = JFS_SBI(sb);
 	log_t *log = sbi->log;
 
@@ -158,8 +160,15 @@
 	 */
 	dbSync(sbi->ipbmap);
 	diSync(sbi->ipimap);
-	filemap_fdatawrite(sbi->direct_inode->i_mapping);
-	filemap_fdatawait(sbi->direct_inode->i_mapping);
+
+	/*
+	 * Note that we have to do this even if sync_blockdev() will
+	 * do exactly the same a few instructions later:  We can't
+	 * mark the superblock clean before everything is flushed to
+	 * disk.
+	 */
+	filemap_fdatawrite(bdev_mapping);
+	filemap_fdatawait(bdev_mapping);
 
 	updateSuper(sb, FM_CLEAN);
 	sbi->log = NULL;
diff -Nru a/fs/jfs/namei.c b/fs/jfs/namei.c
--- a/fs/jfs/namei.c	Mon Sep  9 10:36:13 2002
+++ b/fs/jfs/namei.c	Mon Sep  9 10:36:13 2002
@@ -29,7 +29,6 @@
 
 extern struct inode_operations jfs_file_inode_operations;
 extern struct inode_operations jfs_symlink_inode_operations;
-extern struct inode_operations jfs_special_inode_operations;
 extern struct file_operations jfs_file_operations;
 extern struct address_space_operations jfs_aops;
 
@@ -1338,7 +1337,7 @@
 	if ((rc = dtInsert(tid, dir, &dname, &ino, &btstack)))
 		goto out3;
 
-	ip->i_op = &jfs_special_inode_operations;
+	ip->i_op = &jfs_file_inode_operations;
 	init_special_inode(ip, ip->i_mode, rdev);
 
 	insert_inode_hash(ip);
diff -Nru a/fs/jfs/resize.c b/fs/jfs/resize.c
--- a/fs/jfs/resize.c	Mon Sep  9 10:36:12 2002
+++ b/fs/jfs/resize.c	Mon Sep  9 10:36:12 2002
@@ -79,9 +79,8 @@
 	int log_formatted = 0;
 	struct inode *iplist[1];
 	struct jfs_superblock *j_sb, *j_sb2;
-	metapage_t *sbp, *sb2p;
 	uint old_agsize;
-	struct buffer_head *bh;
+	struct buffer_head *bh, *bh2;
 
 	/* If the volume hasn't grown, get out now */
 
@@ -230,9 +229,9 @@
 		 */
 
 		/* read in superblock */
-		if ((rc = readSuper(sb, &sbp)))
+		if ((rc = readSuper(sb, &bh)))
 			goto error_out;
-		j_sb = (struct jfs_superblock *) (sbp->data);
+		j_sb = (struct jfs_superblock *)bh->b_data;
 
 		/* mark extendfs() in progress */
 		j_sb->s_state |= cpu_to_le32(FM_EXTENDFS);
@@ -243,7 +242,10 @@
 		PXDlength(&j_sb->s_xlogpxd, newLogSize);
 
 		/* synchronously update superblock */
-		flush_metapage(sbp);
+		mark_buffer_dirty(bh);
+		ll_rw_block(WRITE, 1, &bh);
+		wait_on_buffer(bh);
+		brelse(bh);
 
 		/*
 		 * format new inline log synchronously;
@@ -474,12 +476,13 @@
 
 	diWriteSpecial(ipbmap2, 1);
 	diFreeSpecial(ipbmap2);
+
 	/*
 	 *      update superblock
 	 */
-	if ((rc = readSuper(sb, &sbp)))
+	if ((rc = readSuper(sb, &bh)))
 		goto error_out;
-	j_sb = (struct jfs_superblock *) (sbp->data);
+	j_sb = (struct jfs_superblock *)bh->b_data;
 
 	/* mark extendfs() completion */
 	j_sb->s_state &= cpu_to_le32(~FM_EXTENDFS);
@@ -503,17 +506,22 @@
 	/* sb->s_fsckloglen remains the same */
 
 	/* Update secondary superblock */
-	sb2p = read_metapage(sbi->direct_inode,
-			     SUPER2_OFF >> sb->s_blocksize_bits, PSIZE, 1);
-
-	if (sb2p) {
-		j_sb2 = (struct jfs_superblock *) (sb2p->data);
+	bh2 = sb_bread(sb, SUPER2_OFF >> sb->s_blocksize_bits);
+	if (bh2) {
+		j_sb2 = (struct jfs_superblock *)bh2->b_data;
 		memcpy(j_sb2, j_sb, sizeof (struct jfs_superblock));
-		flush_metapage(sb2p);
+
+		mark_buffer_dirty(bh);
+		ll_rw_block(WRITE, 1, &bh2);
+		wait_on_buffer(bh2);
+		brelse(bh);
 	}
 
 	/* write primary superblock */
-	flush_metapage(sbp);
+	mark_buffer_dirty(bh);
+	ll_rw_block(WRITE, 1, &bh);
+	wait_on_buffer(bh);
+	brelse(bh);
 
 	goto resume;
 
diff -Nru a/fs/jfs/super.c b/fs/jfs/super.c
--- a/fs/jfs/super.c	Mon Sep  9 10:36:11 2002
+++ b/fs/jfs/super.c	Mon Sep  9 10:36:11 2002
@@ -142,17 +142,6 @@
 	unload_nls(sbi->nls_tab);
 	sbi->nls_tab = NULL;
 
-	/*
-	 * We need to clean out the direct_inode pages since this inode
-	 * is not in the inode hash.
-	 */
-	filemap_fdatawrite(sbi->direct_inode->i_mapping);
-	filemap_fdatawait(sbi->direct_inode->i_mapping);
-	truncate_inode_pages(sbi->direct_mapping, 0);
-	iput(sbi->direct_inode);
-	sbi->direct_inode = NULL;
-	sbi->direct_mapping = NULL;
-
 	kfree(sbi);
 }
 
@@ -221,7 +210,6 @@
 
 int jfs_remount(struct super_block *sb, int *flags, char *data)
 {
-	struct jfs_sb_info *sbi = JFS_SBI(sb);
 	s64 newLVSize = 0;
 	int rc = 0;
 
@@ -239,15 +227,9 @@
 			return rc;
 	}
 
-	if ((sb->s_flags & MS_RDONLY) && !(*flags & MS_RDONLY)) {
-		/*
-		 * Invalidate any previously read metadata.  fsck may
-		 * have changed the on-disk data since we mounted r/o
-		 */
-		truncate_inode_pages(sbi->direct_mapping, 0);
-
+	if ((sb->s_flags & MS_RDONLY) && !(*flags & MS_RDONLY))
 		return jfs_mount_rw(sb, 1);
-	} else if ((!(sb->s_flags & MS_RDONLY)) && (*flags & MS_RDONLY))
+	else if ((!(sb->s_flags & MS_RDONLY)) && (*flags & MS_RDONLY))
 		return jfs_umount_rw(sb);
 
 	return 0;
@@ -289,28 +271,13 @@
 	sb->s_op = &jfs_super_operations;
 	sb->s_export_op = &jfs_export_operations;
 
-	/*
-	 * Initialize direct-mapping inode/address-space
-	 */
-	inode = new_inode(sb);
-	if (inode == NULL)
-		goto out_kfree;
-	inode->i_ino = 0;
-	inode->i_nlink = 1;
-	inode->i_size = 0x0000010000000000LL;
-	inode->i_mapping->a_ops = &direct_aops;
-	inode->i_mapping->gfp_mask = GFP_NOFS;
-
-	sbi->direct_inode = inode;
-	sbi->direct_mapping = inode->i_mapping;
-
 	rc = jfs_mount(sb);
 	if (rc) {
 		if (!silent) {
 			jERROR(1,
 			       ("jfs_mount failed w/return code = %d\n", rc));
 		}
-		goto out_mount_failed;
+		goto out_kfree;
 	}
 	if (sb->s_flags & MS_RDONLY)
 		sbi->log = 0;
@@ -360,14 +327,6 @@
 	if (rc) {
 		jERROR(1, ("jfs_umount failed with return code %d\n", rc));
 	}
-out_mount_failed:
-	filemap_fdatawrite(sbi->direct_inode->i_mapping);
-	filemap_fdatawait(sbi->direct_inode->i_mapping);
-	truncate_inode_pages(sbi->direct_mapping, 0);
-	make_bad_inode(sbi->direct_inode);
-	iput(sbi->direct_inode);
-	sbi->direct_inode = NULL;
-	sbi->direct_mapping = NULL;
 out_kfree:
 	if (sbi->nls_tab)
 		unload_nls(sbi->nls_tab);
diff -Nru a/fs/jfs/xattr.c b/fs/jfs/xattr.c
--- a/fs/jfs/xattr.c	Mon Sep  9 10:36:11 2002
+++ b/fs/jfs/xattr.c	Mon Sep  9 10:36:11 2002
@@ -79,10 +79,10 @@
 #define EA_MALLOC	0x0008
 
 /* Forward references */
-void ea_release(struct inode *inode, struct ea_buffer *ea_buf);
+static void ea_release(struct inode *inode, struct ea_buffer *ea_buf);
 
 /*
- * NAME: jfs_WriteEAInLine
+ * NAME: ea_write_inline
  *                                                                    
  * FUNCTION: Attempt to write an EA inline if area is available
  *                                                                    
@@ -103,8 +103,8 @@
  *
  * RETURNS: 0 for successful copy to inline area; -1 if area not available
  */
-static int jfs_WriteEAInLine(struct inode *ip, struct jfs_ea_list *ealist,
-			     int size, dxd_t * ea)
+static int ea_write_inline(struct inode *ip, struct jfs_ea_list *ealist,
+			   int size, dxd_t * ea)
 {
 	struct jfs_inode_info *ji = JFS_IP(ip);
 
@@ -144,7 +144,7 @@
 }
 
 /*
- * NAME: jfs_WriteEA
+ * NAME: ea_write
  *                                                                    
  * FUNCTION: Write an EA for an inode
  *                                                                    
@@ -162,7 +162,7 @@
  *
  * RETURNS: 0 for success; Anything else indicates failure
  */
-static int jfs_WriteEA(struct inode *ip, struct jfs_ea_list *ealist, int size,
+static int ea_write(struct inode *ip, struct jfs_ea_list *ealist, int size,
 		       dxd_t * ea)
 {
 	struct super_block *sb = ip->i_sb;
@@ -181,7 +181,7 @@
 	 * and empty EAs are all in-linable, provided the space exists.
 	 */
 	if (!ealist || size <= sizeof (ji->i_inline_ea)) {
-		if (!jfs_WriteEAInLine(ip, ealist, size, ea))
+		if (!ea_write_inline(ip, ealist, size, ea))
 			return 0;
 	}
 
@@ -257,7 +257,7 @@
 }
 
 /*
- * NAME: jfs_ReadEAInLine
+ * NAME: ea_read_inline
  *                                                                    
  * FUNCTION: Read an inlined EA into user's buffer
  *                                                                    
@@ -267,7 +267,7 @@
  *
  * RETURNS: 0
  */
-static int jfs_ReadEAInLine(struct inode *ip, struct jfs_ea_list *ealist)
+static int ea_read_inline(struct inode *ip, struct jfs_ea_list *ealist)
 {
 	struct jfs_inode_info *ji = JFS_IP(ip);
 	int ea_size = sizeDXD(&ji->ea);
@@ -288,7 +288,7 @@
 }
 
 /*
- * NAME: jfs_ReadEA
+ * NAME: ea_read
  *                                                                    
  * FUNCTION: copy EA data into user's buffer
  *                                                                    
@@ -296,11 +296,11 @@
  *	ip	- Inode pointer
  *	ealist	- Pointer to buffer to fill in with EA
  *
- * NOTES:  If EA is inline calls jfs_ReadEAInLine() to copy EA.
+ * NOTES:  If EA is inline calls ea_read_inline() to copy EA.
  *
  * RETURNS: 0 for success; other indicates failure
  */
-static int jfs_ReadEA(struct inode *ip, struct jfs_ea_list *ealist)
+static int ea_read(struct inode *ip, struct jfs_ea_list *ealist)
 {
 	struct super_block *sb = ip->i_sb;
 	struct jfs_inode_info *ji = JFS_IP(ip);
@@ -315,7 +315,7 @@
 
 	/* quick check for in-line EA */
 	if (ji->ea.flag & DXD_INLINE)
-		return jfs_ReadEAInLine(ip, ealist);
+		return ea_read_inline(ip, ealist);
 
 	nbytes = sizeDXD(&ji->ea);
 	assert(nbytes);
@@ -372,7 +372,7 @@
  *
  * RETURNS: 0 for success; Other indicates failure
  */
-int ea_get(struct inode *inode, struct ea_buffer *ea_buf, int min_size)
+static int ea_get(struct inode *inode, struct ea_buffer *ea_buf, int min_size)
 {
 	struct jfs_inode_info *ji = JFS_IP(inode);
 	struct super_block *sb = inode->i_sb;
@@ -436,8 +436,7 @@
 		if (ea_size == 0)
 			return 0;
 
-		rc = jfs_ReadEA(inode, ea_buf->xattr);
-		if (rc) {
+		if ((rc = ea_read(inode, ea_buf->xattr))) {
 			kfree(ea_buf->xattr);
 			ea_buf->xattr = NULL;
 			return rc;
@@ -472,8 +471,7 @@
 		    ~(sb->s_blocksize - 1);
 		if (ea_size == 0)
 			return 0;
-		rc = jfs_ReadEA(inode, ea_buf->xattr);
-		if (rc) {
+		if ((rc = ea_read(inode, ea_buf->xattr))) {
 			discard_metapage(ea_buf->mp);
 			dbFree(inode, blkno, (s64) blocks_needed);
 			return rc;
@@ -500,7 +498,7 @@
 	return ea_size;
 }
 
-void ea_release(struct inode *inode, struct ea_buffer *ea_buf)
+static void ea_release(struct inode *inode, struct ea_buffer *ea_buf)
 {
 	if (ea_buf->flag & EA_MALLOC)
 		kfree(ea_buf->xattr);
@@ -514,7 +512,7 @@
 	}
 }
 
-int ea_put(struct inode *inode, struct ea_buffer *ea_buf, int new_size)
+static int ea_put(struct inode *inode, struct ea_buffer *ea_buf, int new_size)
 {
 	struct jfs_inode_info *ji = JFS_IP(inode);
 	unsigned long old_blocks, new_blocks;
@@ -532,16 +530,14 @@
 		DXDaddress(&ea_buf->new_ea, 0);
 		DXDlength(&ea_buf->new_ea, 0);
 	} else if (ea_buf->flag & EA_MALLOC) {
-		rc = jfs_WriteEA(inode, ea_buf->xattr, new_size,
-				 &ea_buf->new_ea);
+		rc = ea_write(inode, ea_buf->xattr, new_size, &ea_buf->new_ea);
 		kfree(ea_buf->xattr);
 	} else if (ea_buf->flag & EA_NEW) {
 		/* We have already allocated a new dxd */
 		flush_metapage(ea_buf->mp);
 	} else {
 		/* ->xattr must point to original ea's metapage */
-		rc = jfs_WriteEA(inode, ea_buf->xattr, new_size,
-				 &ea_buf->new_ea);
+		rc = ea_write(inode, ea_buf->xattr, new_size, &ea_buf->new_ea);
 		discard_metapage(ea_buf->mp);
 	}
 	if (rc)
diff -Nru a/fs/lockd/clntlock.c b/fs/lockd/clntlock.c
--- a/fs/lockd/clntlock.c	Mon Sep  9 10:36:17 2002
+++ b/fs/lockd/clntlock.c	Mon Sep  9 10:36:17 2002
@@ -202,7 +202,6 @@
 	struct inode *inode;
 
 	daemonize();
-	reparent_to_init();
 	snprintf(current->comm, sizeof(current->comm),
 		 "%s-reclaim",
 		 host->h_name);
diff -Nru a/fs/lockd/svc.c b/fs/lockd/svc.c
--- a/fs/lockd/svc.c	Mon Sep  9 10:36:12 2002
+++ b/fs/lockd/svc.c	Mon Sep  9 10:36:12 2002
@@ -98,7 +98,6 @@
 	up(&lockd_start);
 
 	daemonize();
-	reparent_to_init();
 	sprintf(current->comm, "lockd");
 
 	/* Process request with signals blocked.  */
diff -Nru a/fs/locks.c b/fs/locks.c
--- a/fs/locks.c	Mon Sep  9 10:36:17 2002
+++ b/fs/locks.c	Mon Sep  9 10:36:17 2002
@@ -997,9 +997,7 @@
 	if (arg == F_UNLCK) {
 		struct file *filp = fl->fl_file;
 
-		filp->f_owner.pid = 0;
-		filp->f_owner.uid = 0;
-		filp->f_owner.euid = 0;
+		f_delown(filp);
 		filp->f_owner.signum = 0;
 		locks_delete_lock(before);
 	}
@@ -1277,13 +1275,7 @@
 	*before = fl;
 	list_add(&fl->fl_link, &file_lock_list);
 
-	error = security_ops->file_set_fowner(filp);
-	if (error)
-		goto out_unlock;
-
-	filp->f_owner.pid = current->pid;
-	filp->f_owner.uid = current->uid;
-	filp->f_owner.euid = current->euid;
+	error = f_setown(filp, current->pid, 1);
 out_unlock:
 	unlock_kernel();
 	return error;
diff -Nru a/fs/minix/dir.c b/fs/minix/dir.c
--- a/fs/minix/dir.c	Mon Sep  9 10:36:01 2002
+++ b/fs/minix/dir.c	Mon Sep  9 10:36:01 2002
@@ -7,6 +7,7 @@
  */
 
 #include "minix.h"
+#include <linux/highmem.h>
 #include <linux/smp_lock.h>
 
 typedef struct minix_dir_entry minix_dirent;
@@ -261,7 +262,7 @@
 {
 	struct address_space *mapping = page->mapping;
 	struct inode *inode = (struct inode*)mapping->host;
-	char *kaddr = (char*)page_address(page);
+	char *kaddr = page_address(page);
 	unsigned from = (char*)de - kaddr;
 	unsigned to = from + minix_sb(inode->i_sb)->s_dirsize;
 	int err;
@@ -286,7 +287,7 @@
 	struct page *page = grab_cache_page(mapping, 0);
 	struct minix_sb_info * sbi = minix_sb(inode->i_sb);
 	struct minix_dir_entry * de;
-	char *base;
+	char *kaddr;
 	int err;
 
 	if (!page)
@@ -297,15 +298,16 @@
 		goto fail;
 	}
 
-	base = (char*)page_address(page);
-	memset(base, 0, PAGE_CACHE_SIZE);
+	kaddr = kmap_atomic(page, KM_USER0);
+	memset(kaddr, 0, PAGE_CACHE_SIZE);
 
-	de = (struct minix_dir_entry *) base;
+	de = (struct minix_dir_entry *)kaddr;
 	de->inode = inode->i_ino;
 	strcpy(de->name,".");
 	de = minix_next_entry(de, sbi);
 	de->inode = dir->i_ino;
 	strcpy(de->name,"..");
+	kunmap_atomic(kaddr, KM_USER0);
 
 	err = dir_commit_chunk(page, 0, 2 * sbi->s_dirsize);
 fail:
diff -Nru a/fs/namei.c b/fs/namei.c
--- a/fs/namei.c	Mon Sep  9 10:36:01 2002
+++ b/fs/namei.c	Mon Sep  9 10:36:01 2002
@@ -2200,8 +2200,9 @@
 	err = mapping->a_ops->prepare_write(NULL, page, 0, len-1);
 	if (err)
 		goto fail_map;
-	kaddr = page_address(page);
+	kaddr = kmap_atomic(page, KM_USER0);
 	memcpy(kaddr, symname, len-1);
+	kunmap_atomic(kaddr, KM_USER0);
 	mapping->a_ops->commit_write(NULL, page, 0, len-1);
 	/*
 	 * Notice that we are _not_ going to block here - end of page is
diff -Nru a/fs/partitions/Makefile b/fs/partitions/Makefile
--- a/fs/partitions/Makefile	Mon Sep  9 10:36:11 2002
+++ b/fs/partitions/Makefile	Mon Sep  9 10:36:11 2002
@@ -2,7 +2,7 @@
 # Makefile for the linux kernel.
 #
 
-export-objs := check.o msdos.o
+export-objs := msdos.o
 
 obj-y := check.o
 
diff -Nru a/fs/partitions/check.c b/fs/partitions/check.c
--- a/fs/partitions/check.c	Mon Sep  9 10:36:07 2002
+++ b/fs/partitions/check.c	Mon Sep  9 10:36:07 2002
@@ -35,7 +35,7 @@
 #include "efi.h"
 
 #if CONFIG_BLK_DEV_MD
-extern void md_autodetect_dev(kdev_t dev);
+extern void md_autodetect_dev(dev_t dev);
 #endif
 
 int warn_no_part = 1; /*This is ugly: should make genhd removable media aware*/
@@ -87,46 +87,27 @@
  * a pointer to that same buffer (for convenience).
  */
 
-char *disk_name (struct gendisk *hd, int minor, char *buf)
+char *disk_name(struct gendisk *hd, int part, char *buf)
 {
-	unsigned int unit = (minor >> hd->minor_shift);
-	unsigned int part = (minor & ((1 << hd->minor_shift) -1 ));
-	struct hd_struct *p = hd->part + minor - hd->first_minor;
-	char s[40];
-	const char *maj;
-
-	if ((((minor - hd->first_minor) >> hd->minor_shift) < hd->nr_real) &&
-	     p->de) {
-		int pos;
-
-		pos = devfs_generate_path(p->de, buf, 64);
-		if (pos >= 0)
-			return buf + pos;
-	}
-
-	/*
-	 * Yes, I know, ... in cases is gccism and not a pretty one.  
-	 * However, the first variant will eventually consume _all_ cases
-	 * and switch will disappear.
-	 */
-	switch (hd->major) {
-		default:
-			maj = hd->major_name;
-			break;
-		case MD_MAJOR:
-			sprintf(s, "%s%d", "md", unit);
-			maj = s;
-			break;
-		case I2O_MAJOR:
-			sprintf(s, "%s%c", hd->major_name, unit + 'a');
-			maj = s;
-	}
-	if (!part)
-		sprintf(buf, "%s", maj);
-	else if (isdigit(maj[strlen(maj)-1]))
-		sprintf(buf, "%sp%d", maj, part);
-	else
-		sprintf(buf, "%s%d", maj, part);
+	int pos;
+	if (!part) {
+		if (hd->disk_de) {
+			pos = devfs_generate_path(hd->disk_de, buf, 64);
+			if (pos >= 0)
+				return buf + pos;
+		}
+		sprintf(buf, "%s", hd->major_name);
+	} else {
+		if (hd->part[part-1].de) {
+			pos = devfs_generate_path(hd->part[part-1].de, buf, 64);
+			if (pos >= 0)
+				return buf + pos;
+		}
+		if (isdigit(hd->major_name[strlen(hd->major_name)-1]))
+			sprintf(buf, "%sp%d", hd->major_name, part);
+		else
+			sprintf(buf, "%s%d", hd->major_name, part);
+	}
 	return buf;
 }
 
@@ -147,118 +128,91 @@
 }
 static DEVICE_ATTR(type,S_IRUGO,partition_device_type_read,NULL);
 
-void driverfs_create_partitions(struct gendisk *hd, int minor)
+static void driverfs_create_partitions(struct gendisk *hd)
 {
-	int pos = -1;
-	int devnum = (minor - hd->first_minor) >> hd->minor_shift;
-	char dirname[256];
-	struct device *parent = 0;
-	int max_p;
+	int max_p = 1<<hd->minor_shift;
+	struct hd_struct *p = hd->part;
+	char name[DEVICE_NAME_SIZE];
+	char bus_id[BUS_ID_SIZE];
+	struct device *dev, *parent;
 	int part;
-	devfs_handle_t dir = 0;
-	struct hd_struct *p = hd->part + minor - hd->first_minor;
-	
-	/* get parent driverfs device structure */
-	if (hd->driverfs_dev_arr)
-		parent = hd->driverfs_dev_arr[devnum];
-	else /* if driverfs not supported by subsystem, skip partitions */
-		return;
-	
-	/* get parent device node directory name */
-	if (hd->de_arr) {
-		dir = hd->de_arr[devnum];
-		if (dir)
-			pos = devfs_generate_path (dir, dirname, 
-						   sizeof dirname);
-	}
-	
-	if (pos < 0) {
-		disk_name(hd, minor, dirname);
-		pos = 0;
-	}
-	
-	max_p = (1 << hd->minor_shift);
-	
-	/* for all partitions setup parents and device node names */
-	for(part=0; part < max_p; part++) {
-		if ((part == 0) || (p[part].nr_sects >= 1)) {
-			struct device * current_driverfs_dev = 
-				&p[part].hd_driverfs_dev;
-			current_driverfs_dev->parent = parent;
-			/* handle disc case */
-			current_driverfs_dev->driver_data =
-					(void *)(long)__mkdev(hd->major, minor+part);
-			if (part == 0) {
-				if (parent)  {
-					sprintf(current_driverfs_dev->name,
-						"%sdisc", parent->name);
-					sprintf(current_driverfs_dev->bus_id,
-						"%s:disc", parent->bus_id);
-				} else {
-					sprintf(current_driverfs_dev->name, 
-						"disc");
-					sprintf(current_driverfs_dev->bus_id,
-						"disc");
-				}
-			} else { /* this is a partition */
-				if (parent) {
-					sprintf(current_driverfs_dev->name,
-						"%spart%d", parent->name, part);
-					sprintf(current_driverfs_dev->bus_id,
-						"%s:p%d", parent->bus_id, part);
-				} else {
-					sprintf(current_driverfs_dev->name, 
-						"part%d", part);
-					sprintf(current_driverfs_dev->bus_id, 
-						"p%d" ,part);
-				}
-			}
-			if (parent) current_driverfs_dev->bus = parent->bus;
-			device_register(current_driverfs_dev);
-			device_create_file(current_driverfs_dev,
-					   &dev_attr_type);
-			device_create_file(current_driverfs_dev,
-					   &dev_attr_kdev);
-		}
+
+	/* if driverfs not supported by subsystem, skip partitions */
+	if (!(hd->flags & GENHD_FL_DRIVERFS))
+		return;
+
+	parent = hd->driverfs_dev;
+
+	if (parent)  {
+		sprintf(name, "%s", parent->name);
+		sprintf(bus_id, "%s:", parent->bus_id);
+	} else {
+		*name = *bus_id = '\0';
+	}
+
+	dev = &hd->disk_dev;
+	dev->driver_data = (void *)(long)__mkdev(hd->major, hd->first_minor);
+	sprintf(dev->name, "%sdisc", name);
+	sprintf(dev->bus_id, "%sdisc", bus_id);
+	for (part=1; part < max_p; part++) {
+		dev = &p[part-1].hd_driverfs_dev;
+		sprintf(dev->name, "%spart%d", name, part);
+		sprintf(dev->bus_id, "%s:p%d", bus_id, part);
+		if (!p[part-1].nr_sects)
+			continue;
+		dev->driver_data =
+				(void *)(long)__mkdev(hd->major, hd->first_minor+part);
+	}
+
+	dev = &hd->disk_dev;
+	dev->parent = parent;
+	if (parent)
+		dev->bus = parent->bus;
+	device_register(dev);
+	device_create_file(dev, &dev_attr_type);
+	device_create_file(dev, &dev_attr_kdev);
+
+	for (part=0; part < max_p-1; part++) {
+		dev = &p[part].hd_driverfs_dev;
+		dev->parent = parent;
+		if (parent)
+			dev->bus = parent->bus;
+		if (!dev->driver_data)
+			continue;
+		device_register(dev);
+		device_create_file(dev, &dev_attr_type);
+		device_create_file(dev, &dev_attr_kdev);
 	}
 }
 
-void driverfs_remove_partitions(struct gendisk *hd, int minor)
+static void driverfs_remove_partitions(struct gendisk *hd)
 {
-	int max_p;
+	int max_p = 1<<hd->minor_shift;
+	struct device *dev;
+	struct hd_struct *p;
 	int part;
-	struct device * current_driverfs_dev;
-	struct hd_struct *p = hd->part + minor - hd->first_minor;
-	
-	max_p=(1 << hd->minor_shift);
-	
-	/* for all parts setup parent relationships and device node names */
-	for(part=1; part < max_p; part++) {
-		if ((p[part].nr_sects >= 1)) {
-			current_driverfs_dev = &p[part].hd_driverfs_dev;
-			device_remove_file(current_driverfs_dev,
-					   &dev_attr_type);
-			device_remove_file(current_driverfs_dev,
-					   &dev_attr_kdev);
-			put_device(current_driverfs_dev);	
+
+	for (part=1, p = hd->part; part < max_p; part++, p++) {
+		dev = &p->hd_driverfs_dev;
+		if (dev->driver_data) {
+			device_remove_file(dev, &dev_attr_type);
+			device_remove_file(dev, &dev_attr_kdev);
+			put_device(dev);	
+			dev->driver_data = NULL;
 		}
 	}
-	current_driverfs_dev = &p->hd_driverfs_dev;
-	device_remove_file(current_driverfs_dev,
-			   &dev_attr_type);
-	device_remove_file(current_driverfs_dev,
-			   &dev_attr_kdev);
-	put_device(current_driverfs_dev);	
-	return;
+	dev = &hd->disk_dev;
+	if (dev->driver_data) {
+		device_remove_file(dev, &dev_attr_type);
+		device_remove_file(dev, &dev_attr_kdev);
+		put_device(dev);	
+		dev->driver_data = NULL;
+	}
 }
 
-/*
- *	DON'T EXPORT
- */
-void check_partition(struct gendisk *hd, struct block_device *bdev)
+static void check_partition(struct gendisk *hd, struct block_device *bdev)
 {
 	devfs_handle_t de = NULL;
-	kdev_t dev = to_kdev_t(bdev->bd_dev);
 	char buf[64];
 	struct parsed_partitions *state;
 	int i;
@@ -267,17 +221,16 @@
 	if (!state)
 		return;
 
-	if (hd->de_arr)
-		de = hd->de_arr[(minor(dev)-hd->first_minor)>>hd->minor_shift];
+	if (hd->flags & GENHD_FL_DEVFS)
+		de = hd->de;
 	i = devfs_generate_path (de, buf, sizeof buf);
 	if (i >= 0) {
 		printk(KERN_INFO " /dev/%s:", buf + i);
 		sprintf(state->name, "p");
 	} else {
-		unsigned n = hd->major;
-		disk_name(hd, minor(dev), state->name);
+		disk_name(hd, 0, state->name);
 		printk(KERN_INFO " %s:", state->name);
-		if (n - COMPAQ_SMART2_MAJOR <= 7 || n - COMPAQ_CISS_MAJOR <= 7)
+		if (isdigit(state->name[strlen(state->name)-1]))
 			sprintf(state->name, "p");
 	}
 	state->limit = 1<<hd->minor_shift;
@@ -291,68 +244,65 @@
 		if (res < 0) {
 			if (warn_no_part)
 				printk(" unable to read partition table\n");
-			goto out;
+			return;
 		} 
-		p = hd->part + minor(dev) - hd->first_minor;
+		p = hd->part;
 		for (j = 1; j < state->limit; j++) {
-			p[j].start_sect = state->parts[j].from;
-			p[j].nr_sects = state->parts[j].size;
+			p[j-1].start_sect = state->parts[j].from;
+			p[j-1].nr_sects = state->parts[j].size;
 #if CONFIG_BLK_DEV_MD
-			if (!state->parts[j].flags)
+			if (!state->parts[j-1].flags)
 				continue;
-			md_autodetect_dev(mk_kdev(major(dev),minor(dev)+j));
+			md_autodetect_dev(bdev->bd_dev+j);
 #endif
 		}
-		goto out;
+		return;
 	}
-
 	printk(" unknown partition table\n");
-out:
-	driverfs_create_partitions(hd, minor(dev));
-	devfs_register_partitions (hd, minor(dev), 0);
 }
 
-#ifdef CONFIG_DEVFS_FS
-static void devfs_register_partition (struct gendisk *dev, int minor, int part)
+static void devfs_register_partition(struct gendisk *dev, int part)
 {
-	int devnum = (minor - dev->first_minor) >> dev->minor_shift;
+#ifdef CONFIG_DEVFS_FS
 	devfs_handle_t dir;
 	unsigned int devfs_flags = DEVFS_FL_DEFAULT;
-	struct hd_struct *p = dev->part + minor - dev->first_minor;
+	struct hd_struct *p = dev->part;
 	char devname[16];
 
-	if (p[part].de)
+	if (p[part-1].de)
 		return;
-	dir = devfs_get_parent(p[0].de);
+	dir = devfs_get_parent(dev->disk_de);
 	if (!dir)
 		return;
-	if ( dev->flags && (dev->flags[devnum] & GENHD_FL_REMOVABLE) )
+	if (dev->flags & GENHD_FL_REMOVABLE)
 		devfs_flags |= DEVFS_FL_REMOVABLE;
-	sprintf (devname, "part%d", part);
-	p[part].de = devfs_register (dir, devname, devfs_flags,
-				    dev->major, minor + part,
+	sprintf(devname, "part%d", part);
+	p[part-1].de = devfs_register (dir, devname, devfs_flags,
+				    dev->major, dev->first_minor + part,
 				    S_IFBLK | S_IRUSR | S_IWUSR,
 				    dev->fops, NULL);
+#endif
 }
 
+#ifdef CONFIG_DEVFS_FS
 static struct unique_numspace disc_numspace = UNIQUE_NUMBERSPACE_INITIALISER;
+#endif
 
-static void devfs_register_disc (struct gendisk *dev, int minor)
+static void devfs_create_partitions(struct gendisk *dev)
 {
+#ifdef CONFIG_DEVFS_FS
 	int pos = 0;
-	int devnum = (minor - dev->first_minor) >> dev->minor_shift;
 	devfs_handle_t dir, slave;
 	unsigned int devfs_flags = DEVFS_FL_DEFAULT;
 	char dirname[64], symlink[16];
 	static devfs_handle_t devfs_handle;
-	struct hd_struct *p = dev->part + minor - dev->first_minor;
+	int part, max_p = 1<<dev->minor_shift;
+	struct hd_struct *p = dev->part;
 
-	if (p[0].de)
-		return;
-	if ( dev->flags && (dev->flags[devnum] & GENHD_FL_REMOVABLE) )
+	if (dev->flags & GENHD_FL_REMOVABLE)
 		devfs_flags |= DEVFS_FL_REMOVABLE;
-	if (dev->de_arr) {
-		dir = dev->de_arr[devnum];
+	if (dev->flags & GENHD_FL_DEVFS) {
+		dir = dev->de;
 		if (!dir)  /*  Aware driver wants to block disc management  */
 			return;
 		pos = devfs_generate_path(dir, dirname + 3, sizeof dirname-3);
@@ -362,46 +312,39 @@
 	} else {
 		/*  Unaware driver: construct "real" directory  */
 		sprintf(dirname, "../%s/disc%d", dev->major_name,
-			(dev->first_minor >> dev->minor_shift) + devnum);
+			dev->first_minor >> dev->minor_shift);
 		dir = devfs_mk_dir(NULL, dirname + 3, NULL);
 	}
 	if (!devfs_handle)
 		devfs_handle = devfs_mk_dir(NULL, "discs", NULL);
-	p[0].number = devfs_alloc_unique_number (&disc_numspace);
-	sprintf(symlink, "disc%d", p[0].number);
+	dev->number = devfs_alloc_unique_number (&disc_numspace);
+	sprintf(symlink, "disc%d", dev->number);
 	devfs_mk_symlink (devfs_handle, symlink, DEVFS_FL_DEFAULT,
 			  dirname + pos, &slave, NULL);
-	p[0].de = devfs_register (dir, "disc", devfs_flags, dev->major, minor,
+	dev->disk_de = devfs_register(dir, "disc", devfs_flags,
+			    dev->major, dev->first_minor,
 			    S_IFBLK | S_IRUSR | S_IWUSR, dev->fops, NULL);
-	devfs_auto_unregister(p[0].de, slave);
-	if (!dev->de_arr)
+	devfs_auto_unregister(dev->disk_de, slave);
+	if (!(dev->flags & GENHD_FL_DEVFS))
 		devfs_auto_unregister (slave, dir);
+	for (part = 1, p++; part < max_p; part++, p++)
+		if (p->nr_sects)
+			devfs_register_partition(dev, part);
+#endif
 }
-#endif  /*  CONFIG_DEVFS_FS  */
 
-void devfs_register_partitions (struct gendisk *dev, int minor, int unregister)
+static void devfs_remove_partitions(struct gendisk *dev)
 {
 #ifdef CONFIG_DEVFS_FS
-	int part, max_p;
-	struct hd_struct *p = dev->part + minor - dev->first_minor;
-
-	if (!unregister)
-		devfs_register_disc (dev, minor);
-	max_p = (1 << dev->minor_shift);
-	for (part = 1; part < max_p; part++) {
-		if ( unregister || (p[part].nr_sects < 1) ) {
-			devfs_unregister(p[part].de);
-			p[part].de = NULL;
-			continue;
-		}
-		devfs_register_partition (dev, minor, part);
-	}
-	if (unregister) {
-		devfs_unregister(p[0].de);
-		p[0].de = NULL;
-		devfs_dealloc_unique_number(&disc_numspace, p[0].number);
-	}
-#endif  /*  CONFIG_DEVFS_FS  */
+	int part;
+	for (part = (1<<dev->minor_shift)-1; part--; ) {
+		devfs_unregister(dev->part[part].de);
+		dev->part[part].de = NULL;
+	}
+	devfs_unregister(dev->disk_de);
+	dev->disk_de = NULL;
+	devfs_dealloc_unique_number(&disc_numspace, dev->number);
+#endif
 }
 
 /*
@@ -414,28 +357,18 @@
  * done
  */
 
-void register_disk(struct gendisk *gdev, kdev_t dev, unsigned minors,
+void register_disk(struct gendisk *disk, kdev_t dev, unsigned minors,
 	struct block_device_operations *ops, long size)
 {
-	if (!gdev)
-		return;
-	grok_partitions(dev, size);
-}
-
-void grok_partitions(kdev_t dev, long size)
-{
 	struct block_device *bdev;
-	struct gendisk *g = get_gendisk(dev);
-	struct hd_struct *p;
 
-	if (!g)
+	if (!disk)
 		return;
 
-	p = g->part + minor(dev) - g->first_minor;
-	p[0].nr_sects = size;
+	set_capacity(disk, size);
 
 	/* No minors to use for partitions */
-	if (!g->minor_shift)
+	if (!disk->minor_shift)
 		return;
 
 	/* No such device (e.g., media were just removed) */
@@ -445,10 +378,66 @@
 	bdev = bdget(kdev_t_to_nr(dev));
 	if (blkdev_get(bdev, FMODE_READ, 0, BDEV_RAW) < 0)
 		return;
-	check_partition(g, bdev);
+	check_partition(disk, bdev);
+	driverfs_create_partitions(disk);
+	devfs_create_partitions(disk);
 	blkdev_put(bdev, BDEV_RAW);
 }
 
+void update_partition(struct gendisk *disk, int part)
+{
+	struct hd_struct *p = disk->part + part - 1;
+	struct device *dev = &p->hd_driverfs_dev;
+
+	if (!p->nr_sects) {
+		if (p->de) {
+			devfs_unregister(p->de);
+			p->de = NULL;
+		}
+		if (dev->driver_data) {
+			device_remove_file(dev, &dev_attr_type);
+			device_remove_file(dev, &dev_attr_kdev);
+			put_device(dev);	
+			dev->driver_data = NULL;
+		}
+		return;
+	}
+	if (!p->de)
+		devfs_register_partition(disk, part);
+	if (dev->driver_data || !(disk->flags & GENHD_FL_DRIVERFS))
+		return;
+	dev->driver_data =
+		(void *)(long)__mkdev(disk->major, disk->first_minor+part);
+	device_register(dev);
+	device_create_file(dev, &dev_attr_type);
+	device_create_file(dev, &dev_attr_kdev);
+}
+
+int rescan_partitions(struct gendisk *disk, struct block_device *bdev)
+{
+	kdev_t dev = to_kdev_t(bdev->bd_dev);
+	int p, res;
+	if (!bdev->bd_invalidated)
+		return 0;
+	if (bdev->bd_part_count)
+		return -EBUSY;
+	res = invalidate_device(dev, 1);
+	if (res)
+		return res;
+	bdev->bd_invalidated = 0;
+	for (p = 0; p < (1<<disk->minor_shift) - 1; p++) {
+		disk->part[p].start_sect = 0;
+		disk->part[p].nr_sects = 0;
+	}
+	if (bdev->bd_op->revalidate)
+		bdev->bd_op->revalidate(dev);
+	if (get_capacity(disk))
+		check_partition(disk, bdev);
+	for (p = 1; p < (1<<disk->minor_shift); p++)
+		update_partition(disk, p);
+	return res;
+}
+
 unsigned char *read_dev_sector(struct block_device *bdev, unsigned long n, Sector *p)
 {
 	struct address_space *mapping = bdev->bd_inode->i_mapping;
@@ -472,38 +461,46 @@
 	return NULL;
 }
 
-int wipe_partitions(kdev_t dev)
+static int wipe_partitions(struct gendisk *disk)
 {
-	struct gendisk *g;
+	int max_p = 1 << disk->minor_shift;
 	kdev_t devp;
-	int p, major, minor, minor0, max_p, res;
-	struct hd_struct *part;
-
-	g = get_gendisk(dev);
-	if (g == NULL)
-		return -EINVAL;
-
-	max_p = 1 << g->minor_shift;
-	major = major(dev);
-	minor = minor(dev);
-	minor0 = minor & ~(max_p - 1);
-	if (minor0 != minor)		/* for now only whole-disk reread */
-		return -EINVAL;		/* %%% later.. */
+	int res;
+	int p;
 
-	part = g->part + minor - g->first_minor;
 	/* invalidate stuff */
-	for (p = max_p - 1; p >= 0; p--) {
-		minor = minor0 + p;
-		devp = mk_kdev(major,minor);
+	for (p = max_p - 1; p > 0; p--) {
+		devp = mk_kdev(disk->major,disk->first_minor + p);
 #if 0					/* %%% superfluous? */
-		if (part[p].nr_sects == 0)
+		if (disk->part[p-1].nr_sects == 0)
 			continue;
 #endif
 		res = invalidate_device(devp, 1);
 		if (res)
 			return res;
-		part[p].start_sect = 0;
-		part[p].nr_sects = 0;
+		disk->part[p-1].start_sect = 0;
+		disk->part[p-1].nr_sects = 0;
 	}
+	devp = mk_kdev(disk->major,disk->first_minor);
+#if 0					/* %%% superfluous? */
+	if (disk->part[p].nr_sects == 0)
+		continue;
+#endif
+	res = invalidate_device(devp, 1);
+	if (res)
+		return res;
+	disk->capacity = 0;
 	return 0;
+}
+
+void del_gendisk(struct gendisk *disk)
+{
+	driverfs_remove_partitions(disk);
+	wipe_partitions(disk);
+	unlink_gendisk(disk);
+	devfs_remove_partitions(disk);
+	if (disk->part) {
+		kfree(disk->part);
+		disk->part = NULL;
+	}
 }
diff -Nru a/fs/ramfs/inode.c b/fs/ramfs/inode.c
--- a/fs/ramfs/inode.c	Mon Sep  9 10:36:01 2002
+++ b/fs/ramfs/inode.c	Mon Sep  9 10:36:01 2002
@@ -26,6 +26,7 @@
 #include <linux/module.h>
 #include <linux/fs.h>
 #include <linux/pagemap.h>
+#include <linux/highmem.h>
 #include <linux/init.h>
 #include <linux/string.h>
 #include <linux/smp_lock.h>
@@ -47,8 +48,10 @@
 static int ramfs_readpage(struct file *file, struct page * page)
 {
 	if (!PageUptodate(page)) {
-		memset(kmap(page), 0, PAGE_CACHE_SIZE);
-		kunmap(page);
+		char *kaddr = kmap_atomic(page, KM_USER0);
+
+		memset(kaddr, 0, PAGE_CACHE_SIZE);
+		kunmap_atomic(kaddr, KM_USER0);
 		flush_dcache_page(page);
 		SetPageUptodate(page);
 	}
@@ -58,10 +61,12 @@
 
 static int ramfs_prepare_write(struct file *file, struct page *page, unsigned offset, unsigned to)
 {
-	void *addr = kmap(page);
 	if (!PageUptodate(page)) {
-		memset(addr, 0, PAGE_CACHE_SIZE);
+		char *kaddr = kmap_atomic(page, KM_USER0);
+
+		memset(kaddr, 0, PAGE_CACHE_SIZE);
 		flush_dcache_page(page);
+		kunmap_atomic(kaddr, KM_USER0);
 		SetPageUptodate(page);
 	}
 	SetPageDirty(page);
@@ -73,7 +78,6 @@
 	struct inode *inode = page->mapping->host;
 	loff_t pos = ((loff_t)page->index << PAGE_CACHE_SHIFT) + to;
 
-	kunmap(page);
 	if (pos > inode->i_size)
 		inode->i_size = pos;
 	return 0;
diff -Nru a/fs/reiserfs/bitmap.c b/fs/reiserfs/bitmap.c
--- a/fs/reiserfs/bitmap.c	Mon Sep  9 10:36:12 2002
+++ b/fs/reiserfs/bitmap.c	Mon Sep  9 10:36:12 2002
@@ -1,26 +1,63 @@
 /*
  * Copyright 2000 by Hans Reiser, licensing governed by reiserfs/README
  */
+/* Reiserfs block (de)allocator, bitmap-based. */
 
 #include <linux/config.h>
 #include <linux/time.h>
 #include <linux/reiserfs_fs.h>
-#include <asm/bitops.h>
-#include <linux/list.h>
+#include <linux/errno.h>
 #include <linux/buffer_head.h>
+#include <linux/kernel.h>
+#include <linux/reiserfs_fs.h>
+#include <linux/reiserfs_fs_sb.h>
+#include <linux/reiserfs_fs_i.h>
 
-#ifdef CONFIG_REISERFS_CHECK
+#define PREALLOCATION_SIZE 9
+
+/* different reiserfs block allocator options */
+
+#define SB_ALLOC_OPTS(s) (REISERFS_SB(s)->s_alloc_options.bits)
 
-/* this is a safety check to make sure
-** blocks are reused properly.  used for debugging only.
-**
-** this checks, that block can be reused, and it has correct state
-**   (free or busy) 
-*/
+#define  _ALLOC_concentrating_formatted_nodes 0
+#define  _ALLOC_displacing_large_files 1
+#define  _ALLOC_displacing_new_packing_localities 2
+#define  _ALLOC_old_hashed_relocation 3
+#define  _ALLOC_new_hashed_relocation 4
+#define  _ALLOC_skip_busy 5
+#define  _ALLOC_displace_based_on_dirid 6
+#define  _ALLOC_hashed_formatted_nodes 7
+#define  _ALLOC_old_way 8
+#define  _ALLOC_hundredth_slices 9
+
+#define  concentrating_formatted_nodes(s)	test_bit(_ALLOC_concentrating_formatted_nodes, &SB_ALLOC_OPTS(s))
+#define  displacing_large_files(s)		test_bit(_ALLOC_displacing_large_files, &SB_ALLOC_OPTS(s))
+#define  displacing_new_packing_localities(s)	test_bit(_ALLOC_displacing_new_packing_localities, &SB_ALLOC_OPTS(s))
+
+#define SET_OPTION(optname) \
+   do { \
+        reiserfs_warning("reiserfs: option \"%s\" is set\n", #optname); \
+        set_bit(_ALLOC_ ## optname , &SB_ALLOC_OPTS(s)); \
+    } while(0)
+#define TEST_OPTION(optname, s) \
+    test_bit(_ALLOC_ ## optname , &SB_ALLOC_OPTS(s))
+
+static inline void get_bit_address (struct super_block * s,
+				    unsigned long block, int * bmap_nr, int * offset)
+{
+    /* It is in the bitmap block number equal to the block
+     * number divided by the number of bits in a block. */
+    *bmap_nr = block / (s->s_blocksize << 3);
+    /* Within that bitmap block it is located at bit offset *offset. */
+    *offset = block & ((s->s_blocksize << 3) - 1 );
+    return;
+}
+
+#ifdef CONFIG_REISERFS_CHECK
 int is_reusable (struct super_block * s, unsigned long block, int bit_value)
 {
     int i, j;
-  
+
     if (block == 0 || block >= SB_BLOCK_COUNT (s)) {
 	reiserfs_warning ("vs-4010: is_reusable: block number is out of range %lu (%u)\n",
 			  block, SB_BLOCK_COUNT (s));
@@ -29,104 +66,269 @@
 
     /* it can't be one of the bitmap blocks */
     for (i = 0; i < SB_BMAP_NR (s); i ++)
-	if (block == SB_AP_BITMAP (s)[i]->b_blocknr) {
+	if (block == SB_AP_BITMAP (s)[i].bh->b_blocknr) {
 	    reiserfs_warning ("vs: 4020: is_reusable: "
 			      "bitmap block %lu(%u) can't be freed or reused\n",
 			      block, SB_BMAP_NR (s));
 	    return 0;
 	}
   
-    i = block / (s->s_blocksize << 3);
+    get_bit_address (s, block, &i, &j);
+
     if (i >= SB_BMAP_NR (s)) {
 	reiserfs_warning ("vs-4030: is_reusable: there is no so many bitmap blocks: "
 			  "block=%lu, bitmap_nr=%d\n", block, i);
 	return 0;
     }
 
-    j = block % (s->s_blocksize << 3);
     if ((bit_value == 0 && 
-         reiserfs_test_le_bit(j, SB_AP_BITMAP(s)[i]->b_data)) ||
+         reiserfs_test_le_bit(j, SB_AP_BITMAP(s)[i].bh->b_data)) ||
 	(bit_value == 1 && 
-	 reiserfs_test_le_bit(j, SB_AP_BITMAP (s)[i]->b_data) == 0)) {
+	 reiserfs_test_le_bit(j, SB_AP_BITMAP (s)[i].bh->b_data) == 0)) {
 	reiserfs_warning ("vs-4040: is_reusable: corresponding bit of block %lu does not "
 			  "match required value (i==%d, j==%d) test_bit==%d\n",
-		block, i, j, reiserfs_test_le_bit (j, SB_AP_BITMAP (s)[i]->b_data));
+		block, i, j, reiserfs_test_le_bit (j, SB_AP_BITMAP (s)[i].bh->b_data));
+
 	return 0;
     }
 
     if (bit_value == 0 && block == SB_ROOT_BLOCK (s)) {
 	reiserfs_warning ("vs-4050: is_reusable: this is root block (%u), "
-			  "it must be busy", SB_ROOT_BLOCK (s));
+			  "it must be busy\n", SB_ROOT_BLOCK (s));
 	return 0;
     }
 
     return 1;
 }
+#endif /* CONFIG_REISERFS_CHECK */
+
+/* searches in journal structures for a given block number (bmap, off). If block
+   is found in reiserfs journal it suggests next free block candidate to test. */
+static inline  int is_block_in_journal (struct super_block * s, int bmap, int
+off, int *next)
+{
+    unsigned long tmp;
 
+    if (reiserfs_in_journal (s, bmap, off, 1, &tmp)) {
+	if (tmp) {              /* hint supplied */
+	    *next = tmp;
+	    PROC_INFO_INC( s, scan_bitmap.in_journal_hint );
+	} else {
+	    (*next) = off + 1;          /* inc offset to avoid looping. */
+	    PROC_INFO_INC( s, scan_bitmap.in_journal_nohint );
+	}
+	PROC_INFO_INC( s, scan_bitmap.retry );
+	return 1;
+    }
+    return 0;
+}
 
+/* it searches for a window of zero bits with given minimum and maximum lengths in one bitmap
+ * block; */
+static int scan_bitmap_block (struct reiserfs_transaction_handle *th,
+			      int bmap_n, int *beg, int boundary, int min, int max, int unfm)
+{
+    struct super_block *s = th->t_super;
+    struct reiserfs_bitmap_info *bi=&SB_AP_BITMAP(s)[bmap_n];
+    int end, next;
+    int org = *beg;
+
+    RFALSE(bmap_n >= SB_BMAP_NR (s), "Bitmap %d is out of range (0..%d)\n",bmap_n, SB_BMAP_NR (s) - 1);
+    PROC_INFO_INC( s, scan_bitmap.bmap );
+/* this is unclear and lacks comments, explain how journal bitmaps
+   work here for the reader.  Convey a sense of the design here. What
+   is a window? */
+/* - I mean `a window of zero bits' as in description of this function - Zam. */
+  
+    if ( !bi ) {
+	printk("Hey, bitmap info pointer is zero for bitmap %d!\n",bmap_n);
+	return 0;
+    }
+    if (buffer_locked (bi->bh)) {
+       PROC_INFO_INC( s, scan_bitmap.wait );
+       __wait_on_buffer (bi->bh);
+    }
+
+    /* If we know that first zero bit is only one or first zero bit is
+       closer to the end of bitmap than our start pointer */
+    if (bi->first_zero_hint > *beg || bi->free_count == 1)
+	*beg = bi->first_zero_hint;
+
+    while (1) {
+	cont:
+	if (bi->free_count < min)
+		return 0; // No free blocks in this bitmap
+
+	/* search for a first zero bit -- beggining of a window */
+	*beg = reiserfs_find_next_zero_le_bit
+	        ((unsigned long*)(bi->bh->b_data), boundary, *beg);
+  
+	if (*beg + min > boundary) { /* search for a zero bit fails or the rest of bitmap block
+				      * cannot contain a zero window of minimum size */
+	    return 0;
+	}
 
+	if (unfm && is_block_in_journal(s,bmap_n, *beg, beg))
+	    continue;
+	/* first zero bit found; we check next bits */
+	for (end = *beg + 1;; end ++) {
+	    if (end >= *beg + max || end >= boundary || reiserfs_test_le_bit (end, bi->bh->b_data)) {
+		next = end;
+		break;
+	    }
+	    /* finding the other end of zero bit window requires looking into journal structures (in
+	     * case of searching for free blocks for unformatted nodes) */
+	    if (unfm && is_block_in_journal(s, bmap_n, end, &next))
+		break;
+	}
 
-#endif /* CONFIG_REISERFS_CHECK */
+	/* now (*beg) points to beginning of zero bits window,
+	 * (end) points to one bit after the window end */
+	if (end - *beg >= min) { /* it seems we have found window of proper size */
+	    int i;
+	    reiserfs_prepare_for_journal (s, bi->bh, 1);
+	    /* try to set all blocks used checking are they still free */
+	    for (i = *beg; i < end; i++) {
+		/* It seems that we should not check in journal again. */
+		if (reiserfs_test_and_set_le_bit (i, bi->bh->b_data)) {
+		    /* bit was set by another process
+		     * while we slept in prepare_for_journal() */
+		    PROC_INFO_INC( s, scan_bitmap.stolen );
+		    if (i >= *beg + min)	{ /* we can continue with smaller set of allocated blocks,
+					   * if length of this set is more or equal to `min' */
+			end = i;
+			break;
+		    }
+		    /* otherwise we clear all bit were set ... */
+		    while (--i >= *beg)
+			reiserfs_test_and_clear_le_bit (i, bi->bh->b_data);
+		    reiserfs_restore_prepared_buffer (s, bi->bh);
+		    *beg = max(org, (int)bi->first_zero_hint);
+		    /* ... and search again in current block from beginning */
+		    goto cont;	
+		}
+	    }
+	    bi->free_count -= (end - *beg);
+
+	    /* if search started from zero_hint bit, and zero hint have not
+                changed since, then we need to update first_zero_hint */
+	    if ( bi->first_zero_hint >= *beg)
+		/* no point in looking for free bit if there is not any */
+		bi->first_zero_hint = (bi->free_count > 0 ) ?
+			reiserfs_find_next_zero_le_bit
+			((unsigned long*)(bi->bh->b_data), s->s_blocksize << 3, end) : (s->s_blocksize << 3);
+
+	    journal_mark_dirty (th, s, bi->bh);
+
+	    /* free block count calculation */
+	    reiserfs_prepare_for_journal (s, SB_BUFFER_WITH_SB(s), 1);
+	    PUT_SB_FREE_BLOCKS(s, SB_FREE_BLOCKS(s) - (end - *beg));
+	    journal_mark_dirty (th, s, SB_BUFFER_WITH_SB(s));
 
-/* get address of corresponding bit (bitmap block number and offset in it) */
-static inline void get_bit_address (struct super_block * s, unsigned long block, int * bmap_nr, int * offset)
+	    return end - (*beg);
+	} else {
+	    *beg = next;
+	}
+    }
+  }
+  
+/* Tries to find contiguous zero bit window (given size) in given region of
+ * bitmap and place new blocks there. Returns number of allocated blocks. */
+static int scan_bitmap (struct reiserfs_transaction_handle *th,
+			unsigned long *start, unsigned long finish,
+			int min, int max, int unfm, unsigned long file_block)
 {
-                                /* It is in the bitmap block number equal to the block number divided by the number of
-                                   bits in a block. */
-    *bmap_nr = block / (s->s_blocksize << 3);
-                                /* Within that bitmap block it is located at bit offset *offset. */
-    *offset = block % (s->s_blocksize << 3);
-    return;
-}
+    int nr_allocated=0;
+    struct super_block * s = th->t_super;
+    /* find every bm and bmap and bmap_nr in this file, and change them all to bitmap_blocknr
+     * - Hans, it is not a block number - Zam. */
 
+    int bm, off;
+    int end_bm, end_off;
+    int off_max = s->s_blocksize << 3;
+
+    PROC_INFO_INC( s, scan_bitmap.call ); 
+    if ( SB_FREE_BLOCKS(s) <= 0)
+	return 0; // No point in looking for more free blocks
+
+    get_bit_address (s, *start, &bm, &off);
+    get_bit_address (s, finish, &end_bm, &end_off);
+
+    // With this option set first we try to find a bitmap that is at least 10%
+    // free, and if that fails, then we fall back to old whole bitmap scanning
+    if ( TEST_OPTION(skip_busy, s) && SB_FREE_BLOCKS(s) > SB_BLOCK_COUNT(s)/20 ) {
+	for (;bm < end_bm; bm++, off = 0) {
+	    if ( ( off && (!unfm || (file_block != 0))) || SB_AP_BITMAP(s)[bm].free_count > (s->s_blocksize << 3) / 10 )
+		nr_allocated = scan_bitmap_block(th, bm, &off, off_max, min, max, unfm);
+	    if (nr_allocated)
+		goto ret;
+        }
+	get_bit_address (s, *start, &bm, &off);
+    }
+
+    for (;bm < end_bm; bm++, off = 0) {
+	nr_allocated = scan_bitmap_block(th, bm, &off, off_max, min, max, unfm);
+	if (nr_allocated)
+	    goto ret;
+    }
 
-/* There would be a modest performance benefit if we write a version
-   to free a list of blocks at once. -Hans */
-				/* I wonder if it would be less modest
-                                   now that we use journaling. -Hans */
-static void _reiserfs_free_block (struct reiserfs_transaction_handle *th, unsigned long block)
+    nr_allocated = scan_bitmap_block(th, bm, &off, end_off + 1, min, max, unfm);
+  
+ ret:
+    *start = bm * off_max + off;
+    return nr_allocated;
+
+}
+
+static void _reiserfs_free_block (struct reiserfs_transaction_handle *th,
+				  unsigned long block)
 {
     struct super_block * s = th->t_super;
     struct reiserfs_super_block * rs;
     struct buffer_head * sbh;
-    struct buffer_head ** apbh;
+    struct reiserfs_bitmap_info *apbi;
     int nr, offset;
 
-  PROC_INFO_INC( s, free_block );
+    PROC_INFO_INC( s, free_block );
 
-  rs = SB_DISK_SUPER_BLOCK (s);
-  sbh = SB_BUFFER_WITH_SB (s);
-  apbh = SB_AP_BITMAP (s);
-
-  get_bit_address (s, block, &nr, &offset);
-
-  if (nr >= sb_bmap_nr (rs)) {
-	  reiserfs_warning ("vs-4075: reiserfs_free_block: "
-			    "block %lu is out of range on %s\n", 
-			    block, reiserfs_bdevname (s));
-	  return;
-  }
+    rs = SB_DISK_SUPER_BLOCK (s);
+    sbh = SB_BUFFER_WITH_SB (s);
+    apbi = SB_AP_BITMAP(s);
 
-  reiserfs_prepare_for_journal(s, apbh[nr], 1 ) ;
+    get_bit_address (s, block, &nr, &offset);
 
-  /* clear bit for the given block in bit map */
-  if (!reiserfs_test_and_clear_le_bit (offset, apbh[nr]->b_data)) {
-      reiserfs_warning ("vs-4080: reiserfs_free_block: "
-			"free_block (%s:%lu)[dev:blocknr]: bit already cleared\n", 
-			reiserfs_bdevname (s), block);
-  }
-  journal_mark_dirty (th, s, apbh[nr]);
+    if (nr >= sb_bmap_nr (rs)) {
+	reiserfs_warning ("vs-4075: reiserfs_free_block: "
+			  "block %lu is out of range on %s\n", 
+			  block, reiserfs_bdevname (s));
+	return;
+    }
+
+    reiserfs_prepare_for_journal(s, apbi[nr].bh, 1 ) ;
 
-  reiserfs_prepare_for_journal(s, sbh, 1) ;
-  /* update super block */
-  set_sb_free_blocks( rs, sb_free_blocks(rs) + 1 );
+    /* clear bit for the given block in bit map */
+    if (!reiserfs_test_and_clear_le_bit (offset, apbi[nr].bh->b_data)) {
+	reiserfs_warning ("vs-4080: reiserfs_free_block: "
+			  "free_block (%s:%lu)[dev:blocknr]: bit already cleared\n", 
+			  reiserfs_bdevname (s), block);
+    }
+    if (offset < apbi[nr].first_zero_hint) {
+      apbi[nr].first_zero_hint = offset;
+    }
+    apbi[nr].free_count ++;
+    journal_mark_dirty (th, s, apbi[nr].bh);
 
-  journal_mark_dirty (th, s, sbh);
+    reiserfs_prepare_for_journal(s, sbh, 1) ;
+    /* update super block */
+    set_sb_free_blocks( rs, sb_free_blocks(rs) + 1 );
+
+    journal_mark_dirty (th, s, sbh);
   s->s_dirt = 1;
 }
 
 void reiserfs_free_block (struct reiserfs_transaction_handle *th, 
-                          unsigned long block) {
+                          unsigned long block)
+{
     struct super_block * s = th->t_super;
 
     RFALSE(!s, "vs-4061: trying to free block on nonexistent device");
@@ -144,571 +346,557 @@
     _reiserfs_free_block(th, block) ;
 }
 
-/* beginning from offset-th bit in bmap_nr-th bitmap block,
-   find_forward finds the closest zero bit. It returns 1 and zero
-   bit address (bitmap, offset) if zero bit found or 0 if there is no
-   zero bit in the forward direction */
-/* The function is NOT SCHEDULE-SAFE! */
-static int find_forward (struct super_block * s, int * bmap_nr, int * offset, int for_unformatted)
-{
-  int i, j;
-  struct buffer_head * bh;
-  unsigned long block_to_try = 0;
-  unsigned long next_block_to_try = 0 ;
-
-  PROC_INFO_INC( s, find_forward.call );
-
-  for (i = *bmap_nr; i < SB_BMAP_NR (s); i ++, *offset = 0, 
-	       PROC_INFO_INC( s, find_forward.bmap )) {
-    /* get corresponding bitmap block */
-    bh = SB_AP_BITMAP (s)[i];
-    if (buffer_locked (bh)) {
-	PROC_INFO_INC( s, find_forward.wait );
-        __wait_on_buffer (bh);
-    }
-retry:
-    j = reiserfs_find_next_zero_le_bit ((unsigned long *)bh->b_data, 
-                                         s->s_blocksize << 3, *offset);
-
-    /* wow, this really needs to be redone.  We can't allocate a block if
-    ** it is in the journal somehow.  reiserfs_in_journal makes a suggestion
-    ** for a good block if the one you ask for is in the journal.  Note,
-    ** reiserfs_in_journal might reject the block it suggests.  The big
-    ** gain from the suggestion is when a big file has been deleted, and
-    ** many blocks show free in the real bitmap, but are all not free
-    ** in the journal list bitmaps.
-    **
-    ** this whole system sucks.  The bitmaps should reflect exactly what
-    ** can and can't be allocated, and the journal should update them as
-    ** it goes.  TODO.
-    */
-    if (j < (s->s_blocksize << 3)) {
-      block_to_try = (i * (s->s_blocksize << 3)) + j; 
-
-      /* the block is not in the journal, we can proceed */
-      if (!(reiserfs_in_journal(s, block_to_try, for_unformatted, &next_block_to_try))) {
-	*bmap_nr = i;
-	*offset = j;
-	return 1;
-      } 
-      /* the block is in the journal */
-      else if ((j+1) < (s->s_blocksize << 3)) { /* try again */
-	/* reiserfs_in_journal suggested a new block to try */
-	if (next_block_to_try > 0) {
-	  int new_i ;
-	  get_bit_address (s, next_block_to_try, &new_i, offset);
-
-	  PROC_INFO_INC( s, find_forward.in_journal_hint );
-
-	  /* block is not in this bitmap. reset i and continue
-	  ** we only reset i if new_i is in a later bitmap.
-	  */
-	  if (new_i > i) {
-	    i = (new_i - 1 ); /* i gets incremented by the for loop */
-	    PROC_INFO_INC( s, find_forward.in_journal_out );
-	    continue ;
-	  }
-	} else {
-	  /* no suggestion was made, just try the next block */
-	  *offset = j+1 ;
+static void __discard_prealloc (struct reiserfs_transaction_handle * th,
+				struct reiserfs_inode_info *ei)
+{
+    unsigned long save = ei->i_prealloc_block ;
+#ifdef CONFIG_REISERFS_CHECK
+    if (ei->i_prealloc_count < 0)
+	reiserfs_warning("zam-4001:%s: inode has negative prealloc blocks count.\n", __FUNCTION__ );
+#endif
+    while (ei->i_prealloc_count > 0) {
+	reiserfs_free_prealloc_block(th,ei->i_prealloc_block);
+	ei->i_prealloc_block++;
+	ei->i_prealloc_count --;
+    }
+    ei->i_prealloc_block = save;
+    list_del_init(&(ei->i_prealloc_list));
+}
+
+/* FIXME: It should be inline function */
+void reiserfs_discard_prealloc (struct reiserfs_transaction_handle *th, 
+				struct inode * inode)
+{
+    struct reiserfs_inode_info *ei = REISERFS_I(inode);
+    if (ei->i_prealloc_count) {
+	__discard_prealloc(th, ei);
+    }
+}
+
+void reiserfs_discard_all_prealloc (struct reiserfs_transaction_handle *th)
+{
+    struct list_head * plist = &SB_JOURNAL(th->t_super)->j_prealloc_list;
+
+    while (!list_empty(plist)) {
+	struct reiserfs_inode_info *ei;
+	ei = list_entry(plist->next, struct reiserfs_inode_info, i_prealloc_list);
+#ifdef CONFIG_REISERFS_CHECK
+	if (!ei->i_prealloc_count) {
+	    reiserfs_warning("zam-4001:%s: inode is in prealloc list but has no preallocated blocks.\n", __FUNCTION__);
 	}
-	PROC_INFO_INC( s, find_forward.retry );
-	goto retry ;
-      }
+#endif
+	__discard_prealloc(th, ei);
     }
-  }
-    /* zero bit not found */
-    return 0;
 }
+/* block allocator related options are parsed here */
+int reiserfs_parse_alloc_options(struct super_block * s, char * options)
+{
+    char * this_char, * value;
+
+    REISERFS_SB(s)->s_alloc_options.bits = 0; /* clear default settings */
 
-/* return 0 if no free blocks, else return 1 */
-/* The function is NOT SCHEDULE-SAFE!  
-** because the bitmap block we want to change could be locked, and on its
-** way to the disk when we want to read it, and because of the 
-** flush_async_commits.  Per bitmap block locks won't help much, and 
-** really aren't needed, as we retry later on if we try to set the bit
-** and it is already set.
-*/
-static int find_zero_bit_in_bitmap (struct super_block * s, 
-                                    unsigned long search_start, 
-				    int * bmap_nr, int * offset, 
-				    int for_unformatted)
-{
-  int retry_count = 0 ;
-  /* get bit location (bitmap number and bit offset) of search_start block */
-  get_bit_address (s, search_start, bmap_nr, offset);
-
-    /* note that we search forward in the bitmap, benchmarks have shown that it is better to allocate in increasing
-       sequence, which is probably due to the disk spinning in the forward direction.. */
-    if (find_forward (s, bmap_nr, offset, for_unformatted) == 0) {
-      /* there wasn't a free block with number greater than our
-         starting point, so we are going to go to the beginning of the disk */
-
-retry:
-      search_start = 0; /* caller will reset search_start for itself also. */
-      get_bit_address (s, search_start, bmap_nr, offset);
-      if (find_forward (s, bmap_nr,offset,for_unformatted) == 0) {
-	if (for_unformatted) {	/* why only unformatted nodes? -Hans */
-	  if (retry_count == 0) {
-	    /* we've got a chance that flushing async commits will free up
-	    ** some space.  Sync then retry
-	    */
-	    flush_async_commits(s) ;
-	    retry_count++ ;
-	    goto retry ;
-	  } else if (retry_count > 0) {
-	    /* nothing more we can do.  Make the others wait, flush
-	    ** all log blocks to disk, and flush to their home locations.
-	    ** this will free up any blocks held by the journal
-	    */
-	    SB_JOURNAL(s)->j_must_wait = 1 ;
-	  }
+    for (this_char = strsep (&options, ":"); this_char != NULL; ) {
+	if ((value = strchr (this_char, '=')) != NULL)
+	    *value++ = 0;
+
+	if (!strcmp(this_char, "concentrating_formatted_nodes")) {
+	    int temp;
+	    SET_OPTION(concentrating_formatted_nodes);
+	    temp = (value && *value) ? simple_strtoul (value, &value, 0) : 10;
+	    if (temp <= 0 || temp > 100) {
+		REISERFS_SB(s)->s_alloc_options.border = 10;
+	    } else {
+		REISERFS_SB(s)->s_alloc_options.border = 100 / temp;
+	   }
+	    continue;
 	}
-        return 0;
+	if (!strcmp(this_char, "displacing_large_files")) {
+	    SET_OPTION(displacing_large_files);
+	    REISERFS_SB(s)->s_alloc_options.large_file_size =
+		(value && *value) ? simple_strtoul (value, &value, 0) : 16;
+	    continue;
+	}
+	if (!strcmp(this_char, "displacing_new_packing_localities")) {
+	    SET_OPTION(displacing_new_packing_localities);
+	    continue;
+	};
+
+	if (!strcmp(this_char, "old_hashed_relocation")) {
+	    SET_OPTION(old_hashed_relocation);
+	    continue;
+	}
+
+	if (!strcmp(this_char, "new_hashed_relocation")) {
+	    SET_OPTION(new_hashed_relocation);
+	    continue;
+	}
+
+	if (!strcmp(this_char, "hashed_formatted_nodes")) {
+	    SET_OPTION(hashed_formatted_nodes);
+	    continue;
+	}
+
+	if (!strcmp(this_char, "skip_busy")) {
+	    SET_OPTION(skip_busy);
+	    continue;
+	}
+
+	if (!strcmp(this_char, "hundredth_slices")) {
+	    SET_OPTION(hundredth_slices);
+	    continue;
+	}
+
+	if (!strcmp(this_char, "old_way")) {
+	    SET_OPTION(old_way);
+	    continue;
+	}
+
+	if (!strcmp(this_char, "displace_based_on_dirid")) {
+	    SET_OPTION(displace_based_on_dirid);
+	    continue;
+	}
+
+	if (!strcmp(this_char, "preallocmin")) {
+	    REISERFS_SB(s)->s_alloc_options.preallocmin =
+		(value && *value) ? simple_strtoul (value, &value, 0) : 4;
+	    continue;
+	}
+
+	if (!strcmp(this_char, "preallocsize")) {
+	    REISERFS_SB(s)->s_alloc_options.preallocsize =
+		(value && *value) ? simple_strtoul (value, &value, 0) : PREALLOCATION_SIZE;
+	    continue;
+	}
+
+	reiserfs_warning("zam-4001: %s : unknown option - %s\n", __FUNCTION__ , this_char);
+	return 1;
       }
-    }
-  return 1;
+  
+    return 0;
 }
+  
+static void inline new_hashed_relocation (reiserfs_blocknr_hint_t * hint)
+{
+    char * hash_in;
+    if (hint->formatted_node) {
+	    hash_in = (char*)&hint->key.k_dir_id;
+    } else {
+	if (!hint->inode) {
+	    //hint->search_start = hint->beg;
+	    hash_in = (char*)&hint->key.k_dir_id;
+	} else 
+	    if ( TEST_OPTION(displace_based_on_dirid, hint->th->t_super))
+		hash_in = (char *)(&INODE_PKEY(hint->inode)->k_dir_id);
+	    else
+		hash_in = (char *)(&INODE_PKEY(hint->inode)->k_objectid);
+      }
 
-/* get amount_needed free block numbers from scanning the bitmap of
-   free/used blocks.
-   
-   Optimize layout by trying to find them starting from search_start
-   and moving in increasing blocknr direction.  (This was found to be
-   faster than using a bi-directional elevator_direction, in part
-   because of disk spin direction, in part because by the time one
-   reaches the end of the disk the beginning of the disk is the least
-   congested).
-
-   search_start is the block number of the left
-   semantic neighbor of the node we create.
-
-   return CARRY_ON if everything is ok
-   return NO_DISK_SPACE if out of disk space
-   return NO_MORE_UNUSED_CONTIGUOUS_BLOCKS if the block we found is not contiguous to the last one
-   
-   return block numbers found, in the array free_blocknrs.  assumes
-   that any non-zero entries already present in the array are valid.
-   This feature is perhaps convenient coding when one might not have
-   used all blocknrs from the last time one called this function, or
-   perhaps it is an archaism from the days of schedule tracking, one
-   of us ought to reread the code that calls this, and analyze whether
-   it is still the right way to code it.
-
-   spare space is used only when priority is set to 1. reiserfsck has
-   its own reiserfs_new_blocknrs, which can use reserved space
-
-   exactly what reserved space?  the SPARE_SPACE?  if so, please comment reiserfs.h.
-
-   Give example of who uses spare space, and say that it is a deadlock
-   avoidance mechanism.  -Hans */
-
-/* This function is NOT SCHEDULE-SAFE! */
-
-static int do_reiserfs_new_blocknrs (struct reiserfs_transaction_handle *th,
-                                     unsigned long * free_blocknrs, 
-				     unsigned long search_start, 
-				     int amount_needed, int priority, 
-				     int for_unformatted,
-				     int for_prealloc)
-{
-  struct super_block * s = th->t_super;
-  int i, j;
-  unsigned long * block_list_start = free_blocknrs;
-  int init_amount_needed = amount_needed;
-  unsigned long new_block = 0 ; 
-
-    if (SB_FREE_BLOCKS (s) < SPARE_SPACE && !priority)
-	/* we can answer NO_DISK_SPACE being asked for new block with
-	   priority 0 */
-	return NO_DISK_SPACE;
-
-  RFALSE( !s, "vs-4090: trying to get new block from nonexistent device");
-  RFALSE( search_start == MAX_B_NUM,
-	  "vs-4100: we are optimizing location based on "
-	  "the bogus location of a temp buffer (%lu).", search_start);
-  RFALSE( amount_needed < 1 || amount_needed > 2,
-	  "vs-4110: amount_needed parameter incorrect (%d)", amount_needed);
-
-  /* We continue the while loop if another process snatches our found
-   * free block from us after we find it but before we successfully
-   * mark it as in use */
-
-  while (amount_needed--) {
-    /* skip over any blocknrs already gotten last time. */
-    if (*(free_blocknrs) != 0) {
-      RFALSE( is_reusable (s, *free_blocknrs, 1) == 0, 
-	      "vs-4120: bad blocknr on free_blocknrs list");
-      free_blocknrs++;
-      continue;
-    }
-    /* look for zero bits in bitmap */
-    if (find_zero_bit_in_bitmap(s,search_start, &i, &j,for_unformatted) == 0) {
-      if (find_zero_bit_in_bitmap(s,search_start,&i,&j, for_unformatted) == 0) {
-				/* recode without the goto and without
-				   the if.  It will require a
-				   duplicate for.  This is worth the
-				   code clarity.  Your way was
-				   admirable, and just a bit too
-				   clever in saving instructions.:-)
-				   I'd say create a new function, but
-				   that would slow things also, yes?
-				   -Hans */
-free_and_return:
-	for ( ; block_list_start != free_blocknrs; block_list_start++) {
-	  reiserfs_free_block (th, *block_list_start);
-	  *block_list_start = 0;
-	}
-	if (for_prealloc) 
-	    return NO_MORE_UNUSED_CONTIGUOUS_BLOCKS;
-	else
-	    return NO_DISK_SPACE;
+    hint->search_start = hint->beg + keyed_hash(hash_in, 4) % (hint->end - hint->beg);
+}
+
+static void inline get_left_neighbor(reiserfs_blocknr_hint_t *hint)
+{
+    struct path * path;
+    struct buffer_head * bh;
+    struct item_head * ih;
+    int pos_in_item;
+    __u32 * item;
+
+    if (!hint->path)		/* reiserfs code can call this function w/o pointer to path
+				 * structure supplied; then we rely on supplied search_start */
+	return;
+
+    path = hint->path;
+    bh = get_last_bh(path);
+    RFALSE( !bh, "green-4002: Illegal path specified to get_left_neighbor\n");
+    ih = get_ih(path);
+    pos_in_item = path->pos_in_item;
+    item = get_item (path);
+
+    hint->search_start = bh->b_blocknr;
+
+    if (!hint->formatted_node && is_indirect_le_ih (ih)) {
+	/* for indirect item: go to left and look for the first non-hole entry
+	   in the indirect item */
+	if (pos_in_item == I_UNFM_NUM (ih))
+	    pos_in_item--;
+//	    pos_in_item = I_UNFM_NUM (ih) - 1;
+	while (pos_in_item >= 0) {
+	    int t=get_block_num(item,pos_in_item);
+	    if (t) {
+		hint->search_start = t;
+		break;
+	    }
+	    pos_in_item --;
+	}
+    } else {
       }
-    }
-    
-    /* i and j now contain the results of the search. i = bitmap block
-       number containing free block, j = offset in this block.  we
-       compute the blocknr which is our result, store it in
-       free_blocknrs, and increment the pointer so that on the next
-       loop we will insert into the next location in the array.  Also
-       in preparation for the next loop, search_start is changed so
-       that the next search will not rescan the same range but will
-       start where this search finished.  Note that while it is
-       possible that schedule has occurred and blocks have been freed
-       in that range, it is perhaps more important that the blocks
-       returned be near each other than that they be near their other
-       neighbors, and it also simplifies and speeds the code this way.  */
-
-    /* journal: we need to make sure the block we are giving out is not
-    ** a log block, horrible things would happen there.
-    */
-    new_block = (i * (s->s_blocksize << 3)) + j; 
-    if (for_prealloc && (new_block - 1) != search_start) {
-      /* preallocated blocks must be contiguous, bail if we didnt find one.
-      ** this is not a bug.  We want to do the check here, before the
-      ** bitmap block is prepared, and before we set the bit and log the
-      ** bitmap. 
-      **
-      ** If we do the check after this function returns, we have to 
-      ** call reiserfs_free_block for new_block, which would be pure
-      ** overhead.
-      **
-      ** for_prealloc should only be set if the caller can deal with the
-      ** NO_MORE_UNUSED_CONTIGUOUS_BLOCKS return value.  This can be
-      ** returned before the disk is actually full
-      */
-      goto free_and_return ;
-    }
-    search_start = new_block ;
-
-
-    /* make sure the block is not of journal or reserved area */
-    if (is_block_in_log_or_reserved_area(s, search_start)) {
-      reiserfs_warning("vs-4130: reiserfs_new_blocknrs: trying to allocate log block %lu\n",
-		       search_start) ;
-      search_start++ ;
-      amount_needed++ ;
-      continue ;
-    }
-    
-    
-    reiserfs_prepare_for_journal(s, SB_AP_BITMAP(s)[i], 1) ;
 
-    RFALSE( buffer_locked (SB_AP_BITMAP (s)[i]) || 
-	    is_reusable (s, search_start, 0) == 0,
-	    "vs-4140: bitmap block is locked or bad block number found");
-
-    /* if this bit was already set, we've scheduled, and someone else
-    ** has allocated it.  loop around and try again
-    */
-    if (reiserfs_test_and_set_le_bit (j, SB_AP_BITMAP (s)[i]->b_data)) {
-	reiserfs_warning("vs-4150: reiserfs_new_blocknrs, block not free");
-	reiserfs_restore_prepared_buffer(s, SB_AP_BITMAP(s)[i]) ;
-	amount_needed++ ;
-	continue ;
-    }    
-    journal_mark_dirty (th, s, SB_AP_BITMAP (s)[i]); 
-    *free_blocknrs = search_start ;
-    free_blocknrs ++;
-  }
+    /* does result value fit into specified region? */
+    return;
+}
 
-  reiserfs_prepare_for_journal(s, SB_BUFFER_WITH_SB(s), 1) ;
-  /* update free block count in super block */
-  PUT_SB_FREE_BLOCKS( s, SB_FREE_BLOCKS(s) - init_amount_needed );
-  journal_mark_dirty (th, s, SB_BUFFER_WITH_SB (s));
-  s->s_dirt = 1;
+/* should be, if formatted node, then try to put on first part of the device
+   specified as number of percent with mount option device, else try to put
+   on last of device.  This is not to say it is good code to do so,
+   but the effect should be measured.  */
+static void inline set_border_in_hint(struct super_block *s, reiserfs_blocknr_hint_t *hint)
+{
+    b_blocknr_t border = SB_BLOCK_COUNT(s) / REISERFS_SB(s)->s_alloc_options.border;
 
-  return CARRY_ON;
+    if (hint->formatted_node)
+	hint->end = border - 1;
+    else
+	hint->beg = border;
 }
 
-// this is called only by get_empty_nodes
-int reiserfs_new_blocknrs (struct reiserfs_transaction_handle *th, unsigned long * free_blocknrs,
-			    unsigned long search_start, int amount_needed) {
-  return do_reiserfs_new_blocknrs(th, free_blocknrs, search_start, amount_needed, 0/*priority*/, 0/*for_formatted*/, 0/*for_prealloc */) ;
+static void inline displace_large_file(reiserfs_blocknr_hint_t *hint)
+{
+    if ( TEST_OPTION(displace_based_on_dirid, hint->th->t_super))
+	hint->search_start = hint->beg + keyed_hash((char *)(&INODE_PKEY(hint->inode)->k_dir_id), 4) % (hint->end - hint->beg);
+    else
+	hint->search_start = hint->beg + keyed_hash((char *)(&INODE_PKEY(hint->inode)->k_objectid), 4) % (hint->end - hint->beg);
 }
 
+static void inline hash_formatted_node(reiserfs_blocknr_hint_t *hint)
+{
+   char * hash_in;
 
-// called by get_new_buffer and by reiserfs_get_block with amount_needed == 1
-int reiserfs_new_unf_blocknrs(struct reiserfs_transaction_handle *th, unsigned long * free_blocknrs,
-			      unsigned long search_start) {
-  return do_reiserfs_new_blocknrs(th, free_blocknrs, search_start, 
-                                  1/*amount_needed*/,
-				  0/*priority*/, 
-				  1/*for formatted*/,
-				  0/*for prealloc */) ;
-}
-
-#ifdef REISERFS_PREALLOCATE
-
-/* 
-** We pre-allocate 8 blocks.  Pre-allocation is used for files > 16 KB only.
-** This lowers fragmentation on large files by grabbing a contiguous set of
-** blocks at once.  It also limits the number of times the bitmap block is
-** logged by making X number of allocation changes in a single transaction.
-**
-** We are using a border to divide the disk into two parts.  The first part
-** is used for tree blocks, which have a very high turnover rate (they
-** are constantly allocated then freed)
-**
-** The second part of the disk is for the unformatted nodes of larger files.
-** Putting them away from the tree blocks lowers fragmentation, and makes
-** it easier to group files together.  There are a number of different
-** allocation schemes being tried right now, each is documented below.
-**
-** A great deal of the allocator's speed comes because reiserfs_get_block
-** sends us the block number of the last unformatted node in the file.  Once
-** a given block is allocated past the border, we don't collide with the
-** blocks near the search_start again.
-** 
-*/
-int reiserfs_new_unf_blocknrs2 (struct reiserfs_transaction_handle *th, 
-				struct inode       * p_s_inode,
-				unsigned long      * free_blocknrs,
-				unsigned long        search_start)
-{
-  struct reiserfs_inode_info *ei = REISERFS_I(p_s_inode);
-  int ret=0, blks_gotten=0;
-  unsigned long border = 0;
-  unsigned long bstart = 0;
-  unsigned long hash_in, hash_out;
-  unsigned long saved_search_start=search_start;
-  int allocated[PREALLOCATION_SIZE];
-  int blks;
-
-  if (!reiserfs_no_border(th->t_super)) {
-    /* we default to having the border at the 10% mark of the disk.  This
-    ** is an arbitrary decision and it needs tuning.  It also needs a limit
-    ** to prevent it from taking too much space on huge drives.
-    */
-    bstart = (SB_BLOCK_COUNT(th->t_super) / 10); 
-  }
-  if (!reiserfs_no_unhashed_relocation(th->t_super)) {
-    /* this is a very simple first attempt at preventing too much grouping
-    ** around the border value.  Since k_dir_id is never larger than the
-    ** highest allocated oid, it is far from perfect, and files will tend
-    ** to be grouped towards the start of the border
-    */
-    border = le32_to_cpu(INODE_PKEY(p_s_inode)->k_dir_id) % (SB_BLOCK_COUNT(th->t_super) - bstart - 1) ;
-  } else if (!reiserfs_hashed_relocation(th->t_super)) {
-      hash_in = le32_to_cpu((INODE_PKEY(p_s_inode))->k_dir_id);
-				/* I wonder if the CPU cost of the
-                                   hash will obscure the layout
-                                   effect? Of course, whether that
-                                   effect is good or bad we don't
-                                   know.... :-) */
-      
-      hash_out = keyed_hash(((char *) (&hash_in)), 4);
-      border = hash_out % (SB_BLOCK_COUNT(th->t_super) - bstart - 1) ;
-  }
-  border += bstart ;
-  allocated[0] = 0 ; /* important.  Allows a check later on to see if at
-                      * least one block was allocated.  This prevents false
-		      * no disk space returns
-		      */
-
-  if ( (p_s_inode->i_size < 4 * 4096) || 
-       !(S_ISREG(p_s_inode->i_mode)) )
-    {
-      if ( search_start < border 
-	   || (
-				/* allow us to test whether it is a
-                                   good idea to prevent files from
-                                   getting too far away from their
-                                   packing locality by some unexpected
-                                   means.  This might be poor code for
-                                   directories whose files total
-                                   larger than 1/10th of the disk, and
-                                   it might be good code for
-                                   suffering from old insertions when the disk
-                                   was almost full. */
-               /* changed from !reiserfs_test3(th->t_super), which doesn't
-               ** seem like a good idea.  Think about adding blocks to
-               ** a large file.  If you've allocated 10% of the disk
-               ** in contiguous blocks, you start over at the border value
-               ** for every new allocation.  This throws away all the
-               ** information sent in about the last block that was allocated
-               ** in the file.  Not a good general case at all.
-               ** -chris
-               */
-	       reiserfs_test4(th->t_super) && 
-	       (search_start > border + (SB_BLOCK_COUNT(th->t_super) / 10))
-	       )
-	   )
-	search_start=border;
-  
-      ret = do_reiserfs_new_blocknrs(th, free_blocknrs, search_start, 
-				     1/*amount_needed*/, 
-				     0/*use reserved blocks for root */,
-				     1/*for_formatted*/,
-				     0/*for prealloc */) ;  
-      return ret;
-    }
-
-  /* take a block off the prealloc list and return it -Hans */
-  if (ei->i_prealloc_count > 0) {
-    ei->i_prealloc_count--;
-    *free_blocknrs = ei->i_prealloc_block++;
-
-    /* if no more preallocated blocks, remove inode from list */
-    if (! ei->i_prealloc_count) {
-      list_del_init(&ei->i_prealloc_list);
-    }
+   if (!hint->inode)
+	hash_in = (char*)&hint->key.k_dir_id;
+    else if ( TEST_OPTION(displace_based_on_dirid, hint->th->t_super))
+	hash_in = (char *)(&INODE_PKEY(hint->inode)->k_dir_id);
+    else
+	hash_in = (char *)(&INODE_PKEY(hint->inode)->k_objectid);
+
+	hint->search_start = hint->beg + keyed_hash(hash_in, 4) % (hint->end - hint->beg);
+}
+
+static int inline this_blocknr_allocation_would_make_it_a_large_file(reiserfs_blocknr_hint_t *hint)
+{
+    return hint->block == REISERFS_SB(hint->th->t_super)->s_alloc_options.large_file_size;
+}
+
+#ifdef DISPLACE_NEW_PACKING_LOCALITIES
+static void inline displace_new_packing_locality (reiserfs_blocknr_hint_t *hint)
+{
+    struct key * key = &hint->key;
+
+    hint->th->displace_new_blocks = 0;
+    hint->search_start = hint->beg + keyed_hash((char*)(&key->k_objectid),4) % (hint->end - hint->beg);
+}
+  #endif
+
+static int inline old_hashed_relocation (reiserfs_blocknr_hint_t * hint)
+{
+    unsigned long border;
+    unsigned long hash_in;
     
-    return ret;
-  }
+    if (hint->formatted_node || hint->inode == NULL) {
+	return 0;
+      }
 
-				/* else get a new preallocation for the file */
-  reiserfs_discard_prealloc (th, p_s_inode);
-  /* this uses the last preallocated block as the search_start.  discard
-  ** prealloc does not zero out this number.
-  */
-  if (search_start <= ei->i_prealloc_block) {
-    search_start = ei->i_prealloc_block;
+    hash_in = le32_to_cpu((INODE_PKEY(hint->inode))->k_dir_id);
+    border = hint->beg + (unsigned long) keyed_hash(((char *) (&hash_in)), 4) % (hint->end - hint->beg - 1);
+    if (border > hint->search_start)
+	hint->search_start = border;
+
+    return 1;
   }
   
-  /* doing the compare again forces search_start to be >= the border,
-  ** even if the file already had prealloction done.  This seems extra,
-  ** and should probably be removed
-  */
-  if ( search_start < border ) search_start=border; 
-
-  /* If the disk free space is already below 10% we should 
-  ** start looking for the free blocks from the beginning 
-  ** of the partition, before the border line.
-  */
-  if ( SB_FREE_BLOCKS(th->t_super) <= (SB_BLOCK_COUNT(th->t_super) / 10) ) {
-    search_start=saved_search_start;
-  }
-
-  *free_blocknrs = 0;
-  blks = PREALLOCATION_SIZE-1;
-  for (blks_gotten=0; blks_gotten<PREALLOCATION_SIZE; blks_gotten++) {
-
-    ret = do_reiserfs_new_blocknrs(th, free_blocknrs, search_start, 
-				   1/*amount_needed*/, 
-				   0/*for root reserved*/,
-				   1/*for_formatted*/,
-				   (blks_gotten > 0)/*must_be_contiguous*/) ;
-    /* if we didn't find a block this time, adjust blks to reflect
-    ** the actual number of blocks allocated
-    */ 
-    if (ret != CARRY_ON) {
-      blks = blks_gotten > 0 ? (blks_gotten - 1) : 0 ;
-      break ;
+static int inline old_way (reiserfs_blocknr_hint_t * hint)
+{
+    unsigned long border;
+    
+    if (hint->formatted_node || hint->inode == NULL) {
+	return 0;
     }
-    allocated[blks_gotten]= *free_blocknrs;
-#ifdef CONFIG_REISERFS_CHECK
-    if ( (blks_gotten>0) && (allocated[blks_gotten] - allocated[blks_gotten-1]) != 1 ) {
-      /* this should be caught by new_blocknrs now, checking code */
-      reiserfs_warning("yura-1, reiserfs_new_unf_blocknrs2: pre-allocated not contiguous set of blocks!\n") ;
-      reiserfs_free_block(th, allocated[blks_gotten]);
-      blks = blks_gotten-1; 
-      break;
+  
+      border = hint->beg + le32_to_cpu(INODE_PKEY(hint->inode)->k_dir_id) % (hint->end  - hint->beg);
+    if (border > hint->search_start)
+	hint->search_start = border;
+
+    return 1;
+}
+
+static void inline hundredth_slices (reiserfs_blocknr_hint_t * hint)
+{
+    struct key * key = &hint->key;
+    unsigned long slice_start;
+
+    slice_start = (keyed_hash((char*)(&key->k_dir_id),4) % 100) * (hint->end / 100);
+    if ( slice_start > hint->search_start || slice_start + (hint->end / 100) <= hint->search_start) {
+	hint->search_start = slice_start;
     }
+}
+  
+static void inline determine_search_start(reiserfs_blocknr_hint_t *hint,
+					  int amount_needed)
+{
+    struct super_block *s = hint->th->t_super;
+    hint->beg = 0;
+    hint->end = SB_BLOCK_COUNT(s) - 1;
+
+    /* This is former border algorithm. Now with tunable border offset */
+    if (concentrating_formatted_nodes(s))
+	set_border_in_hint(s, hint);
+
+#ifdef DISPLACE_NEW_PACKING_LOCALITIES
+    /* whenever we create a new directory, we displace it.  At first we will
+       hash for location, later we might look for a moderately empty place for
+       it */
+    if (displacing_new_packing_localities(s)
+	&& hint->th->displace_new_blocks) {
+	displace_new_packing_locality(hint);
+
+	/* we do not continue determine_search_start,
+	 * if new packing locality is being displaced */
+	return;
+    }				      
 #endif
-    if (blks_gotten==0) {
-      ei->i_prealloc_block = *free_blocknrs;
+  
+    /* all persons should feel encouraged to add more special cases here and
+     * test them */
+
+    if (displacing_large_files(s) && !hint->formatted_node
+	&& this_blocknr_allocation_would_make_it_a_large_file(hint)) {
+	displace_large_file(hint);
+	return;
+    }
+
+    /* attempt to copy a feature from old block allocator code */
+    if (TEST_OPTION(old_hashed_relocation, s) && !hint->formatted_node) {
+	old_hashed_relocation(hint);
+    }
+
+    /* if none of our special cases is relevant, use the left neighbor in the
+       tree order of the new node we are allocating for */
+    if (hint->formatted_node && TEST_OPTION(hashed_formatted_nodes,s)) {
+	hash_formatted_node(hint);
+	return;
+    } 
+
+    get_left_neighbor(hint);
+
+    /* Mimic old block allocator behaviour, that is if VFS allowed for preallocation,
+       new blocks are displaced based on directory ID. Also, if suggested search_start
+       is less than last preallocated block, we start searching from it, assuming that
+       HDD dataflow is faster in forward direction */
+    if ( TEST_OPTION(old_way, s)) {
+	if (!hint->formatted_node) {
+	    if ( !reiserfs_hashed_relocation(s))
+		old_way(hint);
+	    else if (!reiserfs_no_unhashed_relocation(s))
+		old_hashed_relocation(hint);
+
+	    if ( hint->inode && hint->search_start < REISERFS_I(hint->inode)->i_prealloc_block)
+		hint->search_start = REISERFS_I(hint->inode)->i_prealloc_block;
+	}
+	return;
     }
-    search_start = *free_blocknrs; 
-    *free_blocknrs = 0;
-  }
-  ei->i_prealloc_count = blks;
-  *free_blocknrs = ei->i_prealloc_block;
-  ei->i_prealloc_block++;
-
-  /* if inode has preallocated blocks, link him to list */
-  if (ei->i_prealloc_count) {
-    list_add(&ei->i_prealloc_list,
-	     &SB_JOURNAL(th->t_super)->j_prealloc_list);
-  } 
-  /* we did actually manage to get 1 block */
-  if (ret != CARRY_ON && allocated[0] > 0) {
-    return CARRY_ON ;
-  }
-  /* NO_MORE_UNUSED_CONTIGUOUS_BLOCKS should only mean something to
-  ** the preallocation code.  The rest of the filesystem asks for a block
-  ** and should either get it, or know the disk is full.  The code
-  ** above should never allow ret == NO_MORE_UNUSED_CONTIGUOUS_BLOCK,
-  ** as it doesn't send for_prealloc = 1 to do_reiserfs_new_blocknrs
-  ** unless it has already successfully allocated at least one block.
-  ** Just in case, we translate into a return value the rest of the
-  ** filesystem can understand.
-  **
-  ** It is an error to change this without making the
-  ** rest of the filesystem understand NO_MORE_UNUSED_CONTIGUOUS_BLOCKS
-  ** If you consider it a bug to return NO_DISK_SPACE here, fix the rest
-  ** of the fs first.
-  */
-  if (ret == NO_MORE_UNUSED_CONTIGUOUS_BLOCKS) {
-#ifdef CONFIG_REISERFS_CHECK
-    reiserfs_warning("reiser-2015: this shouldn't happen, may cause false out of disk space error");
-#endif
-     return NO_DISK_SPACE; 
-  }
-  return ret;
-}
 
+    /* This is an approach proposed by Hans */
+    if ( TEST_OPTION(hundredth_slices, s) && ! (displacing_large_files(s) && !hint->formatted_node)) {
+	hundredth_slices(hint);
+	return;
+    }
 
-static void __discard_prealloc (struct reiserfs_transaction_handle * th,
-				struct reiserfs_inode_info *ei)
+    if (TEST_OPTION(old_hashed_relocation, s))
+	old_hashed_relocation(hint);
+    if (TEST_OPTION(new_hashed_relocation, s))
+	new_hashed_relocation(hint);
+    return;
+}
+
+static int determine_prealloc_size(reiserfs_blocknr_hint_t * hint)
 {
-  unsigned long save = ei->i_prealloc_block ;
-  while (ei->i_prealloc_count > 0) {
-    reiserfs_free_prealloc_block(th,ei->i_prealloc_block);
-    ei->i_prealloc_block++;
-    ei->i_prealloc_count --;
-  }
-  ei->i_prealloc_block = save;
-  list_del_init(&(ei->i_prealloc_list));
+    /* make minimum size a mount option and benchmark both ways */
+    /* we preallocate blocks only for regular files, specific size */
+    /* benchmark preallocating always and see what happens */
+
+    hint->prealloc_size = 0;
+
+    if (!hint->formatted_node && hint->preallocate) {
+	if (S_ISREG(hint->inode->i_mode)
+	    && hint->inode->i_size >= REISERFS_SB(hint->th->t_super)->s_alloc_options.preallocmin * hint->inode->i_sb->s_blocksize)
+	    hint->prealloc_size = REISERFS_SB(hint->th->t_super)->s_alloc_options.preallocsize - 1;
+    }
+    return CARRY_ON;
+}
+
+/* XXX I know it could be merged with upper-level function;
+   but may be result function would be too complex. */
+static inline int allocate_without_wrapping_disk (reiserfs_blocknr_hint_t * hint,
+					 b_blocknr_t * new_blocknrs,
+					 b_blocknr_t start, b_blocknr_t finish,
+					 int amount_needed, int prealloc_size)
+{
+    int rest = amount_needed;
+    int nr_allocated;
+  
+    while (rest > 0) {
+	nr_allocated = scan_bitmap (hint->th, &start, finish, 1,
+				    rest + prealloc_size, !hint->formatted_node,
+				    hint->block);
+
+	if (nr_allocated == 0)	/* no new blocks allocated, return */
+	    break;
+	
+	/* fill free_blocknrs array first */
+	while (rest > 0 && nr_allocated > 0) {
+	    * new_blocknrs ++ = start ++;
+	    rest --; nr_allocated --;
+	}
+
+	/* do we have something to fill prealloc. array also ? */
+	if (nr_allocated > 0) {
+	    /* it means prealloc_size was greater that 0 and we do preallocation */
+	    list_add(&REISERFS_I(hint->inode)->i_prealloc_list,
+		     &SB_JOURNAL(hint->th->t_super)->j_prealloc_list);
+	    REISERFS_I(hint->inode)->i_prealloc_block = start;
+	    REISERFS_I(hint->inode)->i_prealloc_count = nr_allocated;
+	    break;
+	}
+    }
+
+    return (amount_needed - rest);
 }
 
+static inline int blocknrs_and_prealloc_arrays_from_search_start
+    (reiserfs_blocknr_hint_t *hint, b_blocknr_t *new_blocknrs, int amount_needed)
+{
+    struct super_block *s = hint->th->t_super;
+    b_blocknr_t start = hint->search_start;
+    b_blocknr_t finish = SB_BLOCK_COUNT(s) - 1;
+    int second_pass = 0;
+    int nr_allocated = 0;
+
+    determine_prealloc_size(hint);
+    while((nr_allocated
+	  += allocate_without_wrapping_disk(hint, new_blocknrs + nr_allocated, start, finish,
+					  amount_needed - nr_allocated, hint->prealloc_size))
+	  < amount_needed) {
+
+	/* not all blocks were successfully allocated yet*/
+	if (second_pass) {	/* it was a second pass; we must free all blocks */
+	    while (nr_allocated --)
+		reiserfs_free_block(hint->th, new_blocknrs[nr_allocated]);
 
-void reiserfs_discard_prealloc (struct reiserfs_transaction_handle *th, 
-				struct inode * inode)
+	    return NO_DISK_SPACE;
+	} else {		/* refine search parameters for next pass */
+	    second_pass = 1;
+	    finish = start;
+	    start = 0;
+	    continue;
+	}
+      }
+    return CARRY_ON;
+}
+
+/* grab new blocknrs from preallocated list */
+/* return amount still needed after using them */
+static int use_preallocated_list_if_available (reiserfs_blocknr_hint_t *hint,
+					       b_blocknr_t *new_blocknrs, int amount_needed)
 {
-  struct reiserfs_inode_info *ei = REISERFS_I(inode);
-#ifdef CONFIG_REISERFS_CHECK
-  if (ei->i_prealloc_count < 0)
-     reiserfs_warning("zam-4001:%s inode has negative prealloc blocks count.\n", __FUNCTION__);
-#endif  
-    if (ei->i_prealloc_count > 0) {
-    __discard_prealloc(th, ei);
-  }
+    struct inode * inode = hint->inode;
+
+    if (REISERFS_I(inode)->i_prealloc_count > 0) {
+	while (amount_needed) {
+
+	    *new_blocknrs ++ = REISERFS_I(inode)->i_prealloc_block ++;
+	    REISERFS_I(inode)->i_prealloc_count --;
+
+	    amount_needed --;
+
+	    if (REISERFS_I(inode)->i_prealloc_count <= 0) {
+		list_del(&REISERFS_I(inode)->i_prealloc_list);  
+		break;
+	    }
+	}
       }
+    /* return amount still needed after using preallocated blocks */
+    return amount_needed;
+}
 
-void reiserfs_discard_all_prealloc (struct reiserfs_transaction_handle *th)
+int reiserfs_allocate_blocknrs(reiserfs_blocknr_hint_t *hint,
+			       b_blocknr_t * new_blocknrs, int amount_needed,
+			       int reserved_by_us /* Amount of blocks we have
+						      already reserved */)
 {
-  struct list_head * plist = &SB_JOURNAL(th->t_super)->j_prealloc_list;
-  
-  while (!list_empty(plist)) {
-	struct reiserfs_inode_info *ei;
-	ei = list_entry(plist->next, struct reiserfs_inode_info, i_prealloc_list);
-#ifdef CONFIG_REISERFS_CHECK
-	if (!ei->i_prealloc_count) {
-		reiserfs_warning("zam-4001:%s: inode is in prealloc list but has no preallocated blocks.\n", __FUNCTION__);
+    int initial_amount_needed = amount_needed;
+    int ret;
+
+    /* Check if there is enough space, taking into account reserved space */
+    if ( SB_FREE_BLOCKS(hint->th->t_super) - REISERFS_SB(hint->th->t_super)->reserved_blocks <
+	 amount_needed - reserved_by_us)
+        return NO_DISK_SPACE;
+    /* should this be if !hint->inode &&  hint->preallocate? */
+    /* do you mean hint->formatted_node can be removed ? - Zam */
+    /* hint->formatted_node cannot be removed because we try to access
+       inode information here, and there is often no inode assotiated with
+       metadata allocations - green */
+
+    if (!hint->formatted_node && hint->preallocate) {
+	amount_needed = use_preallocated_list_if_available
+	    (hint, new_blocknrs, amount_needed);
+	if (amount_needed == 0)	/* all blocknrs we need we got from
+                                   prealloc. list */
+	    return CARRY_ON;
+	new_blocknrs += (initial_amount_needed - amount_needed);
+    }
+
+    /* find search start and save it in hint structure */
+    determine_search_start(hint, amount_needed);
+
+    /* allocation itself; fill new_blocknrs and preallocation arrays */
+    ret = blocknrs_and_prealloc_arrays_from_search_start
+	(hint, new_blocknrs, amount_needed);
+
+    /* we used prealloc. list to fill (partially) new_blocknrs array. If final allocation fails we
+     * need to return blocks back to prealloc. list or just free them. -- Zam (I chose second
+     * variant) */
+
+    if (ret != CARRY_ON) {
+	while (amount_needed ++ < initial_amount_needed) {
+	    reiserfs_free_block(hint->th, *(--new_blocknrs));
 	}
-#endif
-	__discard_prealloc(th, ei);
     }
+    return ret;
+}
+
+/* These 2 functions are here to provide blocks reservation to the rest of kernel */
+/* Reserve @blocks amount of blocks in fs pointed by @sb. Caller must make sure
+   there are actually this much blocks on the FS available */
+void reiserfs_claim_blocks_to_be_allocated( 
+				      struct super_block *sb, /* super block of
+							        filesystem where
+								blocks should be
+								reserved */
+				      int blocks /* How much to reserve */
+					  )
+{
+
+    /* Fast case, if reservation is zero - exit immediately. */
+    if ( !blocks )
+	return;
+
+    REISERFS_SB(sb)->reserved_blocks += blocks;
+}
+
+/* Unreserve @blocks amount of blocks in fs pointed by @sb */
+void reiserfs_release_claimed_blocks( 
+				struct super_block *sb, /* super block of
+							  filesystem where
+							  blocks should be
+							  reserved */
+				int blocks /* How much to unreserve */
+					  )
+{
+
+    /* Fast case, if unreservation is zero - exit immediately. */
+    if ( !blocks )
+	return;
+
+    REISERFS_SB(sb)->reserved_blocks -= blocks;
+    RFALSE( REISERFS_SB(sb)->reserved_blocks < 0, "amount of blocks reserved became zero?");
 }
-#endif
diff -Nru a/fs/reiserfs/fix_node.c b/fs/reiserfs/fix_node.c
--- a/fs/reiserfs/fix_node.c	Mon Sep  9 10:36:01 2002
+++ b/fs/reiserfs/fix_node.c	Mon Sep  9 10:36:01 2002
@@ -795,8 +795,8 @@
   else /* If we have enough already then there is nothing to do. */
     return CARRY_ON;
 
-  if ( reiserfs_new_blocknrs (p_s_tb->transaction_handle, a_n_blocknrs,
-			      PATH_PLAST_BUFFER(p_s_tb->tb_path)->b_blocknr, n_amount_needed) == NO_DISK_SPACE )
+  if ( reiserfs_new_form_blocknrs (p_s_tb, a_n_blocknrs,
+                                   n_amount_needed) == NO_DISK_SPACE )
     return NO_DISK_SPACE;
 
   /* for each blocknumber we just got, get a buffer and stick it on FEB */
diff -Nru a/fs/reiserfs/hashes.c b/fs/reiserfs/hashes.c
--- a/fs/reiserfs/hashes.c	Mon Sep  9 10:36:01 2002
+++ b/fs/reiserfs/hashes.c	Mon Sep  9 10:36:01 2002
@@ -19,6 +19,7 @@
 //
 
 #include <asm/types.h>
+#include <asm/page.h>
 
 
 
@@ -57,7 +58,6 @@
 	u32 pad;
 	int i;
  
-
 	//	assert(len >= 0 && len < 256);
 
 	pad = (u32)len | ((u32)len << 8);
@@ -92,7 +92,7 @@
 	{
 	    	//assert(len < 16);
 		if (len >= 16)
-		    *(int *)0 = 0;
+		    BUG();
 
 		a = (u32)msg[ 0]      |
 		    (u32)msg[ 1] << 8 |
@@ -118,7 +118,7 @@
 	{
 	    	//assert(len < 12);
 		if (len >= 12)
-		    *(int *)0 = 0;
+		    BUG();
 		a = (u32)msg[ 0]      |
 		    (u32)msg[ 1] << 8 |
 		    (u32)msg[ 2] << 16|
@@ -139,7 +139,7 @@
 	{
 	    	//assert(len < 8);
 		if (len >= 8)
-		    *(int *)0 = 0;
+		    BUG();
 		a = (u32)msg[ 0]      |
 		    (u32)msg[ 1] << 8 |
 		    (u32)msg[ 2] << 16|
@@ -156,7 +156,7 @@
 	{
 	    	//assert(len < 4);
 		if (len >= 4)
-		    *(int *)0 = 0;
+		    BUG();
 		a = b = c = d = pad;
 		for(i = 0; i < len; i++)
 		{
diff -Nru a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c
--- a/fs/reiserfs/inode.c	Mon Sep  9 10:36:01 2002
+++ b/fs/reiserfs/inode.c	Mon Sep  9 10:36:01 2002
@@ -7,6 +7,7 @@
 #include <linux/reiserfs_fs.h>
 #include <linux/smp_lock.h>
 #include <linux/pagemap.h>
+#include <linux/highmem.h>
 #include <asm/uaccess.h>
 #include <asm/unaligned.h>
 #include <linux/buffer_head.h>
@@ -156,33 +157,6 @@
     }
 }
 
-
-
-
-/* we need to allocate a block for new unformatted node.  Try to figure out
-   what point in bitmap reiserfs_new_blocknrs should start from. */
-static b_blocknr_t find_tag (struct buffer_head * bh, struct item_head * ih,
-			     __u32 * item, int pos_in_item)
-{
-  __u32 block ;
-  if (!is_indirect_le_ih (ih))
-	 /* something more complicated could be here */
-	 return bh->b_blocknr;
-
-  /* for indirect item: go to left and look for the first non-hole entry in
-	  the indirect item */
-  if (pos_in_item == I_UNFM_NUM (ih))
-	 pos_in_item --;
-  while (pos_in_item >= 0) {
-	 block = get_block_num(item, pos_in_item) ;
-	 if (block)
-		return block ;
-	 pos_in_item --;
-  }
-  return bh->b_blocknr;
-}
-
-
 /* reiserfs_get_block does not need to allocate a block only if it has been
    done already or non-hole position has been found in the indirect item */
 static inline int allocation_needed (int retval, b_blocknr_t allocated, 
@@ -341,10 +315,10 @@
     ** kmap schedules
     */
     if (!p) {
-    p = (char *)kmap(bh_result->b_page) ;
-    if (fs_changed (fs_gen, inode->i_sb) && item_moved (&tmp_ih, &path)) {
-        goto research;
-    }
+	p = (char *)kmap(bh_result->b_page) ;
+	if (fs_changed (fs_gen, inode->i_sb) && item_moved (&tmp_ih, &path)) {
+	    goto research;
+	}
     }
     p += offset ;
     memset (p, 0, inode->i_sb->s_blocksize);
@@ -505,24 +479,24 @@
 }
 
 static inline int _allocate_block(struct reiserfs_transaction_handle *th,
+			   long block,
                            struct inode *inode, 
 			   b_blocknr_t *allocated_block_nr, 
-			   unsigned long tag,
+			   struct path * path,
 			   int flags) {
   
 #ifdef REISERFS_PREALLOCATE
     if (!(flags & GET_BLOCK_NO_ISEM)) {
-        return reiserfs_new_unf_blocknrs2(th, inode, allocated_block_nr, tag);
+	return reiserfs_new_unf_blocknrs2(th, inode, allocated_block_nr, path, block);
     }
 #endif
-    return reiserfs_new_unf_blocknrs (th, allocated_block_nr, tag);
+    return reiserfs_new_unf_blocknrs (th, allocated_block_nr, path, block);
 }
 
 int reiserfs_get_block (struct inode * inode, sector_t block,
 			struct buffer_head * bh_result, int create)
 {
     int repeat, retval;
-    unsigned long tag;
     b_blocknr_t allocated_block_nr = 0;// b_blocknr_t is unsigned long
     INITIALIZE_PATH(path);
     int pos_in_item;
@@ -601,7 +575,6 @@
 
     if (allocation_needed (retval, allocated_block_nr, ih, item, pos_in_item)) {
 	/* we have to allocate block for the unformatted node */
-	tag = find_tag (bh, ih, item, pos_in_item);
 	if (!transaction_started) {
 	    pathrelse(&path) ;
 	    journal_begin(&th, inode->i_sb, jbegin_count) ;
@@ -610,7 +583,7 @@
 	    goto research ;
 	}
 
-	repeat = _allocate_block(&th, inode, &allocated_block_nr, tag, create);
+	repeat = _allocate_block(&th, block, inode, &allocated_block_nr, &path, create);
 
 	if (repeat == NO_DISK_SPACE) {
 	    /* restart the transaction to give the journal a chance to free
@@ -618,7 +591,7 @@
 	    ** research if we succeed on the second try
 	    */
 	    restart_transaction(&th, inode, &path) ; 
-	    repeat = _allocate_block(&th, inode,&allocated_block_nr,tag,create);
+	    repeat = _allocate_block(&th, block, inode, &allocated_block_nr, NULL, create);
 
 	    if (repeat != NO_DISK_SPACE) {
 		goto research ;
@@ -769,8 +742,8 @@
 	    add_to_flushlist(inode, unbh) ;
 
 	    /* mark it dirty now to prevent commit_write from adding
-	    ** this buffer to the inode's dirty buffer list
-	    */
+	     ** this buffer to the inode's dirty buffer list
+	     */
 		/*
 		 * AKPM: changed __mark_buffer_dirty to mark_buffer_dirty().
 		 * It's still atomic, but it sets the page dirty too,
@@ -778,7 +751,7 @@
 		 * VM (which was also the case with __mark_buffer_dirty())
 		 */
 	    mark_buffer_dirty(unbh) ;
-		  
+
 	    //inode->i_blocks += inode->i_sb->s_blocksize / 512;
 	    //mark_tail_converted (inode);
 	} else {
@@ -919,7 +892,7 @@
 	inode->i_blocks = sd_v1_blocks(sd);
 	inode->i_generation = le32_to_cpu (INODE_PKEY (inode)->k_dir_id);
 	blocks = (inode->i_size + 511) >> 9;
-	blocks = _ROUND_UP (blocks, inode->i_blksize >> 9);
+	blocks = _ROUND_UP (blocks, inode->i_sb->s_blocksize >> 9);
 	if (inode->i_blocks > blocks) {
 	    // there was a bug in <=3.5.23 when i_blocks could take negative
 	    // values. Starting from 3.5.17 this value could even be stored in
@@ -1591,6 +1564,10 @@
 	set_inode_sd_version (inode, STAT_DATA_V2);
     
     /* insert the stat data into the tree */
+#ifdef DISPLACE_NEW_PACKING_LOCALITIES
+    if (REISERFS_I(dir)->new_packing_locality)
+	th->displace_new_blocks = 1;
+#endif
     retval = reiserfs_insert_item (th, &path_to_key, &key, &ih, (char *)(&sd));
     if (retval) {
 	err = retval;
@@ -1598,6 +1575,10 @@
 	goto out_bad_inode;
     }
 
+#ifdef DISPLACE_NEW_PACKING_LOCALITIES
+    if (!th->displace_new_blocks)
+	REISERFS_I(dir)->new_packing_locality = 0;
+#endif
     if (S_ISDIR(mode)) {
 	/* insert item with "." and ".." */
 	retval = reiserfs_new_directory (th, &ih, &path_to_key, dir);
@@ -1692,8 +1673,6 @@
     if (error)
 	goto unlock ;
 
-    kunmap(page) ; /* mapped by block_prepare_write */
-
     head = page_buffers(page) ;      
     bh = head;
     do {
@@ -1773,25 +1752,28 @@
     reiserfs_update_inode_transaction(p_s_inode) ;
     windex = push_journal_writer("reiserfs_vfs_truncate_file") ;
     if (update_timestamps)
-           /* we are doing real truncate: if the system crashes before the last
-              transaction of truncating gets committed - on reboot the file
-              either appears truncated properly or not truncated at all */
-           add_save_link (&th, p_s_inode, 1);
+	    /* we are doing real truncate: if the system crashes before the last
+	       transaction of truncating gets committed - on reboot the file
+	       either appears truncated properly or not truncated at all */
+	add_save_link (&th, p_s_inode, 1);
     reiserfs_do_truncate (&th, p_s_inode, page, update_timestamps) ;
     pop_journal_writer(windex) ;
     journal_end(&th, p_s_inode->i_sb,  JOURNAL_PER_BALANCE_CNT * 2 + 1 ) ;
 
     if (update_timestamps)
-       remove_save_link (p_s_inode, 1/* truncate */);
+	remove_save_link (p_s_inode, 1/* truncate */);
 
     if (page) {
         length = offset & (blocksize - 1) ;
 	/* if we are not on a block boundary */
 	if (length) {
+	    char *kaddr;
+
 	    length = blocksize - length ;
-	    memset((char *)kmap(page) + offset, 0, length) ;   
+	    kaddr = kmap_atomic(page, KM_USER0) ;
+	    memset(kaddr + offset, 0, length) ;   
 	    flush_dcache_page(page) ;
-	    kunmap(page) ;
+	    kunmap_atomic(kaddr, KM_USER0) ;
 	    if (buffer_mapped(bh) && bh->b_blocknr != 0) {
 	        mark_buffer_dirty(bh) ;
 	    }
@@ -1941,23 +1923,25 @@
     struct buffer_head *arr[PAGE_CACHE_SIZE/512] ;
     int nr = 0 ;
 
-    if (!page_has_buffers(page)) {
+    if (!page_has_buffers(page))
         block_prepare_write(page, 0, 0, NULL) ;
-	kunmap(page) ;
-    }
+
     /* last page in the file, zero out any contents past the
     ** last byte in the file
     */
     if (page->index >= end_index) {
+	char *kaddr;
+
         last_offset = inode->i_size & (PAGE_CACHE_SIZE - 1) ;
 	/* no file contents in this page */
 	if (page->index >= end_index + 1 || !last_offset) {
 	    error =  -EIO ;
 	    goto fail ;
 	}
-	memset((char *)kmap(page)+last_offset, 0, PAGE_CACHE_SIZE-last_offset) ;
+	kaddr = kmap_atomic(page, KM_USER0);
+	memset(kaddr + last_offset, 0, PAGE_CACHE_SIZE-last_offset) ;
 	flush_dcache_page(page) ;
-	kunmap(page) ;
+	kunmap_atomic(kaddr, KM_USER0) ;
     }
     head = page_buffers(page) ;
     bh = head ;
diff -Nru a/fs/reiserfs/journal.c b/fs/reiserfs/journal.c
--- a/fs/reiserfs/journal.c	Mon Sep  9 10:36:12 2002
+++ b/fs/reiserfs/journal.c	Mon Sep  9 10:36:12 2002
@@ -510,14 +510,12 @@
 **
 */
 int reiserfs_in_journal(struct super_block *p_s_sb,
-                        unsigned long bl, int search_all, 
+                        int bmap_nr, int bit_nr, int search_all, 
 			unsigned long *next_zero_bit) {
   struct reiserfs_journal_cnode *cn ;
   struct reiserfs_list_bitmap *jb ;
   int i ;
-  int bmap_nr = bl / (p_s_sb->s_blocksize << 3) ;
-  int bit_nr = bl % (p_s_sb->s_blocksize << 3) ;
-  int tmp_bit ;
+  unsigned long bl;
 
   *next_zero_bit = 0 ; /* always start this at zero. */
 
@@ -537,15 +535,15 @@
       jb = SB_JOURNAL(p_s_sb)->j_list_bitmap + i ;
       if (jb->journal_list && jb->bitmaps[bmap_nr] &&
           test_bit(bit_nr, (unsigned long *)jb->bitmaps[bmap_nr]->data)) {
-	tmp_bit = find_next_zero_bit((unsigned long *)
+	*next_zero_bit = find_next_zero_bit((unsigned long *)
 	                             (jb->bitmaps[bmap_nr]->data),
 	                             p_s_sb->s_blocksize << 3, bit_nr+1) ; 
-	*next_zero_bit = bmap_nr * (p_s_sb->s_blocksize << 3) + tmp_bit ;
 	return 1 ;
       }
     }
   }
 
+  bl = bmap_nr * (p_s_sb->s_blocksize << 3) + bit_nr;
   /* is it in any old transactions? */
   if (search_all && (cn = get_journal_hash_dev(p_s_sb, SB_JOURNAL(p_s_sb)->j_list_hash_table, bl))) {
     return 1; 
@@ -1820,7 +1818,8 @@
   jl = SB_JOURNAL_LIST(ct->p_s_sb) + ct->jindex ;
 
   flush_commit_list(ct->p_s_sb, SB_JOURNAL_LIST(ct->p_s_sb) + ct->jindex, 1) ; 
-  if (jl->j_len > 0 && atomic_read(&(jl->j_nonzerolen)) > 0 && 
+
+  if (jl->j_len > 0 && atomic_read(&(jl->j_nonzerolen)) > 0 &&
       atomic_read(&(jl->j_commit_left)) == 0) {
     kupdate_one_transaction(ct->p_s_sb, jl) ;
   }
diff -Nru a/fs/reiserfs/namei.c b/fs/reiserfs/namei.c
--- a/fs/reiserfs/namei.c	Mon Sep  9 10:36:11 2002
+++ b/fs/reiserfs/namei.c	Mon Sep  9 10:36:11 2002
@@ -661,6 +661,10 @@
     struct reiserfs_transaction_handle th ;
     int jbegin_count = JOURNAL_PER_BALANCE_CNT * 3; 
 
+#ifdef DISPLACE_NEW_PACKING_LOCALITIES
+    /* set flag that new packing locality created and new blocks for the content     * of that directory are not displaced yet */
+    REISERFS_I(dir)->new_packing_locality = 1;
+#endif
     mode = S_IFDIR | mode;
     if (!(inode = new_inode(dir->i_sb))) {
 	return -ENOMEM ;
diff -Nru a/fs/reiserfs/procfs.c b/fs/reiserfs/procfs.c
--- a/fs/reiserfs/procfs.c	Mon Sep  9 10:36:01 2002
+++ b/fs/reiserfs/procfs.c	Mon Sep  9 10:36:01 2002
@@ -111,7 +111,7 @@
 #define SF( x ) ( r -> x )
 #define SFP( x ) SF( s_proc_info_data.x )
 #define SFPL( x ) SFP( x[ level ] )
-#define SFPF( x ) SFP( find_forward.x )
+#define SFPF( x ) SFP( scan_bitmap.x )
 #define SFPJ( x ) SFP( journal.x )
 
 #define D2C( x ) le16_to_cpu( x )
@@ -165,6 +165,12 @@
 			"search_by_key_fs_changed: \t%lu\n"
 			"search_by_key_restarted: \t%lu\n"
 			
+			"insert_item_restarted: \t%lu\n"
+			"paste_into_item_restarted: \t%lu\n"
+			"cut_from_item_restarted: \t%lu\n"
+			"delete_solid_item_restarted: \t%lu\n"
+			"delete_item_restarted: \t%lu\n"
+
 			"leaked_oid: \t%lu\n"
 			"leaves_removable: \t%lu\n",
 
@@ -178,7 +184,7 @@
 			reiserfs_no_unhashed_relocation( sb ) ? "NO_UNHASHED_RELOCATION " : "",
 			reiserfs_hashed_relocation( sb ) ? "UNHASHED_RELOCATION " : "",
 			reiserfs_test4( sb ) ? "TEST4 " : "",
-			dont_have_tails( sb ) ? "NO_TAILS " : "TAILS ",
+			have_large_tails( sb ) ? "TAILS " : have_small_tails(sb)?"SMALL_TAILS ":"NO_TAILS ",
 			replay_only( sb ) ? "REPLAY_ONLY " : "",
 			reiserfs_dont_log( sb ) ? "DONT_LOG " : "LOG ",
 			convert_reiserfs( sb ) ? "CONV " : "",
@@ -201,6 +207,13 @@
 			SFP( search_by_key ),
 			SFP( search_by_key_fs_changed ),
 			SFP( search_by_key_restarted ),
+
+			SFP( insert_item_restarted ),
+			SFP( paste_into_item_restarted ),
+			SFP( cut_from_item_restarted ),
+			SFP( delete_solid_item_restarted ),
+			SFP( delete_item_restarted ),
+
 			SFP( leaked_oid ),
 			SFP( leaves_removable ) );
 
@@ -301,27 +314,30 @@
 	r = REISERFS_SB(sb);
 
 	len += sprintf( &buffer[ len ], "free_block: %lu\n"
-			"find_forward:"
-			"         wait"
-			"         bmap"
-			"        retry"
-			" journal_hint"
-			"  journal_out"
+			"  scan_bitmap:"
+			"          wait"
+			"          bmap"
+			"         retry"
+			"        stolen"
+			"  journal_hint"
+			"journal_nohint"
 			"\n"
-			" %12lu"
-			" %12lu"
-			" %12lu"
-			" %12lu"
-			" %12lu"
-			" %12lu"
+			" %14lu"
+			" %14lu"
+			" %14lu"
+			" %14lu"
+			" %14lu"
+			" %14lu"
+			" %14lu"
 			"\n",
 			SFP( free_block ),
 			SFPF( call ), 
 			SFPF( wait ), 
 			SFPF( bmap ),
 			SFPF( retry ),
+			SFPF( stolen ),
 			SFPF( in_journal_hint ),
-			SFPF( in_journal_out ) );
+			SFPF( in_journal_nohint ) );
 
 	procinfo_epilogue( sb );
 	return reiserfs_proc_tail( len, buffer, start, offset, count, eof );
diff -Nru a/fs/reiserfs/resize.c b/fs/reiserfs/resize.c
--- a/fs/reiserfs/resize.c	Mon Sep  9 10:36:01 2002
+++ b/fs/reiserfs/resize.c	Mon Sep  9 10:36:01 2002
@@ -19,7 +19,8 @@
 int reiserfs_resize (struct super_block * s, unsigned long block_count_new)
 {
 	struct reiserfs_super_block * sb;
-	struct buffer_head ** bitmap, * bh;
+        struct reiserfs_bitmap_info *bitmap;
+	struct buffer_head * bh;
 	struct reiserfs_transaction_handle th;
 	unsigned int bmap_nr_new, bmap_nr;
 	unsigned int block_r_new, block_r;
@@ -103,26 +104,29 @@
 	
 	    /* allocate additional bitmap blocks, reallocate array of bitmap
 	     * block pointers */
-	    bitmap = reiserfs_kmalloc(sizeof(struct buffer_head *) * bmap_nr_new, GFP_KERNEL, s);
+	    bitmap = vmalloc(sizeof(struct reiserfs_bitmap_info) * bmap_nr_new);
 	    if (!bitmap) {
 		printk("reiserfs_resize: unable to allocate memory.\n");
 		return -ENOMEM;
 	    }
+	    memset (bitmap, 0, sizeof (struct reiserfs_bitmap_info) * SB_BMAP_NR(s));
 	    for (i = 0; i < bmap_nr; i++)
 		bitmap[i] = SB_AP_BITMAP(s)[i];
 	    for (i = bmap_nr; i < bmap_nr_new; i++) {
-		bitmap[i] = sb_getblk(s, i * s->s_blocksize * 8);
-		memset(bitmap[i]->b_data, 0, sb_blocksize(sb));
-		reiserfs_test_and_set_le_bit(0, bitmap[i]->b_data);
-
-		mark_buffer_dirty(bitmap[i]) ;
-		set_buffer_uptodate(bitmap[i]);
-		ll_rw_block(WRITE, 1, bitmap + i);
-		wait_on_buffer(bitmap[i]);
+		bitmap[i].bh = sb_getblk(s, i * s->s_blocksize * 8);
+		memset(bitmap[i].bh->b_data, 0, sb_blocksize(sb));
+		reiserfs_test_and_set_le_bit(0, bitmap[i].bh->b_data);
+
+		mark_buffer_dirty(bitmap[i].bh) ;
+		set_buffer_uptodate(bitmap[i].bh);
+		ll_rw_block(WRITE, 1, &bitmap[i].bh);
+		wait_on_buffer(bitmap[i].bh);
+		// update bitmap_info stuff
+		bitmap[i].first_zero_hint=1;
+		bitmap[i].free_count = sb_blocksize(sb) * 8 - 1;
 	    }	
 	    /* free old bitmap blocks array */
-	    reiserfs_kfree(SB_AP_BITMAP(s), 
-			   sizeof(struct buffer_head *) * bmap_nr, s);
+	    vfree(SB_AP_BITMAP(s));
 	    SB_AP_BITMAP(s) = bitmap;
 	}
 	
@@ -130,18 +134,26 @@
 	journal_begin(&th, s, 10);
 
 	/* correct last bitmap blocks in old and new disk layout */
-	reiserfs_prepare_for_journal(s, SB_AP_BITMAP(s)[bmap_nr - 1], 1);
+	reiserfs_prepare_for_journal(s, SB_AP_BITMAP(s)[bmap_nr - 1].bh, 1);
 	for (i = block_r; i < s->s_blocksize * 8; i++)
 	    reiserfs_test_and_clear_le_bit(i, 
-					   SB_AP_BITMAP(s)[bmap_nr - 1]->b_data);
-	journal_mark_dirty(&th, s, SB_AP_BITMAP(s)[bmap_nr - 1]);
+					   SB_AP_BITMAP(s)[bmap_nr - 1].bh->b_data);
+	SB_AP_BITMAP(s)[bmap_nr - 1].free_count += s->s_blocksize * 8 - block_r;
+	if ( !SB_AP_BITMAP(s)[bmap_nr - 1].first_zero_hint)
+	    SB_AP_BITMAP(s)[bmap_nr - 1].first_zero_hint = block_r;
 
-	reiserfs_prepare_for_journal(s, SB_AP_BITMAP(s)[bmap_nr_new - 1], 1);
+	journal_mark_dirty(&th, s, SB_AP_BITMAP(s)[bmap_nr - 1].bh);
+
+	reiserfs_prepare_for_journal(s, SB_AP_BITMAP(s)[bmap_nr_new - 1].bh, 1);
 	for (i = block_r_new; i < s->s_blocksize * 8; i++)
 	    reiserfs_test_and_set_le_bit(i,
-					 SB_AP_BITMAP(s)[bmap_nr_new - 1]->b_data);
-	journal_mark_dirty(&th, s, SB_AP_BITMAP(s)[bmap_nr_new - 1]);
+					 SB_AP_BITMAP(s)[bmap_nr_new - 1].bh->b_data);
+	journal_mark_dirty(&th, s, SB_AP_BITMAP(s)[bmap_nr_new - 1].bh);
  
+	SB_AP_BITMAP(s)[bmap_nr_new - 1].free_count -= s->s_blocksize * 8 - block_r_new;
+	/* Extreme case where last bitmap is the only valid block in itself. */
+	if ( !SB_AP_BITMAP(s)[bmap_nr_new - 1].free_count )
+	    SB_AP_BITMAP(s)[bmap_nr_new - 1].first_zero_hint = 0;
  	/* update super */
 	reiserfs_prepare_for_journal(s, SB_BUFFER_WITH_SB(s), 1) ;
 	free_blocks = SB_FREE_BLOCKS(s);
diff -Nru a/fs/reiserfs/stree.c b/fs/reiserfs/stree.c
--- a/fs/reiserfs/stree.c	Mon Sep  9 10:36:13 2002
+++ b/fs/reiserfs/stree.c	Mon Sep  9 10:36:13 2002
@@ -1245,6 +1245,8 @@
 	if ( n_ret_value != REPEAT_SEARCH )
 	    break;
 
+	PROC_INFO_INC( p_s_sb, delete_item_restarted );
+
 	// file system changed, repeat search
 	n_ret_value = search_for_position_by_key(p_s_sb, p_s_item_key, p_s_path);
 	if (n_ret_value == IO_ERROR)
@@ -1284,15 +1286,15 @@
         **
         ** p_s_un_bh is from the page cache (all unformatted nodes are
         ** from the page cache) and might be a highmem page.  So, we
-        ** can't use p_s_un_bh->b_data.  But, the page has already been
-        ** kmapped, so we can use page_address()
+        ** can't use p_s_un_bh->b_data.
 	** -clm
 	*/
 
-        data = page_address(p_s_un_bh->b_page) ;
+        data = kmap_atomic(p_s_un_bh->b_page, KM_USER0);
 	off = ((le_ih_k_offset (&s_ih) - 1) & (PAGE_CACHE_SIZE - 1));
 	memcpy(data + off,
 	       B_I_PITEM(PATH_PLAST_BUFFER(p_s_path), &s_ih), n_ret_value);
+	kunmap_atomic(data, KM_USER0);
     }
 
     /* Perform balancing after all resources have been collected at once. */ 
@@ -1355,8 +1357,10 @@
 	}
 
 	retval = fix_nodes (M_DELETE, &tb, NULL, 0);
-	if (retval == REPEAT_SEARCH)
+	if (retval == REPEAT_SEARCH) {
+	    PROC_INFO_INC( th -> t_super, delete_solid_item_restarted );
 	    continue;
+	}
 
 	if (retval == CARRY_ON) {
 	    do_balance (&tb, 0, 0, M_DELETE);
@@ -1543,6 +1547,8 @@
       	if ( n_ret_value != REPEAT_SEARCH )
 	    break;
 	
+	PROC_INFO_INC( p_s_sb, cut_from_item_restarted );
+
 	n_ret_value = search_for_position_by_key(p_s_sb, p_s_item_key, p_s_path);
 	if (n_ret_value == POSITION_FOUND)
 	    continue;
@@ -1614,9 +1620,9 @@
     
     do_balance(&s_cut_balance, NULL, NULL, c_mode);
     if ( n_is_inode_locked ) {
-	/* we've done an indirect->direct conversion.  when the data block 
-	** was freed, it was removed from the list of blocks that must 
-	** be flushed before the transaction commits, so we don't need to 
+	/* we've done an indirect->direct conversion.  when the data block
+	** was freed, it was removed from the list of blocks that must
+	** be flushed before the transaction commits, so we don't need to
 	** deal with it here.
 	*/
 	REISERFS_I(p_s_inode)->i_flags &= ~i_pack_on_close_mask ;
@@ -1807,16 +1813,20 @@
     int                 retval;
 
     init_tb_struct(th, &s_paste_balance, th->t_super, p_s_search_path, n_pasted_size);
+#ifdef DISPLACE_NEW_PACKING_LOCALITIES
+    s_paste_balance.key = p_s_key->on_disk_key;
+#endif
     
     while ( (retval = fix_nodes(M_PASTE, &s_paste_balance, NULL, p_c_body)) == REPEAT_SEARCH ) {
 	/* file system changed while we were in the fix_nodes */
+	PROC_INFO_INC( th -> t_super, paste_into_item_restarted );
 	retval = search_for_position_by_key (th->t_super, p_s_key, p_s_search_path);
 	if (retval == IO_ERROR) {
 	    retval = -EIO ;
 	    goto error_out ;
 	}
 	if (retval == POSITION_FOUND) {
-	    reiserfs_warning ("PAP-5710: reiserfs_paste_into_item: entry or pasted byte (%K) exists", p_s_key);
+	    reiserfs_warning ("PAP-5710: reiserfs_paste_into_item: entry or pasted byte (%K) exists\n", p_s_key);
 	    retval = -EEXIST ;
 	    goto error_out ;
 	}
@@ -1851,6 +1861,9 @@
     int                 retval;
 
     init_tb_struct(th, &s_ins_balance, th->t_super, p_s_path, IH_SIZE + ih_item_len(p_s_ih));
+#ifdef DISPLACE_NEW_PACKING_LOCALITIES
+    s_ins_balance.key = key->on_disk_key;
+#endif
 
     /*
     if (p_c_body == 0)
@@ -1860,6 +1873,7 @@
 
     while ( (retval = fix_nodes(M_INSERT, &s_ins_balance, p_s_ih, p_c_body)) == REPEAT_SEARCH) {
 	/* file system changed while we were in the fix_nodes */
+	PROC_INFO_INC( th -> t_super, insert_item_restarted );
 	retval = search_item (th->t_super, key, p_s_path);
 	if (retval == IO_ERROR) {
 	    retval = -EIO;
diff -Nru a/fs/reiserfs/super.c b/fs/reiserfs/super.c
--- a/fs/reiserfs/super.c	Mon Sep  9 10:36:11 2002
+++ b/fs/reiserfs/super.c	Mon Sep  9 10:36:11 2002
@@ -13,6 +13,7 @@
 
 #include <linux/config.h>
 #include <linux/module.h>
+#include <linux/vmalloc.h>
 #include <linux/time.h>
 #include <asm/uaccess.h>
 #include <linux/reiserfs_fs.h>
@@ -374,9 +375,9 @@
   journal_release(&th, s) ;
 
   for (i = 0; i < SB_BMAP_NR (s); i ++)
-    brelse (SB_AP_BITMAP (s)[i]);
+    brelse (SB_AP_BITMAP (s)[i].bh);
 
-  reiserfs_kfree (SB_AP_BITMAP (s), sizeof (struct buffer_head *) * SB_BMAP_NR (s), s);
+  vfree (SB_AP_BITMAP (s));
 
   brelse (SB_BUFFER_WITH_SB (s));
 
@@ -387,6 +388,11 @@
 		      REISERFS_SB(s)->s_kmallocs);
   }
 
+  if (REISERFS_SB(s)->reserved_blocks != 0) {
+    reiserfs_warning ("green-2005: reiserfs_put_super: reserved blocks left %d\n",
+		      REISERFS_SB(s)->reserved_blocks);
+  }
+
   reiserfs_proc_unregister( s, "journal" );
   reiserfs_proc_unregister( s, "oidmap" );
   reiserfs_proc_unregister( s, "on-disk-super" );
@@ -518,6 +524,13 @@
     {NULL, -1}
 };
 
+const arg_desc_t tails[] = {
+    {"on", REISERFS_LARGETAIL},
+    {"off", -1},
+    {"small", REISERFS_SMALLTAIL},
+    {NULL, 0}
+};
+
 
 /* proceed only one option from a list *cur - string containing of mount options
    opts - array of options which are accepted
@@ -525,7 +538,7 @@
    in the input - pointer to the argument is stored here
    bit_flags - if option requires to set a certain bit - it is set here
    return -1 if unknown option is found, opt->arg_required otherwise */
-static int reiserfs_getopt (char ** cur, opt_desc_t * opts, char ** opt_arg,
+static int reiserfs_getopt ( struct super_block * s, char ** cur, opt_desc_t * opts, char ** opt_arg,
 			    unsigned long * bit_flags)
 {
     char * p;
@@ -547,7 +560,16 @@
 	*(*cur) = '\0';
 	(*cur) ++;
     }
-    
+
+    if ( !strncmp (p, "alloc=", 6) ) {
+	/* Ugly special case, probably we should redo options parser so that
+	   it can understand several arguments for some options, also so that
+	   it can fill several bitfields with option values. */
+	reiserfs_parse_alloc_options( s, p + 6);
+	return 0;
+    }
+
+ 
     /* for every option in the list */
     for (opt = opts; opt->option_name; opt ++) {
 	if (!strncmp (p, opt->option_name, strlen (opt->option_name))) {
@@ -612,7 +634,7 @@
 
 
 /* returns 0 if something is wrong in option string, 1 - otherwise */
-static int reiserfs_parse_options (char * options, /* string given via mount's -o */
+static int reiserfs_parse_options (struct super_block * s, char * options, /* string given via mount's -o */
 				   unsigned long * mount_options,
 				   /* after the parsing phase, contains the
 				      collection of bitflags defining what
@@ -624,14 +646,14 @@
     char * arg = NULL;
     char * pos;
     opt_desc_t opts[] = {
-		{"notail", 0, 0, NOTAIL},
+		{"tails", 't', tails, -1},
+		{"notail", 0, 0, -1}, /* Compatibility stuff, so that -o notail
+for old setups still work */
 		{"conv", 0, 0, REISERFS_CONVERT}, 
 		{"attrs", 0, 0, REISERFS_ATTRS}, 
 		{"nolog", 0, 0, -1},
 		{"replayonly", 0, 0, REPLAYONLY},
-		
 		{"block-allocator", 'a', balloc, -1}, 
-		
 		{"resize", 'r', 0, -1},
 		{"jdev", 'j', 0, -1},
 		{NULL, 0, 0, -1}
@@ -642,9 +664,12 @@
 	/* use default configuration: create tails, journaling on, no
 	   conversion to newest format */
 	return 1;
+    else
+	/* Drop defaults to zeroes */
+	*mount_options = 0;
     
     for (pos = options; pos; ) {
-	c = reiserfs_getopt (&pos, opts, &arg, mount_options);
+	c = reiserfs_getopt (s, &pos, opts, &arg, mount_options);
 	if (c == -1)
 	    /* wrong option is given */
 	    return 0;
@@ -681,7 +706,7 @@
 
   rs = SB_DISK_SUPER_BLOCK (s);
 
-  if (!reiserfs_parse_options(arg, &mount_options, &blocks, NULL))
+  if (!reiserfs_parse_options(s, arg, &mount_options, &blocks, NULL))
     return -EINVAL;
   
   if(blocks) {
@@ -731,32 +756,84 @@
   return 0;
 }
 
+/* load_bitmap_info_data - Sets up the reiserfs_bitmap_info structure from disk.
+ * @sb - superblock for this filesystem
+ * @bi - the bitmap info to be loaded. Requires that bi->bh is valid.
+ *
+ * This routine counts how many free bits there are, finding the first zero
+ * as a side effect. Could also be implemented as a loop of test_bit() calls, or
+ * a loop of find_first_zero_bit() calls. This implementation is similar to
+ * find_first_zero_bit(), but doesn't return after it finds the first bit.
+ * Should only be called on fs mount, but should be fairly efficient anyways.
+ *
+ * bi->first_zero_hint is considered unset if it == 0, since the bitmap itself
+ * will * invariably occupt block 0 represented in the bitmap. The only
+ * exception to this is when free_count also == 0, since there will be no
+ * free blocks at all.
+ */
+
+static void load_bitmap_info_data (struct super_block *sb,
+                                   struct reiserfs_bitmap_info *bi)
+{
+    unsigned long *cur = (unsigned long *)bi->bh->b_data;
+
+    while ((char *)cur < (bi->bh->b_data + sb->s_blocksize)) {
+
+	/* No need to scan if all 0's or all 1's.
+	 * Since we're only counting 0's, we can simply ignore all 1's */
+	if (*cur == 0) {
+	    if (bi->first_zero_hint == 0) {
+		bi->first_zero_hint = ((char *)cur - bi->bh->b_data) << 3;
+	    }
+	    bi->free_count += sizeof(unsigned long)*8;
+	} else if (*cur != ~0L) {
+	    int b;
+	    for (b = 0; b < sizeof(unsigned long)*8; b++) {
+		if (!reiserfs_test_le_bit (b, cur)) {
+		    bi->free_count ++;
+		    if (bi->first_zero_hint == 0)
+			bi->first_zero_hint =
+					(((char *)cur - bi->bh->b_data) << 3) + b;
+		    }
+		}
+	    }
+	cur ++;
+    }
 
+#ifdef CONFIG_REISERFS_CHECK
+// This outputs a lot of unneded info on big FSes
+//    reiserfs_warning ("bitmap loaded from block %d: %d free blocks\n",
+//		      bi->bh->b_blocknr, bi->free_count);
+#endif
+}
+  
 static int read_bitmaps (struct super_block * s)
 {
     int i, bmap_nr;
 
-    SB_AP_BITMAP (s) = reiserfs_kmalloc (sizeof (struct buffer_head *) * SB_BMAP_NR(s), GFP_NOFS, s);
+    SB_AP_BITMAP (s) = vmalloc (sizeof (struct reiserfs_bitmap_info) * SB_BMAP_NR(s));
     if (SB_AP_BITMAP (s) == 0)
 	return 1;
+    memset (SB_AP_BITMAP (s), 0, sizeof (struct reiserfs_bitmap_info) * SB_BMAP_NR(s));
     for (i = 0, bmap_nr = REISERFS_DISK_OFFSET_IN_BYTES / s->s_blocksize + 1;
 	 i < SB_BMAP_NR(s); i++, bmap_nr = s->s_blocksize * 8 * i) {
-	SB_AP_BITMAP (s)[i] = sb_getblk(s, bmap_nr);
-	if (!buffer_uptodate(SB_AP_BITMAP(s)[i]))
-	    ll_rw_block(READ, 1, SB_AP_BITMAP(s) + i);
+	SB_AP_BITMAP (s)[i].bh = sb_getblk(s, bmap_nr);
+	if (!buffer_uptodate(SB_AP_BITMAP(s)[i].bh))
+	    ll_rw_block(READ, 1, &SB_AP_BITMAP(s)[i].bh);
     }
     for (i = 0; i < SB_BMAP_NR(s); i++) {
-	wait_on_buffer(SB_AP_BITMAP (s)[i]);
-	if (!buffer_uptodate(SB_AP_BITMAP(s)[i])) {
+	wait_on_buffer(SB_AP_BITMAP (s)[i].bh);
+	if (!buffer_uptodate(SB_AP_BITMAP(s)[i].bh)) {
 	    reiserfs_warning("sh-2029: reiserfs read_bitmaps: "
 			 "bitmap block (#%lu) reading failed\n",
-			 SB_AP_BITMAP(s)[i]->b_blocknr);
+			 SB_AP_BITMAP(s)[i].bh->b_blocknr);
 	    for (i = 0; i < SB_BMAP_NR(s); i++)
-		brelse(SB_AP_BITMAP(s)[i]);
-	    reiserfs_kfree(SB_AP_BITMAP(s), sizeof(struct buffer_head *) * SB_BMAP_NR(s), s);
+		brelse(SB_AP_BITMAP(s)[i].bh);
+	    vfree(SB_AP_BITMAP(s));
 	    SB_AP_BITMAP(s) = NULL;
 	    return 1;
 	}
+	load_bitmap_info_data (s, SB_AP_BITMAP (s) + i);
     }
     return 0;
 }
@@ -768,16 +845,17 @@
   int bmp1 = (REISERFS_OLD_DISK_OFFSET_IN_BYTES / s->s_blocksize) + 1;  /* first of bitmap blocks */
 
   /* read true bitmap */
-  SB_AP_BITMAP (s) = reiserfs_kmalloc (sizeof (struct buffer_head *) * sb_bmap_nr(rs), GFP_NOFS, s);
+  SB_AP_BITMAP (s) = vmalloc (sizeof (struct reiserfs_buffer_info *) * sb_bmap_nr(rs));
   if (SB_AP_BITMAP (s) == 0)
     return 1;
 
-  memset (SB_AP_BITMAP (s), 0, sizeof (struct buffer_head *) * sb_bmap_nr(rs));
+  memset (SB_AP_BITMAP (s), 0, sizeof (struct reiserfs_buffer_info *) * sb_bmap_nr(rs));
 
   for (i = 0; i < sb_bmap_nr(rs); i ++) {
-    SB_AP_BITMAP (s)[i] = sb_bread (s, bmp1 + i);
-    if (!SB_AP_BITMAP (s)[i])
+    SB_AP_BITMAP (s)[i].bh = sb_bread (s, bmp1 + i);
+    if (!SB_AP_BITMAP (s)[i].bh)
       return 1;
+    load_bitmap_info_data (s, SB_AP_BITMAP (s) + i);
   }
 
   return 0;
@@ -790,7 +868,7 @@
   char * buf;
 
   while (i < SB_BLOCK_COUNT (s)) {
-    buf = SB_AP_BITMAP (s)[i / (s->s_blocksize * 8)]->b_data;
+    buf = SB_AP_BITMAP (s)[i / (s->s_blocksize * 8)].bh->b_data;
     if (!reiserfs_test_le_bit (i % (s->s_blocksize * 8), buf))
       free ++;
     i ++;
@@ -899,10 +977,11 @@
   }
 
   for (i = 0; i < SB_BMAP_NR(s) ; i++) {
-    ll_rw_block(READ, 1, &(SB_AP_BITMAP(s)[i])) ;
-    wait_on_buffer(SB_AP_BITMAP(s)[i]) ;
-    if (!buffer_uptodate(SB_AP_BITMAP(s)[i])) {
-      printk("reread_meta_blocks, error reading bitmap block number %d at %ld\n", i, SB_AP_BITMAP(s)[i]->b_blocknr) ;
+    ll_rw_block(READ, 1, &(SB_AP_BITMAP(s)[i].bh)) ;
+    wait_on_buffer(SB_AP_BITMAP(s)[i].bh) ;
+    if (!buffer_uptodate(SB_AP_BITMAP(s)[i].bh)) {
+      printk("reread_meta_blocks, error reading bitmap block number %d at
+      %ld\n", i, SB_AP_BITMAP(s)[i].bh->b_blocknr) ;
       return 1 ;
     }
   }
@@ -1087,9 +1166,17 @@
     }
     s->u.generic_sbp = sbi;
     memset (sbi, 0, sizeof (struct reiserfs_sb_info));
+    /* Set default values for options: non-aggressive tails */
+    REISERFS_SB(s)->s_mount_opt = ( 1 << REISERFS_SMALLTAIL );
+    /* default block allocator option: skip_busy */
+    REISERFS_SB(s)->s_alloc_options.bits = ( 1 << 5);
+    /* If file grew past 4 blocks, start preallocation blocks for it. */
+    REISERFS_SB(s)->s_alloc_options.preallocmin = 4;
+    /* Preallocate by 8 blocks (9-1) at once */
+    REISERFS_SB(s)->s_alloc_options.preallocsize = 9;
 
     jdev_name = NULL;
-    if (reiserfs_parse_options ((char *) data, &(sbi->s_mount_opt), &blocks, &jdev_name) == 0) {
+    if (reiserfs_parse_options (s, (char *) data, &(sbi->s_mount_opt), &blocks, &jdev_name) == 0) {
 	goto error;
     }
 
@@ -1236,10 +1323,10 @@
     if (SB_DISK_SUPER_BLOCK (s)) {
 	for (j = 0; j < SB_BMAP_NR (s); j ++) {
 	    if (SB_AP_BITMAP (s))
-		brelse (SB_AP_BITMAP (s)[j]);
+		brelse (SB_AP_BITMAP (s)[j].bh);
 	}
 	if (SB_AP_BITMAP (s))
-	    reiserfs_kfree (SB_AP_BITMAP (s), sizeof (struct buffer_head *) * SB_BMAP_NR (s), s);
+	    vfree (SB_AP_BITMAP (s));
     }
     if (SB_BUFFER_WITH_SB (s))
 	brelse(SB_BUFFER_WITH_SB (s));
diff -Nru a/fs/reiserfs/tail_conversion.c b/fs/reiserfs/tail_conversion.c
--- a/fs/reiserfs/tail_conversion.c	Mon Sep  9 10:36:18 2002
+++ b/fs/reiserfs/tail_conversion.c	Mon Sep  9 10:36:18 2002
@@ -122,11 +122,12 @@
     }
     /* if we've copied bytes from disk into the page, we need to zero
     ** out the unused part of the block (it was not up to date before)
-    ** the page is still kmapped (by whoever called reiserfs_get_block)
     */
     if (up_to_date_bh) {
         unsigned pgoff = (tail_offset + total_tail - 1) & (PAGE_CACHE_SIZE - 1);
-	memset(page_address(unbh->b_page) + pgoff, 0, n_blk_size - total_tail) ;
+	char *kaddr=kmap_atomic(up_to_date_bh->b_page, KM_USER0);
+	memset(kaddr + pgoff, 0, n_blk_size - total_tail) ;
+	kunmap_atomic(kaddr, KM_USER0);
     }
 
     REISERFS_I(inode)->i_first_direct_byte = U32_MAX;
diff -Nru a/fs/sysv/dir.c b/fs/sysv/dir.c
--- a/fs/sysv/dir.c	Mon Sep  9 10:36:01 2002
+++ b/fs/sysv/dir.c	Mon Sep  9 10:36:01 2002
@@ -14,6 +14,7 @@
  */
 
 #include <linux/pagemap.h>
+#include <linux/highmem.h>
 #include <linux/smp_lock.h>
 #include "sysv.h"
 
@@ -273,6 +274,7 @@
 
 	if (!page)
 		return -ENOMEM;
+	kmap(page);
 	err = mapping->a_ops->prepare_write(NULL, page, 0, 2 * SYSV_DIRSIZE);
 	if (err) {
 		unlock_page(page);
@@ -291,6 +293,7 @@
 
 	err = dir_commit_chunk(page, 0, 2 * SYSV_DIRSIZE);
 fail:
+	kunmap(page);
 	page_cache_release(page);
 	return err;
 }
diff -Nru a/include/asm-alpha/core_t2.h b/include/asm-alpha/core_t2.h
--- a/include/asm-alpha/core_t2.h	Mon Sep  9 10:36:11 2002
+++ b/include/asm-alpha/core_t2.h	Mon Sep  9 10:36:11 2002
@@ -19,7 +19,7 @@
  *
  */
 
-#define T2_MEM_R1_MASK 0x03ffffff  /* Mem sparse region 1 mask is 26 bits */
+#define T2_MEM_R1_MASK 0x07ffffff  /* Mem sparse region 1 mask is 26 bits */
 
 /* GAMMA-SABLE is a SABLE with EV5-based CPUs */
 #define _GAMMA_BIAS		0x8000000000UL
@@ -402,13 +402,17 @@
  *
  */
 
+#define t2_set_hae { \
+	msb = addr  >> 27; \
+	addr &= T2_MEM_R1_MASK; \
+	set_hae(msb); \
+}
+
 __EXTERN_INLINE u8 t2_readb(unsigned long addr)
 {
 	unsigned long result, msb;
 
-	msb = addr & 0xE0000000;
-	addr &= T2_MEM_R1_MASK;
-	set_hae(msb);
+	t2_set_hae;
 
 	result = *(vip) ((addr << 5) + T2_SPARSE_MEM + 0x00);
 	return __kernel_extbl(result, addr & 3);
@@ -418,9 +422,7 @@
 {
 	unsigned long result, msb;
 
-	msb = addr & 0xE0000000;
-	addr &= T2_MEM_R1_MASK;
-	set_hae(msb);
+	t2_set_hae;
 
 	result = *(vuip) ((addr << 5) + T2_SPARSE_MEM + 0x08);
 	return __kernel_extwl(result, addr & 3);
@@ -431,9 +433,7 @@
 {
 	unsigned long msb;
 
-	msb = addr & 0xE0000000;
-	addr &= T2_MEM_R1_MASK;
-	set_hae(msb);
+	t2_set_hae;
 
 	return *(vuip) ((addr << 5) + T2_SPARSE_MEM + 0x18);
 }
@@ -442,9 +442,7 @@
 {
 	unsigned long r0, r1, work, msb;
 
-	msb = addr & 0xE0000000;
-	addr &= T2_MEM_R1_MASK;
-	set_hae(msb);
+	t2_set_hae;
 
 	work = (addr << 5) + T2_SPARSE_MEM + 0x18;
 	r0 = *(vuip)(work);
@@ -456,9 +454,7 @@
 {
 	unsigned long msb, w;
 
-	msb = addr & 0xE0000000;
-	addr &= T2_MEM_R1_MASK;
-	set_hae(msb);
+	t2_set_hae;
 
 	w = __kernel_insbl(b, addr & 3);
 	*(vuip) ((addr << 5) + T2_SPARSE_MEM + 0x00) = w;
@@ -468,9 +464,7 @@
 {
 	unsigned long msb, w;
 
-	msb = addr & 0xE0000000;
-	addr &= T2_MEM_R1_MASK;
-	set_hae(msb);
+	t2_set_hae;
 
 	w = __kernel_inswl(b, addr & 3);
 	*(vuip) ((addr << 5) + T2_SPARSE_MEM + 0x08) = w;
@@ -481,9 +475,7 @@
 {
 	unsigned long msb;
 
-	msb = addr & 0xE0000000;
-	addr &= T2_MEM_R1_MASK;
-	set_hae(msb);
+	t2_set_hae;
 
 	*(vuip) ((addr << 5) + T2_SPARSE_MEM + 0x18) = b;
 }
@@ -492,9 +484,7 @@
 {
 	unsigned long msb, work;
 
-	msb = addr & 0xE0000000;
-	addr &= T2_MEM_R1_MASK;
-	set_hae(msb);
+	t2_set_hae;
 
 	work = (addr << 5) + T2_SPARSE_MEM + 0x18;
 	*(vuip)work = b;
diff -Nru a/include/asm-alpha/dma.h b/include/asm-alpha/dma.h
--- a/include/asm-alpha/dma.h	Mon Sep  9 10:36:13 2002
+++ b/include/asm-alpha/dma.h	Mon Sep  9 10:36:13 2002
@@ -75,34 +75,49 @@
 
 #define MAX_DMA_CHANNELS	8
 
-/* The maximum address that we can perform a DMA transfer to on Alpha XL,
-   due to a hardware SIO (PCI<->ISA bus bridge) chip limitation, is 64MB.
-   See <asm/apecs.h> for more info.
+/*
+  ISA DMA limitations on Alpha platforms,
+
+  These may be due to SIO (PCI<->ISA bridge) chipset limitation, or
+  just a wiring limit.
+*/
+
+/* The maximum address for ISA DMA transfer on Alpha XL, due to an
+   hardware SIO limitation, is 64MB.
 */
-/* The maximum address that we can perform a DMA transfer to on RUFFIAN,
-   due to a hardware SIO (PCI<->ISA bus bridge) chip limitation, is 16MB.
-   See <asm/pyxis.h> for more info.
+#define ALPHA_XL_MAX_DMA_ADDRESS	(IDENT_ADDR+0x04000000UL)
+
+/* The maximum address for ISA DMA transfer on RUFFIAN and NAUTILUS,
+   due to an hardware SIO limitation, is 16MB.
 */
-/* NOTE: we must define the maximum as something less than 64Mb, to prevent 
-   virt_to_bus() from returning an address in the first window, for a
-   data area that goes beyond the 64Mb first DMA window. Sigh...
-   We MUST coordinate the maximum with <asm/apecs.h> for consistency.
-   For now, this limit is set to 48Mb...
+#define ALPHA_RUFFIAN_MAX_DMA_ADDRESS	(IDENT_ADDR+0x01000000UL)
+#define ALPHA_NAUTILUS_MAX_DMA_ADDRESS	(IDENT_ADDR+0x01000000UL)
+
+/* The maximum address for ISA DMA transfer on SABLE, and some ALCORs,
+   due to an hardware SIO chip limitation, is 2GB.
+*/
+#define ALPHA_SABLE_MAX_DMA_ADDRESS	(IDENT_ADDR+0x80000000UL)
+#define ALPHA_ALCOR_MAX_DMA_ADDRESS	(IDENT_ADDR+0x80000000UL)
+
+/*
+  Maximum address for all the others is the complete 32-bit bus
+  address space.
 */
-#define ALPHA_XL_MAX_DMA_ADDRESS	(IDENT_ADDR+0x3000000UL)
-#define ALPHA_RUFFIAN_MAX_DMA_ADDRESS	(IDENT_ADDR+0x1000000UL)
-#define ALPHA_NAUTILUS_MAX_DMA_ADDRESS	(IDENT_ADDR+0x1000000UL)
-#define ALPHA_MAX_DMA_ADDRESS		(~0UL)
+#define ALPHA_MAX_DMA_ADDRESS		(IDENT_ADDR+0x100000000UL)
 
 #ifdef CONFIG_ALPHA_GENERIC
 # define MAX_DMA_ADDRESS		(alpha_mv.max_dma_address)
 #else
-# ifdef CONFIG_ALPHA_XL
+# if defined(CONFIG_ALPHA_XL)
 #  define MAX_DMA_ADDRESS		ALPHA_XL_MAX_DMA_ADDRESS
 # elif defined(CONFIG_ALPHA_RUFFIAN)
 #  define MAX_DMA_ADDRESS		ALPHA_RUFFIAN_MAX_DMA_ADDRESS
 # elif defined(CONFIG_ALPHA_NAUTILUS)
 #  define MAX_DMA_ADDRESS		ALPHA_NAUTILUS_MAX_DMA_ADDRESS
+# elif defined(CONFIG_ALPHA_SABLE)
+#  define MAX_DMA_ADDRESS		ALPHA_SABLE_MAX_DMA_ADDRESS
+# elif defined(CONFIG_ALPHA_ALCOR)
+#  define MAX_DMA_ADDRESS		ALPHA_ALCOR_MAX_DMA_ADDRESS
 # else
 #  define MAX_DMA_ADDRESS		ALPHA_MAX_DMA_ADDRESS
 # endif
diff -Nru a/include/asm-alpha/floppy.h b/include/asm-alpha/floppy.h
--- a/include/asm-alpha/floppy.h	Mon Sep  9 10:36:17 2002
+++ b/include/asm-alpha/floppy.h	Mon Sep  9 10:36:17 2002
@@ -97,24 +97,21 @@
 
 /*
  * Most Alphas have no problems with floppy DMA crossing 64k borders,
- * except for XL and RUFFIAN.  They are also the only one with DMA
- * limits, so we use that to test in the generic kernel.
+ * except for certain ones, like XL and RUFFIAN.
+ *
+ * However, the test is simple and fast, and this *is* floppy, after all,
+ * so we do it for all platforms, just to make sure.
+ *
+ * This is advantageous in other circumstances as well, as in moving
+ * about the PCI DMA windows and forcing the floppy to start doing
+ * scatter-gather when it never had before, and there *is* a problem
+ * on that platform... ;-}
  */
 
-#define __CROSS_64KB(a,s)					\
+#define CROSS_64KB(a,s)						\
 ({ unsigned long __s64 = (unsigned long)(a);			\
    unsigned long __e64 = __s64 + (unsigned long)(s) - 1;	\
    (__s64 ^ __e64) & ~0xfffful; })
-
-#ifdef CONFIG_ALPHA_GENERIC
-# define CROSS_64KB(a,s)   (__CROSS_64KB(a,s) && ~alpha_mv.max_dma_address)
-#else
-# if defined(CONFIG_ALPHA_XL) || defined(CONFIG_ALPHA_RUFFIAN) || defined(CONFIG_ALPHA_NAUTILUS)
-#  define CROSS_64KB(a,s)  __CROSS_64KB(a,s)
-# else
-#  define CROSS_64KB(a,s)  (0)
-# endif
-#endif
 
 #define EXTRA_FLOPPY_PARAMS
 
diff -Nru a/include/asm-alpha/ide.h b/include/asm-alpha/ide.h
--- a/include/asm-alpha/ide.h	Mon Sep  9 10:36:13 2002
+++ b/include/asm-alpha/ide.h	Mon Sep  9 10:36:13 2002
@@ -80,6 +80,17 @@
 #endif
 }
 
+#define ide_request_irq(irq,hand,flg,dev,id)	request_irq((irq),(hand),(flg),(dev),(id))
+#define ide_free_irq(irq,dev_id)		free_irq((irq), (dev_id))
+#define ide_check_region(from,extent)		check_region((from), (extent))
+#define ide_request_region(from,extent,name)	request_region((from), (extent), (name))
+#define ide_release_region(from,extent)		release_region((from), (extent))
+
+#define ide_ack_intr(hwif)		(1)
+#define ide_fix_driveid(id)		do {} while (0)
+#define ide_release_lock(lock)		do {} while (0)
+#define ide_get_lock(lock, hdlr, data)	do {} while (0)
+
 #endif /* __KERNEL__ */
 
 #endif /* __ASMalpha_IDE_H */
diff -Nru a/include/asm-alpha/kmap_types.h b/include/asm-alpha/kmap_types.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/include/asm-alpha/kmap_types.h	Mon Sep  9 10:36:18 2002
@@ -0,0 +1,31 @@
+#ifndef _ASM_KMAP_TYPES_H
+#define _ASM_KMAP_TYPES_H
+
+/* Dummy header just to define km_type. */
+
+#include <linux/config.h>
+
+#if CONFIG_DEBUG_HIGHMEM
+# define D(n) __KM_FENCE_##n ,
+#else
+# define D(n)
+#endif
+
+enum km_type {
+D(0)	KM_BOUNCE_READ,
+D(1)	KM_SKB_SUNRPC_DATA,
+D(2)	KM_SKB_DATA_SOFTIRQ,
+D(3)	KM_USER0,
+D(4)	KM_USER1,
+D(5)	KM_BIO_SRC_IRQ,
+D(6)	KM_BIO_DST_IRQ,
+D(7)	KM_PTE0,
+D(8)	KM_PTE1,
+D(9)	KM_IRQ0,
+D(10)	KM_IRQ1,
+D(11)	KM_TYPE_NR
+};
+
+#undef D
+
+#endif
diff -Nru a/include/asm-alpha/mmzone.h b/include/asm-alpha/mmzone.h
--- a/include/asm-alpha/mmzone.h	Mon Sep  9 10:36:05 2002
+++ b/include/asm-alpha/mmzone.h	Mon Sep  9 10:36:05 2002
@@ -52,14 +52,14 @@
 
 #if 1
 #define PLAT_NODE_DATA_LOCALNR(p, n)	\
-	(((p) - PLAT_NODE_DATA(n)->gendata.node_start_paddr) >> PAGE_SHIFT)
+	(((p) >> PAGE_SHIFT) - PLAT_NODE_DATA(n)->gendata.node_start_pfn)
 #else
 static inline unsigned long
 PLAT_NODE_DATA_LOCALNR(unsigned long p, int n)
 {
 	unsigned long temp;
-	temp = p - PLAT_NODE_DATA(n)->gendata.node_start_paddr;
-	return (temp >> PAGE_SHIFT);
+	temp = p >> PAGE_SHIFT;
+	return temp - PLAT_NODE_DATA(n)->gendata.node_start_pfn;
 }
 #endif
 
@@ -96,7 +96,7 @@
  * and returns the kaddr corresponding to first physical page in the
  * node's mem_map.
  */
-#define LOCAL_BASE_ADDR(kaddr)	((unsigned long)__va(NODE_DATA(KVADDR_TO_NID(kaddr))->node_start_paddr))
+#define LOCAL_BASE_ADDR(kaddr)	((unsigned long)__va(NODE_DATA(KVADDR_TO_NID(kaddr))->node_start_pfn << PAGE_SHIFT))
 
 #define LOCAL_MAP_NR(kvaddr) \
 	(((unsigned long)(kvaddr)-LOCAL_BASE_ADDR(kvaddr)) >> PAGE_SHIFT)
diff -Nru a/include/asm-alpha/pgtable.h b/include/asm-alpha/pgtable.h
--- a/include/asm-alpha/pgtable.h	Mon Sep  9 10:36:01 2002
+++ b/include/asm-alpha/pgtable.h	Mon Sep  9 10:36:01 2002
@@ -195,8 +195,8 @@
 #define PAGE_TO_PA(page)	((page - mem_map) << PAGE_SHIFT)
 #else
 #define PAGE_TO_PA(page) \
-		((((page)-(page)->zone->zone_mem_map) << PAGE_SHIFT) \
-		+ (page)->zone->zone_start_paddr)
+		((( (page) - (page)->zone->zone_mem_map ) \
+		+ (page)->zone->zone_start_pfn) << PAGE_SHIFT)
 #endif
 
 #ifndef CONFIG_DISCONTIGMEM
@@ -216,7 +216,7 @@
 	unsigned long pfn;							\
 										\
 	pfn = ((unsigned long)((page)-(page)->zone->zone_mem_map)) << 32;	\
-	pfn += (page)->zone->zone_start_paddr << (32-PAGE_SHIFT);		\
+	pfn += (page)->zone->zone_start_pfn << 32);				\
 	pte_val(pte) = pfn | pgprot_val(pgprot);				\
 										\
 	pte;									\
diff -Nru a/include/asm-alpha/user.h b/include/asm-alpha/user.h
--- a/include/asm-alpha/user.h	Mon Sep  9 10:35:51 2002
+++ b/include/asm-alpha/user.h	Mon Sep  9 10:35:51 2002
@@ -1,6 +1,7 @@
 #ifndef _ALPHA_USER_H
 #define _ALPHA_USER_H
 
+#include <linux/sched.h>
 #include <linux/ptrace.h>
 
 #include <asm/page.h>
diff -Nru a/include/asm-arm/memory.h b/include/asm-arm/memory.h
--- a/include/asm-arm/memory.h	Mon Sep  9 10:36:13 2002
+++ b/include/asm-arm/memory.h	Mon Sep  9 10:36:17 2002
@@ -80,8 +80,8 @@
  * around in memory.
  */
 #define page_to_pfn(page)					\
-	(((page) - page_zone(page)->zone_mem_map)		\
-	  + (page_zone(page)->zone_start_paddr >> PAGE_SHIFT))
+	(( (page) - page_zone(page)->zone_mem_map)		\
+	  + page_zone(page)->zone_start_pfn)
 
 #define pfn_to_page(pfn)					\
 	(PFN_TO_MAPBASE(pfn) + LOCAL_MAP_NR((pfn) << PAGE_SHIFT))
diff -Nru a/include/asm-generic/percpu.h b/include/asm-generic/percpu.h
--- a/include/asm-generic/percpu.h	Mon Sep  9 10:36:01 2002
+++ b/include/asm-generic/percpu.h	Mon Sep  9 10:36:01 2002
@@ -10,7 +10,7 @@
 /* Separate out the type, so (int[3], foo) works. */
 #ifndef MODULE
 #define DEFINE_PER_CPU(type, name) \
-    __attribute__((__section__(".percpu"))) __typeof__(type) name##__per_cpu
+    __attribute__((__section__(".data.percpu"))) __typeof__(type) name##__per_cpu
 #endif
 
 /* var is in discarded region: offset to particular copy we want */
diff -Nru a/include/asm-i386/highmem.h b/include/asm-i386/highmem.h
--- a/include/asm-i386/highmem.h	Mon Sep  9 10:35:56 2002
+++ b/include/asm-i386/highmem.h	Mon Sep  9 10:35:56 2002
@@ -81,7 +81,7 @@
 	enum fixed_addresses idx;
 	unsigned long vaddr;
 
-	preempt_disable();
+	inc_preempt_count();
 	if (page < highmem_start_page)
 		return page_address(page);
 
@@ -104,7 +104,7 @@
 	enum fixed_addresses idx = type + KM_TYPE_NR*smp_processor_id();
 
 	if (vaddr < FIXADDR_START) { // FIXME
-		preempt_enable();
+		dec_preempt_count();
 		return;
 	}
 
@@ -119,7 +119,7 @@
 	__flush_tlb_one(vaddr);
 #endif
 
-	preempt_enable();
+	dec_preempt_count();
 }
 
 #endif /* __KERNEL__ */
diff -Nru a/include/asm-i386/io.h b/include/asm-i386/io.h
--- a/include/asm-i386/io.h	Mon Sep  9 10:36:11 2002
+++ b/include/asm-i386/io.h	Mon Sep  9 10:36:11 2002
@@ -96,11 +96,7 @@
 /*
  * Change "struct page" to physical address.
  */
-#ifdef CONFIG_HIGHMEM64G
-#define page_to_phys(page)	((u64)(page - mem_map) << PAGE_SHIFT)
-#else
-#define page_to_phys(page)	((page - mem_map) << PAGE_SHIFT)
-#endif
+#define page_to_phys(page)    ((dma_addr_t)page_to_pfn(page) << PAGE_SHIFT)
 
 extern void * __ioremap(unsigned long offset, unsigned long size, unsigned long flags);
 
diff -Nru a/include/asm-i386/max_numnodes.h b/include/asm-i386/max_numnodes.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/include/asm-i386/max_numnodes.h	Mon Sep  9 10:36:18 2002
@@ -0,0 +1,12 @@
+#ifndef _ASM_MAX_NUMNODES_H
+#define _ASM_MAX_NUMNODES_H
+
+#include <linux/config.h>
+
+#ifdef CONFIG_X86_NUMAQ
+#include <asm/numaq.h>
+#else
+#define MAX_NUMNODES	1
+#endif /* CONFIG_X86_NUMAQ */
+
+#endif /* _ASM_MAX_NUMNODES_H */
diff -Nru a/include/asm-i386/mmzone.h b/include/asm-i386/mmzone.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/include/asm-i386/mmzone.h	Mon Sep  9 10:36:18 2002
@@ -0,0 +1,101 @@
+/*
+ * Written by Pat Gaughen (gone@us.ibm.com) Mar 2002
+ *
+ */
+
+#ifndef _ASM_MMZONE_H_
+#define _ASM_MMZONE_H_
+
+#ifdef CONFIG_DISCONTIGMEM
+
+#ifdef CONFIG_X86_NUMAQ
+#include <asm/numaq.h>
+#else
+#define PHYSADDR_TO_NID(pa)	(0)
+#define PFN_TO_NID(pfn)		(0)
+#ifdef CONFIG_NUMA
+#define _cpu_to_node(cpu) 0
+#endif /* CONFIG_NUMA */
+#endif /* CONFIG_X86_NUMAQ */
+
+#ifdef CONFIG_NUMA
+#define numa_node_id() _cpu_to_node(smp_processor_id())
+#endif /* CONFIG_NUMA */
+
+struct plat_pglist_data {
+	pg_data_t	gendata;
+};
+
+extern struct plat_pglist_data *plat_node_data[];
+
+/*
+ * Following are macros that are specific to this numa platform.
+ */
+#define reserve_bootmem(addr, size) \
+	reserve_bootmem_node(NODE_DATA(0), (addr), (size))
+#define alloc_bootmem(x) \
+	__alloc_bootmem_node(NODE_DATA(0), (x), SMP_CACHE_BYTES, __pa(MAX_DMA_ADDRESS))
+#define alloc_bootmem_low(x) \
+	__alloc_bootmem_node(NODE_DATA(0), (x), SMP_CACHE_BYTES, 0)
+#define alloc_bootmem_pages(x) \
+	__alloc_bootmem_node(NODE_DATA(0), (x), PAGE_SIZE, __pa(MAX_DMA_ADDRESS))
+#define alloc_bootmem_low_pages(x) \
+	__alloc_bootmem_node(NODE_DATA(0), (x), PAGE_SIZE, 0)
+#define alloc_bootmem_node(ignore, x) \
+	__alloc_bootmem_node(NODE_DATA(0), (x), SMP_CACHE_BYTES, __pa(MAX_DMA_ADDRESS))
+#define alloc_bootmem_pages_node(ignore, x) \
+	__alloc_bootmem_node(NODE_DATA(0), (x), PAGE_SIZE, __pa(MAX_DMA_ADDRESS))
+#define alloc_bootmem_low_pages_node(ignore, x) \
+	__alloc_bootmem_node(NODE_DATA(0), (x), PAGE_SIZE, 0)
+
+#define PLAT_NODE_DATA(n)		(plat_node_data[(n)])
+#define PLAT_NODE_DATA_STARTNR(n)	\
+	(PLAT_NODE_DATA(n)->gendata.node_start_mapnr)
+#define PLAT_NODE_DATA_SIZE(n)		(PLAT_NODE_DATA(n)->gendata.node_size)
+#define PLAT_NODE_DATA_LOCALNR(pfn, n) \
+	((pfn) - PLAT_NODE_DATA(n)->gendata.node_start_pfn)
+
+/*
+ * Following are macros that each numa implmentation must define.
+ */
+
+/*
+ * Given a kernel address, find the home node of the underlying memory.
+ */
+#define KVADDR_TO_NID(kaddr)	PHYSADDR_TO_NID(__pa(kaddr))
+
+/*
+ * Return a pointer to the node data for node n.
+ */
+#define NODE_DATA(n)	(&((PLAT_NODE_DATA(n))->gendata))
+
+/*
+ * NODE_MEM_MAP gives the kaddr for the mem_map of the node.
+ */
+#define NODE_MEM_MAP(nid)	(NODE_DATA(nid)->node_mem_map)
+
+/*
+ * Given a kaddr, ADDR_TO_MAPBASE finds the owning node of the memory
+ * and returns the the mem_map of that node.
+ */
+#define ADDR_TO_MAPBASE(kaddr) \
+			NODE_MEM_MAP(KVADDR_TO_NID((unsigned long)(kaddr)))
+
+/*
+ * Given a kaddr, LOCAL_BASE_ADDR finds the owning node of the memory
+ * and returns the kaddr corresponding to first physical page in the
+ * node's mem_map.
+ */
+#define LOCAL_BASE_ADDR(kaddr)	((unsigned long)__va(NODE_DATA(KVADDR_TO_NID(kaddr))->node_start_pfn << PAGE_SHIFT))
+
+#define LOCAL_MAP_NR(kvaddr) \
+	(((unsigned long)(kvaddr)-LOCAL_BASE_ADDR(kvaddr)) >> PAGE_SHIFT)
+
+#define kern_addr_valid(kaddr)	test_bit(LOCAL_MAP_NR(kaddr), \
+					 NODE_DATA(KVADDR_TO_NID(kaddr))->valid_addr_bitmap)
+
+#define pfn_to_page(pfn)	(NODE_MEM_MAP(PFN_TO_NID(pfn)) + PLAT_NODE_DATA_LOCALNR(pfn, PFN_TO_NID(pfn)))
+#define page_to_pfn(page)	((page - page_zone(page)->zone_mem_map) + page_zone(page)->zone_start_pfn)
+#define pmd_page(pmd)		(pfn_to_page(pmd_val(pmd) >> PAGE_SHIFT))
+#endif /* CONFIG_DISCONTIGMEM */
+#endif /* _ASM_MMZONE_H_ */
diff -Nru a/include/asm-i386/numaq.h b/include/asm-i386/numaq.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/include/asm-i386/numaq.h	Mon Sep  9 10:36:18 2002
@@ -0,0 +1,179 @@
+/*
+ * Written by: Patricia Gaughen, IBM Corporation
+ *
+ * Copyright (C) 2002, IBM Corp.
+ *
+ * All rights reserved.          
+ *
+ * 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.
+ *
+ * This program 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, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Send feedback to <gone@us.ibm.com>
+ */
+
+#ifndef NUMAQ_H
+#define NUMAQ_H
+
+#ifdef CONFIG_X86_NUMAQ
+
+#include <asm/smpboot.h>
+
+/*
+ * for now assume that 64Gb is max amount of RAM for whole system
+ *    64Gb * 1024Mb/Gb = 65536 Mb
+ *    65536 Mb / 256Mb = 256
+ */
+#define MAX_ELEMENTS 256
+#define ELEMENT_REPRESENTS 8 /* 256 Mb */
+
+#define PHYSADDR_TO_NID(pa) numaqpa_to_nid(pa)
+#define PFN_TO_NID(pa) numaqpfn_to_nid(pa)
+#define MAX_NUMNODES		8
+#ifdef CONFIG_NUMA
+#define _cpu_to_node(cpu) (cpu_to_logical_apicid(cpu) >> 4)
+#endif /* CONFIG_NUMA */
+extern int numaqpa_to_nid(u64);
+extern int numaqpfn_to_nid(unsigned long);
+extern void get_memcfg_numaq(void);
+#define get_memcfg_numa() get_memcfg_numaq()
+
+/*
+ * SYS_CFG_DATA_PRIV_ADDR, struct eachquadmem, and struct sys_cfg_data are the
+ */
+#define SYS_CFG_DATA_PRIV_ADDR		0x0009d000 /* place for scd in private quad space */
+
+/*
+ * Communication area for each processor on lynxer-processor tests.
+ *
+ * NOTE: If you change the size of this eachproc structure you need
+ *       to change the definition for EACH_QUAD_SIZE.
+ */
+struct eachquadmem {
+	unsigned int	priv_mem_start;		/* Starting address of this */
+						/* quad's private memory. */
+						/* This is always 0. */
+						/* In MB. */
+	unsigned int	priv_mem_size;		/* Size of this quad's */
+						/* private memory. */
+						/* In MB. */
+	unsigned int	low_shrd_mem_strp_start;/* Starting address of this */
+						/* quad's low shared block */
+						/* (untranslated). */
+						/* In MB. */
+	unsigned int	low_shrd_mem_start;	/* Starting address of this */
+						/* quad's low shared memory */
+						/* (untranslated). */
+						/* In MB. */
+	unsigned int	low_shrd_mem_size;	/* Size of this quad's low */
+						/* shared memory. */
+						/* In MB. */
+	unsigned int	lmmio_copb_start;	/* Starting address of this */
+						/* quad's local memory */
+						/* mapped I/O in the */
+						/* compatibility OPB. */
+						/* In MB. */
+	unsigned int	lmmio_copb_size;	/* Size of this quad's local */
+						/* memory mapped I/O in the */
+						/* compatibility OPB. */
+						/* In MB. */
+	unsigned int	lmmio_nopb_start;	/* Starting address of this */
+						/* quad's local memory */
+						/* mapped I/O in the */
+						/* non-compatibility OPB. */
+						/* In MB. */
+	unsigned int	lmmio_nopb_size;	/* Size of this quad's local */
+						/* memory mapped I/O in the */
+						/* non-compatibility OPB. */
+						/* In MB. */
+	unsigned int	io_apic_0_start;	/* Starting address of I/O */
+						/* APIC 0. */
+	unsigned int	io_apic_0_sz;		/* Size I/O APIC 0. */
+	unsigned int	io_apic_1_start;	/* Starting address of I/O */
+						/* APIC 1. */
+	unsigned int	io_apic_1_sz;		/* Size I/O APIC 1. */
+	unsigned int	hi_shrd_mem_start;	/* Starting address of this */
+						/* quad's high shared memory.*/
+						/* In MB. */
+	unsigned int	hi_shrd_mem_size;	/* Size of this quad's high */
+						/* shared memory. */
+						/* In MB. */
+	unsigned int	mps_table_addr;		/* Address of this quad's */
+						/* MPS tables from BIOS, */
+						/* in system space.*/
+	unsigned int	lcl_MDC_pio_addr;	/* Port-I/O address for */
+						/* local access of MDC. */
+	unsigned int	rmt_MDC_mmpio_addr;	/* MM-Port-I/O address for */
+						/* remote access of MDC. */
+	unsigned int	mm_port_io_start;	/* Starting address of this */
+						/* quad's memory mapped Port */
+						/* I/O space. */
+	unsigned int	mm_port_io_size;	/* Size of this quad's memory*/
+						/* mapped Port I/O space. */
+	unsigned int	mm_rmt_io_apic_start;	/* Starting address of this */
+						/* quad's memory mapped */
+						/* remote I/O APIC space. */
+	unsigned int	mm_rmt_io_apic_size;	/* Size of this quad's memory*/
+						/* mapped remote I/O APIC */
+						/* space. */
+	unsigned int	mm_isa_start;		/* Starting address of this */
+						/* quad's memory mapped ISA */
+						/* space (contains MDC */
+						/* memory space). */
+	unsigned int	mm_isa_size;		/* Size of this quad's memory*/
+						/* mapped ISA space (contains*/
+						/* MDC memory space). */
+	unsigned int	rmt_qmi_addr;		/* Remote addr to access QMI.*/
+	unsigned int	lcl_qmi_addr;		/* Local addr to access QMI. */
+};
+
+/*
+ * Note: This structure must be NOT be changed unless the multiproc and
+ * OS are changed to reflect the new structure.
+ */
+struct sys_cfg_data {
+	unsigned int	quad_id;
+	unsigned int	bsp_proc_id; /* Boot Strap Processor in this quad. */
+	unsigned int	scd_version; /* Version number of this table. */
+	unsigned int	first_quad_id;
+	unsigned int	quads_present31_0; /* 1 bit for each quad */
+	unsigned int	quads_present63_32; /* 1 bit for each quad */
+	unsigned int	config_flags;
+	unsigned int	boot_flags;
+	unsigned int	csr_start_addr; /* Absolute value (not in MB) */
+	unsigned int	csr_size; /* Absolute value (not in MB) */
+	unsigned int	lcl_apic_start_addr; /* Absolute value (not in MB) */
+	unsigned int	lcl_apic_size; /* Absolute value (not in MB) */
+	unsigned int	low_shrd_mem_base; /* 0 or 512MB or 1GB */
+	unsigned int	low_shrd_mem_quad_offset; /* 0,128M,256M,512M,1G */
+					/* may not be totally populated */
+	unsigned int	split_mem_enbl; /* 0 for no low shared memory */ 
+	unsigned int	mmio_sz; /* Size of total system memory mapped I/O */
+				 /* (in MB). */
+	unsigned int	quad_spin_lock; /* Spare location used for quad */
+					/* bringup. */
+	unsigned int	nonzero55; /* For checksumming. */
+	unsigned int	nonzeroaa; /* For checksumming. */
+	unsigned int	scd_magic_number;
+	unsigned int	system_type;
+	unsigned int	checksum;
+	/*
+	 *	memory configuration area for each quad
+	 */
+        struct	eachquadmem eq[MAX_NUMNODES];	/* indexed by quad id */
+};
+
+#endif /* CONFIG_X86_NUMAQ */
+#endif /* NUMAQ_H */
+
diff -Nru a/include/asm-i386/page.h b/include/asm-i386/page.h
--- a/include/asm-i386/page.h	Mon Sep  9 10:36:01 2002
+++ b/include/asm-i386/page.h	Mon Sep  9 10:36:01 2002
@@ -134,8 +134,10 @@
 #define MAXMEM			((unsigned long)(-PAGE_OFFSET-VMALLOC_RESERVE))
 #define __pa(x)			((unsigned long)(x)-PAGE_OFFSET)
 #define __va(x)			((void *)((unsigned long)(x)+PAGE_OFFSET))
+#ifndef CONFIG_DISCONTIGMEM
 #define pfn_to_page(pfn)	(mem_map + (pfn))
 #define page_to_pfn(page)	((unsigned long)((page) - mem_map))
+#endif /* !CONFIG_DISCONTIGMEM */
 #define virt_to_page(kaddr)	pfn_to_page(__pa(kaddr) >> PAGE_SHIFT)
 
 #define pfn_valid(pfn)		((pfn) < max_mapnr)
diff -Nru a/include/asm-i386/pci.h b/include/asm-i386/pci.h
--- a/include/asm-i386/pci.h	Mon Sep  9 10:36:11 2002
+++ b/include/asm-i386/pci.h	Mon Sep  9 10:36:11 2002
@@ -107,7 +107,7 @@
 	if (direction == PCI_DMA_NONE)
 		BUG();
 
-	return (dma_addr_t)(page - mem_map) * PAGE_SIZE + offset;
+	return (dma_addr_t)(page_to_pfn(page)) * PAGE_SIZE + offset;
 }
 
 static inline void pci_unmap_page(struct pci_dev *hwdev, dma_addr_t dma_address,
@@ -236,9 +236,7 @@
 static __inline__ struct page *
 pci_dac_dma_to_page(struct pci_dev *pdev, dma64_addr_t dma_addr)
 {
-	unsigned long poff = (dma_addr >> PAGE_SHIFT);
-
-	return mem_map + poff;
+	return pfn_to_page(dma_addr >> PAGE_SHIFT);
 }
 
 static __inline__ unsigned long
diff -Nru a/include/asm-i386/pgalloc.h b/include/asm-i386/pgalloc.h
--- a/include/asm-i386/pgalloc.h	Mon Sep  9 10:35:56 2002
+++ b/include/asm-i386/pgalloc.h	Mon Sep  9 10:35:56 2002
@@ -13,7 +13,7 @@
 static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmd, struct page *pte)
 {
 	set_pmd(pmd, __pmd(_PAGE_TABLE +
-		((unsigned long long)(pte - mem_map) <<
+		((unsigned long long)page_to_pfn(pte) <<
 			(unsigned long long) PAGE_SHIFT)));
 }
 /*
diff -Nru a/include/asm-i386/pgtable.h b/include/asm-i386/pgtable.h
--- a/include/asm-i386/pgtable.h	Mon Sep  9 10:36:13 2002
+++ b/include/asm-i386/pgtable.h	Mon Sep  9 10:36:13 2002
@@ -234,8 +234,9 @@
 #define pmd_page_kernel(pmd) \
 ((unsigned long) __va(pmd_val(pmd) & PAGE_MASK))
 
-#define pmd_page(pmd) \
-	(mem_map + (pmd_val(pmd) >> PAGE_SHIFT))
+#ifndef CONFIG_DISCONTIGMEM
+#define pmd_page(pmd) (pfn_to_page(pmd_val(pmd) >> PAGE_SHIFT))
+#endif /* !CONFIG_DISCONTIGMEM */
 
 #define pmd_large(pmd) \
 	((pmd_val(pmd) & (_PAGE_PSE|_PAGE_PRESENT)) == (_PAGE_PSE|_PAGE_PRESENT))
@@ -280,7 +281,9 @@
 
 #endif /* !__ASSEMBLY__ */
 
+#ifndef CONFIG_DISCONTIGMEM
 #define kern_addr_valid(addr)	(1)
+#endif /* !CONFIG_DISCONTIGMEM */
 
 #define io_remap_page_range remap_page_range
 
diff -Nru a/include/asm-i386/setup.h b/include/asm-i386/setup.h
--- a/include/asm-i386/setup.h	Mon Sep  9 10:36:12 2002
+++ b/include/asm-i386/setup.h	Mon Sep  9 10:36:12 2002
@@ -6,5 +6,38 @@
 #ifndef _i386_SETUP_H
 #define _i386_SETUP_H
 
+#define PFN_UP(x)	(((x) + PAGE_SIZE-1) >> PAGE_SHIFT)
+#define PFN_DOWN(x)	((x) >> PAGE_SHIFT)
+#define PFN_PHYS(x)	((x) << PAGE_SHIFT)
+
+/*
+ * Reserved space for vmalloc and iomap - defined in asm/page.h
+ */
+#define MAXMEM_PFN	PFN_DOWN(MAXMEM)
+#define MAX_NONPAE_PFN	(1 << 20)
+
+/*
+ * This is set up by the setup-routine at boot-time
+ */
+#define PARAM	((unsigned char *)empty_zero_page)
+#define SCREEN_INFO (*(struct screen_info *) (PARAM+0))
+#define EXT_MEM_K (*(unsigned short *) (PARAM+2))
+#define ALT_MEM_K (*(unsigned long *) (PARAM+0x1e0))
+#define E820_MAP_NR (*(char*) (PARAM+E820NR))
+#define E820_MAP    ((struct e820entry *) (PARAM+E820MAP))
+#define APM_BIOS_INFO (*(struct apm_bios_info *) (PARAM+0x40))
+#define DRIVE_INFO (*(struct drive_info_struct *) (PARAM+0x80))
+#define SYS_DESC_TABLE (*(struct sys_desc_table_struct*)(PARAM+0xa0))
+#define MOUNT_ROOT_RDONLY (*(unsigned short *) (PARAM+0x1F2))
+#define RAMDISK_FLAGS (*(unsigned short *) (PARAM+0x1F8))
+#define VIDEO_MODE (*(unsigned short *) (PARAM+0x1FA))
+#define ORIG_ROOT_DEV (*(unsigned short *) (PARAM+0x1FC))
+#define AUX_DEVICE_INFO (*(unsigned char *) (PARAM+0x1FF))
+#define LOADER_TYPE (*(unsigned char *) (PARAM+0x210))
+#define KERNEL_START (*(unsigned long *) (PARAM+0x214))
+#define INITRD_START (*(unsigned long *) (PARAM+0x218))
+#define INITRD_SIZE (*(unsigned long *) (PARAM+0x21c))
+#define COMMAND_LINE ((char *) (PARAM+2048))
+#define COMMAND_LINE_SIZE 256
 
 #endif /* _i386_SETUP_H */
diff -Nru a/include/asm-i386/spinlock.h b/include/asm-i386/spinlock.h
--- a/include/asm-i386/spinlock.h	Mon Sep  9 10:36:01 2002
+++ b/include/asm-i386/spinlock.h	Mon Sep  9 10:36:01 2002
@@ -158,6 +158,8 @@
 
 #define rwlock_init(x)	do { *(x) = RW_LOCK_UNLOCKED; } while(0)
 
+#define rwlock_is_locked(x) ((x)->lock != RW_LOCK_BIAS)
+
 /*
  * On x86, we implement read-write locks as a 32-bit counter
  * with the high bit (sign) being the "contended" bit.
diff -Nru a/include/asm-i386/tlbflush.h b/include/asm-i386/tlbflush.h
--- a/include/asm-i386/tlbflush.h	Mon Sep  9 10:36:11 2002
+++ b/include/asm-i386/tlbflush.h	Mon Sep  9 10:36:11 2002
@@ -45,11 +45,21 @@
 			__flush_tlb();					\
 	} while (0)
 
-#ifndef CONFIG_X86_INVLPG
-#define __flush_tlb_one(addr) __flush_tlb()
+#define cpu_has_invlpg	(boot_cpu_data.x86 > 3)
+
+#define __flush_tlb_single(addr) \
+	__asm__ __volatile__("invlpg %0": :"m" (*(char *) addr))
+
+#ifdef CONFIG_X86_INVLPG
+# define __flush_tlb_one(addr) __flush_tlb_single(addr)
 #else
-#define __flush_tlb_one(addr) \
-__asm__ __volatile__("invlpg %0": :"m" (*(char *) addr))
+# define __flush_tlb_one(addr)						\
+	do {								\
+		if (cpu_has_invlpg)					\
+			__flush_tlb_single(addr);			\
+		else							\
+			__flush_tlb();					\
+	} while (0)
 #endif
 
 /*
diff -Nru a/include/asm-mips64/mmzone.h b/include/asm-mips64/mmzone.h
--- a/include/asm-mips64/mmzone.h	Mon Sep  9 10:35:56 2002
+++ b/include/asm-mips64/mmzone.h	Mon Sep  9 10:35:56 2002
@@ -27,7 +27,7 @@
 #define PLAT_NODE_DATA_STARTNR(n)    (PLAT_NODE_DATA(n)->gendata.node_start_mapnr)
 #define PLAT_NODE_DATA_SIZE(n)	     (PLAT_NODE_DATA(n)->gendata.node_size)
 #define PLAT_NODE_DATA_LOCALNR(p, n) \
-		(((p) - PLAT_NODE_DATA(n)->gendata.node_start_paddr) >> PAGE_SHIFT)
+		(((p) >> PAGE_SHIFT) - PLAT_NODE_DATA(n)->gendata.node_start_pfn)
 
 #define numa_node_id()	cputocnode(current->processor)
 
diff -Nru a/include/asm-mips64/pgtable.h b/include/asm-mips64/pgtable.h
--- a/include/asm-mips64/pgtable.h	Mon Sep  9 10:36:17 2002
+++ b/include/asm-mips64/pgtable.h	Mon Sep  9 10:36:17 2002
@@ -484,8 +484,8 @@
 #define PAGE_TO_PA(page)	((page - mem_map) << PAGE_SHIFT)
 #else
 #define PAGE_TO_PA(page) \
-		((((page)-(page)->zone->zone_mem_map) << PAGE_SHIFT) \
-		+ ((page)->zone->zone_start_paddr))
+		(( ((page)-(page)->zone->zone_mem_map) + \
+		   (page)->zone->zone_start_pfn) << PAGE_SHIFT)
 #endif
 #define mk_pte(page, pgprot)						\
 ({									\
diff -Nru a/include/asm-ppc/elf.h b/include/asm-ppc/elf.h
--- a/include/asm-ppc/elf.h	Mon Sep  9 10:35:49 2002
+++ b/include/asm-ppc/elf.h	Mon Sep  9 10:35:49 2002
@@ -1,5 +1,5 @@
 /*
- * BK Id: SCCS/s.elf.h 1.14 08/21/01 16:07:48 trini
+ * BK Id: %F% %I% %G% %U% %#%
  */
 #ifndef __PPC_ELF_H
 #define __PPC_ELF_H
@@ -100,12 +100,13 @@
  */
 #define ARCH_DLINFO							\
 do {									\
+	/* Handle glibc compatibility. */				\
+	NEW_AUX_ENT(AT_IGNOREPPC, AT_IGNOREPPC);			\
+	NEW_AUX_ENT(AT_IGNOREPPC, AT_IGNOREPPC);			\
+	/* Cache size items */						\
 	NEW_AUX_ENT(AT_DCACHEBSIZE, dcache_bsize);			\
 	NEW_AUX_ENT(AT_ICACHEBSIZE, icache_bsize);			\
 	NEW_AUX_ENT(AT_UCACHEBSIZE, ucache_bsize);			\
-	/* Now handle glibc compatibility. */				\
-	NEW_AUX_ENT(AT_IGNOREPPC, AT_IGNOREPPC);			\
-	NEW_AUX_ENT(AT_IGNOREPPC, AT_IGNOREPPC);			\
  } while (0)
 
 #endif /* __KERNEL__ */
diff -Nru a/include/asm-ppc/hardirq.h b/include/asm-ppc/hardirq.h
--- a/include/asm-ppc/hardirq.h	Mon Sep  9 10:35:49 2002
+++ b/include/asm-ppc/hardirq.h	Mon Sep  9 10:35:49 2002
@@ -35,8 +35,8 @@
  * - ( bit 26 is the PREEMPT_ACTIVE flag. )
  *
  * PREEMPT_MASK: 0x000000ff
- * HARDIRQ_MASK: 0x0000ff00
- * SOFTIRQ_MASK: 0x00ff0000
+ * SOFTIRQ_MASK: 0x0000ff00
+ * HARDIRQ_MASK: 0x00ff0000
  */
 
 #define PREEMPT_BITS	8
@@ -85,8 +85,10 @@
 #define irq_enter()		(preempt_count() += HARDIRQ_OFFSET)
 
 #if CONFIG_PREEMPT
+# define in_atomic()	(preempt_count() != kernel_locked())
 # define IRQ_EXIT_OFFSET (HARDIRQ_OFFSET-1)
 #else
+# define in_atomic()	(preempt_count() != 0)
 # define IRQ_EXIT_OFFSET HARDIRQ_OFFSET
 #endif
 #define irq_exit()							\
diff -Nru a/include/asm-ppc/highmem.h b/include/asm-ppc/highmem.h
--- a/include/asm-ppc/highmem.h	Mon Sep  9 10:36:11 2002
+++ b/include/asm-ppc/highmem.h	Mon Sep  9 10:36:11 2002
@@ -88,6 +88,7 @@
 	unsigned int idx;
 	unsigned long vaddr;
 
+	inc_preempt_count();
 	if (page < highmem_start_page)
 		return page_address(page);
 
@@ -109,8 +110,10 @@
 	unsigned long vaddr = (unsigned long) kvaddr & PAGE_MASK;
 	unsigned int idx = type + KM_TYPE_NR*smp_processor_id();
 
-	if (vaddr < KMAP_FIX_BEGIN) // FIXME
+	if (vaddr < KMAP_FIX_BEGIN) { // FIXME
+		dec_preempt_count();
 		return;
+	}
 
 	if (vaddr != KMAP_FIX_BEGIN + idx * PAGE_SIZE)
 		BUG();
@@ -122,6 +125,7 @@
 	pte_clear(kmap_pte+idx);
 	flush_tlb_page(0, vaddr);
 #endif
+	dec_preempt_count();
 }
 
 #endif /* __KERNEL__ */
diff -Nru a/include/asm-ppc/io.h b/include/asm-ppc/io.h
--- a/include/asm-ppc/io.h	Mon Sep  9 10:36:01 2002
+++ b/include/asm-ppc/io.h	Mon Sep  9 10:36:01 2002
@@ -295,7 +295,7 @@
 /*
  * Change "struct page" to physical address.
  */
-#define page_to_phys(page)	((page - mem_map) << PAGE_SHIFT)
+#define page_to_phys(page)	(page_to_pfn(page) << PAGE_SHIFT)
 #define page_to_bus(page)	(page_to_phys(page) + PCI_DRAM_OFFSET)
 
 #endif /* __KERNEL__ */
diff -Nru a/include/asm-ppc/pci-bridge.h b/include/asm-ppc/pci-bridge.h
--- a/include/asm-ppc/pci-bridge.h	Mon Sep  9 10:35:56 2002
+++ b/include/asm-ppc/pci-bridge.h	Mon Sep  9 10:35:56 2002
@@ -31,6 +31,7 @@
  */
 extern int pci_device_from_OF_node(struct device_node *node,
 				   u8* bus, u8* devfn);
+extern struct device_node* pci_busdev_to_OF_node(struct pci_bus *, int);
 extern struct device_node* pci_device_to_OF_node(struct pci_dev *);
 extern void pci_create_OF_bus_map(void);
 
diff -Nru a/include/asm-ppc/pgalloc.h b/include/asm-ppc/pgalloc.h
--- a/include/asm-ppc/pgalloc.h	Mon Sep  9 10:35:47 2002
+++ b/include/asm-ppc/pgalloc.h	Mon Sep  9 10:35:47 2002
@@ -26,7 +26,7 @@
 #define pmd_populate_kernel(mm, pmd, pte)	\
 		(pmd_val(*(pmd)) = __pa(pte))
 #define pmd_populate(mm, pmd, pte)	\
-		(pmd_val(*(pmd)) = ((pte) - mem_map) << PAGE_SHIFT)
+		(pmd_val(*(pmd)) = (page_to_pfn(pte) << PAGE_SHIFT))
 
 extern pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long addr);
 extern struct page *pte_alloc_one(struct mm_struct *mm, unsigned long addr);
diff -Nru a/include/asm-ppc/semaphore.h b/include/asm-ppc/semaphore.h
--- a/include/asm-ppc/semaphore.h	Mon Sep  9 10:36:11 2002
+++ b/include/asm-ppc/semaphore.h	Mon Sep  9 10:36:11 2002
@@ -1,5 +1,5 @@
 /*
- * BK Id: SCCS/s.semaphore.h 1.15 05/17/01 18:14:25 cort
+ * BK Id: %F% %I% %G% %U% %#%
  */
 #ifndef _PPC_SEMAPHORE_H
 #define _PPC_SEMAPHORE_H
@@ -12,7 +12,7 @@
  * -- Ani Joshi (ajoshi@unixbox.com)
  *
  * Remove spinlock-based RW semaphores; RW semaphore definitions are
- * now in rwsem.h and we use the the generic lib/rwsem.c implementation.
+ * now in rwsem.h and we use the generic lib/rwsem.c implementation.
  * Rework semaphores to use atomic_dec_if_positive.
  * -- Paul Mackerras (paulus@samba.org)
  */
diff -Nru a/include/asm-ppc64/mmzone.h b/include/asm-ppc64/mmzone.h
--- a/include/asm-ppc64/mmzone.h	Mon Sep  9 10:36:17 2002
+++ b/include/asm-ppc64/mmzone.h	Mon Sep  9 10:36:17 2002
@@ -31,7 +31,7 @@
 	(PLAT_NODE_DATA(n)->gendata.node_start_mapnr)
 #define PLAT_NODE_DATA_SIZE(n)		(PLAT_NODE_DATA(n)->gendata.node_size)
 #define PLAT_NODE_DATA_LOCALNR(p, n)	\
-	(((p) - PLAT_NODE_DATA(n)->gendata.node_start_paddr) >> PAGE_SHIFT)
+	(((p) >> PAGE_SHIFT) - PLAT_NODE_DATA(n)->gendata.node_start_pfn)
 
 #ifdef CONFIG_DISCONTIGMEM
 
@@ -67,7 +67,7 @@
  * node's mem_map.
  */
 #define LOCAL_BASE_ADDR(kaddr) \
-	((unsigned long)__va(NODE_DATA(KVADDR_TO_NID(kaddr))->node_start_paddr))
+	((unsigned long)__va(NODE_DATA(KVADDR_TO_NID(kaddr))->node_start_pfn << PAGE_SHIFT))
 
 #define LOCAL_MAP_NR(kvaddr) \
 	(((unsigned long)(kvaddr)-LOCAL_BASE_ADDR(kvaddr)) >> PAGE_SHIFT)
diff -Nru a/include/asm-ppc64/page.h b/include/asm-ppc64/page.h
--- a/include/asm-ppc64/page.h	Mon Sep  9 10:35:51 2002
+++ b/include/asm-ppc64/page.h	Mon Sep  9 10:35:51 2002
@@ -207,7 +207,7 @@
 #ifdef CONFIG_DISCONTIGMEM
 #define page_to_pfn(page) \
 		((page) - page_zone(page)->zone_mem_map + \
-		(page_zone(page)->zone_start_paddr >> PAGE_SHIFT))
+		(page_zone(page)->zone_start_pfn))
 #define pfn_to_page(pfn)	discontigmem_pfn_to_page(pfn)
 #else
 #define pfn_to_page(pfn)	(mem_map + (pfn))
diff -Nru a/include/asm-sparc/hardirq.h b/include/asm-sparc/hardirq.h
--- a/include/asm-sparc/hardirq.h	Mon Sep  9 10:36:18 2002
+++ b/include/asm-sparc/hardirq.h	Mon Sep  9 10:36:18 2002
@@ -113,6 +113,12 @@
 #define irq_exit()		br_read_unlock(BR_GLOBALIRQ_LOCK)
 #endif
 
+#if CONFIG_PREEMPT
+# define in_atomic()	(preempt_count() != kernel_locked())
+#else
+# define in_atomic()	(preempt_count() != 0)
+#endif
+
 #ifndef CONFIG_SMP
 
 #define synchronize_irq()	barrier()
diff -Nru a/include/asm-sparc/highmem.h b/include/asm-sparc/highmem.h
--- a/include/asm-sparc/highmem.h	Mon Sep  9 10:36:17 2002
+++ b/include/asm-sparc/highmem.h	Mon Sep  9 10:36:18 2002
@@ -83,6 +83,7 @@
 	unsigned long idx;
 	unsigned long vaddr;
 
+	inc_preempt_count();
 	if (page < highmem_start_page)
 		return page_address(page);
 
@@ -116,8 +117,10 @@
 	unsigned long vaddr = (unsigned long) kvaddr;
 	unsigned long idx = type + KM_TYPE_NR*smp_processor_id();
 
-	if (vaddr < FIX_KMAP_BEGIN) // FIXME
+	if (vaddr < FIX_KMAP_BEGIN) { // FIXME
+		dec_preempt_count();
 		return;
+	}
 
 	if (vaddr != FIX_KMAP_BEGIN + idx * PAGE_SIZE)
 		BUG();
@@ -142,6 +145,7 @@
 	flush_tlb_all();
 #endif
 #endif
+	dec_preempt_count();
 }
 
 #endif /* __KERNEL__ */
diff -Nru a/include/asm-sparc64/hardirq.h b/include/asm-sparc64/hardirq.h
--- a/include/asm-sparc64/hardirq.h	Mon Sep  9 10:36:01 2002
+++ b/include/asm-sparc64/hardirq.h	Mon Sep  9 10:36:01 2002
@@ -35,8 +35,8 @@
  * - ( bit 26 is the PREEMPT_ACTIVE flag. )
  *
  * PREEMPT_MASK: 0x000000ff
- * HARDIRQ_MASK: 0x0000ff00
- * SOFTIRQ_MASK: 0x00ff0000
+ * SOFTIRQ_MASK: 0x0000ff00
+ * HARDIRQ_MASK: 0x00ff0000
  */
 
 #define PREEMPT_BITS	8
diff -Nru a/include/linux/blkdev.h b/include/linux/blkdev.h
--- a/include/linux/blkdev.h	Mon Sep  9 10:36:01 2002
+++ b/include/linux/blkdev.h	Mon Sep  9 10:36:01 2002
@@ -281,10 +281,7 @@
 
 extern struct sec_size * blk_sec[MAX_BLKDEV];
 extern struct blk_dev_struct blk_dev[MAX_BLKDEV];
-extern void grok_partitions(kdev_t dev, long size);
-extern int wipe_partitions(kdev_t dev);
 extern void register_disk(struct gendisk *dev, kdev_t first, unsigned minors, struct block_device_operations *ops, long size);
-extern void check_partition(struct gendisk *disk, struct block_device *bdev);
 extern void generic_make_request(struct bio *bio);
 extern inline request_queue_t *bdev_get_queue(struct block_device *bdev);
 extern void blk_put_request(struct request *);
diff -Nru a/include/linux/bootmem.h b/include/linux/bootmem.h
--- a/include/linux/bootmem.h	Mon Sep  9 10:36:13 2002
+++ b/include/linux/bootmem.h	Mon Sep  9 10:36:13 2002
@@ -36,9 +36,10 @@
 
 extern unsigned long __init bootmem_bootmap_pages (unsigned long);
 extern unsigned long __init init_bootmem (unsigned long addr, unsigned long memend);
-extern void __init reserve_bootmem (unsigned long addr, unsigned long size);
 extern void __init free_bootmem (unsigned long addr, unsigned long size);
 extern void * __init __alloc_bootmem (unsigned long size, unsigned long align, unsigned long goal);
+#ifndef CONFIG_HAVE_ARCH_BOOTMEM_NODE
+extern void __init reserve_bootmem (unsigned long addr, unsigned long size);
 #define alloc_bootmem(x) \
 	__alloc_bootmem((x), SMP_CACHE_BYTES, __pa(MAX_DMA_ADDRESS))
 #define alloc_bootmem_low(x) \
@@ -47,6 +48,7 @@
 	__alloc_bootmem((x), PAGE_SIZE, __pa(MAX_DMA_ADDRESS))
 #define alloc_bootmem_low_pages(x) \
 	__alloc_bootmem((x), PAGE_SIZE, 0)
+#endif /* !CONFIG_HAVE_ARCH_BOOTMEM_NODE */
 extern unsigned long __init free_all_bootmem (void);
 
 extern unsigned long __init init_bootmem_node (pg_data_t *pgdat, unsigned long freepfn, unsigned long startpfn, unsigned long endpfn);
@@ -54,11 +56,13 @@
 extern void __init free_bootmem_node (pg_data_t *pgdat, unsigned long addr, unsigned long size);
 extern unsigned long __init free_all_bootmem_node (pg_data_t *pgdat);
 extern void * __init __alloc_bootmem_node (pg_data_t *pgdat, unsigned long size, unsigned long align, unsigned long goal);
+#ifndef CONFIG_HAVE_ARCH_BOOTMEM_NODE
 #define alloc_bootmem_node(pgdat, x) \
 	__alloc_bootmem_node((pgdat), (x), SMP_CACHE_BYTES, __pa(MAX_DMA_ADDRESS))
 #define alloc_bootmem_pages_node(pgdat, x) \
 	__alloc_bootmem_node((pgdat), (x), PAGE_SIZE, __pa(MAX_DMA_ADDRESS))
 #define alloc_bootmem_low_pages_node(pgdat, x) \
 	__alloc_bootmem_node((pgdat), (x), PAGE_SIZE, 0)
+#endif /* !CONFIG_HAVE_ARCH_BOOTMEM_NODE */
 
 #endif /* _LINUX_BOOTMEM_H */
diff -Nru a/include/linux/compiler.h b/include/linux/compiler.h
--- a/include/linux/compiler.h	Mon Sep  9 10:35:56 2002
+++ b/include/linux/compiler.h	Mon Sep  9 10:35:56 2002
@@ -16,7 +16,7 @@
 /* This macro obfuscates arithmetic on a variable address so that gcc
    shouldn't recognize the original var, and make assumptions about it */
 #define RELOC_HIDE(ptr, off)					\
-  ({ __typeof__(ptr) __ptr;					\
-    __asm__ ("" : "=g"(__ptr) : "0"((void *)(ptr) + (off)));	\
-    __ptr; })
+  ({ unsigned long __ptr;					\
+    __asm__ ("" : "=g"(__ptr) : "0"(ptr));		\
+    (typeof(ptr)) (__ptr + (off)); })
 #endif /* __LINUX_COMPILER_H */
diff -Nru a/include/linux/device.h b/include/linux/device.h
--- a/include/linux/device.h	Mon Sep  9 10:36:05 2002
+++ b/include/linux/device.h	Mon Sep  9 10:36:05 2002
@@ -57,9 +57,9 @@
 	rwlock_t		lock;
 	atomic_t		refcount;
 
-	list_t			node;
-	list_t			devices;
-	list_t			drivers;
+	struct list_head	node;
+	struct list_head	devices;
+	struct list_head	drivers;
 
 	struct driver_dir_entry	dir;
 	struct driver_dir_entry	device_dir;
diff -Nru a/include/linux/fs.h b/include/linux/fs.h
--- a/include/linux/fs.h	Mon Sep  9 10:36:01 2002
+++ b/include/linux/fs.h	Mon Sep  9 10:36:01 2002
@@ -322,8 +322,8 @@
 	struct list_head	io_pages;	/* being prepared for I/O */
 	unsigned long		nrpages;	/* number of total pages */
 	struct address_space_operations *a_ops;	/* methods */
-	list_t			i_mmap;		/* list of private mappings */
-	list_t			i_mmap_shared;	/* list of private mappings */
+	struct list_head	i_mmap;		/* list of private mappings */
+	struct list_head	i_mmap_shared;	/* list of private mappings */
 	spinlock_t		i_shared_lock;  /* and spinlock protecting it */
 	unsigned long		dirtied_when;	/* jiffies of first page dirtying */
 	int			gfp_mask;	/* how to allocate the pages */
@@ -368,7 +368,7 @@
 	atomic_t		i_count;
 	dev_t			i_dev;
 	umode_t			i_mode;
-	nlink_t			i_nlink;
+	unsigned int		i_nlink;
 	uid_t			i_uid;
 	gid_t			i_gid;
 	kdev_t			i_rdev;
@@ -432,6 +432,7 @@
 #include <linux/efs_fs_i.h>
 
 struct fown_struct {
+	rwlock_t lock;          /* protects pid, uid, euid fields */
 	int pid;		/* pid or -pgrp where SIGIO should be sent */
 	uid_t uid, euid;	/* uid/euid of process setting the owner */
 	int signum;		/* posix.1b rt signal to be delivered on IO */
@@ -614,6 +615,10 @@
 extern void kill_fasync(struct fasync_struct **, int, int);
 /* only for net: no internal synchronization */
 extern void __kill_fasync(struct fasync_struct *, int, int);
+
+extern int f_setown(struct file *filp, unsigned long arg, int force);
+extern void f_delown(struct file *filp);
+extern int send_sigurg(struct fown_struct *fown);
 
 /*
  *	Umount options
diff -Nru a/include/linux/genhd.h b/include/linux/genhd.h
--- a/include/linux/genhd.h	Mon Sep  9 10:36:01 2002
+++ b/include/linux/genhd.h	Mon Sep  9 10:36:01 2002
@@ -62,11 +62,12 @@
 	unsigned long start_sect;
 	unsigned long nr_sects;
 	devfs_handle_t de;              /* primary (master) devfs entry  */
-	int number;                     /* stupid old code wastes space  */
 	struct device hd_driverfs_dev;  /* support driverfs hiearchy     */
 };
 
 #define GENHD_FL_REMOVABLE  1
+#define GENHD_FL_DRIVERFS  2
+#define GENHD_FL_DEVFS	4
 
 struct gendisk {
 	int major;			/* major number of driver */
@@ -76,24 +77,35 @@
 					   get real minor */
 
 	struct hd_struct *part;		/* [indexed by minor] */
-	int nr_real;			/* number of real devices */
-
 	struct gendisk *next;
 	struct block_device_operations *fops;
+	sector_t capacity;
 
-	devfs_handle_t *de_arr;         /* one per physical disc */
-	struct device **driverfs_dev_arr;/* support driverfs hierarchy */
-	char *flags;                    /* one per physical disc */
+	int flags;
+	int number;			/* devfs crap */
+	devfs_handle_t de;		/* more of the same */
+	devfs_handle_t disk_de;		/* piled higher and deeper */
+	struct device *driverfs_dev;
+	struct device disk_dev;
 };
 
 /* drivers/block/genhd.c */
 extern void add_gendisk(struct gendisk *gp);
 extern void del_gendisk(struct gendisk *gp);
+extern void unlink_gendisk(struct gendisk *gp);
 extern struct gendisk *get_gendisk(kdev_t dev);
 static inline unsigned long get_start_sect(struct block_device *bdev)
 {
 	return bdev->bd_offset;
 }
+static inline sector_t get_capacity(struct gendisk *disk)
+{
+	return disk->capacity;
+}
+static inline void set_capacity(struct gendisk *disk, sector_t size)
+{
+	disk->capacity = size;
+}
 
 #endif  /*  __KERNEL__  */
 
@@ -242,11 +254,10 @@
 
 #ifdef __KERNEL__
 
-char *disk_name (struct gendisk *hd, int minor, char *buf);
+char *disk_name (struct gendisk *hd, int part, char *buf);
 
-extern void devfs_register_partitions (struct gendisk *dev, int minor,
-				       int unregister);
-extern void driverfs_remove_partitions (struct gendisk *hd, int minor);
+extern int rescan_partitions(struct gendisk *disk, struct block_device *bdev);
+extern void update_partition(struct gendisk *disk, int part);
 
 static inline unsigned int disk_index (kdev_t dev)
 {
diff -Nru a/include/linux/highmem.h b/include/linux/highmem.h
--- a/include/linux/highmem.h	Mon Sep  9 10:36:01 2002
+++ b/include/linux/highmem.h	Mon Sep  9 10:36:01 2002
@@ -24,8 +24,8 @@
 
 #define kunmap(page) do { (void) (page); } while (0)
 
-#define kmap_atomic(page,idx)		kmap(page)
-#define kunmap_atomic(page,idx)		kunmap(page)
+#define kmap_atomic(page, idx)		page_address(page)
+#define kunmap_atomic(addr, idx)	do { } while (0)
 
 #endif /* CONFIG_HIGHMEM */
 
diff -Nru a/include/linux/ide.h b/include/linux/ide.h
--- a/include/linux/ide.h	Mon Sep  9 10:36:11 2002
+++ b/include/linux/ide.h	Mon Sep  9 10:36:11 2002
@@ -464,7 +464,6 @@
 	byte     nice1;			/* flag: give potential excess bandwidth */
 	unsigned present	: 1;	/* drive is physically present */
 	unsigned noprobe 	: 1;	/* from:  hdx=noprobe */
-	unsigned busy		: 1;	/* currently doing revalidate_disk() */
 	unsigned removable	: 1;	/* 1 if need to do check_media_change */
 	unsigned forced_geom	: 1;	/* 1 if hdx=c,h,s was given at boot */
 	unsigned no_unmask	: 1;	/* disallow setting unmask bit */
@@ -506,9 +505,7 @@
 	unsigned long long capacity48;	/* total number of sectors */
 	unsigned int	drive_data;	/* for use by tuneproc/selectproc as needed */
 	struct hwif_s	  *hwif;	/* actually (ide_hwif_t *) */
-	wait_queue_head_t wqueue;	/* used to wait for drive in open() */
 	struct hd_driveid *id;		/* drive model identification info */
-	struct hd_struct  *part;	/* drive partition table */
 	char		name[4];	/* drive name, such as "hda" */
 	struct ide_driver_s *driver;	/* (ide_driver_t *) */
 	void		*driver_data;	/* extra driver data */
@@ -530,6 +527,7 @@
 	unsigned int	failures;	/* current failure count */
 	unsigned int	max_failures;	/* maximum allowed failure count */
 	struct list_head list;
+	struct gendisk *disk;
 } ide_drive_t;
 
 /*
@@ -716,7 +714,6 @@
  */
 	hw_regs_t	hw;		/* Hardware info */
 	ide_drive_t	drives[MAX_DRIVES];	/* drive info */
-	struct gendisk	*gd[MAX_DRIVES];/* gendisk structure */
 	int		addressing;	/* hosts addressing */
 	void		(*tuneproc)(ide_drive_t *, byte);	/* routine to tune PIO mode for drives */
 	int		(*speedproc)(ide_drive_t *, byte);	/* routine to retune DMA modes for drives */
diff -Nru a/include/linux/igmp.h b/include/linux/igmp.h
--- a/include/linux/igmp.h	Mon Sep  9 10:36:11 2002
+++ b/include/linux/igmp.h	Mon Sep  9 10:36:11 2002
@@ -115,7 +115,7 @@
 extern void ip_mc_destroy_dev(struct in_device *);
 extern void ip_mc_up(struct in_device *);
 extern void ip_mc_down(struct in_device *);
-extern int ip_mc_dec_group(struct in_device *in_dev, u32 addr);
+extern void ip_mc_dec_group(struct in_device *in_dev, u32 addr);
 extern void ip_mc_inc_group(struct in_device *in_dev, u32 addr);
 #endif
 #endif
diff -Nru a/include/linux/init_task.h b/include/linux/init_task.h
--- a/include/linux/init_task.h	Mon Sep  9 10:35:56 2002
+++ b/include/linux/init_task.h	Mon Sep  9 10:35:56 2002
@@ -29,10 +29,11 @@
 	.mmlist		= LIST_HEAD_INIT(name.mmlist),	\
 }
 
-#define INIT_SIGNALS {	\
+#define INIT_SIGNALS(sig) {	\
 	.count		= ATOMIC_INIT(1), 		\
 	.action		= { {{0,}}, }, 			\
-	.siglock	= SPIN_LOCK_UNLOCKED 		\
+	.siglock	= SPIN_LOCK_UNLOCKED, 		\
+	.shared_pending	= { NULL, &sig.shared_pending.head, {{0}}}, \
 }
 
 /*
diff -Nru a/include/linux/list.h b/include/linux/list.h
--- a/include/linux/list.h	Mon Sep  9 10:35:51 2002
+++ b/include/linux/list.h	Mon Sep  9 10:35:51 2002
@@ -19,12 +19,10 @@
 	struct list_head *next, *prev;
 };
 
-typedef struct list_head list_t;
-
 #define LIST_HEAD_INIT(name) { &(name), &(name) }
 
 #define LIST_HEAD(name) \
-	list_t name = LIST_HEAD_INIT(name)
+	struct list_head name = LIST_HEAD_INIT(name)
 
 #define INIT_LIST_HEAD(ptr) do { \
 	(ptr)->next = (ptr); (ptr)->prev = (ptr); \
@@ -36,7 +34,9 @@
  * This is only for internal list manipulation where we know
  * the prev/next entries already!
  */
-static inline void __list_add(list_t *new, list_t *prev, list_t *next)
+static inline void __list_add(struct list_head *new,
+			      struct list_head *prev,
+			      struct list_head *next)
 {
 	next->prev = new;
 	new->next = next;
@@ -52,7 +52,7 @@
  * Insert a new entry after the specified head.
  * This is good for implementing stacks.
  */
-static inline void list_add(list_t *new, list_t *head)
+static inline void list_add(struct list_head *new, struct list_head *head)
 {
 	__list_add(new, head, head->next);
 }
@@ -65,7 +65,7 @@
  * Insert a new entry before the specified head.
  * This is useful for implementing queues.
  */
-static inline void list_add_tail(list_t *new, list_t *head)
+static inline void list_add_tail(struct list_head *new, struct list_head *head)
 {
 	__list_add(new, head->prev, head);
 }
@@ -77,7 +77,7 @@
  * This is only for internal list manipulation where we know
  * the prev/next entries already!
  */
-static inline void __list_del(list_t * prev, list_t * next)
+static inline void __list_del(struct list_head * prev, struct list_head * next)
 {
 	next->prev = prev;
 	prev->next = next;
@@ -88,7 +88,7 @@
  * @entry: the element to delete from the list.
  * Note: list_empty on entry does not return true after this, the entry is in an undefined state.
  */
-static inline void list_del(list_t *entry)
+static inline void list_del(struct list_head *entry)
 {
 	__list_del(entry->prev, entry->next);
 	entry->next = (void *) 0;
@@ -99,7 +99,7 @@
  * list_del_init - deletes entry from list and reinitialize it.
  * @entry: the element to delete from the list.
  */
-static inline void list_del_init(list_t *entry)
+static inline void list_del_init(struct list_head *entry)
 {
 	__list_del(entry->prev, entry->next);
 	INIT_LIST_HEAD(entry); 
@@ -110,7 +110,7 @@
  * @list: the entry to move
  * @head: the head that will precede our entry
  */
-static inline void list_move(list_t *list, list_t *head)
+static inline void list_move(struct list_head *list, struct list_head *head)
 {
         __list_del(list->prev, list->next);
         list_add(list, head);
@@ -121,7 +121,8 @@
  * @list: the entry to move
  * @head: the head that will follow our entry
  */
-static inline void list_move_tail(list_t *list, list_t *head)
+static inline void list_move_tail(struct list_head *list,
+				  struct list_head *head)
 {
         __list_del(list->prev, list->next);
         list_add_tail(list, head);
@@ -131,16 +132,17 @@
  * list_empty - tests whether a list is empty
  * @head: the list to test.
  */
-static inline int list_empty(list_t *head)
+static inline int list_empty(struct list_head *head)
 {
 	return head->next == head;
 }
 
-static inline void __list_splice(list_t *list, list_t *head)
+static inline void __list_splice(struct list_head *list,
+				 struct list_head *head)
 {
-	list_t *first = list->next;
-	list_t *last = list->prev;
-	list_t *at = head->next;
+	struct list_head *first = list->next;
+	struct list_head *last = list->prev;
+	struct list_head *at = head->next;
 
 	first->prev = head;
 	head->next = first;
@@ -154,7 +156,7 @@
  * @list: the new list to add.
  * @head: the place to add it in the first list.
  */
-static inline void list_splice(list_t *list, list_t *head)
+static inline void list_splice(struct list_head *list, struct list_head *head)
 {
 	if (!list_empty(list))
 		__list_splice(list, head);
@@ -167,7 +169,8 @@
  *
  * The list at @list is reinitialised
  */
-static inline void list_splice_init(list_t *list, list_t *head)
+static inline void list_splice_init(struct list_head *list,
+				    struct list_head *head)
 {
 	if (!list_empty(list)) {
 		__list_splice(list, head);
@@ -177,7 +180,7 @@
 
 /**
  * list_entry - get the struct for this entry
- * @ptr:	the &list_t pointer.
+ * @ptr:	the &struct list_head pointer.
  * @type:	the type of the struct this is embedded in.
  * @member:	the name of the list_struct within the struct.
  */
@@ -186,7 +189,7 @@
 
 /**
  * list_for_each	-	iterate over a list
- * @pos:	the &list_t to use as a loop counter.
+ * @pos:	the &struct list_head to use as a loop counter.
  * @head:	the head for your list.
  */
 #define list_for_each(pos, head) \
@@ -194,7 +197,7 @@
         	pos = pos->next, prefetch(pos->next))
 /**
  * list_for_each_prev	-	iterate over a list backwards
- * @pos:	the &list_t to use as a loop counter.
+ * @pos:	the &struct list_head to use as a loop counter.
  * @head:	the head for your list.
  */
 #define list_for_each_prev(pos, head) \
@@ -203,8 +206,8 @@
         	
 /**
  * list_for_each_safe	-	iterate over a list safe against removal of list entry
- * @pos:	the &list_t to use as a loop counter.
- * @n:		another &list_t to use as temporary storage
+ * @pos:	the &struct list_head to use as a loop counter.
+ * @n:		another &struct list_head to use as temporary storage
  * @head:	the head for your list.
  */
 #define list_for_each_safe(pos, n, head) \
diff -Nru a/include/linux/mm.h b/include/linux/mm.h
--- a/include/linux/mm.h	Mon Sep  9 10:35:56 2002
+++ b/include/linux/mm.h	Mon Sep  9 10:35:56 2002
@@ -61,7 +61,7 @@
 	 * one of the address_space->i_mmap{,shared} lists,
 	 * for shm areas, the list of attaches, otherwise unused.
 	 */
-	list_t shared;
+	struct list_head shared;
 
 	/* Function pointers to deal with this struct. */
 	struct vm_operations_struct * vm_ops;
@@ -316,8 +316,8 @@
 #else /* CONFIG_HIGHMEM || WANT_PAGE_VIRTUAL */
 
 #define page_address(page)						\
-	__va( (((page) - page_zone(page)->zone_mem_map) << PAGE_SHIFT)	\
-			+ page_zone(page)->zone_start_paddr)
+	__va( ( ((page) - page_zone(page)->zone_mem_map)		\
+			+ page_zone(page)->zone_start_pfn) << PAGE_SHIFT)
 
 #endif /* CONFIG_HIGHMEM || WANT_PAGE_VIRTUAL */
 
@@ -398,7 +398,7 @@
 
 extern void free_area_init(unsigned long * zones_size);
 extern void free_area_init_node(int nid, pg_data_t *pgdat, struct page *pmap,
-	unsigned long * zones_size, unsigned long zone_start_paddr, 
+	unsigned long * zones_size, unsigned long zone_start_pfn, 
 	unsigned long *zholes_size);
 extern void mem_init(void);
 extern void show_mem(void);
diff -Nru a/include/linux/mmzone.h b/include/linux/mmzone.h
--- a/include/linux/mmzone.h	Mon Sep  9 10:35:51 2002
+++ b/include/linux/mmzone.h	Mon Sep  9 10:35:51 2002
@@ -110,7 +110,8 @@
 	 */
 	struct pglist_data	*zone_pgdat;
 	struct page		*zone_mem_map;
-	unsigned long		zone_start_paddr;
+	/* zone_start_pfn == zone_start_paddr >> PAGE_SHIFT */
+	unsigned long		zone_start_pfn;
 	unsigned long		zone_start_mapnr;
 
 	/*
@@ -161,7 +162,7 @@
 	struct page *node_mem_map;
 	unsigned long *valid_addr_bitmap;
 	struct bootmem_data *bdata;
-	unsigned long node_start_paddr;
+	unsigned long node_start_pfn;
 	unsigned long node_start_mapnr;
 	unsigned long node_size;
 	int node_id;
diff -Nru a/include/linux/page-flags.h b/include/linux/page-flags.h
--- a/include/linux/page-flags.h	Mon Sep  9 10:36:01 2002
+++ b/include/linux/page-flags.h	Mon Sep  9 10:36:01 2002
@@ -229,36 +229,6 @@
 #define TestClearPageDirect(page)	test_and_clear_bit(PG_direct, &(page)->flags)
 
 /*
- * inlines for acquisition and release of PG_chainlock
- */
-static inline void pte_chain_lock(struct page *page)
-{
-	/*
-	 * Assuming the lock is uncontended, this never enters
-	 * the body of the outer loop. If it is contended, then
-	 * within the inner loop a non-atomic test is used to
-	 * busywait with less bus contention for a good time to
-	 * attempt to acquire the lock bit.
-	 */
-	preempt_disable();
-#ifdef CONFIG_SMP
-	while (test_and_set_bit(PG_chainlock, &page->flags)) {
-		while (test_bit(PG_chainlock, &page->flags))
-			cpu_relax();
-	}
-#endif
-}
-
-static inline void pte_chain_unlock(struct page *page)
-{
-#ifdef CONFIG_SMP
-	smp_mb__before_clear_bit();
-	clear_bit(PG_chainlock, &page->flags);
-#endif
-	preempt_enable();
-}
-
-/*
  * The PageSwapCache predicate doesn't use a PG_flag at this time,
  * but it may again do so one day.
  */
diff -Nru a/include/linux/pci.h b/include/linux/pci.h
--- a/include/linux/pci.h	Mon Sep  9 10:36:11 2002
+++ b/include/linux/pci.h	Mon Sep  9 10:36:11 2002
@@ -386,6 +386,9 @@
 	int		ro;		/* ISAPnP: read only */
 	unsigned short	regs;		/* ISAPnP: supported registers */
 
+	/* These fields are used by common fixups */
+	unsigned short	transparent:1;	/* Transparent PCI bridge */
+
 	int (*prepare)(struct pci_dev *dev);	/* ISAPnP hooks */
 	int (*activate)(struct pci_dev *dev);
 	int (*deactivate)(struct pci_dev *dev);
@@ -406,6 +409,10 @@
 #define PCI_ROM_RESOURCE 6
 #define PCI_BRIDGE_RESOURCES 7
 #define PCI_NUM_RESOURCES 11
+
+#ifndef PCI_BUS_NUM_RESOURCES
+#define PCI_BUS_NUM_RESOURCES 4
+#endif
   
 #define PCI_REGION_FLAG_MASK 0x0fU	/* These bits of resource flags tell us the PCI region flags */
 
@@ -415,7 +422,8 @@
 	struct list_head children;	/* list of child buses */
 	struct list_head devices;	/* list of devices on this bus */
 	struct pci_dev	*self;		/* bridge device as seen by parent */
-	struct resource	*resource[4];	/* address space routed to this bus */
+	struct resource	*resource[PCI_BUS_NUM_RESOURCES];
+					/* address space routed to this bus */
 
 	struct pci_ops	*ops;		/* configuration access functions */
 	void		*sysdata;	/* hook for sys-specific extension */
@@ -588,8 +596,6 @@
 {
 	return pci_bus_write_config_dword (dev->bus, dev->devfn, where, val);
 }
-
-extern spinlock_t pci_lock;
 
 extern spinlock_t pci_lock;
 
diff -Nru a/include/linux/pci_ids.h b/include/linux/pci_ids.h
--- a/include/linux/pci_ids.h	Mon Sep  9 10:36:11 2002
+++ b/include/linux/pci_ids.h	Mon Sep  9 10:36:11 2002
@@ -820,11 +820,13 @@
 #define PCI_DEVICE_ID_AL_M1531		0x1531
 #define PCI_DEVICE_ID_AL_M1533		0x1533
 #define PCI_DEVICE_ID_AL_M1541		0x1541
-#define PCI_DEVICE_ID_AL_M1621          0x1621
-#define PCI_DEVICE_ID_AL_M1631          0x1631
-#define PCI_DEVICE_ID_AL_M1641          0x1641
-#define PCI_DEVICE_ID_AL_M1647          0x1647
-#define PCI_DEVICE_ID_AL_M1651          0x1651
+#define PCI_DEVICE_ID_AL_M1621		0x1621
+#define PCI_DEVICE_ID_AL_M1631		0x1631
+#define PCI_DEVICE_ID_AL_M1632		0x1632
+#define PCI_DEVICE_ID_AL_M1641		0x1641
+#define PCI_DEVICE_ID_AL_M1644		0x1644
+#define PCI_DEVICE_ID_AL_M1647		0x1647
+#define PCI_DEVICE_ID_AL_M1651		0x1651
 #define PCI_DEVICE_ID_AL_M1543		0x1543
 #define PCI_DEVICE_ID_AL_M3307		0x3307
 #define PCI_DEVICE_ID_AL_M4803		0x5215
@@ -961,7 +963,7 @@
 #define PCI_DEVICE_ID_VIA_82C597_0	0x0597
 #define PCI_DEVICE_ID_VIA_82C598_0	0x0598
 #define PCI_DEVICE_ID_VIA_8601_0	0x0601
-#define PCI_DEVICE_ID_VIA_8605_0	0x0605
+#define PCI_DEVICE_ID_VIA_82C694X_0	0x0605
 #define PCI_DEVICE_ID_VIA_82C680	0x0680
 #define PCI_DEVICE_ID_VIA_82C686	0x0686
 #define PCI_DEVICE_ID_VIA_82C691	0x0691
@@ -1637,6 +1639,9 @@
 #define PCI_DEVICE_ID_INTEL_I960	0x0960
 #define PCI_DEVICE_ID_INTEL_82562ET	0x1031
 #define PCI_DEVICE_ID_INTEL_82801CAM	0x1038
+#define PCI_DEVICE_ID_INTEL_82815_MC	0x1130
+#define PCI_DEVICE_ID_INTEL_82815_AB	0x1131
+#define PCI_DEVICE_ID_INTEL_82815_CGC	0x1132
 #define PCI_DEVICE_ID_INTEL_82559ER	0x1209
 #define PCI_DEVICE_ID_INTEL_82092AA_0	0x1221
 #define PCI_DEVICE_ID_INTEL_82092AA_1	0x1222
@@ -1653,6 +1658,8 @@
 #define PCI_DEVICE_ID_INTEL_82380FB	0x124b
 #define PCI_DEVICE_ID_INTEL_82439	0x1250
 #define PCI_DEVICE_ID_INTEL_80960_RP	0x1960
+#define PCI_DEVICE_ID_INTEL_82840_HB	0x1a21
+#define PCI_DEVICE_ID_INTEL_82845_HB	0x1a30
 #define PCI_DEVICE_ID_INTEL_82801AA_0	0x2410
 #define PCI_DEVICE_ID_INTEL_82801AA_1	0x2411
 #define PCI_DEVICE_ID_INTEL_82801AA_2	0x2412
@@ -1693,6 +1700,14 @@
 #define PCI_DEVICE_ID_INTEL_82801CA_12	0x248c
 #define PCI_DEVICE_ID_INTEL_82801DB_9	0x24cb
 #define PCI_DEVICE_ID_INTEL_82801DB_11	PCI_DEVICE_ID_INTEL_82801DB_9
+#define PCI_DEVICE_ID_INTEL_82820_HB	0x2500
+#define PCI_DEVICE_ID_INTEL_82820_UP_HB	0x2501
+#define PCI_DEVICE_ID_INTEL_82850_HB	0x2530
+#define PCI_DEVICE_ID_INTEL_82860_HB	0x2531
+#define PCI_DEVICE_ID_INTEL_82845G_HB	0x2560
+#define PCI_DEVICE_ID_INTEL_82845G_IG	0x2562
+#define PCI_DEVICE_ID_INTEL_82830_HB	0x3575
+#define PCI_DEVICE_ID_INTEL_82830_CGC	0x3577
 #define PCI_DEVICE_ID_INTEL_80310	0x530d
 #define PCI_DEVICE_ID_INTEL_82371SB_0	0x7000
 #define PCI_DEVICE_ID_INTEL_82371SB_1	0x7010
@@ -1707,6 +1722,8 @@
 #define PCI_DEVICE_ID_INTEL_82810_IG1	0x7121
 #define PCI_DEVICE_ID_INTEL_82810_MC3	0x7122
 #define PCI_DEVICE_ID_INTEL_82810_IG3	0x7123
+#define PCI_DEVICE_ID_INTEL_82810E_MC	0x7124
+#define PCI_DEVICE_ID_INTEL_82810E_IG	0x7125
 #define PCI_DEVICE_ID_INTEL_82443LX_0	0x7180
 #define PCI_DEVICE_ID_INTEL_82443LX_1	0x7181
 #define PCI_DEVICE_ID_INTEL_82443BX_0	0x7190
@@ -1716,6 +1733,8 @@
 #define PCI_DEVICE_ID_INTEL_82443MX_1	0x7199
 #define PCI_DEVICE_ID_INTEL_82443MX_2	0x719a
 #define PCI_DEVICE_ID_INTEL_82443MX_3	0x719b
+#define PCI_DEVICE_ID_INTEL_82443GX_0	0x71a0
+#define PCI_DEVICE_ID_INTEL_82443GX_1	0x71a1
 #define PCI_DEVICE_ID_INTEL_82372FB_0	0x7600
 #define PCI_DEVICE_ID_INTEL_82372FB_1	0x7601
 #define PCI_DEVICE_ID_INTEL_82372FB_2	0x7602
@@ -1723,6 +1742,7 @@
 #define PCI_DEVICE_ID_INTEL_82454GX	0x84c4
 #define PCI_DEVICE_ID_INTEL_82450GX	0x84c5
 #define PCI_DEVICE_ID_INTEL_82451NX	0x84ca
+#define PCI_DEVICE_ID_INTEL_84460GX	0x84ea
 
 #define PCI_VENDOR_ID_COMPUTONE		0x8e0e
 #define PCI_DEVICE_ID_COMPUTONE_IP2EX	0x0291
diff -Nru a/include/linux/preempt.h b/include/linux/preempt.h
--- a/include/linux/preempt.h	Mon Sep  9 10:36:01 2002
+++ b/include/linux/preempt.h	Mon Sep  9 10:36:01 2002
@@ -48,22 +48,12 @@
 	preempt_check_resched(); \
 } while (0)
 
-#define inc_preempt_count_non_preempt()	do { } while (0)
-#define dec_preempt_count_non_preempt()	do { } while (0)
-
 #else
 
 #define preempt_disable()		do { } while (0)
 #define preempt_enable_no_resched()	do { } while (0)
 #define preempt_enable()		do { } while (0)
 #define preempt_check_resched()		do { } while (0)
-
-/*
- * Sometimes we want to increment the preempt count, but we know that it's
- * already incremented if the kernel is compiled for preemptibility.
- */
-#define inc_preempt_count_non_preempt()	inc_preempt_count()
-#define dec_preempt_count_non_preempt()	dec_preempt_count()
 
 #endif
 
diff -Nru a/include/linux/ptrace.h b/include/linux/ptrace.h
--- a/include/linux/ptrace.h	Mon Sep  9 10:35:56 2002
+++ b/include/linux/ptrace.h	Mon Sep  9 10:35:56 2002
@@ -24,6 +24,7 @@
 #define PTRACE_SYSCALL		  24
 
 #include <asm/ptrace.h>
+#include <linux/sched.h>
 
 extern int ptrace_readdata(struct task_struct *tsk, unsigned long src, char *dst, int len);
 extern int ptrace_writedata(struct task_struct *tsk, char * src, unsigned long dst, int len);
diff -Nru a/include/linux/raid/md.h b/include/linux/raid/md.h
--- a/include/linux/raid/md.h	Mon Sep  9 10:35:56 2002
+++ b/include/linux/raid/md.h	Mon Sep  9 10:35:56 2002
@@ -61,7 +61,6 @@
 #define MD_PATCHLEVEL_VERSION           0
 
 extern int md_size[MAX_MD_DEVS];
-extern struct hd_struct md_hd_struct[MAX_MD_DEVS];
 
 extern char * partition_name (kdev_t dev);
 extern inline char * bdev_partition_name (struct block_device *bdev)
diff -Nru a/include/linux/reiserfs_fs.h b/include/linux/reiserfs_fs.h
--- a/include/linux/reiserfs_fs.h	Mon Sep  9 10:36:13 2002
+++ b/include/linux/reiserfs_fs.h	Mon Sep  9 10:36:13 2002
@@ -59,7 +59,8 @@
 #define USE_INODE_GENERATION_COUNTER
 
 #define REISERFS_PREALLOCATE
-#define PREALLOCATION_SIZE 8
+#define DISPLACE_NEW_PACKING_LOCALITIES
+#define PREALLOCATION_SIZE 9
 
 /* n must be power of 2 */
 #define _ROUND_UP(x,n) (((x)+(n)-1u) & ~((n)-1u))
@@ -326,7 +327,7 @@
    time cost for a 4 block file and saves an amount of space that is
    less significant as a percentage of space, or so goes the hypothesis.
    -Hans */
-#define STORE_TAIL_IN_UNFM(n_file_size,n_tail_size,n_block_size) \
+#define STORE_TAIL_IN_UNFM_S1(n_file_size,n_tail_size,n_block_size) \
 (\
   (!(n_tail_size)) || \
   (((n_tail_size) > MAX_DIRECT_ITEM_LEN(n_block_size)) || \
@@ -339,6 +340,18 @@
      ( (n_tail_size) >=   (MAX_DIRECT_ITEM_LEN(n_block_size) * 3)/4) ) ) \
 )
 
+/* Another strategy for tails, this one means only create a tail if all the
+   file would fit into one DIRECT item.
+   Primary intention for this one is to increase performance by decreasing
+   seeking.
+*/   
+#define STORE_TAIL_IN_UNFM_S2(n_file_size,n_tail_size,n_block_size) \
+(\
+  (!(n_tail_size)) || \
+  (((n_file_size) > MAX_DIRECT_ITEM_LEN(n_block_size)) ) \
+)
+
+
 
 /*
  * values for s_umount_state field
@@ -1433,6 +1446,10 @@
 
   int fs_gen;                  /* saved value of `reiserfs_generation' counter
 			          see FILESYSTEM_CHANGED() macro in reiserfs_fs.h */
+#ifdef DISPLACE_NEW_PACKING_LOCALITIES
+  struct key  key;	      /* key pointer, to pass to block allocator or
+				 another low-level subsystem */
+#endif
 } ;
 
 /* These are modes of balancing */
@@ -1673,7 +1690,7 @@
 int push_journal_writer(char *w) ;
 int pop_journal_writer(int windex) ;
 int journal_transaction_should_end(struct reiserfs_transaction_handle *, int) ;
-int reiserfs_in_journal(struct super_block *p_s_sb, unsigned long bl, int searchall, unsigned long *next) ;
+int reiserfs_in_journal(struct super_block *p_s_sb, int bmap_nr, int bit_nr, int searchall, unsigned long *next) ;
 int journal_begin(struct reiserfs_transaction_handle *, struct super_block *p_s_sb, unsigned long) ;
 void flush_async_commits(struct super_block *p_s_sb) ;
 
@@ -1818,8 +1835,8 @@
 #define file_size(inode) ((inode)->i_size)
 #define tail_size(inode) (file_size (inode) & (i_block_size (inode) - 1))
 
-#define tail_has_to_be_packed(inode) (!dont_have_tails ((inode)->i_sb) &&\
-!STORE_TAIL_IN_UNFM(file_size (inode), tail_size(inode), i_block_size (inode)))
+#define tail_has_to_be_packed(inode) (have_large_tails ((inode)->i_sb)?\
+!STORE_TAIL_IN_UNFM_S1(file_size (inode), tail_size(inode), inode->i_sb->s_blocksize):have_small_tails ((inode)->i_sb)?!STORE_TAIL_IN_UNFM_S2(file_size (inode), tail_size(inode), inode->i_sb->s_blocksize):0 )
 
 void padd_item (char * item, int total_length, int length);
 
@@ -2015,22 +2032,87 @@
 struct buffer_head * get_FEB (struct tree_balance *);
 
 /* bitmap.c */
+
+/* structure contains hints for block allocator, and it is a container for
+ * arguments, such as node, search path, transaction_handle, etc. */
+ struct __reiserfs_blocknr_hint {
+     struct inode * inode;		/* inode passed to allocator, if we allocate unf. nodes */
+     long block;			/* file offset, in blocks */
+     struct key key;
+     struct path * path;		/* search path, used by allocator to deternine search_start by
+					 * various ways */
+     struct reiserfs_transaction_handle * th; /* transaction handle is needed to log super blocks and
+					       * bitmap blocks changes  */
+     b_blocknr_t beg, end;
+     b_blocknr_t search_start;		/* a field used to transfer search start value (block number)
+					 * between different block allocator procedures
+					 * (determine_search_start() and others) */
+    int prealloc_size;			/* is set in determine_prealloc_size() function, used by underlayed
+					 * function that do actual allocation */
+
+    int formatted_node:1;		/* the allocator uses different polices for getting disk space for
+					 * formatted/unformatted blocks with/without preallocation */
+    int preallocate:1;
+};
+
+typedef struct __reiserfs_blocknr_hint reiserfs_blocknr_hint_t;
+
+int reiserfs_parse_alloc_options (struct super_block *, char *);
 int is_reusable (struct super_block * s, unsigned long block, int bit_value);
 void reiserfs_free_block (struct reiserfs_transaction_handle *th, unsigned long);
-int reiserfs_new_blocknrs (struct reiserfs_transaction_handle *th,
-			   unsigned long * pblocknrs, unsigned long start_from, int amount_needed);
-int reiserfs_new_unf_blocknrs (struct reiserfs_transaction_handle *th,
-			       unsigned long * pblocknr, unsigned long start_from);
+int reiserfs_allocate_blocknrs(reiserfs_blocknr_hint_t *, b_blocknr_t * , int, int);
+extern inline int reiserfs_new_form_blocknrs (struct tree_balance * tb,
+					      b_blocknr_t *new_blocknrs, int amount_needed)
+{
+    reiserfs_blocknr_hint_t hint = {
+	th:tb->transaction_handle,
+	path: tb->tb_path,
+	inode: NULL,
+	key: tb->key,
+	block: 0,
+	formatted_node:1
+    };
+    return reiserfs_allocate_blocknrs(&hint, new_blocknrs, amount_needed, 0);
+}
+
+extern inline int reiserfs_new_unf_blocknrs (struct reiserfs_transaction_handle *th,
+					     b_blocknr_t *new_blocknrs,
+					     struct path * path, long block)
+{
+    reiserfs_blocknr_hint_t hint = {
+	th: th,
+	path: path,
+	inode: NULL,
+	block: block,
+	formatted_node: 0,
+	preallocate: 0
+    };
+    return reiserfs_allocate_blocknrs(&hint, new_blocknrs, 1, 0);
+}
+
 #ifdef REISERFS_PREALLOCATE
-int reiserfs_new_unf_blocknrs2 (struct reiserfs_transaction_handle *th, 
-				struct inode * inode,
-				unsigned long * pblocknr, 
-				unsigned long start_from);
+extern inline int reiserfs_new_unf_blocknrs2(struct reiserfs_transaction_handle *th,
+					     struct inode * inode,
+					     b_blocknr_t *new_blocknrs,
+					     struct path * path, long block)
+{
+    reiserfs_blocknr_hint_t hint = {
+	th: th,
+	path: path,
+	inode: inode,
+	block: block,
+	formatted_node: 0,
+	preallocate: 1
+    };
+    return reiserfs_allocate_blocknrs(&hint, new_blocknrs, 1, 0);
+}
 
 void reiserfs_discard_prealloc (struct reiserfs_transaction_handle *th, 
 				struct inode * inode);
 void reiserfs_discard_all_prealloc (struct reiserfs_transaction_handle *th);
 #endif
+void reiserfs_claim_blocks_to_be_allocated( struct super_block *sb, int blocks);
+void reiserfs_release_claimed_blocks( struct super_block *sb, int blocks);
 
 /* hashes.c */
 __u32 keyed_hash (const signed char *msg, int len);
diff -Nru a/include/linux/reiserfs_fs_i.h b/include/linux/reiserfs_fs_i.h
--- a/include/linux/reiserfs_fs_i.h	Mon Sep  9 10:36:01 2002
+++ b/include/linux/reiserfs_fs_i.h	Mon Sep  9 10:36:01 2002
@@ -37,6 +37,10 @@
     struct list_head i_prealloc_list; /* per-transaction list of inodes which
                                        * have preallocated blocks */
 
+    int new_packing_locality:1;	      /* new_packig_locality is created; new blocks
+				       * for the contents of this directory should be
+				       * displaced */
+
     /* we use these for fsync or O_SYNC to decide which transaction
     ** needs to be committed in order for this inode to be properly
     ** flushed */
diff -Nru a/include/linux/reiserfs_fs_sb.h b/include/linux/reiserfs_fs_sb.h
--- a/include/linux/reiserfs_fs_sb.h	Mon Sep  9 10:36:11 2002
+++ b/include/linux/reiserfs_fs_sb.h	Mon Sep  9 10:36:11 2002
@@ -160,7 +160,10 @@
   int t_blocks_allocated ;      /* number of blocks this writer allocated */
   unsigned long t_trans_id ;    /* sanity check, equals the current trans id */
   struct super_block *t_super ; /* super for this FS when journal_begin was 
-                                   called. */
+                                   called. saves calls to reiserfs_get_super */
+  int displace_new_blocks:1;	/* if new block allocation occurres, that block
+				   should be displaced from others */
+
 } ;
 
 /*
@@ -254,6 +257,14 @@
 
 typedef __u32 (*hashf_t) (const signed char *, int);
 
+struct reiserfs_bitmap_info
+{
+    // FIXME: Won't work with block sizes > 8K
+    __u16  first_zero_hint;
+    __u16  free_count;
+    struct buffer_head *bh; /* the actual bitmap */
+};
+
 struct proc_dir_entry;
 
 #if defined( CONFIG_PROC_FS ) && defined( CONFIG_REISERFS_PROC_INFO )
@@ -270,6 +281,12 @@
   stat_cnt_t search_by_key_fs_changed;
   stat_cnt_t search_by_key_restarted;
 
+  stat_cnt_t insert_item_restarted;
+  stat_cnt_t paste_into_item_restarted;
+  stat_cnt_t cut_from_item_restarted;
+  stat_cnt_t delete_solid_item_restarted;
+  stat_cnt_t delete_item_restarted;
+
   stat_cnt_t leaked_oid;
   stat_cnt_t leaves_removable;
 
@@ -292,14 +309,15 @@
   stat_cnt_t need_r_neighbor[ 5 ];
 
   stat_cnt_t free_block;
-  struct __find_forward_stats {
+  struct __scan_bitmap_stats {
 	stat_cnt_t call;
 	stat_cnt_t wait;
 	stat_cnt_t bmap;
 	stat_cnt_t retry;
 	stat_cnt_t in_journal_hint;
-	stat_cnt_t in_journal_out;
-  } find_forward;
+	stat_cnt_t in_journal_nohint;
+	stat_cnt_t stolen;
+  } scan_bitmap;
   struct __journal_stats {
 	stat_cnt_t in_journal;
 	stat_cnt_t in_journal_bitmap;
@@ -329,7 +347,7 @@
 				/* both the comment and the choice of
                                    name are unclear for s_rs -Hans */
     struct reiserfs_super_block * s_rs;           /* Pointer to the super block in the buffer */
-    struct buffer_head ** s_ap_bitmap;       /* array of buffers, holding block bitmap */
+    struct reiserfs_bitmap_info * s_ap_bitmap;
     struct reiserfs_journal *s_journal ;		/* pointer to journal information */
     unsigned short s_mount_state;                 /* reiserfs state (valid, invalid) */
   
@@ -342,6 +360,16 @@
                                    here (currently - NOTAIL, NOLOG,
                                    REPLAYONLY) */
 
+    struct {			/* This is a structure that describes block allocator options */
+	unsigned long bits;	/* Bitfield for enable/disable kind of options */
+	unsigned long large_file_size; /* size started from which we consider file to be a large one(in blocks) */
+	int border;		/* percentage of disk, border takes */
+	int preallocmin;	/* Minimal file size (in blocks) starting from which we do preallocations */
+	int preallocsize;	/* Number of blocks we try to prealloc when file
+				   reaches preallocmin size (in blocks) or
+				   prealloc_list is empty. */
+    } s_alloc_options;
+
 				/* Comment? -Hans */
     wait_queue_head_t s_wait;
 				/* To be obsoleted soon by per buffer seals.. -Hans */
@@ -368,6 +396,7 @@
     int s_is_unlinked_ok;
     reiserfs_proc_info_data_t s_proc_info_data;
     struct proc_dir_entry *procdir;
+    int reserved_blocks; /* amount of blocks reserved for further allocations */
 };
 
 /* Definitions of reiserfs on-disk properties: */
@@ -375,7 +404,8 @@
 #define REISERFS_3_6 1
 
 /* Mount options */
-#define NOTAIL 0  /* -o notail: no tails will be created in a session */
+#define REISERFS_LARGETAIL 0  /* large tails will be created in a session */
+#define REISERFS_SMALLTAIL 17  /* small (for files less than block size) tails will be created in a session */
 #define REPLAYONLY 3 /* replay journal and return 0. Use by fsck */
 #define REISERFS_NOLOG 4      /* -o nolog: turn journalling off */
 #define REISERFS_CONVERT 5    /* -o conv: causes conversion of old
@@ -423,7 +453,8 @@
 #define reiserfs_hashed_relocation(s) (REISERFS_SB(s)->s_mount_opt & (1 << REISERFS_HASHED_RELOCATION))
 #define reiserfs_test4(s) (REISERFS_SB(s)->s_mount_opt & (1 << REISERFS_TEST4))
 
-#define dont_have_tails(s) (REISERFS_SB(s)->s_mount_opt & (1 << NOTAIL))
+#define have_large_tails(s) (REISERFS_SB(s)->s_mount_opt & (1 << REISERFS_LARGETAIL))
+#define have_small_tails(s) (REISERFS_SB(s)->s_mount_opt & (1 << REISERFS_SMALLTAIL))
 #define replay_only(s) (REISERFS_SB(s)->s_mount_opt & (1 << REPLAYONLY))
 #define reiserfs_dont_log(s) (REISERFS_SB(s)->s_mount_opt & (1 << REISERFS_NOLOG))
 #define old_format_only(s) (REISERFS_SB(s)->s_properties & (1 << REISERFS_3_5))
diff -Nru a/include/linux/rmap-locking.h b/include/linux/rmap-locking.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/include/linux/rmap-locking.h	Mon Sep  9 10:36:18 2002
@@ -0,0 +1,33 @@
+/*
+ * include/linux/rmap-locking.h
+ *
+ * Locking primitives for exclusive access to a page's reverse-mapping
+ * pte chain.
+ */
+
+static inline void pte_chain_lock(struct page *page)
+{
+	/*
+	 * Assuming the lock is uncontended, this never enters
+	 * the body of the outer loop. If it is contended, then
+	 * within the inner loop a non-atomic test is used to
+	 * busywait with less bus contention for a good time to
+	 * attempt to acquire the lock bit.
+	 */
+	preempt_disable();
+#ifdef CONFIG_SMP
+	while (test_and_set_bit(PG_chainlock, &page->flags)) {
+		while (test_bit(PG_chainlock, &page->flags))
+			cpu_relax();
+	}
+#endif
+}
+
+static inline void pte_chain_unlock(struct page *page)
+{
+#ifdef CONFIG_SMP
+	smp_mb__before_clear_bit();
+	clear_bit(PG_chainlock, &page->flags);
+#endif
+	preempt_enable();
+}
diff -Nru a/include/linux/sched.h b/include/linux/sched.h
--- a/include/linux/sched.h	Mon Sep  9 10:35:56 2002
+++ b/include/linux/sched.h	Mon Sep  9 10:35:56 2002
@@ -211,6 +211,11 @@
 	atomic_t		count;
 	struct k_sigaction	action[_NSIG];
 	spinlock_t		siglock;
+
+        /* current thread group signal load-balancing target: */
+        task_t                  *curr_target;
+
+	struct sigpending	shared_pending;
 };
 
 /*
@@ -264,7 +269,7 @@
 	int lock_depth;		/* Lock depth */
 
 	int prio, static_prio;
-	list_t run_list;
+	struct list_head run_list;
 	prio_array_t *array;
 
 	unsigned long sleep_avg;
@@ -356,7 +361,7 @@
 	spinlock_t sigmask_lock;	/* Protects signal and blocked */
 	struct signal_struct *sig;
 
-	sigset_t blocked;
+	sigset_t blocked, real_blocked, shared_unblocked;
 	struct sigpending pending;
 
 	unsigned long sas_ss_sp;
@@ -431,6 +436,7 @@
 extern void set_user_nice(task_t *p, long nice);
 extern int task_prio(task_t *p);
 extern int task_nice(task_t *p);
+extern int task_curr(task_t *p);
 extern int idle_cpu(int cpu);
 
 void yield(void);
@@ -455,7 +461,7 @@
 extern struct   mm_struct init_mm;
 
 /* PID hashing. (shouldnt this be dynamic?) */
-#define PIDHASH_SZ (4096 >> 2)
+#define PIDHASH_SZ 8192
 extern struct task_struct *pidhash[PIDHASH_SZ];
 
 #define pid_hashfn(x)	((((x) >> 8) ^ (x)) & (PIDHASH_SZ - 1))
@@ -535,7 +541,7 @@
 extern void flush_signals(struct task_struct *);
 extern void flush_signal_handlers(struct task_struct *);
 extern void sig_exit(int, int, struct siginfo *);
-extern int dequeue_signal(sigset_t *, siginfo_t *);
+extern int dequeue_signal(struct sigpending *pending, sigset_t *mask, siginfo_t *info);
 extern void block_all_signals(int (*notifier)(void *priv), void *priv,
 			      sigset_t *mask);
 extern void unblock_all_signals(void);
@@ -654,6 +660,7 @@
 extern void exit_mm(struct task_struct *);
 extern void exit_files(struct task_struct *);
 extern void exit_sighand(struct task_struct *);
+extern void remove_thread_group(struct task_struct *tsk, struct signal_struct *sig);
 
 extern void reparent_to_init(void);
 extern void daemonize(void);
@@ -786,8 +793,29 @@
 #define for_each_thread(task) \
 	for (task = next_thread(current) ; task != current ; task = next_thread(task))
 
-#define next_thread(p) \
-	list_entry((p)->thread_group.next, struct task_struct, thread_group)
+static inline task_t *next_thread(task_t *p)
+{
+	if (!p->sig)
+		BUG();
+#if CONFIG_SMP
+	if (!spin_is_locked(&p->sig->siglock) &&
+				!rwlock_is_locked(&tasklist_lock))
+		BUG();
+#endif
+	return list_entry((p)->thread_group.next, task_t, thread_group);
+}
+
+static inline task_t *prev_thread(task_t *p)
+{
+	if (!p->sig)
+		BUG();
+#if CONFIG_SMP
+	if (!spin_is_locked(&p->sig->siglock) &&
+				!rwlock_is_locked(&tasklist_lock))
+		BUG();
+#endif
+	return list_entry((p)->thread_group.prev, task_t, thread_group);
+}
 
 #define thread_group_leader(p)	(p->pid == p->tgid)
 
@@ -903,21 +931,8 @@
    This is required every time the blocked sigset_t changes.
    Athread cathreaders should have t->sigmask_lock.  */
 
-static inline void recalc_sigpending_tsk(struct task_struct *t)
-{
-	if (has_pending_signals(&t->pending.signal, &t->blocked))
-		set_tsk_thread_flag(t, TIF_SIGPENDING);
-	else
-		clear_tsk_thread_flag(t, TIF_SIGPENDING);
-}
-
-static inline void recalc_sigpending(void)
-{
-	if (has_pending_signals(&current->pending.signal, &current->blocked))
-		set_thread_flag(TIF_SIGPENDING);
-	else
-		clear_thread_flag(TIF_SIGPENDING);
-}
+extern FASTCALL(void recalc_sigpending_tsk(struct task_struct *t));
+extern void recalc_sigpending(void);
 
 /*
  * Wrappers for p->thread_info->cpu access. No-op on UP.
diff -Nru a/include/linux/sysctl.h b/include/linux/sysctl.h
--- a/include/linux/sysctl.h	Mon Sep  9 10:35:51 2002
+++ b/include/linux/sysctl.h	Mon Sep  9 10:35:51 2002
@@ -127,6 +127,7 @@
 	KERN_CORE_USES_PID=52,		/* int: use core or core.%pid */
 	KERN_TAINTED=53,	/* int: various kernel tainted flags */
 	KERN_CADPID=54,		/* int: PID of the process to notify on CAD */
+	KERN_PIDMAX=55,		/* int: PID # limit */
 };
 
 
diff -Nru a/include/linux/threads.h b/include/linux/threads.h
--- a/include/linux/threads.h	Mon Sep  9 10:35:55 2002
+++ b/include/linux/threads.h	Mon Sep  9 10:35:55 2002
@@ -19,7 +19,6 @@
 /*
  * This controls the maximum pid allocated to a process
  */
-#define PID_MASK 0x3fffffff
-#define PID_MAX (PID_MASK+1)
+#define DEFAULT_PID_MAX 0x8000
 
 #endif
diff -Nru a/include/net/inet_common.h b/include/net/inet_common.h
--- a/include/net/inet_common.h	Mon Sep  9 10:36:13 2002
+++ b/include/net/inet_common.h	Mon Sep  9 10:36:13 2002
@@ -34,9 +34,6 @@
 extern int			inet_getsockopt(struct socket *sock, int level,
 						int optname, char *optval, 
 						int *optlen);
-extern int			inet_fcntl(struct socket *sock, 
-					   unsigned int cmd, 
-					   unsigned long arg);
 extern int			inet_listen(struct socket *sock, int backlog);
 
 extern void			inet_sock_release(struct sock *sk);
diff -Nru a/include/net/sctp/structs.h b/include/net/sctp/structs.h
--- a/include/net/sctp/structs.h	Mon Sep  9 10:36:11 2002
+++ b/include/net/sctp/structs.h	Mon Sep  9 10:36:11 2002
@@ -203,7 +203,7 @@
 	/* This is a list of groups of functions for each address
 	 * family that we support.
 	 */
-	list_t address_families;
+	struct list_head address_families;
 
 	/* This is the hash of all endpoints. */
 	int ep_hashsize;
@@ -225,7 +225,7 @@
 	 *
 	 * It is a list of struct sockaddr_storage_list.
 	 */
-	list_t local_addr_list;
+	struct list_head local_addr_list;
 	spinlock_t local_addr_lock;
 };
 
@@ -250,7 +250,7 @@
 	__u16		net_header_len;	
 	int		sockaddr_len;
 	sa_family_t	sa_family;
-	list_t          list;
+	struct list_head list;
 } sctp_func_t;
 
 sctp_func_t *sctp_get_af_specific(const sockaddr_storage_t *address);
@@ -494,7 +494,7 @@
  * sin_addr -- cast to either (struct in_addr) or (struct in6_addr)
  */
 struct sockaddr_storage_list {
-	list_t list;
+	struct list_head list;
 	sockaddr_storage_t a;
 };
 
@@ -582,7 +582,7 @@
  */
 struct SCTP_transport {
 	/* A list of transports. */
-	list_t transports;
+	struct list_head transports;
 
 	/* Reference counting. */
 	atomic_t refcnt;
@@ -863,7 +863,7 @@
 	 *	has bound.  This information is passed to one's
 	 *	peer(s) in INIT and INIT ACK chunks.
 	 */
-	list_t address_list;
+	struct list_head address_list;
 
 	int malloced;        /* Are we kfree()able?  */
 };
@@ -988,7 +988,7 @@
 	 *            is implemented.
 	 */
 	/* This is really a list of sctp_association_t entries. */
-	list_t asocs;
+	struct list_head asocs;
 
 	/* Secret Key: A secret key used by this endpoint to compute
 	 *            the MAC.  This SHOULD be a cryptographic quality
@@ -1070,7 +1070,7 @@
 	sctp_endpoint_common_t base;
 
 	/* Associations on the same socket. */
-	list_t asocs;
+	struct list_head asocs;
 
 	/* This is a signature that lets us know that this is a
 	 * sctp_association_t data structure.  Used for mapping an
@@ -1104,7 +1104,7 @@
 		 *
 		 * It is a list of SCTP_transport's.
 		 */
-		list_t transport_addr_list;
+		struct list_head transport_addr_list;
 
 		/* port
 		 *   The transport layer port number.
diff -Nru a/include/net/sock.h b/include/net/sock.h
--- a/include/net/sock.h	Mon Sep  9 10:36:13 2002
+++ b/include/net/sock.h	Mon Sep  9 10:36:13 2002
@@ -132,7 +132,6 @@
 	unsigned char		rcvtstamp;
 	unsigned char		no_largesend;
 	int			route_caps;
-	int			proc;
 	unsigned long	        lingertime;
 
 	int			hashent;
@@ -292,7 +291,6 @@
 #define SOCK_BINDADDR_LOCK	4
 #define SOCK_BINDPORT_LOCK	8
 
-#include <linux/fs.h>	/* just for inode - yeuch.*/
 
 
 /* Used by processes to "lock" a socket state, so that
@@ -362,6 +360,7 @@
 						      int *errcode);
 extern void *sock_kmalloc(struct sock *sk, int size, int priority);
 extern void sock_kfree_s(struct sock *sk, void *mem, int size);
+extern void sk_send_sigurg(struct sock *sk);
 
 /*
  * Functions to fill in entries in struct proto_ops when a protocol
@@ -388,8 +387,6 @@
 						   char *, int *);
 extern int			sock_no_setsockopt(struct socket *, int, int,
 						   char *, int);
-extern int 			sock_no_fcntl(struct socket *, 
-					      unsigned int, unsigned long);
 extern int                      sock_no_sendmsg(struct socket *,
 						struct msghdr *, int,
 						struct scm_cookie *);
diff -Nru a/include/net/tcp.h b/include/net/tcp.h
--- a/include/net/tcp.h	Mon Sep  9 10:35:59 2002
+++ b/include/net/tcp.h	Mon Sep  9 10:35:59 2002
@@ -27,6 +27,7 @@
 #include <linux/config.h>
 #include <linux/tcp.h>
 #include <linux/slab.h>
+#include <linux/cache.h>
 #include <net/checksum.h>
 #include <net/sock.h>
 #if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
@@ -120,8 +121,7 @@
 	 * Now align to a new cache line as all the following members
 	 * are often dirty.
 	 */
-	rwlock_t __tcp_lhash_lock
-		__attribute__((__aligned__(SMP_CACHE_BYTES)));
+	rwlock_t __tcp_lhash_lock ____cacheline_aligned;
 	atomic_t __tcp_lhash_users;
 	wait_queue_head_t __tcp_lhash_wait;
 	spinlock_t __tcp_portalloc_lock;
diff -Nru a/init/do_mounts.c b/init/do_mounts.c
--- a/init/do_mounts.c	Mon Sep  9 10:36:11 2002
+++ b/init/do_mounts.c	Mon Sep  9 10:36:11 2002
@@ -28,6 +28,7 @@
 	 unsigned long flags, void *data);
 extern asmlinkage long sys_mkdir(const char *name, int mode);
 extern asmlinkage long sys_chdir(const char *name);
+extern asmlinkage long sys_fchdir(int fd);
 extern asmlinkage long sys_chroot(const char *name);
 extern asmlinkage long sys_unlink(const char *name);
 extern asmlinkage long sys_symlink(const char *old, const char *new);
@@ -730,17 +731,13 @@
 }
 
 #ifdef CONFIG_BLK_DEV_INITRD
+static int old_fd, root_fd;
 static int do_linuxrc(void * shell)
 {
 	static char *argv[] = { "linuxrc", NULL, };
 	extern char * envp_init[];
 
-	sys_chdir("/root");
-	sys_mount(".", "/", NULL, MS_MOVE, NULL);
-	sys_chroot(".");
-
-	mount_devfs_fs ();
-
+	close(old_fd);close(root_fd);
 	close(0);close(1);close(2);
 	setsid();
 	(void) open("/dev/console",O_RDWR,0);
@@ -758,9 +755,16 @@
 	int i, pid;
 
 	create_dev("/dev/root.old", Root_RAM0, NULL);
+	/* mount initrd on rootfs' /root */
 	mount_block_root("/dev/root.old", root_mountflags & ~MS_RDONLY);
 	sys_mkdir("/old", 0700);
-	sys_chdir("/old");
+	root_fd = open("/", 0, 0);
+	old_fd = open("/old", 0, 0);
+	/* move initrd over / and chdir/chroot in initrd root */
+	sys_chdir("/root");
+	sys_mount(".", "/", NULL, MS_MOVE, NULL);
+	sys_chroot(".");
+	mount_devfs_fs ();
 
 	pid = kernel_thread(do_linuxrc, "/linuxrc", SIGCHLD);
 	if (pid > 0) {
@@ -768,7 +772,14 @@
 			yield();
 	}
 
-	sys_mount("..", ".", NULL, MS_MOVE, NULL);
+	/* move initrd to rootfs' /old */
+	sys_fchdir(old_fd);
+	sys_mount("/", ".", NULL, MS_MOVE, NULL);
+	/* switch root and cwd back to / of rootfs */
+	sys_fchdir(root_fd);
+	sys_chroot(".");
+	close(old_fd);
+	close(root_fd);
 	sys_umount("/old/dev", 0);
 
 	if (real_root_dev == Root_RAM0) {
diff -Nru a/init/main.c b/init/main.c
--- a/init/main.c	Mon Sep  9 10:36:01 2002
+++ b/init/main.c	Mon Sep  9 10:36:01 2002
@@ -490,16 +490,6 @@
  */
 static void __init do_basic_setup(void)
 {
-	/*
-	 * Tell the world that we're going to be the grim
-	 * reaper of innocent orphaned children.
-	 *
-	 * We don't want people to have to make incorrect
-	 * assumptions about where in the task array this
-	 * can be found.
-	 */
-	child_reaper = current;
-
 #if defined(CONFIG_MTRR)	/* Do this after SMP initialization */
 /*
  * We should probably create some architecture-dependent "fixup after
@@ -545,6 +535,16 @@
 	static char * argv_sh[] = { "sh", NULL, };
 
 	lock_kernel();
+	/*
+	 * Tell the world that we're going to be the grim
+	 * reaper of innocent orphaned children.
+	 *
+	 * We don't want people to have to make incorrect
+	 * assumptions about where in the task array this
+	 * can be found.
+	 */
+	child_reaper = current;
+
 	/* Sets up cpus_possible() */
 	smp_prepare_cpus(max_cpus);
 
diff -Nru a/kernel/exit.c b/kernel/exit.c
--- a/kernel/exit.c	Mon Sep  9 10:36:01 2002
+++ b/kernel/exit.c	Mon Sep  9 10:36:01 2002
@@ -36,7 +36,6 @@
 	nr_threads--;
 	unhash_pid(p);
 	REMOVE_LINKS(p);
-	list_del(&p->thread_group);
 	p->pid = 0;
 	proc_dentry = p->proc_dentry;
 	if (unlikely(proc_dentry != NULL)) {
@@ -66,9 +65,14 @@
 	atomic_dec(&p->user->processes);
 	security_ops->task_free_security(p);
 	free_uid(p->user);
-	BUG_ON(p->ptrace || !list_empty(&p->ptrace_list) ||
-					!list_empty(&p->ptrace_children));
+	if (unlikely(p->ptrace)) {
+		write_lock_irq(&tasklist_lock);
+		__ptrace_unlink(p);
+		write_unlock_irq(&tasklist_lock);
+	}
+	BUG_ON(!list_empty(&p->ptrace_list) || !list_empty(&p->ptrace_children));
 	unhash_process(p);
+	exit_sighand(p);
 
 	release_thread(p);
 	if (p != current) {
@@ -233,12 +237,15 @@
  	exit_files(current);
 	current->files = init_task.files;
 	atomic_inc(&current->files->count);
+
+	reparent_to_init();
 }
 
 static void reparent_thread(task_t *p, task_t *reaper, task_t *child_reaper)
 {
 	/* We dont want people slaying init */
-	p->exit_signal = SIGCHLD;
+	if (p->exit_signal != -1)
+		p->exit_signal = SIGCHLD;
 	p->self_exec_id++;
 
 	/* Make sure we're not reparenting to ourselves */
@@ -406,18 +413,15 @@
  */
 static inline void forget_original_parent(struct task_struct * father)
 {
-	struct task_struct *p, *reaper;
-	list_t *_p;
+	struct task_struct *p, *reaper = father;
+	struct list_head *_p;
 
-	read_lock(&tasklist_lock);
+	write_lock_irq(&tasklist_lock);
 
-	/* Next in our thread group, if they're not already exiting */
-	reaper = father;
-	do {
-		reaper = next_thread(reaper);
-		if (!(reaper->flags & PF_EXITING))
-			break;
-	} while (reaper != father);
+	if (father->exit_signal != -1)
+		reaper = prev_thread(reaper);
+	else
+		reaper = child_reaper;
 
 	if (reaper == father)
 		reaper = child_reaper;
@@ -426,7 +430,7 @@
 	 * There are only two places where our children can be:
 	 *
 	 * - in our child list
-	 * - in the global ptrace list
+	 * - in our ptraced child list
 	 *
 	 * Search them and reparent children.
 	 */
@@ -438,17 +442,29 @@
 		p = list_entry(_p,struct task_struct,ptrace_list);
 		reparent_thread(p, reaper, child_reaper);
 	}
-	read_unlock(&tasklist_lock);
+	write_unlock_irq(&tasklist_lock);
 }
 
-static inline void zap_thread(task_t *p, task_t *father)
+static inline void zap_thread(task_t *p, task_t *father, int traced)
 {
-	ptrace_unlink(p);
-	list_del_init(&p->sibling);
-	p->ptrace = 0;
+	/* If someone else is tracing this thread, preserve the ptrace links.  */
+	if (unlikely(traced)) {
+		task_t *trace_task = p->parent;
+		int ptrace_flag = p->ptrace;
+		BUG_ON (ptrace_flag == 0);
+
+		__ptrace_unlink(p);
+		p->ptrace = ptrace_flag;
+		__ptrace_link(p, trace_task);
+	} else {
+		/* Otherwise, if we were tracing this thread, untrace it.  */
+		ptrace_unlink (p);
+
+		list_del_init(&p->sibling);
+		p->parent = p->real_parent;
+		list_add_tail(&p->sibling, &p->parent->children);
+	}
 
-	p->parent = p->real_parent;
-	list_add_tail(&p->sibling, &p->parent->children);
 	if (p->state == TASK_ZOMBIE && p->exit_signal != -1)
 		do_notify_parent(p, p->exit_signal);
 	/*
@@ -477,7 +493,7 @@
 static void exit_notify(void)
 {
 	struct task_struct *t;
-	list_t *_p, *_n;
+	struct list_head *_p, *_n;
 
 	forget_original_parent(current);
 	/*
@@ -516,7 +532,7 @@
 	 *	
 	 */
 	
-	if(current->exit_signal != SIGCHLD &&
+	if (current->exit_signal != SIGCHLD && current->exit_signal != -1 &&
 	    ( current->parent_exec_id != t->self_exec_id  ||
 	      current->self_exec_id != current->parent_exec_id) 
 	    && !capable(CAP_KILL))
@@ -539,11 +555,11 @@
 
 zap_again:
 	list_for_each_safe(_p, _n, &current->children)
-		zap_thread(list_entry(_p,struct task_struct,sibling), current);
+		zap_thread(list_entry(_p,struct task_struct,sibling), current, 0);
 	list_for_each_safe(_p, _n, &current->ptrace_children)
-		zap_thread(list_entry(_p,struct task_struct,ptrace_list), current);
+		zap_thread(list_entry(_p,struct task_struct,ptrace_list), current, 1);
 	/*
-	 * reparent_thread might drop the tasklist lock, thus we could
+	 * zap_thread might drop the tasklist lock, thus we could
 	 * have new children queued back from the ptrace list into the
 	 * child list:
 	 */
@@ -586,7 +602,6 @@
 	__exit_files(tsk);
 	__exit_fs(tsk);
 	exit_namespace(tsk);
-	exit_sighand(tsk);
 	exit_thread();
 
 	if (current->leader)
@@ -632,6 +647,41 @@
 	do_exit((error_code&0xff)<<8);
 }
 
+static inline int eligible_child(pid_t pid, int options, task_t *p)
+{
+	if (pid>0) {
+		if (p->pid != pid)
+			return 0;
+	} else if (!pid) {
+		if (p->pgrp != current->pgrp)
+			return 0;
+	} else if (pid != -1) {
+		if (p->pgrp != -pid)
+			return 0;
+	}
+
+	/*
+	 * Do not consider detached threads that are
+	 * not ptraced:
+	 */
+	if (p->exit_signal == -1 && !p->ptrace)
+		return 0;
+
+	/* Wait for all children (clone and not) if __WALL is set;
+	 * otherwise, wait for clone children *only* if __WCLONE is
+	 * set; otherwise, wait for non-clone children *only*.  (Note:
+	 * A "clone" child here is one that reports to its parent
+	 * using a signal other than SIGCHLD.) */
+	if (((p->exit_signal != SIGCHLD) ^ ((options & __WCLONE) != 0))
+	    && !(options & __WALL))
+		return 0;
+
+	if (security_ops->task_wait(p))
+		return 0;
+
+	return 1;
+}
+
 asmlinkage long sys_wait4(pid_t pid,unsigned int * stat_addr, int options, struct rusage * ru)
 {
 	int flag, retval;
@@ -652,34 +702,8 @@
 		struct list_head *_p;
 		list_for_each(_p,&tsk->children) {
 			p = list_entry(_p,struct task_struct,sibling);
-			if (pid>0) {
-				if (p->pid != pid)
-					continue;
-			} else if (!pid) {
-				if (p->pgrp != current->pgrp)
-					continue;
-			} else if (pid != -1) {
-				if (p->pgrp != -pid)
-					continue;
-			}
-			/*
-			 * Do not consider detached threads that are
-			 * not ptraced:
-			 */
-			if (p->exit_signal == -1 && !p->ptrace)
+			if (!eligible_child(pid, options, p))
 				continue;
-			/* Wait for all children (clone and not) if __WALL is set;
-			 * otherwise, wait for clone children *only* if __WCLONE is
-			 * set; otherwise, wait for non-clone children *only*.  (Note:
-			 * A "clone" child here is one that reports to its parent
-			 * using a signal other than SIGCHLD.) */
-			if (((p->exit_signal != SIGCHLD) ^ ((options & __WCLONE) != 0))
-			    && !(options & __WALL))
-				continue;
-
-			if (security_ops->task_wait(p))
-				continue;
-
 			flag = 1;
 			switch (p->state) {
 			case TASK_STOPPED:
@@ -714,28 +738,33 @@
 				retval = p->pid;
 				if (p->real_parent != p->parent) {
 					write_lock_irq(&tasklist_lock);
-					ptrace_unlink(p);
+					__ptrace_unlink(p);
 					do_notify_parent(p, SIGCHLD);
 					write_unlock_irq(&tasklist_lock);
-				} else {
-					if (p->ptrace) {
-						write_lock_irq(&tasklist_lock);
-						ptrace_unlink(p);
-						write_unlock_irq(&tasklist_lock);
-					}
+				} else
 					release_task(p);
-				}
 				goto end_wait4;
 			default:
 				continue;
 			}
 		}
+		if (!flag) {
+			list_for_each (_p,&tsk->ptrace_children) {
+				p = list_entry(_p,struct task_struct,ptrace_list);
+				if (!eligible_child(pid, options, p))
+					continue;
+				flag = 1;
+				break;
+			}
+		}
 		if (options & __WNOTHREAD)
 			break;
 		tsk = next_thread(tsk);
+		if (tsk->sig != current->sig)
+			BUG();
 	} while (tsk != current);
 	read_unlock(&tasklist_lock);
-	if (flag || !list_empty(&current->ptrace_children)) {
+	if (flag) {
 		retval = 0;
 		if (options & WNOHANG)
 			goto end_wait4;
diff -Nru a/kernel/fork.c b/kernel/fork.c
--- a/kernel/fork.c	Mon Sep  9 10:35:56 2002
+++ b/kernel/fork.c	Mon Sep  9 10:35:56 2002
@@ -46,6 +46,14 @@
 
 int max_threads;
 unsigned long total_forks;	/* Handle normal Linux uptimes. */
+
+/*
+ * Protects next_safe, last_pid and pid_max:
+ */
+spinlock_t lastpid_lock = SPIN_LOCK_UNLOCKED;
+
+static int next_safe = DEFAULT_PID_MAX;
+int pid_max = DEFAULT_PID_MAX;
 int last_pid;
 
 struct task_struct *pidhash[PIDHASH_SZ];
@@ -151,11 +159,8 @@
 	return tsk;
 }
 
-spinlock_t lastpid_lock = SPIN_LOCK_UNLOCKED;
-
 static int get_pid(unsigned long flags)
 {
-	static int next_safe = PID_MAX;
 	struct task_struct *p;
 	int pid;
 
@@ -163,34 +168,35 @@
 		return 0;
 
 	spin_lock(&lastpid_lock);
-	if((++last_pid) & ~PID_MASK) {
+	if (++last_pid > pid_max) {
 		last_pid = 300;		/* Skip daemons etc. */
 		goto inside;
 	}
-	if(last_pid >= next_safe) {
+
+	if (last_pid >= next_safe) {
 inside:
-		next_safe = PID_MAX;
+		next_safe = pid_max;
 		read_lock(&tasklist_lock);
 	repeat:
 		for_each_task(p) {
-			if(p->pid == last_pid	||
+			if (p->pid == last_pid	||
 			   p->pgrp == last_pid	||
 			   p->tgid == last_pid	||
 			   p->session == last_pid) {
-				if(++last_pid >= next_safe) {
-					if(last_pid & ~PID_MASK)
+				if (++last_pid >= next_safe) {
+					if (last_pid >= pid_max)
 						last_pid = 300;
-					next_safe = PID_MAX;
+					next_safe = pid_max;
 				}
 				goto repeat;
 			}
-			if(p->pid > last_pid && next_safe > p->pid)
+			if (p->pid > last_pid && next_safe > p->pid)
 				next_safe = p->pid;
-			if(p->pgrp > last_pid && next_safe > p->pgrp)
+			if (p->pgrp > last_pid && next_safe > p->pgrp)
 				next_safe = p->pgrp;
-			if(p->tgid > last_pid && next_safe > p->tgid)
+			if (p->tgid > last_pid && next_safe > p->tgid)
 				next_safe = p->tgid;
-			if(p->session > last_pid && next_safe > p->session)
+			if (p->session > last_pid && next_safe > p->session)
 				next_safe = p->session;
 		}
 		read_unlock(&tasklist_lock);
@@ -624,6 +630,9 @@
 	spin_lock_init(&sig->siglock);
 	atomic_set(&sig->count, 1);
 	memcpy(tsk->sig->action, current->sig->action, sizeof(tsk->sig->action));
+	sig->curr_target = NULL;
+	init_sigpending(&sig->shared_pending);
+
 	return 0;
 }
 
@@ -658,6 +667,12 @@
 	if ((clone_flags & (CLONE_NEWNS|CLONE_FS)) == (CLONE_NEWNS|CLONE_FS))
 		return ERR_PTR(-EINVAL);
 
+	/*
+	 * Thread groups must share signals as well:
+	 */
+	if (clone_flags & CLONE_THREAD)
+		clone_flags |= CLONE_SIGHAND;
+
 	retval = security_ops->task_create(clone_flags);
 	if (retval)
 		goto fork_out;
@@ -830,21 +845,22 @@
 	write_lock_irq(&tasklist_lock);
 
 	/* CLONE_PARENT re-uses the old parent */
-	p->real_parent = current->real_parent;
-	p->parent = current->parent;
-	if (!(clone_flags & CLONE_PARENT)) {
+	if (clone_flags & CLONE_PARENT)
+		p->real_parent = current->real_parent;
+	else
 		p->real_parent = current;
-		if (!(p->ptrace & PT_PTRACED))
-			p->parent = current;
-	}
+	p->parent = p->real_parent;
 
 	if (clone_flags & CLONE_THREAD) {
+		spin_lock(&current->sig->siglock);
 		p->tgid = current->tgid;
 		list_add(&p->thread_group, &current->thread_group);
+		spin_unlock(&current->sig->siglock);
 	}
 
 	SET_LINKS(p);
-	ptrace_link(p, p->parent);
+	if (p->ptrace & PT_PTRACED)
+		__ptrace_link(p, current->parent);
 	hash_pid(p);
 	nr_threads++;
 	write_unlock_irq(&tasklist_lock);
diff -Nru a/kernel/futex.c b/kernel/futex.c
--- a/kernel/futex.c	Mon Sep  9 10:36:01 2002
+++ b/kernel/futex.c	Mon Sep  9 10:36:01 2002
@@ -276,9 +276,14 @@
 	filp->f_dentry = dget(futex_mnt->mnt_root);
 
 	if (signal) {
-		filp->f_owner.pid = current->tgid;
-		filp->f_owner.uid = current->uid;
-		filp->f_owner.euid = current->euid;
+		int ret;
+		
+		ret = f_setown(filp, current->tgid, 1);
+		if (ret) {
+			put_unused_fd(fd);
+			put_filp(filp);
+			return ret;
+		}
 		filp->f_owner.signum = signal;
 	}
 
diff -Nru a/kernel/ksyms.c b/kernel/ksyms.c
--- a/kernel/ksyms.c	Mon Sep  9 10:35:51 2002
+++ b/kernel/ksyms.c	Mon Sep  9 10:35:51 2002
@@ -335,17 +335,13 @@
 EXPORT_SYMBOL(bdev_read_only);
 EXPORT_SYMBOL(set_device_ro);
 EXPORT_SYMBOL(bmap);
-EXPORT_SYMBOL(devfs_register_partitions);
-EXPORT_SYMBOL(driverfs_remove_partitions);
 EXPORT_SYMBOL(blkdev_open);
 EXPORT_SYMBOL(blkdev_get);
 EXPORT_SYMBOL(blkdev_put);
 EXPORT_SYMBOL(ioctl_by_bdev);
-EXPORT_SYMBOL(grok_partitions);
 EXPORT_SYMBOL(register_disk);
 EXPORT_SYMBOL(read_dev_sector);
 EXPORT_SYMBOL(init_buffer);
-EXPORT_SYMBOL(wipe_partitions);
 EXPORT_SYMBOL_GPL(generic_file_direct_IO);
 
 /* tty routines */
@@ -524,7 +520,6 @@
 EXPORT_SYMBOL(get_random_bytes);
 EXPORT_SYMBOL(securebits);
 EXPORT_SYMBOL(cap_bset);
-EXPORT_SYMBOL(reparent_to_init);
 EXPORT_SYMBOL(daemonize);
 EXPORT_SYMBOL(csum_partial); /* for networking and md */
 EXPORT_SYMBOL(seq_escape);
diff -Nru a/kernel/ptrace.c b/kernel/ptrace.c
--- a/kernel/ptrace.c	Mon Sep  9 10:36:18 2002
+++ b/kernel/ptrace.c	Mon Sep  9 10:36:18 2002
@@ -29,7 +29,7 @@
 	if (!list_empty(&child->ptrace_list))
 		BUG();
 	if (child->parent == new_parent)
-		BUG();
+		return;
 	list_add(&child->ptrace_list, &child->parent->ptrace_children);
 	REMOVE_LINKS(child);
 	child->parent = new_parent;
diff -Nru a/kernel/sched.c b/kernel/sched.c
--- a/kernel/sched.c	Mon Sep  9 10:36:01 2002
+++ b/kernel/sched.c	Mon Sep  9 10:36:01 2002
@@ -133,7 +133,7 @@
 struct prio_array {
 	int nr_active;
 	unsigned long bitmap[BITMAP_SIZE];
-	list_t queue[MAX_PRIO];
+	struct list_head queue[MAX_PRIO];
 };
 
 /*
@@ -152,7 +152,7 @@
 	int prev_nr_running[NR_CPUS];
 
 	task_t *migration_thread;
-	list_t migration_queue;
+	struct list_head migration_queue;
 
 } ____cacheline_aligned;
 
@@ -739,7 +739,7 @@
 	int imbalance, idx, this_cpu = smp_processor_id();
 	runqueue_t *busiest;
 	prio_array_t *array;
-	list_t *head, *curr;
+	struct list_head *head, *curr;
 	task_t *tmp;
 
 	busiest = find_busiest_queue(this_rq, this_cpu, idle, &imbalance);
@@ -937,7 +937,7 @@
 	task_t *prev, *next;
 	runqueue_t *rq;
 	prio_array_t *array;
-	list_t *queue;
+	struct list_head *queue;
 	int idx;
 
 	if (unlikely(in_interrupt()))
@@ -1032,15 +1032,12 @@
 {
 	struct thread_info *ti = current_thread_info();
 
-	if (unlikely(ti->preempt_count))
-		return;
-	if (unlikely(irqs_disabled())) {
-		preempt_disable();
-		printk("bad: schedule() with irqs disabled!\n");
-		show_stack(NULL);
-		preempt_enable_no_resched();
+	/*
+	 * If there is a non-zero preempt_count or interrupts are disabled,
+	 * we do not want to preempt the current task.  Just return..
+	 */
+	if (unlikely(ti->preempt_count || irqs_disabled()))
 		return;
-	}
 
 need_resched:
 	ti->preempt_count = PREEMPT_ACTIVE;
@@ -1339,6 +1336,15 @@
 }
 
 /**
+ * task_curr - is this task currently executing on a CPU?
+ * @p: the task in question.
+ */
+int task_curr(task_t *p)
+{
+	return cpu_curr(task_cpu(p)) == p;
+}
+
+/**
  * idle_cpu - is a given cpu idle currently?
  * @cpu: the processor in question.
  */
@@ -1899,7 +1905,7 @@
  */
 
 typedef struct {
-	list_t list;
+	struct list_head list;
 	task_t *task;
 	struct completion done;
 } migration_req_t;
diff -Nru a/kernel/signal.c b/kernel/signal.c
--- a/kernel/signal.c	Mon Sep  9 10:36:11 2002
+++ b/kernel/signal.c	Mon Sep  9 10:36:11 2002
@@ -6,6 +6,8 @@
  *  1997-11-02  Modified for POSIX.1b signals by Richard Henderson
  */
 
+#define __KERNEL_SYSCALLS__
+
 #include <linux/config.h>
 #include <linux/slab.h>
 #include <linux/module.h>
@@ -16,7 +18,7 @@
 #include <linux/fs.h>
 #include <linux/tty.h>
 #include <linux/binfmts.h>
-
+#include <asm/param.h>
 #include <asm/uaccess.h>
 #include <asm/siginfo.h>
 
@@ -24,40 +26,146 @@
  * SLAB caches for signal bits.
  */
 
-#define DEBUG_SIG 0
-
-#if DEBUG_SIG
-#define SIG_SLAB_DEBUG	(SLAB_RED_ZONE /* | SLAB_POISON */)
-#else
-#define SIG_SLAB_DEBUG	0
-#endif
-
 static kmem_cache_t *sigqueue_cachep;
 
 atomic_t nr_queued_signals;
 int max_queued_signals = 1024;
 
+/*********************************************************
+
+    POSIX thread group signal behavior:
+
+----------------------------------------------------------
+|                    |  userspace       |  kernel        |
+----------------------------------------------------------
+|  SIGHUP            |  load-balance    |  kill-all      |
+|  SIGINT            |  load-balance    |  kill-all      |
+|  SIGQUIT           |  load-balance    |  kill-all+core |
+|  SIGILL            |  specific        |  kill-all+core |
+|  SIGTRAP           |  specific        |  kill-all+core |
+|  SIGABRT/SIGIOT    |  specific        |  kill-all+core |
+|  SIGBUS            |  specific        |  kill-all+core |
+|  SIGFPE            |  specific        |  kill-all+core |
+|  SIGKILL           |  n/a             |  kill-all      |
+|  SIGUSR1           |  load-balance    |  kill-all      |
+|  SIGSEGV           |  specific        |  kill-all+core |
+|  SIGUSR2           |  load-balance    |  kill-all      |
+|  SIGPIPE           |  specific        |  kill-all      |
+|  SIGALRM           |  load-balance    |  kill-all      |
+|  SIGTERM           |  load-balance    |  kill-all      |
+|  SIGCHLD           |  load-balance    |  ignore        |
+|  SIGCONT           |  specific        |  continue-all  |
+|  SIGSTOP           |  n/a             |  stop-all      |
+|  SIGTSTP           |  load-balance    |  stop-all      |
+|  SIGTTIN           |  load-balance    |  stop-all      |
+|  SIGTTOU           |  load-balance    |  stop-all      |
+|  SIGURG            |  load-balance    |  ignore        |
+|  SIGXCPU           |  specific        |  kill-all+core |
+|  SIGXFSZ           |  specific        |  kill-all+core |
+|  SIGVTALRM         |  load-balance    |  kill-all      |
+|  SIGPROF           |  specific        |  kill-all      |
+|  SIGPOLL/SIGIO     |  load-balance    |  kill-all      |
+|  SIGSYS/SIGUNUSED  |  specific        |  kill-all+core |
+|  SIGSTKFLT         |  specific        |  kill-all      |
+|  SIGWINCH          |  load-balance    |  ignore        |
+|  SIGPWR            |  load-balance    |  kill-all      |
+|  SIGRTMIN-SIGRTMAX |  load-balance    |  kill-all      |
+----------------------------------------------------------
+*/
+
+#define M(sig) (1UL << (sig))
+
+#define SIG_USER_SPECIFIC_MASK (\
+	M(SIGILL)    |  M(SIGTRAP)   |  M(SIGABRT)   |  M(SIGBUS)    | \
+	M(SIGFPE)    |  M(SIGSEGV)   |  M(SIGPIPE)   |  M(SIGXFSZ)   | \
+	M(SIGPROF)   |  M(SIGSYS)    |  M(SIGSTKFLT) |  M(SIGCONT)   )
+
+#define SIG_USER_LOAD_BALANCE_MASK (\
+        M(SIGHUP)    |  M(SIGINT)    |  M(SIGQUIT)   |  M(SIGUSR1)   | \
+        M(SIGUSR2)   |  M(SIGALRM)   |  M(SIGTERM)   |  M(SIGCHLD)   | \
+        M(SIGURG)    |  M(SIGVTALRM) |  M(SIGPOLL)   |  M(SIGWINCH)  | \
+        M(SIGPWR)    |  M(SIGTSTP)   |  M(SIGTTIN)   |  M(SIGTTOU)   )
+
+#define SIG_KERNEL_SPECIFIC_MASK (\
+        M(SIGCHLD)   |   M(SIGURG)   |  M(SIGWINCH)                  )
+
+#define SIG_KERNEL_BROADCAST_MASK (\
+	M(SIGHUP)    |  M(SIGINT)    |  M(SIGQUIT)   |  M(SIGILL)    | \
+	M(SIGTRAP)   |  M(SIGABRT)   |  M(SIGBUS)    |  M(SIGFPE)    | \
+	M(SIGKILL)   |  M(SIGUSR1)   |  M(SIGSEGV)   |  M(SIGUSR2)   | \
+	M(SIGPIPE)   |  M(SIGALRM)   |  M(SIGTERM)   |  M(SIGXCPU)   | \
+	M(SIGXFSZ)   |  M(SIGVTALRM) |  M(SIGPROF)   |  M(SIGPOLL)   | \
+	M(SIGSYS)    |  M(SIGSTKFLT) |  M(SIGPWR)    |  M(SIGCONT)   | \
+        M(SIGSTOP)   |  M(SIGTSTP)   |  M(SIGTTIN)   |  M(SIGTTOU)   )
+
+#define SIG_KERNEL_ONLY_MASK (\
+	M(SIGKILL)   |  M(SIGSTOP)                                   )
+
+#define SIG_KERNEL_COREDUMP_MASK (\
+        M(SIGQUIT)   |  M(SIGILL)    |  M(SIGTRAP)   |  M(SIGABRT)   | \
+        M(SIGFPE)    |  M(SIGSEGV)   |  M(SIGBUS)    |  M(SIGSYS)    | \
+        M(SIGXCPU)   |  M(SIGXFSZ)                                   )
+
+#define T(sig, mask) \
+	((1UL << (sig)) & mask)
+
+#define sig_user_specific(sig)		T(sig, SIG_USER_SPECIFIC_MASK)
+#define sig_user_load_balance(sig) \
+		(T(sig, SIG_USER_LOAD_BALANCE_MASK) || ((sig) >= SIGRTMIN))
+#define sig_kernel_specific(sig)	T(sig, SIG_KERNEL_SPECIFIC_MASK)
+#define sig_kernel_broadcast(sig) \
+		(T(sig, SIG_KERNEL_BROADCAST_MASK) || ((sig) >= SIGRTMIN))
+#define sig_kernel_only(sig)		T(sig, SIG_KERNEL_ONLY_MASK)
+#define sig_kernel_coredump(sig)	T(sig, SIG_KERNEL_COREDUMP_MASK)
+
+#define sig_user_defined(t, sig) \
+	(((t)->sig->action[(sig)-1].sa.sa_handler != SIG_DFL) &&	\
+	 ((t)->sig->action[(sig)-1].sa.sa_handler != SIG_IGN))
+
+#define sig_ignored(t, sig) \
+	(((sig) != SIGCHLD) && \
+		((t)->sig->action[(sig)-1].sa.sa_handler == SIG_IGN))
+
 void __init signals_init(void)
 {
 	sigqueue_cachep =
 		kmem_cache_create("sigqueue",
 				  sizeof(struct sigqueue),
 				  __alignof__(struct sigqueue),
-				  SIG_SLAB_DEBUG, NULL, NULL);
+				  0, NULL, NULL);
 	if (!sigqueue_cachep)
 		panic("signals_init(): cannot create sigqueue SLAB cache");
 }
 
+#define PENDING(p,b) has_pending_signals(&(p)->signal, (b))
+
+void recalc_sigpending_tsk(struct task_struct *t)
+{
+	if (PENDING(&t->pending, &t->blocked) ||
+			PENDING(&t->sig->shared_pending, &t->blocked))
+		set_tsk_thread_flag(t, TIF_SIGPENDING);
+	else
+		clear_tsk_thread_flag(t, TIF_SIGPENDING);
+}
+
+void recalc_sigpending(void)
+{
+	if (PENDING(&current->pending, &current->blocked) ||
+		    PENDING(&current->sig->shared_pending, &current->blocked))
+		set_thread_flag(TIF_SIGPENDING);
+	else
+		clear_thread_flag(TIF_SIGPENDING);
+}
 
 /* Given the mask, find the first available signal that should be serviced. */
 
 static int
-next_signal(struct task_struct *tsk, sigset_t *mask)
+next_signal(struct sigpending *pending, sigset_t *mask)
 {
 	unsigned long i, *s, *m, x;
 	int sig = 0;
 	
-	s = tsk->pending.signal.sig;
+	s = pending->signal.sig;
 	m = mask->sig;
 	switch (_NSIG_WORDS) {
 	default:
@@ -113,15 +221,36 @@
 	flush_sigqueue(&t->pending);
 }
 
+void remove_thread_group(struct task_struct *tsk, struct signal_struct *sig)
+{
+	write_lock_irq(&tasklist_lock);
+	spin_lock(&tsk->sig->siglock);
+
+	if (tsk == sig->curr_target)
+		sig->curr_target = next_thread(tsk);
+	list_del_init(&tsk->thread_group);
+
+	spin_unlock(&tsk->sig->siglock);
+	write_unlock_irq(&tasklist_lock);
+}
+
 void exit_sighand(struct task_struct *tsk)
 {
 	struct signal_struct * sig = tsk->sig;
 
+	if (!sig)
+		BUG();
+	if (!atomic_read(&sig->count))
+		BUG();
+	remove_thread_group(tsk, sig);
+
 	spin_lock_irq(&tsk->sigmask_lock);
 	if (sig) {
 		tsk->sig = NULL;
-		if (atomic_dec_and_test(&sig->count))
+		if (atomic_dec_and_test(&sig->count)) {
+			flush_sigqueue(&sig->shared_pending);
 			kmem_cache_free(sigact_cachep, sig);
+		}
 	}
 	clear_tsk_thread_flag(tsk,TIF_SIGPENDING);
 	flush_sigqueue(&tsk->pending);
@@ -153,24 +282,10 @@
 void
 sig_exit(int sig, int exit_code, struct siginfo *info)
 {
-	struct task_struct *t;
-
 	sigaddset(&current->pending.signal, sig);
 	recalc_sigpending();
 	current->flags |= PF_SIGNALED;
 
-	/* Propagate the signal to all the tasks in
-	 *  our thread group
-	 */
-	if (info && (unsigned long)info != 1
-	    && info->si_code != SI_TKILL) {
-		read_lock(&tasklist_lock);
-		for_each_thread(t) {
-			force_sig_info(sig, info, t);
-		}
-		read_unlock(&tasklist_lock);
-	}
-
 	do_exit(exit_code);
 	/* NOTREACHED */
 }
@@ -209,7 +324,7 @@
 	spin_unlock_irqrestore(&current->sigmask_lock, flags);
 }
 
-static int collect_signal(int sig, struct sigpending *list, siginfo_t *info)
+static inline int collect_signal(int sig, struct sigpending *list, siginfo_t *info)
 {
 	if (sigismember(&list->signal, sig)) {
 		/* Collect the siginfo appropriate to this signal.  */
@@ -221,9 +336,10 @@
 			pp = &q->next;
 		}
 
-		/* Ok, it wasn't in the queue.  We must have
-		   been out of queue space.  So zero out the
-		   info.  */
+		/* Ok, it wasn't in the queue.  This must be
+		   a fast-pathed signal or we must have been
+		   out of queue space.  So zero out the info.
+		 */
 		sigdelset(&list->signal, sig);
 		info->si_signo = sig;
 		info->si_errno = 0;
@@ -261,20 +377,14 @@
  * Dequeue a signal and return the element to the caller, which is 
  * expected to free it.
  *
- * All callers must be holding current->sigmask_lock.
+ * All callers have to hold the siglock and the sigmask_lock.
  */
 
-int
-dequeue_signal(sigset_t *mask, siginfo_t *info)
+int dequeue_signal(struct sigpending *pending, sigset_t *mask, siginfo_t *info)
 {
 	int sig = 0;
 
-#if DEBUG_SIG
-printk(KERN_DEBUG "SIG dequeue (%s:%d): %d ", current->comm, current->pid,
-	signal_pending(current));
-#endif
-
-	sig = next_signal(current, mask);
+	sig = next_signal(pending, mask);
 	if (sig) {
 		if (current->notifier) {
 			if (sigismember(current->notifier_mask, sig)) {
@@ -285,7 +395,7 @@
 			}
 		}
 
-		if (!collect_signal(sig, &current->pending, info))
+		if (!collect_signal(sig, pending, info))
 			sig = 0;
 				
 		/* XXX: Once POSIX.1b timers are in, if si_code == SI_TIMER,
@@ -293,10 +403,6 @@
 	}
 	recalc_sigpending();
 
-#if DEBUG_SIG
-printk(KERN_DEBUG " %d -> %d\n", signal_pending(current), sig);
-#endif
-
 	return sig;
 }
 
@@ -338,9 +444,10 @@
 /*
  * Bad permissions for sending the signal
  */
-int bad_signal(int sig, struct siginfo *info, struct task_struct *t)
+static inline int bad_signal(int sig, struct siginfo *info, struct task_struct *t)
 {
-	return (!info || ((unsigned long)info != 1 && SI_FROMUSER(info)))
+	return (!info || ((unsigned long)info != 1 &&
+			(unsigned long)info != 2 && SI_FROMUSER(info)))
 	    && ((sig != SIGCONT) || (current->session != t->session))
 	    && (current->euid ^ t->suid) && (current->euid ^ t->uid)
 	    && (current->uid ^ t->suid) && (current->uid ^ t->uid)
@@ -436,6 +543,13 @@
 {
 	struct sigqueue * q = NULL;
 
+	/*
+	 * fast-pathed signals for kernel-internal things like SIGSTOP
+	 * or SIGKILL.
+	 */
+	if ((unsigned long)info == 2)
+		goto out_set;
+
 	/* Real-time signals must be queued if sent by sigqueue, or
 	   some other real-time mechanism.  It is implementation
 	   defined whether kill() does so.  We attempt to do so, on
@@ -444,9 +558,8 @@
 	   make sure at least one signal gets delivered and don't
 	   pass on the info struct.  */
 
-	if (atomic_read(&nr_queued_signals) < max_queued_signals) {
+	if (atomic_read(&nr_queued_signals) < max_queued_signals)
 		q = kmem_cache_alloc(sigqueue_cachep, GFP_ATOMIC);
-	}
 
 	if (q) {
 		atomic_inc(&nr_queued_signals);
@@ -473,14 +586,14 @@
 				break;
 		}
 	} else if (sig >= SIGRTMIN && info && (unsigned long)info != 1
-		   && info->si_code != SI_USER) {
+		   && info->si_code != SI_USER)
 		/*
 		 * Queue overflow, abort.  We may abort if the signal was rt
 		 * and sent by user using something other than kill().
 		 */
 		return -EAGAIN;
-	}
 
+out_set:
 	sigaddset(&signals->signal, sig);
 	return 0;
 }
@@ -528,17 +641,17 @@
 	return retval;
 }
 
-int
-send_sig_info(int sig, struct siginfo *info, struct task_struct *t)
+static int
+__send_sig_info(int sig, struct siginfo *info, struct task_struct *t, int shared)
 {
-	unsigned long flags;
 	int ret;
 
-
-#if DEBUG_SIG
-printk(KERN_DEBUG "SIG queue (%s:%d): %d ", t->comm, t->pid, sig);
+	if (!irqs_disabled())
+		BUG();
+#if CONFIG_SMP
+	if (!spin_is_locked(&t->sig->siglock))
+		BUG();
 #endif
-
 	ret = -EINVAL;
 	if (sig < 0 || sig > _NSIG)
 		goto out_nolock;
@@ -556,7 +669,7 @@
 	if (!sig || !t->sig)
 		goto out_nolock;
 
-	spin_lock_irqsave(&t->sigmask_lock, flags);
+	spin_lock(&t->sigmask_lock);
 	handle_stop_signal(sig, t);
 
 	/* Optimize away the signal, if it's a signal that can be
@@ -566,20 +679,25 @@
 	if (ignored_signal(sig, t))
 		goto out;
 
-	/* Support queueing exactly one non-rt signal, so that we
-	   can get more detailed information about the cause of
-	   the signal. */
-	if (sig < SIGRTMIN && sigismember(&t->pending.signal, sig))
-		goto out;
+#define LEGACY_QUEUE(sigptr, sig) \
+	(((sig) < SIGRTMIN) && sigismember(&(sigptr)->signal, (sig)))
+
+	if (!shared) {
+		/* Support queueing exactly one non-rt signal, so that we
+		   can get more detailed information about the cause of
+		   the signal. */
+		if (LEGACY_QUEUE(&t->pending, sig))
+			goto out;
 
-	ret = deliver_signal(sig, info, t);
+		ret = deliver_signal(sig, info, t);
+	} else {
+		if (LEGACY_QUEUE(&t->sig->shared_pending, sig))
+			goto out;
+		ret = send_signal(sig, info, &t->sig->shared_pending);
+	}
 out:
-	spin_unlock_irqrestore(&t->sigmask_lock, flags);
+	spin_unlock(&t->sigmask_lock);
 out_nolock:
-#if DEBUG_SIG
-printk(KERN_DEBUG " %d -> %d\n", signal_pending(t), ret);
-#endif
-
 	return ret;
 }
 
@@ -605,7 +723,157 @@
 	recalc_sigpending_tsk(t);
 	spin_unlock_irqrestore(&t->sigmask_lock, flags);
 
-	return send_sig_info(sig, info, t);
+	return send_sig_info(sig, (void *)1, t);
+}
+
+static int
+__force_sig_info(int sig, struct task_struct *t)
+{
+	unsigned long int flags;
+
+	spin_lock_irqsave(&t->sigmask_lock, flags);
+	if (t->sig == NULL) {
+		spin_unlock_irqrestore(&t->sigmask_lock, flags);
+		return -ESRCH;
+	}
+
+	if (t->sig->action[sig-1].sa.sa_handler == SIG_IGN)
+		t->sig->action[sig-1].sa.sa_handler = SIG_DFL;
+	sigdelset(&t->blocked, sig);
+	recalc_sigpending_tsk(t);
+	spin_unlock_irqrestore(&t->sigmask_lock, flags);
+
+	return __send_sig_info(sig, (void *)2, t, 0);
+}
+
+#define can_take_signal(p, sig)	\
+	(((unsigned long) p->sig->action[sig-1].sa.sa_handler > 1) && \
+	!sigismember(&p->blocked, sig) && (task_curr(p) || !signal_pending(p)))
+
+static inline
+int load_balance_thread_group(struct task_struct *p, int sig,
+				struct siginfo *info)
+{
+	struct task_struct *tmp;
+	int ret;
+
+	/*
+	 * if the specified thread is not blocking this signal
+	 * then deliver it.
+	 */
+	if (can_take_signal(p, sig))
+		return __send_sig_info(sig, info, p, 0);
+
+	/*
+	 * Otherwise try to find a suitable thread.
+	 * If no such thread is found then deliver to
+	 * the original thread.
+	 */
+
+	tmp = p->sig->curr_target;
+
+	if (!tmp || tmp->tgid != p->tgid)
+		/* restart balancing at this thread */
+		p->sig->curr_target = p;
+
+	else for (;;) {
+		if (list_empty(&p->thread_group))
+			BUG();
+		if (!tmp || tmp->tgid != p->tgid)
+			BUG();
+
+		/*
+		 * Do not send signals that are ignored or blocked,
+		 * or to not-running threads that are overworked:
+		 */
+		if (!can_take_signal(tmp, sig)) {
+			tmp = next_thread(tmp);
+			p->sig->curr_target = tmp;
+			if (tmp == p)
+				break;
+			continue;
+		}
+		ret = __send_sig_info(sig, info, tmp, 0);
+		return ret;
+	}
+	/*
+	 * No suitable thread was found - put the signal
+	 * into the shared-pending queue.
+	 */
+	return __send_sig_info(sig, info, p, 1);
+}
+
+int __broadcast_thread_group(struct task_struct *p, int sig)
+{
+	struct task_struct *tmp;
+	struct list_head *entry;
+	int err = 0;
+
+	/* send a signal to the head of the list */
+	err = __force_sig_info(sig, p);
+
+	/* send a signal to all members of the list */
+	list_for_each(entry, &p->thread_group) {
+		tmp = list_entry(entry, task_t, thread_group);
+		err = __force_sig_info(sig, tmp);
+	}
+	return err;
+}
+
+int
+send_sig_info(int sig, struct siginfo *info, struct task_struct *p)
+{
+	unsigned long flags;
+	int ret = 0;
+
+	if (!p)
+		BUG();
+	if (!p->sig)
+		BUG();
+	spin_lock_irqsave(&p->sig->siglock, flags);
+
+	/* not a thread group - normal signal behavior */
+	if (list_empty(&p->thread_group) || !sig)
+		goto out_send;
+
+	if (sig_user_defined(p, sig)) {
+		if (sig_user_specific(sig))
+			goto out_send;
+		if (sig_user_load_balance(sig)) {
+			ret = load_balance_thread_group(p, sig, info);
+			goto out_unlock;
+		}
+
+		/* must not happen */
+		BUG();
+	}
+	/* optimize away ignored signals: */
+	if (sig_ignored(p, sig))
+		goto out_unlock;
+
+	/* blocked (or ptraced) signals get posted */
+	spin_lock(&p->sigmask_lock);
+	if ((p->ptrace & PT_PTRACED) || sigismember(&p->blocked, sig) ||
+					sigismember(&p->real_blocked, sig)) {
+		spin_unlock(&p->sigmask_lock);
+		goto out_send;
+	}
+	spin_unlock(&p->sigmask_lock);
+
+	if (sig_kernel_broadcast(sig) || sig_kernel_coredump(sig)) {
+		ret = __broadcast_thread_group(p, sig);
+		goto out_unlock;
+	}
+	if (sig_kernel_specific(sig))
+		goto out_send;
+
+	/* must not happen */
+	BUG();
+out_send:
+	ret = __send_sig_info(sig, info, p, 0);
+out_unlock:
+	spin_unlock_irqrestore(&p->sig->siglock, flags);
+	return ret;
 }
 
 /*
@@ -670,15 +938,8 @@
 	read_lock(&tasklist_lock);
 	p = find_task_by_pid(pid);
 	error = -ESRCH;
-	if (p) {
-		if (!thread_group_leader(p)) {
-                       struct task_struct *tg;
-                       tg = find_task_by_pid(p->tgid);
-                       if (tg)
-                               p = tg;
-                }
+	if (p)
 		error = send_sig_info(sig, info, p);
-	}
 	read_unlock(&tasklist_lock);
 	return error;
 }
@@ -755,25 +1016,36 @@
  * Joy. Or not. Pthread wants us to wake up every thread
  * in our parent group.
  */
-static void wake_up_parent(struct task_struct *parent)
+static inline void wake_up_parent(struct task_struct *p)
 {
-	struct task_struct *tsk = parent;
+	struct task_struct *parent = p->parent, *tsk = parent;
 
+	/*
+	 * Fortunately this is not necessary for thread groups:
+	 */
+	if (p->tgid == tsk->tgid) {
+		wake_up_interruptible(&tsk->wait_chldexit);
+		return;
+	}
+	spin_lock_irq(&parent->sig->siglock);
 	do {
 		wake_up_interruptible(&tsk->wait_chldexit);
 		tsk = next_thread(tsk);
+		if (tsk->sig != parent->sig)
+			BUG();
 	} while (tsk != parent);
+	spin_unlock_irq(&parent->sig->siglock);
 }
 
 /*
  * Let a parent know about a status change of a child.
  */
+
 void do_notify_parent(struct task_struct *tsk, int sig)
 {
 	struct siginfo info;
 	int why, status;
 
-	/* is the thread detached? */
 	if (sig == -1)
 		BUG();
 
@@ -812,7 +1084,7 @@
 	info.si_status = status;
 
 	send_sig_info(sig, &info, tsk->parent);
-	wake_up_parent(tsk->parent);
+	wake_up_parent(tsk);
 }
 
 
@@ -837,13 +1109,24 @@
 
 int get_signal_to_deliver(siginfo_t *info, struct pt_regs *regs)
 {
+	sigset_t *mask = &current->blocked;
+
 	for (;;) {
-		unsigned long signr;
+		unsigned long signr = 0;
 		struct k_sigaction *ka;
 
-		spin_lock_irq(&current->sigmask_lock);
-		signr = dequeue_signal(&current->blocked, info);
-		spin_unlock_irq(&current->sigmask_lock);
+		local_irq_disable();
+		if (current->sig->shared_pending.head) {
+			spin_lock(&current->sig->siglock);
+			signr = dequeue_signal(&current->sig->shared_pending, mask, info);
+			spin_unlock(&current->sig->siglock);
+		}
+		if (!signr) {
+			spin_lock(&current->sigmask_lock);
+			signr = dequeue_signal(&current->pending, mask, info);
+			spin_unlock(&current->sigmask_lock);
+		}
+		local_irq_enable();
 
 		if (!signr)
 			break;
@@ -1137,8 +1420,11 @@
 			return -EINVAL;
 	}
 
-	spin_lock_irq(&current->sigmask_lock);
-	sig = dequeue_signal(&these, &info);
+	spin_lock_irq(&current->sig->siglock);
+	spin_lock(&current->sigmask_lock);
+	sig = dequeue_signal(&current->sig->shared_pending, &these, &info);
+	if (!sig)
+		sig = dequeue_signal(&current->pending, &these, &info);
 	if (!sig) {
 		timeout = MAX_SCHEDULE_TIMEOUT;
 		if (uts)
@@ -1149,21 +1435,27 @@
 			/* None ready -- temporarily unblock those we're
 			 * interested while we are sleeping in so that we'll
 			 * be awakened when they arrive.  */
-			sigset_t oldblocked = current->blocked;
+			current->real_blocked = current->blocked;
 			sigandsets(&current->blocked, &current->blocked, &these);
 			recalc_sigpending();
-			spin_unlock_irq(&current->sigmask_lock);
+			spin_unlock(&current->sigmask_lock);
+			spin_unlock_irq(&current->sig->siglock);
 
 			current->state = TASK_INTERRUPTIBLE;
 			timeout = schedule_timeout(timeout);
 
-			spin_lock_irq(&current->sigmask_lock);
-			sig = dequeue_signal(&these, &info);
-			current->blocked = oldblocked;
+			spin_lock_irq(&current->sig->siglock);
+			spin_lock(&current->sigmask_lock);
+			sig = dequeue_signal(&current->sig->shared_pending, &these, &info);
+			if (!sig)
+				sig = dequeue_signal(&current->pending, &these, &info);
+			current->blocked = current->real_blocked;
+			siginitset(&current->real_blocked, 0);
 			recalc_sigpending();
 		}
 	}
-	spin_unlock_irq(&current->sigmask_lock);
+	spin_unlock(&current->sigmask_lock);
+	spin_unlock_irq(&current->sig->siglock);
 
 	if (sig) {
 		ret = sig;
@@ -1195,33 +1487,35 @@
 }
 
 /*
- *  Kill only one task, even if it's a CLONE_THREAD task.
+ *  Send a signal to only one task, even if it's a CLONE_THREAD task.
  */
 asmlinkage long
 sys_tkill(int pid, int sig)
 {
-       struct siginfo info;
-       int error;
-       struct task_struct *p;
-
-       /* This is only valid for single tasks */
-       if (pid <= 0)
-           return -EINVAL;
-
-       info.si_signo = sig;
-       info.si_errno = 0;
-       info.si_code = SI_TKILL;
-       info.si_pid = current->pid;
-       info.si_uid = current->uid;
-
-       read_lock(&tasklist_lock);
-       p = find_task_by_pid(pid);
-       error = -ESRCH;
-       if (p) {
-               error = send_sig_info(sig, &info, p);
-       }
-       read_unlock(&tasklist_lock);
-       return error;
+	struct siginfo info;
+	int error;
+	struct task_struct *p;
+
+	/* This is only valid for single tasks */
+	if (pid <= 0)
+		return -EINVAL;
+
+	info.si_signo = sig;
+	info.si_errno = 0;
+	info.si_code = SI_TKILL;
+	info.si_pid = current->pid;
+	info.si_uid = current->uid;
+
+	read_lock(&tasklist_lock);
+	p = find_task_by_pid(pid);
+	error = -ESRCH;
+	if (p) {
+		spin_lock_irq(&p->sig->siglock);
+		error = __send_sig_info(sig, &info, p, 0);
+		spin_unlock_irq(&p->sig->siglock);
+	}
+	read_unlock(&tasklist_lock);
+	return error;
 }
 
 asmlinkage long
@@ -1247,13 +1541,12 @@
 {
 	struct k_sigaction *k;
 
-	if (sig < 1 || sig > _NSIG ||
-	    (act && (sig == SIGKILL || sig == SIGSTOP)))
+	if (sig < 1 || sig > _NSIG || (act && sig_kernel_only(sig)))
 		return -EINVAL;
 
 	k = &current->sig->action[sig-1];
 
-	spin_lock(&current->sig->siglock);
+	spin_lock_irq(&current->sig->siglock);
 
 	if (oact)
 		*oact = *k;
@@ -1292,7 +1585,7 @@
 		}
 	}
 
-	spin_unlock(&current->sig->siglock);
+	spin_unlock_irq(&current->sig->siglock);
 	return 0;
 }
 
diff -Nru a/kernel/softirq.c b/kernel/softirq.c
--- a/kernel/softirq.c	Mon Sep  9 10:36:01 2002
+++ b/kernel/softirq.c	Mon Sep  9 10:36:01 2002
@@ -59,7 +59,7 @@
 asmlinkage void do_softirq()
 {
 	__u32 pending;
-	long flags;
+	unsigned long flags;
 	__u32 mask;
 	int cpu;
 
@@ -129,7 +129,7 @@
 
 void raise_softirq(unsigned int nr)
 {
-	long flags;
+	unsigned long flags;
 
 	local_irq_save(flags);
 	cpu_raise_softirq(smp_processor_id(), nr);
diff -Nru a/kernel/suspend.c b/kernel/suspend.c
--- a/kernel/suspend.c	Mon Sep  9 10:36:01 2002
+++ b/kernel/suspend.c	Mon Sep  9 10:36:01 2002
@@ -468,31 +468,33 @@
 {
 	int chunk_size;
 	int nr_copy_pages = 0;
-	int loop;
+	int pfn;
+	struct page *page;
 	
 	if (max_mapnr != num_physpages)
 		panic("mapnr is not expected");
-	for (loop = 0; loop < max_mapnr; loop++) {
-		if (PageHighMem(mem_map+loop))
+	for (pfn = 0; pfn < max_mapnr; pfn++) {
+		page = pfn_to_page(pfn);
+		if (PageHighMem(page))
 			panic("Swsusp not supported on highmem boxes. Send 1GB of RAM to <pavel@ucw.cz> and try again ;-).");
-		if (!PageReserved(mem_map+loop)) {
-			if (PageNosave(mem_map+loop))
+		if (!PageReserved(page)) {
+			if (PageNosave(page))
 				continue;
 
-			if ((chunk_size=is_head_of_free_region(mem_map+loop))!=0) {
-				loop += chunk_size - 1;
+			if ((chunk_size=is_head_of_free_region(page))!=0) {
+				pfn += chunk_size - 1;
 				continue;
 			}
-		} else if (PageReserved(mem_map+loop)) {
-			BUG_ON (PageNosave(mem_map+loop));
+		} else if (PageReserved(page)) {
+			BUG_ON (PageNosave(page));
 
 			/*
 			 * Just copy whole code segment. Hopefully it is not that big.
 			 */
-			if (ADDRESS(loop) >= (unsigned long)
-				&__nosave_begin && ADDRESS(loop) < 
+			if (ADDRESS(pfn) >= (unsigned long)
+				&__nosave_begin && ADDRESS(pfn) < 
 				(unsigned long)&__nosave_end) {
-				PRINTK("[nosave %x]", ADDRESS(loop));
+				PRINTK("[nosave %x]", ADDRESS(pfn));
 				continue;
 			}
 			/* Hmm, perhaps copying all reserved pages is not too healthy as they may contain 
@@ -501,7 +503,7 @@
 
 		nr_copy_pages++;
 		if (pagedir_p) {
-			pagedir_p->orig_address = ADDRESS(loop);
+			pagedir_p->orig_address = ADDRESS(pfn);
 			copy_page(pagedir_p->address, pagedir_p->orig_address);
 			pagedir_p++;
 		}
diff -Nru a/kernel/sysctl.c b/kernel/sysctl.c
--- a/kernel/sysctl.c	Mon Sep  9 10:35:56 2002
+++ b/kernel/sysctl.c	Mon Sep  9 10:35:56 2002
@@ -51,6 +51,7 @@
 extern int sysrq_enabled;
 extern int core_uses_pid;
 extern int cad_pid;
+extern int pid_max;
 
 /* this is needed for the proc_dointvec_minmax for [fs_]overflow UID and GID */
 static int maxolduid = 65535;
@@ -255,6 +256,8 @@
 	{KERN_S390_USER_DEBUG_LOGGING,"userprocess_debug",
 	 &sysctl_userprocess_debug,sizeof(int),0644,NULL,&proc_dointvec},
 #endif
+	{KERN_PIDMAX, "pid_max", &pid_max, sizeof (int),
+	 0600, NULL, &proc_dointvec},
 	{0}
 };
 
diff -Nru a/mm/bootmem.c b/mm/bootmem.c
--- a/mm/bootmem.c	Mon Sep  9 10:36:01 2002
+++ b/mm/bootmem.c	Mon Sep  9 10:36:01 2002
@@ -318,10 +318,12 @@
 	return(init_bootmem_core(&contig_page_data, start, 0, pages));
 }
 
+#ifndef CONFIG_HAVE_ARCH_BOOTMEM_NODE
 void __init reserve_bootmem (unsigned long addr, unsigned long size)
 {
 	reserve_bootmem_core(contig_page_data.bdata, addr, size);
 }
+#endif /* !CONFIG_HAVE_ARCH_BOOTMEM_NODE */
 
 void __init free_bootmem (unsigned long addr, unsigned long size)
 {
diff -Nru a/mm/filemap.c b/mm/filemap.c
--- a/mm/filemap.c	Mon Sep  9 10:36:01 2002
+++ b/mm/filemap.c	Mon Sep  9 10:36:01 2002
@@ -1036,7 +1036,52 @@
 	UPDATE_ATIME(inode);
 }
 
-int file_read_actor(read_descriptor_t * desc, struct page *page, unsigned long offset, unsigned long size)
+/*
+ * Fault a userspace page into pagetables.  Return non-zero on a fault.
+ *
+ * FIXME: this assumes that two userspace pages are always sufficient.  That's
+ * not true if PAGE_CACHE_SIZE > PAGE_SIZE.
+ */
+static inline int fault_in_pages_writeable(char *uaddr, int size)
+{
+	int ret;
+
+	/*
+	 * Writing zeroes into userspace here is OK, because we know that if
+	 * the zero gets there, we'll be overwriting it.
+	 */
+	ret = __put_user(0, uaddr);
+	if (ret == 0) {
+		char *end = uaddr + size - 1;
+
+		/*
+		 * If the page was already mapped, this will get a cache miss
+		 * for sure, so try to avoid doing it.
+		 */
+		if (((unsigned long)uaddr & PAGE_MASK) !=
+				((unsigned long)end & PAGE_MASK))
+		 	ret = __put_user(0, end);
+	}
+	return ret;
+}
+
+static inline void fault_in_pages_readable(const char *uaddr, int size)
+{
+	volatile char c;
+	int ret;
+
+	ret = __get_user(c, (char *)uaddr);
+	if (ret == 0) {
+		const char *end = uaddr + size - 1;
+
+		if (((unsigned long)uaddr & PAGE_MASK) !=
+				((unsigned long)end & PAGE_MASK))
+		 	__get_user(c, (char *)end);
+	}
+}
+
+int file_read_actor(read_descriptor_t *desc, struct page *page,
+			unsigned long offset, unsigned long size)
 {
 	char *kaddr;
 	unsigned long left, count = desc->count;
@@ -1044,14 +1089,28 @@
 	if (size > count)
 		size = count;
 
+	/*
+	 * Faults on the destination of a read are common, so do it before
+	 * taking the kmap.
+	 */
+	if (!fault_in_pages_writeable(desc->buf, size)) {
+		kaddr = kmap_atomic(page, KM_USER0);
+		left = __copy_to_user(desc->buf, kaddr + offset, size);
+		kunmap_atomic(kaddr, KM_USER0);
+		if (left == 0)
+			goto success;
+	}
+
+	/* Do it the slow way */
 	kaddr = kmap(page);
 	left = __copy_to_user(desc->buf, kaddr + offset, size);
 	kunmap(page);
-	
+
 	if (left) {
 		size -= left;
 		desc->error = -EFAULT;
 	}
+success:
 	desc->count = count - size;
 	desc->written += size;
 	desc->buf += size;
@@ -1838,6 +1897,26 @@
 	}
 }
 
+static inline int
+filemap_copy_from_user(struct page *page, unsigned long offset,
+			const char *buf, unsigned bytes)
+{
+	char *kaddr;
+	int left;
+
+	kaddr = kmap_atomic(page, KM_USER0);
+	left = __copy_from_user(kaddr + offset, buf, bytes);
+	kunmap_atomic(kaddr, KM_USER0);
+
+	if (left != 0) {
+		/* Do it the slow way */
+		kaddr = kmap(page);
+		left = __copy_from_user(kaddr + offset, buf, bytes);
+		kunmap(page);
+	}
+	return left;
+}
+
 /*
  * Write to a file through the page cache. 
  *
@@ -1990,7 +2069,6 @@
 		unsigned long index;
 		unsigned long offset;
 		long page_fault;
-		char *kaddr;
 
 		offset = (pos & (PAGE_CACHE_SIZE -1)); /* Within page */
 		index = pos >> PAGE_CACHE_SHIFT;
@@ -2004,10 +2082,7 @@
 		 * same page as we're writing to, without it being marked
 		 * up-to-date.
 		 */
-		{ volatile unsigned char dummy;
-			__get_user(dummy, buf);
-			__get_user(dummy, buf+bytes-1);
-		}
+		fault_in_pages_readable(buf, bytes);
 
 		page = __grab_cache_page(mapping, index, &cached_page, &lru_pvec);
 		if (!page) {
@@ -2015,22 +2090,19 @@
 			break;
 		}
 
-		kaddr = kmap(page);
 		status = a_ops->prepare_write(file, page, offset, offset+bytes);
 		if (unlikely(status)) {
 			/*
 			 * prepare_write() may have instantiated a few blocks
 			 * outside i_size.  Trim these off again.
 			 */
-			kunmap(page);
 			unlock_page(page);
 			page_cache_release(page);
 			if (pos + bytes > inode->i_size)
 				vmtruncate(inode, inode->i_size);
 			break;
 		}
-		page_fault = __copy_from_user(kaddr + offset, buf, bytes);
-		flush_dcache_page(page);
+		page_fault = filemap_copy_from_user(page, offset, buf, bytes);
 		status = a_ops->commit_write(file, page, offset, offset+bytes);
 		if (unlikely(page_fault)) {
 			status = -EFAULT;
@@ -2045,7 +2117,6 @@
 				buf += status;
 			}
 		}
-		kunmap(page);
 		if (!PageReferenced(page))
 			SetPageReferenced(page);
 		unlock_page(page);
diff -Nru a/mm/highmem.c b/mm/highmem.c
--- a/mm/highmem.c	Mon Sep  9 10:35:56 2002
+++ b/mm/highmem.c	Mon Sep  9 10:35:56 2002
@@ -383,7 +383,7 @@
 		/*
 		 * is destination page below bounce pfn?
 		 */
-		if ((page - page_zone(page)->zone_mem_map) + (page_zone(page)->zone_start_paddr >> PAGE_SHIFT) < pfn)
+		if ((page - page_zone(page)->zone_mem_map) + (page_zone(page)->zone_start_pfn) < pfn)
 			continue;
 
 		/*
diff -Nru a/mm/memory.c b/mm/memory.c
--- a/mm/memory.c	Mon Sep  9 10:36:11 2002
+++ b/mm/memory.c	Mon Sep  9 10:36:11 2002
@@ -1033,11 +1033,11 @@
 	return VM_FAULT_OOM;
 }
 
-static void vmtruncate_list(list_t *head, unsigned long pgoff)
+static void vmtruncate_list(struct list_head *head, unsigned long pgoff)
 {
 	unsigned long start, end, len, diff;
 	struct vm_area_struct *vma;
-	list_t *curr;
+	struct list_head *curr;
 
 	list_for_each(curr, head) {
 		vma = list_entry(curr, struct vm_area_struct, shared);
diff -Nru a/mm/numa.c b/mm/numa.c
--- a/mm/numa.c	Mon Sep  9 10:36:01 2002
+++ b/mm/numa.c	Mon Sep  9 10:36:01 2002
@@ -22,11 +22,11 @@
  * Should be invoked with paramters (0, 0, unsigned long *[], start_paddr).
  */
 void __init free_area_init_node(int nid, pg_data_t *pgdat, struct page *pmap,
-	unsigned long *zones_size, unsigned long zone_start_paddr, 
+	unsigned long *zones_size, unsigned long zone_start_pfn, 
 	unsigned long *zholes_size)
 {
 	free_area_init_core(0, &contig_page_data, &mem_map, zones_size, 
-				zone_start_paddr, zholes_size, pmap);
+				zone_start_pfn, zholes_size, pmap);
 }
 
 #endif /* !CONFIG_DISCONTIGMEM */
@@ -48,7 +48,7 @@
  * Nodes can be initialized parallely, in no particular order.
  */
 void __init free_area_init_node(int nid, pg_data_t *pgdat, struct page *pmap,
-	unsigned long *zones_size, unsigned long zone_start_paddr, 
+	unsigned long *zones_size, unsigned long zone_start_pfn, 
 	unsigned long *zholes_size)
 {
 	int i, size = 0;
@@ -57,7 +57,7 @@
 	if (mem_map == NULL)
 		mem_map = (struct page *)PAGE_OFFSET;
 
-	free_area_init_core(nid, pgdat, &discard, zones_size, zone_start_paddr,
+	free_area_init_core(nid, pgdat, &discard, zones_size, zone_start_pfn,
 					zholes_size, pmap);
 	pgdat->node_id = nid;
 
diff -Nru a/mm/page_alloc.c b/mm/page_alloc.c
--- a/mm/page_alloc.c	Mon Sep  9 10:35:56 2002
+++ b/mm/page_alloc.c	Mon Sep  9 10:35:56 2002
@@ -46,9 +46,9 @@
  */
 static inline int bad_range(struct zone *zone, struct page *page)
 {
-	if (page - mem_map >= zone->zone_start_mapnr + zone->size)
+	if (page_to_pfn(page) >= zone->zone_start_pfn + zone->size)
 		return 1;
-	if (page - mem_map < zone->zone_start_mapnr)
+	if (page_to_pfn(page) < zone->zone_start_pfn)
 		return 1;
 	if (zone != page_zone(page))
 		return 1;
@@ -237,7 +237,7 @@
         struct zone *zone = page_zone(page);
         unsigned long flags;
 	int order;
-	list_t *curr;
+	struct list_head *curr;
 
 	/*
 	 * Should not matter as we need quiescent system for
@@ -652,7 +652,7 @@
 
 	for (pgdat = pgdat_list; pgdat; pgdat = pgdat->pgdat_next)
 		for (type = 0; type < MAX_NR_ZONES; type++) {
-			list_t *elem;
+			struct list_head *elem;
 			struct zone *zone = &pgdat->node_zones[type];
  			unsigned long nr, flags, order, total = 0;
 
@@ -773,7 +773,7 @@
  *   - clear the memory bitmaps
  */
 void __init free_area_init_core(int nid, pg_data_t *pgdat, struct page **gmap,
-	unsigned long *zones_size, unsigned long zone_start_paddr, 
+	unsigned long *zones_size, unsigned long zone_start_pfn, 
 	unsigned long *zholes_size, struct page *lmem_map)
 {
 	unsigned long i, j;
@@ -781,13 +781,10 @@
 	unsigned long totalpages, offset, realtotalpages;
 	const unsigned long zone_required_alignment = 1UL << (MAX_ORDER-1);
 
-	BUG_ON(zone_start_paddr & ~PAGE_MASK);
-
 	totalpages = 0;
-	for (i = 0; i < MAX_NR_ZONES; i++) {
-		unsigned long size = zones_size[i];
-		totalpages += size;
-	}
+	for (i = 0; i < MAX_NR_ZONES; i++)
+		totalpages += zones_size[i];
+
 	realtotalpages = totalpages;
 	if (zholes_size)
 		for (i = 0; i < MAX_NR_ZONES; i++)
@@ -810,7 +807,7 @@
 	}
 	*gmap = pgdat->node_mem_map = lmem_map;
 	pgdat->node_size = totalpages;
-	pgdat->node_start_paddr = zone_start_paddr;
+	pgdat->node_start_pfn = zone_start_pfn;
 	pgdat->node_start_mapnr = (lmem_map - mem_map);
 	pgdat->nr_zones = 0;
 
@@ -825,7 +822,7 @@
 		if (zholes_size)
 			realsize -= zholes_size[j];
 
-		printk("zone(%lu): %lu pages.\n", j, size);
+		printk("  %s zone: %lu pages\n", zone_names[j], realsize);
 		zone->size = size;
 		zone->name = zone_names[j];
 		spin_lock_init(&zone->lock);
@@ -868,9 +865,9 @@
 
 		zone->zone_mem_map = mem_map + offset;
 		zone->zone_start_mapnr = offset;
-		zone->zone_start_paddr = zone_start_paddr;
+		zone->zone_start_pfn = zone_start_pfn;
 
-		if ((zone_start_paddr >> PAGE_SHIFT) & (zone_required_alignment-1))
+		if ((zone_start_pfn) & (zone_required_alignment-1))
 			printk("BUG: wrong zone alignment, it will crash\n");
 
 		/*
@@ -885,8 +882,12 @@
 			SetPageReserved(page);
 			INIT_LIST_HEAD(&page->list);
 			if (j != ZONE_HIGHMEM)
-				set_page_address(page, __va(zone_start_paddr));
-			zone_start_paddr += PAGE_SIZE;
+				/*
+				 * The shift left won't overflow because the
+				 * ZONE_NORMAL is below 4G.
+				 */
+				set_page_address(page, __va(zone_start_pfn << PAGE_SHIFT));
+			zone_start_pfn++;
 		}
 
 		offset += size;
diff -Nru a/mm/pdflush.c b/mm/pdflush.c
--- a/mm/pdflush.c	Mon Sep  9 10:36:18 2002
+++ b/mm/pdflush.c	Mon Sep  9 10:36:18 2002
@@ -88,7 +88,6 @@
 static int __pdflush(struct pdflush_work *my_work)
 {
 	daemonize();
-	reparent_to_init();
 	strcpy(current->comm, "pdflush");
 
 	/* interruptible sleep, so block all signals */
diff -Nru a/mm/rmap.c b/mm/rmap.c
--- a/mm/rmap.c	Mon Sep  9 10:36:17 2002
+++ b/mm/rmap.c	Mon Sep  9 10:36:17 2002
@@ -25,6 +25,7 @@
 #include <linux/swapops.h>
 #include <linux/slab.h>
 #include <linux/init.h>
+#include <linux/rmap-locking.h>
 
 #include <asm/pgalloc.h>
 #include <asm/rmap.h>
diff -Nru a/mm/vmscan.c b/mm/vmscan.c
--- a/mm/vmscan.c	Mon Sep  9 10:35:59 2002
+++ b/mm/vmscan.c	Mon Sep  9 10:35:59 2002
@@ -25,6 +25,7 @@
 #include <linux/buffer_head.h>		/* for try_to_release_page() */
 #include <linux/mm_inline.h>
 #include <linux/pagevec.h>
+#include <linux/rmap-locking.h>
 
 #include <asm/pgalloc.h>
 #include <asm/tlbflush.h>
@@ -482,7 +483,7 @@
 	ratio = (unsigned long)nr_pages * zone->nr_active /
 				((zone->nr_inactive | 1) * 2);
 	atomic_add(ratio+1, &zone->refill_counter);
-	if (atomic_read(&zone->refill_counter) > SWAP_CLUSTER_MAX) {
+	while (atomic_read(&zone->refill_counter) > SWAP_CLUSTER_MAX) {
 		atomic_sub(SWAP_CLUSTER_MAX, &zone->refill_counter);
 		refill_inactive_zone(zone, SWAP_CLUSTER_MAX);
 	}
@@ -516,7 +517,7 @@
 
 	first_classzone = classzone->zone_pgdat->node_zones;
 	zone = classzone;
-	while (zone >= first_classzone) {
+	while (zone >= first_classzone && nr_pages > 0) {
 		if (zone->free_pages <= zone->pages_high) {
 			nr_pages = shrink_zone(zone, priority,
 					gfp_mask, nr_pages);
diff -Nru a/net/802/Makefile b/net/802/Makefile
--- a/net/802/Makefile	Mon Sep  9 10:36:11 2002
+++ b/net/802/Makefile	Mon Sep  9 10:36:11 2002
@@ -2,7 +2,7 @@
 # Makefile for the Linux 802.x protocol layers.
 #
 
-export-objs		:= p8022.o psnap.o tr.o
+export-objs		:= p8022.o psnap.o
 
 obj-y			:= p8023.o
 
diff -Nru a/net/core/dst.c b/net/core/dst.c
--- a/net/core/dst.c	Mon Sep  9 10:36:12 2002
+++ b/net/core/dst.c	Mon Sep  9 10:36:12 2002
@@ -5,8 +5,7 @@
  *
  */
 
-#include <asm/system.h>
-#include <asm/bitops.h>
+#include <linux/bitops.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
diff -Nru a/net/core/sock.c b/net/core/sock.c
--- a/net/core/sock.c	Mon Sep  9 10:36:13 2002
+++ b/net/core/sock.c	Mon Sep  9 10:36:13 2002
@@ -103,7 +103,6 @@
 #include <linux/string.h>
 #include <linux/sockios.h>
 #include <linux/net.h>
-#include <linux/fcntl.h>
 #include <linux/mm.h>
 #include <linux/slab.h>
 #include <linux/interrupt.h>
@@ -1048,34 +1047,6 @@
 	return -EOPNOTSUPP;
 }
 
-/* 
- * Note: if you add something that sleeps here then change sock_fcntl()
- *       to do proper fd locking.
- */
-int sock_no_fcntl(struct socket *sock, unsigned int cmd, unsigned long arg)
-{
-	struct sock *sk = sock->sk;
-
-	switch(cmd)
-	{
-		case F_SETOWN:
-			/*
-			 * This is a little restrictive, but it's the only
-			 * way to make sure that you can't send a sigurg to
-			 * another process.
-			 */
-			if (current->pgrp != -arg &&
-				current->pid != arg &&
-				!capable(CAP_KILL)) return(-EPERM);
-			sk->proc = arg;
-			return(0);
-		case F_GETOWN:
-			return(sk->proc);
-		default:
-			return(-EINVAL);
-	}
-}
-
 int sock_no_sendmsg(struct socket *sock, struct msghdr *m, int flags,
 		    struct scm_cookie *scm)
 {
@@ -1177,6 +1148,13 @@
 {
 	if (sk->protinfo)
 		kfree(sk->protinfo);
+}
+
+void sk_send_sigurg(struct sock *sk)
+{
+	if (sk->socket && sk->socket->file)
+		if (send_sigurg(&sk->socket->file->f_owner))
+			sk_wake_async(sk, 3, POLL_PRI);
 }
 
 void sock_init_data(struct socket *sock, struct sock *sk)
diff -Nru a/net/econet/af_econet.c b/net/econet/af_econet.c
--- a/net/econet/af_econet.c	Mon Sep  9 10:36:11 2002
+++ b/net/econet/af_econet.c	Mon Sep  9 10:36:11 2002
@@ -651,13 +651,10 @@
 		case SIOCSPGRP:
 			if (get_user(pid, (int *) arg))
 				return -EFAULT; 
-			if (current->pid != pid && current->pgrp != -pid && !capable(CAP_NET_ADMIN))
-				return -EPERM;
-			sk->proc = pid;
-			return(0);
+			return f_setown(sock->file, pid, 1);
 		case FIOGETOWN:
 		case SIOCGPGRP:
-			return put_user(sk->proc, (int *)arg);
+			return put_user(sock->file->f_owner.pid, (int *)arg);
 		case SIOCGSTAMP:
 			if(sk->stamp.tv_sec==0)
 				return -ENOENT;
diff -Nru a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
--- a/net/ipv4/af_inet.c	Mon Sep  9 10:35:59 2002
+++ b/net/ipv4/af_inet.c	Mon Sep  9 10:35:59 2002
@@ -857,16 +857,12 @@
 		case SIOCSPGRP:
 			if (get_user(pid, (int *)arg))
 				err = -EFAULT;
-			else if (current->pid != pid &&
-				 current->pgrp != -pid &&
-				!capable(CAP_NET_ADMIN))
-				err = -EPERM;
 			else
-				sk->proc = pid;
+				err = f_setown(sock->file, pid, 1);
 			break;
 		case FIOGETOWN:
 		case SIOCGPGRP:
-			err = put_user(sk->proc, (int *)arg);
+			err = put_user(sock->file->f_owner.pid, (int *)arg);
 			break;
 		case SIOCGSTAMP:
 			if (!sk->stamp.tv_sec)
diff -Nru a/net/ipv4/igmp.c b/net/ipv4/igmp.c
--- a/net/ipv4/igmp.c	Mon Sep  9 10:36:17 2002
+++ b/net/ipv4/igmp.c	Mon Sep  9 10:36:17 2002
@@ -530,9 +530,8 @@
  *	A socket has left a multicast group on device dev
  */
 
-int ip_mc_dec_group(struct in_device *in_dev, u32 addr)
+void ip_mc_dec_group(struct in_device *in_dev, u32 addr)
 {
-	int err = -ESRCH;
 	struct ip_mc_list *i, **ip;
 	
 	ASSERT_RTNL();
@@ -549,13 +548,11 @@
 					ip_rt_multicast_event(in_dev);
 
 				ip_ma_put(i);
-				return 0;
+				return;
 			}
-			err = 0;
 			break;
 		}
 	}
-	return -ESRCH;
 }
 
 /* Device going down */
diff -Nru a/net/ipv4/netfilter/Makefile b/net/ipv4/netfilter/Makefile
--- a/net/ipv4/netfilter/Makefile	Mon Sep  9 10:36:01 2002
+++ b/net/ipv4/netfilter/Makefile	Mon Sep  9 10:36:01 2002
@@ -2,7 +2,7 @@
 # Makefile for the netfilter modules on top of IPv4.
 #
 
-export-objs  := ip_conntrack_standalone.o ip_fw_compat.o ip_nat_standalone.o \
+export-objs  := ip_conntrack_standalone.o ip_nat_standalone.o \
 		ip_tables.o arp_tables.o
 
 # objects for the conntrack and NAT core (used by standalone and backw. compat)
diff -Nru a/net/ipv4/netfilter/ip_nat_helper.c b/net/ipv4/netfilter/ip_nat_helper.c
--- a/net/ipv4/netfilter/ip_nat_helper.c	Mon Sep  9 10:36:01 2002
+++ b/net/ipv4/netfilter/ip_nat_helper.c	Mon Sep  9 10:36:01 2002
@@ -382,9 +382,9 @@
 			const char *tmp = me->me->name;
 			
 			if (strlen(tmp) + 6 > MODULE_MAX_NAMELEN) {
-				printk(__FUNCTION__ ": unable to "
+				printk("%s: unable to "
 				       "compute conntrack helper name "
-				       "from %s\n", tmp);
+				       "from %s\n", __FUNCTION__, tmp);
 				return -EBUSY;
 			}
 			tmp += 6;
@@ -467,7 +467,8 @@
 		    && ct_helper->me) {
 			__MOD_DEC_USE_COUNT(ct_helper->me);
 		} else 
-			printk(__FUNCTION__ ": unable to decrement usage count"
-			       " of conntrack helper %s\n", me->me->name);
+			printk("%s: unable to decrement usage count"
+			       " of conntrack helper %s\n",
+			       __FUNCTION__, me->me->name);
 	}
 }
diff -Nru a/net/ipv4/netfilter/ipchains_core.c b/net/ipv4/netfilter/ipchains_core.c
--- a/net/ipv4/netfilter/ipchains_core.c	Mon Sep  9 10:36:01 2002
+++ b/net/ipv4/netfilter/ipchains_core.c	Mon Sep  9 10:36:01 2002
@@ -1779,4 +1779,4 @@
 #endif
 	return ret;
 }
-MODULE_LICENSE("BSD without advertisement clause");
+MODULE_LICENSE("Dual BSD/GPL");
diff -Nru a/net/ipv4/netfilter/ipfwadm_core.c b/net/ipv4/netfilter/ipfwadm_core.c
--- a/net/ipv4/netfilter/ipfwadm_core.c	Mon Sep  9 10:36:11 2002
+++ b/net/ipv4/netfilter/ipfwadm_core.c	Mon Sep  9 10:36:11 2002
@@ -156,7 +156,7 @@
 #define dprint_ip(a)
 #endif
 
-static rwlock_t ip_fw_lock = RW_LOCK_UNLOCKED;
+static DECLARE_RWLOCK(ip_fw_lock);
 
 #if defined(CONFIG_IP_ACCT) || defined(CONFIG_IP_FIREWALL)
 
diff -Nru a/net/ipv4/netfilter/ipt_ULOG.c b/net/ipv4/netfilter/ipt_ULOG.c
--- a/net/ipv4/netfilter/ipt_ULOG.c	Mon Sep  9 10:36:05 2002
+++ b/net/ipv4/netfilter/ipt_ULOG.c	Mon Sep  9 10:36:05 2002
@@ -10,6 +10,8 @@
  *            nlgroup now global (sysctl)
  * 2001/04/19 ulog-queue reworked, now fixed buffer size specified at
  * 	      module loadtime -HW
+ * 2002/07/07 remove broken nflog_rcv() function -HW
+ * 2002/08/29 fix shifted/unshifted nlgroup bug -HW
  *
  * Released under the terms of the GPL
  *
@@ -29,7 +31,7 @@
  *   Specify, after how many clock ticks (intel: 100 per second) the queue
  * should be flushed even if it is not full yet.
  *
- * ipt_ULOG.c,v 1.18 2002/04/16 07:33:00 laforge Exp
+ * ipt_ULOG.c,v 1.21 2002/08/29 10:54:34 laforge Exp
  */
 
 #include <linux/module.h>
@@ -48,8 +50,11 @@
 #include <linux/netfilter_ipv4/ipt_ULOG.h>
 #include <linux/netfilter_ipv4/lockhelp.h>
 #include <net/sock.h>
+#include <asm/bitops.h>
 
 MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>");
+MODULE_DESCRIPTION("IP tables userspace logging module");
 
 #define ULOG_NL_EVENT		111		/* Harald's favorite number */
 #define ULOG_MAXNLGROUPS	32		/* numer of nlgroups */
@@ -63,10 +68,6 @@
 
 #define PRINTR(format, args...) do { if (net_ratelimit()) printk(format, ## args); } while (0)
 
-MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>");
-MODULE_DESCRIPTION("IP tables userspace logging module");
-
-
 static unsigned int nlbufsiz = 4096;
 MODULE_PARM(nlbufsiz, "i");
 MODULE_PARM_DESC(nlbufsiz, "netlink buffer size");
@@ -91,9 +92,9 @@
 DECLARE_LOCK(ulog_lock);	/* spinlock */
 
 /* send one ulog_buff_t to userspace */
-static void ulog_send(unsigned int nlgroup)
+static void ulog_send(unsigned int nlgroupnum)
 {
-	ulog_buff_t *ub = &ulog_buffers[nlgroup];
+	ulog_buff_t *ub = &ulog_buffers[nlgroupnum];
 
 	if (timer_pending(&ub->timer)) {
 		DEBUGP("ipt_ULOG: ulog_send: timer was pending, deleting\n");
@@ -104,10 +105,10 @@
 	if (ub->qlen > 1)
 		ub->lastnlh->nlmsg_type = NLMSG_DONE;
 
-	NETLINK_CB(ub->skb).dst_groups = nlgroup;
+	NETLINK_CB(ub->skb).dst_groups = (1 << nlgroupnum);
 	DEBUGP("ipt_ULOG: throwing %d packets to netlink mask %u\n",
 		ub->qlen, nlgroup);
-	netlink_broadcast(nflognl, ub->skb, 0, nlgroup, GFP_ATOMIC);
+	netlink_broadcast(nflognl, ub->skb, 0, (1 << nlgroupnum), GFP_ATOMIC);
 
 	ub->qlen = 0;
 	ub->skb = NULL;
@@ -128,11 +129,6 @@
 	UNLOCK_BH(&ulog_lock);
 }
 
-static void nflog_rcv(struct sock *sk, int len)
-{
-	printk("ipt_ULOG:nflog_rcv() did receive netlink message ?!?\n");
-}
-
 struct sk_buff *ulog_alloc_skb(unsigned int size)
 {
 	struct sk_buff *skb;
@@ -169,6 +165,11 @@
 	struct nlmsghdr *nlh;
 	struct ipt_ulog_info *loginfo = (struct ipt_ulog_info *) targinfo;
 
+	/* ffs == find first bit set, necessary because userspace
+	 * is already shifting groupnumber, but we need unshifted.
+	 * ffs() returns [1..32], we need [0..31] */
+	unsigned int groupnum = ffs(loginfo->nl_group) - 1;
+
 	/* calculate the size of the skb needed */
 	if ((loginfo->copy_range == 0) ||
 	    (loginfo->copy_range > (*pskb)->len)) {
@@ -179,7 +180,7 @@
 
 	size = NLMSG_SPACE(sizeof(*pm) + copy_len);
 
-	ub = &ulog_buffers[loginfo->nl_group];
+	ub = &ulog_buffers[groupnum];
 	
 	LOCK_BH(&ulog_lock);
 
@@ -191,7 +192,7 @@
 		/* either the queue len is too high or we don't have 
 		 * enough room in nlskb left. send it to userspace. */
 
-		ulog_send(loginfo->nl_group);
+		ulog_send(groupnum);
 
 		if (!(ub->skb = ulog_alloc_skb(size)))
 			goto alloc_failure;
@@ -325,7 +326,7 @@
 		ulog_buffers[i].timer.data = i;
 	}
 
-	nflognl = netlink_kernel_create(NETLINK_NFLOG, nflog_rcv);
+	nflognl = netlink_kernel_create(NETLINK_NFLOG, NULL);
 	if (!nflognl)
 		return -ENOMEM;
 
diff -Nru a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
--- a/net/ipv4/tcp_input.c	Mon Sep  9 10:36:01 2002
+++ b/net/ipv4/tcp_input.c	Mon Sep  9 10:36:01 2002
@@ -3103,13 +3103,7 @@
 		return;
 
 	/* Tell the world about our new urgent pointer. */
-	if (sk->proc != 0) {
-		if (sk->proc > 0)
-			kill_proc(sk->proc, SIGURG, 1);
-		else
-			kill_pg(-sk->proc, SIGURG, 1);
-		sk_wake_async(sk, 3, POLL_PRI);
-	}
+	sk_send_sigurg(sk);
 
 	/* We may be adding urgent data when the last byte read was
 	 * urgent. To do this requires some care. We cannot just ignore
diff -Nru a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c
--- a/net/ipv4/tcp_minisocks.c	Mon Sep  9 10:36:01 2002
+++ b/net/ipv4/tcp_minisocks.c	Mon Sep  9 10:36:01 2002
@@ -676,7 +676,6 @@
 
 		newsk->done = 0;
 		newsk->userlocks = sk->userlocks & ~SOCK_BINDPORT_LOCK;
-		newsk->proc = 0;
 		newsk->backlog.head = newsk->backlog.tail = NULL;
 		newsk->callback_lock = RW_LOCK_UNLOCKED;
 		skb_queue_head_init(&newsk->error_queue);
diff -Nru a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
--- a/net/ipv4/tcp_output.c	Mon Sep  9 10:36:13 2002
+++ b/net/ipv4/tcp_output.c	Mon Sep  9 10:36:13 2002
@@ -478,6 +478,56 @@
 	return 0;
 }
 
+/* This is similar to __pskb_pull_head() (it will go to core/skbuff.c
+ * eventually). The difference is that pulled data not copied, but
+ * immediately discarded.
+ */
+unsigned char * __pskb_trim_head(struct sk_buff *skb, int len)
+{
+	int i, k, eat;
+
+	eat = len;
+	k = 0;
+	for (i=0; i<skb_shinfo(skb)->nr_frags; i++) {
+		if (skb_shinfo(skb)->frags[i].size <= eat) {
+			put_page(skb_shinfo(skb)->frags[i].page);
+			eat -= skb_shinfo(skb)->frags[i].size;
+		} else {
+			skb_shinfo(skb)->frags[k] = skb_shinfo(skb)->frags[i];
+			if (eat) {
+				skb_shinfo(skb)->frags[k].page_offset += eat;
+				skb_shinfo(skb)->frags[k].size -= eat;
+				eat = 0;
+			}
+			k++;
+		}
+	}
+	skb_shinfo(skb)->nr_frags = k;
+
+	skb->tail = skb->data;
+	skb->data_len -= len;
+	skb->len = skb->data_len;
+	return skb->tail;
+}
+
+static int tcp_trim_head(struct sock *sk, struct sk_buff *skb, u32 len)
+{
+	if (skb_cloned(skb) &&
+	    pskb_expand_head(skb, 0, 0, GFP_ATOMIC))
+		return -ENOMEM;
+
+	if (len <= skb_headlen(skb)) {
+		__skb_pull(skb, len);
+	} else {
+		if (__pskb_trim_head(skb, len-skb_headlen(skb)) == NULL)
+			return -ENOMEM;
+	}
+
+	TCP_SKB_CB(skb)->seq += len;
+	skb->ip_summed = CHECKSUM_HW;
+	return 0;
+}
+
 /* This function synchronize snd mss to current pmtu/exthdr set.
 
    tp->user_mss is mss set by user by TCP_MAXSEG. It does NOT counts
@@ -836,8 +886,6 @@
 		return -EAGAIN;
 
 	if (before(TCP_SKB_CB(skb)->seq, tp->snd_una)) {
-		struct sk_buff *skb2;
-
 		if (before(TCP_SKB_CB(skb)->end_seq, tp->snd_una))
 			BUG();
 
@@ -847,13 +895,8 @@
 			tp->mss_cache = tp->mss_cache_std;
 		}
 
-		if(tcp_fragment(sk, skb, tp->snd_una - TCP_SKB_CB(skb)->seq))
+		if (tcp_trim_head(sk, skb, tp->snd_una - TCP_SKB_CB(skb)->seq))
 			return -ENOMEM;
-
-		skb2 = skb->next;
-		__skb_unlink(skb, skb->list);
-		tcp_free_skb(sk, skb);
-		skb = skb2;
 	}
 
 	/* If receiver has shrunk his window, and skb is out of
diff -Nru a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c
--- a/net/ipv6/af_inet6.c	Mon Sep  9 10:36:11 2002
+++ b/net/ipv6/af_inet6.c	Mon Sep  9 10:36:11 2002
@@ -463,15 +463,10 @@
 	case SIOCSPGRP:
 		if (get_user(pid, (int *) arg))
 			return -EFAULT;
-		/* see sock_no_fcntl */
-		if (current->pid != pid && current->pgrp != -pid && 
-		    !capable(CAP_NET_ADMIN))
-			return -EPERM;
-		sk->proc = pid;
-		return(0);
+		return f_setown(sock->file, pid, 1);
 	case FIOGETOWN:
 	case SIOCGPGRP:
-		return put_user(sk->proc,(int *)arg);
+		return put_user(sock->file->f_owner.pid, (int *)arg);
 	case SIOCGSTAMP:
 		if(sk->stamp.tv_sec==0)
 			return -ENOENT;
@@ -663,8 +658,8 @@
 					   sizeof(struct raw6_sock), 0,
                                            SLAB_HWCACHE_ALIGN, 0, 0);
         if (!tcp6_sk_cachep || !udp6_sk_cachep || !raw6_sk_cachep)
-                printk(KERN_CRIT __FUNCTION__
-                        ": Can't create protocol sock SLAB caches!\n");
+                printk(KERN_CRIT "%s: Can't create protocol sock SLAB "
+		       "caches!\n", __FUNCTION__);
 
 	/* Register the socket-side information for inet6_create.  */
 	for(r = &inetsw6[0]; r < &inetsw6[SOCK_MAX]; ++r)
diff -Nru a/net/ipx/Makefile b/net/ipx/Makefile
--- a/net/ipx/Makefile	Mon Sep  9 10:36:13 2002
+++ b/net/ipx/Makefile	Mon Sep  9 10:36:13 2002
@@ -2,8 +2,6 @@
 # Makefile for the Linux IPX layer.
 #
 
-export-objs = af_ipx.o
-
 obj-$(CONFIG_IPX) += ipx.o
 
 ipx-y			:= af_ipx.o
diff -Nru a/net/packet/af_packet.c b/net/packet/af_packet.c
--- a/net/packet/af_packet.c	Mon Sep  9 10:35:59 2002
+++ b/net/packet/af_packet.c	Mon Sep  9 10:35:59 2002
@@ -1463,15 +1463,11 @@
 			int pid;
 			if (get_user(pid, (int *) arg))
 				return -EFAULT; 
-			if (current->pid != pid && current->pgrp != -pid && 
-			    !capable(CAP_NET_ADMIN))
-				return -EPERM;
-			sk->proc = pid;
-			break;
+			return f_setown(sock->file, pid, 1);
 		}
 		case FIOGETOWN:
 		case SIOCGPGRP:
-			return put_user(sk->proc, (int *)arg);
+			return put_user(sock->file->f_owner.pid, (int *)arg);
 		case SIOCGSTAMP:
 			if(sk->stamp.tv_sec==0)
 				return -ENOENT;
diff -Nru a/net/sctp/associola.c b/net/sctp/associola.c
--- a/net/sctp/associola.c	Mon Sep  9 10:35:56 2002
+++ b/net/sctp/associola.c	Mon Sep  9 10:35:56 2002
@@ -296,7 +296,7 @@
 {
 	sctp_transport_t *transport;
 	sctp_endpoint_t *ep;
-	list_t *pos, *temp;
+	struct list_head *pos, *temp;
 	int i;
 
 	ep = asoc->ep;
@@ -482,7 +482,7 @@
 					  const sockaddr_storage_t *address)
 {
 	sctp_transport_t *t;
-	list_t *pos;
+	struct list_head *pos;
 
 	/* Cycle through all transports searching for a peer address. */
 
@@ -508,7 +508,7 @@
 	sctp_transport_t *first;
 	sctp_transport_t *second;
 	sctp_ulpevent_t *event;
-	list_t *pos;
+	struct list_head *pos;
 	int spc_state = 0;
 
 	/* Record the transition on the transport.  */
@@ -780,7 +780,7 @@
 {
 	sctp_transport_t *active;
 	sctp_transport_t *match;
-	list_t *entry, *pos;
+	struct list_head *entry, *pos;
 	sctp_transport_t *transport;
 	sctp_chunk_t *chunk;
 	__u32 key = htonl(tsn);
@@ -983,8 +983,8 @@
 sctp_transport_t *sctp_assoc_choose_shutdown_transport(sctp_association_t *asoc)
 {
 	sctp_transport_t *t, *next;
-	list_t *head = &asoc->peer.transport_addr_list;
-	list_t *pos;
+	struct list_head *head = &asoc->peer.transport_addr_list;
+	struct list_head *pos;
 
 	/* If this is the first time SHUTDOWN is sent, use the active
 	 * path.
diff -Nru a/net/sctp/bind_addr.c b/net/sctp/bind_addr.c
--- a/net/sctp/bind_addr.c	Mon Sep  9 10:36:13 2002
+++ b/net/sctp/bind_addr.c	Mon Sep  9 10:36:13 2002
@@ -65,7 +65,7 @@
 			sctp_scope_t scope, int priority, int flags)
 {
 	struct sockaddr_storage_list *addr;
-	list_t *pos;
+	struct list_head *pos;
 	int error = 0;
 
 	/* All addresses share the same port.  */
@@ -119,7 +119,7 @@
 static void sctp_bind_addr_clean(sctp_bind_addr_t *bp)
 {
 	struct sockaddr_storage_list *addr;
-	list_t *pos, *temp;
+	struct list_head *pos, *temp;
 
 	/* Empty the bind address list. */
 	list_for_each_safe(pos, temp, &bp->address_list) {
@@ -173,7 +173,7 @@
  */
 int sctp_del_bind_addr(sctp_bind_addr_t *bp, sockaddr_storage_t *del_addr)
 {
-	list_t *pos, *temp;
+	struct list_head *pos, *temp;
 	struct sockaddr_storage_list *addr;
 
 	list_for_each_safe(pos, temp, &bp->address_list) {
@@ -206,7 +206,7 @@
 	sctpIpAddress_t rawaddr_space;
 	int len;
 	struct sockaddr_storage_list *addr;
-	list_t *pos;
+	struct list_head *pos;
 
 	retval.v = NULL;
 	addrparms_len = 0;
@@ -284,7 +284,7 @@
 int sctp_bind_addr_has_addr(sctp_bind_addr_t *bp, const sockaddr_storage_t *addr)
 {
 	struct sockaddr_storage_list *laddr;
-	list_t *pos;
+	struct list_head *pos;
 
 	list_for_each(pos, &bp->address_list) {
 		laddr = list_entry(pos, struct sockaddr_storage_list, list);
diff -Nru a/net/sctp/endpointola.c b/net/sctp/endpointola.c
--- a/net/sctp/endpointola.c	Mon Sep  9 10:35:59 2002
+++ b/net/sctp/endpointola.c	Mon Sep  9 10:35:59 2002
@@ -257,7 +257,7 @@
 {
 	int rport;
 	sctp_association_t *asoc;
-	list_t *pos;
+	struct list_head *pos;
 
 	rport = paddr->v4.sin_port;
 
diff -Nru a/net/sctp/outqueue.c b/net/sctp/outqueue.c
--- a/net/sctp/outqueue.c	Mon Sep  9 10:36:01 2002
+++ b/net/sctp/outqueue.c	Mon Sep  9 10:36:01 2002
@@ -104,7 +104,7 @@
 void sctp_outqueue_teardown(sctp_outqueue_t *q)
 {
 	sctp_transport_t *transport;
-	list_t *lchunk, *pos;
+	struct list_head *lchunk, *pos;
 	sctp_chunk_t *chunk;
 
 	/* Throw away unacknowledged chunks. */
@@ -948,7 +948,7 @@
 int sctp_sack_outqueue(sctp_outqueue_t *q, sctp_sackhdr_t *sack)
 {
 	sctp_chunk_t *tchunk;
-	list_t *lchunk, *transport_list, *pos;
+	struct list_head *lchunk, *transport_list, *pos;
 	__u32 tsn;
 	__u32 sack_ctsn;
 	__u32 ctsn;
diff -Nru a/net/sctp/protocol.c b/net/sctp/protocol.c
--- a/net/sctp/protocol.c	Mon Sep  9 10:36:11 2002
+++ b/net/sctp/protocol.c	Mon Sep  9 10:36:11 2002
@@ -198,7 +198,7 @@
 static void __sctp_free_local_addr_list(sctp_protocol_t *proto)
 {
 	struct sockaddr_storage_list *addr;
-	list_t *pos, *temp;
+	struct list_head *pos, *temp;
 
 	list_for_each_safe(pos, temp, &proto->local_addr_list) {
 		addr = list_entry(pos, struct sockaddr_storage_list, list);
@@ -223,7 +223,7 @@
 {
 	struct sockaddr_storage_list *addr;
 	int error = 0;
-	list_t *pos;
+	struct list_head *pos;
 	long flags __attribute__ ((unused));
 
 	sctp_spin_lock_irqsave(&proto->local_addr_lock, flags);
@@ -327,7 +327,7 @@
  */
 sctp_func_t *sctp_get_af_specific(const sockaddr_storage_t *address)
 {
-	list_t *pos;
+	struct list_head *pos;
 	sctp_protocol_t *proto = sctp_get_protocol();
 	sctp_func_t *retval, *af;
 
diff -Nru a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c
--- a/net/sctp/sm_make_chunk.c	Mon Sep  9 10:35:59 2002
+++ b/net/sctp/sm_make_chunk.c	Mon Sep  9 10:35:59 2002
@@ -1417,7 +1417,7 @@
 	sctpParam_t param;
 	__u8 *end;
 	sctp_transport_t *transport;
-	list_t *pos, *temp;
+	struct list_head *pos, *temp;
 
 	/* We must include the address that the INIT packet came from.
 	 * This is the only address that matters for an INIT packet.
@@ -1595,7 +1595,7 @@
 
 	case SCTP_PARAM_STATE_COOKIE:
 		asoc->peer.cookie_len =
-			ntohs(param.p->length) =
+			ntohs(param.p->length) -
 			sizeof(sctp_paramhdr_t);
 		asoc->peer.cookie = param.cookie->body;
 		break;
diff -Nru a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c
--- a/net/sctp/sm_sideeffect.c	Mon Sep  9 10:36:12 2002
+++ b/net/sctp/sm_sideeffect.c	Mon Sep  9 10:36:12 2002
@@ -1053,7 +1053,7 @@
 				     sctp_association_t *asoc)
 {
 	sctp_transport_t *t;
-	list_t *pos;
+	struct list_head *pos;
 
 	/* Start a heartbeat timer for each transport on the association.
 	 * hold a reference on the transport to make sure none of
@@ -1072,7 +1072,7 @@
 void sctp_cmd_set_bind_addrs(sctp_cmd_seq_t *cmds, sctp_association_t *asoc,
 			     sctp_bind_addr_t *bp)
 {
-	list_t *pos, *temp;
+	struct list_head *pos, *temp;
 
 	list_for_each_safe(pos, temp, &bp->address_list) {
 		list_del_init(pos);
diff -Nru a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c
--- a/net/sctp/sm_statefuns.c	Mon Sep  9 10:35:56 2002
+++ b/net/sctp/sm_statefuns.c	Mon Sep  9 10:35:56 2002
@@ -1056,7 +1056,7 @@
 	sctp_ulpevent_t *ev;
 	sctp_chunk_t *repl;
 	sctp_transport_t *new_addr, *addr;
-	list_t *pos, *pos2, *temp;
+	struct list_head *pos, *pos2, *temp;
 	int found, error;
 
 	/* new_asoc is a brand-new association, so these are not yet
diff -Nru a/net/sctp/socket.c b/net/sctp/socket.c
--- a/net/sctp/socket.c	Mon Sep  9 10:36:11 2002
+++ b/net/sctp/socket.c	Mon Sep  9 10:36:11 2002
@@ -439,7 +439,7 @@
 #if CONFIG_IP_SCTP_ADDIP
 	/* Add these addresses to all associations on this endpoint.  */
 	if (retval >= 0) {
-		list_t *pos;
+		struct list_head *pos;
 		sctp_endpoint_t *ep;
 		sctp_association_t *asoc;
 		ep = sctp_sk(sk)->ep;
@@ -560,7 +560,7 @@
 #if CONFIG_IP_SCTP_ADDIP
 	/* Remove these addresses from all associations on this endpoint.  */
 	if (retval >= 0) {
-		list_t *pos;
+		struct list_head *pos;
 		sctp_endpoint_t *ep;
 		sctp_association_t *asoc;
 
@@ -666,7 +666,7 @@
 {
 	sctp_endpoint_t *ep;
 	sctp_association_t *asoc;
-	list_t *pos, *temp;
+	struct list_head *pos, *temp;
 
 	SCTP_DEBUG_PRINTK("sctp_close(sk: 0x%p...)\n", sk);
 
@@ -1238,7 +1238,7 @@
 	int retval = 0;
 	char * tmp;
 	sctp_protocol_t *proto = sctp_get_protocol();
-	list_t *pos;
+	struct list_head *pos;
 	sctp_func_t *af;
 
 	SCTP_DEBUG_PRINTK("sctp_setsockopt(sk: %p... optname: %d)\n",
@@ -1661,7 +1661,7 @@
 	int retval = 0;
 	sctp_protocol_t *proto = sctp_get_protocol();
 	sctp_func_t *af;
-	list_t *pos;
+	struct list_head *pos;
 	int len;
 
 	SCTP_DEBUG_PRINTK("sctp_getsockopt(sk: %p, ...)\n", sk);
@@ -2649,7 +2649,7 @@
 void sctp_write_space(struct sock *sk)
 {
 	sctp_association_t *asoc;
-	list_t *pos;
+	struct list_head *pos;
 
 	/* Wake up the tasks in each wait queue.  */
 	list_for_each(pos, &((sctp_sk(sk))->ep->asocs)) {
diff -Nru a/net/socket.c b/net/socket.c
--- a/net/socket.c	Mon Sep  9 10:36:05 2002
+++ b/net/socket.c	Mon Sep  9 10:36:05 2002
@@ -1516,24 +1516,6 @@
 	return err;
 }
 
-
-/*
- *	Perform a file control on a socket file descriptor.
- *
- *	Doesn't acquire a fd lock, because no network fcntl
- *	function sleeps currently.
- */
-
-int sock_fcntl(struct file *filp, unsigned int cmd, unsigned long arg)
-{
-	struct socket *sock;
-
-	sock = SOCKET_I (filp->f_dentry->d_inode);
-	if (sock && sock->ops)
-		return sock_no_fcntl(sock, cmd, arg);
-	return(-EINVAL);
-}
-
 /* Argument list sizes for sys_socketcall */
 #define AL(x) ((x) * sizeof(unsigned long))
 static unsigned char nargs[18]={AL(0),AL(3),AL(3),AL(3),AL(2),AL(3),
diff -Nru a/net/wanrouter/af_wanpipe.c b/net/wanrouter/af_wanpipe.c
--- a/net/wanrouter/af_wanpipe.c	Mon Sep  9 10:36:17 2002
+++ b/net/wanrouter/af_wanpipe.c	Mon Sep  9 10:36:17 2002
@@ -1876,14 +1876,10 @@
 			err = get_user(pid, (int *) arg);
 			if (err)
 				return err; 
-			if (current->pid != pid && current->pgrp != -pid && 
-			    !capable(CAP_NET_ADMIN))
-				return -EPERM;
-			sk->proc = pid;
-			return(0);
+			return f_setown(sock->file, pid, 1);
 		case FIOGETOWN:
 		case SIOCGPGRP:
-			return put_user(sk->proc, (int *)arg);
+			return put_user(sock->file->f_owner.pid, (int *)arg);
 		case SIOCGSTAMP:
 			if(sk->stamp.tv_sec==0)
 				return -ENOENT;
diff -Nru a/net/x25/x25_in.c b/net/x25/x25_in.c
--- a/net/x25/x25_in.c	Mon Sep  9 10:36:17 2002
+++ b/net/x25/x25_in.c	Mon Sep  9 10:36:17 2002
@@ -283,13 +283,7 @@
 				skb_queue_tail(&x25->interrupt_in_queue, skb);
 				queued = 1;
 			}
-			if (sk->proc != 0) {
-				if (sk->proc > 0)
-					kill_proc(sk->proc, SIGURG, 1);
-				else
-					kill_pg(-sk->proc, SIGURG, 1);
-				sock_wake_async(sk->socket, 3, POLL_PRI);
-			}
+			sk_send_sigurg(sk);
 			x25_write_internal(sk, X25_INTERRUPT_CONFIRMATION);
 			break;
 
